view tests/logexceptions.py @ 44311:2b72c4ff8ed1

nodemap: use an intermediate "docket" file to carry small metadata This intermediate file will make mmapping, transaction and content validation easier. (Most of this usefulness will arrive gradually in later changeset). In particular it will become very useful to append new data are the end of raw file instead of rewriting on the file on each transaction. See in code comments for details. Differential Revision: https://phab.mercurial-scm.org/D7838
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Wed, 15 Jan 2020 15:47:50 +0100
parents 2372284d9457
children d4ba4d51f85f
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)