# 
# get.sh - get a revision from an archive, making a project tree
################################################################
# 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 "construct a project tree for a revision\\n"
                printf "usage: get [options] [archive/]revision [dir]\\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 "  --cache DIR                  cache directory for locally cached\\n"
                printf "                                 revisions\\n"
                printf "\\n"
                printf " --no-pristine                 don't save a pristine copy\\n"
                printf "\\n"
                printf " --silent                      no output (except odd errors)\\n"
                printf " --quiet                       brief output\\n"
                printf " --report                      default output\\n"
                printf " --verbose                     maximal output\\n"
                printf " --debug                       debugging output\\n"
                printf "\\n"
                printf "Extract REVISION from an archive, creating the new project tree\\n"
                printf "DIR.   If DIR is not specified, store the working copy in a subdirectory\\n"
                printf "of the current directory, giving it the name of the revision.\\n"
                printf "Either way, the project tree must not already exist.\\n"
                printf "\\n"
                exit 0
                ;;

      *)
                ;;
    esac
  done
fi

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

archroot=
archive=
cache_dir=

no_pristine=

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

__restart=

while test $# -ne 0 ; do

  case "$1" in 

    --no-pristine)      shift
                        no_pristine=--no-pristine
                        ;;

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

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

    -R|--root)          shift
                        if test $# -eq 0 ; then
                          printf "get: -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 "get: -A and --archive require an argument\\n" 1>&2
                          printf "try --help\\n" 1>&2
                          exit 1
                        fi
                        archive="$1"
                        shift
                        ;;

    --cache)            shift
                        if test $# -eq 0 ; then
                          printf "get: --cache requires an argument\\n" 1>&2
                          printf "try --help\\n" 1>&2
                          exit 1
                        fi
                        cache_dir="$1"
                        shift
                        ;;

    --)                 shift
                        break
                        ;;

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

    *)                  break
                        ;;
  esac

done



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

if test $# -lt 1 -o $# -gt 2 ; then
  printf "usage: get [options] [archive/]revision [dir]\\n" 1>&2
  printf "try --help\\n" 1>&2
  exit 1
fi

rvnspec="$1"
shift

if test $# -eq 1 ; then
  parent="`dirname \"$1\"`"
  dirname="`basename \"$1\"`"
else
  parent="."
  dirname=
fi

################################################################
# Sanity Check and Process Defaults
# 
  
cd "$parent"
parent="`pwd`"

larch valid-package-name -e get -t -- "$rvnspec"
archive=`larch parse-package-name -R "$archroot" -A "$archive" --arch "$rvnspec"`
revision=`larch parse-package-name --non-arch "$rvnspec"`
base=`larch parse-package-name --basename $revision`
branch=`larch parse-package-name --package $revision`

if larch valid-package-name -t --vsn -- $revision ; then
  vsn=`larch parse-package-name --vsn $revision`
else
  vsn=
fi

if larch valid-package-name --patch-level -- "$revision" ; then
  patchlvl=`larch parse-package-name --patch-level $revision`
else
  patchlvl=
fi

if test -z "$cache_dir" ; then
  cache_dir="$parent"
fi

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

if test "(" -z "$__restart" -a  ! -z "$quiet" ")" -o ! -z "$report" ; then
  larch heading "get\\n"
  printf "arguments: %s\\n" "$command_line" | fold -w 60 | larch body-indent
  larch heading --sub "get start time: %s\\n" "`date`"
  larch heading --sub "output dir: %s\\n" "$parent/$dirname"
  larch heading --sub "archive: %s\\n" "$archive"
  larch heading --sub "revision requested: %s\\n" "$revision"
fi


################################################################
# Ensure an Archive Connection
# 

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

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

  cd "$parent"
  exec larch with-archive -A "$archive" larch get --cache "$cache_dir" \
                        $silent_opt $quiet_opt $report_opt $verbose_opt $debug_opt \
                        ----restart \
                        $no_pristine \
                        "$archive/$revision" "$dirname"

