Patchwork [15,of,35] commands: add norepo argument to command decorator

login
register
mail settings
Submitter Gregory Szorc
Date May 5, 2014, 5:51 a.m.
Message ID <28363b7aa15d67a3136a.1399269080@vm-ubuntu-main.gateway.sonic.net>
Download mbox | patch
Permalink /patch/4606/
State Accepted
Commit 75a96326cecb47fa7281456827b53e043f1d1298
Headers show

Comments

Gregory Szorc - May 5, 2014, 5:51 a.m.
# HG changeset patch
# User Gregory Szorc <gregory.szorc@gmail.com>
# Date 1399262305 25200
#      Sun May 04 20:58:25 2014 -0700
# Branch stable
# Node ID 28363b7aa15d67a3136a642beb678366d5fdecf1
# Parent  ca7af5ec72526886c534970251a47e3f706f1203
commands: add norepo argument to command decorator

Since decorators are evaluated at module load time and since the
@command decorator imports commands, the norepo variable (along with
its friends) may not be declared yet. These variables are now declared
before @command usage to ensure they are present.
Pierre-Yves David - May 8, 2014, 7:20 p.m.
On 05/04/2014 10:51 PM, Gregory Szorc wrote:
> # HG changeset patch
> # User Gregory Szorc <gregory.szorc@gmail.com>
> # Date 1399262305 25200
> #      Sun May 04 20:58:25 2014 -0700
> # Branch stable
> # Node ID 28363b7aa15d67a3136a642beb678366d5fdecf1
> # Parent  ca7af5ec72526886c534970251a47e3f706f1203
> commands: add norepo argument to command decorator
>
> Since decorators are evaluated at module load time and since the
> @command decorator imports commands, the norepo variable (along with
> its friends) may not be declared yet. These variables are now declared
> before @command usage to ensure they are present.
>
> diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
> --- a/mercurial/cmdutil.py
> +++ b/mercurial/cmdutil.py
> @@ -2425,24 +2425,33 @@ def command(table):
>
>       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.
>       """
> -
> -    def cmd(name, options=(), synopsis=None):
> +    def cmd(name, options=(), synopsis=None, norepo=False):
>           def decorator(func):
>               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))
> +

Meh, we could move it elsewhere to prevent the cycle. But that would 
break BC and and I'm not fan of gratuitously breaking BC for basic 
extension feature user.

(This mean I'm not fan of this hunk, but I've no better idea yet)

> --- a/mercurial/commands.py
> +++ b/mercurial/commands.py
> @@ -21,16 +21,23 @@ import dagparser, context, simplemerge,
>   import random
>   import setdiscovery, treediscovery, dagutil, pvec, localrepo
>   import phases, obsolete, exchange
>
>   table = {}
>
>   command = cmdutil.command(table)
>
> +norepo = ("clone init version help debugcommands debugcomplete"
> +          " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
> +          " debugknown debuggetbundle debugbundle")
> +optionalrepo = ("identify paths serve config showconfig debugancestor debugdag"
> +                " debugdata debugindex debugindexdot debugrevlog")
> +inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
> +             " remove resolve status debugwalk")
>   # common command options
>
>   globalopts = [
>       ('R', 'repository', '',
>        _('repository root directory or name of overlay bundle file'),
>        _('REPO')),
>       ('', 'cwd', '',
>        _('change working directory'), _('DIR')),
> @@ -5909,16 +5916,8 @@ def version_(ui):
>                % util.version())
>       ui.status(_(
>           "(see http://mercurial.selenic.com for more information)\n"
>           "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
>           "This is free software; see the source for copying conditions. "
>           "There is NO\nwarranty; "
>           "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
>       ))
> -
> -norepo = ("clone init version help debugcommands debugcomplete"
> -          " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
> -          " debugknown debuggetbundle debugbundle")
> -optionalrepo = ("identify paths serve config showconfig debugancestor debugdag"
> -                " debugdata debugindex debugindexdot debugrevlog")
> -inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
> -             " remove resolve status debugwalk")

Could have been in another changeset.

Patch

diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -2425,24 +2425,33 @@  def command(table):
 
     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.
     """
-
-    def cmd(name, options=(), synopsis=None):
+    def cmd(name, options=(), synopsis=None, norepo=False):
         def decorator(func):
             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))
+
             return func
         return decorator
 
     return cmd
 
 # a list of (ui, repo, otherpeer, opts, missing) functions called by
 # commands.outgoing.  "missing" is "missing" of the result of
 # "findcommonoutgoing()"
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -21,16 +21,23 @@  import dagparser, context, simplemerge, 
 import random
 import setdiscovery, treediscovery, dagutil, pvec, localrepo
 import phases, obsolete, exchange
 
 table = {}
 
 command = cmdutil.command(table)
 
+norepo = ("clone init version help debugcommands debugcomplete"
+          " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
+          " debugknown debuggetbundle debugbundle")
+optionalrepo = ("identify paths serve config showconfig debugancestor debugdag"
+                " debugdata debugindex debugindexdot debugrevlog")
+inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
+             " remove resolve status debugwalk")
 # common command options
 
 globalopts = [
     ('R', 'repository', '',
      _('repository root directory or name of overlay bundle file'),
      _('REPO')),
     ('', 'cwd', '',
      _('change working directory'), _('DIR')),
@@ -5909,16 +5916,8 @@  def version_(ui):
              % util.version())
     ui.status(_(
         "(see http://mercurial.selenic.com for more information)\n"
         "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
         "This is free software; see the source for copying conditions. "
         "There is NO\nwarranty; "
         "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
     ))
-
-norepo = ("clone init version help debugcommands debugcomplete"
-          " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
-          " debugknown debuggetbundle debugbundle")
-optionalrepo = ("identify paths serve config showconfig debugancestor debugdag"
-                " debugdata debugindex debugindexdot debugrevlog")
-inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
-             " remove resolve status debugwalk")