Git Stream Wrapper für PHP 1.0.0-beta veröffentlicht

Am Sonntag haben wir den Git Stream Wrapper für PHP in Version 1.0.0-beta veröffentlicht – mit drei interessanten neuen Features nach umfangreichem Refactoring. Die Komponente ist in ihrer öffentlichen API weiterhin kompatibel zu den alten 0.*-Releases, die Interna haben sich jedoch drastisch geändert, sodass eigene Erweiterungen nun möglicherweise nicht mehr funktionieren.
Das erste neue Feature erlaubt es, Repository-Pfade am Stream Wrapper zu registrieren, um die Pfade zu verkürzen, die für den Zugriff auf Dateien in diesen Repositories nötig sind. Das ist besonders nützlich, wenn Sie nur ein oder zwei verschiedene Repositories verwenden.
<?php
use TQGitStreamWrapperStreamWrapper;
use TQGitRepositoryRepository;
StreamWrapper::register('git', '/usr/bin/git');
StreamWrapper::getRepositoryRegistry()->addRepositories(
array(
'repo1' => Repository::open('/path/to/repository/1', '/usr/bin/git', false),
'repo2' => Repository::open('/path/to/repository/2', '/usr/bin/git', false),
)
);
$content1 = file_get_contents('git://repo1/file_0.txt');
$content2 = file_get_contents('git://repo2/file_0.txt');
Anstelle des vollständigen Pfads git:///path/to/repository/1/file_0.txt können Sie diesen nun auf git://repo1/file_0.txt verkürzen. Das macht den Code lesbarer und erlaubt es, Repository-Pfade an einer zentralen Stelle zu konfigurieren.
Für diejenigen unter Ihnen, die Gaufrette kennen: Wir haben außerdem einen Gaufrette-Adapter hinzugefügt, der Gaufrettes Filesystem mit einem Git-Repository verbindet. Für diejenigen, die Gaufrette nicht kennen: Sie sollten unbedingt einen Blick darauf werfen. Gaufrette ist eine Dateisystem-Abstraktionsschicht, die eine Vielzahl sogenannter Adapter bereitstellt, mit denen Sie verschiedene Speichersysteme transparent in Ihrem Code verwenden können. Es gibt Adapter für Amazon S3, Azure, Datenbanken, Dropbox, GridFS, (S)FTP usw. sowie einen speziellen In-Memory-Adapter, der besonders beim Testen praktisch ist. Der Git Stream Wrapper für PHP bringt nun seinen eigenen Gaufrette-Adapter mit.
<?php
use GaufretteFilesystem;
use GaufretteStreamWrapper;
use TQGitRepositoryRepository;
use TQVcsGaufretteAdapter as GitAdapter;
$repository = Repository::open('/path/to/repository/1', '/usr/bin/git', false);
$adapter = new GitAdapter($repository);
$filesystem = new Filesystem($adapter);
$content = $filesystem->read('file_0.txt');
$content = 'Hello I am the new content';
$filesystem->write('file_0.txt', $content);
Dateiänderungen, -löschungen und -hinzufügungen werden automatisch in das zugrunde liegende Repository committet. Sie können sogar den Gaufrette Stream Wrapper verwenden.
$map = StreamWrapper::getFilesystemMap();
$map->set('repo1', $filesystem);
StreamWrapper::register();
echo file_get_contents('gaufrette://repo1/file_0.txt');
Das zuletzt hinzugefügte Feature ist vielleicht das spannendste – auch wenn es den Bibliotheksnamen „Git Stream Wrapper für PHP“ überholt erscheinen lässt. Als reinen Proof of Concept für die zugrunde liegende Komponentenarchitektur haben wir zusätzlich SVN-Unterstützung eingebaut. Eigentlich ist es also nun der „Git/SVN Stream Wrapper für PHP“. Die SVN-Unterstützung ist transparent in die Bibliothek integriert, sodass Sie die für Ihr Projekt am besten geeignete Versionsverwaltungstechnologie wählen können. Wie bei der Git-Unterstützung müssen die Subversion-Binaries auf der Maschine installiert sein, auf der der PHP-Code läuft. Aufgrund einiger Einschränkungen des SVN-Binarys im Vergleich zum Git-Binary konnten wir nicht alle Features unterstützen, die mit der Git-Komponente verfügbar sind. Insbesondere die verschiedenen Subversion-Versionen stellten eine große Herausforderung dar. Auf meinem Mac läuft beispielsweise eine lokalisierte (deutsche) Version von Subversion 1.8.x (via Macports) oder die (nicht lokalisierte) 1.7.x-Version, die Apple mit Mac OS X ausliefert, während Travis CI (das die Unit-Tests auf PHP 5.3, 5.4 und 5.5 ausführt) Ubuntu 12.04 mit dessen Subversion 1.6.* verwendet (ja, das ist noch die Version mit .svn-Verzeichnissen überall). Git hingegen zeigte diese Art von Inkompatibilität zwischen seinen verschiedenen Versionen nicht – nur um es gesagt zu haben.
<?php
use TQSvnRepositoryRepository;
// open an already initialized repository
$svn = Repository::open('/path/to/your/repository', '/usr/bin/svn');
// open repository
$svn = Repository::open('/path/to/your/repository', '/usr/bin/svn');
// get status of working directory
$status = $svn->getStatus();
// are there uncommitted changes in the working directory
$isDirty = $svn->isDirty();
// retrieve the commit log limited to $limit entries skipping the first $skip
$log = $svn->getLog($limit, $skip);
// retrieve the second to last commit
$commit = $svn->showCommit($svn->getCurrentCommit() - 1);
// list the directory contents two commits before
$list = $svn->listDirectory('.', $svn->getCurrentCommit() - 2);
// show contents of file $file at commit 322...
$contents = $svn->showFile($file, 322);
// write a file and commit the changes
$commit = $svn->writeFile('test.txt', 'Test', 'Added test.txt');
// remove multiple files
$commit = $svn->removeFile('file_*', 'Removed all files not needed any more');
// rename a file
$commit = $c->renameFile('test.txt', 'test.txt-old', 'Made a backup copy');
// do some file operations and commit all changes at once
$result = $svn->transactional(function(TQVcsRepositoryTransaction $t) {
file_put_contents($t->getRepositoryPath().'/text1.txt', 'Test 1');
file_put_contents($t->getRepositoryPath().'/text2.txt', 'Test 2');
unlink($t->resolvePath('old.txt'));
rename($t->resolvePath('to_keep.txt'), $t->resolvePath('test3.txt'));
$t->setCommitMsg('Don't know what to write here');
// if we throw an exception from within the callback the changes are discarded
// throw new Exception('No we don't want to to these changes');
// note: the exception will be re-thrown by the repository so you have to catch
// the exception yourself outside the transactional scope.
});
Die Verwendung des Stream Wrappers funktioniert ebenfalls genauso wie mit Git. Bitte beachten Sie, dass es derzeit nicht möglich ist, denselben Stream Wrapper sowohl für Git- als auch für SVN-Zugriffe zu verwenden. In diesem Fall müssten Sie beide Stream Wrapper registrieren.
Nur ein Wort der Warnung: Die SVN-Komponente ist (anders als die Git-Komponente) noch nicht produktiv erprobt, seien Sie sich also möglicher Bugs, Inkompatibilitäten und anderer Probleme bewusst. Öffnen Sie gerne Issues auf der GitHub-Seite des Projekts oder liefern Sie – noch besser – Patches und/oder Pull Requests, um diese Probleme zu beheben.
Bitte lesen Sie das README-Dokument für weitere Informationen – insbesondere zu den Änderungen, die beim Einrichten der Unit-Tests nötig sind.
Eine letzte Anmerkung: Wir haben außerdem versucht, die Travis-CI-Tests auf HHVM (HipHop Virtual Machine für PHP) laufen zu lassen, aber die Tests schlagen fehl. Der Grund scheint zu sein, dass HHVM derzeit stream_context_get_options() nicht unterstützt.