Applikationskonfiguation mit XML Dateien

Windows Nutzer kennen die typischen INI-Files, in denen Werte zur Laufzeit in eine Applikation geladen werden können. Dieses Konzept hat mit der starken Verbreitung von XML eine neue Renaissance erfahren. In diesem Zusammenhang sind die Paradigmen Don’t Repeat Yourself (DRY) und Convention Over Configuration (COC) zum Maß der Dinge avanciert. Die freien Frameworks Ruby On Rails und Maven 2, gehören zu den bekanntesten Tools, die mit dieser Technologie arbeiten.

In Hochsprachen wie C oder Java müssen die Quelldateien in ein binäres Format gebracht werden, dieser Vorgang kann je nach Umfang eines Programms, einiges an Rechenzeit verbrauchen. Um verschiedene Parameter einer Anwendung zur Laufzeit verändern zu können, wurde eine Möglichkeit geschaffen, die Werte aus einfachen Textdateien lesen kann.

Damit erübrigt sich das Kompilieren, da die Initialisierung der Variablen nun nicht mehr im Quelltext hinterlegt ist. Hinter dem Begriff DRY verbirgt daher nichts anderes, als die Vermeidung unnötiger und sich wiederholender Arbeitsschritte. COC erweitert diese Idee um die Forderung, dass jede Variable die konfiguriert werden kann, mit einem Defaultwert vorbelegt ist. In der Konfigurationsdatei werden nur noch Parameter angegeben, die vom vorgegebenen Standart abweichen. Die Übersichtlichkeit und Lesbarkeit der Konfiguration steigt somit rapide an, da es im praktischen Einsatz sehr unwahrscheinlich ist, dass alle Konfigurationsmöglichkeiten überschreiben werden müssen. Um effektiv mit den Paradigmen DRY und COC arbeiten zu können ist es, wichtig die möglichen Konfigurationsparameter und deren Bedeutung zu kennen. Daher sollte an einer ausführlichen Dokumentation nicht gespart werden.

Für PHP ist die Verwendung von XML als Konfigurationsdatei aus zwei Gründen sinnvoll. Die wichtigste Eigenschaft ist vor allem eine Trennung von internen Applikationszuständen, die dem Anwender verborgen bleiben sollen. Ausschließlich die notwendigen Anpassungen an das Zielsystem, wie Datenbankanbindungen und Layouteinstellungen werden zentral in der Konfigurationsdatei vorgehalten. Der zweite Aspekt, der für XML spricht, ist die Möglichkeit Daten einfach und lesbar zu strukturieren. So praktisch die Nutzung von XML auch ist, so soll die davon ausgehende Gefahr nicht unterschlagen werden. Ohne geeignete Maßnahmen können die Daten der Konfigurationsdatei von Dritten ausgespäht werden. Der Aspekt über die Sicherheit wird im Anschluss an eine kurze Einführung zu XML besprochen.

XML

Die Extensible Markup Language (XML) wird für die unterschiedlichsten Aufgaben verwendet. Der Grund liegt in der einfachen Möglichkeit, Strukturen und Daten zu modellieren. Im Gegensatz zu HTML sind die Tags nicht mehr fest vorgeschrieben, sondern können frei gewählt werden. Genauso verhält es sich auch mit den Attributen für die Elemente. Damit dies auch gelingt, muss eine XML-Datei verschiedenen Regeln entsprechen. Werden die Regeln eingehalten, spricht man von einem wohlgeformten Dokument. Einige XML Editoren verweigern das Abspeichern nicht wohlgeformter Dokumente.

Um festzustellen, ob das Dokument auch der vorgegebenen Datenstruktur entspricht, kann entweder gegen eine Dokument Type Definition (DTD) oder ein XML Schema (XSD) validiert werden. Entwicklungsumgebungen greifen oft auf die angegebene DTD bzw. XSD Datei zu, um eine intelligente Codevervollständigung anbieten zu können. Wer mehr über das breite Spektrum der Extensible Markup Language erfahren möchte, dem sei andieser Stelle die einschlägige iteratur zur Thematik Herz gelegt, da dieser Artikel lediglich die Grundlagen von XML streift und seinen Fokus auf die Verwendung mit PHP legt.

