--- /dev/null
+#!/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
+