#!/bin/bash
#---------------------------------------------------------------------
## @Synopsis Functions for dealing with resurrecting a spell
##
## @Copyright Copyright (C) 2005 The Source Mage Team
## &lt;http://www.sourcemage.org&gt;
##
## @Globals TBD
##
#---------------------------------------------------------------------


#---------------------------------------------------------------------
## @param spellname
## determines if a particular version of a spell can be cast
## test -f $INSTALL_CACHE/$SPELL-$VERSION-$HOST.tar.bz2
#---------------------------------------------------------------------
function can_resurrect()  {
  debug "libresurrect" "can_resurrect - $*"
  local SPELL=$1
  local VERSION=$2
  
  # FIXME accept files of other extensions
  local file=$INSTALL_CACHE/$SPELL-$VERSION-$HOST.tar$EXTENSION &&
  test -f $file &&
  echo $file &&
  debug "libresurrect" "I am able to resurrect." &&
  return 0
}

#------------------------------------------------------------------------
# @param spell 
# @param version
#
# High level overview:
#
# ensure theres a cache tarball
#
# unpack the tarball somewhere
#
# if the spell is installed backup everything
#
# split the files into three categories: state data, config files, regular files
#   this can be roughly viewed as (its slightly more complicated)
#   state data is data owned by sorcery (/var/state)
#   config files are defined in the /var/lib/sorcery/configs file
#   things not in the above categories are regular files
#
# copy regular files onto the system
# copy config files carefully (dont trample on user changes)
#   if the file does not exist, just copy the new one
#   elif the file exists and is identical to the new one, do nothing
#   else the file exists and differs from the new one then
#     if it is owned by the old spell with a valid md5
#       replace the file
#     elif it is owned by the old spell with an invalid md5 (admin changed it)
#       ask if the user wants to change it
#     else the file might be owned by another spell, or might be an alien
#       ask if the user wants to change it
#
# if the spell was installed
#   remove regular files unique to the old spell
#   remove unchanged config files
#   ask about changed config files
# 
# update state data
# call it a day
#
# FIXME: some of the informative message calls might work better as debug messages
#------------------------------------------------------------------------
function resurrect()  { (
  debug "libresurrect" "resurrect - $*"
  local SPELL=$1
  local VERSION=$2

  spell_held $SPELL && {
    message "Refusing to resurrect a held spell, please unhold it first"
    return 1
  }

  if [[ ! $VERSION ]] ; then
    debug libresurrect "No spell version passed in"
    return 1
  fi

  # 1) if no cache file exists fail

  local CACHE_COMP=$(can_resurrect $SPELL $VERSION) || {
    message "No cache file could be found"
    return 1
  }

  if test -z $CACHE_COMP || ! test -f $CACHE_COMP ; then
    message "bug in can_resurrect, failing!"
    return 1
  fi

  # 2) become king of the hill
  acquire_cast_lock

  # 3) setup resurrect sandbox

  local RESURRECT_DIR=$BUILD_DIRECTORY/resurrect-$SPELL-$VERSION

  mkdir -p $BUILD_DIRECTORY &&
  mk_source_dir $RESURRECT_DIR || {
    debug "libresurrect" "Failed to make $RESURRECT_DIR"
    resurrect_fail
    return 1
  }

  pushd $RESURRECT_DIR &>/dev/null || {
    message "Failed to change directories to $RESURRECT_DIR"
    resurrect_fail
    return 1
  }

  # 4) unpack tarball to resurrect dir or fail
  # note: tarballs are cached relative to $INSTALL_ROOT and $STATE_ROOT
  # eg, with no special prefix, however install logs are relative to
  # track_root and state root (isnt this fun?)

  # FIXME get a generic routine to unpack this stuff
  if  [  -n  "$EXTENSION"  ];  then
    $COMPRESSBIN   -cd   $CACHE_COMP  |  tar  -x  1>/dev/null  2>&1
  else
    tar  -xf  $CACHE_COMP  1>/dev/null  2>&1
  fi || {
    message "Failed to unpack $CACHE_COMP"
    resurrect_fail
    return 1
  }

  # 5) if the spell is installed, take its install/md5 logs, and normalize them
  # every way possible so I dont have to think about it later
  local installed
  if spell_ok $SPELL ; then
    installed=yes
    # note if installed is not yes, none of this should be assumed to exist

    # welcome to the first ring of pathname adjustment hell
    local OLD_SPELL_VERSION=$(installed_version $SPELL)
    local OLD_INSTALL_LOG=${INSTALL_LOGS}/$SPELL-$OLD_SPELL_VERSION
    local OLD_MD5_LOG=${MD5SUM_LOGS}/$SPELL-$OLD_SPELL_VERSION

    local OLD_INSTALL_LOG_F=$TMP_DIR/old.install.$SPELL.filterable
    local OLD_INSTALL_LOG_R=$TMP_DIR/old.install.$SPELL.root

    local OLD_DATA_F=$TMP_DIR/old.data.$SPELL.filterable
    local OLD_DATA_R=$TMP_DIR/old.data.$SPELL.root
    local OLD_DATA_F_C=$TMP_DIR/old.data.$SPELL.filterable.config
    local OLD_DATA_R_C=$TMP_DIR/old.data.$SPELL.root.config
    local OLD_DATA_F_NC=$TMP_DIR/old.data.$SPELL.filterable.nonconfig
    local OLD_DATA_R_NC=$TMP_DIR/old.data.$SPELL.root.nonconfig

    local OLD_MDATA_F=$TMP_DIR/old.mdata.$SPELL.filterable
    local OLD_MDATA_R=$TMP_DIR/old.mdata.$SPELL.root

    local OLD_MD5_LOG_F=$TMP_DIR/old.md5.$SPELL.filterable
    local OLD_MD5_LOG_R=$TMP_DIR/old.md5.$SPELL.root

    if test -e $OLD_INSTALL_LOG ; then
      log_adjuster $OLD_INSTALL_LOG $OLD_INSTALL_LOG_F log filterable
      log_adjuster $OLD_INSTALL_LOG $OLD_INSTALL_LOG_R log root
      # dont include the logs in meta-data
      seperate_state_files $OLD_INSTALL_LOG_F $OLD_DATA_F /dev/stdout |
      grep -v "$LOG_DIRECTORY" > $OLD_MDATA_F
      log_adjuster $OLD_DATA_F $OLD_DATA_R filterable root
      cat $OLD_DATA_F| filter_configs -v > $OLD_DATA_F_C
      log_adjuster $OLD_DATA_F_C $OLD_DATA_R_C filterable root
      cat $OLD_DATA_F| filter_configs > $OLD_DATA_F_NC
      log_adjuster $OLD_DATA_F_NC $OLD_DATA_R_NC filterable root
      log_adjuster $OLD_MDATA_F $OLD_MDATA_R filterable root
    fi

    if test -e $OLD_MD5_LOG ; then
      log_adjuster $OLD_MD5_LOG $OLD_MD5_LOG_F log filterable md5_log_filter
      log_adjuster $OLD_MD5_LOG $OLD_MD5_LOG_R log root md5_log_filter
    fi
  fi

  # 5) if theres a tablet in the cache, load it, otherwise load the
  # "regular" spell info
  # load spell or tablet

  # notice the magic dot
  local TABLET_PATH=.${TABLET_PATH#$STATE_ROOT}
  local OLD_TABLET_DIR
  local SPELL_CONFIG_FILTER
  local SECTION_CONFIG_FILTER
  local GRIMOIRE_CONFIG_FILTER
  tablet_find_resurrect_dir $SPELL OLD_TABLET_DIR
  local TMP_VERSION=$VERSION
  if [[ $OLD_TABLET_DIR ]] && test -d $OLD_TABLET_DIR ; then
    debug "libresurrect" "loading tablet at $OLD_TABLET_DIR"
    tablet_set_spell $SPELL $OLD_TABLET_DIR || {
      message "something is wrong with $OLD_TABLET_DIR"
      returrect_fail
      return 1
    }
    tablet_get_spell_filter "$OLD_TABLET_DIR" configs SPELL_CONFIG_FILTER
    tablet_get_grimoire_filter "$OLD_TABLET_DIR" configs SECTION_CONFIG_FILTER
    tablet_get_section_filter "$OLD_TABLET_DIR" configs GRIMOIRE_CONFIG_FILTER
  else
    unset $OLD_TABLET_DIR
    debug "libresurrect" "no tablet"
    codex_set_current_spell_by_name $SPELL
    SPELL_CONFIG_FILTER=$SCRIPT_DIRECTORY/configs
    SECTION_CONFIG_FILTER=$SECTION_DIRECTORY/configs
    GRIMOIRE_CONFIG_FILTER=$GRIMOIRE/configs
    # loading the spell may give us a different version which we dont want
  fi
  local CONFIG_FILTERS="$GRIMOIRE_CONFIG_FILTER $SECTION_CONFIG_FILTER $SPELL_CONFIG_FILTER"
  VERSION=${VERSION:-TMP_VERSION}

  # 6) find the cache's install log and divide it up every way imaginable
  if ! [[ $OLD_TABLET_DIR ]] ; then
    # in this case we know nothing about how the install log was built, so
    # we have to make one up
    local NEW_INSTALL_LOG=$TMP_DIR/new.install.log
    find . | sed 's/^.//'|
    log_adjuster /dev/stdin $NEW_INSTALL_LOG filterable log
  else
    local NEW_INSTALL_LOG=${INSTALL_LOGS#$STATE_ROOT/}/$SPELL-$VERSION
    test -f $NEW_INSTALL_LOG || {
      message "No install log found in unpacked cache, expected $INSTALL_LOG"
      resurrect_fail
      return 1
    }
  fi

  # welcome back, did you get cold outside?
  local NEW_INSTALL_LOG_F=$TMP_DIR/new.install.$SPELL.filterable
  local NEW_INSTALL_LOG_R=$TMP_DIR/new.install.$SPELL.root

  local NEW_DATA_F=$TMP_DIR/new.data.$SPELL.filterable
  local NEW_DATA_R=$TMP_DIR/new.data.$SPELL.root
  local NEW_DATA_F_C=$TMP_DIR/new.data.$SPELL.config.filterable
  local NEW_DATA_R_C=$TMP_DIR/new.data.$SPELL.config.root
  local NEW_DATA_F_NC=$TMP_DIR/new.data.$SPELL.nonconfig.filterable
  local NEW_DATA_R_NC=$TMP_DIR/new.data.$SPELL.nonconfig.root

  local NEW_MDATA_F=$TMP_DIR/new.mdata.$SPELL.filterable
  local NEW_MDATA_R=$TMP_DIR/new.mdata.$SPELL.root

  log_adjuster $NEW_INSTALL_LOG $NEW_INSTALL_LOG_F log filterable
  log_adjuster $NEW_INSTALL_LOG $NEW_INSTALL_LOG_R log root
  seperate_state_files $NEW_INSTALL_LOG_F $NEW_DATA_F $NEW_MDATA_F
  log_adjuster $NEW_DATA_F $NEW_DATA_R filterable root
  # cannot use filter_configs here because the tablet is in a
  # non-standard location and may not exist at all...
  cat $NEW_DATA_F| filter_in $CONFIGS $CONFIG_FILTERS > $NEW_DATA_F_C
  log_adjuster $NEW_DATA_F_C $NEW_DATA_R_C filterable root
  cat $NEW_DATA_F| filter $CONFIGS $CONFIG_FILTERS > $NEW_DATA_F_NC
  log_adjuster $NEW_DATA_F_NC $NEW_DATA_R_NC filterable root
  log_adjuster $NEW_MDATA_F $NEW_MDATA_R filterable root

  # now that we have the install logs from the cache sorted out we can
  # restore these which may have been overridden by tablet
  tablet_unload_roots

  # 7) take install lock
  lock_resources "libgrimoire" "install"

  # 8) backup the installed version of the spell
  if [[ $installed == yes ]] && test -e $OLD_INSTALL_LOG ; then
    # TODO evaluate the usefulness of this (see note in resurrect_fail
    #local SAVE_DIR=$RESURRECT_DIR/save.dir.$$
    #backup_spell $SPELL $SAVE_DIR $OLD_INSTALL_LOG_R || {
      #message "Failed to backup old installation"
      #resurrect_fail
      #return 1
    #}
    # its okay to remove this stuff because its presumably been backed up
    remove_files_and_dirs $OLD_MDATA_R $STATE_ROOT
  fi

  # 9) remove conflicts, but not self-conflicts, they make no sense
  run_conflicts $SPELL || {
    resurrect_fail
    return 1
  }

  #####
  # Start of critical region
  #####

  resurrect_sub || return $?

  #####
  # End of critical region
  #####

  resurrect_success
  unlock_resources "libgrimoire" "install"
  unlock_resources "cast" "$SPELL"
  unlock_resources "solo" "cast"

  # do a cleanse --fix if requested (FIXME make this turn off-able)
  #cleanse --fix  $SILENT  $SPELL

  # n) run triggers
  #run_triggers

  return 0
) }


function resurrect_sub() {
  # 10) if theres a PRE_RESURRECT run it or fail/rollback
  if test -x $SCRIPT_DIRECTORY/PRE_RESURRECT ; then
    . $SCRIPT_DIRECTORY/PRE_RESURRECT || {
      debug "libresurrect" "PRE_RESURRECT failed"
      resurrect_fail 1
      return 1
    }
  fi


  # 11) for each non-config file, all old files are already backed up
  # tar is nice enough to preserve permissions, atime, etc. for us, using
  # mkdir and cp it isnt so easy, this also has the advantage of not
  # totally screwing us if we stomp on some critical libraries.
  # ld-linux.so.2 anyone?
  local res_fail=0
  cat $NEW_DATA_F_NC | while read line; do
    # filterable data also has the clever trait that to make it relative
    # in this context we prepend a .

    # tar doesnt like directories, but symlinks to directories pass
    # test -d so handle them specially
    test -h ".$line" && echo .$line ||
    test -d ".$line" || echo .$line
  done | sort | tar -cT - | tar -xvf - -C ${INSTALL_ROOT:-/} || { 
    debug "libresurrect" "Failed to install regular files"
    resurrect_fail 1
    return 1
  }
  ldconfig # can never be too careful

  # 12) carefully install config files (save old ones too), or fail/rollback
  # this is interactive and so we must use iterator
  local savetime=$(date +'%Y%m%d%H%M')

  local res_fail=0 BREAK
  function resurrect_install_conf_sub() {
    debug libresurrect "resurrect_install_conf_sub -- $@"
    test -d ".$1" ||
    internal_install_config_file ".$1" "${INSTALL_ROOT}${1}" $savetime \
                                                         "$OLD_MD5_LOG" || {
      res_fail=1
      BREAK=1
    }
  }
  iterate resurrect_install_conf_sub $'\n' "$(<$NEW_DATA_F_C)"

  [[ $res_fail == 0 ]] || {
    debug "libresurrect" "Failed to install config files"
    resurrect_fail 1
    return 1
  }
  ldconfig # paranoia paranoia

  # 13) remove un-replaced files
  if [[ $installed == yes ]] && test -e $OLD_INSTALL_LOG ; then
    # show what is in arg 1 but isnt in arg 2
    # this handles non-configs which can be removed
    awk -F : 'BEGIN {
      while (getline < ARGV[2] ) { fc[$1]=1; }
      while (getline < ARGV[1] ) { if( fc[$1] != 1 ) { print $1; } }
    }' $OLD_DATA_F_NC $NEW_DATA_F_NC |
    log_adjuster /dev/stdin  $TMP_DIR/leftover.$SPELL.non-config filterable root

    # clear out old files/symlinks
    remove_files_and_dirs $TMP_DIR/leftover.$SPELL.non-config "$INSTALL_ROOT"

    # this handles configs which must be backed up if they've changed
    awk -F : 'BEGIN {
      while (getline < ARGV[2] ) { fc[$1]=1; }
      while (getline < ARGV[1] ) { if( fc[$1] != 1 ) { print $1; } }
    }' $OLD_DATA_F_C $NEW_DATA_F_C |
    log_adjuster /dev/stdin  $TMP_DIR/leftover.$SPELL.config filterable root
    touch $TMP_DIR/leftover.$SPELL.config
    while read file; do
      if check_if_modified "$OLD_MD5_LOG"; then
        reap_modified_file $file
      fi
    done < $TMP_DIR/leftover.$SPELL.config
  fi

  # 14) if theres a POST_RESURRECT run it
  if test -x $SCRIPT_DIRECTORY/POST_RESURRECT ; then
    . $SCRIPT_DIRECTORY/POST_RESURRECT || {
      message "POST_RESURRECT failed"
      resurrect_fail 1
      return 1
    }
  fi
  ldconfig # can never be too careful
}


