#!/bin/sh

set -e

action=$(basename $0 .sh)

projects=${1:-$(find -mindepth 1 -maxdepth 1 -type d -printf '%f\n')}
for project in $projects; do
	if [ -x $project/$action.sh ]; then
		echo " ** Custom updating project $project... **"
		(cd $project && ./$action.sh)
	else
		targets=${2:-$(find $project -mindepth 1 -maxdepth 1 -type d -printf '%f\n')}
		for target in $targets; do
			versys=""
			versysfile=""
			repository=""
			branch=""
			tar_excludes=""
			if [ -d "$project/$target/CVS" ]; then
				versys="CVS"
				versysfile="cvs"
				repository="$(cat $project/$target/CVS/Repository)"
				# Get branch if available
				if [ -f "$project/$target/CVS/Tag" ]; then
#					branch="$(egrep '^N' $project/$target/CVS/Tag | sed 's/^N//')"
					branch="$(egrep '^T' $project/$target/CVS/Tag | sed 's/^T//')"
				fi
				tar_excludes="$tar_excludes --exclude CVSROOT --exclude .cvsignore"
			fi
			if [ -d "$project/$target/.svn" ]; then
				versys="SVN"
				versysfile="svn"
				repository=""
				branch=""
				tar_excludes="$tar_excludes --exclude .svn"
			fi
			if [ -d "$project/$target/{arch}" ]; then
				versys="ARCH"
				versysfile="arch"
				repository="$(cat $project/$target/{arch}/++default-version)"
				branch=""
				tar_excludes="$tar_excludes --exclude .arch-ids --exclude {arch}"
			fi
			if [ -d "$project/$target/.hg" ]; then
				versys="Mercurial"
				versysfile="hg"
				repository="$(cat $project/$target/.hg/hgrc | perl -n -e '/^default\s+=\s+(\S+)/ && print "$1\n"')"
				branch=""
				tar_excludes="$tar_excludes --exclude .hg --exclude .hgignore --exclude .hgtags"
			fi
			if [ -d "$project/$target/.git" ]; then
				versys="GIT"
				versysfile="git"
				repository="$(cat $project/$target/.git/description | perl -n -e '/^Unnamed/ or print "$_\n"')"
				branch=""
			fi
			if [ -d "$project/$target/.bzr" ]; then
				versys="Bazaar"
				versysfile="bzr"
				repository="$(cd $project/$target && bzr nick)"
				branch=""
			fi
			if [ -d "$project/$target/_darcs" ]; then
				versys="Darcs"
				versysfile="darcs"
				repository=""
				branch=""
			fi
			if [ -z "$versys" ] || [ -z "$versysfile" ]; then
				echo "ERROR: Unknown version control system used for \"$project/$target\"."
				exit 1
			fi
			case $action in
			    update)
				echo " ** Updating $versys project \"$project\" target \"$target\"${repository:+ (repository \"$repository\"${branch:+ branch \"$branch\"})}"
				case $versys in
				    CVS)
					( cd $project/$target && cvs -z3 update -dP 2>&1 || exit 1 ) \
						| egrep -v '^cvs(pserver)? (server|update): Updating' || [ $? -lt 2 ] # catch grep failures
					;;
				    SVN)
					( cd $project/$target && svn update )
					;;
				    ARCH)
					( cd $project/$target && tla update )
					;;
				    Mercurial)
					( cd $project/$target && hg pull -u )
					;;
				    GIT)
					( cd $project/$target && git pull )
					;;
				    Bazaar)
					( cd $project/$target && bzr pull )
					;;
				    Darcs)
					( cd $project/$target && darcs pull -a )
					;;
				    *)
					echo "ERROR: Action \"$action\" not supported for \"$project/$target\"."
					exit 1
					;;
				esac
				;;
			    archive)
				echo " ** Creating snapshot of $versys project \"$project\" target \"$target\"${repository:+ (repository \"$repository\"${branch:+ branch \"$branch\"})}"
				case $versys in
				    CVS|SVN|ARCH|Mercurial)
					( cd $project && tar chf - --exclude CVS $tar_excludes $target ) \
						| gzip -f9 > $project/$target-$versysfile$(date '+%Y%m%d').tar.gz
					;;
				    GIT)
					# FIXME: use tar_exclude to suppress other dirt than git itself
					( cd $project/$target && git archive --format=tar --prefix="$target/" HEAD^{tree} ) \
						| gzip -f9 > $project/$target-$versysfile$(date '+%Y%m%d').tar.gz
					;;
				    Bazaar)
					# FIXME: use tar_exclude to suppress other dirt than bzr itself
					( cd $project/$target && bzr export ../$target-$versysfile$(date '+%Y%m%d').tar.gz )
					;;
				    Darcs)
					# FIXME: use tar_exclude to suppress other dirt than bzr itself
					( cd $project/$target && darcs dist && mv $target.tar.gz ../$target-$versysfile$(date '+%Y%m%d').tar.gz )
					;;
				    *)
					echo "ERROR: Action \"$action\" not supported for \"$project/$target\"."
					exit 1
					;;
				esac
				;;
			    mkchanges)
				echo " ** Building changelog of $versys project \"$project\" target \"$target\"${repository:+ (repository \"$repository\"${branch:+ branch \"$branch\"})}"
				case $versys in
				    CVS)
					( cd $project/$target && cvs2cl --gmt -S --no-wrap -F ${branch:-TRUNK} -f ../$target.ChangeLog 2>&1 || exit 1 ) \
						| egrep -v '^cvs(pserver)? (server|log): Logging' || [ $? -lt 2 ] # catch grep failures
					;;
				    SVN)
					( cd $project/$target && test -f ../$target.ChangeLog && mv -f ../$target.ChangeLog ../$target.ChangeLog.bak )
					( cd $project/$target && svn log -v | localsvnlog2cl > ../$target.ChangeLog )
					;;
				    ARCH)
					( cd $project/$target && test -f ../$target.ChangeLog && mv -f ../$target.ChangeLog ../$target.ChangeLog.bak )
					( cd $project/$target && tla changelog > ../$target.ChangeLog )
					;;
				    Mercurial)
					( cd $project/$target && test -f ../$target.ChangeLog && mv -f ../$target.ChangeLog ../$target.ChangeLog.bak )
					( cd $project/$target && hg log -v > ../$target.ChangeLog )
					;;
				    GIT)
					( cd $project/$target && test -f ../$target.ChangeLog && mv -f ../$target.ChangeLog ../$target.ChangeLog.bak )
					( cd $project/$target && git log > ../$target.ChangeLog )
					;;
				    Bazaar)
					( cd $project/$target && test -f ../$target.ChangeLog && mv -f ../$target.ChangeLog ../$target.ChangeLog.bak )
					( cd $project/$target && bzr log --short > ../$target.ChangeLog )
					;;
				    Darcs)
					( cd $project/$target && test -f ../$target.ChangeLog && mv -f ../$target.ChangeLog ../$target.ChangeLog.bak )
					( cd $project/$target && darcs changes > ../$target.ChangeLog )
					;;
				    *)
					echo "ERROR: Action \"$action\" not supported for \"$project/$target\"."
					exit 1
					;;
				esac
				;;
			    *)
				echo "ERROR: Unknown action \"$action\" for \"$project/$target\"."
				exit 1
				;;
			esac
		done
	fi
done