# build-revision.sh - build a revision from an archive and cache
# 
################################################################
# 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 "*build a revision from a connected database and local cache\\n"
                printf "usage: build-revision [options] 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 " --cache dir                   specify where cached revisions are\\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 "See \"larch get --help\".\\n"
                printf "\\n"
                exit 0
                ;;

      *)
                ;;
    esac
  done
fi

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

archroot=
archive=
cache=

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

while test $# -ne 0 ; do

  case "$1" in 

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

    -R|--root)          shift
                        if test $# -eq 0 ; then
                          printf "build-revision: -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 "build-revision: -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 "build-revision: --cache requires an argument\\n" 1>&2
                          printf "try --help\\n" 1>&2
                          exit 1
                        fi
                        cache="$1"
                        shift
                        ;;

    --)                 shift
                        break
                        ;;

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

    *)                  break
                        ;;
  esac

done



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

if test $# -ne 1 ; then
  printf "usage: build-revision [options] revision\\n" 1>&2
  printf "try --help\\n" 1>&2
  exit 1
fi

revision="$1"
larch valid-package-name -e build-revision -l -- "$revision"

archive="`larch parse-package-name -A "$archive" --arch "$revision"`"
spec="`larch parse-package-name -A "$archive" --non-arch "$revision"`"
category="`larch parse-package-name --basename \"$revision\"`"
branch="`larch parse-package-name --package \"$revision\"`"

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

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


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

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

  cd "$parent"

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

  exec larch with-archive -A "$archive" \
                larch build-revision --cache "$cache_dir" \
                        $silent_opt $quiet_opt $report_opt $verbose_opt $debug_opt \
                        ----restart \
                        "$archive/$spec"

fi

################################################################
# What Revision is Intended?
# 

revision="`larch indicated-revision -e build-revision \"$archive/$spec\"`"
version="`larch parse-package-name --package-version \"$revision\"`"
lvl="`larch parse-package-name --patch-level \"$revision\"`"


################################################################
# Build It
# 
# 
# We start at the goal revision and search patch levels backwards
# until we find:
# 
#       1. A revision in the local cache
#       2. A revision with a cached source tree in the archive
#       3. A fresh-start base revision
# 
# Then we move forward through the missing patch levels, 
# applying patches, until the final goal revision is reached.
# 

top()
{
  if test $# = 0 ; then
    printf "stack underflow\\n" 1>&2
    exit 1
  else
    printf "%s\\n" "$1" 
  fi
}


pop()
{
  if test $# = 0 ; then
    printf "stack underflow\\n" 1>&2
    exit 1
  else
    shift
    printf "%s\\n" "$*" 
  fi
}

goal="$revision"
goal_stack=

while true ; do

  if test ! -z "$verbose" ; then
    larch heading --sub "revision goal: %s\\n" "$goal"
    larch heading --sub "goal stack: %s\\n" "$goal_stack"
  fi

  if    larch nested larch copy-from-library -R "$archroot" -A "$archive" \
                                           $silent_opt $quiet_opt $report_opt $verbose_opt $debug_opt \
                                           -- "$goal" \
     || larch nested larch copy-from-cache -R "$archroot" -A "$archive" \
                                         $silent_opt $quiet_opt $report_opt $verbose_opt $debug_opt \
                                        -- "$cache" "$goal" \
     || larch nested larch copy-from-archive-cache $silent_opt $quiet_opt $report_opt $verbose_opt $debug_opt \
                                                 "$goal" \
     || larch nested larch copy-from-fresh-start-base $silent_opt $quiet_opt $report_opt $verbose_opt $debug_opt \
                                                    "$goal" ; then

    break

  else

    prev=`larch previous-patch-level -R "$archroot" -A "$archive" "$goal"`

    prev_archive=${prev%%/*}
    prev_revision=${prev#*/}

    goal_stack="$goal $goal_stack"
    goal=$prev_revision

    if test "$prev_archive" = "$prev" -o "$prev_archive" = "$archive" ; then

      continue

    else

      larch with-archive -R "$archroot" -A "$prev_archive"  \
        larch nested larch build-revision $silent_opt $quiet_opt $report_opt $verbose_opt $debug_opt \
                                        -R "$archroot" -A "$prev_archive" --cache "$cache" \
                                        "$prev_revision"
      break

    fi

  fi

done

while test "x$goal_stack" != x ; do

  goal=`top $goal_stack`
  goal_stack=`pop $goal_stack`

  larch nested larch build-by-patching $silent_opt $quiet_opt $report_opt $verbose_opt $debug_opt "$goal"
done


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