'''This page is mostly a meeting log. Please refer to [[PackagingGuide/PatchSystems]] instead.''' ---- = 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 .diff.gz}}} only contains {{{debian/}}}. The first attempts to split-out patches were pretty trivial: storing patches in {{{debian/patches/}}}, and adding some {{{patch}}} and {{{patch -R}}} snippets to {{{debian/rules}}}. This worked for small patches, but it provided no tools for editing these patches, updating them for new upstream releases, 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 demos, describing how to add a new patch and how to edit one. For demoing, we will use some real-world packages as examples. We will look at one package for each of the available patching systems. It is recommended that you follow the same steps in a terminal, so that you get a better feeling for the process. '''Warning''': These examples were originally written up using packages from Ubuntu Dapper (6.06). Things may have since changed; the packages may no longer use the same patching systems. If you want to try the stuff yourself, please execute 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 ##}}} == General Tips == There will almost always be the need to apply patches before building a package. Here are a few patching tips taken from http://wiki.debian.org/Games/ToolsDiscuss . Some tips on how to use patches efficiently (Thanks Linas Žvirblis): * Provide descriptive file names for your patches: 'fix-loading-libfoo-on-architecture-bar.patch' is a good name, '001.patch' is not; * Make your patches stand-alone. Each patch should apply cleanly without depending on any other patch being applied; * Avoid modifying the same file in multiple patches; * If you absolutely need to create patches that depend on each other, specify that in the filenames: '00patchfoo-do-this.patch', '01patchfoo-do-that.patch' or similar; * Do not include multiple unrelated modifications into a single patch; * Patch your packages at build time. There is no need to ship a patch plus an already patched source. This only increases the size of the diff. * Make sure patch is applied before anything else happens with your package. Make configure rule depend on the patch rule; * Clean first, unpatch afterwards. Some files could have been modified during the build so unpatching may fail, unless you restore them. If simply makecleaning the sources does not restore their state, it may be a good idea to make backup copies, for example, in patch rule. == inline patches (example package: cron) == In this case, no formal patch system is used at all; there's 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). == separate patches, but no patch system (example package: udev) == 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: 0. copy the clean source tree to a temporary directory. for example: {{{cp /path/to/clean-source /tmp/old}}} 0. apply all patches up to the one you wish 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 will have to look in {{{debian/rules}}} to see how it should be invoked. 0.#3 copy the whole source tree again. for example: {{{cp -a /tmp/old /tmp/new}}} 0. go into /tmp/new, and make your modifications 0. create the patch: {{{ cd ../ diff -Nurp old new > mypatchname.patch }}} 0. go back into your original source directory and move the patch to the proper place: {{{ cd /path/to/clean-source mv mypatchname.patch ./debian/patches/mypatchname.patch }}} udev example 1: Let's create a new patch 90_penguins.patch: {{{ cd /wherever/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. ## XXX: I commented out the stuff about using 'dsrc-new-patch'... It doesn't seem terribly important in teaching the basics. I think it might be easier to swallow this stuff without it (?). Sorry if you disagree... ##Lot's of 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 ## ##}}} ##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 # apply the current version of the patch, so that you can edit it patch -p1 < debian/patches/10-selinux-include-udev-h.patch # make some silly changes... 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). == cdbs with simple-patchsys (example package: pmount) == 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 /wherever/you/unpacked/the/source/pmount-0.9.11 cdbs-edit-patch 03-simple-readme.patch echo 'This should document pmount' > README }}} Editing an already-existing patch works exactly the same way. Since the Ubuntu Edgy version of cdbs, {{{cdbs-edit-patch}}} also works for packages using tarball.mk, and it can edit patches which produce rejections. == dpatch (example package: ed) == {{{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 patches under {{{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 must make sure you do not forget to update {{{00list}}} if you add a new patch. * {{{dpatch}}} patches are actually scripts that are executed, not just patches fed to the {{{patch}}} command. 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 }}} This will edit an already existing patch and make sure that all previous patches are applied in order. {{{ dpatch-edit-patch foo.dpatch 06_testsuite-Makefile.dpatch 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. == quilt (example package: xterm) == {{{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}}}, a package needs to add a symlink). 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 /wherever/you/unpacked/the/source/xterm-208 ln -s debian/patches patches cd patches touch series cd /wherever/you/unpacked/the/source/xterm-208 export QUILT_PATCHES=debian/patches }}} 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 quilt pop -a }}} 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 quilt pop -a }}} ---- Go back to '''[[MOTU/School]]'''.<
><
> [[CategoryArchive]]