changeset 32337:46ba2cdda476

registrar: move cmdutil.command to registrar module (API) cmdutil.command wasn't a member of the registrar framework only for a historical reason. Let's make that happen. This patch keeps cmdutil.command as an alias for extension compatibility.
author Yuya Nishihara <yuya@tcha.org>
date Sat, 09 Jan 2016 23:07:20 +0900
parents ff874d34c856
children ec84db232fc2
files contrib/debugshell.py contrib/perf.py contrib/synthrepo.py hgext/blackbox.py hgext/censor.py hgext/children.py hgext/churn.py hgext/convert/__init__.py hgext/extdiff.py hgext/fetch.py hgext/gpg.py hgext/graphlog.py hgext/hgk.py hgext/histedit.py hgext/journal.py hgext/keyword.py hgext/largefiles/lfcommands.py hgext/mq.py hgext/patchbomb.py hgext/purge.py hgext/rebase.py hgext/record.py hgext/relink.py hgext/schemes.py hgext/share.py hgext/shelve.py hgext/show.py hgext/strip.py hgext/transplant.py mercurial/cmdutil.py mercurial/commands.py mercurial/debugcommands.py mercurial/registrar.py tests/autodiff.py tests/drawdag.py tests/fakemergerecord.py tests/test-bad-extension.t tests/test-bundle2-format.t tests/test-chg.t tests/test-commandserver.t tests/test-devel-warnings.t tests/test-encoding-align.t tests/test-encoding-textwrap.t tests/test-extension.t tests/test-help.t tests/test-lock-badness.t tests/test-logtoprocess.t tests/test-obsolete.t tests/test-pager-legacy.t tests/test-pager.t tests/test-profile.t tests/test-progress.t tests/test-rebuildstate.t tests/test-resolve.t tests/test-revset.t tests/test-worker.t
diffstat 56 files changed, 169 insertions(+), 146 deletions(-) [+]
line wrap: on
line diff
--- a/contrib/debugshell.py	Sat May 13 17:53:55 2017 +0900
+++ b/contrib/debugshell.py	Sat Jan 09 23:07:20 2016 +0900
@@ -6,12 +6,12 @@
 import mercurial
 import sys
 from mercurial import (
-    cmdutil,
     demandimport,
+    registrar,
 )
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 
 def pdb(ui, repo, msg, **opts):
     objects = {
--- a/contrib/perf.py	Sat May 13 17:53:55 2017 +0900
+++ b/contrib/perf.py	Sat Jan 09 23:07:20 2016 +0900
@@ -49,6 +49,11 @@
 except ImportError:
     pass
 try:
+    from mercurial import registrar # since 3.7 (or 37d50250b696)
+    dir(registrar) # forcibly load it
+except ImportError:
+    registrar = None
+try:
     from mercurial import repoview # since 2.5 (or 3a6ddacb7198)
 except ImportError:
     pass
@@ -101,7 +106,9 @@
 def parsealiases(cmd):
     return cmd.lstrip("^").split("|")
 
-if safehasattr(cmdutil, 'command'):
+if safehasattr(registrar, 'command'):
+    command = registrar.command(cmdtable)
+elif safehasattr(cmdutil, 'command'):
     import inspect
     command = cmdutil.command(cmdtable)
     if 'norepo' not in inspect.getargspec(command)[0]:
--- a/contrib/synthrepo.py	Sat May 13 17:53:55 2017 +0900
+++ b/contrib/synthrepo.py	Sat Jan 09 23:07:20 2016 +0900
@@ -53,11 +53,11 @@
     short,
 )
 from mercurial import (
-    cmdutil,
     context,
     error,
     hg,
     patch,
+    registrar,
     scmutil,
     util,
 )
@@ -69,7 +69,7 @@
 testedwith = 'ships-with-hg-core'
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 
 newfile = {'new fi', 'rename', 'copy f', 'copy t'}
 
--- a/hgext/blackbox.py	Sat May 13 17:53:55 2017 +0900
+++ b/hgext/blackbox.py	Sat Jan 09 23:07:20 2016 +0900
@@ -44,13 +44,13 @@
 from mercurial.node import hex
 
 from mercurial import (
-    cmdutil,
+    registrar,
     ui as uimod,
     util,
 )
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
 # be specifying the version(s) of Mercurial they are tested with, or
--- a/hgext/censor.py	Sat May 13 17:53:55 2017 +0900
+++ b/hgext/censor.py	Sat Jan 09 23:07:20 2016 +0900
@@ -31,17 +31,17 @@
 from mercurial.node import short
 
 from mercurial import (
-    cmdutil,
     error,
     filelog,
     lock as lockmod,
+    registrar,
     revlog,
     scmutil,
     util,
 )
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
 # be specifying the version(s) of Mercurial they are tested with, or
