#!/bin/sh
# commit.sh - archive a pre-patch revision
################################################################
# Copyright (C) 2001 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)

                printf "Hackerlab commit 0.0 (archive a revision)\\n"
                printf "Copyright 2001, Tom Lord\\n"
                printf "\\n"
                printf "\\n"
                printf "This is free software; see the source for copying conditions.\\n"
                printf "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\\n"
                printf "PARTICULAR PURPOSE.\\n"
                printf "\\n"
                exit 0
                ;;

      --help|-h)
                printf "archive a revision\\n"
                printf "usage: commit [options] [[archive/]version [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 "\\n"
                printf " -L --log-file file            specify the log-file\\n"
                printf " -d --not-default              do not make this the default branch\\n"
                printf " --no-lint                     do not lint the project tree\\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 " --seal                        commit the version revision\\n"
                printf " --fix                         commit a versionfix- patch level\\n"
                printf " --continuation [archive/]prev-revision  commit a continuation revision\\n"
                printf " --out-of-date-ok              permit commit even if project tree is\\n"
                printf "                                 not up to date\\n"
                printf "\\n"
                printf " --changelog FILE              update the ChangeLog file to reflect\\n"
                printf "                                 the commit\\n"
                printf "\\n"
                printf " --dry-run                     don't actually commit -- just\\n"
                printf "                               prepare the patch set\\n"
                printf "\\n"
                printf "Archive a revision of the project tree containing DIR (or the\\n"
                printf "current directory)\\n"
                printf "\\n"
                printf "If there is a top-level ChangeLog file and the first line contains\\n"
                printf "the string \"arch changelog\", --changelog is implied.\\n"
                printf "\\n"
                exit 0
                ;;

      *)
                ;;
    esac
  done
fi

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

archroot=
archive=

no_lint=
makedefault=1
logfile=
continuation=0
continuation_revision=
fix=0
seal=0
out_of_date_ok=0
changelog=
changelog_file=
dry_run=

__restart=

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

while test $# -ne 0 ; do

  case "$1" in 

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


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

    -L|--log-file)      shift
                        if test $# -eq 0 ; then
                          printf "commit: -L and --log-file require an argument\\n" 1>&2
                          printf "try --help\\n" 1>&2
                          exit 1
                        fi
                        logfile="$1"
                        shift
                        ;;

    -d|--not-default)   shift
                        makedefault=0
                        ;;

    --fix)              shift
                        fix=1
                        seal=0
                        continuation=0
                        ;;

    --seal)             shift
                        fix=0
                        seal=1
                        continuation=0
                        ;;

    --continuation)     shift
                        fix=0
                        seal=0
                        continuation=1
                        if test $# -eq 0 ; then
                          printf "commit: --continuation requires an argument\\n" 1>&2
                          printf "try --help\\n" 1>&2
                          exit 1
                        fi
                        continuation_revision="$1"
                        shift
                        ;;

    --out-of-date-ok)   shift
                        out_of_date_ok=1
                        ;;

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

    --dry-run)          shift
                        dry_run=--dry-run
                        ;;

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

    *)                  break
                        ;;
  esac

done



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

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

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

if test $# -gt 0 ; then
  dir="$1"
  shift
else
  dir="."
fi

################################################################
# Sanity Check and Process Defaults
# 
  
start_dir="`pwd`"

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

wdroot="`arch tree-root --accurate`"
cd "$wdroot"

if ( test -z "$changelog" -a -e ChangeLog ) \
   && ( head -1 ChangeLog | grep -q "arch changelog" ) \
; then
  changelog=--changelog
  changelog_file="$wdroot/ChangeLog"
fi

if test ! -z "$changelog_file" ; then
  cd "$start_dir"
  cd "`dirname \"$changelog_file\"`"
  changelog_file="`pwd`/`basename \"$changelog_file\"`"
fi

if test "x$archive_version" = x ; then
  archive_version=`arch tree-version`
else
  arch valid-package-name -e commit --vsn -- "$archive_version"
fi

