view contrib/debugcmdserver.py @ 41462:9b2b8794f801

hgweb: log error before attempting I/O Previously, an uncaught exception during HTTP request serving would attempt to send an error response then log the exception. If an exception occurred during I/O, this exception would be raised and the original exception wouldn't be logged. This commit changes behavior so the original exception is logged first, before we attempt to do anything else. This ensures the exception is logged. This change resulted in new tracebacks appearing in various tests. Because tracebacks can vary between Python versions, we added a simple script to filter the stack part of traceback lines. This makes testing much simpler, as we don't need to glob over lines and make lines conditional. Differential Revision: https://phab.mercurial-scm.org/D5749
author Gregory Szorc <gregory.szorc@gmail.com>
date Wed, 30 Jan 2019 11:44:34 -0800
parents cd03fbd5ab57
children 2372284d9457
line wrap: on
line source

#!/usr/bin/env python
#
# Dumps output generated by Mercurial's command server in a formatted style to a
# given file or stderr if '-' is specified. Output is also written in its raw
# format to stdout.
#
# $ ./hg serve --cmds pipe | ./contrib/debugcmdserver.py -
# o, 52   -> 'capabilities: getencoding runcommand\nencoding: UTF-8'

from __future__ import absolute_import, print_function
import struct
import sys

if len(sys.argv) != 2:
    print('usage: debugcmdserver.py FILE')
    sys.exit(1)

outputfmt = '>cI'
outputfmtsize = struct.calcsize(outputfmt)

if sys.argv[1] == '-':
    log = sys.stderr
else:
    log = open(sys.argv[1], 'a')

def read(size):
    data = sys.stdin.read(size)
    if not data:
        raise EOFError
    sys.stdout.write(data)
    sys.stdout.flush()
    return data

try:
    while True:
        header = read(outputfmtsize)
        channel, length = struct.unpack(outputfmt, header)
        log.write('%s, %-4d' % (channel, length))
        if channel in 'IL':
            log.write(' -> waiting for input\n')
        else:
            data = read(length)
            log.write(' -> %r\n' % data)
        log.flush()
except EOFError:
    pass
finally:
    if log != sys.stderr:
        log.close()