--- a/hgext/children.py	Sat May 13 17:53:55 2017 +0900
+++ b/hgext/children.py	Sat Jan 09 23:07:20 2016 +0900
@@ -20,12 +20,13 @@
 from mercurial import (
     cmdutil,
     commands,
+    registrar,
 )
 
 templateopts = commands.templateopts
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
 # be specifying the version(s) of Mercurial they are tested with, or
--- a/hgext/churn.py	Sat May 13 17:53:55 2017 +0900
+++ b/hgext/churn.py	Sat Jan 09 23:07:20 2016 +0900
@@ -20,12 +20,13 @@
     commands,
     encoding,
     patch,
+    registrar,
     scmutil,
     util,
 )
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
 # be specifying the version(s) of Mercurial they are tested with, or
--- a/hgext/convert/__init__.py	Sat May 13 17:53:55 2017 +0900
+++ b/hgext/convert/__init__.py	Sat Jan 09 23:07:20 2016 +0900
@@ -11,7 +11,6 @@
 
 from mercurial.i18n import _
 from mercurial import (
-    cmdutil,
     registrar,
 )
 
@@ -22,7 +21,7 @@
 )
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
 # be specifying the version(s) of Mercurial they are tested with, or
--- a/hgext/extdiff.py	Sat May 13 17:53:55 2017 +0900
+++ b/hgext/extdiff.py	Sat Jan 09 23:07:20 2016 +0900
@@ -78,12 +78,13 @@
     error,
     filemerge,
     pycompat,
+    registrar,
     scmutil,
     util,
 )
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
 # be specifying the version(s) of Mercurial they are tested with, or
--- a/hgext/fetch.py	Sat May 13 17:53:55 2017 +0900
+++ b/hgext/fetch.py	Sat Jan 09 23:07:20 2016 +0900
@@ -20,12 +20,13 @@
     exchange,
     hg,
     lock,
+    registrar,
     util,
 )
 
 release = lock.release
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
 # be specifying the version(s) of Mercurial they are tested with, or
--- a/hgext/gpg.py	Sat May 13 17:53:55 2017 +0900
+++ b/hgext/gpg.py	Sat Jan 09 23:07:20 2016 +0900
@@ -19,11 +19,12 @@
     match,
     node as hgnode,
     pycompat,
+    registrar,
     util,
 )
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
 # be specifying the version(s) of Mercurial they are tested with, or
--- a/hgext/graphlog.py	Sat May 13 17:53:55 2017 +0900
+++ b/hgext/graphlog.py	Sat Jan 09 23:07:20 2016 +0900
@@ -19,12 +19,12 @@
 
 from mercurial.i18n import _
 from mercurial import (
-    cmdutil,
     commands,
+    registrar,
 )
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
 # be specifying the version(s) of Mercurial they are tested with, or
--- a/hgext/hgk.py	Sat May 13 17:53:55 2017 +0900
+++ b/hgext/hgk.py	Sat Jan 09 23:07:20 2016 +0900
@@ -45,15 +45,15 @@
     short,
 )
 from mercurial import (
-    cmdutil,
     commands,
     obsolete,
     patch,
+    registrar,
     scmutil,
 )
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
 # be specifying the version(s) of Mercurial they are tested with, or
--- a/hgext/histedit.py	Sat May 13 17:53:55 2017 +0900
+++ b/hgext/histedit.py	Sat Jan 09 23:07:20 2016 +0900
@@ -201,6 +201,7 @@
     mergeutil,
     node,
     obsolete,
+    registrar,
     repair,
     scmutil,
     util,
@@ -209,7 +210,7 @@
 pickle = util.pickle
 release = lock.release
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 
 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
--- a/hgext/journal.py	Sat May 13 17:53:55 2017 +0900
+++ b/hgext/journal.py	Sat Jan 09 23:07:20 2016 +0900
@@ -31,13 +31,14 @@
     localrepo,
     lock,
     node,
+    registrar,
     util,
 )
 
 from . import share
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 
 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
--- a/hgext/keyword.py	Sat May 13 17:53:55 2017 +0900
+++ b/hgext/keyword.py	Sat Jan 09 23:07:20 2016 +0900
@@ -111,7 +111,7 @@
 )
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
 # be specifying the version(s) of Mercurial they are tested with, or
--- a/hgext/largefiles/lfcommands.py	Sat May 13 17:53:55 2017 +0900
+++ b/hgext/largefiles/lfcommands.py	Sat Jan 09 23:07:20 2016 +0900
@@ -25,6 +25,7 @@
     lock,
     match as matchmod,
     node,
