simplemerge: make merge_lines() a free function
IMO, the rendering of a conflict as text with merge markers should be
separate from the code for resolving conflicts. The latter is what
`Merge3Text` is mostly about already.
Differential Revision: https://phab.mercurial-scm.org/D11974
--- a/mercurial/debugcommands.py Fri Jan 07 18:42:31 2022 -0800
+++ b/mercurial/debugcommands.py Fri Jan 07 22:16:22 2022 -0800
@@ -272,7 +272,7 @@
x[fn].data() for x in (pa, p1, p2)
]
m3 = simplemerge.Merge3Text(base, local, other)
- ml = [l.strip() for l in m3.merge_lines()[0]]
+ ml = [l.strip() for l in simplemerge.merge_lines(m3)[0]]
ml.append(b"")
elif at > 0:
ml = p1[fn].data().split(b"\n")
--- a/mercurial/simplemerge.py Fri Jan 07 18:42:31 2022 -0800
+++ b/mercurial/simplemerge.py Fri Jan 07 22:16:22 2022 -0800
@@ -87,54 +87,6 @@
self.a = a
self.b = b
- def merge_lines(
- self,
- name_a=None,
- name_b=None,
- name_base=None,
- start_marker=b'<<<<<<<',
- mid_marker=b'=======',
- end_marker=b'>>>>>>>',
- base_marker=None,
- minimize=False,
- ):
- """Return merge in cvs-like form."""
- conflicts = False
- newline = b'\n'
- if len(self.a) > 0:
- if self.a[0].endswith(b'\r\n'):
- newline = b'\r\n'
- elif self.a[0].endswith(b'\r'):
- newline = b'\r'
- if name_a and start_marker:
- start_marker = start_marker + b' ' + name_a
- if name_b and end_marker:
- end_marker = end_marker + b' ' + name_b
- if name_base and base_marker:
- base_marker = base_marker + b' ' + name_base
- merge_groups = self.merge_groups()
- if minimize:
- merge_groups = self.minimize(merge_groups)
- lines = []
- for what, group_lines in merge_groups:
- if what == b'conflict':
- base_lines, a_lines, b_lines = group_lines
- conflicts = True
- if start_marker is not None:
- lines.append(start_marker + newline)
- lines.extend(a_lines)
- if base_marker is not None:
- lines.append(base_marker + newline)
- lines.extend(base_lines)
- if mid_marker is not None:
- lines.append(mid_marker + newline)
- lines.extend(b_lines)
- if end_marker is not None:
- lines.append(end_marker + newline)
- else:
- lines.extend(group_lines)
- return lines, conflicts
-
def merge_groups(self):
"""Yield sequence of line groups. Each one is a tuple:
@@ -389,6 +341,55 @@
return result
+def merge_lines(
+ m3,
+ name_a=None,
+ name_b=None,
+ name_base=None,
+ start_marker=b'<<<<<<<',
+ mid_marker=b'=======',
+ end_marker=b'>>>>>>>',
+ base_marker=None,
+ minimize=False,
+):
+ """Return merge in cvs-like form."""
+ conflicts = False
+ newline = b'\n'
+ if len(m3.a) > 0:
+ if m3.a[0].endswith(b'\r\n'):
+ newline = b'\r\n'
+ elif m3.a[0].endswith(b'\r'):
+ newline = b'\r'
+ if name_a and start_marker:
+ start_marker = start_marker + b' ' + name_a
+ if name_b and end_marker:
+ end_marker = end_marker + b' ' + name_b
+ if name_base and base_marker:
+ base_marker = base_marker + b' ' + name_base
+ merge_groups = m3.merge_groups()
+ if minimize:
+ merge_groups = m3.minimize(merge_groups)
+ lines = []
+ for what, group_lines in merge_groups:
+ if what == b'conflict':
+ base_lines, a_lines, b_lines = group_lines
+ conflicts = True
+ if start_marker is not None:
+ lines.append(start_marker + newline)
+ lines.extend(a_lines)
+ if base_marker is not None:
+ lines.append(base_marker + newline)
+ lines.extend(base_lines)
+ if mid_marker is not None:
+ lines.append(mid_marker + newline)
+ lines.extend(b_lines)
+ if end_marker is not None:
+ lines.append(end_marker + newline)
+ else:
+ lines.extend(group_lines)
+ return lines, conflicts
+
+
def _mergediff(m3, name_a, name_b, name_base):
lines = []
conflicts = False
@@ -508,8 +509,8 @@
extrakwargs['base_marker'] = b'|||||||'
extrakwargs['name_base'] = name_base
extrakwargs['minimize'] = False
- lines, conflicts = m3.merge_lines(
- name_a=name_a, name_b=name_b, **extrakwargs
+ lines, conflicts = merge_lines(
+ m3, name_a=name_a, name_b=name_b, **extrakwargs
)
mergedtext = b''.join(lines)
--- a/tests/test-simplemerge.py Fri Jan 07 18:42:31 2022 -0800
+++ b/tests/test-simplemerge.py Fri Jan 07 22:16:22 2022 -0800
@@ -179,7 +179,7 @@
self.assertEqual(list(m3.merge_regions()), [(b'a', 0, 2)])
- self.assertEqual(m3.merge_lines(), ([b'aaa', b'bbb'], False))
+ self.assertEqual(simplemerge.merge_lines(m3), ([b'aaa', b'bbb'], False))
def test_no_conflicts(self):
"""No conflicts because only one side changed"""
@@ -204,7 +204,9 @@
[b'aaa\n', b'bbb\n'],
)
- self.assertEqual(b''.join(m3.merge_lines()[0]), b'aaa\nbbb\n222\n')
+ self.assertEqual(
+ b''.join(simplemerge.merge_lines(m3)[0]), b'aaa\nbbb\n222\n'
+ )
def test_append_b(self):
m3 = Merge3(
@@ -213,7 +215,9 @@
[b'aaa\n', b'bbb\n', b'222\n'],
)
- self.assertEqual(b''.join(m3.merge_lines()[0]), b'aaa\nbbb\n222\n')
+ self.assertEqual(
+ b''.join(simplemerge.merge_lines(m3)[0]), b'aaa\nbbb\n222\n'
+ )
def test_append_agreement(self):
m3 = Merge3(
@@ -222,7 +226,9 @@
[b'aaa\n', b'bbb\n', b'222\n'],
)
- self.assertEqual(b''.join(m3.merge_lines()[0]), b'aaa\nbbb\n222\n')
+ self.assertEqual(
+ b''.join(simplemerge.merge_lines(m3)[0]), b'aaa\nbbb\n222\n'
+ )
def test_append_clash(self):
m3 = Merge3(
@@ -231,7 +237,8 @@
[b'aaa\n', b'bbb\n', b'333\n'],
)
- ml, conflicts = m3.merge_lines(
+ ml, conflicts = simplemerge.merge_lines(
+ m3,
name_a=b'a',
name_b=b'b',
start_marker=b'<<',
@@ -250,7 +257,8 @@
[b'aaa\n', b'222\n', b'bbb\n'],
)
- ml, conflicts = m3.merge_lines(
+ ml, conflicts = simplemerge.merge_lines(
+ m3,
name_a=b'a',
name_b=b'b',
start_marker=b'<<',
@@ -290,7 +298,8 @@
],
)
- ml, conflicts = m3.merge_lines(
+ ml, conflicts = simplemerge.merge_lines(
+ m3,
name_a=b'a',
name_b=b'b',
start_marker=b'<<',
@@ -338,7 +347,7 @@
def test_merge_poem(self):
"""Test case from diff3 manual"""
m3 = Merge3(TZU, LAO, TAO)
- ml, conflicts = m3.merge_lines(b'LAO', b'TAO')
+ ml, conflicts = simplemerge.merge_lines(m3, b'LAO', b'TAO')
self.log(b'merge result:')
self.log(b''.join(ml))
self.assertEqual(ml, MERGED_RESULT)
@@ -356,7 +365,7 @@
other_text.splitlines(True),
this_text.splitlines(True),
)
- m_lines, conflicts = m3.merge_lines(b'OTHER', b'THIS')
+ m_lines, conflicts = simplemerge.merge_lines(m3, b'OTHER', b'THIS')
self.assertEqual(
b'<<<<<<< OTHER\r\nc\r\n=======\r\nb\r\n'
b'>>>>>>> THIS\r\n'.splitlines(True),
@@ -372,7 +381,7 @@
other_text.splitlines(True),
this_text.splitlines(True),
)
- m_lines, conflicts = m3.merge_lines(b'OTHER', b'THIS')
+ m_lines, conflicts = simplemerge.merge_lines(m3, b'OTHER', b'THIS')
self.assertEqual(
b'<<<<<<< OTHER\rc\r=======\rb\r'
b'>>>>>>> THIS\r'.splitlines(True),