[PATCH 4 of 4] dispatch: store norepo/optionalrepo/inferrepo attributes in function (API)

Yuya Nishihara yuya at tcha.org
Sun Feb 28 01:55:43 EST 2016


# HG changeset patch
# User Yuya Nishihara <yuya at tcha.org>
# Date 1451654185 -32400
#      Fri Jan 01 22:16:25 2016 +0900
# Node ID 31acfd12c0748e0b9ba902dc036d267f82d57c90
# Parent  c8ea5f04dfb0c291ca29d89ab3bf93e75de60506
dispatch: store norepo/optionalrepo/inferrepo attributes in function (API)

This can eliminate import cycles and ugly push/pop of global variables at
_checkshellalias(). Attributes of aliascmd are directly accessible.

Because norepo/optionalrepo/inferrepo lists aren't populated, extensions
examining them no longer work. That's why this patch removes these lists
to signal the API incompatibility.

This breaks 3rd-party extensions that are yet to be ported to @command
decorator.

diff --git a/hgext/mq.py b/hgext/mq.py
--- a/hgext/mq.py
+++ b/hgext/mq.py
@@ -3560,12 +3560,11 @@ def extsetup(ui):
     entry = extensions.wrapcommand(commands.table, 'init', mqinit)
     entry[1].extend(mqopt)
 
-    nowrap = set(commands.norepo.split(" "))
-
     def dotable(cmdtable):
-        for cmd in cmdtable.keys():
+        for cmd, entry in cmdtable.iteritems():
             cmd = cmdutil.parsealiases(cmd)[0]
-            if cmd in nowrap:
+            func = entry[0]
+            if func.norepo:
                 continue
             entry = extensions.wrapcommand(cmdtable, cmd, mqcommand)
             entry[1].extend(mqopt)
diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -3264,24 +3264,13 @@ def command(table):
     def cmd(name, options=(), synopsis=None, norepo=False, optionalrepo=False,
             inferrepo=False):
         def decorator(func):
+            func.norepo = norepo
+            func.optionalrepo = optionalrepo
+            func.inferrepo = inferrepo
             if synopsis:
                 table[name] = func, list(options), synopsis
             else:
                 table[name] = func, list(options)
-
-            if norepo:
-                # Avoid import cycle.
-                import commands
-                commands.norepo += ' %s' % ' '.join(parsealiases(name))
-
-            if optionalrepo:
-                import commands
-                commands.optionalrepo += ' %s' % ' '.join(parsealiases(name))
-
-            if inferrepo:
-                import commands
-                commands.inferrepo += ' %s' % ' '.join(parsealiases(name))
-
             return func
         return decorator
 
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -29,18 +29,6 @@ table = {}
 
 command = cmdutil.command(table)
 
-# Space delimited list of commands that don't require local repositories.
-# This should be populated by passing norepo=True into the @command decorator.
-norepo = ''
-# Space delimited list of commands that optionally require local repositories.
-# This should be populated by passing optionalrepo=True into the @command
-# decorator.
-optionalrepo = ''
-# Space delimited list of commands that will examine arguments looking for
-# a repository. This should be populated by passing inferrepo=True into the
-# @command decorator.
-inferrepo = ''
-
 # label constants
 # until 3.5, bookmarks.current was the advertised name, not
 # bookmarks.active, so we must use both to avoid breaking old
diff --git a/mercurial/dispatch.py b/mercurial/dispatch.py
--- a/mercurial/dispatch.py
+++ b/mercurial/dispatch.py
@@ -496,11 +496,11 @@ class cmdalias(object):
                 self.fn, self.opts = tableentry
 
             self.args = aliasargs(self.fn, args)
-            if cmd not in commands.norepo.split(' '):
+            if not self.fn.norepo:
                 self.norepo = False
-            if cmd in commands.optionalrepo.split(' '):
+            if self.fn.optionalrepo:
                 self.optionalrepo = True
-            if cmd in commands.inferrepo.split(' '):
+            if self.fn.inferrepo:
                 self.inferrepo = True
             if self.help.startswith("hg " + cmd):
                 # drop prefix in old-style help lines so hg shows the alias
@@ -556,12 +556,6 @@ def addaliases(ui, cmdtable):
             pass
 
         cmdtable[aliasdef.name] = (aliasdef, aliasdef.opts, aliasdef.help)
-        if aliasdef.norepo:
-            commands.norepo += ' %s' % alias
-        if aliasdef.optionalrepo:
-            commands.optionalrepo += ' %s' % alias
-        if aliasdef.inferrepo:
-            commands.inferrepo += ' %s' % alias
 
 def _parse(ui, args):
     options = {}
@@ -728,26 +722,16 @@ def _checkshellalias(lui, ui, args, prec
 
     if precheck:
         strict = True
-        norepo = commands.norepo
-        optionalrepo = commands.optionalrepo
-        inferrepo = commands.inferrepo
-        def restorecommands():
-            commands.norepo = norepo
-            commands.optionalrepo = optionalrepo
-            commands.inferrepo = inferrepo
         cmdtable = commands.table.copy()
         addaliases(lui, cmdtable)
     else:
         strict = False
-        def restorecommands():
-            pass
         cmdtable = commands.table
 
     cmd = args[0]
     try:
         aliases, entry = cmdutil.findcmd(cmd, cmdtable, strict)
     except (error.AmbiguousCommand, error.UnknownCommand):
-        restorecommands()
         return
 
     cmd = aliases[0]
@@ -758,8 +742,6 @@ def _checkshellalias(lui, ui, args, prec
         return lambda: runcommand(lui, None, cmd, args[:1], ui, options, d,
                                   [], {})
 
-    restorecommands()
-
 _loaded = set()
 def _dispatch(req):
     args = req.args
@@ -876,7 +858,7 @@ def _dispatch(req):
 
     repo = None
     cmdpats = args[:]
-    if cmd not in commands.norepo.split():
+    if not func.norepo:
         # use the repo from the request only if we don't have -R
         if not rpath and not cwd:
             repo = req.repo
@@ -897,9 +879,9 @@ def _dispatch(req):
             except error.RepoError:
                 if rpath and rpath[-1]: # invalid -R path
                     raise
-                if cmd not in commands.optionalrepo.split():
-                    if (cmd in commands.inferrepo.split() and
-                        args and not path): # try to infer -R from command args
+                if not func.optionalrepo:
+                    if func.inferrepo and args and not path:
+                        # try to infer -R from command args
                         repos = map(cmdutil.findrepo, args)
                         guess = repos[0]
                         if guess and repos.count(guess) == len(repos):


More information about the Mercurial-devel mailing list