archive=`arch parse-package-name -R "archroot" -A "$archive" --arch $archive_version`
version=`arch parse-package-name -R "archroot" -A "$archive" --package-version $archive_version`
category=`arch parse-package-name --basename $version`
branch=`arch parse-package-name $version`
vsn=`arch parse-package-name -v $version`

if test "x$logfile" = x ; then
  logfile=++log.$version--$archive
fi

cd "$start_dir"
logfile_dir="`dirname \"$logfile\"`"
logfile_base="`basename \"$logfile\"`"
cd "$logfile_dir"
logfile="`pwd`/$logfile_base"

# Make sure the wd has a patch log for this version.
# 
arch wd-check-for-patch-log -e commit -R "$archroot" -A "$archive" "$version" "$wdroot"

# Make sure we have a valid log file for this revision.
# 
arch valid-log-file -e commit -- "$logfile"

tmpdir="$wdroot/,,commit-tmp-dir"


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

if test "(" -z "$__restart" -a ! -z "$quiet" ")" -o ! -z "$report" ; then
  arch heading "commit\\n"
  printf "arguments %s\\n"  "$command_line" | fold -w 60 | arch body-indent
  arch heading --sub "commit start time %s\\n" "`date`"
  arch heading --sub "project tree: %s\\n" "$wdroot"
  arch heading --sub "archive: %s\\n" "$archive"
  arch heading --sub "version: %s\\n" "$version"
  if test ! -z "$continuation_revision" ; then
    arch heading --sub "this is a continuation revision (--continuation)\\n"
  elif test $fix -ne 0 ; then
    arch heading --sub "this is versionfix revision (--fix)\\n"
  elif test $seal -ne 0 ; then
    arch heading --sub "this is version revision (--seal)\\n"
  fi
  if test ! -z "$dry_run" ; then 
    arch heading --sub "this is a dry run (no modifications to the archive)\\n"
  fi
fi

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

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

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

  flags=

  if test $makedefault -eq 0 ; then
    flags="-d $flags"
  fi

  if test $fix -ne 0 ; then
    flags="--fix $flags"
  elif test $seal -ne 0 ; then
    flags="--seal $flags"
  elif test $continuation -ne 0 ; then
    flags="--continuation $continuation_revision $flags"
  fi

  if test $out_of_date_ok -ne 0 ; then
    flags="--out-of-date-ok $flags"
  fi

  exec arch with-archive -R "$archroot" -A "$archive" \
      arch commit -R "$archroot" -A "$archive" \
                  -L "$logfile" \
                  $silent_opt $quiet_opt $report_opt $verbose_opt \
                  $no_lint \
                  $changelog $changelog_file \
                  $flags \
                  $dry_run \
                  ----restart \
                  "$archive/$version" \
                  "$dir"
fi



################################################################
# Create a Temp Dir in Which to Build the Patch
# 

bail()
{
  rm -rf "$tmpdir"
  exit 1
}

trap "printf \"commit: interrupted -- cleaning up\\n\" 1>&2 ; bail" INT

mkdir "$tmpdir"


################################################################
# Process Defaults for the Continuation Revision
# 

first()
{
  if test $# = 0 ; then
    printf "first called on empty list\\n" 1>&2
    bail
  else
    printf "%s\\n" "$1" 
  fi
}

second()
{
  if test $# -lt 2 ; then
    printf "first called on short list\\n" 1>&2
    bail
  else
    printf "%s\\n" "$2" 
  fi
}

if test ! -z "$continuation_revision" ; then


  indicated_continuation="`arch indicated-revision -e commit -R \"$archroot\" -A \"$archive\" \"$continuation_revision\"`"

  continuation_archive=${indicated_continuation%%/*}
  continuation_revision=${indicated_continuation#*/}

  continuation_category=`arch parse-package-name --basename $continuation_revision`
  continuation_branch=`arch parse-package-name $continuation_revision`
  continuation_vsn=`arch parse-package-name --vsn $continuation_revision`
  continuation_lvl=`arch parse-package-name --patch-level $continuation_revision`

fi



################################################################
# What Revision Comes Next?
# 


