# redo.sh - redo undone changes in a project tree
#
################################################################
# Copyright (C) 2001, 2002, 2003 Tom Lord, Alexander Deruwe
# 
# See the file "COPYING" for further information about
# the copyright and warranty status of this work.
# 

set -e
command_line="$*"

################################################################
# special options
# 
# Some options are special:
# 
#        --version | -V
#        --help | -h
# 
if test $# -ne 0 ; then
  for opt in "$@" ; do
    case $opt in
      --version|-V)
          exec larch --version
          ;;

      --help|-h)
          printf "redo undone changes in project tree\\n"
          printf "usage: redo [options]\\n"
          printf "\\n"
          printf " -V --version                  print version info\\n"
          printf " -h --help                     display help\\n"
          printf "\\n"
          printf " --silent                      no output (except odd errors)\\n"
          printf " --quiet                       brief output\\n"
          printf " --report                      outline output\\n"
          printf " --verbose                     maximal output\\n"
          printf " --debug                       debugging output\\n"
          printf "\\n"
          printf " -d --dir DIR                  cd to DIR first\\n"
          printf "\\n"
          printf " -p --patch PATCH              find the patch in directory PATCH\\n"
          printf "\\n"
          printf " -k --keep                     do not delete the patch dir\\n"
          printf "\\n"
          printf "Apply PATCH to the project tree containing DIR and then\\n"
          printf "delete the directory PATCH.\\n"
          printf "\\n"
          printf "If \"-d\" or \"--dir\" is not used, DIR defaults to \".\"\\n"
          printf "\\n"
          printf "If \"-p\" or \"--patch\" is not used, the highest numbered\\n"
          printf "\",,undo-N\" file in the project tree root is used.\\n"
          printf "\\n"
          printf "If \"--keep\" is provided, the patch directory is not\\n"
          printf "deleted.\\n"
          printf "\\n"
          printf "See also \"larch undo --help\" \\n"
          printf "and \"larch dopatch --help\".\\n"
          printf "\\n"
          exit 0
          ;;

      *)
          ;;
    esac
  done
fi

################################################################
# Ordinary Options
# 

dir=.

patch=
keep=

quiet=--quiet
report=--report
verbose=
silent_opt=
quiet_opt=
report_opt=
verbose_opt=
debug_opt=

while test $# -ne 0 ; do
  case "$1" in 
    --silent)       shift
                    quiet=
                    report=
                    verbose=
                    silent_opt=--silent
                    quiet_opt=
                    report_opt=
                    verbose_opt=
                    ;;

    --quiet)        shift
                    quiet==--quiet
                    report=
                    verbose=
                    silent_opt=
                    quiet_opt=--quiet
                    report_opt=
                    verbose_opt=
                    ;;

    --report)       shift
                    quiet=--quiet
                    report=--report
                    verbose=
                    silent_opt=
                    quiet_opt=
                    report_opt=--report
                    verbose_opt=
                    ;;
        
    --verbose)      shift
                    quiet=--quiet
                    report=--report
                    verbose=--verbose
                    silent_opt=
                    quiet_opt=
                    report_opt=
                    verbose_opt=--verbose
                    ;;

    --debug)        shift
                    larch heading "redo: debugging output enabled\\n"
                    set -x
                    debug=--debug
                    ;;

    -d|--dir)       shift
                    if test $# -lt 1 ; then
                      printf "redo: -d and --dir require an argument\\n" 1>&2
                      printf "try --help\\n" 1>&2
                      exit 1
                    fi
                    dir="$1"
                    shift
                    ;;

    -p|--patch)     shift
                    if test $# -lt 1 ; then
                      printf "redo: -p and --patch require an argument\\n" 1>&2
                      printf "try --help\\n" 1>&2
                      exit 1
                    fi
                    patch="$1"
                    shift
                    ;;

    -k|--keep)      shift
                    keep=--keep
                    ;;

    -*)
        printf "redo: unrecognized option (%s)\\n" "$1" 1>&2
        printf "try --help\\n" 1>&2
        exit 1
        ;;

    *)
        break
        ;;
  esac
done



################################################################
# Ordinary Arguments
# 

if test $# -gt 0 ; then
  printf "usage: redo [options]\\n"
  printf "try --help\\n"
  exit 1
fi


################################################################
# Sanity Check and Process Defaults
#

here="`pwd`"

cd "$dir"
dir="`pwd`"

wdroot="`larch tree-root`"
cd "$wdroot"

if test ! -z "$patch" ; then

  cd "$here"
  cd $(dirname "$patch")
  patch_dir="`pwd`"
  patch_basename=$(basename "$patch")
  patch="$patch_dir/$patch_basename"

else

  cd "$wdroot"

  undo_prefix=",,undo"

  level=`ls | grep -E -e "^$undo_prefix-[0-9]+$" | sort -t - -k 2,2n -r | head -n 1 | sed -e 's/.*-//'`

  if test -z "$level" ; then
    printf "redo: no patch directory found\\n" 1>&2
    printf "  looking in dir: %s\\n" "$patch" 1>&2
    printf "\\n" 1>&2
  fi

  patch_dir="$wdroot"
  patch_basename="$undo_prefix-$level"
  patch="$patch_dir/$patch_basename"

fi

if test ! -e "$patch" ; then
  printf "redo: patch directory does not exist\\n" 1>&2
  printf "  dir: %s\\n" "$patch" 1>&2
  printf "\\n" 1>&2
  exit 1
fi


################################################################
# Greetings
#

if test ! -z "$quiet" ; then
  larch heading "redo\\n"
  printf "arguments: %s\\n" "$command_line" | fold -w 60 | larch body-indent
  larch heading --sub "project tree: %s\\n" "$wdroot"
  larch heading --sub "patch directory: %s\\n" "$patch"
fi


################################################################
# Lint the Tree
# 
# Make sure that there is nothing fatally bad in the tree.
# 

cd "$wdroot"

if test -z "$silent" ; then
  larch nested larch tree-lint > /dev/null
else
  larch nested larch tree-lint
fi


################################################################
# Re-apply changes in the working directory
# 

if test ! -z "$report" ; then
  larch heading --sub "applying patch set\\n"
  if test ! -z "$verbose" ; then
    larch heading --sub --sub "start time: %s\\n" "`date`"
  fi
fi

larch nested larch dopatch --quiet $silent_opt $report_opt $verbose_opt $debug_opt "$patch" "$wdroot"

if test ! -z "$verbose" ; then
  larch heading --sub --sub "finish time: %s\\n" "`date`"
fi


################################################################
# Remove patch directory
#

if test -z "$keep" ; then
  if test ! -z "$report" ; then
    larch heading --sub "removing patch directory\\n"
    larch heading --sub --sub "dir: %s\\n" "$patch"
  fi
  rm -rf "$patch"
fi

exit 0

#
# vim: set expandtab shiftwidth=2 softtabstop=2:
