#! /bin/sh
#
# Create archives in a destination directory from files in an input tree
# using manifest files listed on stdin.
#
# Takes the following arguments:
#
#	--to=<dir>	The directory in which to create the archives,
#			typically something like "ADE-dist:951208".
#
#	--from=<dir>	The root of the tree containing the files named in
#			the manifest files whose names are read from stdin.
#			Typically something like "ADE-src" or "ADE-bin".
#
#	--tmp=<dir>	A temporary directory in which to create temporary
#			subdirs used in creating the archives.
#
#	--tgz		Build gzip compresed tar archives rather than
#			lha archives.  This is a more portable format
#			and is used for things like source archives, which
#			are potentially useful on non-Amiga systems.
#
# Builds the output file name from components of the input manifest file
# pathname and the version number read from an associated Product-Info file.
#
# The associated product info file for each archive is found either by
# looking for an appropriate *-pi file in the manifests subdir, or from the
# Product-Info in the same directory as the manifests subdir.
#
# For example, if the manifest file is "fsf/cpio/manifests/bin", then the
# archive filename will be something like "cpio-X.Y-bin.lha" where X.Y is
# read from the Product-Info file in "fsf/cpio".
#
# As another example, if the manifest file is "manifests/GNU-Startup-bin"
# then the archive filename will be "GNU-Startup-bin.lha".

# Process the options and remember them for future use.

