Patches
Inhaltsverzeichnis |
Beschreibung
Ein Patch ist eine Änderung am Original-Quelltext eines Programms. In der Patchdatei befinden sich nur die geänderten Statements und Kommentare darüber, wie diese in den Sourcecode eingepflegt werden müssen. Sie bezieht sich immer auf eine bestimmte Version der Originaldatei.
Nach dem Einspielen eines Patches ist der Quellcode neu zu kompilieren. Für VDR existieren diverse Patches z.B. um die Optik des OSD zu verbessern. (s.a. Plugins)
Anleitung
Was ist ein Patch? Ein Patch (oder auch diff-Datei genannt) ist nichts anderes als eine Differenzmenge zwischen 2 Dateien. Im vdr-Bereich sind diese Dateien zu 99,99% Textdateien wie z.B. Scripte oder Quellcodes. Da man bei unterschieden ja auch dokumentieren muß, was wo unterschiedlich ist, enthält die Datei ein paar Steuerinformationen, so reicht es nicht zu sagen "Datei 10 wurde gelöscht", wenn man gar nicht dazu sagt, ob in der alten oder in der neuen Datei, apropos Datei, der Patch enthält außerdem eine Information um welche Datei es überhaupt geht.
Wie ist ein Patch aufgebaut?
Nehmen wir an wir haben eine fiktive Datei D1:
code:
1.Zeile 1 2.Zeile 2 3.Zeile 3 4.Zeile 4 5.Zeile 5
Und fiktive Datei D2:
code:
1. Zeile 1 2. Zeile 2 3. Zeile 3 neu 4. Zeile 4 5. Zeile 5
dann ergäbe das eine Patchdatei mit dem Inhalt:
code:
1. --- D1 2005-02-21 18:44:01.000000000 +0100 2. +++ D2 2005-02-21 18:44:40.000000000 +0100 3. @@ -1,5 +1,5 @@ 4. Zeile 1 5. Zeile 2 6.-Zeile 3 7.+Zeile 3 neu 8. Zeile 4 9. Zeile 5
Als erstes gibt es Informationen welche Dateien betroffen sind, die Ausgangsdatei (--- -Zeile) und die Zieldatei (+++ -Zeile). Außerdem gibt es eine Angabe "@@ -1,5 +1,5 @@" dieses heißt soviel wie "irgendwo bei der 5. Zeile ist was unterschiedlich" das patchprogramm weiß also später in welche Zeile es erst einmal springen muß. Weiterhin gibt es nun Zeilen mit + und mit -, das ist ... genau ... das was getan wird. Es wird nach einer Zeile mit dem inhalt "Zeile 3" gesucht und diese gelöscht, dann wird eine Zeile mit dem Inhalt "Zeile 3 neu" eingefügt.
Das Patchprogramm bekommt also nun Informationen wo was wodurch ersetzt werden soll.
Soviel zur Information was eigentlich ein Patch ist und wie er aufgebaut ist.
Nun geht es weiter.
Wie liegt ein Patch vor?
Ein Patch kann auf mehrere Arten vorliegen.
a) als gepackte Datei b) als ungepackte Datei c) als Archiv mit mehreren gepackten Dateien
Beispiele:
a) patch.gz, patch.diff.gz, patch.diff.bz2 b) patch.diff, patch.patch c) patch.tgz, patch.tar.bz2, patch.zip
Die Namen sind frei wählbar, man erkennt aber meist sehr schnell worum es sich handelt, mehr Informationen dazu gibt es gleich noch.
Bitte was? "mehrere gepackte Dateien"? Was das sein soll? Die Erklärung ist ganz einfach. Stellt euch vor ihr wollt ein Programm mit 100 Dateien patchen und jeder patch wäre eine einzelne Datei. Beim Patchrstellen würdet ihr irre werden und der der die Patches einspielen muß ebenfalls. Daher kommen Patches öfters in der Variante c) vor, da sind dann intern mehrere Patch-Dateien enthalten, aber für das einspielen ändert das gar nix, man merkt davon nicht einmal etwas.
Wie spielt man einen Patch ein?
Kurz: Man übergibt ihn an das Programm "patch".
Ausführlich: Das Programm "patch" dient zum einspielen der Patches, dazu muß man dem Programm sagen wo der Patch zu finden ist, also z.B.:
torsten@torstenpc:/tmp > patch < /irgendwo/in/dem/verzeichnisbaum/liegt/diese/datei.diff
schon legt er los. Er versucht nun im aktuellen Verzeichnis, in diesem Fall also "/tmp" eine Datei namens D1 zu finden um sie zu patchen (ich nehme die Beispiele von oben weiterhin). Bei mir geht das, denn ich habe die Datei dort angelegt, doch würde ich mich im verzeichnis "/freigabe" befinden, dann gäbe es einen fehler:
code:
1. torsten@torstenpc:/freigabe > patch < /tmp/patch.diff 2. can't find file to patch at input line 3 3. Perhaps you should have used the -p or --strip option? 4. The text leading up to this was: 5. -------------------------- 6. |--- D1 2005-02-21 18:44:01.000000000 +0100 7. |+++ D2 2005-02-21 18:44:40.000000000 +0100 8. ------------------------- 9. File to patch:
Gesundheit. Die entscheidenden Informationen stehen hier:
can't find file to patch at input line 3
er kann eine Datei aus dem Patch nicht finden. Dieses ist meist ein Zeichen dafür, dass man sich in einem falschen Verzeichnis befindet. Doch es kann auch etwas anderes sein, er deutet es schon an:
Perhaps you should have used the -p or --strip option?
Was soll das heißen? Die Erklärung ist auch hier sehr einfach wenn man es einmal verstanden hat :)
Nehmen wir an meine Dateien sind über viele Unterverzeichnisse verteilt, dann würde ich ja kirre werden, wenn ich in jedes Unterverzeichnis gehen müßte um die zu analyiseren. Daher versteht die Patchdatei auch Verzeichnisse, nun könnte meine Datei anfangen mit:
#|--- tmp/D1 2005-02-21 18:44:01.000000000 +0100 #|+++ tmp/D2 2005-02-21 18:44:40.000000000 +0100
Er würde also die Dateien IMMER im Unterverzeichnis "./tmp" suchen, aktuell also in /freigabe/tmp.
Es geht zu schnell, ich merks :)
Situation:
Ich bin in: /freigabe der Patch sucht in: ./tmp der Patch sucht nach: D1 Also sucht der Patch nach /freigabe/tmp/D1
Diese Datei habe ich gar nicht, es gibt bei mit in /freigabe noch nicht einmal ein Unterverzeichnis names "tmp", allerdings habe ich meine Datei schon nach "/freigabe" kopiert.
Ich bin in: /freigabe der Patch sucht in: ./tmp der Patch sucht nach: D1 Ich habe: /freigabe/D1
Ich kann also:
a) ein Verzeichnis tmp anlegen und die Datei reinkopieren b) dem Patcher sagen: "Hey du depp, ignoriere einfach mal dein erstes Verzeichnis"
Man wird a) nie machen, denn b) ist die Lösung der Wahl, genau das ist der "-p1" Parameter. -p1 schneidet ein Verzeichnis weg -p2 zwei Verzeichnisse etc.
Ich kann also in /freigabe bleiben und meinen patch mit:
patch -p1 < /tmp/patch.diff
einspielen.
Nun ein paar Worte zu den Archiven also den Patchvorkommen a) und c) von oben.
Statt
"patch < /tmp/patch" könnte ich auch schreiben "cat /tmp/patch.diff|patch"
also den Inhalt an patch "pipen", das ist technisch quasi dasselbe in diesem Fall. Das Programm "patch" kann nur ascii-Dateien also entpackte verstehen. Man kann nun
a) die Archive auspacken und einzeln patchen b) einem Programm diese Arbeit machen lassen
Naja :) Keine Worte oder?
Nehmen wir b), das geht ganze einfach.
Für die gängigen Formate wie "tgz/tar.gz" und "gz" und auch "bz2" gibt es cat-Ableger, diese heißen einfach: zcat, bzcat einfach das entsprechende benutzen:
zcat /tmp/patch.diff.gz|patch
fertig.
Was kann beim Patchen passieren?
Eigentlich "nur" 3 Dinge.
a) nix :) b) Hunks c) Rejects
Passiert nix, dann ist alles ok, der Patchvorgang schaut etwa so aus:
torsten@torstenpc:/tmp > patch < patch.diff patching file D1 torsten@torstenpc:/tmp >
fertig.
Hunks sind kleine Mißstände, die Patch aber korrigierenkann, sie sehen so aus:
torsten@torstenpc:/tmp > patch < patch.diff patching file D1 Hunk #1 succeeded at 2 (offset 1 line). torsten@torstenpc:/tmp >
Das heißt nix anderes als dass er einen Hunk hatte (#Nummer zählt er hoch) und zwar mußte er eine Patchzeile um 1 Zeile verschieben.
Was war passiert?
Meine D1 war nicht mehr so wie oben, sondern war nun:
code:
1. Zeile 0 2. Zeile 1 3. Zeile 2 4. Zeile 3 5. Zeile 4 6. Zeile 5
also eine Zeile mehr in der Gegend wo er patchen muß, er hat sich also gewundert und nochmal genauer hingeschaut, hat seine "Zeile 3" gefunden die er ersetzen soll und munter weitergemacht.
Hunks sind im normalfall genauso wie "nix" solange alles läuft einfach ignorieren, sie treten sehr schnell auf sobald mal irgendwo eine Dokumentarzeile eingefügt wurde oder ähnliches.
Kommen wir zu den Rejects. Unsere neue Datei D1:
code:
1. Zeile 1 2. Zeile 2 3. Zeile 4 4. Zeile 5
Unsere Zeile "Zeile 3" fehlt also, genau das wo er patchen soll: das schaut so aus:
torsten@torstenpc:/tmp > patch < patch.diff patching file D1 Hunk #1 FAILED at 1. 1 out of 1 hunk FAILED -- saving rejects to file D1.rej
igitt. Aber er sagt ja: "saving rejects to file D1.rej" Also schauen wir da mal rein:
code:
1. * ************** 2. *** 1,5 **** 3. Zeile 1 4. Zeile 2 5.- Zeile 3 6. Zeile 4 7. Zeile 5 8.--- 1,5 ---- 9. Zeile 1 10. Zeile 2 11.+ Zeile 3 neu 12. Zeile 4 13. Zeile 5
nix neues, er sagt nur noch einmal was er machen sollte, nämlich "Zeile 3" löschen und durch "Zeile 3 neu" ersetzen, gibts nur nicht mehr, also bringt er einen Fehler.
In diesem Fall muß man fachlich tätig werden, man muß schauen was hier geändert wurde, denn es könnte ja auch etwas anderes sein, nämlich sowas:
Unsere neue Datei D1:
code:
1. Zeile 1 2. Zeile 2 3. Zeile 3 alt 4. Zeile 4 5. Zeile 5
also statt "Zeile 3" der String "Zeile 3 alt" auch das findet er nicht, die Fehlermeldung ist absolut dieselbe wie oben, man muß also im Detail schauen was hier los ist. In den meisten Fällen wurden nur Leerzeichen eingefügt (er würde bei " Zeile 3" auch abbrechen) oder es wurden Parameter in den Methoden geändert, oder halt sogar der komplette Block neu geschrieben. Wie gesagt, pauschalisieren kann man hier nicht, da muß man genauer reinschauen was da los ist. Man kann sich da aber mit ein wenig Zeit gut einlesen, denn man weiß ja nun wo was wodurch ersetzt werden soll.
Orginal gefunden im Tread[1] von Torsten/WarEagle (weiter unten im Thread)
Beispiel
Mal sehen ...
Hier mal meine Annahme, beispielhaft erläutert durch einen Patch mit drei Patchaufgaben für ein imaginäres Script: Aufgabe sei, bei Zeile 7 angefangen 3 Zeilen zu verändern, dann bei Zeile 20ff 4 Zeilen wegzunehmen, um schließlich am Ende bei Zeile 30ff 10 neu hinzuzufügen
(ff = folgende)
Code:
@@ -7,5 +7,5 @@ mach # zeile 7 - einfach - überhaupt - nichts + bitte + etwas + besonderes jetzt
Folge sollte sein: ab Zeile 7 sind die nächsten 5 Zeilen betroffen. Steht nichts am Beginn der Zeile (auch Leerzeilen!) bleibts wie es ist.
Ein MINUS nimmt diesen Teil der 5 betroffenen Zeilen weg und stattdessen werden die Zeilen mit PLUS am Anfang eingefügt. Im Patch sinds halt zusammen Acht Zeilen, weil die alten und die neuen dastehen
In diesem Fall einfach: 3 raus 3 rein
...nun der nächste Schritt:
Code:
@@ -20,5 +20,5 @@ jetzt #Zeile 20 - sind - wir - also - hier
auch noch einfach: Ab Zeile 20 sind 5 Zeilen betroffen 4 fliegen raus
Der letzte Schritt:
Code:
@@ -30,1 +26,11 @@ Ende...#vor dem Patch Zeile 30 + das + ist + nun + das + ende + der + Erklärung + wie + ichs + verstehe
...mal sehen: Der vorherige (2te) Schritt hatte 4 Zeilen gelöscht und deshalb wird hier im Zweiten Zahlenblock die Zeilenanzahl der veränderten (gepatchten) Datei vorangestellt und nach dem Komma die Anzahl der betroffenen Zeilen. Also -30,... +26,... Die alte 30 war bisher das Ende des zu patchenden Skripts, also sind 11 Zeilen betroffen
- Die Zeile zu Beginn wird nicht verändert, ist aber die einzige "betroffene" im alten Sript
- Zehn Zeilen kommen dazu
- Elf Zeilen sind also "betroffen" aus Sicht des Patches
;-)
Liste
Plugin | Beschreibung |
AC3overDVB | Aktiviert den digitalen Ausgang der DVB Karte |
AC3Switch | Erlaubt das an/abschalten von DD |
AudioChannelSelect | Schaltet zwischen verschiedenen Audiokanälen einer Sendung um |
CutterQueue | Schnitte in Warteschleife abarbeiten |
Disable-Double-Epg-Entrys | Entfernt doppelte EPG Eintraege |
DVD-Archive | Archiviert Aufnahmen über eindeudige Nummern |
EasyInput | Vereinfachte Texteingabe |
Elchi-AIO | Verandert die Optik des OSD |
enAIO | Umbenennen von Aufnahmen und Anzeige deren Länge |
JumpPlay | Automatisches überspringen von Aufnahmeteilen anhand von Schnittmarken |
Keymacros-For-Hidden-Plugins | Macht versteckte Hauptmenüeintrage wieder über Hotkeys verfügbar |
LNB-Sharing | Eine Satellitenleitung zwischen mehreren DVB Karten teilen |
Memory-NoEPG-cxflags | Deaktiviert den EPG-Scan und gibt Speicher frei (nur 4MB) |
MDK-Lirc | für LIRC Mandrake 9.1 RPMs |
noEPG | Verwendung externer EPG Daten für bestimmte Sender |
nrkbd | Verbesserte Texteingabe |
onlypid | Option ausschließlich die PIDs der Sender zu aktualisieren |
PreferredChannel | Bestimmter Kanal beim Start von VDR |
Settime | stellt Uhrzeit anhand der EPG Daten, ohne daß vdr als root laufen muß |
SetupOptionShowValidInput | fügt bei Setupeingaben ein "<" vor dem Wert ein falls ein kleinerer Wert existiert, dito für ">" |
Submenu | Untermenüs für das Befehle-Menü |
svdrp_rename | Aufnahmen mittels SVDRP umbenennen |
WarEagleIcon | Ein paar Icons zu Verschönerung |
Zap | Ausgewählte Sendungen beim Zappen überspringen |