/** * The resolve conflict way of three way merging * * @param baseTree * @param headTree * @param mergeTree * @param ignoreConflicts Controls what to do in case a content-merge is done and a conflict is * detected. The default setting for this should be <code>false</code>. In this case the * working tree file is filled with new content (containing conflict markers) and the index is * filled with multiple stages containing BASE, OURS and THEIRS content. Having such non-0 * stages is the sign to git tools that there are still conflicts for that path. * <p>If <code>true</code> is specified the behavior is different. In case a conflict is * detected the working tree file is again filled with new content (containing conflict * markers). But also stage 0 of the index is filled with that content. No other stages are * filled. Means: there is no conflict on that path but the new content (including conflict * markers) is stored as successful merge result. This is needed in the context of {@link * RecursiveMerger} where when determining merge bases we don't want to deal with * content-merge conflicts. * @return whether the trees merged cleanly * @throws IOException * @since 3.5 */ protected boolean mergeTrees( AbstractTreeIterator baseTree, RevTree headTree, RevTree mergeTree, boolean ignoreConflicts) throws IOException { builder = dircache.builder(); DirCacheBuildIterator buildIt = new DirCacheBuildIterator(builder); tw = new NameConflictTreeWalk(reader); tw.addTree(baseTree); tw.addTree(headTree); tw.addTree(mergeTree); tw.addTree(buildIt); if (workingTreeIterator != null) { tw.addTree(workingTreeIterator); } else { tw.setFilter(TreeFilter.ANY_DIFF); } if (!mergeTreeWalk(tw, ignoreConflicts)) { return false; } if (!inCore) { // No problem found. The only thing left to be done is to // checkout all files from "theirs" which have been selected to // go into the new index. checkout(); // All content-merges are successfully done. If we can now write the // new index we are on quite safe ground. Even if the checkout of // files coming from "theirs" fails the user can work around such // failures by checking out the index again. if (!builder.commit()) { cleanUp(); throw new IndexWriteException(); } builder = null; } else { builder.finish(); builder = null; } if (getUnmergedPaths().isEmpty() && !failed()) { resultTree = dircache.writeTree(getObjectInserter()); return true; } else { resultTree = null; return false; } }
private boolean isModified(String path) throws CorruptObjectException, IOException { NameConflictTreeWalk tw = new NameConflictTreeWalk(repo); tw.addTree(new DirCacheIterator(dc)); tw.addTree(new FileTreeIterator(repo)); tw.setRecursive(true); tw.setFilter(PathFilter.create(path)); DirCacheIterator dcIt; WorkingTreeIterator wtIt; while (tw.next()) { dcIt = tw.getTree(0, DirCacheIterator.class); wtIt = tw.getTree(1, WorkingTreeIterator.class); if (dcIt == null || wtIt == null) return true; if (wtIt.isModified(dcIt.getDirCacheEntry(), true)) { return true; } } return false; }
/** * Scan head, index and merge tree. Used during normal checkout or merge operations. * * @throws CorruptObjectException * @throws IOException */ public void preScanTwoTrees() throws CorruptObjectException, IOException { removed.clear(); updated.clear(); conflicts.clear(); walk = new NameConflictTreeWalk(repo); builder = dc.builder(); addTree(walk, headCommitTree); addTree(walk, mergeCommitTree); walk.addTree(new DirCacheBuildIterator(builder)); walk.addTree(workingTree); while (walk.next()) { processEntry( walk.getTree(0, CanonicalTreeParser.class), walk.getTree(1, CanonicalTreeParser.class), walk.getTree(2, DirCacheBuildIterator.class), walk.getTree(3, WorkingTreeIterator.class)); if (walk.isSubtree()) walk.enterSubtree(); } }
/** * Scan index and merge tree (no HEAD). Used e.g. for initial checkout when there is no head yet. * * @throws MissingObjectException * @throws IncorrectObjectTypeException * @throws CorruptObjectException * @throws IOException */ public void prescanOneTree() throws MissingObjectException, IncorrectObjectTypeException, CorruptObjectException, IOException { removed.clear(); updated.clear(); conflicts.clear(); builder = dc.builder(); walk = new NameConflictTreeWalk(repo); walk.addTree(mergeCommitTree); walk.addTree(new DirCacheBuildIterator(builder)); walk.addTree(workingTree); while (walk.next()) { processEntry( walk.getTree(0, CanonicalTreeParser.class), walk.getTree(1, DirCacheBuildIterator.class), walk.getTree(2, WorkingTreeIterator.class)); if (walk.isSubtree()) walk.enterSubtree(); } conflicts.removeAll(removed); }