##// END OF EJS Templates
pycompat: switch to util.stringio for py3 compat
pycompat: switch to util.stringio for py3 compat

File last commit:

r28861:86db5cb5 default
r28861:86db5cb5 default
Show More
dispatch.py
1084 lines | 37.6 KiB | text/x-python | PythonLexer
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 # dispatch.py - command dispatching for mercurial
#
# Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
#
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
Gregory Szorc
dispatch: use print function...
r27615 from __future__ import absolute_import, print_function
Gregory Szorc
dispatch: use absolute_import...
r25932
import atexit
Augie Fackler
dispatch: offer near-edit-distance suggestions for {file,rev}set functions...
r24221 import difflib
Gregory Szorc
dispatch: use absolute_import...
r25932 import errno
import os
import pdb
import re
import shlex
import signal
import socket
import sys
import time
import traceback
from .i18n import _
from . import (
cmdutil,
commands,
demandimport,
encoding,
error,
extensions,
fancyopts,
FUJIWARA Katsunori
registrar: add filesetpredicate to mark a function as fileset predicate...
r28447 fileset,
Gregory Szorc
dispatch: use absolute_import...
r25932 hg,
hook,
FUJIWARA Katsunori
revset: replace extpredicate by revsetpredicate of registrar...
r28394 revset,
FUJIWARA Katsunori
registrar: add templatefilter to mark a function as template filter (API)...
r28692 templatefilters,
FUJIWARA Katsunori
registrar: add templatekeyword to mark a function as template keyword (API)...
r28538 templatekw,
FUJIWARA Katsunori
registrar: add templatefunc to mark a function as template function (API)...
r28695 templater,
Gregory Szorc
dispatch: use absolute_import...
r25932 ui as uimod,
util,
)
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
Idan Kamara
dispatch: wrap dispatch related information in a request class...
r14438 class request(object):
Brodie Rao
cleanup: eradicate long lines
r16683 def __init__(self, args, ui=None, repo=None, fin=None, fout=None,
ferr=None):
Idan Kamara
dispatch: wrap dispatch related information in a request class...
r14438 self.args = args
Idan Kamara
dispatch: use the request to store the ui object...
r14439 self.ui = ui
Idan Kamara
dispatch: add repo to the request...
r14510 self.repo = repo
Idan Kamara
dispatch: wrap dispatch related information in a request class...
r14438
Idan Kamara
dispatch: add I/O descriptors to the request
r14613 # input/output/error streams
self.fin = fin
self.fout = fout
self.ferr = ferr
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 def run():
"run the command in sys.argv"
Mads Kiilerich
dispatch: exit with 8-bit exit code...
r15439 sys.exit((dispatch(request(sys.argv[1:])) or 0) & 255)
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
Augie Fackler
dispatch: offer near-edit-distance suggestions for {file,rev}set functions...
r24221 def _getsimilar(symbols, value):
sim = lambda x: difflib.SequenceMatcher(None, value, x).ratio()
# The cutoff for similarity here is pretty arbitrary. It should
# probably be investigated and tweaked.
return [s for s in symbols if sim(s) > 0.6]
Bryan O'Sullivan
dispatch: report similar names consistently
r27623 def _reportsimilar(write, similar):
if len(similar) == 1:
write(_("(did you mean %s?)\n") % similar[0])
elif similar:
ss = ", ".join(sorted(similar))
write(_("(did you mean one of %s?)\n") % ss)
Augie Fackler
dispatch: consolidate formatting of ParseErrors
r24039 def _formatparse(write, inst):
Augie Fackler
dispatch: offer near-edit-distance suggestions for {file,rev}set functions...
r24221 similar = []
if isinstance(inst, error.UnknownIdentifier):
# make sure to check fileset first, as revset can invoke fileset
similar = _getsimilar(inst.symbols, inst.function)
Augie Fackler
dispatch: consolidate formatting of ParseErrors
r24039 if len(inst.args) > 1:
write(_("hg: parse error at %s: %s\n") %
(inst.args[1], inst.args[0]))
if (inst.args[0][0] == ' '):
write(_("unexpected leading whitespace\n"))
else:
write(_("hg: parse error: %s\n") % inst.args[0])
Bryan O'Sullivan
dispatch: report similar names consistently
r27623 _reportsimilar(write, similar)
Jun Wu
dispatch: extract common logic for handling ParseError...
r28515 if inst.hint:
write(_("(%s)\n") % inst.hint)
Augie Fackler
dispatch: consolidate formatting of ParseErrors
r24039
Idan Kamara
dispatch: wrap dispatch related information in a request class...
r14438 def dispatch(req):
"run the command specified in req.args"
Idan Kamara
dispatch: assign I/O descriptors from the request to the ui
r14615 if req.ferr:
ferr = req.ferr
elif req.ui:
ferr = req.ui.ferr
else:
ferr = sys.stderr
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 try:
Idan Kamara
dispatch: use the request to store the ui object...
r14439 if not req.ui:
req.ui = uimod.ui()
Idan Kamara
dispatch: wrap dispatch related information in a request class...
r14438 if '--traceback' in req.args:
Mads Kiilerich
config: give a useful hint of source for the most common command line settings...
r20788 req.ui.setconfig('ui', 'traceback', 'on', '--traceback')
Idan Kamara
dispatch: assign I/O descriptors from the request to the ui
r14615
# set ui streams from the request
if req.fin:
req.ui.fin = req.fin
if req.fout:
req.ui.fout = req.fout
if req.ferr:
req.ui.ferr = req.ferr
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 except error.Abort as inst:
Idan Kamara
dispatch: assign I/O descriptors from the request to the ui
r14615 ferr.write(_("abort: %s\n") % inst)
Benoit Boissinot
Abort: add a hint argument, printed in the next line inside parenthesis...
r11574 if inst.hint:
Idan Kamara
dispatch: assign I/O descriptors from the request to the ui
r14615 ferr.write(_("(%s)\n") % inst.hint)
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 return -1
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except error.ParseError as inst:
Augie Fackler
dispatch: consolidate formatting of ParseErrors
r24039 _formatparse(ferr.write, inst)
Martin Geisler
dispatch: catch ConfigError while constructing ui
r9470 return -1
Idan Kamara
dispatch: assign I/O descriptors from the request to the ui
r14615
Durham Goode
blackbox: fix recording exit codes (issue3938)...
r19229 msg = ' '.join(' ' in a and repr(a) or a for a in req.args)
starttime = time.time()
ret = None
try:
ret = _runcatch(req)
Yuya Nishihara
dispatch: catch KeyboardInterrupt more broadly...
r28520 except KeyboardInterrupt:
try:
req.ui.warn(_("interrupted!\n"))
except IOError as inst:
if inst.errno != errno.EPIPE:
raise
ret = -1
Durham Goode
blackbox: fix recording exit codes (issue3938)...
r19229 finally:
duration = time.time() - starttime
Jun Wu
dispatch: flush ui before returning from dispatch...
r28534 req.ui.flush()
Durham Goode
blackbox: fix recording exit codes (issue3938)...
r19229 req.ui.log("commandfinish", "%s exited %s after %0.2f seconds\n",
msg, ret or 0, duration)
Yuya Nishihara
dispatch: catch KeyboardInterrupt more broadly...
r28520 return ret
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
Idan Kamara
dispatch: use the request to store the ui object...
r14439 def _runcatch(req):
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 def catchterm(*args):
Matt Mackall
error: move SignalInterrupt...
r7644 raise error.SignalInterrupt
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
Idan Kamara
dispatch: use the request to store the ui object...
r14439 ui = req.ui
Simon Heimberg
dispatch: ignore if signals can not be set...
r10952 try:
for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM':
num = getattr(signal, name, None)
if num:
signal.signal(num, catchterm)
except ValueError:
pass # happens if called in a thread
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
try:
try:
Sean Farley
dispatch: add ability to specify a custom pdb module as a debugger...
r19640 debugger = 'pdb'
debugtrace = {
'pdb' : pdb.set_trace
}
debugmortem = {
'pdb' : pdb.post_mortem
}
Sean Farley
dispatch: move command line --config argument parsing to _runcatch()...
r19639
# read --config before doing anything else
# (e.g. to change trust settings for reading .hg/hgrc)
cfgs = _parseconfig(req.ui, _earlygetopt(['--config'], req.args))
if req.repo:
# copy configs that were passed on the cmdline (--config) to
# the repo ui
Matt Mackall
check-code: check for argument passing py2.6ism
r20796 for sec, name, val in cfgs:
req.repo.ui.setconfig(sec, name, val, source='--config')
Sean Farley
dispatch: move command line --config argument parsing to _runcatch()...
r19639
Matt Mackall
debugger: mark developer-only option...
r25833 # developer config: ui.debugger
Sean Farley
dispatch: add ability to specify a custom pdb module as a debugger...
r19640 debugger = ui.config("ui", "debugger")
Jordi Gutiérrez Hermoso
dispatch: only do __import__(debugger) when a debugger is requested...
r20826 debugmod = pdb
Sean Farley
dispatch: turn off custom debugger for HGPLAIN mode...
r20122 if not debugger or ui.plain():
Matt Mackall
debugger: mark developer-only option...
r25833 # if we are in HGPLAIN mode, then disable custom debugging
Sean Farley
dispatch: add ability to specify a custom pdb module as a debugger...
r19640 debugger = 'pdb'
Jordi Gutiérrez Hermoso
dispatch: only do __import__(debugger) when a debugger is requested...
r20826 elif '--debugger' in req.args:
# This import can be slow for fancy debuggers, so only
# do it when absolutely necessary, i.e. when actual
# debugging has been requested
Jordi Gutiérrez Hermoso
dispatch: disable demandimport for the --debugger option...
r25329 with demandimport.deactivated():
try:
debugmod = __import__(debugger)
except ImportError:
pass # Leave debugmod = pdb
Sean Farley
dispatch: add ability to specify a custom pdb module as a debugger...
r19640
debugtrace[debugger] = debugmod.set_trace
debugmortem[debugger] = debugmod.post_mortem
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 # enter the debugger before command execution
Idan Kamara
dispatch: wrap dispatch related information in a request class...
r14438 if '--debugger' in req.args:
Mads Kiilerich
debugger: give a little intro before entering pdb
r11495 ui.warn(_("entering debugger - "
"type c to continue starting hg or h for help\n"))
Sean Farley
dispatch: add ability to specify a custom pdb module as a debugger...
r19640
if (debugger != 'pdb' and
debugtrace[debugger] == debugtrace['pdb']):
ui.warn(_("%s debugger specified "
"but its module was not found\n") % debugger)
Jordi Gutiérrez Hermoso
dispatch: use the right context manager to deactivate demandimport...
r26236 with demandimport.deactivated():
Jordi Gutiérrez Hermoso
dispatch: disable demandimport when invoking the debugger...
r26216 debugtrace[debugger]()
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 try:
Idan Kamara
dispatch: use the request to store the ui object...
r14439 return _dispatch(req)
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 finally:
ui.flush()
Brodie Rao
check-code: ignore naked excepts with a "re-raise" comment...
r16705 except: # re-raises
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 # enter the debugger when we hit an exception
Idan Kamara
dispatch: wrap dispatch related information in a request class...
r14438 if '--debugger' in req.args:
Mads Kiilerich
debugger: show traceback before entering pdb post-mortem
r11494 traceback.print_exc()
Sean Farley
dispatch: add ability to specify a custom pdb module as a debugger...
r19640 debugmortem[debugger](sys.exc_info()[2])
Matt Mackall
ui: print_exc() -> traceback()
r8206 ui.traceback()
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 raise
Matt Mackall
dispatch: sort exception handlers
r7645 # Global exception handling, alphabetically
# Mercurial-specific first, followed by built-in and library exceptions
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except error.AmbiguousCommand as inst:
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 ui.warn(_("hg: command '%s' is ambiguous:\n %s\n") %
(inst.args[0], " ".join(inst.args[1])))
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except error.ParseError as inst:
Augie Fackler
dispatch: consolidate formatting of ParseErrors
r24039 _formatparse(ui.warn, inst)
Matt Mackall
error: add new ParseError for various parsing errors
r11288 return -1
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except error.LockHeld as inst:
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 if inst.errno == errno.ETIMEDOUT:
reason = _('timed out waiting for lock held by %s') % inst.locker
else:
reason = _('lock held by %s') % inst.locker
ui.warn(_("abort: %s: %s\n") % (inst.desc or inst.filename, reason))
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except error.LockUnavailable as inst:
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 ui.warn(_("abort: could not lock %s: %s\n") %
(inst.desc or inst.filename, inst.strerror))
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except error.CommandError as inst:
Matt Mackall
dispatch: sort exception handlers
r7645 if inst.args[0]:
ui.warn(_("hg %s: %s\n") % (inst.args[0], inst.args[1]))
Martin Geisler
help: add -c/--command flag to only show command help (issue2799)
r14286 commands.help_(ui, inst.args[0], full=False, command=True)
Matt Mackall
dispatch: sort exception handlers
r7645 else:
ui.warn(_("hg: %s\n") % inst.args[1])
commands.help_(ui, 'shortlist')
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except error.OutOfBandError as inst:
Pierre-Yves David
error: allow a 'hint' to OutOfBandError...
r25242 if inst.args:
msg = _("abort: remote error:\n")
else:
msg = _("abort: remote error\n")
ui.warn(msg)
if inst.args:
ui.warn(''.join(inst.args))
if inst.hint:
ui.warn('(%s)\n' % inst.hint)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except error.RepoError as inst:
Matt Mackall
dispatch: sort exception handlers
r7645 ui.warn(_("abort: %s!\n") % inst)
Pierre-Yves David
error: Add a hint argument to RepoError...
r14761 if inst.hint:
ui.warn(_("(%s)\n") % inst.hint)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except error.ResponseError as inst:
Matt Mackall
dispatch: sort exception handlers
r7645 ui.warn(_("abort: %s") % inst.args[0])
if not isinstance(inst.args[1], basestring):
ui.warn(" %r\n" % (inst.args[1],))
elif not inst.args[1]:
ui.warn(_(" empty string\n"))
else:
ui.warn("\n%r\n" % util.ellipsis(inst.args[1]))
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except error.CensoredNodeError as inst:
Mike Edgar
error: add CensoredNodeError, will be thrown when content deliberately erased...
r22595 ui.warn(_("abort: file censored %s!\n") % inst)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except error.RevlogError as inst:
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 ui.warn(_("abort: %s!\n") % inst)
Matt Mackall
error: move SignalInterrupt...
r7644 except error.SignalInterrupt:
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 ui.warn(_("killed!\n"))
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except error.UnknownCommand as inst:
Matt Mackall
dispatch: sort exception handlers
r7645 ui.warn(_("hg: unknown command '%s'\n") % inst.args[0])
Brodie Rao
dispatch: provide help for disabled extensions and commands...
r10364 try:
# check if the command is in a disabled extension
# (but don't check for extensions themselves)
commands.help_(ui, inst.args[0], unknowncmd=True)
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 except (error.UnknownCommand, error.Abort):
Augie Fackler
dispatch: offer suggestions of similar-named commands...
r24222 suggested = False
if len(inst.args) == 2:
sim = _getsimilar(inst.args[1], inst.args[0])
if sim:
Bryan O'Sullivan
dispatch: report similar names consistently
r27623 _reportsimilar(ui.warn, sim)
Augie Fackler
dispatch: offer suggestions of similar-named commands...
r24222 suggested = True
if not suggested:
commands.help_(ui, 'shortlist')
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except error.InterventionRequired as inst:
Augie Fackler
dispatch: catch InterventionRequired and print the message with no prefix
r18932 ui.warn("%s\n" % inst)
timeless
error: make InterventionRequired take a hint
r27628 if inst.hint:
ui.warn(_("(%s)\n") % inst.hint)
Augie Fackler
dispatch: exit with status 1 for an InterventionRequired exception (bc)
r18935 return 1
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 except error.Abort as inst:
Matt Mackall
dispatch: sort exception handlers
r7645 ui.warn(_("abort: %s\n") % inst)
Benoit Boissinot
Abort: add a hint argument, printed in the next line inside parenthesis...
r11574 if inst.hint:
Patrick Mezard
dispatch: write Abort hint to stderr too
r11683 ui.warn(_("(%s)\n") % inst.hint)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except ImportError as inst:
Dan Villiom Podlaski Christiansen
dispatch: don't mangle ImportError abort messages...
r11053 ui.warn(_("abort: %s!\n") % inst)
Matt Mackall
dispatch: sort exception handlers
r7645 m = str(inst).split()[-1]
if m in "mpatch bdiff".split():
ui.warn(_("(did you forget to compile extensions?)\n"))
elif m in "zlib".split():
ui.warn(_("(is your Python install correct?)\n"))
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except IOError as inst:
Augie Fackler
dispatch: use safehasattr instead of hasattr
r14950 if util.safehasattr(inst, "code"):
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 ui.warn(_("abort: %s\n") % inst)
Augie Fackler
dispatch: use safehasattr instead of hasattr
r14950 elif util.safehasattr(inst, "reason"):
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 try: # usually it is in the form (errno, strerror)
reason = inst.reason.args[1]
Dan Villiom Podlaski Christiansen
dispatch: handle IndexErrors
r14096 except (AttributeError, IndexError):
Mads Kiilerich
check-code: indent 4 spaces in py files
r17299 # it might be anything, for example a string
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 reason = inst.reason
Yuya Nishihara
dispatch: work around UnicodeDecodeError caused by SSLError of Python 2.7.9...
r24152 if isinstance(reason, unicode):
# SSLError of Python 2.7.9 contains a unicode
reason = reason.encode(encoding.encoding, 'replace')
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 ui.warn(_("abort: error: %s\n") % reason)
Matt Mackall
dispatch: handle empty IOError args...
r21824 elif (util.safehasattr(inst, "args")
and inst.args and inst.args[0] == errno.EPIPE):
Daniel Colascione
dispatch: stop warning about EPIPE in --debug mode...
r26350 pass
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 elif getattr(inst, "strerror", None):
if getattr(inst, "filename", None):
ui.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
else:
ui.warn(_("abort: %s\n") % inst.strerror)
else:
raise
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except OSError as inst:
Mads Kiilerich
dispatch: show empty filename in OSError aborts...
r18227 if getattr(inst, "filename", None) is not None:
ui.warn(_("abort: %s: '%s'\n") % (inst.strerror, inst.filename))
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 else:
ui.warn(_("abort: %s\n") % inst.strerror)
Matt Mackall
dispatch: sort exception handlers
r7645 except KeyboardInterrupt:
Yuya Nishihara
dispatch: catch KeyboardInterrupt more broadly...
r28520 raise
Matt Mackall
dispatch: report OOM rather than traceback
r5633 except MemoryError:
ui.warn(_("abort: out of memory\n"))
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except SystemExit as inst:
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 # Commands shouldn't sys.exit directly, but give a return code.
# Just in case catch this and and pass exit code to caller.
return inst.code
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except socket.error as inst:
Matt Mackall
dispatch: sort exception handlers
r7645 ui.warn(_("abort: %s\n") % inst.args[-1])
Martijn Pieters
dispatch: factor out command failure handling into a function...
r28784 except: # perhaps re-raises
if not handlecommandexception(ui):
raise
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
return -1
Alexander Solovyov
add positional arguments to non-shell aliases
r14265 def aliasargs(fn, givenargs):
args = getattr(fn, 'args', [])
Matt Mackall
alias: abort on missing positional args (issue3331)
r16294 if args:
Alexander Solovyov
add positional arguments to non-shell aliases
r14265 cmd = ' '.join(map(util.shellquote, args))
nums = []
def replacer(m):
num = int(m.group(1)) - 1
nums.append(num)
Matt Mackall
aliases: use empty string for missing position parameters (issue3331)
r16277 if num < len(givenargs):
return givenargs[num]
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('too few arguments for command alias'))
Alexander Solovyov
add positional arguments to non-shell aliases
r14265 cmd = re.sub(r'\$(\d+|\$)', replacer, cmd)
givenargs = [x for i, x in enumerate(givenargs)
if i not in nums]
args = shlex.split(cmd)
return args + givenargs
Brendan Cully
Move alias into core
r8655
Siddharth Agarwal
alias: expand "$@" as list of parameters quoted individually (BC) (issue4200)...
r22158 def aliasinterpolate(name, args, cmd):
'''interpolate args into cmd for shell aliases
This also handles $0, $@ and "$@".
'''
# util.interpolate can't deal with "$@" (with quotes) because it's only
# built to match prefix + patterns.
replacemap = dict(('$%d' % (i + 1), arg) for i, arg in enumerate(args))
replacemap['$0'] = name
replacemap['$$'] = '$'
replacemap['$@'] = ' '.join(args)
# Typical Unix shells interpolate "$@" (with quotes) as all the positional
# parameters, separated out into words. Emulate the same behavior here by
# quoting the arguments individually. POSIX shells will then typically
# tokenize each argument into exactly one word.
replacemap['"$@"'] = ' '.join(util.shellquote(arg) for arg in args)
# escape '\$' for regex
regex = '|'.join(replacemap.keys()).replace('$', r'\$')
r = re.compile(regex)
return r.sub(lambda x: replacemap[x.group()], cmd)
Brendan Cully
Move alias into core
r8655 class cmdalias(object):
timeless
help: report source of aliases
r28828 def __init__(self, name, definition, cmdtable, source):
Brodie Rao
alias: make shadowing behavior more consistent (issue2054)...
r12039 self.name = self.cmd = name
Brodie Rao
alias: print what command is being shadowed in debug message
r12092 self.cmdname = ''
Brendan Cully
Move alias into core
r8655 self.definition = definition
Yuya Nishihara
alias: keep error message in "badalias" so that help can see it...
r22160 self.fn = None
Brendan Cully
Move alias into core
r8655 self.args = []
self.opts = []
self.help = ''
Yuya Nishihara
alias: keep error message in "badalias" so that help can see it...
r22160 self.badalias = None
Yuya Nishihara
alias: provide "unknowncmd" flag to tell help to look for disabled command...
r22161 self.unknowncmd = False
timeless
help: report source of aliases
r28828 self.source = source
Brendan Cully
Move alias into core
r8655
try:
Brodie Rao
alias: make shadowing behavior more consistent (issue2054)...
r12039 aliases, entry = cmdutil.findcmd(self.name, cmdtable)
for alias, e in cmdtable.iteritems():
if e is entry:
self.cmd = alias
break
Brendan Cully
Move alias into core
r8655 self.shadows = True
except error.UnknownCommand:
self.shadows = False
if not self.definition:
Yuya Nishihara
alias: keep error message in "badalias" so that help can see it...
r22160 self.badalias = _("no definition for alias '%s'") % self.name
Brendan Cully
Move alias into core
r8655 return
Steve Losh
dispatch: add shell aliases...
r11524 if self.definition.startswith('!'):
Steve Losh
alias: only allow global options before a shell alias, pass later ones through...
r12536 self.shell = True
Steve Losh
dispatch: add shell aliases...
r11524 def fn(ui, *args):
Steve Losh
aliases: provide more flexible ways to work with shell alias arguments...
r11989 env = {'HG_ARGS': ' '.join((self.name,) + args)}
def _checkvar(m):
Roman Sokolov
dispatch: support for $ escaping in shell-alias definition...
r13392 if m.groups()[0] == '$':
return m.group()
elif int(m.groups()[0]) <= len(args):
Steve Losh
aliases: provide more flexible ways to work with shell alias arguments...
r11989 return m.group()
else:
David Soria Parra
i18n: remove translation of debug messages
r14708 ui.debug("No argument found for substitution "
"of %i variable in alias '%s' definition."
Roman Sokolov
dispatch: debug message for missing arguments in shell alias...
r13393 % (int(m.groups()[0]), self.name))
Steve Losh
aliases: provide more flexible ways to work with shell alias arguments...
r11989 return ''
Roman Sokolov
dispatch: support for $ escaping in shell-alias definition...
r13392 cmd = re.sub(r'\$(\d+|\$)', _checkvar, self.definition[1:])
Siddharth Agarwal
alias: expand "$@" as list of parameters quoted individually (BC) (issue4200)...
r22158 cmd = aliasinterpolate(self.name, args, cmd)
Yuya Nishihara
util.system: use ui.system() in place of optional ui.fout parameter
r23270 return ui.system(cmd, environ=env)
Steve Losh
dispatch: add shell aliases...
r11524 self.fn = fn
return
Yuya Nishihara
alias: handle shlex error in command aliases...
r21569 try:
args = shlex.split(self.definition)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except ValueError as inst:
Yuya Nishihara
alias: keep error message in "badalias" so that help can see it...
r22160 self.badalias = (_("error in definition for alias '%s': %s")
% (self.name, inst))
Yuya Nishihara
alias: handle shlex error in command aliases...
r21569 return
Brodie Rao
alias: print what command is being shadowed in debug message
r12092 self.cmdname = cmd = args.pop(0)
Alexander Solovyov
expand paths in aliases
r10793 args = map(util.expandpath, args)
Brendan Cully
Move alias into core
r8655
Simon Heimberg
dispatch: also a separate warning message on aliases with --config...
r18693 for invalidarg in ("--cwd", "-R", "--repository", "--repo", "--config"):
Dan Villiom Podlaski Christiansen
alias: improved diagnostic when arguments include --cwd, etc....
r11695 if _earlygetopt([invalidarg], args):
Yuya Nishihara
alias: keep error message in "badalias" so that help can see it...
r22160 self.badalias = (_("error in definition for alias '%s': %s may "
"only be given on the command line")
% (self.name, invalidarg))
Dan Villiom Podlaski Christiansen
alias: improved diagnostic when arguments include --cwd, etc....
r11695 return
Brendan Cully
Move alias into core
r8655 try:
Nicolas Dumazet
alias: do not crash when aliased command has no usage help text
r9993 tableentry = cmdutil.findcmd(cmd, cmdtable, False)[1]
if len(tableentry) > 2:
self.fn, self.opts, self.help = tableentry
else:
self.fn, self.opts = tableentry
Alexander Solovyov
add positional arguments to non-shell aliases
r14265 self.args = aliasargs(self.fn, args)
Peter Arrenbrecht
alias: improve help text for command aliases...
r9876 if self.help.startswith("hg " + cmd):
# drop prefix in old-style help lines so hg shows the alias
self.help = self.help[4 + len(cmd):]
Yuya Nishihara
alias: fixes exception when displaying translated help text...
r10564 self.__doc__ = self.fn.__doc__
Peter Arrenbrecht
alias: improve help text for command aliases...
r9876
Brendan Cully
Move alias into core
r8655 except error.UnknownCommand:
Yuya Nishihara
alias: keep error message in "badalias" so that help can see it...
r22160 self.badalias = (_("alias '%s' resolves to unknown command '%s'")
% (self.name, cmd))
Yuya Nishihara
alias: provide "unknowncmd" flag to tell help to look for disabled command...
r22161 self.unknowncmd = True
Brendan Cully
Move alias into core
r8655 except error.AmbiguousCommand:
Yuya Nishihara
alias: keep error message in "badalias" so that help can see it...
r22160 self.badalias = (_("alias '%s' resolves to ambiguous command '%s'")
% (self.name, cmd))
Brendan Cully
Move alias into core
r8655
Yuya Nishihara
dispatch: make cmdalias forward command attributes to function...
r28621 def __getattr__(self, name):
adefaults = {'norepo': True, 'optionalrepo': False, 'inferrepo': False}
if name not in adefaults:
raise AttributeError(name)
if self.badalias or util.safehasattr(self, 'shell'):
return adefaults[name]
return getattr(self.fn, name)
Brendan Cully
Move alias into core
r8655 def __call__(self, ui, *args, **opts):
Yuya Nishihara
alias: keep error message in "badalias" so that help can see it...
r22160 if self.badalias:
Yuya Nishihara
alias: exit from bad definition by Abort
r22164 hint = None
Yuya Nishihara
alias: provide "unknowncmd" flag to tell help to look for disabled command...
r22161 if self.unknowncmd:
Brodie Rao
dispatch: provide help for disabled extensions and commands...
r10364 try:
# check if the command is in a disabled extension
Yuya Nishihara
alias: show one-line hint for command provided by disabled extension...
r22163 cmd, ext = extensions.disabledcmd(ui, self.cmdname)[:2]
Yuya Nishihara
alias: exit from bad definition by Abort
r22164 hint = _("'%s' is provided by '%s' extension") % (cmd, ext)
Brodie Rao
dispatch: provide help for disabled extensions and commands...
r10364 except error.UnknownCommand:
pass
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(self.badalias, hint=hint)
Brendan Cully
Move alias into core
r8655 if self.shadows:
Martin Geisler
Backed out changeset 1ec8bd909ac3...
r14704 ui.debug("alias '%s' shadows command '%s'\n" %
Brodie Rao
alias: print what command is being shadowed in debug message
r12092 (self.name, self.cmdname))
Brendan Cully
Move alias into core
r8655
Augie Fackler
dispatch: use safehasattr instead of hasattr
r14950 if util.safehasattr(self, 'shell'):
Steve Losh
aliases: provide more flexible ways to work with shell alias arguments...
r11989 return self.fn(ui, *args, **opts)
else:
Brodie Rao
alias: on --debug, print expansion when it has invalid arguments
r12093 try:
Yuya Nishihara
alias: fix loss of non-zero return code in command aliases...
r21556 return util.checksignature(self.fn)(ui, *args, **opts)
Brodie Rao
alias: on --debug, print expansion when it has invalid arguments
r12093 except error.SignatureError:
args = ' '.join([self.cmdname] + self.args)
Martin Geisler
Backed out changeset 1ec8bd909ac3...
r14704 ui.debug("alias '%s' expands to '%s'\n" % (self.name, args))
Brodie Rao
alias: on --debug, print expansion when it has invalid arguments
r12093 raise
Brendan Cully
Move alias into core
r8655
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'):
timeless
help: report source of aliases
r28828 source = ui.configsource('alias', alias)
aliasdef = cmdalias(alias, definition, cmdtable, source)
Idan Kamara
dispatch: don't rewrap aliases that have the same definition...
r15019
try:
olddef = cmdtable[aliasdef.cmd][0]
if olddef.definition == aliasdef.definition:
continue
except (KeyError, AttributeError):
# definition might not exist or it might not be a cmdalias
pass
Augie Fackler
alias: don't shadow commands that we only partially matched (issue2993) (BC)...
r15233 cmdtable[aliasdef.name] = (aliasdef, aliasdef.opts, aliasdef.help)
Brendan Cully
Move alias into core
r8655
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 def _parse(ui, args):
options = {}
cmdoptions = {}
try:
args = fancyopts.fancyopts(args, commands.globalopts, options)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except fancyopts.getopt.GetoptError as inst:
Matt Mackall
error: change ParseError to CommandError
r11287 raise error.CommandError(None, inst)
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
if args:
cmd, args = args[0], args[1:]
Henri Wiechers
dispatch: minor refactoring...
r9875 aliases, entry = cmdutil.findcmd(cmd, commands.table,
Yuya Nishihara
commands: parse ui.strict config item as bool
r16591 ui.configbool("ui", "strict"))
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 cmd = aliases[0]
Alexander Solovyov
add positional arguments to non-shell aliases
r14265 args = aliasargs(entry[0], args)
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 defaults = ui.config("defaults", cmd)
if defaults:
Alexander Solovyov
make path expanding more consistent...
r9610 args = map(util.expandpath, shlex.split(defaults)) + args
Henri Wiechers
dispatch: minor refactoring...
r9875 c = list(entry[1])
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 else:
cmd = None
c = []
# combine global options into local
for o in commands.globalopts:
c.append((o[0], o[1], options[o[1]], o[3]))
try:
Augie Fackler
fancyopts: Parse options that occur after arguments....
r7772 args = fancyopts.fancyopts(args, c, cmdoptions, True)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except fancyopts.getopt.GetoptError as inst:
Matt Mackall
error: change ParseError to CommandError
r11287 raise error.CommandError(cmd, inst)
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
# separate global options back out
for o in commands.globalopts:
n = o[1]
options[n] = cmdoptions[n]
del cmdoptions[n]
Henri Wiechers
dispatch: minor refactoring...
r9875 return (cmd, cmd and entry[0] or None, args, options, cmdoptions)
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
Matt Mackall
ui: kill updateopts...
r8137 def _parseconfig(ui, config):
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 """parse the --config options from the command line"""
Idan Kamara
dispatch: return read config options
r14753 configs = []
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 for cfg in config:
try:
Tony Tung
dispatch: strip command line options like config file options...
r28081 name, value = [cfgelem.strip()
for cfgelem in cfg.split('=', 1)]
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 section, name = name.split('.', 1)
if not section or not name:
raise IndexError
Mads Kiilerich
config: give a useful hint of source for the most common command line settings...
r20788 ui.setconfig(section, name, value, '--config')
Idan Kamara
dispatch: return read config options
r14753 configs.append((section, name, value))
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 except (IndexError, ValueError):
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('malformed --config option: %r '
Bill Schroeder
dispatch: better error message for --config option
r9825 '(use --config section.name=value)') % cfg)
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
Idan Kamara
dispatch: return read config options
r14753 return configs
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 def _earlygetopt(aliases, args):
"""Return list of values for an option (or aliases).
The values are listed in the order they appear in args.
The options and values are removed from args.
Bryan O'Sullivan
dispatch: add doctests for _earlygetopt
r19098
>>> args = ['x', '--cwd', 'foo', 'y']
>>> _earlygetopt(['--cwd'], args), args
(['foo'], ['x', 'y'])
Bryan O'Sullivan
dispatch: add support for --option=value to _earlygetopt...
r19099 >>> args = ['x', '--cwd=bar', 'y']
>>> _earlygetopt(['--cwd'], args), args
(['bar'], ['x', 'y'])
Bryan O'Sullivan
dispatch: add doctests for _earlygetopt
r19098 >>> args = ['x', '-R', 'foo', 'y']
>>> _earlygetopt(['-R'], args), args
(['foo'], ['x', 'y'])
>>> args = ['x', '-Rbar', 'y']
>>> _earlygetopt(['-R'], args), args
(['bar'], ['x', 'y'])
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 """
try:
argcount = args.index("--")
except ValueError:
argcount = len(args)
shortopts = [opt for opt in aliases if len(opt) == 2]
values = []
pos = 0
while pos < argcount:
Bryan O'Sullivan
dispatch: add support for --option=value to _earlygetopt...
r19099 fullarg = arg = args[pos]
equals = arg.find('=')
if equals > -1:
arg = arg[:equals]
if arg in aliases:
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 del args[pos]
Bryan O'Sullivan
dispatch: add support for --option=value to _earlygetopt...
r19099 if equals > -1:
values.append(fullarg[equals + 1:])
argcount -= 1
else:
if pos + 1 >= argcount:
# ignore and let getopt report an error if there is no value
break
values.append(args.pop(pos))
argcount -= 2
elif arg[:2] in shortopts:
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 # short option can have no following space, e.g. hg log -Rfoo
values.append(args.pop(pos)[2:])
argcount -= 1
else:
pos += 1
return values
Chad Dombrova
provide pre- and post- hooks with parsed command line arguments....
r11330 def runcommand(lui, repo, cmd, fullargs, ui, options, d, cmdpats, cmdoptions):
Bill Barry
dispatch: extract command execution block into method...
r7819 # run pre-hook, and abort if it fails
Siddharth Agarwal
dispatch: print 'abort:' when a pre-command hook fails (BC)...
r19011 hook.hook(lui, repo, "pre-%s" % cmd, True, args=" ".join(fullargs),
pats=cmdpats, opts=cmdoptions)
Bill Barry
dispatch: extract command execution block into method...
r7819 ret = _runcommand(ui, options, cmd, d)
# run post-hook, passing command result
hook.hook(lui, repo, "post-%s" % cmd, False, args=" ".join(fullargs),
Chad Dombrova
provide pre- and post- hooks with parsed command line arguments....
r11330 result=ret, pats=cmdpats, opts=cmdoptions)
Bill Barry
dispatch: extract command execution block into method...
r7819 return ret
Jun Wu
dispatch: add wd parameter to _getlocal...
r28263 def _getlocal(ui, rpath, wd=None):
Steve Losh
alias: only allow global options before a shell alias, pass later ones through...
r12536 """Return (path, local ui object) for the given target path.
Martin Geisler
check-code: find trailing whitespace
r12770
Steve Losh
alias: only allow global options before a shell alias, pass later ones through...
r12536 Takes paths in [cwd]/.hg/hgrc into account."
"""
Jun Wu
dispatch: add wd parameter to _getlocal...
r28263 if wd is None:
try:
wd = os.getcwd()
except OSError as e:
raise error.Abort(_("error getting current working directory: %s") %
e.strerror)
Mads Kiilerich
dispatch: give better error message when cwd doesn't exist (issue2293)...
r11675 path = cmdutil.findrepo(wd) or ""
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 if not path:
lui = ui
Andrey Somov
improve code readability
r9436 else:
Brodie Rao
dispatch: remove superfluous try/except when reading local ui config...
r12636 lui = ui.copy()
Brodie Rao
dispatch: properly handle relative path aliases used with -R (issue2376)...
r12637 lui.readconfig(os.path.join(path, ".hg", "hgrc"), path)
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
Matt Mackall
dispatch: fix checking of rpath in _getlocal...
r14860 if rpath and rpath[-1]:
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 path = lui.expandpath(rpath[-1])
Matt Mackall
ui: kill most users of parentui name and arg, replace with .copy()
r8190 lui = ui.copy()
Brodie Rao
dispatch: properly handle relative path aliases used with -R (issue2376)...
r12637 lui.readconfig(os.path.join(path, ".hg", "hgrc"), path)
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
Steve Losh
alias: only allow global options before a shell alias, pass later ones through...
r12536 return path, lui
FUJIWARA Katsunori
dispatch: make "_checkshellalias" reusable regardless of adding aliases...
r22376 def _checkshellalias(lui, ui, args, precheck=True):
"""Return the function to run the shell alias, if it is required
'precheck' is whether this function is invoked before adding
aliases or not.
"""
Steve Losh
alias: only allow global options before a shell alias, pass later ones through...
r12536 options = {}
Steve Losh
alias: fail gracefully when invalid global options are given (issue2442)...
r12748
try:
args = fancyopts.fancyopts(args, commands.globalopts, options)
except fancyopts.getopt.GetoptError:
return
Steve Losh
alias: only allow global options before a shell alias, pass later ones through...
r12536
if not args:
return
FUJIWARA Katsunori
dispatch: make "_checkshellalias" reusable regardless of adding aliases...
r22376 if precheck:
FUJIWARA Katsunori
dispatch: check shell alias again after loading extensions (issue4355)...
r22377 strict = True
FUJIWARA Katsunori
dispatch: make "_checkshellalias" reusable regardless of adding aliases...
r22376 cmdtable = commands.table.copy()
addaliases(lui, cmdtable)
else:
FUJIWARA Katsunori
dispatch: check shell alias again after loading extensions (issue4355)...
r22377 strict = False
FUJIWARA Katsunori
dispatch: make "_checkshellalias" reusable regardless of adding aliases...
r22376 cmdtable = commands.table
Steve Losh
alias: only allow global options before a shell alias, pass later ones through...
r12536
cmd = args[0]
try:
FUJIWARA Katsunori
dispatch: check shell alias again after loading extensions (issue4355)...
r22377 aliases, entry = cmdutil.findcmd(cmd, cmdtable, strict)
Steve Losh
alias: fall back to normal error handling for ambigious commands (fixes issue2475)
r12932 except (error.AmbiguousCommand, error.UnknownCommand):
Steve Losh
alias: only allow global options before a shell alias, pass later ones through...
r12536 return
cmd = aliases[0]
fn = entry[0]
Augie Fackler
dispatch: use safehasattr instead of hasattr
r14950 if cmd and util.safehasattr(fn, 'shell'):
Steve Losh
alias: only allow global options before a shell alias, pass later ones through...
r12536 d = lambda: fn(ui, *args[1:])
Brodie Rao
cleanup: eradicate long lines
r16683 return lambda: runcommand(lui, None, cmd, args[:1], ui, options, d,
[], {})
Steve Losh
alias: only allow global options before a shell alias, pass later ones through...
r12536
Yuya Nishihara
dispatch: extract function that tests command attributes...
r28622 def _cmdattr(ui, cmd, func, attr):
Yuya Nishihara
dispatch: show deprecation warning if command has no attributes (issue5137)...
r28623 try:
return getattr(func, attr)
except AttributeError:
ui.deprecwarn("missing attribute '%s', use @command decorator "
"to register '%s'" % (attr, cmd), '3.8')
return False
Yuya Nishihara
dispatch: extract function that tests command attributes...
r28622
Steve Losh
alias: only allow global options before a shell alias, pass later ones through...
r12536 _loaded = set()
FUJIWARA Katsunori
dispatch: make loading extra information from extension extensible...
r28391
# list of (objname, loadermod, loadername) tuple:
# - objname is the name of an object in extension module, from which
# extra information is loaded
# - loadermod is the module where loader is placed
# - loadername is the name of the function, which takes (ui, extensionname,
# extraobj) arguments
extraloaders = [
('cmdtable', commands, 'loadcmdtable'),
FUJIWARA Katsunori
registrar: add filesetpredicate to mark a function as fileset predicate...
r28447 ('filesetpredicate', fileset, 'loadpredicate'),
FUJIWARA Katsunori
revset: replace extpredicate by revsetpredicate of registrar...
r28394 ('revsetpredicate', revset, 'loadpredicate'),
FUJIWARA Katsunori
registrar: add templatefilter to mark a function as template filter (API)...
r28692 ('templatefilter', templatefilters, 'loadfilter'),
FUJIWARA Katsunori
registrar: add templatefunc to mark a function as template function (API)...
r28695 ('templatefunc', templater, 'loadfunction'),
FUJIWARA Katsunori
registrar: add templatekeyword to mark a function as template keyword (API)...
r28538 ('templatekeyword', templatekw, 'loadkeyword'),
FUJIWARA Katsunori
dispatch: make loading extra information from extension extensible...
r28391 ]
Idan Kamara
dispatch: use the request to store the ui object...
r14439 def _dispatch(req):
Idan Kamara
dispatch: wrap dispatch related information in a request class...
r14438 args = req.args
Idan Kamara
dispatch: use the request to store the ui object...
r14439 ui = req.ui
Steve Losh
alias: only allow global options before a shell alias, pass later ones through...
r12536 # check for cwd
cwd = _earlygetopt(['--cwd'], args)
if cwd:
os.chdir(cwd[-1])
rpath = _earlygetopt(["-R", "--repository", "--repo"], args)
path, lui = _getlocal(ui, rpath)
Matt Mackall
dispatch: move shell alias handling after early arg handling...
r14886 # Now that we're operating in the right directory/repository with
# the right config settings, check for shell aliases
Matt Mackall
alias: pass local ui to shell alias...
r14888 shellaliasfn = _checkshellalias(lui, ui, args)
Matt Mackall
dispatch: move shell alias handling after early arg handling...
r14886 if shellaliasfn:
return shellaliasfn()
Martin Geisler
extensions: load and configure extensions in well-defined phases...
r9410 # Configure extensions in phases: uisetup, extsetup, cmdtable, and
# reposetup. Programs like TortoiseHg will call _dispatch several
# times so we keep track of configured extensions in _loaded.
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 extensions.loadall(lui)
Martin Geisler
extensions: load and configure extensions in well-defined phases...
r9410 exts = [ext for ext in extensions.extensions() if ext[0] not in _loaded]
Brodie Rao
color/progress: subclass ui instead of using wrapfunction (issue2096)...
r11555 # Propagate any changes to lui.__class__ by extensions
ui.__class__ = lui.__class__
Kirill Smelkov
dispatch: allow extensions to provide setup code...
r5828
Yuya Nishihara
extensions: changed to call extsetup() from extensions.loadall()...
r9660 # (uisetup and extsetup are handled in extensions.loadall)
Kirill Smelkov
dispatch: allow extensions to provide setup code...
r5828
Martin Geisler
extensions: load and configure extensions in well-defined phases...
r9410 for name, module in exts:
FUJIWARA Katsunori
dispatch: make loading extra information from extension extensible...
r28391 for objname, loadermod, loadername in extraloaders:
extraobj = getattr(module, objname, None)
if extraobj is not None:
getattr(loadermod, loadername)(ui, name, extraobj)
Martin Geisler
dispatch: remember loaded extensions in a real set
r8304 _loaded.add(name)
Brendan Cully
Move alias into core
r8655
Martin Geisler
extensions: load and configure extensions in well-defined phases...
r9410 # (reposetup is handled in hg.repository)
Brendan Cully
Move alias into core
r8655 addaliases(lui, commands.table)
FUJIWARA Katsunori
dispatch: check shell alias again after loading extensions (issue4355)...
r22377 if not lui.configbool("ui", "strict"):
# All aliases and commands are completely defined, now.
# Check abbreviation/ambiguity of shell alias again, because shell
# alias may cause failure of "_parse" (see issue4355)
shellaliasfn = _checkshellalias(lui, ui, args, precheck=False)
if shellaliasfn:
return shellaliasfn()
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 # check for fallback encoding
fallback = lui.config('ui', 'fallbackencoding')
if fallback:
Matt Mackall
move encoding bits from util to encoding...
r7948 encoding.fallbackencoding = fallback
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
fullargs = args
cmd, func, args, options, cmdoptions = _parse(lui, args)
if options["config"]:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_("option --config may not be abbreviated!"))
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 if options["cwd"]:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_("option --cwd may not be abbreviated!"))
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 if options["repository"]:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_(
Martin Geisler
dispatch: lowercase abort message
r15781 "option -R has to be separated from other options (e.g. not -qR) "
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 "and --repository may only be abbreviated as --repo!"))
if options["encoding"]:
Matt Mackall
move encoding bits from util to encoding...
r7948 encoding.encoding = options["encoding"]
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 if options["encodingmode"]:
Matt Mackall
move encoding bits from util to encoding...
r7948 encoding.encodingmode = options["encodingmode"]
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 if options["time"]:
def get_times():
t = os.times()
if t[4] == 0.0: # Windows leaves this as zero, so use time.clock()
t = (t[0], t[1], t[2], t[3], time.clock())
return t
s = get_times()
def print_time():
t = get_times()
Martin Geisler
dispatch: lowercase --time message
r16933 ui.warn(_("time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
atexit.register(print_time)
Idan Kamara
dispatch: set global options on the request repo.ui...
r14752 uis = set([ui, lui])
if req.repo:
uis.add(req.repo.ui)
Idan Kamara
dispatch: make sure global options on the command line take precedence...
r14992 if options['verbose'] or options['debug'] or options['quiet']:
for opt in ('verbose', 'debug', 'quiet'):
val = str(bool(options[opt]))
Idan Kamara
dispatch: set global options on the request repo.ui...
r14752 for ui_ in uis:
Mads Kiilerich
config: give a useful hint of source for the most common command line settings...
r20788 ui_.setconfig('ui', opt, val, '--' + opt)
Idan Kamara
dispatch: make sure global options on the command line take precedence...
r14992
if options['traceback']:
for ui_ in uis:
Mads Kiilerich
config: give a useful hint of source for the most common command line settings...
r20788 ui_.setconfig('ui', 'traceback', 'on', '--traceback')
Idan Kamara
dispatch: make sure unspecified global ui options don't override old values
r14748
Matt Mackall
ui: refactor option setting...
r8136 if options['noninteractive']:
Idan Kamara
dispatch: set global options on the request repo.ui...
r14752 for ui_ in uis:
Mads Kiilerich
config: give a useful hint of source for the most common command line settings...
r20788 ui_.setconfig('ui', 'interactive', 'off', '-y')
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
Yuya Nishihara
url: add --insecure option to bypass verification of ssl certificates...
r13328 if cmdoptions.get('insecure', False):
Idan Kamara
dispatch: set global options on the request repo.ui...
r14752 for ui_ in uis:
Yuya Nishihara
ssl: set explicit symbol "!" to web.cacerts to disable SSL verification (BC)...
r24290 ui_.setconfig('web', 'cacerts', '!', '--insecure')
Yuya Nishihara
url: add --insecure option to bypass verification of ssl certificates...
r13328
Matt Mackall
help: drop with_version...
r15020 if options['version']:
return commands.version_(ui)
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 if options['help']:
timeless
help: fix help -c/help -e/help -k...
r27325 return commands.help_(ui, cmd, command=cmd is not None)
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 elif not cmd:
return commands.help_(ui, 'shortlist')
repo = None
Chad Dombrova
provide pre- and post- hooks with parsed command line arguments....
r11330 cmdpats = args[:]
Yuya Nishihara
dispatch: extract function that tests command attributes...
r28622 if not _cmdattr(ui, cmd, func, 'norepo'):
Idan Kamara
dispatch: add repo to the request...
r14510 # use the repo from the request only if we don't have -R
Idan Kamara
dispatch: don't use request repo if we have --cwd
r14863 if not rpath and not cwd:
Idan Kamara
dispatch: add repo to the request...
r14510 repo = req.repo
Idan Kamara
dispatch: set descriptors on the request repo.ui
r14744 if repo:
# set the descriptors of the repo ui to those of ui
repo.ui.fin = ui.fin
repo.ui.fout = ui.fout
repo.ui.ferr = ui.ferr
else:
Idan Kamara
dispatch: add repo to the request...
r14510 try:
repo = hg.repository(ui, path=path)
if not repo.local():
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_("repository '%s' is not local") % path)
Mads Kiilerich
config: give a useful hint of source for the most common command line settings...
r20788 repo.ui.setconfig("bundle", "mainreporoot", repo.root, 'repo')
Idan Kamara
dispatch: add repo to the request...
r14510 except error.RequirementError:
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 raise
Idan Kamara
dispatch: add repo to the request...
r14510 except error.RepoError:
Yuya Nishihara
dispatch: error out on invalid -R path even if optionalrepo (issue4805) (BC)...
r26142 if rpath and rpath[-1]: # invalid -R path
raise
Yuya Nishihara
dispatch: extract function that tests command attributes...
r28622 if not _cmdattr(ui, cmd, func, 'optionalrepo'):
if (_cmdattr(ui, cmd, func, 'inferrepo') and
args and not path):
Yuya Nishihara
dispatch: store norepo/optionalrepo/inferrepo attributes in function (API)...
r28313 # try to infer -R from command args
Idan Kamara
dispatch: add repo to the request...
r14510 repos = map(cmdutil.findrepo, args)
guess = repos[0]
if guess and repos.count(guess) == len(repos):
req.args = ['--repository', guess] + fullargs
return _dispatch(req)
if not path:
David Golub
dispatch: avoid double backslashes in error message...
r14914 raise error.RepoError(_("no repository found in '%s'"
Brodie Rao
cleanup: eradicate long lines
r16683 " (.hg not found)")
% os.getcwd())
Idan Kamara
dispatch: add repo to the request...
r14510 raise
Idan Kamara
dispatch: pass the correct ui to runcommand...
r14743 if repo:
ui = repo.ui
Julien Cristau
dispatch: take --hidden from individual commands into account...
r20330 if options['hidden']:
repo = repo.unfiltered()
Matt Mackall
dispatch: generalize signature checking for extension command wrapping
r7388 args.insert(0, repo)
Matt Mackall
warn if --repository provided for norepo commands
r7733 elif rpath:
Martin Geisler
mark ui.warn strings for translation
r11600 ui.warn(_("warning: --repository ignored\n"))
Matt Mackall
dispatch: generalize signature checking for extension command wrapping
r7388
Matt Mackall
log: add logging for commands
r11985 msg = ' '.join(' ' in a and repr(a) or a for a in fullargs)
Durham Goode
blackbox: fix exception when logging commands with format characters...
r18758 ui.log("command", '%s\n', msg)
Matt Mackall
dispatch: generalize signature checking for extension command wrapping
r7388 d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
Adrian Buehlmann
Make sure bundlerepo doesn't leak temp files (issue2491)...
r13382 try:
Durham Goode
blackbox: fix recording exit codes (issue3938)...
r19229 return runcommand(lui, repo, cmd, fullargs, ui, options, d,
cmdpats, cmdoptions)
Adrian Buehlmann
Make sure bundlerepo doesn't leak temp files (issue2491)...
r13382 finally:
Idan Kamara
dispatch: check for None before closing repo...
r14727 if repo and repo != req.repo:
Adrian Buehlmann
Make sure bundlerepo doesn't leak temp files (issue2491)...
r13382 repo.close()
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
Bryan O'Sullivan
dispatch: add support for statprof as a profiler...
r16392 def lsprofile(ui, func, fp):
format = ui.config('profiling', 'format', default='text')
field = ui.config('profiling', 'sort', default='inlinetime')
Mads Kiilerich
profiling: introduce limit configuration option...
r18548 limit = ui.configint('profiling', 'limit', default=30)
Matt Mackall
profile: disable nested report in lsprof by default...
r25277 climit = ui.configint('profiling', 'nested', default=0)
Bryan O'Sullivan
dispatch: add support for statprof as a profiler...
r16392
Brodie Rao
cleanup: "not x in y" -> "x not in y"
r16686 if format not in ['text', 'kcachegrind']:
Bryan O'Sullivan
dispatch: add support for statprof as a profiler...
r16392 ui.warn(_("unrecognized profiling format '%s'"
" - Ignored\n") % format)
format = 'text'
try:
Gregory Szorc
dispatch: use absolute_import...
r25932 from . import lsprof
Bryan O'Sullivan
dispatch: add support for statprof as a profiler...
r16392 except ImportError:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_(
Bryan O'Sullivan
dispatch: add support for statprof as a profiler...
r16392 'lsprof not available - install from '
'http://codespeak.net/svn/user/arigo/hack/misc/lsprof/'))
p = lsprof.Profiler()
p.enable(subcalls=True)
try:
return func()
finally:
p.disable()
if format == 'kcachegrind':
Gregory Szorc
dispatch: use absolute_import...
r25932 from . import lsprofcalltree
Bryan O'Sullivan
dispatch: add support for statprof as a profiler...
r16392 calltree = lsprofcalltree.KCacheGrind(p)
calltree.output(fp)
else:
# format == 'text'
stats = lsprof.Stats(p.getstats())
stats.sort(field)
Mads Kiilerich
profiling: introduce limit configuration option...
r18548 stats.pprint(limit=limit, file=fp, climit=climit)
Bryan O'Sullivan
dispatch: add support for statprof as a profiler...
r16392
Augie Fackler
dispatch: add support for python-flamegraph[0] profiling...
r25187 def flameprofile(ui, func, fp):
try:
from flamegraph import flamegraph
except ImportError:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_(
Augie Fackler
dispatch: add support for python-flamegraph[0] profiling...
r25187 'flamegraph not available - install from '
'https://github.com/evanhempel/python-flamegraph'))
Matt Mackall
profiler: mark developer-only config option
r25834 # developer config: profiling.freq
Augie Fackler
dispatch: add support for python-flamegraph[0] profiling...
r25187 freq = ui.configint('profiling', 'freq', default=1000)
filter_ = None
collapse_recursion = True
thread = flamegraph.ProfileThread(fp, 1.0 / freq,
filter_, collapse_recursion)
start_time = time.clock()
try:
thread.start()
func()
finally:
thread.stop()
thread.join()
Gregory Szorc
dispatch: use print function...
r27615 print('Collected %d stack frames (%d unique) in %2.2f seconds.' % (
Augie Fackler
dispatch: add support for python-flamegraph[0] profiling...
r25187 time.clock() - start_time, thread.num_frames(),
Gregory Szorc
dispatch: use print function...
r27615 thread.num_frames(unique=True)))
Augie Fackler
dispatch: add support for python-flamegraph[0] profiling...
r25187
Bryan O'Sullivan
dispatch: add support for statprof as a profiler...
r16392 def statprofile(ui, func, fp):
try:
import statprof
except ImportError:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_(
Bryan O'Sullivan
dispatch: add support for statprof as a profiler...
r16392 'statprof not available - install using "easy_install statprof"'))
freq = ui.configint('profiling', 'freq', default=1000)
if freq > 0:
statprof.reset(freq)
else:
ui.warn(_("invalid sampling frequency '%s' - ignoring\n") % freq)
statprof.start()
try:
return func()
finally:
statprof.stop()
statprof.display(fp)
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 def _runcommand(ui, options, cmd, cmdfunc):
Durham Goode
profiling: add config option for enabling profiling...
r26186 """Enables the profiler if applicable.
``profiling.enabled`` - boolean config that enables or disables profiling
"""
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 def checkargs():
try:
return cmdfunc()
Matt Mackall
error: move SignatureError
r7646 except error.SignatureError:
Matt Mackall
error: change ParseError to CommandError
r11287 raise error.CommandError(cmd, _("invalid arguments"))
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
Durham Goode
profiling: add config option for enabling profiling...
r26186 if options['profile'] or ui.configbool('profiling', 'enabled'):
Bryan O'Sullivan
dispatch: add support for statprof as a profiler...
r16392 profiler = os.getenv('HGPROF')
if profiler is None:
profiler = ui.config('profiling', 'type', default='ls')
Augie Fackler
dispatch: add support for python-flamegraph[0] profiling...
r25187 if profiler not in ('ls', 'stat', 'flame'):
Bryan O'Sullivan
dispatch: add support for statprof as a profiler...
r16392 ui.warn(_("unrecognized profiler '%s' - ignored\n") % profiler)
profiler = 'ls'
Nicolas Dumazet
profiling: Adding a profiling.format config variable...
r8023
Nicolas Dumazet
profiling: Adding profiling.output config variable...
r8022 output = ui.config('profiling', 'output')
Durham Goode
profiling: allow logging profile to the blackbox...
r26191 if output == 'blackbox':
timeless
pycompat: switch to util.stringio for py3 compat
r28861 fp = util.stringio()
Durham Goode
profiling: allow logging profile to the blackbox...
r26191 elif output:
Alexander Solovyov
make path expanding more consistent...
r9610 path = ui.expandpath(output)
Bryan O'Sullivan
dispatch: add support for statprof as a profiler...
r16392 fp = open(path, 'wb')
Nicolas Dumazet
profiling: Adding profiling.output config variable...
r8022 else:
Bryan O'Sullivan
dispatch: add support for statprof as a profiler...
r16392 fp = sys.stderr
Nicolas Dumazet
profiling: Adding profiling.output config variable...
r8022
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 try:
Bryan O'Sullivan
dispatch: add support for statprof as a profiler...
r16392 if profiler == 'ls':
return lsprofile(ui, checkargs, fp)
Augie Fackler
dispatch: add support for python-flamegraph[0] profiling...
r25187 elif profiler == 'flame':
return flameprofile(ui, checkargs, fp)
Bryan O'Sullivan
dispatch: add support for statprof as a profiler...
r16392 else:
return statprofile(ui, checkargs, fp)
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 finally:
Nicolas Dumazet
profiling: Adding profiling.output config variable...
r8022 if output:
Durham Goode
profiling: allow logging profile to the blackbox...
r26191 if output == 'blackbox':
val = "Profile:\n%s" % fp.getvalue()
# ui.log treats the input as a format string,
# so we need to escape any % signs.
val = val.replace('%', '%%')
ui.log('profile', val)
Bryan O'Sullivan
dispatch: add support for statprof as a profiler...
r16392 fp.close()
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 else:
Thomas Arendsen Hein
Backed out changeset b913d3aacddc (see issue971/msg5317)
r6141 return checkargs()
Martijn Pieters
dispatch: factor out command failure handling into a function...
r28784
Martijn Pieters
dispatch: split out warning message generation to separate function...
r28821 def _exceptionwarning(ui):
"""Produce a warning message for the current active exception"""
Martijn Pieters
dispatch: factor out command failure handling into a function...
r28784
# For compatibility checking, we discard the portion of the hg
# version after the + on the assumption that if a "normal
# user" is running a build with a + in it the packager
# probably built from fairly close to a tag and anyone with a
# 'make local' copy of hg (where the version number can be out
# of date) will be clueful enough to notice the implausible
# version number and try updating.
ct = util.versiontuple(n=2)
worst = None, ct, ''
if ui.config('ui', 'supportcontact', None) is None:
for name, mod in extensions.extensions():
testedwith = getattr(mod, 'testedwith', '')
report = getattr(mod, 'buglink', _('the extension author.'))
if not testedwith.strip():
# We found an untested extension. It's likely the culprit.
worst = name, 'unknown', report
break
# Never blame on extensions bundled with Mercurial.
if testedwith == 'internal':
continue
tested = [util.versiontuple(t, 2) for t in testedwith.split()]
if ct in tested:
continue
lower = [t for t in tested if t < ct]
nearest = max(lower or tested)
if worst[0] is None or nearest < worst[1]:
worst = name, nearest, report
if worst[0] is not None:
name, testedwith, report = worst
if not isinstance(testedwith, str):
testedwith = '.'.join([str(c) for c in testedwith])
warning = (_('** Unknown exception encountered with '
'possibly-broken third-party extension %s\n'
'** which supports versions %s of Mercurial.\n'
'** Please disable %s and try your action again.\n'
'** If that fixes the bug please report it to %s\n')
% (name, testedwith, name, report))
else:
bugtracker = ui.config('ui', 'supportcontact', None)
if bugtracker is None:
bugtracker = _("https://mercurial-scm.org/wiki/BugTracker")
warning = (_("** unknown exception encountered, "
"please report by visiting\n** ") + bugtracker + '\n')
warning += ((_("** Python %s\n") % sys.version.replace('\n', '')) +
(_("** Mercurial Distributed SCM (version %s)\n") %
util.version()) +
(_("** Extensions loaded: %s\n") %
", ".join([x[0] for x in extensions.extensions()])))
Martijn Pieters
dispatch: split out warning message generation to separate function...
r28821 return warning
def handlecommandexception(ui):
"""Produce a warning message for broken commands
Called when handling an exception; the exception is reraised if
this function returns False, ignored otherwise.
"""
warning = _exceptionwarning(ui)
Martijn Pieters
dispatch: factor out command failure handling into a function...
r28784 ui.log("commandexception", "%s\n%s\n", warning, traceback.format_exc())
ui.warn(warning)
return False # re-raise the exception