# join-branch.sh: join a sibling branch
# 
################################################################
# Copyright (C) 2001, 2002 Tom Lord
# 
# 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 "join-branch a sibling branch\\n"
                printf "usage: join-branch [options] old-dir new-dir [[archive/]revision]\\n"
                printf "usage: join-branch --in-place [options] dir [[archive/]revision]\\n"
                printf "\\n"
                printf " -V --version                  print version info\\n"
                printf " -h --help                     display help\\n"
                printf "\\n"
                printf " -R --root root                specify the local archive root\\n"
                printf " -A --archive archive          specify the archive name\\n"
                printf "\\n"
                printf " --in-place                    modify an existing directory\\n"
                printf " --force                       apply the patch even if the tree\\n"
                printf "                                 already has a patch log for the\\n"
                printf "                                 indicated revision\\n"
                printf "\\n"
                printf "REVISION must be a continuation (e.g. tag) of an ancestor of\\n"
                printf "the project tree.   The command replays the changeset for\\n"
                printf "REVISION in the project tree.  That has the effect\\n"
                printf "of adding the log for the branch (making the tag an ancestor of\\n"
                printf "of the resulting tree.\\n"
                printf "\\n"
                printf "As an exception to the usual rules, REVISION may be abbreviated\\n"
                printf "as a version name, in which case the \"base-0\" revision of that\\n"
                printf "version is indicated.\\n"
                printf "\\n"
                exit 0
                ;;

      *)
                ;;
    esac
  done
fi

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

archroot=
archive=

in_place=

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

force=


while test $# -ne 0 ; do

  case "$1" in 

    --force)    shift
                force=--force
                ;;

    ----restart) shift
                __restart=----restart
                ;;

    --no-lint)  shift
                no_lint=--no-lint
                ;;

    --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 "join-branch: debugging output enabled\\n"
                set -x
                debug_opt=--debug
                ;;


    -R|--root)          shift
                        if test $# -eq 0 ; then
                          printf "join-branch: -R and --root require an argument\\n" 1>&2
                          printf "try --help\\n" 1>&2
                          exit 1
                        fi
                        archroot="$1"
                        shift
                        ;;

    -A|--archive)       shift
                        if test $# -eq 0 ; then
                          printf "join-branch: -A and --archive require an argument\\n" 1>&2
                          printf "try --help\\n" 1>&2
                          exit 1
                        fi
                        archive="$1"
                        shift
                        ;;

    --in-place)         shift
                        in_place=--in-place
                        ;;

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

    *)                  break
                        ;;
  esac

done



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

if test -z "$in_place" ; then
  n_dir_args=2
else
  n_dir_args=1
fi

req_args=$(($n_dir_args + 1))

if test $# -ne $req_args ; then
  printf "usage: join-branch [options] old-dir new-dir [[archive/]revision]\\n" 1>&2
  printf "       join-branch --in-place [options] dir [archive/]revision\\n" 1>&2
  printf "try --help\\n" 1>&2
  exit 1
fi

old_dir="$1"
shift

if test -z "$in_place" ; then
  new_dir="$1"
  shift
else
  new_dir="$old_dir"
fi

if test $# -ne 0 ; then
  archive_version="$1"
  shift
else
  archive_version=
fi

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

here="`pwd`"

cd "$old_dir"
old_dir="`pwd`"

cd "$here"
cd "`dirname \"$new_dir\"`"
output_dir="`pwd`"
new_base="`basename \"$new_dir\"`"
new_dir="$output_dir/$new_base"

cd "$old_dir"
old_dir="`larch tree-root --accurate`"

if larch valid-package-name --vsn -- "$archive_version" ; then
  archive_version="$archive_version--base-0"
fi

larch valid-package-name -e join-branch --patch-level -- "$archive_version"

archive="`larch parse-package-name -R \"$archroot\" -A \"$archive\" --arch \"$archive_version\"`"
spec="`larch parse-package-name --non-arch \"$archive_version\"`"
category="`larch parse-package-name --basename \"$archive_version\"`"
branch="`larch parse-package-name \"$archive_version\"`"
version="`larch parse-package-name --package-version \"$spec\"`"

if    test -z "$force" \
   && larch wd-check-for-patch-log "$archive/$version" \
   && larch log-ls "$archive/$spec" > /dev/null \
; then
  printf "\\n" 1>&2
  printf "join-branch: tree already has log entry for patch\\n" 1>&2
  printf "  tree: %s\\n" "$old_dir" 1>&2
  printf "  revision: %s\\n" "$archive/$spec" 1>&2
  printf "\\n" 1>&2
  exit 1
