Mercurial > hg-stable
changeset 9851:9e7b2c49d25d
Make it possible to debug failed hook imports via use of --traceback
Prior to this change, if a Python hook module failed to load (e.g. due
to an import error or path problem), it was impossible to figure out
why the error occurred, because the ImportErrors that got raised were
caught but never displayed.
If run with --traceback or ui.traceback=True, hg now prints tracebacks
of both of the ImportError instances that get raised before it bails.
author | Bryan O'Sullivan <bos@serpentine.com> |
---|---|
date | Thu, 12 Nov 2009 14:05:52 -0800 |
parents | 004bf1d6e6af |
children | a033929bd34e |
files | mercurial/hook.py mercurial/ui.py tests/test-hook tests/test-hook.out |
diffstat | 4 files changed, 39 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/hook.py Thu Nov 12 14:34:07 2009 -0600 +++ b/mercurial/hook.py Thu Nov 12 14:05:52 2009 -0800 @@ -37,10 +37,18 @@ try: obj = __import__(modname) except ImportError: + e1 = sys.exc_type, sys.exc_value, sys.exc_traceback try: # extensions are loaded with hgext_ prefix obj = __import__("hgext_%s" % modname) except ImportError: + e2 = sys.exc_type, sys.exc_value, sys.exc_traceback + if ui.tracebackflag: + ui.warn(_('exception from first failed import attempt:\n')) + ui.traceback(e1) + if ui.tracebackflag: + ui.warn(_('exception from second failed import attempt:\n')) + ui.traceback(e2) raise util.Abort(_('%s hook is invalid ' '(import of "%s" failed)') % (hname, modname))
--- a/mercurial/ui.py Thu Nov 12 14:34:07 2009 -0600 +++ b/mercurial/ui.py Thu Nov 12 14:05:52 2009 -0800 @@ -15,7 +15,7 @@ class ui(object): def __init__(self, src=None): self._buffers = [] - self.quiet = self.verbose = self.debugflag = self._traceback = False + self.quiet = self.verbose = self.debugflag = self.tracebackflag = False self._reportuntrusted = True self._ocfg = config.config() # overlay self._tcfg = config.config() # trusted @@ -101,7 +101,7 @@ if self.verbose and self.quiet: self.quiet = self.verbose = False self._reportuntrusted = self.configbool("ui", "report_untrusted", True) - self._traceback = self.configbool('ui', 'traceback', False) + self.tracebackflag = self.configbool('ui', 'traceback', False) # update trust information self._trustusers.update(self.configlist('trusted', 'users')) @@ -337,13 +337,16 @@ return t - def traceback(self): + def traceback(self, exc=None): '''print exception traceback if traceback printing enabled. only to call in exception handler. returns true if traceback printed.''' - if self._traceback: - traceback.print_exc() - return self._traceback + if self.tracebackflag: + if exc: + traceback.print_exception(exc[0], exc[1], exc[2]) + else: + traceback.print_exc() + return self.tracebackflag def geteditor(self): '''return editor to use'''
--- a/tests/test-hook Thu Nov 12 14:34:07 2009 -0600 +++ b/tests/test-hook Thu Nov 12 14:05:52 2009 -0800 @@ -248,4 +248,18 @@ cd ../repo hg commit +cd ../../b +echo '# make sure --traceback works on hook import failure' +cat > importfail.py <<EOF +import somebogusmodule +# dereference something in the module to force demandimport to load it +somebogusmodule.whatever +EOF + +echo '[hooks]' > .hg/hgrc +echo 'precommit.importfail = python:importfail.whatever' >> .hg/hgrc + +echo a >> a +hg --traceback commit -Ama 2>&1 | grep '^\(exception\|Traceback\|ImportError\)' + exit 0
--- a/tests/test-hook.out Thu Nov 12 14:34:07 2009 -0600 +++ b/tests/test-hook.out Thu Nov 12 14:05:52 2009 -0800 @@ -163,3 +163,11 @@ # test python hook configured with python:[file]:[hook] syntax hook works nothing changed +# make sure --traceback works on hook import failure +exception from first failed import attempt: +Traceback (most recent call last): +ImportError: No module named somebogusmodule +exception from second failed import attempt: +Traceback (most recent call last): +ImportError: No module named hgext_importfail +Traceback (most recent call last):