view tests/logexceptions.py @ 37178:68ee61822182

thirdparty: port zope.interface to relative imports By using relative imports, we're guaranteed to get modules vendored with Mercurial rather than other random modules that might be in sys.path. My editor strips trailing whitespace on save. So some minor source code cleanup was also performed as part of this commit. # no-check-commit because some modified lines have double newlines Differential Revision: https://phab.mercurial-scm.org/D2930
author Gregory Szorc <gregory.szorc@gmail.com>
date Wed, 21 Mar 2018 19:52:30 -0700
parents 8de90e006c78
children 2372284d9457
line wrap: on
line source

# logexceptions.py - Write files containing info about Mercurial exceptions
#
# Copyright 2017 Matt Mackall <mpm@selenic.com>
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.

from __future__ import absolute_import

import inspect
import os
import sys
import traceback
import uuid

from mercurial import (
    dispatch,
    extensions,
)

def handleexception(orig, ui):
    res = orig(ui)

    if not ui.environ.get(b'HGEXCEPTIONSDIR'):
        return res

    dest = os.path.join(ui.environ[b'HGEXCEPTIONSDIR'],
                        str(uuid.uuid4()).encode('ascii'))

    exc_type, exc_value, exc_tb = sys.exc_info()

    stack = []
    tb = exc_tb
    while tb:
        stack.append(tb)
        tb = tb.tb_next
    stack.reverse()

    hgframe = 'unknown'
    hgline = 'unknown'

    # Find the first Mercurial frame in the stack.
    for tb in stack:
        mod = inspect.getmodule(tb)
        if not mod.__name__.startswith(('hg', 'mercurial')):
            continue

        frame = tb.tb_frame

        try:
            with open(inspect.getsourcefile(tb), 'r') as fh:
                hgline = fh.readlines()[frame.f_lineno - 1].strip()
        except (IndexError, OSError):
            pass

        hgframe = '%s:%d' % (frame.f_code.co_filename, frame.f_lineno)
        break

    primary = traceback.extract_tb(exc_tb)[-1]
    primaryframe = '%s:%d' % (primary.filename, primary.lineno)

    with open(dest, 'wb') as fh:
        parts = [
            str(exc_value),
            primaryframe,
            hgframe,
            hgline,
            ui.environ[b'TESTNAME'].decode('utf-8', 'replace'),
        ]
        fh.write(b'\0'.join(p.encode('utf-8', 'replace') for p in parts))

def extsetup(ui):
    extensions.wrapfunction(dispatch, 'handlecommandexception',
                            handleexception)