# 
# what-changed.sh: compare project tree to cached pristine
################################################################
# 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 "compare project tree to cached pristine\\n"
                printf "usage: what-changed [options] [[archive/]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 "  --cache DIR                  cache directory for locally cached\\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 "                                 revisions\\n"
                printf " --dir DIR                     cd to DIR first\\n"
                printf " -o --output OUTUPT            specify an output directory name\\n"
                printf "\\n"
                printf " --omit-empty                  omit empty sections\\n"
                printf " --diffs                       include diffs in outline\\n"
                printf " --html                        also generate HTML format output\\n"
                printf " --url                         output should be a URL\\n"
                printf "                                 implies --html\\n"
                printf "\\n"
                printf "Generate a patch report describing the differences between the\\n"
                printf "project tree containing DIR (or the current directory) and\\n"
                printf "REVISION.\\n"
                printf "\\n"
                printf "The default patch level for a given version is the latest level for\\n"
                printf "which the project tree has a patch.  The default archive and version\\n"
                printf "is as printed by \"larch tree-version\".\\n"
                printf "\\n"
                printf "Output is normally stored in the root of the project tree in the file\\n"
                printf "\\n"
                printf "                ,,what-changed.REVISION--ARCHIVE\\n"
                printf "\\n"
                printf "but that can be overriden with -o (--output)\\n"
                printf "\\n"
                printf "Ordinary output is an outline-format patch report (sans diffs).\\n"
                printf "The flags --diffs causes diffs to be included in the outline.\\n"
                printf "The outline is also stored in the output directory under the name\\n"
                printf "\\n"
                printf "                =REPORT\\n"
                printf "\\n"
                printf "With --html, also generate an \"index.html\" file in the output\\n"
                printf "directory containing an HTML-format report.  (The same file is linked\\n"
                printf "to \"=REPORT.html\").\\n"
                printf "\\n"
                printf "With --url (which implies --html), create the output directory, but\\n"
                printf "instead of copying the report to stdout, print a \"file:\" URL for\\n"
                printf "the HTML report.\\n"
                printf "\\n"
                printf "Note: with --url, all other normal output is suppressed as per --silent.\\n"
                printf "\\n"
                exit 0
                ;;

      *)
                ;;
    esac
  done
fi

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

archroot=
archive=
cache_dir=

dir=
output=
omit_empty=
diffs=
html=
url=

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


while test $# -ne 0 ; do

  case "$1" in 

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


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

    -d|--dir)           shift
                        if test $# -eq 0 ; then
                          printf "what-changed: -d and --dir require an argument\\n" 1>&2
                          printf "try --help\\n" 1>&2
                          exit 1
                        fi
                        dir="$1"
                        shift
                        ;;

    -o|--output)        shift
                        if test $# -eq 0 ; then
                          printf "what-changed: -o and --output require an argument\\n" 1>&2
                          printf "try --help\\n" 1>&2
                          exit 1
                        fi
                        output="$1"
                        shift
                        ;;

    --omit-empty)       shift
                        omit_empty=--omit-empty
                        ;;

    --diffs)            shift
                        diffs=--diffs
                        ;;

    --html)             shift
                        html=--html
                        ;;

    --url)              shift
                        html=--html
                        url=--url
                        ;;

    --)                 shift
                        break
                        ;;

    -*)                 printf "what-changed: 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: what-changed [options] [[archive/]revision]\\n" 1>&2
  printf "try --help\\n" 1>&2
  exit 1
fi

if test $# -ne 0 ; then
  rvnspec="$1"
  shift
else
  rvnspec=
fi

################################################################
# Sanity Check and Process Defaults
# 

cd "$dir"
dir="`pwd`"
wdroot="`larch tree-root`"

cd "$wdroot"

if test -z "$rvnspec" ; then
  rvnspec="`larch tree-version`"
fi

larch valid-package-name -e what-changed -t "$rvnspec"

archive="`larch parse-package-name -R \"$archroot\" -A \"$archive\" --arch \"$rvnspec\"`"
category="`larch parse-package-name -R \"$archroot\" -A \"$archive\" --basename \"$rvnspec\"`"
branch="`larch parse-package-name -R \"$archroot\" -A \"$archive\" --package \"$rvnspec\"`"

