PatchingSources

Differences between revisions 7 and 8
Revision 7 as of 2006-07-25 20:08:54
Size: 8963
Editor: 195
Comment: fix enumeration formattin
Revision 8 as of 2006-08-02 10:24:33
Size: 9101
Editor: 195
Comment: cdbs-edit-patch update
Deletions are marked like this. Additions are marked like this.
Line 102: Line 102:
With the latest edgy version, cdbs-edit-patch also works for packages using tarball.mk, and can edit patches which produce rejections.

2006-07-25 - pitti's presentation on applying patches.

Pitti's notes: from http://people.ubuntu.com/~pitti/tmp/patch-systems.txt IRC log: http://netz.smurf.noris.de/logs/freenode/2006/07/25/%23ubuntu-motu-school.log

Patching Ubuntu packages

Why use separate patches

In earlier times, people just applied patches inline (i. e. directly in the source code tree). However, this makes it very hard to extract patches later to modify them, send them upstream, etc. Also this means that new upstream versions are a pain, since they generate a lot of rejections when applying the package diff.gz to them. With split-out patches it is much easier to send them upstream, keep track of them, develop them, etc., since you always see which changes belong together. The ideal state is an unmodified tarball from upstream, plus clean and separate patches, plus the packaging bits in debian/. That means that lsdiff <sourcepackage>.diff.gz only contains debian/.

The first attempts to split-out patches were pretty trivial: storing patches in debian/patches/, and adding some patch/patch -R snippets to debian/rules. This worked for small patches, but provided no tools for editing these patches, updating them for new upstream versions, etc.

Thus several standard patch systems were created which are easy to deploy and provide tools for patch juggling and editing.

What I would like to do now is to introduce the most common patch systems and show some hands-on demo how to add a new patch and how to edit one. For this, I will download a source package from the current dapper archive, quickly explain the patch system, and show how to apply some (braindead) modifications to it. I recommend you to do the same steps in a terminal, so that you get a feeling for the process and can immediately ask questions.

If you want to try the stuff yourself, please do the following commands as preparation:

  sudo apt-get install dpatch dbs quilt patchutils cdbs
  apt-get source cron udev pmount gnome-volume-manager ed xterm
  wget http://people.ubuntu.com/~pitti/scripts/dsrc-new-patch
  chmod 755 dsrc-new-patch

cron: inline patches

No patch system at all, nothing much to say about this. You directly edit the files in the source tree. This is convenient for a simple and quick change, but will bite back for new upstream versions (see above)

udev: separate patches, but no patch system

This case is the most complicated one since you have to do all the hard work manually. In order to make you understand what a patch system does, and to give you a fallback method that will *always* work with any patch system, I handle this first.

The general approach is:

  1. copy the clean source tree to a temporary directory
  2. apply all patches up to the one you want to edit; if you want to create a new patch, apply all existing ones (this is necessary since in general patches depend on previous patches) if you want, you can use debian/rules for this: remove the patches that come *after* the one you want to edit, and call 'debian/rules patch'. The actual name for the patch target varies, I have seen the following ones so far: patch setup apply-patches unpack patch-stamp. You have to look in debian/rules how it is called.
  3. copy the whole source tree again: cp -a /tmp/old /tmp/new
  4. go into /tmp/new, do your modifications
  5. go back into your original source tree, generate the patch with
    • diff -Nurp /tmp/old /tmp/new > mypatchname.patch

and direct the output to debian/patches/mypatchname.patch

udev example 1, let's create a new patch 90_penguins.patch:

  cd /whereever/you/unpacked/the/source/udev-079
  cp -a . /tmp/old
  pushd /tmp/old
  debian/rules patch
  cp -a . /tmp/new; cd ../new
  sed -i 's/Linux/Penguin/g' README
  cd ..
  diff -Nurp old new > 90_penguins.patch
  popd
  mv /tmp/90_penguins.patch debian/patches
  rm -rf /tmp/old /tmp/new

Now take a look at your shiny new debian/patches/90_penguins.patch.

Pretty much work, isn't it? Since this happens pretty often, I created a very dumb helper script 'dsrc-new-patch' for this purpose. Using this, above steps would reduce to:

  dsrc-new-patch 90_penguins.patch
  sed -i 's/Linux/Penguin/g' README
  <press Control-D to leave the subshell>

