diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java index a891c8591..28d42a616 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java @@ -85,6 +85,7 @@ import org.eclipse.jgit.treewalk.AbstractTreeIterator; import org.eclipse.jgit.treewalk.CanonicalTreeParser; import org.eclipse.jgit.treewalk.NameConflictTreeWalk; +import org.eclipse.jgit.treewalk.TreeWalk; import org.eclipse.jgit.treewalk.WorkingTreeIterator; import org.eclipse.jgit.util.FS; import org.eclipse.jgit.util.FileUtils; @@ -106,7 +107,12 @@ public enum MergeFailureReason { COULD_NOT_DELETE } - private NameConflictTreeWalk tw; + /** + * The tree walk which we'll iterate over to merge entries. + * + * @since 3.4 + */ + protected NameConflictTreeWalk tw; /** * string versions of a list of commit SHA1s @@ -115,17 +121,47 @@ public enum MergeFailureReason { */ protected String commitNames[]; - private static final int T_BASE = 0; + /** + * Index of the base tree within the {@link #tw tree walk}. + * + * @since 3.4 + */ + protected static final int T_BASE = 0; - private static final int T_OURS = 1; + /** + * Index of our tree in withthe {@link #tw tree walk}. + * + * @since 3.4 + */ + protected static final int T_OURS = 1; - private static final int T_THEIRS = 2; + /** + * Index of their tree within the {@link #tw tree walk}. + * + * @since 3.4 + */ + protected static final int T_THEIRS = 2; - private static final int T_INDEX = 3; + /** + * Index of the index tree within the {@link #tw tree walk}. + * + * @since 3.4 + */ + protected static final int T_INDEX = 3; - private static final int T_FILE = 4; + /** + * Index of the working directory tree within the {@link #tw tree walk}. + * + * @since 3.4 + */ + protected static final int T_FILE = 4; - private DirCacheBuilder builder; + /** + * Builder to update the cache during this merge. + * + * @since 3.4 + */ + protected DirCacheBuilder builder; /** * merge result as tree @@ -134,19 +170,59 @@ public enum MergeFailureReason { */ protected ObjectId resultTree; - private List unmergedPaths = new ArrayList(); + /** + * Paths that could not be merged by this merger because of an unsolvable + * conflict. + * + * @since 3.4 + */ + protected List unmergedPaths = new ArrayList(); - private List modifiedFiles = new LinkedList(); + /** + * Files modified during this merge operation. + * + * @since 3.4 + */ + protected List modifiedFiles = new LinkedList(); - private Map toBeCheckedOut = new HashMap(); + /** + * If the merger has nothing to do for a file but check it out at the end of + * the operation, it can be added here. + * + * @since 3.4 + */ + protected Map toBeCheckedOut = new HashMap(); - private List toBeDeleted = new ArrayList(); + /** + * Paths in this list will be deleted from the local copy at the end of the + * operation. + * + * @since 3.4 + */ + protected List toBeDeleted = new ArrayList(); - private Map> mergeResults = new HashMap>(); + /** + * Low-level textual merge results. Will be passed on to the callers in case + * of conflicts. + * + * @since 3.4 + */ + protected Map> mergeResults = new HashMap>(); - private Map failingPaths = new HashMap(); + /** + * Paths for which the merge failed altogether. + * + * @since 3.4 + */ + protected Map failingPaths = new HashMap(); - private boolean enterSubtree; + /** + * Updated as we merge entries of the tree walk. Tells us whether we should + * recurse into the entry if it is a subtree. + * + * @since 3.4 + */ + protected boolean enterSubtree; /** * Set to true if this merge should work in-memory. The repos dircache and @@ -277,8 +353,10 @@ private void createDir(File f) throws IOException { * @throws IOException * @throws CorruptObjectException * @throws NoWorkTreeException + * @since 3.4 */ - private void cleanUp() throws NoWorkTreeException, CorruptObjectException, + protected void cleanUp() throws NoWorkTreeException, + CorruptObjectException, IOException { if (inCore) { modifiedFiles.clear(); @@ -386,8 +464,9 @@ private DirCacheEntry keep(DirCacheEntry e) { * @throws IncorrectObjectTypeException * @throws CorruptObjectException * @throws IOException + * @since 3.4 */ - private boolean processEntry(CanonicalTreeParser base, + protected boolean processEntry(CanonicalTreeParser base, CanonicalTreeParser ours, CanonicalTreeParser theirs, DirCacheBuildIterator index, WorkingTreeIterator work) throws MissingObjectException, IncorrectObjectTypeException, @@ -932,19 +1011,8 @@ protected boolean mergeTrees(AbstractTreeIterator baseTree, if (workingTreeIterator != null) tw.addTree(workingTreeIterator); - while (tw.next()) { - if (!processEntry( - tw.getTree(T_BASE, CanonicalTreeParser.class), - tw.getTree(T_OURS, CanonicalTreeParser.class), - tw.getTree(T_THEIRS, CanonicalTreeParser.class), - tw.getTree(T_INDEX, DirCacheBuildIterator.class), - (workingTreeIterator == null) ? null : tw.getTree(T_FILE, - WorkingTreeIterator.class))) { - cleanUp(); - return false; - } - if (tw.isSubtree() && enterSubtree) - tw.enterSubtree(); + if (!mergeTreeWalk(tw)) { + return false; } if (!inCore) { @@ -976,4 +1044,32 @@ protected boolean mergeTrees(AbstractTreeIterator baseTree, return false; } } + + /** + * Process the given TreeWalk's entries. + * + * @param treeWalk + * The walk to iterate over. + * @return Whether the trees merged cleanly. + * @throws IOException + * @since 3.4 + */ + protected boolean mergeTreeWalk(TreeWalk treeWalk) throws IOException { + boolean hasWorkingTreeIterator = tw.getTreeCount() > T_FILE; + while (treeWalk.next()) { + if (!processEntry( + treeWalk.getTree(T_BASE, CanonicalTreeParser.class), + treeWalk.getTree(T_OURS, CanonicalTreeParser.class), + treeWalk.getTree(T_THEIRS, CanonicalTreeParser.class), + treeWalk.getTree(T_INDEX, DirCacheBuildIterator.class), + hasWorkingTreeIterator ? treeWalk.getTree(T_FILE, + WorkingTreeIterator.class) : null)) { + cleanUp(); + return false; + } + if (treeWalk.isSubtree() && enterSubtree) + treeWalk.enterSubtree(); + } + return true; + } }