Regeln für wohlgeformte XML Dokumente:

  • Das Wurzel-Element (Root) darf nur einmalig im Dokument vorkommen
  • Tags werden stets kleingeschrieben und sind durch die Zeichen < > begrenzt
  • Namen für Tags dürfen nur mit _ und Buchstaben beginnen, anschließend können Zahlen,
  • Buchstaben, Punkte, Bindestriche und Unterstriche verwendet werden.
  • Jedes geöffnete Tag muss geschlossen werden, Beispiel:
  • Verschachtelte Tags müssen immer in der Reihenfolge geschlossen werden wie sie geöffnet werden
  • Die Sondernotation für Elemente, die kein schließendes Tag benötigen, nennt sich leeres Tag und
  • hat folgende Syntax:
  • Werte für Attribute müssen durch Anführungszeichen eingeschlossen werden

Es existiert mittlerweile eine erhebliche Menge an XML Editoren, die um die Gunst der Nutzer buhlen. Im kommerziellen Umfeld ist der XMLSpy von Altova der absolute Platzhirsch. XMLSpy beherrscht sämtliche Disziplinen, die im Umgang mit XML notwendig sind, dafür müssen für die Anschaffung der Enterprise Version allerdings ca. 800€ eingeplant werden. Wer lieber auf Freeware zurückgreifen möchte, findet in Notepad++ einen sehr vielseitigen Editor. Verfechter von Microsoft können auf eine sehr gelungene Anwendung mit dem Namen XML Notepad zurückgreifen. Unter den IDE’s ist vor allem Eclipse zu nennen, das neben XML auch ein sehr leistungsstarkes PHP-Plugin bietet. Gerade die Tatsache, das PHP und XML mit ein und demselben Werkzeug bearbeitet werden ist maßgebend für einen flüssigen Arbeitsablauf.

Datenbank vs. XML

Sicherlich wird sich der ein oder andere Leser die Frage stellen, wieso die in der XML gespeicherten Daten nicht einfach in eine Datenbanktabelle ausgelagert werden. Die meisten Applikationen benötigen generell von Haus aus eine Datenbank zur Datenhaltung, also kann diese, die Aufgabe der Konfiguration mit übernehmen. Die Verwaltung komplexer Datenbanksysteme ist dank geeigneter Werkzeuge wie beispielsweise phpMyAdmin auch relativ gut beherrschbar. Da die typischen Verbindungsparameter wie Host und Datenbankname nicht in der Datenbank gespeichert werden können, müssen diese in der Anwendung vorgehalten werden. Um alle notwendigen Einstellungen nicht in der gesamten Applikation zu verstreuen, hat sich das DRY und COC Prinzip etabliert. Die mitgelieferten Installationsroutinen zum Deployen der Programme besitzen einen entscheidenden Nachteil.

Meist wird eine solches System auf einem lokalen Testsystem installiert und soll dann später per FTP auf den Webserver übertragen werden. Zu 99% aller Fälle beginnt nun das große Suchen nach den Einstellungen, die angepasst werden müssen, um die Applikation auf dem Webserver lauffähig zu bekommen. Selbst ein kompletter Database -Dump vom Testsystem auf Produktionsumgebung beherbergt stets die Gefahr falsche Konfigurationseinstellungen mit zu übertragen. Das Szenario lässt sich noch weiter steigern, mit der Annahme eines Datenbank Clusters und verschiedener Replikationsstrategien. Der Abschnitt XML und PHP zeigt in der Beispielanwendung wie zwischen Testumgebung und Produktionssystem unterschieden werden kann. Für kleinere Projekte, kann es durchaus sinnvoll sein komplett auf Datenbanken zu verzichten und die gesamte Datenhaltung über XML zu organisieren. Das erspart zum einen den Aufwand der Datenbankkonfiguration und vereinfacht das Backup der Datenhaltung. Eine simpler Link oder Terminverwaltung kann ohne Content Management System (CMS) auch problemlos vom Kunden gepflegt werden. Vorraussetzung ist, dass die Datenmenge gering ist und der Anwender ein geeignetes Maß an Erfahrung mitbringt. Unter Verwendung dieser Technologie lassen sich äußerst kostengünstig Projekte realisieren.

Sicherheitsaspekte

Da es sich bei XML um eine einfache Textdatei handelt, kann sie problemlos von Menschen gelesen und interpretiert werden. Wenn der Name und der Pfad zur Datei auf dem Server bekannt ist, wird beim Aufruf in aller Regel der Inhalt der Datei im Webbrowser angezeigt. Dieses Verhalten ist natürlich für unseren Fall äußerst problematisch, da in der Datei wichtige Daten hinterlegt sind, die nicht für Dritte bestimmt sind. Das Finden solcher Informationen kann durch unglückliche Dateinamen begünstigt werden, da mit sehr hoher Wahrscheinlichkeit bei einem Angriff zuerst config.xml im Root Verzeichnis des Webservers ausprobiert wird. Das Ergebnis einer solchen Abfrage ist im Screenshot_01 zu sehen.