if larch valid-package-name --vsn -t "$rvnspec" ; then
  version="`larch parse-package-name --package-version \"$rvnspec\"`"
else
  version="`larch logs -r \"$branch\" | head -n 1`"
  if test -z "$version" ; then
    printf "what-changed: no logs for that branch\\n" 1>&2
    printf "  branch: %s\\n" "$branch" 1>&2
    printf "\\n"
    exit 1
  fi
  version="`larch parse-package-name --package-version \"$version\"`"
fi

if larch valid-package-name --patch-level -t "$rvnspec" ; then
  revision="`larch parse-package-name --non-arch \"$rvnspec\"`"
else
  lvl="`larch log-ls -r \"$archive/$version\" | head -n 1`"
  if test -z "$lvl" ; then
    printf "what-changed: no patch level for that version\\n" 1>&2
    printf "  branch: %s\\n" "$version" 1>&2
    printf "\\n"
    exit 1
  fi
  revision="$version--$lvl"
fi

if test -z "$cache_dir" ; then
  cd "$wdroot/.."
  cache_dir="`pwd`"
  cd "$wdroot"
fi

if larch library-find --silent -A "$archive" "$revision" > /dev/null ; then

  revision_tree="`larch library-find --silent -A \"$archive\" \"$revision\"`"

else
  set +e
  revision_tree="`larch find-in-cache -A \"$archive\" \"$cache_dir\" \"$revision\"`"
  status=$?
  set -e

  if test $status -ne 0 ; then
    printf "what-changed: revision not in library or local cache\\n" 1>&2
    printf "  revision: %s\\n" "$revision" 1>&2
    printf "\\n" 1>&2
    printf "See \"larch add-pristine\"\\n" 1>&2
    printf "\\n" 1>&2
    exit 1
  fi

fi

if test -z "$output" ; then
  output="$wdroot/,,what-changed.$revision--$archive"
  rm -rf "$output"
fi

if test -e "$output" ; then
  printf "what-changed: can't create output directory (EEXIST)\\n" 1>&2
  printf "  output dir: %s\\n" "$output" 1>&2
  printf "\\n" 1>&2
  exit 1
fi


if test ! -z "$url" ; then
  silent_opt=
  quiet_opt=
  report_opt=
  verbose_opt=
  quiet=
  report=
  verbose=
fi


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

if test ! -z "$quiet" ; then
  larch heading "what-changed\\n"
  printf "arguments: %s\\n" "$command_line" | fold -w 60 | larch body-indent
  larch heading --sub "project tree: %s\\n" "$wdroot"
  larch heading --sub "old tree: %s\\n" "$revision_tree"
  larch heading --sub "old revision: %s\\n" "$revision"
  larch heading --sub "output directory: %s\\n" "$output"
fi


################################################################
# Compute Diffs
# 

if test ! -z "$report" ; then
  larch heading --sub "computing patch set\\n"
  if test ! -z "$verbose" ; then
    larch heading --sub --sub "start time: %s\\n" "`date`"
  fi
fi

larch nested larch mkpatch --silent $report_opt $verbose_opt $debug_opt "$revision_tree" "$wdroot" "$output"

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

################################################################
# Compute Patch Report
# 

cd "$output" 

# url html 
# --------
# yes yes               output url only, generate both
# no  yes               output outline, generate both
# no  no                output outline, outline only
# 

if test -z "$url" ; then
  larch patch-report $omit_empty $diffs . | tee =REPORT | larch nest
else
  larch patch-report $omit_emtpy $diffs . > =REPORT
fi

if test ! -z "$html" ; then
  larch patch-report $omit_empty --html . > index.html
  ln index.html =REPORT.html
fi

if test ! -z "$url" ; then
  printf "%s\\n" "file:`pwd`/=REPORT.html" \
  | sed -e '{
              s/ /%20/g
              s/	/%09/g
              s/,/%2c/g
            }'
elif test ! -z "$html" ; then
  larch heading --sub "report url: %s\\n" "file:`pwd`/=REPORT.html" 
fi

# tag: Tom Lord Thu Dec 13 18:32:15 2001 (local-cache/what-changed.sh)
#
