bin/wakey.zsh: Quote arguments to `notify-send' for other shells.
[profile] / bin / mdw-build
CommitLineData
7ee12623
MW
1#! /bin/bash
2###
3### Build script for Debian packages
4###
5### (c) 2008 Mark Wooding
6###
7
8###----- Licensing notice ---------------------------------------------------
9###
10### This program is free software; you can redistribute it and/or modify
11### it under the terms of the GNU General Public License as published by
12### the Free Software Foundation; either version 2 of the License, or
13### (at your option) any later version.
14###
15### This program is distributed in the hope that it will be useful,
16### but WITHOUT ANY WARRANTY; without even the implied warranty of
17### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18### GNU General Public License for more details.
19###
20### You should have received a copy of the GNU General Public License
21### along with this program; if not, write to the Free Software Foundation,
22### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
85b7c21c
MW
24###--------------------------------------------------------------------------
25### Conventions for build systems.
26###
27### This script is designed to work with a variety of `make'-based build
28### systems, but there are a number of conventions which must be followed if
29### this is going to work properly.
30###
31### * There must be a `configure.ac', `configure.in', or `.links' file, or
32### a `.git' directory in the project top-level, so that we can find it.
33###
34### * The following `make' variables must be assigned in the top-level
35### Makefile, after `mdw-build' has constructed it.
36###
37### distdir The name of the top-level project directory in the
38### source distribution, and the base name for
39### distribution archives; should be of the form
40### `PROJECT-VERSION'.
41###
42### The following `make' targets must be available in the top-level
43### Makefile.
44###
45### dist Write to $(distdir).tar.gz a source distribution of
46### the package.
47###
48### distcheck As for `dist', but also build and test the project.
49###
50### * The source distribution constructed by `make dist' must contain a file
51### $(distdir)/RELEASE containing the release name. This isn't currently
52### tested, but it might be later.
53
7ee12623
MW
54set -e
55
56###--------------------------------------------------------------------------
816af8ee
MW
57### Configuration.
58
59unset checkout checkoutrev
60unset setup setupcmd
5a91acc5 61unset sign signkey
b94830d9 62unset sbuild sbuildsrv
5a91acc5 63unset upload uploadpath
816af8ee 64unset dput dputtarget
5a91acc5 65unset build distcheck debian clean vpath native
816af8ee
MW
66for i in \
67 "/etc/mdw-build.conf" \
68 "${XDG_CONFIG_HOME-$HOME/.config}/mdw-build.conf" \
69 "./.mdw-build.conf"
70do
71 if [ -f "$i" ]; then . "$i"; fi
72done
5a91acc5
MW
73default_depends () {
74 var=$1 want=$2
75 eval "p=\${$var+t} q=\${$want+t}"
76 case $p,$q in t,*) ;; *,t) eval "$var=yes" ;; *) eval "$var=no" ;; esac
77}
816af8ee
MW
78: ${checkout=yes} ${checkoutrev=HEAD}
79: ${build=test}
80: ${setup=yes} ${setupcmd=mdw-setup}
81: ${distcheck=yes}
82: ${debian=yes}
816af8ee
MW
83: ${clean=yes}
84: ${vpath=yes}
85: ${native=yes}
b94830d9 86default_depends sbuild sbuildsrv
5a91acc5
MW
87default_depends sign signkey
88default_depends upload uploadpath
89default_depends dput dputtarget
816af8ee
MW
90: ${DEB_BUILD_OPTIONS=parallel=4}; export DEB_BUILD_OPTIONS
91
92###--------------------------------------------------------------------------
7ee12623
MW
93### Parse options.
94
0660d224
MW
95prog=${0##*/}
96
7ee12623
MW
97usage () {
98 cat <<EOF
24a3095a 99Usage: $prog [-v] BUILDOPT
7ee12623
MW
100
101Build options:
102
103 [no]checkout[=REV]
104 [no]release
9c586ae1 105 [no]setup[=RUNE]
7ee12623
MW
106 [no]distcheck
107 [no]debian
5a91acc5
MW
108 [no]upload[=SERVER:PATH]
109 [no]dput[=TARGET]
7ee12623 110 [no]clean
f5b3423e 111 [no]vpath
b94830d9 112 [no]sbuild[=SERVER]
5a91acc5 113 [no]sign[=KEYID]
d87d7867 114 [no]native
7ee12623
MW
115EOF
116}
117
118## Parse simple options.
119verbose=no
24a3095a 120while getopts "hv" opt; do
7ee12623
MW
121 case "$opt" in
122 h) usage; exit 0 ;;
123 v) verbose=yes ;;
124 *) exit 1 ;;
125 esac
126done
127shift $((OPTIND - 1))
128
129## Parse the build options.
5a91acc5
MW
130maybe_set () {
131 var=$1 want=$2
132 eval "p=\${$want+t}\${$want-nil}"
133 case $p in
134 t) eval $var=yes ;;
135 nil) echo >&2 "$prog: $want not set"; exit 1 ;;
136 esac
137}
7ee12623
MW
138for opt; do
139 case "$opt" in
140 checkout) checkout=yes checkoutrev=HEAD ;;
141 checkout=*) checkout=yes checkoutrev=${opt#*=} ;;
7ee12623
MW
142 release) build=release ;;
143 norelease) build=test ;;
9c586ae1
MW
144 setup) setup=yes setupcmd=mdw-setup ;;
145 setup=*) setup=yes setupcmd=${opt#*=} ;;
5a91acc5
MW
146 upload) maybe_set upload uploadpath ;;
147 upload=*) upload=yes uploadpath=${opt#*=} ;;
148 sign) maybe_set sign signkey ;;
149 sign=*) sign=yes signkey=${opt#*=} ;;
b94830d9
MW
150 sbuild) maybe_set sbuild sbuildsrv ;;
151 sbuild=*) sbuild=yes sbuildsrv=${opt#*=} ;;
5a91acc5
MW
152 dput) maybe_set dput dputtarget ;;
153 dput=*) dput=yes dputtarget=${opt#*=} ;;
154
155 distcheck | debian | clean | vpath | native)
7ee12623
MW
156 eval "$opt=yes"
157 ;;
50c72b0f 158 nocheckout | nosetup | nodistcheck | nodebian | \
b94830d9 159 noupload | nodput | noclean | novpath | nonative | nosbuild | nosign)
7ee12623
MW
160 eval "${opt#no}=no"
161 ;;
162 *)
163 usage >&2
164 exit 1
165 ;;
166 esac
167done
168
84dd9069
MW
169## Parse DEB_BUILD_OPTIONS.
170jobs=1
171set -- $DEB_BUILD_OPTIONS
172for opt; do
173 case "$opt" in
174 parallel=*) jobs=${opt#*=} ;;
175 esac
176done
177
178makeopts=""
179case $jobs in 1) ;; *) makeopts="$makeopts -j$jobs" ;; esac
180
7ee12623
MW
181###--------------------------------------------------------------------------
182### Utility functions.
183
184exec 3>&2 4>/dev/null 5>&2
185
186notify () {
187 colour=$1 message=$2
188 echo $message >&4
189 echo "$(tput bold; tput setaf $colour)$message$(tput sgr0; tput op)" >&5
190}
191
192fail () {
193 notify 1 "!!! $*"
194 exit 1
195}
196
f282ba46
MW
197warn () {
198 case $build in
199 release) fail "$*" ;;
200 *) notify 5 "??? $*" ;;
201 esac
202}
203
7ee12623
MW
204info () {
205 notify 6 "--- $*"
206}
207
208assign () {
209 info "$1 = $2"
210 eval "$1=$2"
211}
212
213runx () {
214 notify 2 "+++ $*"
215 "$@" 2>&3 || fail "$1: exit $?"
216}
217
218run () { runx "$@" >&3; }
219
220yesno () {
221 echo -n "(test $*)" >&4
222 if "$@" >&4 2>&4; then
223 echo "(yes)" >&4
224 echo yes
225 else
226 echo "(no)" >&4
227 echo no
228 fi
229}
230
231###--------------------------------------------------------------------------
232### Do the building.
233
234## Find the top-level package directory.
d43de82b
MW
235while [ ! -f configure.ac -a ! -f configure.in -a \
236 ! -f .links -a ! -d .git ]; do
7ee12623
MW
237 case "$(pwd)" in
238 /)
239 fail "couldn't find top-level directory"
240 ;;
241 esac
242 cd ..
243done
b9ad2dae
MW
244assign toppath $(pwd)
245assign srcpath $toppath
7ee12623 246
9243a740
MW
247## Build any necessary qualifiers.
248qual= sep=.
249case ${SBOX_SESSION_DIR+t},${DEB_BUILD_ARCH+t} in
250 t,t) qual=$qual$sep$DEB_BUILD_ARCH; sep=- ;;
251 t,*) fail "unknown build arch" ;;
252esac
253
7ee12623 254## Construct the output directory.
9243a740 255assign releasepath $srcpath/dist-$build$qual
47539e6a 256chmod -R +w $releasepath 2>/dev/null || :
7ee12623
MW
257rm -rf $releasepath 2>/dev/null || :
258mkdir $releasepath
259case $verbose in
260 no)
261 exec 4>$releasepath/mdw-build.log 3>&4 ||
262 fail "Failed to create log."
263 ;;
264esac
265
f282ba46 266## Do we have a Git repository?
7ee12623
MW
267case "$checkout,$setup,$(yesno [ -d $srcpath/.git ])" in
268 yes,no,*)
269 fail "Inconsistent options: can't check out without setup."
270 ;;
271 yes,yes,no)
272 info "No Git repository found."
f282ba46 273 checkout=no gitver=none
7ee12623
MW
274 ;;
275 yes,yes,yes)
276 cd $srcpath
277 [ "$(git ls-files -m)" = "" ] ||
f282ba46 278 warn "working tree has uncommitted changes"
66305913 279 ;;
f282ba46
MW
280esac
281
282## Is there Debian build equipment?
283case "$debian,$(yesno [ -d $srcpath/debian ])" in
284 yes,no)
285 info "No debian directory found."
286 debian=no debver=none
287 ;;
f0905f8c
MW
288 no,*)
289 debver=none
290 ;;
f282ba46 291 yes,yes)
ac1bda22 292 debver=$(dpkg-parsechangelog | sed -n 's/^Version: //p')
40196145
MW
293 debsrc=$(dpkg-parsechangelog | sed -n 's/^Source: //p')
294 debname=$(git config user.name) debemail=$(git config user.email)
f282ba46
MW
295 ;;
296esac
297
46fced9d
MW
298## Maybe check out a copy of the source.
299case "$checkout" in
300 yes)
301 cd $releasepath
302 run git clone -sn $srcpath/.git _source
303 assign srcpath $releasepath/_source
304 cd $srcpath
493856f1
MW
305 run git update-ref refs/heads/mdw-build $checkoutrev ""
306 run git symbolic-ref HEAD refs/heads/mdw-build
307 run git read-tree --reset refs/heads/mdw-build
308 run git checkout-index -afu
ac1bda22 309 assign gitversion "$(git describe --abbrev=4)"
46fced9d
MW
310 ;;
311esac
312
f282ba46 313## Check the version number.
40196145 314hack_dch_p=no
ac1bda22 315case "$gitversion,$debver" in
f282ba46
MW
316 none,* | *,none)
317 ;;
318 *)
ac1bda22
MW
319 dvref=$(echo "$debver" | tr '~' '_')
320 if [ "$gitversion" = "$dvref" ]; then
321 assign debversion "$debver"
322 else
323 warn "Git version $gitversion doesn't match Debian version $debver"
40196145 324 hack_dch=yes
ac1bda22
MW
325 dver=$(echo $gitversion | sed 's/-/+/; s/-/./g')
326 case $debver in *~) dver=$debver$dver ;; esac
327 assign debversion "$dver"
328 now=$(date -R)
40196145 329 fi
f282ba46
MW
330 ;;
331esac
332
7ee12623
MW
333## Maybe refresh the build machinery.
334case "$setup" in
335 yes)
9c586ae1 336 run $setupcmd
7ee12623
MW
337 ;;
338esac
339
340## Initialize the build directory.
f5b3423e
MW
341case "$vpath,$(yesno [ -e $srcpath/configure ])" in
342 yes,yes)
343 assign buildpath $releasepath/_build
344 mkdir $buildpath
345 cd $buildpath
346 run $srcpath/configure
347 ;;
348 no,yes)
349 info "VPATH build disabled"
350 assign buildpath $srcpath
351 distcheck=no
352 cd $srcpath
353 run ./configure
354 ;;
355 *,no)
356 info "no configure script"
357 assign buildpath $srcpath
358 cd $srcpath
359 ;;
360esac
7ee12623
MW
361
362## Discover the release name.
363cat >find-distdir.mk <<'EOF'
364include Makefile
365print-distdir:
dd8d9a6c 366 @echo >&3 $(distdir)
7ee12623 367EOF
dd8d9a6c
MW
368assign distdir \
369 $({ make -f find-distdir.mk print-distdir >/dev/null 2>&1; } 3>&1)
7ee12623
MW
370
371## Get a tarball distribution.
372case "$distcheck" in
373 yes)
84dd9069 374 run make $makeopts distcheck
7ee12623
MW
375 ;;
376 no)
84dd9069 377 run make $makeopts dist
7ee12623
MW
378 ;;
379esac
380
381cd $releasepath
382
d87d7867
MW
383case $native in
384 yes)
385 if ! tar tf $buildpath/$distdir.tar.gz 2>/dev/null | grep -q RELEASE
386 then
387 fail "missing RELEASE file in distribution"
388 fi
389 ;;
390esac
7ee12623
MW
391
392run mv $buildpath/$distdir.tar.gz .
5a91acc5
MW
393case $build,$sign in
394 release,yes)
395 run gpg -u$signkey -ab -o$distdir.tar.gz.gpg $distdir.tar.gz
47f56ea2
MW
396 ;;
397esac
7ee12623
MW
398
399## Maybe build the Debian packages.
f282ba46
MW
400case "$debian" in
401 yes)
7ee12623
MW
402 run tar xvfz $distdir.tar.gz
403 cd $distdir
40196145
MW
404 case $hack_dch in
405 yes)
40196145 406 cat - debian/changelog >debian/changelog.new <<EOF
ac1bda22 407$debsrc ($debversion) experimental; urgency=low
40196145
MW
408
409 * Hacking in process, not intended for release.
410
411 -- $debname <$debemail> $now
412
413EOF
414 mv debian/changelog.new debian/changelog
415 ;;
416 esac
e5099dd8
MW
417 sbuildargs=$sbuildsrv
418 case $sbuild,$build in
419 yes,release)
420 case $sign in yes) sbuildargs="-k$signkey $sbuildargs" ;; esac
421 ;;
6cf97414
MW
422 yes,*)
423 if [ -d $toppath/dist-$build.pkgs ]; then
424 sbuildargs="-p$toppath/dist-$build.pkgs $sbuildargs"
425 fi
426 ;;
e5099dd8 427 esac
b94830d9 428 case $sbuild,$build,$sign in
e5099dd8 429 yes,*) run mdw-sbuild $sbuildargs ;;
b94830d9 430 no,release,yes) run dpkg-buildpackage -k$signkey ;;
5a91acc5
MW
431 no,*) run dpkg-buildpackage -us -uc ;;
432 esac
7ee12623
MW
433 ;;
434esac
435
436## Maybe upload Debian packages.
437cd $releasepath
438case "$upload,$build" in
5a91acc5
MW
439 yes,test) info "Test build: not uploading." ;;
440 yes,release) run rsync $distdir.tar.gz $distdir.tar.gz.gpg $uploadpath ;;
441esac
442case "$debian,$upload,$dput,$build" in
443 yes,yes,yes,release) run dput -f $dputtarget *.changes ;;
7ee12623
MW
444esac
445
446## Tidy up.
447case "$clean" in
448 yes)
449 rm -rf $releasepath/$distdir
450 rm -rf $releasepath/_source
451 rm -rf $releasepath/_build
452 ;;
453esac
454
455## Done.
456info "All OK."
457
458###----- That's all, folks --------------------------------------------------