前段时间我正在寻找一个embeddable distributed version control system in Java, 我想我已经在JGit中找到了它,它是git的纯Java实现。 但是,示例代码或教程的方式并不多。
如何使用JGit检索某个文件的HEAD版本(就像svn cat
或hg cat
那样)?
我想这涉及一些转树走路,我正在寻找代码示例。
答案 0 :(得分:19)
不幸的是,Thilo的答案不适用于最新的JGit API。这是我找到的解决方案:
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)
我希望它更简单。
答案 1 :(得分:16)
这是@ morisil答案的简单版本,使用@directed笑的一些概念并使用JGit 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
是在其他答案中创建的Repository对象。
答案 2 :(得分:11)
我跟着@ Thilo和@ morisil的回答得到了这个,与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();
我没有测试Java版本,但它应该可以工作。它翻译自
(.getBytes (.open repo (.getObjectId (TreeWalk/forPath repo "b/test.txt" tree) 0)))
在clojure中(遵循与顶部相同的设置),这确实有效。
答案 3 :(得分:5)
自己想出来。 API非常低级,但它并不太糟糕:
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 :(得分:4)
我已经开始编写一个名为gitective的库,其中包含许多帮助程序,用于使用JGit处理blob,提交和树,并且已获得MIT许可并可在GitHub上使用。
在HEAD提交中获取文件内容
Repository repo = new FileRepository("/repos/project/.git");
String content = BlobUtils.getHeadContent(repo, "src/Buffer.java");
获取分支上的文件内容
Repository repo = new FileRepository("/repos/project/.git");
String content = BlobUtils.getContent(repo, "master", "src/Buffer.java");
区分两个文件
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);
README中详细介绍了所提供实用程序的更多示例。
答案 5 :(得分:3)
JGit Tutorial有一些信息(但这也不是真正有用也不完整,可能已经过时了,因为他们切换到eclipse尚未提供任何文档。)
答案 6 :(得分:0)
您可以按如下方式阅读给定文件路径的内容。请注意,如果在给定树中找不到路径,TreeWalk可以 null 。所以它需要一些特定的处理。
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.");
}
}
}
例如:
ObjectId head = repo.resolve(Constants.HEAD);
RevCommit last = repo.parseCommit(head);
readFile(last, "docs/README.md")
这个答案是用JGit 4.8.0编写的。