#! /bin/sh

# ckexternal
#	Verifies that the specified build directories contain the expected 
#	files to make the specified product (exports or install).
#
# Constructs the expected file list by listing all files in specified build
# directories minus imported and forced excluded files plus forced included 
# files.  Then constructs a bomgen list of these files and compares it to
# the expected bomgen list.
#
# The build directory is $LOCALVIEW.  The ``builddirlist'' specifies a
# list of directories in $LOCALVIEW which contain files that are, by
# default, assumed to be included in the product (exports or install).
# Files listed in $LOCALVIEW/IMPORTS are, by default, assumed not to
# be included in the product.  In order to include an imported file,
# it must be listed in the ``include'' list.  In order to exclude a
# non-imported file contained in a directory in ``builddirlist'', it
# must be listed in the ``exclude'' list.
#
# Finally, files which are not contained in a directory in ``builddirlist''
#
# Usage:   ckexternal [ -c ] builddirlist bomgen exclude include
#
#	builddirlist - file containing a list of directories in the build 
#		  directory which contain files needed for the product.
#		  This list is typically "i386/tmpos" or perhaps "usr i386".
#		  The list may be empty, in which case the process is driven
#		  entirely from the ``include'' parameter.
#		  (The build directory is $LOCALVIEW.)
#
#	bomgen	- expected bomgen file.  If the -c optioin is given,
#		  a new bomgen file is created by this name to use
#		  with future ckexternal invocations.
#
#	exclude	- file containing a list of files to exclude in addition 
#		  to IMPORTS (same format as first column of bomgen file).
#		  Defaults to /dev/null.
#
#	include	- file containing a list of files to force include
#		  (same format as first column of bomgen file).
#		  This can be used to either force the inclusion of
#		  a file listed in IMPORTS or to include files rooted
#		  in the build directory which are not contained in
#		  the specified builddirlist.
#		  Defaults to /dev/null.
#
#	If -c is specified then a new bomgen file is created.
#	In this case, the specified bomgen file must not already exist.
#
# Assumes the environment contains:
#
# LOCALVIEW	- directory path of local view, e.g., ~user/viewdir


#################################################################
# Setup filenames used						#
#################################################################

