Home Page

Tips page

University Page

Programming

Debian & Linux

Some works

About me

Del.icio.us Bookmarks

BOINC Combined Statistics

Site Statistics

Contact me sending an e-mail (antispam defense activated)

debian

hacker emblem

blogger

GeoURL

View Sandro Tosi's profile on LinkedIn

This is my Google PageRank

HowTo use dpatch

HowTo use dpatch

 Sandro Tosi, 17 September 2006


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:

  1. enter the package source directory
  2. 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:

  1. 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)
  2. change debian/rules as specified in the previous chapter of this article
  3. 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:

  1. download source package from debian repository mirror
  2. extract to a temporary directory, <tempdir> (or let apt-get source do that for you)
  3. import into SVN repository (it will checkout <workdir>)
  4. go into <tempdir> and setup debian/rules as needed (do the same setup on debian/rules in <workdir>)
  5. 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
  6. move both previous files into <workdir> and add them to repository
  7. 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 :)