Externals-Definitionen

Manchmal kann es nützlich sein, eine Arbeitskopie anzulegen, die aus einer Anzahl verschiedener Checkouts besteht. Es könnte beispielsweise sein, dass Sie verschiedene Unterverzeichnisse aus verschiedenen Bereichen des Projektarchivs haben möchten oder vielleicht sogar aus völlig verschiedenen Projektarchiven. Natürlich könnten Sie ein solches Szenario manuell erstellen – indem Sie svn checkout verwenden, um die verschachtelte Verzeichnisstruktur Ihrer Wahl anzulegen. Wenn diese Struktur jedoch für jeden Benutzer Ihres Projektarchivs wichtig ist, müsste jeder andere Benutzer dieselben Checkouts ausführen wie Sie.

Glücklicherweise unterstützt Subversion Externals-Definitionen. Eine Externals-Definition ist eine Abbildung eines lokalen Verzeichnisses auf den URL – und idealerweise eine bestimmte Revision – eines versionierten Verzeichnisses. In Subversion deklarieren Sie Externals-Definitionen in Gruppen unter Verwendung der Eigenschaft svn:externals. Sie können diese Eigenschaft mit svn propset oder svn propedit erstellen oder ändern (siehe „Ändern von Eigenschaften“). Sie kann jedem versionierten Verzeichnis zugeordnet werden, und ihr Wert beschreibt sowohl die Adresse des externen Projektarchivs als auch das Verzeichnis auf dem Client, in dem diese Adresse ausgecheckt werden soll.

Sobald sie mit einem versionierten Verzeichnis verknüpft ist, bietet die Eigenschaft svn:externals den Komfort, dass jeder, der eine Arbeitskopie mit diesem Verzeichnis auscheckt, die Vorteile der Externals-Definition mitbekommt. Mit anderen Worten: Sobald sich jemand die Mühe gemacht hat, die verschachtelte Struktur der Arbeitskopie zu definieren, braucht sich niemand mehr darum zu kümmern – Subversion checkt nach der ursprünglichen Arbeitskopie automatisch die externen Arbeitskopien aus.

[Warnung] Warnung

Die relativen Zielverzeichnisse von Externals-Definitionen dürfen nicht bereits auf Ihrem oder dem Systemen anderer Benutzer vorhanden sein – Subversion erzeugt sie beim Auschecken der externen Arbeitskopie.

Mit dem Design der Externals-Definition bekommen Sie auch alle normalen Vorteile der Subversion-Eigenschaften. Die Definitionen sind versioniert. Falls Sie eine Externals-Definition ändern müssen, können Sie das mit den üblichen Unterbefehlen zum Ändern von Eigenschaften bewerkstelligen. Wenn Sie eine Änderung an der Eigenschaft svn:externals übergeben, wird Subversion beim nächsten svn update die ausgecheckten Elemente mit der geänderten Externals-Definition synchronisieren. Dasselbe passiert, wenn andere ihre Arbeitskopie aktualisieren und Ihre Änderungen an der Externals-Definition erhalten.

[Tipp] Tipp

Da die Eigenschaft svn:externals einen mehrzeiligen Wert besitzt, empfehlen wir dringend, dass Sie svn propedit statt svn propset verwenden.

Subversion-Versionen vor 1.5 akzeptieren ein Format für Externals-Definitionen, welches eine mehrzeilige Tabelle ist, die aus Unterverzeichnissen (relativ zum versionierten Verzeichnis, mit dem die Eigenschaft verknüpft ist), optionalen Revisions-Flags und vollqualifizierten, absoluten Subversion-Projektarchiv-URLs besteht. Ein Beispiel könnte so aussehen:

$ svn propget svn:externals calc
third-party/sounds             http://svn.example.com/repos/sounds
third-party/skins -r148        http://svn.example.com/skinproj
third-party/skins/toolkit -r21 http://svn.example.com/skin-maker

Wenn jemand eine Arbeitskopie des Verzeichnisses calc aus dem obigen Beispiel auscheckt, fährt Subversion damit fort, die Objekte in der Externals-Definition auszuchecken.

$ svn checkout http://svn.example.com/repos/calc
A  calc
A  calc/Makefile
A  calc/integer.c
A  calc/button.c
Ausgecheckt. Revision 148.

Hole externen Verweis nach calc/third-party/sounds
A  calc/third-party/sounds/ding.ogg
A  calc/third-party/sounds/dong.ogg
A  calc/third-party/sounds/clang.ogg
…
A  calc/third-party/sounds/bang.ogg
A  calc/third-party/sounds/twang.ogg
Ausgecheckt. Revision 14.

