# 
# tree-root.sh - print the root of 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 

################################################################
# 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 "find and print the root of a project tree\\n"
                printf "usage: tree-root [options] [dir]\\n"
                printf "\\n"
                printf " -V --version                  print version info\\n"
                printf " -h --help                     display help\\n"
                printf "\\n"
                printf " -s --silent                   suppress error messages --\\n"
                printf "                                ordinary output and exit status\\n"
                printf "                                only\\n"
                printf "\\n"
                printf " --accurate                    require that the project tree log\\n"
                printf "                                 be up-to-date.\\n"
                printf "\\n"
                printf "Find and print the root of the project tree that contains\\n"
                printf "DIR (or the current directory)."
                printf "\\n"
                printf "The option \"--accurate\" checks for three possibilities:\\n"
                printf "\\n"
                printf "    1) The project tree was the subject of a commit that\\n"
                printf "       was killed before the log entry was added to the\\n"
                printf "       tree's patch log.  It is unknown whether or not\\n"
                printf "       the commit took place in the archive.  The {arch}\\n"
                printf "       directory contains the log file as \"++mid-commit\".\\n"
                printf "\\n"
                printf "    2) The project tree was the subject of a killed commit, but\\n"
                printf "       it is certain the commit took place.  The log file\\n"
                printf "       is stored as \"++commit-definite\".\\n"
                printf "\\n"
                printf "    3) The project tree patch log is fully up-to-date (as far as\\n"
                printf "       larch knows).\\n"
                printf "\\n"
                printf "In case 1, exit with an error and error message.\\n"
                printf "\\n"
                printf "In case 2, install the log file before printing the tree root and\\n"
                printf "exiting normally.\\n"
                printf "\\n"
                printf "In case 3, print the tree root and exit normally.\\n"
                printf "\\n"
                exit 0
                ;;

      *)
                ;;
    esac
  done
fi

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

silent=
accurate=

while test $# -ne 0 ; do

  case "$1" in 

    --accurate)         shift
                        accurate=--accurate
                        ;;

    -s|--silent)        shift
                        silent=--silent
                        ;;

    --)                 shift
                        break
                        ;;

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

    *)                  break
                        ;;
  esac

done



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

if test $# -gt 1 ; then
  printf "usage: tree-root [options] [dir]\\n" 1>&2
  printf "try --help\\n" 1>&2
  exit 1
fi

if test $# -eq 1 ; then
  dir="$1"
else
  dir="."
fi

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

################################################################
# Search
# 

while true ; do
  if test -d "{arch}" -a -e "{arch}/.arch-project-tree" ; then
    break
  elif test `pwd` = / ; then
    if test -z "$silent" ; then
      printf "tree-root: not a project tree\\n" 1>&2
      printf "  %s\\n" "$dir" 1>&2
    fi
    exit 1
  else
    cd ..
  fi
done

answer="`pwd`"
cd '{arch}'

if test -z "$accurate" ; then

  printf "%s\\n" "$answer"
  exit 0

elif test -e ++resolve-conflicts ; then

  printf "\\n" 1>&2
  printf "tree-root: intermediate state working directory\\n" 1>&2
  printf "  root: %s\\n" "$answer" 1>&2
  printf "\\n" 1>&2
  printf "A multi-part merge operation was paused in order to allow you\\n" 1>&2
  printf "to clean up conflicts in this directory.  To complete the merge\\n" 1>&2
  printf "operation, run the command: \\n" 1>&2
  printf "\\n" 1>&2
  cat ./++resolve-conflicts/cmd 1>&2
  printf "\\n" 1>&2
  printf "To abort the merge operation, remove the directory:\\n" 1>&2
  printf "\\n" 1>&2
  printf "        %s\\n" "`pwd`/++resolve-conflicts" 1>&2
  printf "\\n" 1>&2
  exit 1

elif test -e ++commit-definite ; then

  archive="`grep -i -E -e ^Archive: ++commit-definite | head -n 1 | sed -e 's/[Aa][Rr][Cc][Hh][Ii][Vv][Ee]:[[:space:]]*//'`"
  revision="`grep -i -E -e ^Revision: ++commit-definite | head -n 1 | sed -e 's/[Rr][Ee][Vv][Ii][Ss][Ii][Oo][Nn]:[[:space:]]*//'`"
  version="`larch parse-package-name --package-version \"$revision\"`"
  lvl="`larch parse-package-name --lvl \"$revision\"`"
  larch copy-to-patch-log ++commit-definite "$archive/$version" "$lvl" "$answer"
  rm ++commit-definite
  printf "%s\\n" "$answer"
  exit 0

elif test -e ++mid-commit ; then

  printf "\\n"
  printf "tree-root: wedged working directory\\n" 1>&2
  printf "  root: %s\\n" "$answer" 1>&2
  printf "\\n"
  printf "A commit operation (such as \"larch commit\") was interrupted\\n" 1>&2
  printf "before this project tree's patch log was fully updated.\\n" 1>&2
  printf "The commit may or may not have succeeded.\\n" 1>&2
  printf "\\n" 1>&2
  printf "To check whether or not the commit took place, and return\\n" 1>&2
  printf "this working directory to a \"non-wedged\" state, try\\n" 1>&2
  printf "\\n" 1>&2
  printf "        larch tree-repair --help\\n" 1>&2
  printf "\\n" 1>&2
  exit 1

else

  printf "%s\\n" "$answer"
  exit 0

fi
