31 Stimmen

Wie kann man eine Datei in JGit "cat"?

Vor einiger Zeit war ich auf der Suche nach einem einbettbares verteiltes Versionskontrollsystem in Java , und ich glaube, ich habe sie gefunden in JGit die eine reine Java-Implementierung von git ist. Allerdings gibt es nicht viel in Form von Beispielcode oder Tutorials.

Wie kann ich JGit verwenden, um die HEAD-Version einer bestimmten Datei abzurufen (genau wie svn cat o hg cat tun würde)?

Ich vermute, dass dies eine gewisse Umdrehungszahl erfordert, und suche nach einem Codebeispiel.

1 Stimmen

Die Entwickler antworten ziemlich schnell auf der Mailingliste: dev.eclipse.org/mailman/listinfo/egit-dev . Ich schlage vor, Sie versuchen es einmal.

23voto

morisil Punkte 1335

Leider funktioniert die Antwort von Thilo nicht mit der neuesten JGit-API. Hier ist die Lösung, die ich gefunden habe:

File repoDir = new File("test-git");
// open the repository
Repository repository = new Repository(repoDir);
// find the HEAD
ObjectId lastCommitId = repository.resolve(Constants.HEAD);
// now we have to get the commit
RevWalk revWalk = new RevWalk(repository);
RevCommit commit = revWalk.parseCommit(lastCommitId);
// and using commit's tree find the path
RevTree tree = commit.getTree();
TreeWalk treeWalk = new TreeWalk(repository);
treeWalk.addTree(tree);
treeWalk.setRecursive(true);
treeWalk.setFilter(PathFilter.create(path));
if (!treeWalk.next()) {
  return null;
}
ObjectId objectId = treeWalk.getObjectId(0);
ObjectLoader loader = repository.open(objectId);

// and then one can use either
InputStream in = loader.openStream()
// or
loader.copyTo(out)

Ich wünschte, es wäre einfacher.

46 Stimmen

Wer in aller Welt hat diese API entwickelt?

3 Stimmen

Wissen Sie, was der n-te Wert von treeWalk.getObjectId(nth) bewirkt? (d.h. was sind die Fälle, in denen wir einen Wert an treeWalk.getObjectId übergeben, der größer als 0 ist)?

0 Stimmen

@DinisCruz TreeWalk kann über mehr als einen Baum gehen (durch Aufruf von addTree mehrere Male). In diesem Fall können Sie getObjectId(N) um die Objekt-ID von Baum N zu erhalten (die je nach Baum gleich oder unterschiedlich sein kann).

18voto

creinig Punkte 1480

Hier ist eine einfachere Version der Antwort von @morisil, die einige der Konzepte von @directed laughs verwendet und mit JGit 2.2.0 getestet wurde:

private String fetchBlob(String revSpec, String path) throws MissingObjectException, IncorrectObjectTypeException,
        IOException {

    // Resolve the revision specification
    final ObjectId id = this.repo.resolve(revSpec);

    // Makes it simpler to release the allocated resources in one go
    ObjectReader reader = this.repo.newObjectReader();

    try {
        // Get the commit object for that revision
        RevWalk walk = new RevWalk(reader);
        RevCommit commit = walk.parseCommit(id);

        // Get the revision's file tree
        RevTree tree = commit.getTree();
        // .. and narrow it down to the single file's path
        TreeWalk treewalk = TreeWalk.forPath(reader, path, tree);

        if (treewalk != null) {
            // use the blob id to read the file's data
            byte[] data = reader.open(treewalk.getObjectId(0)).getBytes();
            return new String(data, "utf-8");
        } else {
            return "";
        }
    } finally {
        reader.close();
    }
}

repo ist ein Repository-Objekt, wie es in den anderen Antworten erstellt wurde.

1 Stimmen

Sieht gut aus, außer dass getBytes() zurückgegeben wird, obwohl der Rückgabetyp String ist. Beachten Sie, dass Sie auch die Funktion release en walk y treeWalk für die Freigabe von Ressourcen. Um dies nur einmal tun zu müssen, rufen Sie ObjectReader reader = repo.newObjectReader() und diese an Revwalk und Treewalk statt an das Repository weitergeben. Dann rufen Sie reader.release() in einem abschließenden Block.

