
Thilo
Vor einiger Zeit suchte ich nach einem integrierbaren verteilten Versionskontrollsystem in Java, und ich glaube, ich habe es gefunden JGit, die eine reine Java-Implementierung von git ist. Es gibt jedoch nicht viel Beispielcode oder Tutorials.
Wie kann ich JGit verwenden, um die HEAD-Version einer bestimmten Datei abzurufen (genau wie svn cat
oder hg cat
wer tun)?
Ich nehme an, dies beinhaltet ein gewisses Rev-Tree-Walking und suche nach einem Codebeispiel.

Morisil
Leider funktioniert Thilos Antwort 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.

kräuseln
Hier ist eine einfachere Version von @morisils Antwort, 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.
Ich bin der Antwort von @Thilo und @morisil gefolgt, 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 es sollte funktionieren. Es übersetzt aus
(.getBytes (.open repo (.getObjectId (TreeWalk/forPath repo "b/test.txt" tree) 0)))
in Clojure (nach dem gleichen Aufbau wie der obere Abschnitt), was funktioniert.
Habe es selbst herausgefunden. Die API ist ziemlich niedrig, aber es ist nicht so schlimm:
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 angefangen, eine Bibliothek namens zu schreiben gitektiv das viele Helfer für die Arbeit mit Blobs, Commits und Bäumen mit JGit enthält und MIT-lizenziert und auf GitHub verfügbar ist.
Holen Sie sich den Inhalt der Datei im HEAD-Commit
Repository repo = new FileRepository("/repos/project/.git");
String content = BlobUtils.getHeadContent(repo, "src/Buffer.java");
Holen Sie sich den Inhalt einer Datei in 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 bereitgestellte Dienstprogramme finden Sie in der Liesmich.

Zittern
Es gibt einige Infos unter JGit-Tutorial (Aber das ist auch weder wirklich hilfreich noch vollständig und wahrscheinlich veraltet, seit sie auf gewechselt haben Finsternis wo noch keine Dokumentation verfügbar ist).

Mincong Huang
Sie können den Inhalt eines bestimmten Dateipfads wie folgt lesen. Bitte beachten Sie, dass der TreeWalk sein kann Null wenn im angegebenen Baum kein Pfad gefunden wurde. Es erfordert also eine 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 wurde mit JGit 4.8.0 geschrieben.
10024100cookie-checkWie kann man eine Datei in JGit „kategorisieren“?yes
Die Entwickler antworten ziemlich schnell auf der Mailingliste: dev.eclipse.org/mailman/listinfo/egit-dev . Ich schlage vor, Sie probieren es aus.
– Robert Munteanu
7. November 2009 um 16:44 Uhr