2 # 2018 by David Lamparter, placed in the Public Domain
6 FRR tarball/dsc helper, intended to run from a git checkout
9 ./tarsource.sh [-dDn] [-i GITPATH] [-o OUTDIR] [-S KEYID]
10 [-C COMMIT] [-e EXTRAVERSION] [-z gz|xz]
13 -i GITPATH path to git working tree or bare repository.
14 - default: parent directory containing this script
15 -o OUTDIR path to place the generated output files in.
16 - default: current directory
17 -C COMMIT build tarball for specified git commit
18 - default: current HEAD
19 -e EXTRAVERSION override automatic package extraversion
20 - default "-YYYYMMDD-NN-gGGGGGGGGGGGG", but the script
21 autodetects if a release tag is checked out
22 -z gz|xz compression format to use
24 -S KEYID sign the output with gpg key
25 -d use dirty git tree with local changes
26 -D generate Debian .dsc and .debian.tar.xz too
27 (note: output files are moved to parent directory)
28 -l remove Debian auto-build changelog entry
29 (always done for releases)
30 -V write version information to config.version and exit
31 -n allow executing from non-git source (NOT RECOMMENDED)
32 -h show this help text
34 Note(1) that this script tries very hard to generate a deterministic,
35 reproducible tarball by eliminating timestamps and similar things. However,
36 since the tarball includes autoconf/automake files, the versions of these
37 tools need to be _exactly_ identical to get the same tarball.
39 Note(2) the debian ".orig" tarball is always identical to the "plain" tarball
40 generated without the -D option.
42 Note(3) if you want the tool to identify github PRs, you need to edit your
43 .git/config to fetch PRs from github like this:
46 url = git@github.com:frrouting/frr.git
47 fetch = +refs/heads/*:refs/remotes/origin/*
48 ADD: fetch = +refs/pull/*/head:refs/remotes/origin/pull/*
54 options
=`getopt -o 'hi:o:C:S:e:z:DdnlV' -l help -- "$@"`
63 while test $# -gt 0; do
64 arg
="$1"; shift; optarg
=$1
66 -h|
--help) help; exit 0;;
70 -i) eval src
=$optarg; shift;;
71 -C) eval commit
=$optarg; shift;;
72 -o) eval outdir
=$optarg; shift;;
73 -e) eval extraver
=$optarg; extraset
=true
; shift;;
74 -z) eval zip=$optarg; shift;;
75 -S) eval keyid
=$optarg; shift;;
76 -l) adjchangelog
=true
;;
77 -V) writeversion
=true
;;
79 *) echo something went wrong with getopt
>&2
86 outdir
="${outdir:-$cwd}"
88 if test -e "$outdir" -a \
! -d "$outdir"; then
89 echo "output $outdir must be a directory" >&2
91 elif test \
! -d "$outdir"; then
100 src
="${src:-$selfdir}"
102 if $writeversion; then
104 echo "The -V option cannot be used without a git tree" >&2
111 gz
) ziptarget
=dist-gzip
; ziptool
="gzip -n -9"; unzip="gzip -k -c";;
112 xz
) ziptarget
=dist-xz
; ziptool
="xz -z -e"; unzip="xz -d -k -c";;
113 *) echo "unknown compression format $zip" >&2
117 # always overwrite file ownership in tars
118 taropt
="--owner=root --group=root"
123 test -n "$tmpdir" -a -d "$tmpdir" && rm -rf "$tmpdir"
125 if test "$rv" -ne 0; then
126 echo -e "\n\033[31;1mfailed\n" >&2
127 if test "$dirty" = true
; then
128 echo please try running the
script without the
-d option.
>&2
134 tmpdir
="`mktemp -d -t frrtar.XXXXXX`"
136 if test -e "$src/.git"; then
137 commit
="`git -C \"$src\" rev-parse \"${commit:-HEAD}\"`"
141 echo -e "\033[31;1mgit: using dirty worktree in $src\033[m" >&2
143 echo -e "\033[33;1mgit: preparing a clean clone of $src\033[m"
144 branch
="${tmpdir##*/}"
147 git
-C "$src" branch
"$branch" "$commit"
148 git clone
--single-branch -s -b "$branch" "$src" source
149 git
-C "$src" branch
-D "$branch"
153 # if we're creating a tarball from git, force the timestamps inside
154 # the tar to match the commit date - this makes the tarball itself
156 gitts
="`TZ=UTC git show -s --format=%cd --date=local $commit`"
157 gitts
="`TZ=UTC date -d "$gitts" '+%Y-%m-%dT%H:%M:%SZ'`"
158 taropt
="--mtime=$gitts $taropt"
160 # check if we're on a release tag
161 gittag
="`git -C \"$src\" describe --tags --match 'frr-*' --first-parent --long $commit`"
162 gittag
="${gittag%-g*}"
163 gittag
="${gittag%-*}"
165 # if there have been changes to packaging or tests, it's still the
167 changes
="`git diff --name-only "$gittag" $commit | \
168 egrep -v '\.git|^m4/|^config|^README|^alpine/|^debian/|^pkgsrc/|^ports/|^redhat/|^snapcraft/|^solaris/|^tests/|^tools/|^gdb/|^docker/|^\.' | \
170 if test "$changes" -eq 0; then
172 echo "detected release build for tag $gittag" >&2
173 $extraset || extraver
=""
174 elif ! $adjchangelog; then
175 gitdate
="`TZ=UTC date -d "$gitts" '+%Y%m%d'`"
176 gitrev
="`git rev-parse --short $commit`"
177 dayseq
="`git rev-list --since \"${gitts%T*} 00:00:00 +0000\" $commit | wc -l`"
178 dayseq
="`printf '%02d' $(( $dayseq - 1 ))`"
180 $extraset || extraver
="-$gitdate-$dayseq-g$gitrev"
182 git
-C "$src" remote
-v |
grep fetch |
sed -e 's% (fetch)$%%' \
183 |
egrep -i '\b(git@github\.com:frrouting/frr\.git|https://github\.com/FRRouting/frr\.git)$' \
184 |
while read remote
; do
185 remote
="${remote%% *}"
187 git
-C "$src" var
-l |
egrep "^remote.$remote.fetch=" \
188 |
while read fetch
; do
192 if test "$from" = "+refs/pull/*/head"; then
193 name
="`git -C \"$src\" name-rev --name-only --refs \"$to\" $commit`"
194 test "$name" = "undefined" && continue
195 realname
="${name%~*}"
196 realname
="${realname%%^*}"
197 realname
="${realname%%@*}"
198 if test "$realname" = "$name"; then
199 echo "${name##*/}" > "$tmpdir/.gitpr"
204 test -n "$gitpr" && break
206 test $extraset = false
-a -f "$tmpdir/.gitpr" && extraver
="-PR`cat \"$tmpdir/.gitpr\"`$extraver"
209 debsrc
="git ls-files debian/"
212 echo -e "\033[31;1mWARNING: this script should be executed from a git tree\033[m" >&2
214 echo -e "\033[31;1mERROR: this script should be executed from a git tree\033[m" >&2
220 if $writeversion; then
221 pkgver
="`egrep ^AC_INIT configure.ac`"
222 pkgver
="${pkgver#*,}"
223 pkgver
="${pkgver%,*}"
224 pkgver
="`echo $pkgver`" # strip whitespace
228 echo -e "\033[32;1mwriting version ID \033[36;1mfrr-$pkgver$extraver\033[m"
230 cat > config.version
<<EOF
231 # config.version override by tarsource.sh
232 EXTRAVERSION="$extraver"
233 DIST_PACKAGE_VERSION="$pkgver$extraver"
237 sed -e "s%@VERSION@%$pkgver$extraver%" \
238 < changelog-auto.
in \
243 echo -e "\033[33;1mpreparing source tree\033[m"
245 # config.version will also overwrite gitts and taropt when tarsource.sh
246 # was used to write the config.version file before - but configure will
247 # overwrite config.version down below!
248 if test -f config.version
; then
249 # never executed for clean git build
252 $extraset || extraver
="$EXTRAVERSION"
255 if test \
! -f configure
; then
256 # always executed for clean git build
259 if test "$EXTRAVERSION" != "$extraver" -o \
! -f config.status
; then
260 # always executed for clean git build
261 # options don't matter really - we just want to make a dist tarball
262 .
/configure
--with-pkg-extra-version=$extraver
266 PACKAGE_VERSION
="$DIST_PACKAGE_VERSION"
268 echo -e "\033[33;1mpacking up \033[36;1mfrr-$PACKAGE_VERSION\033[m"
270 make GZIP_ENV
="-n9" am__tar
="tar -chof - $taropt \"\$\$tardir\"" $ziptarget
271 mv frr-
${PACKAGE_VERSION}.
tar.
$zip "$outdir" || true
272 lsfiles
="frr-${PACKAGE_VERSION}.tar.$zip"
275 mkdir
-p "$tmpdir/debian/source"
276 cat debian
/changelog
> "$tmpdir/debian/changelog"
277 if $adjchangelog; then
278 if grep -q 'autoconf changelog entry' debian
/changelog
; then
279 tail -n +9 debian
/changelog
> "$tmpdir/debian/changelog"
282 echo '3.0 (quilt)' > "$tmpdir/debian/source/format"
283 DEBVER
="`dpkg-parsechangelog -l\"$tmpdir/debian/changelog\" -SVersion`"
285 eval $debsrc |
tar -cho $taropt \
286 --exclude-vcs --exclude debian
/source
/format \
287 --exclude debian
/changelog \
288 --exclude debian
/changelog-auto \
289 --exclude debian
/changelog-auto.
in \
290 --exclude debian
/subdir.am \
291 -T - -f ..
/frr_
${DEBVER}.debian.
tar
292 # add specially prepared files from above
293 tar -uf ..
/frr_
${DEBVER}.debian.
tar $taropt -C "$tmpdir" debian
/source
/format debian
/changelog
295 test -f ..
/frr_
${DEBVER}.debian.
tar.
$zip && rm -f ..
/frr_
${DEBVER}.debian.
tar.
$zip
296 $ziptool ..
/frr_
${DEBVER}.debian.
tar
298 # pack up debian files proper
299 ln -s "$outdir/frr-${PACKAGE_VERSION}.tar.$zip" ..
/frr_
${PACKAGE_VERSION}.orig.
tar.
$zip
300 dpkg-source
-l"$tmpdir/debian/changelog" \
301 --format='3.0 (custom)' --target-format='3.0 (quilt)' \
302 -b . frr_
${PACKAGE_VERSION}.orig.
tar.
$zip frr_
${DEBVER}.debian.
tar.
$zip
304 dpkg-genchanges
-sa -S > ..
/frr_
${DEBVER}_source.changes
306 test -n "$keyid" && debsign ..
/frr_
${DEBVER}_source.changes
-k"$keyid"
308 mv ..
/frr_
${DEBVER}_source.changes
"$outdir" || true
309 mv ..
/frr_
${DEBVER}.dsc
"$outdir" || true
310 mv ..
/frr_
${DEBVER}.debian.
tar.
$zip "$outdir" || true
311 if test -h ..
/frr_
${PACKAGE_VERSION}.orig.
tar.
$zip; then
312 rm ..
/frr_
${PACKAGE_VERSION}.orig.
tar.
$zip || true
314 ln -s frr-
${PACKAGE_VERSION}.
tar.
$zip "$outdir/frr_${PACKAGE_VERSION}.orig.tar.$zip" || true
320 frr_${DEBVER}.debian.tar.$zip \
321 frr_${PACKAGE_VERSION}.orig.tar.$zip \
322 frr_${DEBVER}_source.changes"
326 if test -n "$keyid"; then
327 $unzip frr-
${PACKAGE_VERSION}.
tar.
$zip > frr-
${PACKAGE_VERSION}.
tar
328 test -f frr-
${PACKAGE_VERSION}.
tar.asc
&& rm frr-
${PACKAGE_VERSION}.
tar.asc
329 if gpg
-a --detach-sign -u "$keyid" frr-
${PACKAGE_VERSION}.
tar; then
330 lsfiles
="$lsfiles frr-${PACKAGE_VERSION}.tar.asc"
332 rm frr-
${PACKAGE_VERSION}.
tar
335 echo -e "\n\033[32;1mdone: \033[36;1mfrr-$PACKAGE_VERSION\033[m\n"