fi

lvl="`larch parse-package-name --lvl \"$spec\"`"



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

if test "(" -z "$__restart" -a ! -z "$quiet" ")" -o ! -z "$report" ; then
  larch heading "join-branch\\n"
  printf "arguments: %s\\n"  "$command_line" | fold -w 60 | larch body-indent
  larch heading --sub "join-branch start time: %s\\n" "`date`"
  if test -z "$in_place" ; then
    larch heading --sub "old project tree: %s\\n" "$old_dir"
    larch heading --sub "new project tree: %s\\n" "$new_dir"
  else
    larch heading --sub "NOTE: modifying project tree in place (--in-place)\\n"
    larch heading --sub --sub "project tree: %s\\n" "$old_dir"
  fi
  larch heading --sub "archive: %s\\n" "$archive"
  larch heading --sub "revision: %s\\n" "$spec"
fi


################################################################
# Ensure that We Have an Archive Connection 
# 

if test "$WITHARCHIVE" != "$archive" ; then

  if test ! -z "$quiet" ; then
    larch heading --sub "restarting with connection to archive\\n"
  fi


  if test -z "$in_place" ; then
    exec larch with-archive -A "$archive"  \
                  larch join-branch \
                          -R "$archroot" -A "$archive" \
                          $silent_opt $quiet_opt $report_opt $verbose_opt $debug_opt \
                          ----restart \
                          -- "$old_dir" "$new_dir" $archive_version
  else
    exec larch with-archive -A "$archive"  \
                  larch join-branch \
                          -R "$archroot" -A "$archive" \
                          $silent_opt $quiet_opt $report_opt $verbose_opt $debug_opt \
                          ----restart \
                          --in-place \
                          -- "$old_dir" $archive_version
  fi

  exit 2
fi

################################################################
# Ensure that the Joined Revision is a Continuation Revision of an Ancestor
# 

wftp-home
if ! wftp-cd "$category/$branch/$version/$lvl" 2> /dev/null ; then
  printf "\\n" 1>&2
  printf "join-branch: revision not found in archive\\n" 1>&2
  printf "  archive: %s\\n" "$archive" 1>&2
  printf "  revision: %s\\n" "$spec" 1>&2
  printf "\\n" 1>&2
  exit 1
fi

if ! wftp-get CONTINUATION > /dev/null 2>&1 ; then
  printf "\\n" 1>&2
  printf "join-branch: revision is not a continuation revision\\n" 1>&2
  printf "  archive: %s\\n" "$archive" 1>&2
  printf "  revision: %s\\n" "$spec" 1>&2
  printf "\\n" 1>&2
  exit 1
fi

continuation="`wftp-get CONTINUATION`"

if ! larch valid-package-name --archive --lvl -- "$continuation" ; then
  printf "\\n" 1>&2
  printf "join-branch: CORRUPT ARCHIVE?\\n" 1>&2
  printf "\\n" 1>&2
  printf "  archive: %s\\n" "$archive" 1>&2
  printf "  revision: %s\\n" "$spec" 1>&2
  printf "\\n" 1>&2
  printf "  Revision appears to be a continuation revision, but not of a\\n" 1>&2
  printf "  valid revision.  The continued revision is (illegally) specified\\n" 1>&2
  printf "  in the archive as:\\n" 1>&2
  printf "\\n" 1>&2
  printf "     %s\\n" "$continuation" 1>&2
  printf "\\n" 1>&2
  exit 1
fi

cd "$old_dir"
log_entry="`larch log-ls --full -- \"$continuation\"`"

if test "$log_entry" != "$continuation" ; then
  printf "\\n" 1>&2
  printf "join-branch: unable to join branch at desired revision\\n" 1>&2
  printf "  archive: %s\\n" "$archive" 1>&2
  printf "  revision: %s\\n" "$spec" 1>&2
  printf "\\n" 1>&2
  printf "  That revision is a continuation of revision:\\n" 1>&2
  printf "\\n" 1>&2
  printf "    %s\\n" "$continuation" 1>&2
  printf "\\n" 1>&2
  printf "  but the project tree has no log entry for that revision.\\n" 1>&2
  printf "\\n" 1>&2
  printf "\\n" 1>&2
  exit 1
fi

################################################################
# Do It
# 

if test -z "$in_place" ; then 
  larch nested larch replay --exact "$old_dir" "$new_dir" "$archive/$spec"
else
  larch nested larch replay --exact --in-place "$old_dir" "$archive/$spec"
fi

# tag: Tom Lord Mon Dec 31 17:48:29 2001 (branching-and-merging/join.sh)
#
