Frage

Vor einiger Zeit war ich für eine embeddable verteiltes Versionskontrollsystem in Java suchen , und ich glaube, ich fand es in JGit , die eine reine Java-Implementierung von git ist. Allerdings gibt es in der Art und Weise von Beispielcode oder Tutorials sind nicht viel.

Wie kann ich JGit die HEAD Version einer bestimmten Datei abrufen (wie svn cat oder hg cat tun whould)?

Ich nehme an, dies beinhaltet einige U-Tree-Walking und bin auf der Suche nach einem Codebeispiel.

War es hilfreich?

Lösung

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

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.

Andere Tipps

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

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.release();
    }
}

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

Ich folgte @ Thilo und Antwort des @ morisil diese 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();

habe ich nicht getestet, die Java-Version, aber es sollte funktionieren. Er übersetzt aus

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

in Clojure (nach dem gleichen Aufbau wie der obere Abschnitt), die Arbeit der Fall ist.

Dachte, es selbst heraus. Die API ist ziemlich Low-Level, aber es ist nicht so 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();

Ich habe begonnen, eine Bibliothek zu schreiben genannt gitective , die mit Blobs für die Arbeit vieler Helfer enthält, verpflichtet, und Bäume mit JGit und ist mIT-Lizenz und auf GitHub.

Get Inhalt der Datei in HEAD commit

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

Get Inhalt einer Datei auf einem Zweig

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

Diff zwei Dateien

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 Dienstprogramme zur Verfügung gestellt werden in der README detailliert beschrieben.

Es gibt einige Informationen unter JGit Tutorial (aber das ist auch nicht wirklich hilfreich noch vollständig und wahrscheinlich veraltet, da sie geschaltet eclipse wo keine Dokumentation noch verfügbar ist).

Sie können den Inhalt eines bestimmten Dateipfad wie folgt lauten. Bitte beachten Sie, dass die TreeWalk sein kann null , wenn kein Weg wurde in dem gegebenen Baum gefunden. So erfordert es einige spezielle Handhabung.

public String readFile(RevCommit commit, String filepath) throws IOException {
    try (TreeWalk walk = TreeWalk.forPath(repo, filepath, commit.getTree())) {
        if (walk != null) {
            byte[] bytes = repo.open(walk.getObjectId(0)).getBytes();
            return new String(bytes, StandardCharsets.UTF_8);
        } else {
            throw new IllegalArgumentException("No path found.");
        }
    }
}

Zum Beispiel:

ObjectId head = repo.resolve(Constants.HEAD);
RevCommit last = repo.parseCommit(head);
readFile(last, "docs/README.md")

Diese Antwort geschrieben, mit JGit 4.8.0.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top