#!/bin/sh
# touched-files-prereqs.sh: print prereqs of a revision
# 
################################################################
# Copyright (C) 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 "print prereqs of a revision\\n"
                printf "usage: touched-files-prereqs [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 "\\n"
                printf " --show-files                  list the overlapping files\\n"
                printf "\\n"
                printf " --exclude ERE                 specify an ERE for files to ignore\\n"
                printf "                                the default ERE is \"^.*/ChangeLog[^/]*\$\"\\n"
                printf "\\n"
                printf " --missing-from DIR            list only patches not already\\n"
		printf "                                applied to DIR\\n"
		printf "\\n"
		printf "Print the list of earlier patches in the same version as REVISION\\n"
		printf "which touch the same files (ignoring files named \"ChangeLog\" and\\n"
		printf "larch control files).\\n"
		printf "\\n"
		printf "Note that this command searches patch sets in a library, not\\n"
		printf "in repositories.\\n"
		printf "\\n"
                exit 0
                ;;

      *)
                ;;
    esac
  done
fi

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

archroot=
archive=
show_files=
exclude='^.*/ChangeLog[^/]*\$'
missing_from=

while test $# -ne 0 ; do

  case "$1" in 

    --show-files)	shift
    			show_files=--show-files
			;;

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

    --missing-from)     shift
                        if test $# -eq 0 ; then
                          printf "touched-files-prereqs: --missing-from requires an argument\\n" 1>&2
                          printf "try --help\\n" 1>&2
                          exit 1
                        fi
                        missing_from="$1"
                        shift
                        ;;

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

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

rvnspec="$1"
shift

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

library="`larch my-revision-library -e touched-files-prereqs`"

archive_revision=`larch indicated-revision -e touched-files-prereqs -R "$archroot" -A "$archive" "$rvnspec"`

archive=${archive_revision%%/*}
revision=${archive_revision#*/}
category="`larch parse-package-name --basename \"$revision\"`"
branch="`larch parse-package-name \"$revision\"`"
version="`larch parse-package-name --package-version \"$revision\"`"
lvl="`larch parse-package-name --lvl \"$revision\"`"

if test ! -z "$missing_from" ; then
  missing_from="`larch tree-root --accurate \"$missing_from\"`"
fi


################################################################
# Do It
# 

if test ! -d "$library/$archive/$category/$branch/$version/$revision" ; then

  printf "\\n" 1>&2
  printf "%s: revision not in library\\n" "$errname" 1>&2
  printf "  archive: %s\\n" "$archive" 1>&2
  printf "  revision: %s\\n" "$revision" 1>&2
  printf "\\n" 1>&2
    
else

  cd "$library/$archive/$category/$branch/$version"

  larch library-revisions --reverse "$archive/$version" \
  | awk -v lvl="$lvl" \
	-v archive="$archive" \
	-v version="$version" \
	-v show_files="$show_files" \
	-v exclude="$exclude" \
	-v missing_from="$missing_from" \
    '
	BEGIN {
	        skipping = 1;

		if (missing_from != "")
		  {
		    missing_cmd = "larch log-ls --dir \"" missing_from "\" " archive "/" version;

		    while (0 < (missing_cmd | getline))
		      {
		        already_have[$0] = 1;
		      }
		    close(missing_cmd);
		  }
	      }

	(lvl == $0)	{
			  skipping = 0;
			}

	!skipping	{
			  this = $0;
			  read_touched_files(this);
			  n = n_files_overlap();
			  if ((this == lvl) || (n > 0))
			    {
			      remember_touched_files();
			      if (!already_have[this])
			        {
				  print this;
				  if (show_files != "")
				    {
				      for (x = 0; x < n; ++x)
				        print "\t" overlaps[x];
				      for (x in new_tags)
				        if (!overlap_tags[x])
					print "\t+ " new_tags[x];
				    }
				}
			    }
			}

	function read_touched_files(l)
	{
    	  mod_files_index = version "--" l "/,,patch-set/mod-files-index";
	  mod_dirs_index = version "--" l "/,,patch-set/mod-dirs-index";
	  orig_files_index = version "--" l "/,,patch-set/orig-files-index";
	  orig_dirs_index = version "--" l "/,,patch-set/orig-dirs-index";

	  for (f in new_tags)
	    delete new_tags[f];

	  read_index(mod_files_index);
	  read_index(mod_dirs_index);
	  read_index(orig_files_index);
	  read_index(orig_dirs_index);
	}

	function n_files_overlap()
	{
	  for (t in overlap_tags)
	    delete overlap_tags[t];

	  x = 0;

	  for (f in new_tags)
	    if (touched_tags[f] != "")
	      {
		overlaps[x] = touched_tags[f];
		overlap_tags[f] = 1;
		++x;
	      }
	  return x;
	}

	function remember_touched_files()
	{
	  for (f in new_tags)
	    {
	      if (touched_tags[f] == "")
	        touched_tags[f] = new_tags[f]
	    }
	}

	function read_index(file)
	{
	  while (0 < (getline < file))
	    {
	      loc = $1;
	      tag = $2;

	      if (!match(loc, exclude))
	        new_tags[tag] = loc;
	    }
	  close(file);
	}
    '



fi  

# tag: Tom Lord Fri Feb  8 23:00:07 2002 (library/touched-files-prereqs.sh)
#