Hole externen Verweis nach calc/third-party/skins
…

Seit Subversion 1.5 wird jedoch ein neues Format der Eigenschaft svn:externals unterstützt. Die Externals-Definitionen sind immer noch mehrzeilig, jedoch hat sich die Reihenfolge und das Format der verschiedenen Informationen geändert. Die neue Syntax lehnt sich nun mehr an die Reihenfolge der Argumente an, die Sie svn checkout übergeben: Zunächst kommen die Revisions-Flags, dann der URL des externen Subversion-Projektarchivs und schließlich das relative lokale Unterverzeichnis. Beachten Sie jedoch, dass wir diesmal nicht von vollqualifizierten, absoluten Subversion-Projektarchiv-URLs gesprochen haben. Das liegt daran, dass das neue Format relative URLs und URLs mit Peg-Revisionen unterstützt. Das vorausgegangene Beispiel einer Externals-Definition könnte in Subversion 1.5 so aussehen:

$ svn propget svn:externals calc
      http://svn.example.com/repos/sounds third-party/sounds
-r148 http://svn.example.com/skinproj third-party/skins
-r21  http://svn.example.com/skin-maker third-party/skins/toolkit

Bei Verwendung der Syntax für Peg-Revisionen (die wir detailliert in „Peg- und operative Revisionen“ behandeln), könnte es so aussehen:

$ svn propget svn:externals calc
http://svn.example.com/repos/sounds third-party/sounds
http://svn.example.com/skinproj@148 third-party/skins
http://svn.example.com/skin-maker@21 third-party/skins/toolkit
[Tipp] Tipp

Sie sollten ernsthaft erwägen, explizite Revisionsnummern in all Ihren Externals-Definitionen zu verwenden. Wenn Sie das tun, bedeutet dies, dass Sie entscheiden, wann ein anderer Schnappschuss mit externen Informationen herangezogen werden soll und welcher Schnappschuss genau. Außer der Vermeidung überraschender Änderungen an Projektarchiven Dritter, auf die Sie keinen Einfluss haben, bedeuten explizite Revisionsnummern, dass beim Zurücksetzen Ihrer Arbeitskopie auf eine frühere Revision auch die Externals-Definitionen auf den entsprechenden früheren Stand zurückgesetzt werden, was wiederum bedeutet, dass die externen Arbeitskopien derart aktualisiert werden, dass sie so aussehen wie zum Zeitpunkt Ihres Projektarchivs der früheren Revision. Für Software-Projekte kann das den Unterschied zwischen einem erfolgreichen und einem gescheiterten Build eines älteren Schnappschusses Ihrer komplexen Codebasis ausmachen.

Bei den meisten Projektarchiven bewirken die drei Formate der Externals-Definition letztendlich dasselbe. Alle bringen die gleichen Vorteile. Leider bringen alle aber auch die gleichen Ärgernisse. Da die Definitionen absolute URLs verwenden, hat das Kopieren oder Verschieben eines damit verknüpften Verzeichnisses keine Auswirkungen auf das, was als extern ausgescheckt wird (obwohl natürlich das relative lokale Zielverzeichnis mit dem umbenannten Verzeichnis mitwandert). Das kann in bestimmten Situationen verwirrend – sogar frustrierend – sein. Nehmen wir beispielsweise an, dass Sie ganz oben ein Verzeichnis namens my-project haben und eine Externals-Definition auf eins seiner Unterverzeichnisse erstellt haben (my-project/some-dir), welches wiederum die letzte Revision eines anderen Unterverzeichnisses verfolgt (my-project/external-dir).

$ svn checkout http://svn.example.com/projects .
A    my-project
A    my-project/some-dir
A    my-project/external-dir
…
Hole externen Verweis nach »my-project/some-dir/subdir«
Externer Verweis ausgecheckt, Revision 11.

Ausgecheckt, Revision 11.
$ svn propget svn:externals my-project/some-dir
subdir http://svn.example.com/projects/my-project/external-dir

$

Nun benennen Sie mit svn move das Verzeichnis my-project um. Zu diesem Zeitpunkt verweist Ihre Externals-Definition noch immer auf einen Pfad unterhalb des Verzeichnisses my-project, obwohl das Verzeichnis nicht mehr existiert.

$ svn move -q my-project renamed-project
$ svn commit -m "Rename my-project to renamed-project."
Lösche         my-project
Hinzufügen     renamed-project

Revision 12 übertragen.
$ svn update