However, this script is currently too dumb to edit existing patches, or to put patches somewhere else than the top of the patch stack. If you need this, then you need to do the manual approach. Assume we want to edit 10-selinux-include-udev-h.patch. This patch does not depend on the previous patches, so it's a bit easier that way, too:

udev example 2:

  cd /whereever/you/unpacked/the/source/udev-079
  cp -a . /tmp/old
  pushd /tmp/old
  cp -a . /tmp/new; cd ../new
  patch -p1 < debian/patches/10-selinux-include-udev-h.patch
  # above will apply the current version of the patch, so that you can edit it
  sed -i '1 s/$/***** HELLO WORLD ****/' udev_selinux.c
  cd ..
  diff -Nurp old new > 10-selinux-include-udev-h.patch
  popd
  mv /tmp/10-selinux-include-udev-h.patch debian/patches
  rm -rf /tmp/old /tmp/new

Now debian/patches/10-selinux-include-udev-h.patch contains both the original change and our modification of the first line of the source file.

Since this is so hideously complicated, patch systems were invented to aid you with that. Let's look at the most popular ones now (they are sufficient to allow you to patch about 90% of the archive's source packages; for the rest you have to resort to the manual approach above).

pmount: cdbs with simple-patchsys

cdbs' simple-patchsys.mk module matches its name, it has no bells and whistles whatsoever. However, it is pretty popular since it is sufficient for most tasks, and long ago I wrote a script 'cdbs-edit-patch' which most people can live with pretty well. This script is contained in the normal cdbs package.

You just supply the name of a patch to the script, and depending on whether it already exists or not, it will create a new patch or edit an existing one.

Example with pmount:

  cd /whereever/you/unpacked/the/source/pmount-0.9.11
  cdbs-edit-patch 03-simple-readme.patch
  echo 'This should document pmount' > README
  <press Control-D to leave the subshell>

Editing an already existing patch works exactly the same way.

With the latest edgy version, cdbs-edit-patch also works for packages using tarball.mk, and can edit patches which produce rejections.

ed: dpatch

dpatch is a pretty robust and proven patch system which also ships a script 'dpatch-edit-patch'. The two most important things you should be aware of:

  • dpatch does not apply debian/patches/*, but instead applies all patches mentioned in debian/patches/00list, in the mentioned order. That means that you do not have to rely on asciibetical ordering of the patches and can easily disable patches, but you have to make sure to not forget to update 00list if you add a new patch.
  • dpatch patches are actually scripts that are executed, not just patches fed to 'patch'. That means you can also do fancy things like calling autoconf or using sed in a dpatch if you want.

The manpage is very good and has examples, too, so I will only give an example here:

  cd /whereever/you/unpacked/the/source/ed-0.2
  dpatch-edit-patch 05_ed.1-warning-fix
  <edit stuff, press Ctrl+D>

This will edit an already existing patch and take care that all previous patches are applied in order.

  dpatch-edit-patch foo.dpatch 06_testsuite-Makefile.dpatch
  <edit stuff, press Ctrl+D>
  echo foo.dpatch >> debian/patches/00list

This will create a new patch foo.dpatch relative to the already existing 06_testsuite-Makefile.dpatch. If your patch is very confined and does not depend on other patches, you can leave out the second argument.

xterm: quilt

quilt is the other non-dumb standard patch system. Like dpatch, it has a list of patches to apply in patches/series (to use debian/patches, packages need to add a sylink). It is non-trivial to set up and has a lot of advanced commands which make it very flexible, but not very easy to use.

So I will only show a small example here, too. First, use the existing machinery to set up symlinks and directories for quilt:

  cd /whereever/you/unpacked/the/source/xterm-208
  debian/rules prepare

Now let's edit the already existing patch 901_xterm_manpage.diff:

  quilt push 901_xterm_manpage.diff
  sed -i 's/Copyright/Copyleft/' xterm.man
  quilt refresh 901_xterm_manpage.diff

So unlike the other patch systems, quilt works with patched inline sources, but keeps track of modifications.

Finally, let's add a new patch to the top of the stack:

  quilt push -a
  quilt new muhaha.diff
  quilt add README  # you have to do that for all files you modify
  sed -i '1 s/^/MUHAHA/' README
  quilt refresh


Go back to [:MOTU/School].BRBR [:CategoryMOTU]

MOTU/School/PatchingSources (last edited 2008-08-06 16:38:32 by localhost)