#------------------------------------------------------------------------
## @param from	File we might want to install
## @param to	File to replace
## @param savetime	Backup time if necessary (optional, defaults to
##                      $(date +'%Y%m%d%H%M')
#------------------------------------------------------------------------
function real_install_config_file() {
  if [[ ! $1 ]] || [[ ! $2 ]] ; then
    message "${PROBLEM_COLOR}Missing values for arguments \"$1\" or \"$2\"" \
            "$DEFAULT_COLOR"
    return 1
  fi
  
  local old_md5_log
  if [[ $OLD_SPELL_VERSION ]] ; then
    old_md5_log=$MD5SUM_LOGS/$SPELL-$OLD_SPELL_VERSION
    # log must be in filterable form
    log_adjuster "$old_md5_log" "$TMP_DIR/$SPELL.md5" filterable root
  else
    old_md5_log=/dev/null
  fi
  local savetime=${3:-$(date +'%Y%m%d%H%M')}
  internal_install_config_file "$1" "$2" $savetime $TMP_DIR/$SPELL.md5
  rc=$?
  [[ $OLD_SPELL_VERSION ]] && rm $TMP_DIR/$SPELL.md5

  return $rc
}

#------------------------------------------------------------------------
## @param from	File we might want to install
## @param to	File to replace
## @param savetime	Backup time if necessary
## @param md5_log	MD5 log for previous version of the spell,
#                       must be in root form
#------------------------------------------------------------------------
function internal_install_config_file() {
  local from=$1
  local to=$2
  local savetime=$3
  local md5_log=$4

  debug libresurrect "$FUNCNAME -- $@"
  # if its a symlink, just copy, someday maybe we should figure
  # out where it points to and so something, but thats too annoying
  if test -h "$from" ; then
    mkdir -p "$(dirname "$to")" &&
    cp -pv --no-dereference "$from" "$to"
    return $?
  fi

  # if the file does not exist, 
  if ! test -e "$to"; then
    # copy the new one in (plus leading directories)
    mkdir -p "$(dirname "$to")" &&
    cp -pv "$from" "$to"

  # to get here the file must exist
  elif test -d "$to"; then
    message "Trying to install a file ($from) to what was a directory ($to), I dont know what to do!"
    return 1

  # elif the file exists and is identical to the new one
  elif cmp "$to" "$from" &>/dev/null; then
    echo "$from"
    # preserve modification status
    if check_if_modified "$to" "$md5_log"  ; then
      mark_file_modified "$to"
    fi
  # else the file exists and differs from the new one then
  else
    # if it is owned by the old spell with a valid md5
    # note that the md5_log is a subset of the install log, so if it
    # matches in the md5 log, it is owned by the spell
    if check_if_modified "$to" "$md5_log" ; then
      # it is owned by the old spell with an invalid md5 OR
      # the file might be owned by another spell OR
      # might be an alien, all lead to the same direction
      # note, it might be nice to split the above cases out for more informative
      # user messages
      real_handle_changed_config "$from" "$to" $savetime
    else
      # replace the file
      mkdir -p "$(dirname "$to")" &&
      cp -pv "$from" "$to"
    fi
  fi
}

