simplemerge: rewrite `merge_lines()` using `merge_groups()`
authorMartin von Zweigbergk <martinvonz@google.com>
Wed, 05 Jan 2022 11:34:54 -0800
changeset 48548 88a45330b290
parent 48547 374bf34c9ffd
child 48549 28f0092ec89f
simplemerge: rewrite `merge_lines()` using `merge_groups()` Simple is better. Differential Revision: https://phab.mercurial-scm.org/D11967
mercurial/simplemerge.py
--- a/mercurial/simplemerge.py	Thu Jan 06 09:03:17 2022 -0800
+++ b/mercurial/simplemerge.py	Wed Jan 05 11:34:54 2022 -0800
@@ -112,38 +112,30 @@
             end_marker = end_marker + b' ' + name_b
         if name_base and base_marker:
             base_marker = base_marker + b' ' + name_base
-        merge_regions = self.merge_regions()
+        merge_groups = self.merge_groups()
         if minimize:
-            merge_regions = self.minimize(merge_regions)
-        for t in merge_regions:
-            what = t[0]
-            if what == b'unchanged':
-                for i in range(t[1], t[2]):
-                    yield self.base[i]
-            elif what == b'a' or what == b'same':
-                for i in range(t[1], t[2]):
-                    yield self.a[i]
-            elif what == b'b':
-                for i in range(t[1], t[2]):
-                    yield self.b[i]
-            elif what == b'conflict':
+            merge_groups = self.minimize(merge_groups)
+        for what, lines in merge_groups:
+            if what == b'conflict':
+                base_lines, a_lines, b_lines = lines
                 self.conflicts = True
                 if start_marker is not None:
                     yield start_marker + newline
-                for i in range(t[3], t[4]):
-                    yield self.a[i]
+                for line in a_lines:
+                    yield line
                 if base_marker is not None:
                     yield base_marker + newline
-                    for i in range(t[1], t[2]):
-                        yield self.base[i]
+                    for line in base_lines:
+                        yield line
                 if mid_marker is not None:
                     yield mid_marker + newline
-                for i in range(t[5], t[6]):
-                    yield self.b[i]
+                for line in b_lines:
+                    yield line
                 if end_marker is not None:
                     yield end_marker + newline
             else:
-                raise ValueError(what)
+                for line in lines:
+                    yield line
 
     def merge_groups(self):
         """Yield sequence of line groups.  Each one is a tuple:
@@ -272,66 +264,49 @@
                 ia = aend
                 ib = bend
 
-    def minimize(self, merge_regions):
+    def minimize(self, merge_groups):
         """Trim conflict regions of lines where A and B sides match.
 
         Lines where both A and B have made the same changes at the beginning
         or the end of each merge region are eliminated from the conflict
         region and are instead considered the same.
         """
-        for region in merge_regions:
-            if region[0] != b"conflict":
-                yield region
+        for what, lines in merge_groups:
+            if what != b"conflict":
+                yield what, lines
                 continue
-            # pytype thinks this tuple contains only 3 things, but
-            # that's clearly not true because this code successfully
-            # executes. It might be wise to rework merge_regions to be
-            # some kind of attrs type.
-            (
-                issue,
-                z1,
-                z2,
-                a1,
-                a2,
-                b1,
-                b2,
-            ) = region  # pytype: disable=bad-unpacking
-            alen = a2 - a1
-            blen = b2 - b1
+            base_lines, a_lines, b_lines = lines
+            alen = len(a_lines)
+            blen = len(b_lines)
 
             # find matches at the front
             ii = 0
-            while (
-                ii < alen and ii < blen and self.a[a1 + ii] == self.b[b1 + ii]
-            ):
+            while ii < alen and ii < blen and a_lines[ii] == b_lines[ii]:
                 ii += 1
             startmatches = ii
 
             # find matches at the end
             ii = 0
             while (
-                ii < alen
-                and ii < blen
-                and self.a[a2 - ii - 1] == self.b[b2 - ii - 1]
+                ii < alen and ii < blen and a_lines[-ii - 1] == b_lines[-ii - 1]
             ):
                 ii += 1
             endmatches = ii
 
             if startmatches > 0:
-                yield b'same', a1, a1 + startmatches
+                yield b'same', a_lines[:startmatches]
 
             yield (
                 b'conflict',
-                z1,
-                z2,
-                a1 + startmatches,
-                a2 - endmatches,
-                b1 + startmatches,
-                b2 - endmatches,
+                (
+                    base_lines,
+                    a_lines[startmatches : alen - endmatches],
+                    b_lines[startmatches : blen - endmatches],
+                ),
             )
 
             if endmatches > 0:
-                yield b'same', a2 - endmatches, a2
+                yield b'same', a_lines[alen - endmatches :]
 
     def find_sync_regions(self):
         """Return a list of sync regions, where both descendants match the base.