Ein wirksamer Schutz besteht aus mehreren Schritten. Die Grundidee ist zuerst die config.xml gut zu verstecken. Damit das Versteck auch sicher ist, wird es mit einem simplen aber effektiven Zugriffsschutz verschlossen. Als Erstes wird ein Verzeichnis unterhalb des Root im Projekt mit dem Namen var angelegt. Dieses Verzeichnis darf nicht in der robots.txt mit auftauchen, damit würde man einem potenziellen Angreifer eine Wegbeschreibung in die Hand geben. Es besteht auch keine Gefahr für eine unbeabsichtigte Indizierung des Verzeichnisses durch eine Suchmaschine, da die nur den Links auf URL-Ebene folgen kann. Wer dennoch auf Nummer sicher gehen möchte, kann in var eine eigenständige robots.txt erstellen, die sämtliche Suchmaschinen aussperrt. Dazu genügen die folgenden Einträge:

User-agent: *
Disallow: *

Die beiden Zeilen gelten für alle Dateien und Verzeichnisse, die sich im selben Directory wie die robots.txt befindet. Die Indexierung wird allen Suchmaschinen untersagt. Wichtig ist das es außerhalb des geschützten Verzeichnisses, keinen Hinweis auf dessen Existenz vorhanden ist. Im zweiten Schritt wird eine index.php in var erzeugt. Der gewünschte Effekt ist, dass nun nicht mehr sämtliche Files des Verzeichnisses aufgelistet werden, sondern automatisch die index.php aufgerufen wird. Die Index -File kann leer bleiben oder einen redirect auf die Domain des eigenen Webauftritts haben.

$url = "Location: http://".$_SERVER['SERVER_NAME'];
header("HTTP/1.1 301 Moved Permanently");
header('$url');
header("Connection: close");

Zu Beginn des Listings wird die Zieladresse festgelegt, die in unserem Fall automatisch die Server URL zugewiesen bekommt. Einige Provider haben ihre Webserver mit einem ähnlichen Verhalten konfiguriert. Der Provider 1 und 1 zeigt beispielsweise bei fehlendem Index eine leere Seite an. Die übrigen Funktionen steuern das HTTP Protokoll. Die Header – Funktion ist ein sehr mächtiges Werkzeug, das bei seiner Verwendung einige Sorgfalt erfordert. Nur wenige Operationen sind vor den Funktionen gestattet. Die Verwendung von echo gehört zu den beliebten Fehlern im Umgang mit header. Wer diese Maßnahmen beachtet, kann getrost seine Konfiguration in eine XML-Datei auslagern, ohne böse Überraschungen zu erleben.

XML und PHP

Ab der Version 5 ist die SimpleXML Extension Bestandteil von PHP und ermöglicht, damit eine sehr einfache Art und Weise XML Dateien zu verarbeiten. Zur Demonstration greife ich auf ein kleines Beispiel zurück, das die Datenbankkonfiguration aus einer XML-Datei ausliest und anschließend Werte von einer Datenbank ausgibt. Der Aufbau der Datenbank ist über das Listing database.sql ersichtlich, das auch gleich zum Anlegen der Datenbank verwendet werden kann.

CREATE TABLE IF NOT EXISTS links (
   url char(255) NOT NULL,
   category char(255) NOT NULL DEFAULT 'sonstige',
   description TEXT
);

Die Ausgabe des Listings config.xml ist im Screenshot_01 bereits zu sehen. Der Wurzelknoten ist als dessen Kind angefügt wurde. In dem Tag wird das verwendete Datenbankmanagmentsystem angegeben. Wegen der vielen möglichen Umgebungen in die eine PHP Applikation installiert werden kann besteht der Wunsch nach Flexibilität. Auf das Element wird üblicherweise ein Factory Pattern [8] angewendet, um die verwendete Datenbank problemlos ohne Quelltextänderungen austauschen zu können. Diese Option ist hier nur der Vollständigkeit erwähnt, da eine genauere Erläuterung den Rahmen des Artikels übersteigt.

