[PATCH 2a of 2 STABLE] cmdutil: prevent "show" from matching "showconfig" (BC)

Gregory Szorc gregory.szorc at gmail.com
Thu Apr 27 19:08:50 EDT 2017


# HG changeset patch
# User Gregory Szorc <gregory.szorc at gmail.com>
# Date 1493334106 25200
#      Thu Apr 27 16:01:46 2017 -0700
# Branch stable
# Node ID fe27d189af6214099003e7eab18f0f0dd2e77b8a
# Parent  f495df1ca1cc3583ecfbed208de69a966eb74aea
cmdutil: prevent "show" from matching "showconfig" (BC)

cmdutil.findpossible() performs a string prefix match to determine
if a user-provided command/string should map to a command. If there
is an unambiguous match, the mapped command is used.

This causes problems with commands defined by extensions. These
commands aren't in the commands table. So, the command names and
aliases have no opportunity to create a prefix match and prevent
an unambiguous match.

In the case of `hg show`, "show" was being mapped to "showconfig"
because nothing else in core has a "show" prefix.

This commit adds an argument to the @command decorator to define
strings that won't be allowed to partial match the command.
findpossible() has been taught to consult this value. And
`hg config` now doesn't match against "show."

The single test change demonstrates that an out-of-the-box
`hg show` now properly indicates that the command is provided by
an extension.

diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -317,8 +317,9 @@ def findpossible(cmd, table, strict=Fals
         if cmd in aliases:
             found = cmd
         elif not strict:
+            nomatch = table[e][0].nomatch
             for a in aliases:
-                if a.startswith(cmd):
+                if a.startswith(cmd) and cmd not in nomatch:
                     found = a
                     break
         if found is not None:
@@ -3361,13 +3362,18 @@ def command(table):
     command line arguments. If True, arguments will be examined for potential
     repository locations. See ``findrepo()``. If a repository is found, it
     will be used.
+
+    ``nomatch`` defines an iterable of command strings that should not result
+    in an alias match. Without this, all string prefixes in ``name`` elements
+    will map to this command.
     """
     def cmd(name, options=(), synopsis=None, norepo=False, optionalrepo=False,
-            inferrepo=False):
+            inferrepo=False, nomatch=None):
         def decorator(func):
             func.norepo = norepo
             func.optionalrepo = optionalrepo
             func.inferrepo = inferrepo
+            func.nomatch = nomatch or []
             if synopsis:
                 table[name] = func, list(options), synopsis
             else:
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -1744,7 +1744,9 @@ def _docommit(ui, repo, *pats, **opts):
      ('l', 'local', None, _('edit repository config')),
      ('g', 'global', None, _('edit global config'))] + formatteropts,
     _('[-u] [NAME]...'),
-    optionalrepo=True)
+    optionalrepo=True,
+    # FUTURE can be removed once show extension is moved to core.
+    nomatch=['show'])
 def config(ui, repo, *values, **opts):
     """show combined config settings from all hgrc files
 
diff --git a/mercurial/dispatch.py b/mercurial/dispatch.py
--- a/mercurial/dispatch.py
+++ b/mercurial/dispatch.py
@@ -475,7 +475,12 @@ class cmdalias(object):
         return aliasargs(self.fn, args)
 
     def __getattr__(self, name):
-        adefaults = {'norepo': True, 'optionalrepo': False, 'inferrepo': False}
+        adefaults = {
+            'norepo': True,
+            'optionalrepo': False,
+            'inferrepo': False,
+            'nomatch': [],
+        }
         if name not in adefaults:
             raise AttributeError(name)
         if self.badalias or util.safehasattr(self, 'shell'):
diff --git a/tests/test-show.t b/tests/test-show.t
--- a/tests/test-show.t
+++ b/tests/test-show.t
@@ -1,19 +1,14 @@
 `hg show` without extension enabled says to enable the extension
-TODO this is broken due to matching with showconfig
 
   $ hg show
-  defaults.backout=-d "0 0"
-  defaults.commit=-d "0 0"
-  defaults.shelve=--date "0 0"
-  defaults.tag=-d "0 0"
-  devel.all-warnings=true
-  largefiles.usercache=$TESTTMP/.cache/largefiles
-  ui.slash=True
-  ui.interactive=False
-  ui.mergemarkers=detailed
-  ui.promptecho=True
-  web.address=localhost
-  web.ipv6=False
+  hg: unknown command 'show'
+  'show' is provided by the following extension:
+  
+      show          unified command to show various repository information
+                    (EXPERIMENTAL)
+  
+  (use 'hg help extensions' for information on enabling extensions)
+  [255]
 
   $ cat >> $HGRCPATH << EOF
   > [extensions]


More information about the Mercurial-devel mailing list