merge improvements from MirBSD CVS:
[shellsnippets/shellsnippets.git] / mksh / sysadmin / vcs2deb
1 #!/bin/mksh
2 # $Id: vcs2deb 2504 2011-11-17 15:30:10Z tglase $
3 # $MirOS: contrib/hosted/tg/deb/BuildDSC.sh,v 1.14 2011/11/17 15:27:53 tg Exp $
4 #-
5 # Copyright (c) 2010, 2011
6 #       Thorsten Glaser <t.glaser@tarent.de>
7 #
8 # Provided that these terms and disclaimer and all copyright notices
9 # are retained or reproduced in an accompanying document, permission
10 # is granted to deal in this work without restriction, including un-
11 # limited rights to use, publicly perform, distribute, sell, modify,
12 # merge, give away, or sublicence.
13 #
14 # This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
15 # the utmost extent permitted by applicable law, neither express nor
16 # implied; without malicious intent or gross negligence. In no event
17 # may a licensor, author or contributor be held liable for indirect,
18 # direct, other damage, loss, or other issues arising in any way out
19 # of dealing in the work, even if advised of the possibility of such
20 # damage or existence of a defect, except proven that it results out
21 # of said person's immediate fault when using the work as intended.
22 #-
23 # root@dev-hudson:/usr/local/bin/vcs2deb
24 #
25 # This wants two checkboxen ENABLE_UPLOAD and VERSION_AS_SNAPSHOT in
26 # Jenkins ("parametrized build"). Example usage:
27 # vcs2deb -b lenny-backports -r 'deb foo main' -r 'deb bar tarent' \
28 #     -o -sa -o -m'Dev Jenkins <buildd@domain.de>' -j portal-setup \
29 #     -d squeeze -s main -O [http:/]/path/to/foo-1.2.3.orig.tar.xz \
30 #     -T HEAD :ext:anoncvs@server.com:/cvs src/modulename
31 # These arguments are passed to the scripts as follows:
32 # * kuhbauer [-r {r*}] {b} *.dsc [{o*}]
33 # * mvndput {j} {d} {s} *.changes (if ENABLE_UPLOAD)
34
35 # sanitise environment
36 unset LANGUAGE
37 export LC_ALL=C
38 wd=$(realpath .)
39 cd "$wd"
40
41 usage() { cat <<EOF
42 Syntax: $0 -b DIST [-r aptrepo [-r ...]] [-o debbuiltopt [-o ...]]
43         -j jobname -d targetdistribution -s targetsuite
44         [-O [http:/]/path/to/origtgz] [-T tag] scmpath
45 Tags: cvs (tag/branch[:date]), git (branch), bzr (revisionspec), hg (idem)
46 Knobs: ENABLE_UPLOAD, VERSION_AS_SNAPSHOT
47 Environment: DEBEMAIL (for snapshots)
48 EOF
49         exit ${1:-1}
50 }
51
52 # preload
53 sync
54 date >/dev/null
55 stime_rfc=$(date +"%a, %d %b %Y %H:%M:%S %z")
56 stime_vsn=$(date -u +"%Y%m%d.%H%M%S")
57
58 [[ $VERSION_AS_SNAPSHOT != true ]]; snap=$?
59 [[ $ENABLE_UPLOAD != true ]]; dodput=$?
60
61 if (( snap )) && [[ -z $DEBEMAIL ]]; then
62         print -u2 'Please set $DEBEMAIL to "First M. Last <email@domain.com>"'
63         usage
64 fi
65
66 DIST=
67 targdist=
68 jobname=
69 origtgz=
70 set -A dbo
71 xrepo=
72 targsuite=
73 scmtag=
74 while getopts 'b:d:hj:O:o:r:s:T:' ch; do
75         case $ch {
76         (b)     DIST=$OPTARG ;;
77         (d)     targdist=$OPTARG ;;
78         (h)     usage 0 ;;
79         (j)     jobname=$OPTARG ;;
80         (O)     origtgz=$OPTARG ;;
81         (o)     dbo[${#dbo[*]}]=$OPTARG ;;
82         (r)     xrepo="${xrepo}|$OPTARG" ;;
83         (s)     targsuite=$OPTARG ;;
84         (T)     scmtag=$OPTARG ;;
85         (*)     usage ;;
86         }
87 done
88 shift $((OPTIND - 1))
89
90 [[ -n $1 ]] || usage
91 scmrepo=$1
92 shift
93 case $scmrepo {
94 (:ext:*|:extssh:*|:pserver:*)
95         scmtype=cvs
96         ;;
97 (svn://*|svn+ssh://*)
98         scmtype=svn
99         ;;
100 (git://*)
101         scmtype=git
102         ;;
103 (@(cvs|svn|git|bzr|hg),*)
104         scmtype=${scmrepo%%,*}
105         scmrepo=${scmrepo#*,}
106         ;;
107 (*)
108         print -u2 "Invalid SCM repository '$scmrepo'"
109         print -u2 "Valid are CVS (ext/pserver), Subversion (svn, svn+ssh), git,"
110         print -u2 "or specifying the name of the SCM (cvs, svn, git, bzr, hg)"
111         print -u2 "followed by a comma before the repository identifier."
112         usage
113         ;;
114 }
115 case $scmtype {
116 (cvs)
117         scmmodule=$1
118         i=1
119         ;;
120 (svn)
121         i=0
122         if [[ -n $scmtag ]]; then
123                 print -u2 "Subversion does not support tags or branches."
124                 usage
125         fi
126         ;;
127 (git|bzr|hg)
128         i=0
129         ;;
130 }
131 if (( $# != i )); then
132         print -u2 "Invalid syntax. The first non-option argument must be the"
133         print -u2 "SCM repository identifier. For CVS, another argument must"
134         print -u2 "be passed to specify the module. No further arguments are"
135         print -u2 "permitted."
136         usage
137 fi
138
139 if [[ $DIST != @(sarge|etch|lenny|squeeze|wheezy|sid|dapper|hardy|karmic|lucid|maverick|natty|oneiric|precise)?(-backports?(-sloppy))?(/i386) ]]; then
140         print -u2 "Missing -b option, which is mandatory, or invalid value '$DIST'"
141         usage
142 fi
143 if [[ -z $targdist ]]; then
144         print -u2 "Missing -d option, which is mandatory"
145         usage
146 fi
147 if [[ -z $jobname ]]; then
148         print -u2 "Missing -j option, which is mandatory"
149         usage
150 fi
151 if [[ -z $targsuite ]]; then
152         print -u2 "Missing -s option, which is mandatory"
153         usage
154 fi
155
156 if [[ $DIST = */i386 && $(uname -m) != x86_64 ]]; then
157         print -ru2 "The -b option indicates using an i386 chroot on an amd64"
158         print -ru2 "system, but this is a '$(uname -m)' system."
159         exit 1
160 fi
161
162 if ! T=$(mktemp -d "$wd/vcs2deb.XXXXXXXXXX"); then
163         print -u2 Cannot create temporary directory.
164         exit 255
165 fi
166
167 cd "$T"
168
169 haspipe=0
170 hascmd2=0
171 case $scmtype {
172 (cvs)
173         export CVS_RSH=ssh
174         [[ -n $scmtag ]] || scmtag=HEAD
175         set -A cmd -- cvs -qz3 -d "$scmrepo" export -r"$scmtag" -dwc \
176             "$scmmodule"
177         ;;
178 (svn)
179         set -A cmd -- svn export "$scmrepo" wc
180         ;;
181 (git)
182         set -A cmd -- git archive --format=tar --prefix=wc/ \
183             --remote="$scmrepo" "${scmtag:-master}"
184         set -A cmdpipe -- tar -xvf -
185         # I hate git.
186         haspipe=1
187         # I hate GNU.
188         set -A cmd2 -- rm -f wc/pax_global_header
189         hascmd2=1
190         ;;
191 (bzr)
192         set -A cmd -- bzr export --format=dir
193         if [[ -n $scmtag ]]; then
194                 cmd[${#cmd[*]}]=-r
195                 cmd[${#cmd[*]}]=$scmtag
196         fi
197         cmd[${#cmd[*]}]=wc
198         cmd[${#cmd[*]}]=$scmrepo
199         ;;
200 (hg)
201         # Oh, now this is just too funny. NOT.
202         set -A cmd -- hg clone
203         if [[ -n $scmtag ]]; then
204                 cmd[${#cmd[*]}]=-r
205                 cmd[${#cmd[*]}]=$scmtag
206         fi
207         cmd[${#cmd[*]}]=wc
208         cmd[${#cmd[*]}]=$scmrepo
209         set -A cmd2 -- rm -rf wc/.hg
210         hascmd2=1
211         ;;
212 }
213
214 print -n +
215 for arg in "${cmd[@]}"; do
216         print -nr -- " '${arg//\'/\'\\\'\'}'"
217 done
218 if (( haspipe )); then
219         print -n " |"
220         for arg in "${cmdpipe[@]}"; do
221                 print -nr -- " '${arg//\'/\'\\\'\'}'"
222         done
223         print
224         "${cmd[@]}" | "${cmdpipe[@]}"
225 else
226         print
227         "${cmd[@]}"
228 fi
229 if (( hascmd2 )); then
230         print -n +
231         for arg in "${cmd2[@]}"; do
232                 print -nr -- " '${arg//\'/\'\\\'\'}'"
233         done
234         print
235         "${cmd2[@]}"
236 fi
237 # instead of an errorlevel check…
238 if [[ ! -d wc/debian/. ]]; then
239         print -u2 Checkout failed.
240         cd "$wd"
241         rm -rf "$T"
242         exit 1
243 fi
244
245 if [[ -n $origtgz ]]; then
246         if [[ $origtgz = /* ]]; then
247                 cp "$origtgz" .
248         else
249                 wget -qO "${origtgz##*/}" "$origtgz"
250         fi
251         origtgz=${origtgz##*/}
252         if [[ ! -s $origtgz ]]; then
253                 print -u2 Download of .orig.tar.gz failed.
254                 cd "$wd"
255                 rm -rf "$T"
256                 exit 1
257         fi
258 fi
259
260 cd wc
261
262 rmc=0
263 while :; do
264         dh_testdir >/dev/null 2>&1 && break
265         if [[ -s debian/control.in && -s debian/rules && \
266             -x debian/rules && ! -e debian/control ]]; then
267                 rmc=1
268                 debian/rules debian/control
269         fi
270         dh_testdir >/dev/null 2>&1 && break
271         ls -l
272         ls -l debian/
273         print -u2 Checkout is not a Debian source package.
274         cd "$wd"
275         rm -rf "$T"
276         exit 1
277 done
278 pkgstem=$(dpkg-parsechangelog -n1 | sed -n '/^Source: /s///p')
279 version=$(dpkg-parsechangelog -n1 | sed -n '/^Version: /s///p')
280 if [[ -z $origtgz && $version = *-* ]]; then
281         # Policy v3.9.2.0 §5.6.12
282         print -u2 "Debian native packages MUST NOT contain a dash in their"
283         print -u2 "version number ($version)."
284         cd "$wd"
285         rm -rf "$T"
286         exit 1
287 fi
288 if (( snap )); then
289         updir=$(cd ..; pwd)
290         dist=$(dpkg-parsechangelog -n1 | sed -n '/^Distribution: /s///p')
291         ssuf=snapshot.$stime_vsn
292         if [[ $dist = UNRELEASED || $dist = x* ]]; then
293                 # we’re at “current” already, reduce
294                 version=$version'~'$ssuf
295         else
296                 # we’re at an uploaded version, raise
297                 version=$version'+'$ssuf
298         fi
299         print "$pkgstem ($version) UNRELEASED; urgency=low\n\n  *" \
300             "Automatically built snapshot (not backport) package.\n\n --" \
301             "$DEBEMAIL  $stime_rfc\n" >debian/changelog~
302         cat debian/changelog >>debian/changelog~
303         mv -f debian/changelog~ debian/changelog
304         if (( rmc )); then
305                 rm -f debian/control
306                 debian/rules debian/control
307         fi
308 fi
309 upstreamversion=${version%%-*([!-])}
310 upstreamversion=${upstreamversion#+([0-9]):}
311
312 cd ..
313
314 [[ -n $origtgz ]] && \
315     if [[ $origtgz != ${pkgstem}_$upstreamversion.orig.tar.@(gz|bz2|lzma|xz) ]]; then
316         print -u2 "Invalid name: $origtgz"
317         print -u2 "Expecting: ${pkgstem}_$upstreamversion.orig.tar.*"
318         cd "$wd"
319         rm -rf "$T"
320         exit 1
321 fi
322
323 newname=$pkgstem-$upstreamversion
324 mv wc "$newname"
325 cd "$newname"
326 dpkg-buildpackage -d -rfakeroot -S -us -uc
327 rv=$?
328 cd ..
329 if (( rv )) || [[ ! -s ${pkgstem}_${version}.dsc || \
330     ! -s ${pkgstem}_${version}_source.changes ]]; then
331         ls -l
332         print -u2 "Error $rv creating the .dsc"
333         cd "$wd"
334         rm -rf "$T"
335         exit 1
336 fi
337 rm -f ${pkgstem}_${version}_source.changes
338
339 # * kuhbauer [-r {r*}] {b} *.dsc [{o*}]
340 set -A cmd -- sudo /usr/local/bin/kuhbauer
341 (( snap )) && cmd[${#cmd[*]}]=-S
342 if [[ -n $xrepo ]]; then
343         cmd[${#cmd[*]}]=-r
344         cmd[${#cmd[*]}]=${xrepo#'|'}
345 fi
346 cmd[${#cmd[*]}]=$DIST
347 cmd[${#cmd[*]}]=${pkgstem}_${version}.dsc
348 print -n +
349 for arg in "${cmd[@]}" "${dbo[@]}"; do
350         print -nr -- " '${arg//\'/\'\\\'\'}'"
351 done
352 print
353 "${cmd[@]}" "${dbo[@]}"
354 rv=$?
355 cp *.holzscheit "$wd/"
356 found=
357 for f in ${pkgstem}_${version}_*.changes; do
358         [[ -s $f ]] && found=$f
359         break
360 done
361 if (( rv )) || [[ -z $found ]]; then
362         ls -l
363         print -u2 "Error $rv during build"
364         cd "$wd"
365         rm -rf "$T"
366         exit 1
367 fi
368
369 if (( dodput )); then
370         /opt/mvn-debs/mvndput.sh "$jobname" "$targdist" "$targsuite" "$found"
371         rv=$?
372         if (( rv )); then
373                 print -u2 "Error $rv during repository upload"
374                 cd "$wd"
375                 rm -rf "$T"
376                 exit 1
377         fi
378 fi
379
380 cat >tmpcf <<-EOF
381         [tmpdp]
382         method = local
383         allow_unsigned_uploads = 1
384         incoming = $wd
385 EOF
386 rm -f *.upload
387 dput -c tmpcf tmpdp $found
388 rv=$?
389 if (( rv )); then
390         print -u2 "Error during result move, NOT cleaning up: $T"
391         exit 1
392 fi
393 print -u2 Cleaning up...
394 cd "$wd"
395 rm -rf "$T"
396 exit 0