From: Simon Josefsson <simon@josefsson.org>
Date: Thu, 11 Apr 2024 14:10:11 +0200

Upstream gnulib is a source-only project with no release tarballs,
versioned releases or even git tags.  Consumers of gnulib is typically
other upstream projects that depend on a particular git commit of
gnulib.  As such it is a bit different from most upstream projects.

We intentionally want to ship a complete git repository in the
resulting *.deb, so the *.orig.tar.gz source package has to contain a
complete git repository as well.

The reason for shipping the entire git repository is that other
packages can then Build-Depends on this package and use gnulib-tool
with GNULIB_URL=/usr/share/gnulib/gnulib.bundle and GNULIB_REVISION
stored in bootstrap.conf to pick out the particular git commit that
the relevant project was bootstrapped for.  Maintainers of projects
using gnulib pick a particular gnulib git commit, and there is no
official releases of gnulib to coordinate which commit to pick, so
maintainers usually chose the latest gnulib HEAD commit at the time
they are preparing their releases.  We could in theory prune the git
repository to only contain the particular GNULIB_REVISION commits
necessary for building other packages in Debian, but for simplicitly
this package supports all possible versions by shipping the entire git
repository.

To prepare the *.orig.tar.gz tarball for this package, the following
manual process was performed:

cd $(mktemp -d)
B=stable-202401 # upstream's stable branch you want in /usr/share/gnulib
REV=dfb71172a46ef41f8cf8ab7ca529c1dd3097a41d # commit you want to package
git clone https://git.savannah.gnu.org/git/gnulib.git
git -C gnulib checkout -B master $REV
git -C gnulib checkout $B
git -C gnulib -c 'pack.threads=1' bundle create gnulib.bundle --all
V=$(git -C gnulib/ show -s --date=format:%Y%m%d --pretty=%cd~%h --abbrev=7 master)+$(echo $B | sed 's,-,,').$(git -C gnulib/ show -s --date=format:%Y%m%d --pretty=%cd~%h --abbrev=7 $B)
rm -rf gnulib/.git
mv gnulib gnulib-$V
tar cfz gnulib_$V.orig.tar.gz gnulib-$V
gpg --detach-sign --armor gnulib_$V.orig.tar.gz

A package version "20240411~b57dd0d+stable202401.20240408~aa0aa87"
means that the gnulib git clone had the latest commit on "master"
dated "20240411" with revision "b57dd0d" and the "stable-202401"
branch had a commit dated "20240408" with revision "aa0aa87".  The
files in /usr/share/gnulib correspond to files on the "stable-202401"
branch with revision "aa0aa87", except for
/usr/share/gnulib/gnulib.bundle which is a git bundle containing both
master and stable branches up until "b57dd0d" (master) and "aa0aa87"
(stable-202401) respectively.  This approach enable /usr/share/gnulib
to be an unpacked stable gnulib release, but the
/usr/share/gnulib/gnulib.bundle (which is more likely to be used by
other packages for bootstrapping) can contain newer commits too.

Sidenote: Unfortunately due to how git works, the *.orig.tar.gz
tarball is not reproducible, even when the commands above are run
twice during a short period of time with no upstream commit into git.
The reason is that the generated git bundle differs each time.  Using
the .git/ sub-directory instead has the same problem.  It is thought
that git bundles ought to be more reproducable than .git/ tree
content.  See Appendix for some unsuccessful ideas to improve
reproducability of the bundle.  It would be nice for upstream gnulib
to publish signed git bundles of the git repository, but for as long
as they only publish a git repository this appears to be one way to at
least somehow re-publish the git repository.  Further thinking on this
topic is most welcome!

To import the tarball into git use these commands:

git clone git@salsa.debian.org:debian/gnulib.git
cd gnulib
git remote add upstream https://git.savannah.gnu.org/git/gnulib.git
git fetch upstream
git checkout -B upstream-stable upstream/$B
# verify the commit is still the same as when generating the tarball
git tag -m "Imported branch $B of upstream $V" -s upstream/$(echo $V | sed 's,[+~],.,g')
git checkout debian/sid
$EDITOR debian/changelog # fix version
pristine-tar commit -s ../gnulib_$V.orig.tar.gz.asc ../gnulib_$V.orig.tar.gz upstream-stable

Then build the package as usual:

gbp buildpackage --git-pbuilder --git-pbuilder-options=--source-only-changes

Happy hacking!

Appendix: Unsuccessful attempts to get a reproducible git bundle

# dumb protocol doesn't repack the objects
GIT_SMART_HTTP=0 git clone https://git.savannah.gnu.org/git/gnulib.git

# using rsync fetches .git identical as upstream
rsync -av git.savannah.gnu.org::git/gnulib.git/ gnulib
