diff --git a/mercurial/configitems.py b/mercurial/configitems.py --- a/mercurial/configitems.py +++ b/mercurial/configitems.py @@ -1193,6 +1193,9 @@ coreconfigitem('ui', 'paginate', coreconfigitem('ui', 'patch', default=None, ) +coreconfigitem('ui', 'pre-merge-tool-output-template', + default=None, +) coreconfigitem('ui', 'portablefilenames', default='warn', ) diff --git a/mercurial/filemerge.py b/mercurial/filemerge.py --- a/mercurial/filemerge.py +++ b/mercurial/filemerge.py @@ -13,7 +13,11 @@ import re import shutil from .i18n import _ -from .node import nullid, short +from .node import ( + hex, + nullid, + short, +) from . import ( encoding, @@ -27,6 +31,7 @@ from . import ( tagmerge, templatekw, templater, + templateutil, util, ) @@ -536,6 +541,44 @@ def _xmergeimm(repo, mynode, orig, fcd, raise error.InMemoryMergeConflictsError('in-memory merge does not support ' 'external merge tools') +def _describemerge(ui, repo, mynode, fcl, fcb, fco, env, toolpath, args): + tmpl = ui.config('ui', 'pre-merge-tool-output-template') + if not tmpl: + return + + mappingdict = templateutil.mappingdict + props = {'ctx': fcl.changectx(), + 'node': hex(mynode), + 'path': fcl.path(), + 'local': mappingdict({'ctx': fcl.changectx(), + 'fctx': fcl, + 'node': hex(mynode), + 'name': _('local'), + 'islink': 'l' in fcl.flags(), + 'label': env['HG_MY_LABEL']}), + 'base': mappingdict({'ctx': fcb.changectx(), + 'fctx': fcb, + 'name': _('base'), + 'islink': 'l' in fcb.flags(), + 'label': env['HG_BASE_LABEL']}), + 'other': mappingdict({'ctx': fco.changectx(), + 'fctx': fco, + 'name': _('other'), + 'islink': 'l' in fco.flags(), + 'label': env['HG_OTHER_LABEL']}), + 'toolpath': toolpath, + 'toolargs': args} + + # TODO: make all of this something that can be specified on a per-tool basis + tmpl = templater.unquotestring(tmpl) + + # Not using cmdutil.rendertemplate here since it causes errors importing + # things for us to import cmdutil. + tres = formatter.templateresources(ui, repo) + t = formatter.maketemplater(ui, tmpl, defaults=templatekw.keywords, + resources=tres) + ui.status(t.renderdefault(props)) + def _xmerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None): tool, toolpath, binary, symlink, scriptfn = toolconf if fcd.isabsent() or fco.isabsent(): @@ -584,6 +627,7 @@ def _xmerge(repo, mynode, orig, fcd, fco if scriptfn is None: cmd = toolpath + ' ' + args repo.ui.debug('launching merge tool: %s\n' % cmd) + _describemerge(ui, repo, mynode, fcd, fca, fco, env, toolpath, args) r = ui.system(cmd, cwd=repo.root, environ=env, blockedtag='mergetool') else: diff --git a/mercurial/help/config.txt b/mercurial/help/config.txt --- a/mercurial/help/config.txt +++ b/mercurial/help/config.txt @@ -2296,6 +2296,16 @@ User interface controls. On Windows, this configuration option is ignored and the command aborted. +``pre-merge-tool-output-template`` + A template that is printed before executing an external merge tool. This can + be used to print out additional context that might be useful to have during + the conflict resolution, such as the description of the various commits + involved or bookmarks/tags. + + Additional information is available in the ``local`, ``base``, and ``other`` + dicts. For example: ``{local.label}``, ``{base.name}``, or + ``{other.islink}``. + ``quiet`` Reduce the amount of output printed. (default: False) diff --git a/tests/test-merge-tools.t b/tests/test-merge-tools.t --- a/tests/test-merge-tools.t +++ b/tests/test-merge-tools.t @@ -1946,6 +1946,25 @@ internal merge tools is checked strictly 0000: 00 01 02 03 |....| $ hg merge --abort -q +Check that the extra information is printed correctly + + $ hg merge 9 \ + > --config merge-tools.testecho.executable='echo' \ + > --config merge-tools.testecho.args='merge runs here ...' \ + > --config merge-tools.testecho.binary=True \ + > --config ui.merge=testecho \ + > --config ui.pre-merge-tool-output-template='\n{label("extmerge.running_merge_tool", "Running merge tool for {path} ({toolpath}):")}\n{separate("\n", extmerge_section(local), extmerge_section(base), extmerge_section(other))}\n' \ + > --config 'templatealias.extmerge_section(sect)="- {pad("{sect.name} ({sect.label})", 20, left=True)}: {revset(sect.node)%"{rev}:{shortest(node,8)} {desc|firstline} {separate(" ", tags, bookmarks, branch)}"}"' + merging b + + Running merge tool for b (*/bin/echo): (glob) + - local (working copy): 10:2d1f533d add binary file (#2) tip default + - base (base): -1:00000000 default + - other (merge rev): 9:1e7ad7d7 add binary file (#1) default + merge runs here ... + 0 files updated, 1 files merged, 0 files removed, 0 files unresolved + (branch merge, don't forget to commit) + Check that debugpicktool examines which merge tool is chosen for specified file as expected