diff options
Diffstat (limited to 'org.eclipse.jgit/src')
-rw-r--r-- | org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java | 82 |
1 files changed, 75 insertions, 7 deletions
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 b763568951..8211780ca1 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java @@ -51,6 +51,7 @@ import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; @@ -378,12 +379,46 @@ public class ResolveMerger extends ThreeWayMerger { if (isIndexDirty()) return false; - if (nonTree(modeO) && modeO == modeT && tw.idEqual(T_OURS, T_THEIRS)) { - // OURS and THEIRS are equal: it doesn't matter which one we choose. - // OURS is chosen. - add(tw.getRawPath(), ours, DirCacheEntry.STAGE_0); - // no checkout needed! - return true; + if (nonTree(modeO) && nonTree(modeT) && tw.idEqual(T_OURS, T_THEIRS)) { + // OURS and THEIRS have equal content. Check the file mode + if (modeO == modeT) { + // content and mode of OURS and THEIRS are equal: it doesn't + // matter which one we choose. OURS is chosen. + add(tw.getRawPath(), ours, DirCacheEntry.STAGE_0); + // no checkout needed! + return true; + } else { + // same content but different mode on OURS and THEIRS. + // Try to merge the mode and report an error if this is + // not possible. + int newMode = mergeFileModes(modeB, modeO, modeT); + if (newMode != FileMode.MISSING.getBits()) { + if (newMode == modeO) + // ours version is preferred + add(tw.getRawPath(), ours, DirCacheEntry.STAGE_0); + else { + // the preferred version THEIRS has a different mode + // than ours. Check it out! + if (isWorktreeDirty()) + return false; + DirCacheEntry e = add(tw.getRawPath(), theirs, + DirCacheEntry.STAGE_0); + toBeCheckedOut.put(tw.getPathString(), e); + } + return true; + } else { + // FileModes are not mergeable. We found a conflict on modes + add(tw.getRawPath(), base, DirCacheEntry.STAGE_1); + add(tw.getRawPath(), ours, DirCacheEntry.STAGE_2); + add(tw.getRawPath(), theirs, DirCacheEntry.STAGE_3); + unmergedPaths.add(tw.getPathString()); + mergeResults.put( + tw.getPathString(), + new MergeResult<RawText>(Collections + .<RawText> emptyList())); + } + return true; + } } if (nonTree(modeO) && modeB == modeT && tw.idEqual(T_BASE, T_THEIRS)) { @@ -582,7 +617,12 @@ public class ResolveMerger extends ThreeWayMerger { // no conflict occurred, the file will contain fully merged content. // the index will be populated with the new merged version DirCacheEntry dce = new DirCacheEntry(tw.getPathString()); - dce.setFileMode(tw.getFileMode(0)); + int newMode = mergeFileModes(tw.getRawMode(0), tw.getRawMode(1), + tw.getRawMode(2)); + // set the mode for the new content. Fall back to REGULAR_FILE if + // you can't merge modes of OURS and THEIRS + dce.setFileMode((newMode == FileMode.MISSING.getBits()) ? FileMode.REGULAR_FILE + : FileMode.fromBits(newMode)); dce.setLastModified(of.lastModified()); dce.setLength((int) of.length()); InputStream is = new FileInputStream(of); @@ -599,6 +639,34 @@ public class ResolveMerger extends ThreeWayMerger { } } + /** + * Try to merge filemodes. If only ours or theirs have changed the mode + * (compared to base) we choose that one. If ours and theirs have equal + * modes return that one. If also that is not the case the modes are not + * mergeable. Return {@link FileMode#MISSING} int that case. + * + * @param modeB + * filemode found in BASE + * @param modeO + * filemode found in OURS + * @param modeT + * filemode found in THEIRS + * + * @return the merged filemode or {@link FileMode#MISSING} in case of a + * conflict + */ + private int mergeFileModes(int modeB, int modeO, int modeT) { + if (modeO == modeT) + return modeO; + if (modeB == modeO) + // Base equal to Ours -> chooses Theirs if that is not missing + return (modeT == FileMode.MISSING.getBits()) ? modeO : modeT; + if (modeB == modeT) + // Base equal to Theirs -> chooses Ours if that is not missing + return (modeO == FileMode.MISSING.getBits()) ? modeT : modeO; + return FileMode.MISSING.getBits(); + } + private static RawText getRawText(ObjectId id, Repository db) throws IOException { if (id.equals(ObjectId.zeroId())) |