##// END OF EJS Templates
config: type `rcutil`...
config: type `rcutil` It helps to understand what is going on here and catch future errors.

File last commit:

r53313:0a81f3ef default
r53317:91f22b89 default
Show More
dispatch.py
1389 lines | 46.0 KiB | text/x-python | PythonLexer
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 # dispatch.py - command dispatching for mercurial
#
Raphaël Gomès
contributor: change mentions of mpm to olivia...
r47575 # Copyright 2005-2007 Olivia Mackall <olivia@selenic.com>
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 #
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
Matt Harbison
typing: add `from __future__ import annotations` to most files...
r52756 from __future__ import annotations
Gregory Szorc
dispatch: use absolute_import...
r25932
import errno
Pulkit Goyal
fancyopts: switch from fancyopts.getopt.* to getopt.*...
r30576 import getopt
Gregory Szorc
dispatch: force \n for newlines on sys.std* streams (BC)...
r45141 import io
Gregory Szorc
dispatch: use absolute_import...
r25932 import os
import pdb
import re
import signal
import sys
import traceback
from .i18n import _
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 from hgdemandimport import tracing
Gregory Szorc
dispatch: use absolute_import...
r25932 from . import (
cmdutil,
Pierre-Yves David
color: load 'colortable' from extension using an 'extraloader'...
r30653 color,
Gregory Szorc
dispatch: use absolute_import...
r25932 commands,
demandimport,
encoding,
error,
extensions,
fancyopts,
Augie Fackler
dispatch: rearrange 'unknown command' code to better employ pager...
r31060 help,
Gregory Szorc
dispatch: use absolute_import...
r25932 hg,
hook,
Pulkit Goyal
dispatch: load shared source repository config in share-safe mode...
r46367 localrepo,
Gregory Szorc
profiling: move profiling code from dispatch.py (API)...
r29781 profiling,
Pulkit Goyal
py3: use pycompat.sysargv in dispatch.run()...
r30468 pycompat,
rdamazio@google.com
help: displaying documented aliases by default...
r40450 registrar,
Pulkit Goyal
dispatch: load shared source repository config in share-safe mode...
r46367 requirements as requirementsmod,
Jun Wu
dispatch: move part of callcatch to scmutil...
r30520 scmutil,
Gregory Szorc
dispatch: use absolute_import...
r25932 ui as uimod,
util,
Pulkit Goyal
dispatch: load shared source repository config in share-safe mode...
r46367 vfs,
Gregory Szorc
dispatch: use absolute_import...
r25932 )
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
config: move `rcutil` module under a new `mercurial.configuration` module...
r53313 from .configuration import rcutil
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 from .utils import (
Yuya Nishihara
procutil: bulk-replace util.std* to point to new module
r37137 procutil,
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 stringutil,
dispatch: use the new API to resolve --repository...
r47719 urlutil,
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 )
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
py3: use class X: instead of class X(object):...
r49801 class request:
Augie Fackler
formatting: blacken the codebase...
r43346 def __init__(
self,
args,
ui=None,
repo=None,
fin=None,
fout=None,
ferr=None,
fmsg=None,
prereposetups=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
Yuya Nishihara
dispatch: pass around ui.fmsg channel...
r40623 # separate stream for status/error messages
self.fmsg = fmsg
Idan Kamara
dispatch: add I/O descriptors to the request
r14613
Yuya Nishihara
dispatch: replace _earlyreq*() with new fancyopts-based parser
r35224 # remember options pre-parsed by _earlyparseopts()
Yuya Nishihara
dispatch: abort if early boolean options can't be parsed...
r35059 self.earlyoptions = {}
Jun Wu
dispatch: make request accept additional reposetups...
r32379 # reposetups which run before extensions, useful for chg to pre-fill
# low-level repo state (for example, changelog) before extensions.
self.prereposetups = prereposetups or []
Boris Feld
logtoprocess: sends the canonical command name to the subprocess...
r40438 # store the parsed and canonical command
self.canonical_command = None
Matt Harbison
typing: lock in correct changes from pytype 2023.04.11 -> 2023.06.16...
r52708 def _runexithandlers(self) -> None:
Bryan O'Sullivan
ui: add special-purpose atexit functionality...
r31956 exc = None
handlers = self.ui._exithandlers
try:
while handlers:
func, args, kwargs = handlers.pop()
try:
func(*args, **kwargs)
Augie Fackler
formatting: blacken the codebase...
r43346 except: # re-raises below
Bryan O'Sullivan
ui: add special-purpose atexit functionality...
r31956 if exc is None:
exc = sys.exc_info()[1]
Augie Fackler
cleanup: mark some ui.(status|note|warn|write) calls as not needing i18n...
r43350 self.ui.warnnoi18n(b'error in exit handlers:\n')
Bryan O'Sullivan
ui: add special-purpose atexit functionality...
r31956 self.ui.traceback(force=True)
finally:
if exc is not None:
raise exc
Augie Fackler
formatting: blacken the codebase...
r43346
Pulkit Goyal
dispatch: move IOError handling and flushing of streams to `dispatch()`...
r46717 def _flushstdio(ui, err):
Pulkit Goyal
commandserver: handle IOError related to flushing of streams...
r46702 status = None
# In all cases we try to flush stdio streams.
safehasattr: drop usage in favor of hasattr...
r51821 if hasattr(ui, 'fout'):
Pulkit Goyal
commandserver: handle IOError related to flushing of streams...
r46702 assert ui is not None # help pytype
assert ui.fout is not None # help pytype
try:
ui.fout.flush()
except IOError as e:
err = e
status = -1
safehasattr: drop usage in favor of hasattr...
r51821 if hasattr(ui, 'ferr'):
Pulkit Goyal
commandserver: handle IOError related to flushing of streams...
r46702 assert ui is not None # help pytype
assert ui.ferr is not None # help pytype
try:
if err is not None and err.errno != errno.EPIPE:
ui.ferr.write(
b'abort: %s\n' % encoding.strtolocal(err.strerror)
)
ui.ferr.flush()
# There's not much we can do about an I/O error here. So (possibly)
# change the status code and move on.
except IOError:
status = -1
return status
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 def run():
Matt Harbison
cleanup: fix docstring formatting...
r44226 """run the command in sys.argv"""
Bryan O'Sullivan
stdio: catch StdioError in dispatch.run and clean up appropriately...
r31960 try:
Yuya Nishihara
dispatch: indent run() function...
r45661 initstdio()
with tracing.log('parse args into request'):
req = request(pycompat.sysargv[1:])
Gregory Szorc
dispatch: minor code refactor...
r38014
Pulkit Goyal
dispatch: move IOError handling and flushing of streams to `dispatch()`...
r46717 status = dispatch(req)
Yuya Nishihara
dispatch: indent run() function...
r45661 _silencestdio()
Yuya Nishihara
dispatch: handle late KeyboardInterrupt occurred in run()...
r45662 except KeyboardInterrupt:
# Catch early/late KeyboardInterrupt as last ditch. Here nothing will
# be printed to console to avoid another IOError/KeyboardInterrupt.
status = -1
Bryan O'Sullivan
stdio: catch StdioError in dispatch.run and clean up appropriately...
r31960 sys.exit(status & 255)
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
dispatch: remove Python 2 function variants...
r49746 def initstdio():
# stdio streams on Python 3 are io.TextIOWrapper instances proxying another
# buffer. These streams will normalize \n to \r\n by default. Mercurial's
# preferred mechanism for writing output (ui.write()) uses io.BufferedWriter
# instances, which write to the underlying stdio file descriptor in binary
# mode. ui.write() uses \n for line endings and no line ending normalization
# is attempted through this interface. This "just works," even if the system
# preferred line ending is not \n.
#
# But some parts of Mercurial (e.g. hooks) can still send data to sys.stdout
# and sys.stderr. They will inherit the line ending normalization settings,
# potentially causing e.g. \r\n to be emitted. Since emitting \n should
# "just work," here we change the sys.* streams to disable line ending
# normalization, ensuring compatibility with our ui type.
Gregory Szorc
dispatch: force \n for newlines on sys.std* streams (BC)...
r45141
Gregory Szorc
dispatch: remove Python 2 function variants...
r49746 if sys.stdout is not None:
# write_through is new in Python 3.7.
kwargs = {
"newline": "\n",
"line_buffering": sys.stdout.line_buffering,
}
safehasattr: drop usage in favor of hasattr...
r51821 if hasattr(sys.stdout, "write_through"):
Gregory Szorc
dispatch: remove Python 2 function variants...
r49746 # pytype: disable=attribute-error
kwargs["write_through"] = sys.stdout.write_through
# pytype: enable=attribute-error
sys.stdout = io.TextIOWrapper(
sys.stdout.buffer, sys.stdout.encoding, sys.stdout.errors, **kwargs
)
Gregory Szorc
dispatch: force \n for newlines on sys.std* streams (BC)...
r45141
Gregory Szorc
dispatch: remove Python 2 function variants...
r49746 if sys.stderr is not None:
kwargs = {
"newline": "\n",
"line_buffering": sys.stderr.line_buffering,
}
safehasattr: drop usage in favor of hasattr...
r51821 if hasattr(sys.stderr, "write_through"):
Gregory Szorc
dispatch: remove Python 2 function variants...
r49746 # pytype: disable=attribute-error
kwargs["write_through"] = sys.stderr.write_through
# pytype: enable=attribute-error
sys.stderr = io.TextIOWrapper(
sys.stderr.buffer, sys.stderr.encoding, sys.stderr.errors, **kwargs
)
Yuya Nishihara
py3: silence the final IOError by closing stdout/err slightly early...
r36655
Gregory Szorc
dispatch: remove Python 2 function variants...
r49746 if sys.stdin is not None:
# No write_through on read-only stream.
sys.stdin = io.TextIOWrapper(
sys.stdin.buffer,
sys.stdin.encoding,
sys.stdin.errors,
# None is universal newlines mode.
newline=None,
line_buffering=sys.stdin.line_buffering,
)
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
dispatch: remove Python 2 function variants...
r49746 def _silencestdio():
for fp in (sys.stdout, sys.stderr):
if fp is None:
continue
# Check if the file is okay
try:
fp.flush()
continue
except IOError:
pass
# Otherwise mark it as closed to silence "Exception ignored in"
# message emitted by the interpreter finalizer.
try:
fp.close()
except IOError:
pass
Yuya Nishihara
py3: silence the final IOError by closing stdout/err slightly early...
r36655
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
dispatch: consolidate formatting of arguments...
r31492 def _formatargs(args):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b' '.join(procutil.shellquote(a) for a in args)
Augie Fackler
dispatch: consolidate formatting of arguments...
r31492
Augie Fackler
formatting: blacken the codebase...
r43346
Idan Kamara
dispatch: wrap dispatch related information in a request class...
r14438 def dispatch(req):
Yuya Nishihara
dispatch: unify handling of None returned by a command function...
r38015 """run the command specified in req.args; returns an integer status code"""
Pulkit Goyal
dispatch: move IOError handling and flushing of streams to `dispatch()`...
r46717 err = None
try:
status = _rundispatch(req)
except error.StdioError as e:
err = e
status = -1
Raphaël Gomès
backout: backed out changeset 2f2107c01dee...
r49072 ret = _flushstdio(req.ui, err)
if ret and not status:
status = ret
Pulkit Goyal
dispatch: move IOError handling and flushing of streams to `dispatch()`...
r46717 return status
Matt Harbison
typing: lock in correct changes from pytype 2023.04.11 -> 2023.06.16...
r52708 def _rundispatch(req) -> int:
Pulkit Goyal
dispatch: move IOError handling and flushing of streams to `dispatch()`...
r46717 with tracing.log('dispatch._rundispatch'):
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 if req.ferr:
ferr = req.ferr
elif req.ui:
ferr = req.ui.ferr
else:
ferr = procutil.stderr
Idan Kamara
dispatch: assign I/O descriptors from the request to the ui
r14615
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 try:
if not req.ui:
req.ui = uimod.ui.load()
req.earlyoptions.update(_earlyparseopts(req.ui, req.args))
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if req.earlyoptions[b'traceback']:
req.ui.setconfig(b'ui', b'traceback', b'on', b'--traceback')
Idan Kamara
dispatch: assign I/O descriptors from the request to the ui
r14615
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 # 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
Yuya Nishihara
dispatch: pass around ui.fmsg channel...
r40623 if req.fmsg:
req.ui.fmsg = req.fmsg
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 except error.Abort as inst:
Martin von Zweigbergk
errors: format "abort: " text in a new Abort.format() method...
r46497 ferr.write(inst.format())
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 return -1
Idan Kamara
dispatch: assign I/O descriptors from the request to the ui
r14615
Valentin Gatien-Baron
dispatch: fix silly blackbox entries when hg is interrupted...
r49855 formattedargs = _formatargs(req.args)
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 starttime = util.timer()
ret = 1 # default of Python exit code on unhandled exception
Yuya Nishihara
dispatch: catch KeyboardInterrupt more broadly...
r28520 try:
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 ret = _runcatch(req) or 0
except error.ProgrammingError as inst:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 req.ui.error(_(b'** ProgrammingError: %s\n') % inst)
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 if inst.hint:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 req.ui.error(_(b'** (%s)\n') % inst.hint)
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 raise
except KeyboardInterrupt as inst:
try:
if isinstance(inst, error.SignalInterrupt):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 msg = _(b"killed!\n")
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 msg = _(b"interrupted!\n")
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 req.ui.error(msg)
except error.SignalInterrupt:
# maybe pager would quit without consuming all the output, and
# SIGPIPE was raised. we cannot print anything in this case.
pass
Manuel Jacob
py3: catch BrokenPipeError instead of checking errno == EPIPE
r50199 except BrokenPipeError:
pass
Raphaël Gomès
backout: backed out changeset 6edc8800dbc3...
r49071 ret = -1
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 finally:
duration = util.timer() - starttime
Raphaël Gomès
backout: backed out changeset 2f2107c01dee...
r49072 req.ui.flush() # record blocked times
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 if req.ui.logblockedtimes:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 req.ui._blockedtimes[b'command_duration'] = duration * 1000
Augie Fackler
formatting: blacken the codebase...
r43346 req.ui.log(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'uiblocked',
b'ui blocked ms\n',
Matt Harbison
format: add many "missing" comma...
r52755 **pycompat.strkwargs(req.ui._blockedtimes),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Boris Feld
logtoprocess: update commandfinish options arguments...
r40687 return_code = ret & 255
req.ui.log(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"commandfinish",
b"%s exited %d after %0.2f seconds\n",
Valentin Gatien-Baron
dispatch: fix silly blackbox entries when hg is interrupted...
r49855 formattedargs,
Boris Feld
logtoprocess: update commandfinish options arguments...
r40687 return_code,
duration,
return_code=return_code,
duration=duration,
canonical_command=req.canonical_command,
)
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 try:
req._runexithandlers()
Augie Fackler
formatting: blacken the codebase...
r43346 except: # exiting, so no re-raises
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 ret = ret or -1
Yuya Nishihara
dispatch: adjust ui.flush() timing to stabilize test-blackbox.t...
r45813 # do flush again since ui.log() and exit handlers may write to ui
Raphaël Gomès
backout: backed out changeset 2f2107c01dee...
r49072 req.ui.flush()
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 return ret
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
Augie Fackler
formatting: blacken the codebase...
r43346
Idan Kamara
dispatch: use the request to store the ui object...
r14439 def _runcatch(req):
Augie Fackler
cleanup: hgdemandimport.tracing accepts strings, not bytes...
r43532 with tracing.log('dispatch._runcatch'):
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 def catchterm(*args):
raise error.SignalInterrupt
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 ui = req.ui
Augie Fackler
dispatch: protect against malicious 'hg serve --stdio' invocations (sec)...
r32050 try:
safehasattr: pass attribute name as string instead of bytes...
r51462 for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM':
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 num = getattr(signal, name, None)
if num:
signal.signal(num, catchterm)
except ValueError:
Augie Fackler
formatting: blacken the codebase...
r43346 pass # happens if called in a thread
Augie Fackler
dispatch: protect against malicious 'hg serve --stdio' invocations (sec)...
r32050
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 def _runcatchfunc():
realcmd = None
try:
cmdargs = fancyopts.fancyopts(
Augie Fackler
formatting: blacken the codebase...
r43346 req.args[:], commands.globalopts, {}
)
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 cmd = cmdargs[0]
aliases, entry = cmdutil.findcmd(cmd, commands.table, False)
realcmd = aliases[0]
Augie Fackler
formatting: blacken the codebase...
r43346 except (
error.UnknownCommand,
error.AmbiguousCommand,
IndexError,
getopt.GetoptError,
):
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 # Don't handle this here. We know the command is
# invalid, but all we're worried about for now is that
# it's not a command that server operators expect to
# be safe to offer to users in a sandbox.
pass
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if realcmd == b'serve' and b'--stdio' in cmdargs:
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 # We want to constrain 'hg serve --stdio' instances pretty
# closely, as many shared-ssh access tools want to grant
# access to run *only* 'hg -R $repo serve --stdio'. We
# restrict to exactly that set of arguments, and prohibit
# any repo name that starts with '--' to prevent
# shenanigans wherein a user does something like pass
# --debugger or --config=ui.debugger=1 as a repo
# name. This used to actually run the debugger.
Manuel Jacob
hidden: support passing --hidden with `serve --stdio`...
r51315 nbargs = 4
hashiddenaccess = b'--hidden' in cmdargs
if hashiddenaccess:
nbargs += 1
Augie Fackler
formatting: blacken the codebase...
r43346 if (
Manuel Jacob
hidden: support passing --hidden with `serve --stdio`...
r51315 len(req.args) != nbargs
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 or req.args[0] != b'-R'
or req.args[1].startswith(b'--')
or req.args[2] != b'serve'
or req.args[3] != b'--stdio'
Manuel Jacob
hidden: support passing --hidden with `serve --stdio`...
r51315 or hashiddenaccess
and req.args[4] != b'--hidden'
Augie Fackler
formatting: blacken the codebase...
r43346 ):
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'potentially unsafe serve --stdio invocation: %s')
Augie Fackler
formatting: blacken the codebase...
r43346 % (stringutil.pprint(req.args),)
)
Sean Farley
dispatch: move command line --config argument parsing to _runcatch()...
r19639
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 debugger = b'pdb'
debugtrace = {b'pdb': pdb.set_trace}
debugmortem = {b'pdb': pdb.post_mortem}
Sean Farley
dispatch: move command line --config argument parsing to _runcatch()...
r19639
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 # read --config before doing anything else
# (e.g. to change trust settings for reading .hg/hgrc)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 cfgs = _parseconfig(req.ui, req.earlyoptions[b'config'])
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291
if req.repo:
# copy configs that were passed on the cmdline (--config) to
# the repo ui
for sec, name, val in cfgs:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 req.repo.ui.setconfig(
sec, name, val, source=b'--config'
)
Sean Farley
dispatch: add ability to specify a custom pdb module as a debugger...
r19640
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 # developer config: ui.debugger
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 debugger = ui.config(b"ui", b"debugger")
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 debugmod = pdb
if not debugger or ui.plain():
# if we are in HGPLAIN mode, then disable custom debugging
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 debugger = b'pdb'
elif req.earlyoptions[b'debugger']:
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 # This import can be slow for fancy debuggers, so only
# do it when absolutely necessary, i.e. when actual
# debugging has been requested
with demandimport.deactivated():
try:
Jordi Gutiérrez Hermoso
dispatch: don't attempt to import debugger as bytestring...
r52271 debugmod = __import__(pycompat.sysstr(debugger))
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 except ImportError:
Augie Fackler
formatting: blacken the codebase...
r43346 pass # Leave debugmod = pdb
Sean Farley
dispatch: add ability to specify a custom pdb module as a debugger...
r19640
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 debugtrace[debugger] = debugmod.set_trace
debugmortem[debugger] = debugmod.post_mortem
Sean Farley
dispatch: add ability to specify a custom pdb module as a debugger...
r19640
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 # enter the debugger before command execution
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if req.earlyoptions[b'debugger']:
Augie Fackler
formatting: blacken the codebase...
r43346 ui.warn(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"entering debugger - "
b"type c to continue starting hg or h for help\n"
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
Augie Fackler
formatting: blacken the codebase...
r43346 if (
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 debugger != b'pdb'
and debugtrace[debugger] == debugtrace[b'pdb']
Augie Fackler
formatting: blacken the codebase...
r43346 ):
ui.warn(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"%s debugger specified "
b"but its module was not found\n"
Augie Fackler
formatting: blacken the codebase...
r43346 )
% debugger
)
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 with demandimport.deactivated():
debugtrace[debugger]()
try:
return _dispatch(req)
finally:
Raphaël Gomès
backout: backed out changeset 2f2107c01dee...
r49072 ui.flush()
Augie Fackler
formatting: blacken the codebase...
r43346 except: # re-raises
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 # enter the debugger when we hit an exception
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if req.earlyoptions[b'debugger']:
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 traceback.print_exc()
debugmortem[debugger](sys.exc_info()[2])
raise
Augie Fackler
formatting: blacken the codebase...
r43346
Augie Fackler
dispatch: have dispatch.dispatch and dispatch._runcatch emit trace events...
r39291 return _callcatch(ui, _runcatchfunc)
Jun Wu
dispatch: split global error handling out so it can be reused...
r29761
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
dispatch: mark callcatch() as a private function
r32040 def _callcatch(ui, func):
Jun Wu
dispatch: move part of callcatch to scmutil...
r30520 """like scmutil.callcatch but handles more high-level exceptions about
config parsing and commands. besides, use handlecommandexception to handle
uncaught exceptions.
Jun Wu
dispatch: split global error handling out so it can be reused...
r29761 """
Martin von Zweigbergk
error: use detailed exit code 10 for command errors...
r46888 detailed_exit_code = -1
Jun Wu
dispatch: split global error handling out so it can be reused...
r29761 try:
Jun Wu
dispatch: move part of callcatch to scmutil...
r30520 return scmutil.callcatch(ui, func)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except error.AmbiguousCommand as inst:
Martin von Zweigbergk
error: use detailed exit code 10 for command errors...
r46888 detailed_exit_code = 10
Augie Fackler
formatting: blacken the codebase...
r43346 ui.warn(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"hg: command '%s' is ambiguous:\n %s\n")
Martin von Zweigbergk
errors: name arguments to AmbiguousCommand constructor...
r46271 % (inst.prefix, b" ".join(inst.matches))
Augie Fackler
formatting: blacken the codebase...
r43346 )
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except error.CommandError as inst:
Martin von Zweigbergk
error: use detailed exit code 10 for command errors...
r46888 detailed_exit_code = 10
Martin von Zweigbergk
errors: name arguments to CommandError constructor...
r46270 if inst.command:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.pager(b'help')
Martin von Zweigbergk
errors: name arguments to CommandError constructor...
r46270 msgbytes = pycompat.bytestr(inst.message)
ui.warn(_(b"hg %s: %s\n") % (inst.command, msgbytes))
commands.help_(ui, inst.command, full=False, command=True)
Matt Mackall
dispatch: sort exception handlers
r7645 else:
Martin von Zweigbergk
errors: name arguments to CommandError constructor...
r46270 ui.warn(_(b"hg: %s\n") % inst.message)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.warn(_(b"(use 'hg help -v' for a list of global options)\n"))
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except error.UnknownCommand as inst:
Martin von Zweigbergk
error: use detailed exit code 10 for command errors...
r46888 detailed_exit_code = 10
Martin von Zweigbergk
errors: name arguments to UnknownCommand constructor...
r46272 nocmdmsg = _(b"hg: unknown command '%s'\n") % inst.command
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)
Augie Fackler
formatting: blacken the codebase...
r43346 formatted = help.formattedhelp(
Martin von Zweigbergk
errors: name arguments to UnknownCommand constructor...
r46272 ui, commands, inst.command, unknowncmd=True
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
dispatch: rearrange 'unknown command' code to better employ pager...
r31060 ui.warn(nocmdmsg)
ui.write(formatted)
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
Martin von Zweigbergk
errors: name arguments to UnknownCommand constructor...
r46272 if inst.all_commands:
Martin von Zweigbergk
errors: move similarity_hint() to error module...
r46494 sim = error.getsimilar(inst.all_commands, inst.command)
Augie Fackler
dispatch: offer suggestions of similar-named commands...
r24222 if sim:
Augie Fackler
dispatch: rearrange 'unknown command' code to better employ pager...
r31060 ui.warn(nocmdmsg)
Martin von Zweigbergk
errors: move similarity_hint() to error module...
r46494 ui.warn(b"(%s)\n" % error.similarity_hint(sim))
Augie Fackler
dispatch: offer suggestions of similar-named commands...
r24222 suggested = True
if not suggested:
Augie Fackler
dispatch: rearrange 'unknown command' code to better employ pager...
r31060 ui.warn(nocmdmsg)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.warn(_(b"(use 'hg help' for a list of commands)\n"))
Jun Wu
dispatch: move part of callcatch to scmutil...
r30520 except IOError:
raise
Matt Mackall
dispatch: sort exception handlers
r7645 except KeyboardInterrupt:
Yuya Nishihara
dispatch: catch KeyboardInterrupt more broadly...
r28520 raise
Jun Wu
dispatch: move part of callcatch to scmutil...
r30520 except: # probably re-raises
Martijn Pieters
dispatch: factor out command failure handling into a function...
r28784 if not handlecommandexception(ui):
raise
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
Martin von Zweigbergk
error: use detailed exit code 10 for command errors...
r46888 if ui.configbool(b'ui', b'detailed-exit-code'):
return detailed_exit_code
else:
return -1
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
Augie Fackler
formatting: blacken the codebase...
r43346
Alexander Solovyov
add positional arguments to non-shell aliases
r14265 def aliasargs(fn, givenargs):
Jun Wu
wrapfunction: use functools.partial if possible...
r34089 args = []
# only care about alias 'args', ignore 'args' set by extensions.wrapfunction
safehasattr: drop usage in favor of hasattr...
r51821 if not hasattr(fn, '_origfunc'):
Jun Wu
wrapfunction: use functools.partial if possible...
r34089 args = getattr(fn, 'args', args)
Matt Mackall
alias: abort on missing positional args (issue3331)
r16294 if args:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 cmd = b' '.join(map(procutil.shellquote, args))
Alexander Solovyov
add positional arguments to non-shell aliases
r14265
nums = []
Augie Fackler
formatting: blacken the codebase...
r43346
Alexander Solovyov
add positional arguments to non-shell aliases
r14265 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]
Martin von Zweigbergk
errors: raise InputError when too few arguments given to alias...
r46526 raise error.InputError(_(b'too few arguments for command alias'))
Augie Fackler
formatting: blacken the codebase...
r43346
Pulkit Goyal
py3: make the regular expression bytes to prevent TypeError
r31491 cmd = re.sub(br'\$(\d+|\$)', replacer, cmd)
Augie Fackler
formatting: blacken the codebase...
r43346 givenargs = [x for i, x in enumerate(givenargs) if i not in nums]
Pulkit Goyal
py3: have a bytes version of shlex.split()...
r30678 args = pycompat.shlexsplit(cmd)
Alexander Solovyov
add positional arguments to non-shell aliases
r14265 return args + givenargs
Brendan Cully
Move alias into core
r8655
Augie Fackler
formatting: blacken the codebase...
r43346
Siddharth Agarwal
alias: expand "$@" as list of parameters quoted individually (BC) (issue4200)...
r22158 def aliasinterpolate(name, args, cmd):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """interpolate args into cmd for shell aliases
Siddharth Agarwal
alias: expand "$@" as list of parameters quoted individually (BC) (issue4200)...
r22158
This also handles $0, $@ and "$@".
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
Siddharth Agarwal
alias: expand "$@" as list of parameters quoted individually (BC) (issue4200)...
r22158 # util.interpolate can't deal with "$@" (with quotes) because it's only
# built to match prefix + patterns.
Augie Fackler
cleanup: run pyupgrade on our source tree to clean up varying things...
r44937 replacemap = {b'$%d' % (i + 1): arg for i, arg in enumerate(args)}
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 replacemap[b'$0'] = name
replacemap[b'$$'] = b'$'
replacemap[b'$@'] = b' '.join(args)
Siddharth Agarwal
alias: expand "$@" as list of parameters quoted individually (BC) (issue4200)...
r22158 # 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.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 replacemap[b'"$@"'] = b' '.join(procutil.shellquote(arg) for arg in args)
Siddharth Agarwal
alias: expand "$@" as list of parameters quoted individually (BC) (issue4200)...
r22158 # escape '\$' for regex
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 regex = b'|'.join(replacemap.keys()).replace(b'$', br'\$')
Siddharth Agarwal
alias: expand "$@" as list of parameters quoted individually (BC) (issue4200)...
r22158 r = re.compile(regex)
return r.sub(lambda x: replacemap[x.group()], cmd)
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
py3: use class X: instead of class X(object):...
r49801 class cmdalias:
Rodrigo Damazio
help: supporting both help and doc for aliases...
r37152 def __init__(self, ui, name, definition, cmdtable, source):
Brodie Rao
alias: make shadowing behavior more consistent (issue2054)...
r12039 self.name = self.cmd = name
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.cmdname = b''
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
Jun Wu
dispatch: defer environment variable resolution in alias commands (BC)...
r29087 self.givenargs = []
Brendan Cully
Move alias into core
r8655 self.opts = []
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.help = b''
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)
Gregory Szorc
global: bulk replace simple pycompat.iteritems(x) with x.items()...
r49768 for alias, e in cmdtable.items():
Brodie Rao
alias: make shadowing behavior more consistent (issue2054)...
r12039 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:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.badalias = _(b"no definition for alias '%s'") % self.name
Brendan Cully
Move alias into core
r8655 return
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if self.definition.startswith(b'!'):
Rodrigo Damazio
help: supporting both help and doc for aliases...
r37152 shdef = self.definition[1:]
Steve Losh
alias: only allow global options before a shell alias, pass later ones through...
r12536 self.shell = True
Augie Fackler
formatting: blacken the codebase...
r43346
Steve Losh
dispatch: add shell aliases...
r11524 def fn(ui, *args):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 env = {b'HG_ARGS': b' '.join((self.name,) + args)}
Augie Fackler
formatting: blacken the codebase...
r43346
Steve Losh
aliases: provide more flexible ways to work with shell alias arguments...
r11989 def _checkvar(m):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if m.groups()[0] == b'$':
Roman Sokolov
dispatch: support for $ escaping in shell-alias definition...
r13392 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:
Augie Fackler
formatting: blacken the codebase...
r43346 ui.debug(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"No argument found for substitution "
b"of %i variable in alias '%s' definition.\n"
Augie Fackler
formatting: blacken the codebase...
r43346 % (int(m.groups()[0]), self.name)
)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return b''
Augie Fackler
formatting: blacken the codebase...
r43346
Rodrigo Damazio
help: supporting both help and doc for aliases...
r37152 cmd = re.sub(br'\$(\d+|\$)', _checkvar, shdef)
Siddharth Agarwal
alias: expand "$@" as list of parameters quoted individually (BC) (issue4200)...
r22158 cmd = aliasinterpolate(self.name, args, cmd)
Augie Fackler
formatting: blacken the codebase...
r43346 return ui.system(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 cmd, environ=env, blockedtag=b'alias_%s' % self.name
Augie Fackler
formatting: blacken the codebase...
r43346 )
Steve Losh
dispatch: add shell aliases...
r11524 self.fn = fn
rdamazio@google.com
help: displaying documented aliases by default...
r40450 self.alias = True
Rodrigo Damazio
help: supporting both help and doc for aliases...
r37152 self._populatehelp(ui, name, shdef, self.fn)
Steve Losh
dispatch: add shell aliases...
r11524 return
Yuya Nishihara
alias: handle shlex error in command aliases...
r21569 try:
Pulkit Goyal
py3: have a bytes version of shlex.split()...
r30678 args = pycompat.shlexsplit(self.definition)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except ValueError as inst:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.badalias = _(b"error in definition for alias '%s': %s") % (
Augie Fackler
formatting: blacken the codebase...
r43346 self.name,
stringutil.forcebytestr(inst),
)
Yuya Nishihara
alias: handle shlex error in command aliases...
r21569 return
Yuya Nishihara
dispatch: replace _earlygetopt(strip=True) with new parser...
r35225 earlyopts, args = _earlysplitopts(args)
if earlyopts:
Augie Fackler
formatting: blacken the codebase...
r43346 self.badalias = _(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"error in definition for alias '%s': %s may "
b"only be given on the command line"
) % (self.name, b'/'.join(pycompat.ziplist(*earlyopts)[0]))
Yuya Nishihara
dispatch: replace _earlygetopt(strip=True) with new parser...
r35225 return
Brodie Rao
alias: print what command is being shadowed in debug message
r12092 self.cmdname = cmd = args.pop(0)
Jun Wu
dispatch: defer environment variable resolution in alias commands (BC)...
r29087 self.givenargs = args
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:
Rodrigo Damazio
help: supporting both help and doc for aliases...
r37152 self.fn, self.opts, cmdhelp = tableentry
Nicolas Dumazet
alias: do not crash when aliased command has no usage help text
r9993 else:
self.fn, self.opts = tableentry
Rodrigo Damazio
help: supporting both help and doc for aliases...
r37152 cmdhelp = None
Nicolas Dumazet
alias: do not crash when aliased command has no usage help text
r9993
rdamazio@google.com
help: displaying documented aliases by default...
r40450 self.alias = True
Rodrigo Damazio
help: supporting both help and doc for aliases...
r37152 self._populatehelp(ui, name, cmd, self.fn, cmdhelp)
Peter Arrenbrecht
alias: improve help text for command aliases...
r9876
Brendan Cully
Move alias into core
r8655 except error.UnknownCommand:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.badalias = _(
b"alias '%s' resolves to unknown command '%s'"
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 ) % (
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:
Augie Fackler
formatting: blacken the codebase...
r43346 self.badalias = _(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"alias '%s' resolves to ambiguous command '%s'"
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 ) % (
self.name,
cmd,
)
Brendan Cully
Move alias into core
r8655
Rodrigo Damazio
help: supporting both help and doc for aliases...
r37152 def _populatehelp(self, ui, name, cmd, fn, defaulthelp=None):
Yuya Nishihara
alias: reject non-ascii characters in user help/doc strings...
r37157 # confine strings to be passed to i18n.gettext()
cfg = {}
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 for k in (b'doc', b'help', b'category'):
v = ui.config(b'alias', b'%s:%s' % (name, k), None)
Yuya Nishihara
alias: reject non-ascii characters in user help/doc strings...
r37157 if v is None:
continue
if not encoding.isasciistr(v):
Augie Fackler
formatting: blacken the codebase...
r43346 self.badalias = _(
Martin von Zweigbergk
cleanup: join string literals that are already on one line...
r43387 b"non-ASCII character in alias definition '%s:%s'"
Augie Fackler
formatting: blacken the codebase...
r43346 ) % (name, k)
Yuya Nishihara
alias: reject non-ascii characters in user help/doc strings...
r37157 return
cfg[k] = v
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.help = cfg.get(b'help', defaulthelp or b'')
if self.help and self.help.startswith(b"hg " + cmd):
Rodrigo Damazio
help: supporting both help and doc for aliases...
r37152 # drop prefix in old-style help lines so hg shows the alias
Augie Fackler
formatting: blacken the codebase...
r43346 self.help = self.help[4 + len(cmd) :]
Rodrigo Damazio
help: supporting both help and doc for aliases...
r37152
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.owndoc = b'doc' in cfg
doc = cfg.get(b'doc', pycompat.getdoc(fn))
Yuya Nishihara
py3: bytes/unicode dance on __doc__ of cmdalias
r37158 if doc is not None:
doc = pycompat.sysstr(doc)
self.__doc__ = doc
Rodrigo Damazio
help: supporting both help and doc for aliases...
r37152
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 self.helpcategory = cfg.get(
b'category', registrar.command.CATEGORY_NONE
)
rdamazio@google.com
help: displaying documented aliases by default...
r40450
Jun Wu
dispatch: defer environment variable resolution in alias commands (BC)...
r29087 @property
def args(self):
Pulkit Goyal
dispatch: use pycompat.maplist() instead of map() to get a list
r31629 args = pycompat.maplist(util.expandpath, self.givenargs)
Jun Wu
dispatch: defer environment variable resolution in alias commands (BC)...
r29087 return aliasargs(self.fn, args)
Yuya Nishihara
dispatch: make cmdalias forward command attributes to function...
r28621 def __getattr__(self, name):
Augie Fackler
formatting: blacken the codebase...
r43346 adefaults = {
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 'norepo': True,
'intents': set(),
'optionalrepo': False,
'inferrepo': False,
Augie Fackler
formatting: blacken the codebase...
r43346 }
Yuya Nishihara
dispatch: make cmdalias forward command attributes to function...
r28621 if name not in adefaults:
raise AttributeError(name)
safehasattr: drop usage in favor of hasattr...
r51821 if self.badalias or hasattr(self, 'shell'):
Yuya Nishihara
dispatch: make cmdalias forward command attributes to function...
r28621 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]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 hint = _(b"'%s' is provided by '%s' extension") % (cmd, ext)
Brodie Rao
dispatch: provide help for disabled extensions and commands...
r10364 except error.UnknownCommand:
pass
Martin von Zweigbergk
errors: raise ConfigError on bad alias definition...
r46524 raise error.ConfigError(self.badalias, hint=hint)
Brendan Cully
Move alias into core
r8655 if self.shadows:
Augie Fackler
formatting: blacken the codebase...
r43346 ui.debug(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"alias '%s' shadows command '%s'\n" % (self.name, self.cmdname)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Brendan Cully
Move alias into core
r8655
Augie Fackler
formatting: blacken the codebase...
r43346 ui.log(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'commandalias',
b"alias '%s' expands to '%s'\n",
Augie Fackler
formatting: blacken the codebase...
r43346 self.name,
self.definition,
)
safehasattr: drop usage in favor of hasattr...
r51821 if hasattr(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:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 args = b' '.join([self.cmdname] + self.args)
ui.debug(b"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
Augie Fackler
formatting: blacken the codebase...
r43346
Gregory Szorc
py3: use class X: instead of class X(object):...
r49801 class lazyaliasentry:
Jun Wu
alias: make alias command lazily resolved...
r34307 """like a typical command entry (func, opts, help), but is lazy"""
Rodrigo Damazio
help: supporting both help and doc for aliases...
r37152 def __init__(self, ui, name, definition, cmdtable, source):
self.ui = ui
Jun Wu
alias: make alias command lazily resolved...
r34307 self.name = name
self.definition = definition
self.cmdtable = cmdtable.copy()
self.source = source
rdamazio@google.com
help: displaying documented aliases by default...
r40450 self.alias = True
Jun Wu
alias: make alias command lazily resolved...
r34307
@util.propertycache
def _aliasdef(self):
Augie Fackler
formatting: blacken the codebase...
r43346 return cmdalias(
self.ui, self.name, self.definition, self.cmdtable, self.source
)
Jun Wu
alias: make alias command lazily resolved...
r34307
def __getitem__(self, n):
aliasdef = self._aliasdef
if n == 0:
return aliasdef
elif n == 1:
return aliasdef.opts
elif n == 2:
return aliasdef.help
else:
raise IndexError
def __iter__(self):
for i in range(3):
yield self[i]
def __len__(self):
return 3
Augie Fackler
formatting: blacken the codebase...
r43346
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.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 for alias, definition in ui.configitems(b'alias', ignoresub=True):
Idan Kamara
dispatch: don't rewrap aliases that have the same definition...
r15019 try:
Jun Wu
alias: make alias command lazily resolved...
r34307 if cmdtable[alias].definition == definition:
Idan Kamara
dispatch: don't rewrap aliases that have the same definition...
r15019 continue
except (KeyError, AttributeError):
# definition might not exist or it might not be a cmdalias
pass
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 source = ui.configsource(b'alias', alias)
Rodrigo Damazio
help: supporting both help and doc for aliases...
r37152 entry = lazyaliasentry(ui, alias, definition, cmdtable, source)
Jun Wu
alias: make alias command lazily resolved...
r34307 cmdtable[alias] = entry
Brendan Cully
Move alias into core
r8655
Augie Fackler
formatting: blacken the codebase...
r43346
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)
Pulkit Goyal
fancyopts: switch from fancyopts.getopt.* to getopt.*...
r30576 except getopt.GetoptError as inst:
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 raise error.CommandError(None, stringutil.forcebytestr(inst))
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
if args:
cmd, args = args[0], args[1:]
Augie Fackler
formatting: blacken the codebase...
r43346 aliases, entry = cmdutil.findcmd(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 cmd, commands.table, ui.configbool(b"ui", b"strict")
Augie Fackler
formatting: blacken the codebase...
r43346 )
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)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 defaults = ui.config(b"defaults", cmd)
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 if defaults:
Augie Fackler
formatting: blacken the codebase...
r43346 args = (
pycompat.maplist(util.expandpath, pycompat.shlexsplit(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
dispatch: explicitly pass fancyopts optional arg as a keyword...
r29822 args = fancyopts.fancyopts(args, c, cmdoptions, gnu=True)
Pulkit Goyal
fancyopts: switch from fancyopts.getopt.* to getopt.*...
r30576 except getopt.GetoptError as inst:
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 raise error.CommandError(cmd, stringutil.forcebytestr(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
Augie Fackler
formatting: blacken the codebase...
r43346
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:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 name, value = [cfgelem.strip() for cfgelem in cfg.split(b'=', 1)]
section, name = name.split(b'.', 1)
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 if not section or not name:
raise IndexError
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.setconfig(section, name, value, b'--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):
Martin von Zweigbergk
errors: raise InputError on early parse error in dispatch...
r46734 raise error.InputError(
Augie Fackler
formatting: blacken the codebase...
r43346 _(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'malformed --config option: %r '
b'(use --config section.name=value)'
Augie Fackler
formatting: blacken the codebase...
r43346 )
% pycompat.bytestr(cfg)
)
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
Idan Kamara
dispatch: return read config options
r14753 return configs
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
dispatch: replace _earlyreq*() with new fancyopts-based parser
r35224 def _earlyparseopts(ui, args):
Yuya Nishihara
dispatch: add HGPLAIN=+strictflags to restrict early parsing of global options...
r35180 options = {}
Augie Fackler
formatting: blacken the codebase...
r43346 fancyopts.fancyopts(
args,
commands.globalopts,
options,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 gnu=not ui.plain(b'strictflags'),
Augie Fackler
formatting: blacken the codebase...
r43346 early=True,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 optaliases={b'repository': [b'repo']},
Augie Fackler
formatting: blacken the codebase...
r43346 )
Yuya Nishihara
dispatch: add HGPLAIN=+strictflags to restrict early parsing of global options...
r35180 return options
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
dispatch: replace _earlygetopt(strip=True) with new parser...
r35225 def _earlysplitopts(args):
"""Split args into a list of possible early options and remainder args"""
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 shortoptions = b'R:'
Yuya Nishihara
dispatch: replace _earlygetopt(strip=True) with new parser...
r35225 # TODO: perhaps 'debugger' should be included
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 longoptions = [b'cwd=', b'repository=', b'repo=', b'config=']
Augie Fackler
formatting: blacken the codebase...
r43346 return fancyopts.earlygetopt(
args, shortoptions, longoptions, gnu=True, keepsep=True
)
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
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
Augie Fackler
formatting: blacken the codebase...
r43346 hook.hook(
lui,
repo,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"pre-%s" % cmd,
Augie Fackler
formatting: blacken the codebase...
r43346 True,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 args=b" ".join(fullargs),
Augie Fackler
formatting: blacken the codebase...
r43346 pats=cmdpats,
opts=cmdoptions,
)
Jordi Gutiérrez Hermoso
dispatch: add fail-* family of hooks...
r29129 try:
ret = _runcommand(ui, options, cmd, d)
# run post-hook, passing command result
Augie Fackler
formatting: blacken the codebase...
r43346 hook.hook(
lui,
repo,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"post-%s" % cmd,
Augie Fackler
formatting: blacken the codebase...
r43346 False,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 args=b" ".join(fullargs),
Augie Fackler
formatting: blacken the codebase...
r43346 result=ret,
pats=cmdpats,
opts=cmdoptions,
)
Jordi Gutiérrez Hermoso
dispatch: add fail-* family of hooks...
r29129 except Exception:
# run failure hook and re-raise
Augie Fackler
formatting: blacken the codebase...
r43346 hook.hook(
lui,
repo,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"fail-%s" % cmd,
Augie Fackler
formatting: blacken the codebase...
r43346 False,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 args=b" ".join(fullargs),
Augie Fackler
formatting: blacken the codebase...
r43346 pats=cmdpats,
opts=cmdoptions,
)
Jordi Gutiérrez Hermoso
dispatch: add fail-* family of hooks...
r29129 raise
Bill Barry
dispatch: extract command execution block into method...
r7819 return ret
Augie Fackler
formatting: blacken the codebase...
r43346
Pulkit Goyal
dispatch: load shared source repository config in share-safe mode...
r46367 def _readsharedsourceconfig(ui, path):
"""if the current repository is shared one, this tries to read
.hg/hgrc of shared source if we are in share-safe mode
Config read is loaded into the ui object passed
This should be called before reading .hg/hgrc or the main repo
as that overrides config set in shared source"""
try:
with open(os.path.join(path, b".hg", b"requires"), "rb") as fp:
requirements = set(fp.read().splitlines())
if not (
requirementsmod.SHARESAFE_REQUIREMENT in requirements
and requirementsmod.SHARED_REQUIREMENT in requirements
):
return
hgvfs = vfs.vfs(os.path.join(path, b".hg"))
sharedvfs = localrepo._getsharedvfs(hgvfs, requirements)
Pulkit Goyal
dispatch: pass root path in ui.readconfig() as root of main repo...
r46532 root = sharedvfs.base
ui.readconfig(sharedvfs.join(b"hgrc"), root)
Pulkit Goyal
dispatch: load shared source repository config in share-safe mode...
r46367 except IOError:
pass
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."
"""
Arun Kulshreshtha
dispatch: change cwd when loading local config...
r50317 try:
cwd = encoding.getcwd()
except OSError as e:
raise error.Abort(
_(b"error getting current working directory: %s")
% encoding.strtolocal(e.strerror)
)
# If using an alternate wd, temporarily switch to it so that relative
# paths are resolved correctly during config loading.
oldcwd = None
Jun Wu
dispatch: add wd parameter to _getlocal...
r28263 if wd is None:
Arun Kulshreshtha
dispatch: change cwd when loading local config...
r50317 wd = cwd
else:
oldcwd = cwd
os.chdir(wd)
config: also respect HGRCSKIPREPO in `dispatch._getlocal`...
r44728
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 path = cmdutil.findrepo(wd) or b""
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()
config: also respect HGRCSKIPREPO in `dispatch._getlocal`...
r44728 if rcutil.use_repo_hgrc():
Pulkit Goyal
dispatch: load shared source repository config in share-safe mode...
r46367 _readsharedsourceconfig(lui, path)
config: also respect HGRCSKIPREPO in `dispatch._getlocal`...
r44728 lui.readconfig(os.path.join(path, b".hg", b"hgrc"), path)
Pulkit Goyal
config: add a .hg/hgrc-not-shared which won't be shared in share-safe mode...
r46368 lui.readconfig(os.path.join(path, b".hg", b"hgrc-not-shared"), path)
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
Yuya Nishihara
dispatch: convert non-list option parsed by _earlygetopt() to string...
r35062 if rpath:
path: use `get_clone_path_obj` in _getlocal...
r50637 path_obj = urlutil.get_clone_path_obj(lui, rpath)
path = path_obj.rawloc
Matt Mackall
ui: kill most users of parentui name and arg, replace with .copy()
r8190 lui = ui.copy()
config: also respect HGRCSKIPREPO in `dispatch._getlocal`...
r44728 if rcutil.use_repo_hgrc():
Pulkit Goyal
dispatch: load shared source repository config in share-safe mode...
r46367 _readsharedsourceconfig(lui, path)
config: also respect HGRCSKIPREPO in `dispatch._getlocal`...
r44728 lui.readconfig(os.path.join(path, b".hg", b"hgrc"), path)
Pulkit Goyal
config: add a .hg/hgrc-not-shared which won't be shared in share-safe mode...
r46368 lui.readconfig(os.path.join(path, b".hg", b"hgrc-not-shared"), path)
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
Arun Kulshreshtha
dispatch: change cwd when loading local config...
r50317 if oldcwd:
os.chdir(oldcwd)
Steve Losh
alias: only allow global options before a shell alias, pass later ones through...
r12536 return path, lui
Augie Fackler
formatting: blacken the codebase...
r43346
Jun Wu
dispatch: always load extensions before running shell aliases (issue5230)...
r29132 def _checkshellalias(lui, ui, args):
"""Return the function to run the shell alias, if it is required"""
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)
Pulkit Goyal
fancyopts: switch from fancyopts.getopt.* to getopt.*...
r30576 except getopt.GetoptError:
Steve Losh
alias: fail gracefully when invalid global options are given (issue2442)...
r12748 return
Steve Losh
alias: only allow global options before a shell alias, pass later ones through...
r12536
if not args:
return
Jun Wu
dispatch: always load extensions before running shell aliases (issue5230)...
r29132 cmdtable = commands.table
Steve Losh
alias: only allow global options before a shell alias, pass later ones through...
r12536
cmd = args[0]
try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 strict = ui.configbool(b"ui", b"strict")
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]
safehasattr: drop usage in favor of hasattr...
r51821 if cmd and hasattr(fn, 'shell'):
Yuya Nishihara
dispatch: verify result of early command parsing...
r35063 # shell alias shouldn't receive early options which are consumed by hg
Yuya Nishihara
dispatch: replace _earlygetopt(strip=True) with new parser...
r35225 _earlyopts, args = _earlysplitopts(args)
Steve Losh
alias: only allow global options before a shell alias, pass later ones through...
r12536 d = lambda: fn(ui, *args[1:])
Augie Fackler
formatting: blacken the codebase...
r43346 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
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
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 cwd = req.earlyoptions[b'cwd']
Steve Losh
alias: only allow global options before a shell alias, pass later ones through...
r12536 if cwd:
Yuya Nishihara
dispatch: convert non-list option parsed by _earlygetopt() to string...
r35062 os.chdir(cwd)
Steve Losh
alias: only allow global options before a shell alias, pass later ones through...
r12536
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 rpath = req.earlyoptions[b'repository']
Steve Losh
alias: only allow global options before a shell alias, pass later ones through...
r12536 path, lui = _getlocal(ui, rpath)
Martin von Zweigbergk
cleanup: use set literals...
r32291 uis = {ui, lui}
Bryan O'Sullivan
dispatch: move detection of profiling earlier during startup
r30933
if req.repo:
uis.add(req.repo.ui)
Augie Fackler
formatting: blacken the codebase...
r43346 if (
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 req.earlyoptions[b'verbose']
or req.earlyoptions[b'debug']
or req.earlyoptions[b'quiet']
Augie Fackler
formatting: blacken the codebase...
r43346 ):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 for opt in (b'verbose', b'debug', b'quiet'):
Boris Feld
debug: process --debug flag earlier...
r38552 val = pycompat.bytestr(bool(req.earlyoptions[opt]))
for ui_ in uis:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui_.setconfig(b'ui', opt, val, b'--' + opt)
Boris Feld
debug: process --debug flag earlier...
r38552
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if req.earlyoptions[b'profile']:
Bryan O'Sullivan
dispatch: move detection of profiling earlier during startup
r30933 for ui_ in uis:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui_.setconfig(b'profiling', b'enabled', b'true', b'--profile')
Kyle Lippincott
profiling: add --no-profile to disable profiling enabled via config...
r47787 elif req.earlyoptions[b'profile'] is False:
# Check for it being set already, so that we don't pollute the config
# with this when using chg in the very common case that it's not
# enabled.
if lui.configbool(b'profiling', b'enabled'):
# Only do this on lui so that `chg foo` with a user config setting
# profiling.enabled=1 still shows profiling information (chg will
# specify `--no-profile` when `hg serve` is starting up, we don't
# want that to propagate to every later invocation).
lui.setconfig(b'profiling', b'enabled', b'false', b'--no-profile')
Bryan O'Sullivan
dispatch: move detection of profiling earlier during startup
r30933
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 profile = lui.configbool(b'profiling', b'enabled')
profile: drop maybeprofile...
r32788 with profiling.profile(lui, enabled=profile) as profiler:
Bryan O'Sullivan
dispatch: start profiling earlier...
r30934 # Configure extensions in phases: uisetup, extsetup, cmdtable, and
FUJIWARA Katsunori
dispatch: remove unused _loaded...
r33053 # reposetup
Bryan O'Sullivan
dispatch: start profiling earlier...
r30934 extensions.loadall(lui)
# Propagate any changes to lui.__class__ by extensions
ui.__class__ = lui.__class__
Kirill Smelkov
dispatch: allow extensions to provide setup code...
r5828
Bryan O'Sullivan
dispatch: start profiling earlier...
r30934 # (uisetup and extsetup are handled in extensions.loadall)
Kirill Smelkov
dispatch: allow extensions to provide setup code...
r5828
Bryan O'Sullivan
dispatch: start profiling earlier...
r30934 # (reposetup is handled in hg.repository)
Martin Geisler
extensions: load and configure extensions in well-defined phases...
r9410
Bryan O'Sullivan
dispatch: start profiling earlier...
r30934 addaliases(lui, commands.table)
Brendan Cully
Move alias into core
r8655
Bryan O'Sullivan
dispatch: start profiling earlier...
r30934 # All aliases and commands are completely defined, now.
# Check abbreviation/ambiguity of shell alias.
shellaliasfn = _checkshellalias(lui, ui, args)
if shellaliasfn:
Yuya Nishihara
extensions: add "uipopulate" hook, called per instance, not per process...
r40760 # no additional configs will be set, set up the ui instances
for ui_ in uis:
extensions.populateui(ui_)
Arun Kulshreshtha
dispatch: make hg --profile wrap reposetup...
r30006 return shellaliasfn()
FUJIWARA Katsunori
dispatch: check shell alias again after loading extensions (issue4355)...
r22377
Bryan O'Sullivan
dispatch: start profiling earlier...
r30934 # check for fallback encoding
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 fallback = lui.config(b'ui', b'fallbackencoding')
Bryan O'Sullivan
dispatch: start profiling earlier...
r30934 if fallback:
encoding.fallbackencoding = fallback
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
Bryan O'Sullivan
dispatch: start profiling earlier...
r30934 fullargs = args
cmd, func, args, options, cmdoptions = _parse(lui, args)
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
Boris Feld
logtoprocess: sends the canonical command name to the subprocess...
r40438 # store the canonical command name in request object for later access
req.canonical_command = cmd
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if options[b"config"] != req.earlyoptions[b"config"]:
Martin von Zweigbergk
errors: raise InputError on bad top-level flags...
r46530 raise error.InputError(_(b"option --config may not be abbreviated"))
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if options[b"cwd"] != req.earlyoptions[b"cwd"]:
Martin von Zweigbergk
errors: raise InputError on bad top-level flags...
r46530 raise error.InputError(_(b"option --cwd may not be abbreviated"))
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if options[b"repository"] != req.earlyoptions[b"repository"]:
Martin von Zweigbergk
errors: raise InputError on bad top-level flags...
r46530 raise error.InputError(
Augie Fackler
formatting: blacken the codebase...
r43346 _(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"option -R has to be separated from other options (e.g. not "
Martin von Zweigbergk
errors: remove trailing "!" in messages about bad top-level args...
r46521 b"-qR) and --repository may only be abbreviated as --repo"
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if options[b"debugger"] != req.earlyoptions[b"debugger"]:
Martin von Zweigbergk
errors: raise InputError on bad top-level flags...
r46530 raise error.InputError(
_(b"option --debugger may not be abbreviated")
)
Yuya Nishihara
dispatch: abort if early boolean options can't be parsed...
r35059 # don't validate --profile/--traceback, which can be enabled from now
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if options[b"encoding"]:
encoding.encoding = options[b"encoding"]
if options[b"encodingmode"]:
encoding.encodingmode = options[b"encodingmode"]
if options[b"time"]:
Augie Fackler
formatting: blacken the codebase...
r43346
Bryan O'Sullivan
dispatch: start profiling earlier...
r30934 def get_times():
t = os.times()
if t[4] == 0.0:
Matt Harbison
py3: replace `time.clock()` with `time.perf_counter()`...
r44469 # Windows leaves this as zero, so use time.perf_counter()
t = (t[0], t[1], t[2], t[3], util.timer())
Bryan O'Sullivan
dispatch: start profiling earlier...
r30934 return t
Augie Fackler
formatting: blacken the codebase...
r43346
Bryan O'Sullivan
dispatch: start profiling earlier...
r30934 s = get_times()
Augie Fackler
formatting: blacken the codebase...
r43346
Bryan O'Sullivan
dispatch: start profiling earlier...
r30934 def print_time():
t = get_times()
ui.warn(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n")
Augie Fackler
formatting: blacken the codebase...
r43346 % (
t[4] - s[4],
t[0] - s[0],
t[2] - s[2],
t[1] - s[1],
t[3] - s[3],
)
)
Bryan O'Sullivan
atexit: switch to home-grown implementation
r31958 ui.atexit(print_time)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if options[b"profile"]:
profile: support --profile in alias and abbreviated version (--prof)...
r32787 profiler.start()
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
Boris Feld
debug: process --debug flag earlier...
r38552 # if abbreviated version of this were used, take them in account, now
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if options[b'verbose'] or options[b'debug'] or options[b'quiet']:
for opt in (b'verbose', b'debug', b'quiet'):
Boris Feld
debug: process --debug flag earlier...
r38552 if options[opt] == req.earlyoptions[opt]:
continue
Yuya Nishihara
py3: replace "if ispy3" by pycompat.bytestr()
r35916 val = pycompat.bytestr(bool(options[opt]))
Bryan O'Sullivan
dispatch: start profiling earlier...
r30934 for ui_ in uis:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui_.setconfig(b'ui', opt, val, b'--' + opt)
Bryan O'Sullivan
dispatch: start profiling earlier...
r30934
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if options[b'traceback']:
Idan Kamara
dispatch: set global options on the request repo.ui...
r14752 for ui_ in uis:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui_.setconfig(b'ui', b'traceback', b'on', b'--traceback')
Idan Kamara
dispatch: make sure global options on the command line take precedence...
r14992
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if options[b'noninteractive']:
Bryan O'Sullivan
dispatch: start profiling earlier...
r30934 for ui_ in uis:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui_.setconfig(b'ui', b'interactive', b'off', b'-y')
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if cmdoptions.get(b'insecure', False):
Bryan O'Sullivan
dispatch: start profiling earlier...
r30934 for ui_ in uis:
ui_.insecureconnections = True
Yuya Nishihara
url: add --insecure option to bypass verification of ssl certificates...
r13328
FUJIWARA Katsunori
dispatch: setup color before pager for correct console information on windows...
r32404 # setup color handling before pager, because setting up pager
# might cause incorrect console information
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 coloropt = options[b'color']
Pierre-Yves David
color: move triggering of the initialisation logic in core...
r31105 for ui_ in uis:
Pierre-Yves David
color: add a 'ui.color' option to control color behavior...
r31110 if coloropt:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui_.setconfig(b'ui', b'color', coloropt, b'--color')
Pierre-Yves David
color: add a 'ui.color' option to control color behavior...
r31110 color.setup(ui_)
Pierre-Yves David
color: move triggering of the initialisation logic in core...
r31105
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if stringutil.parsebool(options[b'pager']):
FUJIWARA Katsunori
ui: enable pager always for explicit --pager=on (issue5580)...
r33622 # ui.pager() expects 'internal-always-' prefix in this case
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.pager(b'internal-always-' + cmd)
elif options[b'pager'] != b'auto':
Jun Wu
dispatch: when --pager=no is passed, also disable pager on req.repo.ui...
r34639 for ui_ in uis:
ui_.disablepager()
FUJIWARA Katsunori
dispatch: setup color before pager for correct console information on windows...
r32404
Yuya Nishihara
extensions: add "uipopulate" hook, called per instance, not per process...
r40760 # configs are fully loaded, set up the ui instances
for ui_ in uis:
extensions.populateui(ui_)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if options[b'version']:
Bryan O'Sullivan
dispatch: start profiling earlier...
r30934 return commands.version_(ui)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if options[b'help']:
Bryan O'Sullivan
dispatch: start profiling earlier...
r30934 return commands.help_(ui, cmd, command=cmd is not None)
elif not cmd:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 return commands.help_(ui, b'shortlist')
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
Arun Kulshreshtha
dispatch: change indentation level in _dispatch()...
r30005 repo = None
cmdpats = args[:]
Augie Fackler
dispatch: add some assertions to give pytype a helping hand...
r44105 assert func is not None # help out pytype
Augie Fackler
dispatch: stop supporting non-use of @command...
r30485 if not func.norepo:
Arun Kulshreshtha
dispatch: change indentation level in _dispatch()...
r30005 # use the repo from the request only if we don't have -R
if not rpath and not cwd:
repo = req.repo
Idan Kamara
dispatch: add repo to the request...
r14510
Arun Kulshreshtha
dispatch: change indentation level in _dispatch()...
r30005 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
Yuya Nishihara
dispatch: pass around ui.fmsg channel...
r40623 repo.ui.fmsg = ui.fmsg
Arun Kulshreshtha
dispatch: change indentation level in _dispatch()...
r30005 else:
try:
Augie Fackler
formatting: blacken the codebase...
r43346 repo = hg.repository(
ui,
path=path,
presetupfuncs=req.prereposetups,
intents=func.intents,
)
Arun Kulshreshtha
dispatch: change indentation level in _dispatch()...
r30005 if not repo.local():
Martin von Zweigbergk
errors: raise InputError on bad repo arguments...
r46523 raise error.InputError(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"repository '%s' is not local") % path
Augie Fackler
formatting: blacken the codebase...
r43346 )
repo.ui.setconfig(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"bundle", b"mainreporoot", repo.root, b'repo'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Arun Kulshreshtha
dispatch: change indentation level in _dispatch()...
r30005 except error.RequirementError:
Yuya Nishihara
dispatch: error out on invalid -R path even if optionalrepo (issue4805) (BC)...
r26142 raise
Arun Kulshreshtha
dispatch: change indentation level in _dispatch()...
r30005 except error.RepoError:
Augie Fackler
formatting: blacken the codebase...
r43346 if rpath: # invalid -R path
Arun Kulshreshtha
dispatch: change indentation level in _dispatch()...
r30005 raise
Augie Fackler
dispatch: stop supporting non-use of @command...
r30485 if not func.optionalrepo:
if func.inferrepo and args and not path:
Arun Kulshreshtha
dispatch: change indentation level in _dispatch()...
r30005 # try to infer -R from command args
Pulkit Goyal
py3: use pycompat.maplist() instead of map()...
r35150 repos = pycompat.maplist(cmdutil.findrepo, args)
Arun Kulshreshtha
dispatch: change indentation level in _dispatch()...
r30005 guess = repos[0]
if guess and repos.count(guess) == len(repos):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 req.args = [b'--repository', guess] + fullargs
req.earlyoptions[b'repository'] = guess
Arun Kulshreshtha
dispatch: change indentation level in _dispatch()...
r30005 return _dispatch(req)
if not path:
Martin von Zweigbergk
errors: raise InputError on bad repo arguments...
r46523 raise error.InputError(
Augie Fackler
formatting: blacken the codebase...
r43346 _(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"no repository found in"
b" '%s' (.hg not found)"
Augie Fackler
formatting: blacken the codebase...
r43346 )
% encoding.getcwd()
)
Arun Kulshreshtha
dispatch: change indentation level in _dispatch()...
r30005 raise
if repo:
ui = repo.ui
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if options[b'hidden']:
Arun Kulshreshtha
dispatch: change indentation level in _dispatch()...
r30005 repo = repo.unfiltered()
args.insert(0, repo)
elif rpath:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.warn(_(b"warning: --repository ignored\n"))
Matt Mackall
dispatch: generalize signature checking for extension command wrapping
r7388
Augie Fackler
dispatch: consolidate formatting of arguments...
r31492 msg = _formatargs(fullargs)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ui.log(b"command", b'%s\n', msg)
Pulkit Goyal
py3: make keys of keyword arguments strings...
r30586 strcmdopt = pycompat.strkwargs(cmdoptions)
d = lambda: util.checksignature(func)(ui, *args, **strcmdopt)
Arun Kulshreshtha
dispatch: change indentation level in _dispatch()...
r30005 try:
Augie Fackler
formatting: blacken the codebase...
r43346 return runcommand(
lui, repo, cmd, fullargs, ui, options, d, cmdpats, cmdoptions
)
Arun Kulshreshtha
dispatch: change indentation level in _dispatch()...
r30005 finally:
if repo and repo != req.repo:
repo.close()
Matt Mackall
dispatch: move command dispatching into its own module...
r5178
Augie Fackler
formatting: blacken the codebase...
r43346
Matt Mackall
dispatch: move command dispatching into its own module...
r5178 def _runcommand(ui, options, cmd, cmdfunc):
Gregory Szorc
profiling: add a context manager that no-ops if profiling isn't enabled...
r29784 """Run a command function, possibly with profiling enabled."""
Arun Kulshreshtha
dispatch: make hg --profile wrap reposetup...
r30006 try:
Augie Fackler
cleanup: hgdemandimport.tracing accepts strings, not bytes...
r43532 with tracing.log("Running %s command" % cmd):
Boris Feld
tracing: trace command function execution...
r39548 return cmdfunc()
Arun Kulshreshtha
dispatch: make hg --profile wrap reposetup...
r30006 except error.SignatureError:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.CommandError(cmd, _(b'invalid arguments'))
Martijn Pieters
dispatch: factor out command failure handling into a function...
r28784
Augie Fackler
formatting: blacken the codebase...
r43346
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)
Matt Harbison
dispatch: print the version of the extension being blamed in a bug report...
r46563 worst = None, ct, b'', b''
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if ui.config(b'ui', b'supportcontact') is None:
Martijn Pieters
dispatch: factor out command failure handling into a function...
r28784 for name, mod in extensions.extensions():
Yuya Nishihara
py3: replace "if ispy3" by pycompat.sysbytes() or util.forcebytestr()
r35917 # 'testedwith' should be bytes, but not all extensions are ported
# to py3 and we don't want UnicodeException because of that.
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 testedwith = stringutil.forcebytestr(
getattr(mod, 'testedwith', b'')
)
Matt Harbison
dispatch: print the version of the extension being blamed in a bug report...
r46563 version = extensions.moduleversion(mod)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 report = getattr(mod, 'buglink', _(b'the extension author.'))
Martijn Pieters
dispatch: factor out command failure handling into a function...
r28784 if not testedwith.strip():
# We found an untested extension. It's likely the culprit.
Matt Harbison
dispatch: print the version of the extension being blamed in a bug report...
r46563 worst = name, b'unknown', report, version
Martijn Pieters
dispatch: factor out command failure handling into a function...
r28784 break
# Never blame on extensions bundled with Mercurial.
Yuya Nishihara
extensions: use ismoduleinternal() thoroughly...
r29884 if extensions.ismoduleinternal(mod):
Martijn Pieters
dispatch: factor out command failure handling into a function...
r28784 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]:
Matt Harbison
dispatch: print the version of the extension being blamed in a bug report...
r46563 worst = name, nearest, report, version
Martijn Pieters
dispatch: factor out command failure handling into a function...
r28784 if worst[0] is not None:
Matt Harbison
dispatch: print the version of the extension being blamed in a bug report...
r46563 name, testedwith, report, version = worst
Augie Fackler
dispatch: allow testedwith to be bytes or str
r31179 if not isinstance(testedwith, (bytes, str)):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 testedwith = b'.'.join(
Augie Fackler
formatting: blacken the codebase...
r43346 [stringutil.forcebytestr(c) for c in testedwith]
)
Matt Harbison
dispatch: print the version of the extension being blamed in a bug report...
r46563 extver = version or _(b"(version N/A)")
Augie Fackler
formatting: blacken the codebase...
r43346 warning = _(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'** Unknown exception encountered with '
Matt Harbison
dispatch: quote the extension when printing the bug report...
r46564 b'possibly-broken third-party extension "%s" %s\n'
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'** which supports versions %s of Mercurial.\n'
Matt Harbison
dispatch: quote the extension when printing the bug report...
r46564 b'** Please disable "%s" and try your action again.\n'
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'** If that fixes the bug please report it to %s\n'
Matt Harbison
dispatch: print the version of the extension being blamed in a bug report...
r46563 ) % (name, extver, testedwith, name, stringutil.forcebytestr(report))
Martijn Pieters
dispatch: factor out command failure handling into a function...
r28784 else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 bugtracker = ui.config(b'ui', b'supportcontact')
Martijn Pieters
dispatch: factor out command failure handling into a function...
r28784 if bugtracker is None:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 bugtracker = _(b"https://mercurial-scm.org/wiki/BugTracker")
Augie Fackler
formatting: blacken the codebase...
r43346 warning = (
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"** unknown exception encountered, "
b"please report by visiting\n** "
Augie Fackler
formatting: blacken the codebase...
r43346 )
+ bugtracker
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 + b'\n'
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 sysversion = pycompat.sysbytes(sys.version).replace(b'\n', b'')
Matt Harbison
dispatch: print the version of each extension in the bug report, if available...
r46566
def ext_with_ver(x):
ext = x[0]
ver = extensions.moduleversion(x[1])
if ver:
ext += b' ' + ver
return ext
Augie Fackler
formatting: blacken the codebase...
r43346 warning += (
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 (_(b"** Python %s\n") % sysversion)
+ (_(b"** Mercurial Distributed SCM (version %s)\n") % util.version())
Augie Fackler
formatting: blacken the codebase...
r43346 + (
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"** Extensions loaded: %s\n")
Matt Harbison
dispatch: print the version of each extension in the bug report, if available...
r46566 % b", ".join(
[ext_with_ver(x) for x in sorted(extensions.extensions())]
)
Augie Fackler
formatting: blacken the codebase...
r43346 )
)
Martijn Pieters
dispatch: split out warning message generation to separate function...
r28821 return warning
Augie Fackler
formatting: blacken the codebase...
r43346
Martijn Pieters
dispatch: split out warning message generation to separate function...
r28821 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)
Augie Fackler
formatting: blacken the codebase...
r43346 ui.log(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"commandexception",
b"%s\n%s\n",
Augie Fackler
formatting: blacken the codebase...
r43346 warning,
pycompat.sysbytes(traceback.format_exc()),
)
Martijn Pieters
dispatch: factor out command failure handling into a function...
r28784 ui.warn(warning)
return False # re-raise the exception