使用 JGit 将 git 存储库克隆到 InMemoryRepository
Clone a git repository into an InMemoryRepository with JGit
我需要使用 JGit 将现有 git 存储库克隆到 InMemoryRepository
,更改文件内容并将更改推送回远程存储库。
我找不到任何将存储库克隆到内存存储库的示例。
我试过这个:
InMemoryRepository.Builder builder = new InMemoryRepository.Builder();
InMemoryRepository inm = builder.build();
Git.cloneRepository().setURI("git@[github_url].git").setDirectory(inm.getDirectory()).call();
导致错误:
'Destination path ".git" already exists and is not an empty
directory'.
我检查了 InMemoryRepository.Builder
和 Repository
类 的配置选项,但没有发现任何有用的东西。
怎么办?在那之后,更改文件内容并将其推送到 github 是否有任何问题,全部来自内存存储库?
CloneCommand
将始终创建基于文件的存储库。 post 中创建 InMemoryRepository
的行对克隆命令没有影响。
如果您只需要存储库进行更改并推送结果,我建议克隆到一个临时位置。
例如:
Git.cloneRepository().setURI( ... ).setDirectory( new File("/path/to/empty/dir" ) ).call();
JGit中的InMemoryRepository
仍然需要一个工作目录来进行结帐等操作。只有通常在.git
目录中找到的对象数据库存储在内存中
有一个正确的解决方案,磁盘上没有任何文件,即使是临时文件:
// sample usage
private void loadFromGit() throws Exception {
ObjectLoader loader = loadRemote("https://github.com/msangel/promisified-resource-loader", "master", "README.md");
loader.copyTo(System.out);
}
private ObjectLoader loadRemote(String uri, String branch, String filename) throws Exception {
DfsRepositoryDescription repoDesc = new DfsRepositoryDescription();
InMemoryRepository repo = new InMemoryRepository(repoDesc);
Git git = new Git(repo);
git.fetch()
.setRemote(uri)
.setRefSpecs(new RefSpec("+refs/heads/*:refs/heads/*"))
.call();
repo.getObjectDatabase();
ObjectId lastCommitId = repo.resolve("refs/heads/"+ branch);
RevWalk revWalk = new RevWalk(repo);
RevCommit commit = revWalk.parseCommit(lastCommitId);
RevTree tree = commit.getTree();
TreeWalk treeWalk = new TreeWalk(repo);
treeWalk.addTree(tree);
treeWalk.setRecursive(true);
treeWalk.setFilter(PathFilter.create(filename));
if (!treeWalk.next()) {
return null;
}
ObjectId objectId = treeWalk.getObjectId(0);
ObjectLoader loader = repo.open(objectId);
return loader;
}
所以,实际上你在这里有 TreeWalk(默认为递归),但你可以更改它并手动从 repo 迭代所有内容。
另外,对之前的回答稍作调整:
- 列出提交中的所有文件
正在按扩展名过滤文件
public Function<String, List<String>> lastCommitFiles = (extension) -> {
final List<String> paths = new ArrayList<>();
try {
...
try (TreeWalk walk = new TreeWalk(inMemoryRepository)) {
walk.addTree(revTree);
walk.setRecursive(true);
walk.setPostOrderTraversal(true);
while (walk.next()) {
if ((extension != null && extension.length() > 0)) {
if (walk.getPathString().lastIndexOf(extension) != -1) {
paths.add(walk.getPathString());
}
} else paths.add(walk.getPathString());
}
}
return paths;
} catch (GitAPIException | IOException e) {
log.error(e.getMessage());
}
return paths;
};
我需要使用 JGit 将现有 git 存储库克隆到 InMemoryRepository
,更改文件内容并将更改推送回远程存储库。
我找不到任何将存储库克隆到内存存储库的示例。
我试过这个:
InMemoryRepository.Builder builder = new InMemoryRepository.Builder();
InMemoryRepository inm = builder.build();
Git.cloneRepository().setURI("git@[github_url].git").setDirectory(inm.getDirectory()).call();
导致错误:
'Destination path ".git" already exists and is not an empty directory'.
我检查了 InMemoryRepository.Builder
和 Repository
类 的配置选项,但没有发现任何有用的东西。
怎么办?在那之后,更改文件内容并将其推送到 github 是否有任何问题,全部来自内存存储库?
CloneCommand
将始终创建基于文件的存储库。 post 中创建 InMemoryRepository
的行对克隆命令没有影响。
如果您只需要存储库进行更改并推送结果,我建议克隆到一个临时位置。
例如:
Git.cloneRepository().setURI( ... ).setDirectory( new File("/path/to/empty/dir" ) ).call();
JGit中的InMemoryRepository
仍然需要一个工作目录来进行结帐等操作。只有通常在.git
目录中找到的对象数据库存储在内存中
有一个正确的解决方案,磁盘上没有任何文件,即使是临时文件:
// sample usage
private void loadFromGit() throws Exception {
ObjectLoader loader = loadRemote("https://github.com/msangel/promisified-resource-loader", "master", "README.md");
loader.copyTo(System.out);
}
private ObjectLoader loadRemote(String uri, String branch, String filename) throws Exception {
DfsRepositoryDescription repoDesc = new DfsRepositoryDescription();
InMemoryRepository repo = new InMemoryRepository(repoDesc);
Git git = new Git(repo);
git.fetch()
.setRemote(uri)
.setRefSpecs(new RefSpec("+refs/heads/*:refs/heads/*"))
.call();
repo.getObjectDatabase();
ObjectId lastCommitId = repo.resolve("refs/heads/"+ branch);
RevWalk revWalk = new RevWalk(repo);
RevCommit commit = revWalk.parseCommit(lastCommitId);
RevTree tree = commit.getTree();
TreeWalk treeWalk = new TreeWalk(repo);
treeWalk.addTree(tree);
treeWalk.setRecursive(true);
treeWalk.setFilter(PathFilter.create(filename));
if (!treeWalk.next()) {
return null;
}
ObjectId objectId = treeWalk.getObjectId(0);
ObjectLoader loader = repo.open(objectId);
return loader;
}
所以,实际上你在这里有 TreeWalk(默认为递归),但你可以更改它并手动从 repo 迭代所有内容。
另外,对之前的回答稍作调整:
- 列出提交中的所有文件
正在按扩展名过滤文件
public Function<String, List<String>> lastCommitFiles = (extension) -> { final List<String> paths = new ArrayList<>(); try { ... try (TreeWalk walk = new TreeWalk(inMemoryRepository)) { walk.addTree(revTree); walk.setRecursive(true); walk.setPostOrderTraversal(true); while (walk.next()) { if ((extension != null && extension.length() > 0)) { if (walk.getPathString().lastIndexOf(extension) != -1) { paths.add(walk.getPathString()); } } else paths.add(walk.getPathString()); } } return paths; } catch (GitAPIException | IOException e) { log.error(e.getMessage()); } return paths;
};