|
|
@ -204,6 +204,13 @@ public class ResolveMerger extends ThreeWayMerger { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!inCore) { |
|
|
|
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
|
|
|
|
// 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
|
|
|
|
// new index we are on quite safe ground. Even if the checkout of
|
|
|
|
// files coming from "theirs" fails the user can work around such
|
|
|
|
// files coming from "theirs" fails the user can work around such
|
|
|
@ -214,10 +221,6 @@ public class ResolveMerger extends ThreeWayMerger { |
|
|
|
} |
|
|
|
} |
|
|
|
builder = null; |
|
|
|
builder = null; |
|
|
|
|
|
|
|
|
|
|
|
// 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(); |
|
|
|
|
|
|
|
} else { |
|
|
|
} else { |
|
|
|
builder.finish(); |
|
|
|
builder.finish(); |
|
|
|
builder = null; |
|
|
|
builder = null; |
|
|
@ -313,19 +316,43 @@ public class ResolveMerger extends ThreeWayMerger { |
|
|
|
* @param path |
|
|
|
* @param path |
|
|
|
* @param p |
|
|
|
* @param p |
|
|
|
* @param stage |
|
|
|
* @param stage |
|
|
|
|
|
|
|
* @param lastMod |
|
|
|
|
|
|
|
* @param len |
|
|
|
* @return the entry which was added to the index |
|
|
|
* @return the entry which was added to the index |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private DirCacheEntry add(byte[] path, CanonicalTreeParser p, int stage) { |
|
|
|
private DirCacheEntry add(byte[] path, CanonicalTreeParser p, int stage, |
|
|
|
|
|
|
|
long lastMod, long len) { |
|
|
|
if (p != null && !p.getEntryFileMode().equals(FileMode.TREE)) { |
|
|
|
if (p != null && !p.getEntryFileMode().equals(FileMode.TREE)) { |
|
|
|
DirCacheEntry e = new DirCacheEntry(path, stage); |
|
|
|
DirCacheEntry e = new DirCacheEntry(path, stage); |
|
|
|
e.setFileMode(p.getEntryFileMode()); |
|
|
|
e.setFileMode(p.getEntryFileMode()); |
|
|
|
e.setObjectId(p.getEntryObjectId()); |
|
|
|
e.setObjectId(p.getEntryObjectId()); |
|
|
|
|
|
|
|
e.setLastModified(lastMod); |
|
|
|
|
|
|
|
e.setLength(len); |
|
|
|
builder.add(e); |
|
|
|
builder.add(e); |
|
|
|
return e; |
|
|
|
return e; |
|
|
|
} |
|
|
|
} |
|
|
|
return null; |
|
|
|
return null; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* adds a entry to the index builder which is a copy of the specified |
|
|
|
|
|
|
|
* DirCacheEntry |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @param e |
|
|
|
|
|
|
|
* the entry which should be copied |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* @return the entry which was added to the index |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
private DirCacheEntry keep(DirCacheEntry e) { |
|
|
|
|
|
|
|
DirCacheEntry newEntry = new DirCacheEntry(e.getPathString(), e.getStage()); |
|
|
|
|
|
|
|
newEntry.setFileMode(e.getFileMode()); |
|
|
|
|
|
|
|
newEntry.setObjectId(e.getObjectId()); |
|
|
|
|
|
|
|
newEntry.setLastModified(e.getLastModified()); |
|
|
|
|
|
|
|
newEntry.setLength(e.getLength()); |
|
|
|
|
|
|
|
builder.add(newEntry); |
|
|
|
|
|
|
|
return newEntry; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Processes one path and tries to merge. This method will do all do all |
|
|
|
* Processes one path and tries to merge. This method will do all do all |
|
|
|
* trivial (not content) merges and will also detect if a merge will fail. |
|
|
|
* trivial (not content) merges and will also detect if a merge will fail. |
|
|
@ -382,12 +409,27 @@ public class ResolveMerger extends ThreeWayMerger { |
|
|
|
if (isIndexDirty()) |
|
|
|
if (isIndexDirty()) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DirCacheEntry ourDce = null; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (index == null) { |
|
|
|
|
|
|
|
// create a fake DCE, but only if ours is valid. ours is kept only
|
|
|
|
|
|
|
|
// in case it is valid, so a null ourDce is ok in all other cases.
|
|
|
|
|
|
|
|
if (modeO != 0) { |
|
|
|
|
|
|
|
ourDce = new DirCacheEntry(tw.getRawPath()); |
|
|
|
|
|
|
|
ourDce.setObjectId(tw.getObjectId(T_OURS)); |
|
|
|
|
|
|
|
ourDce.setFileMode(tw.getFileMode(T_OURS)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
ourDce = index.getDirCacheEntry(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (nonTree(modeO) && nonTree(modeT) && tw.idEqual(T_OURS, T_THEIRS)) { |
|
|
|
if (nonTree(modeO) && nonTree(modeT) && tw.idEqual(T_OURS, T_THEIRS)) { |
|
|
|
// OURS and THEIRS have equal content. Check the file mode
|
|
|
|
// OURS and THEIRS have equal content. Check the file mode
|
|
|
|
if (modeO == modeT) { |
|
|
|
if (modeO == modeT) { |
|
|
|
// content and mode of OURS and THEIRS are equal: it doesn't
|
|
|
|
// content and mode of OURS and THEIRS are equal: it doesn't
|
|
|
|
// matter which one we choose. OURS is chosen.
|
|
|
|
// matter which one we choose. OURS is chosen. Since the index
|
|
|
|
add(tw.getRawPath(), ours, DirCacheEntry.STAGE_0); |
|
|
|
// is clean (the index matches already OURS) we can keep the existing one
|
|
|
|
|
|
|
|
keep(ourDce); |
|
|
|
// no checkout needed!
|
|
|
|
// no checkout needed!
|
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} else { |
|
|
|
} else { |
|
|
@ -398,22 +440,25 @@ public class ResolveMerger extends ThreeWayMerger { |
|
|
|
if (newMode != FileMode.MISSING.getBits()) { |
|
|
|
if (newMode != FileMode.MISSING.getBits()) { |
|
|
|
if (newMode == modeO) |
|
|
|
if (newMode == modeO) |
|
|
|
// ours version is preferred
|
|
|
|
// ours version is preferred
|
|
|
|
add(tw.getRawPath(), ours, DirCacheEntry.STAGE_0); |
|
|
|
keep(ourDce); |
|
|
|
else { |
|
|
|
else { |
|
|
|
// the preferred version THEIRS has a different mode
|
|
|
|
// the preferred version THEIRS has a different mode
|
|
|
|
// than ours. Check it out!
|
|
|
|
// than ours. Check it out!
|
|
|
|
if (isWorktreeDirty(work)) |
|
|
|
if (isWorktreeDirty(work)) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
// we know about length and lastMod only after we have written the new content.
|
|
|
|
|
|
|
|
// This will happen later. Set these values to 0 for know.
|
|
|
|
DirCacheEntry e = add(tw.getRawPath(), theirs, |
|
|
|
DirCacheEntry e = add(tw.getRawPath(), theirs, |
|
|
|
DirCacheEntry.STAGE_0); |
|
|
|
DirCacheEntry.STAGE_0, 0, 0); |
|
|
|
toBeCheckedOut.put(tw.getPathString(), e); |
|
|
|
toBeCheckedOut.put(tw.getPathString(), e); |
|
|
|
} |
|
|
|
} |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
// FileModes are not mergeable. We found a conflict on modes
|
|
|
|
// FileModes are not mergeable. We found a conflict on modes.
|
|
|
|
add(tw.getRawPath(), base, DirCacheEntry.STAGE_1); |
|
|
|
// For conflicting entries we don't know lastModified and length.
|
|
|
|
add(tw.getRawPath(), ours, DirCacheEntry.STAGE_2); |
|
|
|
add(tw.getRawPath(), base, DirCacheEntry.STAGE_1, 0, 0); |
|
|
|
add(tw.getRawPath(), theirs, DirCacheEntry.STAGE_3); |
|
|
|
add(tw.getRawPath(), ours, DirCacheEntry.STAGE_2, 0, 0); |
|
|
|
|
|
|
|
add(tw.getRawPath(), theirs, DirCacheEntry.STAGE_3, 0, 0); |
|
|
|
unmergedPaths.add(tw.getPathString()); |
|
|
|
unmergedPaths.add(tw.getPathString()); |
|
|
|
mergeResults.put( |
|
|
|
mergeResults.put( |
|
|
|
tw.getPathString(), |
|
|
|
tw.getPathString(), |
|
|
@ -426,8 +471,8 @@ public class ResolveMerger extends ThreeWayMerger { |
|
|
|
|
|
|
|
|
|
|
|
if (nonTree(modeO) && modeB == modeT && tw.idEqual(T_BASE, T_THEIRS)) { |
|
|
|
if (nonTree(modeO) && modeB == modeT && tw.idEqual(T_BASE, T_THEIRS)) { |
|
|
|
// THEIRS was not changed compared to BASE. All changes must be in
|
|
|
|
// THEIRS was not changed compared to BASE. All changes must be in
|
|
|
|
// OURS. OURS is chosen.
|
|
|
|
// OURS. OURS is chosen. We can keep the existing entry.
|
|
|
|
add(tw.getRawPath(), ours, DirCacheEntry.STAGE_0); |
|
|
|
keep(ourDce); |
|
|
|
// no checkout needed!
|
|
|
|
// no checkout needed!
|
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
@ -440,8 +485,11 @@ public class ResolveMerger extends ThreeWayMerger { |
|
|
|
if (isWorktreeDirty(work)) |
|
|
|
if (isWorktreeDirty(work)) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
if (nonTree(modeT)) { |
|
|
|
if (nonTree(modeT)) { |
|
|
|
|
|
|
|
// we know about length and lastMod only after we have written
|
|
|
|
|
|
|
|
// the new content.
|
|
|
|
|
|
|
|
// This will happen later. Set these values to 0 for know.
|
|
|
|
DirCacheEntry e = add(tw.getRawPath(), theirs, |
|
|
|
DirCacheEntry e = add(tw.getRawPath(), theirs, |
|
|
|
DirCacheEntry.STAGE_0); |
|
|
|
DirCacheEntry.STAGE_0, 0, 0); |
|
|
|
if (e != null) |
|
|
|
if (e != null) |
|
|
|
toBeCheckedOut.put(tw.getPathString(), e); |
|
|
|
toBeCheckedOut.put(tw.getPathString(), e); |
|
|
|
return true; |
|
|
|
return true; |
|
|
@ -460,16 +508,16 @@ public class ResolveMerger extends ThreeWayMerger { |
|
|
|
// detected later
|
|
|
|
// detected later
|
|
|
|
if (nonTree(modeO) && !nonTree(modeT)) { |
|
|
|
if (nonTree(modeO) && !nonTree(modeT)) { |
|
|
|
if (nonTree(modeB)) |
|
|
|
if (nonTree(modeB)) |
|
|
|
add(tw.getRawPath(), base, DirCacheEntry.STAGE_1); |
|
|
|
add(tw.getRawPath(), base, DirCacheEntry.STAGE_1, 0, 0); |
|
|
|
add(tw.getRawPath(), ours, DirCacheEntry.STAGE_2); |
|
|
|
add(tw.getRawPath(), ours, DirCacheEntry.STAGE_2, 0, 0); |
|
|
|
unmergedPaths.add(tw.getPathString()); |
|
|
|
unmergedPaths.add(tw.getPathString()); |
|
|
|
enterSubtree = false; |
|
|
|
enterSubtree = false; |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
if (nonTree(modeT) && !nonTree(modeO)) { |
|
|
|
if (nonTree(modeT) && !nonTree(modeO)) { |
|
|
|
if (nonTree(modeB)) |
|
|
|
if (nonTree(modeB)) |
|
|
|
add(tw.getRawPath(), base, DirCacheEntry.STAGE_1); |
|
|
|
add(tw.getRawPath(), base, DirCacheEntry.STAGE_1, 0, 0); |
|
|
|
add(tw.getRawPath(), theirs, DirCacheEntry.STAGE_3); |
|
|
|
add(tw.getRawPath(), theirs, DirCacheEntry.STAGE_3, 0, 0); |
|
|
|
unmergedPaths.add(tw.getPathString()); |
|
|
|
unmergedPaths.add(tw.getPathString()); |
|
|
|
enterSubtree = false; |
|
|
|
enterSubtree = false; |
|
|
|
return true; |
|
|
|
return true; |
|
|
@ -502,10 +550,10 @@ public class ResolveMerger extends ThreeWayMerger { |
|
|
|
if (((modeO != 0 && !tw.idEqual(T_BASE, T_OURS)) || (modeT != 0 && !tw |
|
|
|
if (((modeO != 0 && !tw.idEqual(T_BASE, T_OURS)) || (modeT != 0 && !tw |
|
|
|
.idEqual(T_BASE, T_THEIRS)))) { |
|
|
|
.idEqual(T_BASE, T_THEIRS)))) { |
|
|
|
|
|
|
|
|
|
|
|
add(tw.getRawPath(), base, DirCacheEntry.STAGE_1); |
|
|
|
add(tw.getRawPath(), base, DirCacheEntry.STAGE_1, 0, 0); |
|
|
|
add(tw.getRawPath(), ours, DirCacheEntry.STAGE_2); |
|
|
|
add(tw.getRawPath(), ours, DirCacheEntry.STAGE_2, 0, 0); |
|
|
|
DirCacheEntry e = add(tw.getRawPath(), theirs, |
|
|
|
DirCacheEntry e = add(tw.getRawPath(), theirs, |
|
|
|
DirCacheEntry.STAGE_3); |
|
|
|
DirCacheEntry.STAGE_3, 0, 0); |
|
|
|
|
|
|
|
|
|
|
|
// OURS was deleted checkout THEIRS
|
|
|
|
// OURS was deleted checkout THEIRS
|
|
|
|
if (modeO == 0) { |
|
|
|
if (modeO == 0) { |
|
|
@ -609,9 +657,9 @@ public class ResolveMerger extends ThreeWayMerger { |
|
|
|
// a conflict occurred, the file will contain conflict markers
|
|
|
|
// a conflict occurred, the file will contain conflict markers
|
|
|
|
// the index will be populated with the three stages and only the
|
|
|
|
// the index will be populated with the three stages and only the
|
|
|
|
// workdir (if used) contains the halfways merged content
|
|
|
|
// workdir (if used) contains the halfways merged content
|
|
|
|
add(tw.getRawPath(), base, DirCacheEntry.STAGE_1); |
|
|
|
add(tw.getRawPath(), base, DirCacheEntry.STAGE_1, 0, 0); |
|
|
|
add(tw.getRawPath(), ours, DirCacheEntry.STAGE_2); |
|
|
|
add(tw.getRawPath(), ours, DirCacheEntry.STAGE_2, 0, 0); |
|
|
|
add(tw.getRawPath(), theirs, DirCacheEntry.STAGE_3); |
|
|
|
add(tw.getRawPath(), theirs, DirCacheEntry.STAGE_3, 0, 0); |
|
|
|
mergeResults.put(tw.getPathString(), result); |
|
|
|
mergeResults.put(tw.getPathString(), result); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
// no conflict occurred, the file will contain fully merged content.
|
|
|
|
// no conflict occurred, the file will contain fully merged content.
|
|
|
|