preclude_fix()
{
  if test $fix -ne 0 ; then
    printf "commit: too early for versionfix patches\\n" 1>&2
    printf "\\n" 1>&2
    printf "  version-0 patch level doesn't exist yet.\\n" 1>&2
    printf "\\n" 1>&2
    printf "Try \"--seal\" (see \"arch commit --help\").\\n" 1>&2
    printf "\\n" 1>&2
    bail
  fi
}

all_levels="`arch revisions -R \"$archroot\" -A \"$archive\" --reverse \"$version\"`"

if test "x$all_levels" = x ; then

  if test $continuation -ne 0 ; then
    lvl=base-0
  else
    printf "commit: version has no revisions yet\\n" 1>&2
    printf "\\n" 1>&2
    printf "  version: %s\\n" $version 1>&2
    printf "\\n" 1>&2
    printf "Try \"arch import --help\" or \"commit --continuation\" instead.\\n" 1>&2
    printf "\\n" 1>&2
    bail
  fi

else

  latest_lvl=`first $all_levels`

  case "$latest_lvl" in
    base-0)             preclude_fix
                        if test $seal -eq 0 ; then
                          lvl=patch-1
                        else
                          lvl=version-0
                        fi
                        ;;

    patch-*)            preclude_fix
                        if test $seal -eq 0 ; then
                          lvl="patch-$((${latest_lvl#patch-} + 1))"
                        else
                          lvl=version-0
                        fi
                        ;;

    version-0|versionfix-*)

                        lvl="versionfix-$((${latest_lvl##*-} + 1))"
                        if test $fix -eq 0 ; then
                          printf "commit: too late for ordinary patches\\n" 1>&2
                          printf "\\n" 1>&2
                          printf "  version-0 already exists.\\n" 1>&2
                          printf "\\n" 1>&2
                          printf "Try \"--fix\" (see \"arch commit --help\").\\n" 1>&2
                          printf "\\n" 1>&2
                          bail
                        fi
                        ;;

    
  esac

fi


# Conditions
#
#   lvl set to the patch level name for the revision 
#     we should create
# 
#   latest_lvl set to the patch level name of the previous revision 
# 
################################################################
# Is the Working Dir Sufficiently Up to Date
# 
# 
#

if test $out_of_date_ok -eq 0 ; then

  cd "$wdroot"

  missing=

  for rev in $all_levels ; do
    if test ! -e "{arch}/$category/$branch/$version/$archive/patch-log/$rev" ; then
      missing="$rev $missing"
    fi
  done

  if test "x$missing" != x ; then
    printf "commit: project tree out of date\\n" 1>&2
    printf "\\n" 1>&2
    printf "  Working directory is missing these patches:\n" 1>&2
    printf "\\n" 1>&2
    for m in $missing ; do
      printf "\t%s\\n" $m 1>&2
    done
    printf "\\n" 1>&2
    printf "  Unable to complete \"commit\".\\n" 1>&2
    printf "\\n" 1>&2
    printf "Try \"arch update --help\" or \"arch commit --out-of-date-ok\"\\n" 1>&2
    printf "\\n" 1>&2
    bail 
  fi

fi


################################################################
# Lint the Source Tree
# 

if test -z "$no_lint" ; then
  cd "$wdroot"

  if test ! -z "$quiet" ; then
    arch nested arch tree-lint
  else
    arch tree-lint > /dev/null
  fi
fi




################################################################
# Get a Pristine Copy of the Previous Revision to Compare With
# 

cd "$tmpdir"

if test ! -z "$report" ; then
  arch heading --sub "finding (or making) previous revision for comparison\\n"
  if test ! -z "$verbose" ; then
    arch heading --sub --sub "start time %s\\n" "`date`"
  fi
fi

if test $continuation -eq 0 ; then

  prev_archive="$archive"
  prev_category="$category"
  prev_branch="$branch"
  prev_vsn="$vsn"
  prev_lvl="$latest_lvl"

else

  prev_archive="$continuation_archive"
  prev_category="$continuation_category"
  prev_branch="$continuation_branch"
  prev_vsn="$continuation_vsn"
  prev_lvl="$continuation_lvl"

fi

