in eden/scm/edenscm/mercurial/dispatch.py [0:0]
def dispatch(req):
"run the command specified in req.args"
if req.ferr:
ferr = req.ferr
elif req.ui:
ferr = req.ui.ferr
else:
ferr = util.stderr
try:
if not req.ui:
req.ui = uimod.ui.load()
req.earlyoptions.update(_earlyparseopts(req.ui, req.args))
if req.earlyoptions["traceback"] or req.earlyoptions["trace"]:
req.ui.setconfig("ui", "traceback", "on", "--traceback")
# 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
except error.Abort as inst:
ferr.write(_("abort: %s\n") % inst)
if inst.hint:
ferr.write(_("(%s)\n") % inst.hint)
return -1
except error.ParseError as inst:
_formatparse(ferr.write, inst)
return -1
if req.ui.configbool("ui", "threaded"):
util.preregistersighandlers()
cmdmsg = _formatargs(req.args)
starttime = util.timer()
ret = None
retmask = 255
def logatexit():
ui = req.ui
if ui.logmeasuredtimes:
ui.log("measuredtimes", **(ui._measuredtimes))
hgmetrics = bindings.hgmetrics.summarize()
if hgmetrics:
# Comma-separated list of metric prefixes to skip
# TODO(meyer): Just skip printing metrics, rather than skipping logging them entirely.
skip = ui.configlist("devel", "skip-metrics", [])
# Re-arrange metrics so "a_b_c", "a_b_d", "a_c" becomes
# {'a': {'b': {'c': ..., 'd': ...}, 'c': ...}
metrics = {}
splitre = re.compile(r"_|/|\.")
for key, value in hgmetrics.items():
for prefix in skip:
if key.startswith(prefix):
break
else:
cur = metrics
names = splitre.split(key)
for name in names[:-1]:
cur = cur.setdefault(name, {})
cur[names[-1]] = value
# pprint.pformat stablizes the output
from pprint import pformat
if metrics:
# developer config: devel.print-metrics
if ui.configbool("devel", "print-metrics"):
# Print it out.
msg = "%s\n" % pformat({"metrics": metrics}).replace("'", " ")
ui.flush()
ui.write_err(msg, label="hgmetrics")
# Write to blackbox, and sampling
ui.log(
"metrics", pformat({"metrics": metrics}, width=1024), **hgmetrics
)
blackbox.sync()
if util.isoldversion():
hintutil.trigger("old-version")
# by registering this exit handler here, we guarantee that it runs
# after other exithandlers, like the killpager one
req.ui.atexit(logatexit)
try:
ret = _runcatch(req)
except error.ProgrammingError as inst:
req.ui.warn(_("** ProgrammingError: %s\n") % inst)
if inst.hint:
req.ui.warn(_("** (%s)\n") % inst.hint)
raise
except KeyboardInterrupt as inst:
try:
if isinstance(inst, error.SignalInterrupt):
msg = _("killed!\n")
else:
msg = _("interrupted!\n")
req.ui.warn(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
except IOError as inst:
if inst.errno != errno.EPIPE:
raise
ret = -1
except IOError as inst:
# Windows does not have SIGPIPE, so pager exit does not
# get raised as a SignalInterrupt. Let's handle the error
# explicitly here
if not pycompat.iswindows or inst.errno != errno.EINVAL:
raise
ret = -1
finally:
duration = util.timer() - starttime
req.ui.flush()
req.ui.log(
"command_finish",
"%s exited %d after %0.2f seconds\n",
cmdmsg,
ret or 0,
duration,
)
threshold = req.ui.configint("tracing", "threshold")
if duration >= threshold:
key = "flat/perftrace-%(host)s-%(pid)s-%(time)s" % {
"host": socket.gethostname(),
"pid": os.getpid(),
"time": time.time(),
}
# TODO: Move this into a background task that renders from
# blackbox instead.
# The "duration" is chosen dynamically for long commands.
# The ASCII implementation will fold repetitive calls so
# the length of the output is practically bounded.
output = bindings.tracing.singleton.ascii(
# Minimum resolution = 1% of max(duration, threshold)
# It's in microseconds (1e6) to divide it by 100 = 1e4
int((max([duration, threshold]) * 1e4))
)
if req.ui.configbool("tracing", "stderr"):
req.ui.warn("%s\n" % output)
req.ui.log("perftrace", "Trace:\n%s\n", output, key=key, payload=output)
req.ui.log("perftracekey", "Trace key:%s\n", key, perftracekey=key)
def truncateduration(duration):
"""Truncate the passed in duration to only 3 significant digits."""
millis = int(duration * 1000)
if millis < 1000:
return millis
for power in range(3, 19):
threshold = 10 ** power
if millis < threshold:
factor = int(threshold / 1000)
return int(millis / factor) * factor
return millis
req.ui._measuredtimes["command_duration"] = truncateduration(duration)
retmask = req.ui.configint("ui", "exitcodemask")
try:
req._runexithandlers()
except: # exiting, so no re-raises
ret = ret or -1
if ret is None:
ret = 0
return ret & retmask