Spannend ist das folgende Tag . Hier werden zwei Verbindungen gespeichert. Die Überlegung ist, eine lokale (Testumgebung) und eine Server-Konfiguration (Produktionsumgebung) zu definieren. Das erspart bei der Übertragung der der Projektdateien zum Server eine vorherige Anpassung an die dort vorhandene Datenbank. Das Tag besitzt als Attribute name und prefix. Mit name ist der Datenbankname gemeint, während prefix eine „Vorsilbe“ der Tabellen definiert. Ein Präfix ist stets optional und gestattet eine mehrfache Installation der Anwendung in der gleichen Datenbank. Das ergibt sich aus der Forderung, das Tabellennamen stets eindeutig sein müssen und nicht mehrfach vergeben werden dürfen. Die Elemente Host, User und Login sind selbstsprechend. Type ist der Indikator, welcher uns verrät ob es sich um die Test- oder die Produktionsumgebung handelt. Eine spätere Abfrage der Variable $_SERVER['SERVER_NAME'] == “localhost”; stellt die Prüfbedingung für das Zielsystem. Soweit nur zur Vorbereitung.

Der erste Schritt besteht darin, die zu verarbeitende Datei zu öffnen. Dies geschieht mit der Anweisung: $config = simplexml_load_file(“config.xml”); in der die Variable $config steht nun der gesamte Inhalt aus config.xml zur Verfügung. Um dbms auslesen zu können, wird folgende Zeile benötigt: $dbms = $config->dbms; für den Fall das es mehrere Tag’s mit derselben Bezeichnung gibt kann der gestammte Inhalt sequentiell ausgelesen werden.

foreach ($config->connection->database as $xmlvars) {
   $database = $xmlvars['prefix']." ".$xmlvars['name'];
   $host = $xmlvars->host;
   $user = $xmlvars->user;
   $login = $xmlvars->login;
}

Das Beispiel iteriert mit einer foreach Schleife über dem Kindelement , das sich unterhalb von befindet. In dem assoziativen Array $xmlvars, kann nun auf die einzelnen Element zugegriffen werden. Wie in Zeile 01 bereits zu erkennen ist, muss nicht zwangsläufig die gesamte XML Datei ab dem Root- Element verarbeitet werden, um ein Ergebnis zu erzielen. Die Bezeichnungen aus dem Beispiel leiten sich aus den Namen der XML-Elemente ab. In Zeile 02 wird demonstriert, wie Attribute eines Tags ausgelesen werden. In den Zeilen 03 bis 05 werden die Werte der Kindelemente , und den Entsprechenden Variablen zugewiesen. Würde man beabsichtigen in dieser Konstellation auf ein Attribut von zu zugreifen ist die korrekte Syntax: $hostAttribut = $xmlvars->host['attribut']. Wie man sieht, enthalten die wenigen Zeilen des Listings den Großteil des notwenigen Know-hows für den praktischen Einsatz. Die Logik für die Unterscheidung zwischen Webserver und lokaler Installation erweitert das vorangegangene Listing und ist zwischen die Zeile 01 und 02 einzufügen.

if($_SERVER['SERVER_NAME'] == "localhost" && $xmlvars->type == "offline") {
   $database = $xmlvars ['name'];
   $host = $xmlvars->host;
   $user = $xmlvars->user;
   $login = $xmlvars->login;
   break;
}

Die IF-Anweisung wird erst dann ausgeführt, wenn die Server-Variable den Wert localhost annimmt. Alternativ kann auch anstatt des Domainnamenes die IP-Adresse zur Identifizierung des Rechners herangezogen werden. Um den korrekten Datensatz an den ermittelten Server zu binden, wird eine zweite Prüfbedingung benötigt. In iesem Beispiel werden die korrekten Einstellungen über das Element erkannt. Sobald beide Kriterien erfüllt sind, können die Variablen ihre Werte aufnehmen. Die break Anweisung sorgt dafür, dass die foreach Schleife nach der Initialisierung verlassen wird. Das verhindert ein versehentliches überschreiben der Werte durch den nächsten Datensatz in einem weiteren Schleifendurchlauf. Das würde zwangsläufig passieren, da der nachfolgende Datensatz keiner Prüfbedingung standhalten muss. Wenn mehrere Server zu berücksichtigen sind, kann die IF–Anweisung um den ifelse Ausdruck erweitert werden. Selbstverständlich lässt sich das Konstrukt auch durch eine switch Kontrollstruktur abbilden. Eine Datenbankabfrage sowie die Ausgabe werden durch die üblichen Bordmittel von PHP realisiert. Die auf der Heft CD beigefügten Listings sind vollständig und zeigen, wie die gesamte Applikation arbeitet.

