无法使用 JGit 在无 blob 克隆上执行一些我可以通过命令行上的 Git 执行的操作。特别是稍后无法获取斑点。例如,考虑命令行上的以下 Git 操作顺序:
# Clone the repository but don't checkout any blobs
git clone --no-checkout --filter=blob:none <GIT-URL> .
# Checkout a branch that is *not* the main branch on the remote
git fetch origin develop:develop
# Move to the new branch
git symbolic-ref HEAD refs/heads/develop
git checkout develop <DIRECTORY-OR-FILE>
...
我尝试将其转换为 JGit 调用,如下所示:
FilterSpec filter = FilterSpec.fromFilterLine("blob:none");
try (Git git = Git.cloneRepository()
.setCredentialsProvider(getCredentialsProvider())
.setDirectory(new File("/tmp/repository"))
.setURI(<GIT-URL>)
.setRemote(Constants.DEFAULT_REMOTE_NAME)
.setTransportConfigCallback(t -> t.setFilterSpec(filter))
.setNoCheckout(true)
.call()) {
git.fetch()
.setCredentialsProvider(getCredentialsProvider())
.setRemote(Constants.DEFAULT_REMOTE_NAME)
.setRefSpecs("refs/heads/develop:refs/heads/develop")
.call();
git.getRepository()
.getRefDatabase()
.newUpdate(Constants.HEAD, false)
.link("refs/heads/develop");
git.checkout()
.setName("develop")
.addPath(<DIRECTORY-OR-FILE>)
.call();
...
}
checkout
失败并显示以下消息:
org.eclipse.jgit.errors.MissingObjectException: Missing unknown 57a7e7d782f72a1e846b08415c56684f8f42e5bf
它也从 JGit 克隆的存储库上的命令行失败,如果我在命令行上执行所有操作,则情况并非如此。
当要签出的 blob 尚不可用(如在无 blob 克隆中)时,命令行
git checkout ...
实际上会变成 git fetch ...
。
就 JGit 而言,
CheckoutCommand
无法转变为或调用 FetchCommand
- 除其他外,无法为获取提供凭证提供程序。
解决方案是通过如下所示遍历修订图来获取所有需要的 blob。
void fetch(Git git, List<String> paths) throws IOException, GitAPIException {
if (paths == null || paths.isEmpty()) {
return;
}
Repository repository = git.getRepository();
TreeWalk treeWalk = new TreeWalk(repository);
RevTree tree = new RevWalk(repository).parseCommit(repository.findRef(HEAD).getObjectId()).getTree();
treeWalk.addTree(tree);
treeWalk.setRecursive(false);
TreeFilter filter = paths.size() == 1 ? PathFilter.create(paths.get(0)) :
OrTreeFilter.create(paths.stream().map(PathFilter::create).collect(Collectors.toList()));
treeWalk.setFilter(filter);
String root = repository.getDirectory().getParentFile().getAbsolutePath();
Map<ObjectId, String> files = new HashMap<>();
List<String> directories = new ArrayList<>();
while(treeWalk.next()) {
if (treeWalk.isSubtree()) {
//noinspection ResultOfMethodCallIgnored
new File(root + File.separator + treeWalk.getPathString()).mkdirs();
directories.add(treeWalk.getObjectId(0).getName());
treeWalk.enterSubtree();
} else {
files.put(treeWalk.getObjectId(0), treeWalk.getPathString());
}
}
// Fetch all the requested blobs.
String[] dirsAndFiles = Stream.concat(files.keySet().stream().map(ObjectId::getName), directories.stream()).toArray(String[]::new);
files.keySet().stream().map(ObjectId::getName).forEach(directories::add);
git.fetch()
.setCredentialsProvider(getCredentialsProvider())
.setRefSpecs(dirsAndFiles)
.setCheckFetchedObjects(true)
.call();
// Write out the files.
files.forEach((key, value) -> {
try {
repository.open(key).copyTo(new FileOutputStream(root + File.separator + value));
} catch (IOException e) {
throw new RuntimeException(e + " File = " + value);
}
});
}