Magellan Linux

Contents of /trunk/mage/usr/lib/mage/etc-update

Parent Directory Parent Directory | Revision Log Revision Log


Revision 283 - (show annotations) (download)
Wed Oct 26 08:11:30 2005 UTC (18 years, 6 months ago) by niro
File size: 10651 byte(s)
synced with upstream:
- fixed several segfaults
- allow single quotes in config-file
- now really using less as pager

1 #!/bin/bash
2 # Copyright 1999-2004 Gentoo Foundation
3 # Distributed under the terms of the GNU General Public License v2
4 # $Header: /home/cvsd/magellan-cvs/magellan-src/mage/usr/lib/mage/etc-update,v 1.7 2005-10-26 08:11:30 niro Exp $
5
6 # Author Brandon Low <lostlogic@gentoo.org>
7 #
8 # Previous version (from which I've borrowed a few bits) by:
9 # Jochem Kossen <j.kossen@home.nl>
10 # Leo Lipelis <aeoo@gentoo.org>
11 # Karl Trygve Kalleberg <karltk@gentoo.org>
12 #
13 # $Header: /home/cvsd/magellan-cvs/magellan-src/mage/usr/lib/mage/etc-update,v 1.7 2005-10-26 08:11:30 niro Exp $
14
15 # Modified by Niels Rogalla <niro@magellan-linux.de> to use this with Magellan-Linux
16 # version: 0.4.0-r8
17
18 export PORTAGE_CALLER="etc-update"
19
20 function get_config() {
21 item=$1
22
23 # First strip off comment lines, then grab the configuration
24 # item. If there's more than one of the same configuration item,
25 # then allow the last setting to take precedence.
26 cut -d'#' -f1-1 /etc/etc-update.conf | \
27 sed -ne "s/^ *$item *= *\([\"']\{0,1\}\)\(.*\)\1/\2/p" |sed -e '$p;d'
28 }
29
30 function scan() {
31
32 echo "Scanning Configuration files..."
33 rm -rf ${TMP}/files > /dev/null 2>&1
34 mkdir ${TMP}/files || die "Failed mkdir command!" 1
35 count=0
36 input=0
37
38 for path in ${CONFIG_PROTECT}; do if [ -d ${path} ]; then
39 ofile=""
40 for file in `find ${path}/ -iname "._cfg????_*" |
41 sed -e "s:\(^.*/\)\(\._cfg[0-9]*_\)\(.*$\):\1\2\3\%\2\%\3:" |
42 sort -t'%' -k3 -k2 | LANG=POSIX LC_ALL=POSIX cut -f1 -d'%'`; do
43 rpath=`echo "${file/\/\///}" | sed -e "s:/[^/]*$::"`
44 rfile=`echo "${file/\/\///}" | sed -e "s:^.*/::"`
45 for mpath in ${CONFIG_PROTECT_MASK}; do
46 if [[ "${rpath}" == "${mpath}"* ]]; then
47 mv ${rpath}/${rfile} ${rpath}/${rfile:10}
48 break
49 fi
50 done
51 [ ! -f ${file} ] && continue
52
53
54 if [[ "${ofile:10}" != "${rfile:10}" ]] ||
55 [[ ${opath} != ${rpath} ]]; then
56 MATCHES=0
57 if [[ "${EU_AUTOMERGE}" == "yes" ]]; then
58 if [ ! -e "${rpath}/${rfile}" ] || [ ! -e "${rpath}/${rfile:10}" ]; then
59 MATCHES=0
60 else
61 diff -Bbua ${rpath}/${rfile} ${rpath}/${rfile:10} | egrep '^[+-]' | egrep -v '^[+-][\t ]*#|^--- |^\+\+\+ ' | egrep -qv '^[-+][\t ]*$'
62 MATCHES=$?
63 fi
64 elif [[ -z `diff -Nua ${rpath}/${rfile} ${rpath}/${rfile:10}|
65 grep "^[+-][^+-]"|grep -v '# .Header:.*'` ]]; then
66 MATCHES=1
67 fi
68 if [[ "${MATCHES}" == "1" ]]; then
69 echo "Automerging trivial changes in: ${rfile:10}"
70 mv ${rpath}/${rfile} ${rpath}/${rfile:10}
71 continue
72 else
73 count=${count}+1
74 echo "${rpath}/${rfile:10}" > ${TMP}/files/${count}
75 echo "${rpath}/${rfile}" >> ${TMP}/files/${count}
76 ofile="${rfile}"
77 opath="${rpath}"
78 continue
79 fi
80 fi
81
82 if [[ -z `diff -Nua ${rpath}/${rfile} ${rpath}/${ofile}|
83 grep "^[+-][^+-]"|grep -v '# .Header:.*'` ]]; then
84 mv ${rpath}/${rfile} ${rpath}/${ofile}
85 continue
86 else
87 echo "${rpath}/${rfile}" >> ${TMP}/files/${count}
88 ofile="${rfile}"
89 opath="${rpath}"
90 fi
91 done
92 fi; done
93
94 }
95
96 function sel_file() {
97 local -i isfirst=0
98 until [ -f ${TMP}/files/${input} ] || [ ${input} == -1 ] || [ ${input} == -3 ]; do
99 for file in `ls ${TMP}/files|sort -n`; do
100 if (( ${isfirst} == 0 )); then
101 isfirst=${file}
102 fi
103 echo -n "${file}${PAR} "
104 if (( ${mode} == 0 )); then
105 for word in `cat ${TMP}/files/${file}`; do
106 echo ${word}
107 done
108 else
109 head -n1 ${TMP}/files/${file}
110 fi
111 done > ${TMP}/menuitems
112
113 if [ "${OVERWRITE_ALL}" == "yes" ]; then
114 input=0
115 else
116 if (( ${mode} == 0 )); then
117 echo "The following is the list of files which need updating, each
118 configuration file is followed by a list of possible replacement files."
119 else
120 local my_title="Please select a file to update"
121 fi
122
123 if (( ${mode} == 0 )); then
124 cat ${TMP}/menuitems
125 echo "Please select a file to edit by entering the corresponding number."
126 echo " (don't use -3 or -5 if you're unsure what to do)"
127 echo " (-1 to exit) (-3 to auto merge all remaining files)"
128 echo -n " (-5 to auto-merge AND not use 'mv -i'): "
129 read input
130 else
131 dialog --title "${title}" --menu "${my_title}" \
132 0 0 0 `echo "-1 Exit";cat ${TMP}/menuitems` \
133 2> ${TMP}/input
134 input=`cat ${TMP}/input`
135 fi
136 if (( ${input} == -5 )); then
137 input=-3
138 export mv_opts=""
139 fi
140 if (( ${input} == -3 )); then
141 input=0
142 export OVERWRITE_ALL="yes"
143 fi
144 fi # -3 automerge
145 if (( ${input} == 0 )); then
146 input=${isfirst}
147 fi
148 done
149 }
150
151 function do_file() {
152 echo
153 local -i my_input
154 local -i fcount=0
155 until (( `cat ${TMP}/files/${input}|wc -l` < 2 )); do
156 my_input=0
157 if (( `cat ${TMP}/files/${input}|wc -l` == 2 )); then
158 my_input=1
159 fi
160 until (( ${my_input} > 0 )) && (( ${my_input} < `cat ${TMP}/files/${input}|wc -l` )); do
161 fcount=0
162
163 if [ "${OVERWRITE_ALL}" == "yes" ]; then
164 my_input=0
165 else
166 for line in `cat ${TMP}/files/${input}`; do
167 if (( ${fcount} > 0 )); then
168 echo -n "${fcount}${PAR} "
169 echo "${line}"
170 else
171 if (( ${mode} == 0 )); then
172 echo "Below are the new config files for ${line}:"
173 else
174 local my_title="Please select a file to process for ${line}"
175 fi
176 fi
177 fcount=${fcount}+1
178 done > ${TMP}/menuitems
179
180 if (( ${mode} == 0 )); then
181 cat ${TMP}/menuitems
182 echo -n "Please select a file to process (-1 to exit this file): "
183 read my_input
184 else
185 dialog --title "${title}" --menu "${my_title}" \
186 0 0 0 `cat ${TMP}/menuitems;echo "${fcount} Exit"` \
187 2> ${TMP}/input
188 my_input=`cat ${TMP}/input`
189 fi
190 fi # OVERWRITE_ALL
191
192 if (( ${my_input} == 0 )); then
193 my_input=1
194 elif (( ${my_input} == -1 )); then
195 input=0
196 return
197 elif (( ${my_input} == ${fcount} )); then
198 break
199 fi
200 done
201 if (( ${my_input} == ${fcount} )); then
202 break
203 fi
204
205 fcount=${my_input}+1
206
207 file=`cat ${TMP}/files/${input} | sed -e "${fcount}p;d"`
208 ofile=`head -n1 ${TMP}/files/${input}`
209
210 do_cfg "${file}" "${ofile}"
211
212 cat ${TMP}/files/${input}|sed -e "${fcount}!p;d" > ${TMP}/files/sed
213 mv ${TMP}/files/sed ${TMP}/files/${input}
214
215 if (( ${my_input} == -1 )); then
216 break
217 fi
218 done
219 echo
220 rm ${TMP}/files/${input}
221 count=${count}-1
222 }
223
224 function do_cfg() {
225
226 local file="${1}"
227 local ofile="${2}"
228 local -i my_input=0
229
230 until (( ${my_input} == -1 )) || [ ! -f ${file} ]; do
231 if [ "${OVERWRITE_ALL}" == "yes" ]; then
232 my_input=1
233 else
234 showdiffcmd=$(echo "${diff_command}" |
235 sed -e "s:%file1:${ofile}:" -e "s:%file2:${file}:")
236
237 if [ "${using_editor}" == 0 ]; then
238 (
239 echo "Showing differences between ${ofile} and ${file}"
240 ${showdiffcmd}
241 ) | ${pager}
242 else
243 echo "Beginning of differences between ${ofile} and ${file}"
244 ${showdiffcmd}
245 echo "End of differences between ${ofile} and ${file}"
246 fi
247 if [ -L "${file}" ]; then
248 echo
249 echo "-------------------------------------------------------------"
250 echo "NOTE: File is a symlink to another file. REPLACE recommended."
251 echo " The original file may simply have moved. Please review."
252 echo "-------------------------------------------------------------"
253 echo
254 fi
255 echo -n "1) Replace original with update
256 2) Delete update, keeping original as is
257 3) Interactively merge original with update
258 4) Show differences again
259 Please select from the menu above (-1 to ignore this update): "
260 read my_input
261 fi
262
263 case ${my_input} in
264 1) echo "Replacing ${ofile} with ${file}"
265 mv ${mv_opts} ${file} ${ofile}
266 my_input=-1
267 continue
268 ;;
269 2) echo "Deleting ${file}"
270 rm ${rm_opts} ${file}
271 continue
272 ;;
273 3) do_merge "${file}" "${ofile}"
274 my_input=${?}
275 # [ ${my_input} == 255 ] && my_input=-1
276 continue
277 ;;
278 4) continue
279 ;;
280 *) continue
281 ;;
282 esac
283 done
284 }
285
286 function do_merge() {
287
288 local file="${1}"
289 local ofile="${2}"
290 local mfile="${2}.merged"
291 local -i my_input=0
292 echo "${file} ${ofile} ${mfile}"
293
294 if [ -e ${mfile} ] ; then
295 echo "A previous version of the merged file exists, cleaning..."
296 rm ${rm_opts} ${mfile}
297 fi
298
299 until (( ${my_input} == -1 )); do
300 echo "Merging ${file} and ${ofile}"
301 `echo "${merge_command}" |
302 sed -e "s:%merged:${mfile}:g" \
303 -e "s:%orig:${ofile}:g" \
304 -e "s:%new:${file}:g"`
305 until (( ${my_input} == -1 )); do
306 echo -n "1) Replace ${ofile} with merged file
307 2) Show differences between merged file and original
308 3) Remerge original with update
309 4) Edit merged file
310 5) Return to the previous menu
311 Please select from the menu above (-1 to exit, losing this merge): "
312 read my_input
313 case ${my_input} in
314 1) echo "Replacing ${ofile} with ${mfile}"
315 chmod --reference=${ofile} ${mfile}
316 mv ${mv_opts} ${mfile} ${ofile}
317 rm ${rm_opts} ${file}
318 return 255
319 ;;
320 2) ( echo "Showing differences between ${ofile} and ${mfile}"
321 `echo "${diff_command}" | \
322 sed -e "s:%file1:${ofile}:" \
323 -e "s:%file2:${mfile}:"` ) | ${pager}
324 continue
325 ;;
326 3) break
327 ;;
328 4) ${EDITOR:-nano -w} "${mfile}"
329 continue
330 ;;
331 5) rm ${rm_opts} ${mfile}
332 return 0
333 ;;
334 *) continue
335 ;;
336 esac
337 done
338 done
339 rm ${rm_opts} ${mfile}
340 return 255
341 }
342
343 function die() {
344 trap "" term
345 trap "" kill
346 echo "Exiting: ${1}"
347 rm -rf ${TMP}
348 exit ${2}
349 }
350
351 #
352 # Run the script
353 #
354 scriptname=`basename $0`
355
356 trap die term
357
358 TMP="/tmp/$$"
359 rm -rf ${TMP} 2> /dev/null
360 mkdir ${TMP} || die "failed mkdir command!" 1
361
362 # I need the CONFIG_PROTECT value
363 #CONFIG_PROTECT=$(/usr/lib/portage/bin/portageq config_protect)
364 #CONFIG_PROTECT_MASK=$(/usr/lib/portage/bin/portageq config_protect_mask)
365 source /etc/profile
366
367 # load etc-config's configuration
368 EU_AUTOMERGE=`get_config eu_automerge`
369 rm_opts=`get_config rm_opts`
370 mv_opts=`get_config mv_opts`
371 cp_opts=`get_config cp_opts`
372 pager=`get_config pager`
373 diff_command=`get_config diff_command`
374 using_editor=`get_config using_editor`
375 merge_command=`get_config merge_command`
376 declare -i mode=`get_config mode`
377 [ -z ${mode} ] && mode=0
378 [ -z "${pager}" ] && pager="cat"
379
380 #echo "rm_opts: $rm_opts, mv_opts: $mv_opts, cp_opts: $cp_opts"
381 #echo "pager: $pager, diff_command: $diff_command, merge_command: $merge_command"
382
383 if (( ${mode} == 0 )); then
384 PAR=")"
385 else
386 PAR=""
387 fi
388
389 declare -i count=0
390 declare -i input=0
391 declare title="Gentoolkit's etc-update tool!"
392
393 scan
394
395 until (( ${input} == -1 )); do
396 if (( ${count} == 0 )); then
397 die "Nothing left to do; exiting. :)" 0
398 fi
399 sel_file
400 if (( ${input} != -1 )); then
401 do_file
402 fi
403 done
404
405 die "User termination!" 0

Properties

Name Value
svn:executable *