+    registrar,
     scmutil,
     util,
 )
@@ -44,7 +45,7 @@
 # -- Commands ----------------------------------------------------------
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 
 @command('lfconvert',
     [('s', 'size', '',
--- a/hgext/mq.py	Sat May 13 17:53:55 2017 +0900
+++ b/hgext/mq.py	Sat Jan 09 23:07:20 2016 +0900
@@ -101,7 +101,7 @@
 seriesopts = [('s', 'summary', None, _('print first line of patch header'))]
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
 # be specifying the version(s) of Mercurial they are tested with, or
--- a/hgext/patchbomb.py	Sat May 13 17:53:55 2017 +0900
+++ b/hgext/patchbomb.py	Sat Jan 09 23:07:20 2016 +0900
@@ -89,6 +89,7 @@
     mail,
     node as nodemod,
     patch,
+    registrar,
     scmutil,
     templater,
     util,
@@ -96,7 +97,7 @@
 stringio = util.stringio
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
 # be specifying the version(s) of Mercurial they are tested with, or
--- a/hgext/purge.py	Sat May 13 17:53:55 2017 +0900
+++ b/hgext/purge.py	Sat Jan 09 23:07:20 2016 +0900
@@ -29,15 +29,15 @@
 
 from mercurial.i18n import _
 from mercurial import (
-    cmdutil,
     commands,
     error,
+    registrar,
     scmutil,
     util,
 )
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
 # be specifying the version(s) of Mercurial they are tested with, or
--- a/hgext/rebase.py	Sat May 13 17:53:55 2017 +0900
+++ b/hgext/rebase.py	Sat Jan 09 23:07:20 2016 +0900
@@ -68,7 +68,7 @@
 revskipped = (revignored, revprecursor, revpruned)
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
 # be specifying the version(s) of Mercurial they are tested with, or
--- a/hgext/record.py	Sat May 13 17:53:55 2017 +0900
+++ b/hgext/record.py	Sat Jan 09 23:07:20 2016 +0900
@@ -18,10 +18,11 @@
     commands,
     error,
     extensions,
+    registrar,
 )
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
 # be specifying the version(s) of Mercurial they are tested with, or
--- a/hgext/relink.py	Sat May 13 17:53:55 2017 +0900
+++ b/hgext/relink.py	Sat Jan 09 23:07:20 2016 +0900
@@ -13,14 +13,14 @@
 
 from mercurial.i18n import _
 from mercurial import (
-    cmdutil,
     error,
     hg,
+    registrar,
     util,
 )
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
 # be specifying the version(s) of Mercurial they are tested with, or
--- a/hgext/schemes.py	Sat May 13 17:53:55 2017 +0900
+++ b/hgext/schemes.py	Sat Jan 09 23:07:20 2016 +0900
@@ -46,17 +46,17 @@
 
 from mercurial.i18n import _
 from mercurial import (
-    cmdutil,
     error,
     extensions,
     hg,
     pycompat,
+    registrar,
     templater,
     util,
 )
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
 # be specifying the version(s) of Mercurial they are tested with, or
--- a/hgext/share.py	Sat May 13 17:53:55 2017 +0900
+++ b/hgext/share.py	Sat Jan 09 23:07:20 2016 +0900
@@ -43,11 +43,11 @@
 from mercurial.i18n import _
 from mercurial import (
     bookmarks,
-    cmdutil,
     commands,
     error,
     extensions,
     hg,
+    registrar,
     txnutil,
     util,
 )
@@ -56,7 +56,7 @@
 parseurl = hg.parseurl
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
 # be specifying the version(s) of Mercurial they are tested with, or
--- a/hgext/shelve.py	Sat May 13 17:53:55 2017 +0900
+++ b/hgext/shelve.py	Sat Jan 09 23:07:20 2016 +0900
@@ -43,6 +43,7 @@
     node as nodemod,
     patch,
     phases,
+    registrar,
     repair,
     scmutil,
     templatefilters,
@@ -55,7 +56,7 @@
 )
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
 # be specifying the version(s) of Mercurial they are tested with, or
--- a/hgext/show.py	Sat May 13 17:53:55 2017 +0900
+++ b/hgext/show.py	Sat Jan 09 23:07:20 2016 +0900
@@ -34,7 +34,7 @@
 testedwith = 'ships-with-hg-core'
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 revsetpredicate = registrar.revsetpredicate()
 
 class showcmdfunc(registrar._funcregistrarbase):
--- a/hgext/strip.py	Sat May 13 17:53:55 2017 +0900
+++ b/hgext/strip.py	Sat Jan 09 23:07:20 2016 +0900
@@ -14,6 +14,7 @@
     lock as lockmod,
     merge,
     node as nodemod,
+    registrar,
     repair,
     scmutil,
     util,
@@ -22,7 +23,7 @@
 release = lockmod.release
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
 # be specifying the version(s) of Mercurial they are tested with, or
--- a/hgext/transplant.py	Sat May 13 17:53:55 2017 +0900
+++ b/hgext/transplant.py	Sat Jan 09 23:07:20 2016 +0900
@@ -42,7 +42,7 @@
     pass
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
 # be specifying the version(s) of Mercurial they are tested with, or
--- a/mercurial/cmdutil.py	Sat May 13 17:53:55 2017 +0900
+++ b/mercurial/cmdutil.py	Sat Jan 09 23:07:20 2016 +0900
@@ -38,6 +38,7 @@
     pathutil,
     phases,
     pycompat,
+    registrar,
     repair,
     revlog,
     revset,
@@ -3334,50 +3335,7 @@
         if f in copied:
             repo.dirstate.copy(copied[f], f)
 
-def command(table):
-    """Returns a function object to be used as a decorator for making commands.
-
-    This function receives a command table as its argument. The table should
-    be a dict.
-
-    The returned function can be used as a decorator for adding commands
-    to that command table. This function accepts multiple arguments to define
-    a command.
-
-    The first argument is the command name.
-
-    The options argument is an iterable of tuples defining command arguments.
-    See ``mercurial.fancyopts.fancyopts()`` for the format of each tuple.
-
-    The synopsis argument defines a short, one line summary of how to use the
-    command. This shows up in the help output.
-
-    The norepo argument defines whether the command does not require a
-    local repository. Most commands operate against a repository, thus the
-    default is False.
-
-    The optionalrepo argument defines whether the command optionally requires
-    a local repository.
-
-    The inferrepo argument defines whether to try to find a repository from the
-    command line arguments. If True, arguments will be examined for potential
-    repository locations. See ``findrepo()``. If a repository is found, it
-    will be used.
-    """
-    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)
-            return func
-        return decorator
-
-    return cmd
+command = registrar.command
 
 # a list of (ui, repo, otherpeer, opts, missing) functions called by
 # commands.outgoing.  "missing" is "missing" of the result of
