hgbook

changeset 622:2180358c32c4

Move some files to contrib
author Dongsheng Song <dongsheng.song@gmail.com>
date Thu Mar 12 15:40:40 2009 +0800 (2009-03-12)
parents 1ef7708b3b7f
children 082bb76417f1
files contrib/hg-interdiff contrib/hg-replay contrib/latex-to-docbook contrib/sillybench.py examples/hg-interdiff examples/hg-replay sillybench/sillybench.py tools/latex-to-docbook
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/contrib/hg-interdiff	Thu Mar 12 15:40:40 2009 +0800
     1.3 @@ -0,0 +1,45 @@
     1.4 +#!/usr/bin/env python
     1.5 +#
     1.6 +# Adapter for using interdiff with mercurial's extdiff extension.
     1.7 +#
     1.8 +# Copyright 2006 Bryan O'Sullivan <bos@serpentine.com>
     1.9 +#
    1.10 +# This software may be used and distributed according to the terms of
    1.11 +# the GNU General Public License, incorporated herein by reference.
    1.12 +
    1.13 +import os, sys
    1.14 +
    1.15 +def walk(base):
    1.16 +    # yield all non-directories below the base path.
    1.17 +    for root, dirs, files in os.walk(base):
    1.18 +        for f in files:
    1.19 +            path = os.path.join(root, f)
    1.20 +            yield path[len(base)+1:], path
    1.21 +    else:
    1.22 +        if os.path.isfile(base):
    1.23 +            yield '', base
    1.24 +
    1.25 +# create list of unique file names under both directories.
    1.26 +files = dict(walk(sys.argv[1]))
    1.27 +files.update(walk(sys.argv[2]))
    1.28 +files = files.keys()
    1.29 +files.sort()
    1.30 +
    1.31 +def name(base, f):
    1.32 +    if f:
    1.33 +        path = os.path.join(base, f)
    1.34 +    else:
    1.35 +        path = base
    1.36 +    # interdiff requires two files; use /dev/null if one is missing.
    1.37 +    if os.path.exists(path):
    1.38 +        return path
    1.39 +    return '/dev/null'
    1.40 +
    1.41 +ret = 0
    1.42 +
    1.43 +for f in files:
    1.44 +    if os.system('interdiff "%s" "%s"' % (name(sys.argv[1], f),
    1.45 +                                          name(sys.argv[2], f))):
    1.46 +        ret = 1
    1.47 +
    1.48 +sys.exit(ret)
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/contrib/hg-replay	Thu Mar 12 15:40:40 2009 +0800
     2.3 @@ -0,0 +1,107 @@
     2.4 +#!/usr/bin/env python
     2.5 +#
     2.6 +# Adapter for using interdiff with mercurial's extdiff extension.
     2.7 +#
     2.8 +# Copyright 2006 Bryan O'Sullivan <bos@serpentine.com>
     2.9 +#
    2.10 +# This software may be used and distributed according to the terms of
    2.11 +# the GNU General Public License, incorporated herein by reference.
    2.12 +
    2.13 +import os
    2.14 +import shutil
    2.15 +import sys
    2.16 +import tempfile
    2.17 +
    2.18 +if len(sys.argv) < 4:
    2.19 +    print >> sys.stderr, ('usage: %s srcrepo destrepo cset-to-omit [...]' %
    2.20 +                          os.path.basename(sys.argv[0]))
    2.21 +    sys.exit(1)
    2.22 +
    2.23 +srcrepo, destrepo = sys.argv[1], sys.argv[2]
    2.24 +omit = sys.argv[3:]
    2.25 +    
    2.26 +changemap = {}
    2.27 +revs = []
    2.28 +
    2.29 +parent = None
    2.30 +
    2.31 +sys.stdout.write('gathering history...')
    2.32 +sys.stdout.flush()
    2.33 +
    2.34 +for line in os.popen("hg --cwd %r log -r0:tip --template '{rev}:{node} {parents}\n'" % srcrepo):
    2.35 +    changes = line.split()
    2.36 +    cset = changes[0].split(':')[1]
    2.37 +    rev = len(revs)
    2.38 +    changemap[cset] = rev
    2.39 +    if len(changes) >= 2:
    2.40 +        p1 = int(changes[1].split(':', 1)[0])
    2.41 +    if len(changes) == 3:
    2.42 +        p2 = int(changes[2].split(':', 1)[0])
    2.43 +    else:
    2.44 +        p2 = None
    2.45 +    if len(changes) == 1:
    2.46 +        p1 = parent
    2.47 +    revs.append((cset, p1, p2))
    2.48 +    parent = rev
    2.49 +
    2.50 +sys.stdout.write(' %d revs\n' % len(revs))
    2.51 +
    2.52 +def findrev(r):
    2.53 +    try:
    2.54 +        i = int(r)
    2.55 +        if str(i) == r:
    2.56 +            rev = i
    2.57 +        if rev < 0:
    2.58 +            rev += len(revs)
    2.59 +        if rev < 0 or rev > len(revs):
    2.60 +            print >> sys.stderr, 'bad changeset: %r' % r
    2.61 +            sys.exit(1)
    2.62 +        cset = revs[rev][0]
    2.63 +    except ValueError:
    2.64 +        cset = r
    2.65 +        matches = [changemap[c] for c in changemap if c.startswith(cset)]
    2.66 +        if len(matches) != 1:
    2.67 +            print >> sys.stderr, 'bad changeset: %r' % r
    2.68 +            sys.exit(1)
    2.69 +        rev = matches[0]
    2.70 +    return rev
    2.71 +
    2.72 +def run(cmd):
    2.73 +    print cmd
    2.74 +    ret = os.system(cmd)
    2.75 +    if ret:
    2.76 +        print >> sys.stderr, 'failure:', cmd
    2.77 +        sys.exit(1)
    2.78 +
    2.79 +omit = map(findrev, omit)
    2.80 +omit.sort()
    2.81 +newrevs = revs[:omit[0]]
    2.82 +tip = len(newrevs) - 1
    2.83 +run('hg clone -q -r%s %r %r' % (tip, srcrepo, destrepo))
    2.84 +    
    2.85 +os.environ['HGMERGE'] = 'true'
    2.86 +
    2.87 +patchdir = tempfile.mkdtemp(prefix='replay.')
    2.88 +try:
    2.89 +    run('hg --cwd %r export --git -o %r%s%%R %d:tip' %
    2.90 +        (srcrepo, patchdir, os.sep, omit[0]+1))
    2.91 +    for rev in xrange(omit[0], len(revs)):
    2.92 +        if rev in omit:
    2.93 +            print 'omit', rev
    2.94 +            newrevs.append((None, revs[rev][1], None))
    2.95 +            continue
    2.96 +        _, p1, p2 = revs[rev]
    2.97 +        np1 = newrevs[p1][1]
    2.98 +        if tip != np1:
    2.99 +            run('hg --cwd %r update -q -C %s' % (destrepo, np1))
   2.100 +        np2 = None
   2.101 +        if p2:
   2.102 +            np2 = newrevs[p2][1]
   2.103 +            run('hg --cwd %r merge -q %s' % (destrepo, np2))
   2.104 +            print >> sys.stderr, 'XXX - cannot handle merges properly yet'
   2.105 +        run('hg --cwd %r import -q -f %r%s%d' % (destrepo, patchdir, os.sep, rev))
   2.106 +        tip = len(newrevs) - 1
   2.107 +        newrevs.append((None, tip, np2))
   2.108 +finally:
   2.109 +    print 'cleaning up ...'
   2.110 +    #shutil.rmtree(patchdir)
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/contrib/latex-to-docbook	Thu Mar 12 15:40:40 2009 +0800
     3.3 @@ -0,0 +1,198 @@
     3.4 +#!/usr/bin/python
     3.5 +#
     3.6 +# This is the most horrible of hacks. Pretend you're not looking.</para>
     3.7 +
     3.8 +import cStringIO as StringIO
     3.9 +import re, sys
    3.10 +
    3.11 +sections = {
    3.12 +    'chapter': 'chapter',
    3.13 +    'section': 'sect1',
    3.14 +    'subsection': 'sect2',
    3.15 +    'subsubsection': 'sect3',
    3.16 +    }
    3.17 +
    3.18 +envs = {
    3.19 +    'codesample2': 'programlisting',
    3.20 +    'codesample4': 'programlisting',
    3.21 +    'enumerate': 'orderedlist',
    3.22 +    'figure': 'informalfigure',
    3.23 +    'itemize': 'itemizedlist',
    3.24 +    'note': 'note',
    3.25 +    'quote': 'blockquote',
    3.26 +    }
    3.27 +
    3.28 +def process(ifp, ofp):
    3.29 +    print >> ofp, '<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->\n'
    3.30 +    stack = []
    3.31 +    para = True
    3.32 +    inlist = 0
    3.33 +    for line in ifp:
    3.34 +        if line.startswith('%%% Local Variables:'):
    3.35 +            break
    3.36 +        line = (line.rstrip()
    3.37 +                .replace('~', ' ')
    3.38 +                .replace('&', '&amp;')
    3.39 +                .replace('---', '&emdash;')
    3.40 +                .replace('\_', '_')
    3.41 +                .replace('\{', '{')
    3.42 +                .replace('\}', '}')
    3.43 +                .replace('\$', '$')
    3.44 +                .replace('\%', '%')
    3.45 +                .replace('\#', '#')
    3.46 +                .replace('<', '&lt;')
    3.47 +                .replace('>', '&gt;')
    3.48 +                .replace('``', '<quote>')
    3.49 +                .replace("''", '</quote>')
    3.50 +                .replace('\\', '\\'))
    3.51 +        line = re.sub(r'\s*\\(?:centering|small)\b\s*', '', line)
    3.52 +        line = re.sub(r'\\(?:hgrc\\|hgrc)\b',
    3.53 +                      r'<filename role="special"> /.hgrc</filename>', line)
    3.54 +        line = re.sub(r'\\item\[(?P<key>[^]]+)\]', r'\item \g<key>:', line)
    3.55 +        line = re.sub(r'\\bug{(?P<id>\d+)}',
    3.56 +                      r'<ulink role="hg-bug" url="http://www.selenic.com/mercurial/bts/issue\g<id>">issue \g<id></ulink>', line)
    3.57 +        line = re.sub(r'\\cite{([^}]+)}', r'<citation>\1</citation>', line)
    3.58 +        line = re.sub(r'\\hggopt{(?P<opt>[^}]+)}',
    3.59 +                      r'<option role="hg-opt-global">\g<opt></option>', line)
    3.60 +        line = re.sub(r'\\hgxopt{(?P<ext>[^}]+)}{(?P<cmd>[^}]+)}{(?P<opt>[^}]+)}',
    3.61 +                      r'<option role="hg-ext-\g<ext>-cmd-\g<cmd>-opt">\g<opt></option>', line)
    3.62 +        line = re.sub(r'\\hgxcmd{(?P<ext>[^}]+)}{(?P<cmd>[^}]+)}',
    3.63 +                      r'<command role="hg-ext-\g<ext>">\g<cmd></command>', line)
    3.64 +        line = re.sub(r'\\hgext{(?P<ext>[^}]+)}',
    3.65 +                      r'<literal role="hg-ext">\g<ext></literal>', line)
    3.66 +        line = re.sub(r'\\hgopt{(?P<cmd>[^}]+)}{(?P<opt>[^}]+)}',
    3.67 +                      r'<option role="hg-opt-\g<cmd>">\g<opt></option>',
    3.68 +                      line)
    3.69 +        line = re.sub(r'\\cmdopt{(?P<cmd>[^}]+)}{(?P<opt>[^}]+)}',
    3.70 +                      r'<option role="cmd-opt-\g<cmd>">\g<opt></option>',
    3.71 +                      line)
    3.72 +        line = re.sub(r'\\hgcmd{(?P<cmd>[^}]+)}',
    3.73 +                      r'<command role="hg-cmd">hg \g<cmd></command>', line)
    3.74 +        line = re.sub(r'\\caption{(?P<text>[^}]+?)}',
    3.75 +                      r'<caption><para>\g<text></para></caption>', line)
    3.76 +        line = re.sub(r'\\grafix{(?P<name>[^}]+)}',
    3.77 +                      r'<mediaobject><imageobject><imagedata fileref="\g<name>"/></imageobject><textobject><phrase>XXX add text</phrase></textobject></mediaobject>', line)
    3.78 +        line = re.sub(r'\\envar{(?P<name>[^}]+)}',
    3.79 +                      r'<envar>\g<name></envar>', line)
    3.80 +        line = re.sub(r'\\rcsection{(?P<sect>[^}]+)}',
    3.81 +                      r'<literal role="rc-\g<sect>">\g<sect></literal>', line)
    3.82 +        line = re.sub(r'\\rcitem{(?P<sect>[^}]+)}{(?P<name>[^}]+)}',
    3.83 +                      r'<envar role="rc-item-\g<sect>">\g<name></envar>', line)
    3.84 +        line = re.sub(r'\\dirname{(?P<dir>[^}]+?)}',
    3.85 +                      r'<filename class="directory">\g<dir></filename>', line)
    3.86 +        line = re.sub(r'\\filename{(?P<file>[^}]+?)}',
    3.87 +                      r'<filename>\g<file></filename>', line)
    3.88 +        line = re.sub(r'\\tildefile{(?P<file>[^}]+)}',
    3.89 +                      r'<filename role="home">~/\g<file></filename>', line)
    3.90 +        line = re.sub(r'\\sfilename{(?P<file>[^}]+)}',
    3.91 +                      r'<filename role="special">\g<file></filename>', line)
    3.92 +        line = re.sub(r'\\sdirname{(?P<dir>[^}]+)}',
    3.93 +                      r'<filename role="special" class="directory">\g<dir></filename>', line)
    3.94 +        line = re.sub(r'\\interaction{(?P<id>[^}]+)}',
    3.95 +                      r'<!-- &interaction.\g<id>; -->', line)
    3.96 +        line = re.sub(r'\\excode{(?P<id>[^}]+)}',
    3.97 +                      r'<!-- &example.\g<id>; -->', line)
    3.98 +        line = re.sub(r'\\pymod{(?P<mod>[^}]+)}',
    3.99 +                      r'<literal role="py-mod">\g<mod></literal>', line)
   3.100 +        line = re.sub(r'\\pymodclass{(?P<mod>[^}]+)}{(?P<class>[^}]+)}',
   3.101 +                      r'<literal role="py-mod-\g<mod>">\g<class></literal>', line)
   3.102 +        line = re.sub(r'\\url{(?P<url>[^}]+)}',
   3.103 +                      r'<ulink url="\g<url>">\g<url></ulink>', line)
   3.104 +        line = re.sub(r'\\href{(?P<url>[^}]+)}{(?P<text>[^}]+)}',
   3.105 +                      r'<ulink url="\g<url>">\g<text></ulink>', line)
   3.106 +        line = re.sub(r'\\command{(?P<cmd>[^}]+)}',
   3.107 +                      r'<command>\g<cmd></command>', line)
   3.108 +        line = re.sub(r'\\option{(?P<opt>[^}]+)}',
   3.109 +                      r'<option>\g<opt></option>', line)
   3.110 +        line = re.sub(r'\\ref{(?P<id>[^}]+)}', r'<xref linkend="\g<id>"/>', line)
   3.111 +        line = re.sub(r'\\emph{(?P<txt>[^}]+)}',
   3.112 +                      r'<emphasis>\g<txt></emphasis>', line)
   3.113 +        line = re.sub(r'\\texttt{(?P<txt>[^}]+)}',
   3.114 +                      r'<literal>\g<txt></literal>', line)
   3.115 +        line = re.sub(r'\\textbf{(?P<txt>[^}]+)}',
   3.116 +                      r'<emphasis role="bold">\g<txt></emphasis>', line)
   3.117 +        line = re.sub(r'\\hook{(?P<name>[^}]+)}',
   3.118 +                      r'<literal role="hook">\g<name></literal>', line)
   3.119 +        line = re.sub(r'\\tplfilter{(?P<name>[^}]+)}',
   3.120 +                      r'<literal role="template-filter">\g<name></literal>', line)
   3.121 +        line = re.sub(r'\\tplkword{(?P<name>[^}]+)}',
   3.122 +                      r'<literal role="template-keyword">\g<name></literal>', line)
   3.123 +        line = re.sub(r'\\tplkwfilt{(?P<tpl>[^}]+)}{(?P<name>[^}]+)}',
   3.124 +                      r'<literal role="template-kw-filt-\g<tpl>">\g<name></literal>', line)
   3.125 +        line = re.sub(r'\\[vV]erb(.)(?P<txt>[^\1]+?)\1',
   3.126 +                      r'<literal>\g<txt></literal>', line)
   3.127 +        line = re.sub(r'\\package{(?P<name>[^}]+)}',
   3.128 +                      r'<literal role="package">\g<name></literal>', line)
   3.129 +        line = re.sub(r'\\hgcmdargs{(?P<cmd>[^}]+)}{(?P<args>[^}]+)}',
   3.130 +                      r'<command role="hg-cmd">hg \g<cmd> \g<args></command>',
   3.131 +                      line)
   3.132 +        line = re.sub(r'\\cmdargs{(?P<cmd>[^}]+)}{(?P<args>[^}]+)}',
   3.133 +                      r'<command>\g<cmd> \g<args></command>',
   3.134 +                      line)
   3.135 +        m = re.match(r'\\(chapter|section|subsection|subsubsection){(.*)}', line)
   3.136 +        if m:
   3.137 +            kind, content = m.groups()
   3.138 +            sec = sections[kind]
   3.139 +            while stack and stack[-1] >= sec:
   3.140 +                close = stack.pop()
   3.141 +                print >> ofp, '</%s>' % close
   3.142 +            stack.append(sec)
   3.143 +            print >> ofp, '<%s>\n<title>%s</title>' % (sec, content)
   3.144 +        else:
   3.145 +            m = re.match(r'\s*\\(begin|end){(?P<sect>[^}]+)}', line)
   3.146 +            if m:
   3.147 +                if not para:
   3.148 +                    print >> ofp, '</para>'
   3.149 +                    if inlist:
   3.150 +                        ofp.write('</listitem>')
   3.151 +                    para = True
   3.152 +                state, env = m.groups()
   3.153 +                env = envs[env]
   3.154 +                if state == 'begin':
   3.155 +                    ofp.write('<')
   3.156 +                    if env in ('itemizedlist', 'orderedlist'):
   3.157 +                        inlist = 1
   3.158 +                else:
   3.159 +                    ofp.write('</')
   3.160 +                    if env in ('itemizedlist', 'orderedlist'):
   3.161 +                        inlist = 0
   3.162 +                print >> ofp, env + '>'
   3.163 +            else:
   3.164 +                if line.startswith('\\item '):
   3.165 +                    if inlist > 1:
   3.166 +                        print >> ofp, '</para>'
   3.167 +                        print >> ofp, '</listitem>'
   3.168 +                    else:
   3.169 +                        inlist = 2
   3.170 +                    para = True
   3.171 +                    line = line[6:]
   3.172 +                if line and para:
   3.173 +                    if inlist:
   3.174 +                        ofp.write('<listitem>')
   3.175 +                    ofp.write('<para>')
   3.176 +                    para = False
   3.177 +                if not line and not para:
   3.178 +                    print >> ofp, '</para>'
   3.179 +                    if inlist:
   3.180 +                        ofp.write('</listitem>')
   3.181 +                    para = True
   3.182 +                print >> ofp, line
   3.183 +    while stack:
   3.184 +        print >> ofp, '</%s>' % stack.pop()
   3.185 +    ofp.write('\n'.join(['\n<!--',
   3.186 +                         'local variables: ',
   3.187 +                         'sgml-parent-document: ("00book.xml" "book" "chapter")',
   3.188 +                         'end:',
   3.189 +                         '-->']))
   3.190 +
   3.191 +
   3.192 +if __name__ == '__main__':
   3.193 +    for name in sys.argv[1:]:
   3.194 +        if not name.endswith('.tex'):
   3.195 +            continue
   3.196 +        newname = name[:-3] + 'xml'
   3.197 +        ofp = StringIO.StringIO()
   3.198 +        process(open(name), ofp)
   3.199 +        s = ofp.getvalue()
   3.200 +        s = re.sub('\n+</para>', '</para>', s, re.M)
   3.201 +        open(newname, 'w').write(s)
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/contrib/sillybench.py	Thu Mar 12 15:40:40 2009 +0800
     4.3 @@ -0,0 +1,177 @@
     4.4 +#!/usr/bin/python
     4.5 +#
     4.6 +# Silly benchmarking program, to give a vague idea of how fast a few
     4.7 +# tools are on a handful of common operations.
     4.8 +#
     4.9 +# Use a fairly big and real source tarball to test with: Firefox
    4.10 +# 2.0.0.3 (37622 files, 5374 directories, 343MB unpacked onto
    4.11 +# 4KB-blocksize ext3).
    4.12 +
    4.13 +import csv
    4.14 +import os
    4.15 +import shutil
    4.16 +import sys
    4.17 +import tempfile
    4.18 +import time
    4.19 +import urllib2
    4.20 +
    4.21 +url = 'ftp://ftp.mozilla.org/pub/mozilla.org/firefox/releases/2.0.0.3/source/firefox-2.0.0.3-source.tar.bz2'
    4.22 +
    4.23 +class CommandFailure(Exception):
    4.24 +    pass
    4.25 +
    4.26 +class rcs(object):
    4.27 +    def __init__(self):
    4.28 +        self.logfp = open(self.__class__.__name__ + '.csv', 'w')
    4.29 +        self.csv = csv.writer(self.logfp)
    4.30 +
    4.31 +    def download(self):
    4.32 +        name = url[url.rfind('/')+1:]
    4.33 +        path = os.path.join(os.environ['HOME'], name)
    4.34 +        if not os.path.isfile(path):
    4.35 +            ofp = open(path + '.part', 'wb')
    4.36 +            try:
    4.37 +                ifp = urllib2.urlopen(url)
    4.38 +                nbytes = ifp.info()['content-length']
    4.39 +                sys.stdout.write('%s: %s bytes ' % (name, nbytes))
    4.40 +                sys.stdout.flush()
    4.41 +                while True:
    4.42 +                    data = ifp.read(131072)
    4.43 +                    if not data: break
    4.44 +                    sys.stdout.write('.')
    4.45 +                    sys.stdout.flush()
    4.46 +                    ofp.write(data)
    4.47 +                del ofp
    4.48 +                os.rename(path + '.part', path)
    4.49 +            except:
    4.50 +                if os.path.exists(path + '.part'):
    4.51 +                    os.unlink(path + '.part')
    4.52 +                if os.path.exists(path):
    4.53 +                    os.unlink(path)
    4.54 +                raise
    4.55 +        return path
    4.56 +
    4.57 +    def run(self, args, mustsucceed=True):
    4.58 +        ret = os.spawnvp(os.P_WAIT, args[0], args)
    4.59 +        if ret < 0:
    4.60 +            msg = 'killed by signal %d' % (-ret)
    4.61 +        if ret > 0:
    4.62 +            msg = 'exited with status %d' % (ret)
    4.63 +        if ret:
    4.64 +            if mustsucceed:
    4.65 +                raise CommandFailure('%s: %s' % (msg, ' '.join(args)))
    4.66 +            print >> sys.stderr, 'WARNING: %s: %s' % (msg, ' '.join(args))
    4.67 +
    4.68 +    def time(self, *args, **kwargs):
    4.69 +        start = time.time()
    4.70 +        self.run(*args, **kwargs)
    4.71 +        end = time.time()
    4.72 +        return end - start
    4.73 +        
    4.74 +    def logtime(self, name, elapsed, rest=[]):
    4.75 +        self.log('time:' + name, '%.3f' % elapsed, rest)
    4.76 +
    4.77 +    def log(self, name, value, rest=[]):
    4.78 +        item = (name, value, repr(rest))
    4.79 +        print ' '.join(item)
    4.80 +        self.csv.writerow(item)
    4.81 +        self.logfp.flush()
    4.82 +
    4.83 +    def unpack(self):
    4.84 +        tarball = self.download()
    4.85 +        t = self.time(['tar', '-C', self.wdir, '-jxf', tarball])
    4.86 +        self.logtime('internal:untar', t)
    4.87 +        for name in os.listdir(os.path.join(self.wdir, 'mozilla')):
    4.88 +            os.rename(os.path.join(self.wdir, 'mozilla', name),
    4.89 +                      os.path.join(self.wdir, name))
    4.90 +
    4.91 +    def cleanup(self):
    4.92 +        pass
    4.93 +
    4.94 +    def add(self, paths):
    4.95 +        pass
    4.96 +
    4.97 +    def commit(self, msg, paths):
    4.98 +        pass
    4.99 +
   4.100 +    def status(self, path):
   4.101 +        pass
   4.102 +
   4.103 +    def remove(self, path):
   4.104 +        pass
   4.105 +
   4.106 +
   4.107 +class subversion(rcs):
   4.108 +    def __init__(self, root):
   4.109 +        rcs.__init__(self)
   4.110 +        self.repo = os.path.join(root, 'repo')
   4.111 +        self.wdir = os.path.join(root, 'wc')
   4.112 +        create = self.time(['svnadmin', 'create', '--fs-type=fsfs', self.repo])
   4.113 +        self.logtime('svn:create', create)
   4.114 +        co = self.time(['svn', 'co', 'file://' + self.repo, self.wdir])
   4.115 +        self.logtime('svn:co', co)
   4.116 +        self.logtime('init', create + co)
   4.117 +        os.chdir(self.wdir)
   4.118 +
   4.119 +    def dropmeta(self, names):
   4.120 +        return [n for n in names if os.path.basename(n) != '.svn']
   4.121 +
   4.122 +    def add(self, paths):
   4.123 +        t = self.time(['svn', 'add', '-q'] + paths)
   4.124 +        self.logtime('add %r' % paths, t)
   4.125 +
   4.126 +    def commit(self, msg, paths=[]):
   4.127 +        if paths:
   4.128 +            t = self.time(['svn', 'ci', '-q', '-m', msg] + paths)
   4.129 +        else:
   4.130 +            t = self.time(['svn', 'ci', '-q', '-m', msg])
   4.131 +        self.logtime('commit %r' % paths, t)
   4.132 +
   4.133 +
   4.134 +class mercurial(rcs):
   4.135 +    def __init__(self, root):
   4.136 +        rcs.__init__(self)
   4.137 +        self.repo = os.path.join(root, 'repo')
   4.138 +        self.wdir = self.repo
   4.139 +        init = self.time(['hg', 'init', self.repo])
   4.140 +        self.logtime('init', init)
   4.141 +        os.chdir(self.wdir)
   4.142 +
   4.143 +    def dropmeta(self, names):
   4.144 +        return [n for n in names if os.path.basename(n) != '.hg']
   4.145 +
   4.146 +    def add(self, paths):
   4.147 +        t = self.time(['hg', 'add', '-q'] + paths)
   4.148 +        self.logtime('add %r' % paths, t)
   4.149 +
   4.150 +    def commit(self, msg, paths=[]):
   4.151 +        if paths:
   4.152 +            t = self.time(['hg', 'ci', '-q', '-m', msg] + paths)
   4.153 +        else:
   4.154 +            t = self.time(['hg', 'ci', '-q', '-m', msg])
   4.155 +        self.logtime('commit %r' % paths, t)
   4.156 +
   4.157 +def benchmark(cls):
   4.158 +    oldcwd = os.getcwd()
   4.159 +    root = tempfile.mkdtemp(prefix='sillybench.')
   4.160 +    try:
   4.161 +        print 'root', root
   4.162 +        inst = cls(root)
   4.163 +        inst.unpack()
   4.164 +        names = inst.dropmeta(os.listdir('.'))
   4.165 +        dirs = [n for n in names if os.path.isdir(n)]
   4.166 +        nondirs = [n for n in names if not os.path.isdir(n)]
   4.167 +        dirs.sort(key=hash)
   4.168 +        names.sort(key=hash)
   4.169 +        for d in dirs[:len(dirs)/2]:
   4.170 +            inst.add([d])
   4.171 +            inst.commit('Add %r' % d, [d])
   4.172 +        inst.add(dirs[len(dirs)/2:] + names)
   4.173 +        inst.commit('Add remaining dirs and files')
   4.174 +    finally:
   4.175 +        print >> sys.stderr, '[cleaning up...]'
   4.176 +        shutil.rmtree(root)
   4.177 +        os.chdir(oldcwd)
   4.178 +
   4.179 +benchmark(mercurial)
   4.180 +#benchmark(subversion)
     5.1 --- a/examples/hg-interdiff	Thu Mar 12 15:35:19 2009 +0800
     5.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.3 @@ -1,45 +0,0 @@
     5.4 -#!/usr/bin/env python
     5.5 -#
     5.6 -# Adapter for using interdiff with mercurial's extdiff extension.
     5.7 -#
     5.8 -# Copyright 2006 Bryan O'Sullivan <bos@serpentine.com>
     5.9 -#
    5.10 -# This software may be used and distributed according to the terms of
    5.11 -# the GNU General Public License, incorporated herein by reference.
    5.12 -
    5.13 -import os, sys
    5.14 -
    5.15 -def walk(base):
    5.16 -    # yield all non-directories below the base path.
    5.17 -    for root, dirs, files in os.walk(base):
    5.18 -        for f in files:
    5.19 -            path = os.path.join(root, f)
    5.20 -            yield path[len(base)+1:], path
    5.21 -    else:
    5.22 -        if os.path.isfile(base):
    5.23 -            yield '', base
    5.24 -
    5.25 -# create list of unique file names under both directories.
    5.26 -files = dict(walk(sys.argv[1]))
    5.27 -files.update(walk(sys.argv[2]))
    5.28 -files = files.keys()
    5.29 -files.sort()
    5.30 -
    5.31 -def name(base, f):
    5.32 -    if f:
    5.33 -        path = os.path.join(base, f)
    5.34 -    else:
    5.35 -        path = base
    5.36 -    # interdiff requires two files; use /dev/null if one is missing.
    5.37 -    if os.path.exists(path):
    5.38 -        return path
    5.39 -    return '/dev/null'
    5.40 -
    5.41 -ret = 0
    5.42 -
    5.43 -for f in files:
    5.44 -    if os.system('interdiff "%s" "%s"' % (name(sys.argv[1], f),
    5.45 -                                          name(sys.argv[2], f))):
    5.46 -        ret = 1
    5.47 -
    5.48 -sys.exit(ret)
     6.1 --- a/examples/hg-replay	Thu Mar 12 15:35:19 2009 +0800
     6.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.3 @@ -1,107 +0,0 @@
     6.4 -#!/usr/bin/env python
     6.5 -#
     6.6 -# Adapter for using interdiff with mercurial's extdiff extension.
     6.7 -#
     6.8 -# Copyright 2006 Bryan O'Sullivan <bos@serpentine.com>
     6.9 -#
    6.10 -# This software may be used and distributed according to the terms of
    6.11 -# the GNU General Public License, incorporated herein by reference.
    6.12 -
    6.13 -import os
    6.14 -import shutil
    6.15 -import sys
    6.16 -import tempfile
    6.17 -
    6.18 -if len(sys.argv) < 4:
    6.19 -    print >> sys.stderr, ('usage: %s srcrepo destrepo cset-to-omit [...]' %
    6.20 -                          os.path.basename(sys.argv[0]))
    6.21 -    sys.exit(1)
    6.22 -
    6.23 -srcrepo, destrepo = sys.argv[1], sys.argv[2]
    6.24 -omit = sys.argv[3:]
    6.25 -    
    6.26 -changemap = {}
    6.27 -revs = []
    6.28 -
    6.29 -parent = None
    6.30 -
    6.31 -sys.stdout.write('gathering history...')
    6.32 -sys.stdout.flush()
    6.33 -
    6.34 -for line in os.popen("hg --cwd %r log -r0:tip --template '{rev}:{node} {parents}\n'" % srcrepo):
    6.35 -    changes = line.split()
    6.36 -    cset = changes[0].split(':')[1]
    6.37 -    rev = len(revs)
    6.38 -    changemap[cset] = rev
    6.39 -    if len(changes) >= 2:
    6.40 -        p1 = int(changes[1].split(':', 1)[0])
    6.41 -    if len(changes) == 3:
    6.42 -        p2 = int(changes[2].split(':', 1)[0])
    6.43 -    else:
    6.44 -        p2 = None
    6.45 -    if len(changes) == 1:
    6.46 -        p1 = parent
    6.47 -    revs.append((cset, p1, p2))
    6.48 -    parent = rev
    6.49 -
    6.50 -sys.stdout.write(' %d revs\n' % len(revs))
    6.51 -
    6.52 -def findrev(r):
    6.53 -    try:
    6.54 -        i = int(r)
    6.55 -        if str(i) == r:
    6.56 -            rev = i
    6.57 -        if rev < 0:
    6.58 -            rev += len(revs)
    6.59 -        if rev < 0 or rev > len(revs):
    6.60 -            print >> sys.stderr, 'bad changeset: %r' % r
    6.61 -            sys.exit(1)
    6.62 -        cset = revs[rev][0]
    6.63 -    except ValueError:
    6.64 -        cset = r
    6.65 -        matches = [changemap[c] for c in changemap if c.startswith(cset)]
    6.66 -        if len(matches) != 1:
    6.67 -            print >> sys.stderr, 'bad changeset: %r' % r
    6.68 -            sys.exit(1)
    6.69 -        rev = matches[0]
    6.70 -    return rev
    6.71 -
    6.72 -def run(cmd):
    6.73 -    print cmd
    6.74 -    ret = os.system(cmd)
    6.75 -    if ret:
    6.76 -        print >> sys.stderr, 'failure:', cmd
    6.77 -        sys.exit(1)
    6.78 -
    6.79 -omit = map(findrev, omit)
    6.80 -omit.sort()
    6.81 -newrevs = revs[:omit[0]]
    6.82 -tip = len(newrevs) - 1
    6.83 -run('hg clone -q -r%s %r %r' % (tip, srcrepo, destrepo))
    6.84 -    
    6.85 -os.environ['HGMERGE'] = 'true'
    6.86 -
    6.87 -patchdir = tempfile.mkdtemp(prefix='replay.')
    6.88 -try:
    6.89 -    run('hg --cwd %r export --git -o %r%s%%R %d:tip' %
    6.90 -        (srcrepo, patchdir, os.sep, omit[0]+1))
    6.91 -    for rev in xrange(omit[0], len(revs)):
    6.92 -        if rev in omit:
    6.93 -            print 'omit', rev
    6.94 -            newrevs.append((None, revs[rev][1], None))
    6.95 -            continue
    6.96 -        _, p1, p2 = revs[rev]
    6.97 -        np1 = newrevs[p1][1]
    6.98 -        if tip != np1:
    6.99 -            run('hg --cwd %r update -q -C %s' % (destrepo, np1))
   6.100 -        np2 = None
   6.101 -        if p2:
   6.102 -            np2 = newrevs[p2][1]
   6.103 -            run('hg --cwd %r merge -q %s' % (destrepo, np2))
   6.104 -            print >> sys.stderr, 'XXX - cannot handle merges properly yet'
   6.105 -        run('hg --cwd %r import -q -f %r%s%d' % (destrepo, patchdir, os.sep, rev))
   6.106 -        tip = len(newrevs) - 1
   6.107 -        newrevs.append((None, tip, np2))
   6.108 -finally:
   6.109 -    print 'cleaning up ...'
   6.110 -    #shutil.rmtree(patchdir)
     7.1 --- a/sillybench/sillybench.py	Thu Mar 12 15:35:19 2009 +0800
     7.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.3 @@ -1,177 +0,0 @@
     7.4 -#!/usr/bin/python
     7.5 -#
     7.6 -# Silly benchmarking program, to give a vague idea of how fast a few
     7.7 -# tools are on a handful of common operations.
     7.8 -#
     7.9 -# Use a fairly big and real source tarball to test with: Firefox
    7.10 -# 2.0.0.3 (37622 files, 5374 directories, 343MB unpacked onto
    7.11 -# 4KB-blocksize ext3).
    7.12 -
    7.13 -import csv
    7.14 -import os
    7.15 -import shutil
    7.16 -import sys
    7.17 -import tempfile
    7.18 -import time
    7.19 -import urllib2
    7.20 -
    7.21 -url = 'ftp://ftp.mozilla.org/pub/mozilla.org/firefox/releases/2.0.0.3/source/firefox-2.0.0.3-source.tar.bz2'
    7.22 -
    7.23 -class CommandFailure(Exception):
    7.24 -    pass
    7.25 -
    7.26 -class rcs(object):
    7.27 -    def __init__(self):
    7.28 -        self.logfp = open(self.__class__.__name__ + '.csv', 'w')
    7.29 -        self.csv = csv.writer(self.logfp)
    7.30 -
    7.31 -    def download(self):
    7.32 -        name = url[url.rfind('/')+1:]
    7.33 -        path = os.path.join(os.environ['HOME'], name)
    7.34 -        if not os.path.isfile(path):
    7.35 -            ofp = open(path + '.part', 'wb')
    7.36 -            try:
    7.37 -                ifp = urllib2.urlopen(url)
    7.38 -                nbytes = ifp.info()['content-length']
    7.39 -                sys.stdout.write('%s: %s bytes ' % (name, nbytes))
    7.40 -                sys.stdout.flush()
    7.41 -                while True:
    7.42 -                    data = ifp.read(131072)
    7.43 -                    if not data: break
    7.44 -                    sys.stdout.write('.')
    7.45 -                    sys.stdout.flush()
    7.46 -                    ofp.write(data)
    7.47 -                del ofp
    7.48 -                os.rename(path + '.part', path)
    7.49 -            except:
    7.50 -                if os.path.exists(path + '.part'):
    7.51 -                    os.unlink(path + '.part')
    7.52 -                if os.path.exists(path):
    7.53 -                    os.unlink(path)
    7.54 -                raise
    7.55 -        return path
    7.56 -
    7.57 -    def run(self, args, mustsucceed=True):
    7.58 -        ret = os.spawnvp(os.P_WAIT, args[0], args)
    7.59 -        if ret < 0:
    7.60 -            msg = 'killed by signal %d' % (-ret)
    7.61 -        if ret > 0:
    7.62 -            msg = 'exited with status %d' % (ret)
    7.63 -        if ret:
    7.64 -            if mustsucceed:
    7.65 -                raise CommandFailure('%s: %s' % (msg, ' '.join(args)))
    7.66 -            print >> sys.stderr, 'WARNING: %s: %s' % (msg, ' '.join(args))
    7.67 -
    7.68 -    def time(self, *args, **kwargs):
    7.69 -        start = time.time()
    7.70 -        self.run(*args, **kwargs)
    7.71 -        end = time.time()
    7.72 -        return end - start
    7.73 -        
    7.74 -    def logtime(self, name, elapsed, rest=[]):
    7.75 -        self.log('time:' + name, '%.3f' % elapsed, rest)
    7.76 -
    7.77 -    def log(self, name, value, rest=[]):
    7.78 -        item = (name, value, repr(rest))
    7.79 -        print ' '.join(item)
    7.80 -        self.csv.writerow(item)
    7.81 -        self.logfp.flush()
    7.82 -
    7.83 -    def unpack(self):
    7.84 -        tarball = self.download()
    7.85 -        t = self.time(['tar', '-C', self.wdir, '-jxf', tarball])
    7.86 -        self.logtime('internal:untar', t)
    7.87 -        for name in os.listdir(os.path.join(self.wdir, 'mozilla')):
    7.88 -            os.rename(os.path.join(self.wdir, 'mozilla', name),
    7.89 -                      os.path.join(self.wdir, name))
    7.90 -
    7.91 -    def cleanup(self):
    7.92 -        pass
    7.93 -
    7.94 -    def add(self, paths):
    7.95 -        pass
    7.96 -
    7.97 -    def commit(self, msg, paths):
    7.98 -        pass
    7.99 -
   7.100 -    def status(self, path):
   7.101 -        pass
   7.102 -
   7.103 -    def remove(self, path):
   7.104 -        pass
   7.105 -
   7.106 -
   7.107 -class subversion(rcs):
   7.108 -    def __init__(self, root):
   7.109 -        rcs.__init__(self)
   7.110 -        self.repo = os.path.join(root, 'repo')
   7.111 -        self.wdir = os.path.join(root, 'wc')
   7.112 -        create = self.time(['svnadmin', 'create', '--fs-type=fsfs', self.repo])
   7.113 -        self.logtime('svn:create', create)
   7.114 -        co = self.time(['svn', 'co', 'file://' + self.repo, self.wdir])
   7.115 -        self.logtime('svn:co', co)
   7.116 -        self.logtime('init', create + co)
   7.117 -        os.chdir(self.wdir)
   7.118 -
   7.119 -    def dropmeta(self, names):
   7.120 -        return [n for n in names if os.path.basename(n) != '.svn']
   7.121 -
   7.122 -    def add(self, paths):
   7.123 -        t = self.time(['svn', 'add', '-q'] + paths)
   7.124 -        self.logtime('add %r' % paths, t)
   7.125 -
   7.126 -    def commit(self, msg, paths=[]):
   7.127 -        if paths:
   7.128 -            t = self.time(['svn', 'ci', '-q', '-m', msg] + paths)
   7.129 -        else:
   7.130 -            t = self.time(['svn', 'ci', '-q', '-m', msg])
   7.131 -        self.logtime('commit %r' % paths, t)
   7.132 -
   7.133 -
   7.134 -class mercurial(rcs):
   7.135 -    def __init__(self, root):
   7.136 -        rcs.__init__(self)
   7.137 -        self.repo = os.path.join(root, 'repo')
   7.138 -        self.wdir = self.repo
   7.139 -        init = self.time(['hg', 'init', self.repo])
   7.140 -        self.logtime('init', init)
   7.141 -        os.chdir(self.wdir)
   7.142 -
   7.143 -    def dropmeta(self, names):
   7.144 -        return [n for n in names if os.path.basename(n) != '.hg']
   7.145 -
   7.146 -    def add(self, paths):
   7.147 -        t = self.time(['hg', 'add', '-q'] + paths)
   7.148 -        self.logtime('add %r' % paths, t)
   7.149 -
   7.150 -    def commit(self, msg, paths=[]):
   7.151 -        if paths:
   7.152 -            t = self.time(['hg', 'ci', '-q', '-m', msg] + paths)
   7.153 -        else:
   7.154 -            t = self.time(['hg', 'ci', '-q', '-m', msg])
   7.155 -        self.logtime('commit %r' % paths, t)
   7.156 -
   7.157 -def benchmark(cls):
   7.158 -    oldcwd = os.getcwd()
   7.159 -    root = tempfile.mkdtemp(prefix='sillybench.')
   7.160 -    try:
   7.161 -        print 'root', root
   7.162 -        inst = cls(root)
   7.163 -        inst.unpack()
   7.164 -        names = inst.dropmeta(os.listdir('.'))
   7.165 -        dirs = [n for n in names if os.path.isdir(n)]
   7.166 -        nondirs = [n for n in names if not os.path.isdir(n)]
   7.167 -        dirs.sort(key=hash)
   7.168 -        names.sort(key=hash)
   7.169 -        for d in dirs[:len(dirs)/2]:
   7.170 -            inst.add([d])
   7.171 -            inst.commit('Add %r' % d, [d])
   7.172 -        inst.add(dirs[len(dirs)/2:] + names)
   7.173 -        inst.commit('Add remaining dirs and files')
   7.174 -    finally:
   7.175 -        print >> sys.stderr, '[cleaning up...]'
   7.176 -        shutil.rmtree(root)
   7.177 -        os.chdir(oldcwd)
   7.178 -
   7.179 -benchmark(mercurial)
   7.180 -#benchmark(subversion)
     8.1 --- a/tools/latex-to-docbook	Thu Mar 12 15:35:19 2009 +0800
     8.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.3 @@ -1,198 +0,0 @@
     8.4 -#!/usr/bin/python
     8.5 -#
     8.6 -# This is the most horrible of hacks. Pretend you're not looking.</para>
     8.7 -
     8.8 -import cStringIO as StringIO
     8.9 -import re, sys
    8.10 -
    8.11 -sections = {
    8.12 -    'chapter': 'chapter',
    8.13 -    'section': 'sect1',
    8.14 -    'subsection': 'sect2',
    8.15 -    'subsubsection': 'sect3',
    8.16 -    }
    8.17 -
    8.18 -envs = {
    8.19 -    'codesample2': 'programlisting',
    8.20 -    'codesample4': 'programlisting',
    8.21 -    'enumerate': 'orderedlist',
    8.22 -    'figure': 'informalfigure',
    8.23 -    'itemize': 'itemizedlist',
    8.24 -    'note': 'note',
    8.25 -    'quote': 'blockquote',
    8.26 -    }
    8.27 -
    8.28 -def process(ifp, ofp):
    8.29 -    print >> ofp, '<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->\n'
    8.30 -    stack = []
    8.31 -    para = True
    8.32 -    inlist = 0
    8.33 -    for line in ifp:
    8.34 -        if line.startswith('%%% Local Variables:'):
    8.35 -            break
    8.36 -        line = (line.rstrip()
    8.37 -                .replace('~', ' ')
    8.38 -                .replace('&', '&amp;')
    8.39 -                .replace('---', '&emdash;')
    8.40 -                .replace('\_', '_')
    8.41 -                .replace('\{', '{')
    8.42 -                .replace('\}', '}')
    8.43 -                .replace('\$', '$')
    8.44 -                .replace('\%', '%')
    8.45 -                .replace('\#', '#')
    8.46 -                .replace('<', '&lt;')
    8.47 -                .replace('>', '&gt;')
    8.48 -                .replace('``', '<quote>')
    8.49 -                .replace("''", '</quote>')
    8.50 -                .replace('\\', '\\'))
    8.51 -        line = re.sub(r'\s*\\(?:centering|small)\b\s*', '', line)
    8.52 -        line = re.sub(r'\\(?:hgrc\\|hgrc)\b',
    8.53 -                      r'<filename role="special"> /.hgrc</filename>', line)
    8.54 -        line = re.sub(r'\\item\[(?P<key>[^]]+)\]', r'\item \g<key>:', line)
    8.55 -        line = re.sub(r'\\bug{(?P<id>\d+)}',
    8.56 -                      r'<ulink role="hg-bug" url="http://www.selenic.com/mercurial/bts/issue\g<id>">issue \g<id></ulink>', line)
    8.57 -        line = re.sub(r'\\cite{([^}]+)}', r'<citation>\1</citation>', line)
    8.58 -        line = re.sub(r'\\hggopt{(?P<opt>[^}]+)}',
    8.59 -                      r'<option role="hg-opt-global">\g<opt></option>', line)
    8.60 -        line = re.sub(r'\\hgxopt{(?P<ext>[^}]+)}{(?P<cmd>[^}]+)}{(?P<opt>[^}]+)}',
    8.61 -                      r'<option role="hg-ext-\g<ext>-cmd-\g<cmd>-opt">\g<opt></option>', line)
    8.62 -        line = re.sub(r'\\hgxcmd{(?P<ext>[^}]+)}{(?P<cmd>[^}]+)}',
    8.63 -                      r'<command role="hg-ext-\g<ext>">\g<cmd></command>', line)
    8.64 -        line = re.sub(r'\\hgext{(?P<ext>[^}]+)}',
    8.65 -                      r'<literal role="hg-ext">\g<ext></literal>', line)
    8.66 -        line = re.sub(r'\\hgopt{(?P<cmd>[^}]+)}{(?P<opt>[^}]+)}',
    8.67 -                      r'<option role="hg-opt-\g<cmd>">\g<opt></option>',
    8.68 -                      line)
    8.69 -        line = re.sub(r'\\cmdopt{(?P<cmd>[^}]+)}{(?P<opt>[^}]+)}',
    8.70 -                      r'<option role="cmd-opt-\g<cmd>">\g<opt></option>',
    8.71 -                      line)
    8.72 -        line = re.sub(r'\\hgcmd{(?P<cmd>[^}]+)}',
    8.73 -                      r'<command role="hg-cmd">hg \g<cmd></command>', line)
    8.74 -        line = re.sub(r'\\caption{(?P<text>[^}]+?)}',
    8.75 -                      r'<caption><para>\g<text></para></caption>', line)
    8.76 -        line = re.sub(r'\\grafix{(?P<name>[^}]+)}',
    8.77 -                      r'<mediaobject><imageobject><imagedata fileref="\g<name>"/></imageobject><textobject><phrase>XXX add text</phrase></textobject></mediaobject>', line)
    8.78 -        line = re.sub(r'\\envar{(?P<name>[^}]+)}',
    8.79 -                      r'<envar>\g<name></envar>', line)
    8.80 -        line = re.sub(r'\\rcsection{(?P<sect>[^}]+)}',
    8.81 -                      r'<literal role="rc-\g<sect>">\g<sect></literal>', line)
    8.82 -        line = re.sub(r'\\rcitem{(?P<sect>[^}]+)}{(?P<name>[^}]+)}',
    8.83 -                      r'<envar role="rc-item-\g<sect>">\g<name></envar>', line)
    8.84 -        line = re.sub(r'\\dirname{(?P<dir>[^}]+?)}',
    8.85 -                      r'<filename class="directory">\g<dir></filename>', line)
    8.86 -        line = re.sub(r'\\filename{(?P<file>[^}]+?)}',
    8.87 -                      r'<filename>\g<file></filename>', line)
    8.88 -        line = re.sub(r'\\tildefile{(?P<file>[^}]+)}',
    8.89 -                      r'<filename role="home">~/\g<file></filename>', line)
    8.90 -        line = re.sub(r'\\sfilename{(?P<file>[^}]+)}',
    8.91 -                      r'<filename role="special">\g<file></filename>', line)
    8.92 -        line = re.sub(r'\\sdirname{(?P<dir>[^}]+)}',
    8.93 -                      r'<filename role="special" class="directory">\g<dir></filename>', line)
    8.94 -        line = re.sub(r'\\interaction{(?P<id>[^}]+)}',
    8.95 -                      r'<!-- &interaction.\g<id>; -->', line)
    8.96 -        line = re.sub(r'\\excode{(?P<id>[^}]+)}',
    8.97 -                      r'<!-- &example.\g<id>; -->', line)
    8.98 -        line = re.sub(r'\\pymod{(?P<mod>[^}]+)}',
    8.99 -                      r'<literal role="py-mod">\g<mod></literal>', line)
   8.100 -        line = re.sub(r'\\pymodclass{(?P<mod>[^}]+)}{(?P<class>[^}]+)}',
   8.101 -                      r'<literal role="py-mod-\g<mod>">\g<class></literal>', line)
   8.102 -        line = re.sub(r'\\url{(?P<url>[^}]+)}',
   8.103 -                      r'<ulink url="\g<url>">\g<url></ulink>', line)
   8.104 -        line = re.sub(r'\\href{(?P<url>[^}]+)}{(?P<text>[^}]+)}',
   8.105 -                      r'<ulink url="\g<url>">\g<text></ulink>', line)
   8.106 -        line = re.sub(r'\\command{(?P<cmd>[^}]+)}',
   8.107 -                      r'<command>\g<cmd></command>', line)
   8.108 -        line = re.sub(r'\\option{(?P<opt>[^}]+)}',
   8.109 -                      r'<option>\g<opt></option>', line)
   8.110 -        line = re.sub(r'\\ref{(?P<id>[^}]+)}', r'<xref linkend="\g<id>"/>', line)
   8.111 -        line = re.sub(r'\\emph{(?P<txt>[^}]+)}',
   8.112 -                      r'<emphasis>\g<txt></emphasis>', line)
   8.113 -        line = re.sub(r'\\texttt{(?P<txt>[^}]+)}',
   8.114 -                      r'<literal>\g<txt></literal>', line)
   8.115 -        line = re.sub(r'\\textbf{(?P<txt>[^}]+)}',
   8.116 -                      r'<emphasis role="bold">\g<txt></emphasis>', line)
   8.117 -        line = re.sub(r'\\hook{(?P<name>[^}]+)}',
   8.118 -                      r'<literal role="hook">\g<name></literal>', line)
   8.119 -        line = re.sub(r'\\tplfilter{(?P<name>[^}]+)}',
   8.120 -                      r'<literal role="template-filter">\g<name></literal>', line)
   8.121 -        line = re.sub(r'\\tplkword{(?P<name>[^}]+)}',
   8.122 -                      r'<literal role="template-keyword">\g<name></literal>', line)
   8.123 -        line = re.sub(r'\\tplkwfilt{(?P<tpl>[^}]+)}{(?P<name>[^}]+)}',
   8.124 -                      r'<literal role="template-kw-filt-\g<tpl>">\g<name></literal>', line)
   8.125 -        line = re.sub(r'\\[vV]erb(.)(?P<txt>[^\1]+?)\1',
   8.126 -                      r'<literal>\g<txt></literal>', line)
   8.127 -        line = re.sub(r'\\package{(?P<name>[^}]+)}',
   8.128 -                      r'<literal role="package">\g<name></literal>', line)
   8.129 -        line = re.sub(r'\\hgcmdargs{(?P<cmd>[^}]+)}{(?P<args>[^}]+)}',
   8.130 -                      r'<command role="hg-cmd">hg \g<cmd> \g<args></command>',
   8.131 -                      line)
   8.132 -        line = re.sub(r'\\cmdargs{(?P<cmd>[^}]+)}{(?P<args>[^}]+)}',
   8.133 -                      r'<command>\g<cmd> \g<args></command>',
   8.134 -                      line)
   8.135 -        m = re.match(r'\\(chapter|section|subsection|subsubsection){(.*)}', line)
   8.136 -        if m:
   8.137 -            kind, content = m.groups()
   8.138 -            sec = sections[kind]
   8.139 -            while stack and stack[-1] >= sec:
   8.140 -                close = stack.pop()
   8.141 -                print >> ofp, '</%s>' % close
   8.142 -            stack.append(sec)
   8.143 -            print >> ofp, '<%s>\n<title>%s</title>' % (sec, content)
   8.144 -        else:
   8.145 -            m = re.match(r'\s*\\(begin|end){(?P<sect>[^}]+)}', line)
   8.146 -            if m:
   8.147 -                if not para:
   8.148 -                    print >> ofp, '</para>'
   8.149 -                    if inlist:
   8.150 -                        ofp.write('</listitem>')
   8.151 -                    para = True
   8.152 -                state, env = m.groups()
   8.153 -                env = envs[env]
   8.154 -                if state == 'begin':
   8.155 -                    ofp.write('<')
   8.156 -                    if env in ('itemizedlist', 'orderedlist'):
   8.157 -                        inlist = 1
   8.158 -                else:
   8.159 -                    ofp.write('</')
   8.160 -                    if env in ('itemizedlist', 'orderedlist'):
   8.161 -                        inlist = 0
   8.162 -                print >> ofp, env + '>'
   8.163 -            else:
   8.164 -                if line.startswith('\\item '):
   8.165 -                    if inlist > 1:
   8.166 -                        print >> ofp, '</para>'
   8.167 -                        print >> ofp, '</listitem>'
   8.168 -                    else:
   8.169 -                        inlist = 2
   8.170 -                    para = True
   8.171 -                    line = line[6:]
   8.172 -                if line and para:
   8.173 -                    if inlist:
   8.174 -                        ofp.write('<listitem>')
   8.175 -                    ofp.write('<para>')
   8.176 -                    para = False
   8.177 -                if not line and not para:
   8.178 -                    print >> ofp, '</para>'
   8.179 -                    if inlist:
   8.180 -                        ofp.write('</listitem>')
   8.181 -                    para = True
   8.182 -                print >> ofp, line
   8.183 -    while stack:
   8.184 -        print >> ofp, '</%s>' % stack.pop()
   8.185 -    ofp.write('\n'.join(['\n<!--',
   8.186 -                         'local variables: ',
   8.187 -                         'sgml-parent-document: ("00book.xml" "book" "chapter")',
   8.188 -                         'end:',
   8.189 -                         '-->']))
   8.190 -
   8.191 -
   8.192 -if __name__ == '__main__':
   8.193 -    for name in sys.argv[1:]:
   8.194 -        if not name.endswith('.tex'):
   8.195 -            continue
   8.196 -        newname = name[:-3] + 'xml'
   8.197 -        ofp = StringIO.StringIO()
   8.198 -        process(open(name), ofp)
   8.199 -        s = ofp.getvalue()
   8.200 -        s = re.sub('\n+</para>', '</para>', s, re.M)
   8.201 -        open(newname, 'w').write(s)