Der aufmerksame Leser erwartet, sicherlich an dieser Stelle geeignete Möglichkeiten in eine XML-Datei zu schreiben. Diese Erwartung muss leider enttäuscht werden, da die SimpleXML Extension keine Funktionen zum Schreiben von Dateien bereitstellt. Dies ist auch nicht notwendig, da die bereits in PHP vorhandenen Möglichkeiten völlig ausreichend sind. Dafür können in der Verarbeitungslogik Reguläre Ausdrücke, Stringoperationen und Sortieralgorithmen benutzt werden. Das Ergebnis wird dann über die fwrite Funktion in eine Datei geschrieben.

Resümee

Wie man sehen konnte, ist die Verarbeitung von XML Dateien mit PHP Mitteln recht unkompliziert und Erfolge werden schnell sichtbar. Der Artikel hat zudem einige Anreize für die Verwendungsmöglichkeiten aufgezeigt und Hinweise für Sicherheitsaspekte beschrieben. Dem regen praktischen Einsatz in Ihren eigenen Projekten steht nun nichts mehr im Wege.

Kontrollzentrum

Seit einiger Zeit steht die neue Version 1.5 des Versionsverwaltungs-Tools Subversion (SVN) zum kostenlosen Download bereit. Das Programm ist für verschiedene Plattformen erhältlich, dazu zählen Windows und Linux als die wichtigsten Vertreter. Der Artikel bezieht sich zwar auf das Windows-Betriebssystem, aber mit geringem Aufwand lassen sich die wenigen spezifischen Unterschiede leicht adaptieren. Man kann Subversion auf unterschiedliche Art und Weise betreiben. Für eine lokale Verwendung, bei sehr kleinen Projekten mit lediglich einem einzigen Entwickler, genügt oft die Installation eines Clients. Für Windows Systeme sollte die Wahl des Clients auf TortoiseSVN fallen. Die Anwendung arbeitet als Explorer-Erweiterung und beherrscht alle notwendigen Funktionen zur Arbeit mit SVN. Dazu zählt unter anderem das Anlegen der Projektverzeichnisse, die Repository genannt werden. Der Zugriff auf ein lokales Repository erfolgt über das file:///-Protokoll. Sobald das Repository für mehrere Entwickler bereitstehen soll, wird ein Server benötigt. Man hat die Wahl zwischen einem Standalone-Server oder einer Integration in den Apache Web Server. Die aktuelle Version des SVN-Servers bringt für Windows-Nutzer eine Verbesserung der Konfiguration als Windows-Dienst. Für den Standalone-Server stehen die Protokolle svn:// und svn+ssh:// zur Verfügung. Für diesen Artikel wird vor allem auf die Installation des Apache-Moduls eingegangen. Der Vorteil des Apache liegt darin, mit den Protokollen http:// und https:// auf die Projektverzeichnisse zugreifen zu können. Mit Subclipse liefert Tigris.org SVN als Plug-in für Eclipse, das dem Tortoise-Client kaum in etwas nachsteht. Dank der PHP-Tools ist die Eclipse-IDE nicht mehr nur von Java-Programmierern geschätzt. Abbildung 1 zeigt die Subversion View mit einem geöffneten Projekt in Eclipse.

Abb. 1: Eclipse in der Subversion-Ansicht mit einem geöffneten Projekt

Subversion im Apache

Eine sehr bequeme Möglichkeit Subversion zu nutzen, ist die Integration in den Apache Web Server; damit kann das Repository über das HTTP-Protokoll angesprochen werden. Die Installation ist nicht weiter schwierig, erfordert allerdings eine funktionsfähige Apache-Installation. Wer die aufwändige Installation einer vollständigen Serverumgebung scheut, kann getrost auf XAMPP [4] zurückgreifen. Als Erstes müssen dann die Binaries des SVN für den Apache 2.2.X von der Webseite [5] geladen werden. Die Dateien mod_dav_svn.so, mod_authz_svn.so und der Ordner iconv sind in das Verzeichnis %APACHE_HOME%\modules zu kopieren. Um die Module dem Webserver bekannt zu machen, muss schließlich die Datei httpd.conf im Verzeichnis conf des Apache gemäß Listing 1 editiert werden.