artype="lha"
to=
from=
tmp=
prev=
for option
do

	# If the previous option needs an argument, assign it.
	if test -n "$prev"; then
		eval "$prev=\$option"
		prev=
		continue
	fi

	case "$option" in
		-*=*) optarg=`/bin/echo "$option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
		*) optarg= ;;
	esac

	case "$option" in
		--to)		prev=to ;;
		--to=*)		to="$optarg" ;;
		--from)		prev=from ;;
		--from=*)	from="$optarg" ;;
		--tmp)		prev=tmp ;;
		--tmp=*)	tmp="$optarg" ;;
		--tgz)		artype="tgz" ;;
		-*) { echo "error: $option: invalid option" 1>&2; exit 1; } ;;
	esac
done

# Verify that we have all the options we expect to have.

if test -z "$to"; then
	echo "error: no --to=<dir> argument given" 1>&2
	exit 1
fi

if test -z "$from"; then
	echo "error: no --from=<dir> argument given" 1>&2
	exit 1
fi

if test -z "$tmp"; then
	echo "error: no --tmp=<dir> argument given" 1>&2
	exit 1
fi

# Check to see that the output directory exists.  If not, create it.

if test ! -d "$to"
then
	echo "mkdir -p $to"
	mkdir -p $to
fi

# Check to see that the temporary directory exists.  If not, create it.

WORKDIR="$tmp/GNUpack"
if test ! -d "$WORKDIR"
then
	echo "mkdir -p $WORKDIR"
	mkdir -p $WORKDIR
fi

# Read and process each manifest file from stdin.

while read manifest
do
	echo "Processing $manifest ..."

	# Locate the product info files (if any) that corresponds
	# to this manifest file.  There may be one that is the same
	# name as the manifest file but with "-pi" appended, and there
	# may be one in the parent directory of the location where the
	# manifest file is found.  If there are two, they must agree
	# on the version number.  If neither exist, there is no version
	# number (which is OK).

	vers1=""
	vers2=""
	pifilein=""
	mdot=`dirname $manifest`
	mdotdot=`dirname $mdot`
	product=`basename $mdotdot`
	if test -f "$mdotdot/Product-Info"
	then
		pifilein=$mdotdot/Product-Info
		product=`pitool -b -u -F "%N" -f - $pifilein`
		vers1=`pitool -b -u -F "%V" -f - $pifilein`
	fi
	if test -f "$manifest-pi"
	then
		pifilein=$manifest-pi
		product=`pitool -b -u -F "%N" -f - $pifilein`
		vers2=`pitool -b -u -F "%V" -f - $pifilein`
	fi
	if test -n "$vers1" -a -n "$vers2"
	then
		if test "$vers1" != "$vers2"
		then
			echo "WARNING - conflicting version numbers $vers1 and $vers2" 2>&1
			vers1=""
		fi
	fi
	if test "$vers2" = "?.?"
	then
		version=""
	elif test "$vers1" = "?.?"
	then
		version=""
	elif test -n "$vers2"
	then
		version=$vers2
	elif test -n "$vers1"
	then
		version=$vers1
	else
		version=""
	fi

	# Now create the name of the archive.
	#
	# If the manifest file is from our special global manifest file
	# directory, then the name of the archive is just the name of the
	# manifest file.
	#
	# Otherwise we start with the product name, tack on a version
	# number if one exists, and then tack on the name of the manifest
	# file as a qualifier.
	#
	# Finally we tack on the archive type.

	if test "$mdot" = "manifests"
	then
		archive="`basename $manifest`"
	else
		archive="$product"
		if test -n "$version"
		then
			archive="$archive-$version"
		fi
		archive="$archive-`basename $manifest`"
	fi	
	archive="$archive.$artype"

	# Verify that we have an input Product-Info file

	pifileout="$to/$archive.pi"
	if test -z "$pifilein"
	then
		echo "WARNING: no product info file found to generate $pifileout - skipped"
		continue
	fi

	# Check to see if this archive already exists.  If so, skip
	# creating one.  This allows us to restart a failed build of
	# an complete archive directory.  The tradeoff is that when
	# we want to replace an archive, we have to first delete it
	# manually.

	if test -f $to/$archive
	then
		#echo "$to/$archive exists, not superceded"
		if test -f $pifileout
		then
			true
			#echo "$pifileout exists, not superceded"
		else
			# Install a copy of the product info file alongside the archive.
			echo "	cp $pifilein $pifileout"
			cp $pifilein $pifileout
		fi
		continue
	fi

	# Remove any old trash and create a fresh working directory.

	if test -d $WORKDIR
	then
		sleep 2
		echo "	rm -rf $WORKDIR/*"
		rm -rf $WORKDIR/*
	fi

	absmanifest=`pwd`/$manifest

	# Make a tar archive in $WORKDIR of all the files in the manifest.
	# The files listed in the manifests files are relative to the
	# directory specified in the --from arg.

	if test "$artype" = "tgz"
	then
		echo "	(cd $from && tar -cp -T $absmanifest -f - | gzip -9 >$WORKDIR/tar.out.gz)"
		(cd $from && tar -cp -T $absmanifest -f - | gzip -9 >$WORKDIR/tar.out.gz)
		# If what we want is a compressed tar archive, just copy to the destination.
		echo "	(cd $WORKDIR && cp tar.out.gz $to/$archive)"
		(cd $WORKDIR && cp tar.out.gz $to/$archive)
	else
		# If what we want is an lha archive, then we have to go through
		# more contortions, including working around a couple bugs in lha
		# where lha fails to preserve the case of directory names and also
		# fails to archive files if more than a single arg is given to it.
		echo "	(cd $from && tar -cp -T $absmanifest -f $WORKDIR/tar.out)"
		(cd $from && tar -cp -T $absmanifest -f $WORKDIR/tar.out)
		echo "	(cd $WORKDIR/ && tar -xpf tar.out && rm tar.out)"
		(cd $WORKDIR/ && tar -xpf tar.out && rm tar.out)
		echo "	(cd $WORKDIR && lha -mraxeq a $archive * && cp $archive $to/$archive)"
		here=`pwd`
		cd $WORKDIR
		for file in *
		do
			lha -mraxeq a $archive $file
		done
		cp $archive $to/$archive
		cd $here
	fi
	
	# Install a copy of the product info file alongside the archive.

	echo "	cp $pifilein $pifileout"
	cp $pifilein $pifileout
done
