Ein Überblick über den Status quo

JGit und EGit werden erwachsen

Matthias Sohn

JGit und EGit sind seit mehr als zwei Jahren Eclipse-Projekte, und es wurden seit meinem Artikel im Eclipse Magazin 1.2011 [1] in Abständen von zwei bis drei Monaten fünf weitere Releases veröffentlicht. Nach einigen weiteren Incubation Releases (0.10-0.12) markiert die Auslieferung von Indigo im Juni 2011 mit der Fertigstellung von JGit und EGit 1.0 den Übergang vom Incubation zum Mature Project. Mit dem Indigo Service Release 3.7 SR1 wurde im September 2011 das Release 1.1 geliefert. Mittlerweile ist Version 1.2 von EGit erschienen.

Eclipse Magazin

Der Artikel „JGit und EGit werden erwachsen“ von Matthias Sohn ist erstmalig erschienen im Eclipse Magazin 1.12.

JGit ist die Grundlage aller Java-Git-Anwendungen, die in diesem Artikel vorgestellt werden. Es implementiert die Git-Algorithmen, Transportprotokolle und Datenstrukturen in Java und ist vollständig kompatibel zur kanonischen nativen Git-Implementierung. Da dasselbe Sperrprotokoll verwendet wird, können JGit und das native Git auch konkurrierend auf dem gleichen Repository verwendet werden. Falls Sie JGit in eigenen Anwendungen einsetzen wollen, können Sie es vom JGit Maven Repository [2] herunterladen.

JGit API

JGit exponiert ein Low Level API (entspricht ungefähr den so genannten Plumbing Commands in native Git), das die volle Funktionalität von JGit exponiert. Allerdings ist dieses API unter anderem aus Performancegründen relativ komplex und erfordert einige Zeit zur Einarbeitung. Auf der anderen Seite erhält man damit die Möglichkeit, auch komplexere Anforderungen performant zu implementieren (Abb. 1).

Abb. 1: JGit API

Für einen einfacheren Einstieg in die wichtigste Funktionalität gibt es auch ein High Level API, das entsprechend der Funktionalität der so genannten Porcelain Commands in native Git geschnitten ist und Porcelain API genannt wird. Dieses folgt dem Command Pattern und ist besonders einfach zu verwenden. Es ist seit Helios um viele neue Commands gewachsen. Damit reduziert sich der Aufwand für die Git-Integration in vielen Anwendungsszenarien erheblich. Die Klasse Git dient als Factory für alle Commands im Porcelain API. Die Command Objects, die von ihr erzeugt werden, folgen dabei dem Fluent-Interface-Prinzip [3], sodass viele einfache Szenarien als Einzeiler implementiert werden können. Falls Fehler auftreten, werden Checked Exceptions mit der Superklasse GitAPIException geworfen. Andere interne Fehler werden als Runtime Exception mit der Superklasse JGitInternalException gemeldet. Im Folgenden gebe ich einige Beispiele wie dieses API verwendet wird, um Ihnen den Einstieg zu erleichtern. Beginnen wir mit einem Beispiel zum Klonen eines Repository mit dem CloneCommand:

CloneCommand clone = Git.cloneRepository()
.setDirectory(new File("/tmp/git/egit-training/")
.setURI("http://egit.eclipse.org/egit-training.git")
.setCloneAllBranches(true)
.setTimeout(10)
.call();

Dieser kurze Quellcode zeigt uns Folgendes:

  • cloneRepository()instanziiert das Command Object
  • setDirectory()setzt das Zielverzeichnis für die Clone-Operation
  • setURI()setzt den URL des zu klonenden Repositorys
  • setCloneAllBranches(true) konfiguriert das CloneCommand so, dass alle Branches vom Remote Repository geholt werden
  • setTimeout(10) setzt den Timeout für die Transportoperation auf zehn Sekunden
  • Schließlich wird mit call()das Kommando ausgeführt
Listing 1
File dir = new File(REPO_PATH);
try {
  Git git = Git.open(dir);
  FetchCommand fetch = git.fetch();
  RefSpec spec = new RefSpec(
        "refs/heads/master:refs/remotes/origin/master");
  fetch.setRemote("origin");
  fetch.setRefSpecs(spec);
  FetchResult res = fetch.call();
  System.out.println(res.getMessages());
} catch (JGitInternalException e) {
  e.printStackTrace();
} catch (InvalidRemoteException e) {
  e.printStackTrace();
} catch (IOException e) {
  e.printStackTrace();
}

Listing 1 zeigt das Fetchen neuer Änderungen. setRemote(„origin“) wählt den Remote „origin“ aus, Remotes sind Kurznamen für Git URLs. „origin“ ist der Default für den URL des Repositorys, von dem das vorliegende Repository durch Klonen kopiert wurde. setRefSpecs(spec) setzt die RefSpec, die die Abbildung von Branches im Remote Repository auf lokale Branches definiert Weitere Daten zum Fetch-Resultat können vom zurückgegebenen FetchResult abgefragt werden.

Geschrieben von
Matthias Sohn
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.