--- a/mercurial/commands.py	Sat May 13 17:53:55 2017 +0900
+++ b/mercurial/commands.py	Sat Jan 09 23:07:20 2016 +0900
@@ -44,6 +44,7 @@
     phases,
     pycompat,
     rcutil,
+    registrar,
     revsetlang,
     scmutil,
     server,
@@ -59,7 +60,7 @@
 
 table = {}
 
-command = cmdutil.command(table)
+command = registrar.command(table)
 
 # label constants
 # until 3.5, bookmarks.current was the advertised name, not
--- a/mercurial/debugcommands.py	Sat May 13 17:53:55 2017 +0900
+++ b/mercurial/debugcommands.py	Sat Jan 09 23:07:20 2016 +0900
@@ -51,6 +51,7 @@
     policy,
     pvec,
     pycompat,
+    registrar,
     repair,
     revlog,
     revset,
@@ -72,7 +73,7 @@
 
 # We reuse the command table from commands because it is easier than
 # teaching dispatch about multiple tables.
-command = cmdutil.command(commands.table)
+command = registrar.command(commands.table)
 
 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
 def debugancestor(ui, repo, *args):
--- a/mercurial/registrar.py	Sat May 13 17:53:55 2017 +0900
+++ b/mercurial/registrar.py	Sat Jan 09 23:07:20 2016 +0900
@@ -96,6 +96,51 @@
         """
         pass
 
+def command(table):
+    """Returns a function object to be used as a decorator for making commands.
+
+    This function receives a command table as its argument. The table should
+    be a dict.
+
+    The returned function can be used as a decorator for adding commands
+    to that command table. This function accepts multiple arguments to define
+    a command.
+
+    The first argument is the command name.
+
+    The options argument is an iterable of tuples defining command arguments.
+    See ``mercurial.fancyopts.fancyopts()`` for the format of each tuple.
+
+    The synopsis argument defines a short, one line summary of how to use the
+    command. This shows up in the help output.
+
+    The norepo argument defines whether the command does not require a
+    local repository. Most commands operate against a repository, thus the
+    default is False.
+
+    The optionalrepo argument defines whether the command optionally requires
+    a local repository.
+
+    The inferrepo argument defines whether to try to find a repository from the
+    command line arguments. If True, arguments will be examined for potential
+    repository locations. See ``findrepo()``. If a repository is found, it
+    will be used.
+    """
+    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)
+            return func
+        return decorator
+
+    return cmd
+
 class revsetpredicate(_funcregistrarbase):
     """Decorator to register revset predicate
 
