[beast] BUILD: generate ChangeLog through mkrelease.sh
- From: Tim Janik <timj src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [beast] BUILD: generate ChangeLog through mkrelease.sh
- Date: Mon, 30 Aug 2010 00:49:56 +0000 (UTC)
commit 777f129cf5624cae095b780663f5cdc11accc44c
Author: Tim Janik <timj gtk org>
Date: Fri Aug 27 01:10:42 2010 +0200
BUILD: generate ChangeLog through mkrelease.sh
Makefile.am | 18 +---
mkrelease.sh | 272 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 276 insertions(+), 14 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index aa689c9..cb71ef4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -42,21 +42,11 @@ check: check-recursive
@echo $(ALL_CHECKED_MSG) | sed 's/./=/g'
# === ChangeLog ===
-LAST_COMMITID = ce584d04999a7fb9393e1cfedde2048ba73e8878
-ChangeLog: $(shell ls "$${GIT_DIR:-.git}/packed-refs" "$${GIT_DIR:-.git}/HEAD" "$${GIT_DIR:-.git}/`git symbolic-ref -q HEAD || echo HEAD`" 2>/dev/null )
- : # Generate ChangeLog with -prefixed records
- git log --pretty='format:%ad %an # %H (%cn)%n%n%s%n%n%b' \
- ${LAST_COMMITID}..HEAD > xgen-$(@F)
- : # Tab-indent ChangeLog, except for record start
- sed 's/^/ /;s/^ //;/^[ ]*<unknown>$$/d' -i xgen-$(@F)
- : # Kill trailing whitespaces, compress multiple trailing newlines
- $(PYTHON) -c "import sys, re; sys.stdout.write ( \
- re.compile (r'\n\n\n(?=^\w)', re.M).sub ('\n\n', \
- re.compile ('^[ ]+$$', re.M).sub ('', \
- sys.stdin.read())))" < xgen-$(@F) > xgen2-$(@F)
- cp xgen2-$(@F) $@ && rm -f xgen-$(@F) xgen2-$(@F)
+ChangeLog: $(shell $(srcdir)/mkrelease.sh commit-stamps)
+ $(srcdir)/mkrelease.sh ChangeLog \
+ -R ce584d04999a7fb9393e1cfedde2048ba73e8878..HEAD
noinst_DATA += ChangeLog
-EXTRA_DIST += ChangeLog
+EXTRA_DIST += ChangeLog mkrelease.sh
# fixup automake-1.9.6 distuninstallcheck:-rule reporting files created by update-mime-database(1)
filter_stale_uninstalled = | egrep -v '^.*/share/mime/(subclasses|globs|magic|XMLnamespaces|aliases)$$'
diff --git a/mkrelease.sh b/mkrelease.sh
new file mode 100755
index 0000000..1f49fde
--- /dev/null
+++ b/mkrelease.sh
@@ -0,0 +1,272 @@
+#!/bin/bash
+# mkrelease.sh: Copyright (C) 2010 Tim Janik
+#
+## This work is provided "as is"; see: http://rapicorn.org/LICENSE-AS-IS
+
+# === initial setup ===
+SCRIPT_NAME="$0"
+die() {
+ estatus=1
+ case "$1" in
+ [0-9]|[0-9][0-9]|[0-9][0-9][0-9]) estatus="$1" ; shift ;;
+ esac
+ echo "$SCRIPT_NAME: $*" >&2
+ exit $estatus
+}
+unset R_REVISION
+
+# === Usage ===
+usage() {
+ cat <<-EOF
+ Usage: `basename $SCRIPT_NAME` <command> [options]
+ Commands:
+ commit-stamps list stamp files affected by a commit
+ ChangeLog generate ChangeLog from git history
+ news list commits since last release tag
+ upload check and upload release tarball
+ Options:
+ -h, --help usage help
+ -E <revisionvar> variable to increment (e.g. configure.ac:MICRO)
+ -R <revision> revision range for "ChangeLog" generation
+ last release revision for "news" (auto)
+ -T <disttarball> name of distribution tarball (from Makefile)
+ -U <remoteurl> remote release URL (e.g. example.com:distdir)
+ -V <releaseversion> release version (from Makefile)
+EOF
+ [ -z "$1" ] || exit $1
+}
+
+# === cmdline parsing ===
+unset COMMAND
+VERSION=_parse
+TARBALL=_parse
+REMOTE_URL=
+REVISIONVAR=
+parse_options=1
+while test $# -ne 0 -a $parse_options = 1; do
+ case "$1" in
+ -h|--help) usage 0 ;;
+ -E) REVISIONVAR="$2" ; shift ;;
+ -R) R_REVISION="$2" ; shift ;;
+ -T) TARBALL="$2" ; shift ;;
+ -U) REMOTE_URL="$2" ; shift ;;
+ -V) VERSION="$2" ; shift ;;
+ --) parse_options=0 ;;
+ *) [ -z "$COMMAND" ] || usage 1 ; COMMAND="$1" ;;
+ esac
+ shift
+done
+
+# === commit-stamps ===
+[ "$COMMAND" = "commit-stamps" ] && {
+ # echo stamp files touched by commits
+ ls "${GIT_DIR:-.git}/`git symbolic-ref -q HEAD || echo HEAD`" \
+ "${GIT_DIR:-.git}/packed-refs" \
+ "${GIT_DIR:-.git}/HEAD" \
+ 2>/dev/null
+ exit
+}
+
+# === ChangeLog ===
+[ "$COMMAND" = "ChangeLog" ] && {
+ TEMPF="`mktemp -t yyTMPlog.$$XXXXXX`" && touch $TEMPF || \
+ die 9 "Failed to create temporary file"
+ trap "rm -f $TEMPF" 0 HUP INT QUIT TRAP USR1 PIPE TERM
+ # Generate ChangeLog with -prefixed records
+ git log --date=short --pretty='%ad %an # %h%n%n%s%n%n%b' ${R_REVISION:-HEAD} \
+ | {
+ # Tab-indent ChangeLog, except for record start
+ sed 's/^/ /; s/^ //; /^[ ]*<unknown>$/d'
+ } | {
+ # Kill trailing whitespaces
+ sed 's/[[:space:]]\+$//'
+ } | {
+ # Compress multiple newlines
+ sed '/^\s*$/{ N; /^\s*\n\s*$/D }'
+ } > $TEMPF
+ # replace atomically
+ mv $TEMPF ChangeLog
+ exit
+}
+
+# === news ===
+[ "$COMMAND" = "news" ] && {
+ # list numeric tags
+ TAGS=`git tag -l | grep '^[0-9.]*$'`
+ # collect release tags in linear history
+ if [ "${#R_REVISION[ ]}" = 0 ] ; then # R_REVISION is unset
+ XTAG=
+ for t in $TAGS ; do
+ # release tag?
+ if git cat-file tag $t | sed '1,/^$/d' | head -n1 | grep -qi '\breleased\?\b' ; then
+ # in linear history?
+ TCOMMIT=`git rev-list -n1 $t`
+ [ `git merge-base HEAD $t` = $TCOMMIT ] && {
+ # keep newest tag
+ [ -n "$XTAG" -a "`git merge-base ${XTAG:-$t} $t`" = $TCOMMIT ] || XTAG="$t"
+ }
+ fi
+ done
+ else
+ XTAG="$R_REVISION"
+ fi
+ [ -n "$XTAG" ] && XTAG="$XTAG^!" # turn into exclude pattern
+ # list news, excluding existing tags
+ echo "# git log --date=short --pretty='%s # %cd %an %h%d' --reverse HEAD $XTAG"
+ git log --date=short --pretty='%s # %cd %an %h%d' --reverse HEAD $XTAG | cat
+ exit
+}
+
+# === upload ===
+[ "$COMMAND" = "upload" ] && {
+ # functions
+ check_makefile() {
+ [ -r Makefile ] || die 7 "Failed to find and read Makefile"
+ }
+ parse_makefile_var() {
+ VARNAME="$1"
+ # find VARNAME, strip before '=', print and quit
+ sed -ne "/^[ \t]*$VARNAME[ \t]*=/ { s/^[^=]*=[ \t]*//; p; q }" < Makefile
+ }
+ subst_makefile_vars() {
+ sed -e "{ s/\$(VERSION)\|\${VERSION}/$VERSION/g ;
+ s/\$(PACKAGE)\|\${PACKAGE}/$PACKAGE/g ;
+ s/\$(distdir)\|${distdir}/$distdir/g ; }"
+ }
+ first_arg() { echo "$1" ; }
+ msg_() { printf "%-76s" "$@ " ; }
+ msg() { msg_ " $@" ; }
+ ok() { echo " OK" ; }
+ fail() {
+ echo "FAIL"
+ while [ -n "$1" ] ; do
+ printf "%s\n" "$1" ; shift
+ done
+ exit 1
+ }
+ msg2() {
+ M1=" $1 " ; shift
+ M2="$@"
+ L=`expr length "$M2"`
+ I=$((80 - $L))
+ printf "%-$I""s%s\\n" "$M1" "$M2"
+ }
+ # ensure VERSION, fallback to Makefile
+ [ "$VERSION" = "_parse" ] && check_makefile && VERSION="`parse_makefile_var VERSION`"
+ msg2 "Determine version..." "$VERSION"
+ # extract REVISION from last numeric part in VERSION
+ REVISION=`echo " $VERSION" | sed -n '/[0-9][ \t]*$/{ s/.*\b\([0-9]\+\)[ \t]*$/\1/ ; p ; q }'`
+ [ -n "$REVISION" ] || { msg "Extracting revision from $VERSION..." ; fail ; }
+ msg2 "Determine revision..." "$REVISION"
+ # ensure TARBALL, fallback to Makefile
+ [ "$TARBALL" = "_parse" ] && check_makefile && {
+ # expand tarball from PACKAGE, VERSION, distdir and DIST_ARCHIVES
+ PACKAGE="`parse_makefile_var PACKAGE`"
+ distdir="`parse_makefile_var distdir | subst_makefile_vars`"
+ DIST_ARCHIVES="`parse_makefile_var DIST_ARCHIVES | subst_makefile_vars`"
+ TARBALL="`first_arg $DIST_ARCHIVES`"
+ [ -z "$TARBALL" ] && die "Failed to determine release tarball"
+ }
+ msg2 "Determine tarball..." "$TARBALL"
+ # ensure remote host from remote URL
+ REMOTE_HOST=`printf "%s" "$REMOTE_URL" | sed -e 's/:.*//'`
+ msg2 "Determine remote host..." "$REMOTE_HOST"
+ [ -z "$REMOTE_URL" ] && die "remote release destination unkown, use -U"
+ [ -z "$REMOTE_HOST" ] && die "Failed to determine remote host"
+ # extract remote path, slash terminated
+ REMOTE_PATH=`printf "%s" "$REMOTE_URL" | sed -ne '/:/ { s/[^:]*:// ; p ; q }'`
+ case "$REMOTE_PATH" in *[^/]) REMOTE_PATH="$REMOTE_PATH/" ;; esac
+ msg2 "Determine remote path..." "$REMOTE_PATH"
+ # extract file from REVISIONVAR
+ REVISIONVAR_FILE=`printf "%s" "$REVISIONVAR" | sed -e 's/:.*//'`
+ REVISIONVAR_NAME=`printf "%s" "$REVISIONVAR" | sed -ne '/:/ { s/[^:]*:// ; p ; q }'`
+ [ -n "$REVISIONVAR" ] && {
+ msg2 "Determine file for revision increments..." "$REVISIONVAR_FILE"
+ [ -z "$REVISIONVAR_FILE" ] && die "Failed to extract file from: $REVISIONVAR"
+ msg2 "Determine variable for revision increments..." "$REVISIONVAR_NAME"
+ [ -z "$REVISIONVAR_NAME" ] && die "Failed to extract variable from: $REVISIONVAR"
+ }
+ # release checks
+ msg "Checking for a clean $VERSION working tree..."
+ test 0 = `git diff HEAD | wc -l` && ok \
+ || fail "note: use 'git diff HEAD' to view working tree changes"
+ msg "Checking untagged revision $VERSION..."
+ RNAME=`! git rev-parse --verify -q "$VERSION"` && ok \
+ || fail "note: a revision named '$VERSION' already exists: $RNAME" \
+ "> `git log -n1 --oneline $RNAME`"
+ msg "Checking for updated ChangeLog..."
+ TST=true
+ [ -e ChangeLog ] || TST=false
+ for stamp in `"$SCRIPT_NAME" commit-stamps` ; do
+ [ ChangeLog -nt "$stamp" ] || TST=false
+ done
+ $TST && ok || fail "note: ChangeLog outdated; see: $SCRIPT_NAME ChangeLog"
+ msg "Checking for NEWS to cover $VERSION..."
+ head -n2 NEWS | grep -q "$VERSION" && ok || \
+ fail "note: NEWS fails to describe version $VERSION"
+ msg "Checking release tarball $TARBALL..."
+ test -r "$TARBALL" && ok || fail "note: tarball unreadable"
+ msg "Checking tarball against ChangeLog age..."
+ test "$TARBALL" -nt ChangeLog && ok \
+ || fail "note: ChangeLog appears to be newer; make distcheck"
+ msg "Checking tarball against NEWS age..."
+ test "$TARBALL" -nt NEWS && ok \
+ || fail "note: NEWS appears to be newer; make distcheck"
+ [ -n "$REVISIONVAR" ] && {
+ msg "Checking revision variable to match version..."
+ N=`sed -ne "/^$REVISIONVAR_NAME\s*=\s*[0-9]/ { s/^[^=]*=\s*\([0-9]\+\).*/\1/ ; p ; q }" $REVISIONVAR_FILE`
+ [ -n "$N" -a "$N" = "$REVISION" ] && ok \
+ || fail "note: mismatching revisions for $VERSION: '$REVISION' != '$N'"
+ msg "Checking for git tracking of $REVISIONVAR_FILE..."
+ git rev-list --max-count=1 HEAD -- "$REVISIONVAR_FILE" | grep -q '.' && ok \
+ || fail "note: unexisting file in git HEAD: $REVISIONVAR_FILE"
+ }
+ msg "Checking for even revision in version $VERSION..."
+ test "$REVISION" = `echo "$REVISION / 2 * 2" | bc` && ok \
+ || fail "note: refusing to release development version with odd revision: $REVISION"
+ msg "Checking remote for unique release tarball..."
+ ssh "$REMOTE_HOST" test ! -e "$REMOTE_PATH$TARBALL" && ok \
+ || fail "note: file already exists: $REMOTE_HOST:$REMOTE_PATH$TARBALL"
+ # planned steps
+ msg2 "* Planned: upload tarball $TARBALL..."
+ msg2 "* Planned: tag HEAD as '$VERSION' release..."
+ [ -n "$REVISIONVAR" ] && \
+ msg2 "* Planned: commit revision increment of $REVISIONVAR_FILE:$REVISIONVAR_NAME"
+ read -ei n -p "--- Proceed as planned [y/n]? " ANS
+ case "$ANS" in
+ Y|YES|Yes|y|yes|1) msg "Confirmed planned procedures..." ; ok ;;
+ *) die 1 "User cancellation..." ;;
+ esac
+ # upload
+ msg_ "* Uploading release tarball $TARBALL..."
+ rsync -lpt --delay-updates "$TARBALL" "$REMOTE_HOST:$REMOTE_PATH" && ok \
+ || fail "note: rsync transfer failed"
+ RLS=$(ssh "$REMOTE_HOST" ls -l \`readlink -f "$REMOTE_PATH/$TARBALL"\`)
+ msg2 ">" "$RLS"
+ # tag release
+ msg_ "* Tagging HEAD as '$VERSION' release..."
+ git tag -m "Released $TARBALL" "$VERSION" && ok || fail
+ git tag -n1 -l "$VERSION" | sed 's/^/ > /'
+ # bump version
+ [ -n "$REVISIONVAR" ] && {
+ N=$((1 + $REVISION))
+ msg "Increment $REVISIONVAR_FILE:$REVISIONVAR_NAME to $N..."
+ TEMPF="`mktemp -t yyREVfile.$$XXXXXX`" && touch $TEMPF || \
+ die 9 "Failed to create temporary file"
+ trap "rm -f $TEMPF" 0 HUP INT QUIT TRAP USR1 PIPE TERM
+ sed "0,/^\($REVISIONVAR_NAME\s*=\s*\)[0-9]\+/s//\1$N/" < "$REVISIONVAR_FILE" > $TEMPF \
+ && ok || fail
+ mv $TEMPF "$REVISIONVAR_FILE"
+ git diff -U0 "$REVISIONVAR_FILE" | sed 's/^/ > /'
+ git commit -v -m "$REVISIONVAR_FILE: revision increment of $REVISIONVAR_NAME to $N" \
+ -- "$REVISIONVAR_FILE" | sed 's/^/ > /' || die "git commit failed"
+ msg_ "* Comitted revision increment of $REVISIONVAR_NAME to $N" ; ok
+ msg2 "Note, push HEAD with: # git push origin"
+ }
+ msg2 "Note, push tag with: # git push origin '$VERSION'"
+ msg2 "Done."
+ exit
+}
+
+# === missing command ===
+usage 1
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]