#!/bin/sh
# tla-switch -- Switch an arch project tree to a new branch/version/revision
# Usage: tla-switch [OPTION...] NEW
#
#  Copyright (C) 2004  Miles Bader <miles@gnu.org>
#
# This program 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.
#
# Written by Miles Bader <miles@gnu.org>
#
#-
#   -A, --archive    Override `my-default-archive'
#   -d, --dir DIR    Use project tree in DIR
#
#       --help       Display a help message and exit
#       --version    Display a release identifier string and exit
# 
# This command should be run in an arch project tree.  It will apply the
# changes between the current tree contents and NEW and set the
# tree-version accordingly.  If NEW is a version, the last revision in
# it is used.  As a special case, if NEW contains _only_ an archive
# name, the non-archive portion of the current tree's version is
# appended to it; this is handy for switching a tree to a new archive
# when the archive is revved.
#
# It is essentially the same as `tla get NEW', except that it works
# in-place, and preserves any files or directories in the project tree
# which are not committed to the archive; as such it is mainly useful
# when there are such files or directories.

# (---- beginning of hdr.shpp ----)
# hdr.shpp

me=`basename $0`

bindir='/usr/bin'
AWK='/usr/bin/nawk'; export AWK
TLA='tla'; export TLA
SED='/bin/sed'; export SED
UUIDGEN='uuidgen'; export UUIDGEN

# (---- TLA_TOOLS_VERSION defined from ,tla-tools-version ----)
TLA_TOOLS_VERSION='jgoerzen@complete.org--debian/tla-tools--debian--1.0--patch-18
'
# (---- end of TLA_TOOLS_VERSION defined from ,tla-tools-version ----)

TLA_TOOL_PFX="${bindir+$bindir/}"
export TLA_TOOL_PFX

TLA_ESCAPE='yes'

if test "$TLA_ESCAPE" = yes; then
  TLA_UNESCAPED_OPT='--unescaped'
else
  TLA_UNESCAPED_OPT=''
fi

# Some tools get completely confused in stupid ways by non-default
# settings of LANG (like gawk, which fucks up regexp character ranges).
LANG=C; export LANG

# (---- end of hdr.shpp ----)
# (---- beginning of cmd-line.shpp ----)
# cmd-line.shpp -- Command-line helper functions for shell scripts

script="$0"
case "$script" in
  */*) ;;
  *)   script="${TLA_TOOL_PFX}$script";;
esac

usage ()
{
  $SED -n -e '/^\([^#]\|#-* *$\)/{s@.*@Usage: '"$me"' [--help|--version]@p;q;}'	\
         -e '/^# *Usage:/,/^# *$/{s/^# //p;q;}'				\
     < "$script"
}

short_help ()
{
  $SED -n -e '/^\([^#]\|-*# *$\|# *Usage:\)/q'				\
	 -e '/^#!/d;s/^.*-- */# /;s/^#[ 	]*//p'			\
     < "$script" | fmt
}

help_body ()
{
  $SED -n '/^ *$/q;/^#-/,/^[^#]/s/^#\( \|$\)//p' < "$script"
}

help ()
{
  usage
  short_help
  echo ''
  help_body
}

version ()
{
  local no_nl_vers=`echo "$TLA_TOOLS_VERSION"`
  echo "$me (tla-tools) $no_nl_vers"
  $SED -n '/^[^#]/q;/^#-/q;s/^# *\(Written by\)/\
\1/p' < "$script"
  $SED -n '/^[^#]/q;/^#-/q;s/^# *\(Copyright\)/\
\1/p' < "$script"
}

unrec_opt ()
{
  echo 1>&2 "$me: unrecognized option "\`"$1'"
  echo 1>&2 "Try "\`"$me --help' for more information."
}

cmd_line_err ()
{
  usage 1>&2
  echo 1>&2 "Try "\`"$me --help' for more information."
}

long_opt_val ()
{
  echo "$1" | $SED 's/^[^=]*=//'
}

short_opt_val ()
{
  echo "$1" | $SED 's/^-.//'
}

# (---- end of cmd-line.shpp ----)

dir='.'
default_archive=''

# Parse command-line options
while :; do
  case "$1" in
    -A|--archive)
      default_archive="$2"; shift 2;;
    --archive=*)
      default_archive=`long_opt_val "$1"`; shift;;
    -A*)
      default_archive=`short_opt_val "$1"`; shift;;
    -d|--dir)
      dir="$2"; shift 2;;
    --dir=*)
      dir=`long_opt_val "$1"`; shift;;
    -d*)
      dir=`short_opt_val "$1"`; shift;;
    --help|-h|-H)
      help; exit 0;;
    --version|-V)
      version; exit 0;;
    -[!-]?*)
      # split concatenated single-letter options apart
      FIRST="$1"; shift
      set -- `echo $FIRST | $SED 's/-\(.\)\(.*\)/-\1 -\2/'` "$@"
      ;;
    -*)
      unrec_opt "$1"; exit 1;;
    *)
      break;
  esac
done

test "$#" = 1 || { cmd_line_err; exit 1; }

new="$1"
tree_ver=`$TLA tree-version "$dir"`

if test x"$default_archive" = x; then
  default_archive=`$TLA my-default-archive`
fi

# We want to apply the switching changeset in the tree-root
tree_root=`$TLA tree-root 2>/dev/null` || { echo 1>&2 "$me: Not in an arch project tree"; exit 2; }
cd "$tree_root"

# Check for the special case of _only_ an archive name being specified,
# in which case we switch to the same version as the current tree,
# except in the new archive.
case "$new" in
  */?*|*--*--*--*)
    # A non-archive part was specified, use it unchanged
    ;;
  *@*--*/)
    new="$new`basename "$tree_ver"`";;
  *@*--*)
    new="$new/`basename "$tree_ver"`";;
esac

archive=`$TLA parse-package-name -a -A"$default_archive" "$new"`
non_arch=`$TLA parse-package-name --non-arch "$new"`
new="$archive/$non_arch"

case "$new" in
  */*--*--*--*)
    new_ver=`echo "$new" | $SED 's@\([^/]*--[^/]*/.*--.*--.*\)--.*@\1@'`
    new_rev="$new"
    ;;
  *)
    new_ver="$new"
    new_rev=`$TLA revisions -f "$new_ver" | $SED -n '$p'`
    ;;
esac

reapply_local_changes=no
if ! $TLA changes -q -d"$dir"; then
  echo "* setting aside local changes temporarily"
  tla undo -d"$dir"
  reapply_local_changes=yes
fi

exit_status=0

if $TLA apply-delta -d"$dir" "$dir" "$new_rev"; then
  if test x"$new_ver" != x"$tree_ver"; then
    if $TLA set-tree-version -d"$dir" "$new_ver"; then
      echo "* tree version set to $new_ver"
    else
      exit_status=$?
    fi
  fi
else
  exit_status=$?
fi

if test $reapply_local_changes = yes; then
  echo "* reapplying local changes"
  tla redo -d"$dir"
fi

exit $exit_status

