set -e
+###--------------------------------------------------------------------------
+### Configuration.
+
+unset checkout checkoutrev
+unset setup setupcmd
+unset sign signkey
+unset sbuild sbuildsrv
+unset upload uploadpath
+unset dput dputtarget
+unset build distcheck debian clean vpath native
+for i in \
+ "/etc/mdw-build.conf" \
+ "${XDG_CONFIG_HOME-$HOME/.config}/mdw-build.conf" \
+ "./.mdw-build.conf"
+do
+ if [ -f "$i" ]; then . "$i"; fi
+done
+default_depends () {
+ var=$1 want=$2
+ eval "p=\${$var+t} q=\${$want+t}"
+ case $p,$q in t,*) ;; *,t) eval "$var=yes" ;; *) eval "$var=no" ;; esac
+}
+: ${checkout=yes} ${checkoutrev=HEAD}
+: ${build=test}
+: ${setup=yes} ${setupcmd=!guess}
+: ${distcheck=yes}
+: ${debian=yes}
+: ${clean=yes}
+: ${vpath=yes}
+: ${native=yes}
+: ${make=make}
+: ${test=yes}
+default_depends sbuild sbuildsrv
+default_depends sign signkey
+default_depends upload uploadpath
+default_depends dput dputtarget
+: ${DEB_BUILD_OPTIONS=parallel=4}; export DEB_BUILD_OPTIONS
+
###--------------------------------------------------------------------------
### Parse options.
+prog=${0##*/}
+
usage () {
cat <<EOF
-Usage: $0 [-vr] BUILDOPT
+Usage: $prog [-v] BUILDOPT
Build options:
[no]setup[=RUNE]
[no]distcheck
[no]debian
- [no]upload
+ [no]upload[=SERVER:PATH]
+ [no]dput[=TARGET]
[no]clean
[no]vpath
+ [no]sbuild[=SERVER]
+ [no]sign[=KEYID]
+ [no]test
[no]native
+ make=MAKE
EOF
}
## Parse simple options.
verbose=no
-while getopts "hvr" opt; do
+while getopts "hv" opt; do
case "$opt" in
h) usage; exit 0 ;;
v) verbose=yes ;;
shift $((OPTIND - 1))
## Parse the build options.
-checkout=yes
-checkoutrev=HEAD
-build=test
-setup=yes
-setupcmd=mdw-setup
-distcheck=yes
-debian=yes
-upload=yes
-clean=yes
-vpath=yes
-native=yes
+maybe_set () {
+ var=$1 want=$2
+ eval "p=\${$want+t}\${$want-nil}"
+ case $p in
+ t) eval $var=yes ;;
+ nil) echo >&2 "$prog: $want not set"; exit 1 ;;
+ esac
+}
for opt; do
case "$opt" in
checkout) checkout=yes checkoutrev=HEAD ;;
checkout=*) checkout=yes checkoutrev=${opt#*=} ;;
release) build=release ;;
norelease) build=test ;;
- setup) setup=yes setupcmd=mdw-setup ;;
+ setup) setup=yes setupcmd=!guess ;;
setup=*) setup=yes setupcmd=${opt#*=} ;;
-
- distcheck | debian | upload | clean | vpath | native)
+ upload) maybe_set upload uploadpath ;;
+ upload=*) upload=yes uploadpath=${opt#*=} ;;
+ sign) maybe_set sign signkey ;;
+ sign=*) sign=yes signkey=${opt#*=} ;;
+ sbuild) maybe_set sbuild sbuildsrv ;;
+ sbuild=*) sbuild=yes sbuildsrv=${opt#*=} ;;
+ dput) maybe_set dput dputtarget ;;
+ dput=*) dput=yes dputtarget=${opt#*=} ;;
+ make=*) make=${opt#*=} ;;
+
+ distcheck | debian | clean | vpath | native | test)
eval "$opt=yes"
;;
nocheckout | nosetup | nodistcheck | nodebian | \
- noupload | noclean | novpath | nonative)
+ noupload | nodput | noclean | novpath | nonative | notest | \
+ nosbuild | nosign )
eval "${opt#no}=no"
;;
*)
for opt; do
case "$opt" in
parallel=*) jobs=${opt#*=} ;;
+ nocheck) test=no ;;
esac
done
###--------------------------------------------------------------------------
### Utility functions.
-exec 3>&2 4>/dev/null 5>&2
+## File descriptor assignments:
+##
+## 0 -- original stdin (never touched)
+## 1, 2 -- stdout, stderr, redirected to 3 while running comamnds
+## log -- logfile and original stderr (verbose), or logfile only (quiet);
+## captures command output
+## diag -- logfile; primary diagnostic output
+## term -- orginal stderr; secondary diagnostic output (with colours)
notify () {
colour=$1 message=$2
- echo $message >&4
- echo "$(tput bold; tput setaf $colour)$message$(tput sgr0; tput op)" >&5
+ echo $message >&$diag
+ echo "$(tput bold; tput setaf $colour)$message$(tput sgr0; tput op)" >&$term
}
fail () {
runx () {
notify 2 "+++ $*"
- "$@" 2>&3 || fail "$1: exit $?"
+ nice "$@" 2>&$log {log}>&- {diag}>&- {term}>&- || fail "$1: exit $?"
}
-run () { runx "$@" >&3; }
+run () { runx "$@" >&$log; }
yesno () {
- echo -n "(test $*)" >&4
- if "$@" >&4 2>&4; then
- echo "(yes)" >&4
+ echo -n "(test $*)" >&$diag
+ if "$@" >&$diag 2>&$diag {log}>&- {diag}>&- {term}>&-; then
+ echo "(yes)" >&$diag
echo yes
else
- echo "(no)" >&4
+ echo "(no)" >&$diag
echo no
fi
}
###--------------------------------------------------------------------------
### Do the building.
+## Some preflight checks.
+case $test,$build in
+ no,release) fail "refusing to make release build without testing" ;;
+esac
+case $test,$distcheck in
+ no,yes)
+ info "forcing \`distcheck' off because tsting disabled"
+ distcheck=no
+ ;;
+esac
+
## Find the top-level package directory.
while [ ! -f configure.ac -a ! -f configure.in -a \
! -f .links -a ! -d .git ]; do
esac
cd ..
done
-assign srcpath $(pwd)
+toppath=$(pwd)
+
+## Build any necessary qualifiers.
+qual= sep=.
+case ${SBOX_SESSION_DIR+t},${DEB_BUILD_ARCH+t} in
+ t,t) qual=$qual$sep$DEB_BUILD_ARCH; sep=- ;;
+ t,*) fail "unknown build arch" ;;
+esac
## Construct the output directory.
-assign releasepath $srcpath/dist-$build
+releasepath=$toppath/dist-$build$qual
chmod -R +w $releasepath 2>/dev/null || :
rm -rf $releasepath 2>/dev/null || :
mkdir $releasepath
+logfile=$releasepath/mdw-build.log
+exec {term}>&2
+exec {diag}>>$logfile || fail "Failed to create log."
case $verbose in
- no)
- exec 4>$releasepath/mdw-build.log 3>&4 ||
- fail "Failed to create log."
- ;;
+ no) exec {log}>&$diag ;;
+ yes) exec {log}> >(tee -a $logfile >&$term {term}>&- {diag}>&-) ;;
esac
+## Repeat the earlier assignments for tbe benefit of the logfile.
+assign toppath $toppath
+assign releasepath $releasepath
+assign logfile $logfile
+
## Do we have a Git repository?
-case "$checkout,$setup,$(yesno [ -d $srcpath/.git ])" in
+case "$checkout,$setup,$(yesno [ -d $toppath/.git ])" in
yes,no,*)
fail "Inconsistent options: can't check out without setup."
;;
checkout=no gitver=none
;;
yes,yes,yes)
- cd $srcpath
+ cd $toppath
[ "$(git ls-files -m)" = "" ] ||
warn "working tree has uncommitted changes"
- gitver=$(git describe --abbrev=4)
+ ;;
esac
## Is there Debian build equipment?
-case "$debian,$(yesno [ -d $srcpath/debian ])" in
+case "$debian,$(yesno [ -d $toppath/debian ])" in
yes,no)
info "No debian directory found."
debian=no debver=none
debver=none
;;
yes,yes)
- debver=$(dpkg-parsechangelog | sed -n 's/^Version: //p' | tr \~ -)
+ debver=$(dpkg-parsechangelog | sed -n 's/^Version: //p')
debsrc=$(dpkg-parsechangelog | sed -n 's/^Source: //p')
debname=$(git config user.name) debemail=$(git config user.email)
;;
esac
+## Maybe check out a copy of the source.
+case "$checkout" in
+ yes)
+ cd $releasepath
+ run git clone -sn $toppath/.git _source
+ assign srcpath $releasepath/_source
+ cd $srcpath
+ run git update-ref refs/heads/mdw-build $checkoutrev ""
+ run git symbolic-ref HEAD refs/heads/mdw-build
+ run git read-tree --reset refs/heads/mdw-build
+ run git checkout-index -afu
+ assign gitversion "$(git describe --abbrev=4)"
+ ;;
+ no)
+ assign srcpath $toppath
+ ;;
+esac
+
## Check the version number.
hack_dch_p=no
-case "$gitver,$debver" in
+case "$gitversion,$debver" in
none,* | *,none)
;;
*)
- if [ "$gitver" != "$debver" ]; then
- warn "Git version $gitver doesn't match Debian version $debver"
+ dvref=$(echo "$debver" | tr '~' '_')
+ if [ "$gitversion" = "$dvref" ]; then
+ assign debversion "$debver"
+ else
+ warn "Git version $gitversion doesn't match Debian version $debver"
hack_dch=yes
+ dver=$(echo $gitversion | sed 's/-/+/; s/-/./g')
+ case $debver in *~) dver=$debver$dver ;; esac
+ assign debversion "$dver"
+ now=$(date -R)
fi
;;
esac
-## Maybe check out a copy of the source.
-case "$checkout" in
- yes)
- cd $releasepath
- run git clone -sn $srcpath/.git _source
- assign srcpath $releasepath/_source
- cd $srcpath
- run git checkout -b mdw-build $checkoutrev
- ;;
-esac
-
## Maybe refresh the build machinery.
case "$setup" in
yes)
+ case $setupcmd in
+ !guess)
+ if [ -f .links ]; then setupcmd=mdw-setup
+ elif [ -x autogen.sh ]; then setupcmd=./autogen.sh
+ elif [ -x setup ]; then setupcmd=./setup
+ elif [ -f configure.ac ]; then setupcmd="autoreconf -is"
+ else setupcmd=mdw-setup
+ fi
+ ;;
+ esac
run $setupcmd
;;
esac
cat >find-distdir.mk <<'EOF'
include Makefile
print-distdir:
- @echo >&3 $(distdir)
+ @echo >&$(fd) $(distdir)
EOF
assign distdir \
- $({ make -f find-distdir.mk print-distdir >/dev/null 2>&1; } 3>&1)
+ $({ $make -f find-distdir.mk print-distdir fd=$t >/dev/null 2>&1; } {t}>&1)
## Get a tarball distribution.
case "$distcheck" in
yes)
- run make $makeopts distcheck
+ run $make $makeopts distcheck
;;
no)
- run make $makeopts dist
+ run $make $makeopts dist
;;
esac
esac
run mv $buildpath/$distdir.tar.gz .
-case $build in
- release)
- run gpg -u$(mdw-conf releasekey) -ab -o$distdir.tar.gz.gpg \
- $distdir.tar.gz
+case $build,$sign in
+ release,yes)
+ run gpg -u$signkey -ab -o$distdir.tar.gz.gpg $distdir.tar.gz
;;
esac
cd $distdir
case $hack_dch in
yes)
- dver=$(echo $gitver | sed 's/-/+/; s/-/./g')
- now=$(date -R)
cat - debian/changelog >debian/changelog.new <<EOF
-$debsrc ($dver) experimental; urgency=low
+$debsrc ($debversion) experimental; urgency=low
* Hacking in process, not intended for release.
mv debian/changelog.new debian/changelog
;;
esac
- run dpkg-buildpackage -k$(mdw-conf releasekey)
+ sbuildargs=$sbuildsrv
+ case $sbuild,$build in
+ yes,release)
+ case $sign in yes) sbuildargs="-k$signkey $sbuildargs" ;; esac
+ ;;
+ yes,*)
+ if [ -d $toppath/dist-$build.pkgs ]; then
+ sbuildargs="-p$toppath/dist-$build.pkgs $sbuildargs"
+ fi
+ ;;
+ esac
+ case "$sbuild,$test, $DEB_BUILD_OPTIONS " in
+ yes,no,*) sbuildargs="-T $sbuildargs" ;;
+ *" nocheck "*) ;;
+ no,no,*)
+ DEB_BUILD_OPTIONS=${DEB_BUILD_OPTIONS+"$DEB_BUILD_OPTIONS nocheck"}
+ ;;
+ esac
+ case $sbuild,$build,$sign in
+ yes,*) run mdw-sbuild $sbuildargs ;;
+ no,release,yes) run dpkg-buildpackage -k$signkey ;;
+ no,*) run dpkg-buildpackage -us -uc ;;
+ esac
;;
esac
## Maybe upload Debian packages.
cd $releasepath
case "$upload,$build" in
- yes,test)
- info "Test build: not uploading."
- ;;
- yes,release)
- run rsync $distdir.tar.gz $distdir.tar.gz.gpg \
- $(mdw-conf upload-target ftp.distorted.org.uk:~ftp/pub/mdw/)
- case "$debian" in
- yes)
- run dput -f $(mdw-conf dput-target distorted) *.changes
- ;;
- esac
+ yes,test) info "Test build: not uploading." ;;
+ yes,release) run rsync $distdir.tar.gz $distdir.tar.gz.gpg $uploadpath ;;
+esac
+case "$debian,$upload,$dput,$build" in
+ yes,yes,yes,release) run dput -f $dputtarget *.changes ;;
esac
## Tidy up.