An important rules that every package maintainer should follow is to avoid directly upstream code modification.
The Right Way is to create a set of patches to be applied to upstream code at package build-time; this will let diff.gz contains only changes inside debian/ directory, which is a Good Thing.
A common tool to manage patches for packaging is dpatch.
0. Basic tasks
First of all, you have to install dpatch:
# apt-get install dpatch
and add dpatch to Build-Depends in debian/control . Moreover, you have to create the directory debian/patches: that will be the place where all patches will be stored.
In the same directory, there will be a file, debian/patches/00list: this will include a list of <patch_file_names> and the patches will be applied with the same order which are in that file.
1. Create a patch
The previous installed package, contains a useful tool, dpatch-edit-patch:
- enter the package source directory
- execute dpatch-edit-patch <patch_name>
this will create a copy of source package, and will open a shell on that copy; do your changes and exit from the shell: file debian/patches/<patch_name> will be created with changes you’ve done.
Remember to update file debian/patches/00list.
A good practice is to add copyright note to patches: you can use a (example) policy where you put trivial patches on « public domain » and the program license for the ones you’d like to forward upstream.
2. Convert a patch
This script (thanks to Charles Plessy) takes modified and original file, creates a patch in unified format and then convert it to dpatch format.
diff -u source-tree-original/the-file source-tree/the-file | \
dpatch patch-template -p « <number>_<short_description> » \
« <what the patch does> » > path/to/debian/patches/<number>_<short_description>.dpatch
(replace <tags> with meaningful thing).
Usually patch (mainly the one sent throu BTS) are sent as a file: to convert such a patch, replace diff -u … with cat /path/to/file.patch and that’s all.
3. Test a patch
Ok, you’ve just forged a patch, but how to test if it does what it needs to do? Apply it!
From inside the extracted source package (the working copy for package creation) execute
dpatch apply-all
and to revert
dpatch deapply-all
a
4. Use dpatch in debian/rules
Now, we have only left to instruct debian/rules to apply patches (in the order listed in debian/patches/00list) from debian/patches/ .
I think, the easiest way is to modify debian/rules this way:
include /usr/share/dpatch/dpatch.make
…
build: build-stamp
build-stamp: patch-stamp
…
build stuff here
…
clean: unpatch
…
clean stuff here
…
…
But if you want, you can explicitly include patch/unpatch target as in this example:
build-stamp: patch
…
build stuff here
…
clean: clean1 unpatch
clean1:
…
clean stuff here
…
…
patch: patch-stamp
patch-stamp:
dpatch apply-all -v
#dpatch call-all -a=pkg-info >patch-stamp
unpatch:
dpatch deapply-all
rm -rf patch-stamp debian/patched
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install patch unpatch \
clean1
Anyway, I suggest to follow the first way, which is cleaner a less error prone.
5. Restore pristine upstream code
The very first thing every Debian package maintainer has to rememeber is: NEVER change upstream code in your package, use patches. Even if you follow this Master Rule when packaging a tool by yourself, you may face upstream code changes when adopting a pacakge.
There is a way you can convert such changes (done by previous package maintainer) in a dpatch patch:
- obtain package source code, using apt-get source <pkg> or whatever you want; we suppose the source package is uncompressed in <pkg-ver> directory: go into that (note that source file are in the parent directory)
- change debian/rules as specified in the previous chapter of this article
- use dpatch-convert-diffgz: this tool takes .diff.gz, extract changes done on upstream files and convert them in a dpatch file, to be applied during package building
If you manage your packages the old way (no source code versioning system), you’ve done. I use Subversion to maintain my source packages, and that requires some additional steps:
- download source package from debian repository mirror
- extract to a temporary directory, <tempdir> (or let apt-get source do that for you)
- import into SVN repository (it will checkout <workdir>)
- go into <tempdir> and setup debian/rules as needed (do the same setup on debian/rules in <workdir>)
- execute dpatch-convert-diffgz 01 restore_pristine_code (you can choose whatever name you prefere); this will create files debian/patches/01_restore_pristine_code.dpatch and debian/patches/00list
- move both previous files into <workdir> and add them to repository
- revert back to pristine version source files modified by previous maintainer: this could mean copy the file by hand (cp -p ….) from an uncompressed upstream tarball or maybe executing fakeroot debian/rules patch ; fakeroot debian/rules unpatch (last way is NOT guaranteed).
It’s a little bit complex, but this way you can adopt a package and use dpatch: that’s good 🙂