--- a/tests/autodiff.py	Sat May 13 17:53:55 2017 +0900
+++ b/tests/autodiff.py	Sat Jan 09 23:07:20 2016 +0900
@@ -3,14 +3,14 @@
 from __future__ import absolute_import
 
 from mercurial import (
-    cmdutil,
     error,
     patch,
+    registrar,
     scmutil,
 )
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 
 @command('autodiff',
     [('', 'git', '', 'git upgrade mode (yes/no/auto/warn/abort)')],
--- a/tests/drawdag.py	Sat May 13 17:53:55 2017 +0900
+++ b/tests/drawdag.py	Sat Jan 09 23:07:20 2016 +0900
@@ -80,16 +80,16 @@
 
 from mercurial.i18n import _
 from mercurial import (
-    cmdutil,
     context,
     error,
     node,
+    registrar,
     scmutil,
     tags as tagsmod,
 )
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 
 _pipechars = '\\/+-|'
 _nonpipechars = ''.join(chr(i) for i in xrange(33, 127)
--- a/tests/fakemergerecord.py	Sat May 13 17:53:55 2017 +0900
+++ b/tests/fakemergerecord.py	Sat Jan 09 23:07:20 2016 +0900
@@ -5,12 +5,12 @@
 from __future__ import absolute_import
 
 from mercurial import (
-    cmdutil,
     merge,
+    registrar,
 )
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 
 @command('fakemergerecord',
          [('X', 'mandatory', None, 'add a fake mandatory record'),
--- a/tests/test-bad-extension.t	Sat May 13 17:53:55 2017 +0900
+++ b/tests/test-bad-extension.t	Sat Jan 09 23:07:20 2016 +0900
@@ -62,9 +62,9 @@
 names of extensions failed to load can be accessed via extensions.notloaded()
 
   $ cat <<EOF > showbadexts.py
-  > from mercurial import cmdutil, commands, extensions
+  > from mercurial import commands, extensions, registrar
   > cmdtable = {}
-  > command = cmdutil.command(cmdtable)
+  > command = registrar.command(cmdtable)
   > @command('showbadexts', norepo=True)
   > def showbadexts(ui, *pats, **opts):
   >     ui.write('BADEXTS: %s\n' % ' '.join(sorted(extensions.notloaded())))
--- a/tests/test-bundle2-format.t	Sat May 13 17:53:55 2017 +0900
+++ b/tests/test-bundle2-format.t	Sat Jan 09 23:07:20 2016 +0900
@@ -14,7 +14,6 @@
   > """
   > 
   > import sys, os, gc
-  > from mercurial import cmdutil
   > from mercurial import util
   > from mercurial import bundle2
   > from mercurial import scmutil
@@ -22,6 +21,7 @@
   > from mercurial import changegroup
   > from mercurial import error
   > from mercurial import obsolete
+  > from mercurial import registrar
   > 
   > 
   > try:
@@ -33,7 +33,7 @@
   >     pass
   > 
   > cmdtable = {}
-  > command = cmdutil.command(cmdtable)
+  > command = registrar.command(cmdtable)
   > 
   > ELEPHANTSSONG = """Patali Dirapata, Cromda Cromda Ripalo, Pata Pata, Ko Ko Ko
   > Bokoro Dipoulito, Rondi Rondi Pepino, Pata Pata, Ko Ko Ko
--- a/tests/test-chg.t	Sat May 13 17:53:55 2017 +0900
+++ b/tests/test-chg.t	Sat Jan 09 23:07:20 2016 +0900
@@ -105,9 +105,9 @@
 chg waits for pager if runcommand raises
 
   $ cat > $TESTTMP/crash.py <<EOF
-  > from mercurial import cmdutil
+  > from mercurial import registrar
   > cmdtable = {}
-  > command = cmdutil.command(cmdtable)
+  > command = registrar.command(cmdtable)
   > @command('crash')
   > def pagercrash(ui, repo, *pats, **opts):
   >     ui.write('going to crash\n')
--- a/tests/test-commandserver.t	Sat May 13 17:53:55 2017 +0900
+++ b/tests/test-commandserver.t	Sat Jan 09 23:07:20 2016 +0900
@@ -579,9 +579,9 @@
 
   $ cat <<EOF > dbgui.py
   > import os, sys
-  > from mercurial import cmdutil, commands
+  > from mercurial import commands, registrar
   > cmdtable = {}
-  > command = cmdutil.command(cmdtable)
+  > command = registrar.command(cmdtable)
   > @command("debuggetpass", norepo=True)
   > def debuggetpass(ui):
   >     ui.write("%s\\n" % ui.getpass())
--- a/tests/test-devel-warnings.t	Sat May 13 17:53:55 2017 +0900
+++ b/tests/test-devel-warnings.t	Sat Jan 09 23:07:20 2016 +0900
@@ -3,10 +3,10 @@
   > """A small extension that tests our developer warnings
   > """
   > 
-  > from mercurial import cmdutil, repair, util
+  > from mercurial import registrar, repair, util
   > 
   > cmdtable = {}
-  > command = cmdutil.command(cmdtable)
+  > command = registrar.command(cmdtable)
   > 
   > @command('buggylocking', [], '')
   > def buggylocking(ui, repo):
--- a/tests/test-encoding-align.t	Sat May 13 17:53:55 2017 +0900
+++ b/tests/test-encoding-align.t	Sat Jan 09 23:07:20 2016 +0900
@@ -16,9 +16,9 @@
   > f = file('l', 'w'); f.write(l); f.close()
   > # instant extension to show list of options
   > f = file('showoptlist.py', 'w'); f.write("""# encoding: utf-8
-  > from mercurial import cmdutil
+  > from mercurial import registrar
   > cmdtable = {}
-  > command = cmdutil.command(cmdtable)
+  > command = registrar.command(cmdtable)
   > 
   > @command('showoptlist',
   >     [('s', 'opt1', '', 'short width'  + ' %(s)s' * 8, '%(s)s'),
--- a/tests/test-encoding-textwrap.t	Sat May 13 17:53:55 2017 +0900
+++ b/tests/test-encoding-textwrap.t	Sat Jan 09 23:07:20 2016 +0900
@@ -6,10 +6,10 @@
 define commands to display help text
 
   $ cat << EOF > show.py
-  > from mercurial import cmdutil
+  > from mercurial import registrar
   > 
   > cmdtable = {}
-  > command = cmdutil.command(cmdtable)
+  > command = registrar.command(cmdtable)
   > 
   > # Japanese full-width characters:
   > @command('show_full_ja', [], '')
--- a/tests/test-extension.t	Sat May 13 17:53:55 2017 +0900
+++ b/tests/test-extension.t	Sat Jan 09 23:07:20 2016 +0900
@@ -2,9 +2,9 @@
 
   $ cat > foobar.py <<EOF
   > import os
-  > from mercurial import cmdutil, commands
+  > from mercurial import commands, registrar
   > cmdtable = {}
-  > command = cmdutil.command(cmdtable)
+  > command = registrar.command(cmdtable)
   > def uisetup(ui):
   >     ui.write("uisetup called\\n")
   >     ui.flush()
@@ -380,9 +380,9 @@
 
   $ cat > $TESTTMP/absextroot/__init__.py <<EOF
   > from __future__ import absolute_import
-  > from mercurial import cmdutil
+  > from mercurial import registrar
   > cmdtable = {}
-  > command = cmdutil.command(cmdtable)
+  > command = registrar.command(cmdtable)
   > 
   > # "absolute" and "relative" shouldn't be imported before actual
   > # command execution, because (1) they import same modules, and (2)
@@ -444,9 +444,9 @@
   > EOF
 
   $ cat > $TESTTMP/checkrelativity.py <<EOF
-  > from mercurial import cmdutil
+  > from mercurial import registrar
   > cmdtable = {}
-  > command = cmdutil.command(cmdtable)
+  > command = registrar.command(cmdtable)
   > 
   > # demand import avoids failure of importing notexist here
   > import extlibroot.lsub1.lsub2.notexist
@@ -487,9 +487,9 @@
   $ cat > debugextension.py <<EOF
   > '''only debugcommands
   > '''
-  > from mercurial import cmdutil
+  > from mercurial import registrar
   > cmdtable = {}
-  > command = cmdutil.command(cmdtable)
+  > command = registrar.command(cmdtable)
   > @command('debugfoobar', [], 'hg debugfoobar')
   > def debugfoobar(ui, repo, *args, **opts):
   >     "yet another debug command"
@@ -726,9 +726,9 @@
 Test help topic with same name as extension
 
   $ cat > multirevs.py <<EOF
-  > from mercurial import cmdutil, commands
+  > from mercurial import commands, registrar
   > cmdtable = {}
-  > command = cmdutil.command(cmdtable)
+  > command = registrar.command(cmdtable)
   > """multirevs extension
   > Big multi-line module docstring."""
   > @command('multirevs', [], 'ARG', norepo=True)
@@ -803,9 +803,9 @@
   > This is an awesome 'dodo' extension. It does nothing and
   > writes 'Foo foo'
   > """
-  > from mercurial import cmdutil, commands
+  > from mercurial import commands, registrar
   > cmdtable = {}
-  > command = cmdutil.command(cmdtable)
+  > command = registrar.command(cmdtable)
   > @command('dodo', [], 'hg dodo')
   > def dodo(ui, *args, **kwargs):
   >     """Does nothing"""
@@ -914,9 +914,9 @@
   > This is an awesome 'dudu' extension. It does something and
   > also writes 'Beep beep'
   > """
-  > from mercurial import cmdutil, commands
+  > from mercurial import commands, registrar
   > cmdtable = {}
-  > command = cmdutil.command(cmdtable)
+  > command = registrar.command(cmdtable)
   > @command('something', [], 'hg something')
   > def something(ui, *args, **kwargs):
   >     """Does something"""
@@ -1157,9 +1157,9 @@
   [255]
 
   $ cat > throw.py <<EOF
-  > from mercurial import cmdutil, commands, util
+  > from mercurial import commands, registrar, util
   > cmdtable = {}
-  > command = cmdutil.command(cmdtable)
+  > command = registrar.command(cmdtable)
   > class Bogon(Exception): pass
   > @command('throw', [], 'hg throw', norepo=True)
   > def throw(ui, **opts):
--- a/tests/test-help.t	Sat May 13 17:53:55 2017 +0900
+++ b/tests/test-help.t	Sat Jan 09 23:07:20 2016 +0900
@@ -680,10 +680,10 @@
 
   $ cat > helpext.py <<EOF
   > import os
-  > from mercurial import cmdutil, commands
+  > from mercurial import commands, registrar
   > 
   > cmdtable = {}
-  > command = cmdutil.command(cmdtable)
+  > command = registrar.command(cmdtable)
   > 
   > @command('nohelp',
   >     [('', 'longdesc', 3, 'x'*90),
--- a/tests/test-lock-badness.t	Sat May 13 17:53:55 2017 +0900
+++ b/tests/test-lock-badness.t	Sat Jan 09 23:07:20 2016 +0900
@@ -14,10 +14,10 @@
 Test that raising an exception in the release function doesn't cause the lock to choke
 
   $ cat > testlock.py << EOF
-  > from mercurial import cmdutil, error, error
+  > from mercurial import error, registrar
   > 
   > cmdtable = {}
-  > command = cmdutil.command(cmdtable)
+  > command = registrar.command(cmdtable)
   > 
   > def acquiretestlock(repo, releaseexc):
   >     def unlock():
--- a/tests/test-logtoprocess.t	Sat May 13 17:53:55 2017 +0900
+++ b/tests/test-logtoprocess.t	Sat Jan 09 23:07:20 2016 +0900
@@ -6,10 +6,10 @@
 
   $ hg init
   $ cat > $TESTTMP/foocommand.py << EOF
-  > from mercurial import cmdutil
+  > from mercurial import registrar
   > from time import sleep
   > cmdtable = {}
-  > command = cmdutil.command(cmdtable)
+  > command = registrar.command(cmdtable)
   > @command('foo', [])
   > def foo(ui, repo):
   >     ui.log('foo', 'a message: %(bar)s\n', bar='spam')
--- a/tests/test-obsolete.t	Sat May 13 17:53:55 2017 +0900
+++ b/tests/test-obsolete.t	Sat Jan 09 23:07:20 2016 +0900
@@ -1065,11 +1065,11 @@
 Test heads computation on pending index changes with obsolescence markers
   $ cd ..
   $ cat >$TESTTMP/test_extension.py  << EOF
-  > from mercurial import cmdutil
+  > from mercurial import cmdutil, registrar
   > from mercurial.i18n import _
   > 
   > cmdtable = {}
-  > command = cmdutil.command(cmdtable)
+  > command = registrar.command(cmdtable)
   > @command("amendtransient",[], _('hg amendtransient [rev]'))
   > def amend(ui, repo, *pats, **opts):
   >   def commitfunc(ui, repo, message, match, opts):
--- a/tests/test-pager-legacy.t	Sat May 13 17:53:55 2017 +0900
+++ b/tests/test-pager-legacy.t	Sat Jan 09 23:07:20 2016 +0900
@@ -214,9 +214,9 @@
 Pager should not override the exit code of other commands
 
   $ cat >> $TESTTMP/fortytwo.py <<'EOF'
-  > from mercurial import cmdutil, commands
+  > from mercurial import registrar, commands
   > cmdtable = {}
-  > command = cmdutil.command(cmdtable)
+  > command = registrar.command(cmdtable)
   > @command('fortytwo', [], 'fortytwo', norepo=True)
   > def fortytwo(ui, *opts):
   >     ui.write('42\n')
--- a/tests/test-pager.t	Sat May 13 17:53:55 2017 +0900
+++ b/tests/test-pager.t	Sat Jan 09 23:07:20 2016 +0900
@@ -223,9 +223,9 @@
 Pager should not override the exit code of other commands
 
   $ cat >> $TESTTMP/fortytwo.py <<'EOF'
-  > from mercurial import cmdutil, commands
+  > from mercurial import commands, registrar
   > cmdtable = {}
-  > command = cmdutil.command(cmdtable)
+  > command = registrar.command(cmdtable)
   > @command('fortytwo', [], 'fortytwo', norepo=True)
   > def fortytwo(ui, *opts):
   >     ui.write('42\n')
--- a/tests/test-profile.t	Sat May 13 17:53:55 2017 +0900
+++ b/tests/test-profile.t	Sat Jan 09 23:07:20 2016 +0900
@@ -51,9 +51,9 @@
 
   $ cat >> sleepext.py << EOF
   > import time
-  > from mercurial import cmdutil, commands
+  > from mercurial import registrar, commands
   > cmdtable = {}
-  > command = cmdutil.command(cmdtable)
+  > command = registrar.command(cmdtable)
   > @command('sleep', [], 'hg sleep')
   > def sleep(ui, *args, **kwargs):
   >     time.sleep(0.1)
--- a/tests/test-progress.t	Sat May 13 17:53:55 2017 +0900
+++ b/tests/test-progress.t	Sat Jan 09 23:07:20 2016 +0900
@@ -1,10 +1,10 @@
 
   $ cat > loop.py <<EOF
-  > from mercurial import cmdutil, commands
+  > from mercurial import commands, registrar
   > import time
   > 
   > cmdtable = {}
-  > command = cmdutil.command(cmdtable)
+  > command = registrar.command(cmdtable)
   > 
   > class incrementingtime(object):
   >     def __init__(self):
--- a/tests/test-rebuildstate.t	Sat May 13 17:53:55 2017 +0900
+++ b/tests/test-rebuildstate.t	Sat Jan 09 23:07:20 2016 +0900
@@ -1,8 +1,8 @@
 
   $ cat > adddrop.py <<EOF
-  > from mercurial import cmdutil
+  > from mercurial import registrar
   > cmdtable = {}
-  > command = cmdutil.command(cmdtable)
+  > command = registrar.command(cmdtable)
   > @command('debugadddrop',
   >   [('', 'drop', False, 'drop file from dirstate', 'FILE'),
   >    ('', 'normal-lookup', False, 'add file to dirstate', 'FILE')],
--- a/tests/test-resolve.t	Sat May 13 17:53:55 2017 +0900
+++ b/tests/test-resolve.t	Sat Jan 09 23:07:20 2016 +0900
@@ -85,9 +85,9 @@
 
   $ cat > $TESTTMP/markdriver.py << EOF
   > '''mark and unmark files as driver-resolved'''
-  > from mercurial import cmdutil, merge, scmutil
+  > from mercurial import merge, registrar, scmutil
   > cmdtable = {}
-  > command = cmdutil.command(cmdtable)
+  > command = registrar.command(cmdtable)
   > @command('markdriver',
   >   [('u', 'unmark', None, '')],
   >   'FILE...')
--- a/tests/test-revset.t	Sat May 13 17:53:55 2017 +0900
+++ b/tests/test-revset.t	Sat Jan 09 23:07:20 2016 +0900
@@ -37,14 +37,14 @@
   $ cat <<EOF > debugrevlistspec.py
   > from __future__ import absolute_import
   > from mercurial import (
-  >     cmdutil,
   >     node as nodemod,
+  >     registrar,
   >     revset,
   >     revsetlang,
   >     smartset,
   > )
   > cmdtable = {}
-  > command = cmdutil.command(cmdtable)
+  > command = registrar.command(cmdtable)
   > @command('debugrevlistspec',
   >     [('', 'optimize', None, 'print parsed tree after optimizing'),
   >      ('', 'bin', None, 'unhexlify arguments')])
--- a/tests/test-worker.t	Sat May 13 17:53:55 2017 +0900
+++ b/tests/test-worker.t	Sat Jan 09 23:07:20 2016 +0900
@@ -4,8 +4,8 @@
   > from __future__ import absolute_import, print_function
   > import time
   > from mercurial import (
-  >     cmdutil,
   >     error,
+  >     registrar,
   >     ui as uimod,
   >     worker,
   > )
@@ -30,7 +30,7 @@
   >     'runme': runme,
   > }
   > cmdtable = {}
-  > command = cmdutil.command(cmdtable)
+  > command = registrar.command(cmdtable)
   > @command('test', [], 'hg test [COST] [FUNC]')
   > def t(ui, repo, cost=1.0, func='runme'):
   >     cost = float(cost)