0 Stimmen

RevWalk muss ebenfalls freigegeben werden, verschieben Sie den Aufruf zu newObjectReader auf und verwenden new RevWalk(reader) stattdessen.

0 Stimmen

Ein weiterer Kommentar (sorry :)), this.repo.open sollte ebenfalls ersetzt werden durch reader.open .

12voto

directed laugh Punkte 403

Ich folgte @Thilo's und @morisil's Antwort, um dies zu erhalten, kompatibel mit JGit 1.2.0:

File repoDir = new File("test-git/.git");
// open the repository
Repository repo = new Repository(repoDir);
// find the HEAD
Commit head = repo.mapCommit(Constants.HEAD);
// retrieve the tree in HEAD
Tree tree = head.getTree();

// 1.2.0 api version here
// find a file (as a TreeEntry, which contains the blob object id)
TreeWalk treewalk = TreeWalk.forPath(repo, "b/test.txt", tree);
// use the blob id to read the file's data
byte[] data = repo.open(treewalk.getObjectId(0)).getBytes();

Ich habe die Java-Version nicht getestet, aber sie sollte funktionieren. Es übersetzt von

(.getBytes (.open repo (.getObjectId (TreeWalk/forPath repo "b/test.txt" tree) 0)))

in Clojure (mit dem gleichen Aufbau wie im oberen Abschnitt), was auch funktioniert.

0 Stimmen

Funktioniert prima! Ich bin direkt zur Datei gegangen: FileOutputStream fileOS = new FileOutputStream(path); if (treewalk != null){repo.open(treewalk.getObjectId(0)).copyTo(fileOS);} dann fileOS.close;

0 Stimmen

Mehr Java-Fragen sollten in Clojure beantwortet werden.

4voto

Thilo Punkte 248982

Ich habe es selbst herausgefunden. Die API ist ziemlich Low-Level, aber es ist nicht allzu schlecht:

File repoDir = new File("test-git/.git");
// open the repository
Repository repo = new Repository(repoDir);
// find the HEAD
Commit head = repo.mapCommit(Constants.HEAD);
// retrieve the tree in HEAD
Tree tree = head.getTree();
// find a file (as a TreeEntry, which contains the blob object id)
TreeEntry entry = tree.findBlobMember("b/test.txt");
// use the blob id to read the file's data
byte[] data = repo.openBlob(entry.getId()).getBytes();

4 Stimmen

Dies scheint ein veraltetes Beispiel für die aktuelle JGit-Version zu sein. Die API hat sich ein wenig geändert, Vorsicht.

1 Stimmen

@Jonathan Dumaine: Bitte aktualisieren Sie den Beitrag, wenn nötig (und Sie wissen wie)

4voto

Kevin Sawicki Punkte 2954

Ich habe mit dem Schreiben einer Bibliothek namens gitektonische das viele Hilfsprogramme für die Arbeit mit Blobs, Commits und Bäumen mit JGit enthält. Es ist MIT-lizenziert und auf GitHub verfügbar.

Inhalt der Datei in der HEAD-Übertragung abrufen

Repository repo = new FileRepository("/repos/project/.git");
String content = BlobUtils.getHeadContent(repo, "src/Buffer.java");

Inhalt einer Datei in einer Verzweigung abrufen

Repository repo = new FileRepository("/repos/project/.git");
String content = BlobUtils.getContent(repo, "master", "src/Buffer.java");

Zwei Dateien vergleichen

Repository repo = new FileRepository("/repos/project/.git");
ObjectId current = BlobUtils.getId(repo, "master", "Main.java");
ObjectId previous = BlobUtils.getId(repo, "master~1", "Main.java");
Collection<Edit> edit = BlobUtils.diff(repo, previous, current);

Weitere Beispiele für bereitgestellte Dienstprogramme finden Sie im Abschnitt README .

1 Stimmen

Es sieht gut aus. Wenn ich mein jGit-Projekt nicht schon geschrieben hätte, würde ich es auf jeden Fall verwenden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X