mercurial/simplemerge.py
changeset 46108 bdc2bf68f19e
parent 46100 a771ffc378a8
child 46113 59fa3890d40a
--- a/mercurial/simplemerge.py	Thu Dec 10 14:39:22 2020 -0800
+++ b/mercurial/simplemerge.py	Tue Dec 08 16:45:13 2020 -0800
@@ -455,6 +455,68 @@
     return ctx.node() != nodemod.nullid
 
 
+def _mergediff(m3, name_a, name_b, name_base):
+    lines = []
+    conflicts = False
+    for group in m3.merge_groups():
+        if group[0] == b'conflict':
+            base_lines, a_lines, b_lines = group[1:]
+            base_text = b''.join(base_lines)
+            b_blocks = list(
+                mdiff.allblocks(
+                    base_text,
+                    b''.join(b_lines),
+                    lines1=base_lines,
+                    lines2=b_lines,
+                )
+            )
+            a_blocks = list(
+                mdiff.allblocks(
+                    base_text,
+                    b''.join(a_lines),
+                    lines1=base_lines,
+                    lines2=b_lines,
+                )
+            )
+
+            def matching_lines(blocks):
+                return sum(
+                    block[1] - block[0]
+                    for block, kind in blocks
+                    if kind == b'='
+                )
+
+            def diff_lines(blocks, lines1, lines2):
+                for block, kind in blocks:
+                    if kind == b'=':
+                        for line in lines1[block[0] : block[1]]:
+                            yield b' ' + line
+                    else:
+                        for line in lines1[block[0] : block[1]]:
+                            yield b'-' + line
+                        for line in lines2[block[2] : block[3]]:
+                            yield b'+' + line
+
+            lines.append(b"<<<<<<<\n")
+            if matching_lines(a_blocks) < matching_lines(b_blocks):
+                lines.append(b"======= %s\n" % name_a)
+                lines.extend(a_lines)
+                lines.append(b"------- %s\n" % name_base)
+                lines.append(b"+++++++ %s\n" % name_b)
+                lines.extend(diff_lines(b_blocks, base_lines, b_lines))
+            else:
+                lines.append(b"------- %s\n" % name_base)
+                lines.append(b"+++++++ %s\n" % name_a)
+                lines.extend(diff_lines(a_blocks, base_lines, a_lines))
+                lines.append(b"======= %s\n" % name_b)
+                lines.extend(b_lines)
+            lines.append(b">>>>>>>\n")
+            conflicts = True
+        else:
+            lines.extend(group[1])
+    return lines, conflicts
+
+
 def simplemerge(ui, localctx, basectx, otherctx, **opts):
     """Performs the simplemerge algorithm.
 
@@ -499,9 +561,15 @@
         extrakwargs[b'name_base'] = name_base
         extrakwargs[b'minimize'] = False
 
-    lines = m3.merge_lines(
-        name_a=name_a, name_b=name_b, **pycompat.strkwargs(extrakwargs)
-    )
+    if mode == b'mergediff':
+        lines, conflicts = _mergediff(m3, name_a, name_b, name_base)
+    else:
+        lines = list(
+            m3.merge_lines(
+                name_a=name_a, name_b=name_b, **pycompat.strkwargs(extrakwargs)
+            )
+        )
+        conflicts = m3.conflicts
 
     # merge flags if necessary
     flags = localctx.flags()
@@ -519,5 +587,5 @@
     else:
         localctx.write(mergedtext, flags)
 
-    if m3.conflicts and not mode == b'union':
+    if conflicts and not mode == b'union':
         return 1