Die Schnittstelle zwischen Subversion und externen Zwei- und
Dreiwege-Vergleichsprogrammen geht zurück bis in eine Zeit, als
sich die kontextabhängigen Vergleichsfähigkeiten von Subversion
allein auf Aufrufe der GNU-diffutils-Werkzeuge stützten,
insbesondere diff und
diff3. Um das von Subversion benötigte
Verhalten zu bekommen, wurden diese Werkzeuge mit mehr als einer
handvoll Optionen und Parametern aufgerufen, von denen die
meisten sehr werkzeugspezifisch waren. Einige Zeit später
entwickelte Subversion seine eigene interne
Vergleichsbibliothek, und als Ausfallsicherung wurden dem
Subversion-Kommandozeilen-Client die Optionen
--diff-cmd
und --diff3-cmd
hinzugefügt, so dass Benutzer auf einfache Art mitteilen
konnten, dass sie die GNU-Werkzeuge diff und diff3 gegenüber der
neumodischen internen Vergleichsbibliothek bevorzugen. Wenn
diese Optionen verwendet wurden, ignorierte Subversion einfach
die interne Vergleichsbibliothek und benutzte die externen
Programmen mit den langen Argumentlisten und dem ganzen
Drumherum. Uns so ist es noch heute.
Es dauerte nicht lange, bis einige Leute feststellten, das diese einfachen Konfigurationsmechanismen zur Festlegung der Benutzung der externen GNU-Werkzeuge diff und diff3, die an einem bestimmten Ort im System liegen, auch für andere Vergleichswerkzeuge verwendet werden können. Schließlich hat Subversion nicht überprüft, ob die Werkzeuge zur Werkzeugkette der GNU diffutils gehören. Der einzige konfigurierbare Aspekt bei der Verwendung dieser externen Werkzeuge ist allerdings der Speicherort im System – weder die Menge der Optionen noch die Reihenfolge der Parameter usw. Subversion übergibt all diese GNU-Werkzeug-Optionen an Ihr externes Vergleichswerkzeug, ohne zu berücksichtigen, ob das Programm sie überhaupt versteht. Und hier hört es für die meisten Benutzer auf, intuitiv zu sein.
Der Schlüssel zur Benutzung externer Zwei- und Dreiwege-Vergleichsprogramme (natürlich anderer als GNU diff und diff3) mit Subversion besteht darin, die Werkzeuge in Skripte „einzupacken“, die die Eingaben von Subversion in etwas umwandeln, das Ihr Werkzeug versteht, und dann die Ausgabe Ihres Werkzeugs in ein von Subversion erwartetes Format umzuwandeln – das Format, das die GNU-Werkzeuge verwendet hätten. Die folgenden Abschnitte behandeln die Besonderheiten dieser Erwartungen.
Anmerkung | |
---|---|
Die Entscheidung, wann ein kontextabhängiges Zwei- oder
Dreiwege-Vergleichsprogramm als Teil einer größeren Operation
von Subversion gestartet wird, obliegt allein Subversion und
wird unter anderem dadurch beeinflusst, ob die Dateien nach
Maßgabe der Eigenschaft |
Subversion 1.5 führt die interaktive Auflösung von
Konflikten ein (in „Konflikte auflösen (Änderungen anderer einarbeiten)“
beschrieben), und eine den Benutzern angebotene Option ist die
Fähigkeit, ein Zusammenführungsprogramm eines Drittanbieters zu
starten. Wenn dieses Vorgehen gewählt wird, ermittelt Subversion
über die Laufzeitoption merge-tool-cmd
den
Namen eines externen Zusammenführungsprogramms und startet dies
mit den entsprechenden Eingabedateien, sofern es gefunden wird.
Dies ist in vielerlei Hinsicht ein Unterschied zum
konfigurierbaren Dreiwege-Vergleichsprogramm. Erstens wird das
Vergleichsprogramm stets verwendet, um Dreiwege-Vergleiche
vorzunehmen, wohingegen das Zusammenführungsprogramm nur dann
angewendet wird, falls das Dreiwege-Vergleichsprogramm einen
Konflikt entdeckt hat. Zweitens ist die Schnittstelle sehr viel
sauberer – Ihr konfiguriertes Zusammenführungsprogramm
braucht nur vier Pfadangaben als Kommandozeilenparameter zu
akzeptieren: die Basisdatei, die „fremde“ Datei
(die die Änderungen aus dem Projektarchiv enthält), die
„eigene“ Datei (die lokale Änderungen enthält) und
den Pfad der Datei, in der der endgültige Inhalt nach
Konfliktauflösung gespeichert werden soll.
Subversion ruft externe diff-Programme mit Parametern auf, die für GNU diff passen und erwartet lediglich, dass das externe Programm mit einem Erfolg signalisierenden Rückgabewert zurückkommt. Für die meisten alternativen diff-Programme sind nur die Argumente an sechster und siebter Stelle interessant – die Pfade der Dateien, die die linke bzw. rechte Seite des Vergleichs repräsentieren. Beachten Sie, dass Subversion das diff-Programm jeweils einmal pro modifizierter Datei aufruft, die die Subversion-Operation berührt, falls Ihr Programm also asynchron läuft (oder als „Hintergrundprozess“), könnte es sein, dass mehrere Instanzen gleichzeitig ausgeführt werden. Schließlich erwartet Subversion, dass Ihr Programm den Rückgabewert 1 liefert, falls es Unterschiede entdeckt hat, oder 0, falls nicht – jeder andere Rückgabewert wird als fataler Fehler angesehen. [48]
Beispiel 7.2, „diffwrap.py“ und Beispiel 7.3, „diffwrap.bat“ sind „Verpackungs“-Vorlagen für externe diff-Werkzeuge in den Skriptsprachen Python bzw. Windows-Batch.
Beispiel 7.2. diffwrap.py
#!/usr/bin/env python import sys import os # Geben Sie hier Ihr bevorzugtes diff-Programm an. DIFF = "/usr/local/bin/my-diff-tool" # Subversion liefert die benötigten Pfade als die letzten beiden Parameter. LEFT = sys.argv[-2] RIGHT = sys.argv[-1] # Aufruf des diff-Befehls (ändern Sie die folgende Zeile passend für # Ihr diff-Programm). cmd = [DIFF, '--left', LEFT, '--right', RIGHT] os.execv(cmd[0], cmd) # Rückgabewert 0 falls keine Unterschiede, 1 falls doch. # Jeder andere Rückgabewert wird als fatal betrachtet.
Beispiel 7.3. diffwrap.bat
@ECHO OFF REM Geben Sie hier Ihr bevorzugtes diff-Programm an. SET DIFF="C:\Program Files\Funky Stuff\My Diff Tool.exe" REM Subversion liefert die benötigten Pfade als die letzten beiden Parameter. REM Das sind die Parameter 6 und 7 (außer Sie benutzen svn diff -x, dann REM ist alles möglich). SET LEFT=%6 SET RIGHT=%7 REM Aufruf des diff-Befehls (ändern Sie die folgende Zeile passend für REM Ihr diff-Programm). %DIFF% --left %LEFT% --right %RIGHT% REM Rückgabewert 0 falls keine Unterschiede, 1 falls doch. REM Jeder andere Rückgabewert wird als fatal betrachtet.
Subversion ruft externe Zusammenführungsprogramme mit Parametern auf, die für das GNU diff3-Werkzeug passen und erwartet, dass das externe Programm einen Erfolg signalisierenden Rückgabewert liefert und der vollständige Inhalt als Ergebnis der beendeten Zusammenführung in den Standardausgabestrom geschrieben wird (damit Subversion diesen in die entsprechende Datei unter Versionskontrolle umleiten kann). Für die meisten alternativen Zusammenführungsprogramme sind nur die Argumente an neunter, zehnter und elfter Stelle interessant, die den Pfaden der Dateien entsprechen, die die Eingaben „eigene“, „ältere“ bzw. „fremde“ repräsentieren. Beachten Sie, dass Ihr Skript nicht beendet werden darf, bevor die Ausgabe an Subversion abgeliefert wurde, da Subversion auf die Ausgabe Ihres Zusammenführungsprogramms angewiesen ist. Wenn es schließlich beendet wird, sollte es einen Rückgabewert 0 im Erfolgsfall und 1 bei verbleibenden Konflikten zurückgeben – jeder andere Rückgabewert wird als fataler Fehler angesehen.
Beispiel 7.4, „diff3wrap.py“ und Beispiel 7.5, „diff3wrap.bat“ sind „Verpackungs“-Vorlagen für externe Zusammenführungsprogramme in den Skriptsprachen Python bzw. Windows-Batch.
Beispiel 7.4. diff3wrap.py
#!/usr/bin/env python import sys import os # Geben Sie hier Ihr bevorzugtes diff-Programm an. DIFF3 = "/usr/local/bin/my-merge-tool" # Subversion liefert die benötigten Pfade als die letzten drei Parameter. MINE = sys.argv[-3] OLDER = sys.argv[-2] YOURS = sys.argv[-1] # Aufruf des merge-Befehls (ändern Sie die folgende Zeile passend für # Ihr merge-Programm). cmd = [DIFF3, '--older', OLDER, '--mine', MINE, '--yours', YOURS] os.execv(cmd[0], cmd) # Nach der Zusammenführung muss dieses Skript den Inhalt der # zusammengeführten Datei nach stdout schreiben. Machen Sie das, wie # Sie wollen. # Rückgabewert 0 bei erfolgreicher Zusammenführung, 1 falls noch # unaufgelöste Konflikte vorhanden. Alles andere wird als fatal # betrachtet,
Beispiel 7.5. diff3wrap.bat
@ECHO OFF REM Geben Sie hier Ihr bevorzugtes diff-Programm an. SET DIFF3="C:\Program Files\Funky Stuff\My Merge Tool.exe" REM Subversion liefert die benötigten Pfade als die letzten drei Parameter. REM Das sind die Parameter 9, 10 und 11. Allerdings haben wir zu einem REM gegebenen Zeitpunkt nur Zugriff auf neun Parameter, so dass wir REM unser Fenster aus neun Parametern zweimal verschieben, um das zu REM bekommen, was wir benötigen. SHIFT SHIFT SET MINE=%7 SET OLDER=%8 SET YOURS=%9 REM Aufruf des merge-Befehls (ändern Sie die folgende Zeile passend für REM Ihr merge-Programm). %DIFF3% --older %OLDER% --mine %MINE% --yours %YOURS% REM Nach der Zusammenführung muss dieses Skript den Inhalt der REM zusammengeführten Datei nach stdout schreiben. Machen Sie das, wie REM Sie wollen. REM Rückgabewert 0 bei erfolgreicher Zusammenführung, 1 falls noch REM unaufgelöste Konflikte vorhanden. Alles andere wird als fatal REM betrachtet,
[48] Das Handbuch zu GNU diff beschreibt es so: „Ein Rückgabewert 0 bedeutet, dass keine Unterschiede gefunden wurden, 1 bedeutet, dass einige Unterschiede gefunden wurden und 2 bedeutet Ärger.“