git 如何在 JGit 中“cat”一个文件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1685228/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to "cat" a file in JGit?
提问by Thilo
A while back I was looking for an embeddable distributed version control system in Java, and I think I have found it in JGit, which is a pure Java implementation of git. However, there is not much in the way of sample code or tutorials.
不久前,我在 Java中寻找可嵌入的分布式版本控制系统,我想我在JGit 中找到了它,它是 git 的纯 Java 实现。但是,示例代码或教程的方式并不多。
How can I use JGit to retrieve the HEAD version of a certain file (just like svn cat
or hg cat
whould do)?
如何使用 JGit 检索某个文件的 HEAD 版本(就像svn cat
或应该hg cat
做的那样)?
I suppose this involves some rev-tree-walking and am looking for a code sample.
我想这涉及一些 rev-tree-walking 并且正在寻找代码示例。
采纳答案by morisil
Unfortunately Thilo's answer does not work with the latest JGit API. Here is the solution I found:
不幸的是,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)
I wish it was simpler.
我希望它更简单。
回答by creinig
Here's a simpler version of @morisil's answer, using some of the concepts from @directed laugh's and tested with JGit 2.2.0:
这是@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.close();
}
}
repo
is a Repository object as created in the other answers.
repo
是在其他答案中创建的 Repository 对象。
回答by directed laugh
I followed @Thilo's and @morisil's answer to get this, compatible with JGit 1.2.0:
我按照@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();
I didn't test the Java version but it should work. It translates from
我没有测试 Java 版本,但它应该可以工作。它翻译自
(.getBytes (.open repo (.getObjectId (TreeWalk/forPath repo "b/test.txt" tree) 0)))
in clojure (following the same setup as the top section), which does work.
在 clojure 中(遵循与顶部相同的设置),它确实有效。
回答by Thilo
Figured it out by myself. The API is quite low-level, but it's not too bad:
我自己想出来的。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();
回答by Kevin Sawicki
I have started writing a library called gitectivethat contains many helpers for working with blobs, commits, and trees using JGit and is MIT-licensed and available on GitHub.
我已经开始编写一个名为gitective的库,它包含许多使用 JGit 处理 blob、提交和树的帮助程序,并且是 MIT 许可的,可在 GitHub 上获得。
Get content of file in HEAD commit
获取 HEAD 提交中的文件内容
Repository repo = new FileRepository("/repos/project/.git");
String content = BlobUtils.getHeadContent(repo, "src/Buffer.java");
Get content of a file on a branch
获取分支上文件的内容
Repository repo = new FileRepository("/repos/project/.git");
String content = BlobUtils.getContent(repo, "master", "src/Buffer.java");
Diff two files
区分两个文件
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);
More examples of utilities provided are detailed in the README.
README中详细介绍了提供的更多实用程序示例。
回答by jitter
There is some info at JGit Tutorial(but that also is neither really helpful nor complete and probably outdated since they switched to eclipsewhere no documentation is available yet).
JGit 教程中有一些信息(但这也不是很有帮助也不是完整的,并且可能已经过时,因为他们切换到eclipse而没有可用的文档)。
回答by Mincong Huang
You can read the content of a given filepath as follows. Please be aware that the TreeWalk can be nullif no path was found in the given tree. So it requires some specific handling.
您可以按如下方式读取给定文件路径的内容。请注意,如果在给定的树中找不到路径,则 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.");
}
}
}
For example:
例如:
ObjectId head = repo.resolve(Constants.HEAD);
RevCommit last = repo.parseCommit(head);
readFile(last, "docs/README.md")
This answer is written with JGit 4.8.0.
这个答案是用 JGit 4.8.0 编写的。