#!/bin/sh
#ident   @(#)bldpkghist.sh 1.10 99/06/02 SMI
#
# arg 1 : directory of old package maps
#    <directory> is of form:
#
#             <directory>
#		  |
#            --------------------
#	    |         |        |
#	SUNWcsr    SUNWcar.m  SUNWadmr   ......
#           |          |        |
#        pkgmap      pkgmap    pkgmap
#
# arg 2 : directory containing new packages (flat directory structure,
#         similar to that of the directory of the old package maps,
#         but these must the full packages).
# arg 3 : pathname of old history file
# arg 4 : directory containing any consolidation-provided "special"
#         new pkghistory entries (for changes that can't be detected
#	  automatically, such as package renames).  The entries are
#	  names <package_name>.ph .  A "-" supplied for this argument
#         means that there are no "special" entries to be provided (an
#         empty directory will have the same result).
# arg 5 : file containing list of internal packages which should not
#	  be examined for new history entries ("-" if none).
# arg 6 : output location for final hist file
#

# THE LINE ABOVE THIS ONE MUST BE BLANK

cleanup ()
{
    rm -f /tmp/*.$$
    rm -fr /tmp/hist.concat.$$
    exit $1
}

usage ()
{
    # This is a hack, but it's easier than trying to fit the above into
    # a proper usage statement.  It prints all comments starting from the
    # top of the file down to the first blank line.
    awk '/^$/ { exit; } /^#!\/bin\/sh/ || /^#ident/ { next; } /^#/ { print ; } ' <$0
}

if [ $# != 6 ] ; then
    usage
    exit 1
fi

opd=$1
npd=$2
oldhistfile=$3
newhistdir=$4
excludefile=$5
finalhistfile=$6

#
# FIRST:  build file of components removed from the packages.
#

rm -f /tmp/*.$$

if [ "$excludefile" != "-" ] ; then
	excludelist=`cat $excludefile`
fi

echo Building list of packages:
(cd $npd;
for j in */pkginfo; do
	pkgname=`dirname $j`
	if [ "$excludelist" != "" ] ; then
		for i in $excludelist ; do
			if [ $i = $pkgname ] ; then
				pkgname=""
				break;
			fi
		done
	fi
	if [ "$pkgname" != "" ] ; then
		echo $pkgname
	fi
done ) > /tmp/pkglist.$$

#
# SECOND: Generate the list of files that have been removed between the old
#	  and new versions of the packages
#
echo Building removed file list:
cat > /tmp/cmp.sed.$$ << EOF
/ i /d
/^:/d
s/^1 . [^ ]* \([^ =]*\)[ =].*$/\1/
EOF

