Refactor ResolveMerger
1. Perform an explicit check for untracked files. 2. Extract 'dirty checks' into separate methods 3. Clean up comments. 4. Tests: also check contents of files not affected by merge. Change-Id: Ieb089668834d0a395c9ab192c555538917dfdc47 Signed-off-by: Philipp Thun <philipp.thun@sap.com>
This commit is contained in:
parent
c0112f97a1
commit
fdb0a34abf
|
@ -411,6 +411,7 @@ public void testSuccessfulContentMergeAndDirtyworkingTree()
|
||||||
assertEquals("1\nb(side)\n3\n", read(new File(db.getWorkTree(), "b")));
|
assertEquals("1\nb(side)\n3\n", read(new File(db.getWorkTree(), "b")));
|
||||||
assertEquals("1\nc(main)\n3\n", read(new File(db.getWorkTree(),
|
assertEquals("1\nc(main)\n3\n", read(new File(db.getWorkTree(),
|
||||||
"c/c/c")));
|
"c/c/c")));
|
||||||
|
assertEquals("--- dirty ---", read(new File(db.getWorkTree(), "d")));
|
||||||
|
|
||||||
assertEquals(null, result.getConflicts());
|
assertEquals(null, result.getConflicts());
|
||||||
|
|
||||||
|
@ -468,6 +469,7 @@ public void testSingleDeletion() throws Exception {
|
||||||
assertFalse(new File(db.getWorkTree(), "b").exists());
|
assertFalse(new File(db.getWorkTree(), "b").exists());
|
||||||
assertEquals("1\nc(main)\n3\n",
|
assertEquals("1\nc(main)\n3\n",
|
||||||
read(new File(db.getWorkTree(), "c/c/c")));
|
read(new File(db.getWorkTree(), "c/c/c")));
|
||||||
|
assertEquals("1\nd\n3\n", read(new File(db.getWorkTree(), "d")));
|
||||||
|
|
||||||
// Do the opposite, be on a branch where we have deleted a file and
|
// Do the opposite, be on a branch where we have deleted a file and
|
||||||
// merge in a old commit where this file was not deleted
|
// merge in a old commit where this file was not deleted
|
||||||
|
@ -482,6 +484,7 @@ public void testSingleDeletion() throws Exception {
|
||||||
assertFalse(new File(db.getWorkTree(), "b").exists());
|
assertFalse(new File(db.getWorkTree(), "b").exists());
|
||||||
assertEquals("1\nc(main)\n3\n",
|
assertEquals("1\nc(main)\n3\n",
|
||||||
read(new File(db.getWorkTree(), "c/c/c")));
|
read(new File(db.getWorkTree(), "c/c/c")));
|
||||||
|
assertEquals("1\nd\n3\n", read(new File(db.getWorkTree(), "d")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -554,6 +557,7 @@ public void testDeletionAndConflict() throws Exception {
|
||||||
assertFalse(new File(db.getWorkTree(), "b").exists());
|
assertFalse(new File(db.getWorkTree(), "b").exists());
|
||||||
assertEquals("1\nc(main)\n3\n",
|
assertEquals("1\nc(main)\n3\n",
|
||||||
read(new File(db.getWorkTree(), "c/c/c")));
|
read(new File(db.getWorkTree(), "c/c/c")));
|
||||||
|
assertEquals("1\nd\n3\n", read(new File(db.getWorkTree(), "d")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -59,10 +59,10 @@
|
||||||
|
|
||||||
import org.eclipse.jgit.JGitText;
|
import org.eclipse.jgit.JGitText;
|
||||||
import org.eclipse.jgit.diff.DiffAlgorithm;
|
import org.eclipse.jgit.diff.DiffAlgorithm;
|
||||||
|
import org.eclipse.jgit.diff.DiffAlgorithm.SupportedAlgorithm;
|
||||||
import org.eclipse.jgit.diff.RawText;
|
import org.eclipse.jgit.diff.RawText;
|
||||||
import org.eclipse.jgit.diff.RawTextComparator;
|
import org.eclipse.jgit.diff.RawTextComparator;
|
||||||
import org.eclipse.jgit.diff.Sequence;
|
import org.eclipse.jgit.diff.Sequence;
|
||||||
import org.eclipse.jgit.diff.DiffAlgorithm.SupportedAlgorithm;
|
|
||||||
import org.eclipse.jgit.dircache.DirCache;
|
import org.eclipse.jgit.dircache.DirCache;
|
||||||
import org.eclipse.jgit.dircache.DirCacheBuildIterator;
|
import org.eclipse.jgit.dircache.DirCacheBuildIterator;
|
||||||
import org.eclipse.jgit.dircache.DirCacheBuilder;
|
import org.eclipse.jgit.dircache.DirCacheBuilder;
|
||||||
|
@ -364,42 +364,42 @@ private boolean processEntry(CanonicalTreeParser base,
|
||||||
CorruptObjectException, IOException {
|
CorruptObjectException, IOException {
|
||||||
enterSubtree = true;
|
enterSubtree = true;
|
||||||
final int modeO = tw.getRawMode(T_OURS);
|
final int modeO = tw.getRawMode(T_OURS);
|
||||||
final int modeI = tw.getRawMode(T_INDEX);
|
|
||||||
|
|
||||||
// Each index entry has to match ours, means: it has to be clean
|
|
||||||
if (nonTree(modeI)
|
|
||||||
&& !(tw.idEqual(T_INDEX, T_OURS) && modeO == modeI)) {
|
|
||||||
failingPaths.put(tw.getPathString(), MergeFailureReason.DIRTY_INDEX);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
final int modeT = tw.getRawMode(T_THEIRS);
|
final int modeT = tw.getRawMode(T_THEIRS);
|
||||||
|
final int modeB = tw.getRawMode(T_BASE);
|
||||||
|
|
||||||
|
if (modeO == 0 && modeT == 0 && modeB == 0)
|
||||||
|
// File is either untracked or new, staged but uncommitted
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (isIndexDirty())
|
||||||
|
return false;
|
||||||
|
|
||||||
if (nonTree(modeO) && modeO == modeT && tw.idEqual(T_OURS, T_THEIRS)) {
|
if (nonTree(modeO) && modeO == modeT && tw.idEqual(T_OURS, T_THEIRS)) {
|
||||||
// ours and theirs are equal: it doesn'nt matter
|
// OURS and THEIRS are equal: it doesn't matter which one we choose.
|
||||||
// which one we choose. OURS is choosen here.
|
// OURS is chosen.
|
||||||
add(tw.getRawPath(), ours, DirCacheEntry.STAGE_0);
|
add(tw.getRawPath(), ours, DirCacheEntry.STAGE_0);
|
||||||
// no checkout needed!
|
// no checkout needed!
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
final int modeB = tw.getRawMode(T_BASE);
|
|
||||||
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. Choose OURS.
|
// OURS. OURS is chosen.
|
||||||
add(tw.getRawPath(), ours, DirCacheEntry.STAGE_0);
|
add(tw.getRawPath(), ours, DirCacheEntry.STAGE_0);
|
||||||
|
// no checkout needed!
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (modeB == modeO && tw.idEqual(T_BASE, T_OURS)) {
|
if (modeB == modeO && tw.idEqual(T_BASE, T_OURS)) {
|
||||||
// OURS was not changed compared to base. All changes must be in
|
// OURS was not changed compared to BASE. All changes must be in
|
||||||
// THEIRS. Choose THEIRS.
|
// THEIRS. THEIRS is chosen.
|
||||||
if (nonTree(modeT)) {
|
if (nonTree(modeT)) {
|
||||||
DirCacheEntry e = add(tw.getRawPath(), theirs,
|
DirCacheEntry e = add(tw.getRawPath(), theirs,
|
||||||
DirCacheEntry.STAGE_0);
|
DirCacheEntry.STAGE_0);
|
||||||
if (e != null)
|
if (e != null)
|
||||||
toBeCheckedOut.put(tw.getPathString(), e);
|
toBeCheckedOut.put(tw.getPathString(), e);
|
||||||
return true;
|
return true;
|
||||||
} else if ((modeT == 0) && (modeB != 0)) {
|
} else if (modeT == 0 && modeB != 0) {
|
||||||
// we want THEIRS ... but THEIRS contains the deletion of the
|
// we want THEIRS ... but THEIRS contains the deletion of the
|
||||||
// file
|
// file
|
||||||
toBeCheckedOut.put(tw.getPathString(), null);
|
toBeCheckedOut.put(tw.getPathString(), null);
|
||||||
|
@ -441,18 +441,9 @@ private boolean processEntry(CanonicalTreeParser base,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nonTree(modeO) && nonTree(modeT)) {
|
if (nonTree(modeO) && nonTree(modeT)) {
|
||||||
if (!inCore) {
|
// Check worktree before modifying files
|
||||||
// We are going to update the worktree. Make sure the worktree
|
if (isWorktreeDirty())
|
||||||
// is not modified
|
return false;
|
||||||
if (work != null
|
|
||||||
&& (!nonTree(work.getEntryRawMode()) || work
|
|
||||||
.isModified(index.getDirCacheEntry(), true))) {
|
|
||||||
failingPaths.put(tw.getPathString(),
|
|
||||||
MergeFailureReason.DIRTY_WORKTREE);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!contentMerge(base, ours, theirs)) {
|
if (!contentMerge(base, ours, theirs)) {
|
||||||
unmergedPaths.add(tw.getPathString());
|
unmergedPaths.add(tw.getPathString());
|
||||||
}
|
}
|
||||||
|
@ -461,6 +452,35 @@ private boolean processEntry(CanonicalTreeParser base,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isIndexDirty() {
|
||||||
|
final int modeI = tw.getRawMode(T_INDEX);
|
||||||
|
final int modeO = tw.getRawMode(T_OURS);
|
||||||
|
|
||||||
|
// Index entry has to match ours to be considered clean
|
||||||
|
final boolean isDirty = nonTree(modeI)
|
||||||
|
&& !(tw.idEqual(T_INDEX, T_OURS) && modeO == modeI);
|
||||||
|
if (isDirty)
|
||||||
|
failingPaths
|
||||||
|
.put(tw.getPathString(), MergeFailureReason.DIRTY_INDEX);
|
||||||
|
return isDirty;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isWorktreeDirty() {
|
||||||
|
if (inCore)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
final int modeF = tw.getRawMode(T_FILE);
|
||||||
|
final int modeO = tw.getRawMode(T_OURS);
|
||||||
|
|
||||||
|
// Worktree entry has to match ours to be considered clean
|
||||||
|
final boolean isDirty = nonTree(modeF)
|
||||||
|
&& !(tw.idEqual(T_FILE, T_OURS) && modeO == modeF);
|
||||||
|
if (isDirty)
|
||||||
|
failingPaths.put(tw.getPathString(),
|
||||||
|
MergeFailureReason.DIRTY_WORKTREE);
|
||||||
|
return isDirty;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean contentMerge(CanonicalTreeParser base,
|
private boolean contentMerge(CanonicalTreeParser base,
|
||||||
CanonicalTreeParser ours, CanonicalTreeParser theirs)
|
CanonicalTreeParser ours, CanonicalTreeParser theirs)
|
||||||
throws FileNotFoundException, IllegalStateException, IOException {
|
throws FileNotFoundException, IllegalStateException, IOException {
|
||||||
|
|
Loading…
Reference in New Issue