if test -e "$wdroot/{arch}/++pristine-trees/locked/$prev_category/$prev_branch/$prev_branch--$prev_vsn/$prev_archive/$prev_branch--$prev_vsn--$prev_lvl" ; then

  prev_tree="$wdroot/{arch}/++pristine-trees/locked/$prev_category/$prev_branch/$prev_branch--$prev_vsn/$prev_archive/$prev_branch--$prev_vsn--$prev_lvl"

elif test -e "$wdroot/{arch}/++pristine-trees/unlocked/$prev_category/$prev_branch/$prev_branch--$prev_vsn/$prev_archive/$prev_branch--$prev_vsn--$prev_lvl" ; then

  prev_tree="$wdroot/{arch}/++pristine-trees/unlocked/$prev_category/$prev_branch/$prev_branch--$prev_vsn/$prev_archive/$prev_branch--$prev_vsn--$prev_lvl"

else

  prev_tree="$tmpdir/,,prev_tree"
  mkdir "$prev_tree"
  cd "$prev_tree"

  if ! arch nested arch build-revision -R "$archroot" -A "$prev_archive" \
                                       --silent $quiet_opt $report_opt $verbose_opt $debug_opt \
                                       --cache "$wdroot/.." $prev_branch--$prev_vsn--$prev_lvl ; then
    bail
  fi

fi

if test ! -z "$verbose" ; then
  arch heading --sub --sub "finish time %s\\n" "`date`"
fi

# Conditions
#
#   prev_tree points to a pristine tree for the previous revision
# 
################################################################
# Make a Pristine Copy of the Working Dir Tree
# 
# 

if test ! -z "$report" ; then
  arch heading --sub "making a pristine copy of the working dir tree\\n"
  if test ! -z "$verbose" ; then
    arch heading --sub --sub "start time: %s\\n" "`date`"
  fi
fi

tmptree="$tmpdir/$version--$lvl"
mkdir "$tmptree"

( cd "$wdroot" ; \
  arch inventory --source --all \
  | tar --files-from - --norecurse -cf - ) \
| ( cd "$tmptree" ; tar -xpf - )

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

################################################################
# Install the Log File
# 
# This is sleazy.  Later on, we'll replace the log file
# with a mangled version, and hack the patch for that.
# It needs to be there now so that mkpatch finds it.
# 

arch copy-to-patch-log -R "$archroot" -A "$archive" "$logfile" "$version" $lvl "$tmptree"


################################################################
# Modify the ChangeLog
# 
# More Sleaze -- to force the ChangeLog to show up in 
# the new or modified files lists.
# 

if test ! -z "changelog" ; then
  printf "\\n" >> "$changelog_file"
fi



################################################################
# Make a Patch Set Between The two Trees
# 

if test ! -z "$report" ; then
  arch heading --sub "making patch set\\n" 
fi

cd "$tmpdir"

arch nested arch mkpatch $silent_opt $quiet_opt $report_opt $verbose_opt "$prev_tree" "$tmptree" ,,patch-set


################################################################
# Compute the Changed File Sets
# 
# 

cd "$tmptree"
touch "$tmpdir/,,log-ls"
for v in `arch logs` ; do
  for p in `arch log-ls $v` ; do
    printf "%s--%s\\n" $v $p >> "$tmpdir/,,log-ls"
  done
done

cd "$prev_tree"
touch "$tmpdir/,,prev-patches"
for v in `arch logs` ; do
  for p in `arch log-ls $v` ; do
    printf "%s--%s\\n" $v $p  >> "$tmpdir/,,prev-patches"
  done
done

cd "$tmpdir"

rm -f ,,tmp
mv ,,log-ls ,,tmp
sort ,,tmp > ,,log-ls

rm -f ,,tmp
mv ,,prev-patches ,,tmp
sort ,,tmp > ,,prev-patches
rm -f ,,tmp

comm -2 -3 ,,prev-patches ,,log-ls >> ,,prev-only-patches
comm -1 -3 ,,prev-patches ,,log-ls >> ,,wd-only-patches

cd "$tmpdir/,,patch-set/patches"
find . -type f "(" -name "*.link-mod" -o -name "*.modified" -o -name "*.patch" -o -name "*.meta-mod" ")" \
| sed -e "s/\.[^.]*$//" \
| sort -u \
> "$tmpdir/,,modified-files"

