Patching senza un sistema di patching

Come menzionato prima, è possibile applicare patch al codice sorgente originale nel pacchetto sorgente. Un esempio concreto di ciò è dato da cron. Se scarichi il pacchetto sorgente di cron e osservi il file .diff.gz noterai che parecchi file dei sorgenti originali sono stati modificati.

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

Ma come abbiamo menzionato prima questo non è sicuramente il miglior modo per rappresentare le patch. Un modo migliore è creare patch individuali, collocarle in debian/patches/ e applicare le patch (usando application>patch

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

Il file rules contiene le seguenti regole per applicare e rimuovere le patch:

# 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

Tutto questo è molto piacevole, ma come possiamo creare nuove patch per udev usando questo schema? L'approccio comune è:

  1. copia l'albero dei sorgenti puliti in una directory temporanea

  2. applica tutte le patch fino alla versione che desideri modificare; se vuoi creare una nuova patch, applica tutte quelle esistenti (questo è necessario dato che di solito le patch dipendono da quelle precedentemente applicate)

    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. copia l'intero albero dei sorgenti ancora una volta:

    cp -a /tmp/old /tmp/new
  4. entra in /tmp/new ed effettua le tue modifiche

  5. ritorna nell'albero dei sorgenti originale, genera la patch con:

    diff -Nurp /tmp/old /tmp/new > mypatchname.patch

Esempio 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

Esempio 2.

Cosa succede se volessimo modificare una patch esistente? Potremmo usare una procedura simile a quella dell'Esempio 1 ma dovremmo applicare la patch da modificare prima:

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/$/***** CIAO MONDO ****/' 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

Questo modo per applicare patch ai sorgenti, anche se tecnicamente valido, può diventare molto complicato e ingestibile. Per creare patch più facilmente e in modo lineare sono stati sviluppati i sistemi di patching. Andremo ad osservare due dei più popolari.