fi

################################################################
# Sanity Check and Process Defaults (part 2)
# 
# 

if test "x$patchlvl" != x ; then

  # The user explicitly specified a patch level.
  # (This assignment is redundant, but explanatory)
  # 
  revision="$branch--$vsn--$patchlvl"

else

  # We have to search for the latest patch level.
  # The user might have specified a version, or might
  # only have specified a branch.
  # 
  # Compute $versions -- a list of version names to search
  # for the latest patch level.  The list must be ordered
  # from most to least recent.
  # 

  if test "x$vsn" = x ; then
    versions=`larch versions -R "$archroot" -A "$archive" -r "$branch"`
  else
    versions=$branch--$vsn
  fi

  if test "x$versions" = x ; then
    printf "get: no versions found for branch\\n" 1>&2
    printf "  archive: %s\\n" "$archive" 1>&2
    printf "  branch: %s\\n" "$branch" 1>&2
    exit 1
  fi

  # search for the first version in versions
  # that has at least one patch level
  # 

  for v in $versions ; do

    patchlvl=`larch revisions -R "$archroot" -A "$archive" -r "$v" | head -n 1`

    if test "x$patchlvl" != x ; then
      revision=$v--$patchlvl
      break
    fi

  done

  if test "x$patchlvl" = x ; then
    printf "get: no revisions found for version\\n" 1>&2
    printf "  archive: %s\\n" "$archive" 1>&2
    printf "  in version(s): %s\\n" "$versions" 1>&2
    exit 1
  fi

fi

if test ! -z "$quiet" ; then
  larch heading --sub "revision sought: %s\\n" "$revision"
fi

################################################################
# Post Condition
# 
# $revision is now set to a valid revision name (i.e. with
# version and patch level)
# 

vsn=`larch parse-package-name -v $revision`

################################################################
# Make Sure We Have a Directory Name for the Working Dir
# 
if test "x$dirname" = x ; then
  dirname="$revision"
fi

cd "$parent"

if test -e "$dirname" ; then
  printf "get: project tree already exists\\n" 1>&2
  printf "   %s\\n" "$parent/$dirname" 1>&2
  exit 1
fi

if test -e ",,$dirname" ; then
  printf "get: temp directory already exists\\n" 1>&2
  printf "  %s\\n" ",,$dirname" 1>&2
  printf "\\n" 1>&2
  printf "That directory was probably made by a concurrent\\n" 1>&2
  printf "get for the same revision, or by a previous get\\n" 1>&2
  printf "that failed.  Please remove or rename that temp\\n" 1>&2
  printf "directory and try again, or specify a different\\n" 1>&2
  printf "name for the project tree.\\n" 1>&2
  printf "\\n" 1>&2
  exit 1
fi

################################################################
# Create the New Working Directory
# 

rm -rf ",,$dirname"
mkdir ",,$dirname"
cd ",,$dirname"

if test -z "$no_pristine" ; then
  mkdir ,,pristine
  cd ,,pristine
fi

larch nested larch build-revision $silent_opt $quiet_opt $report_opt $verbose_opt $debug_opt \
                                -R "$archroot" -A "$archive" --cache "$cache_dir" \
                                $revision

if test -z "$no_pristine" ; then

  if test ! -z "$report" ; then
    larch heading --sub "making extra copy for pristine revision cache\\n"
  fi

  cd "$parent/,,$dirname/,,pristine"

  find . \
  | copy-file-list -- - . "$parent/,,$dirname"

  cd "$parent/,,$dirname"

  larch wd-mv-pristine "$archive" $revision ,,pristine

fi

if test ! -z "$report" ; then
  larch heading --sub "setting default version of new project tree\\n"
  larch heading --sub "version: %s\\n" "$archive/$branch--$vsn"
fi

cd "$parent/,,$dirname" 

larch set-tree-version -R "$archroot" -A "$archive" "$archive/$branch--$vsn"

cd "$parent"
mv ",,$dirname" "$dirname"

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