cd "$tmpdir/,,patch-set/patches"
find . -type f -name "=dir-meta-mod" \
| xargs -r -n 1 dirname \
| sort \
> "$tmpdir/,,modified-dirs"


################################################################
# Has Anything Really Changed?
# 

cd "$tmpdir"

( printf "%s\\n" "./{arch}" ; \
  printf "%s\\n" "./{arch}/$category" ; \
  printf "%s\\n" "./{arch}/$category/$branch" ; \
  printf "%s\\n" "./{arch}/$category/$branch/$version" ; \
  printf "%s\\n" "./{arch}/$category/$branch/$version/$archive" ; \
  printf "%s\\n" "./{arch}/$category/$branch/$version/$archive/patch-log" ) \
| sed -e '{
            s,[/$*[\\],\\&,g
            s,^,/^,
            s,$,$/d,
          }' \
> ,,ignored-dirs-sed-script

if test ! -z "`cat ,,prev-only-patches ,,modified-files ,,modified-dirs | head -1`" \
        -o "`cat ,,wd-only-patches`" != "$archive/$version--$lvl" \
        -o "`join -v 2 -o 2.1 -1 2 -2 2 ,,patch-set/orig-files-index ,,patch-set/mod-files-index`" != "./{arch}/$category/$branch/$version/$archive/patch-log/$lvl" \
        -o ! -z "`join -v 1 -o 1.1 -1 2 -2 2 ,,patch-set/orig-files-index ,,patch-set/mod-files-index | head -1`" \
        -o ! -z "`join -v 2 -o 2.1 -1 2 -2 2 ,,patch-set/orig-dirs-index ,,patch-set/mod-dirs-index | sed -f ,,ignored-dirs-sed-script`" \
        -o ! -z "`join -v 1 -o 1.1 -1 2 -2 2 ,,patch-set/orig-dirs-index ,,patch-set/mod-dirs-index | head -1`" \
; then

  # something changed -- illegal with --seal or --continuation
  # 
  if test $seal -ne 0 -o $continuation -ne 0 ; then

    printf "commit: --seal and --continuation requires an unmodified project tree\\n" 1>&2
    printf "\\n" 1>&2
    printf "Try \"arch wd-changes --help\"\\n" 1>&2
    printf "\\n" 1>&2
    bail
  fi

else

  # nothing changed -- illegal without --seal or --continuation
  # 
  if test $seal -eq 0 -a $continuation -eq 0 ; then

    printf "project tree contains no modifications\\n" 1>&2
    printf "\\n" 1>&2
    bail
  fi

fi



################################################################
# Fix Up the Log File
# 

if test ! -z "$report" ; then
  arch heading --sub "mangling the log file\\n"
fi

cd "$wdroot"
cp "$logfile" "$tmpdir/,,raw-log"

cd "$tmpdir"

(   printf "Revision: %s\\n" $version--$lvl
 && printf "Archive: %s\\n" $archive
 && printf "Creator: %s\\n" "`arch my-id`"
 && printf "Date: %s\\n" "`date`"
 && printf "Standard-date: %s\\n" "`date +%Y-%m-%d`"
 && sed -e "/^\$/,\$d" ,,raw-log \
 && (  join -v 2 -o 2.1 -1 2 -2 2 ,,patch-set/orig-files-index ,,patch-set/mod-files-index \
     | sed -e 's,^\./,,' \
     | unfold -w 60 \
     | sed -e "1s/^/New-files: /" -e "1!s/^/  /" ) \
 && (  join -v 2 -o 2.1 -1 2 -2 2 ,,patch-set/orig-dirs-index ,,patch-set/mod-dirs-index \
     | sed -e 's,^\./,,' \
     | unfold -w 60 \
     | sed -e "1s/^/New-directories: /" -e "1!s/^/  /" ) \
 && (   join -v 1 -o 1.1 -1 2 -2 2 ,,patch-set/orig-files-index ,,patch-set/mod-files-index \
      | sed -e 's,^\./,,' \
      | unfold -w 60 \
      | sed -e "1s/^/Removed-files: /" -e "1!s/^/  /" ) \
 && (  join -v 1 -o 1.1 -1 2 -2 2 ,,patch-set/orig-dirs-index ,,patch-set/mod-dirs-index \
     | sed -e 's,^\./,,' \
     | unfold -w 60 \
     | sed -e "1s/^/Removed-directories: /" -e "1!s/^/  /" ) \
 && ( cat ,,modified-files | sed -e 's,^\./,,' | unfold -w 60 | sed -e "1s/^/Modified-files: /" -e "1!s/^/  /" ) \
 && ( cat ,,modified-dirs | sed -e 's,^\./,,' | unfold -w 60 | sed -e "1s/^/Modified-directories: /" -e "1!s/^/  /" ) \
 && ( cat ,,wd-only-patches | sed -e 's,^\./,,' | unfold -w 60 | sed -e "1s/^/New-patches: /" -e "1!s/^/  /" ) \
 && ( cat ,,prev-only-patches | sed -e 's,^\./,,' | unfold -w 60 | sed -e "1s/^/Removed-patches: /" -e "1!s/^/  /" ) \
 && printf "\\n" \
 && sed -e "1,/^\$/d" ,,raw-log ) \
