changeset 32296:9bc36198338e

debugcommands: add debugpickmergetool to examine which merge tool is chosen Before this patch, there is no convenient way to know which merge tool is chosen for each managed files without actual merging.
author FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
date Sat, 13 May 2017 03:37:50 +0900
parents 7e35d31b41fd
children 205bd3936179
files mercurial/debugcommands.py tests/test-completion.t tests/test-help.t tests/test-merge-tools.t
diffstat 4 files changed, 148 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/debugcommands.py	Sat May 13 03:31:42 2017 +0900
+++ b/mercurial/debugcommands.py	Sat May 13 03:37:50 2017 +0900
@@ -40,6 +40,7 @@
     error,
     exchange,
     extensions,
+    filemerge,
     fileset,
     formatter,
     hg,
@@ -1502,6 +1503,84 @@
     ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
     ui.write('\n')
 
+@command('debugpickmergetool',
+        [('r', 'rev', '', _('check for files in this revision'), _('REV')),
+         ('', 'changedelete', None, _('emulate merging change and delete')),
+        ] + commands.walkopts + commands.mergetoolopts,
+        _('[PATTERN]...'),
+        inferrepo=True)
+def debugpickmergetool(ui, repo, *pats, **opts):
+    """examine which merge tool is chosen for specified file
+
+    As described in :hg:`help merge-tools`, Mercurial examines
+    configurations below in this order to decide which merge tool is
+    chosen for specified file.
+
+    1. ``--tool`` option
+    2. ``HGMERGE`` environment variable
+    3. configurations in ``merge-patterns`` section
+    4. configuration of ``ui.merge``
+    5. configurations in ``merge-tools`` section
+    6. ``hgmerge`` tool (for historical reason only)
+    7. default tool for fallback (``:merge`` or ``:prompt``)
+
+    This command writes out examination result in the style below::
+
+        FILE = MERGETOOL
+
+    By default, all files known in the first parent context of the
+    working directory are examined. Use file patterns and/or -I/-X
+    options to limit target files. -r/--rev is also useful to examine
+    files in another context without actual updating to it.
+
+    With --debug, this command shows warning messages while matching
+    against ``merge-patterns`` and so on, too. It is recommended to
+    use this option with explicit file patterns and/or -I/-X options,
+    because this option increases amount of output per file according
+    to configurations in hgrc.
+
+    With -v/--verbose, this command shows configurations below at
+    first (only if specified).
+
+    - ``--tool`` option
+    - ``HGMERGE`` environment variable
+    - configuration of ``ui.merge``
+
+    If merge tool is chosen before matching against
+    ``merge-patterns``, this command can't show any helpful
+    information, even with --debug. In such case, information above is
+    useful to know why a merge tool is chosen.
+    """
+    overrides = {}
+    if opts['tool']:
+        overrides[('ui', 'forcemerge')] = opts['tool']
+        ui.note(('with --tool %r\n') % (opts['tool']))
+
+    with ui.configoverride(overrides, 'debugmergepatterns'):
+        hgmerge = encoding.environ.get("HGMERGE")
+        if hgmerge is not None:
+            ui.note(('with HGMERGE=%r\n') % (hgmerge))
+        uimerge = ui.config("ui", "merge")
+        if uimerge:
+            ui.note(('with ui.merge=%r\n') % (uimerge))
+
+        ctx = scmutil.revsingle(repo, opts.get('rev'))
+        m = scmutil.match(ctx, pats, opts)
+        changedelete = opts['changedelete']
+        for path in ctx.walk(m):
+            fctx = ctx[path]
+            try:
+                if not ui.debugflag:
+                    ui.pushbuffer(error=True)
+                tool, toolpath = filemerge._picktool(repo, ui, path,
+                                                     fctx.isbinary(),
+                                                     'l' in fctx.flags(),
+                                                     changedelete)
+            finally:
+                if not ui.debugflag:
+                    ui.popbuffer()
+            ui.write(('%s = %s\n') % (path, tool))
+
 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
     '''access the pushkey key/value protocol
--- a/tests/test-completion.t	Sat May 13 03:31:42 2017 +0900
+++ b/tests/test-completion.t	Sat May 13 03:37:50 2017 +0900
@@ -99,6 +99,7 @@
   debugnamecomplete
   debugobsolete
   debugpathcomplete
+  debugpickmergetool
   debugpushkey
   debugpvec
   debugrebuilddirstate
@@ -272,6 +273,7 @@
   debugnamecomplete: 
   debugobsolete: flags, record-parents, rev, index, delete, date, user, template
   debugpathcomplete: full, normal, added, removed
+  debugpickmergetool: rev, changedelete, include, exclude, tool
   debugpushkey: 
   debugpvec: 
   debugrebuilddirstate: rev, minimal
--- a/tests/test-help.t	Sat May 13 03:31:42 2017 +0900
+++ b/tests/test-help.t	Sat May 13 03:37:50 2017 +0900
@@ -912,6 +912,8 @@
    debugoptEXP   (no help text available)
    debugpathcomplete
                  complete part or all of a tracked path
+   debugpickmergetool
+                 examine which merge tool is chosen for specified file
    debugpushkey  access the pushkey key/value protocol
    debugpvec     (no help text available)
    debugrebuilddirstate
--- a/tests/test-merge-tools.t	Sat May 13 03:31:42 2017 +0900
+++ b/tests/test-merge-tools.t	Sat May 13 03:37:50 2017 +0900
@@ -1281,3 +1281,68 @@
   */f~base.?????? $TESTTMP/f.txt.orig */f~other.??????.txt $TESTTMP/f.txt (glob)
   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
+
+  $ beforemerge
+  [merge-tools]
+  false.whatever=
+  true.priority=1
+  true.executable=cat
+  # hg update -C 1
+
+(default behavior: checking files in the working parent context)
+
+  $ hg manifest
+  f
+  $ hg debugpickmergetool
+  f = true
+
+(-X/-I and file patterns limmit examination targets)
+
+  $ hg debugpickmergetool -X f
+  $ hg debugpickmergetool unknown
+  unknown: no such file in rev ef83787e2614
+
+(--changedelete emulates merging change and delete)
+
+  $ hg debugpickmergetool --changedelete
+  f = :prompt
+
+(-r REV causes checking files in specified revision)
+
+  $ hg manifest -r tip
+  f.txt
+  $ hg debugpickmergetool -r tip
+  f.txt = true
+
+#if symlink
+
+(symlink causes chosing :prompt)
+
+  $ hg debugpickmergetool -r 6d00b3726f6e
+  f = :prompt
+
+#endif
+
+(--verbose shows some configurations)
+
+  $ hg debugpickmergetool --tool foobar -v
+  with --tool 'foobar'
+  f = foobar
+
+  $ HGMERGE=false hg debugpickmergetool -v
+  with HGMERGE='false'
+  f = false
+
+  $ hg debugpickmergetool --config ui.merge=false -v
+  with ui.merge='false'
+  f = false
+
+(--debug shows errors detected intermediately)
+
+  $ hg debugpickmergetool --config merge-patterns.f=true --config merge-tools.true.executable=nonexistentmergetool --debug f
+  couldn't find merge tool true (for pattern f)
+  couldn't find merge tool true
+  f = false