2

I am using the StashApplyCommand class to apply stashed commits to the working tree. In case conflicts occur, the call() method of this class throws a StashApplyFailureException.

However, I can't find a way to retrieve the list of conflicts. Unlike the MergeCommand, the StashApplyCommand does not return this list as part of the return value of the call() method.

Is it at all possible to retrieve the conflicts caused by a stash apply in JGit?

Rüdiger Herrmann
  • 20,512
  • 11
  • 62
  • 79
Epicurus
  • 2,103
  • 7
  • 29
  • 39

1 Answers1

3

I was facing the same problem and couldn't find a way to have the StashApplyCommand tell me which files cause a conflict.

The workaround I currently use is to use a ResolveMerger to see if the stash can be applied. If there are conflicting files, the merger is able to list them.

For example:

ObjectId headCommitId = // id of head commit
RevCommit stashCommit = // parsed stash (commit) to be applied
ObjectId stashHeadCommit = stashCommit.getParent(0);
ResolveMerger merger = (ResolveMerger)MergeStrategy.RESOLVE.newMerger(repository, true);
merger.setWorkingTreeIterator(new FileTreeIterator(repository));
merger.setBase(stashHeadCommit);
if(!merger.merge(headCommitId, stashCommit)) {
  // look into merger.getFailingPaths() and merger.getUnmergedPaths()
}

Note that the above code snippet would not detect index conflicts as in my environment, the index can never cause conflicts. Though it should be possible to extend this approach to examine the index for conflicts. IIRC stashCommit.getParent( 1 ) points to the stashed index.

In the hope that the workaround becomes obsolete one day, I've filed an enhancement request: https://bugs.eclipse.org/bugs/show_bug.cgi?id=501475

Rüdiger Herrmann
  • 20,512
  • 11
  • 62
  • 79
  • Thank you for the suggestion and for filing the enhancement request. Your approach looks like it should work, but for some reason it doesn't detect any conflicts. The stashed changes I am trying to apply are not staged, so this should not involve the index in my case. There is, however, one aspect of your answer that I do not understand. Why is it necessary to call stashCommit.getParent(0)? Won't this call return the same commit that stashCommit identifies? – Epicurus Sep 15 '16 at 18:05
  • I took the `getParent(0)` 'detour' from the `StashApplyCommand`, in the believe that it references the commit of the stashed files. But reading again I might be wrong here (though I am wondering why my tests pass...). However, re-reading the JGit code and [this post](http://stackoverflow.com/questions/27012878/why-is-a-stash-represented-as-2-commits) you might be successful when using `stashCommit` instead of `stashCommit.getParent(0)`. Parent 1 seems to point to the HEAD the stash was created from. And HEAD can alsways be merged with itself. – Rüdiger Herrmann Sep 15 '16 at 18:36
  • If you could share a standalone test case with your non-functioning conflict detection, that would help to track down what's going wrong. – Rüdiger Herrmann Sep 15 '16 at 18:43
  • I was finally able to make it work thanks to your link to the explanation of how stashing creates two seprate commits. My solution was to set the base of the 3-way merge to the stashed index commit using `merger.setBase(stashCommit.getParent(1))`. This works because in my particular case all changes to HEAD that happen after stash creation are caused by running a pull command, which of course advances the HEAD to a new commit. Thanks again for the help, I think I now understand how stashing works. – Epicurus Sep 16 '16 at 08:25
  • Thanks for you feedback. After re-reading the JGit sources, I think the merger should be configured with the base at `stashCommit.getParent(0)` and called with `merger.merge( headCommit, stashCommit )`. I've changed my own code accordingly and all existing tests stay green, plus additional tests for other conflict scenarios are green. – Rüdiger Herrmann Sep 16 '16 at 15:48
  • You are right, your updated snippet matches what I ended up using in my code, and it also seems logical. Thanks again for the help. – Epicurus Sep 21 '16 at 12:51