diff mercurial/filemerge.py @ 21519:25d5a9ecbb85

merge: add conflict marker formatter (BC) Adds a conflict marker formatter that can produce custom conflict marker descriptions. It can be set via ui.mergemarkertemplate. The old behavior can be used still by setting ui.mergemarkers=basic. The default format is similar to: {node|short} {tag} {branch} {bookmarks} - {author}: "{desc|firstline}" And renders as: contextblahblah <<<<<<< local: c7fdd7ce4652 - durham: "Fix broken stuff in my feature branch" line from my changes ======= line from the other changes >>>>>>> other: a3e55d7f4d38 master - sid0: "This is a commit to master th... morecontextblahblah
author Durham Goode <durham@fb.com>
date Thu, 08 May 2014 16:50:22 -0700
parents 20b8090d8125
children 47b97d9af27e
line wrap: on
line diff
--- a/mercurial/filemerge.py	Tue Apr 22 12:20:10 2014 -0700
+++ b/mercurial/filemerge.py	Thu May 08 16:50:22 2014 -0700
@@ -7,7 +7,7 @@
 
 from node import short
 from i18n import _
-import util, simplemerge, match, error
+import util, simplemerge, match, error, templater, templatekw
 import os, tempfile, re, filecmp
 
 def _toolstr(ui, tool, part, default=""):
@@ -269,6 +269,55 @@
         return True, r
     return False, 0
 
+def _formatconflictmarker(repo, ctx, template, label, pad):
+    """Applies the given template to the ctx, prefixed by the label.
+
+    Pad is the minimum width of the label prefix, so that multiple markers
+    can have aligned templated parts.
+    """
+    if ctx.node() is None:
+        ctx = ctx.p1()
+
+    props = templatekw.keywords.copy()
+    props['templ'] = template
+    props['ctx'] = ctx
+    props['repo'] = repo
+    templateresult = template('conflictmarker', **props)
+
+    label = ('%s:' % label).ljust(pad + 1)
+    mark = '%s %s' % (label, templater.stringify(templateresult))
+
+    # The <<< marks add 8 to the length, and '...' adds three, so max
+    # length of the actual marker is 69.
+    maxlength = 80 - 8 - 3
+    if len(mark) > maxlength:
+        mark = mark[:maxlength] + '...'
+    return mark
+
+_defaultconflictmarker = ('{node|short} ' +
+    '{ifeq(tags, "tip", "", "{tags} ")}' +
+    '{if(bookmarks, "{bookmarks} ")}' +
+    '{ifeq(branch, "default", "", "{branch} ")}' +
+    '- {author|user}: "{desc|firstline}"')
+
+def _formatlabels(repo, fcd, fco, labels):
+    """Formats the given labels using the conflict marker template.
+
+    Returns a list of formatted labels.
+    """
+    cd = fcd.changectx()
+    co = fco.changectx()
+
+    ui = repo.ui
+    template = ui.config('ui', 'mergemarkertemplate', _defaultconflictmarker)
+    template = templater.parsestring(template, quoted=False)
+    tmpl = templater.templater(None, cache={ 'conflictmarker' : template })
+
+    pad = max(len(labels[0]), len(labels[1]))
+
+    return [_formatconflictmarker(repo, cd, tmpl, labels[0], pad),
+            _formatconflictmarker(repo, co, tmpl, labels[1], pad)]
+
 def filemerge(repo, mynode, orig, fcd, fco, fca):
     """perform a 3-way merge in the working directory
 
@@ -326,9 +375,15 @@
 
     ui.debug("my %s other %s ancestor %s\n" % (fcd, fco, fca))
 
+    markerstyle = ui.config('ui', 'mergemarkers', 'detailed')
     labels = ['local', 'other']
+    if markerstyle == 'basic':
+        formattedlabels = labels
+    else:
+        formattedlabels = _formatlabels(repo, fcd, fco, labels)
+
     needcheck, r = func(repo, mynode, orig, fcd, fco, fca, toolconf,
-                        (a, b, c, back), labels=labels)
+                        (a, b, c, back), labels=formattedlabels)
     if not needcheck:
         if r:
             if onfailure: