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.
--- a/hgext/mq.py Sat Jan 09 20:04:03 2016 +0900
+++ b/hgext/mq.py Fri Jan 01 22:16:25 2016 +0900
@@ -3560,12 +3560,11 @@
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)
--- a/mercurial/cmdutil.py Sat Jan 09 20:04:03 2016 +0900
+++ b/mercurial/cmdutil.py Fri Jan 01 22:16:25 2016 +0900
@@ -3270,24 +3270,13 @@
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
--- a/mercurial/commands.py Sat Jan 09 20:04:03 2016 +0900
+++ b/mercurial/commands.py Fri Jan 01 22:16:25 2016 +0900
@@ -29,18 +29,6 @@
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
--- a/mercurial/dispatch.py Sat Jan 09 20:04:03 2016 +0900
+++ b/mercurial/dispatch.py Fri Jan 01 22:16:25 2016 +0900
@@ -496,11 +496,11 @@
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 @@
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 @@
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 @@
return lambda: runcommand(lui, None, cmd, args[:1], ui, options, d,
[], {})
- restorecommands()
-
_loaded = set()
def _dispatch(req):
args = req.args
@@ -876,7 +858,7 @@
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 @@
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):