Hole externen Verweis nach »renamed-project/some-dir/subdir«
svn: Zielpfad existiert nicht
$

Absolute URLs können außerdem Probleme bei Projektarchiven hervorrufen, die über verschiedene URL-Schemata verfügbar sind. Falls Ihr Subversion-Server so konfiguriert sein sollte, dass jeder das Projektarchiv über http:// oder https:// auschecken darf, Übertragungen jedoch nur über https:// erlaubt sind, haben Sie ein interessantes Problem. Wenn Ihre Externals-Definitionen die http://-Form der Projektarchiv-URLs verwenden, werden Sie nicht im Stande sein, irgend etwas aus den mit diesen Externals erzeugten Arbeitskopien zu übertragen. Wenn Sie andererseits die https://-Form der URLs verwenden, kann jemand, der mit http:// auscheckt, da sein Client https:// nicht unterstützt, die externen Verweise nicht heranziehen. Beachten Sie ferner, dass beim Umhängen Ihrer Arbeitskopie (mit svn switch und der Option --relocate) die Externals-Definitionen nicht automatisch umgehängt werden.

Subversion 1.5 unternimmt einen riesigen Schritt, um diese Frustrationen zu lindern. Wie bereits früher erwähnt wurde, können die URLs im neuen Externals-Format relativ sein, und Subversion stellt eine besondere Syntax zur Verfügung, um verschiedene Arten relativer URLs darzustellen.

../

Relativ zum URL des Verzeichnisses, an dem die Eigenschaft svn:externals gesetzt ist

^/

Relativ zur Wurzel des Projektarchivs, in dem die Eigenschaft svn:externals versioniert ist

//

Relativ zum Schema des URL des Verzeichnisses, an dem die Eigenschaft svn:externals gesetzt ist

/

Relativ zum Wurzel-URL des Servers, auf dem die Eigenschaft svn:externals versioniert ist

Wenn wir uns nun ein viertes Mal das vorangegangene Beispiel mit der Externals-Definition ansehen und von der neuen absoluten URL-Syntax auf verschiedene Weise Gebrauch machen, könnten wir nun das sehen:

$ svn propget svn:externals calc
^/sounds third-party/sounds
/skinproj@148 third-party/skins
//svn.example.com/skin-maker@21 third-party/skins/toolkit

Subversions Unterstützung für Externals-Definitionen bleibt aber trotzdem alles andere als ideal. Eine Externals-Definition kann nur auf Verzeichnisse zeigen, nicht auf Dateien. Auch darf der lokale Unterverzeichnis-Teil keine ..-Verweise auf Elternverzeichnisse enthalten (etwa ../../skins/myskin). Die größte Enttäuschung ist vielleicht, dass Arbeitskopien, die mit Unterstützung von Externals-Definitionen erzeugt wurden, nach wie vor getrennt sind von der primären Arbeitskopie (auf deren versionierten Verzeichnissen die Eigenschaft svn:externals ursprünglich gesetzt wurde). Und Subversion arbeitet nur auf nicht-disjunkten Arbeitskopien genau. Wenn Sie beispielsweise Änderungen übertragen möchten, die Sie in einer oder mehreren dieser externen Arbeitskopien vorgenommen haben, müssen Sie für diese Arbeitskopien explizit svn commit aufrufen – das Übertragen der primären Arbeitskopie greift nicht auf irgendwelche externen über.

Wir haben bereits einige der Mängel des alten Formats von svn:externals und die Verbesserungen durch das neue Format von Subversion 1.5 erwähnt. Seien Sie jedoch vorsichtig, dass Sie bei Verwendung des neuen Formats nicht versehentlich Probleme für andere verursachen, die mit älteren Subversion-Clients auf Ihr Projektarchiv zugreifen wollen. Während Clients von Subversion 1.5 weiterhin das ursprüngliche Format der Externals-Definitionen verstehen und unterstützen, sind ältere Clients nicht in der Lage, das neue Format korrekt zu verarbeiten.

Neben den Befehlen svn checkout, svn update, svn switch und svn export, welche die disjunkten (oder unzusammenhängenden) Unterverzeichnisse mit den ausgecheckten Externals eigentlich verwalten, berücksichtigt auch der Befehl svn status Externals-Definitionen. Er zeigt für die disjunkten externen Unterverzeichnisse einen Zustandscode X an und durchläuft dann diese Verzeichnisse, um den Zustand der eigentlichen externen Objekte anzuzeigen. Sie können jedem dieser Unterbefehle die Option --ignore-externals mitgeben, um die Bearbeitung der Externals-Definitionen zu unterbinden.