dh-kpatches implementation
@

# The two Parts

The dh-kpatches system is made of two parts. The first one takes patch descriptions, and produces kernel-patch packages; the second one is (currently) contained in those patch packages, and handles application of the patches to a kernel source tree, as well as their removal.

The application/removal scripts are (currently) generated from templates by the `dh_installkpatches` script for each kernel-patch package.

Currently, the patch descriptions are completely parsed by `dh_installkpatches`, and the apply/unpatch scripts are specific to each package, and can only act on the patches `dh_installkpatches` taught them about.

## Packaging-time work

### The `dh_installkpatches` helper

This is the debhelper-based script that will cause our packages to install patches in the One True Way. Its base structure is that of a standard debhelper script. <>= #!/usr/bin/perl -w # # dh_installkpatches $Revision: 1.17.1.4.1.24.1.5 $ # # Reads debian/$package.kpatches[.foo], installs all files necessary # to have make-kpkg use the kernel patches described in there. # # (c) 2000-2003 Yann Dirson # Some parts based on code from Adam Di Carlo and Joey Hess use strict; use Debian::Debhelper::Dh_Lib; init(); <> PACKAGE: foreach my $package (@{$dh{DOPACKAGES}}) { my $tmp = tmpdir($package); my $ext = pkgext($package); # There are two filename formats, the usual # plus an extended format (debian/package.*). opendir(DEB,"debian/") || error("can't read debian directory: $!"); # If this is the main package, we need to handle unprefixed filenames. # For all packages, we must support both the usual filename format plus # that format with a period an something appended. my $regexp="\Q$package\E\."; if ($package eq $dh{MAINPACKAGE}) { $regexp="(|$regexp)"; } my @files = grep { /^${regexp}kpatches(\..*)?$/ } readdir(DEB); closedir(DEB); # next package if there are no patches in there next PACKAGE if $#files < 0; <> } @

### Patch processing

For each binary package, all `kpatches` files are processed to generate one `apply` script with a single `diff` operation (and its corresponding `unpatch` script). <>= <> foreach my $file (@files) { my %patchinfo = read_control_file ("debian/$file"); # use Data::Dumper; # print Dumper (%patchinfo); my $patchid = $patchinfo{general}->{'patch-id'}; # transformation of the ID to be acceptable as part of an envvar's name $patchinfo{general}->{'clean-patch-id'} = $patchinfo{general}->{'patch-id'}; $patchinfo{general}->{'clean-patch-id'} =~ s/-/_/g; # protect pipes and dquotes for sed command-line $patchinfo{general}->{'patch-name'} =~ s,([|\"]),\\$1,g; <> } <> @

### `kpatch:depends` substvar

A number of packages are needed by kernel-patch packages:

bash 2.x or better
  because apply scripts use arrays
patch
  because we (currently) only apply patches made of diff files
grep-dctrl
  is used to register the version of the kernel-patch package into the kernel-image package

<>= my $pkgdeps = "bash (>= 2.0), patch, grep-dctrl"; @

The substvar code was derived from similar functionnality in dh_perl v3.4.1. For idempotency, we first remove anything this program might have previously added to the substvars file. <>= if (-e "debian/${ext}substvars") { complex_doit("grep -v ^kpatch:Depends= debian/${ext}substvars > debian/${ext}substvars.new || true"); doit("mv", "debian/${ext}substvars.new","debian/${ext}substvars"); } complex_doit("echo 'kpatch:Depends=$pkgdeps' >> debian/${ext}substvars"); @

We also make sure the package uses our substvar, and abort if not. <>= die 'debian/control must make package ' . $package . ' depend on ${kpatch:Depends}' if system ("dpkg-gencontrol -p$package -Pdebian -O -T/dev/null -Vkpatch:Depends=KPATCHISUSED 2>/dev/null |" . "grep -q '^Depends: .*KPATCHISUSED'") != 0; @

## Kernel-build-time work

For each v0 kpatches file, we produce an apply and an unpatch script, necessary to work properly with make-kpkg. Those are currently produced from templates.

### Apply script

<>= #! /bin/bash set -e <> <> DEPENDS=(#DEPENDS#) KVERSIONS=(#KVERSIONS#) PATCHFILES=(#PATCHFILES#) DEBPATCHFILES=(#DEBPATCHFILES#) STRIPLEVELS=(#STRIPLEVELS#) <> <> <