--- a/doc/hgrc.5.txt Sat May 30 19:37:01 2009 +0200
+++ b/doc/hgrc.5.txt Sat May 30 11:32:23 2009 -0700
@@ -100,6 +100,29 @@
Mercurial "hgrc" file, the purpose of each section, its possible
keys, and their possible values.
+[[alias]]
+alias::
+ Defines command aliases.
+ Aliases allow you to define your own commands in terms of other
+ commands (or aliases), optionally including arguments.
++
+Alias definitions consist of lines of the form:
++
+ <alias> = <command> [<argument]...
++
+For example, this definition:
++
+ latest = log --limit 5
++
+creates a new command `latest` that shows only the five most recent
+changesets. You can define subsequent aliases using earlier ones:
++
+ stable5 = latest -b stable
++
+*Note*: It is possible to create aliases with the same names as
+existing commands, which will then override the original
+definitions. This is almost always a bad idea!
+
[[auth]]
auth::
Authentication credentials for HTTP authentication.
--- a/hgext/alias.py Sat May 30 19:37:01 2009 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-# Copyright (C) 2007 Brendan Cully <brendan@kublai.com>
-# This file is published under the GNU GPL.
-
-'''allow user-defined command aliases
-
-To use, create entries in your hgrc of the form
-
-[alias]
-mycmd = cmd --args
-'''
-
-from mercurial.i18n import _
-from mercurial import commands, cmdutil, error
-
-cmdtable = {}
-
-class RecursiveCommand(Exception): pass
-
-class lazycommand(object):
- '''defer command lookup until needed, so that extensions loaded
- after alias can be aliased'''
- def __init__(self, ui, name, target):
- self._ui = ui
- self._name = name
- self._target = target
- self._cmd = None
-
- def __len__(self):
- self._resolve()
- return len(self._cmd)
-
- def __getitem__(self, key):
- self._resolve()
- return self._cmd[key]
-
- def __iter__(self):
- self._resolve()
- return self._cmd.__iter__()
-
- def _resolve(self):
- if self._cmd is not None:
- return
-
- try:
- self._cmd = cmdutil.findcmd(self._target, commands.table, False)[1]
- if self._cmd == self:
- raise RecursiveCommand()
- if self._target in commands.norepo.split(' '):
- commands.norepo += ' %s' % self._name
- return
- except error.UnknownCommand:
- msg = _('*** [alias] %s: command %s is unknown') % \
- (self._name, self._target)
- except error.AmbiguousCommand:
- msg = _('*** [alias] %s: command %s is ambiguous') % \
- (self._name, self._target)
- except RecursiveCommand:
- msg = _('*** [alias] %s: circular dependency on %s') % \
- (self._name, self._target)
- def nocmd(*args, **opts):
- self._ui.warn(msg + '\n')
- return 1
- nocmd.__doc__ = msg
- self._cmd = (nocmd, [], '')
- commands.norepo += ' %s' % self._name
-
-def uisetup(ui):
- for cmd, target in ui.configitems('alias'):
- if not target:
- ui.warn(_('*** [alias] %s: no definition\n') % cmd)
- continue
- args = target.split(' ', 1)
- tcmd = args.pop(0)
- if args:
- args = args[0]
- defaults = ui.config('defaults', cmd)
- if defaults:
- args = ' '.join((args, defaults))
- ui.setconfig('defaults', cmd, args)
- cmdtable[cmd] = lazycommand(ui, cmd, tcmd)
--- a/mercurial/dispatch.py Sat May 30 19:37:01 2009 +0200
+++ b/mercurial/dispatch.py Sat May 30 11:32:23 2009 -0700
@@ -161,6 +161,74 @@
return p
+def aliasargs(fn):
+ if hasattr(fn, 'args'):
+ return fn.args
+ return []
+
+class cmdalias(object):
+ def __init__(self, name, definition, cmdtable):
+ self.name = name
+ self.definition = definition
+ self.args = []
+ self.opts = []
+ self.help = ''
+ self.norepo = True
+
+ try:
+ cmdutil.findcmd(self.name, cmdtable, True)
+ self.shadows = True
+ except error.UnknownCommand:
+ self.shadows = False
+
+ if not self.definition:
+ def fn(ui, *args):
+ ui.warn(_("no definition for alias '%s'\n") % self.name)
+ return 1
+ self.fn = fn
+
+ return
+
+ args = shlex.split(self.definition)
+ cmd = args.pop(0)
+ opts = []
+ help = ''
+
+ try:
+ self.fn, self.opts, self.help = cmdutil.findcmd(cmd, cmdtable, False)[1]
+ self.args = aliasargs(self.fn) + args
+ if cmd not in commands.norepo.split(' '):
+ self.norepo = False
+ except error.UnknownCommand:
+ def fn(ui, *args):
+ ui.warn(_("alias '%s' resolves to unknown command '%s'\n") \
+ % (self.name, cmd))
+ return 1
+ self.fn = fn
+ except error.AmbiguousCommand:
+ def fn(ui, *args):
+ ui.warn(_("alias '%s' resolves to ambiguous command '%s'\n") \
+ % (self.name, cmd))
+ return 1
+ self.fn = fn
+
+ def __call__(self, ui, *args, **opts):
+ if self.shadows:
+ ui.debug(_("alias '%s' shadows command\n") % self.name)
+
+ return self.fn(ui, *args, **opts)
+
+def addaliases(ui, cmdtable):
+ # aliases are processed after extensions have been loaded, so they
+ # may use extension commands. Aliases can also use other alias definitions,
+ # but only if they have been defined prior to the current definition.
+ for alias, definition in ui.configitems('alias'):
+ aliasdef = cmdalias(alias, definition, cmdtable)
+
+ cmdtable[alias] = (aliasdef, aliasdef.opts, aliasdef.help)
+ if aliasdef.norepo:
+ commands.norepo += ' %s' % alias
+
def _parse(ui, args):
options = {}
cmdoptions = {}
@@ -175,6 +243,7 @@
aliases, i = cmdutil.findcmd(cmd, commands.table,
ui.config("ui", "strict"))
cmd = aliases[0]
+ args = aliasargs(i[0]) + args
defaults = ui.config("defaults", cmd)
if defaults:
args = shlex.split(defaults) + args
@@ -301,6 +370,9 @@
% (name, " ".join(overrides)))
commands.table.update(cmdtable)
_loaded.add(name)
+
+ addaliases(lui, commands.table)
+
# check for fallback encoding
fallback = lui.config('ui', 'fallbackencoding')
if fallback:
--- a/tests/test-alias Sat May 30 19:37:01 2009 +0200
+++ b/tests/test-alias Sat May 30 11:32:23 2009 -0700
@@ -1,18 +1,17 @@
#!/bin/sh
cat >> $HGRCPATH <<EOF
-[extensions]
-alias=
-
[alias]
myinit = init
cleanstatus = status -c
unknown = bargle
ambiguous = s
recursive = recursive
+nodefinition =
mylog = log
lognull = log -r null
shortlog = log --template '{rev} {node|short} | {date|isodate}\n'
+dln = lognull --debug
[defaults]
mylog = -q
@@ -32,6 +31,9 @@
echo '% recursive'
hg recursive
+echo '% no definition'
+hg nodef
+
cd alias
echo foo > foo
hg ci -Amfoo
@@ -45,3 +47,6 @@
echo '% interaction with defaults'
hg mylog
hg lognull
+
+echo '% properly recursive'
+hg dln
--- a/tests/test-alias.out Sat May 30 19:37:01 2009 +0200
+++ b/tests/test-alias.out Sat May 30 11:32:23 2009 -0700
@@ -1,10 +1,12 @@
% basic
% unknown
-*** [alias] unknown: command bargle is unknown
+alias 'unknown' resolves to unknown command 'bargle'
% ambiguous
-*** [alias] ambiguous: command s is ambiguous
+alias 'ambiguous' resolves to ambiguous command 's'
% recursive
-*** [alias] recursive: circular dependency on recursive
+alias 'recursive' resolves to unknown command 'recursive'
+% no definition
+no definition for alias 'nodefinition'
adding foo
% with opts
C foo
@@ -13,3 +15,12 @@
% interaction with defaults
0:e63c23eaa88a
-1:000000000000
+% properly recursive
+changeset: -1:0000000000000000000000000000000000000000
+parent: -1:0000000000000000000000000000000000000000
+parent: -1:0000000000000000000000000000000000000000
+manifest: -1:0000000000000000000000000000000000000000
+user:
+date: Thu Jan 01 00:00:00 1970 +0000
+extra: branch=default
+