# Anpassungen der httpd.conf
LoadModule dav_svn_module modules/mod_dav_svn.so
LoadModule authz_svn_module modules/mod_authz_svn.so

Include conf/svn.conf
Plaintext

Die ersten beiden Zeilen aktivieren die SVN-Module für den Apache. Um die Konfigurationsdatei übersichtlich zu halten, wird die eigentliche Konfiguration von Subversion über die Anweisung aus Zeile drei in die Datei svn.conf ausgelagert (Listing 2). Die Datei muss im gleichen Verzeichnis wie die httpd.conf angelegt werden.

<IfModule dav_svn_module>
  <Location /svn>
    DAV svn
    SVNListParentPath on
    SVNParentPath D:\Subversion
  </Location>
</IfModule>
XML

Über den Eintrag wird die darin eingeschlossene Konfiguration nur dann ausgeführt, wenn das Modul dav_svn_module wie in Listing 1 aktiviert wurde. bestimmt den Pfad, wie das Repository angesprochen werden soll. In diesem Fall ist http://127.0.0.1/svn der korrekte URL, um auf die Repositories zuzugreifen. Der absolute Pfad, in dem die Projektverzeichnisse abgelegt werden, wird mit dem Eintrag SVNParentPath gesetzt. Die Option SVN-ListPArentPath on listet alle Repositories in D:/Subversion über den URL http://localhost/svn auf. Kommentare werden mit # in Apache-Konfigurationsdateien eingeleitet und gelten nur bis zum Zeilenende. Sobald die Konfiguration abgeschlossen ist, muss der Server neu gestartet werden, um die Änderungen wirksam zu machen.

Das Repository

Wie schon erwähnt, heißt das Projektverzeichnis, das von SVN verwaltet wird, Repository. Für jedes Projekt wird üblicherweise ein eigenes Repository verwendet, es ist aber auch möglich, mehrere Projekte in einem gemeinsamen Verzeichnis abzulegen. Neue Projekte werden im Hauptverzeichnis Subversion angelegt, das für den Apache konfiguriert wurde. Für unser Beispiel aus Listing 2 ist dieses Hauptverzeichnis D:/Subversion. Darin wird ein neuer Ordner erzeugt, der den Namen des Projekts erhält. Im nächsten Schritt wird in dem neuen Ordner das eigentliche Repository generiert. Dazu wird mit einem Rechtsklick auf den Ordner, der das Projektverzeichnis beherbergen soll, der Eintrag TortoiseSVN/Projektverzeichnis hier erstellen ausgewählt. Die notwendigen Schritte werden von Tortoise anschließend automatisch ausgeführt und das Projektverzeichnis kann nun benutzt werden. Die von SVN angelegte Ordnerstruktur sollte nun nicht weiter verändert werden, alle Zugriffe auf das Verzeichnis erfolgen über den SVN-Client Tortoise.

In den einzelnen Repositories hat es sich bewährt, die Unterverzeichnisse trunk, branches und tags anzulegen. Der trunk (Stamm) beinhaltet das aktuelle Arbeitsverzeichnis, dort werden alle Projektdateien nach den persönlichen Vorlieben organisiert. Damit stellt der trunk den aktuellen Projektstand dar. In tags (Markierungen) werden spezielle Markierungen während des Projektfortschritts erzeugt. Eine solche Markierung ist beispielsweise eine neue Version der Anwendung. Branches (Verzweigungen) stellen parallele Entwicklungsstränge dar. Das ist meist dann der Fall, wenn eine Version abgeschlossen ist und nach einer Auslieferung weitergepflegt wird. Eine Weiterentwicklung von abgeschlossenen Versionen ist in der Regel dann notwendig, wenn nachträglich Fehler bekannt werden, die direkt behoben werden müssen, noch bevor eine neue Version ausgeliefert werden kann. Damit die Änderungen anschließend auch in der neuen Version verfügbar sind, können beide branches mit einem Merge zusammengeführt werden. Der besondere Vorteil von SVN gegenüber CVS ist die effiziente Art, wie die Verzweigungen und Markierungen gespeichert sind. Subversion erzeugt dafür keine physische Kopie, sondern nutzt Verlinkungen zum Hauptentwicklungsstrang.

Nachträgliche Manipulationen am Repository

