#!/bin/bash # # usage: cut-release [-n] version-designation [make-args...] # function isthatright { if $dryrun; then echo -n "[DRY RUN] " fi if [ -z "$1" ]; then echo -n "Does that look right? [y/n] " else echo -n "$1? [y/n] " fi while read yn; do if [ "$yn" = y -o "$yn" = Y -o "$yn" = yes -o "$yn" = YES -o "$yn" = Yes ]; then break elif [ "$yn" = n -o "$yn" = N -o "$yn" = no -o "$yn" = NO -o "$yn" = No ]; then echo "Aborting as per user request." >&2 exit 1 else echo -n "[y/n] " fi done } if [ "$1" = -n ]; then dryrun=true shift echo echo '************************* DRY RUN *************************' else dryrun=false fi if [ $# -lt 1 ]; then echo "Usage: $(basename "$0") [-n] version-designation [make-args...]" >&2 echo "-n does a dry run (i.e., do sanity checks and build but don't touch the repository)" exit 1 fi if ! [ -e src/expr/node.h -a -e .git ]; then echo "$(basename "$0"): ERROR: You should run this from the top-level of a CVC4 git working directory" >&2 exit 1 fi version="$1" shift if echo "$version" | grep '[^a-zA-Z0-9_.+(){}^%#-]' &>/dev/null; then echo "$(basename "$0"): ERROR: Version designation \`$version' contains illegal characters" >&2 exit 1 fi eval "declare -a vs=($(echo "$version" | sed 's,^\([0-9]*\)\.\([0-9]*\)\(\.\([0-9]*\)\)\?\(.*\),[0]=\1 [1]=\2 [2]=\4 [3]=\5,'))" major=${vs[0]} minor=${vs[1]}; if [ -z "$minor" ]; then minor=0; fi release=${vs[2]}; if [ -z "$release" ]; then release=0; fi extra=${vs[3]} echo echo "Major : $major" echo "Minor : $minor" echo "Release: $release" echo "Extra : $extra" echo version="$major.$minor" if [ "$release" != 0 ]; then version="$version.$release" fi version="$version$extra" echo "Version: $version" echo isthatright echo "Checking whether release \`$version' already exists..." if [ -n "`git tag -l "$version"`" ]; then echo "$(basename "$0"): ERROR: Git repo already contains a release \`$version'" >&2 $dryrun || exit 1 fi echo "Checking working directory for local modifications..." if $dryrun; then if [ -n "$(git status -s configure.ac)" ]; then echo "$(basename "$0"): ERROR: In dry-run mode, cannot operate properly with local modifications to \"configure.ac\", sorry" >&2 exit 1 fi elif [ -n "$(git status -s | grep -v '^ *M *\(NEWS\|README\|AUTHORS\|RELEASE-NOTES\|INSTALL\|THANKS\|library_versions\|contrib/cut-release\)$')" ]; then echo "$(basename "$0"): ERROR: \"git status\" indicates there are local modifications; please commit first" >&2 exit 1 fi echo "Checking repo for unmerged updates..." git fetch &>/dev/null if git status -sb | grep -q '^## .* \[.*behind '; then echo "$(basename "$0"): ERROR: This working directory isn't up to date" 2>&1 $dryrun || exit 1 fi echo "Checking sources for broken public headers..." suspect_files="\ $(grep -r --exclude-dir=.git '^[ \t]*#[ \t]*include[ \t]*"[^/]*"' src | grep -v '"cvc4parser_public\.h"' | grep -v '"cvc4_public\.h"' | grep -v '"cvc4_private\.h"' | grep -v '"cvc4autoconfig\.h"' | grep -v '"cvc4parser_private\.h"' | cut -f1 -d: | sort -u | xargs grep -l '^[ \t]*#[ \t]*include[ \t]*"cvc4.*public\.h"' | xargs echo)" if [ -n "$suspect_files" ]; then echo "$(basename "$0"): ERROR: The following publicly-installed headers appear" 2>&1 echo "$(basename "$0"): ERROR: to have relative #includes and may be broken" 2>&1 echo "$(basename "$0"): ERROR: after install: $suspect_files" 2>&1 $dryrun || exit 1 fi for updatefile in NEWS README AUTHORS RELEASE-NOTES INSTALL THANKS; do echo "Checking $updatefile file for recent updates..." if [ -n "$(git status -s $updatefile)" ]; then echo "+ It's locally modified." else git log -n 1 --date=local --pretty=format:'+ Last changed on %ad (%ar)' $updatefile echo case $updatefile in NEWS) echo "You should make sure to put some notes in the NEWS file for" echo "release $version, indicating the most important changes since the" echo "last release." ;; AUTHORS) echo "You should make sure there are no new authors to list for $version." ;; *) echo "You should ensure that $updatefile is appropriately updated" echo "for $version before continuing. (Maybe it even lists the previous" echo "version number!)" ;; esac echo isthatright "Continue without updating $updatefile" fi done echo "Adjusting version info lines in configure.ac..." if ! grep '^m4_define(_CVC4_MAJOR, *[0-9][0-9]* *)' configure.ac &>/dev/null || ! grep '^m4_define(_CVC4_MINOR, *[0-9][0-9]* *)' configure.ac &>/dev/null || ! grep '^m4_define(_CVC4_RELEASE, *[0-9][0-9]* *)' configure.ac &>/dev/null || ! grep '^m4_define(_CVC4_EXTRAVERSION, *\[.*\] *)' configure.ac &>/dev/null; then echo "$(basename "$0"): ERROR: Cannot locate the version info lines of configure.ac" >&2 $dryrun || exit 1 fi perl -pi -e 's/^m4_define\(_CVC4_MAJOR, ( *)[0-9]+( *)\)/m4_define(_CVC4_MAJOR, ${1}'"$major"'$2)/; s/^m4_define\(_CVC4_MINOR, ( *)[0-9]+( *)\)/m4_define(_CVC4_MINOR, ${1}'"$minor"'$2)/; s/^m4_define\(_CVC4_RELEASE, ( *)[0-9]+( *)\)/m4_define(_CVC4_RELEASE, ${1}'"$release"'$2)/; s/^m4_define\(_CVC4_EXTRAVERSION, ( *)\[.*\]( *)\)/m4_define(_CVC4_EXTRAVERSION, $1\['"$extra"'\]$2)/' configure.ac trap 'echo; echo; echo "Aborting in error."; git co -- configure.ac; echo' EXIT echo echo 'Made the following change to configure.ac:' echo git diff configure.ac echo isthatright if ! grep '^m4_define(_CVC4_MAJOR, *'"$major"' *)' configure.ac &>/dev/null || ! grep '^m4_define(_CVC4_MINOR, *'"$minor"' *)' configure.ac &>/dev/null || ! grep '^m4_define(_CVC4_RELEASE, *'"$release"' *)' configure.ac &>/dev/null || ! grep '^m4_define(_CVC4_EXTRAVERSION, *\['"$extra"'\] *)' configure.ac &>/dev/null; then echo "$(basename "$0"): INTERNAL ERROR: Cannot find the modified version info lines in configure.ac, bailing..." >&2 exit 1 fi if [ -z "$(git status -s configure.ac)" ]; then echo "$(basename "$0"): INTERNAL ERROR: \"git status\" indicates there are no local modifications to configure.ac; I expected the ones I just made!" >&2 exit 1 fi echo "Building and checking distribution \`cvc4-$version'..." if ! $SHELL -c '\ version="'$version'"; \ set -ex; \ ./autogen.sh || echo "autoconf failed; does library_versions have something to match $version?"; \ mkdir "release-$version"; \ cd "release-$version"; \ ../configure production-staticbinary --disable-shared --enable-unit-testing --with-readline --with-portfolio; \ make dist "$@"; \ tar xf "cvc4-$version.tar.gz"; \ cd "cvc4-$version"; \ ./configure production-staticbinary --disable-shared --enable-unit-testing --with-readline --with-portfolio; \ make check "$@"; \ make distcheck "$@"; \ '; then exit 1 fi if ! [ -e release-$version/cvc4-$version.tar.gz ]; then echo "$(basename "$0"): INTERNAL ERROR: Cannot find the distribution tarball I just built" >&2 exit 1 fi if ! [ -e release-$version/cvc4-$version/builds/src/main/cvc4 ]; then echo "$(basename "$0"): INTERNAL ERROR: Cannot find the binary I just built" >&2 exit 1 fi echo echo 'This release of CVC4 will identify itself as:' echo release-$version/cvc4-$version/builds/src/main/cvc4 --version echo isthatright echo echo 'This binary release of CVC4 will identify itself as being configured like this:' echo release-$version/cvc4-$version/builds/src/main/cvc4 --show-config echo isthatright echo echo "Signing tarball..." cp -p "release-$version/cvc4-$version.tar.gz" . gpg -b --armor "cvc4-$version.tar.gz" #echo #echo "Signing cvc4 binary..." #cp -p "release-$version/cvc4-$version/builds/src/main/cvc4" "cvc4-$version" #gpg -b --armor "cvc4-$version" #echo #echo "Signing pcvc4 binary..." #cp -p "release-$version/src/main/pcvc4" "pcvc4-$version" #gpg -b --armor "pcvc4-$version" if $dryrun; then echo echo '************************* DRY RUN *************************' fi echo echo "About to run: git commit -am \"Cutting release $version.\"" isthatright $dryrun || git commit -am "Cutting release $version." echo echo "About to run: git tag \"$version\"" isthatright $dryrun || git tag "$version" echo andbranch= if git status -bs | grep -q '^## master\($\| *\|\.\.\.\)'; then if [ "$release" = 0 ]; then echo "About to run: git branch \"$version.x\"" isthatright $dryrun || git branch "$version.x" andbranch=", the $version.x branch," else echo "Not branching, because this is a minor release (i.e., not a \"dot-oh\"" echo "release), so I'm guessing you have a devel branch outside of master" echo "somewhere? You can still make a branch manually, of course." fi else echo "Not branching, because it appears there already is a branch" echo "to work with for version $version ..? (You're not on master.)" echo "You can still make a branch manually, of course." fi echo echo "Done. Next steps are to:" echo echo "1. push to GitHub (don't forget to push master$andbranch and the $version tag)" echo "2. upload source and binaries" echo "3. advertise these packages" echo "4. add a $version release and next-milestone to Bugzilla." echo "5. change $version to pre-release in master$andbranch" echo " (in configure.ac) and update library_versions and NEWS." echo trap '' EXIT