260 lines
7.6 KiB
Bash
Executable file
260 lines
7.6 KiB
Bash
Executable file
#!/bin/bash
|
||
|
||
version=0.20
|
||
program=${0##*/}
|
||
progdir=${0%/*}
|
||
if [ "$progdir" = "$program" ]; then progdir="."; fi
|
||
|
||
# ----------------------------------------------------------------------
|
||
function usage() {
|
||
cat <<EOF
|
||
NAME
|
||
$program - merge and commit a sprint branch
|
||
|
||
SYNOPSIS
|
||
$program [OPTIONS] BRANCH SVNREV
|
||
|
||
DESCRIPTION
|
||
Merge and commit a sprint branch
|
||
|
||
EOF
|
||
echo -e "OPTIONS"
|
||
if [ "$(uname)" = "Linux" ]; then
|
||
egrep "^[ ]+[-][A-Za-z| -]+\*?\)[ ]+[A-Za-z].+#" $0 | tr -s "\t|" "\t," | sed -r -e 's/\)[ \t]+([A-Z]+)=\$2[^#]*#/=\1\t/' -e 's/\)[^#]*#/\t/'
|
||
else
|
||
egrep "^[ ]+[-][A-Za-z| -]+\*?\)[ ]+[A-Za-z].+#" $0 | sed 's/\|.*\$2[^#]*#/ /'| sed -E 's/\|.*\)[^#]*#/ /'
|
||
fi
|
||
cat <<EOF
|
||
|
||
FILES
|
||
|
||
AUTHOR
|
||
Written by Henrik Levkowetz, <henrik@tools.ietf.org>
|
||
|
||
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"
|
||
|
||
|