Nach einem erfolgreichen Commit lassen sich mit der Standardeinstellung keine Änderungen mehr vornehmen. Wenn Logmeldungen nach dem Commit bearbeitet werden sollen, ist es notwendig, einige Veränderungen vorzunehmen. Dazu wechselt man in den Ordner hooks des betreffenden Repositories. Dort wird die Datei pre-revprop-change.bat mit dem folgenden Inhalt angelegt:

if “%4“ == “svn:log“ exit 0
echo Eigenschaft ‘%4‘ kann nicht geändert werden >&2
exit 1

Das Listing ermöglicht es, die Logmeldungen im Nachhinein noch zu ändern. In hooks können verschiedene Skripte abhängig zu den Aktionen gesteuert werden.

Erste Schritte mit SVN

Um die Projektstruktur in das Repository übertragen zu können, müssen die Ordner und Dateien zuerst im Dateisystem angelegt werden. Sobald das geschehen ist, kann der erste Commit ins Subversion erfolgen. Das Senden der Daten ist als Transaktion angelegt, das bedeutet, im Fehlerfall wird die gesamte Übertragung verworfen. Nur wenn alle Dateien erfolgreich übermittelt worden sind, ist die Änderung erfolgreich. Um einen Import auszuführen, muss auf das Root-Verzeichnis mit den zu übertragenden Dateien navigiert werden. Nun kann mit einem Rechtsklick auf den Hauptordner die Option TortoiseSVN/Import ausgewählt werden. Im Importdialog muss nun der URL zum Projektarchiv angegeben werden. Wenn der Apache Web Server nach Listing 2 konfiguriert wurde, lautet die richtige Adresse http://127.0.0.1/svn/[meinProjekt]. Dazu kann noch eine Logmeldung eingetragen werden.

Der Erfolg des Importierens kann wie üblich über eine Rechtsklick mit dem Eintrag TortoiseSVN/Projektarchiv kontrolliert werden. War der Import erfolgreich, kann die erzeugte Projektstruktur getrost gelöscht werden und es steht der erste Checkout aus dem Projektarchiv an. Dazu wird an die gewünschte Position im Dateisystem gewechselt und dort mit Rechtsklick der Eintrag SVN Auschecken genutzt. Damit nun nicht das gesamte Repository heruntergeladen wird, sondern nur der aktuelle Projektfortschritt, muss der Download-URL um das Verzeichnis trunk erweitert werden. Die übertragenen Dateien werden als lokale Arbeitskopie bezeichnet und sind

Abb. 2: Funktionsumfang des TortoiseSVN-Clients

Der Screenshot in Abbildung 2 zeigt die typischen Funktionen von TortoiseSVN, die stets mit einem Rechtsklick erreicht werden. Das Kontextmenü unterscheidet bei einer Selektion zwischen Dateien und Verzeichnissen. Bei nichtversionierten Verzeichnissen stehen die Optionen Hinzufügen, Importieren und Ignorieren zur Auswahl. Wenn die Optionen gleich nach der Aufnahme neuer Dateien in die lokale Arbeitskopie gesetzt werden, sind spätere Falschübertragungen bei einem Commit wesentlich geringer. Durch die Verwendung solcher Markierungen werden stets die richtigen Dateien für die Übertragung vorselektiert, und einem falsch gesetzten Haken unter Zeitstress ist so einfach vorzubeugen.

Jeder Commit in das SVN lässt eine interne Revisionsnummer um eins erhöhen. Die letzte übermittelte Revision wird als HEAD bezeichnet und stellt immer den aktuellen Stand dar. Um auf frühere Versionen des Projekts zugreifen zu können, wird diese Revisionsnummer benötigt. Über die Logmeldungen lässt sich nachvollziehen, welche Änderung in einer Revision gemacht wurde. Es ist somit möglich, jederzeit eine bestimmte Revision aus dem Projektarchiv auszuchecken. Bei sehr vielen Revisionen kann die interne Suchfunktion des Clients verwendet werden, um bestimmte Schlüsselwörter in den Logs zu finden. Dies ist auch ein Grund, von vornherein mit Weitblick sinnvolle Beschreibungen zu finden. Eine Logmeldung sollte die Art der Änderung, die betroffenen Funktionen und eine kurze Beschreibung beinhalten. Ein Beispiel für eine solche Meldung ist: >>FEATURE: Kalender – Berechnung Ostersonntag hinzugefügt.<<

Revision oder Version?