if [ $# -lt 2 ]
then
	echo usage: ckexternal [ -c ] builddirlist bomgen exclude include
	exit 1
fi

#
# If the -c option is specified then create a new bomgen file.
#
if [ "$1" = "-c" ]
then
	CREATE_BOM=TRUE
	shift
else
	CREATE_BOM=FALSE
fi


BUILDDIRLIST=$1			# List of directories in $BUILDDIR containing
				# files for the specified product

BOMGEN=$2			# Name of bomgen file to compare or create.

FORCE_EXCLUDE=$3		# Name of file with list of files to exclude
				# in addition to IMPORTS; in same format as
				# IMPORTS

FORCE_INCLUDE=$4		# Name of file with list of files to include.
				# This is used to force an IMPORTED file to
				# be included.


BUILDDIR=$LOCALVIEW		# build directory
IMPORTS=$LOCALVIEW/IMPORTS	# IMPORTS file or /dev/null if no imports


if [ ! -f "$IMPORTS" ]
then
	IMPORTS=/dev/null	# no IMPORTS file, default it
fi

if [ ! -f "$BUILDDIRLIST" ]
then
	echo "Error: $BUILDDIRLIST missing."
	exit 1
fi

if [ -z "$FORCE_EXCLUDE" ]
then
	FORCE_EXCLUDE=/dev/null	# no FORCE_EXCLUDE file, default it
fi

if [ -z "$FORCE_INCLUDE" ]
then
	FORCE_INCLUDE=/dev/null	# no FORCE_INCLUDE file, default it
fi

DYNIX="-f /dynix"                               # On a Dynix 3.0 System?
DYNIXPSX="-f /unix"                             # On a Dynix/psx System?

if [ $DYNIX ] ;then
        FIND=/usr/.bin/find
elif [ $DYNIXPSX ] ;then
        FIND=/bin/find
else
        echo $0: confused as to what host machine is
        exit 1
fi

#
# If user requested a new bomgen file to be created, ensure it doesn't
# already exist.  Otherwise, ensure it does exist.
#
if [ $CREATE_BOM = TRUE ]
then
	if [ -f $BOMGEN ]
	then
		echo "Error: $BOMGEN already exists, can't create."
		exit 1
	fi
else
	if [ ! -f $BOMGEN ]
	then
		echo "Error: $BOMGEN missing."
		exit 1
	fi
fi

#
# Temporary files
#
TMP_IMPORTS=/tmp/imports.$$
TMP_EXCLUDE=/tmp/exclude.$$
TMP_INCLUDE=/tmp/include.$$
TMP_BUILDFILES=/tmp/buildfiles.$$
TMP=/tmp/tmp.$$
NEWBOMGEN=/tmp/bomgen.$$
INBOMGEN=/tmp/inbomgen.$$


#################################################################
# Setup file lists						#
#################################################################

#
# Create a list of all IMPORTED files/directories.
#
sed -n "/^	/s/^	//p" $IMPORTS | sort -u		> $TMP_IMPORTS

#
# Create a list of additional files forced to be EXCLUDED.
#
sort -u $FORCE_EXCLUDE					> $TMP_EXCLUDE

#
# Create a list of files forced to be INCLUDED.
#
sort -u $FORCE_INCLUDE					> $TMP_INCLUDE

#
# Determine whether $BUILDDIRLIST is empty and
# verify that all entries are directories.
#
EMPTY=true
for i in `cat $BUILDDIRLIST`
do
	EMPTY=false	# at least one entry
	if [ ! -d $BUILDDIR/$i ]
	then
		echo "Error: $i in build directory list ($BUILDDIRLIST)"
		echo "       is not a directory."
		exit 1
	fi
done

#
# Create a list of all files/directories in the specified build directories.
#
if [ $EMPTY = false ]
then
	(CWD=`pwd`; cd $BUILDDIR; $FIND `cd $CWD; cat $BUILDDIRLIST` -print)
fi	|	sort	> $TMP_BUILDFILES


#################################################################
# Sanity check							#
#################################################################

#
# Any files appear in both the imports and exclude lists?
#
comm -12 $TMP_IMPORTS $TMP_EXCLUDE > $TMP

if [ -s $TMP ]
then
	echo " "
	echo "WARNING: The following files appear in both $IMPORTS & $FORCE_EXCLUDE"
	echo " "
	cat $TMP
fi

#
# Any files appear in both the force include and exclude lists?
#
comm -12 $TMP_INCLUDE $TMP_EXCLUDE > $TMP

if [ -s $TMP ]
then
	echo " "
	echo "Error: The following files appear in both $FORCE_INCLUDE & $FORCE_EXCLUDE"
	echo " "
	cat $TMP
	exit 1
fi

#
# Any excluded files missing in build file list?
#
comm -23 $TMP_EXCLUDE $TMP_BUILDFILES > $TMP

if [ -s $TMP ]
then
	echo " "
	echo "Error: The following files appear in $FORCE_EXCLUDE but not $BUILDDIR"
	echo " "
	cat $TMP
	exit 1
fi

#################################################################
# Create new bomgen list based on final file list.		#
# Compare to expected bomgen list.				#
#################################################################

#
# The following pipeline does the following steps:
#
# Create a final list of files to omit from the build file list by 
#	merging the imports and exclude lists.
# Create a list of all current files/directories in the build file list 
#	minus the omitted files/directories.
# Add to the list the list of included files.
# Pass that list through expandpath to add all directories needed
#	for files in the list; sort/uniq the list.
# Pass that list through bomgen to create a BOM format file.
# Pass the BOM file through massagebom to ignore the size & checksum fields.
#
(
sort -u $TMP_IMPORTS $TMP_EXCLUDE		|
comm -23 $TMP_BUILDFILES -			|
sort -u $TMP_INCLUDE -				|
expandpath					|
sort -u						|
(cd $BUILDDIR; bomgen)				|
massagebom					> $NEWBOMGEN
) 2> $TMP	# capture stderr for pipeline

#
# If any error messages were generated then print them and quit.
#
if [ -s $TMP ]
then
	echo " "
	echo "Error: The following errors were detected while constructing"
	echo "       the expected BOM file:"
	echo " "
	cat $TMP
	exit 1
fi

#
# If creating a new bomgen file, make a new one and exit.
#
if [ $CREATE_BOM = TRUE ]
then
	echo "CREATING NEW BOMGEN FILE: $BOMGEN"
	cp $NEWBOMGEN $BOMGEN
	exit 0
fi

#
# Compare new bomgen file to expected bomgen file.
#
sort -u $BOMGEN > $INBOMGEN
diff $INBOMGEN $NEWBOMGEN > $TMP

if [ ! -s $TMP ]
then
	echo "Resulting file list MATCHES expected $BOMGEN exactly."
	EXIT=0
else
	#
	# New bomgen file differs from expected bomgen file; report differences.
	#
	echo " "
	echo "Error: Resulting file list DIFFERS from expected $BOMGEN."
	echo " "
	echo "Output from diff $INBOMGEN NEWBOMGEN:"
	echo " "
	echo "<   - Indicates files missing from the build directory"
	echo "      or unexpectedly excluded"
	echo " "
	echo ">   - Indicates unexpected files in the build directory"
	echo "      or files unexpectedly included"
	echo " "
	cat $TMP
	EXIT=1
fi


#################################################################
# Cleanup:  Remove tmp files.					#
#################################################################

rm -f	$TMP_IMPORTS $TMP_EXCLUDE $TMP_INCLUDE $TMP_BUILDFILES $TMP $NEWBOMGEN \
	$INBOMGEN

exit $EXIT
