#!/bin/sh
#
# Author: Tobi Vollebregt
#
# This script is to be used to auto-merge trunk revisions with the "BUGFIX"
# keyword to the current working directory.
#
# Run it from inside a svn checkout of the release branch, optionally a
# subdirectory of it (it will merge only in that subdirectory in that case).
#
# Pass two numeric revision arguments to the script. The script
# will loop through all revisions in this range & get the log message from that
# commit in trunk. If the log message contains the "BUGFIX" keyword it merges
# that revision to the working copy.
#
# As a special case, revision1 may be "AUTO" in which case the script
# examines the log messages of the branch in reverse order (from latest to
# oldest). If a log message contains a line "AUTO_MERGE r1 r2" it sets
# sets the revision1 argument to r2+1.
#
# As a special case, revision2 may be "HEAD" in which case the script replaces
# it with the revision the current checkout is at. (from the output of svn info)
#
# Extra arguments are interpreted as additional revisions numbers to merge.
# (ie. where the BUGFIX keyword was forgottten).
#
# After running the script you should review the diff & commit the merge.
# The script will give you the command to run for committing (includes a
# generated log message)
#


# Set this to 1 for debugging output
verbose=0

args="$@"


#
# Some sanity checks
#

quit=0

# Enough arguments?
if [[ $# < 2 ]]; then
        echo "Usage: $0 revision1 revision2"
        quit=1
fi

# Are we inside a svn checkout directory?
[ "x$(svn info)" != "x" ] || quit=1

if [ "$quit" != "0" ]; then
        exit "$quit"
fi


#
# Some generic code to set up $url, $branch and $path
#

url=$(svn info | grep "Repository Root" | sed 's,Repository Root: ,,g')/
[ $verbose != 0 ] &&  echo "Repo   : $url"

path=$(svn info | grep "URL" | sed "s,URL: ,,g;s,$url,,g")/

if [ "$(echo "$path" | awk -F / '{print $1}')" == "branches" ]; then
	branch=$(echo $path | awk -F / '{ print $1"/"$2 }')/
else
	branch="trunk/"
fi
[ $verbose != 0 ] && echo "Branch : $branch"

path=$(echo "$path" | sed "s,$branch,,g")
[ $verbose != 0 ] && echo "Path   : $path"


#
# Retrieve & parse the log & merge BUGFIX revisions
#

r1=$1
r2=$2
shift 2
logurl="$url""trunk/$path"
merge=0
commitmsg="__merge_commit__.txt"

[ $verbose != 0 ] && echo "URL    : $logurl"

# Truncate $commitmsg file before we start appending to it.
rm -f "$commitmsg"

# Resolve AUTO to the first unprocessed revision (by looking at the log).
if [ "$r1" == "AUTO" ]; then
	r1=$(svn info | grep "Revision" | sed 's,Revision: ,,g')
	logurl2="$url$branch"
	for (( r=$r1 ; ; r=$r-1 )); do
		echo "* Checking revision $r for AUTO_MERGE." 1>&2
		automerge=$(svn log -r "$r" "$logurl2" | grep AUTO_MERGE)
		if [ "x$automerge" != "x" ]; then
			r1=$(echo "$automerge" | awk '{print $3}')
			r1=$(($r1+1))
			[ $verbose != 0 ] && echo "AUTO   : $r1"
			break
		fi
	done
fi

# Replace HEAD by revision number so we can do arithmetic with it
if [ "$r2" == "HEAD" ]; then
	r2=$(svn info | grep "Revision" | sed 's,Revision: ,,g')
	[ $verbose != 0 ] && echo "HEAD   : $r2"
fi

# Loop through the revision range
for (( r=$r1 ; r <= $r2 ; r=$r+1 )); do

	echo "* Checking revision $r for BUGFIX." 1>&2

	# Check BUGFIX keyword in log
	if [ "x$(svn log -r "$r" "$logurl" | grep BUGFIX)" != "x" ] || [ "x$(echo $@ | grep $r)" != "x" ] ; then
		[ $verbose != 0 ] && echo "  Revision $r is a BUGFIX revision, trying to merge ..."
		# Perform merge
		svn merge -r "$(($r-1)):$r" "$logurl"
		merge=$(($merge+1))
		# Put entry in commit message
		echo "* Automated merge of bugfix revision $r." >> "$commitmsg"
	fi
done

# This is parsed by this script if revision1 is set to "AUTO".
echo "AUTO_MERGE $r1 $r2" >> "$commitmsg"
echo "(This commit has been generated by the command '$0 $args')" >> "$commitmsg"


#
# Summary & further instructions
#

echo

if [ "$merge" == 0 ]; then
	echo "No BUGFIX revisions found."
elif [ "$merge" == 1 ]; then
	echo "Performed 1 merge."
else
	echo "Performed $merge merges."
fi

if [ "$merge" != 0 ]; then
	echo "Check the diff and commit the changes using the command:"
	echo "svn commit -F $commitmsg"
	echo
	cat "$commitmsg"
fi

echo
