##// END OF EJS Templates
debug-revlog: details about non-ancestors delta-bases...
debug-revlog: details about non-ancestors delta-bases Deltas against a base that is not an ancestor of the revision that owns this delta are notable. For example, they introduce complexity during the bundling process as the base might not exist on the unbundling side. We detect them in `hg debugrevlog` and print information about them.

File last commit:

r50317:3681a476 default
r50556:511106bc default
Show More
dispatch.py
1382 lines | 45.8 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
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 _
Gregory Szorc
py3: manually import getattr where it is needed...
r43359 from .pycompat import getattr
Gregory Szorc
dispatch: use absolute_import...
r25932
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,
config: also respect HGRCSKIPREPO in `dispatch._getlocal`...
r44728 rcutil,
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
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
Bryan O'Sullivan
ui: add special-purpose atexit functionality...
r31956 def _runexithandlers(self):
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.
if util.safehasattr(ui, b'fout'):
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
if util.safehasattr(ui, b'ferr'):
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,
}
if util.safehasattr(sys.stdout, "write_through"):
# 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,
}
if util.safehasattr(sys.stderr, "write_through"):
# 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
def _rundispatch(req):
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',
Augie Fackler
formatting: blacken the codebase...
r43346 **pycompat.strkwargs(req.ui._blockedtimes)
)
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:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 for name in b'SIGBREAK', b'SIGHUP', b'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.
Augie Fackler
formatting: blacken the codebase...
r43346 if (
len(req.args) != 4
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'
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:
debugmod = __import__(debugger)
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
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not util.safehasattr(fn, b'_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)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if self.badalias or util.safehasattr(self, b'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,
)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if util.safehasattr(self, b'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:
dispatch: use the new API to resolve --repository...
r47719 path = urlutil.get_clone_path(lui, rpath)[0]
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]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if cmd and util.safehasattr(fn, b'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