]> source.dussan.org Git - jgit.git/commitdiff
Optimize MergeAlgorithm if ours or theirs is empty 10/3410/3
authorChristian Halstrick <christian.halstrick@sap.com>
Tue, 17 May 2011 08:59:17 +0000 (10:59 +0200)
committerChristian Halstrick <christian.halstrick@sap.com>
Tue, 17 May 2011 08:59:17 +0000 (10:59 +0200)
Previously when merging two contents with a non-empty base and one of
the contents was empty (size == 0) and the other was modified there
was a potentially expensive calculation until we finally always come
to the same result -> the complete non-deleted content should collide
with the empty content.

This proposal adds an optimization to detect empty input content and
to produce the appropriate result immediatly.

Change-Id: Ie6a837260c19d808f0e99173f570ff96dd22acd3
Signed-off-by: Christian Halstrick <christian.halstrick@sap.com>
org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/MergeAlgorithmTest.java
org.eclipse.jgit/src/org/eclipse/jgit/merge/MergeAlgorithm.java

index aa8f8281e480213a3e0556e813fbf25a3e5f3fa6..8a33425b1dd09cc095ae77bba153ae5d33241145 100644 (file)
@@ -198,6 +198,25 @@ public class MergeAlgorithmTest {
 
        }
 
+       /**
+        * Test situations where (at least) one input value is the empty text
+        *
+        * @throws IOException
+        */
+       @Test
+       public void testEmptyTexts() throws IOException {
+               // test modification against deletion
+               assertEquals(t("<AB=>"), merge("A", "AB", ""));
+               assertEquals(t("<=AB>"), merge("A", "", "AB"));
+
+               // test unmodified against deletion
+               assertEquals(t(""), merge("AB", "AB", ""));
+               assertEquals(t(""), merge("AB", "", "AB"));
+
+               // test deletion against deletion
+               assertEquals(t(""), merge("AB", "", ""));
+       }
+
        private String merge(String commonBase, String ours, String theirs) throws IOException {
                MergeResult r = new MergeAlgorithm().merge(RawTextComparator.DEFAULT,
                                T(commonBase), T(ours), T(theirs));
@@ -231,5 +250,4 @@ public class MergeAlgorithmTest {
        public static RawText T(String text) {
                return new RawText(Constants.encode(t(text)));
        }
-
 }
index e6688f5bc97a168b07d360a1b74600e899200e3a..112550a1de8500a9508744f6bbf9e0c1c7ae59e2 100644 (file)
@@ -103,6 +103,37 @@ public final class MergeAlgorithm {
                sequences.add(ours);
                sequences.add(theirs);
                MergeResult<S> result = new MergeResult<S>(sequences);
+
+               if (ours.size() == 0) {
+                       if (theirs.size() != 0) {
+                               EditList theirsEdits = diffAlg.diff(cmp, base, theirs);
+                               if (!theirsEdits.isEmpty()) {
+                                       // we deleted, they modified -> Let their complete content
+                                       // conflict with empty text
+                                       result.add(1, 0, 0, ConflictState.FIRST_CONFLICTING_RANGE);
+                                       result.add(2, 0, theirs.size(),
+                                                       ConflictState.NEXT_CONFLICTING_RANGE);
+                               } else
+                                       // we deleted, they didn't modify -> Let our deletion win
+                                       result.add(1, 0, 0, ConflictState.NO_CONFLICT);
+                       } else
+                               // we and they deleted -> return a single chunk of nothing
+                               result.add(1, 0, 0, ConflictState.NO_CONFLICT);
+                       return result;
+               } else if (theirs.size() == 0) {
+                       EditList oursEdits = diffAlg.diff(cmp, base, ours);
+                       if (!oursEdits.isEmpty()) {
+                               // we modified, they deleted -> Let our complete content
+                               // conflict with empty text
+                               result.add(1, 0, ours.size(),
+                                               ConflictState.FIRST_CONFLICTING_RANGE);
+                               result.add(2, 0, 0, ConflictState.NEXT_CONFLICTING_RANGE);
+                       } else
+                               // they deleted, we didn't modify -> Let their deletion win
+                               result.add(2, 0, 0, ConflictState.NO_CONFLICT);
+                       return result;
+               }
+
                EditList oursEdits = diffAlg.diff(cmp, base, ours);
                Iterator<Edit> baseToOurs = oursEdits.iterator();
                EditList theirsEdits = diffAlg.diff(cmp, base, theirs);