#!/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: //')") [ -z "$by" ] && by=${RELEASER_REAL_NAME} [ -z "$by" ] && by=$(getent passwd $(whoami) | cut -d ':' -f 5 | tr -d ',') [ -z "$by" ] && die "Can't determine the real name of the user running this script" python -c 'import django' || die "Can't find django - can't run tests" 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" # "Check there's no uncommitted changes ..." echo "" $do svn st | grep "^[AMGRD] " && { echo "" read -p "There are uncommitted changes. Really do merge? [y/N] " [ "$REPLY" = "Y" -o "$REPLY" = "y" ] || exit } 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 "$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:" note "svn diff -c $rev $repo/$branch" 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 - # Potentially run flake8 at this point # read -p "Run flake8? [y/N] " # if [ "$REPLY" = "Y" -o "$REPLY" = "y"]; then # mod=$(svn st | cut -c 9- | grep '\.py$') # flake8 $mod | less # fi read -p "Continue with tests? [Y/n] " [ "$REPLY" = "Y" -o "$REPLY" = "y" -o "$REPLY" = "" ] || exit 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>" SEND_ARGS="" [ "${RELEASER_EMAIL}" ] && SEND_ARGS="-r ${RELEASER_EMAIL}" mail "${SEND_ARGS}" -s "Merged datatracker branch personal/$branch@$rev to trunk" $who -c rjsparks@nostrum.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, $by (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"