tests/svnxml.py
author Gregory Szorc <gregory.szorc@gmail.com>
Fri, 14 Apr 2017 00:33:56 -0700
changeset 32002 bf855efe5664
parent 28947 812eb3b7dc43
child 40216 c17d73bf6a4d
permissions -rw-r--r--
httppeer: wrap HTTPResponse.read() globally There were a handful of places in the code where HTTPResponse.read() was called with no explicit error handling or with inconsistent error handling. In order to eliminate this class of bug, we globally swap out HTTPResponse.read() with a unified error handler. I initially attempted to fix all call sites. However, after going down that rabbit hole, I figured it was best to just change read() to do what we want. This appears to be a worthwhile change, as the tests demonstrate many of our uncaught exceptions go away. To better represent this class of failure, we introduce a new error type. The main benefit over IOError is it can hold a hint. I'm receptive to tweaking its name or inheritance.

# Read the output of a "svn log --xml" command on stdin, parse it and
# print a subset of attributes common to all svn versions tested by
# hg.
from __future__ import absolute_import
import sys
import xml.dom.minidom

def xmltext(e):
    return ''.join(c.data for c
                   in e.childNodes
                   if c.nodeType == c.TEXT_NODE)

def parseentry(entry):
    e = {}
    e['revision'] = entry.getAttribute('revision')
    e['author'] = xmltext(entry.getElementsByTagName('author')[0])
    e['msg'] = xmltext(entry.getElementsByTagName('msg')[0])
    e['paths'] = []
    paths = entry.getElementsByTagName('paths')
    if paths:
        paths = paths[0]
        for p in paths.getElementsByTagName('path'):
            action = p.getAttribute('action')
            path = xmltext(p)
            frompath = p.getAttribute('copyfrom-path')
            fromrev = p.getAttribute('copyfrom-rev')
            e['paths'].append((path, action, frompath, fromrev))
    return e

def parselog(data):
    entries = []
    doc = xml.dom.minidom.parseString(data)
    for e in doc.getElementsByTagName('logentry'):
        entries.append(parseentry(e))
    return entries

def printentries(entries):
    fp = sys.stdout
    for e in entries:
        for k in ('revision', 'author', 'msg'):
            fp.write(('%s: %s\n' % (k, e[k])).encode('utf-8'))
        for path, action, fpath, frev in sorted(e['paths']):
            frominfo = ''
            if frev:
                frominfo = ' (from %s@%s)' % (fpath, frev)
            p = ' %s %s%s\n' % (action, path, frominfo)
            fp.write(p.encode('utf-8'))

if __name__ == '__main__':
    data = sys.stdin.read()
    entries = parselog(data)
    printentries(entries)