Patchwork [2,of,8,V2] registrar: move cmdutil.command to registrar module (API)

login
register
mail settings
Submitter Yuya Nishihara
Date May 19, 2017, 3:25 p.m.
Message ID <cda425df1285840b3042.1495207512@mimosa>
Download mbox | patch
Permalink /patch/20721/
State Accepted
Headers show

Comments

Yuya Nishihara - May 19, 2017, 3:25 p.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1452348440 -32400
#      Sat Jan 09 23:07:20 2016 +0900
# Node ID cda425df1285840b30421dfa1959a6757855137a
# Parent  329d4934ca617e7044d1e5be2daa664043a97078
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.

Patch

diff --git a/contrib/debugshell.py b/contrib/debugshell.py
--- a/contrib/debugshell.py
+++ b/contrib/debugshell.py
@@ -6,12 +6,12 @@  import code
 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 = {
diff --git a/contrib/perf.py b/contrib/perf.py
--- a/contrib/perf.py
+++ b/contrib/perf.py
@@ -49,6 +49,11 @@  try:
 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 @@  cmdtable = {}
 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]:
diff --git a/contrib/synthrepo.py b/contrib/synthrepo.py
--- a/contrib/synthrepo.py
+++ b/contrib/synthrepo.py
@@ -53,11 +53,11 @@  from mercurial.node import (
     short,
 )
 from mercurial import (
-    cmdutil,
     context,
     error,
     hg,
     patch,
+    registrar,
     scmutil,
     util,
 )
