#!/bin/bash # # GUBLLT - Copyright 2019 Knut Petersen (address@hidden) # # abort if some programs we need are not present requireProg () { if [[ -z `which $1 2> /dev/null` ]]; then echo "GUBLLT ERROR: We need '$1' but could not find it!" exit 1 fi } requireProg sed requireProg grep requireProg wget requireProg mktemp requireProg git requireProg patch requireProg make # init vars used in function clean GITPID=0 TMPSRVDIR="" LILYTREETORESTORE="" # clean up clean () { if [ $GITPID -ne 0 ]; then echo "GUBLLT INFO:" echo "GUBLLT INFO: Killing git daemon (ppid $GITPID)" kill -n 9 -- $(ps -o pid= --ppid $GITPID) fi if [ "x$TMPSRVDIR" != "x" ]; then if [ -d "$TMPSRVDIR" ]; then echo "GUBLLT INFO: Removing $TMPSRVDIR." rm -rf $TMPSRVDIR fi fi if [ "x$LILYTREETORESTORE" != "x" ]; then cd $LILYREPODIR git checkout $LILYTREETORESTORE &> /dev/null echo "GUBLLT INFO: checked out '$LILYTREETORESTORE'" fi } # errex is used as the general error exit errex () { echo -e "\nGUBLLT ERROR: Abnormal termination of gubllt script!" clean exit 2 } # trapex is used called if we receive SIGINT or SIGTERM trapex () { echo -e "\nGUBLLT ERROR: Terminated by signal!" clean exit 3 } # trap some signals trap trapex SIGINT SIGTERM # define procFN function --- canonicalize / simplify a path name procFN () { echo $1 | \ sed -e "s|^./|$PWD/|" \ -e "s|^../|$PWD/../|" \ -e "s|\(^[^/]\)|$PWD/\1|" \ -e ':loopA s|/[^/]*/../|/|; t loopA' \ -e ':loopB s|/./|/|; t loopB' } # abort if not exactly 4 arguments are provided if [ $# -ne 4 ]; then echo "" echo "Usage:" echo "" echo " gubllt gubdir lilydr basever testver" echo "" echo " 'gubdir' is the directory of your local gub repository" echo " 'lilydir' is the directory of your local lilypond repository" echo " 'basever' is an object identifier (a branch name, the sha-1" echo " of a commit) in your lilypond repository." echo " 'testver' is either an object identifier in your local lilypond" echo " repository or an URL pointing to a Rietveld patch." echo " If an URL is given the patch will be applied on top" echo " of 'basever'." echo "" echo "After some initial checks gubllt first uses gub to build a regression" echo "test archive for the lilypond version described by 'basever'." echo "Then gubllt uses gub to build the installers for the lilypond version" echo "described by 'testver' for all supported architectures. It also builds" echo "the lilypond documentation and executes the regression tests." echo "" echo "Installers, documentation, etc. are stored in 'gubdir/uploads'." echo "" echo "To view the regression test results use a browser, e.g.:" echo " firefox file:///gubdir/uploads/webtest" echo "Whatever the real version number may be, the results of 'basever'" echo "are shown as results of lilypond version v0.0.0-1 as gub does not" echo "support comparing tests results with identical version numbers." echo "" echo "To view the local documentation use a browser, e.g.:" echo " firefox file:///gubdir/uploads/localdoc" echo "" echo "===============================================================" echo "" echo "ATTENTION!" echo "" echo "gubllt will DELETE some files after passing its initial tests." echo "It executes 'rm -rf' with the following patterns:" echo "" echo " gubdir/uploads/*" echo " gubdir/regtests/*" echo " gubdir/target/*/*/*lilypond*" echo "" echo "You'll find some new files here after gubllt succeeds ;-)" echo "" echo "===============================================================" echo "" echo -n "GUBLLT ERROR: Invalid number of command line arguments!" errex else echo "GUBLLT INFO:" echo "GUBLLT INFO: GUB Local Lilypond Tester (gubllt) version 0.01" echo "GUBLLT INFO: Checking arguments:" fi GUBDIR=`procFN $1` LILYREPODIR=`procFN $2` LILYTESTBASE=$3 LILYTESTVER=$4 # abort if GUBDIR parameter is invalid if [ ! -f "$GUBDIR/bin/gub" ]; then echo "GUBLLT ERROR: gub_directory parameter '$GUBDIR' invalid!" errex else echo "GUBLLT INFO: Gub directory '$GUBDIR' exists." # we need those directories, and they are not present in a fresh gub mkdir -p $GUBDIR/regtests $GUBDIR/target $GUBDIR/uploads fi # abort if LILYREPODIR parameter is invalid if [ ! -f "$LILYREPODIR/lily/lilypond-version.cc" ]; then echo "GUBLLT ERROR: lilypond_repository_directory '$LILYREPODIR' invalid!" errex else echo "GUBLLT INFO: Lilypond repository directory '$LILYREPODIR' exists." fi # abort if LILYTESTBASE isn't a valid object in LILYREPODIR cd $LILYREPODIR LILYTESTBASEHASH=`git rev-parse --quiet --verify $LILYTESTBASE` if [ $? -ne 0 ]; then echo "GUBLLT ERROR: Object '$LILYTESTBASE' does not exist " \ "in repository $LILYREPODIR!" errex else echo "GUBLLT INFO: Object '$LILYTESTBASE' points to " \ "commit '$LILYTESTBASEHASH'" fi # create a temporary git server directory in GUBDIR, abort if this fails TMPSRVDIR=$(mktemp -d -t -p $GUBDIR/ gubllt-XXXXXXXXXX) if [ ! -d "$TMPSRVDIR" ]; then echo "GUBLLT ERROR: Failed to created the directory '$TMPSRVDIR'!" TMPSRVDIR="" errex fi PATCHFILE="" echo $LILYTESTVER | \ grep -o https://codereview.appspot.com/download/issue[0-9]*_[0-9]*.diff \ &> /dev/null if [ $? -eq 0 ]; then cd $TMPSRVDIR wget $LILYTESTVER &> /dev/null PATCHFILE=`echo $LILYTESTVER | \ sed -e "s|https://codereview.appspot.com/download/||"` if [ ! -f "$PATCHFILE" ]; then echo "GUBLLT ERROR: Download of '$LILYTESTVER' failed!" else echo "GUBLLT INFO: Downloaded $LILYTESTVER to '$TMPSRVDIR/$PATCHFILE'" fi else # LILYTESTVER is assumed to be a valid object identifier in LILYREPODIR # abort if LILYTESTVER isn't a valid object in LILYREPODIR cd $LILYREPODIR LILYTESTVERHASH=`git rev-parse --quiet --verify $LILYTESTVER` if [ $? -ne 0 ]; then echo "GUBLLT ERROR: Object '$LILYTESTVER' does not exist " \ "in repository $LILYREPODIR!" errex else echo "GUBLLT INFO: Object '$LILYTESTVER' points to " \ "commit '$LILYTESTVERHASH'." fi fi # abort if LILYREPODIR isn't clean cd $LILYREPODIR if [[ -z $(git status -s --porcelain) ]]; then echo "GUBLLT INFO: Repository '$LILYREPODIR' is clean." LILYTREETORESTORE=`LANG=c git branch | grep "^\*" | \ sed -e "s|^* *||" -e "s|(HEAD detached at \([0-9a-f]*\))|\1|"` if [[ -n "$LILYTREETORESTORE" ]]; then echo "GUBLLT INFO: Saved working tree '$LILYTREETORESTORE'" fi else echo "GUBLLT ERROR: Repository '$LILYREOPDIR' isn't clean." echo "GUBLLT ERROR: Either commit your changes or use e.g." echo "GUBLLT ERROR: git reset --hard HEAD; git clean -dfx" echo "GUBLLT ERROR: to clean the working tree of $LILYREPODIR!" errex fi # abort if a git-daemon is active ps ax | grep git-daemon | grep -v grep | grep git-daemon if [ $? -eq 0 ]; then echo "GUBLLT ERROR: A git-daemon is already running on this system!" errex fi # create a lilypond.git link in TMPSRVDIR ln -s $LILYREPODIR $TMPSRVDIR/lilypond.git # start git-daemon in the background git daemon --log-destination=none --export-all --reuseaddr \ --base-path=$TMPSRVDIR/ $TMPSRVDIR &> /dev/null & GITPID=$! echo "GUBLLT INFO: Started git daemon with PID $GITPID." # wait until git-daemon starts to provide its service ... # abort if this does not occur within a reasonable time # it is assumed that every lilypond git repository has a # valid branch master, so test for that. i=0 while [ $i -le 10 ] do ((i++)) echo "GUBLLT INFO: Waiting for git daemon ..." TESTOUT=`git ls-remote git://localhost/lilypond.git master 2>&1 | \ grep -o refs/heads/master` if [ "$TESTOUT" == "refs/heads/master" ]; then break; fi if [ $i -eq 10 ]; then echo "GUBLLT ERROR: Git daemon timed out!" errex fi sleep 1 done # remove old tmp-gubllt-test branch cd $LILYREPODIR git checkout master &> /dev/null git branch -D tmp-gubllt-test &> /dev/null # create temporary branch for commit/branch LILYTESTBASE git branch -f tmp-gubllt-test $LILYTESTBASEHASH if [ $? -ne 0 ]; then echo "GUBLLT ERROR: Could not create branch 'tmp-gubllt-test'!" errex else echo "GUBLLT INFO: Created temporary branch 'tmp-gubllt-test' " \ "for commit '$LILYTESTBASEHASH'." fi # build LILYTESTBASE regtest archive echo "GUBLLT INFO: Execute GUB to build regression test archive " \ "for '$LILYTESTBASEHASH'." echo "GUBLLT INFO:" cd $GUBDIR rm -rf regtests/* uploads/* target/*/*/*lilypond* \ ./downloads/lilypond/git/refs/heads/localhost/lilypond.git/tmp-gubllt-test bin/gub git://localhost/lilypond-test.git?branch=tmp-gubllt-test TESTOUT=`ls uploads/lilypond*.*.*-*.test-output.tar.bz2` if [ "x$TESTOUT" == "x" ]; then echo "GUBLLT ERROR: Could not create testbase regression test archive " \ "for '$LILYTESTBASEHASH'!" errex fi cd $LILYREPODIR if [ -n "$PATCHFILE" ]; then git checkout tmp-gubllt-test &> /dev/null patch -p 1 < $TMPSRVDIR/$PATCHFILE &> /dev/null if [ $? -ne 0 ]; then echo "GUBLLT ERROR: Patching $LILYTESTBASE with $PATCHFILE failed!" errex fi git add --all &> /dev/null if [ $? -ne 0 ]; then echo "GUBLLT ERROR: unexpected error 1" errex fi git commit -m "Rietveld $PATCHFILE" &> /dev/null if [ $? -ne 0 ]; then echo "GUBLLT ERROR: unexpected error 2" errex fi echo "GUBLLT INFO:" echo "GUBLLT INFO: Applied $PATCHFILE on top of $LILYTESTBASEHASH." git checkout master &> /dev/null if [ $? -ne 0 ]; then echo "GUBLLT ERROR: unexpected error 3" errex fi else git branch -f tmp-gubllt-test $LILYTESTVERHASH if [ $? -ne 0 ]; then echo "GUBLLT ERROR: could not create branch 'tmp-gubllt-test'!" errex else echo "GUBLLT INFO: Created temporary branch 'tmp-gubllt-test' for " \ "commit '$LILYTESTVERHASH'." fi fi # build LILYTESTVER -- everthing cd $GUBDIR cp $TESTOUT regtests/lilypond-0.00.0-1.test-output.tar.bz2 touch regtests/ignore rm -rf uploads/* target/*/*/*lilypond* echo "GUBLLT INFO: Execute 'make ... lilypond'." echo "GUBLLT INFO:" make LILYPOND_REPO_URL=git://localhost/lilypond.git \ LILYPOND_BRANCH=tmp-gubllt-test lilypond # kill our git daemon and remove our temporary git server directory clean # display some info about the files that were created: cd $GUBDIR/uploads dispRes () { TESTOUT=`ls -1 $1` if [ "A$TESTOUT" != "A" ]; then echo "$2 `procFN $TESTOUT`" fi } echo "GUBLLT INFO:" echo "GUBLLT INFO: ============================================" echo "GUBLLT INFO: A large number of files have been generated," echo "GUBLLT INFO: of particular interest to you probably are:" echo "GUBLLT INFO: ============================================" echo "GUBLLT INFO:" dispRes webtest/*/compare-v0.0.0-1/index.html \ "GUBLLT INFO: the regression tests results: " dispRes localdoc/v2.21.0/index.html \ "GUBLLT INFO: the local documentation tree: " echo "GUBLLT INFO:" dispRes lilypond*linux-64.sh \ "GUBLLT INFO: the GNU/Linux x86 64-bit installer:" dispRes lilypond*linux-x86.sh \ "GUBLLT INFO: the GNU/Linux x86 32-bit installer:" dispRes lilypond*linux-ppc.sh \ "GUBLLT INFO: the GNU/Linux PPC installer: " dispRes lilypond*darwin-ppc.tar.bz2 \ "GUBLLT INFO: the MacOS X 10.4+ PPC installer: " dispRes lilypond*darwin-x86.tar.bz2 \ "GUBLLT INFO: the MacOS X 10.4+ x86 installer: " dispRes lilypond*freebsd-64.sh \ "GUBLLT INFO: the FreeBSD x86 64-bit installer: " dispRes lilypond*freebsd-x86.sh \ "GUBLLT INFO: the FreeBSD x86 32-bit installer: " dispRes lilypond*mingw.exe \ "GUBLLT INFO: the Windows installer: " echo "GUBLLT INFO:" dispRes lilypond*documentation.tar.bz2 \ "GUBLLT INFO: the lilypond documentation tarball:" dispRes lilypond-2.21.0.tar.gz \ "GUBLLT INFO: the lilypond source tarball: " echo "GUBLLT INFO:" exit 0