|
|
@ -59,10 +59,10 @@ import java.util.Map; |
|
|
|
|
|
|
|
|
|
|
|
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 @@ public class ResolveMerger extends ThreeWayMerger { |
|
|
|
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); |
|
|
|
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; |
|
|
|
|
|
|
|
|
|
|
|
// Each index entry has to match ours, means: it has to be clean
|
|
|
|
if (isIndexDirty()) |
|
|
|
if (nonTree(modeI) |
|
|
|
|
|
|
|
&& !(tw.idEqual(T_INDEX, T_OURS) && modeO == modeI)) { |
|
|
|
|
|
|
|
failingPaths.put(tw.getPathString(), MergeFailureReason.DIRTY_INDEX); |
|
|
|
|
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
final int modeT = tw.getRawMode(T_THEIRS); |
|
|
|
|
|
|
|
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 @@ public class ResolveMerger extends ThreeWayMerger { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
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 @@ public class ResolveMerger extends ThreeWayMerger { |
|
|
|
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 { |
|
|
|