> ,,cooked-log

if test ! -z "$quiet" ; then
  sed -e "/^\$/,\$d" ,,cooked-log | arch body-indent --sub
fi

################################################################
# Install the Log File
# 

arch copy-to-patch-log -R "$archroot" -A "$archive" "$tmpdir/,,cooked-log" "$version" $lvl "$tmptree"
new_file="$tmpdir/,,patch-set/new-files-archive/{arch}/$category/$branch/$version/$archive/patch-log/$lvl"
rm "$new_file"
cp "$tmpdir/,,cooked-log" "$new_file"


################################################################
# Fix Up the ChangeLog as it Appears in the Patch Set
# 

if test ! -z "$changelog" ; then
  cd "$tmptree"
  arch changelog "$archive/$version" > "$changelog_file"

  # where is the changelog in the prev tree?
  # 
  printf "%s\\n" "$changelog_file" > "$tmpdir/,,changelog_path"

  prev_changelog_file="`sort -k 1 \"$tmpdir/,,patch-set/mod-files-index\" \
                        | join -o 2.2 -1 1 -2 1 \"$tmpdir/,,changelog_path\" - \
                        | join -o 2.1 -1 1 -2 1 - \"$tmpdir/,,patch-set/orig-files-index\"`"

  if test -e "$tmpdir/,,patch-set/patches/$changelog_file.patch" ; then
    set +e
    diff -c "$prev_tree/$prev_changelog_file" "$tmptree/$changelog_file" >  "$tmpdir/,,patch-set/patches/$changelog_file.patch"
    diff_stat=$?
    set -e
    if test $diff_stat -ne 0 -a $diff_stat -ne 1 ; then
      printf "commit: internal error updating ChangeLog.patch\\n" 1>&2
      printf "  original file: %s\\n" "$prev_tree/$prev_changelog_file" 1>&2
      printf "  modified file: %s\\n" "$tmptree/$changelog_log" 1>&2
      printf "  diff exit status: %d\\n" $diff_stat 1>&2
      printf "\\n"
      exit 1
    fi
  elif test -e "$tmpdir/,,patch-set/new-files-archive/$changelog_file" ; then
    rm -f  "$tmpdir/,,patch-set/new-files-archive/$changelog_file"
    cp -p ChangeLog  "$tmpdir/,,patch-set/new-files-archive/$changelog_file"
  else
    printf "commit: internal error\\n" 1>&2
    printf "  can't figure out how to modify patch set for ChangeLog\\n"
    printf "\\n"
  fi
  rm -f "$tmpdir/,,changelog"
  cp "$changelog_file" "$tmpdir/,,changelog"
  dangerous-rename "$tmpdir/,,changelog" "$wdroot/$changelog_file"
fi


# Conditions
#
#   $tmpdir/,,patch-set         -- patch set for new revision
#   $tmpdir/,,cooked-log        -- log file for new revision
#   $tmpdir/$version--$lvl      -- pristine tree of new revision
#
################################################################
# Construct the Arch Template Dir
# 
#

