-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprepare-src.sh
More file actions
executable file
·378 lines (311 loc) · 8.87 KB
/
prepare-src.sh
File metadata and controls
executable file
·378 lines (311 loc) · 8.87 KB
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
377
378
#!/bin/bash
ROOT=`pwd`
PKG=`basename "$ROOT"`
UPSTREAM=upstream
MASTER=master
PACKAGING=packaging
SCRIPTS=`(cd ${BASH_SOURCE%/*}; pwd )`
#
# a block of functions
# look for "main" to skip it
#
function die() {
echo "ERROR: $1" >&2
exit 1
}
function warn() {
echo "WARNING: $1" >&2
}
# ignore stdout of pushd/popd
function pushd()
{
builtin pushd "$@" >/dev/null || die "pushd failed: $@"
}
function popd()
{
builtin popd "$@" >/dev/null || die "popd failed: $@"
}
#
# main
#
#
# Check we're being run from the project root
#
if ! [[ -d "$ROOT/.git" ]]; then
die "Run this script from the project root"
fi
#TODO: check we're in the packaging branch?
#TODO: check that upstream/master/packaging branches exist
#TODO: check master has been merged into the packaging branch
#
# Check options
#
if [[ "$1" == "-h" ]] || [[ "$1" == "--help" ]] ; then
echo "Usage: $0 [force]" >&2
exit 1
fi
FORCE=false
[[ "$1" == "force" ]] && FORCE=true
# check for uncommitted changes
if git status --porcelain -- "$ROOT"|grep -q M; then
warn "Uncommited changes:"
git status --short >&2
if git status --porcelain -- "$ROOT" |grep -q M && ! $FORCE; then
die "Please commit your changes to git first. To override, run: $0 force"
fi
fi
# get the commit the user wants to make a package from
# and verify that we're on a tagged commit
HASH=`git log -1 --pretty="format:%H"`
TAG=`git tag --points-at HEAD`
if [[ -z $TAG ]]; then
warn "Not on a tagged commit."
TAG=`git describe --abbrev=0`
[[ -z $TAG ]] && exit 1
if ! $FORCE; then
die "To use the most recent tag ($TAG) as the version string, run: $0 force"
fi
fi
#TODO: check VERSION format
VERSION=$TAG
UPSTREAM_VERSION=${VERSION%.*}
RELEASE_VERSION=${VERSION##*.}
echo "Using $VERSION as version string."
#
# Create the directory of package sources
# If OUTPUT_DIR is not set, it will be created under the sources directory
#
D=`mktemp -d`
SRCDIR="$D/$PKG"
PATCHES_MASTER=$D/patches-master
OUTPUT_DIR=${OUTPUT_DIR:-${SRCDIR}/output}
mkdir "$SRCDIR" || die "Cannot create a temporary directory $SRCDIR"
mkdir "$PATCHES_MASTER" || die "Cannot create a temporary directory $PATCHES_MASTER"
mkdir -p "$OUTPUT_DIR"
# create upstream tarball
git archive --prefix=${PKG}-${UPSTREAM_VERSION}/ $UPSTREAM | gzip -n > "${OUTPUT_DIR}/${PKG}_${UPSTREAM_VERSION}.orig.tar.gz"
# create patch series between upstream and master
#git format-patch -o $PATCHES_MASTER $UPSTREAM..$MASTER
git diff $UPSTREAM..$MASTER >$PATCHES_MASTER/0000-upstream-master.patch
# copy distro-specific files
git archive $PACKAGING -- rpm deb | tar -x -C $SRCDIR
# get distro-specific patches if needed
if [ -d patches-distro -a -d series-distro ] ; then
git archive $PACKAGING -- patches-distro series-distro 2>/dev/null | tar -x -C $SRCDIR
fi
#
# Generate packages
#
################### rpm #############
function rpm_generate_changes_file() {
# TODO: we need to ensure proper ordering of the git log;
# this condenses each commit to a single line, sorts using sort,
# and then splits the lines again. This is probably wrong! FIXME!
# we also want to properly describe merge commits!
git log --date-order --first-parent --pretty=format:\
'%at;-------------------------------------------------------------------|n|'\
'%ad - %ce|n||n|- %s|n| %h|n|'\
start..$MASTER | sort -nr -t \; -k 1 | sed 's/^[0-9]*;//;s/|n|/\n/g'
}
function gen_rpm() {
SRC=$1
OUTPUT="$2"
DISTNAME=$3
pushd $SRC
# generate spec.patch_declare and spec.patch_apply temporary files
n=0
for i in patches/*; do
[[ -e $i ]] || continue
f=${i##*/}
n=$((n+1))
echo "Patch$n: $f" >> spec.patch_declare
echo "%patch$n -p1" >> spec.patch_apply
[[ -e "$OUTPUT/$f" ]] || cp $i "$OUTPUT"
done
# generate the spec file, filling in marked fields from the template
sed -e 's/__UPSTREAM_VERSION__/'$UPSTREAM_VERSION'/
s/__RELEASE_VERSION__/'$RELEASE_VERSION'/
/__PATCHES_DECLARE__/ {
r spec.patch_declare
d
};
/__PATCHES_APPLY__/ {
r spec.patch_apply
d
}' $PKG.spec >"$OUTPUT/${PKG}${DISTNAME:+-}${DISTNAME}.spec"
rm spec.patch_declare spec.patch_apply
{
# needs to be run in the git directory
pushd $ROOT
rpm_generate_changes_file
popd
} >"$OUTPUT/${PKG}${DISTNAME:+-}${DISTNAME}.changes"
popd
}
################### deb #############
function deb_generate_changes_file() {
# TODO: we need to ensure proper ordering of the git log;
# this condenses each commit to a single line, sorts using sort,
# and then splits the lines again. This is probably wrong! FIXME!
# we also want to properly describe merge commits!
git log --date-order --first-parent --pretty=format:\
"%at;"\
"$PKG ($DEBIAN_VERSION) unstable; urgency=low|n||n|"\
" * %s (%h)|n||n|"\
" -- %cn <%ce> %aD"\
start..$MASTER | sort -nr -t \; -k 1 | sed 's/^[0-9]*;//;s/|n|/\n/g'
}
# reimplement associative arrays to support bash < 4.0
function field_var_name() {
local varname=${1//-/_}
echo ${varname^^}
}
# parses the control file and saves the information in bash variables
function parse_control_file() {
PREFIX=FIELD
PKG_NUM=0
PKG_MAX=$PKG_NUM
mode="general"
ALL_FIELDS=""
IFS_ORIG="$IFS"
while read field value ; do
[ -z "$field" ] && continue
field=${field/:/}
fieldvar=$(field_var_name $field)
if [ "$mode" = "package" -a "$field" = "Description" ] ; then
IN_EOF=1
eval "${PREFIX}_${fieldvar}=\"\$value\""
while IFS= read -r line ; do
if [ "${line:0:1}" != " " ] ; then
IN_EOF=0
break
fi
eval "${PREFIX}_${fieldvar}=\"\${${PREFIX}_${fieldvar}}
\${line}\""
done
ALL_FIELDS="${ALL_FIELDS} ${PREFIX}_${fieldvar}"
if [ "${IN_EOF}" = 1 ] ; then
break
else
read field value <<<"$line"
[ -z "$field" ] && continue
field=${field/:/}
fieldvar=$(field_var_name $field)
fi
fi
if [ "$field" = "Package" ] ; then
PKG_NUM=$(( PKG_NUM + 1 ))
PKG_MAX=$PKG_NUM
PREFIX="PACKAGE_${PKG_NUM}"
fieldvar="NAME"
mode="package"
fi
eval "${PREFIX}_${fieldvar}=\"${value}\""
ALL_FIELDS="${ALL_FIELDS} ${PREFIX}_${fieldvar}"
done < control
}
# fields we want to be put in the dsc, stored in bsah variables by the above
# parse_... functions
declare -a DSC_OUTPUT_FIELDS=(
"Source"
"Binary"
"Maintainer"
"Architecture"
"Build-Depends"
"Files"
"Vcs-Git"
)
function output_dsc() {
echo "Format: $(< source/format)"
echo "Architecture: any all"
echo "Version: $VERSION_DISTNAME"
for field in "${DSC_OUTPUT_FIELDS[@]}" ; do
fieldvar=$(field_var_name $field)
eval "f=\${FIELD_${fieldvar}}"
[ -n "$f" ] && eval echo \"${field}: \${FIELD_${fieldvar}}\"
done
echo -n "Binary: "
for ((i=1; i<=$PKG_MAX; ++i)); do
eval "f=\${PACKAGE_${i}_NAME}"
echo -n $f
if [[ $i == $PKG_MAX ]]; then
echo ""
else
echo -n ", "
fi
done
echo "Package-List:"
for ((i=1; i<=$PKG_MAX; ++i)); do
eval "f=\${PACKAGE_${i}_NAME}"
eval "a=\${PACKAGE_${i}_ARCHITECTURE}"
echo " $f deb misc optional arch=$a"
done
pushd "$OUTPUT"
echo "Files:" >> $DSC
for i in ${PKG}_${UPSTREAM_VERSION}.orig.tar.gz ${PKG}_${VERSION_DISTNAME}.debian.tar.gz; do
MD5=`md5sum $i`
MD5=${MD5%% *}
SIZE=`stat -c%s $i`
echo " $MD5 $SIZE $i"
done >> $DSC
popd
}
function deb_generate_dsc() {
parse_control_file
output_dsc
}
function gen_deb() {
SRC=$1
OUTPUT="$2"
DISTNAME=$3
# distribution-version specific files have the distribution version
# appended to the package version using +
DISTNAME_ALPHANUM=${DISTNAME//[._-]/}
DEBIAN_VERSION=${UPSTREAM_VERSION}-${RELEASE_VERSION}
VERSION_DISTNAME=${DEBIAN_VERSION}${DISTNAME_ALPHANUM:++}${DISTNAME_ALPHANUM}
pushd $SRC
echo "9" > compat
mkdir -p source
echo "3.0 (quilt)" > source/format
pushd patches
ls -1 |grep -v "^series$" > series
popd
{
pushd $ROOT
# needs to be run in the git directory
deb_generate_changes_file
popd
} > changelog
tar -czf "$OUTPUT/${PKG}_${VERSION_DISTNAME}.debian.tar.gz" --transform='s%^\.%debian%' .
DSC="$OUTPUT/${PKG}${DISTNAME:+-}${DISTNAME}.dsc"
deb_generate_dsc > $DSC
popd
}
pushd $SRCDIR
# the packaging branch of each package needs to have a directory for
# each supported package format
DISTRO_TEMPLATES="rpm deb"
for template in $DISTRO_TEMPLATES ; do
# generic package source for this package format
cp -a $PATCHES_MASTER ${template}/patches
gen_$template $template "${OUTPUT_DIR}" ""
[[ -d series-distro/${template} ]] || continue
# distribution-version specific patches
for dist_full in series-distro/${template}/* ; do
[[ -e "$dist_full" ]] || continue
dist=${dist_full##*/}
# copy the generic package source generated above and apply
# the distribution-version specific patches
cp -a ${template} ${dist}
pushd ${dist}
while read patch; do
[[ -f ../patches-distro/$patch ]] || continue
patch -p1 < ../patches-distro/$patch
done <../series-distro/$template/${dist}
popd
#generate the distribution-version specific package source
gen_$template ${dist} "${OUTPUT_DIR}" ${dist}
done
done
popd #SRCDIR
echo -e "Sources of the package are stored at\n $OUTPUT_DIR" >&2