JGit 和无 blob 克隆:稍后无法获取 blob

问题描述 投票:0回答:1

无法使用 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 克隆的存储库上的命令行失败,如果我在命令行上执行所有操作,则情况并非如此。

clone jgit git-refspec
1个回答
0
投票

当要签出的 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);
      }
    });
  }
© www.soinside.com 2019 - 2024. All rights reserved.