#!/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, so the extra diff file # shouldn't be submitted. It's only left for (in?)convenience. SELF=${0/#*\/} AIRCRAFT=${PWD/#*\/} CVS=/usr/bin/cvs ARCHIVE=$AIRCRAFT.tar.bz2 DIFF=$AIRCRAFT.diff CDIFF=$DIFF.bz2 function ERROR { echo -e "\e[31;1m$*\e[m"; } function LOG { echo -e "\e[35m$*\e[m"; } function NEW { echo -e "\e[32m\t+ $*\e[m"; } function CHANGED { echo -e "\e[36m\t+ $*\e[m"; } function REJECT { echo -e "\e[31m\t- $*\e[m"; } function diffstat { # output diff statistics, similar to the "diffstat" utility awk ' function line(a, r, c, f) { print "\t\033[32m"a"\033[m\t\033[31m"r"\033[m\t\033[34m"c"\033[m\t"f } function dofile() { if (!file) { return } if (bin) { line("\033[m. . . .", "\033[mbinary", "\033[m. . . .", file) } else { line(a, r, c, file) at += a; rt += r; ct += c; } a = r = c = 0 } BEGIN { print "\tadded---removed-changed----------------------------------------" a = r = c = at = rt = ct = n = bin = 0 } /^Index: / { dofile(); scan = bin = 0; file = $2; n += 1; next } /^@@/ { scan = 1; next } /^Binary/ { if (!scan) { bin = 1 } next } /^+/ { if (scan) { a += 1 } next } /^-/ { if (scan) { r += 1 } next } /^!/ { if (scan) { c += 1 } next } END { dofile() print "\t----------------------------------------total------------------" line(at, rt, ct, "\033[min "n" files") } ' <$1 } # create temporary dir that's automatcally removed on exit TMP=$(mktemp -d -t $SELF.$AIRCRAFT.XXX) || (echo "$0: can't create temporary dir"; exit 1) trap "rm -rf $TMP" 0 1 2 3 13 15 # move older archive or diff files out of the way [ -f $DIFF ] && mv $DIFF $(mktemp $DIFF.X) [ -f $CDIFF ] && mv $CDIFF $(mktemp $CDIFF.X) [ -f $ARCHIVE ] && mv $ARCHIVE $(mktemp $ARCHIVE.X) LOG "updating and checking for 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 -up >$DIFF; then LOG "diff statistics:" diffstat $DIFF echo # add diff file itself echo $DIFF >>$TMP/files # add changed binary files awk ' /^Index: / { scan = 1; file = $2; next } /^@@/ { scan = 0; next } /^Binary/ { if (scan) { print file } } ' <$DIFF >>$TMP/files else rm -f $DIFF fi LOG "checking for files to submit ..." if [ -f $TMP/files ]; then cat $TMP/files|while read i; do CHANGED "$i" done fi grep "^? " $TMP/up|while read i; do find ${i#? } -type f >>$TMP/check done # classify and filter files if [ -f $TMP/check ]; then for i in $(cat $TMP/check); do case "$i" in $ARCHIVE*|$DIFF*) # don't add files generated by the script ;; */.*|.*) # silently drop hidden files ;; *~|*.|*.bak|*.orig) REJECT "$i\t\t(backup file)" ;; CVS/*|*/CVS/*) REJECT "$i\t\t(CVS file)" ;; *.blend|*.blend[0-9]|*.blend[0-9][0-9]) REJECT "$i\t\t(blender file)" ;; *.xcf|*.tga|*.bmp|*.BMP|*.png) REJECT "$i\t\t(graphics file)" ;; *) NEW "$i" echo "$i" >>$TMP/files ;; esac done fi if ! [ -f $TMP/files ]; then LOG "no changed or new files found" exit 0 fi echo numfiles=$(awk '//{n+=1}END{print n}' <$TMP/files) if [ -f $DIFF -a $numfiles == 1 ]; then LOG "only changed non-binary files found" LOG "creating compressed diff \e[1;37;40m$CDIFF\e[m\e[35m ..." bzip2 -k $DIFF else LOG "changed and/or new files found" LOG "creating archive \e[1;37;40m$ARCHIVE\e[m\e[35m ..." tar -cjf $ARCHIVE --files-from $TMP/files fi exit 0