#------------------------------------------------------------------------
## @param from	File we might want to install
## @param to	File to replace
## @param savetime	Backup time if necessary
##
## Present the user with the following menu
## (0) trash $to and install over it
## (1) backup $to to $to.$savetime, install the new file in its place
## (2) leave $to in its place, copy the new file to $to.$savetime
## (3) do nothing
## (4) see a diff between $to and the new file
## choice 2 is currently the default, someday there will be a menu to
## choose what the default will be
#------------------------------------------------------------------------
function real_handle_changed_config() {
  local from=$1
  local to=$2
  local savetime=$3
  local number
  local default=2 # TODO: this should come from a variable someday

  local continue=yes
  message "${MESSAGE_COLOR}Installing to $to, please choose an option:"
  while [[ "$continue" == "yes" ]] ; do
    message "${QUERY_COLOR}"
    message "(0) trash $to and install over it"
    message "(1) backup $to to $to.$savetime, install the new file in its place"
    message "(2) leave $to in its place, copy the new file to $to.$savetime"
    message "(3) do nothing"
    message "(4) see a diff between $to and the new file"
    # TODO: someday add an option to use an external merge tool

    number=""
    while [[ $number != [0-9]* ]] || (( " $number >= 5 " )); do
      message -n "\n${QUERY_COLOR}Which one do you want? [$default]" \
                 "$DEFAULT_COLOR"
      read -n 1 -t $PROMPT_DELAY number
      if [[ ! -n $number ]]; then
          number=$default
      fi
    done
    echo
    case $number in
      0)  cp -pv "$from" "$to"
          break ;;
      1)  cp -pv "$to" "$to.$savetime"
          cp -pv "$from" "$to"
          break ;;
      2)  cp -pv "$from" "$to.$savetime"
          mark_file_modified "$to"
          # this is deliberatly not track_manual, if this is run from
          # FINAL the user might not have wanted the files tracked
          # so we wont make an assumption on what the user intends
          touch "$to"
          break ;;
      3)  mark_file_modified "$to"
          touch "$to"
          break ;;
      4)  diff "$to" "$from" | $PAGER;;
    esac
    message "\n\nPlease select another option"
  done

}

