tests/logexceptions.py
changeset 35190 bd8875b6473c
child 36037 8de90e006c78
equal deleted inserted replaced
35189:073843b5e353 35190:bd8875b6473c
       
     1 # logexceptions.py - Write files containing info about Mercurial exceptions
       
     2 #
       
     3 # Copyright 2017 Matt Mackall <mpm@selenic.com>
       
     4 #
       
     5 # This software may be used and distributed according to the terms of the
       
     6 # GNU General Public License version 2 or any later version.
       
     7 
       
     8 from __future__ import absolute_import
       
     9 
       
    10 import inspect
       
    11 import os
       
    12 import sys
       
    13 import traceback
       
    14 import uuid
       
    15 
       
    16 from mercurial import (
       
    17     dispatch,
       
    18     extensions,
       
    19 )
       
    20 
       
    21 def handleexception(orig, ui):
       
    22     res = orig(ui)
       
    23 
       
    24     if not ui.environ.get(b'HGEXCEPTIONSDIR'):
       
    25         return res
       
    26 
       
    27     dest = os.path.join(ui.environ[b'HGEXCEPTIONSDIR'],
       
    28                         str(uuid.uuid4()).encode('ascii'))
       
    29 
       
    30     exc_type, exc_value, exc_tb = sys.exc_info()
       
    31 
       
    32     stack = []
       
    33     tb = exc_tb
       
    34     while tb:
       
    35         stack.append(tb)
       
    36         tb = tb.tb_next
       
    37     stack.reverse()
       
    38 
       
    39     hgframe = 'unknown'
       
    40     hgline = 'unknown'
       
    41 
       
    42     # Find the first Mercurial frame in the stack.
       
    43     for tb in stack:
       
    44         mod = inspect.getmodule(tb)
       
    45         if not mod.__name__.startswith(('hg', 'mercurial')):
       
    46             continue
       
    47 
       
    48         frame = tb.tb_frame
       
    49 
       
    50         try:
       
    51             with open(inspect.getsourcefile(tb), 'r') as fh:
       
    52                 hgline = fh.readlines()[frame.f_lineno - 1].strip()
       
    53         except (IndexError, OSError):
       
    54             pass
       
    55 
       
    56         hgframe = '%s:%d' % (frame.f_code.co_filename, frame.f_lineno)
       
    57         break
       
    58 
       
    59     primary = traceback.extract_tb(exc_tb)[-1]
       
    60     primaryframe = '%s:%d' % (primary.filename, primary.lineno)
       
    61 
       
    62     with open(dest, 'wb') as fh:
       
    63         parts = [
       
    64             str(exc_value),
       
    65             primaryframe,
       
    66             hgframe,
       
    67             hgline,
       
    68         ]
       
    69         fh.write(b'\0'.join(p.encode('utf-8', 'replace') for p in parts))
       
    70 
       
    71 def extsetup(ui):
       
    72     extensions.wrapfunction(dispatch, 'handlecommandexception',
       
    73                             handleexception)