Wie „Katze“, um eine Datei in JGit?
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.
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.