Hi everybody!

Attached find a bash script gubllt.

Gubllt

 * first builds a regression test archive for a specified version of lilypond,
 * performs a full build (installers for all supported platforms, 
documentation, etc) for another specified version of lilypond. The regression 
test archive generated in the first step is used for the test.


Gubllt takes for arguments:

1. A relative or absolute path to the local gub repository that shall be used.
2. A relative or absolute path to the local lilypond repository that shall be 
used.
3. The lilypond version to use as a testbase. This might be a branch name, the 
sha-1 of a commit, even something like 'HEAD~1' is acceptable.
4. The lilypond version to test. This might be a branch name, the sha-1 of a 
commit, even something like 'HEAD~1' is acceptable. You might also give the URL 
of a rietveld review patch.

The gubllt script tries to handle error conditions gracefully, it should be 
stored in a directory listed in PATH.

Examples:

   gubllt /home/foobar/devel/gub /home/foobar/devel/lily master testver
   gubllt ~/devel/gub ~/devel/lily master 0e9237da8
   gubllt gub lily master 
https://codereview.appspot.com/download/issue572640043_552640044.diff

Knut


#!/bin/bash
#
# GUBLLT - Copyright 2019 Knut Petersen (knup...@gmail.com)
#

# 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
_______________________________________________
lilypond-devel mailing list
lilypond-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-devel

Reply via email to