#!/bin/bash version=0.20 program=${0##*/} progdir=${0%/*} if [ "$progdir" = "$program" ]; then progdir="."; fi # ---------------------------------------------------------------------- function usage() { cat < COPYRIGHT Copyright 2010 Henrik Levkowetz. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. There is NO WARRANTY; not even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. EOF } # ---------------------------------------------------------------------- function die() { echo -e "\n$program: error: $*" > /dev/stderr exit 1 } function note() { if [ -n "$VERBOSE" ]; then echo -e "$*"; fi } # ---------------------------------------------------------------------- function version() { echo -e "$program $version" } # ---------------------------------------------------------------------- trap 'echo "$program($LINENO): Command failed with error code $? ([$$] $0 $*)"; exit 1' ERR # ---------------------------------------------------------------------- # Option parsing # Options shortopts=cnhvV longopts=commit,no-commit,help,verbose,version # Default values ARG_COMMIT=1 if [ "$(uname)" = "Linux" ]; then args=$(getopt -o "$shortopts" --long "$longopts" -n '$program' -- $SV "$@") if [ $? != 0 ] ; then die "Terminating..." >&2 ; exit 1 ; fi eval set -- "$args" sed="sed -r" else # Darwin, BSDs args=$(getopt -o$shortopts $SV $*) if [ $? != 0 ] ; then die "Terminating..." >&2 ; exit 1 ; fi set -- $args sed="sed -E" fi while true ; do case "$1" in -c| --commit) ARG_COMMIT=1;; # Run commit in addition to merge -n| --no-commit) ARG_COMMIT=0;; # Don't commit after merge -h| --help) usage; exit;; # Show this help, then exit -v| --verbose) VERBOSE=1;; # Be more talkative -V| --version) version; exit;; # Show program version, then exit --) shift; break;; *) die "Internal error, inconsistent option specification: '$1'";; esac shift done # ---------------------------------------------------------------------- # The program itself # Argument validation [[ $1 =~ @ ]] && set ${1/@/ } [ $# -ge 2 ] || die "Expected branch and repository revision on the command line" [ ${PWD##*/} = trunk ] || die "Expected this script to be run in trunk" # Global settings cwd=${PWD##*/} branch=$1 rev=$2 fix=$3 # remove leading 'r' from rev, if present rev=${rev#r} repo=$(echo -n "$(svn info | grep "^Repository Root: " | sed 's/Repository Root: //')") note "Identify the branch:" if svn info $branch > /dev/null 2>&1; then branch="${branch#^/}" elif svn info ${repo}/personal/$branch > /dev/null 2>&1; then branch="personal/$branch" elif svn info ${repo}/branch/$branch > /dev/null 2>&1; then branch="branch/$branch" elif svn info ${repo}/$branch > /dev/null 2>&1; then true else die "Could not find a branch matching '$branch'" fi note "Svn update, to make sure we don't have a mixed revision working copy" svn update -q mergelog=$(mktemp) svn propget svn:mergeinfo . > $mergelog if grep "@$rev $branch" $mergelog; then die "Changeset $branch@$rev is already in the merge log. Skipping it."; exit 0; fi note "Will attempt merge from $branch@$rev" note "Extract who and what:" info=$(svn log ${repo}/ -r $rev --incremental) set $(echo "$info" | tail -n +2 | head -n 1 | tr "|" "\t") who=$2; echo -e "\n$who" comment=$(echo "$info" | tail -n +3); echo -e "$comment\n" comment=$(echo "$comment" | sed -r -e 's/(commit )?ready (for|to) merge\.?//i' -e '/^$/d') files=$(svn diff ${repo}/ -c $rev --summarize | awk '{$1=""; print;}' | while read file; do echo "${file/$repo\/$branch\//}"; done) echo -e "Files: \n$files\n" read -p "Continue with diff? [Y/n] " [ "$REPLY" = "Y" -o "$REPLY" = "y" -o "$REPLY" = "" ] || exit note "Diff:" svn diff -c $rev $repo/$branch | less echo "" read -p "Additional descriptive text (hit return for none): " if [ "$REPLY" != "" ]; then comment="$REPLY $comment" fi echo "" read -p "Continue with the merge? [Y/n] " [ "$REPLY" = "Y" -o "$REPLY" = "y" -o "$REPLY" = "" ] || exit note "Do the merge:" if [[ $rev =~ : ]]; then svn merge -r $rev ${repo}/$branch . || die "Merge of $branch @$rev failed. The merge command was: svn merge -r $rev ${repo}/$branch ." else svn merge -c $rev ${repo}/$branch . || die "Merge of $branch @$rev failed. The merge command was: svn merge -c $rev ${repo}/$branch ." fi note "Writing commit script" echo -e "#!/bin/bash\n\nsvn commit -m \"Merged in [$rev] from $who:\n ${comment//\"/\'} ${fix//\"/\'}\"" > ../cicmd/commit-${rev}-merge.sh chmod +x ../cicmd/commit-${rev}-merge.sh M=$(svn st | cut -c 1-7 | grep -oh 'M' | head -n 1) C=$(svn st | cut -c 1-7 | grep -oh 'C' | head -n 1) G=$(svn st | cut -c 1-7 | grep -oh 'G' | head -n 1) ##cd ../ ##rsync -a $cwd/ merged@$rev/ ##cp cicmd/commit-${rev}-merge.sh merged@$rev/commit ##cd - echo -e "\nRunning tests" time { ietf/manage.py test --settings=settings_sqlitetest \ || die "Tests failed.\nThe commit script is ../cicmd/commit-${rev}-merge.sh"; } 3>&1 1>&2 2>&3 | bin/count echo "" note "Sending email to changeset author: <$who>" mail -s "Merged datatracker branch personal/$branch@$rev to trunk" $who -c henrik@levkowetz.com <<-EOF Hi, This is an automatic merge info message. Your code in personal/$branch@$rev has been merged to trunk, and will be part of the next release if nothing goes wrong during final testing. Regards, Henrik (via the mergesprintbranch script) EOF echo "" read -p "Continue with the commit? [Y/n] " [ "$REPLY" = "Y" -o "$REPLY" = "y" -o "$REPLY" = "" ] || ARG_COMMIT=0 if [ "$ARG_COMMIT" != 0 ]; then echo "Svn update:" svn update -q echo "Committing the merge:" echo "" svn commit -m "Merged in [$rev] from $who: ${comment//\"/\'} ${fix//\"/\'}" else echo "This merge has not been committed yet." echo "To commit it, run this commit command: ../cicmd/commit-$rev-merge.sh" fi echo -e "\n------------------------------------------------------------------------\n\n"