#!/bin/bash
#
# This script called in a CVS directory generates an archive in that
# same directory, which contains all locally added new files (except
# those rejected by the script) and a diff with all local changes.
# This archive can then be offered to one of the CVS maintainers for
# committing.
#
# Usage:
#         $ cd $FG_ROOT/Aircraft/foo
#         $ fg-submit      # generates foo.tar.bz2 and foo.diff
#
# The archive contains a copy of the diff, which is only left for
# convenience and doesn't have to be submitted.

SELF=$(basename $0)
AIRCRAFT=$(basename $PWD)

CVS=/usr/bin/cvs
ARCHIVE=$AIRCRAFT.tar.bz2
DIFF=$AIRCRAFT.diff


function ERROR  { echo -e "\e[31;1m$*\e[m";   }
function LOG    { echo -e "\e[35m$*\e[m";     }
function ADD    { echo -e "\e[32m\t+ $*\e[m"; }
function REJECT { echo -e "\e[31m\t- $*\e[m"; }

function diffstat {
	# output diff statistics, similar to the "diffstat" utility
	awk '
		function out() {
			if (bin) {
				print "\t\tbinary\t\t"file;
			} else {
				print "\t+"a"\t-"r"\t!"c"\t"file
			}
		}
		BEGIN      {
			print "\tadded___removed_changed___________________________________";
			a = r = c = at = rt = ct = n = bin = 0;
		}
		/^Index: / { if (file) { out() } a = r = c = scan = bin = 0; file = $2; n += 1 }
		/^@@/      { scan = 1 }
		/^Binary/  { if (!scan) { bin = 1 } }
		/^+/       { if (scan) { a += 1; at += 1 } }
		/^-/       { if (scan) { r += 1; rt += 1 } }
		/^!/       { if (scan) { c += 1; ct += 1 } }
		END        {
			if (file) { out() }
			print "\t-----------------------------------total------------------";
			print "\t+"at"\t-"rt"\t!"ct"\tin "n" files"
		}
	' < $1
}


# create temporary dir that's automatcally removed on exit
TMP=$(mktemp -d /tmp/$SELF.$AIRCRAFT.XXXXXX) || (echo "$0: can't create temporary dir"; exit 1)
trap "rm -rf $TMP" 0 1 2 3 13 15


# move older archive or diff file out of the way
[ -f $DIFF ] && mv -i $DIFF $DIFF~
[ -f $ARCHIVE ] && mv -i $ARCHIVE $ARCHIVE~


LOG "updating and checking for changed and new files ..."
$CVS -q up -dP >$TMP/up


if grep "^C " $TMP/up &>/dev/null; then
	ERROR "there are conflicts with the following files:"
	grep "^C " $TMP/up
	exit 1
fi


LOG "making diff ..."
if ! $CVS -q diff >$DIFF; then
	LOG "diff statistics:"
	diffstat $DIFF

	# add diff file itself
	echo $DIFF >> $TMP/include

	# add changed binary files
	awk '
		/^Index: / { scan = 1; file = $2 }
		/^@@/      { scan = 0 }
		/^Binary/  { if (scan) { print file } }
	' < $DIFF >>$TMP/include
else
	rm -f $DIFF
fi


# write list of all files to add
LOG "adding to archive ..."
if [ -f $TMP/include ]; then
	cat $TMP/include|while read i; do
		ADD "$i"
		echo $i >> $TMP/files
	done
fi
grep "^? " $TMP/up|while read i; do
	FILE=${i#? }
	find $FILE -type f >> $TMP/files
done


# classify and filter files
if [ -f $TMP/files ]; then
	for FILE in $(cat $TMP/files); do
		case "$FILE" in
		$ARCHIVE*|$DIFF*) # don't add files generated by the script
			;;
		*/.*|.*)          # silently drop hidden files
			;;
		*~|*.bak|*.orig|*..)
			REJECT "$FILE\t\t(backup file)"
			;;
		*CVS/*)
			REJECT "$FILE\t\t(CVS file)"
			;;
		*.blend|*.blend[0-9]|*.blend[0-9][0-9])
			REJECT "$FILE\t\t(blender file)"
			;;
		*.xcf|*.tga|*.bmp|*.BMP|*.png)
			REJECT "$FILE\t\t(graphics file)"
			;;
		*)
			ADD "$FILE"
			echo "$FILE" >> $TMP/include
			;;
		esac
	done
fi


if [ -f $TMP/include ]; then
	LOG "creating archive $ARCHIVE"
	tar -cjf $ARCHIVE --files-from $TMP/include
else
	LOG "no changes or new files detected"
fi
exit 0