cat /tmp/pkglist.$$ | while read i ; do
	if [ -d $opd/$i ] ; then
		# generate list of files in old package, resolving macros
		echo $i

		# generate file of PKG-ARCH-VERSION info for new pkgs
		grep '^PKG=' $npd/$i/pkginfo >> /tmp/newpkgs.$$
		grep '^ARCH=' $npd/$i/pkginfo >> /tmp/newpkgs.$$
		grep '^VERSION=' $npd/$i/pkginfo >> /tmp/newpkgs.$$

		# If the pkgmap and pkginfo are identical, then we can skip the
		# removed files check for this package
		cmp $opd/$i/pkgmap $npd/$i/pkgmap >/dev/null 2>&1 &&
		    cmp $opd/$i/pkginfo $npd/$i/pkginfo >/dev/null 2>&1 &&
		    continue
		
		if grep '\$' $opd/$i/pkgmap >/dev/null 2>&1 ; then
			(rm -f /tmp/pkgmacros.$$ /tmp/resolvedfiles.$$
			cat $opd/$i/pkginfo |
			while read j
			do
				echo `echo $j| sed -e 's/^\(.*\)=.*/\1/'`=\"`echo $j|sed -e 's/^\(.*\=\)//'`\" | grep -v '^PATH' >> /tmp/pkgmacros.$$
			done
			. /tmp/pkgmacros.$$
			sed -f /tmp/cmp.sed.$$ $opd/$i/pkgmap | 
		    	( while read j
		    	do
				eval echo $j 
		    	done ) | sort > /tmp/omap.$$
			)
		else
			sed -f /tmp/cmp.sed.$$ $opd/$i/pkgmap | sort > \
			    /tmp/omap.$$
		fi

		# generate list of files in new package, resolving macros
		if grep '\$' $npd/$i/pkgmap >/dev/null 2>&1 ; then
			(rm -f /tmp/pkgmacros.$$ /tmp/resolvedfiles.$$
			cat $npd/$i/pkginfo |
			while read j
			do
				echo `echo $j| sed -e 's/^\(.*\)=.*/\1/'`=\"`echo $j|sed -e 's/^\(.*\=\)//'`\" | grep -v '^PATH' >> /tmp/pkgmacros.$$
			done
			. /tmp/pkgmacros.$$
			sed -f /tmp/cmp.sed.$$ $npd/$i/pkgmap | 
		    	( while read j
		    	do
				eval echo $j 
		    	done ) | sort > /tmp/nmap.$$
			)
		else
			sed -f /tmp/cmp.sed.$$ $npd/$i/pkgmap | sort > \
			    /tmp/nmap.$$
		fi

		# find files that are in old package, but not in new
		comm -23 /tmp/omap.$$ /tmp/nmap.$$  | sort -r > /tmp/rmfiles.$$
		(if [ -s /tmp/rmfiles.$$ ] ; then
			grep '^PKG=' $npd/$i/pkginfo
			grep '^ARCH=' $npd/$i/pkginfo
			grep '^VERSION=' $npd/$i/pkginfo
			sed 's/^./REMOVED_FILES=&/' /tmp/rmfiles.$$
		fi) >> /tmp/all_rmfiles.$$
	fi
done


#
# Build concatenated file of new history entries
#

touch /tmp/newhistfile.raw.$$
touch /tmp/newhistfile.$$
anyfound=0
origdir=`pwd`
if [ "$newhistdir" != "-" ] ; then
	cd $newhistdir
	if ls *.ph >/dev/null 2>&1 ; then
	    for j in *.ph ; do
		#
		# VERSION can be:
		#	xxx
		#	xxx:yyy
		#	latest
		#	xxx:latest
		#
		# Where the string 'latest' will be replaced by the
		# latest version
		#
		grep '^VERSION=.*latest' $j >/dev/null 2>&1
		if [ $? = 0 ] ; then
			grep '^VERSION=latest.*:' $j >/dev/null 2>&1
			if [ $? = 0 ] ; then
				echo "Error: $j: bad version"
				cleanup 99
			fi
			pkgname=`basename $j ".ph"`
			version=`grep "^VERSION=" $npd/$pkgname/pkginfo`
			version=`expr $version : 'VERSION=\(.*\)'`
			sed "/^VERSION/s/latest/$version/" $j \
			   >> /tmp/newhistfile.raw.$$
		else
			cat $j >> /tmp/newhistfile.raw.$$
		fi
		# Add a newline just in case the submitted ph file
		# didn't have one on the last line.  This will cause
		# blank lines to be generated after entries that do
		# have newlines on their last lines.
		echo >>/tmp/newhistfile.raw.$$
	    done
	fi
	cd $origdir
fi

# Strip out the spurious newlines (if any) generated by the echo statement
# above.
sed -e '/^$/d' </tmp/newhistfile.raw.$$ >/tmp/newhistfile.$$

#
# combine them all into final history file
#

#
# Look for buildhist
#
if [ -x "./buildhist" ] ; then
    BUILDHIST=./buildhist
elif [ -x "`dirname $0`/buildhist" ] ; then
    BUILDHIST="`dirname $0`/buildhist"
else
    echo "Couldn't find buildhist" >&2
    cleanup 1
fi

echo Building final history file using "$BUILDHIST"

#
# If the removed file list is empty, don't send in the -r argument.
#
cmdline="$BUILDHIST -p $oldhistfile -n /tmp/newhistfile.$$ \
	-v /tmp/newpkgs.$$ -o $finalhistfile"
if [ -f /tmp/all_rmfiles.$$ ]; then
	cmdline="$cmdline -r /tmp/all_rmfiles.$$"
fi
$cmdline
cleanup $?