@@ -69,7 +69,7 @@  from mercurial import (
 testedwith = 'ships-with-hg-core'
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 
 newfile = {'new fi', 'rename', 'copy f', 'copy t'}
 
diff --git a/hgext/blackbox.py b/hgext/blackbox.py
--- a/hgext/blackbox.py
+++ b/hgext/blackbox.py
@@ -44,13 +44,13 @@  from mercurial.i18n import _
 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
diff --git a/hgext/censor.py b/hgext/censor.py
--- a/hgext/censor.py
+++ b/hgext/censor.py
@@ -31,17 +31,17 @@  from mercurial.i18n import _
 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
diff --git a/hgext/children.py b/hgext/children.py
--- a/hgext/children.py
+++ b/hgext/children.py
@@ -20,12 +20,13 @@  from mercurial.i18n import _
 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
diff --git a/hgext/churn.py b/hgext/churn.py
--- a/hgext/churn.py
+++ b/hgext/churn.py
@@ -20,12 +20,13 @@  from mercurial import (
     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
diff --git a/hgext/convert/__init__.py b/hgext/convert/__init__.py
--- a/hgext/convert/__init__.py
+++ b/hgext/convert/__init__.py
@@ -11,7 +11,6 @@  from __future__ import absolute_import
 
 from mercurial.i18n import _
 from mercurial import (
-    cmdutil,
     registrar,
 )
 
@@ -22,7 +21,7 @@  from . import (
 )
 
 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
diff --git a/hgext/extdiff.py b/hgext/extdiff.py
--- a/hgext/extdiff.py
+++ b/hgext/extdiff.py
@@ -78,12 +78,13 @@  from mercurial import (
     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
diff --git a/hgext/fetch.py b/hgext/fetch.py
--- a/hgext/fetch.py
+++ b/hgext/fetch.py
@@ -20,12 +20,13 @@  from mercurial import (
     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
diff --git a/hgext/gpg.py b/hgext/gpg.py
--- a/hgext/gpg.py
+++ b/hgext/gpg.py
@@ -19,11 +19,12 @@  from mercurial import (
     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
diff --git a/hgext/graphlog.py b/hgext/graphlog.py
--- a/hgext/graphlog.py
+++ b/hgext/graphlog.py
@@ -19,12 +19,12 @@  from __future__ import absolute_import
 
 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
diff --git a/hgext/hgk.py b/hgext/hgk.py
--- a/hgext/hgk.py
+++ b/hgext/hgk.py
@@ -45,15 +45,15 @@  from mercurial.node import (
     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
diff --git a/hgext/histedit.py b/hgext/histedit.py
--- a/hgext/histedit.py
+++ b/hgext/histedit.py
@@ -201,6 +201,7 @@  from mercurial import (
     mergeutil,
     node,
     obsolete,
+    registrar,
     repair,
     scmutil,
     util,
@@ -209,7 +210,7 @@  from mercurial import (
 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
diff --git a/hgext/journal.py b/hgext/journal.py
--- a/hgext/journal.py
+++ b/hgext/journal.py
@@ -31,13 +31,14 @@  from mercurial import (
     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
diff --git a/hgext/keyword.py b/hgext/keyword.py
--- a/hgext/keyword.py
+++ b/hgext/keyword.py
@@ -111,7 +111,7 @@  from mercurial import (
 )
 
 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
diff --git a/hgext/largefiles/lfcommands.py b/hgext/largefiles/lfcommands.py
--- a/hgext/largefiles/lfcommands.py
+++ b/hgext/largefiles/lfcommands.py
@@ -25,6 +25,7 @@  from mercurial import (
     lock,
     match as matchmod,
     node,
+    registrar,
     scmutil,
     util,
 )
@@ -44,7 +45,7 @@  release = lock.release
 # -- Commands ----------------------------------------------------------
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 
 @command('lfconvert',
     [('s', 'size', '',
diff --git a/hgext/mq.py b/hgext/mq.py
--- a/hgext/mq.py
+++ b/hgext/mq.py
@@ -101,7 +101,7 @@  release = lockmod.release
 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
diff --git a/hgext/patchbomb.py b/hgext/patchbomb.py
--- a/hgext/patchbomb.py
+++ b/hgext/patchbomb.py
@@ -89,6 +89,7 @@  from mercurial import (
     mail,
     node as nodemod,
     patch,
+    registrar,
     scmutil,
     templater,
     util,
@@ -96,7 +97,7 @@  from mercurial import (
 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
diff --git a/hgext/purge.py b/hgext/purge.py
--- a/hgext/purge.py
+++ b/hgext/purge.py
@@ -29,15 +29,15 @@  import os
 
 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
diff --git a/hgext/rebase.py b/hgext/rebase.py
--- a/hgext/rebase.py
+++ b/hgext/rebase.py
@@ -68,7 +68,7 @@  revpruned = -5
 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
diff --git a/hgext/record.py b/hgext/record.py
--- a/hgext/record.py
+++ b/hgext/record.py
@@ -18,10 +18,11 @@  from mercurial import (
     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
diff --git a/hgext/relink.py b/hgext/relink.py
--- a/hgext/relink.py
+++ b/hgext/relink.py
@@ -13,14 +13,14 @@  import stat
 
 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
diff --git a/hgext/schemes.py b/hgext/schemes.py
--- a/hgext/schemes.py
+++ b/hgext/schemes.py
@@ -46,17 +46,17 @@  import re
 
 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
diff --git a/hgext/share.py b/hgext/share.py
--- a/hgext/share.py
+++ b/hgext/share.py
@@ -43,11 +43,11 @@  import errno
 from mercurial.i18n import _
 from mercurial import (
     bookmarks,
-    cmdutil,
     commands,
     error,
     extensions,
     hg,
+    registrar,
     txnutil,
     util,
 )
@@ -56,7 +56,7 @@  repository = hg.repository
 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
diff --git a/hgext/shelve.py b/hgext/shelve.py
--- a/hgext/shelve.py
+++ b/hgext/shelve.py
@@ -43,6 +43,7 @@  from mercurial import (
     node as nodemod,
     patch,
     phases,
+    registrar,
     repair,
     scmutil,
     templatefilters,
@@ -55,7 +56,7 @@  from . import (
 )
 
 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
diff --git a/hgext/show.py b/hgext/show.py
--- a/hgext/show.py
+++ b/hgext/show.py
@@ -34,7 +34,7 @@  from mercurial import (
 testedwith = 'ships-with-hg-core'
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = registrar.command(cmdtable)
 revsetpredicate = registrar.revsetpredicate()
 
 class showcmdfunc(registrar._funcregistrarbase):
diff --git a/hgext/strip.py b/hgext/strip.py
--- a/hgext/strip.py
+++ b/hgext/strip.py
@@ -14,6 +14,7 @@  from mercurial import (
     lock as lockmod,
     merge,
     node as nodemod,
+    registrar,
     repair,
     scmutil,
     util,
@@ -22,7 +23,7 @@  nullid = nodemod.nullid
 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
diff --git a/hgext/transplant.py b/hgext/transplant.py
--- a/hgext/transplant.py
+++ b/hgext/transplant.py
@@ -42,7 +42,7 @@  class TransplantError(error.Abort):
     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
diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -38,6 +38,7 @@  from . import (
     pathutil,
     phases,
     pycompat,
+    registrar,
     repair,
     revlog,
     revset,
@@ -3334,50 +3335,7 @@  def _performrevert(repo, parents, ctx, a
         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
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -44,6 +44,7 @@  from . import (
     phases,
     pycompat,
     rcutil,
+    registrar,
     revsetlang,
     scmutil,
     server,
@@ -59,7 +60,7 @@  release = lockmod.release
 
 table = {}
 
-command = cmdutil.command(table)
+command = registrar.command(table)
 
 # label constants
 # until 3.5, bookmarks.current was the advertised name, not
diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py
--- a/mercurial/debugcommands.py
+++ b/mercurial/debugcommands.py
@@ -51,6 +51,7 @@  from . import (
     policy,
     pvec,
     pycompat,
+    registrar,
     repair,
     revlog,
     revset,
@@ -72,7 +73,7 @@  release = lockmod.release
 
 # 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):
diff --git a/mercurial/registrar.py b/mercurial/registrar.py
--- a/mercurial/registrar.py
+++ b/mercurial/registrar.py
@@ -96,6 +96,51 @@  class _funcregistrarbase(object):
         """
         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
 
diff --git a/tests/autodiff.py b/tests/autodiff.py
--- a/tests/autodiff.py
+++ b/tests/autodiff.py
@@ -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)')],
diff --git a/tests/drawdag.py b/tests/drawdag.py
--- a/tests/drawdag.py
+++ b/tests/drawdag.py
@@ -80,16 +80,16 @@  import itertools
 
 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)
diff --git a/tests/fakemergerecord.py b/tests/fakemergerecord.py
--- a/tests/fakemergerecord.py
+++ b/tests/fakemergerecord.py
@@ -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'),
diff --git a/tests/test-bad-extension.t b/tests/test-bad-extension.t
--- a/tests/test-bad-extension.t
+++ b/tests/test-bad-extension.t
@@ -62,9 +62,9 @@  show traceback
 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())))
diff --git a/tests/test-bundle2-format.t b/tests/test-bundle2-format.t
--- a/tests/test-bundle2-format.t
+++ b/tests/test-bundle2-format.t
@@ -14,7 +14,6 @@  Create an extension to test bundle2 API
   > """
   > 
   > import sys, os, gc
-  > from mercurial import cmdutil
   > from mercurial import util
   > from mercurial import bundle2
   > from mercurial import scmutil
@@ -22,6 +21,7 @@  Create an extension to test bundle2 API
   > from mercurial import changegroup
   > from mercurial import error
   > from mercurial import obsolete
+  > from mercurial import registrar
   > 
   > 
   > try:
@@ -33,7 +33,7 @@  Create an extension to test bundle2 API
   >     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
diff --git a/tests/test-chg.t b/tests/test-chg.t
--- a/tests/test-chg.t
+++ b/tests/test-chg.t
@@ -105,9 +105,9 @@  pager should be enabled if the attached 
 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')
diff --git a/tests/test-commandserver.t b/tests/test-commandserver.t
--- a/tests/test-commandserver.t
+++ b/tests/test-commandserver.t
@@ -579,9 +579,9 @@  changelog and manifest would have invali
 
   $ 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())
diff --git a/tests/test-devel-warnings.t b/tests/test-devel-warnings.t
--- a/tests/test-devel-warnings.t
+++ b/tests/test-devel-warnings.t
@@ -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):
diff --git a/tests/test-encoding-align.t b/tests/test-encoding-align.t
--- a/tests/test-encoding-align.t
+++ b/tests/test-encoding-align.t
@@ -16,9 +16,9 @@  Test alignment of multibyte characters
   > 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'),
diff --git a/tests/test-encoding-textwrap.t b/tests/test-encoding-textwrap.t
--- a/tests/test-encoding-textwrap.t
+++ b/tests/test-encoding-textwrap.t
@@ -6,10 +6,10 @@  Test text wrapping for multibyte charact
 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', [], '')
diff --git a/tests/test-extension.t b/tests/test-extension.t
--- a/tests/test-extension.t
+++ b/tests/test-extension.t
@@ -2,9 +2,9 @@  Test basic extension support
 
   $ 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 @@  Setup main procedure of extension.
 
   $ 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 @@  See also issue5208 for detail about exam
   > 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 @@  hide outer repo
   $ 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 @@  Extension module help vs command help:
 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 @@  along with extension help itself
   > 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 @@  along with extension help
   > 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 @@  Broken disabled extension and command:
   [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):
diff --git a/tests/test-help.t b/tests/test-help.t
--- a/tests/test-help.t
+++ b/tests/test-help.t
@@ -680,10 +680,10 @@  this is a section and erroring out weird
 
   $ 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),
diff --git a/tests/test-lock-badness.t b/tests/test-lock-badness.t
--- a/tests/test-lock-badness.t
+++ b/tests/test-lock-badness.t
@@ -14,10 +14,10 @@  Prepare
 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():
diff --git a/tests/test-logtoprocess.t b/tests/test-logtoprocess.t
--- a/tests/test-logtoprocess.t
+++ b/tests/test-logtoprocess.t
@@ -6,10 +6,10 @@  Test if logtoprocess correctly captures 
 
   $ 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')
diff --git a/tests/test-obsolete.t b/tests/test-obsolete.t
--- a/tests/test-obsolete.t
+++ b/tests/test-obsolete.t
@@ -1065,11 +1065,11 @@  Test issue 4506
 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):
diff --git a/tests/test-pager-legacy.t b/tests/test-pager-legacy.t
--- a/tests/test-pager-legacy.t
+++ b/tests/test-pager-legacy.t
@@ -214,9 +214,9 @@  pager is globally set to off using a fla
 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')
diff --git a/tests/test-pager.t b/tests/test-pager.t
--- a/tests/test-pager.t
+++ b/tests/test-pager.t
@@ -223,9 +223,9 @@  pager is globally set to off using a fla
 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')
diff --git a/tests/test-profile.t b/tests/test-profile.t
--- a/tests/test-profile.t
+++ b/tests/test-profile.t
@@ -51,9 +51,9 @@  Install an extension that can sleep and 
 
   $ 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)
diff --git a/tests/test-progress.t b/tests/test-progress.t
--- a/tests/test-progress.t
+++ b/tests/test-progress.t
@@ -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):
diff --git a/tests/test-rebuildstate.t b/tests/test-rebuildstate.t
--- a/tests/test-rebuildstate.t
+++ b/tests/test-rebuildstate.t
@@ -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')],
diff --git a/tests/test-resolve.t b/tests/test-resolve.t
--- a/tests/test-resolve.t
+++ b/tests/test-resolve.t
@@ -85,9 +85,9 @@  don't allow marking or unmarking driver-
 
   $ 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...')
diff --git a/tests/test-revset.t b/tests/test-revset.t
--- a/tests/test-revset.t
+++ b/tests/test-revset.t
@@ -37,14 +37,14 @@  these predicates use '\0' as a separator
   $ 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')])
diff --git a/tests/test-worker.t b/tests/test-worker.t
--- a/tests/test-worker.t
+++ b/tests/test-worker.t
@@ -4,8 +4,8 @@  Test UI worker interaction
   > from __future__ import absolute_import, print_function
   > import time
   > from mercurial import (
-  >     cmdutil,
   >     error,
+  >     registrar,
   >     ui as uimod,
   >     worker,
   > )
@@ -30,7 +30,7 @@  Test UI worker interaction
   >     '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)