Patching Without a Patch System

As was mentioned above, one can patch the original source by simply making the changes in the unpacked source directory. A real-life example of this is cron. If you grab cron's source package and look at the .diff.gz you will see that several of the original source's files were changed.

apt-get source cron
zgrep +++ cron*.diff.gz

But as we mentioned before this is not really the best way to represent patches. One better way is to create individual patch files, but them in debian/patches/ and apply the patches (using patch) in debian/rules. This is what is done for udev:

apt-get source udev
zgrep +++ udev*.diff.gz
ls udev*/debian/patches/
less udev*/debian/rules

The rules file has the following rules for applying and unapplying the patches:

# Apply patches to the package
patch: patch-stamp
patch-stamp:
        dh_testdir
        @patches=debian/patches/*.patch; for patch in $$patches; do \
                test -f $$patch || continue; \
                echo "Applying $$patch"; \
                patch -stuN -p1 < $$patch || exit 1; \
        done
        touch $@

# Remove patches from the package
unpatch:
        dh_testdir
        @if test -f patch-stamp; then \
                patches=debian/patches/*.patch; \
                for patch in $$patches; do \
                        reversepatches="$$patch $$reversepatches"; \
                done; \
                for patch in $$reversepatches; do \
                        test -f $$patch || continue; \
                        echo "Reversing $$patch"; \
                        patch -suRf -p1 < $$patch || exit 1; \
                done; \
                rm -f patch-stamp; \
        fi

That is all very nice, but how do we create new patches for udev using this scheme? 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 to see what 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

Example 1.

Let us make a new patch for udev called 90_penguins.patch which replaces Linux with Penguin in the udev README file:

cd udev*/
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

Example 2.

What happens if we want to edit an existing patch? We can us a similar procedure as Example 1 but we will apply the patch to be edited first:

cp -a . /tmp/old
pushd /tmp/old
cp -a . /tmp/new; cd ../new
patch -p1 < debian/patches/10-selinux-include-udev-h.patch
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

So this way of patching the source, while technically fine, can become very complicated and unmanageable. To make patching easier and more straightforward patch systems were developed. We will take a look at couple popular ones.