-
Notifications
You must be signed in to change notification settings - Fork 13
/
build-package
executable file
·376 lines (335 loc) · 12.9 KB
/
build-package
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
#!/bin/bash
# https://gist.github.com/smoser/6391b854e6a80475aac473bba4ef0310
VERBOSITY=0
ASSUME_YES=false
OFFLINE=false
TEMP_D=""
START_D="$PWD"
FORMATS=".tar.gz .tar.xz .tar.bz2"
MSG_BORDER_LINE="========================================"
cleanup(){
[ ! -d "$TEMP_D" ] || rm -Rf "$TEMP_D";
git worktree prune
}
error() { echo "$@" 1>&2; }
fail() { [ $# -eq 0 ] || error "$@"; exit 1; }
Usage() {
cat <<EOF
Usage: ${0##*/} [ options ] <<ARGUMENTS>>
build a package, put output in ../out
By default debuild is invoked to build a source package with:
-d -S -nc -v<version>
-v<version> is deteremined heuristically for dpkg-genchanges(1).
If you want to build with other flags, add debuild flags on
the cmdline. For example, to build with -sa:
${0##*/} -- -d -S -sa -nc
options:
--ref R what to build from [default to current branch].
--offline perform no upstream orig.tar.gz downloads
-o | --output D put output in D. [default ../out]
--skip-genchanges-version do not attempt to find the
correct '-v<version>' flag.
EOF
}
bad_Usage() { Usage 1>&2; [ $# -eq 0 ] || error "$@"; return 1; }
prompt_yes_no() {
[ "${ASSUME_YES}" = "true" ] && {
error "assuming yes to prompt:" "$@"
return 0
}
local resp
echo -n "$@" "? (y/n) "
read resp || fail "failed to read user input"
if [ "$resp" = "y" ]; then
return 0
fi
return 1
}
debug() {
local level=${1}; shift;
[ "${level}" -gt "${VERBOSITY}" ] && return
error "${@}"
}
find_orig() {
local src="$1" ver="$2" dir="" n="" ext="" nver=""
shift 2
nver=$(no_epoch "$ver")
for dir in "$@"; do
for ext in $FORMATS; do
n="${src}_${nver}.orig${ext}"
[ -f "$dir/$n" ] && _RET="$dir/$n" &&
echo "$dir/$n" && return 0
done
done
return 1
}
# no_epoch(version): drop a leading epoch from a version
# no_epoch(1:15.0+dfsg1-1ubuntu2.1) = 15.0+dfsg1-1ubuntu2.1
# no_epoch("1.0") = "1.0"
no_epoch() {
case "$1" in
[0-9]:*|[0-9][0-9]:*) echo "${1#*:}";;
*) echo "$1"
esac
}
get_genchanges_version() {
local pkg_name="$1" suite="$2" collapsed_args="$3" devel=""
# if args already had a '-v' in it, then do nothing.
_RET=""
[ "${collapsed_args#* -v}" = "${collapsed_args}" ] ||
{ debug 1 "-v already present in args"; return 0; }
devel=$(distro-info --devel)
[ "$suite" = "$devel" ] &&
{ debug 1 "-v not relevant for devel suite ($suite)"; return 0; }
[ "${suite^^}" = "UNRELEASED" ] &&
{ debug 1 "-v not relevant for unreleased"; return 0; }
case "$suite" in
unstable|sid|testing)
debug 1 "no genchanges support for debian ($suite): skipping."
return 0;;
esac
if ! command -v rmadison >/dev/null 2>&1; then
debug 1 "rmadison not available."
return 0
fi
local ga_suite="" ga_version="" updates_suite="" updates_version=""
case "$suite" in
*-proposed|*-updates)
updates_suite=${suite%-*}-updates
ga_suite=${suite%-*};;
*)
updates_suite="$suite-updates";
ga_suite=${suite};;
esac
updates_version=$(
rmadison --url=ubuntu --suite="${updates_suite}" $pkg_name |
awk '-F|' '$4 ~ /source/ {gsub(/ /, ""); print $2}')
ga_version=$(
rmadison --url=ubuntu --suite="${ga_suite}" $pkg_name |
awk '-F|' '$4 ~ /source/ {gsub(/ /, ""); print $2}')
debug 1 "$pkg_name versions updates=${updates_version} ga=${ga_version}"
if [ -n "$updates_version" ]; then
_RET="-v${updates_version}"
elif [ -n "$ga_version" ]; then
_RET="-v${ga_version}"
else
error "Failed to get version info for $pkg_name in" \
"$updates_suite or $ga_suite."
return 1
fi
}
get_orig_tarball() {
local changelog_file="$1" dir="${2:-..}" offset="$3" verbose="$4"
local tarball_fp
if [ "$OFFLINE" = "true" ]; then
error "Skipping download of orig.tar.gz due to --offline param"
return 0
fi
if ! get-orig-tarball "${changelog_file}" "${dir}" ${offset:+--offset=${offset}} $verbose; then
error "failed to get orig tarball for $pkg_name at $pkg_ver"
return 1
fi
tarball_fp=$(find_orig "${pkg_name}" "${upstream_ver}" "${dir}")
if [ -z "${tarball_fp}" ]; then
error "did not get a tarball at $upstream_ver with get-orig-tarball"
return 1
elif [ ! -f "$tarball_fp" ]; then
error "orig tarball not a file: $tarball_fp"
return 1
fi
error ${MSG_BORDER_LINE}
error " Using orig tarball in $tarball_fp"
sha256sum "${orig_tarball_fp}"
error ${MSG_BORDER_LINE}
return 0
}
main() {
local short_opts="ho:vy"
local long_opts="help,offline,output:,offset:,ref:,skip-genchanges-version:,yes,verbose"
local getopt_out=""
getopt_out=$(getopt --name "${0##*/}" \
--options "${short_opts}" --long "${long_opts}" -- "$@") &&
eval set -- "${getopt_out}" ||
{ bad_Usage; return; }
local cur="" next="" out_d="../out" ref="" offset="0"
local do_genchanges_v=true
while [ $# -ne 0 ]; do
cur="$1"; next="$2";
case "$cur" in
-h|--help) Usage ; exit 0;;
--offset) offset=$next; shift;;
-o|--output) out_d=$next; shift;;
--offline) OFFLINE=true;;
--skip-genchanges-version) do_genchanges_v=false;;
-v|--verbose) VERBOSITY=$((${VERBOSITY}+1));;
-y|--yes) ASSUME_YES=true;;
--ref) ref=$next; shift;;
--) shift; break;;
esac
shift;
done
if [ -z "$ref" ]; then
cur_branch=$(git rev-parse --abbrev-ref HEAD) ||
fail "failed to get current branch"
ref="$cur_branch"
fi
TEMP_D=$(mktemp -d "${TMPDIR:-/tmp}/${0##*/}.XXXXXX") ||
fail "failed to make tempdir"
trap cleanup EXIT
local wtd="${TEMP_D}/wtd" pkg_ver pkg_name upstream_ver upstream_hash
local orig_tarball orig_tarball_fp
git worktree add --force "$wtd" "$ref" ||
fail "failed worktree add $wtd $ref"
pkg_ver=$( cd "$wtd" && dpkg-parsechangelog --show-field Version) ||
fail "failed reading package version"
pkg_name=$(cd "$wtd" && dpkg-parsechangelog --show-field Source) ||
fail "failed to read Source from changelog"
suite=$(cd "$wtd" && dpkg-parsechangelog --show-field Distribution) ||
fail "failed to read Distribution from changelog"
if [ "${suite^^}" = "UNRELEASED" ]; then
prompt_yes_no "Found ${suite} in debian/changelog." \
"Do you really want to build-package" ||
fail "Set debian/changelog '${suite}' to a public release name"
fi
upstream_ver=${pkg_ver%-*}
# turn 0.7.7-10-gbc2c326-0ubuntu1 into 'bc2c326'
upstream_hash=${upstream_ver##*-g}
# turn 23.3~3gbc2c326-0ubuntu1 into 'bc2c326'
upstream_hash=${upstream_ver##*~[0-9]g}
local native=false
local dsf="debian/source/format"
if [ -f "$wtd/$dsf" ]; then
local fmt="" native3="3.0 (native)"
read fmt < "$wtd/$dsf"
case "$fmt" in
"$native3"|*native*)
debug 0 "package ${pkg_name} is native per $dsf"
native=true;;
esac
fi
if [ "$native" = "false" ]; then
case "${pkg_ver}" in
*-*) :;;
*) debug 0 "package ${pkg_name} is native per version ${pkg_ver}"
native=true;;
esac
fi
if [ "$native" = "true" ]; then
# rename this dir from 'wtd' to <pkg>-<ver> as the top level dir
# gets used in the tarball.
mv "$wtd" "${TEMP_D}/$pkg_name-$pkg_ver"
wtd="${TEMP_D}/$pkg_name-$pkg_ver"
else
error "pkg_name=$pkg_name pkg_ver=$pkg_ver upstream_ver=$upstream_ver suite=$suite"
local orig_tarball_fp="" orig_tarball_fp=""
orig_tarball_fp=$(find_orig "${pkg_name}" "${upstream_ver}" .. ../dl)
if [ -n "$orig_tarball_fp" ]; then
tarball_dir=$(dirname "$orig_tarball_fp")
if [ "${tarball_dir}" = "../dl" ]; then
# Download and compare this tarball with latest upstream
if ! get_orig_tarball debian/changelog ../dl "${offset}"; then
prompt_yes_no "No upstream tarball for ${upstream_ver}, " \
"should we create a new orig.tar.gz from the local " \
"branch" ||
fail "No upstream tarball found for ${upstream_ver}"
fi
fi
if ! prompt_yes_no "Proceed with build-package"; then
tar_dir=$(dirname "${orig_tarball_fp}")
error "Cancelled build-package."
error "To replace orig.tar.gz with latest upstream:"
error " get-orig-tarball debian/changelog ${tar_dir} -v"
if [ -x tools/make-tarball ]; then
error "To create orig.tar.gz from local branch:"
error " ./tools/make-tarball ../dl/${pkg_name}_$upstream_ver.orig.tar.gz"
fi
exit 0
fi
elif [ -x tools/make-tarball ]; then
if [ ! -d "../dl" ]; then
mkdir ../dl ||
fail "failed to create ../dl from $PWD"
error "created ../dl from $PWD for orig tarballs."
fi
orig_tarball="${pkg_name}_$(no_epoch "${upstream_ver}").orig.tar.gz"
orig_tarball_fp="../dl/$orig_tarball"
if prompt_yes_no "Check for an upstream cloud-init_${upstream_ver}.orig.tar.gz on which to base this debdiff"; then
if ! get_orig_tarball debian/changelog ../dl "${offset}"; then
error ${MSG_BORDER_LINE}
error " No cloud-init_${upstream_ver}.orig.tar.gz found"
error "Creating $orig_tarball_fp using" \
"make-tarball --output=$orig_tarball_fp $upstream_hash"
error ${MSG_BORDER_LINE}
sleep 1
./tools/make-tarball "--output=$orig_tarball_fp" "$upstream_hash" ||
fail "failed to make tarball"
fi
else
sleep 1
error ${MSG_BORDER_LINE}
echo ./tools/make-tarball "--output=$orig_tarball_fp"
./tools/make-tarball "--output=$orig_tarball_fp" ||
fail "failed to make tarball"
error ${MSG_BORDER_LINE}
fi
else
if ! get_orig_tarball "" "${offset}" -v; then
fail ""
fi
fi
local ofp_name
ofp_name=$(basename "$orig_tarball_fp")
orig_tarball_fp=$(readlink -f "$orig_tarball_fp") ||
fail "failed to get full path to $orig_tarball_fp"
ln -s "$orig_tarball_fp" "$TEMP_D/${ofp_name}"
fi
if [ "$native" != "true" ]; then
local debtar="${TEMP_D}/extra/debian.tar"
mkdir "${TEMP_D}/extra" || fail "failed mkdir ${TEMP_D}/extra"
# copy out debian dir.
tar -C "$wtd" -cf "${TEMP_D}/extra/debian.tar" debian/ ||
fail "failed to create tarball of debian."
# clean wtd completely and create empty dir.
rm -Rf "$wtd" ||
fail "failed removing $wtd"
mkdir "$wtd" ||
fail "failed creating $wtd"
# extract upstream tarball, remove it's debian dir, extract ours.
tar -C "$wtd" --strip-components=1 -xf "${orig_tarball_fp}" ||
fail "failed to extract $orig_tarball_fp in $wtd"
if [ -d "$wtd/debian" ]; then
debug 0 "Removing upstream's debian dir in favor of packaging."
rm -Rf "$wtd/debian" ||
fail "failed removing debian dir from upstream tarball."
fi
tar -C "$wtd" -xf "$debtar" ||
fail "failed extracting debian tarball in wordir"
else
rm -Rf "$wtd/.git" || fail "failed removing .git dir"
fi
# try to magically add '-v' if its not present.
local genchanges_v=""
if [ "${do_genchanges_v}" = "true" ]; then
get_genchanges_version "$pkg_name" "$suite" " $* " ||
fail "Failed to get genchanges version for $pkg_name $suite ' $* '" \
"try with --skip-genchanges-version"
genchanges_v="$_RET"
fi
if [ $# -eq 0 ]; then
set -- -d -S -nc ${genchanges_v}
elif [ -n "${genchanges_v}" ]; then
set -- "$@" ${genchanges_v}
fi
debug 0 "building with:" "$@"
( cd "$wtd" && debuild "$@" ) || fail "FAILED: debuild $*"
( for f in "$TEMP_D/"*; do echo "$f"; done )
mkdir -p "$out_d"
for f in "${TEMP_D}/"*; do
[ -f "$f" ] || continue
cp "$f" "$out_d/" && echo "wrote ${out_d}/${f##*/}" ||
fail "failed to copy $f to $out_d"
done
return 0
}
main "$@"
# vi: ts=4 expandtab