summaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit/src
diff options
context:
space:
mode:
authorMarkus Duft <markus.duft@salomon.at>2012-07-17 18:32:38 +0200
committerChristian Halstrick <christian.halstrick@sap.com>2012-07-19 10:30:59 +0200
commit3ea694c2523d909190b5350e13254a62e94ec5d5 (patch)
tree2300dc1a49a79d291c9392f844f402d2387385a3 /org.eclipse.jgit/src
parentaeb28b1f3e8763c006dd26e690fbcad0920bc1a4 (diff)
downloadjgit-3ea694c2523d909190b5350e13254a62e94ec5d5.tar.gz
jgit-3ea694c2523d909190b5350e13254a62e94ec5d5.zip
Teach ResolveMerger to create more correct DirCacheEntry's
Currently, after a merge/cherry-pick/rebase, all index entries are smudged as the ResolveMerger never sets entry lengths and/or modification times. This change teaches it to re-set them at least for things it did not touch. The other entries are then repaired when the index is persisted, or entries are checked out. Change-Id: I0944f2017483d32043d0d09409b13055b5609a4b Signed-off-by: Christian Halstrick <christian.halstrick@sap.com>
Diffstat (limited to 'org.eclipse.jgit/src')
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java100
1 files changed, 74 insertions, 26 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 2410d6fe04..3034bfb5d3 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/ResolveMerger.java
@@ -204,6 +204,13 @@ public class ResolveMerger extends ThreeWayMerger {
}
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
@@ -214,10 +221,6 @@ public class ResolveMerger extends ThreeWayMerger {
}
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 {
builder.finish();
builder = null;
@@ -313,13 +316,18 @@ public class ResolveMerger extends ThreeWayMerger {
* @param path
* @param p
* @param stage
+ * @param lastMod
+ * @param len
* @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)) {
DirCacheEntry e = new DirCacheEntry(path, stage);
e.setFileMode(p.getEntryFileMode());
e.setObjectId(p.getEntryObjectId());
+ e.setLastModified(lastMod);
+ e.setLength(len);
builder.add(e);
return e;
}
@@ -327,6 +335,25 @@ public class ResolveMerger extends ThreeWayMerger {
}
/**
+ * 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
* trivial (not content) merges and will also detect if a merge will fail.
* The merge will fail when one of the following is true
@@ -382,12 +409,27 @@ public class ResolveMerger extends ThreeWayMerger {
if (isIndexDirty())
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)) {
// 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);
+ // matter which one we choose. OURS is chosen. Since the index
+ // is clean (the index matches already OURS) we can keep the existing one
+ keep(ourDce);
// no checkout needed!
return true;
} else {
@@ -398,22 +440,25 @@ public class ResolveMerger extends ThreeWayMerger {
if (newMode != FileMode.MISSING.getBits()) {
if (newMode == modeO)
// ours version is preferred
- add(tw.getRawPath(), ours, DirCacheEntry.STAGE_0);
+ keep(ourDce);
else {
// the preferred version THEIRS has a different mode
// than ours. Check it out!
if (isWorktreeDirty(work))
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.STAGE_0);
+ DirCacheEntry.STAGE_0, 0, 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);
+ // FileModes are not mergeable. We found a conflict on modes.
+ // For conflicting entries we don't know lastModified and length.
+ add(tw.getRawPath(), base, DirCacheEntry.STAGE_1, 0, 0);
+ add(tw.getRawPath(), ours, DirCacheEntry.STAGE_2, 0, 0);
+ add(tw.getRawPath(), theirs, DirCacheEntry.STAGE_3, 0, 0);
unmergedPaths.add(tw.getPathString());
mergeResults.put(
tw.getPathString(),
@@ -426,8 +471,8 @@ public class ResolveMerger extends ThreeWayMerger {
if (nonTree(modeO) && modeB == modeT && tw.idEqual(T_BASE, T_THEIRS)) {
// THEIRS was not changed compared to BASE. All changes must be in
- // OURS. OURS is chosen.
- add(tw.getRawPath(), ours, DirCacheEntry.STAGE_0);
+ // OURS. OURS is chosen. We can keep the existing entry.
+ keep(ourDce);
// no checkout needed!
return true;
}
@@ -440,8 +485,11 @@ public class ResolveMerger extends ThreeWayMerger {
if (isWorktreeDirty(work))
return false;
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.STAGE_0);
+ DirCacheEntry.STAGE_0, 0, 0);
if (e != null)
toBeCheckedOut.put(tw.getPathString(), e);
return true;
@@ -460,16 +508,16 @@ public class ResolveMerger extends ThreeWayMerger {
// detected later
if (nonTree(modeO) && !nonTree(modeT)) {
if (nonTree(modeB))
- add(tw.getRawPath(), base, DirCacheEntry.STAGE_1);
- add(tw.getRawPath(), ours, DirCacheEntry.STAGE_2);
+ add(tw.getRawPath(), base, DirCacheEntry.STAGE_1, 0, 0);
+ add(tw.getRawPath(), ours, DirCacheEntry.STAGE_2, 0, 0);
unmergedPaths.add(tw.getPathString());
enterSubtree = false;
return true;
}
if (nonTree(modeT) && !nonTree(modeO)) {
if (nonTree(modeB))
- add(tw.getRawPath(), base, DirCacheEntry.STAGE_1);
- add(tw.getRawPath(), theirs, DirCacheEntry.STAGE_3);
+ add(tw.getRawPath(), base, DirCacheEntry.STAGE_1, 0, 0);
+ add(tw.getRawPath(), theirs, DirCacheEntry.STAGE_3, 0, 0);
unmergedPaths.add(tw.getPathString());
enterSubtree = false;
return true;
@@ -502,10 +550,10 @@ public class ResolveMerger extends ThreeWayMerger {
if (((modeO != 0 && !tw.idEqual(T_BASE, T_OURS)) || (modeT != 0 && !tw
.idEqual(T_BASE, T_THEIRS)))) {
- add(tw.getRawPath(), base, DirCacheEntry.STAGE_1);
- add(tw.getRawPath(), ours, DirCacheEntry.STAGE_2);
+ add(tw.getRawPath(), base, DirCacheEntry.STAGE_1, 0, 0);
+ add(tw.getRawPath(), ours, DirCacheEntry.STAGE_2, 0, 0);
DirCacheEntry e = add(tw.getRawPath(), theirs,
- DirCacheEntry.STAGE_3);
+ DirCacheEntry.STAGE_3, 0, 0);
// OURS was deleted checkout THEIRS
if (modeO == 0) {
@@ -609,9 +657,9 @@ public class ResolveMerger extends ThreeWayMerger {
// a conflict occurred, the file will contain conflict markers
// the index will be populated with the three stages and only the
// workdir (if used) contains the halfways merged content
- add(tw.getRawPath(), base, DirCacheEntry.STAGE_1);
- add(tw.getRawPath(), ours, DirCacheEntry.STAGE_2);
- add(tw.getRawPath(), theirs, DirCacheEntry.STAGE_3);
+ add(tw.getRawPath(), base, DirCacheEntry.STAGE_1, 0, 0);
+ add(tw.getRawPath(), ours, DirCacheEntry.STAGE_2, 0, 0);
+ add(tw.getRawPath(), theirs, DirCacheEntry.STAGE_3, 0, 0);
mergeResults.put(tw.getPathString(), result);
} else {
// no conflict occurred, the file will contain fully merged content.