sapling/errorredirect.py
Jun Wu a6e1589c4f errorredirect: wrap handlecommandexception instead of sys.exit
Summary:
Since `handlecommandexception` is in core, wrap it to suppress original
crash text, instead of doing an ugly `sys.exit()`. It's much simpler and
cleaner than before. It also fixes an issue with current chg since chgserver
will print an traceback when it encounters SystemExit.

Although `logtoprocess` are doing very similar things with `errorredirect`,
it currently cannot replace `errorredirect` because we need synchronized
behavior to return the user to their shell prompt correctly. If we can get
the synchronized behavior and a way to disable builtin warning (may be tricky)
in `logtoprocess` upstream, the `errorredirect` extension could be just a thin
wrapper around `logtoprocess` using `setconfig`.

Besides, we no longer need `suppresscommandfailure` since the feature will
be either in `errorredirect` or `logtoprocess`.

Test Plan:
Run `hg crash` with `errorredirect.script` set to confirm it is compatible
with the old behavior.

Also run unittest `test-errorredirect.t`

Reviewers: #sourcecontrol, ttung, mjpieters

Reviewed By: mjpieters

Subscribers: rmcelroy, durham, lcharignon, mjpieters

Differential Revision: https://phabricator.fb.com/D3191840

Signature: t1:3191840:1461088280:77febd539c2f38a55778af3977738c045f63a0d8
2016-04-19 10:59:22 -07:00

60 lines
1.6 KiB
Python

# errorredirect.py
#
# Copyright 2015 Facebook, Inc.
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
"""redirect error message
Redirect error message, the stack trace, of an uncaught exception to
a custom shell script. This is useful for further handling the error,
for example posting it to a support group and logging it somewhere.
The config option errorredirect.script is the shell script to execute.
If it's empty, the extension will do nothing and fallback to the old
behavior.
Two environment variables are set: TRACE is the stack trace, which
is the same as piped content. WARNING is the warning message, which
usually contains contact message and software versions, etc.
Examples::
[errorredirect]
script = tee hgerr.log && echo 'Error written to hgerr.log'
[errorredirect]
script = echo "$WARNING$TRACE" >&2
[errorredirect]
script = (echo "$WARNING"; cat) | cat >&2
"""
import os
import subprocess
import sys
import traceback
from mercurial import (
dispatch,
extensions,
)
def _handlecommandexception(orig, ui):
script = ui.config('errorredirect', 'script')
if not script:
return orig(ui)
warning = dispatch._exceptionwarning(ui)
trace = traceback.format_exc()
env = os.environ.copy()
env['WARNING'] = warning
env['TRACE'] = trace
p = subprocess.Popen(script, shell=True, stdin=subprocess.PIPE, env=env)
p.communicate(trace)
return True # do not re-raise
def uisetup(ui):
extensions.wrapfunction(dispatch, 'handlecommandexception',
_handlecommandexception)