function resurrect_success() {

  local INSTALL_LOG=$INSTALL_LOGS/$SPELL-$VERSION
  local MD5_LOG=$MD5SUM_LOGS/$SPELL-$VERSION
  local TMP_INSTALL_LOG_STATE=$TMP_DIR/$SPELL.tmp.ilog.state
  local TMP_INSTALL_LOG_DATA=$TMP_DIR/$SPELL.tmp.ilog.data
  local TMP_INSTALL_LOG=$TMP_DIR/$SPELL.tmp.ilog.all

  # 14) copy compile log
  # this file is not regenerated unlike its friends install and md5sum
  local OLD_COMPILE_LOG=$(find .${COMPILE_LOGS#$INSTALL_ROOT}/ -maxdepth 1 -type f|head -n 1)
  local COMPILE_LOG="$COMPILE_LOGS/$(basename "$OLD_COMPILE_LOG")"
  # also relative to STATE_ROOT
  cp "$OLD_COMPILE_LOG" "$COMPILE_LOG"

  # 15) commit state data:
  if [[ $OLD_TABLET_DIR ]] ; then
    # depends info if it exists
    local t_DEPENDS_STATUS=$(lock_start_transaction "$DEPENDS_STATUS")
    # none of the old values are valid, only the new, uncommitted values are
    remove_depends_status $t_DEPENDS_STATUS $SPELL
    local spell_depends=$OLD_TABLET_DIR/depends
    if [ -e $spell_depends ] ; then
      cat  $spell_depends >> $t_DEPENDS_STATUS
    fi
    lock_commit_transaction $DEPENDS_STATUS
 
    #   if theres a tablet dir, store it with a new timestamp
    if new_tablet=$(tablet_get_path $SPELL) ; then
      cp -Rp $OLD_TABLET_DIR/* $new_tablet
      ln $INSTALL_LOG -sf $new_tablet/logs/install
      ln $MD5_LOG -sf $new_tablet/logs/md5sum
      ln $COMPILE_LOG -sf $new_tablet/logs/compile
      find $new_tablet > $TMP_INSTALL_LOG_STATE # relative to STATE_ROOT
    else
      debug "libresurrect" "WARNING: unable to make tablet for $SPELL, oh well"
    fi
  fi


  echo $COMPILE_LOG >> $TMP_INSTALL_LOG_STATE
  echo $INSTALL_LOG >> $TMP_INSTALL_LOG_STATE
  echo $MD5_LOG >> $TMP_INSTALL_LOG_STATE
  
  # Use the cache's listing of files in filterable form
  # dont use root form because it may be different
  log_adjuster $NEW_DATA_F $TMP_INSTALL_LOG_DATA filterable root
  cat $TMP_INSTALL_LOG_STATE $TMP_INSTALL_LOG_DATA > $TMP_INSTALL_LOG
  log_adjuster $TMP_INSTALL_LOG $INSTALL_LOG root log

  create_md5list $TMP_INSTALL_LOG /dev/stdout |
  log_adjuster /dev/stdin $MD5_LOG root log md5_log_filter

  # add packages line
  add_spell "$SPELL" "installed" "$VERSION"

  pop_install_queue "$SPELL"
  echo $SPELL >> $SUCCESS_LIST

  popd &>/dev/null

  rm_source_dir $RESURRECT_DIR

  clear_line
  activity_log  "resurrect"  "$SPELL"  "$VERSION"  "success"
  message  "${RESURRECT_COLOR}Resurrected spell: ${SPELL_COLOR}${SPELL}" \
           "${DEFAULT_COLOR} version ${VERSION_COLOR}${VERSION}"         \
           "${DEFAULT_COLOR}" 
}


function resurrect_fail() {
  message  "${PROBLEM_COLOR}Resurrect failed for spell:" \
           "${SPELL_COLOR}${SPELL}${DEFAULT_COLOR} version" \
           "${VERSION_COLOR}${VERSION}${DEFAULT_COLOR}" 

  #if [[ $1 == 1 ]] ; then
    #TODO evaluate the usefulness of a backup/rollback scheme
    # this would be the location in which to do rollback, however
    # I think it adds needless complexity and can be dangerous
    # also, it shouldnt be needed in a properly functioning resurrect
  #fi

  unlock_resources "libgrimoire" "install"
  unlock_resources "cast" "$SPELL"
  unlock_resources "solo" "cast"

  [[  $CLEAN_SOURCE == on ]] && rm_source_dir $RESURRECT_DIR 2>/dev/null
  
  echo $SPELL >> $FAILED_LIST
}

#---------------------------------------------------------------------
## @License
##
## This software is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This software is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this software; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
##
#---------------------------------------------------------------------