Wichtig im Umgang mit einer Versionsverwaltung ist die Unterscheidung der Begriffe Build und Version. Ein Build ist ein einzelner Iterationsschritt, welcher der erstellten Anwendung nur eine einzige neue Funktion, beziehungsweise ein Feature hinzufügt. Ein Build ist mit der Revisionsnummer im SVN gleichzusetzen. Die Version einer Software ist eine Zusammenstellung verschiedener Funktionen und Features. Erst wenn die geforderte Funktionalität einer Version implementiert ist, erfolgt das Erhöhen der Versionsnummer. Die Version besteht also aus mehreren Builds.

In manchen Fällen ist es wichtig, im Repository Dateien gegen Veränderungen zu sichern. Dafür kann der Mechanismus Sperre holen und Sperre freigeben benutzt werden. Solange Dateien gesperrt sind, können sie nicht durch einen Commit verändert werden. Das beugt Konflikten vor, die entstehen, wenn eine Datei gleichzeitig editiert wird. Um Unterschiede in den Revisionen einer Datei zu erkennen, steht ein so genannter Diff zur Verfügung. Die Abbildung 3 zeigt einen solchen Diff. Es wird immer der Unterschied der aktuellen Arbeitskopie zur vorhergehenden Revision angezeigt. Tortoise lässt sich auch mit dem freien Tool WinMerge kombinieren, um weitere Funktionen zum Dateivergleich zur Verfügung zu haben. Das ist besonders dann interessant, wenn mehrere Revisionen einer Datei verglichen werden müssen. Dazu muss nicht immer das ganze Projekt ausgecheckt werden, es genügt durchaus, nur die betreffenden Files herunterzuladen.

Abb. 3: Diff-Ansicht des Tortoise-Clients

Markieren und Verzweigen

Abb. 4: Verzweigen/Markieren-Dialog

Eine Markierung stellt einen semantischen Zusammenhang des Projektfortschritts zu einer Revisionsnummer im Repository dar. Um das Repository übersichtlich zu halten, werden nur vorher festgelegte Revisionen getaggt. Eine solche Revision kann beispielsweise der Sprung auf eine neue Version der eigenen Applikation sein oder ein Upgrade eines verwendeten Frameworks auf eine aktuelle Version. Wenn einmal eine Markierung nicht sofort angelegt wurde, ist dies auch nicht problematisch. Tags können jederzeit auch aus jeder beliebigen Revisionsnummer erzeugt werden. Daher ist es unproblematisch, nach mehreren Commits die gewünschte Revision im Nachhinein zu taggen. Um eine Markierung zu erzeugen, wird der Eintrag Verzweigen/Markieren im Kontexmenü benutzt. Dazu ist es wichtig, auch im Root-Ordner des gesamten Projekts zu sein, da sonst nur Teile getaggt werden. In Abbildung 4 ist der betreffende Dialog dargestellt. An der ersten Position ist das Quellverzeichnis angegeben. Im Eingabefeld Zu URL wird der Pfad von trunk nach tags korrigiert. In tags ist es notwendig, den Pfad mit einem neuen Ordner zu erweitern, der z. B. die Versionsnummer als Namen besitzt. Wenn der Pfad des trunks nicht erweitert wird, kommt es zu einer Fehlermeldung und der tag wird nicht angelegt. Als Nächstes wird die Auswahl getroffen, welche Revision verwendet werden soll. Zu guter Letzt darf natürlich auch eine Logmeldung nicht fehlen. Wenn nun das Projektarchiv geöffnet wird, ist im Verzeichnis tags ein neuer Ordner angelegt, der sämtliche Projektdateien zu einem bestimmten Revisionsstand enthält. In tags werden keine Änderungen übertragen.

Für Verzweigungen wird analog vorgegangen, nur dass das Verzeichnis tags durch branches ersetzt werden muss. Bei der späteren Arbeit mit Entwicklungszweigen, die vom trunk abweichen, muss der Commit auch stets in das entsprechende Unterverzeichnis von branches übertragen werden. Das Zusammenführen eines branchs mit der HEAD-Revision des trunks erfolgt über das Kontexmenü. Die vorhandenen Konflikte müssen von Hand über den Diff-Betrachter aufgelöst werden.

Fazit

Wie zu erkennen ist, handelt es sich bei Subversion um ein sehr leistungsfähiges Werkzeug, dessen Leistungsspektrum von diesem Artikel nur angerissen werden konnte. Eine ausführliche Abhandlung zur Theorie und weiterführende Konzepte mit Subversion sind im SVN Book zu finden.