Aufbau eines Patches¶
Ein Patch ist eine Datei im Textformat, die für gewöhnlich die Endung
.patch (manchmal auf .diff) hat und eine Liste von Unterschieden
zwischen zwei Version einer Datei enthält. Patches enthalten nur
Unterschiede in Textdateien. Unterschiede in Binärdateien können nicht
gepatched werden.
Zu Beginn eines Patch kann ein Kommentar stehen, der beschreibt wo der
Patch herkommt, wer daran mitgewirkt hat, welches Problem er löst usw.
Der eigentliche Beginn der Unterschiede wird durch --- gekennzeichnet.
Für gewöhnlich enthält ein Patch 3 Zeilen Kontext vor und nach jeder
geänderten Zeile. Diese dienen als Referenz, so dass der Patch auch noch
angewendet werden kann falls an der zu patchenden Datei eine Änderung
vorgenommen wurde und die Zeilennummern nicht mehr korrekt sind.
Dieser Patch ist ein Beispiel und fügt menuconfig einen neuen Eintrag hinzu.
Index: make/Config.in
===================================================================
--- make/Config.in (Revision 7307)
+++ make/Config.in (Arbeitskopie)
@@ -51,6 +51,7 @@
source make/netcat/Config.in
source make/nc6/Config.in
source make/netsnmp/Config.in
+source make/newpackage/Config.in
source make/nfs-utils/Config.in
source make/ntfs/Config.in
source make/openntpd/Config.in
In den meisten Fällen lauten die 2 Dateinamen (hier make/Config.in)
gleich, manchmal Unterscheiden sie sich in der Endung (.orig), je
nachdem wie der Patch erstellt wurde. Im Beispiel ist also eine Änderung
an der Datei make/Config.in beschrieben. Konkret wurde hier ein neues
Paket newpackage geschrieben und soll jetzt dem menuconfig hinzugefügt
werden. Die fünfte Zeile des Patches enthält Informationen darüber wo
sich der zu patchende Abschnitt (hunk) in der Datei befindet und wie
viele Textzeilen der Patch verändert. Im Beispiel beginnt der Patch ab
Zeile 51 und fügt eine Zeile (7-6=1), gekennzeichnet durch ein +,
hinzu. Man könnte also das gleiche Ergebnis erreichen, wenn man die
Datei make/Config.in in einem Texteditor öffnet und die Zeile
source make/newpackage/Config.in an der beschriebenen Stelle
hinzufügt.
Erzeugen eines Patches¶
Man hat eine Datei (Config.in) geändert und difft sie gegen SVN:
Alle Änderungen im Verzeichnis + Unterverzeichnisse:
Falls man neue Dateien angelegt hat müssen diese erst dem SVN
hinzugefügt werden:
Patch anwenden oder rückgängig machen¶
Patch anwenden:
Patch rückgängig machen:
Falls ihr so etwas seht:
$ patch -p0 < Config.patch
patching file Config.in
Hunk #1 FAILED at 1.
1 out of 1 hunk FAILED -- saving rejects to file Config.in.rej
Dann passt der Patch nicht mehr und muss erneuert werden.
- TODO (evtl. aus dem
ippf-Wiki
kopieren)
Wie finde ich die zu patchende Stelle?¶
Auf diese Frage muss man primär antworten: Es kommt darauf an, worum es
geht. Weil das aber hier im Wiki natürlich nicht so befriedigend ist,
folgen ein paar Tipps von RalfFriedl am konkreten Beispiel von crond
bzw. dem Frotend dazu, nämlich dem crontab-Fenster im Freetz WebGUI.
Da cron nicht ein extra Paket ist, sondern zum Freetz Basis-System
gehört, liegen die Dateien für cron unter dem Verzeichnis
"make/mod/root/files". Wenn es ein eigenes Paket wäre, z.B. inetd,
wären die Dateien unter "make/inetd/files/root".
Im folgenden geht es darum, wie man die Web-Oberfläche von crontab
ändert und dann patcht. Am einfachsten findet man die Datei, wenn man
nach einem Text sucht, der sonst hoffentlich selten vorkommt,
"crontab" scheint hier ein guter Wert zu sein.
$ grep -r crontab make 2> /dev/null | fgrep -v /.svn/
make/mod/files/root/etc/init.d/rc.crond: cat /tmp/flash/mod/crontab /etc/cron.d/* /tmp/cron.d/* 2> /dev/null |
make/mod/files/root/etc/init.d/rc.crond: crontab -u root -
make/mod/files/root/etc/init.d/rc.crond: [ -r /tmp/flash/crontab.save ] && mv /tmp/flash/crontab.save /tmp/flash/mod/crontab
make/mod/files/root/etc/init.d/rc.crond: modreg file mod crontab 'crontab' 0 "crontab"
make/mod/files/root/etc/init.d/rc.crond: modunreg file mod crontab
make/mod/files/root/etc/default.mod/crontab.def:CAPTION='Freetz: crontab'
make/mod/files/root/etc/default.mod/crontab.def:CONFIG_FILE='/tmp/flash/mod/crontab'
Das suchen in "make" ist nur für den Fall, dass man nicht sicher ist,
in welchem Verzeichnis sich die Dateien befinden. Wenn man weiss, daß
cron zum Hauptsystem gehört, kann man direkt in "make/mod/files"
suchen, dann geht es schneller. Die Umleitung "2> /dev/null"
unterdrückt Fehlermeldungen wegen nicht gefundener Dateien/Links.
Die Ergebnisse in Dateien mit "/.svn/" im Pfad sind hier nicht von
Bedeutung.
Der Text "crontab" kommt also in den Dateien rc.crond und crontab.def
vor. Das sagt uns leider noch nicht, was man machen muss, um eine Hilfe
auf die Seite zu bringen. Also suchen wir einmal nach "Hosts", weil
auf der Hosts-Seite schon eine Hilfe da ist.
$ grep -r Hosts make 2> /dev/null | fgrep -v /.svn/
...
make/mod/files/root/etc/default.mod/hosts.def:CAPTION='Freetz: hosts'
root/etc/init.d/rc.mod: modreg file 'exhosts' 'Hosts' 1 "$deffile"
... und noch viele andere Treffer
Die Definitionsdatei, aus der der Text "hosts" kommt, ist also
make/mod/files/root/etc/default.mod/hosts.def. Schauen wir uns also mal
die Datei an:
$ cat make/mod/files/root/etc/default.mod/hosts.def
CAPTION='Freetz: hosts'
DESCRIPTION='Syntax: <ip> <mac> <interface> <host> [<aliases|#description>]<br>
($(lang de:"z.B.: 10.0.0.1 * * www.local mfh1 # Mein Server" en:"e.g. 10.0.0.1 * * www.local mfh1 # my server")) *="$(lang de:"nicht definiert" en:"not defined")"'
... der Rest ist hier nicht von Bedeutung
Wir sehen also, dass die Beschreibung aus dem Eintrag DESCRIPTION kommt,
der in der Datei make/mod/files/root/etc/default.mod/crontab.def nicht
vorhanden ist. Man muss also in der Datei
make/mod/files/root/etc/default.mod/crontab.def einen Eintrag
DESCRIPTION anlegen.
Wenn man will, dass mehrere Sprachen mit $(lang ...) unterstützt
werden, dann muss man auch sicherstellen, dass die Datei in der
passenden Liste hinterlegt ist. Dies ist die datei ".language" im
Verzeichnis make/\<Paket>/files.
Die Datei sieht so aus:
$ cat .language
languages
{ de en }
default
{ en }
files
{
etc/default.mod/*.def
etc/init.d/rc.mod
usr/bin/modreg
...
}
Wir sehen hier, dass alle Dateien etc/default.mod/*.def schon
inkludiert werden und kein weiterer Eintrag notwendig ist.
Die geänderte Datei ist in diesem Fall nur
make/mod/files/root/etc/default.mod/crontab.def und es geht weiter wie
unten beschrieben.
Hintergrundinfos finden sich in diesem
IPPF-Thread.
Links¶
Wikipedia Artikel zu diff
(Englisch)
Wikipedia Artikel zu patch
(Englisch)