if test ! -z "$report" ; then
  arch heading --sub "assembling the archive directory\\n"
  if test ! -z "$verbose" ; then
    arch heading --sub --sub "start time: %s\\n" "`date`"
  fi
fi

tmparch="$tmpdir/,,arch"
tmparch2="$tmpdir/arch"

mkdir "$tmparch"

mv "$tmpdir/,,patch-set" "$tmparch/$version--$lvl.patches"
cd "$tmparch"
tar zcf "$version--$lvl.patches.tar.gz" "$version--$lvl.patches"
mv "$version--$lvl.patches" ../,,patch-set

cp "$tmpdir/,,cooked-log" "$tmparch/log"

cd "$tmparch"

arch make-lock revision-lock

if test $continuation -ne 0 ; then
  printf "%s\\n" "$continuation_archive/$continuation_branch--$continuation_vsn--$continuation_lvl" > CONTINUATION
fi

mv "$tmparch" "$tmparch2"

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

# Conditions
# 
#   $tmptree                    -- pristine copy of new revision
#   $tmparch2                   -- template of revision directory
# 
# $tmpdir has these files:
#    ,,prev_tree        (might be missing -- tree for previous revision.
#                        $prev_tree points to ,,prev_tree or to a tree
#                        in the cache)
#    
#    ,,wd-dirs          Various specialized file lists
#    ,,wd-files
#    ,,log-ls
#    
#    ,,prev-dirs
#    ,,prev-files
#    ,,prev-patches
#    
#    ,,wd-only-dirs     Various file list diffs and intersections
#    ,,prev-only-dirs
#    
#    ,,wd-only-files
#    ,,prev-only-files
#    ,,files-in-both
#    
#    ,,wd-only-patches
#    ,,wd-only-patches
#    
#    ,,modified-files   List of modified files
#    
#    ,,raw-log          Log as written by user
#    
#    ,,cooked-log       Log with headers added
#    
#    ,,patch-set        The pach-set tree
#    
#    arch               A template of the archive directory
# 
#    $version--$lvl     A copy of the project tree
# 
# 
# 
# 
################################################################
# Install the Arch Template Dir or Clean Up the Output Dir
# 
# 

if test -z "$dry_run" ; then

  if test ! -z "$quiet" ; then
    arch heading --sub "installing the archive directory in the archive\\n"
    if test ! -z "$verbose" ; then
      arch heading --sub --sub "start time: %s\\n" "`date`"
    fi
  fi

  # where does this get stored in the archive?
  # 
  destdir="$category/$branch/$version/$lvl"

  wftp-home

  if ! arch with-archive -R "$archroot" -A "$archive" \
           arch putlast -e commit -R "$archroot" -A "$archive" \
                   lock-revision\
                   "$tmparch2" "$destdir" \
                   wd-txn "$wdroot" "$archive" "$version--$lvl" "$tmparch2/log" \
  ; then

    if test ! -z "$verbose" ; then
      arch heading --sub --sub "ARCHIVE TRANSACTION FAILED\\n"
      arch heading --sub --sub "finish time: %s\\n" "`date`"
    fi

    status=1

  else

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

    arch wd-mv-pristine $archive $version--$lvl "$tmptree" "$wdroot"
    cd "$wdroot"

    rm -rf "$tmpdir"
    rm -f "$logfile~"
    mv "$logfile" "$logfile~"

  fi

else

  status=0

  cd "$tmpdir"

  mv ,,patch-set patch-set

  if test -e ,,prev_tree ; then
     arch wd-mv-pristine $prev_archive $prev_branch--$prev_vsn--$prev_lvl ,,prev_tree "$wdroot"
  fi

  ln -s "`arch find-in-cache \"$wdroot/..\" $prev_branch--$prev_vsn--$prev_lvl`" $prev_branch--$prev_vsn--$prev_lvl

  if test -z "$quiet" ; then
    arch heading --sub "output in %s\\n" "$tmpdir"
  fi

fi

if test ! -z "$quiet" ; then
  arch heading --sub "commit finish time %s\\n" "`date`"
  arch heading --sub "commit exit status %s\\n" "$status"
fi

exit $status

