7

Contex

I'm trying to detect possible file rename that occurred after last commit, in a working copy. On my example, I have a clean working copy and I do that:

git mv old.txt new.txt

Running $ git status shows the expected result:

# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       renamed:    old.txt -> new.txt

I tried

Using a StatusCommand, I can see old.txt in the removed list, and new.txt in the added list. But I can't find a way to link them together.

I'm aware of the existence of RenameDetector, but it works using DiffEntry, and I don't know how to get DiffEntries between HEAD and the Working Copy.

Serge Farny
  • 932
  • 10
  • 22

2 Answers2

9

Never mind, found the answer. JGit's API is very complicated..

TreeWalk tw = new TreeWalk(repository);
tw.setRecursive(true);
tw.addTree(CommitUtils.getHead(repository).getTree());
tw.addTree(new FileTreeIterator(repository));

RenameDetector rd = new RenameDetector(repository);
rd.addAll(DiffEntry.scan(tw));

List<DiffEntry> lde = rd.compute(tw.getObjectReader(), null);
for (DiffEntry de : lde) {
    if (de.getScore() >= rd.getRenameScore()) {
        System.out.println("file: " + de.getOldPath() + " copied/moved to: " + de.getNewPath());
    }
}

(This snippet also use Gitective library)

Serge Farny
  • 932
  • 10
  • 22
0

In a case that someone wants to use path filter when getting DiffEntry, new and old path should be provided.

 List<DiffEntry> diffs = git.diff()
            .setOldTree(prepareTreeParser(repository, oldCommit))
            .setNewTree(prepareTreeParser(repository, newCommit))
            .setPathFilter(PathFilterGroup.createFromStrings(new String[]{"new/b.txt","b.txt"}))
            .call();
 RenameDetector rd = new RenameDetector(repository);
 rd.addAll(diffs);
 diffs = rd.compute();

If you want code of tree parser method:

 private static AbstractTreeIterator prepareTreeParser(Repository repository, String objectId) throws IOException {
    try (RevWalk walk = new RevWalk(repository)) {
      RevCommit commit = walk.parseCommit(repository.resolve(objectId));
      RevTree tree = walk.parseTree(commit.getTree().getId());
      CanonicalTreeParser treeParser = new CanonicalTreeParser();
      try (ObjectReader reader = repository.newObjectReader()) {
           treeParser.reset(reader, tree.getId());
      }
      walk.dispose();
      return treeParser;
    }
}