Patchwork [4,of,4] debugcommands: add debugpickmergetool to examine which merge tool is chosen

login
register
mail settings
Submitter Katsunori FUJIWARA
Date May 12, 2017, 6:42 p.m.
Message ID <045ec01b035fc06e14df.1494614531@speaknoevil>
Download mbox | patch
Permalink /patch/20591/
State Accepted
Headers show

Comments

Katsunori FUJIWARA - May 12, 2017, 6:42 p.m.
# HG changeset patch
# User FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
# Date 1494614270 -32400
#      Sat May 13 03:37:50 2017 +0900
# Node ID 045ec01b035fc06e14df4ea579d84b2e0f489831
# Parent  f175a47c78c9a6bdc640b278f9055b097cec29db
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.
Augie Fackler - May 13, 2017, 2:19 a.m.
On Sat, May 13, 2017 at 03:42:11AM +0900, FUJIWARA Katsunori wrote:
> # HG changeset patch
> # User FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
> # Date 1494614270 -32400
> #      Sat May 13 03:37:50 2017 +0900
> # Node ID 045ec01b035fc06e14df4ea579d84b2e0f489831
> # Parent  f175a47c78c9a6bdc640b278f9055b097cec29db
> debugcommands: add debugpickmergetool to examine which merge tool is chosen

queued, thanks

Patch

diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py
--- a/mercurial/debugcommands.py
+++ b/mercurial/debugcommands.py
@@ -40,6 +40,7 @@  from . import (
     error,
     exchange,
     extensions,
+    filemerge,
     fileset,
     formatter,
     hg,
@@ -1502,6 +1503,84 @@  def debugpathcomplete(ui, repo, *specs, 
     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
diff --git a/tests/test-completion.t b/tests/test-completion.t
--- a/tests/test-completion.t
+++ b/tests/test-completion.t
@@ -99,6 +99,7 @@  Show debug commands if there are no othe
   debugnamecomplete
   debugobsolete
   debugpathcomplete
+  debugpickmergetool
   debugpushkey
   debugpvec
   debugrebuilddirstate
@@ -272,6 +273,7 @@  Show all commands + options
   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
diff --git a/tests/test-help.t b/tests/test-help.t
--- a/tests/test-help.t
+++ b/tests/test-help.t
@@ -912,6 +912,8 @@  Test list of internal help commands
    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
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
@@ -1281,3 +1281,68 @@  Verify naming of temporary files and tha
   */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