/var/lib/sorcery/modules/libresurrect
1 #!/bin/bash
2 #---------------------------------------------------------------------
3 ## @Synopsis Functions for dealing with resurrecting a spell
4 ##
5 ## @Copyright Copyright (C) 2005 The Source Mage Team
6 ## <http://www.sourcemage.org>
7 ##
8 ## @Globals TBD
9 ##
10 #---------------------------------------------------------------------
11
12
13 #---------------------------------------------------------------------
14 ## @param spellname
15 ## determines if a particular version of a spell can be resurrected
16 #---------------------------------------------------------------------
17 function can_resurrect() {
18 debug "libresurrect" "can_resurrect - $*"
19 local SPELL=$1
20 local VERSION=$2
21
22 find_cache "$INSTALL_CACHE/$SPELL-$VERSION-$HOST" || return 1
23 debug "libresurrect" "I am able to resurrect."
24 return 0
25 }
26
27 #------------------------------------------------------------------------
28 ## @param spell
29 ## @param version
30 ## @param cache file (optional)
31 ##
32 ## High level overview:
33 ##
34 ## ensure theres a cache tarball
35 ##
36 ## unpack the tarball somewhere
37 ##
38 ## if the spell is installed backup everything
39 ##
40 ## split the files into three categories: state data, config files, regular files
41 ## this can be roughly viewed as (its slightly more complicated)
42 ## state data is data owned by sorcery (/var/state)
43 ## config files are defined in the /var/lib/sorcery/configs file
44 ## things not in the above categories are regular files
45 ##
46 ## copy regular files onto the system
47 ## copy config files carefully (dont trample on user changes)
48 ## if the file does not exist, just copy the new one
49 ## elif the file exists and is identical to the new one, do nothing
50 ## else the file exists and differs from the new one then
51 ## if it is owned by the old spell with a valid md5
52 ## replace the file
53 ## elif it is owned by the old spell with an invalid md5 (admin changed it)
54 ## ask if the user wants to change it
55 ## else the file might be owned by another spell, or might be an alien
56 ## ask if the user wants to change it
57 ##
58 ## if the spell was installed
59 ## remove regular files unique to the old spell
60 ## remove unchanged config files
61 ## ask about changed config files
62 ##
63 ## update state data
64 ## call it a day
65 ##
66 ## FIXME: some of the informative message calls might work better as debug messages
67 #------------------------------------------------------------------------
68 function resurrect_spell() { (
69 debug "libresurrect" "resurrect - $*"
70 local SPELL=$1
71 local VERSION=$2
72 local CACHE_COMP=$3
73
74 spell_held $SPELL && {
75 message "Refusing to resurrect a held spell, please unhold it first"
76 return 1
77 }
78
79 if [[ ! $VERSION ]] ; then
80 debug libresurrect "No spell version passed in"
81 return 1
82 fi
83
84 # 1) if no cache file exists fail
85 if [[ -z $CACHE_COMP ]]; then
86 CACHE_COMP=$(can_resurrect $SPELL $VERSION) || {
87 message "No cache file could be found"
88 return 1
89 }
90 fi
91
92 if test -z $CACHE_COMP || ! test -f $CACHE_COMP ; then
93 message "bug in can_resurrect, failing!"
94 return 1
95 fi
96
97 # 2) become king of the hill
98 acquire_cast_lock
99
100 # 3) setup resurrect sandbox
101
102 local RESURRECT_DIR=$BUILD_DIRECTORY/resurrect-$SPELL-$VERSION
103
104 mkdir -p $BUILD_DIRECTORY &&
105 mk_source_dir $RESURRECT_DIR || {
106 debug "libresurrect" "Failed to make $RESURRECT_DIR"
107 resurrect_fail
108 return 1
109 }
110
111 pushd $RESURRECT_DIR &>/dev/null || {
112 message "Failed to change directories to $RESURRECT_DIR"
113 resurrect_fail
114 return 1
115 }
116
117 # 4) unpack tarball to resurrect dir or fail
118 # note: tarballs are cached relative to $INSTALL_ROOT and $STATE_ROOT
119 # eg, with no special prefix, however install logs are relative to
120 # track_root and state root (isnt this fun?)
121 uncompress_unpack_cache $CACHE_COMP || {
122 message "Failed to unpack $CACHE_COMP"
123 resurrect_fail
124 return 1
125 }
126
127 # 5) if the spell is installed, take its install/md5 logs, and normalize them
128 # every way possible so I dont have to think about it later
129 local installed
130 if spell_ok $SPELL ; then
131 installed=yes
132 # note if installed is not yes, none of this should be assumed to exist
133
134 # welcome to the first ring of pathname adjustment hell
135 local OLD_SPELL_VERSION=$(private_installed_version $SPELL)
136 local OLD_INSTALL_LOG=${INSTALL_LOGS}/$SPELL-$OLD_SPELL_VERSION
137 local OLD_MD5_LOG=${MD5SUM_LOGS}/$SPELL-$OLD_SPELL_VERSION
138
139 local OLD_INSTALL_LOG_F=$TMP_DIR/old.install.$SPELL.filterable
140 local OLD_INSTALL_LOG_R=$TMP_DIR/old.install.$SPELL.root
141
142 local OLD_DATA_F=$TMP_DIR/old.data.$SPELL.filterable
143 local OLD_DATA_R=$TMP_DIR/old.data.$SPELL.root
144 local OLD_DATA_F_C=$TMP_DIR/old.data.$SPELL.filterable.config
145 local OLD_DATA_R_C=$TMP_DIR/old.data.$SPELL.root.config
146 local OLD_DATA_F_NC=$TMP_DIR/old.data.$SPELL.filterable.nonconfig
147 local OLD_DATA_R_NC=$TMP_DIR/old.data.$SPELL.root.nonconfig
148
149 local OLD_MDATA_F=$TMP_DIR/old.mdata.$SPELL.filterable
150 local OLD_MDATA_R=$TMP_DIR/old.mdata.$SPELL.root
151
152 local OLD_MD5_LOG_F=$TMP_DIR/old.md5.$SPELL.filterable
153 local OLD_MD5_LOG_R=$TMP_DIR/old.md5.$SPELL.root
154
155 if test -e $OLD_INSTALL_LOG ; then
156 log_adjuster $OLD_INSTALL_LOG $OLD_INSTALL_LOG_F log filterable
157 log_adjuster $OLD_INSTALL_LOG $OLD_INSTALL_LOG_R log root
158 # dont include the logs in meta-data
159 seperate_state_files $OLD_INSTALL_LOG_F $OLD_DATA_F /dev/stdout |
160 grep -v "$LOG_DIRECTORY" > $OLD_MDATA_F
161 log_adjuster $OLD_DATA_F $OLD_DATA_R filterable root
162 cat $OLD_DATA_F| filter_configs -v > $OLD_DATA_F_C
163 log_adjuster $OLD_DATA_F_C $OLD_DATA_R_C filterable root
164 cat $OLD_DATA_F| filter_configs > $OLD_DATA_F_NC
165 log_adjuster $OLD_DATA_F_NC $OLD_DATA_R_NC filterable root
166 log_adjuster $OLD_MDATA_F $OLD_MDATA_R filterable root
167 fi
168
169 if test -e $OLD_MD5_LOG ; then
170 log_adjuster $OLD_MD5_LOG $OLD_MD5_LOG_F log filterable md5_log_filter
171 log_adjuster $OLD_MD5_LOG $OLD_MD5_LOG_R log root md5_log_filter
172 fi
173 fi
174
175 # 5) if theres a tablet in the cache, load it, otherwise load the
176 # "regular" spell info
177 # load spell or tablet
178
179 # notice the magic dot
180 local TABLET_PATH=.${TABLET_PATH#$STATE_ROOT}
181 local OLD_TABLET_DIR
182 local SPELL_CONFIG_FILTER
183 local SECTION_CONFIG_FILTER
184 local GRIMOIRE_CONFIG_FILTER
185 tablet_find_resurrect_dir $SPELL OLD_TABLET_DIR
186 local TMP_VERSION=$VERSION
187 if [[ $OLD_TABLET_DIR ]] && test -d $OLD_TABLET_DIR ; then
188 debug "libresurrect" "loading tablet at $OLD_TABLET_DIR"
189 tablet_set_spell $SPELL $OLD_TABLET_DIR || {
190 message "something is wrong with $OLD_TABLET_DIR"
191 returrect_fail
192 return 1
193 }
194 tablet_get_spell_filter "$OLD_TABLET_DIR" configs SPELL_CONFIG_FILTER
195 tablet_get_grimoire_filter "$OLD_TABLET_DIR" configs SECTION_CONFIG_FILTER
196 tablet_get_section_filter "$OLD_TABLET_DIR" configs GRIMOIRE_CONFIG_FILTER
197 else
198 unset OLD_TABLET_DIR
199 debug "libresurrect" "no tablet"
200 codex_set_current_spell_by_name $SPELL
201 SPELL_CONFIG_FILTER=$SCRIPT_DIRECTORY/configs
202 SECTION_CONFIG_FILTER=$SECTION_DIRECTORY/configs
203 GRIMOIRE_CONFIG_FILTER=$GRIMOIRE/configs
204 fi
205 local CONFIG_FILTERS="$GRIMOIRE_CONFIG_FILTER $SECTION_CONFIG_FILTER $SPELL_CONFIG_FILTER"
206 # loading the spell may give us a different version which we dont want
207 if [[ $VERSION != $TMP_VERSION ]]; then
208 debug "libresurrect" "restoring VERSION from $VERSION to $TMP_VERSION"
209 fi
210 VERSION=$TMP_VERSION
211
212 # 6) find the cache's install log and divide it up every way imaginable
213 if ! [[ $OLD_TABLET_DIR ]] ; then
214 # in this case we know nothing about how the install log was built, so
215 # we have to make one up
216 local NEW_INSTALL_LOG=$TMP_DIR/new.install.log
217 find . | sed 's/^.//'|
218 log_adjuster /dev/stdin $NEW_INSTALL_LOG filterable log
219 else
220 local NEW_INSTALL_LOG=${INSTALL_LOGS#$STATE_ROOT/}/$SPELL-$VERSION
221 test -f $NEW_INSTALL_LOG || {
222 message "No install log found in unpacked cache, expected $NEW_INSTALL_LOG"
223 resurrect_fail
224 return 1
225 }
226 fi
227
228 # welcome back, did you get cold outside?
229 local NEW_INSTALL_LOG_F=$TMP_DIR/new.install.$SPELL.filterable
230 local NEW_INSTALL_LOG_R=$TMP_DIR/new.install.$SPELL.root
231
232 local NEW_DATA_F=$TMP_DIR/new.data.$SPELL.filterable
233 local NEW_DATA_R=$TMP_DIR/new.data.$SPELL.root
234 local NEW_DATA_F_C=$TMP_DIR/new.data.$SPELL.config.filterable
235 local NEW_DATA_R_C=$TMP_DIR/new.data.$SPELL.config.root
236 local NEW_DATA_F_NC=$TMP_DIR/new.data.$SPELL.nonconfig.filterable
237 local NEW_DATA_R_NC=$TMP_DIR/new.data.$SPELL.nonconfig.root
238
239 local NEW_MDATA_F=$TMP_DIR/new.mdata.$SPELL.filterable
240 local NEW_MDATA_R=$TMP_DIR/new.mdata.$SPELL.root
241
242 log_adjuster $NEW_INSTALL_LOG $NEW_INSTALL_LOG_F log filterable
243 log_adjuster $NEW_INSTALL_LOG $NEW_INSTALL_LOG_R log root
244 seperate_state_files $NEW_INSTALL_LOG_F $NEW_DATA_F $NEW_MDATA_F
245 log_adjuster $NEW_DATA_F $NEW_DATA_R filterable root
246 # cannot use filter_configs here because the tablet is in a
247 # non-standard location and may not exist at all...
248 cat $NEW_DATA_F| filter_in $CONFIGS $CONFIG_FILTERS > $NEW_DATA_F_C
249 log_adjuster $NEW_DATA_F_C $NEW_DATA_R_C filterable root
250 cat $NEW_DATA_F| filter $CONFIGS $CONFIG_FILTERS > $NEW_DATA_F_NC
251 log_adjuster $NEW_DATA_F_NC $NEW_DATA_R_NC filterable root
252 log_adjuster $NEW_MDATA_F $NEW_MDATA_R filterable root
253
254 # now that we have the install logs from the cache sorted out we can
255 # restore these which may have been overridden by tablet
256 tablet_unload_roots
257
258 # 7) take install lock
259 lock_resources "libgrimoire" "install"
260
261 # 8) backup the installed version of the spell
262 if [[ $installed == yes ]] && test -e $OLD_INSTALL_LOG ; then
263 # TODO evaluate the usefulness of this (see note in resurrect_fail
264 #local SAVE_DIR=$RESURRECT_DIR/save.dir.$$
265 #backup_spell $SPELL $SAVE_DIR $OLD_INSTALL_LOG_R || {
266 #message "Failed to backup old installation"
267 #resurrect_fail
268 #return 1
269 #}
270 # its okay to remove this stuff because its presumably been backed up
271 remove_files_and_dirs $OLD_MDATA_R $STATE_ROOT
272 fi
273
274 # 9) remove conflicts, but not self-conflicts, they make no sense
275 # be extra careful to get the right list, since we may be called from within cast
276 local conflicts;
277 if [[ -z $CAST_TMPDIR ]]; then
278 conflicts="$TMP_DIR/list.of.conflicts"
279 > "$conflicts"
280 else
281 conflicts="$CAST_TMPDIR/conflict_list" # the original $CONFLICT_LIST
282 fi
283 # we need the CONFLICTS file for this, but it wasn't unpacked yet
284 # change the SCRIPT_DIRECTORY out of the tablet (in the making) for this
285 # TODO: unpack just this file instead if it turns out there are problems
286 local tmp="$SCRIPT_DIRECTORY"
287 SCRIPT_DIRECTORY=$(codex_find_spell_by_name $SPELL)
288 query_conflicts $SPELL "$conflicts"
289 if [[ $? == 0 ]] && dispel_conflicts $SPELL "$conflicts"; then
290 rm "$conflicts"
291 else
292 rm "$conflicts"
293 resurrect_fail
294 return 1
295 fi
296 SCRIPT_DIRECTORY="$tmp"
297
298 #####
299 # Start of critical region
300 #####
301
302 resurrect_sub || return $?
303
304 #####
305 # End of critical region
306 #####
307
308 resurrect_success
309 unlock_resources "libgrimoire" "install"
310 unlock_resources "cast" "$SPELL"
311 unlock_resources "solo" "cast"
312
313 # do a cleanse --fix if requested (FIXME make this turn off-able)
314 #cleanse --fix $SILENT $SPELL
315
316 # n) run triggers
317 #TABLET_PATH=$STATE_DIRECTORY/tablet # reset to default, was relative
318 #SPELL_CONFIG="$DEPENDS_CONFIG/$SPELL"
319 #run_triggers # doesn't work since the spell isn't installed yet
320
321 return 0
322 ) }
323
324
325 function resurrect_sub() {
326 # 10) if theres a PRE_RESURRECT run it or fail/rollback
327 if test -x $SCRIPT_DIRECTORY/PRE_RESURRECT ; then
328 . $SCRIPT_DIRECTORY/PRE_RESURRECT || {
329 debug "libresurrect" "PRE_RESURRECT failed"
330 resurrect_fail 1
331 return 1
332 }
333 fi
334
335
336 # 11) for each non-config file, all old files are already backed up
337 # tar is nice enough to preserve permissions, atime, etc. for us, using
338 # mkdir and cp it isnt so easy, this also has the advantage of not
339 # totally screwing us if we stomp on some critical libraries.
340 # ld-linux.so.2 anyone?
341 local res_fail=0
342 local verbose
343 [[ $VOYEUR != off ]] && verbose=-v
344 cat $NEW_DATA_F_NC | while read line; do
345 # filterable data also has the clever trait that to make it relative
346 # in this context we prepend a .
347
348 # tar doesnt like directories, but symlinks to directories pass
349 # test -d so handle them specially
350 test -h ".$line" && echo .$line ||
351 test -d ".$line" || echo .$line
352 done | sort | tar -cT - | tar $verbose -xf - -C ${INSTALL_ROOT:-/} || {
353 debug "libresurrect" "Failed to install regular files"
354 resurrect_fail 1
355 return 1
356 }
357 ldconfig # can never be too careful
358
359 # 12) carefully install config files (save old ones too), or fail/rollback
360 # this is interactive and so we must use iterator
361 local savetime=$(date +'%Y%m%d%H%M')
362
363 local res_fail=0 BREAK
364 function resurrect_install_conf_sub() {
365 debug libresurrect "resurrect_install_conf_sub -- $@"
366 test -d ".$1" ||
367 internal_install_config_file ".$1" "${INSTALL_ROOT}${1}" $savetime \
368 "$OLD_MD5_LOG_R" || {
369 res_fail=1
370 BREAK=1
371 }
372 }
373 iterate resurrect_install_conf_sub $'\n' "$(<$NEW_DATA_F_C)"
374
375 [[ $res_fail == 0 ]] || {
376 debug "libresurrect" "Failed to install config files"
377 resurrect_fail 1
378 return 1
379 }
380 ldconfig # paranoia paranoia
381
382 # 13) remove un-replaced files
383 if [[ $installed == yes ]] && test -e $OLD_INSTALL_LOG ; then
384 # show what is in arg 1 but isnt in arg 2
385 # this handles non-configs which can be removed
386 awk -F : 'BEGIN {
387 while (getline < ARGV[2] ) { fc[$1]=1; }
388 while (getline < ARGV[1] ) { if( fc[$1] != 1 ) { print $1; } }
389 }' $OLD_DATA_F_NC $NEW_DATA_F_NC |
390 log_adjuster /dev/stdin $TMP_DIR/leftover.$SPELL.non-config filterable root
391
392 # clear out old files/symlinks
393 remove_files_and_dirs $TMP_DIR/leftover.$SPELL.non-config "$INSTALL_ROOT"
394
395 # this handles configs which must be backed up if they've changed
396 awk -F : 'BEGIN {
397 while (getline < ARGV[2] ) { fc[$1]=1; }
398 while (getline < ARGV[1] ) { if( fc[$1] != 1 ) { print $1; } }
399 }' $OLD_DATA_F_C $NEW_DATA_F_C |
400 log_adjuster /dev/stdin $TMP_DIR/leftover.$SPELL.config filterable root
401 touch $TMP_DIR/leftover.$SPELL.config
402 while read file; do
403 if check_if_modified "$OLD_MD5_LOG"; then
404 reap_modified_file $file
405 fi
406 done < $TMP_DIR/leftover.$SPELL.config
407 fi
408
409 # 14) if theres a POST_RESURRECT run it
410 if test -x $SCRIPT_DIRECTORY/POST_RESURRECT ; then
411 . $SCRIPT_DIRECTORY/POST_RESURRECT || {
412 message "POST_RESURRECT failed"
413 resurrect_fail 1
414 return 1
415 }
416 fi
417 ldconfig # can never be too careful
418 }
419
420
421 #------------------------------------------------------------------------
422 ## @param from File we might want to install
423 ## @param to File to replace
424 ## @param savetime Backup time if necessary (optional, defaults to $(date +'%Y%m%d%H%M')
425 #------------------------------------------------------------------------
426 function real_install_config_file() {
427 if [[ ! $1 ]] || [[ ! $2 ]] ; then
428 message "${PROBLEM_COLOR}Missing values for arguments \"$1\" or \"$2\"" \
429 "$DEFAULT_COLOR"
430 return 1
431 fi
432
433 local old_md5_log
434 if [[ $OLD_SPELL_VERSION ]] ; then
435 old_md5_log=$MD5SUM_LOGS/$SPELL-$OLD_SPELL_VERSION
436 # log must be in filterable form
437 log_adjuster "$old_md5_log" "$TMP_DIR/$SPELL.md5" filterable root
438 else
439 old_md5_log=/dev/null
440 fi
441 local savetime=${3:-$(date +'%Y%m%d%H%M')}
442 internal_install_config_file "$1" "$2" $savetime $TMP_DIR/$SPELL.md5
443 rc=$?
444 [[ $OLD_SPELL_VERSION ]] && rm $TMP_DIR/$SPELL.md5
445
446 return $rc
447 }
448
449 #------------------------------------------------------------------------
450 ## @param from File we might want to install
451 ## @param to File to replace
452 ## @param savetime Backup time if necessary
453 ## @param md5_log MD5 log for previous version of the spell, must be in root form
454 #------------------------------------------------------------------------
455 function internal_install_config_file() {
456 local from=$1
457 local to=$2
458 local savetime=$3
459 local md5_log=$4
460
461 debug libresurrect "$FUNCNAME -- $@"
462 # if its a symlink, just copy, someday maybe we should figure
463 # out where it points to and so something, but thats too annoying
464 if test -h "$from" ; then
465 mkdir -p "$(smgl_dirname "$to")" &&
466 cp -v --no-dereference --preserve=mode,timestamps "$from" "$to"
467 return $?
468 fi
469
470 # if the file does not exist, or stage root is invoked
471 if ! test -e "$to" || [[ $STAGED_INSTALL == on ]] ; then
472 # copy the new one in (plus leading directories)
473 mkdir -p "$(smgl_dirname "$to")" &&
474 cp -v --preserve=mode,timestamps "$from" "$to"
475 # to get here the file must exist
476 elif test -d "$to"; then
477 message "Trying to install a file ($from) to what was a directory ($to), I dont know what to do!"
478 return 1
479
480 # elif the file exists and is identical to the new one
481 elif cmp "$to" "$from" &>/dev/null; then
482 echo "$from"
483 # preserve modification status
484 if check_if_modified "$to" "$md5_log" ; then
485 mark_file_modified "$to"
486 fi
487 # else the file exists and differs from the new one then
488 else
489 # if it is owned by the old spell with a valid md5
490 # note that the md5_log is a subset of the install log, so if it
491 # matches in the md5 log, it is owned by the spell
492 if check_if_modified "$to" "$md5_log" ; then
493 # it is owned by the old spell with an invalid md5 OR
494 # the file might be owned by another spell OR
495 # might be an alien, all lead to the same direction
496 # note, it might be nice to split the above cases out for more informative
497 # user messages
498 real_handle_changed_config "$from" "$to" $savetime
499 else
500 # replace the file
501 mkdir -p "$(smgl_dirname "$to")" &&
502 cp -v --preserve=mode,timestamps "$from" "$to"
503 fi
504 fi
505 }
506
507 #------------------------------------------------------------------------
508 ## @param from File we might want to install
509 ## @param to File to replace
510 ## @param savetime Backup time if necessary
511 ##
512 ## Present the user with the following menu
513 ## (0) trash $to and install over it
514 ## (1) backup $to to $to.$savetime, install the new file in its place
515 ## (2) leave $to in its place, copy the new file to $to.$savetime
516 ## (3) do nothing
517 ## (4) see a diff between $to and the new file
518 ## choice 2 is currently the default, someday there will be a menu to
519 ## choose what the default will be
520 #------------------------------------------------------------------------
521 function real_handle_changed_config() {
522 local from=$1
523 local to=$2
524 local savetime=$3
525 local number
526 local default=$DEFAULT_CHANGED_CONFIG_ACTION
527
528 local continue=yes
529 message "${MESSAGE_COLOR}Installing to $to, please choose an option:"
530 while [[ "$continue" == "yes" ]] ; do
531 message -n "${QUERY_COLOR}"
532 message "(0) trash $to and install over it"
533 message "(1) backup $to to $to.$savetime.old, install the new file in its place"
534 message "(2) leave $to in its place, copy the new file to $to.$savetime.new"
535 message "(3) do nothing - leave $to in its place, discard new file"
536 message "(4) see a diff between $to and the new file"
537 # TODO: someday add an option to use an external merge tool
538
539 number=""
540 while [[ $number != [0-9]* ]] || (( " $number >= 5 " )); do
541 message -n "\n${QUERY_COLOR}Which one do you want? [$default]" \
542 "$DEFAULT_COLOR"
543 read -n 1 -t $PROMPT_DELAY number
544 if [[ ! -n $number ]]; then
545 number=$default
546 fi
547 done
548 echo
549 case $number in
550 0) cp -v --preserve=mode,timestamps "$from" "$to"
551 break ;;
552 1) cp -v --preserve=mode,timestamps "$to" "$to.$savetime.old"
553 cp -v --preserve=mode,timestamps "$from" "$to"
554 break ;;
555 2) cp -v --preserve=mode,timestamps "$from" "$to.$savetime.new"
556 mark_file_modified "$to"
557 # this is deliberatly not track_manual, if this is run from
558 # FINAL the user might not have wanted the files tracked
559 # so we wont make an assumption on what the user intends
560 touch "$to"
561 break ;;
562 3) mark_file_modified "$to"
563 touch "$to"
564 break ;;
565 4) diff -u "$to" "$from" | $PAGER;;
566 esac
567 message "\n\nPlease select another option"
568 done
569
570 }
571
572 function resurrect_success() {
573
574 local INSTALL_LOG=$INSTALL_LOGS/$SPELL-$VERSION
575 local MD5_LOG=$MD5SUM_LOGS/$SPELL-$VERSION
576 local TMP_INSTALL_LOG_STATE=$TMP_DIR/$SPELL.tmp.ilog.state
577 local TMP_INSTALL_LOG_DATA=$TMP_DIR/$SPELL.tmp.ilog.data
578 local TMP_INSTALL_LOG=$TMP_DIR/$SPELL.tmp.ilog.all
579
580 # 14) copy compile log
581 # this file is not regenerated unlike its friends install and md5sum
582 local OLD_COMPILE_LOG=$(find .${COMPILE_LOGS#$INSTALL_ROOT}/ -maxdepth 1 -type f|head -n 1)
583 local COMPILE_LOG="$COMPILE_LOGS/$(smgl_basename "$OLD_COMPILE_LOG")"
584 # also relative to STATE_ROOT
585 cp "$OLD_COMPILE_LOG" "$COMPILE_LOG"
586
587 # 15) commit state data:
588 if [[ $OLD_TABLET_DIR ]] ; then
589 # depends info if it exists
590 # none of the old values are valid, only the new, uncommitted values are
591 remove_depends_status $DEPENDS_STATUS $SPELL
592 local spell_depends=$OLD_TABLET_DIR/depends
593 local t_DEPENDS_STATUS t_SUB_DEPENDS_STATUS
594 lock_start_transaction "$DEPENDS_STATUS" t_DEPENDS_STATUS
595 if [ -e $spell_depends ] ; then
596 cat $spell_depends >> $t_DEPENDS_STATUS
597 fi
598 lock_commit_transaction $DEPENDS_STATUS
599
600 remove_sub_depends $SUB_DEPENDS_STATUS ".*" $SPELL
601 local spell_sub_depends=$OLD_TABLET_DIR/sub_depends
602 if [[ -e $spell_sub_depends ]]; then
603 lock_start_transaction "$SUB_DEPENDS_STATUS" t_SUB_DEPENDS_STATUS
604 cat $spell_sub_depends >> $t_SUB_DEPENDS_STATUS
605 lock_commit_transaction $SUB_DEPENDS_STATUS
606 fi
607
608 # if theres a tablet dir, store it with a new timestamp
609 if new_tablet=$(tablet_get_path $SPELL) ; then
610 cp -Rp $OLD_TABLET_DIR/* $new_tablet
611 ln $INSTALL_LOG -sf $new_tablet/logs/install
612 ln $MD5_LOG -sf $new_tablet/logs/md5sum
613 ln $COMPILE_LOG -sf $new_tablet/logs/compile
614 find $new_tablet > $TMP_INSTALL_LOG_STATE # relative to STATE_ROOT
615 else
616 debug "libresurrect" "WARNING: unable to make tablet for $SPELL, oh well"
617 fi
618 fi
619
620
621 echo $COMPILE_LOG >> $TMP_INSTALL_LOG_STATE
622 echo $INSTALL_LOG >> $TMP_INSTALL_LOG_STATE
623 echo $MD5_LOG >> $TMP_INSTALL_LOG_STATE
624
625 # Use the cache's listing of files in filterable form
626 # dont use root form because it may be different
627 log_adjuster $NEW_DATA_F $TMP_INSTALL_LOG_DATA filterable root
628 cat $TMP_INSTALL_LOG_STATE $TMP_INSTALL_LOG_DATA > $TMP_INSTALL_LOG
629 log_adjuster $TMP_INSTALL_LOG $INSTALL_LOG root log
630
631 create_md5list $TMP_INSTALL_LOG /dev/stdout |
632 log_adjuster /dev/stdin $MD5_LOG root log md5_log_filter
633
634 tablet_check_version_cache "$VERSION_STATUS" &&
635 (
636 if [[ $new_tablet ]]; then
637 tablet_get_patchlevel $new_tablet PATCHLEVEL
638 tablet_get_security_patch $new_tablet SECURITY_PATCH
639 tablet_get_updated $new_tablet UPDATED
640 else
641 debug "libresurrect" "bad tablet for version cache; new_tablet: $new_tablet"
642 # we don't have a good tablet, so we don't know what we just resurrected
643 # insert dummy values
644 UPDATED=0
645 PATCHLEVEL=0
646 SECURITY_PATCH=0
647 fi
648 add_version_cache "$VERSION_STATUS" "$SPELL" "$VERSION" "$PATCHLEVEL" "$SECURITY_PATCH" "$UPDATED"
649 )
650
651 # add packages line
652 add_spell "$SPELL" "installed" "$VERSION"
653
654 pop_install_queue "$SPELL"
655 echo $SPELL >> $SUCCESS_LIST
656
657 popd &>/dev/null
658
659 rm_source_dir $RESURRECT_DIR
660
661 clear_line
662 activity_log "resurrect" "$SPELL" "$VERSION" "success"
663 message "${RESURRECT_COLOR}Resurrected spell: ${SPELL_COLOR}${SPELL}${DEFAULT_COLOR}" \
664 "version ${VERSION_COLOR}${VERSION}${DEFAULT_COLOR}"
665 }
666
667
668 function resurrect_fail() {
669 message "${PROBLEM_COLOR}Resurrect failed for spell:" \
670 "${SPELL_COLOR}${SPELL}${DEFAULT_COLOR} version" \
671 "${VERSION_COLOR}${VERSION}${DEFAULT_COLOR}"
672
673 #if [[ $1 == 1 ]] ; then
674 #TODO evaluate the usefulness of a backup/rollback scheme
675 # this would be the location in which to do rollback, however
676 # I think it adds needless complexity and can be dangerous
677 # also, it shouldnt be needed in a properly functioning resurrect
678 #fi
679
680 unlock_resources "libgrimoire" "install"
681 unlock_resources "cast" "$SPELL"
682 unlock_resources "solo" "cast"
683
684 [[ $CLEAN_SOURCE == on ]] && rm_source_dir $RESURRECT_DIR 2>/dev/null
685
686 echo $SPELL >> $FAILED_LIST
687 }
688
689 #---------------------------------------------------------------------
690 ## @License
691 ##
692 ## This software is free software; you can redistribute it and/or modify
693 ## it under the terms of the GNU General Public License as published by
694 ## the Free Software Foundation; either version 2 of the License, or
695 ## (at your option) any later version.
696 ##
697 ## This software is distributed in the hope that it will be useful,
698 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
699 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
700 ## GNU General Public License for more details.
701 ##
702 ## You should have received a copy of the GNU General Public License
703 ## along with this software; if not, write to the Free Software
704 ## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
705 ##
706 #---------------------------------------------------------------------