java - 为什么 jGit 的 RevWalk.reset() 方法行为异常?

标签 java git version-control jgit

假设我们在 git 存储库中有两个文件,path/to/file1.txt 和 path/to/file2.txt。 file1.txt 先提交,然后是 file2.txt,因此它们属于具有不同 SHA1 的提交。我想使用 jGit 检索对应于每个文件的 SHA1。这是我到目前为止的代码:

String localPath = "/path/to/repo";
Repository localRepo = new FileRepository(localPath + "/.git");

Ref headRef = localRepo.getRef("refs/heads/master");
RevWalk revWalk = new RevWalk(localRepo);
RevCommit headCommit = revWalk.parseCommit(headRef.getObjectId());
TreeWalk tw = new TreeWalk(localRepo);
tw.addTree(headCommit.getTree());
tw.setRecursive(true);

HashMap<String, String> fileShas = new HashMap<String, String>();
RevWalk commitFinder = new RevWalk(localRepo);

while (tw.next()) {
  ArrayList<PathFilter> filters = new ArrayList<PathFilter>();
  filters.add(PathFilter.create(tw.getPathString()));

  commitFinder.reset();
  RevCommit iterHead = commitFinder.lookupCommit(headRef.getObjectId());
  commitFinder.markStart(iterHead);
  commitFinder.setTreeFilter(AndTreeFilter.create(PathFilterGroup.create(filters), TreeFilter.ANY_DIFF));
  commitFinder.setRevFilter(MaxCountRevFilter.create(1));

  RevCommit commit = commitFinder.next();
  fileShas.put(tw.getPathString(), commit.getId().getName());
}

不幸的是,这不起作用。我得到第一个文件的正确 SHA1,但第二个文件没有。看起来 commitFinder.reset(); 没有完成它的工作。如果我在每次迭代时创建一个新的 RevWalk,它可以工作但速度非常慢。知道为什么 reset() 不起作用吗?

最佳答案

尽管这并没有回答我的问题,但我还是将我的发现放在这里以提高可读性。下面显示的测试中的 getLatestModification 方法返回上次修改给定文件的提交 ID。

虽然代码比原始代码片段短,但问题仍然是 reset 显然不起作用。

public class RevWalkResetLearningTest {

  @Rule
  public final TemporaryFolder tempFolder = new TemporaryFolder();

  private Repository repository;

  @Test
  public void testReset() throws Exception {
    RevWalk revWalk = new RevWalk( repository );
    RevCommit beerCommit = getLastModification( revWalk, "plugins/emoji/public/images/beer.png" );
//    RevCommit discourseCommit = getLastModification( new RevWalk( repository ), "images/discourse.png" );
    RevCommit discourseCommit = getLastModification( revWalk, "images/discourse.png" );

    assertEquals( "8278fdb9ddbc61eea9f6e6045b705106678ce532", beerCommit.name() );
    assertEquals( "50cd44df2dec27c0834be4a2975fe175c3fac64f", discourseCommit.name() );
  }

  private RevCommit getLastModification( RevWalk revWalk, String path ) throws IOException {
    revWalk.reset();
    revWalk.markStart( revWalk.parseCommit( repository.resolve( "refs/heads/master" ) ) );
    revWalk.setTreeFilter( AndTreeFilter.create( PathFilter.create( path ), TreeFilter.ANY_DIFF ) );
    return revWalk.next();
  }

  @Before
  public void setUp() throws Exception {
//    Git git = Git.cloneRepository().setURI( "https://github.com/discourse/discourse.git" ).setDirectory( tempFolder.getRoot() ).call();
//    repository = git.getRepository();
    repository = new FileRepositoryBuilder().setMustExist( true ).setGitDir( new File( "/path/to/discourse/.git" ) ).build();
  }

  @After
  public void tearDown() {
    repository.close();
  }
}

测试失败,因为discourseCommit的commit-id与beerCommit相同。如果我更改代码,以便每次调用 getLastModification 时都会得到一个新的 RevWalk 实例(请参阅注释行),则测试会成功。

我建议开一个bug report或询问 JGit mailing list寻求帮助。

关于java - 为什么 jGit 的 RevWalk.reset() 方法行为异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24795001/

相关文章:

java - 从布局中删除组件失败

java - Spring webflux 中处理条件响应的正确方法是什么

linux - 我怎样才能恢复 git 提交但保留最原始的 git 提交历史(在 git blame 中)

git - 提交时从文件中删除的所有行以及添加到文件中的所有行

windows - git 可以在本地 Windows NTFS 机器上保留文件所有者、权限、ACL 和文件属性吗?

svn - github中的私有(private)文件夹

version-control - 如何在 Bazaar (bzr merge) 中进行忽略空格的合并?

java - 调用WebService时SSL握手失败

git 痛苦第 2 部分 : what does it mean when git won't commit, pull 或推文件?

java - 当光标放在窗口上时弹出窗口