#! /bin/sh

#
# babarchive_prep_topshasum
# Copyright (C) 2001-2016 by John Heidemann  <johnh@isi.edu>
#
# (was: prep_cdrom_all)
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License along
#    with this program; if not, write to the Free Software Foundation, Inc.,
#    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#

usage () {
    cat 1>&2 <<END
usage: $0 [-a alg] [-o OUTFILE] [-s] [DIR...]

options:
    -a alg      algorithm (defaults to 256 for sha256)
    -j N        use N parallel instances (if -s is not specified)
    -s          use .shasum files in each dir instead of recomputing all sums
    -o OUTFILE  send out OUTFILE (or - for stdout)

make an .shasum.jdb directory in the root of DIR
END
    exit 1
}

die () {
	echo "$@" 1>&2
	exit 1
}

set -o pipefail

test "x$1" = 'x-?' && usage

alg=256
algprog=""
algargs=""
algprefix=sha
algsuffix=fsdb
out=''
debug=false
usedotsums=false

while getopts "a:do:j:s" ch; do
    case $ch in
    ( a ) alg=$OPTARG;;
    ( d ) debug=true;;
    ( o ) out=$OPTARG;;
    ( j ) parallel_sums=$OPTARG;;
    ( s ) usedotsums=true; ;;    
    ( * ) usage;;
    esac
done
shift $(($OPTIND - 1))

case x$alg in
	xmd5)
		alg=md5; algprog=md5sum; algargs=""; algprefix=md5; algsuffix=jdb;;
	xsha1|x1)
		alg=1; algprog=sha1sum; algargs=""; algprefix=sha1; algsuffix=jdb;;
	xsha256|x256|xauto)
		alg=256; algprog=shasum; algargs="--binary -a $alg";  algprefix=sha; algsuffix=fsdb;;
	*)
		die "unknown algorithm $alg"
		;;
esac
test x"$out" = "x" && out=.${algprefix}sum.$algsuffix

tmpfile=/tmp/prep-cdrom-all.$$
trap 'rm -f $tmpfile*; exit 1' 1 2 15
trap 'rm -f $tmpfile*; exit 1' 0

remove_optional_stuff_from_file() {
	# shasum wants to mark binary files.  ick.
	perl -ne 'my($sum,$rest)=(/^([0-9a-f]+)\s+(\S.*)/); 
		$rest =~ s/^\*//; 
		$rest =~ s@^\.\/@@; 
		print "$sum  $rest\n";'
}

PARALLEL_SUMS=4
for DIR in $*; do
	(
		cd $DIR
        : >$tmpfile || die "ERROR: cannot write to $tmpfile"
        if $usedotsums; then
            find . -type d -print |
                while read dir; do
                    dotsum="$dir/.${algprefix}sum"
                    [ -e "$dotsum" ] || die "ERROR: '$dotsum' does not exist"
		    < "$dotsum" remove_optional_stuff_from_file | \
			    sed "s@  @  $dir/@" >>$tmpfile || die "ERROR: cannot read '$dotsum'"
                done
        else
            find .  -type f \
		            ! \( -name .md5sum -o -name .sha1sum -o -name .sha1sum.jdb -o -name .shasum -o -name .shasum.fsdb \) \
		            -print0 |
                    xargs -0 -n1 -P${parallel_sums:-$PARALLEL_SUMS} ${algprefix}sum ${algargs} |\
		    	remove_optional_stuff_from_file >$tmpfile || die "FAILED to process $DIR"
        fi

        {
            echo "#fsdb -F t checksum file path"
            <$tmpfile perl -ne 'my($sum,$path)=(/^([0-9a-f]+)\s+(\S.*)/); my($file)=($path =~ m@/([^/]+)$@); print "$sum\t$file\t$path\n";' | LC_COLLATE=C sort -k 3,3
        } >$tmpfile.$algsuffix || die "FAILED to generate .jdb file"

		if [ "x$out" = x- ]; then
			cat $tmpfile.$algsuffix
		else
			mv $tmpfile.$algsuffix $out || die "FAILED to install $out"
		fi
        rm -f $tmpfile*
	)
done

exit 0
