Patchwork [2,of,4] dispatch: print traceback in scmutil.callcatch() if --traceback specified

login
register
mail settings
Submitter Yuya Nishihara
Date April 15, 2017, 10:18 a.m.
Message ID <5f5fbac079aaa4c9872c.1492251516@mimosa>
Download mbox | patch
Permalink /patch/20213/
State Accepted
Delegated to: Kevin Bullock
Headers show

Comments

Yuya Nishihara - April 15, 2017, 10:18 a.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1492228954 -32400
#      Sat Apr 15 13:02:34 2017 +0900
# Node ID 5f5fbac079aaa4c9872c101152a2be319ae9d19b
# Parent  7efffd8f101592f72eb22ff771b336dd919c6f80
dispatch: print traceback in scmutil.callcatch() if --traceback specified

Otherwise, traceback wouldn't be printed for a known exception occurred in
worker processes.

Patch

diff --git a/mercurial/dispatch.py b/mercurial/dispatch.py
--- a/mercurial/dispatch.py
+++ b/mercurial/dispatch.py
@@ -255,7 +255,6 @@  def _runcatch(req):
             if '--debugger' in req.args:
                 traceback.print_exc()
                 debugmortem[debugger](sys.exc_info()[2])
-            ui.traceback()
             raise
 
     return _callcatch(ui, _runcatchfunc)
diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -142,7 +142,11 @@  def callcatch(ui, func):
     and return an exit code accordingly. does not handle all exceptions.
     """
     try:
-        return func()
+        try:
+            return func()
+        except: # re-raises
+            ui.traceback()
+            raise
     # Global exception handling, alphabetically
     # Mercurial-specific first, followed by built-in and library exceptions
     except error.LockHeld as inst:
diff --git a/tests/test-worker.t b/tests/test-worker.t
--- a/tests/test-worker.t
+++ b/tests/test-worker.t
@@ -4,20 +4,31 @@  Test UI worker interaction
   > from __future__ import absolute_import, print_function
   > from mercurial import (
   >     cmdutil,
+  >     error,
   >     ui as uimod,
   >     worker,
   > )
+  > def abort(ui, args):
+  >     if args[0] == 0:
+  >         # by first worker for test stability
+  >         raise error.Abort('known exception')
+  >     return runme(ui, [])
   > def runme(ui, args):
   >     for arg in args:
   >         ui.status('run\n')
   >         yield 1, arg
+  > functable = {
+  >     'abort': abort,
+  >     'runme': runme,
+  > }
   > cmdtable = {}
   > command = cmdutil.command(cmdtable)
-  > @command('test', [], 'hg test [COST]')
-  > def t(ui, repo, cost=1.0):
+  > @command('test', [], 'hg test [COST] [FUNC]')
+  > def t(ui, repo, cost=1.0, func='runme'):
   >     cost = float(cost)
+  >     func = functable[func]
   >     ui.status('start\n')
-  >     runs = worker.worker(ui, cost, runme, (ui,), range(8))
+  >     runs = worker.worker(ui, cost, func, (ui,), range(8))
   >     for n, i in runs:
   >         pass
   >     ui.status('done\n')
@@ -52,3 +63,15 @@  Run tests without worker by forcing a lo
   run
   run
   done
+
+Known exception should be caught, but printed if --traceback is enabled
+
+  $ hg --config "extensions.t=$abspath" --config 'worker.numcpus=2' \
+  > test 100000.0 abort
+  start
+  abort: known exception
+  done
+
+  $ hg --config "extensions.t=$abspath" --config 'worker.numcpus=2' \
+  > test 100000.0 abort --traceback 2>&1 | grep '^Traceback'
+  Traceback (most recent call last):