< Using Git for Debian | Russ Allbery > Technical Notes > Debian | sbuild with btrfs > |
Introduction
The debian/rules
File
Other Packaging Files
VCS Repository Structure
I prefer to stick to a discipline of managing everything of significance that I install on my systems in Debian packages. This gives me the full power of the package system to handle dependencies, makes it easier to ensure that I have the current version installed on all of my systems, and avoids multiple copies of files checked into different repositories and templates.
However, some of the software I use comes in the form of stand-alone scripts distributed as simple downloads rather than versioned tarballs. This requires some machinations to build a reasonable Debian package since the normal packaging workflows assume an upstream tarball with a Makefile and similar machinery.
This page summarizes my approach in the hope that it will save other people some time. Most of it is obvious, but it's sometimes still nice to have something to cut and paste.
All code examples on this page are hereby placed in the public domain if that's possible in your jurisdiction, and in any case may be treated as if they were in the public domain.
debian/rules
File
The first trick with scripts is to create a reasonable upstream tarball
for use as the .orig.tar.gz
file. I use the following code in
debian/rules
to implement a get-orig-source
target, this for
an example filter-syslog
script.
SCRIPT = filter-syslog URL = http://archives.eyrie.org/software/system/filter-syslog NEW = `awk '/Id: / { print $$6; exit }' $(SCRIPT).new` get-orig-source: wget -O $(SCRIPT).new $(URL) chmod 755 $(SCRIPT).new mkdir $(SCRIPT)-$(NEW) cp -p $(SCRIPT).new $(SCRIPT)-$(NEW)/$(SCRIPT) tar cfz $(SCRIPT)_$(NEW).orig.tar.gz $(SCRIPT)-$(NEW) rm -r $(SCRIPT)-$(NEW) $(SCRIPT).new
The number of column to print in the awk command depends on how the Id
string is represented in the script. This example assumes setting a
variable with an our
delcaration. If that's not the case, you may
want $$5
instead. If you cut and paste this, be careful to change
the leading spaces in the lines after the get-orig-source:
target
to tabs.
This rule downloads the script from a URL (which will need to be changed
for the script that you're using) and creates an .orig.tar.gz
file
from it.
The above rule extracts the version number of the script from a CVS- or
Subversion-style Id
string, which matches my convention for script
versioning. Depending on the script, you may have to do something else,
such as run the script with -v
and extract the version from the
output. Unfortunately, you cannot use :=
or $(shell)
to
extract the version number since it can't run before the new script is
downloaded.
The rest of debian/rules
depends on whether you are installing a
man page you wrote yourself, or whether you're generating one from the
script. If you're installing one yourself, you can just put it into
debian/manpages
and then use the fully minimal debhelper 7 rules:
#!/usr/bin/make -f %: dh $@
plus the get-orig-source
target. If you need to generate the man
page during the build, you need something more complex. Most of the
scripts I package are in Perl with POD documentation, so I use something
like:
VERSION := $(shell awk '/Id: / { print $$6; exit }' $(SCRIPT)) override_dh_auto_build: pod2man --release=$(VERSION) --center="$(SCRIPT)" $(SCRIPT) \ > $(SCRIPT).1 %: dh $@
for the rest of debian/rules
. As above, replace the awk code with
something else if needed to get the version of the script and replace
leading spaces with tabs. You can do something similar if you're using
help2man or some other system to generate the man page. Don't forget to
add the generated man page to debian/clean
and to
debian/manpages
.
The other packaging files are very simple and similar to a normal Debian
arch-all package. If you use the above techniques for
debian/rules
, you of course need to declare a build-dependency on
debhelper (>= 7.0.50~)
for override support and create a
debian/compat
file containing 7
.
For Perl scripts, remember that you can use ${perl:Depends}
in
debian/control
for the Perl dependency of the generated package,
but you still have to separately declare the dependencies on the modules
that the script uses.
If you're generating the man page during the build, remember to add a
Build-Depends-Indep
line for whatever tools generate the man page.
In the case of pod2man, this is simply the perl package, but an explicit
build dependency is still good form since perl-base may not include the
pod2man components. (Yes, debhelper depends on perl so this isn't
strictly necessary, but it's not good form to rely on the dependencies of
your dependencies when you call the programs directly.)
I add a watch file containing something like this:
# Since upstream makes this script available as a simple file download # and the download link doesn't contain the version number, there # isn't a way to write a meaningful watch file. # # To check the current upstream release, go to the package home page # and check the version number listed there.
for scripts whose download links aren't versioned. This silences Lintian and documents the situation for anyone running DEHS or uscan on the package.
I keep all of my Debian packaging in Git, even simple things like this.
For scripts, I use a simplified version of my normal
Git packaging structure and configuration that
maintains all Debian packaging and changes in the master
branch.
The following details assume that you've already set up git-buildpackage
and friends as described there.
First, to bootstrap the repository, you want to create an upstream
branch containing just the script, a pristine-tar
branch containing
the metadata for the .orig.tar.gz
files that you will create, and a
master
branch that will be used for releases, packaging, and
Debian-specific changes. Start with:
git init git branch upstream
in a new empty directory. This creates an empty upstream
branch
that you'll use later.
Then, what I find useful is to write the skeleton of the Debian packaging
first, particularly including the get-orig-source
target in
debian/rules
, and commit that to an empty repository created with
git init
. Then, the following commands will bootstrap things:
debian/rules get-orig-source git checkout upstream tar xf <script>_<version>.orig.tar.gz mv <script>-<version>/<script> . rmdir <script>-<version> git add <script> git commit -m 'Import upstream version <version>' git tag upstream/<version> git checkout master pristine-tar commit <script>_<version>.orig.tar.gz rm <script>_<version>.orig.tar.gz git merge upstream
replacing <script> and <version> with the name of the script and its current version.
This process will create an upstream
branch that contains just the
current version of the script as distributed by upstream and a
pristine-tar
branch with the necessary information to recreate your
tarball, and then merges the upstream
branch into master
.
You can now finish whatever additional packaging bits you need to do and
continue as normal.
Once you've bootstrapped the repository, importing a new upstream version is as easy as:
git checkout master debian/rules get-orig-source mv <script>_<version>.orig.tar.gz .. git-import-orig ../<script>_<version>.orig.tar.gz
I've had better luck with keeping the .orig.tar.gz
file outside of
the working directory of the repository when running the git-import-orig
magic.
< Using Git for Debian | Russ Allbery > Technical Notes > Debian | sbuild with btrfs > |