Fixed Merge Algorithm regarding concurrent file creations
When in OURS and THEIRS a new file is created we want a conflict when the two contents differ. If on two branches the same file with the same content is created this should not be a conflict. But: the current merge algorithm is throwing NPEs in this case. Fix this by choosing an empty RawText as common base if the base is empty. Change-Id: I21cb23f852965b82fb82ccd66ec961c7edb3ac3d Signed-off-by: Christian Halstrick <christian.halstrick@sap.com>
This commit is contained in:
parent
d29b5db695
commit
deabacc420
|
@ -247,6 +247,57 @@ public void testMergeNonVersionedPaths() throws Exception {
|
|||
assertEquals(RepositoryState.MERGING, db.getRepositoryState());
|
||||
}
|
||||
|
||||
public void testMultipleCreations() throws Exception {
|
||||
Git git = new Git(db);
|
||||
|
||||
writeTrashFile("a", "1\na\n3\n");
|
||||
git.add().addFilepattern("a").call();
|
||||
RevCommit initialCommit = git.commit().setMessage("initial").call();
|
||||
|
||||
createBranch(initialCommit, "refs/heads/side");
|
||||
checkoutBranch("refs/heads/side");
|
||||
|
||||
writeTrashFile("b", "1\nb(side)\n3\n");
|
||||
git.add().addFilepattern("b").call();
|
||||
RevCommit secondCommit = git.commit().setMessage("side").call();
|
||||
|
||||
checkoutBranch("refs/heads/master");
|
||||
|
||||
writeTrashFile("b", "1\nb(main)\n3\n");
|
||||
git.add().addFilepattern("b").call();
|
||||
git.commit().setMessage("main").call();
|
||||
|
||||
MergeResult result = git.merge().include(secondCommit.getId())
|
||||
.setStrategy(MergeStrategy.RESOLVE).call();
|
||||
assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
|
||||
}
|
||||
|
||||
public void testMultipleCreationsSameContent() throws Exception {
|
||||
Git git = new Git(db);
|
||||
|
||||
writeTrashFile("a", "1\na\n3\n");
|
||||
git.add().addFilepattern("a").call();
|
||||
RevCommit initialCommit = git.commit().setMessage("initial").call();
|
||||
|
||||
createBranch(initialCommit, "refs/heads/side");
|
||||
checkoutBranch("refs/heads/side");
|
||||
|
||||
writeTrashFile("b", "1\nb(1)\n3\n");
|
||||
git.add().addFilepattern("b").call();
|
||||
RevCommit secondCommit = git.commit().setMessage("side").call();
|
||||
|
||||
checkoutBranch("refs/heads/master");
|
||||
|
||||
writeTrashFile("b", "1\nb(1)\n3\n");
|
||||
git.add().addFilepattern("b").call();
|
||||
git.commit().setMessage("main").call();
|
||||
|
||||
MergeResult result = git.merge().include(secondCommit.getId())
|
||||
.setStrategy(MergeStrategy.RESOLVE).call();
|
||||
assertEquals(MergeStatus.MERGED, result.getMergeStatus());
|
||||
assertEquals("1\nb(1)\n3\n", read(new File(db.getWorkTree(), "b")));
|
||||
}
|
||||
|
||||
public void testSuccessfulContentMerge() throws Exception {
|
||||
Git git = new Git(db);
|
||||
|
||||
|
@ -415,6 +466,34 @@ public void testSingleDeletion() throws Exception {
|
|||
read(new File(db.getWorkTree(), "c/c/c")));
|
||||
}
|
||||
|
||||
public void testMultipleDeletions() throws Exception {
|
||||
Git git = new Git(db);
|
||||
|
||||
writeTrashFile("a", "1\na\n3\n");
|
||||
git.add().addFilepattern("a").call();
|
||||
RevCommit initialCommit = git.commit().setMessage("initial").call();
|
||||
|
||||
createBranch(initialCommit, "refs/heads/side");
|
||||
checkoutBranch("refs/heads/side");
|
||||
|
||||
assertTrue(new File(db.getWorkTree(), "a").delete());
|
||||
git.add().addFilepattern("a").setUpdate(true).call();
|
||||
RevCommit secondCommit = git.commit().setMessage("side").call();
|
||||
|
||||
assertFalse(new File(db.getWorkTree(), "a").exists());
|
||||
checkoutBranch("refs/heads/master");
|
||||
assertTrue(new File(db.getWorkTree(), "a").exists());
|
||||
|
||||
assertTrue(new File(db.getWorkTree(), "a").delete());
|
||||
git.add().addFilepattern("a").setUpdate(true).call();
|
||||
git.commit().setMessage("main").call();
|
||||
|
||||
// We are merging a deletion into our branch
|
||||
MergeResult result = git.merge().include(secondCommit.getId())
|
||||
.setStrategy(MergeStrategy.RESOLVE).call();
|
||||
assertEquals(MergeStatus.MERGED, result.getMergeStatus());
|
||||
}
|
||||
|
||||
public void testDeletionAndConflict() throws Exception {
|
||||
Git git = new Git(db);
|
||||
|
||||
|
|
|
@ -66,6 +66,9 @@
|
|||
* they are converting from "line number" to "element index".
|
||||
*/
|
||||
public class RawText extends Sequence {
|
||||
/** A Rawtext of length 0 */
|
||||
public static final RawText EMPTY_TEXT = new RawText(new byte[0]);
|
||||
|
||||
/** Number of bytes to check for heuristics in {@link #isBinary(byte[])} */
|
||||
private static final int FIRST_FEW_BYTES = 8000;
|
||||
|
||||
|
|
|
@ -467,10 +467,12 @@ private boolean contentMerge(CanonicalTreeParser base,
|
|||
throws FileNotFoundException, IllegalStateException, IOException {
|
||||
MergeFormatter fmt = new MergeFormatter();
|
||||
|
||||
RawText baseText = base == null ? RawText.EMPTY_TEXT : getRawText(
|
||||
base.getEntryObjectId(), db);
|
||||
|
||||
// do the merge
|
||||
MergeResult<RawText> result = mergeAlgorithm.merge(
|
||||
RawTextComparator.DEFAULT,
|
||||
getRawText(base.getEntryObjectId(), db),
|
||||
MergeResult<RawText> result = MergeAlgorithm.merge(
|
||||
RawTextComparator.DEFAULT, baseText,
|
||||
getRawText(ours.getEntryObjectId(), db),
|
||||
getRawText(theirs.getEntryObjectId(), db));
|
||||
|
||||
|
|
Loading…
Reference in New Issue