Clone a git repository into an InMemoryRepository with JGit

后端 未结 3 1981
温柔的废话
温柔的废话 2020-12-06 07:34

I need to clone an existing git repository into an InMemoryRepository, using JGit, change a file\'s content and push the changes back to the remote repository.<

相关标签:
3条回答
  • 2020-12-06 07:39

    The CloneCommand will always create a file-based repository. The lines from your post that create an InMemoryRepository have no effect on the clone command.

    I suggest to clone into a temporary location if you only need the repository to make a change and push the result.

    For example:

    Git.cloneRepository().setURI( ... ).setDirectory( new File("/path/to/empty/dir" ) ).call();  
    

    An InMemoryRepository in JGit still requires a work directory for operations like checkout, etc. Only the object database which is usually found in the .git directory is stored in memory

    0 讨论(0)
  • 2020-12-06 07:40

    There is a proper solution without any files on disk, even temporary:

        // 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;
        }
    
    

    So, actually you have TreeWalk here (which is default to recursive), but you can change this and manually iterate all from repo.

    0 讨论(0)
  • 2020-12-06 07:52

    Also, with a small tweak on previous answer:

    • Listing all files in commit
    • Filtering files by extension

      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;
      

      };

    0 讨论(0)
提交回复
热议问题