Merge with stable
authorMatt Mackall <mpm@selenic.com>
Tue, 11 May 2010 17:03:44 -0500
changeset 11156 b203a95fe68b
parent 11155 245a67fe2574 (diff)
parent 11154 17031fea4e95 (current diff)
child 11161 a2c32edc407b
Merge with stable
mercurial/hg.py
mercurial/localrepo.py
--- a/Makefile	Mon Dec 07 12:31:45 2009 +0200
+++ b/Makefile	Tue May 11 17:03:44 2010 -0500
@@ -51,7 +51,7 @@
 install: install-bin install-doc
 
 install-bin: build
-	$(PYTHON) setup.py $(PURE) install --prefix="$(PREFIX)" --force
+	$(PYTHON) setup.py $(PURE) install --root="$(DESTDIR)/" --prefix="$(PREFIX)" --force
 
 install-doc: doc
 	cd doc && $(MAKE) $(MFLAGS) install
--- a/contrib/check-code.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/contrib/check-code.py	Tue May 11 17:03:44 2010 -0500
@@ -7,12 +7,19 @@
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 
-import sys, re, glob
+import re, glob
+import optparse
 
 def repquote(m):
-    t = re.sub(r"\w", "x", m.group(2))
+    t = re.sub(r"\w", "x", m.group('text'))
     t = re.sub(r"[^\sx]", "o", t)
-    return m.group(1) + t + m.group(1)
+    return m.group('quote') + t + m.group('quote')
+
+def reppython(m):
+    comment = m.group('comment')
+    if comment:
+        return "#" * len(comment)
+    return repquote(m)
 
 def repcomment(m):
     return m.group(1) + "#" * len(m.group(2))
@@ -84,6 +91,7 @@
     (r'[\x80-\xff]', "non-ASCII character literal"),
     (r'("\')\.format\(', "str.format() not available in Python 2.4"),
     (r'^\s*with\s+', "with not available in Python 2.4"),
+    (r'^\s*(any|all)\(', "any/all not available in Python 2.4"),
     (r'if\s.*\selse', "if ... else form not available in Python 2.4"),
     (r'([\(\[]\s\S)|(\S\s[\)\]])', "gratuitous whitespace in () or []"),
 #    (r'\s\s=', "gratuitous whitespace before ="),
@@ -92,15 +100,15 @@
     (r'\s(\+=|-=|!=|<>|<=|>=|<<=|>>=)\S', "missing whitespace around operator"),
     (r'[^+=*!<>&| -](\s=|=\s)[^= ]', "wrong whitespace around ="),
     (r'raise Exception', "don't raise generic exceptions"),
-    (r'ui\.(status|progress|write|note)\([\'\"]x', "unwrapped ui message"),
+    (r'ui\.(status|progress|write|note)\([\'\"]x',
+     "warning: unwrapped ui message"),
 ]
 
 pyfilters = [
-    (r"""(''')(([^']|\\'|'{1,2}(?!'))*)'''""", repquote),
-    (r'''(""")(([^"]|\\"|"{1,2}(?!"))*)"""''', repquote),
-    (r'''(?<!")(")(([^"\n]|\\")+)"(?!")''', repquote),
-    (r"""(?<!')(')(([^'\n]|\\')+)'(?!')""", repquote),
-    (r"( *)(#([^\n]*\S)?)", repcomment),
+    (r"""(?msx)(?P<comment>\#.*?$)|
+         ((?P<quote>('''|\"\"\"|(?<!')'(?!')|(?<!")"(?!")))
+          (?P<text>(([^\\]|\\.)*?))
+          (?P=quote))""", reppython),
 ]
 
 cpats = [
@@ -123,7 +131,7 @@
 
 cfilters = [
     (r'(/\*)(((\*(?!/))|[^*])*)\*/', repccomment),
-    (r'''(?<!")(")(([^"]|\\")+"(?!"))''', repquote),
+    (r'''(?P<quote>(?<!")")(?P<text>([^"]|\\")+)"(?!")''', repquote),
     (r'''(#\s*include\s+<)([^>]+)>''', repinclude),
     (r'(\()([^)]+\))', repcallspaces),
 ]
@@ -134,12 +142,42 @@
     ('c', r'.*\.c$', cfilters, cpats),
 ]
 
-if len(sys.argv) == 1:
-    check = glob.glob("*")
-else:
-    check = sys.argv[1:]
+class norepeatlogger(object):
+    def __init__(self):
+        self._lastseen = None
+
+    def log(self, fname, lineno, line, msg):
+        """print error related a to given line of a given file.
+
+        The faulty line will also be printed but only once in the case
+        of multiple errors.
 
-for f in check:
+        :fname: filename
+        :lineno: line number
+        :line: actual content of the line
+        :msg: error message
+        """
+        msgid = fname, lineno, line
+        if msgid != self._lastseen:
+            print "%s:%d:" % (fname, lineno)
+            print " > %s" % line
+            self._lastseen = msgid
+        print " " + msg
+
+_defaultlogger = norepeatlogger()
+
+def checkfile(f, logfunc=_defaultlogger.log, maxerr=None, warnings=False):
+    """checks style and portability of a given file
+
+    :f: filepath
+    :logfunc: function used to report error
+              logfunc(filename, linenumber, linecontent, errormessage)
+    :maxerr: number of error to display before arborting.
+             Set to None (default) to report all errors
+
+    return True if no error is found, False otherwise.
+    """
+    result = True
     for name, match, filters, pats in checks:
         fc = 0
         if not re.match(match, f):
@@ -154,16 +192,34 @@
         for n, l in z:
             if "check-code" + "-ignore" in l[0]:
                 continue
-            lc = 0
             for p, msg in pats:
+                if not warnings and msg.startswith("warning"):
+                    continue
                 if re.search(p, l[1]):
-                    if not lc:
-                        print "%s:%d:" % (f, n + 1)
-                        print " > %s" % l[0]
-                    print " %s" % msg
-                    lc += 1
+                    logfunc(f, n + 1, l[0], msg)
                     fc += 1
-            if fc == 15:
+                    result = False
+            if maxerr is not None and fc >= maxerr:
                 print " (too many errors, giving up)"
                 break
         break
+    return result
+
+
+if __name__ == "__main__":
+    parser = optparse.OptionParser("%prog [options] [files]")
+    parser.add_option("-w", "--warnings", action="store_true",
+                      help="include warning-level checks")
+    parser.add_option("-p", "--per-file", type="int",
+                      help="max warnings per file")
+
+    parser.set_defaults(per_file=15, warnings=False)
+    (options, args) = parser.parse_args()
+
+    if len(args) == 0:
+        check = glob.glob("*")
+    else:
+        check = args
+
+    for f in check:
+        checkfile(f, maxerr=options.per_file, warnings=options.warnings)
--- a/contrib/git-viz/git-cat-file	Mon Dec 07 12:31:45 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-#!/bin/sh
-
-op=`basename $0 | sed -e 's/^git-//'`
-exec hgit $op "$@"
-
--- a/contrib/git-viz/git-diff-tree	Mon Dec 07 12:31:45 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-#!/bin/sh
-
-op=`basename $0 | sed -e 's/^git-//'`
-exec hgit $op "$@"
-
--- a/contrib/git-viz/git-rev-list	Mon Dec 07 12:31:45 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-#!/bin/sh
-
-op=`basename $0 | sed -e 's/^git-//'`
-exec hgit $op "$@"
-
--- a/contrib/git-viz/git-rev-tree	Mon Dec 07 12:31:45 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
-#!/bin/sh
-
-op=`basename $0 | sed -e 's/^git-//'`
-exec hgit $op "$@"
-
--- a/contrib/git-viz/hg-viz	Mon Dec 07 12:31:45 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-#!/bin/sh
-
-set -e
-
-if test x"$1" != x ; then
-  cd $1
-fi
-
-if [ ! -d ".hg" ]; then
-    echo "${1:-.} is not a mercurial repository" 1>&2
-    echo "Aborting" 1>&2
-    exit 1
-fi
-if [ ! -d ".git" ]; then
-    mkdir -v ".git"
-fi
-if [ -e ".git/HEAD" ]; then
-    if [ ! -e ".git/HEAD.hg-viz-save" ]; then
-        mv -v ".git/HEAD" ".git/HEAD.hg-viz-save"
-    else
-        rm -vf ".git/HEAD"
-    fi
-fi
-hg history | head -1 | awk -F: '{print $3}' > .git/HEAD
-git-viz
-
--- a/contrib/hgdiff	Mon Dec 07 12:31:45 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-#!/usr/bin/env python
-
-import os, sys, struct, stat
-import difflib
-import re
-from optparse import OptionParser
-from mercurial.bdiff import bdiff, blocks
-from mercurial.mdiff import bunidiff, diffopts
-
-VERSION="0.3"
-usage = "usage: %prog [options] file1 file2"
-parser = OptionParser(usage=usage)
-
-parser.add_option("-d", "--difflib", action="store_true", default=False)
-parser.add_option('-x', '--count', default=1)
-parser.add_option('-c', '--context', type="int", default=3)
-parser.add_option('-p', '--show-c-function', action="store_true", default=False)
-parser.add_option('-w', '--ignore-all-space', action="store_true",
-                  default=False)
-
-(options, args) = parser.parse_args()
-
-if not args:
-    parser.print_help()
-    sys.exit(1)
-
-# simple utility function to put all the
-# files from a directory tree into a dict
-def buildlist(names, top):
-    tlen = len(top)
-    for root, dirs, files in os.walk(top):
-        l = root[tlen + 1:]
-        for x in files:
-            p = os.path.join(root, x)
-            st = os.lstat(p)
-            if stat.S_ISREG(st.st_mode):
-                names[os.path.join(l, x)] = (st.st_dev, st.st_ino)
-
-def diff_files(file1, file2):
-    if file1 is None:
-        b = file(file2).read().splitlines(True)
-        l1 = "--- %s\n" % (file2)
-        l2 = "+++ %s\n" % (file2)
-        l3 = "@@ -0,0 +1,%d @@\n" % len(b)
-        l = [l1, l2, l3] + ["+" + e for e in b]
-    elif file2 is None:
-        a = file(file1).read().splitlines(True)
-        l1 = "--- %s\n" % (file1)
-        l2 = "+++ %s\n" % (file1)
-        l3 = "@@ -1,%d +0,0 @@\n" % len(a)
-        l = [l1, l2, l3] + ["-" + e for e in a]
-    else:
-        t1 = file(file1).read()
-        t2 = file(file2).read()
-        l1 = t1.splitlines(True)
-        l2 = t2.splitlines(True)
-        if options.difflib:
-            l = difflib.unified_diff(l1, l2, file1, file2)
-        else:
-            l = bunidiff(t1, t2, l1, l2, file1, file2,
-                         diffopts(context=options.context,
-                                  showfunc=options.show_c_function,
-                                  ignorews=options.ignore_all_space))
-    for x in l:
-        if x[-1] != '\n':
-            x += "\n\ No newline at end of file\n"
-        print x,
-
-file1 = args[0]
-file2 = args[1]
-
-if os.path.isfile(file1) and os.path.isfile(file2):
-    diff_files(file1, file2)
-elif os.path.isdir(file1):
-    if not os.path.isdir(file2):
-        sys.stderr.write("file types don't match\n")
-        sys.exit(1)
-
-    d1 = {}
-    d2 = {}
-
-    buildlist(d1, file1)
-    buildlist(d2, file2)
-    keys = d1.keys()
-    keys.sort()
-    for x in keys:
-        if x not in d2:
-            f2 = None
-        else:
-            f2 = os.path.join(file2, x)
-            st1 = d1[x]
-            st2 = d2[x]
-            del d2[x]
-            if st1[0] == st2[0] and st1[1] == st2[1]:
-                sys.stderr.write("%s is a hard link\n" % x)
-                continue
-        x = os.path.join(file1, x)
-        diff_files(x, f2)
-    keys = d2.keys()
-    keys.sort()
-    for x in keys:
-        f1 = None
-        x = os.path.join(file2, x)
-        diff_files(f1, x)
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/hgweb.fcgi	Tue May 11 17:03:44 2010 -0500
@@ -0,0 +1,18 @@
+#!/usr/bin/env python
+#
+# An example FastCGI script for use with flup, edit as necessary
+
+# Path to repo or hgweb config to serve (see 'hg help hgweb')
+config = "/path/to/repo/or/config"
+
+# Uncomment and adjust if Mercurial is not installed system-wide:
+#import sys; sys.path.insert(0, "/path/to/python/lib")
+
+# Uncomment to send python tracebacks to the browser if an error occurs:
+#import cgitb; cgitb.enable()
+
+from mercurial import demandimport; demandimport.enable()
+from mercurial.hgweb import hgweb
+from flup.server.fcgi import WSGIServer
+application = hgweb(config)
+WSGIServer(application).run()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/hgweb.wsgi	Tue May 11 17:03:44 2010 -0500
@@ -0,0 +1,16 @@
+# An example WSGI for use with mod_wsgi, edit as necessary
+
+# Path to repo or hgweb config to serve (see 'hg help hgweb')
+config = "/path/to/repo/or/config"
+
+# Uncomment and adjust if Mercurial is not installed system-wide:
+#import sys; sys.path.insert(0, "/path/to/python/lib")
+
+# Uncomment to send python tracebacks to the browser if an error occurs:
+#import cgitb; cgitb.enable()
+
+# enable demandloading to reduce startup time
+from mercurial import demandimport; demandimport.enable()
+
+from mercurial.hgweb import hgweb
+application = hgweb(config)
--- a/contrib/hgwebdir.fcgi	Mon Dec 07 12:31:45 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-#!/usr/bin/env python
-#
-# An example CGI script to export multiple hgweb repos, edit as necessary
-
-# adjust python path if not a system-wide install:
-#import sys
-#sys.path.insert(0, "/path/to/python/lib")
-
-# enable demandloading to reduce startup time
-from mercurial import demandimport; demandimport.enable()
-
-# Uncomment to send python tracebacks to the browser if an error occurs:
-#import cgitb
-#cgitb.enable()
-
-# If you'd like to serve pages with UTF-8 instead of your default
-# locale charset, you can do so by uncommenting the following lines.
-# Note that this will cause your .hgrc files to be interpreted in
-# UTF-8 and all your repo files to be displayed using UTF-8.
-#
-#import os
-#os.environ["HGENCODING"] = "UTF-8"
-
-from mercurial.hgweb.hgwebdir_mod import hgwebdir
-from flup.server.fcgi import WSGIServer
-
-# The config file looks like this.  You can have paths to individual
-# repos, collections of repos in a directory tree, or both.
-#
-# [paths]
-# virtual/path1 = /real/path1
-# virtual/path2 = /real/path2
-# virtual/root = /real/root/*
-# / = /real/root2/*
-#
-# [collections]
-# /prefix/to/strip/off = /root/of/tree/full/of/repos
-#
-# paths example: 
-#
-# * First two lines mount one repository into one virtual path, like
-# '/real/path1' into 'virtual/path1'.
-#
-# * The third entry tells every mercurial repository found in
-# '/real/root', recursively, should be mounted in 'virtual/root'. This
-# format is preferred over the [collections] one, using absolute paths
-# as configuration keys is not supported on every platform (including
-# Windows).
-#
-# * The last entry is a special case mounting all repositories in
-# '/real/root2' in the root of the virtual directory.
-#
-# collections example: say directory tree /foo contains repos /foo/bar,
-# /foo/quux/baz.  Give this config section:
-#   [collections]
-#   /foo = /foo
-# Then repos will list as bar and quux/baz.
-#
-# Alternatively you can pass a list of ('virtual/path', '/real/path') tuples
-# or use a dictionary with entries like 'virtual/path': '/real/path'
-
-WSGIServer(hgwebdir('hgweb.config')).run()
--- a/contrib/hgwebdir.wsgi	Mon Dec 07 12:31:45 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-# An example WSGI (use with mod_wsgi) script to export multiple hgweb repos
-
-# adjust python path if not a system-wide install:
-#import sys
-#sys.path.insert(0, "/path/to/python/lib")
-
-# enable demandloading to reduce startup time
-from mercurial import demandimport; demandimport.enable()
-from mercurial.hgweb.hgwebdir_mod import hgwebdir
-
-# If you'd like to serve pages with UTF-8 instead of your default
-# locale charset, you can do so by uncommenting the following lines.
-# Note that this will cause your .hgrc files to be interpreted in
-# UTF-8 and all your repo files to be displayed using UTF-8.
-#
-#import os
-#os.environ["HGENCODING"] = "UTF-8"
-
-# The config file looks like this.  You can have paths to individual
-# repos, collections of repos in a directory tree, or both.
-#
-# [paths]
-# virtual/path1 = /real/path1
-# virtual/path2 = /real/path2
-# virtual/root = /real/root/*
-# / = /real/root2/*
-#
-# paths example:
-#
-# * First two lines mount one repository into one virtual path, like
-# '/real/path1' into 'virtual/path1'.
-#
-# * The third entry tells every mercurial repository found in
-# '/real/root', recursively, should be mounted in 'virtual/root'. This
-# format is preferred over the [collections] one, using absolute paths
-# as configuration keys is not supported on every platform (including
-# Windows).
-#
-# * The last entry is a special case mounting all repositories in
-# '/real/root2' in the root of the virtual directory.
-#
-# collections example: say directory tree /foo contains repos /foo/bar,
-# /foo/quux/baz.  Give this config section:
-#   [collections]
-#   /foo = /foo
-# Then repos will list as bar and quux/baz.
-#
-# Alternatively you can pass a list of ('virtual/path', '/real/path') tuples
-# or use a dictionary with entries like 'virtual/path': '/real/path'
-
-application = hgwebdir('hgweb.config')
--- a/contrib/logo-droplets.svg	Mon Dec 07 12:31:45 2009 +0200
+++ b/contrib/logo-droplets.svg	Tue May 11 17:03:44 2010 -0500
@@ -1,624 +1,5 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/"
-   xmlns:cc="http://web.resource.org/cc/"
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-   xmlns:svg="http://www.w3.org/2000/svg"
-   xmlns="http://www.w3.org/2000/svg"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   version="1.0"
-   width="100"
-   height="120"
-   viewBox="0 0 124.766 152.099"
-   id="Layer_1"
-   xml:space="preserve"
-   sodipodi:version="0.32"
-   inkscape:version="0.45.1"
-   sodipodi:docname="logo-droplets.svg"
-   sodipodi:docbase="/home/oxymoron/waste/selenic/public_html/hg-logo"
-   inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata
-   id="metadata6845"><rdf:RDF><cc:Work
-       rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
-         rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title>Mercurial &quot;droplets&quot; logo</dc:title><dc:creator><cc:Agent><dc:title>Cali Mastny and Matt Mackall</dc:title></cc:Agent></dc:creator><cc:license
-         rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" /><dc:date>Feb 12 2008</dc:date></cc:Work><cc:License
-       rdf:about="http://creativecommons.org/licenses/GPL/2.0/"><cc:permits
-         rdf:resource="http://web.resource.org/cc/Reproduction" /><cc:permits
-         rdf:resource="http://web.resource.org/cc/Distribution" /><cc:requires
-         rdf:resource="http://web.resource.org/cc/Notice" /><cc:permits
-         rdf:resource="http://web.resource.org/cc/DerivativeWorks" /><cc:requires
-         rdf:resource="http://web.resource.org/cc/ShareAlike" /><cc:requires
-         rdf:resource="http://web.resource.org/cc/SourceCode" /></cc:License></rdf:RDF></metadata><sodipodi:namedview
-   inkscape:window-height="576"
-   inkscape:window-width="746"
-   inkscape:pageshadow="2"
-   inkscape:pageopacity="0.0"
-   guidetolerance="10.0"
-   gridtolerance="10.0"
-   objecttolerance="10.0"
-   borderopacity="1.0"
-   bordercolor="#666666"
-   pagecolor="#ffffff"
-   id="base"
-   inkscape:zoom="2.3216673"
-   inkscape:cx="4.1210694"
-   inkscape:cy="65.759396"
-   inkscape:window-x="377"
-   inkscape:window-y="398"
-   inkscape:current-layer="Layer_1"
-   width="100px"
-   height="120px"
-   units="px" /><defs
-   id="defs261" />
-<pattern
-   overflow="visible"
-   viewBox="2.125 -70.896 69 69"
-   id="Polka_Dot_Pattern"
-   patternUnits="userSpaceOnUse"
-   height="69"
-   width="69"
-   y="736.415"
-   x="-316">
-	<g
-   id="g4">
-		<polygon
-   id="polygon6"
-   points="71.125,-1.896 2.125,-1.896 2.125,-70.896 71.125,-70.896   "
-   fill="none" />
-		<polygon
-   id="polygon8"
-   points="71.125,-1.896 2.125,-1.896 2.125,-70.896 71.125,-70.896   "
-   fill="#F7BC60" />
-		<g
-   id="g10">
-			<path
-   id="path12"
-   d="M61.772-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-			<path
-   id="path14"
-   d="M54.105-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-			<path
-   id="path16"
-   d="M46.439-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-			<path
-   id="path18"
-   d="M38.772-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-			<path
-   id="path20"
-   d="M31.105-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-			<path
-   id="path22"
-   d="M23.439-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-			<path
-   id="path24"
-   d="M15.772-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-			<path
-   id="path26"
-   d="M8.105-71.653c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-			<path
-   id="path28"
-   d="M0.439-71.653c0.018,0.072,0.008,0.127-0.026,0.19C0.361-71.362,0.3-71.4,0.248-71.335     c-0.051,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.215,0.124-0.215,0.224c0.002,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-		</g>
-		<g
-   id="g30">
-			<path
-   id="path32"
-   d="M69.439-71.653c0.018,0.072,0.008,0.127-0.026,0.19c-0.052,0.101-0.113,0.062-0.165,0.128     c-0.051,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.215,0.124-0.215,0.224c0.002,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-		</g>
-		<path
-   id="path34"
-   d="M0.495-71.653c0.018,0.072,0.008,0.127-0.026,0.19c-0.052,0.101-0.113,0.062-0.165,0.128    c-0.051,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161    c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631    c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45    c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221    c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337    c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207    c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.215,0.124-0.215,0.224C0.5-71.68,0.503-71.744,0.51-71.626    c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-		<g
-   id="g36">
-			<g
-   id="g38">
-				<path
-   id="path40"
-   d="M69.439-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path42"
-   d="M61.778-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path44"
-   d="M54.118-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path46"
-   d="M46.458-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path48"
-   d="M38.797-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path50"
-   d="M31.137-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path52"
-   d="M23.477-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path54"
-   d="M15.816-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path56"
-   d="M8.156-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path58"
-   d="M0.495-64.001c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143C2-61.45,2.217-61.397,2.391-61.46c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-			</g>
-			<g
-   id="g60">
-				<path
-   id="path62"
-   d="M69.439-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path64"
-   d="M61.778-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path66"
-   d="M54.118-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path68"
-   d="M46.458-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path70"
-   d="M38.797-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path72"
-   d="M31.137-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path74"
-   d="M23.477-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path76"
-   d="M15.816-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path78"
-   d="M8.156-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path80"
-   d="M0.495-56.348c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224C0.5-56.374,0.503-56.438,0.51-56.32      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-			</g>
-			<g
-   id="g82">
-				<path
-   id="path84"
-   d="M69.439-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path86"
-   d="M61.778-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path88"
-   d="M54.118-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path90"
-   d="M46.458-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path92"
-   d="M38.797-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path94"
-   d="M31.137-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path96"
-   d="M23.477-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path98"
-   d="M15.816-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path100"
-   d="M8.156-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path102"
-   d="M0.495-48.695c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-			</g>
-			<g
-   id="g104">
-				<path
-   id="path106"
-   d="M69.439-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path108"
-   d="M61.778-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path110"
-   d="M54.118-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path112"
-   d="M46.458-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path114"
-   d="M38.797-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path116"
-   d="M31.137-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path118"
-   d="M23.477-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path120"
-   d="M15.816-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path122"
-   d="M8.156-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      C8.15-41.004,8.149-41.02,8.14-41.04"
-   fill="#FFFFFF" />
-				<path
-   id="path124"
-   d="M0.495-41.042c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-			</g>
-			<g
-   id="g126">
-				<path
-   id="path128"
-   d="M69.439-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path130"
-   d="M61.778-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path132"
-   d="M54.118-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path134"
-   d="M46.458-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path136"
-   d="M38.797-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path138"
-   d="M31.137-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path140"
-   d="M23.477-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path142"
-   d="M15.816-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path144"
-   d="M8.156-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path146"
-   d="M0.495-33.39c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224C0.5-33.416,0.503-33.48,0.51-33.362      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-			</g>
-			<g
-   id="g148">
-				<path
-   id="path150"
-   d="M69.439-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path152"
-   d="M61.778-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path154"
-   d="M54.118-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path156"
-   d="M46.458-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path158"
-   d="M38.797-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path160"
-   d="M31.137-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path162"
-   d="M23.477-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path164"
-   d="M15.816-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path166"
-   d="M8.156-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path168"
-   d="M0.495-25.736c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-			</g>
-			<g
-   id="g170">
-				<path
-   id="path172"
-   d="M69.439-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path174"
-   d="M61.778-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path176"
-   d="M54.118-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path178"
-   d="M46.458-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path180"
-   d="M38.797-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path182"
-   d="M31.137-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path184"
-   d="M23.477-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path186"
-   d="M15.816-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path188"
-   d="M8.156-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path190"
-   d="M0.495-18.084c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224C0.5-18.11,0.503-18.175,0.51-18.057      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-			</g>
-			<g
-   id="g192">
-				<path
-   id="path194"
-   d="M69.439-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362C69-9.692,69.159-9.523,69.154-9.4c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path196"
-   d="M61.778-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path198"
-   d="M54.118-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path200"
-   d="M46.458-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path202"
-   d="M38.797-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path204"
-   d="M31.137-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path206"
-   d="M23.477-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path208"
-   d="M15.816-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.009,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      c0.177,0.042,0.384-0.104,0.543-0.143c0.18-0.043,0.397,0.01,0.571-0.053C17.933-7.969,17.839-8.227,18-8.34      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path210"
-   d="M8.156-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      C7.915-10.05,7.866-9.836,7.886-9.75C7.717-9.692,7.876-9.523,7.871-9.4C7.868-9.351,7.83-9.295,7.826-9.239      c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631      C9.114-7.652,9.321-7.799,9.48-7.837c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-				<path
-   id="path212"
-   d="M0.495-10.431c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128      C0.254-10.05,0.205-9.836,0.225-9.75C0.056-9.692,0.215-9.523,0.21-9.4c-0.002,0.05-0.041,0.105-0.045,0.161      c-0.01,0.119,0.017,0.266,0.068,0.37C0.33-8.671,0.501-8.456,0.668-8.325c0.19,0.148,0.365,0.572,0.608,0.631      C1.454-7.652,1.66-7.799,1.819-7.837C2-7.88,2.217-7.827,2.391-7.89c0.222-0.079,0.127-0.337,0.288-0.45      c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46C3.477-8.933,3.471-8.995,3.5-9.071      c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337      c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207      c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169      c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-			</g>
-		</g>
-		<g
-   id="g214">
-			<path
-   id="path216"
-   d="M69.439-2.778c0.018,0.072,0.008,0.127-0.026,0.19C69.361-2.487,69.3-2.525,69.248-2.46     c-0.051,0.062-0.099,0.276-0.079,0.362C69-2.04,69.159-1.871,69.154-1.748c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C70.397,0,70.604-0.146,70.763-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.215,0.124-0.215,0.224c0.002,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-			<path
-   id="path218"
-   d="M61.778-2.778c0.018,0.072,0.007,0.127-0.026,0.19C61.7-2.487,61.64-2.525,61.587-2.46     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C62.737,0,62.943-0.146,63.103-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C61.915-3.117,61.78-3.02,61.781-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-			<path
-   id="path220"
-   d="M54.118-2.778c0.018,0.072,0.007,0.127-0.026,0.19C54.04-2.487,53.98-2.525,53.927-2.46     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C55.077,0,55.283-0.146,55.442-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C54.255-3.117,54.12-3.02,54.121-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-			<path
-   id="path222"
-   d="M46.458-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C47.416,0,47.623-0.146,47.782-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C46.594-3.117,46.459-3.02,46.46-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-			<path
-   id="path224"
-   d="M38.797-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C39.756,0,39.962-0.146,40.122-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C38.934-3.117,38.799-3.02,38.8-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-			<path
-   id="path226"
-   d="M31.137-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C32.095,0,32.302-0.146,32.461-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224C31.273-3.117,31.139-3.02,31.14-2.92c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-			<path
-   id="path228"
-   d="M23.477-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C24.435,0,24.642-0.146,24.801-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     c-0.021,0.011-0.021-0.005-0.03-0.025"
-   fill="#FFFFFF" />
-			<path
-   id="path230"
-   d="M15.816-2.778c0.018,0.072,0.007,0.127-0.026,0.19c-0.053,0.101-0.112,0.062-0.165,0.128     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C16.774,0,16.981-0.146,17.14-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789c-0.18,0.034-0.287,0.126-0.442,0.207     c-0.17,0.088-0.139,0.166-0.318,0.224c-0.081,0.026-0.216,0.124-0.215,0.224c0.001,0.115,0.005,0.051,0.012,0.169     C15.81-2.74,15.809-2.756,15.8-2.776"
-   fill="#FFFFFF" />
-			<path
-   id="path232"
-   d="M8.156-2.778c0.018,0.072,0.007,0.127-0.026,0.19C8.077-2.487,8.018-2.525,7.965-2.46     c-0.05,0.062-0.099,0.276-0.079,0.362c-0.169,0.058-0.01,0.227-0.015,0.35C7.868-1.698,7.83-1.643,7.826-1.587     c-0.01,0.119,0.017,0.266,0.068,0.37c0.097,0.198,0.268,0.413,0.435,0.544c0.19,0.148,0.365,0.572,0.608,0.631     C9.114,0,9.321-0.146,9.48-0.185c0.18-0.043,0.397,0.01,0.571-0.053c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.069,0.339-0.263,0.376-0.46c0.016-0.082,0.01-0.145,0.039-0.221     c0.039-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.052-0.12-0.064-0.187c-0.022-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789C8.954-3.54,8.847-3.448,8.692-3.367     c-0.17,0.088-0.139,0.166-0.318,0.224C8.292-3.117,8.158-3.02,8.159-2.92C8.16-2.805,8.164-2.869,8.17-2.751     C8.15-2.74,8.149-2.756,8.14-2.776"
-   fill="#FFFFFF" />
-			<path
-   id="path234"
-   d="M0.495-2.778c0.018,0.072,0.008,0.127-0.026,0.19C0.417-2.487,0.356-2.525,0.304-2.46     C0.253-2.397,0.205-2.184,0.225-2.098C0.056-2.04,0.215-1.871,0.21-1.748c-0.002,0.05-0.041,0.105-0.045,0.161     c-0.01,0.119,0.017,0.266,0.068,0.37C0.33-1.019,0.501-0.804,0.668-0.673c0.19,0.148,0.365,0.572,0.608,0.631     C1.454,0,1.66-0.146,1.819-0.185C2-0.228,2.217-0.175,2.391-0.237c0.222-0.079,0.127-0.337,0.288-0.45     c0.104-0.074,0.287-0.01,0.406-0.051c0.2-0.07,0.339-0.263,0.376-0.46C3.477-1.28,3.471-1.343,3.5-1.419     c0.038-0.103,0.111-0.16,0.09-0.293c-0.01-0.062-0.051-0.12-0.064-0.187c-0.021-0.114,0.002-0.224,0-0.337     c-0.003-0.2,0.017-0.379-0.078-0.55c-0.38-0.688-1.236-0.929-1.975-0.789C1.293-3.54,1.187-3.448,1.031-3.367     c-0.17,0.088-0.139,0.166-0.318,0.224C0.632-3.117,0.498-3.02,0.498-2.92C0.5-2.805,0.503-2.869,0.51-2.751     C0.489-2.74,0.488-2.756,0.479-2.776"
-   fill="#FFFFFF" />
-		</g>
-	</g>
-</pattern>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-<rect
-   style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.97552931;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-   id="rect6847"
-   width="124.77364"
-   height="150.12347"
-   x="0.31690097"
-   y="0.98776293" /><path
-   d="M 9.8480335,124.60683 C 11.62496,123.82337 13.513211,123.43203 15.327243,123.43203 C 17.067063,123.43203 18.177759,123.85879 18.806894,124.74937 C 20.139374,123.8596 21.953416,123.43203 23.360116,123.43203 C 27.581053,123.43203 27.728648,125.14068 27.728648,130.16028 L 27.728648,141.26547 C 27.728648,141.76382 27.802857,141.76382 25.692811,141.76382 L 25.692811,129.94606 C 25.692811,126.31544 25.618592,125.21154 23.213365,125.21154 C 22.139794,125.21154 21.029108,125.4603 19.844204,126.24379 L 19.844204,141.5142 C 19.807099,141.65677 19.732887,141.69215 19.474821,141.72758 C 19.436863,141.72758 19.400602,141.763 19.362653,141.763 L 17.807522,141.763 L 17.807522,129.94606 C 17.807522,126.45791 17.807522,125.17607 15.29098,125.17607 C 14.2174,125.17607 13.143818,125.38944 11.884705,125.99501 L 11.884705,141.26547 C 11.884705,141.76382 11.958925,141.76382 9.8488776,141.76382 L 9.8488776,124.60683 M 37.680118,123.43203 C 34.533596,123.43203 31.053954,124.32176 31.053954,133.8263 C 31.053954,141.15915 33.607611,142.29771 37.125192,142.29771 C 39.826435,142.29771 42.159131,141.40799 42.159131,140.98039 C 42.159131,140.44659 42.084921,139.62768 41.900221,139.16468 C 40.75243,139.94814 39.123081,140.37486 37.309893,140.37486 C 34.829612,140.37486 33.164001,139.66309 33.126052,134.14592 C 34.755402,134.14592 38.902128,134.11044 41.97444,133.50498 C 42.233351,132.33022 42.343821,130.62155 42.343821,129.12711 C 42.343821,125.56743 40.900016,123.43203 37.680118,123.43203 M 37.494584,125.21154 C 39.715955,125.21154 40.307995,126.67048 40.3451,129.51849 C 40.3451,130.26565 40.307995,131.15541 40.19667,132.00972 C 38.123729,132.50815 34.60612,132.50815 33.125209,132.50815 C 33.385806,126.0304 35.606333,125.21154 37.494584,125.21154 M 45.565397,124.99816 C 47.304384,123.85879 48.897464,123.43203 50.525969,123.43203 C 52.34,123.43203 53.191776,123.93046 53.191776,124.53602 C 53.191776,124.89187 53.079617,125.49742 52.894917,125.85331 C 52.376261,125.56823 51.785075,125.31945 50.821131,125.31945 C 49.637079,125.31945 48.526385,125.63909 47.638339,126.42255 L 47.638339,141.26632 C 47.638339,141.7647 47.675453,141.7647 45.565397,141.7647 L 45.565397,124.99816 M 64.254794,124.60683 C 64.254794,124.14383 62.700508,123.43203 61.145377,123.43203 C 58.145598,123.43203 54.481256,124.4643 54.481256,133.25617 C 54.481256,141.58507 56.70347,142.3331 60.589608,142.3331 C 62.514121,142.3331 64.254794,141.30089 64.254794,140.73161 C 64.254794,140.4111 64.181418,139.91269 63.99504,139.48515 C 63.217475,140.05441 62.033423,140.58905 60.775152,140.58905 C 58.11018,140.58905 56.55504,139.84185 56.55504,133.3633 C 56.55504,126.20837 59.108698,125.21154 61.330069,125.21154 C 62.58834,125.21154 63.291694,125.56743 63.99504,126.0304 C 64.181418,125.60367 64.254794,124.99816 64.254794,124.60683 M 78.435657,141.15915 C 76.806308,141.97803 74.659991,142.29851 72.808845,142.29851 C 68.070088,142.29851 67.366733,140.30571 67.366733,135.57114 L 67.366733,124.42971 C 67.366733,123.96757 67.330471,123.96757 69.440527,123.96757 L 69.440527,135.7854 C 69.440527,139.34513 69.958338,140.55538 72.734626,140.55538 C 73.808215,140.55538 75.289126,140.34199 76.399811,139.70105 L 76.399811,124.43056 C 76.399811,123.96839 76.325602,123.96839 78.435657,123.96839 L 78.435657,141.15915 M 82.657438,124.99816 C 84.396406,123.85879 85.98865,123.43203 87.617156,123.43203 C 89.431178,123.43203 90.282962,123.93046 90.282962,124.53602 C 90.282962,124.89187 90.171639,125.49742 89.986938,125.85331 C 89.468283,125.56823 88.876272,125.31945 87.913163,125.31945 C 86.729111,125.31945 85.618415,125.63909 84.729535,126.42255 L 84.729535,141.26632 C 84.729535,141.7647 84.767484,141.7647 82.657438,141.7647 L 82.657438,124.99816 M 95.036045,123.9659 C 93.406714,123.9659 92.926008,123.9659 92.926008,124.92729 L 92.926008,141.76382 C 94.99895,141.76382 95.036045,141.76382 95.036045,141.26547 L 95.036045,123.9659 M 92.851787,117.70149 C 92.851787,118.87629 93.222023,119.30304 93.961631,119.33843 C 94.813415,119.33843 95.220746,118.73376 95.220746,117.66526 C 95.257851,116.56214 94.960991,116.06374 94.11006,116.06374 C 93.296243,116.06374 92.888893,116.66926 92.851787,117.70149 M 98.547748,124.99816 C 98.547748,124.60683 98.62196,124.39264 98.770389,124.28635 C 99.473743,123.89502 102.17666,123.43203 105.24898,123.43203 C 107.58166,123.43203 109.06174,124.53602 109.06174,127.73899 L 109.06174,130.05231 C 109.06174,136.38835 108.87704,141.12293 108.87704,141.12293 C 108.02528,141.58507 106.43387,142.29771 103.84143,142.29771 C 101.17646,142.3331 98.511478,142.0843 98.511478,136.81596 C 98.511478,131.7972 101.25067,131.01375 103.98986,131.01375 C 105.02633,131.01375 106.24834,131.12082 107.06301,131.4413 C 107.06301,131.4413 107.06301,129.12711 107.06301,128.13033 C 107.06301,125.81704 105.87895,125.31862 104.47141,125.31862 C 102.58399,125.31862 99.956127,125.67451 98.808337,126.20837 C 98.585707,125.81704 98.547748,125.21154 98.547748,124.99816 M 107.06216,132.9011 C 106.35882,132.65147 105.35945,132.54522 104.65609,132.54522 C 102.54604,132.54522 100.62069,132.97198 100.62069,136.88763 C 100.62069,140.55363 102.21293,140.58991 104.10032,140.58991 C 105.28522,140.58991 106.47014,140.26946 106.87663,139.84271 C 106.87747,139.84185 107.06216,135.57029 107.06216,132.9011 M 114.91792,141.26547 C 114.91792,141.76382 114.95503,141.76382 112.88124,141.76382 L 112.88124,116.56214 C 112.88124,115.60073 113.28857,115.60073 114.91792,115.60073 L 114.91792,141.26547"
-   style="fill:#010101;stroke-width:2.02999997;stroke-miterlimit:4;stroke-dasharray:none"
-   id="text2611" /><g
-   transform="matrix(0.9351326,0,0,0.9351326,150.39508,-1.251766)"
-   id="g4503"
-   style="opacity:1"><path
-     d="M -45.749655,92.691592 C -25.709638,59.370739 -49.98206,5.3291313 -94.363693,10.819389 C -134.46337,15.776665 -135.10949,57.983708 -99.76917,68.010455 C -69.186498,76.695132 -93.451029,96.093536 -92.742037,109.01138 C -92.030055,121.92728 -66.155038,126.61324 -45.749655,92.691592 z "
-     style="fill:#1b1a1b"
-     id="path2339" /><circle
-     cx="33.728001"
-     cy="85.363998"
-     r="15.414"
-     transform="matrix(1.0917947,-0.2858168,0.2858168,1.0917947,-180.30817,13.494135)"
-     style="fill:#1b1a1b"
-     id="circle2341"
-     sodipodi:cx="33.728001"
-     sodipodi:cy="85.363998"
-     sodipodi:rx="15.414"
-     sodipodi:ry="15.414" /><path
-     d="M -140.06215,48.935849 C -146.31997,49.541603 -150.90082,55.100456 -150.29507,61.358275 C -149.68817,67.620461 -144.12955,72.20487 -137.87064,71.59883 C -131.61373,70.985148 -127.02904,65.427621 -127.63726,59.169282 C -128.24543,52.915596 -133.80324,48.329809 -140.06215,48.935849 z "
-     style="fill:#1b1a1b"
-     id="path2343" /><path
-     d="M -44.99294,91.339709 C -24.951831,58.018571 -49.224253,3.976963 -93.605885,9.4672202 C -133.70556,14.424496 -134.35249,56.632918 -99.012168,66.659664 C -68.429497,75.344341 -92.694028,94.742745 -91.984749,107.66168 C -91.271961,120.5762 -65.398322,125.26135 -44.99294,91.339709 z "
-     style="fill:#bfbfbf"
-     id="path2561" /><path
-     d="M -86.84228,112.75985 C -88.056751,110.79004 -86.19955,108.60176 -84.290569,108.76815 C -81.251858,109.03428 -74.635637,108.73252 -69.415044,105.77341 C -56.372412,98.379694 -36.300952,62.803704 -46.395841,40.365295 C -50.915249,30.320886 -53.115898,27.444964 -57.770162,22.531645 C -58.719625,21.529587 -58.174556,21.584053 -57.531623,21.923221 C -55.014762,23.244092 -50.592026,28.36035 -46.055478,36.687677 C -38.390628,50.757116 -38.788117,67.483141 -41.638835,77.975343 C -43.624548,85.27439 -50.464117,101.78644 -60.480639,108.92577 C -70.5197,116.0815 -82.266433,120.18559 -86.84228,112.75985 z "
-     style="fill:#000000"
-     id="path2563" /><path
-     d="M -95.930347,66.591355 C -102.76341,64.562985 -111.57238,61.738267 -116.66758,55.073789 C -120.42371,50.15984 -122.3305,44.796759 -122.81745,41.755703 C -122.99069,40.670602 -123.13785,39.765332 -122.82526,39.515509 C -122.68064,39.399486 -120.02045,45.412302 -116.04367,50.451645 C -112.06769,55.492366 -106.51047,58.440379 -101.88092,59.511496 C -97.763206,60.46345 -89.233623,62.555175 -86.347769,65.013729 C -83.380949,67.540918 -83.133309,73.00119 -84.131664,73.617197 C -85.138469,74.236583 -87.180025,69.187603 -95.930347,66.591355 z "
-     style="fill:#000000"
-     id="path2565" /><path
-     d="M -81.840812,113.72311 C -81.972699,115.28707 -80.176315,115.59377 -77.75828,115.23141 C -74.658947,114.76654 -72.037923,114.41754 -68.470623,112.62971 C -63.63582,110.20674 -58.742752,106.74072 -55.159223,102.06476 C -44.467444,88.115271 -40.681354,71.610444 -41.264404,69.236185 C -41.459242,71.196944 -44.040349,81.489071 -49.943268,90.767882 C -57.52457,102.68631 -63.022197,109.03464 -75.701416,112.1124 C -79.230011,112.96964 -81.668137,111.66432 -81.840812,113.72311 z "
-     style="fill:#ffffff"
-     id="path2567" /><path
-     d="M -109.96233,59.479354 C -108.51822,60.704238 -105.55938,62.336389 -99.737455,64.245644 C -92.705873,66.551032 -89.282274,68.550326 -87.848506,69.508429 C -86.329222,70.525809 -85.366279,72.795951 -85.27115,70.779631 C -85.17194,68.761076 -86.416123,67.025373 -89.192166,66.104839 C -91.070345,65.481234 -94.229847,63.996111 -97.258539,63.398373 C -99.204694,63.014221 -102.37098,62.251845 -105.08636,61.420426 C -106.57454,60.963046 -108.09089,60.161888 -109.96233,59.479354 z "
-     style="fill:#ffffff"
-     id="path2569" /><circle
-     cx="34.681"
-     cy="84.375"
-     r="15.414"
-     transform="matrix(1.0917947,-0.2858168,0.2858168,1.0917947,-180.30817,13.494135)"
-     style="fill:#bfbfbf"
-     id="circle2577"
-     sodipodi:cx="34.681"
-     sodipodi:cy="84.375"
-     sodipodi:rx="15.414"
-     sodipodi:ry="15.414" /><path
-     d="M -128.68413,108.37945 C -115.15301,120.91784 -94.786007,103.69471 -103.75445,88.482597 C -104.76154,86.774656 -106.06907,85.474351 -105.63906,86.782721 C -102.77288,95.529828 -105.42141,102.44941 -110.3632,106.01451 C -115.20857,109.5112 -121.86847,110.09622 -127.20028,107.33186 C -128.76601,106.5203 -129.41538,107.70291 -128.68413,108.37945 z "
-     style="fill:#000000"
-     id="path2579" /><path
-     d="M -118.06686,110.95477 C -116.34413,110.59244 -106.32442,107.99742 -103.97055,99.756195 C -103.23743,97.186709 -103.1058,97.702893 -103.31295,99.095232 C -104.37035,106.20143 -111.08741,111.44338 -116.80312,111.63773 C -117.963,111.75704 -119.48484,111.25131 -118.06686,110.95477 z "
-     style="fill:#ffffff"
-     id="path2585" /><path
-     d="M -139.30435,47.583681 C -145.56216,48.189435 -150.14301,53.748288 -149.53726,60.006106 C -148.93065,66.2672 -143.37174,70.852702 -137.11392,70.246948 C -130.85592,69.632979 -126.27151,64.074361 -126.88083,57.816308 C -127.48791,51.562336 -133.04544,46.977641 -139.30435,47.583681 z "
-     style="fill:#bfbfbf"
-     id="path2589" /><path
-     d="M -144.46878,67.571208 C -144.39939,68.375508 -143.29781,69.408789 -141.56718,69.883196 C -140.08038,70.290771 -136.24758,71.332594 -131.32372,68.224839 C -126.39986,65.117084 -125.8321,56.804464 -128.07041,54.35955 C -128.76326,53.121154 -129.66426,52.21957 -128.94737,54.195974 C -127.13695,59.186468 -130.65487,63.854586 -133.68917,66.0162 C -136.72238,68.177528 -140.56932,67.154692 -142.14014,66.675779 C -143.71095,66.196867 -144.53929,66.740369 -144.46878,67.571208 z "
-     style="fill:#000000"
-     id="path2591" /><path
-     d="M -138.11472,68.687851 C -137.66344,68.281557 -135.37889,68.447629 -133.31622,67.338341 C -131.25464,66.229338 -128.80419,63.798254 -128.36692,60.343756 C -128.10933,58.315237 -128.03197,58.824631 -127.92942,59.929403 C -128.24939,65.67243 -133.53086,68.844638 -136.55132,69.263202 C -137.36636,69.376239 -138.8007,69.307247 -138.11472,68.687851 z "
-     style="fill:#ffffff"
-     id="path2597" /><path
-     d="M -47.767489,69.693822 C -39.234739,45.099506 -57.090457,7.9576459 -93.212919,12.425552 C -125.85191,16.461012 -126.37823,50.814524 -97.613495,58.976486 C -65.031338,63.908526 -84.650966,88.487524 -87.434101,100.88229 C -89.929232,111.99304 -61.102889,113.82164 -47.767489,69.693822 z "
-     style="fill:#999999"
-     id="path2561_1_" /><path
-     d="M -70.093288,88.904346 C -78.920045,87.812046 -91.622267,107.74061 -79.645446,105.40671 C -67.670523,103.07448 -91.622267,107.74061 -79.645446,105.40671 C -73.888849,104.55302 -69.119803,102.52058 -64.850547,97.64761 C -59.283982,91.295233 -50.968477,77.5735 -48.563483,68.707586 C -46.537563,61.232354 -47.555881,49.650767 -49.644305,60.532553 C -51.786232,71.700167 -61.266532,89.996647 -70.093288,88.904346 z "
-     style="fill:#f3f3f3"
-     id="path2571" /><path
-     d="M -129.3854,104.84502 C -127.34184,104.87935 -126.10573,105.16706 -124.03635,106.61908 C -119.94568,108.31891 -112.42648,107.24179 -108.9543,102.67081 C -105.48212,98.099823 -105.36811,91.801741 -106.69103,87.996073 C -109.92728,78.682039 -123.67593,78.846722 -129.81795,86.579362 C -136.46216,95.2146 -131.42897,104.81069 -129.3854,104.84502 z "
-     style="fill:#999999"
-     id="path2581" /><path
-     d="M -147.63565,61.683628 C -147.22833,62.966318 -146.18754,64.837882 -143.9897,65.149887 C -141.05481,65.566524 -140.45479,66.892551 -136.9892,66.204631 C -133.52361,65.516711 -130.89674,62.676625 -129.84557,59.535064 C -128.64212,55.188187 -130.44406,52.944024 -133.15599,50.940416 C -135.86791,48.936808 -141.83359,49.152263 -145.3938,52.39768 C -147.92393,54.702631 -148.62733,58.560726 -147.63565,61.683628 z "
-     style="fill:#999999"
-     id="path2593_2_" /><path
-     d="M -136.11009,64.55822 C -133.44721,63.861113 -129.92545,60.232613 -131.67381,57.462279 C -133.83086,54.048798 -139.84051,56.970651 -140.04374,60.77103 C -140.24777,64.572786 -138.93238,65.297057 -136.11009,64.55822 z "
-     style="fill:#f3f3f3"
-     id="path256" /><path
-     d="M -116.11512,105.50904 C -113.8431,104.91425 -106.88259,102.0818 -108.18994,91.962983 C -108.85161,86.83742 -111.64725,98.324328 -116.82409,100.04237 C -124.66721,102.64507 -123.78607,107.51719 -116.11512,105.50904 z "
-     style="fill:#f3f3f3"
-     id="path258" /></g>
-</svg>
\ No newline at end of file
+<svg id="Layer_1" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" height="120" width="100" version="1.0" xmlns:cc="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" viewBox="0 0 124.766 152.099"><metadata id="metadata6845"><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/><dc:title>Mercurial &quot;droplets&quot; logo</dc:title><dc:creator><cc:Agent><dc:title>Cali Mastny and Matt Mackall</dc:title></cc:Agent></dc:creator><cc:license rdf:resource="http://creativecommons.org/licenses/GPL/2.0/"/><dc:date>Feb 12 2008</dc:date></cc:Work><cc:License rdf:about="http://creativecommons.org/licenses/GPL/2.0/"><cc:permits rdf:resource="http://web.resource.org/cc/Reproduction"/><cc:permits rdf:resource="http://web.resource.org/cc/Distribution"/><cc:requires rdf:resource="http://web.resource.org/cc/Notice"/><cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/><cc:requires rdf:resource="http://web.resource.org/cc/ShareAlike"/><cc:requires rdf:resource="http://web.resource.org/cc/SourceCode"/></cc:License></rdf:RDF></metadata>
+<rect id="rect6847" stroke-linejoin="miter" style="stroke-dasharray:none;" height="150.12" width="124.77" stroke="#000" stroke-miterlimit="4" y="0.98776" x="0.3169" stroke-width="1.9755" fill="#FFF"/><path id="text2611" style="stroke-dasharray:none;" d="M9.848,124.61c1.777-0.79,3.665-1.18,5.479-1.18,1.74,0,2.851,0.43,3.48,1.32,1.332-0.89,3.146-1.32,4.553-1.32,4.221,0,4.369,1.71,4.369,6.73v11.11c0,0.49,0.074,0.49-2.036,0.49v-11.81c0-3.63-0.074-4.74-2.48-4.74-1.073,0-2.184,0.25-3.369,1.03v15.27c-0.037,0.15-0.111,0.18-0.369,0.22-0.038,0-0.074,0.03-0.112,0.03h-1.555v-11.81c0-3.49,0-4.77-2.517-4.77-1.074,0-2.147,0.21-3.406,0.82v15.27c0,0.49,0.074,0.49-2.0361,0.49v-17.15m27.831-1.18c-3.146,0-6.626,0.89-6.626,10.4,0,7.33,2.554,8.47,6.071,8.47,2.701,0,5.034-0.89,5.034-1.32,0-0.53-0.074-1.35-0.259-1.82-1.148,0.79-2.777,1.21-4.59,1.21-2.48,0-4.146-0.71-4.184-6.22,1.629,0,5.776-0.04,8.848-0.65,0.259-1.17,0.37-2.88,0.37-4.37,0-3.56-1.444-5.7-4.664-5.7m-0.185,1.78c2.221,0,2.813,1.46,2.85,4.31,0,0.75-0.037,1.64-0.148,2.49-2.073,0.5-5.591,0.5-7.072,0.5,0.261-6.48,2.481-7.3,4.37-7.3m8.07-0.21c1.739-1.14,3.332-1.57,4.961-1.57,1.814,0,2.666,0.5,2.666,1.11,0,0.35-0.112,0.96-0.297,1.31-0.519-0.28-1.11-0.53-2.074-0.53-1.184,0-2.295,0.32-3.183,1.1v14.85c0,0.49,0.037,0.49-2.073,0.49v-16.76m18.69-0.39c0-0.47-1.554-1.18-3.11-1.18-2.999,0-6.664,1.03-6.664,9.83,0,8.33,2.222,9.07,6.109,9.07,1.924,0,3.665-1.03,3.665-1.6,0-0.32-0.074-0.82-0.26-1.24-0.778,0.56-1.962,1.1-3.22,1.1-2.665,0-4.22-0.75-4.22-7.23,0-7.15,2.554-8.15,4.775-8.15,1.258,0,1.962,0.36,2.665,0.82,0.186-0.43,0.26-1.03,0.26-1.42m14.181,16.55c-1.63,0.82-3.776,1.14-5.627,1.14-4.739,0-5.442-1.99-5.442-6.73v-11.14c0-0.46-0.037-0.46,2.074-0.46v11.82c0,3.56,0.517,4.77,3.294,4.77,1.073,0,2.554-0.22,3.665-0.86v-15.27c0-0.46-0.074-0.46,2.036-0.46v17.19m4.221-16.16c1.739-1.14,3.332-1.57,4.96-1.57,1.814,0,2.666,0.5,2.666,1.11,0,0.35-0.111,0.96-0.296,1.31-0.519-0.28-1.111-0.53-2.074-0.53-1.184,0-2.295,0.32-3.183,1.1v14.85c0,0.49,0.037,0.49-2.073,0.49v-16.76m12.379-1.03c-1.629,0-2.11,0-2.11,0.96v16.83c2.073,0,2.11,0,2.11-0.49v-17.3m-2.184-6.27c0,1.18,0.37,1.6,1.11,1.64,0.851,0,1.259-0.61,1.259-1.67,0.037-1.11-0.26-1.61-1.111-1.61-0.814,0-1.221,0.61-1.258,1.64m5.696,7.3c0-0.39,0.074-0.61,0.222-0.71,0.704-0.39,3.41-0.86,6.48-0.86,2.33,0,3.81,1.11,3.81,4.31v2.31c0,6.34-0.18,11.07-0.18,11.07-0.85,0.47-2.45,1.18-5.04,1.18-2.66,0.03-5.329-0.22-5.329-5.48,0-5.02,2.739-5.81,5.479-5.81,1.04,0,2.26,0.11,3.07,0.43v-3.31c0-2.31-1.18-2.81-2.59-2.81-1.89,0-4.514,0.35-5.662,0.89-0.222-0.39-0.26-1-0.26-1.21m8.512,7.9c-0.7-0.25-1.7-0.35-2.4-0.35-2.11,0-4.04,0.42-4.04,4.34,0,3.66,1.59,3.7,3.48,3.7,1.19,0,2.37-0.32,2.78-0.75,0,0,0.18-4.27,0.18-6.94m7.86,8.37c0,0.49,0.04,0.49-2.04,0.49v-25.2c0-0.96,0.41-0.96,2.04-0.96v25.67" stroke-miterlimit="4" stroke-width="2.02999997" fill="#010101"/><g id="g4503" transform="matrix(0.9351326,0,0,0.9351326,150.39508,-1.251766)"><path id="path2339" fill="#1b1a1b" d="M-45.75,92.692c20.04-33.321-4.232-87.363-48.614-81.873-40.096,4.958-40.746,47.165-5.405,57.191,30.583,8.685,6.318,28.084,7.027,41,0.712,12.92,26.587,17.6,46.992-16.318z"/><circle id="circle2341" transform="matrix(1.0917947,-0.2858168,0.2858168,1.0917947,-180.30817,13.494135)" cy="85.364" cx="33.728" r="15.414" fill="#1b1a1b"/><path id="path2343" fill="#1b1a1b" d="M-140.06,48.936c-6.26,0.606-10.84,6.164-10.24,12.422,0.61,6.262,6.17,10.847,12.43,10.241,6.26-0.614,10.84-6.171,10.23-12.43-0.61-6.253-6.16-10.839-12.42-10.233z"/><path id="path2561" fill="#bfbfbf" d="M-44.993,91.34c20.041-33.321-4.231-87.363-48.613-81.873-40.104,4.9568-40.744,47.166-5.406,57.193,30.583,8.684,6.318,28.083,7.027,41,0.713,12.92,26.587,17.6,46.992-16.32z"/><path id="path2563" fill="#000" d="M-86.842,112.76c-1.215-1.97,0.642-4.16,2.551-3.99,3.039,0.26,9.655-0.04,14.876-3,13.043-7.39,33.114-42.966,23.019-65.405-4.519-10.044-6.72-12.92-11.374-17.833-0.95-1.002-0.405-0.948,0.238-0.609,2.517,1.321,6.94,6.437,11.477,14.765,7.664,14.069,7.267,30.795,4.416,41.287-1.986,7.299-8.825,23.815-18.842,30.955-10.039,7.15-21.785,11.26-26.361,3.83z"/><path id="path2565" fill="#000" d="M-95.93,66.591c-6.83-2.028-15.64-4.853-20.74-11.517-3.75-4.914-5.66-10.277-6.15-13.318-0.17-1.085-0.32-1.991-0.01-2.24,0.15-0.117,2.81,5.896,6.79,10.936,3.97,5.04,9.53,7.988,14.16,9.059,4.117,0.952,12.646,3.044,15.532,5.503,2.967,2.527,3.215,7.987,2.216,8.603-1.006,0.62-3.048-4.429-11.798-7.026z"/><path id="path2567" fill="#FFF" d="M-81.841,113.72c-0.132,1.57,1.665,1.87,4.083,1.51,3.099-0.46,5.72-0.81,9.287-2.6,4.835-2.42,9.728-5.89,13.312-10.57,10.692-13.945,14.478-30.45,13.895-32.824-0.195,1.961-2.776,12.253-8.679,21.532-7.582,11.922-13.079,18.262-25.758,21.342-3.529,0.86-5.967-0.45-6.14,1.61z"/><path id="path2569" fill="#FFF" d="M-109.96,59.479c1.44,1.225,4.4,2.857,10.223,4.767,7.031,2.305,10.455,4.304,11.888,5.262,1.52,1.018,2.483,3.288,2.578,1.272,0.099-2.019-1.145-3.755-3.921-4.675-1.878-0.624-5.038-2.109-8.067-2.707-1.946-0.384-5.111-1.146-7.831-1.978-1.48-0.457-3-1.258-4.87-1.941z"/><circle id="circle2577" transform="matrix(1.0917947,-0.2858168,0.2858168,1.0917947,-180.30817,13.494135)" cy="84.375" cx="34.681" r="15.414" fill="#bfbfbf"/><path id="path2579" fill="#000" d="M-128.68,108.38c13.53,12.54,33.894-4.69,24.93-19.897-1.01-1.708-2.32-3.009-1.89-1.7,2.87,8.747,0.22,15.667-4.72,19.227-4.85,3.5-11.51,4.09-16.84,1.32-1.57-0.81-2.22,0.37-1.48,1.05z"/><path id="path2585" fill="#FFF" d="M-118.07,110.95c1.73-0.36,11.75-2.95,14.1-11.194,0.73-2.569,0.86-2.053,0.66-0.661-1.06,7.105-7.78,12.345-13.49,12.545-1.16,0.12-2.68-0.39-1.27-0.69z"/><path id="path2589" fill="#bfbfbf" d="M-139.3,47.584c-6.26,0.605-10.84,6.164-10.24,12.422,0.61,6.261,6.17,10.847,12.43,10.241,6.25-0.614,10.84-6.173,10.23-12.431-0.61-6.254-6.17-10.838-12.42-10.232z"/><path id="path2591" fill="#000" d="M-144.47,67.571c0.07,0.805,1.17,1.838,2.9,2.312,1.49,0.408,5.32,1.45,10.25-1.658,4.92-3.108,5.49-11.421,3.25-13.865-0.69-1.239-1.59-2.14-0.88-0.164,1.81,4.99-1.7,9.659-4.74,11.82-3.03,2.162-6.88,1.139-8.45,0.66s-2.4,0.064-2.33,0.895z"/><path id="path2597" fill="#FFF" d="M-138.11,68.688c0.45-0.406,2.73-0.24,4.79-1.35,2.07-1.109,4.52-3.54,4.95-6.994,0.26-2.029,0.34-1.519,0.44-0.415-0.32,5.743-5.6,8.916-8.62,9.334-0.82,0.113-2.25,0.044-1.56-0.575z"/><path id="path2561_1_" fill="#999" d="M-47.767,69.694c8.532-24.594-9.323-61.736-45.446-57.268-32.637,4.035-33.167,38.389-4.4,46.55,32.582,4.933,12.962,29.512,10.179,41.904-2.495,11.11,26.331,12.94,39.667-31.186z"/><path id="path2571" fill="#f3f3f3" d="M-70.093,88.904c-8.827-1.092-21.529,18.836-9.552,16.506,5.756-0.86,10.525-2.89,14.794-7.762,5.567-6.353,13.883-20.074,16.288-28.94,2.025-7.476,1.007-19.057-1.081-8.175-2.142,11.167-11.623,29.464-20.449,28.371z"/><path id="path2581" fill="#999" d="M-129.39,104.85c2.05,0.03,3.28,0.32,5.35,1.77,4.09,1.7,11.61,0.62,15.09-3.95,3.47-4.57,3.58-10.868,2.26-14.674-3.24-9.314-16.99-9.149-23.13-1.417-6.64,8.636-1.61,18.231,0.43,18.271z"/><path id="path2593_2_" fill="#999" d="M-147.64,61.684c0.41,1.282,1.45,3.154,3.65,3.466,2.94,0.417,3.54,1.743,7,1.055,3.47-0.688,6.09-3.528,7.14-6.67,1.21-4.347-0.59-6.591-3.31-8.595-2.71-2.003-8.67-1.788-12.23,1.458-2.53,2.305-3.24,6.163-2.25,9.286z"/><path id="path256" fill="#f3f3f3" d="M-136.11,64.558c2.66-0.697,6.18-4.325,4.44-7.096-2.16-3.413-8.17-0.491-8.37,3.309-0.21,3.802,1.11,4.526,3.93,3.787z"/><path id="path258" fill="#f3f3f3" d="M-116.12,105.51c2.28-0.6,9.24-3.43,7.93-13.547-0.66-5.126-3.46,6.361-8.63,8.077-7.85,2.61-6.97,7.48,0.7,5.47z"/></g>
+</svg>
--- a/contrib/mercurial.spec	Mon Dec 07 12:31:45 2009 +0200
+++ b/contrib/mercurial.spec	Tue May 11 17:03:44 2010 -0500
@@ -38,14 +38,11 @@
 
 %install
 rm -rf $RPM_BUILD_ROOT
-python setup.py install --root $RPM_BUILD_ROOT --prefix %{_prefix}
-make install-doc DESTDIR=$RPM_BUILD_ROOT MANDIR=%{_mandir}
+make install DESTDIR=$RPM_BUILD_ROOT PREFIX=%{_prefix} MANDIR=%{_mandir}
 
 install contrib/hgk          $RPM_BUILD_ROOT%{_bindir}
 install contrib/convert-repo $RPM_BUILD_ROOT%{_bindir}/mercurial-convert-repo
 install contrib/hg-ssh       $RPM_BUILD_ROOT%{_bindir}
-install contrib/git-viz/hg-viz $RPM_BUILD_ROOT%{_bindir}
-install contrib/git-viz/git-rev-tree $RPM_BUILD_ROOT%{_bindir}
 
 bash_completion_dir=$RPM_BUILD_ROOT%{_sysconfdir}/bash_completion.d
 mkdir -p $bash_completion_dir
@@ -77,8 +74,6 @@
 %{_bindir}/hg
 %{_bindir}/hgk
 %{_bindir}/hg-ssh
-%{_bindir}/hg-viz
-%{_bindir}/git-rev-tree
 %{_bindir}/mercurial-convert-repo
 %dir %{_sysconfdir}/bash_completion.d/
 %dir %{_datadir}/zsh/site-functions/
--- a/contrib/mergetools.hgrc	Mon Dec 07 12:31:45 2009 +0200
+++ b/contrib/mergetools.hgrc	Tue May 11 17:03:44 2010 -0500
@@ -13,7 +13,7 @@
 gvimdiff.priority=-9
 
 merge.checkconflicts=True
-merge.priority=-10
+merge.priority=-100
 
 gpyfm.gui=True
 
--- a/contrib/rewrite-log	Mon Dec 07 12:31:45 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-#!/usr/bin/env python
-import sys, os
-from mercurial import revlog, transaction, node, util
-
-f = sys.argv[1]
-
-r1 = revlog.revlog(util.opener(os.getcwd(), audit=False), f + ".i", f + ".d")
-r2 = revlog.revlog(util.opener(os.getcwd(), audit=False), f + ".i2", f + ".d2")
-
-tr = transaction.transaction(sys.stderr.write, open, "journal")
-
-for i in xrange(r1.count()):
-    n = r1.node(i)
-    p1, p2 = r1.parents(n)
-    l = r1.linkrev(n)
-    t = r1.revision(n)
-    n2 = r2.addrevision(t, tr, l, p1, p2)
-tr.close()
-
-os.rename(f + ".i", f + ".i.old")
-os.rename(f + ".d", f + ".d.old")
-os.rename(f + ".i2", f + ".i")
-os.rename(f + ".d2", f + ".d")
--- a/contrib/shrink-revlog.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/contrib/shrink-revlog.py	Tue May 11 17:03:44 2010 -0500
@@ -24,50 +24,81 @@
 from mercurial import changegroup
 from mercurial.i18n import _
 
-def toposort(ui, rl):
+
+def postorder(start, edges):
+    result = []
+    visit = list(start)
+    finished = set()
 
-    children = {}
-    root = []
-    # build children and roots
+    while visit:
+        cur = visit[-1]
+        for p in edges[cur]:
+            if p not in finished:
+                visit.append(p)
+                break
+        else:
+            result.append(cur)
+            finished.add(cur)
+            visit.pop()
+
+    return result
+
+def toposort_reversepostorder(ui, rl):
+    # postorder of the reverse directed graph
+
+    # map rev to list of parent revs (p2 first)
+    parents = {}
+    heads = set()
     ui.status(_('reading revs\n'))
     try:
-        for i in rl:
-            ui.progress(_('reading'), i, total=len(rl))
-            children[i] = []
-            parents = [p for p in rl.parentrevs(i) if p != node.nullrev]
-            # in case of duplicate parents
-            if len(parents) == 2 and parents[0] == parents[1]:
-                del parents[1]
-            for p in parents:
-                assert p in children
-                children[p].append(i)
+        for rev in rl:
+            ui.progress(_('reading'), rev, total=len(rl))
+            (p1, p2) = rl.parentrevs(rev)
+            if p1 == p2 == node.nullrev:
+                parents[rev] = ()       # root node
+            elif p1 == p2 or p2 == node.nullrev:
+                parents[rev] = (p1,)    # normal node
+            else:
+                parents[rev] = (p2, p1) # merge node
+            heads.add(rev)
+            for p in parents[rev]:
+                heads.discard(p)
+    finally:
+        ui.progress(_('reading'), None)
 
-            if len(parents) == 0:
-                root.append(i)
-    finally:
-        ui.progress(_('reading'), None, total=len(rl))
+    heads = list(heads)
+    heads.sort(reverse=True)
+
+    ui.status(_('sorting revs\n'))
+    return postorder(heads, parents)
+
+def toposort_postorderreverse(ui, rl):
+    # reverse-postorder of the reverse directed graph
 
-    # XXX this is a reimplementation of the 'branchsort' topo sort
-    # algorithm in hgext.convert.convcmd... would be nice not to duplicate
-    # the algorithm
+    children = {}
+    roots = set()
+    ui.status(_('reading revs\n'))
+    try:
+        for rev in rl:
+            ui.progress(_('reading'), rev, total=len(rl))
+            (p1, p2) = rl.parentrevs(rev)
+            if p1 == p2 == node.nullrev:
+                roots.add(rev)
+            children[rev] = []
+            if p1 != node.nullrev:
+                children[p1].append(rev)
+            if p2 != node.nullrev:
+                children[p2].append(rev)
+    finally:
+        ui.progress(_('reading'), None)
+
+    root = list(roots)
+    roots.sort()
+
     ui.status(_('sorting revs\n'))
-    visit = root
-    ret = []
-    while visit:
-        i = visit.pop(0)
-        ret.append(i)
-        if i not in children:
-            # This only happens if some node's p1 == p2, which can
-            # happen in the manifest in certain circumstances.
-            continue
-        next = []
-        for c in children.pop(i):
-            parents_unseen = [p for p in rl.parentrevs(c)
-                              if p != node.nullrev and p in children]
-            if len(parents_unseen) == 0:
-                next.append(c)
-        visit = next + visit
-    return ret
+    result = postorder(roots, children)
+    result.reverse()
+    return result
 
 def writerevs(ui, r1, r2, order, tr):
 
@@ -89,7 +120,7 @@
         chunkiter = changegroup.chunkiter(group)
         r2.addgroup(chunkiter, unlookup, tr)
     finally:
-        ui.progress(_('writing'), None, len(order))
+        ui.progress(_('writing'), None)
 
 def report(ui, r1, r2):
     def getsize(r):
@@ -118,9 +149,15 @@
              % (shrink_percent, shrink_factor))
 
 def shrink(ui, repo, **opts):
+    """shrink a revlog by reordering revisions
+
+    Rewrites all the entries in some revlog of the current repository
+    (by default, the manifest log) to save space.
+
+    Different sort algorithms have different performance
+    characteristics.  Use ``--sort`` to select a sort algorithm so you
+    can determine which works best for your data.
     """
-    Shrink revlog by re-ordering revisions. Will operate on manifest for
-    the given repository if no other revlog is specified."""
 
     if not repo.local():
         raise util.Abort(_('not a local repository: %s') % repo.root)
@@ -139,6 +176,12 @@
             raise util.Abort(_('--revlog option must specify a revlog in %s, '
                                'not %s') % (store, indexfn))
 
+    sortname = opts['sort']
+    try:
+        toposort = globals()['toposort_' + sortname]
+    except KeyError:
+        raise util.Abort(_('no such toposort algorithm: %s') % sortname)
+
     if not os.path.exists(indexfn):
         raise util.Abort(_('no such file: %s') % indexfn)
     if '00changelog' in indexfn:
@@ -187,6 +230,15 @@
     try:
         try:
             order = toposort(ui, r1)
+
+            suboptimal = 0
+            for i in xrange(1, len(order)):
+                parents = [p for p in r1.parentrevs(order[i])
+                           if p != node.nullrev]
+                if parents and order[i - 1] not in parents:
+                    suboptimal += 1
+            ui.note(_('%d suboptimal nodes\n') % suboptimal)
+
             writerevs(ui, r1, r2, order, tr)
             report(ui, r1, r2)
             tr.close()
@@ -229,6 +281,7 @@
     'shrink': (shrink,
                [('', 'revlog', '', _('index (.i) file of the revlog to shrink')),
                 ('n', 'dry-run', None, _('do not shrink, simulate only')),
+                ('', 'sort', 'reversepostorder', 'name of sort algorithm to use'),
                 ],
                _('hg shrink [--revlog PATH]'))
 }
--- a/contrib/win32/win32-build.txt	Mon Dec 07 12:31:45 2009 +0200
+++ b/contrib/win32/win32-build.txt	Tue May 11 17:03:44 2010 -0500
@@ -82,16 +82,10 @@
     Microsoft.VC90.MFC.manifest)
 
 Before building the installer, you have to build Mercurial HTML documentation 
-(or fix mercurial.iss to not reference the doc directory). Docutils does not
-come with a ready-made script for rst2html.py, so you will have to write your
-own and put it in %PATH% like:
-
-  @python c:\pythonXX\scripts\rst2html.py %*
-
-Then build the documentation with:
+(or fix mercurial.iss to not reference the doc directory):
 
   cd doc
-  mingw32-make RST2HTML=rst2html.bat html
+  mingw32-make html
   cd ..
 
 If you use ISTool, you open the C:\hg\hg-release\contrib\win32\mercurial.iss
@@ -113,7 +107,7 @@
   echo compiler=mingw32 >> setup.cfg
   python setup.py py2exe -b 1
   cd doc
-  mingw32-make RST2HTML=rst2html.bat html
+  mingw32-make html
   cd ..
   iscc contrib\win32\mercurial.iss /DVERSION=snapshot
 
--- a/contrib/wix/contrib.wxs	Mon Dec 07 12:31:45 2009 +0200
+++ b/contrib/wix/contrib.wxs	Tue May 11 17:03:44 2010 -0500
@@ -1,218 +1,42 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
-    <Fragment>
-        <ComponentGroup Id="contribFolder">
-            <Component Id="cmp807F426F34EC5B808607BA4007244E84" Directory="dirCA1E322A30AE0A461BB6A083C7A87627" Guid="{4D96B8DF-A686-42A8-AD81-E2CB4324C697}">
-                <File Id="fil0BF2562805D37A6C57219F945DC7C3B4" KeyPath="yes" Source="$(var.SourceDir)\bash_completion" />
-            </Component>
-            <Component Id="cmpB28139F1930563D83220AD2C1128B030" Directory="dirCA1E322A30AE0A461BB6A083C7A87627" Guid="{89D69124-1ED8-429B-AAC8-BC3F2B4F2B80}">
-                <File Id="fil8A6DCD57765E3E3FEF179102A0906054" KeyPath="yes" Source="$(var.SourceDir)\hgk" />
-            </Component>
-            <Component Id="cmpB7DA2E5DE9E5C7DDB7696E436D98B142" Directory="dirCA1E322A30AE0A461BB6A083C7A87627" Guid="{C1B3D111-3A62-4B6A-A39B-1DCECEDA08EC}">
-                <File Id="fil18816C74E6F00D731B7DBE0870BDE2D9" KeyPath="yes" Source="$(var.SourceDir)\hgwebdir.fcgi" />
-            </Component>
-            <Component Id="cmpB1DF769846D452FC44EBA6763F12D29F" Directory="dirCA1E322A30AE0A461BB6A083C7A87627" Guid="{63CCAE00-5F02-4AB2-84A9-B11780E618AA}">
-                <File Id="fil5896BB6DFC36A92D41E0AB8C7DB80A97" KeyPath="yes" Source="$(var.SourceDir)\hgwebdir.wsgi" />
-            </Component>
-            <Component Id="cmp7C407D087BF1947C9EC8AFE24B42CD9B" Directory="dirCA1E322A30AE0A461BB6A083C7A87627" Guid="{1200C67E-0A52-462E-AC7B-CDC933F43ACD}">
-                <File Id="fil81E357676284E64EDFEBE9FE5CEB872F" KeyPath="yes" Source="$(var.SourceDir)\logo-droplets.svg" />
-            </Component>
-            <Component Id="cmp6946EABE287930CA55C76B0961DE17E7" Directory="dirCA1E322A30AE0A461BB6A083C7A87627" Guid="{E014BC0E-B6CA-4020-9302-CB503904A4FB}">
-                <File Id="filA77C0B15558EB3894B9E728D2FE3AF9F" KeyPath="yes" Source="$(var.SourceDir)\mercurial.el" />
-            </Component>
-            <Component Id="cmpBEDE8604BDE5144025036F4BB04679B2" Directory="dirCA1E322A30AE0A461BB6A083C7A87627" Guid="{3BB12008-A453-4A1B-B427-F97ADD127ED7}">
-                <File Id="fil3F209A8D711EA35E5B38E05678D0D5E2" KeyPath="yes" Source="$(var.SourceDir)\sample.hgrc" />
-            </Component>
-            <Component Id="cmpED03CB84DEE74E99BB62BE0F8AC356F1" Directory="dirCA1E322A30AE0A461BB6A083C7A87627" Guid="{BE0C6DC7-A91A-4390-A111-54D109148514}">
-                <File Id="filCD2BF173510DF04EA722FE4924B3DAE7" KeyPath="yes" Source="$(var.SourceDir)\tcsh_completion" />
-            </Component>
-            <Component Id="cmp7395336B1B93AB450D822FA0DE0C5FCB" Directory="dirCA1E322A30AE0A461BB6A083C7A87627" Guid="{8F376341-1DEF-419D-8D88-17F393C5F3CA}">
-                <File Id="fil2C004105E9F354CA4156678C4FB76823" KeyPath="yes" Source="$(var.SourceDir)\tcsh_completion_build.sh" />
-            </Component>
-            <Component Id="cmpA914A0A1896C5E91A8381B2B5491564C" Directory="dirCA1E322A30AE0A461BB6A083C7A87627" Guid="{87C90FF2-43D5-4F81-93C2-295E4C7D7718}">
-                <File Id="filBF6BED4F17C843169CEBE289E39FC8FB" KeyPath="yes" Source="$(var.SourceDir)\xml.rnc" />
-            </Component>
-            <Component Id="cmp512D2C19167594DBED53CF4A5896DAC1" Directory="dirCA1E322A30AE0A461BB6A083C7A87627" Guid="{6BAA6FEC-4C90-4B97-A330-A60B34BE0A5A}">
-                <File Id="filA8F4DBB6CE376C77AA79D9E9D715A519" KeyPath="yes" Source="$(var.SourceDir)\zsh_completion" />
-            </Component>
-            <Component Id="cmp82B1C0B5D90172AD872BBE93AD1A4746" Directory="dirBED34C623F6A770B7C7A5C815434688D" Guid="{7EAE9937-D488-43A4-8EED-A726711C02D5}">
-                <File Id="filBB7FA67E9542AD28BADC33AE9FE32A34" KeyPath="yes" Source="$(var.SourceDir)\vim\hg-menu.vim" />
-            </Component>
-            <Component Id="cmp86D915E62A0C3FF73A370E0D48DDE5F1" Directory="dirBED34C623F6A770B7C7A5C815434688D" Guid="{1ECD4227-1385-4073-95E9-5346A21E92F2}">
-                <File Id="filC508D5BC3A9EAE1F33C95F8EF07EF431" KeyPath="yes" Source="$(var.SourceDir)\vim\HGAnnotate.vim" />
-            </Component>
-            <Component Id="cmp6F11D903E1DB0DFC0C3EB42F63394E60" Directory="dirBED34C623F6A770B7C7A5C815434688D" Guid="{41DE72AC-B7BC-489F-82D8-EFB39E280910}">
-                <File Id="filDAC324AFC5566758101A7423165FE7FA" KeyPath="yes" Source="$(var.SourceDir)\vim\hgcommand.vim" />
-            </Component>
-            <Component Id="cmpA55369F11281B52F404E0724200C115F" Directory="dirBED34C623F6A770B7C7A5C815434688D" Guid="{F72CA80F-E453-40C5-AFFD-875C46B7C7D7}">
-                <File Id="fil982E8F72370A711566A7F7645AC8204D" KeyPath="yes" Source="$(var.SourceDir)\vim\patchreview.txt" />
-            </Component>
-            <Component Id="cmp56F529456B47B91250785C4D0A205ED2" Directory="dirBED34C623F6A770B7C7A5C815434688D" Guid="{02A22346-ECA7-4C70-AF97-974550F0D8D3}">
-                <File Id="filC59985C7F91EC21A42FEF97AD3CDD65D" KeyPath="yes" Source="$(var.SourceDir)\vim\patchreview.vim" />
-            </Component>
-        </ComponentGroup>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="INSTALLDIR">
-            <Directory Id="dirCA1E322A30AE0A461BB6A083C7A87627" Name="contrib" />
-        </DirectoryRef>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCA1E322A30AE0A461BB6A083C7A87627" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir0AAB909DA146B054F15679730FA6EDC4" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCA1E322A30AE0A461BB6A083C7A87627" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCA1E322A30AE0A461BB6A083C7A87627" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCA1E322A30AE0A461BB6A083C7A87627" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir0AAB909DA146B054F15679730FA6EDC4" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir0AAB909DA146B054F15679730FA6EDC4" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCA1E322A30AE0A461BB6A083C7A87627" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCA1E322A30AE0A461BB6A083C7A87627" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCA1E322A30AE0A461BB6A083C7A87627" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCA1E322A30AE0A461BB6A083C7A87627" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirBED34C623F6A770B7C7A5C815434688D" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCA1E322A30AE0A461BB6A083C7A87627" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirD2A98CA486D03F46DB07EE76569468D8" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir0AAB909DA146B054F15679730FA6EDC4" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCA1E322A30AE0A461BB6A083C7A87627" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCA1E322A30AE0A461BB6A083C7A87627" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCA1E322A30AE0A461BB6A083C7A87627" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirBED34C623F6A770B7C7A5C815434688D" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCA1E322A30AE0A461BB6A083C7A87627" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir0AAB909DA146B054F15679730FA6EDC4" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCA1E322A30AE0A461BB6A083C7A87627" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCA1E322A30AE0A461BB6A083C7A87627" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir51C59DA466E26BFDB5855AE6BE2E4BDD" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir0AAB909DA146B054F15679730FA6EDC4" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir0AAB909DA146B054F15679730FA6EDC4" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCA1E322A30AE0A461BB6A083C7A87627" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCA1E322A30AE0A461BB6A083C7A87627" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCA1E322A30AE0A461BB6A083C7A87627" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirBED34C623F6A770B7C7A5C815434688D" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirBED34C623F6A770B7C7A5C815434688D" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir3F9A2BE78E3069AB8A904DF734C62404" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir3F9A2BE78E3069AB8A904DF734C62404" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirD2A98CA486D03F46DB07EE76569468D8" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir3F9A2BE78E3069AB8A904DF734C62404" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirBED34C623F6A770B7C7A5C815434688D" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCA1E322A30AE0A461BB6A083C7A87627" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCA1E322A30AE0A461BB6A083C7A87627" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCA1E322A30AE0A461BB6A083C7A87627" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir3F9A2BE78E3069AB8A904DF734C62404" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCA1E322A30AE0A461BB6A083C7A87627" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCA1E322A30AE0A461BB6A083C7A87627" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCA1E322A30AE0A461BB6A083C7A87627" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCA1E322A30AE0A461BB6A083C7A87627" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCA1E322A30AE0A461BB6A083C7A87627" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir51C59DA466E26BFDB5855AE6BE2E4BDD" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir3F9A2BE78E3069AB8A904DF734C62404" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir0AAB909DA146B054F15679730FA6EDC4" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir51C59DA466E26BFDB5855AE6BE2E4BDD" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCA1E322A30AE0A461BB6A083C7A87627" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCA1E322A30AE0A461BB6A083C7A87627" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCA1E322A30AE0A461BB6A083C7A87627">
-            <Directory Id="dirBED34C623F6A770B7C7A5C815434688D" Name="vim" />
-        </DirectoryRef>
-    </Fragment>
+
+  <?include guids.wxi ?>
+
+  <Fragment>
+    <ComponentGroup Id="contribFolder">
+      <ComponentRef Id="contrib" />
+      <ComponentRef Id="contrib.vim" />
+    </ComponentGroup>
+  </Fragment>
+
+  <Fragment>
+    <DirectoryRef Id="INSTALLDIR">
+      <Directory Id="contribdir" Name="contrib" FileSource="$(var.SourceDir)">
+        <Component Id="contrib" Guid="$(var.contrib.guid)">
+          <File Name="bash_completion" KeyPath="yes" />
+          <File Name="hgk" />
+          <File Name="hgweb.fcgi" />
+          <File Name="hgweb.wsgi" />
+          <File Name="logo-droplets.svg" />
+          <File Name="mercurial.el" />
+          <File Name="sample.hgrc" />
+          <File Name="tcsh_completion" />
+          <File Name="tcsh_completion_build.sh" />
+          <File Name="xml.rnc" />
+          <File Name="zsh_completion" />
+        </Component>
+        <Directory Id="vimdir" Name="vim">
+          <Component Id="contrib.vim" Guid="$(var.contrib.vim.guid)">
+            <File Name="hg-menu.vim" KeyPath="yes" />
+            <File Name="HGAnnotate.vim" />
+            <File Name="hgcommand.vim" />
+            <File Name="patchreview.txt" />
+            <File Name="patchreview.vim" />
+          </Component>
+        </Directory>
+      </Directory>
+    </DirectoryRef>
+  </Fragment>
+
 </Wix>
--- a/contrib/wix/doc.wxs	Mon Dec 07 12:31:45 2009 +0200
+++ b/contrib/wix/doc.wxs	Tue May 11 17:03:44 2010 -0500
@@ -1,33 +1,49 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
-    <Fragment>
-        <ComponentGroup Id="docFolder">
-            <Component Id="cmpD8AD113FB988F56EF745AF287E14D1BE" Directory="dir7C3635117912185773B74CE69A101DF6" Guid="{F7DDE641-6FD6-48B9-B869-C92927437CF0}">
-                <File Id="filFC7EC893C906DE77DE4D96687109D8E9" KeyPath="yes" Source="$(var.SourceDir)\hg.1.html">
-                  <Shortcut Id="hg1StartMenu" Directory="ProgramMenuDir" Name="Mercurial Command Reference"
-                            Icon="hgIcon.ico" IconIndex="0" Advertise="yes"/>
-                </File>
-            </Component>
-            <Component Id="cmpB89B9653438B9A899D3AF741EF3D50E7" Directory="dir7C3635117912185773B74CE69A101DF6" Guid="{6289969D-8286-47AE-97B2-2DCB3B6A9EE3}">
-                <File Id="filA7A1E3181858EAEA214687DBA9AEFB27" KeyPath="yes" Source="$(var.SourceDir)\hgignore.5.html" >
-                  <Shortcut Id="hgignore5StartMenu" Directory="ProgramMenuDir" Name="Mercurial Ignore Files"
-                            Icon="hgIcon.ico" IconIndex="0" Advertise="yes"/>
-                </File>
-            </Component>
-            <Component Id="cmp2759E68E80E0FCEA1ACE704650E93C2A" Directory="dir7C3635117912185773B74CE69A101DF6" Guid="{2B13EF1C-5B3A-4A36-85B8-59D8155FB454}">
-                <File Id="fil4B171255CC318D73C35538CAA0AFFC24" KeyPath="yes" Source="$(var.SourceDir)\hgrc.5.html" >
-                  <Shortcut Id="hgrc5StartMenu" Directory="ProgramMenuDir" Name="Mercurial Configuration Files"
-                            Icon="hgIcon.ico" IconIndex="0" Advertise="yes"/>
-                </File>
-            </Component>
-            <Component Id="cmp9ADC9EFD76613D01E16146107BBE6590" Directory="dir7C3635117912185773B74CE69A101DF6" Guid="{673C6217-F669-4845-B5A6-56EA061C38AF}">
-                <File Id="fil7994C9041F416FEA568FA98CA6891FB6" KeyPath="yes" Source="$(var.SourceDir)\style.css" />
-            </Component>
-        </ComponentGroup>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="INSTALLDIR">
-            <Directory Id="dir7C3635117912185773B74CE69A101DF6" Name="doc" />
-        </DirectoryRef>
-    </Fragment>
+
+  <?include guids.wxi ?>
+
+  <Fragment>
+    <ComponentGroup Id="docFolder">
+      <ComponentRef Id="doc.hg.1.html" />
+      <ComponentRef Id="doc.hgignore.5.html" />
+      <ComponentRef Id="doc.hgrc.5.html" />
+      <ComponentRef Id="doc.style.css" />
+    </ComponentGroup>
+  </Fragment>
+
+  <Fragment>
+    <DirectoryRef Id="INSTALLDIR">
+      <Directory Id="docdir" Name="doc" FileSource="$(var.SourceDir)">
+        <Component Id="doc.hg.1.html" Guid="$(var.doc.hg.1.html.guid)">
+          <File Name="hg.1.html" KeyPath="yes">
+            <Shortcut Id="hg1StartMenu" Directory="ProgramMenuDir"
+                      Name="Mercurial Command Reference"
+                      Icon="hgIcon.ico" IconIndex="0" Advertise="yes"
+            />
+          </File>
+        </Component>
+        <Component Id="doc.hgignore.5.html" Guid="$(var.doc.hgignore.5.html.guid)">
+          <File Name="hgignore.5.html" KeyPath="yes">
+            <Shortcut Id="hgignore5StartMenu" Directory="ProgramMenuDir"
+                      Name="Mercurial Ignore Files"
+                      Icon="hgIcon.ico" IconIndex="0" Advertise="yes"
+            />
+          </File>
+        </Component>
+        <Component Id="doc.hgrc.5.html" Guid="$(var.doc.hgrc.5.html)">
+          <File Name="hgrc.5.html" KeyPath="yes">
+            <Shortcut Id="hgrc5StartMenu" Directory="ProgramMenuDir"
+                      Name="Mercurial Configuration Files"
+                      Icon="hgIcon.ico" IconIndex="0" Advertise="yes"
+            />
+          </File>
+        </Component>
+        <Component Id="doc.style.css" Guid="$(var.doc.style.css)">
+          <File Name="style.css" KeyPath="yes" />
+        </Component>
+      </Directory>
+    </DirectoryRef>
+  </Fragment>
+
 </Wix>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/wix/guids.wxi	Tue May 11 17:03:44 2010 -0500
@@ -0,0 +1,46 @@
+<Include>
+  <!-- These are component GUIDs used for Mercurial installers.
+       YOU MUST CHANGE ALL GUIDs below when copying this file
+       and replace 'Mercurial' in this notice with the name of
+       your project. Component GUIDs have global namespace!      -->
+
+  <!-- contrib.wxs -->
+  <?define contrib.guid = {F17D27B7-4A6B-4cd2-AE72-FED3CFAA585E} ?>
+  <?define contrib.vim.guid = {56B49B46-6657-405d-9E91-3FA68D011471} ?>
+
+  <!-- doc.wxs -->
+  <?define doc.hg.1.html.guid = {AAAA3FDA-EDC5-4220-B59D-D342722358A2} ?>
+  <?define doc.hgignore.5.html.guid = {AA9118C4-F3A0-4429-A5F4-5A1906B2D67F} ?>
+  <?define doc.hgrc.5.html = {E0CEA1EB-FA01-408c-844B-EE5965165BAE} ?>
+  <?define doc.style.css = {172F8262-98E0-4711-BD39-4DAE0D77EF05} ?>
+
+  <!-- help.wxs -->
+  <?define helpFolder.guid = {FA1546C1-5730-4e55-8542-76F5830841EE} ?>
+  
+  <!-- i18n.wxs -->
+  <?define i18nFolder.guid = {EADFA693-A0B5-4f31-87C9-3997CFAC1B42} ?>
+
+  <!-- templates.wxs -->
+  <?define templates.root.guid = {111509CB-4C96-4035-80BC-F66A99CD5ACB} ?>
+  <?define templates.atom.guid = {45FCDF84-DE27-44f4-AF6C-C41F5994AE0D} ?>
+  <?define templates.coal.guid = {B63CCAAB-4EAF-43b4-901E-4BD13F5B78FC} ?>
+  <?define templates.gitweb.guid = {5B8DF9A1-F475-45a5-B8F0-FCEA04A3B074} ?>
+  <?define templates.monoblue.guid = {7BA492F4-98F3-4943-A981-0BFE1690CF6E} ?>
+  <?define templates.paper.guid = {294F69D5-EC96-4fa7-8569-DD76C9993F47} ?>
+  <?define templates.raw.guid = {04DE03A2-FBFD-4c5f-8DEA-5436DDF4689D} ?>
+  <?define templates.rss.guid = {A7D608DE-0CF6-44f4-AF1E-EE30CC237FDA} ?>
+  <?define templates.spartan.guid = {80222625-FA8F-44b1-86CE-1781EF375D09} ?>
+  <?define templates.static.guid = {68C9F843-DE7E-480f-9DA2-D220B19D02C3} ?>
+
+  <!-- mercurial.wxs -->
+  <?define ProductUpgradeCode = {A1CC6134-E945-4399-BE36-EB0017FDF7CF} ?>
+
+  <?define ComponentMainExecutableGUID = {D102B8FA-059B-4ACC-9FA3-8C78C3B58EEF} ?>
+
+  <?define ReadMe.guid = {56A8E372-991D-4DCA-B91D-93D775974CF5} ?>
+  <?define COPYING.guid = {B7801DBA-1C49-4BF4-91AD-33C65F5C7895} ?>
+  <?define mercurial.rc.guid = {1D5FAEEE-7E6E-43B1-9F7F-802714316B15} ?>
+  <?define mergetools.rc.guid = {E8A1DC29-FF40-4B5F-BD12-80B9F7BF0CCD} ?>
+  <?define ProgramMenuDir.guid = {D5A63320-1238-489B-B68B-CF053E9577CA} ?>
+
+</Include>
--- a/contrib/wix/help.wxs	Mon Dec 07 12:31:45 2009 +0200
+++ b/contrib/wix/help.wxs	Tue May 11 17:03:44 2010 -0500
@@ -1,72 +1,25 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
-    <Fragment>
-        <ComponentGroup Id="helpFolder">
-            <Component Id="cmpC57BF45B775FC47D736ECD6944E64F6A" Directory="dirFC9FDBD71FA305BA6ECD4D639DB49784" Guid="{7189D54F-D55A-420C-9B2E-65A1CC522329}">
-                <File Id="filA01F5D0329BE64B4368A85C0B3671502" KeyPath="yes" Source="$(var.SourceDir)\config.txt" />
-            </Component>
-            <Component Id="cmp06DE93F7EEC0B3D1B698D92336E2AB11" Directory="dirFC9FDBD71FA305BA6ECD4D639DB49784" Guid="{15D85D50-B81D-41A7-9BDB-0DB57F655E83}">
-                <File Id="fil340415BFF8DB5A5977A364C422E731FF" KeyPath="yes" Source="$(var.SourceDir)\dates.txt" />
-            </Component>
-            <Component Id="cmp19C67CC3F7666886D7413E6F81DF923C" Directory="dirFC9FDBD71FA305BA6ECD4D639DB49784" Guid="{AA3D9BAB-C337-4726-9DAA-3EAAF3563378}">
-                <File Id="filDF5D1C01F4E5DFDF9ADC1B35D27FD592" KeyPath="yes" Source="$(var.SourceDir)\diffs.txt" />
-            </Component>
-            <Component Id="cmp0A78423CDE879648435F77671E14A6C3" Directory="dirFC9FDBD71FA305BA6ECD4D639DB49784" Guid="{EDFD63E7-69F6-4330-8226-07E5C3C5403D}">
-                <File Id="fil826C9369DF9AD54F6EBD9A10CA302D19" KeyPath="yes" Source="$(var.SourceDir)\environment.txt" />
-            </Component>
-            <Component Id="cmpA2B37D3B1AF89288970F0714F8A9AF39" Directory="dirFC9FDBD71FA305BA6ECD4D639DB49784" Guid="{B0D96B76-52E7-4D4E-A91D-24EC66373500}">
-                <File Id="filE8F682CC0E4F56B880D18017BC38DE50" KeyPath="yes" Source="$(var.SourceDir)\extensions.txt" />
-            </Component>
-            <Component Id="cmp417868B7DC07F14CE6B327271D65E5CC" Directory="dirFC9FDBD71FA305BA6ECD4D639DB49784" Guid="{0D01D7B8-8418-4FE6-9D37-0685FCB5DEE1}">
-                <File Id="filA0E27F4B12C85FA269523DC3A3CDC575" KeyPath="yes" Source="$(var.SourceDir)\multirevs.txt" />
-            </Component>
-            <Component Id="cmp339A70D8F3BF8B3AD679BE214A1984C7" Directory="dirFC9FDBD71FA305BA6ECD4D639DB49784" Guid="{EF91B612-EC51-4FC2-B3B1-C00ECBC13A4A}">
-                <File Id="fil6B14DD18C2EEDDDE767B9D83279A2ADA" KeyPath="yes" Source="$(var.SourceDir)\patterns.txt" />
-            </Component>
-            <Component Id="cmp177C53DE57B01391F4C5FDD15FA14EC6" Directory="dirFC9FDBD71FA305BA6ECD4D639DB49784" Guid="{AE7781B5-0F6E-4CF6-943D-B63F9511F274}">
-                <File Id="fil824583354419DB2A4F0AD312B3331FBB" KeyPath="yes" Source="$(var.SourceDir)\revisions.txt" />
-            </Component>
-            <Component Id="cmp69860FA1CEA8FE029A13DEF05E4832DF" Directory="dirFC9FDBD71FA305BA6ECD4D639DB49784" Guid="{895AB77F-A66E-42EF-B3FB-66E96737713D}">
-                <File Id="filF26222C0B0B107CF754108CD2B1C8CCF" KeyPath="yes" Source="$(var.SourceDir)\templates.txt" />
-            </Component>
-            <Component Id="cmpC1E444987188E87D749757D6E686B596" Directory="dirFC9FDBD71FA305BA6ECD4D639DB49784" Guid="{88938242-3A31-4F8E-9074-3B859DE150CD}">
-                <File Id="filCE7C1FF1BA40B646398A71851EB1EF7C" KeyPath="yes" Source="$(var.SourceDir)\urls.txt" />
-            </Component>
-        </ComponentGroup>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="INSTALLDIR">
-            <Directory Id="dirFC9FDBD71FA305BA6ECD4D639DB49784" Name="help" />
-        </DirectoryRef>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirFC9FDBD71FA305BA6ECD4D639DB49784" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirFC9FDBD71FA305BA6ECD4D639DB49784" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirFC9FDBD71FA305BA6ECD4D639DB49784" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirFC9FDBD71FA305BA6ECD4D639DB49784" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirFC9FDBD71FA305BA6ECD4D639DB49784" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirFC9FDBD71FA305BA6ECD4D639DB49784" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirFC9FDBD71FA305BA6ECD4D639DB49784" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirFC9FDBD71FA305BA6ECD4D639DB49784" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirFC9FDBD71FA305BA6ECD4D639DB49784" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirFC9FDBD71FA305BA6ECD4D639DB49784" />
-    </Fragment>
+
+  <?include guids.wxi ?>
+
+  <Fragment>
+    <DirectoryRef Id="INSTALLDIR">
+      <Directory Id="helpdir" Name="help" FileSource="$(var.SourceDir)">
+        <Component Id="helpFolder" Guid="$(var.helpFolder.guid)">
+          <File Name="config.txt" KeyPath="yes" />
+          <File Name="dates.txt" />
+          <File Name="diffs.txt" />
+          <File Name="environment.txt" />
+          <File Name="extensions.txt" />
+          <File Name="multirevs.txt" />
+          <File Name="patterns.txt" />
+          <File Name="revisions.txt" />
+          <File Name="templates.txt" />
+          <File Name="urls.txt" />
+        </Component>
+      </Directory>
+    </DirectoryRef>
+  </Fragment>
+
 </Wix>
--- a/contrib/wix/i18n.wxs	Mon Dec 07 12:31:45 2009 +0200
+++ b/contrib/wix/i18n.wxs	Tue May 11 17:03:44 2010 -0500
@@ -1,78 +1,25 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
-    <Fragment>
-        <ComponentGroup Id="i18nFolder">
-            <Component Id="cmp34947721B29BBB2D9942A0FC95D1F588" Directory="dirE238460D44340499CA44F8E5739FEA52" Guid="{511A94DD-0893-4E5B-A1CF-6DD9CDB1F797}">
-                <File Id="filF2E58DD4817D0D0AF53F4B8AB9836B47" KeyPath="yes" Source="$(var.SourceDir)\da.po" />
-            </Component>
-            <Component Id="cmpDC59717569F92122A034EC7E35A4F80D" Directory="dirE238460D44340499CA44F8E5739FEA52" Guid="{F6FD5F94-81D6-49AD-9D91-563E56224408}">
-                <File Id="fil39753E48327D06086C63EFA7711BB750" KeyPath="yes" Source="$(var.SourceDir)\de.po" />
-            </Component>
-            <Component Id="cmp7E5E80C4438C32CF7A419FDC63FB002D" Directory="dirE238460D44340499CA44F8E5739FEA52" Guid="{861DE2B9-B47D-4ACA-AEB2-645C69148B6B}">
-                <File Id="fil9B0C044DD27F2EE57B045B48BB697C0D" KeyPath="yes" Source="$(var.SourceDir)\el.po" />
-            </Component>
-            <Component Id="cmpA9C546113FA1B46B0C9498FA69F29B13" Directory="dirE238460D44340499CA44F8E5739FEA52" Guid="{756F0EEF-18AE-496F-A037-A063442CFE29}">
-                <File Id="fil6DF0C7BA972338067807AE385588F48A" KeyPath="yes" Source="$(var.SourceDir)\fr.po" />
-            </Component>
-            <Component Id="cmp6046EB31B43E28CD554FDD8D8E8AD420" Directory="dirE238460D44340499CA44F8E5739FEA52" Guid="{0404483D-818E-459B-902B-956D84869AE1}">
-                <File Id="filE99CA9E94849D4956606F72FD0B5FC5E" KeyPath="yes" Source="$(var.SourceDir)\hggettext" />
-            </Component>
-            <Component Id="cmp6133B01CC2B9B358CBF9327F700BD00A" Directory="dirE238460D44340499CA44F8E5739FEA52" Guid="{9B5289AE-FD8B-48ED-9E1C-2DB8BB495D0E}">
-                <File Id="filC69EEB86E4ED9073F34871B19155FED5" KeyPath="yes" Source="$(var.SourceDir)\it.po" />
-            </Component>
-            <Component Id="cmp97F2EE7A098F00025CB2FB889C5F6253" Directory="dirE238460D44340499CA44F8E5739FEA52" Guid="{9139E885-C29E-41C4-A9A5-52B3D1A2D0A0}">
-                <File Id="filA39E9F30340253C998EC80AE177CE43C" KeyPath="yes" Source="$(var.SourceDir)\ja.po" />
-            </Component>
-            <Component Id="cmpF3727AA82BA7F68310A26BB75A6647AD" Directory="dirE238460D44340499CA44F8E5739FEA52" Guid="{721683B1-6F5D-4F4F-A7FC-A134B4023B00}">
-                <File Id="fil80CA8EF53276179809903975CB3979F3" KeyPath="yes" Source="$(var.SourceDir)\pt_BR.po" />
-            </Component>
-            <Component Id="cmp939C74001F1FBEB147E5ADCED4770AC8" Directory="dirE238460D44340499CA44F8E5739FEA52" Guid="{69358529-D448-48EE-AD75-ADC7342F5EB2}">
-                <File Id="fil8F5BDF00539EE96B5270F71C7923CDC6" KeyPath="yes" Source="$(var.SourceDir)\sv.po" />
-            </Component>
-            <Component Id="cmpE23A15AD782608B1EDD835CF6B829378" Directory="dirE238460D44340499CA44F8E5739FEA52" Guid="{BB6C915D-20F7-4A90-91CA-F95629AF9992}">
-                <File Id="filC2CD3385CC6C9F85A582C8BEFF6A36FD" KeyPath="yes" Source="$(var.SourceDir)\zh_CN.po" />
-            </Component>
-            <Component Id="cmp3C3523DBA0ED9315E204C24B28BBECB1" Directory="dirE238460D44340499CA44F8E5739FEA52" Guid="{9A57C9EE-3A56-461C-A2B9-5CCB89080339}">
-                <File Id="fil717A0C3D62D332C48BAC66536FC1B6A0" KeyPath="yes" Source="$(var.SourceDir)\zh_TW.po" />
-            </Component>
-        </ComponentGroup>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="INSTALLDIR">
-            <Directory Id="dirE238460D44340499CA44F8E5739FEA52" Name="i18n" />
-        </DirectoryRef>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirE238460D44340499CA44F8E5739FEA52" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirE238460D44340499CA44F8E5739FEA52" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirE238460D44340499CA44F8E5739FEA52" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirE238460D44340499CA44F8E5739FEA52" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirE238460D44340499CA44F8E5739FEA52" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirE238460D44340499CA44F8E5739FEA52" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirE238460D44340499CA44F8E5739FEA52" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirE238460D44340499CA44F8E5739FEA52" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirE238460D44340499CA44F8E5739FEA52" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirE238460D44340499CA44F8E5739FEA52" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirE238460D44340499CA44F8E5739FEA52" />
-    </Fragment>
+
+  <?include guids.wxi ?>
+
+  <?define hg_po_langs = 
+    da;de;el;fr;it;ja;pt_BR;sv;zh_CN;zh_TW
+  ?>
+
+  <Fragment>
+    <DirectoryRef Id="INSTALLDIR">
+      <Directory Id="i18ndir" Name="i18n" FileSource="$(var.SourceDir)">
+        <Component Id="i18nFolder" Guid="$(var.i18nFolder.guid)">
+          <File Name="hggettext" KeyPath="yes" />
+          <?foreach LANG in $(var.hg_po_langs) ?>
+            <File Id="hg.$(var.LANG).po" 
+                  Name="$(var.LANG).po" 
+            />
+          <?endforeach?>
+        </Component>
+      </Directory>
+    </DirectoryRef>
+  </Fragment>
+
 </Wix>
--- a/contrib/wix/locale.wxs	Mon Dec 07 12:31:45 2009 +0200
+++ b/contrib/wix/locale.wxs	Tue May 11 17:03:44 2010 -0500
@@ -1,172 +1,32 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
-    <Fragment>
-        <ComponentGroup Id="localeFolder">
-            <Component Id="cmp83E7ADE01D9D898727106DBD965E0E17" Directory="dir37691BFCCBD5A038C2B503A0CA9FFDCC" Guid="{45A0DC87-8C6C-4BDA-907A-52F93D183C18}">
-                <File Id="fil9262D6374AF5065C3CD975127E419FD5" KeyPath="yes" Source="$(var.SourceDir)\da\LC_MESSAGES\hg.mo" />
-            </Component>
-            <Component Id="cmp52A447EBEC4DE496C672ED4285986FC2" Directory="dirFD5FFD33B2F5044881CA967A9603AD80" Guid="{D5929D29-3597-4BFA-970C-1336B74AED0D}">
-                <File Id="fil324023D432B614A0F6AD7C1795A47663" KeyPath="yes" Source="$(var.SourceDir)\de\LC_MESSAGES\hg.mo" />
-            </Component>
-            <Component Id="cmpD14AFBC2AB851E0FF50AB01087D37C37" Directory="dir11F21566046EDDA54202617BDCA27A33" Guid="{AEEB8542-91FA-4FDB-A976-C210608D45C4}">
-                <File Id="fil3263B9C209A995DEDAB99C915ADFEDF2" KeyPath="yes" Source="$(var.SourceDir)\el\LC_MESSAGES\hg.mo" />
-            </Component>
-            <Component Id="cmpF8D03402F9CC15628D08BD1547931E33" Directory="dir76A360BADC007F88A0B6C012DBA071F0" Guid="{F983F836-213C-4A8F-84C6-9DE3DDFFC4EF}">
-                <File Id="fil61661147957312ACE1F53D8B7B6FC20C" KeyPath="yes" Source="$(var.SourceDir)\fr\LC_MESSAGES\hg.mo" />
-            </Component>
-            <Component Id="cmpB7A86C8460D0C05C63F89961A89C32C2" Directory="dir84C2343136F7D4B857D28FDACE545F33" Guid="{E53EEBD5-5F54-426A-83C0-18C479C526D5}">
-                <File Id="filBA4BA4851E74E108136A44069A96DB8A" KeyPath="yes" Source="$(var.SourceDir)\it\LC_MESSAGES\hg.mo" />
-            </Component>
-            <Component Id="cmpA2E1D600E985FB335E18566CD5230E38" Directory="dir29F26642414C1248A97432E9C4947B87" Guid="{27F33F75-B5D6-47AD-AE23-DAC135401540}">
-                <File Id="filB4C1367F8EC03C778E275E7C6A4F882B" KeyPath="yes" Source="$(var.SourceDir)\ja\LC_MESSAGES\hg.mo" />
-            </Component>
-            <Component Id="cmp113B5931CE4199C5A5BF62728EA3A755" Directory="dir669486A97BE07EA6B1A33203A89256A6" Guid="{63F05AD9-CABA-420E-9A50-123F0803A8CE}">
-                <File Id="fil0B3347DB0C4538334E8346A9B7844458" KeyPath="yes" Source="$(var.SourceDir)\pt_BR\LC_MESSAGES\hg.mo" />
-            </Component>
-            <Component Id="cmpE35EFB6166609188B151E512DD832276" Directory="dir8637F62A0436F8880FACE0053CC26075" Guid="{81FC0E03-9956-4476-AFEE-1FCD0E98F860}">
-                <File Id="fil518947DB16E6B4E58C52D16C3C8559C1" KeyPath="yes" Source="$(var.SourceDir)\sv\LC_MESSAGES\hg.mo" />
-            </Component>
-            <Component Id="cmpC6F51D89D671AC7F66692F402B916E3D" Directory="dir402295F841398275038CC187DA8A3179" Guid="{198031AC-5DC5-44F9-AF77-A11AC15B82DE}">
-                <File Id="fil1905BB31038C24BBF8557DA796E65A2D" KeyPath="yes" Source="$(var.SourceDir)\zh_CN\LC_MESSAGES\hg.mo" />
-            </Component>
-            <Component Id="cmp2C7860CA004402234F7F1883F1093A1D" Directory="dirF619ECAC819DE44FC21E11EB1715B156" Guid="{EDF8F748-735A-4BC2-B683-14247D691F5C}">
-                <File Id="fil997E71C3D4C6318F0EF7048E50C5C0AA" KeyPath="yes" Source="$(var.SourceDir)\zh_TW\LC_MESSAGES\hg.mo" />
-            </Component>
-        </ComponentGroup>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="INSTALLDIR">
-            <Directory Id="dirA42EA32F4A238F2C40AD5ACF4C831152" Name="locale" />
-        </DirectoryRef>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir669486A97BE07EA6B1A33203A89256A6" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirF619ECAC819DE44FC21E11EB1715B156" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirFD5FFD33B2F5044881CA967A9603AD80" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir37691BFCCBD5A038C2B503A0CA9FFDCC" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir29F26642414C1248A97432E9C4947B87" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir84C2343136F7D4B857D28FDACE545F33" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir402295F841398275038CC187DA8A3179" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir11F21566046EDDA54202617BDCA27A33" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir8637F62A0436F8880FACE0053CC26075" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir76A360BADC007F88A0B6C012DBA071F0" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirA42EA32F4A238F2C40AD5ACF4C831152">
-            <Directory Id="dir0863D143DD8AA8C439D73CEC9FD66C1E" Name="fr" />
-        </DirectoryRef>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirA42EA32F4A238F2C40AD5ACF4C831152">
-            <Directory Id="dir0FE904A675AA86182DE42F092B60D5CB" Name="zh_CN" />
-        </DirectoryRef>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirABB7B0E1FB87A3FA812818303D9504D3">
-            <Directory Id="dir11F21566046EDDA54202617BDCA27A33" Name="LC_MESSAGES" />
-        </DirectoryRef>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirA42EA32F4A238F2C40AD5ACF4C831152">
-            <Directory Id="dir22C8B725631FC803704E5AB85CE4AB85" Name="da" />
-        </DirectoryRef>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirF7EFDAD22D2FB858CCFF6C617192E3F0">
-            <Directory Id="dir29F26642414C1248A97432E9C4947B87" Name="LC_MESSAGES" />
-        </DirectoryRef>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir22C8B725631FC803704E5AB85CE4AB85">
-            <Directory Id="dir37691BFCCBD5A038C2B503A0CA9FFDCC" Name="LC_MESSAGES" />
-        </DirectoryRef>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirA42EA32F4A238F2C40AD5ACF4C831152">
-            <Directory Id="dir40014079D6FD208765D49B2B6E77B444" Name="pt_BR" />
-        </DirectoryRef>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir0FE904A675AA86182DE42F092B60D5CB">
-            <Directory Id="dir402295F841398275038CC187DA8A3179" Name="LC_MESSAGES" />
-        </DirectoryRef>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir40014079D6FD208765D49B2B6E77B444">
-            <Directory Id="dir669486A97BE07EA6B1A33203A89256A6" Name="LC_MESSAGES" />
-        </DirectoryRef>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir0863D143DD8AA8C439D73CEC9FD66C1E">
-            <Directory Id="dir76A360BADC007F88A0B6C012DBA071F0" Name="LC_MESSAGES" />
-        </DirectoryRef>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir8CB5F92AB36FF6BF8CDA8AF1BD4BB402">
-            <Directory Id="dir84C2343136F7D4B857D28FDACE545F33" Name="LC_MESSAGES" />
-        </DirectoryRef>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirE6EE5833D8D4174BB8C9193A44E67309">
-            <Directory Id="dir8637F62A0436F8880FACE0053CC26075" Name="LC_MESSAGES" />
-        </DirectoryRef>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirA42EA32F4A238F2C40AD5ACF4C831152">
-            <Directory Id="dir8CB5F92AB36FF6BF8CDA8AF1BD4BB402" Name="it" />
-        </DirectoryRef>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirA42EA32F4A238F2C40AD5ACF4C831152">
-            <Directory Id="dir97CB62B25E0D4335D79170C310016140" Name="de" />
-        </DirectoryRef>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirA42EA32F4A238F2C40AD5ACF4C831152">
-            <Directory Id="dirABB7B0E1FB87A3FA812818303D9504D3" Name="el" />
-        </DirectoryRef>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirA42EA32F4A238F2C40AD5ACF4C831152">
-            <Directory Id="dirE6EE5833D8D4174BB8C9193A44E67309" Name="sv" />
-        </DirectoryRef>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirA42EA32F4A238F2C40AD5ACF4C831152">
-            <Directory Id="dirF24C7B7028912CC69CE9E1E38F2FEE54" Name="zh_TW" />
-        </DirectoryRef>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirF24C7B7028912CC69CE9E1E38F2FEE54">
-            <Directory Id="dirF619ECAC819DE44FC21E11EB1715B156" Name="LC_MESSAGES" />
-        </DirectoryRef>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirA42EA32F4A238F2C40AD5ACF4C831152">
-            <Directory Id="dirF7EFDAD22D2FB858CCFF6C617192E3F0" Name="ja" />
-        </DirectoryRef>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir97CB62B25E0D4335D79170C310016140">
-            <Directory Id="dirFD5FFD33B2F5044881CA967A9603AD80" Name="LC_MESSAGES" />
-        </DirectoryRef>
-    </Fragment>
+
+  <?define hglocales =
+    da;de;el;fr;it;ja;pt_BR;sv;zh_CN;zh_TW
+  ?>
+
+  <Fragment>
+    <ComponentGroup Id="localeFolder">
+      <?foreach LOC in $(var.hglocales) ?>
+        <ComponentRef Id="hg.locale.$(var.LOC)"/>
+      <?endforeach?>
+    </ComponentGroup>
+  </Fragment>
+
+  <Fragment>
+    <DirectoryRef Id="INSTALLDIR">
+      <Directory Id="localedir" Name="locale" FileSource="$(var.SourceDir)">
+        <?foreach LOC in $(var.hglocales) ?>
+          <Directory Id="hg.locale.$(var.LOC)" Name="$(var.LOC)">
+            <Directory Id="hg.locale.$(var.LOC).LC_MESSAGES" Name="LC_MESSAGES">
+              <Component Id="hg.locale.$(var.LOC)" Guid="*">
+                <File Id="hg.mo.$(var.LOC)" Name="hg.mo" KeyPath="yes" />
+              </Component>
+            </Directory>
+          </Directory>
+        <?endforeach?>
+      </Directory>
+    </DirectoryRef>
+  </Fragment>
+
 </Wix>
--- a/contrib/wix/mercurial.wxs	Mon Dec 07 12:31:45 2009 +0200
+++ b/contrib/wix/mercurial.wxs	Tue May 11 17:03:44 2010 -0500
@@ -6,24 +6,31 @@
   This software may be used and distributed according to the terms of the
   GNU General Public License version 2 or any later version. -->
 
-  <?define ComponentMainExecutableGUID = D102B8FA-059B-4ACC-9FA3-8C78C3B58EEF ?>
-  <?define ProductUpgradeCode = A1CC6134-E945-4399-BE36-EB0017FDF7CF ?>
+  <?include guids.wxi ?>
 
-  <Product Name='Mercurial $(var.Version)' Id='*'
+  <Product Id='*'
+    Name='Mercurial $(var.Version)' 
     UpgradeCode='$(var.ProductUpgradeCode)'
-    Language='1033' Codepage='1252' Version='$(var.Version)' Manufacturer='Matt Mackall and others.'>
+    Language='1033' Codepage='1252' Version='$(var.Version)'
+    Manufacturer='Matt Mackall and others'>
 
-    <Package Id='*' Keywords='Installer' Description="Mercurial distributed SCM (version $(var.Version))"
-      Comments='$(var.Comments)' Manufacturer='Matt Mackall and others.'
+    <Package Id='*'
+      Keywords='Installer'
+      Description="Mercurial distributed SCM (version $(var.Version))"
+      Comments='$(var.Comments)'
+      Manufacturer='Matt Mackall and others'
       InstallerVersion='300' Languages='1033' Compressed='yes' SummaryCodepage='1252' />
 
-    <Media Id='1' Cabinet='mercurial.cab' EmbedCab='yes' DiskPrompt='CD-ROM #1' CompressionLevel='high' />
+    <Media Id='1' Cabinet='mercurial.cab' EmbedCab='yes' DiskPrompt='CD-ROM #1'
+           CompressionLevel='high' />
     <Property Id='DiskPrompt' Value="Mercurial $(var.Version) Installation [1]" />
 
-    <Condition Message='Mercurial requires Windows XP or higher'>VersionNT >= 501</Condition>
+    <Condition Message='Mercurial requires Windows XP or higher'
+      >VersionNT >= 501</Condition>
 
     <Property Id="INSTALLDIR">
-      <ComponentSearch Id='SearchForMainExecutableComponent' Guid='$(var.ComponentMainExecutableGUID)' />
+      <ComponentSearch Id='SearchForMainExecutableComponent'
+                       Guid='$(var.ComponentMainExecutableGUID)' />
     </Property>
 
     <!--Property Id='ARPCOMMENTS'>any comments</Property-->
@@ -37,30 +44,35 @@
     <Property Id='INSTALLEDMERCURIALPRODUCTS' Secure='yes'></Property>
     <Property Id='REINSTALLMODE'>amus</Property>
 
+    <!--Auto-accept the license page-->
+    <Property Id='LicenseAccepted'>1</Property>
+
     <Directory Id='TARGETDIR' Name='SourceDir'>
       <Directory Id='ProgramFilesFolder' Name='PFiles'>
         <Directory Id='INSTALLDIR' Name='Mercurial'>
           <Component Id='MainExecutable' Guid='$(var.ComponentMainExecutableGUID)'>
-            <File Id='hgEXE' Name='hg.exe' DiskId='1' Source='dist\hg.exe' KeyPath='yes' />
-            <File Id='libraryZIP' Name='library.zip' DiskId='1' Source='dist\library.zip' />
-            <File Id='pythonDLL' Name='python26.dll' DiskId='1' Source='dist\python26.dll' />
+            <File Id='hgEXE' Name='hg.exe' Source='dist\hg.exe' KeyPath='yes' />
+            <File Id='libraryZIP' Name='library.zip' Source='dist\library.zip' />
+            <File Id='pythonDLL' Name='python26.dll' Source='dist\python26.dll' />
             <Environment Id="Environment" Name="PATH" Part="last" System="yes"
                          Permanent="no" Value="[INSTALLDIR]" Action="set" />
           </Component>
-          <Component Id='ReadMe' Guid='56A8E372-991D-4DCA-B91D-93D775974CF5'>
-              <File Id='ReadMe' Name='ReadMe.html' DiskId='1' Source='contrib\win32\ReadMe.html' KeyPath='yes'/>
+          <Component Id='ReadMe' Guid='$(var.ReadMe.guid)'>
+              <File Id='ReadMe' Name='ReadMe.html' Source='contrib\win32\ReadMe.html'
+                    KeyPath='yes'/>
           </Component>
-          <Component Id='COPYING' Guid='B7801DBA-1C49-4BF4-91AD-33C65F5C7895'>
-            <File Id='COPYING' Name='COPYING.rtf' DiskId='1' Source='contrib\wix\COPYING.rtf' />
+          <Component Id='COPYING' Guid='$(var.COPYING.guid)'>
+            <File Id='COPYING' Name='COPYING.rtf' Source='contrib\wix\COPYING.rtf'
+                  KeyPath='yes'/>
           </Component>
           <Directory Id='HGRCD' Name='hgrc.d'>
-            <Component Id='mercurial.rc' Guid='1D5FAEEE-7E6E-43B1-9F7F-802714316B15'>
-              <File Id='mercurial.rc' Name='Mercurial.rc' DiskId='1' Source='contrib\win32\mercurial.ini'
-                    ReadOnly='yes'/>
+            <Component Id='mercurial.rc' Guid='$(var.mercurial.rc.guid)'>
+              <File Id='mercurial.rc' Name='Mercurial.rc' Source='contrib\win32\mercurial.ini'
+                    ReadOnly='yes' KeyPath='yes'/>
             </Component>
-            <Component Id='mergetools.rc' Guid='E8A1DC29-FF40-4B5F-BD12-80B9F7BF0CCD'>
-              <File Id='mergetools.rc' Name='MergeTools.rc' DiskId='1' Source='contrib\mergetools.hgrc'
-                    ReadOnly='yes'/>
+            <Component Id='mergetools.rc' Guid='$(var.mergetools.rc.guid)'>
+              <File Id='mergetools.rc' Name='MergeTools.rc' Source='contrib\mergetools.hgrc'
+                    ReadOnly='yes' KeyPath='yes'/>
             </Component>
           </Directory>
         </Directory>
@@ -68,17 +80,16 @@
 
       <Directory Id="ProgramMenuFolder" Name="Programs">
         <Directory Id="ProgramMenuDir" Name="Mercurial $(var.Version)">
-          <Component Id="ProgramMenuDir" Guid="D5A63320-1238-489B-B68B-CF053E9577CA">
+          <Component Id="ProgramMenuDir" Guid="$(var.ProgramMenuDir.guid)">
             <RemoveFolder Id='ProgramMenuDir' On='uninstall' />
             <RegistryValue Root='HKCU' Key='Software\Mercurial\InstallDir' Type='string'
                            Value='[INSTALLDIR]' KeyPath='yes' />
-            <Shortcut Id='UrlShortcut' Directory='ProgramMenuDir' Name='Mercurial Web Site' Target='[ARPHELPLINK]'
-                      Icon="hgIcon.ico" IconIndex='0' />
+            <Shortcut Id='UrlShortcut' Directory='ProgramMenuDir' Name='Mercurial Web Site'
+                      Target='[ARPHELPLINK]' Icon="hgIcon.ico" IconIndex='0' />
           </Component>
         </Directory>
       </Directory>
 
-      <Directory Id="DesktopFolder" Name="Desktop" />
       <Merge Id='VCRuntime' DiskId='1' Language='1033'
              SourceFile='$(var.VCRedistSrcDir)\microsoft.vcxx.crt.x86_msm.msm' />
       <Merge Id='VCRuntimePolicy' DiskId='1' Language='1033'
@@ -95,14 +106,14 @@
         <ComponentRef Id='COPYING' />
         <ComponentRef Id='mercurial.rc' />
         <ComponentRef Id='mergetools.rc' />
-        <ComponentGroupRef Id='helpFolder' />
+        <ComponentRef Id='helpFolder' />
         <ComponentGroupRef Id='templatesFolder' />
         <MergeRef Id='VCRuntime' />
         <MergeRef Id='VCRuntimePolicy' />
       </Feature>
       <Feature Id='Locales' Title='Translations' Description='Translations' Level='1'>
         <ComponentGroupRef Id='localeFolder' />
-        <ComponentGroupRef Id='i18nFolder' />
+        <ComponentRef Id='i18nFolder' />
       </Feature>
       <Feature Id='Documentation' Title='Documentation' Description='HTML man pages' Level='1'>
         <ComponentGroupRef Id='docFolder' />
--- a/contrib/wix/templates.wxs	Mon Dec 07 12:31:45 2009 +0200
+++ b/contrib/wix/templates.wxs	Tue May 11 17:03:44 2010 -0500
@@ -1,801 +1,206 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
-    <Fragment>
-        <ComponentGroup Id="templatesFolder">
-            <Component Id="cmp245D27C2F7D49A9E8A10E551A4913BD8" Directory="dirBFB9D3FD33CE2C696D390C94E4E1B4D8" Guid="{67C4810A-F6CA-4512-9A43-43DD72A525BF}">
-                <File Id="filC46EB4977E850DDE52085CD81647B147" KeyPath="yes" Source="$(var.SourceDir)\map-cmdline.changelog" />
-            </Component>
-            <Component Id="cmpC6E57D5F80AEF6636B609AFDDC1B34C3" Directory="dirBFB9D3FD33CE2C696D390C94E4E1B4D8" Guid="{212A9079-1B49-4DB7-A49E-BACCBCD8AA33}">
-                <File Id="fil66141877E998E34A73C78F52F5525D79" KeyPath="yes" Source="$(var.SourceDir)\map-cmdline.compact" />
-            </Component>
-            <Component Id="cmp3E8935E93A2F8142E0F30B7654DEDB7B" Directory="dirBFB9D3FD33CE2C696D390C94E4E1B4D8" Guid="{70544E9C-F575-4039-94F9-19DAA12BA38B}">
-                <File Id="filB6CE3FEEF27A46E979CF71DFD5071876" KeyPath="yes" Source="$(var.SourceDir)\map-cmdline.default" />
-            </Component>
-            <Component Id="cmpA98C695C9A852CA08358744DE71BBCB4" Directory="dirBFB9D3FD33CE2C696D390C94E4E1B4D8" Guid="{A0123134-AB72-4793-BAAC-109F78D4A35B}">
-                <File Id="fil603AB867DCF6C98CF4E8C908F627AD53" KeyPath="yes" Source="$(var.SourceDir)\map-cmdline.xml" />
-            </Component>
-            <Component Id="cmpDE1FEC5413B37B6300493CAF819462DC" Directory="dirBFB9D3FD33CE2C696D390C94E4E1B4D8" Guid="{F89E0BE4-DEAF-4132-BE18-86A171111051}">
-                <File Id="filFFC56D533BF5BA670CAD613427C30029" KeyPath="yes" Source="$(var.SourceDir)\template-vars.txt" />
-            </Component>
-            <Component Id="cmpD7A2B04E9CF5E810D00331B0D14890C1" Directory="dir35F8598B197DFC5580317F5E7C2E9AE9" Guid="{EEB7B220-90C2-4049-BE87-592C3B5A23D4}">
-                <File Id="filAF2A94DF56A6D0C95DE82C39C151A195" KeyPath="yes" Source="$(var.SourceDir)\atom\changelog.tmpl" />
-            </Component>
-            <Component Id="cmpB2016007359D825073A8ED67A1827DF9" Directory="dir35F8598B197DFC5580317F5E7C2E9AE9" Guid="{EDD3F2A2-160D-4C2C-9C92-E41FA1B5D474}">
-                <File Id="fil417417DF06043E5780F4B5C267352CF9" KeyPath="yes" Source="$(var.SourceDir)\atom\changelogentry.tmpl" />
-            </Component>
-            <Component Id="cmp4AF55640C671810FB1ADF0351BB90E17" Directory="dir35F8598B197DFC5580317F5E7C2E9AE9" Guid="{E15B5539-56E0-4D48-A89A-4E6E286AAC68}">
-                <File Id="filABC1E3A8F08963D46947F5DD71204159" KeyPath="yes" Source="$(var.SourceDir)\atom\error.tmpl" />
-            </Component>
-            <Component Id="cmpEAFBDC0898D5AB411B21780B0B8F2C65" Directory="dir35F8598B197DFC5580317F5E7C2E9AE9" Guid="{3F4C35A0-3860-4C9C-9C4F-96D601C60B0F}">
-                <File Id="filFD94D63312BF0A454BCC74F559F26AC5" KeyPath="yes" Source="$(var.SourceDir)\atom\filelog.tmpl" />
-            </Component>
-            <Component Id="cmp09A2C49717F147CA23C43FA4BE19CB89" Directory="dir35F8598B197DFC5580317F5E7C2E9AE9" Guid="{EFDA7618-5C27-449F-BBDF-13B512CA774D}">
-                <File Id="filD79697217EB1368CCFBAC93891022BA4" KeyPath="yes" Source="$(var.SourceDir)\atom\header.tmpl" />
-            </Component>
-            <Component Id="cmpA1BD3C8A4A8B57A1A224DC625A939716" Directory="dir35F8598B197DFC5580317F5E7C2E9AE9" Guid="{8AFBBBD2-D743-4C72-9C4C-8EB7F9F5E4BD}">
-                <File Id="filC93C0483D9AB074A860A448C8AE7A311" KeyPath="yes" Source="$(var.SourceDir)\atom\map" />
-            </Component>
-            <Component Id="cmp1F8380EC4EB90B7E2893B8ABAFBA3C6C" Directory="dir35F8598B197DFC5580317F5E7C2E9AE9" Guid="{691B5260-2697-43AC-8D71-7E6CBC9784BA}">
-                <File Id="fil38C516EE8F0ED4FFB814F8A78FE04B5B" KeyPath="yes" Source="$(var.SourceDir)\atom\tagentry.tmpl" />
-            </Component>
-            <Component Id="cmp87896A208C9063C4E0F127D6C124A97A" Directory="dir35F8598B197DFC5580317F5E7C2E9AE9" Guid="{BB5DECFE-313E-44FD-B354-FB8DB781199E}">
-                <File Id="fil01F9F5804BA8E9E7D37A07043B4EE7B7" KeyPath="yes" Source="$(var.SourceDir)\atom\tags.tmpl" />
-            </Component>
-            <Component Id="cmpF5D9AB7FE9A07C307EE33CD2AFA719AD" Directory="dir2EDFFCA56732C858816EF19F127E8D0F" Guid="{5D4CD000-740A-445D-B22A-413D27B2D424}">
-                <File Id="fil1B50FD60A3ADF7A829E34C97198D1D52" KeyPath="yes" Source="$(var.SourceDir)\coal\header.tmpl" />
-            </Component>
-            <Component Id="cmpC34DFD4C8EBD5BCABA6F10B70B1D28B1" Directory="dir2EDFFCA56732C858816EF19F127E8D0F" Guid="{5FC3B465-E22F-4B49-8733-2D6D8D5457C4}">
-                <File Id="fil483848B756E76EE840BFB45A62C00DB3" KeyPath="yes" Source="$(var.SourceDir)\coal\map" />
-            </Component>
-            <Component Id="cmpC5067895295DA39B9B11AD3DD4E21B52" Directory="dir3D22B249045A1473460D0D5D104478F2" Guid="{4061F72F-DA6A-4A2E-B917-0179C577EC91}">
-                <File Id="filAB35B91E5DC594F9F0BE979B5C938650" KeyPath="yes" Source="$(var.SourceDir)\gitweb\branches.tmpl" />
-            </Component>
-            <Component Id="cmp7F9AD93FB91A0E4622F452B0EF9352C2" Directory="dir3D22B249045A1473460D0D5D104478F2" Guid="{1B73BD55-F6F1-40B7-99F6-7BFB9252CC85}">
-                <File Id="filB65F6983E85F6327A20D92F0E50C8F3A" KeyPath="yes" Source="$(var.SourceDir)\gitweb\changelog.tmpl" />
-            </Component>
-            <Component Id="cmpB186C4D7FF025E46CE87EA66461F775C" Directory="dir3D22B249045A1473460D0D5D104478F2" Guid="{0F9A4AAA-B82D-4DE4-B475-BDCCA08A81BB}">
-                <File Id="filBBAE80D203E7C7DE353764E8D8ED5CF4" KeyPath="yes" Source="$(var.SourceDir)\gitweb\changelogentry.tmpl" />
-            </Component>
-            <Component Id="cmp4C205C07FEA1B04A79AB62A672FB7034" Directory="dir3D22B249045A1473460D0D5D104478F2" Guid="{0BB9DA75-8FE3-48B1-9F7A-E377C36F7EBB}">
-                <File Id="filD737DB25A84CF6BAC537C01A4C1FD441" KeyPath="yes" Source="$(var.SourceDir)\gitweb\changeset.tmpl" />
-            </Component>
-            <Component Id="cmp4F1AEA9E1182AA3FEB959501A4524E2C" Directory="dir3D22B249045A1473460D0D5D104478F2" Guid="{4CA8A2C5-2401-476C-8863-2AEAC3178B87}">
-                <File Id="filAC2F74FB38AD114EE60B8A858195AAA5" KeyPath="yes" Source="$(var.SourceDir)\gitweb\error.tmpl" />
-            </Component>
-            <Component Id="cmp6D28475C0E5C0EF2C7368197A2543E04" Directory="dir3D22B249045A1473460D0D5D104478F2" Guid="{3E7A0738-9ADA-409F-82D7-63C5212D9FEF}">
-                <File Id="fil7E719E65B937150669EC7A65D931A42E" KeyPath="yes" Source="$(var.SourceDir)\gitweb\fileannotate.tmpl" />
-            </Component>
-            <Component Id="cmp41DDE65FBD7F6C62DE2F904E8BB70D52" Directory="dir3D22B249045A1473460D0D5D104478F2" Guid="{D82ECE81-F30E-4A32-BB33-A5ED30242266}">
-                <File Id="filE5314FDBD1A83FD2071ABDBEB5D75966" KeyPath="yes" Source="$(var.SourceDir)\gitweb\filediff.tmpl" />
-            </Component>
-            <Component Id="cmp73B2345AE1A62971C248A4200125105E" Directory="dir3D22B249045A1473460D0D5D104478F2" Guid="{88E6B5AF-F996-4676-9DD2-755803ED6ADD}">
-                <File Id="fil813DE4E9B8637CB0C9DEEE04871B7154" KeyPath="yes" Source="$(var.SourceDir)\gitweb\filelog.tmpl" />
-            </Component>
-            <Component Id="cmp74429C97DF03C076BB1976374DB4393A" Directory="dir3D22B249045A1473460D0D5D104478F2" Guid="{12709310-806B-443B-8A7D-49A7C2AC83AA}">
-                <File Id="fil80D6BDD10936FB214225A8A9C385CE36" KeyPath="yes" Source="$(var.SourceDir)\gitweb\filerevision.tmpl" />
-            </Component>
-            <Component Id="cmpAC64876FBE3380283CFA6A488C4610E5" Directory="dir3D22B249045A1473460D0D5D104478F2" Guid="{FC6F127E-4BB9-40AE-B3AC-0B0EB4F8315D}">
-                <File Id="fil05FF66A70E6AC220F28CCC9C93327329" KeyPath="yes" Source="$(var.SourceDir)\gitweb\footer.tmpl" />
-            </Component>
-            <Component Id="cmp30DB23C31D0DD655BA9E3F2D0D6C8582" Directory="dir3D22B249045A1473460D0D5D104478F2" Guid="{55E52857-56BD-46E3-BC4D-597CA09CB6C5}">
-                <File Id="filEE919C1EA37972DA70DECD2DE78563C2" KeyPath="yes" Source="$(var.SourceDir)\gitweb\graph.tmpl" />
-            </Component>
-            <Component Id="cmp1D6387539D230EC1EE3F68EC430EAB56" Directory="dir3D22B249045A1473460D0D5D104478F2" Guid="{F6E15E2E-80A2-4194-9763-EA900D9D4517}">
-                <File Id="filD3FF2C0986F56DE61C70A80D6FCD2963" KeyPath="yes" Source="$(var.SourceDir)\gitweb\header.tmpl" />
-            </Component>
-            <Component Id="cmpF4CB95EC9E3B863756FEBD0A4AE3B573" Directory="dir3D22B249045A1473460D0D5D104478F2" Guid="{7098B211-3164-4303-B719-8897458E7474}">
-                <File Id="fil02B1E9DBF857B7D72BF76AADDDB1C11D" KeyPath="yes" Source="$(var.SourceDir)\gitweb\index.tmpl" />
-            </Component>
-            <Component Id="cmp4BFEAC2B08F975649AC2660D56EFA4B7" Directory="dir3D22B249045A1473460D0D5D104478F2" Guid="{BFB237EE-79F5-45E5-B182-61BC41FD366D}">
-                <File Id="fil95099724846977404F6A38059E39F6EE" KeyPath="yes" Source="$(var.SourceDir)\gitweb\manifest.tmpl" />
-            </Component>
-            <Component Id="cmpEF1EB2713EEA62B1F81C5872116A1CEC" Directory="dir3D22B249045A1473460D0D5D104478F2" Guid="{210BD2AF-E37E-4506-9723-AB284A0A2105}">
-                <File Id="fil15115F4F87328A9540B3644B3475A878" KeyPath="yes" Source="$(var.SourceDir)\gitweb\map" />
-            </Component>
-            <Component Id="cmp9F186B6C977DFA7712F92E9FB2DE3891" Directory="dir3D22B249045A1473460D0D5D104478F2" Guid="{5A4A880B-F777-4C4F-96AD-AD18787A2DA1}">
-                <File Id="fil7F7A105718DAA19575A155EBE946F511" KeyPath="yes" Source="$(var.SourceDir)\gitweb\notfound.tmpl" />
-            </Component>
-            <Component Id="cmp1DA3F0160E3BCFE235A3C6F752FB2D12" Directory="dir3D22B249045A1473460D0D5D104478F2" Guid="{85C86EC9-8328-4FDC-9DA4-009A3CBE1421}">
-                <File Id="fil645D98D0A60CFDC1C5D6AABEFCF7F120" KeyPath="yes" Source="$(var.SourceDir)\gitweb\search.tmpl" />
-            </Component>
-            <Component Id="cmpECF912909627794036B7DF5594B928F4" Directory="dir3D22B249045A1473460D0D5D104478F2" Guid="{5F0E4FE5-59D6-48EA-9BBF-0D1D8381E270}">
-                <File Id="fil7A9B36B1AAC6F76DB84BD2DA8FFF44C6" KeyPath="yes" Source="$(var.SourceDir)\gitweb\shortlog.tmpl" />
-            </Component>
-            <Component Id="cmpDA71A47B23710A56F1A612AC01E1A0D7" Directory="dir3D22B249045A1473460D0D5D104478F2" Guid="{D913EF9E-0F02-4C11-B0E9-9F8945854F6E}">
-                <File Id="fil1EDFE0E741E8E14C9A1DB7E66BCC4C9C" KeyPath="yes" Source="$(var.SourceDir)\gitweb\summary.tmpl" />
-            </Component>
-            <Component Id="cmp209D055DDBF11DC7688C0A8765559E32" Directory="dir3D22B249045A1473460D0D5D104478F2" Guid="{9BD8D802-796C-4347-9D21-3D2FC568DA94}">
-                <File Id="fil604852E1873B9EB0D5E2F7A8680CB3D2" KeyPath="yes" Source="$(var.SourceDir)\gitweb\tags.tmpl" />
-            </Component>
-            <Component Id="cmp1823075725AEFF65DFA5A8216B1BBAD1" Directory="dirA4D7AC0F636AD49029D4D19861392983" Guid="{4F380BC7-0658-46A2-8309-6179462CFBA3}">
-                <File Id="filDA3E8C8E479D5D924DD741002D22369B" KeyPath="yes" Source="$(var.SourceDir)\monoblue\branches.tmpl" />
-            </Component>
-            <Component Id="cmpDBF9A5ECD1ABDCF5C28F35FB7B4F7001" Directory="dirA4D7AC0F636AD49029D4D19861392983" Guid="{2522DE9A-08A5-425F-8AF5-499FA6205B85}">
-                <File Id="fil8E8F17BD7047E2FA8D6D83E3C561A136" KeyPath="yes" Source="$(var.SourceDir)\monoblue\changelog.tmpl" />
-            </Component>
-            <Component Id="cmp88FAE67F5F5D776AB06D0DFD7AF6B321" Directory="dirA4D7AC0F636AD49029D4D19861392983" Guid="{7F1857A6-1AB6-40BA-ADD9-D9AD10E86F86}">
-                <File Id="filB923707738590DC420DC9EC081FCD19E" KeyPath="yes" Source="$(var.SourceDir)\monoblue\changelogentry.tmpl" />
-            </Component>
-            <Component Id="cmpD9CA247FB5FD87215801EF6FA1862855" Directory="dirA4D7AC0F636AD49029D4D19861392983" Guid="{DE0C16EC-89C1-4553-9FC2-08BDD881411C}">
-                <File Id="fil40ED0CD11F2D78CC17557BADFA4CE6C7" KeyPath="yes" Source="$(var.SourceDir)\monoblue\changeset.tmpl" />
-            </Component>
-            <Component Id="cmp4BE8112F99779C0F09A4F1FC00C2EF1E" Directory="dirA4D7AC0F636AD49029D4D19861392983" Guid="{31991907-3468-41C5-8B9B-73730BBE6064}">
-                <File Id="fil6D7DFED2D3692BBD082FB0D28D889EA6" KeyPath="yes" Source="$(var.SourceDir)\monoblue\error.tmpl" />
-            </Component>
-            <Component Id="cmp7ABEE036B7DAAD0D1600DDBB43F2C671" Directory="dirA4D7AC0F636AD49029D4D19861392983" Guid="{F9F8FADE-2F02-457B-899E-BB18DFD0AE44}">
-                <File Id="filF2B59AD2AB4DE9C3101DC96F8867A4D5" KeyPath="yes" Source="$(var.SourceDir)\monoblue\fileannotate.tmpl" />
-            </Component>
-            <Component Id="cmpE4F3DB56FD3C5BB582CA58C7BACB0506" Directory="dirA4D7AC0F636AD49029D4D19861392983" Guid="{6E0D083A-19BE-4C8F-8CCF-339395DC638D}">
-                <File Id="fil6BBA7BBD0890DFCC52E62A948092EFB6" KeyPath="yes" Source="$(var.SourceDir)\monoblue\filediff.tmpl" />
-            </Component>
-            <Component Id="cmpEE32268B28EEC3EB3A572522C71905AE" Directory="dirA4D7AC0F636AD49029D4D19861392983" Guid="{493A745D-5342-4436-8C27-A8A6F6AC88EA}">
-                <File Id="filA85CD6E3008BD751106AB7B9A480C492" KeyPath="yes" Source="$(var.SourceDir)\monoblue\filelog.tmpl" />
-            </Component>
-            <Component Id="cmpC761C78428E72FFB5558162BB37B61BD" Directory="dirA4D7AC0F636AD49029D4D19861392983" Guid="{3083DBF6-1661-4722-B30B-1E3B3B90595D}">
-                <File Id="fil0BBD8320FE88C3AC548D940A0C435A05" KeyPath="yes" Source="$(var.SourceDir)\monoblue\filerevision.tmpl" />
-            </Component>
-            <Component Id="cmp17DC3C81B3ABC398360C2007A40ED1E6" Directory="dirA4D7AC0F636AD49029D4D19861392983" Guid="{E3059DE2-D513-473A-9720-DC7FDE13C29F}">
-                <File Id="filCA536CAA1C01B426565F20331B68760B" KeyPath="yes" Source="$(var.SourceDir)\monoblue\footer.tmpl" />
-            </Component>
-            <Component Id="cmp7F175F65C4834FE6069C99E338BDA7E5" Directory="dirA4D7AC0F636AD49029D4D19861392983" Guid="{F04EEDB1-0506-48A8-A4CB-B6A17188FDFE}">
-                <File Id="filC02F1442F76CB500AEB3840EF7356FD6" KeyPath="yes" Source="$(var.SourceDir)\monoblue\graph.tmpl" />
-            </Component>
-            <Component Id="cmpFC525BC58FC3D5CBABF272044899809D" Directory="dirA4D7AC0F636AD49029D4D19861392983" Guid="{2830CCC3-2E3A-4F54-9834-88E61755FDC1}">
-                <File Id="fil8B196B20D79CED85511A9369E5410E12" KeyPath="yes" Source="$(var.SourceDir)\monoblue\header.tmpl" />
-            </Component>
-            <Component Id="cmp5D58BCED0887E9ABCF56A03A3F766C05" Directory="dirA4D7AC0F636AD49029D4D19861392983" Guid="{67B47C67-E7C2-4D2E-BF1E-35072896BF66}">
-                <File Id="fil0F66655D0D9C0515498C736CA70EF2E7" KeyPath="yes" Source="$(var.SourceDir)\monoblue\index.tmpl" />
-            </Component>
-            <Component Id="cmp069EBBE6EAC918EFD74E47E30707A6B1" Directory="dirA4D7AC0F636AD49029D4D19861392983" Guid="{578111BD-AB5C-4E97-8873-F13EF2AB50A6}">
-                <File Id="filB70BAB1BDAC9E692CBD3DF2107E53358" KeyPath="yes" Source="$(var.SourceDir)\monoblue\manifest.tmpl" />
-            </Component>
-            <Component Id="cmp7B96FAA138AD6D0C5632C9AC08396CC7" Directory="dirA4D7AC0F636AD49029D4D19861392983" Guid="{0765336B-6756-4F68-804E-593D19D85696}">
-                <File Id="fil28523FA8BEB5DBE9EB187AC3D8FDFEBA" KeyPath="yes" Source="$(var.SourceDir)\monoblue\map" />
-            </Component>
-            <Component Id="cmp2F6A7B795CB0B56C4FA02196BB6C7DC6" Directory="dirA4D7AC0F636AD49029D4D19861392983" Guid="{A97A84F4-6360-405E-AB51-6604AD513107}">
-                <File Id="fil7AF04A6D9109C9B041BB38DC59E17AF9" KeyPath="yes" Source="$(var.SourceDir)\monoblue\notfound.tmpl" />
-            </Component>
-            <Component Id="cmp0ABEB61C4B9DB9E2FA98E5CD114D7BF3" Directory="dirA4D7AC0F636AD49029D4D19861392983" Guid="{4F97F211-D002-4241-A3F7-A39987524C82}">
-                <File Id="fil0D19104380B37D9A5821C8F0E7C5E77E" KeyPath="yes" Source="$(var.SourceDir)\monoblue\search.tmpl" />
-            </Component>
-            <Component Id="cmp113433EEDE668F21E50B0BFE83C69EEA" Directory="dirA4D7AC0F636AD49029D4D19861392983" Guid="{130A1D16-509D-442B-A990-8E9013D8BD05}">
-                <File Id="filB23212E48881879A57ACC2C8D328E43A" KeyPath="yes" Source="$(var.SourceDir)\monoblue\shortlog.tmpl" />
-            </Component>
-            <Component Id="cmp7F0B6DB5B3B965F203EF66F4BCA0CE8C" Directory="dirA4D7AC0F636AD49029D4D19861392983" Guid="{C452F9A9-67C4-43DC-B0B1-1A833A4F9095}">
-                <File Id="fil696E3BCDF3D23D04000016B5E5B255A2" KeyPath="yes" Source="$(var.SourceDir)\monoblue\summary.tmpl" />
-            </Component>
-            <Component Id="cmpE504AE3BC09BD33B8042C57812C4D1ED" Directory="dirA4D7AC0F636AD49029D4D19861392983" Guid="{9126CF0F-8EE1-4136-B27D-F1773EE2E2AB}">
-                <File Id="filC76BB94267C1E4FFF294F47D87A298D0" KeyPath="yes" Source="$(var.SourceDir)\monoblue\tags.tmpl" />
-            </Component>
-            <Component Id="cmp6A1BCBCE2BB6301A8437B67971E31BBD" Directory="dirCCAE13CC8442C655BA01764423E1EBB7" Guid="{C1507C7D-9D45-4A0E-AF3F-8E52F60E9A49}">
-                <File Id="filE8D51B053A29EE93BF3E1B0AEE6B5604" KeyPath="yes" Source="$(var.SourceDir)\paper\branches.tmpl" />
-            </Component>
-            <Component Id="cmp7FCF7EC491FB8A8C77281BBF71B21092" Directory="dirCCAE13CC8442C655BA01764423E1EBB7" Guid="{8F619F2F-A83A-4B76-986E-7B10826E0EEB}">
-                <File Id="filC65F1E9916A7F8ADC2E07A192FBC5E48" KeyPath="yes" Source="$(var.SourceDir)\paper\changeset.tmpl" />
-            </Component>
-            <Component Id="cmp2601220A329A40F193104A27B1EDD50F" Directory="dirCCAE13CC8442C655BA01764423E1EBB7" Guid="{2CA3DD6E-1BCD-4ED0-95B3-69BD2C723E8F}">
-                <File Id="fil5883423E0C42B6B99C9E22DAEFAEE97D" KeyPath="yes" Source="$(var.SourceDir)\paper\error.tmpl" />
-            </Component>
-            <Component Id="cmp6D80FA8F113931AFEDE452F25CE759C0" Directory="dirCCAE13CC8442C655BA01764423E1EBB7" Guid="{D5E5A96F-CE04-4FA2-82ED-0BB7AEFFEC4A}">
-                <File Id="filFDEDF9406F5102D8471419766BE46784" KeyPath="yes" Source="$(var.SourceDir)\paper\fileannotate.tmpl" />
-            </Component>
-            <Component Id="cmpF4FCB6A530B40B81345B2FF34128015E" Directory="dirCCAE13CC8442C655BA01764423E1EBB7" Guid="{D3307DF3-96CA-4E8B-95C2-5636EC9A71B2}">
-                <File Id="filCB283DE6BE999D0B91EC88F1F05380BA" KeyPath="yes" Source="$(var.SourceDir)\paper\filediff.tmpl" />
-            </Component>
-            <Component Id="cmp928B9D51180E9D420CFB1EDBAE91A65B" Directory="dirCCAE13CC8442C655BA01764423E1EBB7" Guid="{0157773E-9259-41AA-81A0-B032B8114DB0}">
-                <File Id="fil480C6A2482FB8457C07B0B4982C6B2F3" KeyPath="yes" Source="$(var.SourceDir)\paper\filelog.tmpl" />
-            </Component>
-            <Component Id="cmp7294A4A1FDA1C3BABFE78197A25A369D" Directory="dirCCAE13CC8442C655BA01764423E1EBB7" Guid="{DA8F5765-9DFB-425C-964B-7E6EB38BADB3}">
-                <File Id="filE64DC2B6DF6C1636DC6EB3F0EF988F23" KeyPath="yes" Source="$(var.SourceDir)\paper\filelogentry.tmpl" />
-            </Component>
-            <Component Id="cmp3F36EF7AE95420BC80A34E9C24293791" Directory="dirCCAE13CC8442C655BA01764423E1EBB7" Guid="{AB07E3D8-7276-416C-85A6-06555FF945EA}">
-                <File Id="filCDB52360E0BEB00BEE8776FA76441783" KeyPath="yes" Source="$(var.SourceDir)\paper\filerevision.tmpl" />
-            </Component>
-            <Component Id="cmpCFCDDD5FA4AE732AA051C60F8787554D" Directory="dirCCAE13CC8442C655BA01764423E1EBB7" Guid="{C900C800-0660-4B36-ACA3-BDD3BB783CE1}">
-                <File Id="filEF3D2835F8AB4488B82C88BFE4A69D6E" KeyPath="yes" Source="$(var.SourceDir)\paper\footer.tmpl" />
-            </Component>
-            <Component Id="cmp30B241A606B4AD5E3162C0B2CC09DDF9" Directory="dirCCAE13CC8442C655BA01764423E1EBB7" Guid="{71501492-BCD0-4B2F-B653-83D27CCEFAAD}">
-                <File Id="filE02A4F87D721B4B6B68235AF4A8863A6" KeyPath="yes" Source="$(var.SourceDir)\paper\graph.tmpl" />
-            </Component>
-            <Component Id="cmpB668F2549A35840953001CE413A4C827" Directory="dirCCAE13CC8442C655BA01764423E1EBB7" Guid="{CDE48712-F5C9-4BCC-9790-B2910F87992A}">
-                <File Id="filD235AD247D72C6F35605F9AD3D3ACFE6" KeyPath="yes" Source="$(var.SourceDir)\paper\header.tmpl" />
-            </Component>
-            <Component Id="cmp2E517204CC91CC55F5080C62F8C74CB3" Directory="dirCCAE13CC8442C655BA01764423E1EBB7" Guid="{C2BDB761-525B-436D-946D-8327ADCB0762}">
-                <File Id="filE647110321294198E994033415240DE2" KeyPath="yes" Source="$(var.SourceDir)\paper\index.tmpl" />
-            </Component>
-            <Component Id="cmp1169DE962AAC1A97C8820F60C85C2AB5" Directory="dirCCAE13CC8442C655BA01764423E1EBB7" Guid="{8AA0022C-9AE2-41D8-9F43-8AC426DCF7F0}">
-                <File Id="fil3A3927F8011BABF73AF2BF55FD2B9FD2" KeyPath="yes" Source="$(var.SourceDir)\paper\manifest.tmpl" />
-            </Component>
-            <Component Id="cmp563BA8E85BA6CABCF9AEBD11CB585EBD" Directory="dirCCAE13CC8442C655BA01764423E1EBB7" Guid="{74408780-F9AE-4067-B1F8-0A1B12BB1826}">
-                <File Id="fil1FCC19A801EB82E395B5A8EF7E869C62" KeyPath="yes" Source="$(var.SourceDir)\paper\map" />
-            </Component>
-            <Component Id="cmpA9A7FE93F240404E1161E70007AC6A78" Directory="dirCCAE13CC8442C655BA01764423E1EBB7" Guid="{CAE40619-B777-4C7A-8622-CB2DD6756FAA}">
-                <File Id="filFEBD530E5D4F4F2FD23A9E746297721D" KeyPath="yes" Source="$(var.SourceDir)\paper\notfound.tmpl" />
-            </Component>
-            <Component Id="cmpBA354AABF9A7304F201B7C71121A7900" Directory="dirCCAE13CC8442C655BA01764423E1EBB7" Guid="{23095279-8206-46CB-82E4-AFC007E16C63}">
-                <File Id="fil9F42800F509E8B8E019992B77410F683" KeyPath="yes" Source="$(var.SourceDir)\paper\search.tmpl" />
-            </Component>
-            <Component Id="cmp3AB3B632EBF9F9FD18D38605C343A6B0" Directory="dirCCAE13CC8442C655BA01764423E1EBB7" Guid="{107E31F0-B7AB-4757-A1F6-86C17E8C384B}">
-                <File Id="filD59540CF5AFFFD872F212B2B1AE6212A" KeyPath="yes" Source="$(var.SourceDir)\paper\shortlog.tmpl" />
-            </Component>
-            <Component Id="cmpB3F6B93705B00E2E3B0459048506D283" Directory="dirCCAE13CC8442C655BA01764423E1EBB7" Guid="{2F3B2692-5B58-40F8-AE29-844BA58FB312}">
-                <File Id="fil03DA9AB1567E165864A87437FEE91FB8" KeyPath="yes" Source="$(var.SourceDir)\paper\shortlogentry.tmpl" />
-            </Component>
-            <Component Id="cmpEF4594F7D285174D5A356ADEAAFC61ED" Directory="dirCCAE13CC8442C655BA01764423E1EBB7" Guid="{1BE60A48-7183-4886-BC75-3CFF6C51EC3F}">
-                <File Id="fil671A5C071B2BE506FA431651133EFE0A" KeyPath="yes" Source="$(var.SourceDir)\paper\tags.tmpl" />
-            </Component>
-            <Component Id="cmpB25518BB895E3CB4186909EBE6E99C4C" Directory="dir10F9FCD5760425E499FA92F2CAA7A3EA" Guid="{DBB01FA1-EFC7-42E3-81F2-190C060DC035}">
-                <File Id="fil475FD65FC1DCA47748FF999739657468" KeyPath="yes" Source="$(var.SourceDir)\raw\changeset.tmpl" />
-            </Component>
-            <Component Id="cmp17DC05518B1190BEEF5761C10C71854A" Directory="dir10F9FCD5760425E499FA92F2CAA7A3EA" Guid="{4501B072-4375-4458-94C1-2C4E9E991ACD}">
-                <File Id="filFA9899D1B1C1E72B406307FDB9AF7BAF" KeyPath="yes" Source="$(var.SourceDir)\raw\error.tmpl" />
-            </Component>
-            <Component Id="cmpECA65D83D6634896FDB8534E4175FD4F" Directory="dir10F9FCD5760425E499FA92F2CAA7A3EA" Guid="{747870B2-1590-41D5-9112-EB5FFBF50796}">
-                <File Id="fil3CDE49640C240CF6C2C4E1660F904DE9" KeyPath="yes" Source="$(var.SourceDir)\raw\fileannotate.tmpl" />
-            </Component>
-            <Component Id="cmp20CF2D57316DC85D6C9A5B3475F84E80" Directory="dir10F9FCD5760425E499FA92F2CAA7A3EA" Guid="{01ACEDCC-BACF-4D06-B875-0520723B9D37}">
-                <File Id="fil988220F2BAD1CE4CBC544A29C02E82E6" KeyPath="yes" Source="$(var.SourceDir)\raw\filediff.tmpl" />
-            </Component>
-            <Component Id="cmp43DB97D87FF0A11266474A5725C84AC1" Directory="dir10F9FCD5760425E499FA92F2CAA7A3EA" Guid="{CBAFB505-70F0-40BD-9415-AAE3C3FE5C88}">
-                <File Id="fil5066029ABD205C7759437E120CB7018C" KeyPath="yes" Source="$(var.SourceDir)\raw\index.tmpl" />
-            </Component>
-            <Component Id="cmp0C3504452BA0E5A32AE919D1FB100BD3" Directory="dir10F9FCD5760425E499FA92F2CAA7A3EA" Guid="{2EBF0786-F18F-4787-9863-4075D16CAB8F}">
-                <File Id="filAAC49A49F4D6E3A6EAB4EDE1EE2A5808" KeyPath="yes" Source="$(var.SourceDir)\raw\manifest.tmpl" />
-            </Component>
-            <Component Id="cmpE610EB581D7A11C798F107E00759EE30" Directory="dir10F9FCD5760425E499FA92F2CAA7A3EA" Guid="{8834AC2E-11C2-4890-A49B-59BD5CB34953}">
-                <File Id="fil985E1967B655AE5DA8779D2A8E69D986" KeyPath="yes" Source="$(var.SourceDir)\raw\map" />
-            </Component>
-            <Component Id="cmp708C16629B8102ED107B6C79265E1A61" Directory="dir10F9FCD5760425E499FA92F2CAA7A3EA" Guid="{C78C08CA-6F0D-4E00-ADDF-94DA6BFD385A}">
-                <File Id="fil52C7F355B2B8B57D8D8D26F373EED4A4" KeyPath="yes" Source="$(var.SourceDir)\raw\notfound.tmpl" />
-            </Component>
-            <Component Id="cmpEED23BA7882C00E45C04648CCF07C72A" Directory="dirCB380721FE38FED97C74A9E48945B5BC" Guid="{6AFE12A7-D858-4D04-A263-AF21890783F2}">
-                <File Id="fil38EF6BFECB3EA61C18AD8510C540E030" KeyPath="yes" Source="$(var.SourceDir)\rss\changelog.tmpl" />
-            </Component>
-            <Component Id="cmp9293236C7475213E8741C193885BC370" Directory="dirCB380721FE38FED97C74A9E48945B5BC" Guid="{FF79D239-640A-4337-8DC8-C7710DCF6952}">
-                <File Id="fil124495614FA234F165FDFAFB5FCC8B41" KeyPath="yes" Source="$(var.SourceDir)\rss\changelogentry.tmpl" />
-            </Component>
-            <Component Id="cmpF300C87CBE61D8E4F9139A655CC77F2A" Directory="dirCB380721FE38FED97C74A9E48945B5BC" Guid="{76C2B1FF-C1F8-49FC-BEC7-8689FB2676D7}">
-                <File Id="fil975AA04A3938C6B3FA67DE73AD8D8A62" KeyPath="yes" Source="$(var.SourceDir)\rss\error.tmpl" />
-            </Component>
-            <Component Id="cmp3EFC01264101EB280A920E7543FC6BA7" Directory="dirCB380721FE38FED97C74A9E48945B5BC" Guid="{7A44A6EA-6ECB-4235-8EFC-0EFEB2F82E1C}">
-                <File Id="fil15C5D0A18D58A500E90E198CD25799D2" KeyPath="yes" Source="$(var.SourceDir)\rss\filelog.tmpl" />
-            </Component>
-            <Component Id="cmpE86BFF1FA4FE20689AD82969DFD9EF04" Directory="dirCB380721FE38FED97C74A9E48945B5BC" Guid="{F3DE2D70-217D-4DDB-A8F8-C973AAF85D06}">
-                <File Id="fil4516B6122DFF1FAD28410E4F68D37FB4" KeyPath="yes" Source="$(var.SourceDir)\rss\filelogentry.tmpl" />
-            </Component>
-            <Component Id="cmpA55F157640DFAA982E2410BFF396F838" Directory="dirCB380721FE38FED97C74A9E48945B5BC" Guid="{4A467D62-3231-4A5C-B455-EF3C962B1F46}">
-                <File Id="fil0F3AAA97082D3FB22338711F77A7C8C4" KeyPath="yes" Source="$(var.SourceDir)\rss\header.tmpl" />
-            </Component>
-            <Component Id="cmp69196B3D4F0DAC971FC2D765F781B671" Directory="dirCB380721FE38FED97C74A9E48945B5BC" Guid="{26329996-79F4-4E76-8553-1BDFC0873639}">
-                <File Id="filA937974673590803746240DB3A232A66" KeyPath="yes" Source="$(var.SourceDir)\rss\map" />
-            </Component>
-            <Component Id="cmpC696B6493CA1B63C192B073B0D728564" Directory="dirCB380721FE38FED97C74A9E48945B5BC" Guid="{E0719339-E59A-428B-8600-845314285599}">
-                <File Id="filAA576F47CA9747367AF8C4528FD8A217" KeyPath="yes" Source="$(var.SourceDir)\rss\tagentry.tmpl" />
-            </Component>
-            <Component Id="cmp47B99ED43B673977AE8606E3451D8674" Directory="dirCB380721FE38FED97C74A9E48945B5BC" Guid="{F785D87D-0BE0-41C5-BF47-4A7B23CE7BB1}">
-                <File Id="filF3D72D7B79A517201EA2B568C64C19C8" KeyPath="yes" Source="$(var.SourceDir)\rss\tags.tmpl" />
-            </Component>
-            <Component Id="cmp8C4153B109FF248C582A307E7575BDC7" Directory="dirB8FE74E96715E770736FEAFA391ABF15" Guid="{2C281D9F-09BD-43C7-BEB8-89F63217D01E}">
-                <File Id="fil45D9BD7CD3073F10FED6A9FDD57C6303" KeyPath="yes" Source="$(var.SourceDir)\spartan\branches.tmpl" />
-            </Component>
-            <Component Id="cmp258992A63D8561862F924B2F445F480E" Directory="dirB8FE74E96715E770736FEAFA391ABF15" Guid="{9640D202-3867-49AF-B648-6F8B515376FD}">
-                <File Id="filDCE126EE702579CD325AFA89C6040B3D" KeyPath="yes" Source="$(var.SourceDir)\spartan\changelog.tmpl" />
-            </Component>
-            <Component Id="cmpCBC90D7649B7D877F5A4BBAD723F7F2F" Directory="dirB8FE74E96715E770736FEAFA391ABF15" Guid="{DF2B7556-BBFB-489D-908B-6220191EC620}">
-                <File Id="fil9FBF8720F94C113556DDE1C97DF9DDE3" KeyPath="yes" Source="$(var.SourceDir)\spartan\changelogentry.tmpl" />
-            </Component>
-            <Component Id="cmp983EB84EE3C3FA79C2B4B0E126900FF8" Directory="dirB8FE74E96715E770736FEAFA391ABF15" Guid="{78ED06E6-41D9-4598-9697-2142016885D7}">
-                <File Id="filE54688ED547D1CF7DF8EB2E53E47C1C0" KeyPath="yes" Source="$(var.SourceDir)\spartan\changeset.tmpl" />
-            </Component>
-            <Component Id="cmp87B16F191F9EE8A923BD50FFAB5AF8A1" Directory="dirB8FE74E96715E770736FEAFA391ABF15" Guid="{0002AF55-6A71-4F51-8C50-B39F6215F2B0}">
-                <File Id="filCF590744894C82D12672745CA8694FDA" KeyPath="yes" Source="$(var.SourceDir)\spartan\error.tmpl" />
-            </Component>
-            <Component Id="cmp24FC541496FA7F2BB64E40CE1881E9BD" Directory="dirB8FE74E96715E770736FEAFA391ABF15" Guid="{F2E08FF3-744B-4D45-AFA1-5C33A1604F91}">
-                <File Id="filD8A4D1634CFB34AE2A52DD98EFE22B29" KeyPath="yes" Source="$(var.SourceDir)\spartan\fileannotate.tmpl" />
-            </Component>
-            <Component Id="cmp942F916336F4CBA936A065A28D3EADD3" Directory="dirB8FE74E96715E770736FEAFA391ABF15" Guid="{905E4307-E9B4-45E3-AE1C-E7D01A4120F4}">
-                <File Id="fil568DC2C47109CC77F23F9593A16B44F0" KeyPath="yes" Source="$(var.SourceDir)\spartan\filediff.tmpl" />
-            </Component>
-            <Component Id="cmp597CDAFF17F11DA3FED725E5829DD73C" Directory="dirB8FE74E96715E770736FEAFA391ABF15" Guid="{84FBA0CE-7E2C-4504-94D5-9C383DA4BFDE}">
-                <File Id="fil580676C3E18FDF8919786C15B92FDBD2" KeyPath="yes" Source="$(var.SourceDir)\spartan\filelog.tmpl" />
-            </Component>
-            <Component Id="cmpC4ACD09B8854124364CBB8CDAD38FB08" Directory="dirB8FE74E96715E770736FEAFA391ABF15" Guid="{0D0E0B26-EA07-4ADE-96F3-3F30DBC4AA9D}">
-                <File Id="filC736FBCC66C5D91989FC91C2E5931182" KeyPath="yes" Source="$(var.SourceDir)\spartan\filelogentry.tmpl" />
-            </Component>
-            <Component Id="cmpEB22906EBBA0857AECD19E74CE893749" Directory="dirB8FE74E96715E770736FEAFA391ABF15" Guid="{A588ED57-CDFE-4316-AF15-C81E40A67343}">
-                <File Id="filDA153719D47EE0165DB1A908ECF1D9CF" KeyPath="yes" Source="$(var.SourceDir)\spartan\filerevision.tmpl" />
-            </Component>
-            <Component Id="cmp30475C52A92194CBC64BED509F7D7B64" Directory="dirB8FE74E96715E770736FEAFA391ABF15" Guid="{B795B3F2-394E-4F23-B0B7-BD6191E17714}">
-                <File Id="filBAF07E4ACAECCC417DCF35B01D053357" KeyPath="yes" Source="$(var.SourceDir)\spartan\footer.tmpl" />
-            </Component>
-            <Component Id="cmp679ECC15E459B542AA894CD7F0B3690D" Directory="dirB8FE74E96715E770736FEAFA391ABF15" Guid="{82E57B98-1C5F-43D5-81FF-7952EFAAAB62}">
-                <File Id="filABBF8D15F4DE387F2648004FAB23B078" KeyPath="yes" Source="$(var.SourceDir)\spartan\graph.tmpl" />
-            </Component>
-            <Component Id="cmp31A95170275A0F3CEA2EFA0B3EE699EA" Directory="dirB8FE74E96715E770736FEAFA391ABF15" Guid="{382BA9AC-67BC-44BA-8004-F72EFEB68007}">
-                <File Id="fil69E45EBB4E4C69CD7482C487DF64C3D8" KeyPath="yes" Source="$(var.SourceDir)\spartan\header.tmpl" />
-            </Component>
-            <Component Id="cmp4363ACEAD4BD8845B0C9AC2D03465A5E" Directory="dirB8FE74E96715E770736FEAFA391ABF15" Guid="{CF8B8556-687B-4E82-BC6B-62A4916A7E4A}">
-                <File Id="fil5FE55A8E4659024B58AA7C8256CA9439" KeyPath="yes" Source="$(var.SourceDir)\spartan\index.tmpl" />
-            </Component>
-            <Component Id="cmp1B77757C5443F6AA7EED502370927E92" Directory="dirB8FE74E96715E770736FEAFA391ABF15" Guid="{0AB066EA-64CF-4434-9752-2E900396EFFF}">
-                <File Id="filE71CF1D4A57966CE89FED594B3D9E430" KeyPath="yes" Source="$(var.SourceDir)\spartan\manifest.tmpl" />
-            </Component>
-            <Component Id="cmp269E53402BD0050DE38109E3BF5C3945" Directory="dirB8FE74E96715E770736FEAFA391ABF15" Guid="{6B03B3A5-49D5-413B-9DA5-A32BA30F88BC}">
-                <File Id="fil9D51DC7A5EB908A1EECA883E06EB8B31" KeyPath="yes" Source="$(var.SourceDir)\spartan\map" />
-            </Component>
-            <Component Id="cmp73F5CB8A13C8C57CD15DB9064BD9E2BF" Directory="dirB8FE74E96715E770736FEAFA391ABF15" Guid="{3B9DB632-BDDC-4DDF-81FD-1DC6751A3467}">
-                <File Id="filE079FF0AA52D0BCCDB9A5B49A80D5504" KeyPath="yes" Source="$(var.SourceDir)\spartan\notfound.tmpl" />
-            </Component>
-            <Component Id="cmpECE54442CE4E6FD27717A8D578125A2B" Directory="dirB8FE74E96715E770736FEAFA391ABF15" Guid="{886E4B52-C284-4493-B2E5-FA35A9CD3ABA}">
-                <File Id="filE14A89B3EA724AAB48354DEE70DF69C8" KeyPath="yes" Source="$(var.SourceDir)\spartan\search.tmpl" />
-            </Component>
-            <Component Id="cmpFF1D26AC267CDED40E1D2AC476D7F09F" Directory="dirB8FE74E96715E770736FEAFA391ABF15" Guid="{6359A1B3-48B2-4092-A7C4-BE53F05870AB}">
-                <File Id="fil868AF4DF25AC25F53793411E9365297D" KeyPath="yes" Source="$(var.SourceDir)\spartan\shortlog.tmpl" />
-            </Component>
-            <Component Id="cmp2D8D54467D34BA5055A5FF2E67254EAD" Directory="dirB8FE74E96715E770736FEAFA391ABF15" Guid="{F26E20E2-7A04-489B-8F83-183D898174DD}">
-                <File Id="filF4ABFCC411E50C0042C1848016EE5327" KeyPath="yes" Source="$(var.SourceDir)\spartan\shortlogentry.tmpl" />
-            </Component>
-            <Component Id="cmp83ECAEFDCC6805EEFC78A54EF1000146" Directory="dirB8FE74E96715E770736FEAFA391ABF15" Guid="{7A021045-DA97-4A34-87AB-0882F071573C}">
-                <File Id="fil1D8DB7506E3BBD7449459C9BAB25CDAD" KeyPath="yes" Source="$(var.SourceDir)\spartan\tags.tmpl" />
-            </Component>
-            <Component Id="cmpBFBB6F3B9C29C43E991077D6BFC33944" Directory="dirC5A30981F5453B69928F61CEC4F6D629" Guid="{5883A510-590E-4ADE-85A7-B94F373B63CA}">
-                <File Id="filF8DE93E9297B5CAE60372749245F15B2" KeyPath="yes" Source="$(var.SourceDir)\static\background.png" />
-            </Component>
-            <Component Id="cmp0F63F938946462583D4DEE74873DC408" Directory="dirC5A30981F5453B69928F61CEC4F6D629" Guid="{A0C70D4C-E2BE-4173-A95F-A2FB690A65D5}">
-                <File Id="fil00A8D7AEA87233FED8A360F2D862572E" KeyPath="yes" Source="$(var.SourceDir)\static\coal-file.png" />
-            </Component>
-            <Component Id="cmpDE70C42580801A22F32CFD04C7EF4CF9" Directory="dirC5A30981F5453B69928F61CEC4F6D629" Guid="{81A48619-3740-4874-83C3-AE58D74E30A6}">
-                <File Id="fil42C97A38CD59CED3713E93E6CBCDBFFE" KeyPath="yes" Source="$(var.SourceDir)\static\coal-folder.png" />
-            </Component>
-            <Component Id="cmpA45BEDD14DCA07C7A92A417386445E25" Directory="dirC5A30981F5453B69928F61CEC4F6D629" Guid="{030E40CB-67A6-4EB5-ACC2-18B14BC31178}">
-                <File Id="filCC692DA67C62144B4AF34F10014F83FD" KeyPath="yes" Source="$(var.SourceDir)\static\excanvas.js" />
-            </Component>
-            <Component Id="cmp72015354E78AA8A481B54F81AD8F9682" Directory="dirC5A30981F5453B69928F61CEC4F6D629" Guid="{894DAD59-0224-4CD1-8984-CBCB1464E44A}">
-                <File Id="fil690EAE877AB9F8C70C93E471115C52F2" KeyPath="yes" Source="$(var.SourceDir)\static\graph.js" />
-            </Component>
-            <Component Id="cmpB467CD481FE78A9CD052183FE5F3D0C6" Directory="dirC5A30981F5453B69928F61CEC4F6D629" Guid="{DC08B50D-F37D-42FF-A382-037D7DE80008}">
-                <File Id="fil28C1A9E02AE19A9988E8F1BAFDBEAD91" KeyPath="yes" Source="$(var.SourceDir)\static\hgicon.png" />
-            </Component>
-            <Component Id="cmp6B247043D5188A72BAFBCC81DB10B97C" Directory="dirC5A30981F5453B69928F61CEC4F6D629" Guid="{4EC7856F-BA03-4DE8-A84B-7DCF12A9393C}">
-                <File Id="fil8860DD8D5DA074A5BE9F314F442285EC" KeyPath="yes" Source="$(var.SourceDir)\static\hglogo.png" />
-            </Component>
-            <Component Id="cmp4F8B4BF7E8F4DDF9C224F45A94BAE0AA" Directory="dirC5A30981F5453B69928F61CEC4F6D629" Guid="{2363D738-3F01-4C02-95A1-AF17841FC087}">
-                <File Id="filA6C8F4FB422C911ABE0F82752E383E99" KeyPath="yes" Source="$(var.SourceDir)\static\style-coal.css" />
-            </Component>
-            <Component Id="cmpF69080B6DF1E2AA23990F61B4ED884EB" Directory="dirC5A30981F5453B69928F61CEC4F6D629" Guid="{5ED9E813-DE59-45C9-9CCB-1A3248E348E5}">
-                <File Id="fil5078818944548B0CCE1C317796CF7D4A" KeyPath="yes" Source="$(var.SourceDir)\static\style-gitweb.css" />
-            </Component>
-            <Component Id="cmp39B7B1D88ED5B2E8E878FEF7FB7D0F89" Directory="dirC5A30981F5453B69928F61CEC4F6D629" Guid="{5F49B8D0-F497-4848-B95D-040BE4CC3296}">
-                <File Id="filB788208E124431C056B605A46EC7A643" KeyPath="yes" Source="$(var.SourceDir)\static\style-monoblue.css" />
-            </Component>
-            <Component Id="cmp08A2992654457D67292FF9C2B96B5172" Directory="dirC5A30981F5453B69928F61CEC4F6D629" Guid="{474A04D3-84A1-435F-99DB-21BA3079CE55}">
-                <File Id="filE567FA56A8009FB9853EA69E01A0A410" KeyPath="yes" Source="$(var.SourceDir)\static\style-paper.css" />
-            </Component>
-            <Component Id="cmpDABBFD12710BF06B024350932B45E606" Directory="dirC5A30981F5453B69928F61CEC4F6D629" Guid="{54BB78EA-5B06-42EA-8F30-9C5277A8590E}">
-                <File Id="filE018265028110198DEF0E278341C9EB3" KeyPath="yes" Source="$(var.SourceDir)\static\style.css" />
-            </Component>
-        </ComponentGroup>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="INSTALLDIR">
-            <Directory Id="dirBFB9D3FD33CE2C696D390C94E4E1B4D8" Name="templates" />
-        </DirectoryRef>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirA4D7AC0F636AD49029D4D19861392983" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirC5A30981F5453B69928F61CEC4F6D629" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir35F8598B197DFC5580317F5E7C2E9AE9" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirA4D7AC0F636AD49029D4D19861392983" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir10F9FCD5760425E499FA92F2CAA7A3EA" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirC5A30981F5453B69928F61CEC4F6D629" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirA4D7AC0F636AD49029D4D19861392983" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCCAE13CC8442C655BA01764423E1EBB7" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir10F9FCD5760425E499FA92F2CAA7A3EA" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirA4D7AC0F636AD49029D4D19861392983" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirA4D7AC0F636AD49029D4D19861392983" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirB8FE74E96715E770736FEAFA391ABF15" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir3D22B249045A1473460D0D5D104478F2" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir3D22B249045A1473460D0D5D104478F2" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir35F8598B197DFC5580317F5E7C2E9AE9" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir3D22B249045A1473460D0D5D104478F2" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir10F9FCD5760425E499FA92F2CAA7A3EA" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirBFB9D3FD33CE2C696D390C94E4E1B4D8" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirB8FE74E96715E770736FEAFA391ABF15" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirB8FE74E96715E770736FEAFA391ABF15" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCCAE13CC8442C655BA01764423E1EBB7" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirB8FE74E96715E770736FEAFA391ABF15" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirB8FE74E96715E770736FEAFA391ABF15" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCCAE13CC8442C655BA01764423E1EBB7" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirA4D7AC0F636AD49029D4D19861392983" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirB8FE74E96715E770736FEAFA391ABF15" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCCAE13CC8442C655BA01764423E1EBB7" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir3D22B249045A1473460D0D5D104478F2" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirB8FE74E96715E770736FEAFA391ABF15" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirC5A30981F5453B69928F61CEC4F6D629" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCCAE13CC8442C655BA01764423E1EBB7" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirBFB9D3FD33CE2C696D390C94E4E1B4D8" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCB380721FE38FED97C74A9E48945B5BC" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCCAE13CC8442C655BA01764423E1EBB7" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir3D22B249045A1473460D0D5D104478F2" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirB8FE74E96715E770736FEAFA391ABF15" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir10F9FCD5760425E499FA92F2CAA7A3EA" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCB380721FE38FED97C74A9E48945B5BC" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir35F8598B197DFC5580317F5E7C2E9AE9" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirA4D7AC0F636AD49029D4D19861392983" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir3D22B249045A1473460D0D5D104478F2" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir3D22B249045A1473460D0D5D104478F2" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir3D22B249045A1473460D0D5D104478F2" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirC5A30981F5453B69928F61CEC4F6D629" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCCAE13CC8442C655BA01764423E1EBB7" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirB8FE74E96715E770736FEAFA391ABF15" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirA4D7AC0F636AD49029D4D19861392983" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirB8FE74E96715E770736FEAFA391ABF15" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCB380721FE38FED97C74A9E48945B5BC" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCCAE13CC8442C655BA01764423E1EBB7" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirC5A30981F5453B69928F61CEC4F6D629" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir3D22B249045A1473460D0D5D104478F2" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCCAE13CC8442C655BA01764423E1EBB7" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir10F9FCD5760425E499FA92F2CAA7A3EA" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirC5A30981F5453B69928F61CEC4F6D629" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCCAE13CC8442C655BA01764423E1EBB7" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir3D22B249045A1473460D0D5D104478F2" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirB8FE74E96715E770736FEAFA391ABF15" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir3D22B249045A1473460D0D5D104478F2" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirA4D7AC0F636AD49029D4D19861392983" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirA4D7AC0F636AD49029D4D19861392983" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirA4D7AC0F636AD49029D4D19861392983" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirA4D7AC0F636AD49029D4D19861392983" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir3D22B249045A1473460D0D5D104478F2" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCCAE13CC8442C655BA01764423E1EBB7" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirB8FE74E96715E770736FEAFA391ABF15" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir35F8598B197DFC5580317F5E7C2E9AE9" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirB8FE74E96715E770736FEAFA391ABF15" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirA4D7AC0F636AD49029D4D19861392983" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirB8FE74E96715E770736FEAFA391ABF15" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCCAE13CC8442C655BA01764423E1EBB7" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCB380721FE38FED97C74A9E48945B5BC" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirB8FE74E96715E770736FEAFA391ABF15" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirB8FE74E96715E770736FEAFA391ABF15" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir3D22B249045A1473460D0D5D104478F2" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir35F8598B197DFC5580317F5E7C2E9AE9" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirC5A30981F5453B69928F61CEC4F6D629" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCB380721FE38FED97C74A9E48945B5BC" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirBFB9D3FD33CE2C696D390C94E4E1B4D8" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCCAE13CC8442C655BA01764423E1EBB7" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir3D22B249045A1473460D0D5D104478F2" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir3D22B249045A1473460D0D5D104478F2" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir35F8598B197DFC5580317F5E7C2E9AE9" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir10F9FCD5760425E499FA92F2CAA7A3EA" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCCAE13CC8442C655BA01764423E1EBB7" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirC5A30981F5453B69928F61CEC4F6D629" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCCAE13CC8442C655BA01764423E1EBB7" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCCAE13CC8442C655BA01764423E1EBB7" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirC5A30981F5453B69928F61CEC4F6D629" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir2EDFFCA56732C858816EF19F127E8D0F" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirB8FE74E96715E770736FEAFA391ABF15" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir3D22B249045A1473460D0D5D104478F2" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCB380721FE38FED97C74A9E48945B5BC" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirBFB9D3FD33CE2C696D390C94E4E1B4D8" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirA4D7AC0F636AD49029D4D19861392983" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirB8FE74E96715E770736FEAFA391ABF15" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCCAE13CC8442C655BA01764423E1EBB7" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir35F8598B197DFC5580317F5E7C2E9AE9" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirA4D7AC0F636AD49029D4D19861392983" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir3D22B249045A1473460D0D5D104478F2" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirC5A30981F5453B69928F61CEC4F6D629" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirA4D7AC0F636AD49029D4D19861392983" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirBFB9D3FD33CE2C696D390C94E4E1B4D8" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirC5A30981F5453B69928F61CEC4F6D629" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirA4D7AC0F636AD49029D4D19861392983" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirA4D7AC0F636AD49029D4D19861392983" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir10F9FCD5760425E499FA92F2CAA7A3EA" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCB380721FE38FED97C74A9E48945B5BC" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir35F8598B197DFC5580317F5E7C2E9AE9" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirB8FE74E96715E770736FEAFA391ABF15" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir10F9FCD5760425E499FA92F2CAA7A3EA" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirB8FE74E96715E770736FEAFA391ABF15" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir3D22B249045A1473460D0D5D104478F2" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirA4D7AC0F636AD49029D4D19861392983" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCB380721FE38FED97C74A9E48945B5BC" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir3D22B249045A1473460D0D5D104478F2" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCCAE13CC8442C655BA01764423E1EBB7" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCB380721FE38FED97C74A9E48945B5BC" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir3D22B249045A1473460D0D5D104478F2" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirCCAE13CC8442C655BA01764423E1EBB7" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dir2EDFFCA56732C858816EF19F127E8D0F" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirC5A30981F5453B69928F61CEC4F6D629" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirA4D7AC0F636AD49029D4D19861392983" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirB8FE74E96715E770736FEAFA391ABF15" />
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirBFB9D3FD33CE2C696D390C94E4E1B4D8">
-            <Directory Id="dir10F9FCD5760425E499FA92F2CAA7A3EA" Name="raw" />
-        </DirectoryRef>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirBFB9D3FD33CE2C696D390C94E4E1B4D8">
-            <Directory Id="dir2EDFFCA56732C858816EF19F127E8D0F" Name="coal" />
-        </DirectoryRef>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirBFB9D3FD33CE2C696D390C94E4E1B4D8">
-            <Directory Id="dir35F8598B197DFC5580317F5E7C2E9AE9" Name="atom" />
-        </DirectoryRef>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirBFB9D3FD33CE2C696D390C94E4E1B4D8">
-            <Directory Id="dir3D22B249045A1473460D0D5D104478F2" Name="gitweb" />
-        </DirectoryRef>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirBFB9D3FD33CE2C696D390C94E4E1B4D8">
-            <Directory Id="dirA4D7AC0F636AD49029D4D19861392983" Name="monoblue" />
-        </DirectoryRef>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirBFB9D3FD33CE2C696D390C94E4E1B4D8">
-            <Directory Id="dirB8FE74E96715E770736FEAFA391ABF15" Name="spartan" />
-        </DirectoryRef>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirBFB9D3FD33CE2C696D390C94E4E1B4D8">
-            <Directory Id="dirC5A30981F5453B69928F61CEC4F6D629" Name="static" />
-        </DirectoryRef>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirBFB9D3FD33CE2C696D390C94E4E1B4D8">
-            <Directory Id="dirCB380721FE38FED97C74A9E48945B5BC" Name="rss" />
-        </DirectoryRef>
-    </Fragment>
-    <Fragment>
-        <DirectoryRef Id="dirBFB9D3FD33CE2C696D390C94E4E1B4D8">
-            <Directory Id="dirCCAE13CC8442C655BA01764423E1EBB7" Name="paper" />
-        </DirectoryRef>
-    </Fragment>
-</Wix>
+
+  <?include guids.wxi ?>
+
+  <Fragment>
+    <ComponentGroup Id="templatesFolder">
+
+      <ComponentRef Id="templates.root" />
+
+      <ComponentRef Id="templates.atom" />
+      <ComponentRef Id="templates.coal" />
+      <ComponentRef Id="templates.gitweb" />
+      <ComponentRef Id="templates.monoblue" />
+      <ComponentRef Id="templates.paper" />
+      <ComponentRef Id="templates.raw" />
+      <ComponentRef Id="templates.rss" />
+      <ComponentRef Id="templates.spartan" />
+      <ComponentRef Id="templates.static" />
+
+    </ComponentGroup>
+  </Fragment>
+
+  <Fragment>
+    <DirectoryRef Id="INSTALLDIR">
+
+      <Directory Id="templatesdir" Name="templates" FileSource="$(var.SourceDir)">
+
+        <Component Id="templates.root" Guid="$(var.templates.root.guid)">
+          <File Name="map-cmdline.changelog" KeyPath="yes" />
+          <File Name="map-cmdline.compact" />
+          <File Name="map-cmdline.default" />
+          <File Name="map-cmdline.xml" />
+          <File Name="template-vars.txt" />
+        </Component>
+
+        <Directory Id="templates.atomdir" Name="atom">
+          <Component Id="templates.atom" Guid="$(var.templates.atom.guid)">
+            <File Id="atom.changelog.tmpl"      Name="changelog.tmpl" KeyPath="yes" />
+            <File Id="atom.changelogentry.tmpl" Name="changelogentry.tmpl" />
+            <File Id="atom.error.tmpl"          Name="error.tmpl" />
+            <File Id="atom.filelog.tmpl"        Name="filelog.tmpl" />
+            <File Id="atom.header.tmpl"         Name="header.tmpl" />
+            <File Id="atom.map"                 Name="map" />
+            <File Id="atom.tagentry.tmpl"       Name="tagentry.tmpl" />
+            <File Id="atom.tags.tmpl"           Name="tags.tmpl" />
+          </Component>
+        </Directory>
+
+        <Directory Id="templates.coaldir" Name="coal">
+          <Component Id="templates.coal" Guid="$(var.templates.coal.guid)">
+            <File Id="coal.header.tmpl" Name="header.tmpl" KeyPath="yes" />
+            <File Id="coal.map"         Name="map" />
+          </Component>
+        </Directory>
+
+        <Directory Id="templates.gitwebdir" Name="gitweb">
+          <Component Id="templates.gitweb" Guid="$(var.templates.gitweb.guid)">
+            <File Id="gitweb.branches.tmpl"       Name="branches.tmpl" KeyPath="yes" />
+            <File Id="gitweb.changelog.tmpl"      Name="changelog.tmpl" />
+            <File Id="gitweb.changelogentry.tmpl" Name="changelogentry.tmpl" />
+            <File Id="gitweb.changeset.tmpl"      Name="changeset.tmpl" />
+            <File Id="gitweb.error.tmpl"          Name="error.tmpl" />
+            <File Id="gitweb.fileannotate.tmpl"   Name="fileannotate.tmpl" />
+            <File Id="gitweb.filediff.tmpl"       Name="filediff.tmpl" />
+            <File Id="gitweb.filelog.tmpl"        Name="filelog.tmpl" />
+            <File Id="gitweb.filerevision.tmpl"   Name="filerevision.tmpl" />
+            <File Id="gitweb.footer.tmpl"         Name="footer.tmpl" />
+            <File Id="gitweb.graph.tmpl"          Name="graph.tmpl" />
+            <File Id="gitweb.header.tmpl"         Name="header.tmpl" />
+            <File Id="gitweb.index.tmpl"          Name="index.tmpl" />
+            <File Id="gitweb.manifest.tmpl"       Name="manifest.tmpl" />
+            <File Id="gitweb.map"                 Name="map" />
+            <File Id="gitweb.notfound.tmpl"       Name="notfound.tmpl" />
+            <File Id="gitweb.search.tmpl"         Name="search.tmpl" />
+            <File Id="gitweb.shortlog.tmpl"       Name="shortlog.tmpl" />
+            <File Id="gitweb.summary.tmpl"        Name="summary.tmpl" />
+            <File Id="gitweb.tags.tmpl"           Name="tags.tmpl" />
+          </Component>
+        </Directory>
+
+        <Directory Id="templates.monobluedir" Name="monoblue">
+          <Component Id="templates.monoblue" Guid="$(var.templates.monoblue.guid)">
+            <File Id="monoblue.branches.tmpl"       Name="branches.tmpl" KeyPath="yes" />
+            <File Id="monoblue.changelog.tmpl"      Name="changelog.tmpl" />
+            <File Id="monoblue.changelogentry.tmpl" Name="changelogentry.tmpl" />
+            <File Id="monoblue.changeset.tmpl"      Name="changeset.tmpl" />
+            <File Id="monoblue.error.tmpl"          Name="error.tmpl" />
+            <File Id="monoblue.fileannotate.tmpl"   Name="fileannotate.tmpl" />
+            <File Id="monoblue.filediff.tmpl"       Name="filediff.tmpl" />
+            <File Id="monoblue.filelog.tmpl"        Name="filelog.tmpl" />
+            <File Id="monoblue.filerevision.tmpl"   Name="filerevision.tmpl" />
+            <File Id="monoblue.footer.tmpl"         Name="footer.tmpl" />
+            <File Id="monoblue.graph.tmpl"          Name="graph.tmpl" />
+            <File Id="monoblue.header.tmpl"         Name="header.tmpl" />
+            <File Id="monoblue.index.tmpl"          Name="index.tmpl" />
+            <File Id="monoblue.manifest.tmpl"       Name="manifest.tmpl" />
+            <File Id="monoblue.map"                 Name="map" />
+            <File Id="monoblue.notfound.tmpl"       Name="notfound.tmpl" />
+            <File Id="monoblue.search.tmpl"         Name="search.tmpl" />
+            <File Id="monoblue.shortlog.tmpl"       Name="shortlog.tmpl" />
+            <File Id="monoblue.summary.tmpl"        Name="summary.tmpl" />
+            <File Id="monoblue.tags.tmpl"           Name="tags.tmpl" />
+          </Component>
+        </Directory>
+
+        <Directory Id="templates.paperdir" Name="paper">
+          <Component Id="templates.paper" Guid="$(var.templates.paper.guid)">
+            <File Id="paper.branches.tmpl"      Name="branches.tmpl" KeyPath="yes" />
+            <File Id="paper.changeset.tmpl"     Name="changeset.tmpl" />
+            <File Id="paper.error.tmpl"         Name="error.tmpl" />
+            <File Id="paper.fileannotate.tmpl"  Name="fileannotate.tmpl" />
+            <File Id="paper.filediff.tmpl"      Name="filediff.tmpl" />
+            <File Id="paper.filelog.tmpl"       Name="filelog.tmpl" />
+            <File Id="paper.filelogentry.tmpl"  Name="filelogentry.tmpl" />
+            <File Id="paper.filerevision.tmpl"  Name="filerevision.tmpl" />
+            <File Id="paper.footer.tmpl"        Name="footer.tmpl" />
+            <File Id="paper.graph.tmpl"         Name="graph.tmpl" />
+            <File Id="paper.header.tmpl"        Name="header.tmpl" />
+            <File Id="paper.index.tmpl"         Name="index.tmpl" />
+            <File Id="paper.manifest.tmpl"      Name="manifest.tmpl" />
+            <File Id="paper.map"                Name="map" />
+            <File Id="paper.notfound.tmpl"      Name="notfound.tmpl" />
+            <File Id="paper.search.tmpl"        Name="search.tmpl" />
+            <File Id="paper.shortlog.tmpl"      Name="shortlog.tmpl" />
+            <File Id="paper.shortlogentry.tmpl" Name="shortlogentry.tmpl" />
+            <File Id="paper.tags.tmpl"          Name="tags.tmpl" />
+          </Component>
+        </Directory>
+
+        <Directory Id="templates.rawdir" Name="raw">
+          <Component Id="templates.raw" Guid="$(var.templates.raw.guid)">
+            <File Id="raw.changeset.tmpl"    Name="changeset.tmpl" KeyPath="yes" />
+            <File Id="raw.error.tmpl"        Name="error.tmpl" />
+            <File Id="raw.fileannotate.tmpl" Name="fileannotate.tmpl" />
+            <File Id="raw.filediff.tmpl"     Name="filediff.tmpl" />
+            <File Id="raw.index.tmpl"        Name="index.tmpl" />
+            <File Id="raw.manifest.tmpl"     Name="manifest.tmpl" />
+            <File Id="raw.map"               Name="map" />
+            <File Id="raw.notfound.tmpl"     Name="notfound.tmpl" />
+          </Component>
+        </Directory>
+
+        <Directory Id="templates.rssdir" Name="rss">
+          <Component Id="templates.rss" Guid="$(var.templates.rss.guid)">
+            <File Id="rss.changelog.tmpl"      Name="changelog.tmpl" KeyPath="yes" />
+            <File Id="rss.changelogentry.tmpl" Name="changelogentry.tmpl" />
+            <File Id="rss.error.tmpl"          Name="error.tmpl" />
+            <File Id="rss.filelog.tmpl"        Name="filelog.tmpl" />
+            <File Id="rss.filelogentry.tmpl"   Name="filelogentry.tmpl" />
+            <File Id="rss.header.tmpl"         Name="header.tmpl" />
+            <File Id="rss.map"                 Name="map" />
+            <File Id="rss.tagentry.tmpl"       Name="tagentry.tmpl" />
+            <File Id="rss.tags.tmpl"           Name="tags.tmpl" />
+          </Component>
+        </Directory>
+
+        <Directory Id="templates.spartandir" Name="spartan">
+          <Component Id="templates.spartan" Guid="$(var.templates.spartan.guid)">
+            <File Id="spartan.branches.tmpl"       Name="branches.tmpl" KeyPath="yes" />
+            <File Id="spartan.changelog.tmpl"      Name="changelog.tmpl" />
+            <File Id="spartan.changelogentry.tmpl" Name="changelogentry.tmpl" />
+            <File Id="spartan.changeset.tmpl"      Name="changeset.tmpl" />
+            <File Id="spartan.error.tmpl"          Name="error.tmpl" />
+            <File Id="spartan.fileannotate.tmpl"   Name="fileannotate.tmpl" />
+            <File Id="spartan.filediff.tmpl"       Name="filediff.tmpl" />
+            <File Id="spartan.filelog.tmpl"        Name="filelog.tmpl" />
+            <File Id="spartan.filelogentry.tmpl"   Name="filelogentry.tmpl" />
+            <File Id="spartan.filerevision.tmpl"   Name="filerevision.tmpl" />
+            <File Id="spartan.footer.tmpl"         Name="footer.tmpl" />
+            <File Id="spartan.graph.tmpl"          Name="graph.tmpl" />
+            <File Id="spartan.header.tmpl"         Name="header.tmpl" />
+            <File Id="spartan.index.tmpl"          Name="index.tmpl" />
+            <File Id="spartan.manifest.tmpl"       Name="manifest.tmpl" />
+            <File Id="spartan.map"                 Name="map" />
+            <File Id="spartan.notfound.tmpl"       Name="notfound.tmpl" />
+            <File Id="spartan.search.tmpl"         Name="search.tmpl" />
+            <File Id="spartan.shortlog.tmpl"       Name="shortlog.tmpl" />
+            <File Id="spartan.shortlogentry.tmpl"  Name="shortlogentry.tmpl" />
+            <File Id="spartan.tags.tmpl"           Name="tags.tmpl" />
+          </Component>
+        </Directory>
+
+        <Directory Id="templates.staticdir" Name="static">
+          <Component Id="templates.static" Guid="$(var.templates.static.guid)">
+            <File Id="static.background.png"     Name="background.png" KeyPath="yes" />
+            <File Id="static.coal.file.png"      Name="coal-file.png" />
+            <File Id="static.coal.folder.png"    Name="coal-folder.png" />
+            <File Id="static.excanvas.js"        Name="excanvas.js" />
+            <File Id="static.graph.js"           Name="graph.js" />
+            <File Id="static.hgicon.png"         Name="hgicon.png" />
+            <File Id="static.hglogo.png"         Name="hglogo.png" />
+            <File Id="static.style.coal.css"     Name="style-coal.css" />
+            <File Id="static.style.gitweb.css"   Name="style-gitweb.css" />
+            <File Id="static.style.monoblue.css" Name="style-monoblue.css" />
+            <File Id="static.style.paper.css"    Name="style-paper.css" />
+            <File Id="static.style.css"          Name="style.css" />
+          </Component>
+        </Directory>
+
+      </Directory>
+
+    </DirectoryRef>
+  </Fragment>
+
+ </Wix>
--- a/doc/Makefile	Mon Dec 07 12:31:45 2009 +0200
+++ b/doc/Makefile	Tue May 11 17:03:44 2010 -0500
@@ -6,7 +6,6 @@
 MANDIR=$(PREFIX)/share/man
 INSTALL=install -c -m 644
 PYTHON=python
-RST2HTML=$(shell which rst2html 2> /dev/null || echo rst2html.py)
 
 export LANGUAGE=C
 export LC_ALL=C
@@ -25,11 +24,11 @@
 	mv $@.tmp $@
 
 %: %.txt common.txt
-	$(PYTHON) rst2man.py --halt warning \
+	$(PYTHON) runrst manpage --halt warning \
 	  --strip-elements-with-class htmlonly $*.txt $*
 
 %.html: %.txt common.txt
-	$(RST2HTML) --halt warning \
+	$(PYTHON) runrst html --halt warning \
 	  --link-stylesheet --stylesheet-path style.css $*.txt $*.html
 
 MANIFEST: man html
--- a/doc/hgrc.5.txt	Mon Dec 07 12:31:45 2009 +0200
+++ b/doc/hgrc.5.txt	Tue May 11 17:03:44 2010 -0500
@@ -111,10 +111,18 @@
 section, if it has been set previously.
 
 The values are either free-form text strings, lists of text strings,
-or Boolean values. Lists are split on whitespace and commas. Boolean
-values can be set to true using any of "1", "yes", "true", or "on" and
-to false using "0", "no", "false", or "off" (all case insensitive).
+or Boolean values. Boolean values can be set to true using any of "1",
+"yes", "true", or "on" and to false using "0", "no", "false", or "off"
+(all case insensitive).
 
+List values are separated by whitespace or comma, except when values are
+placed in double quotation marks::
+
+  allow_read = "John Doe, PhD", brian, betty
+
+Quotation marks can be escaped by prefixing them with a backslash. Only
+quotation marks at the beginning of a word is counted as a quotation
+(e.g., ``foo"bar baz`` is the list of ``foo"bar`` and ``baz``).
 
 Sections
 --------
@@ -268,8 +276,8 @@
 Use the ``[defaults]`` section to define command defaults, i.e. the
 default options/arguments to pass to the specified commands.
 
-The following example makes ``hg log`` run in verbose mode, and ``hg
-status`` show only the modified files, by default::
+The following example makes :hg:`log` run in verbose mode, and :hg:`hg
+status` show only the modified files, by default::
 
   [defaults]
   log = -v
@@ -446,7 +454,8 @@
   Default: ``$local $base $other``
 ``premerge``
   Attempt to run internal non-interactive 3-way merge tool before
-  launching external tool.
+  launching external tool.  Options are ``true``, ``false``, or ``keep``
+  to leave markers in the file if the premerge fails.
   Default: True
 ``binary``
   This tool can merge binary files. Defaults to False, unless tool
@@ -454,13 +463,21 @@
 ``symlink``
   This tool can merge symlinks. Defaults to False, even if tool was
   selected by file pattern match.
-``checkconflicts``
-  Check whether there are conflicts even though the tool reported
-  success.
+``check``
+  A list of merge success-checking options:
+
+  ``changed``
+    Ask whether merge was successful when the merged file shows no changes.
+  ``conflicts``
+    Check whether there are conflicts even though the tool reported success.
+  ``prompt``
+    Always prompt for merge success, regardless of success reported by tool.
+
+``checkchanged``
+  True is equivalent to ``check = changed``.
   Default: False
-``checkchanged``
-  Check whether outputs were written even though the tool reported
-  success.
+``checkconflicts``
+  True is equivalent to ``check = conflicts``.
   Default: False
 ``fixeol``
   Attempt to fix up EOL changes caused by the merge tool.
@@ -757,7 +774,7 @@
 ``archivemeta``
     Whether to include the .hg_archival.txt file containing meta data
     (hashes for the repository base and for tip) in archives created
-    by the hg archive command or downloaded via hgweb.
+    by the :hg:`archive` command or downloaded via hgweb.
     Default is True.
 ``askusername``
     Whether to prompt for a username when committing. If True, and
@@ -867,20 +884,18 @@
     push is not allowed. If the special value ``*``, any remote user can
     push, including unauthenticated users. Otherwise, the remote user
     must have been authenticated, and the authenticated user name must
-    be present in this list (separated by whitespace or ``,``). The
-    contents of the allow_push list are examined after the deny_push
-    list.
+    be present in this list. The contents of the allow_push list are
+    examined after the deny_push list.
 ``allow_read``
     If the user has not already been denied repository access due to
     the contents of deny_read, this list determines whether to grant
     repository access to the user. If this list is not empty, and the
-    user is unauthenticated or not present in the list (separated by
-    whitespace or ``,``), then access is denied for the user. If the
-    list is empty or not set, then access is permitted to all users by
-    default. Setting allow_read to the special value ``*`` is equivalent
-    to it not being set (i.e. access is permitted to all users). The
-    contents of the allow_read list are examined after the deny_read
-    list.
+    user is unauthenticated or not present in the list, then access is
+    denied for the user. If the list is empty or not set, then access
+    is permitted to all users by default. Setting allow_read to the
+    special value ``*`` is equivalent to it not being set (i.e. access
+    is permitted to all users). The contents of the allow_read list are
+    examined after the deny_read list.
 ``allowzip``
     (DEPRECATED) Whether to allow .zip downloading of repository
     revisions. Default is False. This feature creates temporary files.
@@ -915,17 +930,15 @@
     Whether to deny pushing to the repository. If empty or not set,
     push is not denied. If the special value ``*``, all remote users are
     denied push. Otherwise, unauthenticated users are all denied, and
-    any authenticated user name present in this list (separated by
-    whitespace or ``,``) is also denied. The contents of the deny_push
-    list are examined before the allow_push list.
+    any authenticated user name present in this list is also denied. The
+    contents of the deny_push list are examined before the allow_push list.
 ``deny_read``
     Whether to deny reading/viewing of the repository. If this list is
     not empty, unauthenticated users are all denied, and any
-    authenticated user name present in this list (separated by
-    whitespace or ``,``) is also denied access to the repository. If set
-    to the special value ``*``, all remote users are denied access
-    (rarely needed ;). If deny_read is empty or not set, the
-    determination of repository access depends on the presence and
+    authenticated user name present in this list is also denied access to
+    the repository. If set to the special value ``*``, all remote users
+    are denied access (rarely needed ;). If deny_read is empty or not set,
+    the determination of repository access depends on the presence and
     content of the allow_read list (see description). If both
     deny_read and allow_read are empty or not set, then access is
     permitted to all users by default. If the repository is being
@@ -941,7 +954,7 @@
     Textual description of the repository's purpose or contents.
     Default is "unknown".
 ``encoding``
-    Character encoding name.
+    Character encoding name. Default is the current locale charset.
     Example: "UTF-8"
 ``errorlog``
     Where to output the error log. Default is stderr.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/manpage.py	Tue May 11 17:03:44 2010 -0500
@@ -0,0 +1,1102 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# $Id: manpage.py 6110 2009-08-31 14:40:33Z grubert $
+# Author: Engelbert Gruber <grubert@users.sourceforge.net>
+# Copyright: This module is put into the public domain.
+
+"""
+Simple man page writer for reStructuredText.
+
+Man pages (short for "manual pages") contain system documentation on unix-like
+systems. The pages are grouped in numbered sections:
+
+ 1 executable programs and shell commands
+ 2 system calls
+ 3 library functions
+ 4 special files
+ 5 file formats
+ 6 games
+ 7 miscellaneous
+ 8 system administration
+
+Man pages are written *troff*, a text file formatting system.
+
+See http://www.tldp.org/HOWTO/Man-Page for a start.
+
+Man pages have no subsection only parts.
+Standard parts
+
+  NAME ,
+  SYNOPSIS ,
+  DESCRIPTION ,
+  OPTIONS ,
+  FILES ,
+  SEE ALSO ,
+  BUGS ,
+
+and
+
+  AUTHOR .
+
+A unix-like system keeps an index of the DESCRIPTIONs, which is accesable
+by the command whatis or apropos.
+
+"""
+
+__docformat__ = 'reStructuredText'
+
+import re
+
+from docutils import nodes, writers, languages
+import roman
+
+FIELD_LIST_INDENT = 7
+DEFINITION_LIST_INDENT = 7
+OPTION_LIST_INDENT = 7
+BLOCKQOUTE_INDENT = 3.5
+
+# Define two macros so man/roff can calculate the
+# indent/unindent margins by itself
+MACRO_DEF = (r""".
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+""")
+
+class Writer(writers.Writer):
+
+    supported = ('manpage')
+    """Formats this writer supports."""
+
+    output = None
+    """Final translated form of `document`."""
+
+    def __init__(self):
+        writers.Writer.__init__(self)
+        self.translator_class = Translator
+
+    def translate(self):
+        visitor = self.translator_class(self.document)
+        self.document.walkabout(visitor)
+        self.output = visitor.astext()
+
+
+class Table:
+    def __init__(self):
+        self._rows = []
+        self._options = ['center']
+        self._tab_char = '\t'
+        self._coldefs = []
+    def new_row(self):
+        self._rows.append([])
+    def append_separator(self, separator):
+        """Append the separator for table head."""
+        self._rows.append([separator])
+    def append_cell(self, cell_lines):
+        """cell_lines is an array of lines"""
+        start = 0
+        if len(cell_lines) > 0 and cell_lines[0] == '.sp\n':
+            start = 1
+        self._rows[-1].append(cell_lines[start:])
+        if len(self._coldefs) < len(self._rows[-1]):
+            self._coldefs.append('l')
+    def _minimize_cell(self, cell_lines):
+        """Remove leading and trailing blank and ``.sp`` lines"""
+        while (cell_lines and cell_lines[0] in ('\n', '.sp\n')):
+            del cell_lines[0]
+        while (cell_lines and cell_lines[-1] in ('\n', '.sp\n')):
+            del cell_lines[-1]
+    def as_list(self):
+        text = ['.TS\n']
+        text.append(' '.join(self._options) + ';\n')
+        text.append('|%s|.\n' % ('|'.join(self._coldefs)))
+        for row in self._rows:
+            # row = array of cells. cell = array of lines.
+            text.append('_\n')       # line above
+            text.append('T{\n')
+            for i in range(len(row)):
+                cell = row[i]
+                self._minimize_cell(cell)
+                text.extend(cell)
+                if not text[-1].endswith('\n'):
+                    text[-1] += '\n'
+                if i < len(row)-1:
+                    text.append('T}'+self._tab_char+'T{\n')
+                else:
+                    text.append('T}\n')
+        text.append('_\n')
+        text.append('.TE\n')
+        return text
+
+class Translator(nodes.NodeVisitor):
+    """"""
+
+    words_and_spaces = re.compile(r'\S+| +|\n')
+    document_start = """Man page generated from reStructeredText."""
+
+    def __init__(self, document):
+        nodes.NodeVisitor.__init__(self, document)
+        self.settings = settings = document.settings
+        lcode = settings.language_code
+        self.language = languages.get_language(lcode)
+        self.head = []
+        self.body = []
+        self.foot = []
+        self.section_level = 0
+        self.context = []
+        self.topic_class = ''
+        self.colspecs = []
+        self.compact_p = 1
+        self.compact_simple = None
+        # the list style "*" bullet or "#" numbered
+        self._list_char = []
+        # writing the header .TH and .SH NAME is postboned after
+        # docinfo.
+        self._docinfo = {
+                "title" : "", "title_upper": "",
+                "subtitle" : "",
+                "manual_section" : "", "manual_group" : "",
+                "author" : [],
+                "date" : "",
+                "copyright" : "",
+                "version" : "",
+                    }
+        self._docinfo_keys = []     # a list to keep the sequence as in source.
+        self._docinfo_names = {}    # to get name from text not normalized.
+        self._in_docinfo = None
+        self._active_table = None
+        self._in_literal = False
+        self.header_written = 0
+        self._line_block = 0
+        self.authors = []
+        self.section_level = 0
+        self._indent = [0]
+        # central definition of simple processing rules
+        # what to output on : visit, depart
+        # Do not use paragraph requests ``.PP`` because these set indentation.
+        # use ``.sp``. Remove superfluous ``.sp`` in ``astext``.
+        #
+        # Fonts are put on a stack, the top one is used.
+        # ``.ft P`` or ``\\fP`` pop from stack.
+        # ``B`` bold, ``I`` italic, ``R`` roman should be available.
+        # Hopefully ``C`` courier too.
+        self.defs = {
+                'indent' : ('.INDENT %.1f\n', '.UNINDENT\n'),
+                'definition_list_item' : ('.TP', ''),
+                'field_name' : ('.TP\n.B ', '\n'),
+                'literal' : ('\\fB', '\\fP'),
+                'literal_block' : ('.sp\n.nf\n.ft C\n', '\n.ft P\n.fi\n'),
+
+                'option_list_item' : ('.TP\n', ''),
+
+                'reference' : (r'\%', r'\:'),
+                'emphasis': ('\\fI', '\\fP'),
+                'strong' : ('\\fB', '\\fP'),
+                'term' : ('\n.B ', '\n'),
+                'title_reference' : ('\\fI', '\\fP'),
+
+                'topic-title' : ('.SS ',),
+                'sidebar-title' : ('.SS ',),
+
+                'problematic' : ('\n.nf\n', '\n.fi\n'),
+                    }
+        # NOTE don't specify the newline before a dot-command, but ensure
+        # it is there.
+
+    def comment_begin(self, text):
+        """Return commented version of the passed text WITHOUT end of
+        line/comment."""
+        prefix = '.\\" '
+        out_text = ''.join(
+            [(prefix + in_line + '\n')
+            for in_line in text.split('\n')])
+        return out_text
+
+    def comment(self, text):
+        """Return commented version of the passed text."""
+        return self.comment_begin(text)+'.\n'
+
+    def ensure_eol(self):
+        """Ensure the last line in body is terminated by new line."""
+        if self.body[-1][-1] != '\n':
+            self.body.append('\n')
+
+    def astext(self):
+        """Return the final formatted document as a string."""
+        if not self.header_written:
+            # ensure we get a ".TH" as viewers require it.
+            self.head.append(self.header())
+        # filter body
+        for i in xrange(len(self.body)-1, 0, -1):
+            # remove superfluous vertical gaps.
+            if self.body[i] == '.sp\n':
+                if self.body[i - 1][:4] in ('.BI ','.IP '):
+                    self.body[i] = '.\n'
+                elif (self.body[i - 1][:3] == '.B ' and
+                    self.body[i - 2][:4] == '.TP\n'):
+                    self.body[i] = '.\n'
+                elif (self.body[i - 1] == '\n' and
+                    self.body[i - 2][0] != '.' and
+                    (self.body[i - 3][:7] == '.TP\n.B '
+                        or self.body[i - 3][:4] == '\n.B ')
+                     ):
+                    self.body[i] = '.\n'
+        return ''.join(self.head + self.body + self.foot)
+
+    def deunicode(self, text):
+        text = text.replace(u'\xa0', '\\ ')
+        text = text.replace(u'\u2020', '\\(dg')
+        return text
+
+    def visit_Text(self, node):
+        text = node.astext()
+        text = text.replace('\\','\\e')
+        replace_pairs = [
+            (u'-', ur'\-'),
+            (u'\'', ur'\(aq'),
+            (u'´', ur'\''),
+            (u'`', ur'\(ga'),
+            ]
+        for (in_char, out_markup) in replace_pairs:
+            text = text.replace(in_char, out_markup)
+        # unicode
+        text = self.deunicode(text)
+        if self._in_literal:
+            # prevent interpretation of "." at line start
+            if text[0] == '.':
+                text = '\\&' + text
+            text = text.replace('\n.', '\n\\&.')
+        self.body.append(text)
+
+    def depart_Text(self, node):
+        pass
+
+    def list_start(self, node):
+        class enum_char:
+            enum_style = {
+                    'bullet'     : '\\(bu',
+                    'emdash'     : '\\(em',
+                     }
+
+            def __init__(self, style):
+                self._style = style
+                if node.has_key('start'):
+                    self._cnt = node['start'] - 1
+                else:
+                    self._cnt = 0
+                self._indent = 2
+                if style == 'arabic':
+                    # indentation depends on number of childrens
+                    # and start value.
+                    self._indent = len(str(len(node.children)))
+                    self._indent += len(str(self._cnt)) + 1
+                elif style == 'loweralpha':
+                    self._cnt += ord('a') - 1
+                    self._indent = 3
+                elif style == 'upperalpha':
+                    self._cnt += ord('A') - 1
+                    self._indent = 3
+                elif style.endswith('roman'):
+                    self._indent = 5
+
+            def next(self):
+                if self._style == 'bullet':
+                    return self.enum_style[self._style]
+                elif self._style == 'emdash':
+                    return self.enum_style[self._style]
+                self._cnt += 1
+                # TODO add prefix postfix
+                if self._style == 'arabic':
+                    return "%d." % self._cnt
+                elif self._style in ('loweralpha', 'upperalpha'):
+                    return "%c." % self._cnt
+                elif self._style.endswith('roman'):
+                    res = roman.toRoman(self._cnt) + '.'
+                    if self._style.startswith('upper'):
+                        return res.upper()
+                    return res.lower()
+                else:
+                    return "%d." % self._cnt
+            def get_width(self):
+                return self._indent
+            def __repr__(self):
+                return 'enum_style-%s' % list(self._style)
+
+        if node.has_key('enumtype'):
+            self._list_char.append(enum_char(node['enumtype']))
+        else:
+            self._list_char.append(enum_char('bullet'))
+        if len(self._list_char) > 1:
+            # indent nested lists
+            self.indent(self._list_char[-2].get_width())
+        else:
+            self.indent(self._list_char[-1].get_width())
+
+    def list_end(self):
+        self.dedent()
+        self._list_char.pop()
+
+    def header(self):
+        tmpl = (".TH %(title_upper)s %(manual_section)s"
+                " \"%(date)s\" \"%(version)s\" \"%(manual_group)s\"\n"
+                ".SH NAME\n"
+                "%(title)s \- %(subtitle)s\n")
+        return tmpl % self._docinfo
+
+    def append_header(self):
+        """append header with .TH and .SH NAME"""
+        # NOTE before everything
+        # .TH title_upper section date source manual
+        if self.header_written:
+            return
+        self.body.append(self.header())
+        self.body.append(MACRO_DEF)
+        self.header_written = 1
+
+    def visit_address(self, node):
+        self.visit_docinfo_item(node, 'address')
+
+    def depart_address(self, node):
+        pass
+
+    def visit_admonition(self, node, name=None):
+        if name:
+            self.body.append('.IP %s\n' %
+                        self.language.labels.get(name, name))
+
+    def depart_admonition(self, node):
+        self.body.append('.RE\n')
+
+    def visit_attention(self, node):
+        self.visit_admonition(node, 'attention')
+
+    depart_attention = depart_admonition
+
+    def visit_docinfo_item(self, node, name):
+        if name == 'author':
+            self._docinfo[name].append(node.astext())
+        else:
+            self._docinfo[name] = node.astext()
+        self._docinfo_keys.append(name)
+        raise nodes.SkipNode
+
+    def depart_docinfo_item(self, node):
+        pass
+
+    def visit_author(self, node):
+        self.visit_docinfo_item(node, 'author')
+
+    depart_author = depart_docinfo_item
+
+    def visit_authors(self, node):
+        # _author is called anyway.
+        pass
+
+    def depart_authors(self, node):
+        pass
+
+    def visit_block_quote(self, node):
+        # BUG/HACK: indent alway uses the _last_ indention,
+        # thus we need two of them.
+        self.indent(BLOCKQOUTE_INDENT)
+        self.indent(0)
+
+    def depart_block_quote(self, node):
+        self.dedent()
+        self.dedent()
+
+    def visit_bullet_list(self, node):
+        self.list_start(node)
+
+    def depart_bullet_list(self, node):
+        self.list_end()
+
+    def visit_caption(self, node):
+        pass
+
+    def depart_caption(self, node):
+        pass
+
+    def visit_caution(self, node):
+        self.visit_admonition(node, 'caution')
+
+    depart_caution = depart_admonition
+
+    def visit_citation(self, node):
+        num, text = node.astext().split(None, 1)
+        num = num.strip()
+        self.body.append('.IP [%s] 5\n' % num)
+
+    def depart_citation(self, node):
+        pass
+
+    def visit_citation_reference(self, node):
+        self.body.append('['+node.astext()+']')
+        raise nodes.SkipNode
+
+    def visit_classifier(self, node):
+        pass
+
+    def depart_classifier(self, node):
+        pass
+
+    def visit_colspec(self, node):
+        self.colspecs.append(node)
+
+    def depart_colspec(self, node):
+        pass
+
+    def write_colspecs(self):
+        self.body.append("%s.\n" % ('L '*len(self.colspecs)))
+
+    def visit_comment(self, node,
+                      sub=re.compile('-(?=-)').sub):
+        self.body.append(self.comment(node.astext()))
+        raise nodes.SkipNode
+
+    def visit_contact(self, node):
+        self.visit_docinfo_item(node, 'contact')
+
+    depart_contact = depart_docinfo_item
+
+    def visit_container(self, node):
+        pass
+
+    def depart_container(self, node):
+        pass
+
+    def visit_compound(self, node):
+        pass
+
+    def depart_compound(self, node):
+        pass
+
+    def visit_copyright(self, node):
+        self.visit_docinfo_item(node, 'copyright')
+
+    def visit_danger(self, node):
+        self.visit_admonition(node, 'danger')
+
+    depart_danger = depart_admonition
+
+    def visit_date(self, node):
+        self.visit_docinfo_item(node, 'date')
+
+    def visit_decoration(self, node):
+        pass
+
+    def depart_decoration(self, node):
+        pass
+
+    def visit_definition(self, node):
+        pass
+
+    def depart_definition(self, node):
+        pass
+
+    def visit_definition_list(self, node):
+        self.indent(DEFINITION_LIST_INDENT)
+
+    def depart_definition_list(self, node):
+        self.dedent()
+
+    def visit_definition_list_item(self, node):
+        self.body.append(self.defs['definition_list_item'][0])
+
+    def depart_definition_list_item(self, node):
+        self.body.append(self.defs['definition_list_item'][1])
+
+    def visit_description(self, node):
+        pass
+
+    def depart_description(self, node):
+        pass
+
+    def visit_docinfo(self, node):
+        self._in_docinfo = 1
+
+    def depart_docinfo(self, node):
+        self._in_docinfo = None
+        # NOTE nothing should be written before this
+        self.append_header()
+
+    def visit_doctest_block(self, node):
+        self.body.append(self.defs['literal_block'][0])
+        self._in_literal = True
+
+    def depart_doctest_block(self, node):
+        self._in_literal = False
+        self.body.append(self.defs['literal_block'][1])
+
+    def visit_document(self, node):
+        # no blank line between comment and header.
+        self.body.append(self.comment(self.document_start).rstrip()+'\n')
+        # writing header is postboned
+        self.header_written = 0
+
+    def depart_document(self, node):
+        if self._docinfo['author']:
+            self.body.append('.SH AUTHOR\n%s\n'
+                    % ', '.join(self._docinfo['author']))
+        skip = ('author', 'copyright', 'date',
+                'manual_group', 'manual_section',
+                'subtitle',
+                'title', 'title_upper', 'version')
+        for name in self._docinfo_keys:
+            if name == 'address':
+                self.body.append("\n%s:\n%s%s.nf\n%s\n.fi\n%s%s" % (
+                                    self.language.labels.get(name, name),
+                                    self.defs['indent'][0] % 0,
+                                    self.defs['indent'][0] % BLOCKQOUTE_INDENT,
+                                    self._docinfo[name],
+                                    self.defs['indent'][1],
+                                    self.defs['indent'][1]))
+            elif not name in skip:
+                if name in self._docinfo_names:
+                    label = self._docinfo_names[name]
+                else:
+                    label = self.language.labels.get(name, name)
+                self.body.append("\n%s: %s\n" % (label, self._docinfo[name]))
+        if self._docinfo['copyright']:
+            self.body.append('.SH COPYRIGHT\n%s\n'
+                    % self._docinfo['copyright'])
+        self.body.append(self.comment(
+                        'Generated by docutils manpage writer.\n'))
+
+    def visit_emphasis(self, node):
+        self.body.append(self.defs['emphasis'][0])
+
+    def depart_emphasis(self, node):
+        self.body.append(self.defs['emphasis'][1])
+
+    def visit_entry(self, node):
+        # a cell in a table row
+        if 'morerows' in node:
+            self.document.reporter.warning('"table row spanning" not supported',
+                    base_node=node)
+        if 'morecols' in node:
+            self.document.reporter.warning(
+                    '"table cell spanning" not supported', base_node=node)
+        self.context.append(len(self.body))
+
+    def depart_entry(self, node):
+        start = self.context.pop()
+        self._active_table.append_cell(self.body[start:])
+        del self.body[start:]
+
+    def visit_enumerated_list(self, node):
+        self.list_start(node)
+
+    def depart_enumerated_list(self, node):
+        self.list_end()
+
+    def visit_error(self, node):
+        self.visit_admonition(node, 'error')
+
+    depart_error = depart_admonition
+
+    def visit_field(self, node):
+        pass
+
+    def depart_field(self, node):
+        pass
+
+    def visit_field_body(self, node):
+        if self._in_docinfo:
+            name_normalized = self._field_name.lower().replace(" ","_")
+            self._docinfo_names[name_normalized] = self._field_name
+            self.visit_docinfo_item(node, name_normalized)
+            raise nodes.SkipNode
+
+    def depart_field_body(self, node):
+        pass
+
+    def visit_field_list(self, node):
+        self.indent(FIELD_LIST_INDENT)
+
+    def depart_field_list(self, node):
+        self.dedent()
+
+    def visit_field_name(self, node):
+        if self._in_docinfo:
+            self._field_name = node.astext()
+            raise nodes.SkipNode
+        else:
+            self.body.append(self.defs['field_name'][0])
+
+    def depart_field_name(self, node):
+        self.body.append(self.defs['field_name'][1])
+
+    def visit_figure(self, node):
+        self.indent(2.5)
+        self.indent(0)
+
+    def depart_figure(self, node):
+        self.dedent()
+        self.dedent()
+
+    def visit_footer(self, node):
+        self.document.reporter.warning('"footer" not supported',
+                base_node=node)
+
+    def depart_footer(self, node):
+        pass
+
+    def visit_footnote(self, node):
+        num, text = node.astext().split(None, 1)
+        num = num.strip()
+        self.body.append('.IP [%s] 5\n' % self.deunicode(num))
+
+    def depart_footnote(self, node):
+        pass
+
+    def footnote_backrefs(self, node):
+        self.document.reporter.warning('"footnote_backrefs" not supported',
+                base_node=node)
+
+    def visit_footnote_reference(self, node):
+        self.body.append('['+self.deunicode(node.astext())+']')
+        raise nodes.SkipNode
+
+    def depart_footnote_reference(self, node):
+        pass
+
+    def visit_generated(self, node):
+        pass
+
+    def depart_generated(self, node):
+        pass
+
+    def visit_header(self, node):
+        raise NotImplementedError, node.astext()
+
+    def depart_header(self, node):
+        pass
+
+    def visit_hint(self, node):
+        self.visit_admonition(node, 'hint')
+
+    depart_hint = depart_admonition
+
+    def visit_subscript(self, node):
+        self.body.append('\\s-2\\d')
+
+    def depart_subscript(self, node):
+        self.body.append('\\u\\s0')
+
+    def visit_superscript(self, node):
+        self.body.append('\\s-2\\u')
+
+    def depart_superscript(self, node):
+        self.body.append('\\d\\s0')
+
+    def visit_attribution(self, node):
+        self.body.append('\\(em ')
+
+    def depart_attribution(self, node):
+        self.body.append('\n')
+
+    def visit_image(self, node):
+        self.document.reporter.warning('"image" not supported',
+                base_node=node)
+        text = []
+        if 'alt' in node.attributes:
+            text.append(node.attributes['alt'])
+        if 'uri' in node.attributes:
+            text.append(node.attributes['uri'])
+        self.body.append('[image: %s]\n' % ('/'.join(text)))
+        raise nodes.SkipNode
+
+    def visit_important(self, node):
+        self.visit_admonition(node, 'important')
+
+    depart_important = depart_admonition
+
+    def visit_label(self, node):
+        # footnote and citation
+        if (isinstance(node.parent, nodes.footnote)
+            or isinstance(node.parent, nodes.citation)):
+            raise nodes.SkipNode
+        self.document.reporter.warning('"unsupported "label"',
+                base_node=node)
+        self.body.append('[')
+
+    def depart_label(self, node):
+        self.body.append(']\n')
+
+    def visit_legend(self, node):
+        pass
+
+    def depart_legend(self, node):
+        pass
+
+    # WHAT should we use .INDENT, .UNINDENT ?
+    def visit_line_block(self, node):
+        self._line_block += 1
+        if self._line_block == 1:
+            self.body.append('.sp\n')
+            self.body.append('.nf\n')
+        else:
+            self.body.append('.in +2\n')
+
+    def depart_line_block(self, node):
+        self._line_block -= 1
+        if self._line_block == 0:
+            self.body.append('.fi\n')
+            self.body.append('.sp\n')
+        else:
+            self.body.append('.in -2\n')
+
+    def visit_line(self, node):
+        pass
+
+    def depart_line(self, node):
+        self.body.append('\n')
+
+    def visit_list_item(self, node):
+        # man 7 man argues to use ".IP" instead of ".TP"
+        self.body.append('.IP %s %d\n' % (
+                self._list_char[-1].next(),
+                self._list_char[-1].get_width(),))
+
+    def depart_list_item(self, node):
+        pass
+
+    def visit_literal(self, node):
+        self.body.append(self.defs['literal'][0])
+
+    def depart_literal(self, node):
+        self.body.append(self.defs['literal'][1])
+
+    def visit_literal_block(self, node):
+        self.body.append(self.defs['literal_block'][0])
+        self._in_literal = True
+
+    def depart_literal_block(self, node):
+        self._in_literal = False
+        self.body.append(self.defs['literal_block'][1])
+
+    def visit_meta(self, node):
+        raise NotImplementedError, node.astext()
+
+    def depart_meta(self, node):
+        pass
+
+    def visit_note(self, node):
+        self.visit_admonition(node, 'note')
+
+    depart_note = depart_admonition
+
+    def indent(self, by=0.5):
+        # if we are in a section ".SH" there already is a .RS
+        step = self._indent[-1]
+        self._indent.append(by)
+        self.body.append(self.defs['indent'][0] % step)
+
+    def dedent(self):
+        self._indent.pop()
+        self.body.append(self.defs['indent'][1])
+
+    def visit_option_list(self, node):
+        self.indent(OPTION_LIST_INDENT)
+
+    def depart_option_list(self, node):
+        self.dedent()
+
+    def visit_option_list_item(self, node):
+        # one item of the list
+        self.body.append(self.defs['option_list_item'][0])
+
+    def depart_option_list_item(self, node):
+        self.body.append(self.defs['option_list_item'][1])
+
+    def visit_option_group(self, node):
+        # as one option could have several forms it is a group
+        # options without parameter bold only, .B, -v
+        # options with parameter bold italic, .BI, -f file
+        #
+        # we do not know if .B or .BI
+        self.context.append('.B')           # blind guess
+        self.context.append(len(self.body)) # to be able to insert later
+        self.context.append(0)              # option counter
+
+    def depart_option_group(self, node):
+        self.context.pop()  # the counter
+        start_position = self.context.pop()
+        text = self.body[start_position:]
+        del self.body[start_position:]
+        self.body.append('%s%s\n' % (self.context.pop(), ''.join(text)))
+
+    def visit_option(self, node):
+        # each form of the option will be presented separately
+        if self.context[-1] > 0:
+            self.body.append(', ')
+        if self.context[-3] == '.BI':
+            self.body.append('\\')
+        self.body.append(' ')
+
+    def depart_option(self, node):
+        self.context[-1] += 1
+
+    def visit_option_string(self, node):
+        # do not know if .B or .BI
+        pass
+
+    def depart_option_string(self, node):
+        pass
+
+    def visit_option_argument(self, node):
+        self.context[-3] = '.BI' # bold/italic alternate
+        if node['delimiter'] != ' ':
+            self.body.append('\\fB%s ' % node['delimiter'])
+        elif self.body[len(self.body)-1].endswith('='):
+            # a blank only means no blank in output, just changing font
+            self.body.append(' ')
+        else:
+            # blank backslash blank, switch font then a blank
+            self.body.append(' \\ ')
+
+    def depart_option_argument(self, node):
+        pass
+
+    def visit_organization(self, node):
+        self.visit_docinfo_item(node, 'organization')
+
+    def depart_organization(self, node):
+        pass
+
+    def visit_paragraph(self, node):
+        # ``.PP`` : Start standard indented paragraph.
+        # ``.LP`` : Start block paragraph, all except the first.
+        # ``.P [type]``  : Start paragraph type.
+        # NOTE dont use paragraph starts because they reset indentation.
+        # ``.sp`` is only vertical space
+        self.ensure_eol()
+        self.body.append('.sp\n')
+
+    def depart_paragraph(self, node):
+        self.body.append('\n')
+
+    def visit_problematic(self, node):
+        self.body.append(self.defs['problematic'][0])
+
+    def depart_problematic(self, node):
+        self.body.append(self.defs['problematic'][1])
+
+    def visit_raw(self, node):
+        if node.get('format') == 'manpage':
+            self.body.append(node.astext() + "\n")
+        # Keep non-manpage raw text out of output:
+        raise nodes.SkipNode
+
+    def visit_reference(self, node):
+        """E.g. link or email address."""
+        self.body.append(self.defs['reference'][0])
+
+    def depart_reference(self, node):
+        self.body.append(self.defs['reference'][1])
+
+    def visit_revision(self, node):
+        self.visit_docinfo_item(node, 'revision')
+
+    depart_revision = depart_docinfo_item
+
+    def visit_row(self, node):
+        self._active_table.new_row()
+
+    def depart_row(self, node):
+        pass
+
+    def visit_section(self, node):
+        self.section_level += 1
+
+    def depart_section(self, node):
+        self.section_level -= 1
+
+    def visit_status(self, node):
+        self.visit_docinfo_item(node, 'status')
+
+    depart_status = depart_docinfo_item
+
+    def visit_strong(self, node):
+        self.body.append(self.defs['strong'][0])
+
+    def depart_strong(self, node):
+        self.body.append(self.defs['strong'][1])
+
+    def visit_substitution_definition(self, node):
+        """Internal only."""
+        raise nodes.SkipNode
+
+    def visit_substitution_reference(self, node):
+        self.document.reporter.warning('"substitution_reference" not supported',
+                base_node=node)
+
+    def visit_subtitle(self, node):
+        if isinstance(node.parent, nodes.sidebar):
+            self.body.append(self.defs['strong'][0])
+        elif isinstance(node.parent, nodes.document):
+            self.visit_docinfo_item(node, 'subtitle')
+        elif isinstance(node.parent, nodes.section):
+            self.body.append(self.defs['strong'][0])
+
+    def depart_subtitle(self, node):
+        # document subtitle calls SkipNode
+        self.body.append(self.defs['strong'][1]+'\n.PP\n')
+
+    def visit_system_message(self, node):
+        # TODO add report_level
+        #if node['level'] < self.document.reporter['writer'].report_level:
+        #    Level is too low to display:
+        #    raise nodes.SkipNode
+        attr = {}
+        backref_text = ''
+        if node.hasattr('id'):
+            attr['name'] = node['id']
+        if node.hasattr('line'):
+            line = ', line %s' % node['line']
+        else:
+            line = ''
+        self.body.append('.IP "System Message: %s/%s (%s:%s)"\n'
+                         % (node['type'], node['level'], node['source'], line))
+
+    def depart_system_message(self, node):
+        pass
+
+    def visit_table(self, node):
+        self._active_table = Table()
+
+    def depart_table(self, node):
+        self.ensure_eol()
+        self.body.extend(self._active_table.as_list())
+        self._active_table = None
+
+    def visit_target(self, node):
+        # targets are in-document hyper targets, without any use for man-pages.
+        raise nodes.SkipNode
+
+    def visit_tbody(self, node):
+        pass
+
+    def depart_tbody(self, node):
+        pass
+
+    def visit_term(self, node):
+        self.body.append(self.defs['term'][0])
+
+    def depart_term(self, node):
+        self.body.append(self.defs['term'][1])
+
+    def visit_tgroup(self, node):
+        pass
+
+    def depart_tgroup(self, node):
+        pass
+
+    def visit_thead(self, node):
+        # MAYBE double line '='
+        pass
+
+    def depart_thead(self, node):
+        # MAYBE double line '='
+        pass
+
+    def visit_tip(self, node):
+        self.visit_admonition(node, 'tip')
+
+    depart_tip = depart_admonition
+
+    def visit_title(self, node):
+        if isinstance(node.parent, nodes.topic):
+            self.body.append(self.defs['topic-title'][0])
+        elif isinstance(node.parent, nodes.sidebar):
+            self.body.append(self.defs['sidebar-title'][0])
+        elif isinstance(node.parent, nodes.admonition):
+            self.body.append('.IP "')
+        elif self.section_level == 0:
+            self._docinfo['title'] = node.astext()
+            # document title for .TH
+            self._docinfo['title_upper'] = node.astext().upper()
+            raise nodes.SkipNode
+        elif self.section_level == 1:
+            self.body.append('.SH ')
+            for n in node.traverse(nodes.Text):
+                n.parent.replace(n, nodes.Text(n.astext().upper()))
+        else:
+            self.body.append('.SS ')
+
+    def depart_title(self, node):
+        if isinstance(node.parent, nodes.admonition):
+            self.body.append('"')
+        self.body.append('\n')
+
+    def visit_title_reference(self, node):
+        """inline citation reference"""
+        self.body.append(self.defs['title_reference'][0])
+
+    def depart_title_reference(self, node):
+        self.body.append(self.defs['title_reference'][1])
+
+    def visit_topic(self, node):
+        pass
+
+    def depart_topic(self, node):
+        pass
+
+    def visit_sidebar(self, node):
+        pass
+
+    def depart_sidebar(self, node):
+        pass
+
+    def visit_rubric(self, node):
+        pass
+
+    def depart_rubric(self, node):
+        pass
+
+    def visit_transition(self, node):
+        # .PP      Begin a new paragraph and reset prevailing indent.
+        # .sp N    leaves N lines of blank space.
+        # .ce      centers the next line
+        self.body.append('\n.sp\n.ce\n----\n')
+
+    def depart_transition(self, node):
+        self.body.append('\n.ce 0\n.sp\n')
+
+    def visit_version(self, node):
+        self.visit_docinfo_item(node, 'version')
+
+    def visit_warning(self, node):
+        self.visit_admonition(node, 'warning')
+
+    depart_warning = depart_admonition
+
+    def unimplemented_visit(self, node):
+        raise NotImplementedError('visiting unimplemented node type: %s'
+                                  % node.__class__.__name__)
+
+# vim: set fileencoding=utf-8 et ts=4 ai :
--- a/doc/rst2man.py	Mon Dec 07 12:31:45 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1114 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
-# $Id: manpage.py 6110 2009-08-31 14:40:33Z grubert $
-# Author: Engelbert Gruber <grubert@users.sourceforge.net>
-# Copyright: This module is put into the public domain.
-
-"""
-Simple man page writer for reStructuredText.
-
-Man pages (short for "manual pages") contain system documentation on unix-like
-systems. The pages are grouped in numbered sections:
-
- 1 executable programs and shell commands
- 2 system calls
- 3 library functions
- 4 special files
- 5 file formats
- 6 games
- 7 miscellaneous
- 8 system administration
-
-Man pages are written *troff*, a text file formatting system.
-
-See http://www.tldp.org/HOWTO/Man-Page for a start.
-
-Man pages have no subsection only parts.
-Standard parts
-
-  NAME ,
-  SYNOPSIS ,
-  DESCRIPTION ,
-  OPTIONS ,
-  FILES ,
-  SEE ALSO ,
-  BUGS ,
-
-and
-
-  AUTHOR .
-
-A unix-like system keeps an index of the DESCRIPTIONs, which is accesable
-by the command whatis or apropos.
-
-"""
-
-__docformat__ = 'reStructuredText'
-
-import sys
-import os
-import time
-import re
-from types import ListType
-
-import docutils
-from docutils import nodes, utils, writers, languages
-import roman
-
-FIELD_LIST_INDENT = 7
-DEFINITION_LIST_INDENT = 7
-OPTION_LIST_INDENT = 7
-BLOCKQOUTE_INDENT = 3.5
-
-# Define two macros so man/roff can calculate the
-# indent/unindent margins by itself
-MACRO_DEF = (r""".
-.nr rst2man-indent-level 0
-.
-.de1 rstReportMargin
-\\$1 \\n[an-margin]
-level \\n[rst2man-indent-level]
-level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
--
-\\n[rst2man-indent0]
-\\n[rst2man-indent1]
-\\n[rst2man-indent2]
-..
-.de1 INDENT
-.\" .rstReportMargin pre:
-. RS \\$1
-. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
-. nr rst2man-indent-level +1
-.\" .rstReportMargin post:
-..
-.de UNINDENT
-. RE
-.\" indent \\n[an-margin]
-.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
-.nr rst2man-indent-level -1
-.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
-.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
-..
-""")
-
-class Writer(writers.Writer):
-
-    supported = ('manpage')
-    """Formats this writer supports."""
-
-    output = None
-    """Final translated form of `document`."""
-
-    def __init__(self):
-        writers.Writer.__init__(self)
-        self.translator_class = Translator
-
-    def translate(self):
-        visitor = self.translator_class(self.document)
-        self.document.walkabout(visitor)
-        self.output = visitor.astext()
-
-
-class Table:
-    def __init__(self):
-        self._rows = []
-        self._options = ['center']
-        self._tab_char = '\t'
-        self._coldefs = []
-    def new_row(self):
-        self._rows.append([])
-    def append_separator(self, separator):
-        """Append the separator for table head."""
-        self._rows.append([separator])
-    def append_cell(self, cell_lines):
-        """cell_lines is an array of lines"""
-        start = 0
-        if len(cell_lines) > 0 and cell_lines[0] == '.sp\n':
-            start = 1
-        self._rows[-1].append(cell_lines[start:])
-        if len(self._coldefs) < len(self._rows[-1]):
-            self._coldefs.append('l')
-    def _minimize_cell(self, cell_lines):
-        """Remove leading and trailing blank and ``.sp`` lines"""
-        while (cell_lines and cell_lines[0] in ('\n', '.sp\n')):
-            del cell_lines[0]
-        while (cell_lines and cell_lines[-1] in ('\n', '.sp\n')):
-            del cell_lines[-1]
-    def as_list(self):
-        text = ['.TS\n']
-        text.append(' '.join(self._options) + ';\n')
-        text.append('|%s|.\n' % ('|'.join(self._coldefs)))
-        for row in self._rows:
-            # row = array of cells. cell = array of lines.
-            text.append('_\n')       # line above
-            text.append('T{\n')
-            for i in range(len(row)):
-                cell = row[i]
-                self._minimize_cell(cell)
-                text.extend(cell)
-                if not text[-1].endswith('\n'):
-                    text[-1] += '\n'
-                if i < len(row)-1:
-                    text.append('T}'+self._tab_char+'T{\n')
-                else:
-                    text.append('T}\n')
-        text.append('_\n')
-        text.append('.TE\n')
-        return text
-
-class Translator(nodes.NodeVisitor):
-    """"""
-
-    words_and_spaces = re.compile(r'\S+| +|\n')
-    document_start = """Man page generated from reStructeredText."""
-
-    def __init__(self, document):
-        nodes.NodeVisitor.__init__(self, document)
-        self.settings = settings = document.settings
-        lcode = settings.language_code
-        self.language = languages.get_language(lcode)
-        self.head = []
-        self.body = []
-        self.foot = []
-        self.section_level = 0
-        self.context = []
-        self.topic_class = ''
-        self.colspecs = []
-        self.compact_p = 1
-        self.compact_simple = None
-        # the list style "*" bullet or "#" numbered
-        self._list_char = []
-        # writing the header .TH and .SH NAME is postboned after
-        # docinfo.
-        self._docinfo = {
-                "title" : "", "title_upper": "",
-                "subtitle" : "",
-                "manual_section" : "", "manual_group" : "",
-                "author" : [],
-                "date" : "",
-                "copyright" : "",
-                "version" : "",
-                    }
-        self._docinfo_keys = []     # a list to keep the sequence as in source.
-        self._docinfo_names = {}    # to get name from text not normalized.
-        self._in_docinfo = None
-        self._active_table = None
-        self._in_literal = False
-        self.header_written = 0
-        self._line_block = 0
-        self.authors = []
-        self.section_level = 0
-        self._indent = [0]
-        # central definition of simple processing rules
-        # what to output on : visit, depart
-        # Do not use paragraph requests ``.PP`` because these set indentation.
-        # use ``.sp``. Remove superfluous ``.sp`` in ``astext``.
-        #
-        # Fonts are put on a stack, the top one is used.
-        # ``.ft P`` or ``\\fP`` pop from stack.
-        # ``B`` bold, ``I`` italic, ``R`` roman should be available.
-        # Hopefully ``C`` courier too.
-        self.defs = {
-                'indent' : ('.INDENT %.1f\n', '.UNINDENT\n'),
-                'definition_list_item' : ('.TP', ''),
-                'field_name' : ('.TP\n.B ', '\n'),
-                'literal' : ('\\fB', '\\fP'),
-                'literal_block' : ('.sp\n.nf\n.ft C\n', '\n.ft P\n.fi\n'),
-
-                'option_list_item' : ('.TP\n', ''),
-
-                'reference' : (r'\%', r'\:'),
-                'emphasis': ('\\fI', '\\fP'),
-                'strong' : ('\\fB', '\\fP'),
-                'term' : ('\n.B ', '\n'),
-                'title_reference' : ('\\fI', '\\fP'),
-
-                'topic-title' : ('.SS ',),
-                'sidebar-title' : ('.SS ',),
-
-                'problematic' : ('\n.nf\n', '\n.fi\n'),
-                    }
-        # NOTE don't specify the newline before a dot-command, but ensure
-        # it is there.
-
-    def comment_begin(self, text):
-        """Return commented version of the passed text WITHOUT end of
-        line/comment."""
-        prefix = '.\\" '
-        out_text = ''.join(
-            [(prefix + in_line + '\n')
-            for in_line in text.split('\n')])
-        return out_text
-
-    def comment(self, text):
-        """Return commented version of the passed text."""
-        return self.comment_begin(text)+'.\n'
-
-    def ensure_eol(self):
-        """Ensure the last line in body is terminated by new line."""
-        if self.body[-1][-1] != '\n':
-            self.body.append('\n')
-
-    def astext(self):
-        """Return the final formatted document as a string."""
-        if not self.header_written:
-            # ensure we get a ".TH" as viewers require it.
-            self.head.append(self.header())
-        # filter body
-        for i in xrange(len(self.body)-1, 0, -1):
-            # remove superfluous vertical gaps.
-            if self.body[i] == '.sp\n':
-                if self.body[i - 1][:4] in ('.BI ','.IP '):
-                    self.body[i] = '.\n'
-                elif (self.body[i - 1][:3] == '.B ' and
-                    self.body[i - 2][:4] == '.TP\n'):
-                    self.body[i] = '.\n'
-                elif (self.body[i - 1] == '\n' and
-                    self.body[i - 2][0] != '.' and
-                    (self.body[i - 3][:7] == '.TP\n.B '
-                        or self.body[i - 3][:4] == '\n.B ')
-                     ):
-                    self.body[i] = '.\n'
-        return ''.join(self.head + self.body + self.foot)
-
-    def deunicode(self, text):
-        text = text.replace(u'\xa0', '\\ ')
-        text = text.replace(u'\u2020', '\\(dg')
-        return text
-
-    def visit_Text(self, node):
-        text = node.astext()
-        text = text.replace('\\','\\e')
-        replace_pairs = [
-            (u'-', ur'\-'),
-            (u'\'', ur'\(aq'),
-            (u'´', ur'\''),
-            (u'`', ur'\(ga'),
-            ]
-        for (in_char, out_markup) in replace_pairs:
-            text = text.replace(in_char, out_markup)
-        # unicode
-        text = self.deunicode(text)
-        if self._in_literal:
-            # prevent interpretation of "." at line start
-            if text[0] == '.':
-                text = '\\&' + text
-            text = text.replace('\n.', '\n\\&.')
-        self.body.append(text)
-
-    def depart_Text(self, node):
-        pass
-
-    def list_start(self, node):
-        class enum_char:
-            enum_style = {
-                    'bullet'     : '\\(bu',
-                    'emdash'     : '\\(em',
-                     }
-
-            def __init__(self, style):
-                self._style = style
-                if node.has_key('start'):
-                    self._cnt = node['start'] - 1
-                else:
-                    self._cnt = 0
-                self._indent = 2
-                if style == 'arabic':
-                    # indentation depends on number of childrens
-                    # and start value.
-                    self._indent = len(str(len(node.children)))
-                    self._indent += len(str(self._cnt)) + 1
-                elif style == 'loweralpha':
-                    self._cnt += ord('a') - 1
-                    self._indent = 3
-                elif style == 'upperalpha':
-                    self._cnt += ord('A') - 1
-                    self._indent = 3
-                elif style.endswith('roman'):
-                    self._indent = 5
-
-            def next(self):
-                if self._style == 'bullet':
-                    return self.enum_style[self._style]
-                elif self._style == 'emdash':
-                    return self.enum_style[self._style]
-                self._cnt += 1
-                # TODO add prefix postfix
-                if self._style == 'arabic':
-                    return "%d." % self._cnt
-                elif self._style in ('loweralpha', 'upperalpha'):
-                    return "%c." % self._cnt
-                elif self._style.endswith('roman'):
-                    res = roman.toRoman(self._cnt) + '.'
-                    if self._style.startswith('upper'):
-                        return res.upper()
-                    return res.lower()
-                else:
-                    return "%d." % self._cnt
-            def get_width(self):
-                return self._indent
-            def __repr__(self):
-                return 'enum_style-%s' % list(self._style)
-
-        if node.has_key('enumtype'):
-            self._list_char.append(enum_char(node['enumtype']))
-        else:
-            self._list_char.append(enum_char('bullet'))
-        if len(self._list_char) > 1:
-            # indent nested lists
-            self.indent(self._list_char[-2].get_width())
-        else:
-            self.indent(self._list_char[-1].get_width())
-
-    def list_end(self):
-        self.dedent()
-        self._list_char.pop()
-
-    def header(self):
-        tmpl = (".TH %(title_upper)s %(manual_section)s"
-                " \"%(date)s\" \"%(version)s\" \"%(manual_group)s\"\n"
-                ".SH NAME\n"
-                "%(title)s \- %(subtitle)s\n")
-        return tmpl % self._docinfo
-
-    def append_header(self):
-        """append header with .TH and .SH NAME"""
-        # NOTE before everything
-        # .TH title_upper section date source manual
-        if self.header_written:
-            return
-        self.body.append(self.header())
-        self.body.append(MACRO_DEF)
-        self.header_written = 1
-
-    def visit_address(self, node):
-        self.visit_docinfo_item(node, 'address')
-
-    def depart_address(self, node):
-        pass
-
-    def visit_admonition(self, node, name=None):
-        if name:
-            self.body.append('.IP %s\n' %
-                        self.language.labels.get(name, name))
-
-    def depart_admonition(self, node):
-        self.body.append('.RE\n')
-
-    def visit_attention(self, node):
-        self.visit_admonition(node, 'attention')
-
-    depart_attention = depart_admonition
-
-    def visit_docinfo_item(self, node, name):
-        if name == 'author':
-            self._docinfo[name].append(node.astext())
-        else:
-            self._docinfo[name] = node.astext()
-        self._docinfo_keys.append(name)
-        raise nodes.SkipNode
-
-    def depart_docinfo_item(self, node):
-        pass
-
-    def visit_author(self, node):
-        self.visit_docinfo_item(node, 'author')
-
-    depart_author = depart_docinfo_item
-
-    def visit_authors(self, node):
-        # _author is called anyway.
-        pass
-
-    def depart_authors(self, node):
-        pass
-
-    def visit_block_quote(self, node):
-        # BUG/HACK: indent alway uses the _last_ indention,
-        # thus we need two of them.
-        self.indent(BLOCKQOUTE_INDENT)
-        self.indent(0)
-
-    def depart_block_quote(self, node):
-        self.dedent()
-        self.dedent()
-
-    def visit_bullet_list(self, node):
-        self.list_start(node)
-
-    def depart_bullet_list(self, node):
-        self.list_end()
-
-    def visit_caption(self, node):
-        pass
-
-    def depart_caption(self, node):
-        pass
-
-    def visit_caution(self, node):
-        self.visit_admonition(node, 'caution')
-
-    depart_caution = depart_admonition
-
-    def visit_citation(self, node):
-        num, text = node.astext().split(None, 1)
-        num = num.strip()
-        self.body.append('.IP [%s] 5\n' % num)
-
-    def depart_citation(self, node):
-        pass
-
-    def visit_citation_reference(self, node):
-        self.body.append('['+node.astext()+']')
-        raise nodes.SkipNode
-
-    def visit_classifier(self, node):
-        pass
-
-    def depart_classifier(self, node):
-        pass
-
-    def visit_colspec(self, node):
-        self.colspecs.append(node)
-
-    def depart_colspec(self, node):
-        pass
-
-    def write_colspecs(self):
-        self.body.append("%s.\n" % ('L '*len(self.colspecs)))
-
-    def visit_comment(self, node,
-                      sub=re.compile('-(?=-)').sub):
-        self.body.append(self.comment(node.astext()))
-        raise nodes.SkipNode
-
-    def visit_contact(self, node):
-        self.visit_docinfo_item(node, 'contact')
-
-    depart_contact = depart_docinfo_item
-
-    def visit_container(self, node):
-        pass
-
-    def depart_container(self, node):
-        pass
-
-    def visit_compound(self, node):
-        pass
-
-    def depart_compound(self, node):
-        pass
-
-    def visit_copyright(self, node):
-        self.visit_docinfo_item(node, 'copyright')
-
-    def visit_danger(self, node):
-        self.visit_admonition(node, 'danger')
-
-    depart_danger = depart_admonition
-
-    def visit_date(self, node):
-        self.visit_docinfo_item(node, 'date')
-
-    def visit_decoration(self, node):
-        pass
-
-    def depart_decoration(self, node):
-        pass
-
-    def visit_definition(self, node):
-        pass
-
-    def depart_definition(self, node):
-        pass
-
-    def visit_definition_list(self, node):
-        self.indent(DEFINITION_LIST_INDENT)
-
-    def depart_definition_list(self, node):
-        self.dedent()
-
-    def visit_definition_list_item(self, node):
-        self.body.append(self.defs['definition_list_item'][0])
-
-    def depart_definition_list_item(self, node):
-        self.body.append(self.defs['definition_list_item'][1])
-
-    def visit_description(self, node):
-        pass
-
-    def depart_description(self, node):
-        pass
-
-    def visit_docinfo(self, node):
-        self._in_docinfo = 1
-
-    def depart_docinfo(self, node):
-        self._in_docinfo = None
-        # NOTE nothing should be written before this
-        self.append_header()
-
-    def visit_doctest_block(self, node):
-        self.body.append(self.defs['literal_block'][0])
-        self._in_literal = True
-
-    def depart_doctest_block(self, node):
-        self._in_literal = False
-        self.body.append(self.defs['literal_block'][1])
-
-    def visit_document(self, node):
-        # no blank line between comment and header.
-        self.body.append(self.comment(self.document_start).rstrip()+'\n')
-        # writing header is postboned
-        self.header_written = 0
-
-    def depart_document(self, node):
-        if self._docinfo['author']:
-            self.body.append('.SH AUTHOR\n%s\n'
-                    % ', '.join(self._docinfo['author']))
-        skip = ('author', 'copyright', 'date',
-                'manual_group', 'manual_section',
-                'subtitle',
-                'title', 'title_upper', 'version')
-        for name in self._docinfo_keys:
-            if name == 'address':
-                self.body.append("\n%s:\n%s%s.nf\n%s\n.fi\n%s%s" % (
-                                    self.language.labels.get(name, name),
-                                    self.defs['indent'][0] % 0,
-                                    self.defs['indent'][0] % BLOCKQOUTE_INDENT,
-                                    self._docinfo[name],
-                                    self.defs['indent'][1],
-                                    self.defs['indent'][1]))
-            elif not name in skip:
-                if name in self._docinfo_names:
-                    label = self._docinfo_names[name]
-                else:
-                    label = self.language.labels.get(name, name)
-                self.body.append("\n%s: %s\n" % (label, self._docinfo[name]))
-        if self._docinfo['copyright']:
-            self.body.append('.SH COPYRIGHT\n%s\n'
-                    % self._docinfo['copyright'])
-        self.body.append(self.comment(
-                        'Generated by docutils manpage writer.\n'))
-
-    def visit_emphasis(self, node):
-        self.body.append(self.defs['emphasis'][0])
-
-    def depart_emphasis(self, node):
-        self.body.append(self.defs['emphasis'][1])
-
-    def visit_entry(self, node):
-        # a cell in a table row
-        if 'morerows' in node:
-            self.document.reporter.warning('"table row spanning" not supported',
-                    base_node=node)
-        if 'morecols' in node:
-            self.document.reporter.warning(
-                    '"table cell spanning" not supported', base_node=node)
-        self.context.append(len(self.body))
-
-    def depart_entry(self, node):
-        start = self.context.pop()
-        self._active_table.append_cell(self.body[start:])
-        del self.body[start:]
-
-    def visit_enumerated_list(self, node):
-        self.list_start(node)
-
-    def depart_enumerated_list(self, node):
-        self.list_end()
-
-    def visit_error(self, node):
-        self.visit_admonition(node, 'error')
-
-    depart_error = depart_admonition
-
-    def visit_field(self, node):
-        pass
-
-    def depart_field(self, node):
-        pass
-
-    def visit_field_body(self, node):
-        if self._in_docinfo:
-            name_normalized = self._field_name.lower().replace(" ","_")
-            self._docinfo_names[name_normalized] = self._field_name
-            self.visit_docinfo_item(node, name_normalized)
-            raise nodes.SkipNode
-
-    def depart_field_body(self, node):
-        pass
-
-    def visit_field_list(self, node):
-        self.indent(FIELD_LIST_INDENT)
-
-    def depart_field_list(self, node):
-        self.dedent()
-
-    def visit_field_name(self, node):
-        if self._in_docinfo:
-            self._field_name = node.astext()
-            raise nodes.SkipNode
-        else:
-            self.body.append(self.defs['field_name'][0])
-
-    def depart_field_name(self, node):
-        self.body.append(self.defs['field_name'][1])
-
-    def visit_figure(self, node):
-        self.indent(2.5)
-        self.indent(0)
-
-    def depart_figure(self, node):
-        self.dedent()
-        self.dedent()
-
-    def visit_footer(self, node):
-        self.document.reporter.warning('"footer" not supported',
-                base_node=node)
-
-    def depart_footer(self, node):
-        pass
-
-    def visit_footnote(self, node):
-        num, text = node.astext().split(None, 1)
-        num = num.strip()
-        self.body.append('.IP [%s] 5\n' % self.deunicode(num))
-
-    def depart_footnote(self, node):
-        pass
-
-    def footnote_backrefs(self, node):
-        self.document.reporter.warning('"footnote_backrefs" not supported',
-                base_node=node)
-
-    def visit_footnote_reference(self, node):
-        self.body.append('['+self.deunicode(node.astext())+']')
-        raise nodes.SkipNode
-
-    def depart_footnote_reference(self, node):
-        pass
-
-    def visit_generated(self, node):
-        pass
-
-    def depart_generated(self, node):
-        pass
-
-    def visit_header(self, node):
-        raise NotImplementedError, node.astext()
-
-    def depart_header(self, node):
-        pass
-
-    def visit_hint(self, node):
-        self.visit_admonition(node, 'hint')
-
-    depart_hint = depart_admonition
-
-    def visit_subscript(self, node):
-        self.body.append('\\s-2\\d')
-
-    def depart_subscript(self, node):
-        self.body.append('\\u\\s0')
-
-    def visit_superscript(self, node):
-        self.body.append('\\s-2\\u')
-
-    def depart_superscript(self, node):
-        self.body.append('\\d\\s0')
-
-    def visit_attribution(self, node):
-        self.body.append('\\(em ')
-
-    def depart_attribution(self, node):
-        self.body.append('\n')
-
-    def visit_image(self, node):
-        self.document.reporter.warning('"image" not supported',
-                base_node=node)
-        text = []
-        if 'alt' in node.attributes:
-            text.append(node.attributes['alt'])
-        if 'uri' in node.attributes:
-            text.append(node.attributes['uri'])
-        self.body.append('[image: %s]\n' % ('/'.join(text)))
-        raise nodes.SkipNode
-
-    def visit_important(self, node):
-        self.visit_admonition(node, 'important')
-
-    depart_important = depart_admonition
-
-    def visit_label(self, node):
-        # footnote and citation
-        if (isinstance(node.parent, nodes.footnote)
-            or isinstance(node.parent, nodes.citation)):
-            raise nodes.SkipNode
-        self.document.reporter.warning('"unsupported "label"',
-                base_node=node)
-        self.body.append('[')
-
-    def depart_label(self, node):
-        self.body.append(']\n')
-
-    def visit_legend(self, node):
-        pass
-
-    def depart_legend(self, node):
-        pass
-
-    # WHAT should we use .INDENT, .UNINDENT ?
-    def visit_line_block(self, node):
-        self._line_block += 1
-        if self._line_block == 1:
-            self.body.append('.sp\n')
-            self.body.append('.nf\n')
-        else:
-            self.body.append('.in +2\n')
-
-    def depart_line_block(self, node):
-        self._line_block -= 1
-        if self._line_block == 0:
-            self.body.append('.fi\n')
-            self.body.append('.sp\n')
-        else:
-            self.body.append('.in -2\n')
-
-    def visit_line(self, node):
-        pass
-
-    def depart_line(self, node):
-        self.body.append('\n')
-
-    def visit_list_item(self, node):
-        # man 7 man argues to use ".IP" instead of ".TP"
-        self.body.append('.IP %s %d\n' % (
-                self._list_char[-1].next(),
-                self._list_char[-1].get_width(),))
-
-    def depart_list_item(self, node):
-        pass
-
-    def visit_literal(self, node):
-        self.body.append(self.defs['literal'][0])
-
-    def depart_literal(self, node):
-        self.body.append(self.defs['literal'][1])
-
-    def visit_literal_block(self, node):
-        self.body.append(self.defs['literal_block'][0])
-        self._in_literal = True
-
-    def depart_literal_block(self, node):
-        self._in_literal = False
-        self.body.append(self.defs['literal_block'][1])
-
-    def visit_meta(self, node):
-        raise NotImplementedError, node.astext()
-
-    def depart_meta(self, node):
-        pass
-
-    def visit_note(self, node):
-        self.visit_admonition(node, 'note')
-
-    depart_note = depart_admonition
-
-    def indent(self, by=0.5):
-        # if we are in a section ".SH" there already is a .RS
-        step = self._indent[-1]
-        self._indent.append(by)
-        self.body.append(self.defs['indent'][0] % step)
-
-    def dedent(self):
-        self._indent.pop()
-        self.body.append(self.defs['indent'][1])
-
-    def visit_option_list(self, node):
-        self.indent(OPTION_LIST_INDENT)
-
-    def depart_option_list(self, node):
-        self.dedent()
-
-    def visit_option_list_item(self, node):
-        # one item of the list
-        self.body.append(self.defs['option_list_item'][0])
-
-    def depart_option_list_item(self, node):
-        self.body.append(self.defs['option_list_item'][1])
-
-    def visit_option_group(self, node):
-        # as one option could have several forms it is a group
-        # options without parameter bold only, .B, -v
-        # options with parameter bold italic, .BI, -f file
-        #
-        # we do not know if .B or .BI
-        self.context.append('.B')           # blind guess
-        self.context.append(len(self.body)) # to be able to insert later
-        self.context.append(0)              # option counter
-
-    def depart_option_group(self, node):
-        self.context.pop()  # the counter
-        start_position = self.context.pop()
-        text = self.body[start_position:]
-        del self.body[start_position:]
-        self.body.append('%s%s\n' % (self.context.pop(), ''.join(text)))
-
-    def visit_option(self, node):
-        # each form of the option will be presented separately
-        if self.context[-1] > 0:
-            self.body.append(', ')
-        if self.context[-3] == '.BI':
-            self.body.append('\\')
-        self.body.append(' ')
-
-    def depart_option(self, node):
-        self.context[-1] += 1
-
-    def visit_option_string(self, node):
-        # do not know if .B or .BI
-        pass
-
-    def depart_option_string(self, node):
-        pass
-
-    def visit_option_argument(self, node):
-        self.context[-3] = '.BI' # bold/italic alternate
-        if node['delimiter'] != ' ':
-            self.body.append('\\fB%s ' % node['delimiter'])
-        elif self.body[len(self.body)-1].endswith('='):
-            # a blank only means no blank in output, just changing font
-            self.body.append(' ')
-        else:
-            # blank backslash blank, switch font then a blank
-            self.body.append(' \\ ')
-
-    def depart_option_argument(self, node):
-        pass
-
-    def visit_organization(self, node):
-        self.visit_docinfo_item(node, 'organization')
-
-    def depart_organization(self, node):
-        pass
-
-    def visit_paragraph(self, node):
-        # ``.PP`` : Start standard indented paragraph.
-        # ``.LP`` : Start block paragraph, all except the first.
-        # ``.P [type]``  : Start paragraph type.
-        # NOTE dont use paragraph starts because they reset indentation.
-        # ``.sp`` is only vertical space
-        self.ensure_eol()
-        self.body.append('.sp\n')
-
-    def depart_paragraph(self, node):
-        self.body.append('\n')
-
-    def visit_problematic(self, node):
-        self.body.append(self.defs['problematic'][0])
-
-    def depart_problematic(self, node):
-        self.body.append(self.defs['problematic'][1])
-
-    def visit_raw(self, node):
-        if node.get('format') == 'manpage':
-            self.body.append(node.astext() + "\n")
-        # Keep non-manpage raw text out of output:
-        raise nodes.SkipNode
-
-    def visit_reference(self, node):
-        """E.g. link or email address."""
-        self.body.append(self.defs['reference'][0])
-
-    def depart_reference(self, node):
-        self.body.append(self.defs['reference'][1])
-
-    def visit_revision(self, node):
-        self.visit_docinfo_item(node, 'revision')
-
-    depart_revision = depart_docinfo_item
-
-    def visit_row(self, node):
-        self._active_table.new_row()
-
-    def depart_row(self, node):
-        pass
-
-    def visit_section(self, node):
-        self.section_level += 1
-
-    def depart_section(self, node):
-        self.section_level -= 1
-
-    def visit_status(self, node):
-        self.visit_docinfo_item(node, 'status')
-
-    depart_status = depart_docinfo_item
-
-    def visit_strong(self, node):
-        self.body.append(self.defs['strong'][0])
-
-    def depart_strong(self, node):
-        self.body.append(self.defs['strong'][1])
-
-    def visit_substitution_definition(self, node):
-        """Internal only."""
-        raise nodes.SkipNode
-
-    def visit_substitution_reference(self, node):
-        self.document.reporter.warning('"substitution_reference" not supported',
-                base_node=node)
-
-    def visit_subtitle(self, node):
-        if isinstance(node.parent, nodes.sidebar):
-            self.body.append(self.defs['strong'][0])
-        elif isinstance(node.parent, nodes.document):
-            self.visit_docinfo_item(node, 'subtitle')
-        elif isinstance(node.parent, nodes.section):
-            self.body.append(self.defs['strong'][0])
-
-    def depart_subtitle(self, node):
-        # document subtitle calls SkipNode
-        self.body.append(self.defs['strong'][1]+'\n.PP\n')
-
-    def visit_system_message(self, node):
-        # TODO add report_level
-        #if node['level'] < self.document.reporter['writer'].report_level:
-        #    Level is too low to display:
-        #    raise nodes.SkipNode
-        attr = {}
-        backref_text = ''
-        if node.hasattr('id'):
-            attr['name'] = node['id']
-        if node.hasattr('line'):
-            line = ', line %s' % node['line']
-        else:
-            line = ''
-        self.body.append('.IP "System Message: %s/%s (%s:%s)"\n'
-                         % (node['type'], node['level'], node['source'], line))
-
-    def depart_system_message(self, node):
-        pass
-
-    def visit_table(self, node):
-        self._active_table = Table()
-
-    def depart_table(self, node):
-        self.ensure_eol()
-        self.body.extend(self._active_table.as_list())
-        self._active_table = None
-
-    def visit_target(self, node):
-        # targets are in-document hyper targets, without any use for man-pages.
-        raise nodes.SkipNode
-
-    def visit_tbody(self, node):
-        pass
-
-    def depart_tbody(self, node):
-        pass
-
-    def visit_term(self, node):
-        self.body.append(self.defs['term'][0])
-
-    def depart_term(self, node):
-        self.body.append(self.defs['term'][1])
-
-    def visit_tgroup(self, node):
-        pass
-
-    def depart_tgroup(self, node):
-        pass
-
-    def visit_thead(self, node):
-        # MAYBE double line '='
-        pass
-
-    def depart_thead(self, node):
-        # MAYBE double line '='
-        pass
-
-    def visit_tip(self, node):
-        self.visit_admonition(node, 'tip')
-
-    depart_tip = depart_admonition
-
-    def visit_title(self, node):
-        if isinstance(node.parent, nodes.topic):
-            self.body.append(self.defs['topic-title'][0])
-        elif isinstance(node.parent, nodes.sidebar):
-            self.body.append(self.defs['sidebar-title'][0])
-        elif isinstance(node.parent, nodes.admonition):
-            self.body.append('.IP "')
-        elif self.section_level == 0:
-            self._docinfo['title'] = node.astext()
-            # document title for .TH
-            self._docinfo['title_upper'] = node.astext().upper()
-            raise nodes.SkipNode
-        elif self.section_level == 1:
-            self.body.append('.SH ')
-            for n in node.traverse(nodes.Text):
-                n.parent.replace(n, nodes.Text(n.astext().upper()))
-        else:
-            self.body.append('.SS ')
-
-    def depart_title(self, node):
-        if isinstance(node.parent, nodes.admonition):
-            self.body.append('"')
-        self.body.append('\n')
-
-    def visit_title_reference(self, node):
-        """inline citation reference"""
-        self.body.append(self.defs['title_reference'][0])
-
-    def depart_title_reference(self, node):
-        self.body.append(self.defs['title_reference'][1])
-
-    def visit_topic(self, node):
-        pass
-
-    def depart_topic(self, node):
-        pass
-
-    def visit_sidebar(self, node):
-        pass
-
-    def depart_sidebar(self, node):
-        pass
-
-    def visit_rubric(self, node):
-        pass
-
-    def depart_rubric(self, node):
-        pass
-
-    def visit_transition(self, node):
-        # .PP      Begin a new paragraph and reset prevailing indent.
-        # .sp N    leaves N lines of blank space.
-        # .ce      centers the next line
-        self.body.append('\n.sp\n.ce\n----\n')
-
-    def depart_transition(self, node):
-        self.body.append('\n.ce 0\n.sp\n')
-
-    def visit_version(self, node):
-        self.visit_docinfo_item(node, 'version')
-
-    def visit_warning(self, node):
-        self.visit_admonition(node, 'warning')
-
-    depart_warning = depart_admonition
-
-    def unimplemented_visit(self, node):
-        raise NotImplementedError('visiting unimplemented node type: %s'
-                                  % node.__class__.__name__)
-
-# The following part is taken from the Docutils rst2man.py script:
-if __name__ == "__main__":
-    from docutils.core import publish_cmdline, default_description
-    description = ("Generates plain unix manual documents.  " +
-                   default_description)
-    publish_cmdline(writer=Writer(), description=description)
-
-# vim: set fileencoding=utf-8 et ts=4 ai :
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/runrst	Tue May 11 17:03:44 2010 -0500
@@ -0,0 +1,42 @@
+#!/usr/bin/env python
+#
+# runrst - register custom roles and run correct writer
+#
+# Copyright 2010 Matt Mackall <mpm@selenic.com> and others
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+
+"""usage: %s WRITER args...
+
+where WRITER is the name of a Docutils writer such as 'html' or 'manpage'
+"""
+
+import sys
+from docutils.parsers.rst import roles
+from docutils.core import publish_cmdline
+from docutils import nodes, utils
+
+def role_hg(name, rawtext, text, lineno, inliner,
+            options={}, content=[]):
+    text = "hg " + utils.unescape(text)
+    linktext = nodes.literal(rawtext, text)
+    parts = text.split()
+    cmd, args = parts[1], parts[2:]
+    if cmd == 'help' and args:
+        cmd = args[0] # link to 'dates' for 'hg help dates'
+    node = nodes.reference(rawtext, '', linktext,
+                           refuri="hg.1.html#%s" % cmd)
+    return [node], []
+
+roles.register_local_role("hg", role_hg)
+
+if __name__ == "__main__":
+    if len(sys.argv) < 2:
+        sys.stderr.write(__doc__ % sys.argv[0])
+        sys.exit(1)
+
+    writer = sys.argv[1]
+    del sys.argv[1]
+
+    publish_cmdline(writer_name=writer)
--- a/hgext/acl.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/hgext/acl.py	Tue May 11 17:03:44 2010 -0500
@@ -7,55 +7,176 @@
 
 '''hooks for controlling repository access
 
-This hook makes it possible to allow or deny write access to portions
-of a repository when receiving incoming changesets.
+This hook makes it possible to allow or deny write access to given
+branches and paths of a repository when receiving incoming changesets
+via pretxnchangegroup and pretxncommit.
 
 The authorization is matched based on the local user name on the
 system where the hook runs, and not the committer of the original
 changeset (since the latter is merely informative).
 
 The acl hook is best used along with a restricted shell like hgsh,
-preventing authenticating users from doing anything other than
-pushing or pulling. The hook is not safe to use if users have
-interactive shell access, as they can then disable the hook.
-Nor is it safe if remote users share an account, because then there
-is no way to distinguish them.
+preventing authenticating users from doing anything other than pushing
+or pulling. The hook is not safe to use if users have interactive
+shell access, as they can then disable the hook. Nor is it safe if
+remote users share an account, because then there is no way to
+distinguish them.
+
+The order in which access checks are performed is:
+
+1) Deny  list for branches (section ``acl.deny.branches``)
+2) Allow list for branches (section ``acl.allow.branches``)
+3) Deny  list for paths    (section ``acl.deny``)
+4) Allow list for paths    (section ``acl.allow``)
+
+The allow and deny sections take key-value pairs.
+
+Branch-based Access Control
+---------------------------
+
+Use the ``acl.deny.branches`` and ``acl.allow.branches`` sections to
+have branch-based access control. Keys in these sections can be
+either:
+
+- a branch name, or
+- an asterisk, to match any branch;
+
+The corresponding values can be either:
 
-To use this hook, configure the acl extension in your hgrc like this::
+- a comma-separated list containing users and groups, or
+- an asterisk, to match anyone;
+
+Path-based Access Control
+-------------------------
+
+Use the ``acl.deny`` and ``acl.allow`` sections to have path-based
+access control. Keys in these sections accept a subtree pattern (with
+a glob syntax by default). The corresponding values follow the same
+syntax as the other sections above.
 
-  [extensions]
-  acl =
+Groups
+------
+
+Group names must be prefixed with an ``@`` symbol. Specifying a group
+name has the same effect as specifying all the users in that group.
+
+You can define group members in the ``acl.groups`` section.
+If a group name is not defined there, and Mercurial is running under
+a Unix-like system, the list of users will be taken from the OS.
+Otherwise, an exception will be raised.
+
+Example Configuration
+---------------------
+
+::
 
   [hooks]
+
+  # Use this if you want to check access restrictions at commit time
+  pretxncommit.acl = python:hgext.acl.hook
+  
+  # Use this if you want to check access restrictions for pull, push,
+  # bundle and serve.
   pretxnchangegroup.acl = python:hgext.acl.hook
 
   [acl]
-  # Check whether the source of incoming changes is in this list
-  # ("serve" == ssh or http, "push", "pull", "bundle")
+  # Allow or deny access for incoming changes only if their source is
+  # listed here, let them pass otherwise. Source is "serve" for all
+  # remote access (http or ssh), "push", "pull" or "bundle" when the
+  # related commands are run locally.
+  # Default: serve
   sources = serve
 
-The allow and deny sections take a subtree pattern as key (with a glob
-syntax by default), and a comma separated list of users as the
-corresponding value. The deny list is checked before the allow list
-is. ::
+  [acl.deny.branches] 
+  
+  # Everyone is denied to the frozen branch: 
+  frozen-branch = * 
+  
+  # A bad user is denied on all branches: 
+  * = bad-user 
+  
+  [acl.allow.branches] 
+  
+  # A few users are allowed on branch-a: 
+  branch-a = user-1, user-2, user-3 
+  
+  # Only one user is allowed on branch-b: 
+  branch-b = user-1 
+  
+  # The super user is allowed on any branch: 
+  * = super-user 
+  
+  # Everyone is allowed on branch-for-tests: 
+  branch-for-tests = * 
+
+  [acl.deny]
+  # This list is checked first. If a match is found, acl.allow is not
+  # checked. All users are granted access if acl.deny is not present.
+  # Format for both lists: glob pattern = user, ..., @group, ...
+
+  # To match everyone, use an asterisk for the user:
+  # my/glob/pattern = *
+
+  # user6 will not have write access to any file:
+  ** = user6
+
+  # Group "hg-denied" will not have write access to any file:
+  ** = @hg-denied
+
+  # Nobody will be able to change "DONT-TOUCH-THIS.txt", despite
+  # everyone being able to change all other files. See below.
+  src/main/resources/DONT-TOUCH-THIS.txt = *
 
   [acl.allow]
-  # If acl.allow is not present, all users are allowed by default.
-  # An empty acl.allow section means no users allowed.
+  # if acl.allow is not present, all users are allowed by default
+  # empty acl.allow = no users allowed
+
+  # User "doc_writer" has write access to any file under the "docs"
+  # folder:
   docs/** = doc_writer
+
+  # User "jack" and group "designers" have write access to any file
+  # under the "images" folder:
+  images/** = jack, @designers
+
+  # Everyone (except for "user6" - see acl.deny above) will have write
+  # access to any file under the "resources" folder (except for 1
+  # file. See acl.deny):
+  src/main/resources/** = *
+
   .hgtags = release_engineer
 
-  [acl.deny]
-  # If acl.deny is not present, no users are refused by default.
-  # An empty acl.deny section means all users allowed.
-  glob pattern = user4, user5
-   ** = user6
 '''
 
 from mercurial.i18n import _
 from mercurial import util, match
 import getpass, urllib
 
+def _getusers(ui, group):
+
+    # First, try to use group definition from section [acl.groups]
+    hgrcusers = ui.configlist('acl.groups', group)
+    if hgrcusers:
+        return hgrcusers
+
+    ui.debug('acl: "%s" not defined in [acl.groups]\n' % group)
+    # If no users found in group definition, get users from OS-level group
+    try:
+        return util.groupmembers(group)
+    except KeyError:
+        raise util.Abort(_("group '%s' is undefined") % group)
+
+def _usermatch(ui, user, usersorgroups):
+
+    if usersorgroups == '*':
+        return True
+
+    for ug in usersorgroups.replace(',', ' ').split():
+        if user == ug or ug.find('@') == 0 and user in _getusers(ui, ug[1:]):
+            return True
+
+    return False
+
 def buildmatch(ui, repo, user, key):
     '''return tuple of (match function, list enabled).'''
     if not ui.has_section(key):
@@ -63,19 +184,26 @@
         return None
 
     pats = [pat for pat, users in ui.configitems(key)
-            if users == '*' or user in users.replace(',', ' ').split()]
+            if _usermatch(ui, user, users)]
     ui.debug('acl: %s enabled, %d entries for user %s\n' %
              (key, len(pats), user))
+
+    if not repo:
+        if pats:
+            return lambda b: '*' in pats or b in pats
+        return lambda b: False
+
     if pats:
         return match.match(repo.root, '', pats)
     return match.exact(repo.root, '', [])
 
 
 def hook(ui, repo, hooktype, node=None, source=None, **kwargs):
-    if hooktype != 'pretxnchangegroup':
+    if hooktype not in ['pretxnchangegroup', 'pretxncommit']:
         raise util.Abort(_('config error - hook type "%s" cannot stop '
-                           'incoming changesets') % hooktype)
-    if source not in ui.config('acl', 'sources', 'serve').split():
+                           'incoming changesets nor commits') % hooktype)
+    if (hooktype == 'pretxnchangegroup' and
+        source not in ui.config('acl', 'sources', 'serve').split()):
         ui.debug('acl: changes have source "%s" - skipping\n' % source)
         return
 
@@ -90,12 +218,28 @@
 
     cfg = ui.config('acl', 'config')
     if cfg:
-        ui.readconfig(cfg, sections = ['acl.allow', 'acl.deny'])
+        ui.readconfig(cfg, sections = ['acl.groups', 'acl.allow.branches',
+        'acl.deny.branches', 'acl.allow', 'acl.deny'])
+
+    allowbranches = buildmatch(ui, None, user, 'acl.allow.branches')
+    denybranches = buildmatch(ui, None, user, 'acl.deny.branches')
     allow = buildmatch(ui, repo, user, 'acl.allow')
     deny = buildmatch(ui, repo, user, 'acl.deny')
 
     for rev in xrange(repo[node], len(repo)):
         ctx = repo[rev]
+        branch = ctx.branch()
+        if denybranches and denybranches(branch):
+            raise util.Abort(_('acl: user "%s" denied on branch "%s"'
+                               ' (changeset "%s")')
+                               % (user, branch, ctx))
+        if allowbranches and not allowbranches(branch):
+            raise util.Abort(_('acl: user "%s" not allowed on branch "%s"'
+                               ' (changeset "%s")')
+                               % (user, branch, ctx))
+        ui.debug('acl: branch access granted: "%s" on branch "%s"\n'
+        % (ctx, branch))
+
         for f in ctx.files():
             if deny and deny(f):
                 ui.debug('acl: user %s denied on %s\n' % (user, f))
--- a/hgext/bookmarks.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/hgext/bookmarks.py	Tue May 11 17:03:44 2010 -0500
@@ -88,10 +88,10 @@
 
     Bookmarks are pointers to certain commits that move when
     committing. Bookmarks are local. They can be renamed, copied and
-    deleted. It is possible to use bookmark names in 'hg merge' and
-    'hg update' to merge and update respectively to a given bookmark.
+    deleted. It is possible to use bookmark names in :hg:`merge` and
+    :hg:`update` to merge and update respectively to a given bookmark.
 
-    You can use 'hg bookmark NAME' to set a bookmark on the working
+    You can use :hg:`bookmark NAME` to set a bookmark on the working
     directory's parent revision with the given name. If you specify
     a revision using -r REV (where REV may be an existing bookmark),
     the bookmark is assigned to that revision.
@@ -152,15 +152,22 @@
             for bmark, n in marks.iteritems():
                 if ui.configbool('bookmarks', 'track.current'):
                     current = repo._bookmarkcurrent
-                    prefix = (bmark == current and n == cur) and '*' or ' '
+                    if bmark == current and n == cur:
+                        prefix, label = '*', 'bookmarks.current'
+                    else:
+                        prefix, label = ' ', ''
                 else:
-                    prefix = (n == cur) and '*' or ' '
+                    if n == cur:
+                        prefix, label = '*', 'bookmarks.current'
+                    else:
+                        prefix, label = ' ', ''
 
                 if ui.quiet:
-                    ui.write("%s\n" % bmark)
+                    ui.write("%s\n" % bmark, label=label)
                 else:
                     ui.write(" %s %-25s %d:%s\n" % (
-                        prefix, bmark, repo.changelog.rev(n), hexfn(n)))
+                        prefix, bmark, repo.changelog.rev(n), hexfn(n)),
+                        label=label)
         return
 
 def _revstostrip(changelog, node):
@@ -234,10 +241,10 @@
                 file.close()
             return mark
 
-        def rollback(self):
+        def rollback(self, *args):
             if os.path.exists(self.join('undo.bookmarks')):
                 util.rename(self.join('undo.bookmarks'), self.join('bookmarks'))
-            return super(bookmark_repo, self).rollback()
+            return super(bookmark_repo, self).rollback(*args)
 
         def lookup(self, key):
             if key in self._bookmarks:
@@ -301,7 +308,7 @@
                 super(bookmark_repo, self).invalidate()
                 for attr in ('_bookmarks', '_bookmarkcurrent'):
                     if attr in self.__dict__:
-                        delattr(repo, attr)
+                        delattr(self, attr)
 
     repo.__class__ = bookmark_repo
 
@@ -332,3 +339,5 @@
           ('m', 'rename', '', _('rename a given bookmark'))],
          _('hg bookmarks [-f] [-d] [-m NAME] [-r REV] [NAME]')),
 }
+
+colortable = {'bookmarks.current': 'green'}
--- a/hgext/churn.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/hgext/churn.py	Tue May 11 17:03:44 2010 -0500
@@ -10,7 +10,7 @@
 
 from mercurial.i18n import _
 from mercurial import patch, cmdutil, util, templater
-import sys, os
+import os
 import time, datetime
 
 def maketemplater(ui, repo, tmpl):
@@ -48,7 +48,7 @@
             tmpl.show(ctx)
             return ui.popbuffer()
 
-    state = {'count': 0, 'pct': 0}
+    state = {'count': 0}
     rate = {}
     df = False
     if opts.get('date'):
@@ -74,20 +74,13 @@
             lines = changedlines(ui, repo, ctx1, ctx, fns)
             rate[key] = [r + l for r, l in zip(rate.get(key, (0, 0)), lines)]
 
-        if opts.get('progress'):
-            state['count'] += 1
-            newpct = int(100.0 * state['count'] / max(len(repo), 1))
-            if state['pct'] < newpct:
-                state['pct'] = newpct
-                ui.write("\r" + _("generating stats: %d%%") % state['pct'])
-                sys.stdout.flush()
+        state['count'] += 1
+        ui.progress(_('analyzing'), state['count'], total=len(repo))
 
     for ctx in cmdutil.walkchangerevs(repo, m, opts, prep):
         continue
 
-    if opts.get('progress'):
-        ui.write("\r")
-        sys.stdout.flush()
+    ui.progress(_('analyzing'), None)
 
     return rate
 
@@ -160,8 +153,10 @@
         def format(name, (added, removed)):
             return "%s %15s %s%s\n" % (pad(name, maxname),
                                        '+%d/-%d' % (added, removed),
-                                       '+' * charnum(added),
-                                       '-' * charnum(removed))
+                                       ui.label('+' * charnum(added),
+                                                'diffstat.inserted'),
+                                       ui.label('-' * charnum(removed),
+                                                'diffstat.deleted'))
     else:
         width -= 6
         def format(name, count):
@@ -188,6 +183,6 @@
           ('s', 'sort', False, _('sort by key (default: sort by count)')),
           ('', 'diffstat', False, _('display added/removed lines separately')),
           ('', 'aliases', '', _('file with email aliases')),
-          ('', 'progress', None, _('show progress'))],
-         _("hg churn [-d DATE] [-r REV] [--aliases FILE] [--progress] [FILE]")),
+          ],
+         _("hg churn [-d DATE] [-r REV] [--aliases FILE] [FILE]")),
 }
--- a/hgext/color.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/hgext/color.py	Tue May 11 17:03:44 2010 -0500
@@ -61,314 +61,227 @@
   resolve.resolved = green bold
 
   bookmarks.current = green
+
+The color extension will try to detect whether to use ANSI codes or
+Win32 console APIs, unless it is made explicit::
+
+  [color]
+  mode = ansi
+
+Any value other than 'ansi', 'win32', or 'auto' will disable color.
+
 '''
 
 import os, sys
 
-from mercurial import cmdutil, commands, extensions
+from mercurial import commands, dispatch, extensions
 from mercurial.i18n import _
 
 # start and stop parameters for effects
-_effect_params = {'none': 0,
-                  'black': 30,
-                  'red': 31,
-                  'green': 32,
-                  'yellow': 33,
-                  'blue': 34,
-                  'magenta': 35,
-                  'cyan': 36,
-                  'white': 37,
-                  'bold': 1,
-                  'italic': 3,
-                  'underline': 4,
-                  'inverse': 7,
-                  'black_background': 40,
-                  'red_background': 41,
-                  'green_background': 42,
-                  'yellow_background': 43,
-                  'blue_background': 44,
-                  'purple_background': 45,
-                  'cyan_background': 46,
-                  'white_background': 47}
+_effects = {'none': 0, 'black': 30, 'red': 31, 'green': 32, 'yellow': 33,
+            'blue': 34, 'magenta': 35, 'cyan': 36, 'white': 37, 'bold': 1,
+            'italic': 3, 'underline': 4, 'inverse': 7,
+            'black_background': 40, 'red_background': 41,
+            'green_background': 42, 'yellow_background': 43,
+            'blue_background': 44, 'purple_background': 45,
+            'cyan_background': 46, 'white_background': 47}
+
+_styles = {'grep.match': 'red bold',
+           'diff.changed': 'white',
+           'diff.deleted': 'red',
+           'diff.diffline': 'bold',
+           'diff.extended': 'cyan bold',
+           'diff.file_a': 'red bold',
+           'diff.file_b': 'green bold',
+           'diff.hunk': 'magenta',
+           'diff.inserted': 'green',
+           'diff.trailingwhitespace': 'bold red_background',
+           'diffstat.deleted': 'red',
+           'diffstat.inserted': 'green',
+           'log.changeset': 'yellow',
+           'resolve.resolved': 'green bold',
+           'resolve.unresolved': 'red bold',
+           'status.added': 'green bold',
+           'status.clean': 'none',
+           'status.copied': 'none',
+           'status.deleted': 'cyan bold underline',
+           'status.ignored': 'black bold',
+           'status.modified': 'blue bold',
+           'status.removed': 'red bold',
+           'status.unknown': 'magenta bold underline'}
+
 
 def render_effects(text, effects):
     'Wrap text in commands to turn on each effect.'
-    start = [str(_effect_params[e]) for e in ['none'] + effects]
+    if not text:
+        return text
+    start = [str(_effects[e]) for e in ['none'] + effects.split()]
     start = '\033[' + ';'.join(start) + 'm'
-    stop = '\033[' + str(_effect_params['none']) + 'm'
+    stop = '\033[' + str(_effects['none']) + 'm'
     return ''.join([start, text, stop])
 
-def _colorstatuslike(abbreviations, effectdefs, orig, ui, repo, *pats, **opts):
-    '''run a status-like command with colorized output'''
-    delimiter = opts.get('print0') and '\0' or '\n'
-
-    nostatus = opts.get('no_status')
-    opts['no_status'] = False
-    # run original command and capture its output
-    ui.pushbuffer()
-    retval = orig(ui, repo, *pats, **opts)
-    # filter out empty strings
-    lines_with_status = [line for line in ui.popbuffer().split(delimiter) if line]
-
-    if nostatus:
-        lines = [l[2:] for l in lines_with_status]
-    else:
-        lines = lines_with_status
-
-    # apply color to output and display it
-    for i in xrange(len(lines)):
-        try:
-            status = abbreviations[lines_with_status[i][0]]
-        except KeyError:
-            # Ignore lines with invalid codes, especially in the case of
-            # of unknown filenames containing newlines (issue2036).
-            pass
-        else:
-            effects = effectdefs[status]
-            if effects:
-                lines[i] = render_effects(lines[i], effects)
-        ui.write(lines[i] + delimiter)
-    return retval
-
-
-_status_abbreviations = { 'M': 'modified',
-                          'A': 'added',
-                          'R': 'removed',
-                          '!': 'deleted',
-                          '?': 'unknown',
-                          'I': 'ignored',
-                          'C': 'clean',
-                          ' ': 'copied', }
-
-_status_effects = { 'modified': ['blue', 'bold'],
-                    'added': ['green', 'bold'],
-                    'removed': ['red', 'bold'],
-                    'deleted': ['cyan', 'bold', 'underline'],
-                    'unknown': ['magenta', 'bold', 'underline'],
-                    'ignored': ['black', 'bold'],
-                    'clean': ['none'],
-                    'copied': ['none'], }
-
-def colorstatus(orig, ui, repo, *pats, **opts):
-    '''run the status command with colored output'''
-    return _colorstatuslike(_status_abbreviations, _status_effects,
-                            orig, ui, repo, *pats, **opts)
-
-
-_resolve_abbreviations = { 'U': 'unresolved',
-                           'R': 'resolved', }
-
-_resolve_effects = { 'unresolved': ['red', 'bold'],
-                     'resolved': ['green', 'bold'], }
-
-def colorresolve(orig, ui, repo, *pats, **opts):
-    '''run the resolve command with colored output'''
-    if not opts.get('list'):
-        # only colorize for resolve -l
-        return orig(ui, repo, *pats, **opts)
-    return _colorstatuslike(_resolve_abbreviations, _resolve_effects,
-                            orig, ui, repo, *pats, **opts)
-
-
-_bookmark_effects = { 'current': ['green'] }
-
-def colorbookmarks(orig, ui, repo, *pats, **opts):
-    def colorize(orig, s):
-        lines = s.split('\n')
-        for i, line in enumerate(lines):
-            if line.startswith(" *"):
-                lines[i] = render_effects(line, _bookmark_effects['current'])
-        orig('\n'.join(lines))
-    oldwrite = extensions.wrapfunction(ui, 'write', colorize)
-    try:
-        orig(ui, repo, *pats, **opts)
-    finally:
-        ui.write = oldwrite
-
-def colorqseries(orig, ui, repo, *dummy, **opts):
-    '''run the qseries command with colored output'''
-    ui.pushbuffer()
-    retval = orig(ui, repo, **opts)
-    patchlines = ui.popbuffer().splitlines()
-    patchnames = repo.mq.series
-
-    for patch, patchname in zip(patchlines, patchnames):
-        if opts['missing']:
-            effects = _patch_effects['missing']
-        # Determine if patch is applied.
-        elif [applied for applied in repo.mq.applied
-               if patchname == applied.name]:
-            effects = _patch_effects['applied']
-        else:
-            effects = _patch_effects['unapplied']
-
-        patch = patch.replace(patchname, render_effects(patchname, effects), 1)
-        ui.write(patch + '\n')
-    return retval
-
-_patch_effects = { 'applied': ['blue', 'bold', 'underline'],
-                    'missing': ['red', 'bold'],
-                    'unapplied': ['black', 'bold'], }
-def colorwrap(orig, *args):
-    '''wrap ui.write for colored diff output'''
-    def _colorize(s):
-        lines = s.split('\n')
-        for i, line in enumerate(lines):
-            stripline = line
-            if line and line[0] in '+-':
-                # highlight trailing whitespace, but only in changed lines
-                stripline = line.rstrip()
-            for prefix, style in _diff_prefixes:
-                if stripline.startswith(prefix):
-                    lines[i] = render_effects(stripline, _diff_effects[style])
-                    break
-            if line != stripline:
-                lines[i] += render_effects(
-                    line[len(stripline):], _diff_effects['trailingwhitespace'])
-        return '\n'.join(lines)
-    orig(*[_colorize(s) for s in args])
+def extstyles():
+    for name, ext in extensions.extensions():
+        _styles.update(getattr(ext, 'colortable', {}))
 
-def colorshowpatch(orig, self, node):
-    '''wrap cmdutil.changeset_printer.showpatch with colored output'''
-    oldwrite = extensions.wrapfunction(self.ui, 'write', colorwrap)
-    try:
-        orig(self, node)
-    finally:
-        self.ui.write = oldwrite
-
-def colordiffstat(orig, s):
-    lines = s.split('\n')
-    for i, line in enumerate(lines):
-        if line and line[-1] in '+-':
-            name, graph = line.rsplit(' ', 1)
-            graph = graph.replace('-',
-                        render_effects('-', _diff_effects['deleted']))
-            graph = graph.replace('+',
-                        render_effects('+', _diff_effects['inserted']))
-            lines[i] = ' '.join([name, graph])
-    orig('\n'.join(lines))
-
-def colordiff(orig, ui, repo, *pats, **opts):
-    '''run the diff command with colored output'''
-    if opts.get('stat'):
-        wrapper = colordiffstat
-    else:
-        wrapper = colorwrap
-    oldwrite = extensions.wrapfunction(ui, 'write', wrapper)
-    try:
-        orig(ui, repo, *pats, **opts)
-    finally:
-        ui.write = oldwrite
-
-def colorchurn(orig, ui, repo, *pats, **opts):
-    '''run the churn command with colored output'''
-    if not opts.get('diffstat'):
-        return orig(ui, repo, *pats, **opts)
-    oldwrite = extensions.wrapfunction(ui, 'write', colordiffstat)
-    try:
-        orig(ui, repo, *pats, **opts)
-    finally:
-        ui.write = oldwrite
-
-_diff_prefixes = [('diff', 'diffline'),
-                  ('copy', 'extended'),
-                  ('rename', 'extended'),
-                  ('old', 'extended'),
-                  ('new', 'extended'),
-                  ('deleted', 'extended'),
-                  ('---', 'file_a'),
-                  ('+++', 'file_b'),
-                  ('@', 'hunk'),
-                  ('-', 'deleted'),
-                  ('+', 'inserted')]
-
-_diff_effects = {'diffline': ['bold'],
-                 'extended': ['cyan', 'bold'],
-                 'file_a': ['red', 'bold'],
-                 'file_b': ['green', 'bold'],
-                 'hunk': ['magenta'],
-                 'deleted': ['red'],
-                 'inserted': ['green'],
-                 'changed': ['white'],
-                 'trailingwhitespace': ['bold', 'red_background']}
-
-def extsetup(ui):
-    '''Initialize the extension.'''
-    _setupcmd(ui, 'diff', commands.table, colordiff, _diff_effects)
-    _setupcmd(ui, 'incoming', commands.table, None, _diff_effects)
-    _setupcmd(ui, 'log', commands.table, None, _diff_effects)
-    _setupcmd(ui, 'outgoing', commands.table, None, _diff_effects)
-    _setupcmd(ui, 'tip', commands.table, None, _diff_effects)
-    _setupcmd(ui, 'status', commands.table, colorstatus, _status_effects)
-    _setupcmd(ui, 'resolve', commands.table, colorresolve, _resolve_effects)
-
-    try:
-        mq = extensions.find('mq')
-        _setupcmd(ui, 'qdiff', mq.cmdtable, colordiff, _diff_effects)
-        _setupcmd(ui, 'qseries', mq.cmdtable, colorqseries, _patch_effects)
-    except KeyError:
-        mq = None
-
-    try:
-        rec = extensions.find('record')
-        _setupcmd(ui, 'record', rec.cmdtable, colordiff, _diff_effects)
-    except KeyError:
-        rec = None
-
-    if mq and rec:
-        _setupcmd(ui, 'qrecord', rec.cmdtable, colordiff, _diff_effects)
-    try:
-        churn = extensions.find('churn')
-        _setupcmd(ui, 'churn', churn.cmdtable, colorchurn, _diff_effects)
-    except KeyError:
-        churn = None
-
-    try:
-        bookmarks = extensions.find('bookmarks')
-        _setupcmd(ui, 'bookmarks', bookmarks.cmdtable, colorbookmarks,
-                  _bookmark_effects)
-    except KeyError:
-        # The bookmarks extension is not enabled
-        pass
-
-def _setupcmd(ui, cmd, table, func, effectsmap):
-    '''patch in command to command table and load effect map'''
-    def nocolor(orig, *args, **opts):
-
-        if (opts['no_color'] or opts['color'] == 'never' or
-            (opts['color'] == 'auto' and (os.environ.get('TERM') == 'dumb'
-                                          or not sys.__stdout__.isatty()))):
-            del opts['no_color']
-            del opts['color']
-            return orig(*args, **opts)
-
-        oldshowpatch = extensions.wrapfunction(cmdutil.changeset_printer,
-                                               'showpatch', colorshowpatch)
-        del opts['no_color']
-        del opts['color']
-        try:
-            if func is not None:
-                return func(orig, *args, **opts)
-            return orig(*args, **opts)
-        finally:
-            cmdutil.changeset_printer.showpatch = oldshowpatch
-
-    entry = extensions.wrapcommand(table, cmd, nocolor)
-    entry[1].extend([
-        ('', 'color', 'auto', _("when to colorize (always, auto, or never)")),
-        ('', 'no-color', None, _("don't colorize output (DEPRECATED)")),
-    ])
-
-    for status in effectsmap:
-        configkey = cmd + '.' + status
-        effects = ui.configlist('color', configkey)
-        if effects:
+def configstyles(ui):
+    for status, cfgeffects in ui.configitems('color'):
+        if '.' not in status:
+            continue
+        cfgeffects = ui.configlist('color', status)
+        if cfgeffects:
             good = []
-            for e in effects:
-                if e in _effect_params:
+            for e in cfgeffects:
+                if e in _effects:
                     good.append(e)
                 else:
                     ui.warn(_("ignoring unknown color/effect %r "
                               "(configured in color.%s)\n")
-                            % (e, configkey))
-            effectsmap[status] = good
+                            % (e, status))
+            _styles[status] = ' '.join(good)
+
+_buffers = None
+def style(msg, label):
+    effects = []
+    for l in label.split():
+        s = _styles.get(l, '')
+        if s:
+            effects.append(s)
+    effects = ''.join(effects)
+    if effects:
+        return '\n'.join([render_effects(s, effects)
+                          for s in msg.split('\n')])
+    return msg
+
+def popbuffer(orig, labeled=False):
+    global _buffers
+    if labeled:
+        return ''.join(style(a, label) for a, label in _buffers.pop())
+    return ''.join(a for a, label in _buffers.pop())
+
+mode = 'ansi'
+def write(orig, *args, **opts):
+    label = opts.get('label', '')
+    global _buffers
+    if _buffers:
+        _buffers[-1].extend([(str(a), label) for a in args])
+    elif mode == 'win32':
+        for a in args:
+            win32print(a, orig, **opts)
+    else:
+        return orig(*[style(str(a), label) for a in args], **opts)
+
+def write_err(orig, *args, **opts):
+    label = opts.get('label', '')
+    if mode == 'win32':
+        for a in args:
+            win32print(a, orig, **opts)
+    else:
+        return orig(*[style(str(a), label) for a in args], **opts)
+
+def uisetup(ui):
+    if ui.plain():
+        return
+    global mode
+    mode = ui.config('color', 'mode', 'auto')
+    if mode == 'auto':
+        if os.name == 'nt' and 'TERM' not in os.environ:
+            # looks line a cmd.exe console, use win32 API or nothing
+            mode = w32effects and 'win32' or 'none'
+        else:
+            mode = 'ansi'
+    if mode == 'win32':
+        if w32effects is None:
+            # only warn if color.mode is explicitly set to win32
+            ui.warn(_('win32console not found, please install pywin32\n'))
+            return
+        _effects.update(w32effects)
+    elif mode != 'ansi':
+        return
+    def colorcmd(orig, ui_, opts, cmd, cmdfunc):
+        if (opts['color'] == 'always' or
+            (opts['color'] == 'auto' and (os.environ.get('TERM') != 'dumb'
+                                          and sys.__stdout__.isatty()))):
+            global _buffers
+            _buffers = ui_._buffers
+            extensions.wrapfunction(ui_, 'popbuffer', popbuffer)
+            extensions.wrapfunction(ui_, 'write', write)
+            extensions.wrapfunction(ui_, 'write_err', write_err)
+            ui_.label = style
+            extstyles()
+            configstyles(ui)
+        return orig(ui_, opts, cmd, cmdfunc)
+    extensions.wrapfunction(dispatch, '_runcommand', colorcmd)
+
+commands.globalopts.append(('', 'color', 'auto',
+                            _("when to colorize (always, auto, or never)")))
+
+try:
+    import re, pywintypes
+    from win32console import *
+
+    # http://msdn.microsoft.com/en-us/library/ms682088%28VS.85%29.aspx
+    w32effects = {
+        'none': 0,
+        'black': 0,
+        'red': FOREGROUND_RED,
+        'green': FOREGROUND_GREEN,
+        'yellow': FOREGROUND_RED | FOREGROUND_GREEN,
+        'blue': FOREGROUND_BLUE,
+        'magenta': FOREGROUND_BLUE | FOREGROUND_RED,
+        'cyan': FOREGROUND_BLUE | FOREGROUND_GREEN,
+        'white': FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
+        'bold': FOREGROUND_INTENSITY,
+        'black_background': 0,
+        'red_background': BACKGROUND_RED,
+        'green_background': BACKGROUND_GREEN,
+        'yellow_background': BACKGROUND_RED | BACKGROUND_GREEN,
+        'blue_background': BACKGROUND_BLUE,
+        'purple_background': BACKGROUND_BLUE | BACKGROUND_RED,
+        'cyan_background': BACKGROUND_BLUE | BACKGROUND_GREEN,
+        'white_background': BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE,
+        'bold_background': BACKGROUND_INTENSITY,
+        'underline': COMMON_LVB_UNDERSCORE,     # double-byte charsets only
+        'inverse': COMMON_LVB_REVERSE_VIDEO,    # double-byte charsets only
+    }
+
+    stdout = GetStdHandle(STD_OUTPUT_HANDLE)
+    try:
+        origattr = stdout.GetConsoleScreenBufferInfo()['Attributes']
+    except pywintypes.error:
+        # stdout may be defined but not support
+        # GetConsoleScreenBufferInfo(), when called from subprocess or
+        # redirected.
+        raise ImportError()
+    ansire = re.compile('\033\[([^m]*)m([^\033]*)(.*)', re.MULTILINE | re.DOTALL)
+
+    def win32print(text, orig, **opts):
+        label = opts.get('label', '')
+        attr = 0
+
+        # determine console attributes based on labels
+        for l in label.split():
+            style = _styles.get(l, '')
+            for effect in style.split():
+                attr |= w32effects[effect]
+
+        # hack to ensure regexp finds data
+        if not text.startswith('\033['):
+            text = '\033[m' + text
+
+        # Look for ANSI-like codes embedded in text
+        m = re.match(ansire, text)
+        while m:
+            for sattr in m.group(1).split(';'):
+                if sattr:
+                    val = int(sattr)
+                    attr = val and attr|val or 0
+            stdout.SetConsoleTextAttribute(attr or origattr)
+            orig(m.group(2), **opts)
+            m = re.match(ansire, m.group(3))
+
+        # Explicity reset original attributes
+        stdout.SetConsoleTextAttribute(origattr)
+
+except ImportError:
+    w32effects = None
--- a/hgext/convert/bzr.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/hgext/convert/bzr.py	Tue May 11 17:03:44 2010 -0500
@@ -109,18 +109,16 @@
             # the file is not available anymore - was deleted
             raise IOError(_('%s is not available in %s anymore') %
                     (name, rev))
+        mode = self._modecache[(name, rev)]
         if kind == 'symlink':
             target = revtree.get_symlink_target(fileid)
             if target is None:
                 raise util.Abort(_('%s.%s symlink has no target')
                                  % (name, rev))
-            return target
+            return target, mode
         else:
             sio = revtree.get_file(fileid)
-            return sio.read()
-
-    def getmode(self, name, rev):
-        return self._modecache[(name, rev)]
+            return sio.read(), mode
 
     def getchanges(self, version):
         # set up caches: modecache and revtree
--- a/hgext/convert/common.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/hgext/convert/common.py	Tue May 11 17:03:44 2010 -0500
@@ -77,15 +77,10 @@
         raise NotImplementedError()
 
     def getfile(self, name, rev):
-        """Return file contents as a string. rev is the identifier returned
-        by a previous call to getchanges(). Raise IOError to indicate that
-        name was deleted in rev.
-        """
-        raise NotImplementedError()
-
-    def getmode(self, name, rev):
-        """Return file mode, eg. '', 'x', or 'l'. rev is the identifier
-        returned by a previous call to getchanges().
+        """Return a pair (data, mode) where data is the file content
+        as a string and mode one of '', 'x' or 'l'. rev is the
+        identifier returned by a previous call to getchanges(). Raise
+        IOError to indicate that name was deleted in rev.
         """
         raise NotImplementedError()
 
@@ -192,8 +187,8 @@
         changeset.  'files' is a list of (path, version) tuples,
         'copies' is a dictionary mapping destinations to sources,
         'source' is the source repository, and 'revmap' is a mapfile
-        of source revisions to converted revisions. Only getfile(),
-        getmode(), and lookuprev() should be called on 'source'.
+        of source revisions to converted revisions. Only getfile() and
+        lookuprev() should be called on 'source'.
 
         Note that the sink repository is not told to update itself to
         a particular revision (or even what that revision would be)
--- a/hgext/convert/convcmd.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/hgext/convert/convcmd.py	Tue May 11 17:03:44 2010 -0500
@@ -72,6 +72,25 @@
             ui.note(_("convert: %s\n") % inst)
     raise util.Abort(_('%s: unknown repository type') % path)
 
+class progresssource(object):
+    def __init__(self, ui, source, filecount):
+        self.ui = ui
+        self.source = source
+        self.filecount = filecount
+        self.retrieved = 0
+
+    def getfile(self, file, rev):
+        self.retrieved += 1
+        self.ui.progress(_('retrieving file'), self.retrieved,
+                         item=file, total=self.filecount)
+        return self.source.getfile(file, rev)
+
+    def lookuprev(self, rev):
+        return self.source.lookuprev(rev)
+
+    def close(self):
+        self.ui.progress(_('retrieving file'), None)
+
 class converter(object):
     def __init__(self, ui, source, dest, revmapfile, opts):
 
@@ -111,11 +130,13 @@
             if n in known or n in self.map:
                 continue
             known.add(n)
+            self.ui.progress(_('scanning'), len(known), unit=_('revisions'))
             commit = self.cachecommit(n)
             parents[n] = []
             for p in commit.parents:
                 parents[n].append(p)
                 visit.append(p)
+        self.ui.progress(_('scanning'), None)
 
         return parents
 
@@ -302,8 +323,10 @@
             parents = [self.map.get(p, p) for p in parents]
         except KeyError:
             parents = [b[0] for b in pbranches]
+        source = progresssource(self.ui, self.source, len(files))
         newnode = self.dest.putcommit(files, copies, parents, commit,
-                                      self.source, self.map)
+                                      source, self.map)
+        source.close()
         self.source.converted(rev, newnode)
         self.map[rev] = newnode
 
@@ -321,7 +344,7 @@
             c = None
 
             self.ui.status(_("converting...\n"))
-            for c in t:
+            for i, c in enumerate(t):                
                 num -= 1
                 desc = self.commitcache[c].desc
                 if "\n" in desc:
@@ -331,7 +354,10 @@
                 # 'utf-8'
                 self.ui.status("%d %s\n" % (num, recode(desc)))
                 self.ui.note(_("source: %s\n") % recode(c))
+                self.ui.progress(_('converting'), i, unit=_('revisions'),
+                                 total=len(t))
                 self.copy(c)
+            self.ui.progress(_('converting'), None)
 
             tags = self.source.gettags()
             ctags = {}
--- a/hgext/convert/cvs.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/hgext/convert/cvs.py	Tue May 11 17:03:44 2010 -0500
@@ -200,7 +200,7 @@
         self._parse()
         return self.heads
 
-    def _getfile(self, name, rev):
+    def getfile(self, name, rev):
 
         def chunkedread(fp, count):
             # file-objects returned by socked.makefile() do not handle
@@ -216,6 +216,7 @@
                 output.write(data)
             return output.getvalue()
 
+        self._parse()
         if rev.endswith("(DEAD)"):
             raise IOError
 
@@ -255,18 +256,8 @@
                 else:
                     raise util.Abort(_("unknown CVS response: %s") % line)
 
-    def getfile(self, file, rev):
-        self._parse()
-        data, mode = self._getfile(file, rev)
-        self.modecache[(file, rev)] = mode
-        return data
-
-    def getmode(self, file, rev):
-        return self.modecache[(file, rev)]
-
     def getchanges(self, rev):
         self._parse()
-        self.modecache = {}
         return sorted(self.files[rev].iteritems()), {}
 
     def getcommit(self, rev):
--- a/hgext/convert/cvsps.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/hgext/convert/cvsps.py	Tue May 11 17:03:44 2010 -0500
@@ -239,12 +239,12 @@
                 continue
             match = re_01.match(line)
             if match:
-                raise Exception(match.group(1))
+                raise logerror(match.group(1))
             match = re_02.match(line)
             if match:
-                raise Exception(match.group(2))
+                raise logerror(match.group(2))
             if re_03.match(line):
-                raise Exception(line)
+                raise logerror(line)
 
         elif state == 1:
             # expect 'Working file' (only when using log instead of rlog)
--- a/hgext/convert/darcs.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/hgext/convert/darcs.py	Tue May 11 17:03:44 2010 -0500
@@ -157,11 +157,11 @@
     def getfile(self, name, rev):
         if rev != self.lastrev:
             raise util.Abort(_('internal calling inconsistency'))
-        return open(os.path.join(self.tmppath, name), 'rb').read()
-
-    def getmode(self, name, rev):
-        mode = os.lstat(os.path.join(self.tmppath, name)).st_mode
-        return (mode & 0111) and 'x' or ''
+        path = os.path.join(self.tmppath, name)
+        data = open(path, 'rb').read()
+        mode = os.lstat(path).st_mode
+        mode = (mode & 0111) and 'x' or ''
+        return data, mode
 
     def gettags(self):
         return self.tags
--- a/hgext/convert/filemap.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/hgext/convert/filemap.py	Tue May 11 17:03:44 2010 -0500
@@ -100,8 +100,7 @@
 #
 # - Filter and rename files.  This is mostly wrapped by the filemapper
 #   class above. We hide the original filename in the revision that is
-#   returned by getchanges to be able to find things later in getfile
-#   and getmode.
+#   returned by getchanges to be able to find things later in getfile.
 #
 # - Return only revisions that matter for the files we're interested in.
 #   This involves rewriting the parents of the original revision to
@@ -318,10 +317,9 @@
         self.convertedorder.append((rev, True, None))
         self._discard(*parents)
 
-        # Get the real changes and do the filtering/mapping.
-        # To be able to get the files later on in getfile and getmode,
-        # we hide the original filename in the rev part of the return
-        # value.
+        # Get the real changes and do the filtering/mapping. To be
+        # able to get the files later on in getfile, we hide the
+        # original filename in the rev part of the return value.
         changes, copies = self.base.getchanges(rev)
         newnames = {}
         files = []
@@ -345,10 +343,6 @@
         realname, realrev = rev
         return self.base.getfile(realname, realrev)
 
-    def getmode(self, name, rev):
-        realname, realrev = rev
-        return self.base.getmode(realname, realrev)
-
     def gettags(self):
         return self.base.gettags()
 
--- a/hgext/convert/git.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/hgext/convert/git.py	Tue May 11 17:03:44 2010 -0500
@@ -67,10 +67,9 @@
         return data
 
     def getfile(self, name, rev):
-        return self.catfile(rev, "blob")
-
-    def getmode(self, name, rev):
-        return self.modecache[(name, rev)]
+        data = self.catfile(rev, "blob")
+        mode = self.modecache[(name, rev)]
+        return data, mode
 
     def getchanges(self, version):
         self.modecache = {}
--- a/hgext/convert/gnuarch.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/hgext/convert/gnuarch.py	Tue May 11 17:03:44 2010 -0500
@@ -54,7 +54,6 @@
         self.changes = {}
         self.parents = {}
         self.tags = {}
-        self.modecache = {}
         self.catlogparser = Parser()
         self.locale = locale.getpreferredencoding()
         self.archives = []
@@ -142,16 +141,9 @@
         if not os.path.exists(os.path.join(self.tmppath, name)):
             raise IOError
 
-        data, mode = self._getfile(name, rev)
-        self.modecache[(name, rev)] = mode
-
-        return data
-
-    def getmode(self, name, rev):
-        return self.modecache[(name, rev)]
+        return self._getfile(name, rev)
 
     def getchanges(self, rev):
-        self.modecache = {}
         self._update(rev)
         changes = []
         copies = {}
--- a/hgext/convert/hg.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/hgext/convert/hg.py	Tue May 11 17:03:44 2010 -0500
@@ -134,11 +134,11 @@
         files = dict(files)
         def getfilectx(repo, memctx, f):
             v = files[f]
-            data = source.getfile(f, v)
-            e = source.getmode(f, v)
+            data, mode = source.getfile(f, v)
             if f == '.hgtags':
                 data = self._rewritetags(source, revmap, data)
-            return context.memfilectx(f, data, 'l' in e, 'x' in e, copies.get(f))
+            return context.memfilectx(f, data, 'l' in mode, 'x' in mode,
+                                      copies.get(f))
 
         pl = []
         for p in parents:
@@ -266,13 +266,11 @@
 
     def getfile(self, name, rev):
         try:
-            return self.changectx(rev)[name].data()
+            fctx = self.changectx(rev)[name]
+            return fctx.data(), fctx.flags()
         except error.LookupError, err:
             raise IOError(err)
 
-    def getmode(self, name, rev):
-        return self.changectx(rev).manifest().flags(name)
-
     def getchanges(self, rev):
         ctx = self.changectx(rev)
         parents = self.parents(ctx)
--- a/hgext/convert/monotone.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/hgext/convert/monotone.py	Tue May 11 17:03:44 2010 -0500
@@ -192,18 +192,16 @@
 
         return (files.items(), copies)
 
-    def getmode(self, name, rev):
-        self.mtnloadmanifest(rev)
-        node, attr = self.files.get(name, (None, ""))
-        return attr
-
     def getfile(self, name, rev):
         if not self.mtnisfile(name, rev):
             raise IOError() # file was deleted or renamed
         try:
-            return self.mtnrun("get_file_of", name, r=rev)
+            data = self.mtnrun("get_file_of", name, r=rev)
         except:
             raise IOError() # file was deleted or renamed
+        self.mtnloadmanifest(rev)
+        node, attr = self.files.get(name, (None, ""))
+        return data, attr
 
     def getcommit(self, rev):
         certs   = self.mtngetcerts(rev)
--- a/hgext/convert/p4.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/hgext/convert/p4.py	Tue May 11 17:03:44 2010 -0500
@@ -41,7 +41,6 @@
         self.parent = {}
         self.encoding = "latin_1"
         self.depotname = {}           # mapping from local name to depot name
-        self.modecache = {}
         self.re_type = re.compile(
             "([a-z]+)?(text|binary|symlink|apple|resource|unicode|utf\d+)"
             "(\+\w+)?$")
@@ -183,17 +182,12 @@
         if mode is None:
             raise IOError(0, "bad stat")
 
-        self.modecache[(name, rev)] = mode
-
         if keywords:
             contents = keywords.sub("$\\1$", contents)
         if mode == "l" and contents.endswith("\n"):
             contents = contents[:-1]
 
-        return contents
-
-    def getmode(self, name, rev):
-        return self.modecache[(name, rev)]
+        return contents, mode
 
     def getchanges(self, rev):
         return self.files[rev], {}
--- a/hgext/convert/subversion.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/hgext/convert/subversion.py	Tue May 11 17:03:44 2010 -0500
@@ -371,19 +371,10 @@
 
         return self.heads
 
-    def getfile(self, file, rev):
-        data, mode = self._getfile(file, rev)
-        self.modecache[(file, rev)] = mode
-        return data
-
-    def getmode(self, file, rev):
-        return self.modecache[(file, rev)]
-
     def getchanges(self, rev):
         if self._changescache and self._changescache[0] == rev:
             return self._changescache[1]
         self._changescache = None
-        self.modecache = {}
         (paths, parents) = self.paths[rev]
         if parents:
             files, self.removed, copies = self.expandpaths(rev, paths, parents)
@@ -612,9 +603,6 @@
 
     def expandpaths(self, rev, paths, parents):
         changed, removed = set(), set()
-        # Map of entrypath, revision for finding source of deleted
-        # revisions.
-        copyfrom = {}
         copies = {}
 
         new_module, revnum = self.revsplit(rev)[1:]
@@ -622,7 +610,9 @@
             self.module = new_module
             self.reparent(self.module)
 
-        for path, ent in paths:
+        for i, (path, ent) in enumerate(paths):
+            self.ui.progress(_('scanning paths'), i, item=path,
+                             total=len(paths))
             entrypath = self.getrelpath(path)
 
             kind = self._checkpath(entrypath, revnum)
@@ -652,10 +642,10 @@
                 elif fromkind == svn.core.svn_node_dir:
                     oroot = parentpath.strip('/')
                     nroot = path.strip('/')
-                    children = self._find_children(oroot, prevnum)
-                    children = [s.replace(oroot, nroot) for s in children]
-                    for child in children:
-                        childpath = self.getrelpath("/" + child, pmodule)
+                    children = self._iterfiles(oroot, prevnum)
+                    for childpath in children:
+                        childpath = childpath.replace(oroot, nroot)
+                        childpath = self.getrelpath("/" + childpath, pmodule)
                         if childpath:
                             removed.add(self.recode(childpath))
                 else:
@@ -674,18 +664,10 @@
                     if pkind == svn.core.svn_node_file:
                         removed.add(self.recode(entrypath))
 
-                children = sorted(self._find_children(path, revnum))
-                for child in children:
-                    # Can we move a child directory and its
-                    # parent in the same commit? (probably can). Could
-                    # cause problems if instead of revnum -1,
-                    # we have to look in (copyfrom_path, revnum - 1)
-                    entrypath = self.getrelpath("/" + child)
-                    if entrypath:
-                        # Need to filter out directories here...
-                        kind = self._checkpath(entrypath, revnum)
-                        if kind != svn.core.svn_node_dir:
-                            changed.add(self.recode(entrypath))
+                for childpath in self._iterfiles(path, revnum):
+                    childpath = self.getrelpath("/" + childpath)
+                    if childpath:
+                        changed.add(self.recode(childpath))
 
                 # Handle directory copies
                 if not ent.copyfrom_path or not parents:
@@ -698,19 +680,18 @@
                 copyfrompath = self.getrelpath(ent.copyfrom_path, pmodule)
                 if not copyfrompath:
                     continue
-                copyfrom[path] = ent
                 self.ui.debug("mark %s came from %s:%d\n"
                               % (path, copyfrompath, ent.copyfrom_rev))
-                children = self._find_children(ent.copyfrom_path, ent.copyfrom_rev)
-                children.sort()
-                for child in children:
-                    entrypath = self.getrelpath("/" + child, pmodule)
-                    if not entrypath:
+                children = self._iterfiles(ent.copyfrom_path, ent.copyfrom_rev)
+                for childpath in children:
+                    childpath = self.getrelpath("/" + childpath, pmodule)
+                    if not childpath:
                         continue
-                    copytopath = path + entrypath[len(copyfrompath):]
+                    copytopath = path + childpath[len(copyfrompath):]
                     copytopath = self.getrelpath(copytopath)
-                    copies[self.recode(copytopath)] = self.recode(entrypath)
+                    copies[self.recode(copytopath)] = self.recode(childpath)
 
+        self.ui.progress(_('scanning paths'), None)
         changed.update(removed)
         return (list(changed), removed, copies)
 
@@ -839,10 +820,10 @@
                 raise util.Abort(_('svn: branch has no revision %s') % to_revnum)
             raise
 
-    def _getfile(self, file, rev):
+    def getfile(self, file, rev):
         # TODO: ra.get_file transmits the whole file instead of diffs.
         if file in self.removed:
-            raise IOError()
+            raise IOError()         
         mode = ''
         try:
             new_module, revnum = self.revsplit(rev)[1:]
@@ -871,12 +852,14 @@
                 data = data[len(link_prefix):]
         return data, mode
 
-    def _find_children(self, path, revnum):
+    def _iterfiles(self, path, revnum):
+        """Enumerate all files in path at revnum, recursively."""
         path = path.strip('/')
         pool = Pool()
         rpath = '/'.join([self.baseurl, urllib.quote(path)]).strip('/')
-        return ['%s/%s' % (path, x) for x in
-                svn.client.ls(rpath, optrev(revnum), True, self.ctx, pool).keys()]
+        entries = svn.client.ls(rpath, optrev(revnum), True, self.ctx, pool)            
+        return ((path + '/' + p) for p, e in entries.iteritems()
+                if e.kind == svn.core.svn_node_file)
 
     def getrelpath(self, path, module=None):
         if module is None:
@@ -1111,12 +1094,11 @@
         # Apply changes to working copy
         for f, v in files:
             try:
-                data = source.getfile(f, v)
+                data, mode = source.getfile(f, v)
             except IOError:
                 self.delete.append(f)
             else:
-                e = source.getmode(f, v)
-                self.putfile(f, e, data)
+                self.putfile(f, mode, data)
                 if f in copies:
                     self.copies.append([copies[f], f])
         files = [f[0] for f in files]
--- a/hgext/fetch.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/hgext/fetch.py	Tue May 11 17:03:44 2010 -0500
@@ -28,7 +28,7 @@
     parent, with local changes as the second. To switch the merge
     order, use --switch-parent.
 
-    See 'hg help dates' for a list of formats valid for -d/--date.
+    See :hg:`help dates` for a list of formats valid for -d/--date.
     '''
 
     date = opts.get('date')
--- a/hgext/hgcia.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/hgext/hgcia.py	Tue May 11 17:03:44 2010 -0500
@@ -113,7 +113,7 @@
 
         n = self.ctx.node()
         pbuf = patchbuf()
-        patch.export(self.cia.repo, [n], fp=pbuf)
+        cmdutil.export(self.cia.repo, [n], fp=pbuf)
         return patch.diffstat(pbuf.lines) or ''
 
     def logmsg(self):
--- a/hgext/highlight/highlight.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/hgext/highlight/highlight.py	Tue May 11 17:03:44 2010 -0500
@@ -23,7 +23,7 @@
 def pygmentize(field, fctx, style, tmpl):
 
     # append a <link ...> to the syntax highlighting css
-    old_header = ''.join(tmpl('header'))
+    old_header = tmpl.load('header')
     if SYNTAX_CSS not in old_header:
         new_header =  old_header + SYNTAX_CSS
         tmpl.cache['header'] = new_header
--- a/hgext/inotify/__init__.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/hgext/inotify/__init__.py	Tue May 11 17:03:44 2010 -0500
@@ -41,7 +41,7 @@
         # to start an inotify server if it won't start.
         _inotifyon = True
 
-        def status(self, match, subrepos, ignored, clean, unknown=True):
+        def status(self, match, subrepos, ignored, clean, unknown):
             files = match.files()
             if '.' in files:
                 files = []
--- a/hgext/keyword.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/hgext/keyword.py	Tue May 11 17:03:44 2010 -0500
@@ -1,6 +1,6 @@
 # keyword.py - $Keyword$ expansion for Mercurial
 #
-# Copyright 2007-2009 Christian Ebert <blacktrash@gmx.net>
+# Copyright 2007-2010 Christian Ebert <blacktrash@gmx.net>
 #
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
@@ -49,27 +49,22 @@
 lose speed in huge repositories.
 
 For [keywordmaps] template mapping and expansion demonstration and
-control run "hg kwdemo". See "hg help templates" for a list of
+control run :hg:`kwdemo`. See :hg:`help templates` for a list of
 available templates and filters.
 
 An additional date template filter {date|utcdate} is provided. It
 returns a date like "2006/09/18 15:13:13".
 
-The default template mappings (view with "hg kwdemo -d") can be
-replaced with customized keywords and templates. Again, run "hg
-kwdemo" to control the results of your config changes.
+The default template mappings (view with :hg:`kwdemo -d`) can be
+replaced with customized keywords and templates. Again, run
+:hg:`kwdemo` to control the results of your config changes.
 
-Before changing/disabling active keywords, run "hg kwshrink" to avoid
+Before changing/disabling active keywords, run :hg:`kwshrink` to avoid
 the risk of inadvertently storing expanded keywords in the change
 history.
 
 To force expansion after enabling it, or a configuration change, run
-"hg kwexpand".
-
-Also, when committing with the record extension or using mq's qrecord,
-be aware that keywords cannot be updated. Again, run "hg kwexpand" on
-the files in question to update keyword expansions after all changes
-have been checked in.
+:hg:`kwexpand`.
 
 Expansions spanning more than one line and incremental expansions,
 like CVS' $Log$, are not supported. A keyword template map "Log =
@@ -79,7 +74,6 @@
 from mercurial import commands, cmdutil, dispatch, filelog, revlog, extensions
 from mercurial import patch, localrepo, templater, templatefilters, util, match
 from mercurial.hgweb import webcommands
-from mercurial.lock import release
 from mercurial.node import nullid
 from mercurial.i18n import _
 import re, shutil, tempfile
@@ -93,8 +87,10 @@
 
 # hg commands that trigger expansion only when writing to working dir,
 # not when reading filelog, and unexpand when reading from working dir
-restricted = ('merge record resolve qfold qimport qnew qpush qrefresh qrecord'
-              ' transplant')
+restricted = 'merge record qrecord resolve transplant'
+
+# commands using dorecord
+recordcommands = 'record qrecord'
 
 # provide cvs-like UTC date filter
 utcdate = lambda x: util.datestr((x[0], 0), '%Y/%m/%d %H:%M:%S')
@@ -126,6 +122,7 @@
         self.match = match.match(repo.root, '', [],
                                  kwtools['inc'], kwtools['exc'])
         self.restrict = kwtools['hgcmd'] in restricted.split()
+        self.record = kwtools['hgcmd'] in recordcommands.split()
 
         kwmaps = self.ui.configitems('keywordmaps')
         if kwmaps: # override default templates
@@ -136,16 +133,16 @@
         self.re_kw = re.compile(kwpat)
 
         templatefilters.filters['utcdate'] = utcdate
-        self.ct = cmdutil.changeset_templater(self.ui, self.repo,
-                                              False, None, '', False)
 
     def substitute(self, data, path, ctx, subfunc):
         '''Replaces keywords in data with expanded template.'''
         def kwsub(mobj):
             kw = mobj.group(1)
-            self.ct.use_template(self.templates[kw])
+            ct = cmdutil.changeset_templater(self.ui, self.repo,
+                                             False, None, '', False)
+            ct.use_template(self.templates[kw])
             self.ui.pushbuffer()
-            self.ct.show(ctx, root=self.repo.root, file=path)
+            ct.show(ctx, root=self.repo.root, file=path)
             ekw = templatefilters.firstline(self.ui.popbuffer())
             return '$%s: %s $' % (kw, ekw)
         return subfunc(kwsub, data)
@@ -163,23 +160,22 @@
         Caveat: localrepository._link fails on Windows.'''
         return self.match(path) and not 'l' in flagfunc(path)
 
-    def overwrite(self, node, expand, files):
+    def overwrite(self, node, expand, candidates):
         '''Overwrites selected files expanding/shrinking keywords.'''
         ctx = self.repo[node]
         mf = ctx.manifest()
-        if node is not None:     # commit
-            files = [f for f in ctx.files() if f in mf]
-            notify = self.ui.debug
-        else:                    # kwexpand/kwshrink
-            notify = self.ui.note
-        candidates = [f for f in files if self.iskwfile(f, ctx.flags)]
+        if node is not None:     # commit, record
+            candidates = [f for f in ctx.files() if f in mf]
+        candidates = [f for f in candidates if self.iskwfile(f, ctx.flags)]
         if candidates:
             self.restrict = True # do not expand when reading
             msg = (expand and _('overwriting %s expanding keywords\n')
                    or _('overwriting %s shrinking keywords\n'))
             for f in candidates:
-                fp = self.repo.file(f)
-                data = fp.read(mf[f])
+                if not self.record:
+                    data = self.repo.file(f).read(mf[f])
+                else:
+                    data = self.repo.wread(f)
                 if util.binary(data):
                     continue
                 if expand:
@@ -190,7 +186,7 @@
                 else:
                     found = self.re_kw.search(data)
                 if found:
-                    notify(msg % f)
+                    self.ui.note(msg % f)
                     self.repo.wwrite(f, data, mf.flags(f))
                     if node is None:
                         self.repo.dirstate.normal(f)
@@ -251,10 +247,8 @@
     '''Bails out if [keyword] configuration is not active.
     Returns status of working directory.'''
     if kwt:
-        unknown = (opts.get('unknown') or opts.get('all')
-                   or opts.get('untracked'))
         return repo.status(match=cmdutil.match(repo, pats, opts), clean=True,
-                           unknown=unknown)
+                           unknown=opts.get('unknown') or opts.get('all'))
     if ui.configitems('keyword'):
         raise util.Abort(_('[keyword] patterns cannot match'))
     raise util.Abort(_('no [keyword] patterns configured'))
@@ -264,17 +258,15 @@
     if repo.dirstate.parents()[1] != nullid:
         raise util.Abort(_('outstanding uncommitted merge'))
     kwt = kwtools['templater']
-    status = _status(ui, repo, kwt, *pats, **opts)
-    modified, added, removed, deleted = status[:4]
-    if modified or added or removed or deleted:
-        raise util.Abort(_('outstanding uncommitted changes'))
-    wlock = lock = None
+    wlock = repo.wlock()
     try:
-        wlock = repo.wlock()
-        lock = repo.lock()
-        kwt.overwrite(None, expand, status[6])
+        status = _status(ui, repo, kwt, *pats, **opts)
+        modified, added, removed, deleted, unknown, ignored, clean = status
+        if modified or added or removed or deleted:
+            raise util.Abort(_('outstanding uncommitted changes'))
+        kwt.overwrite(None, expand, clean)
     finally:
-        release(lock, wlock)
+        wlock.release()
 
 def demo(ui, repo, *args, **opts):
     '''print [keywordmaps] configuration and an expansion example
@@ -295,7 +287,6 @@
             ui.write('%s = %s\n' % (k, v))
 
     fn = 'demo.txt'
-    branchname = 'demobranch'
     tmpdir = tempfile.mkdtemp('', 'kwdemo.')
     ui.note(_('creating temporary repository at %s\n') % tmpdir)
     repo = localrepo.localrepository(ui, tmpdir, True)
@@ -331,35 +322,23 @@
 
     uisetup(ui)
     reposetup(ui, repo)
-    for k, v in ui.configitems('extensions'):
-        if k.endswith('keyword'):
-            extension = '%s = %s' % (k, v)
-            break
-    ui.write('[extensions]\n%s\n' % extension)
+    ui.write('[extensions]\nkeyword =\n')
     demoitems('keyword', ui.configitems('keyword'))
     demoitems('keywordmaps', kwmaps.iteritems())
     keywords = '$' + '$\n$'.join(sorted(kwmaps.keys())) + '$\n'
     repo.wopener(fn, 'w').write(keywords)
     repo.add([fn])
-    path = repo.wjoin(fn)
-    ui.note(_('\nkeywords written to %s:\n') % path)
+    ui.note(_('\nkeywords written to %s:\n') % fn)
     ui.note(keywords)
-    ui.note('\nhg -R "%s" branch "%s"\n' % (tmpdir, branchname))
-    # silence branch command if not verbose
-    quiet = ui.quiet
-    ui.quiet = not ui.verbose
-    commands.branch(ui, repo, branchname)
-    ui.quiet = quiet
+    repo.dirstate.setbranch('demobranch')
     for name, cmd in ui.configitems('hooks'):
         if name.split('.', 1)[0].find('commit') > -1:
             repo.ui.setconfig('hooks', name, '')
-    ui.note(_('unhooked all commit hooks\n'))
     msg = _('hg keyword configuration and expansion example')
-    ui.note("hg -R '%s' ci -m '%s'\n" % (tmpdir, msg))
+    ui.note("hg ci -m '%s'\n" % msg)
     repo.commit(text=msg)
     ui.status(_('\n\tkeywords expanded\n'))
     ui.write(repo.wread(fn))
-    ui.debug('\nremoving temporary repository %s\n' % tmpdir)
     shutil.rmtree(tmpdir, ignore_errors=True)
 
 def expand(ui, repo, *pats, **opts):
@@ -382,7 +361,7 @@
     execution by including only files that are actual candidates for
     expansion.
 
-    See "hg help keyword" on how to construct patterns both for
+    See :hg:`help keyword` on how to construct patterns both for
     inclusion and exclusion of files.
 
     With -A/--all and -v/--verbose the codes used to show the status
@@ -398,7 +377,7 @@
     cwd = pats and repo.getcwd() or ''
     modified, added, removed, deleted, unknown, ignored, clean = status
     files = []
-    if not (opts.get('unknown') or opts.get('untracked')) or opts.get('all'):
+    if not opts.get('unknown') or opts.get('all'):
         files = sorted(modified + added + clean)
     wctx = repo[None]
     kwfiles = [f for f in files if kwt.iskwfile(f, wctx.flags)]
@@ -419,7 +398,7 @@
     '''revert expanded keywords in the working directory
 
     Run before changing/disabling active keywords or if you experience
-    problems with "hg import" or "hg merge".
+    problems with :hg:`import` or :hg:`merge`.
 
     kwshrink refuses to run if given files contain local changes.
     '''
@@ -485,22 +464,18 @@
                 del self.commitctx
 
         def kwcommitctx(self, ctx, error=False):
-            wlock = lock = None
-            try:
-                wlock = self.wlock()
-                lock = self.lock()
-                n = super(kwrepo, self).commitctx(ctx, error)
+            n = super(kwrepo, self).commitctx(ctx, error)
+            # no lock needed, only called from repo.commit() which already locks
+            if not kwt.record:
                 kwt.overwrite(n, True, None)
-                return n
-            finally:
-                release(lock, wlock)
+            return n
 
     # monkeypatches
     def kwpatchfile_init(orig, self, ui, fname, opener,
-                         missing=False, eol=None):
+                         missing=False, eolmode=None):
         '''Monkeypatch/wrap patch.patchfile.__init__ to avoid
         rejects or conflicts due to expanded keywords in working dir.'''
-        orig(self, ui, fname, opener, missing, eol)
+        orig(self, ui, fname, opener, missing, eolmode)
         # shrink keywords read from working dir
         self.lines = kwt.shrinklines(self.fname, self.lines)
 
@@ -519,6 +494,20 @@
         kwt.match = util.never
         return orig(web, req, tmpl)
 
+    def kw_dorecord(orig, ui, repo, commitfunc, *pats, **opts):
+        '''Wraps record.dorecord expanding keywords after recording.'''
+        wlock = repo.wlock()
+        try:
+            # record returns 0 even when nothing has changed
+            # therefore compare nodes before and after
+            ctx = repo['.']
+            ret = orig(ui, repo, commitfunc, *pats, **opts)
+            if ctx != repo['.']:
+                kwt.overwrite('.',  True, None)
+            return ret
+        finally:
+            wlock.release()
+
     repo.__class__ = kwrepo
 
     extensions.wrapfunction(patch.patchfile, '__init__', kwpatchfile_init)
@@ -526,6 +515,11 @@
         extensions.wrapfunction(patch, 'diff', kw_diff)
     for c in 'annotate changeset rev filediff diff'.split():
         extensions.wrapfunction(webcommands, c, kwweb_skip)
+    try:
+        record = extensions.find('record')
+        extensions.wrapfunction(record, 'dorecord', kw_dorecord)
+    except KeyError:
+        pass
 
 cmdtable = {
     'kwdemo':
@@ -540,9 +534,6 @@
          [('A', 'all', None, _('show keyword status flags of all files')),
           ('i', 'ignore', None, _('show files excluded from expansion')),
           ('u', 'unknown', None, _('only show unknown (not tracked) files')),
-          ('a', 'all', None,
-           _('show keyword status flags of all files (DEPRECATED)')),
-          ('u', 'untracked', None, _('only show untracked files (DEPRECATED)')),
          ] + commands.walkopts,
          _('hg kwfiles [OPTION]... [FILE]...')),
     'kwshrink': (shrink, commands.walkopts,
--- a/hgext/mq.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/hgext/mq.py	Tue May 11 17:03:44 2010 -0500
@@ -14,7 +14,7 @@
 Known patches are represented as patch files in the .hg/patches
 directory. Applied patches are both patch files and changesets.
 
-Common tasks (use "hg help command" for more details)::
+Common tasks (use :hg:`help command` for more details)::
 
   create new patch                          qnew
   import existing patch                     qimport
@@ -53,18 +53,11 @@
 normname = util.normpath
 
 class statusentry(object):
-    def __init__(self, rev, name=None):
-        if not name:
-            fields = rev.split(':', 1)
-            if len(fields) == 2:
-                self.rev, self.name = fields
-            else:
-                self.rev, self.name = None, None
-        else:
-            self.rev, self.name = rev, name
+    def __init__(self, node, name):
+        self.node, self.name = node, name
 
     def __str__(self):
-        return self.rev + ':' + self.name
+        return hex(self.node) + ':' + self.name
 
 class patchheader(object):
     def __init__(self, pf, plainmode=False):
@@ -79,8 +72,7 @@
                     break
         def eatempty(lines):
             while lines:
-                l = lines[-1]
-                if re.match('\s*$', l):
+                if not lines[-1].strip():
                     del lines[-1]
                 else:
                     break
@@ -265,8 +257,11 @@
     @util.propertycache
     def applied(self):
         if os.path.exists(self.join(self.status_path)):
+            def parse(l):
+                n, name = l.split(':', 1)
+                return statusentry(bin(n), name)
             lines = self.opener(self.status_path).read().splitlines()
-            return [statusentry(l) for l in lines]
+            return [parse(l) for l in lines]
         return []
 
     @util.propertycache
@@ -329,16 +324,12 @@
         return os.path.join(self.path, *p)
 
     def find_series(self, patch):
-        pre = re.compile("(\s*)([^#]+)")
-        index = 0
-        for l in self.full_series:
-            m = pre.match(l)
-            if m:
-                s = m.group(2)
-                s = s.rstrip()
-                if s == patch:
-                    return index
-            index += 1
+        def matchpatch(l):
+            l = l.split('#', 1)[0]
+            return l.strip() == patch
+        for index, l in enumerate(self.full_series):
+            if matchpatch(l):
+                return index
         return None
 
     guard_re = re.compile(r'\s?#([-+][^-+# \t\r\n\f][^# \t\r\n\f]*)')
@@ -486,19 +477,9 @@
     def printdiff(self, repo, diffopts, node1, node2=None, files=None,
                   fp=None, changes=None, opts={}):
         stat = opts.get('stat')
-        if stat:
-            opts['unified'] = '0'
-
         m = cmdutil.match(repo, files, opts)
-        chunks = patch.diff(repo, node1, node2, m, changes, diffopts)
-        write = fp is None and repo.ui.write or fp.write
-        if stat:
-            width = self.ui.interactive() and util.termwidth() or 80
-            write(patch.diffstat(util.iterlines(chunks), width=width,
-                                 git=diffopts.git))
-        else:
-            for chunk in chunks:
-                write(chunk)
+        cmdutil.diffordiffstat(self.ui, repo, diffopts, node1, node2,  m,
+                               changes, stat, fp)
 
     def mergeone(self, repo, mergeq, head, patch, rev, diffopts):
         # first try just applying the patch
@@ -544,22 +525,16 @@
             (p1, p2) = repo.dirstate.parents()
             if p2 == nullid:
                 return p1
-            if len(self.applied) == 0:
+            if not self.applied:
                 return None
-            return bin(self.applied[-1].rev)
-        pp = repo.changelog.parents(rev)
-        if pp[1] != nullid:
-            arevs = [x.rev for x in self.applied]
-            p0 = hex(pp[0])
-            p1 = hex(pp[1])
-            if p0 in arevs:
-                return pp[0]
-            if p1 in arevs:
-                return pp[1]
-        return pp[0]
+            return self.applied[-1].node
+        p1, p2 = repo.changelog.parents(rev)
+        if p2 != nullid and p2 in [x.node for x in self.applied]:
+            return p2
+        return p1
 
     def mergepatch(self, repo, mergeq, series, diffopts):
-        if len(self.applied) == 0:
+        if not self.applied:
             # each of the patches merged in will have two parents.  This
             # can confuse the qrefresh, qdiff, and strip code because it
             # needs to know which parent is actually in the patch queue.
@@ -569,7 +544,7 @@
             pname = ".hg.patches.merge.marker"
             n = repo.commit('[mq]: merge marker', force=True)
             self.removeundo(repo)
-            self.applied.append(statusentry(hex(n), pname))
+            self.applied.append(statusentry(n, pname))
             self.applied_dirty = 1
 
         head = self.qparents(repo)
@@ -587,10 +562,10 @@
             if not info:
                 self.ui.warn(_("patch %s is not applied\n") % patch)
                 return (1, None)
-            rev = bin(info[1])
+            rev = info[1]
             err, head = self.mergeone(repo, mergeq, head, patch, rev, diffopts)
             if head:
-                self.applied.append(statusentry(hex(head), patch))
+                self.applied.append(statusentry(head, patch))
                 self.applied_dirty = 1
             if err:
                 return (err, head)
@@ -613,12 +588,12 @@
         return (True, files, fuzz)
 
     def apply(self, repo, series, list=False, update_status=True,
-              strict=False, patchdir=None, merge=None, all_files={}):
+              strict=False, patchdir=None, merge=None, all_files=None):
         wlock = lock = tr = None
         try:
             wlock = repo.wlock()
             lock = repo.lock()
-            tr = repo.transaction()
+            tr = repo.transaction("qpush")
             try:
                 ret = self._apply(repo, series, list, update_status,
                                   strict, patchdir, merge, all_files=all_files)
@@ -638,7 +613,7 @@
             self.removeundo(repo)
 
     def _apply(self, repo, series, list=False, update_status=True,
-               strict=False, patchdir=None, merge=None, all_files={}):
+               strict=False, patchdir=None, merge=None, all_files=None):
         '''returns (error, hash)
         error = 1 for unable to read, 2 for patch failed, 3 for patch fuzz'''
         # TODO unify with commands.py
@@ -671,7 +646,8 @@
 
             if ph.haspatch:
                 (patcherr, files, fuzz) = self.patch(repo, pf)
-                all_files.update(files)
+                if all_files is not None:
+                    all_files.update(files)
                 patcherr = not patcherr
             else:
                 self.ui.warn(_("patch %s is empty\n") % patchname)
@@ -701,7 +677,7 @@
                 raise util.Abort(_("repo commit failed"))
 
             if update_status:
-                self.applied.append(statusentry(hex(n), patchname))
+                self.applied.append(statusentry(n, patchname))
 
             if patcherr:
                 self.ui.warn(_("patch failed, rejects left in working dir\n"))
@@ -733,7 +709,7 @@
         self.series_dirty = 1
 
     def _revpatches(self, repo, revs):
-        firstrev = repo[self.applied[0].rev].rev()
+        firstrev = repo[self.applied[0].node].rev()
         patches = []
         for i, rev in enumerate(revs):
 
@@ -741,7 +717,7 @@
                 raise util.Abort(_('revision %d is not managed') % rev)
 
             ctx = repo[rev]
-            base = bin(self.applied[i].rev)
+            base = self.applied[i].node
             if ctx.node() != base:
                 msg = _('cannot delete revision %d above applied patches')
                 raise util.Abort(msg % rev)
@@ -789,8 +765,8 @@
         self._cleanup(realpatches, numrevs, opts.get('keep'))
 
     def check_toppatch(self, repo):
-        if len(self.applied) > 0:
-            top = bin(self.applied[-1].rev)
+        if self.applied:
+            top = self.applied[-1].node
             patch = self.applied[-1].name
             pp = repo.dirstate.parents()
             if top not in pp:
@@ -870,7 +846,7 @@
                     raise util.Abort(_("repo commit failed"))
                 try:
                     self.full_series[insert:insert] = [patchfn]
-                    self.applied.append(statusentry(hex(n), patchfn))
+                    self.applied.append(statusentry(n, patchfn))
                     self.parse_series()
                     self.series_dirty = 1
                     self.applied_dirty = 1
@@ -927,7 +903,7 @@
         """returns (index, rev, patch)"""
         for i, a in enumerate(self.applied):
             if a.name == patch:
-                return (i, a.rev, a.name)
+                return (i, a.node, a.name)
         return None
 
     # if the exact patch name does not exist, we try a few
@@ -950,7 +926,7 @@
                 return None
             if matches:
                 return matches[0]
-            if len(self.series) > 0 and len(self.applied) > 0:
+            if self.series and self.applied:
                 if s == 'qtip':
                     return self.series[self.series_end(True)-1]
                 if s == 'qbase':
@@ -1002,7 +978,7 @@
         raise util.Abort(_("patch %s not in series") % patch)
 
     def push(self, repo, patch=None, force=False, list=False,
-             mergeq=None, all=False):
+             mergeq=None, all=False, move=False):
         diffopts = self.diffopts()
         wlock = repo.wlock()
         try:
@@ -1058,6 +1034,15 @@
             if not force:
                 self.check_localchanges(repo)
 
+            if move:
+                try:
+                    del self.full_series[self.full_series.index(patch, start)]
+                except ValueError:
+                    raise util.Abort(_("patch '%s' not found") % patch)
+                self.full_series.insert(start, patch)
+                self.parse_series()
+                self.series_dirty = 1
+
             self.applied_dirty = 1
             if start > 0:
                 self.check_toppatch(repo)
@@ -1068,7 +1053,7 @@
                 end = self.series.index(patch, start) + 1
 
             s = self.series[start:end]
-            all_files = {}
+            all_files = set()
             try:
                 if mergeq:
                     ret = self.mergepatch(repo, mergeq, s, diffopts)
@@ -1078,12 +1063,15 @@
                 self.ui.warn(_('cleaning up working directory...'))
                 node = repo.dirstate.parents()[0]
                 hg.revert(repo, node, None)
-                unknown = repo.status(unknown=True)[4]
                 # only remove unknown files that we know we touched or
                 # created while patching
-                for f in unknown:
-                    if f in all_files:
-                        util.unlink(repo.wjoin(f))
+                for f in all_files:
+                    if f not in repo.dirstate:
+                        try:
+                            util.unlink(repo.wjoin(f))
+                        except OSError, inst:
+                            if inst.errno != errno.ENOENT:
+                                raise
                 self.ui.warn(_('done\n'))
                 raise
 
@@ -1101,10 +1089,6 @@
             wlock.release()
 
     def pop(self, repo, patch=None, force=False, update=True, all=False):
-        def getfile(f, rev, flags):
-            t = repo.file(f).read(rev)
-            repo.wwrite(f, t, flags)
-
         wlock = repo.wlock()
         try:
             if patch:
@@ -1116,7 +1100,7 @@
                 if not info:
                     raise util.Abort(_("patch %s is not applied") % patch)
 
-            if len(self.applied) == 0:
+            if not self.applied:
                 # Allow qpop -a to work repeatedly,
                 # but not qpop without an argument
                 self.ui.warn(_("no patches applied\n"))
@@ -1135,16 +1119,16 @@
 
             if not update:
                 parents = repo.dirstate.parents()
-                rr = [bin(x.rev) for x in self.applied]
+                rr = [x.node for x in self.applied]
                 for p in parents:
                     if p in rr:
                         self.ui.warn(_("qpop: forcing dirstate update\n"))
                         update = True
             else:
-                parents = [p.hex() for p in repo[None].parents()]
+                parents = [p.node() for p in repo[None].parents()]
                 needupdate = False
                 for entry in self.applied[start:]:
-                    if entry.rev in parents:
+                    if entry.node in parents:
                         needupdate = True
                         break
                 update = needupdate
@@ -1154,7 +1138,7 @@
 
             self.applied_dirty = 1
             end = len(self.applied)
-            rev = bin(self.applied[start].rev)
+            rev = self.applied[start].node
             if update:
                 top = self.check_toppatch(repo)[0]
 
@@ -1164,7 +1148,7 @@
                 node = short(rev)
                 raise util.Abort(_('trying to pop unknown node %s') % node)
 
-            if heads != [bin(self.applied[-1].rev)]:
+            if heads != [self.applied[-1].node]:
                 raise util.Abort(_("popping would remove a revision not "
                                    "managed by this patch queue"))
 
@@ -1172,8 +1156,7 @@
             # form of hg.update.
             if update:
                 qp = self.qparents(repo, rev)
-                changes = repo.changelog.read(qp)
-                mmap = repo.manifest.read(changes[0])
+                ctx = repo[qp]
                 m, a, r, d = repo.status(qp, top)[:4]
                 if d:
                     raise util.Abort(_("deletions found between repo revs"))
@@ -1184,18 +1167,16 @@
                         if e.errno != errno.ENOENT:
                             raise
                     repo.dirstate.forget(f)
-                for f in m:
-                    getfile(f, mmap[f], mmap.flags(f))
-                for f in r:
-                    getfile(f, mmap[f], mmap.flags(f))
                 for f in m + r:
+                    fctx = ctx[f]
+                    repo.wwrite(f, fctx.data(), fctx.flags())
                     repo.dirstate.normal(f)
                 repo.dirstate.setparents(qp, nullid)
             for patch in reversed(self.applied[start:end]):
                 self.ui.status(_("popping %s\n") % patch.name)
             del self.applied[start:end]
             self.strip(repo, rev, update=False, backup='strip')
-            if len(self.applied):
+            if self.applied:
                 self.ui.write(_("now at: %s\n") % self.applied[-1].name)
             else:
                 self.ui.write(_("patch queue now empty\n"))
@@ -1216,7 +1197,7 @@
         self.printdiff(repo, diffopts, node1, node2, files=pats, opts=opts)
 
     def refresh(self, repo, pats=None, **opts):
-        if len(self.applied) == 0:
+        if not self.applied:
             self.ui.write(_("no patches applied\n"))
             return 1
         msg = opts.get('msg', '').rstrip()
@@ -1228,8 +1209,7 @@
 
         try:
             self.check_toppatch(repo)
-            (top, patchfn) = (self.applied[-1].rev, self.applied[-1].name)
-            top = bin(top)
+            (top, patchfn) = (self.applied[-1].node, self.applied[-1].name)
             if repo.changelog.heads(top) != [top]:
                 raise util.Abort(_("cannot refresh a revision with children"))
 
@@ -1386,7 +1366,7 @@
                 patchf.rename()
                 n = repo.commit(message, user, ph.date, match=match,
                                 force=True)
-                self.applied.append(statusentry(hex(n), patchfn))
+                self.applied.append(statusentry(n, patchfn))
             except:
                 ctx = repo[cparents[0]]
                 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
@@ -1426,7 +1406,9 @@
 
     def qseries(self, repo, missing=None, start=0, length=None, status=None,
                 summary=False):
-        def displayname(pfx, patchname):
+        def displayname(pfx, patchname, state):
+            if pfx:
+                self.ui.write(pfx)
             if summary:
                 ph = patchheader(self.join(patchname), self.plainmode)
                 msg = ph.message and ph.message[0] or ''
@@ -1436,10 +1418,12 @@
                         msg = util.ellipsis(msg, width)
                     else:
                         msg = ''
-                msg = "%s%s: %s" % (pfx, patchname, msg)
+                self.ui.write(patchname, label='qseries.' + state)
+                self.ui.write(': ')
+                self.ui.write(msg, label='qseries.message.' + state)
             else:
-                msg = pfx + patchname
-            self.ui.write(msg + '\n')
+                self.ui.write(patchname, label='qseries.' + state)
+            self.ui.write('\n')
 
         applied = set([p.name for p in self.applied])
         if length is None:
@@ -1450,17 +1434,17 @@
             for i in xrange(start, start + length):
                 patch = self.series[i]
                 if patch in applied:
-                    stat = 'A'
+                    char, state = 'A', 'applied'
                 elif self.pushable(i)[0]:
-                    stat = 'U'
+                    char, state = 'U', 'unapplied'
                 else:
-                    stat = 'G'
+                    char, state = 'G', 'guarded'
                 pfx = ''
                 if self.ui.verbose:
-                    pfx = '%*d %s ' % (idxwidth, i, stat)
-                elif status and status != stat:
+                    pfx = '%*d %s ' % (idxwidth, i, char)
+                elif status and status != char:
                     continue
-                displayname(pfx, patch)
+                displayname(pfx, patch, state)
         else:
             msng_list = []
             for root, dirs, files in os.walk(self.path):
@@ -1474,7 +1458,7 @@
                         msng_list.append(fl)
             for x in sorted(msng_list):
                 pfx = self.ui.verbose and ('D ') or ''
-                displayname(pfx, x)
+                displayname(pfx, x, 'missing')
 
     def issaveline(self, l):
         if l.name == '.hg.patches.save.line':
@@ -1485,8 +1469,7 @@
             return hg.repository(self.ui, path=self.path, create=create)
 
     def restore(self, repo, rev, delete=None, qupdate=None):
-        c = repo.changelog.read(rev)
-        desc = c[4].strip()
+        desc = repo[rev].description().strip()
         lines = desc.splitlines()
         i = 0
         datastart = None
@@ -1502,12 +1485,11 @@
                 qpp = [bin(x) for x in l]
             elif datastart != None:
                 l = line.rstrip()
-                se = statusentry(l)
-                file_ = se.name
-                if se.rev:
-                    applied.append(se)
+                n, name = l.split(':', 1)
+                if n:
+                    applied.append(statusentry(bin(n), name))
                 else:
-                    series.append(file_)
+                    series.append(l)
         if datastart is None:
             self.ui.warn(_("No saved patch data found\n"))
             return 1
@@ -1541,14 +1523,13 @@
                 hg.clean(r, qpp[0])
 
     def save(self, repo, msg=None):
-        if len(self.applied) == 0:
+        if not self.applied:
             self.ui.warn(_("save: no patches applied, exiting\n"))
             return 1
         if self.issaveline(self.applied[-1]):
             self.ui.warn(_("status is already saved\n"))
             return 1
 
-        ar = [':' + x for x in self.full_series]
         if not msg:
             msg = _("hg patches saved state")
         else:
@@ -1558,18 +1539,18 @@
             pp = r.dirstate.parents()
             msg += "\nDirstate: %s %s" % (hex(pp[0]), hex(pp[1]))
         msg += "\n\nPatch Data:\n"
-        text = msg + "\n".join([str(x) for x in self.applied]) + '\n' + (ar and
-                   "\n".join(ar) + '\n' or "")
-        n = repo.commit(text, force=True)
+        msg += ''.join('%s\n' % x for x in self.applied)
+        msg += ''.join(':%s\n' % x for x in self.full_series)
+        n = repo.commit(msg, force=True)
         if not n:
             self.ui.warn(_("repo commit failed\n"))
             return 1
-        self.applied.append(statusentry(hex(n),'.hg.patches.save.line'))
+        self.applied.append(statusentry(n, '.hg.patches.save.line'))
         self.applied_dirty = 1
         self.removeundo(repo)
 
     def full_series_end(self):
-        if len(self.applied) > 0:
+        if self.applied:
             p = self.applied[-1].name
             end = self.find_series(p)
             if end is None:
@@ -1584,17 +1565,15 @@
         """
         end = 0
         def next(start):
-            if all_patches:
+            if all_patches or start >= len(self.series):
                 return start
-            i = start
-            while i < len(self.series):
+            for i in xrange(start, len(self.series)):
                 p, reason = self.pushable(i)
                 if p:
                     break
                 self.explain_pushable(i)
-                i += 1
             return i
-        if len(self.applied) > 0:
+        if self.applied:
             p = self.applied[-1].name
             try:
                 end = self.series.index(p)
@@ -1631,7 +1610,6 @@
         if (len(files) > 1 or len(rev) > 1) and patchname:
             raise util.Abort(_('option "-n" not valid when importing multiple '
                                'patches'))
-        i = 0
         added = []
         if rev:
             # If mq patches are applied, we can only import revisions
@@ -1642,14 +1620,14 @@
                 raise util.Abort(_('revision %d is the root of more than one '
                                    'branch') % rev[-1])
             if self.applied:
-                base = hex(repo.changelog.node(rev[0]))
-                if base in [n.rev for n in self.applied]:
+                base = repo.changelog.node(rev[0])
+                if base in [n.node for n in self.applied]:
                     raise util.Abort(_('revision %d is already managed')
                                      % rev[0])
-                if heads != [bin(self.applied[-1].rev)]:
+                if heads != [self.applied[-1].node]:
                     raise util.Abort(_('revision %d is not the parent of '
                                        'the queue') % rev[0])
-                base = repo.changelog.rev(bin(self.applied[0].rev))
+                base = repo.changelog.rev(self.applied[0].node)
                 lastparent = repo.changelog.parentrevs(base)[0]
             else:
                 if heads != [repo.changelog.node(rev[0])]:
@@ -1676,10 +1654,10 @@
                 self.full_series.insert(0, patchname)
 
                 patchf = self.opener(patchname, "w")
-                patch.export(repo, [n], fp=patchf, opts=diffopts)
+                cmdutil.export(repo, [n], fp=patchf, opts=diffopts)
                 patchf.close()
 
-                se = statusentry(hex(n), patchname)
+                se = statusentry(n, patchname)
                 self.applied.insert(0, se)
 
                 added.append(patchname)
@@ -1687,7 +1665,7 @@
             self.parse_series()
             self.applied_dirty = 1
 
-        for filename in files:
+        for i, filename in enumerate(files):
             if existing:
                 if filename == '-':
                     raise util.Abort(_('-e is incompatible with import from -'))
@@ -1720,7 +1698,6 @@
                 self.full_series[index:index] = [patchname]
             self.parse_series()
             self.ui.warn(_("adding %s to series file\n") % patchname)
-            i += 1
             added.append(patchname)
             patchname = None
         self.series_dirty = 1
@@ -1897,7 +1874,7 @@
     qbase, destrev = None, None
     if sr.local():
         if sr.mq.applied:
-            qbase = bin(sr.mq.applied[0].rev)
+            qbase = sr.mq.applied[0].node
             if not hg.islocal(dest):
                 heads = set(sr.heads())
                 destrev = list(heads.difference(sr.heads(qbase)))
@@ -2056,9 +2033,9 @@
     last refresh (thus showing what the current patch would become
     after a qrefresh).
 
-    Use 'hg diff' if you only want to see the changes made since the
-    last qrefresh, or 'hg export qtip' if you want to see changes made
-    by the current patch without including changes made since the
+    Use :hg:`diff` if you only want to see the changes made since the
+    last qrefresh, or :hg:`export qtip` if you want to see changes
+    made by the current patch without including changes made since the
     qrefresh.
     """
     repo.mq.diff(repo, pats, opts)
@@ -2158,7 +2135,17 @@
     '''
     def status(idx):
         guards = q.series_guards[idx] or ['unguarded']
-        ui.write('%s: %s\n' % (q.series[idx], ' '.join(guards)))
+        ui.write('%s: ' % ui.label(q.series[idx], 'qguard.patch'))
+        for i, guard in enumerate(guards):
+            if guard.startswith('+'):
+                ui.write(guard, label='qguard.positive')
+            elif guard.startswith('-'):
+                ui.write(guard, label='qguard.negative')
+            else:
+                ui.write(guard, label='qguard.unguarded')
+            if i != len(guards) - 1:
+                ui.write(' ')
+        ui.write('\n')
     q = repo.mq
     patch = None
     args = list(args)
@@ -2244,7 +2231,7 @@
         mergeq = queue(ui, repo.join(""), newpath)
         ui.warn(_("merging with queue at: %s\n") % mergeq.path)
     ret = q.push(repo, patch, force=opts['force'], list=opts['list'],
-                 mergeq=mergeq, all=opts.get('all'))
+                 mergeq=mergeq, all=opts.get('all'), move=opts.get('move'))
     return ret
 
 def pop(ui, repo, patch=None, **opts):
@@ -2555,8 +2542,8 @@
 
         def abort_if_wdir_patched(self, errmsg, force=False):
             if self.mq.applied and not force:
-                parent = hex(self.dirstate.parents()[0])
-                if parent in [s.rev for s in self.mq.applied]:
+                parent = self.dirstate.parents()[0]
+                if parent in [s.node for s in self.mq.applied]:
                     raise util.Abort(errmsg)
 
         def commit(self, text="", user=None, date=None, match=None,
@@ -2581,7 +2568,7 @@
             if not q.applied:
                 return result
 
-            mqtags = [(bin(patch.rev), patch.name) for patch in q.applied]
+            mqtags = [(patch.node, patch.name) for patch in q.applied]
 
             if mqtags[-1][0] not in self.changelog.nodemap:
                 self.ui.warn(_('mq status file refers to unknown node %s\n')
@@ -2607,7 +2594,7 @@
                 return super(mqrepo, self)._branchtags(partial, lrev)
 
             cl = self.changelog
-            qbasenode = bin(q.applied[0].rev)
+            qbasenode = q.applied[0].node
             if qbasenode not in cl.nodemap:
                 self.ui.warn(_('mq status file refers to unknown node %s\n')
                              % short(qbasenode))
@@ -2672,13 +2659,29 @@
     q = repo.mq
     r = q.qrepo()
     if not r:
-        raise util.Abort('no queue repository')
+        raise util.Abort(_('no queue repository'))
     return orig(r.ui, r, *args, **kwargs)
 
+def summary(orig, ui, repo, *args, **kwargs):
+    r = orig(ui, repo, *args, **kwargs)
+    q = repo.mq
+    m = []
+    a, u = len(q.applied), len(q.unapplied(repo))
+    if a:
+        m.append(ui.label(_("%d applied"), 'qseries.applied') % a)
+    if u:
+        m.append(ui.label(_("%d unapplied"), 'qseries.unapplied') % u)
+    if m:
+        ui.write("mq:     %s\n" % ', '.join(m))
+    else:
+        ui.note(_("mq:     (empty queue)\n"))
+    return r
+
 def uisetup(ui):
     mqopt = [('', 'mq', None, _("operate on patch repository"))]
 
     extensions.wrapcommand(commands.table, 'import', mqimport)
+    extensions.wrapcommand(commands.table, 'summary', summary)
 
     entry = extensions.wrapcommand(commands.table, 'init', mqinit)
     entry[1].extend(mqopt)
@@ -2736,7 +2739,7 @@
           ('n', 'none', None, _('drop all guards'))],
          _('hg qguard [-l] [-n] [PATCH] [-- [+GUARD]... [-GUARD]...]')),
     'qheader': (header, [], _('hg qheader [PATCH]')),
-    "^qimport":
+    "qimport":
         (qimport,
          [('e', 'existing', None, _('import file in patch directory')),
           ('n', 'name', '', _('name of patch file')),
@@ -2749,7 +2752,7 @@
         (init,
          [('c', 'create-repo', None, _('create queue repository'))],
          _('hg qinit [-c]')),
-    "qnew":
+    "^qnew":
         (new,
          [('e', 'edit', None, _('edit commit message')),
           ('f', 'force', None, _('import uncommitted changes (DEPRECATED)')),
@@ -2774,8 +2777,9 @@
           ('l', 'list', None, _('list patch name in commit text')),
           ('a', 'all', None, _('apply all patches')),
           ('m', 'merge', None, _('merge from another queue (DEPRECATED)')),
-          ('n', 'name', '', _('merge queue name (DEPRECATED)'))],
-         _('hg qpush [-f] [-l] [-a] [-m] [-n NAME] [PATCH | INDEX]')),
+          ('n', 'name', '', _('merge queue name (DEPRECATED)')),
+          ('', 'move', None, _('reorder patch series and apply only the patch'))],
+         _('hg qpush [-f] [-l] [-a] [-m] [-n NAME] [--move] [PATCH | INDEX]')),
     "^qrefresh":
         (refresh,
          [('e', 'edit', None, _('edit commit message')),
@@ -2818,7 +2822,7 @@
          [('m', 'missing', None, _('print patches not in series')),
          ] + seriesopts,
           _('hg qseries [-ms]')),
-     "^strip":
+     "strip":
          (strip,
          [('f', 'force', None, _('force removal of changesets even if the '
                                  'working directory has uncommitted changes')),
@@ -2837,3 +2841,11 @@
          [('a', 'applied', None, _('finish all applied changesets'))],
          _('hg qfinish [-a] [REV]...')),
 }
+
+colortable = {'qguard.negative': 'red',
+              'qguard.positive': 'yellow',
+              'qguard.unguarded': 'green',
+              'qseries.applied': 'blue bold underline',
+              'qseries.guarded': 'black bold',
+              'qseries.missing': 'red bold',
+              'qseries.unapplied': 'black bold'}
--- a/hgext/pager.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/hgext/pager.py	Tue May 11 17:03:44 2010 -0500
@@ -45,8 +45,8 @@
 
 If pager.attend is present, pager.ignore will be ignored.
 
-To ignore global commands like "hg version" or "hg help", you have to
-specify them in the global .hgrc
+To ignore global commands like :hg:`version` or :hg:`help`, you have
+to specify them in the global .hgrc
 '''
 
 import sys, os, signal
--- a/hgext/patchbomb.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/hgext/patchbomb.py	Tue May 11 17:03:44 2010 -0500
@@ -16,7 +16,7 @@
 
 - The changeset description.
 - [Optional] The result of running diffstat on the patch.
-- The patch itself, as generated by "hg export".
+- The patch itself, as generated by :hg:`export`.
 
 Each message refers to the first in the series using the In-Reply-To
 and References headers, so they will show up as a sequence in threaded
@@ -34,15 +34,16 @@
   to = recipient1, recipient2, ...
   cc = cc1, cc2, ...
   bcc = bcc1, bcc2, ...
+  reply-to = address1, address2, ...
 
 Use ``[patchbomb]`` as configuration section name if you need to
 override global ``[email]`` address settings.
 
-Then you can use the "hg email" command to mail a series of changesets
-as a patchbomb.
+Then you can use the :hg:`email` command to mail a series of
+changesets as a patchbomb.
 
 To avoid sending patches prematurely, it is a good idea to first run
-the "email" command with the "-n" option (test only). You will be
+the :hg:`email` command with the "-n" option (test only). You will be
 prompted for an email recipient address, a subject and an introductory
 message describing the patches of your patchbomb. Then when all is
 done, patchbomb messages are displayed. If the PAGER environment
@@ -105,6 +106,10 @@
         raise util.Abort(_('diffstat rejected'))
     return s
 
+def introneeded(opts, number):
+    '''is an introductory message required?'''
+    return number > 1 or opts.get('intro') or opts.get('desc')
+
 def makepatch(ui, repo, patch, opts, _charsets, idx, total, patchname=None):
 
     desc = []
@@ -170,7 +175,7 @@
         flag = ' ' + flag
 
     subj = desc[0].strip().rstrip('. ')
-    if total == 1 and not opts.get('intro'):
+    if not introneeded(opts, total):
         subj = '[PATCH%s] %s' % (flag, opts.get('subject') or subj)
     else:
         tlen = len(str(total))
@@ -192,7 +197,7 @@
     description. Next, (optionally) if the diffstat program is
     installed and -d/--diffstat is used, the result of running
     diffstat on the patch. Finally, the patch itself, as generated by
-    "hg export".
+    :hg:`export`.
 
     By default the patch is included as text in the email body for
     easy reviewing. Using the -a/--attach option will instead create
@@ -249,7 +254,7 @@
     def getpatches(revs):
         for r in cmdutil.revrange(repo, revs):
             output = cStringIO.StringIO()
-            patch.export(repo, [r], fp=output,
+            cmdutil.export(repo, [r], fp=output,
                          opts=patch.diffopts(ui, opts))
             yield output.getvalue().split('\n')
 
@@ -329,7 +334,7 @@
                             len(patches), name)
             msgs.append(msg)
 
-        if len(patches) > 1 or opts.get('intro'):
+        if introneeded(opts, len(patches)):
             tlen = len(str(len(patches)))
 
             flag = ' '.join(opts.get('flag'))
@@ -386,8 +391,9 @@
         msgs = getpatchmsgs(list(getpatches(revs)))
 
     def getaddrs(opt, prpt=None, default=None):
-        if opts.get(opt):
-            return mail.addrlistencode(ui, opts.get(opt), _charsets,
+        addrs = opts.get(opt.replace('-', '_'))
+        if addrs:
+            return mail.addrlistencode(ui, addrs, _charsets,
                                        opts.get('test'))
 
         addrs = (ui.config('email', opt) or
@@ -400,6 +406,7 @@
     to = getaddrs('to', 'To')
     cc = getaddrs('cc', 'Cc', '')
     bcc = getaddrs('bcc')
+    replyto = getaddrs('reply-to')
 
     ui.write('\n')
 
@@ -438,6 +445,8 @@
             m['Cc']  = ', '.join(cc)
         if bcc:
             m['Bcc'] = ', '.join(bcc)
+        if replyto:
+            m['Reply-To'] = ', '.join(replyto)
         if opts.get('test'):
             ui.status(_('Displaying '), subj, ' ...\n')
             ui.flush()
@@ -489,6 +498,7 @@
           ('n', 'test', None, _('print messages that would be sent')),
           ('m', 'mbox', '',
            _('write messages to mbox file instead of sending them')),
+          ('', 'reply-to', [], _('email addresses replies should be sent to')),
           ('s', 'subject', '',
            _('subject of first message (intro or single patch)')),
           ('', 'in-reply-to', '',
--- a/hgext/progress.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/hgext/progress.py	Tue May 11 17:03:44 2010 -0500
@@ -114,7 +114,7 @@
             if tail:
                 used += len(tail) + 1
             progwidth = termwidth - used - 3
-            if total:
+            if total and pos <= total:
                 amt = pos * progwidth // total
                 bar = '=' * (amt - 1)
                 if amt > 0:
@@ -165,10 +165,10 @@
                 self.show(topic, pos, item, unit, total)
         return orig(topic, pos, item=item, unit=unit, total=total)
 
-    def write(self, orig, *args):
+    def write(self, orig, *args, **opts):
         if self.printed:
             self.clear()
-        return orig(*args)
+        return orig(*args, **opts)
 
 sharedprog = None
 
--- a/hgext/purge.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/hgext/purge.py	Tue May 11 17:03:44 2010 -0500
@@ -37,7 +37,7 @@
 
     This means that purge will delete:
 
-    - Unknown files: files marked with "?" by "hg status"
+    - Unknown files: files marked with "?" by :hg:`status`
     - Empty directories: in fact Mercurial ignores directories unless
       they contain files under source control management
 
@@ -45,7 +45,7 @@
 
     - Modified and unmodified tracked files
     - Ignored files (unless --all is specified)
-    - New files added to the repository (with "hg add")
+    - New files added to the repository (with :hg:`add`)
 
     If directories are given on the command line, only files in these
     directories are considered.
--- a/hgext/rebase.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/hgext/rebase.py	Tue May 11 17:03:44 2010 -0500
@@ -14,7 +14,7 @@
 http://mercurial.selenic.com/wiki/RebaseExtension
 '''
 
-from mercurial import util, repair, merge, cmdutil, commands, error
+from mercurial import hg, util, repair, merge, cmdutil, commands, error
 from mercurial import extensions, ancestor, copies, patch
 from mercurial.commands import templateopts
 from mercurial.node import nullrev
@@ -87,6 +87,9 @@
         keepf = opts.get('keep', False)
         keepbranchesf = opts.get('keepbranches', False)
         detachf = opts.get('detach', False)
+        # keepopen is not meant for use on the command line, but by
+        # other extensions
+        keepopen = opts.get('keepopen', False)
 
         if contf or abortf:
             if contf and abortf:
@@ -178,7 +181,7 @@
 
         ui.note(_('rebase merging completed\n'))
 
-        if collapsef:
+        if collapsef and not keepopen:
             p1, p2 = defineparents(repo, min(state), target,
                                                         state, targetancestors)
             commitmsg = 'Collapsed revision'
@@ -344,10 +347,10 @@
     'Update rebased mq patches - finalize and then import them'
     mqrebase = {}
     for p in repo.mq.applied:
-        if repo[p.rev].rev() in state:
+        if repo[p.node].rev() in state:
             repo.ui.debug('revision %d is an mq patch (%s), finalize it.\n' %
-                                        (repo[p.rev].rev(), p.name))
-            mqrebase[repo[p.rev].rev()] = (p.name, isagitpatch(repo, p.name))
+                                        (repo[p.node].rev(), p.name))
+            mqrebase[repo[p.node].rev()] = (p.name, isagitpatch(repo, p.name))
 
     if mqrebase:
         repo.mq.finish(repo, mqrebase.keys())
@@ -444,8 +447,8 @@
     # This check isn't strictly necessary, since mq detects commits over an
     # applied patch. But it prevents messing up the working directory when
     # a partially completed rebase is blocked by mq.
-    if 'qtip' in repo.tags() and (repo[dest].hex() in
-                            [s.rev for s in repo.mq.applied]):
+    if 'qtip' in repo.tags() and (repo[dest].node() in
+                            [s.node for s in repo.mq.applied]):
         raise util.Abort(_('cannot rebase onto an applied mq patch'))
 
     if src:
@@ -501,7 +504,14 @@
 
         cmdutil.bail_if_changed(repo)
         revsprepull = len(repo)
-        orig(ui, repo, *args, **opts)
+        origpostincoming = commands.postincoming
+        def _dummy(*args, **kwargs):
+            pass
+        commands.postincoming = _dummy
+        try:
+            orig(ui, repo, *args, **opts)
+        finally:
+            commands.postincoming = origpostincoming
         revspostpull = len(repo)
         if revspostpull > revsprepull:
             rebase(ui, repo, **opts)
@@ -509,7 +519,7 @@
             dest = repo[branch].rev()
             if dest != repo['.'].rev():
                 # there was nothing to rebase we force an update
-                merge.update(repo, dest, False, False, False)
+                hg.update(repo, dest)
     else:
         orig(ui, repo, *args, **opts)
 
--- a/hgext/record.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/hgext/record.py	Tue May 11 17:03:44 2010 -0500
@@ -293,6 +293,7 @@
                     _('&Quit, recording no changes'),
                     _('&?'))
             r = ui.promptchoice("%s %s" % (query, resps), choices)
+            ui.write("\n")
             if r == 7: # ?
                 doc = gettext(record.__doc__)
                 c = doc.find(_('y - record this change'))
@@ -359,10 +360,10 @@
 def record(ui, repo, *pats, **opts):
     '''interactively select changes to commit
 
-    If a list of files is omitted, all changes reported by "hg status"
+    If a list of files is omitted, all changes reported by :hg:`status`
     will be candidates for recording.
 
-    See 'hg help dates' for a list of formats valid for -d/--date.
+    See :hg:`help dates` for a list of formats valid for -d/--date.
 
     You will be prompted for whether to record changes to each
     modified file, and for files with multiple changes, for each
@@ -387,7 +388,7 @@
 def qrecord(ui, repo, patch, *pats, **opts):
     '''interactively record a new patch
 
-    See 'hg help qnew' & 'hg help record' for more information and
+    See :hg:`help qnew` & :hg:`help record` for more information and
     usage.
     '''
 
@@ -519,7 +520,18 @@
                 os.rmdir(backupdir)
             except OSError:
                 pass
-    return cmdutil.commit(ui, repo, recordfunc, pats, opts)
+
+    # wrap ui.write so diff output can be labeled/colorized
+    def wrapwrite(orig, *args, **kw):
+        label = kw.pop('label', '')
+        for chunk, l in patch.difflabel(lambda: args):
+            orig(chunk, label=label + l)
+    oldwrite = ui.write
+    extensions.wrapfunction(ui, 'write', wrapwrite)
+    try:
+        return cmdutil.commit(ui, repo, recordfunc, pats, opts)
+    finally:
+        ui.write = oldwrite
 
 cmdtable = {
     "record":
@@ -543,7 +555,7 @@
         (qrecord,
 
          # add qnew options, except '--force'
-         [opt for opt in mq.cmdtable['qnew'][1] if opt[1] != 'force'],
+         [opt for opt in mq.cmdtable['^qnew'][1] if opt[1] != 'force'],
 
          _('hg qrecord [OPTION]... PATCH [FILE]...')),
     }
--- a/hgext/relink.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/hgext/relink.py	Tue May 11 17:03:44 2010 -0500
@@ -145,7 +145,7 @@
         except OSError, inst:
             ui.warn('%s: %s\n' % (tgt, str(inst)))
 
-    ui.progress(_('relinking'), None, unit=_(' files'), total=total)
+    ui.progress(_('relinking'), None)
 
     ui.status(_('relinked %d files (%d bytes reclaimed)\n') %
               (relinked, savedbytes))
--- a/hgext/zeroconf/__init__.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/hgext/zeroconf/__init__.py	Tue May 11 17:03:44 2010 -0500
@@ -98,16 +98,17 @@
     server.registerService(svc)
 
 class hgwebzc(hgweb_mod.hgweb):
-    def __init__(self, repo, name=None):
-        super(hgwebzc, self).__init__(repo, name)
-        name = self.reponame or os.path.basename(repo.root)
+    def __init__(self, repo, name=None, baseui=None):
+        super(hgwebzc, self).__init__(repo, name=name, baseui=baseui)
+        name = self.reponame or os.path.basename(self.repo.root)
         path = self.repo.ui.config("web", "prefix", "").strip('/')
         desc = self.repo.ui.config("web", "description", name)
-        publish(name, desc, path, int(repo.ui.config("web", "port", 8000)))
+        publish(name, desc, path,
+                int(self.repo.ui.config("web", "port", 8000)))
 
 class hgwebdirzc(hgwebdir_mod.hgwebdir):
     def __init__(self, conf, baseui=None):
-        super(hgwebdirzc, self).__init__(conf, baseui)
+        super(hgwebdirzc, self).__init__(conf, baseui=baseui)
         prefix = self.ui.config("web", "prefix", "").strip('/') + '/'
         for repo, path in self.repos:
             u = self.ui.copy()
--- a/hgweb.cgi	Mon Dec 07 12:31:45 2009 +0200
+++ b/hgweb.cgi	Tue May 11 17:03:44 2010 -0500
@@ -1,28 +1,17 @@
 #!/usr/bin/env python
 #
-# An example CGI script to use hgweb, edit as necessary
+# An example hgweb CGI script, edit as necessary
 
-# adjust python path if not a system-wide install:
-#import sys
-#sys.path.insert(0, "/path/to/python/lib")
+# Path to repo or hgweb config to serve (see 'hg help hgweb')
+config = "/path/to/repo/or/config"
 
-# enable importing on demand to reduce startup time
-from mercurial import demandimport; demandimport.enable()
+# Uncomment and adjust if Mercurial is not installed system-wide:
+#import sys; sys.path.insert(0, "/path/to/python/lib")
 
 # Uncomment to send python tracebacks to the browser if an error occurs:
-#import cgitb
-#cgitb.enable()
+#import cgitb; cgitb.enable()
 
-# If you'd like to serve pages with UTF-8 instead of your default
-# locale charset, you can do so by uncommenting the following lines.
-# Note that this will cause your .hgrc files to be interpreted in
-# UTF-8 and all your repo files to be displayed using UTF-8.
-#
-#import os
-#os.environ["HGENCODING"] = "UTF-8"
-
-from mercurial.hgweb.hgweb_mod import hgweb
-import mercurial.hgweb.wsgicgi as wsgicgi
-
-application = hgweb("/path/to/repo", "repository name")
+from mercurial import demandimport; demandimport.enable()
+from mercurial.hgweb import hgweb, wsgicgi
+application = hgweb(config)
 wsgicgi.launch(application)
--- a/hgwebdir.cgi	Mon Dec 07 12:31:45 2009 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-#!/usr/bin/env python
-#
-# An example CGI script to export multiple hgweb repos, edit as necessary
-
-# adjust python path if not a system-wide install:
-#import sys
-#sys.path.insert(0, "/path/to/python/lib")
-
-# enable importing on demand to reduce startup time
-from mercurial import demandimport; demandimport.enable()
-
-# Uncomment to send python tracebacks to the browser if an error occurs:
-#import cgitb
-#cgitb.enable()
-
-# If you'd like to serve pages with UTF-8 instead of your default
-# locale charset, you can do so by uncommenting the following lines.
-# Note that this will cause your .hgrc files to be interpreted in
-# UTF-8 and all your repo files to be displayed using UTF-8.
-#
-#import os
-#os.environ["HGENCODING"] = "UTF-8"
-
-from mercurial.hgweb.hgwebdir_mod import hgwebdir
-import mercurial.hgweb.wsgicgi as wsgicgi
-
-# The config file looks like this.  You can have paths to individual
-# repos, collections of repos in a directory tree, or both.
-#
-# [paths]
-# virtual/path1 = /real/path1
-# virtual/path2 = /real/path2
-# virtual/root = /real/root/*
-# / = /real/root2/*
-# virtual/root2 = /real/root2/**
-#
-# [collections]
-# /prefix/to/strip/off = /root/of/tree/full/of/repos
-#
-# paths example:
-#
-# * First two lines mount one repository into one virtual path, like
-# '/real/path1' into 'virtual/path1'.
-#
-# * The third entry mounts every mercurial repository found in '/real/root'
-# in 'virtual/root'. This format is preferred over the [collections] one,
-# since using absolute paths as configuration keys is not supported on every
-# platform (especially on Windows).
-#
-# * The fourth entry is a special case mounting all repositories in
-# /'real/root2' in the root of the virtual directory.
-#
-# * The fifth entry recursively finds all repositories under the real root,
-# and mounts them using their relative path (to given real root) under the
-# virtual root.
-#
-# collections example: say directory tree /foo contains repos /foo/bar,
-# /foo/quux/baz.  Give this config section:
-#   [collections]
-#   /foo = /foo
-# Then repos will list as bar and quux/baz.
-#
-# Alternatively you can pass a list of ('virtual/path', '/real/path') tuples
-# or use a dictionary with entries like 'virtual/path': '/real/path'
-
-application = hgwebdir('hgweb.config')
-wsgicgi.launch(application)
--- a/i18n/da.po	Mon Dec 07 12:31:45 2009 +0200
+++ b/i18n/da.po	Tue May 11 17:03:44 2010 -0500
@@ -17,8 +17,8 @@
 msgstr ""
 "Project-Id-Version: Mercurial\n"
 "Report-Msgid-Bugs-To: <mercurial-devel@selenic.com>\n"
-"POT-Creation-Date: 2010-04-04 23:48+0200\n"
-"PO-Revision-Date: 2010-04-05 01:09+0200\n"
+"POT-Creation-Date: 2010-04-05 01:22+0200\n"
+"PO-Revision-Date: 2010-04-05 01:37+0200\n"
 "Last-Translator:  <mg@lazybytes.net>\n"
 "Language-Team: Danish\n"
 "MIME-Version: 1.0\n"
@@ -425,9 +425,8 @@
 msgid "Revision %d is a merge, ignoring...\n"
 msgstr "Revision %d er en sammenføjning; ignorerer...\n"
 
-#, python-format
-msgid "generating stats: %d%%"
-msgstr "genererer statistik: %d%%"
+msgid "analyzing"
+msgstr ""
 
 msgid ""
 "histogram of changes to the repository\n"
@@ -524,11 +523,8 @@
 msgid "file with email aliases"
 msgstr "fil med email-aliaser"
 
-msgid "show progress"
-msgstr "vis fremskridt"
-
-msgid "hg churn [-d DATE] [-r REV] [--aliases FILE] [--progress] [FILE]"
-msgstr "hg churn [-d DATO] [-r REV] [--aliases FIL] [--progress] [FIL]"
+msgid "hg churn [-d DATE] [-r REV] [--aliases FILE] [FILE]"
+msgstr "hg churn [-d DATO] [-r REV] [--aliases FIL] [FIL]"
 
 msgid ""
 "colorize output from some commands\n"
@@ -2168,9 +2164,6 @@
 "\n"
 "nøgleord skrevet til %s:\n"
 
-msgid "unhooked all commit hooks\n"
-msgstr ""
-
 msgid "hg keyword configuration and expansion example"
 msgstr "eksempel på konfiguration og ekspansion af nøgleord"
 
@@ -2259,12 +2252,6 @@
 msgid "only show unknown (not tracked) files"
 msgstr "vis kun ukendte (ikke-fulgte) filer"
 
-msgid "show keyword status flags of all files (DEPRECATED)"
-msgstr "vis keyword status for alle filer (FORÆLDET)"
-
-msgid "only show untracked files (DEPRECATED)"
-msgstr "vis kun ikke-fulgte filer (FORÆLDET)"
-
 msgid "hg kwfiles [OPTION]... [FILE]..."
 msgstr "hg kwfiles [TILVALG]... [FIL]..."
 
@@ -4776,6 +4763,9 @@
 msgid "invalid format spec '%%%s' in output filename"
 msgstr "ugyldig formatspecifikation '%%%s' i output filnavn"
 
+msgid "searching"
+msgstr "søger"
+
 #, python-format
 msgid "adding %s\n"
 msgstr "tilføjer %s\n"
@@ -5103,8 +5093,10 @@
 "    By default, the revision used is the parent of the working\n"
 "    directory; use -r/--rev to specify a different revision.\n"
 "\n"
-"    To specify the type of archive to create, use -t/--type. Valid\n"
-"    types are:\n"
+"    The archive type is automatically detected based on file\n"
+"    extension (or override using -t/--type).\n"
+"\n"
+"    Valid types are:\n"
 "\n"
 "    :``files``: a directory full of files (default)\n"
 "    :``tar``:   tar archive, uncompressed\n"
@@ -6781,6 +6773,10 @@
 "    By default, the server logs accesses to stdout and errors to\n"
 "    stderr. Use the -A/--accesslog and -E/--errorlog options to log to\n"
 "    files.\n"
+"\n"
+"    To have the server choose a free port number to listen on, specify\n"
+"    a port number of 0; in this case, the server will print the port\n"
+"    number it uses.\n"
 "    "
 msgstr ""
 "eksporter depotet via HTTP\n"
@@ -6790,6 +6786,10 @@
 "    Som standard logger serveren forespørgsler til stdout og fejl til\n"
 "    stderr. Brug -A/--accesslog og -E/--errorlog tilvalgene for at\n"
 "    logge til filer.\n"
+"\n"
+"    For at få serveren til at vælge et frit portnummer at lytte til,\n"
+"    angiv da portnummer 0; så vil serveren skrive det portnummer den\n"
+"    bruger.\n"
 "    "
 
 #, python-format
@@ -7739,7 +7739,7 @@
 msgid "name of error log file to write to"
 msgstr "navn på fejlllog fil der skrives til"
 
-msgid "port to listen on (default: 8000)"
+msgid "port to listen on (default: 8000"
 msgstr "port der skal lyttes på (standard: 8000)"
 
 msgid "address to listen on (default: all interfaces)"
@@ -9156,9 +9156,6 @@
 msgid "queries"
 msgstr ""
 
-msgid "searching"
-msgstr "søger"
-
 msgid "already have changeset "
 msgstr "har allerede ændringen "
 
@@ -9493,6 +9490,15 @@
 msgid "Unsupported line endings type: %s"
 msgstr "Linieendelse %s understøttes ikke"
 
+msgid ""
+"internal patcher failed\n"
+"please report details to http://mercurial.selenic.com/bts/\n"
+"or mercurial@selenic.com\n"
+msgstr ""
+"intern lappe-funktionalitet fejlede\n"
+"angiv venligst fejldetaljer på http://mercurial.selenic.com/bts/\n"
+"eller mercurial@selenic.com\n"
+
 #, python-format
 msgid " %d files changed, %d insertions(+), %d deletions(-)\n"
 msgstr "%d filer ændret, %d indsættelser(+), %d sletninger(-)\n"
@@ -9640,8 +9646,8 @@
 msgstr "fjerner underdepot %s\n"
 
 #, python-format
-msgid "pulling subrepo %s\n"
-msgstr "hiver fra underdepot %s\n"
+msgid "pulling subrepo %s from %s\n"
+msgstr "hiver underdepot %s fra %s\n"
 
 #, python-format
 msgid "pushing subrepo %s\n"
--- a/i18n/fr.po	Mon Dec 07 12:31:45 2009 +0200
+++ b/i18n/fr.po	Tue May 11 17:03:44 2010 -0500
@@ -1,17 +1,17 @@
 # French translations for Mercurial
 # Traductions françaises de Mercurial
 # Copyright (C) 2009 Matt Mackall <mpm@selenic.com> and others
-#
+# 
 # Quelques règles :
 # - dans l'aide d'une commande, la première ligne descriptive
 #   commence par un verbe au présent sans majuscule
 # - dans l'aide d'une commande, la description des options
 #   utilise un verbe à l'infinitif
-#
+# 
 # Note : la terminologie ci-dessous est loin d'être complète, figée ou
 #        parfaite. À compléter et à améliorer, particulièrement les
 #        termes comportant un point d'interrogation...
-#
+# 
 # Dictionnaire de termes courants :
 #  - to  apply a patch        appliquer un patch
 #  - a   branch               une branche
@@ -46,7 +46,7 @@
 #        untracked            non suivi, non géré, pas sous contrôle du dépôt,
 #                             hors révision ?
 #  - the working directory    le répertoire de travail
-#
+# 
 # Termes très courants repris de l'anglais - à utiliser sans guillemets
 # pour ne pas alourdir inutilement la traduction :
 #  - a   diff                 un diff ? (ou également un patch ? synonymes...)
@@ -54,7 +54,7 @@
 #  - a   patch                un patch
 #  - a   tag                  un tag
 #  - to  tag                  taguer
-#
+# 
 # Termes anglais avec une signification très spécifique, difficile à
 # paraphraser sans alourdir ou perdre le sens - à utiliser avec guillemets :
 #  - a   bundle               un \"bundle\"
@@ -62,7 +62,7 @@
 #  - a   changeset            un \"changeset\"
 #  - a   changegroup          un \"changegroup\"
 #  - the tip                  la révision \"tip\"
-#
+# 
 # Termes dont le classement / la traduction sont à déterminer :
 #  - a   commit               un commit, un \"commit\"
 #  - to  commit               \"committer\" ? (beuark, même dit tous les jours)
@@ -73,7 +73,7 @@
 #  - to  push                 propager ? (utilisé par svn pour commit)
 #                             publier ? pousser ?? envoyer ??
 #  - the series file (mq)     ?
-#
+# 
 # Notes :
 #  - (cédric) je verrais bien l'ajout d'une rubrique générale dans l'aide
 #    (par exemple 'hg help glossary') librement remplissable par chaque équipe
@@ -81,7 +81,7 @@
 #    qui vont être rencontrés dans mercurial - et en particulier permettrait
 #    de faire le lien avec des termes franglisants parfois utilisés
 #    (par ex. fusionner = "merger", etc.) ... ?
-#
+# 
 msgid ""
 msgstr ""
 "Project-Id-Version: Mercurial\n"
@@ -100,10 +100,10 @@
 msgstr " (défaut: %s)"
 
 msgid "OPTIONS"
-msgstr ""
+msgstr "OPTIONS"
 
 msgid "COMMANDS"
-msgstr ""
+msgstr "COMMANDES"
 
 #, fuzzy
 msgid ""
@@ -454,8 +454,7 @@
 "A template is a piece of text, with markup to invoke variable\n"
 "expansion::\n"
 "\n"
-"    $ hg log -r1 --template \"{node}\\n\"\n"
-"    b56ce7b07c52de7d5fd79fb89701ea538af65746\n"
+"    $ hg log -r1 --template \"{node}\\n\"\\n    b56ce7b07c52de7d5fd79fb89701ea538af65746\n"
 "\n"
 "Strings in curly braces are called keywords. The availability of\n"
 "keywords depends on the exact context of the templater. These\n"
@@ -492,8 +491,7 @@
 "variable. You can also use a chain of filters to get the desired\n"
 "output::\n"
 "\n"
-"   $ hg tip --template \"{date|isodate}\\n\"\n"
-"   2008-08-21 18:22 +0000\n"
+"   $ hg tip --template \"{date|isodate}\\n\"\\n   2008-08-21 18:22 +0000\n"
 "\n"
 "List of filters:\n"
 "\n"
@@ -713,8 +711,9 @@
 "    "
 msgstr ""
 
+#, fuzzy
 msgid "a bookmark of this name does not exist"
-msgstr ""
+msgstr "un signet de ce nom n'existe pas"
 
 msgid "a bookmark of the same name already exists"
 msgstr ""
@@ -738,10 +737,10 @@
 msgstr ""
 
 msgid "delete a given bookmark"
-msgstr ""
+msgstr "Supprimer un signet donné"
 
 msgid "rename a given bookmark"
-msgstr ""
+msgstr "Renommer un signet donné"
 
 msgid "hg bookmarks [-f] [-d] [-m NAME] [-r REV] [NAME]"
 msgstr ""
@@ -821,8 +820,7 @@
 "    {hgweb}     Base URL for browsing Mercurial repositories.\n"
 "\n"
 "  Default 'changeset {node|short} in repo {root} refers '\n"
-"          'to bug {bug}.\\ndetails:\\n\\t{desc|tabindent}'\n"
-"\n"
+"          'to bug {bug}.\\ndetails:\\n\\t{desc|tabindent}'\\n\n"
 "strip\n"
 "  The number of slashes to strip from the front of {root} to produce\n"
 "  {webroot}. Default 0.\n"
@@ -864,9 +862,7 @@
 "    bzuser=unknown@domain.com\n"
 "    bzdir=/opt/bugzilla-3.2\n"
 "    template=Changeset {node|short} in {root|basename}.\n"
-"             {hgweb}/{webroot}/rev/{node|short}\\n\n"
-"             {desc}\\n\n"
-"    strip=5\n"
+"             {hgweb}/{webroot}/rev/{node|short}\\n\\n             {desc}\\n\\n    strip=5\n"
 "\n"
 "    [web]\n"
 "    baseurl=http://dev.domain.com/hg\n"
@@ -973,8 +969,9 @@
 msgid "hg children [-r REV] [FILE]"
 msgstr ""
 
+#, fuzzy
 msgid "command to display statistics about repository history"
-msgstr ""
+msgstr "Commande pour afficher les statistiques de l'historique du repository"
 
 #, python-format
 msgid "Revision %d is a merge, ignoring...\n"
@@ -1393,9 +1390,7 @@
 msgid "hg debugcvsps [OPTION]... [PATH]..."
 msgstr ""
 
-msgid ""
-"warning: lightweight checkouts may cause conversion failures, try with a "
-"regular branch instead.\n"
+msgid "warning: lightweight checkouts may cause conversion failures, try with a regular branch instead.\n"
 msgstr ""
 
 msgid "bzr source type could not be determined\n"
@@ -1439,18 +1434,19 @@
 
 #, python-format
 msgid "%s: unknown repository type"
-msgstr ""
+msgstr "%s : type de dépôt inconnu"
 
 #, python-format
 msgid "unknown sort mode: %s"
-msgstr ""
+msgstr "mode de tri inconnu: %s"
 
 #, python-format
 msgid "cycle detected between %s and %s"
-msgstr ""
-
+msgstr "cycle détecté entre %s et %s"
+
+#, fuzzy
 msgid "not all revisions were sorted"
-msgstr ""
+msgstr "Touts les révisions n'ont pas été triées"
 
 #, python-format
 msgid "Writing author map file %s\n"
@@ -1475,22 +1471,24 @@
 msgid "scanning source...\n"
 msgstr ""
 
+#, fuzzy
 msgid "sorting...\n"
-msgstr ""
-
+msgstr "tri en cours...\n"
+
+#, fuzzy
 msgid "converting...\n"
-msgstr ""
+msgstr "conversion en cours...\n"
 
 #, python-format
 msgid "source: %s\n"
-msgstr ""
+msgstr "source: %s\n"
 
 #, python-format
 msgid "assuming destination %s\n"
 msgstr ""
 
 msgid "more than one sort mode specified"
-msgstr ""
+msgstr "plus d'un mode de tri specifié"
 
 msgid "--sourcesort is not supported by this data source"
 msgstr ""
@@ -1501,55 +1499,56 @@
 
 #, python-format
 msgid "connecting to %s\n"
-msgstr ""
+msgstr "connexion à %s\n"
 
 msgid "CVS pserver authentication failed"
-msgstr ""
-
-#, python-format
-msgid ""
-"unexpected response from CVS server (expected \"Valid-requests\", but got %r)"
-msgstr ""
+msgstr "l'authentification au serveur CVS a échoué"
+
+#, python-format, fuzzy
+msgid "unexpected response from CVS server (expected \"Valid-requests\", but got %r)"
+msgstr "réponse innatendue du serveur CVS (\\'Valid-requests\" attendue, mais %r reçue)"
 
 #, python-format
 msgid "%d bytes missing from remote file"
-msgstr ""
+msgstr "%d bytes manquants dans le fichier distant"
 
 #, python-format
 msgid "cvs server: %s\n"
-msgstr ""
+msgstr "serveur cvs : %s\n"
 
 #, python-format
 msgid "unknown CVS response: %s"
-msgstr ""
-
+msgstr "Réponse CVS inconnue : %s"
+
+#, fuzzy
 msgid "collecting CVS rlog\n"
-msgstr ""
+msgstr "récupération des rlog CVS\n"
 
 #, python-format
 msgid "reading cvs log cache %s\n"
 msgstr ""
 
-#, python-format
+#, python-format, fuzzy
 msgid "cache has %d log entries\n"
-msgstr ""
+msgstr "le cache a %d entrées de log\n"
 
 #, python-format
 msgid "error reading cache: %r\n"
-msgstr ""
+msgstr "erreur lors de la lecture du cache : %r\n"
 
 #, python-format
 msgid "running %s\n"
 msgstr ""
 
+#, fuzzy
 msgid "RCS file must be followed by working file"
-msgstr ""
+msgstr "le fichier RCS doit être suivi par le fichier de travail"
 
 msgid "must have at least some revisions"
 msgstr ""
 
 msgid "expected revision number"
-msgstr ""
+msgstr "numéro de révision attendu"
 
 msgid "revision must be followed by date line"
 msgstr ""
@@ -1558,9 +1557,9 @@
 msgid "writing cvs log cache %s\n"
 msgstr ""
 
-#, python-format
+#, python-format, fuzzy
 msgid "%d log entries\n"
-msgstr ""
+msgstr "%d entrées dans les log\n"
 
 msgid "creating changesets\n"
 msgstr ""
@@ -1580,10 +1579,10 @@
 
 #, python-format
 msgid "darcs version 2.1 or newer needed (found %r)"
-msgstr ""
+msgstr "darcs version 2.1 ou supérieur nécessaire (trouvé %r)"
 
 msgid "Python ElementTree module is not available"
-msgstr ""
+msgstr "Le module Python ElementTree n'est pas disponible"
 
 msgid "internal calling inconsistency"
 msgstr ""
@@ -1614,8 +1613,7 @@
 msgstr ""
 
 #, python-format
-msgid ""
-"tree analysis stopped because it points to an unregistered archive %s...\n"
+msgid "tree analysis stopped because it points to an unregistered archive %s...\n"
 msgstr ""
 
 #, python-format
@@ -1624,7 +1622,7 @@
 
 #, python-format
 msgid "%s is not a local Mercurial repo"
-msgstr ""
+msgstr "%s n'est pas un dépôt local de Mercurial"
 
 #, python-format
 msgid "initializing destination %s repository\n"
@@ -1638,7 +1636,7 @@
 msgstr ""
 
 msgid "updating tags\n"
-msgstr ""
+msgstr "mise à jour des tags\n"
 
 #, python-format
 msgid "%s is not a valid start revision"
@@ -1675,9 +1673,9 @@
 msgid "Subversion python bindings are too old, 1.4 or later required"
 msgstr ""
 
-#, python-format
+#, python-format, fuzzy
 msgid "svn: revision %s is not an integer"
-msgstr ""
+msgstr "svn : la révision %s n'est pas un entier"
 
 #, python-format
 msgid "svn: start revision %s is not an integer"
@@ -1712,7 +1710,7 @@
 
 #, python-format
 msgid "no tags found at revision %d\n"
-msgstr ""
+msgstr "aucun tag trouvé dans la révision %d\n"
 
 #, python-format
 msgid "%s not found up to revision %d"
@@ -1732,7 +1730,7 @@
 
 #, python-format
 msgid "initializing svn repo %r\n"
-msgstr ""
+msgstr "initialisation du dépôt svn %r\n"
 
 #, python-format
 msgid "initializing svn wc %r\n"
@@ -1745,7 +1743,7 @@
 msgstr ""
 
 msgid "XXX TAGS NOT IMPLEMENTED YET\n"
-msgstr ""
+msgstr "XXX TAGS PAS ENCORE IMPLÉMENTÉ\n"
 
 msgid ""
 "command to allow external programs to compare revisions\n"
@@ -1796,7 +1794,7 @@
 msgstr ""
 
 msgid "cleaning up temp directory\n"
-msgstr ""
+msgstr "nettoyage du dossier temporaire\n"
 
 msgid ""
 "use external program to diff repository (or selected files)\n"
@@ -1837,10 +1835,8 @@
 "    %(path)s program.\n"
 "\n"
 "    When two revision arguments are given, then changes are shown between\n"
-"    those revisions. If only one revision is specified then that revision "
-"is\n"
-"    compared to the working directory, and, when no revisions are "
-"specified,\n"
+"    those revisions. If only one revision is specified then that revision is\n"
+"    compared to the working directory, and, when no revisions are specified,\n"
 "    the working directory files are compared to its parent."
 msgstr ""
 
@@ -1871,8 +1867,7 @@
 "    "
 msgstr ""
 
-msgid ""
-"working dir not at branch tip (use \"hg update\" to check out branch tip)"
+msgid "working dir not at branch tip (use \"hg update\" to check out branch tip)"
 msgstr ""
 
 msgid "outstanding uncommitted merge"
@@ -1884,23 +1879,18 @@
 msgid "working directory is missing some files"
 msgstr ""
 
-msgid ""
-"multiple heads in this branch (use \"hg heads .\" and \"hg merge\" to merge)"
+msgid "multiple heads in this branch (use \"hg heads .\" and \"hg merge\" to merge)"
 msgstr ""
 
 #, python-format
 msgid "pulling from %s\n"
 msgstr ""
 
-msgid ""
-"Other repository doesn't support revision lookup, so a rev cannot be "
-"specified."
-msgstr ""
-
-#, python-format
-msgid ""
-"not merging with %d other new branch heads (use \"hg heads .\" and \"hg merge"
-"\" to merge them)\n"
+msgid "Other repository doesn't support revision lookup, so a rev cannot be specified."
+msgstr ""
+
+#, python-format
+msgid "not merging with %d other new branch heads (use \"hg heads .\" and \"hg merge\" to merge them)\n"
 msgstr ""
 
 #, python-format
@@ -1934,7 +1924,7 @@
 msgstr ""
 
 msgid "error while verifying signature"
-msgstr ""
+msgstr "erreur lors de la vérification de la signature"
 
 #, python-format
 msgid "%s Bad signature from \"%s\"\n"
@@ -1951,16 +1941,16 @@
 msgid "list signed changesets"
 msgstr ""
 
-#, python-format
+#, python-format, fuzzy
 msgid "%s:%d node does not exist\n"
-msgstr ""
+msgstr "%s: le noeud %d n'existe pas\n"
 
 msgid "verify all the signatures there may be for a particular revision"
 msgstr ""
 
 #, python-format
 msgid "No valid signature for %s\n"
-msgstr ""
+msgstr "Signature invalide pour %s\n"
 
 msgid ""
 "add a signature for the current or given revision\n"
@@ -1978,9 +1968,7 @@
 msgid "Error while signing"
 msgstr ""
 
-msgid ""
-"working copy of .hgsigs is changed (please commit .hgsigs manually or use --"
-"force)"
+msgid "working copy of .hgsigs is changed (please commit .hgsigs manually or use --force)"
 msgstr ""
 
 msgid "unknown signature version"
@@ -2071,8 +2059,7 @@
 "  # Append a diffstat to the log message (optional)\n"
 "  #diffstat = False\n"
 "  # Template to use for log messages (optional)\n"
-"  #template = {desc}\\n{baseurl}/rev/{node}-- {diffstat}\n"
-"  # Style to use (optional)\n"
+"  #template = {desc}\\n{baseurl}/rev/{node}-- {diffstat}\\n  # Style to use (optional)\n"
 "  #style = foo\n"
 "  # The URL of the CIA notification service (optional)\n"
 "  # You can use mailto: URLs to send by email, eg\n"
@@ -2163,7 +2150,7 @@
 msgstr ""
 
 msgid "recursive"
-msgstr ""
+msgstr "récursif"
 
 msgid "pretty"
 msgstr ""
@@ -2175,7 +2162,7 @@
 msgstr ""
 
 msgid "search"
-msgstr ""
+msgstr "recherche"
 
 msgid "hg git-diff-tree [OPTION]... NODE1 NODE2 [FILE]..."
 msgstr ""
@@ -2190,19 +2177,19 @@
 msgstr ""
 
 msgid "ignored"
-msgstr ""
+msgstr "ignoré"
 
 msgid "hg debug-rev-parse REV"
 msgstr ""
 
 msgid "header"
-msgstr ""
+msgstr "en-tête"
 
 msgid "topo-order"
 msgstr ""
 
 msgid "parents"
-msgstr ""
+msgstr "parent"
 
 msgid "max-count"
 msgstr ""
@@ -2296,7 +2283,7 @@
 
 #, python-format
 msgid "found %d\n"
-msgstr ""
+msgstr "trouvé %d\n"
 
 #, python-format
 msgid "*** to raise the limit from %d to %d (run as root):\n"
@@ -2400,8 +2387,7 @@
 "\n"
 "  [interhg]\n"
 "  issues = s!issue(\\d+)!<a href=\"http://bts/issue\\1\">issue\\1</a>!\n"
-"  bugzilla = s!((?:bug|b=|(?=#?\\d{4,}))(?:\\s*#?)(\\d+))!<a..=\\2\">\\1</a>!"
-"i\n"
+"  bugzilla = s!((?:bug|b=|(?=#?\\d{4,}))(?:\\s*#?)(\\d+))!<a..=\\2\">\\1</a>!i\n"
 "  boldify = s!(^|\\s)#(\\d+)\\b! <b>#\\2</b>!\n"
 msgstr ""
 
@@ -2735,8 +2721,7 @@
 msgstr "le patch %s n'est pas appliqué\n"
 
 msgid "patch failed, unable to continue (try -v)\n"
-msgstr ""
-"l'application du patch a échoué, impossible de continuer (essayez avec -v)\n"
+msgstr "l'application du patch a échoué, impossible de continuer (essayez avec -v)\n"
 
 #, python-format
 msgid "applying %s\n"
@@ -2860,9 +2845,7 @@
 
 #, python-format
 msgid "errors during apply, please fix and refresh %s\n"
-msgstr ""
-"des erreurs se sont produites durant l'application, veuillez corriger puis "
-"rafraîchir %s\n"
+msgstr "des erreurs se sont produites durant l'application, veuillez corriger puis rafraîchir %s\n"
 
 #, python-format
 msgid "now at: %s\n"
@@ -2880,16 +2863,14 @@
 msgstr "qpop: %s est déjà le dernier patch appliqué\n"
 
 msgid "qpop: forcing dirstate update\n"
-msgstr ""
-"qpop: mise à jour de l'état du répertoire de travail (dirstate) forcée\n"
+msgstr "qpop: mise à jour de l'état du répertoire de travail (dirstate) forcée\n"
 
 #, python-format
 msgid "trying to pop unknown node %s"
 msgstr "tentative de dépilement d'un nœud inconnu : %s"
 
 msgid "popping would remove a revision not managed by this patch queue"
-msgstr ""
-"le dépilement enlèverait une révision non gérée par cette pile de patchs"
+msgstr "le dépilement enlèverait une révision non gérée par cette pile de patchs"
 
 msgid "deletions found between repo revs"
 msgstr "suppressions trouvées entre des révisions du dépôt"
@@ -2905,12 +2886,8 @@
 msgstr "impossible de rafraîchir une révision possédant des révisions filles"
 
 # restaurer/récupérer ? pas satisfait...
-msgid ""
-"refresh interrupted while patch was popped! (revert --all, qpush to "
-"recover)\n"
-msgstr ""
-"rafraîchissement interrompu alors qu'un patch était en cours de dépilement "
-"(utiliser revert --all, ou qpush pour restaurer l'état)\n"
+msgid "refresh interrupted while patch was popped! (revert --all, qpush to recover)\n"
+msgstr "rafraîchissement interrompu alors qu'un patch était en cours de dépilement (utiliser revert --all, ou qpush pour restaurer l'état)\n"
 
 msgid "patch queue directory already exists"
 msgstr "la pile de patchs existe déjà"
@@ -2963,9 +2940,7 @@
 msgstr "l'option \"-r\" n'est pas utilisable lors de l'importation de fichiers"
 
 msgid "option \"-n\" not valid when importing multiple patches"
-msgstr ""
-"l'option \"-n\" n'est pas utilisable lors de l'importation de plusieurs "
-"patchs"
+msgstr "l'option \"-n\" n'est pas utilisable lors de l'importation de plusieurs patchs"
 
 # origine/base/racine ?
 #, python-format
@@ -3009,8 +2984,7 @@
 msgid ""
 "remove patches from queue\n"
 "\n"
-"    The patches must not be applied, and at least one patch is required. "
-"With\n"
+"    The patches must not be applied, and at least one patch is required. With\n"
 "    -k/--keep, the patch files are preserved in the patch directory.\n"
 "\n"
 "    To stop managing a patch and move it into permanent history,\n"
@@ -3678,9 +3652,7 @@
 msgstr "hg qpush [-f] [-l] [-a] [-m] [-n NOM] [PATCH | INDEX]"
 
 msgid "refresh only files already in the patch and specified files"
-msgstr ""
-"ne rafraîchir que les fichiers déjà présent dans le patch et ceux "
-"explicitement spécifiés"
+msgstr "ne rafraîchir que les fichiers déjà présent dans le patch et ceux explicitement spécifiés"
 
 msgid "add/update author field in patch with current user"
 msgstr ""
@@ -3812,8 +3784,7 @@
 "  maxdiff = 300          # max lines of diffs to include (0=none, -1=all)\n"
 "  maxsubject = 67        # truncate subject line longer than this\n"
 "  diffstat = True        # add a diffstat before the diff content\n"
-"  sources = serve        # notify if source of incoming changes in this "
-"list\n"
+"  sources = serve        # notify if source of incoming changes in this list\n"
 "                         # (serve == ssh or http, push, pull, bundle)\n"
 "  merge = False          # send notification for merges (default True)\n"
 "  [email]\n"
@@ -4138,10 +4109,8 @@
 "\n"
 "      hg email -b               # send bundle of all patches not in default\n"
 "      hg email -b DEST          # send bundle of all patches not in DEST\n"
-"      hg email -b -r 3000       # bundle of all ancestors of 3000 not in "
-"default\n"
-"      hg email -b -r 3000 DEST  # bundle of all ancestors of 3000 not in "
-"DEST\n"
+"      hg email -b -r 3000       # bundle of all ancestors of 3000 not in default\n"
+"      hg email -b -r 3000 DEST  # bundle of all ancestors of 3000 not in DEST\n"
 "\n"
 "    Before using this command, you will need to enable email in your\n"
 "    hgrc. See the [email] section in hgrc(5) for details.\n"
@@ -4201,9 +4170,7 @@
 msgstr "veuillez spécifier au minimum un \"changeset\", à l'aide de -r ou -o"
 
 msgid "--outgoing mode always on with --bundle; do not re-specify --outgoing"
-msgstr ""
-"ne pas spécifier --outgoing, qui est systématiquement activé lorsque --"
-"bundle est utilisé"
+msgstr "ne pas spécifier --outgoing, qui est systématiquement activé lorsque --bundle est utilisé"
 
 msgid "too many destinations"
 msgstr "trop de destinations"
@@ -4272,8 +4239,7 @@
 msgstr "afficher les messages tels qu'ils seraient envoyés"
 
 msgid "write messages to mbox file instead of sending them"
-msgstr ""
-"écrire les messages dans un fichier au format \"mbox\" au lieu de les envoyer"
+msgstr "écrire les messages dans un fichier au format \"mbox\" au lieu de les envoyer"
 
 msgid "subject of first message (intro or single patch)"
 msgstr "sujet du premier message (intro ou patch unique)"
@@ -4294,9 +4260,7 @@
 msgstr "envoyer les modifications non présentes dans le dépôt cible"
 
 msgid "send changes not in target as a binary bundle"
-msgstr ""
-"envoyer les modifications non présentes dans le dépôt cible sous forme de "
-"\"bundle\" binaire"
+msgstr "envoyer les modifications non présentes dans le dépôt cible sous forme de \"bundle\" binaire"
 
 msgid "name of the bundle attachment file"
 msgstr "nom à donner au fichier \"bundle\" envoyé"
@@ -4308,9 +4272,7 @@
 msgstr "procéder même si le dépôt cible n'est pas apparenté (avec -b/--bundle)"
 
 msgid "a base changeset to specify instead of a destination (with -b/--bundle)"
-msgstr ""
-"un \"changeset\" à utiliser comme point de départ, au lieu d'une destination "
-"(avec -b/--bundle)"
+msgstr "un \"changeset\" à utiliser comme point de départ, au lieu d'une destination (avec -b/--bundle)"
 
 msgid "send an introduction email for a single patch"
 msgstr "envoyer un courriel d'introduction pour un patch seul"
@@ -4402,9 +4364,7 @@
 msgstr "afficher les nom des fichiers au lieu de les supprimer"
 
 msgid "end filenames with NUL, for use with xargs (implies -p/--print)"
-msgstr ""
-"terminer les noms de fichiers par un caractère nul, pour utilisation avec "
-"xargs (implique -p/--print)"
+msgstr "terminer les noms de fichiers par un caractère nul, pour utilisation avec xargs (implique -p/--print)"
 
 msgid "hg purge [OPTION]... [DIR]..."
 msgstr "hg purge [OPTION]... [RÉPERTOIRE]..."
@@ -4524,9 +4484,7 @@
 msgid "abort an interrupted rebase"
 msgstr ""
 
-msgid ""
-"hg rebase [-s REV | -b REV] [-d REV] [--collapse] [--keep] [--keepbranches] "
-"| [-c] | [-a]"
+msgid "hg rebase [-s REV | -b REV] [-d REV] [--collapse] [--keep] [--keepbranches] | [-c] | [-a]"
 msgstr ""
 
 msgid "commands to interactively select changes for commit/qrefresh"
@@ -4799,8 +4757,7 @@
 msgid "filter changesets through FILTER"
 msgstr ""
 
-msgid ""
-"hg transplant [-s REPOSITORY] [-b BRANCH [-a]] [-p REV] [-m REV] [REV]..."
+msgid "hg transplant [-s REPOSITORY] [-b BRANCH [-a]] [-p REV] [-m REV] [REV]..."
 msgstr ""
 
 msgid ""
@@ -4858,8 +4815,7 @@
 "  ** = cleverdecode:\n"
 "  # or ** = macdecode:\n"
 "\n"
-"If not doing conversion, to make sure you do not commit CRLF/CR by "
-"accident::\n"
+"If not doing conversion, to make sure you do not commit CRLF/CR by accident::\n"
 "\n"
 "  [hooks]\n"
 "  pretxncommit.crlf = python:hgext.win32text.forbidcrlf\n"
@@ -4950,9 +4906,7 @@
 msgstr "le préfixe donné pour l'archive contient des composants non autorisés"
 
 msgid "cannot give prefix when archiving to files"
-msgstr ""
-"impossible de donner un préfixe pour une création d'archive vers un "
-"répertoire (de type \"files\")"
+msgstr "impossible de donner un préfixe pour une création d'archive vers un répertoire (de type \"files\")"
 
 #, python-format
 msgid "unknown archive type '%s'"
@@ -5012,8 +4966,7 @@
 
 #, python-format
 msgid "invalid format spec '%%%s' in output filename"
-msgstr ""
-"'%%%s'spécification de format invalide dans le nom du fichier de sortie"
+msgstr "'%%%s'spécification de format invalide dans le nom du fichier de sortie"
 
 #, python-format
 msgid "adding %s\n"
@@ -5025,9 +4978,7 @@
 
 #, python-format
 msgid "recording removal of %s as rename to %s (%d%% similar)\n"
-msgstr ""
-"suppression de %s plannifiée, en tant que renommage de %s (similaire à %d%"
-"%)\n"
+msgstr "suppression de %s plannifiée, en tant que renommage de %s (similaire à %d%%)\n"
 
 #, python-format
 msgid "%s: not copying - file is not managed\n"
@@ -5295,8 +5246,7 @@
 "    removed.\n"
 "    "
 msgstr ""
-"crée une archive du dépôt à une révision donnée, sans conserver "
-"l'historique\n"
+"crée une archive du dépôt à une révision donnée, sans conserver l'historique\n"
 "\n"
 "    Par défaut l'archive est créée à partir de la révision parente\n"
 "    du répertoire de travail. Une autre révision peut être spécifiée\n"
@@ -5328,8 +5278,7 @@
 msgstr "le répertoire racine ne peut servir de destination"
 
 msgid "cannot archive plain files to stdout"
-msgstr ""
-"impossible d'envoyer une archive de simples fichiers vers la sortie standard"
+msgstr "impossible d'envoyer une archive de simples fichiers vers la sortie standard"
 
 msgid ""
 "reverse effect of earlier changeset\n"
@@ -5790,14 +5739,10 @@
 msgid " patch test failed!\n"
 msgstr ""
 
-msgid ""
-" (Current patch tool may be incompatible with patch, or misconfigured. "
-"Please check your .hgrc file)\n"
-msgstr ""
-
-msgid ""
-" Internal patcher failure, please report this error to http://mercurial."
-"selenic.com/bts/\n"
+msgid " (Current patch tool may be incompatible with patch, or misconfigured. Please check your .hgrc file)\n"
+msgstr ""
+
+msgid " Internal patcher failure, please report this error to http://mercurial.selenic.com/bts/\n"
 msgstr ""
 
 msgid "Checking commit editor...\n"
@@ -6012,15 +5957,12 @@
 msgstr "utiliser \"hg help\" pour la liste complète des commandes"
 
 msgid "use \"hg help\" for the full list of commands or \"hg -v\" for details"
-msgstr ""
-"utiliser \"hg help\" pour la liste complète des commandes ou \"hg -v\" pour "
-"plus de détails"
+msgstr "utiliser \"hg help\" pour la liste complète des commandes ou \"hg -v\" pour plus de détails"
 
 # la chaîne passée est préfixée par un espace
 #, python-format
 msgid "use \"hg -v help%s\" to show aliases and global options"
-msgstr ""
-"utiliser \"hg -v help%s\" pour afficher les alias et les options globales"
+msgstr "utiliser \"hg -v help%s\" pour afficher les alias et les options globales"
 
 #, python-format
 msgid "use \"hg -v help %s\" to show global options"
@@ -6266,9 +6208,7 @@
 msgid "%s - use \"hg update\" instead"
 msgstr ""
 
-msgid ""
-"working dir not at a head rev - use \"hg update\" or merge with an explicit "
-"rev"
+msgid "working dir not at a head rev - use \"hg update\" or merge with an explicit rev"
 msgstr ""
 
 msgid ""
@@ -7233,9 +7173,7 @@
 msgid "[-nibt] [-r REV] [SOURCE]"
 msgstr ""
 
-msgid ""
-"directory strip option for patch. This has the same meaning as the "
-"corresponding patch option"
+msgid "directory strip option for patch. This has the same meaning as the corresponding patch option"
 msgstr ""
 
 msgid "base path"
@@ -7649,9 +7587,7 @@
 msgstr "** exception inconnue rencontrée, détails ci-dessous\n"
 
 msgid "** report bug details to http://mercurial.selenic.com/bts/\n"
-msgstr ""
-"** veuillez signaler le problème en détails sur http://www.selenic.com/"
-"mercurial/bts\n"
+msgstr "** veuillez signaler le problème en détails sur http://www.selenic.com/mercurial/bts\n"
 
 msgid "** or mercurial@selenic.com\n"
 msgstr "** ou mercurial@selenic.com\n"
@@ -7690,12 +7626,8 @@
 msgid "Option --cwd may not be abbreviated!"
 msgstr "L'option --cwd ne peut être abrégée !"
 
-msgid ""
-"Option -R has to be separated from other options (e.g. not -qR) and --"
-"repository may only be abbreviated as --repo!"
-msgstr ""
-"L'option -R doit être séparée des autres options (autrement dit -qR est "
-"invalide) et --repository ne peut être abrégé qu'en --repo !"
+msgid "Option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!"
+msgstr "L'option -R doit être séparée des autres options (autrement dit -qR est invalide) et --repository ne peut être abrégé qu'en --repo !"
 
 #, python-format
 msgid "Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n"
@@ -7712,9 +7644,7 @@
 msgid "unrecognized profiling format '%s' - Ignored\n"
 msgstr ""
 
-msgid ""
-"lsprof not available - install from http://codespeak.net/svn/user/arigo/hack/"
-"misc/lsprof/"
+msgid "lsprof not available - install from http://codespeak.net/svn/user/arigo/hack/misc/lsprof/"
 msgstr ""
 
 #, python-format
@@ -7836,9 +7766,7 @@
 msgid "destination '%s' is not empty"
 msgstr ""
 
-msgid ""
-"src repository does not support revision lookup and so doesn't support clone "
-"by revision"
+msgid "src repository does not support revision lookup and so doesn't support clone by revision"
 msgstr ""
 
 msgid "clone from remote to remote not supported"
@@ -7849,16 +7777,13 @@
 msgstr "comparaison avec %s\n"
 
 #, python-format
-msgid ""
-"%d files updated, %d files merged, %d files removed, %d files unresolved\n"
+msgid "%d files updated, %d files merged, %d files removed, %d files unresolved\n"
 msgstr ""
 
 msgid "use 'hg resolve' to retry unresolved file merges\n"
 msgstr ""
 
-msgid ""
-"use 'hg resolve' to retry unresolved file merges or 'hg update -C' to "
-"abandon\n"
+msgid "use 'hg resolve' to retry unresolved file merges or 'hg update -C' to abandon\n"
 msgstr ""
 
 msgid "(branch merge, don't forget to commit)\n"
@@ -8126,9 +8051,7 @@
 msgid "requesting all changes\n"
 msgstr ""
 
-msgid ""
-"Partial pull cannot be done because other repository doesn't support "
-"changegroupsubset."
+msgid "Partial pull cannot be done because other repository doesn't support changegroupsubset."
 msgstr ""
 
 #, python-format
@@ -8247,9 +8170,7 @@
 msgstr ""
 
 #, python-format
-msgid ""
-"untracked file in working directory differs from file in requested revision: "
-"'%s'"
+msgid "untracked file in working directory differs from file in requested revision: '%s'"
 msgstr ""
 
 #, python-format
--- a/i18n/sv.po	Mon Dec 07 12:31:45 2009 +0200
+++ b/i18n/sv.po	Tue May 11 17:03:44 2010 -0500
@@ -13,8 +13,8 @@
 msgstr ""
 "Project-Id-Version: Mercurial\n"
 "Report-Msgid-Bugs-To: <mercurial-devel@selenic.com>\n"
-"POT-Creation-Date: 2010-04-19 18:26+0200\n"
-"PO-Revision-Date: 2010-04-19 18:57+0100\n"
+"POT-Creation-Date: 2010-04-19 18:58+0200\n"
+"PO-Revision-Date: 2010-04-19 19:49+0200\n"
 "Last-Translator: Jens Bäckman <jens.backman@gmail.com>\n"
 "Language-Team: Swedish\n"
 "MIME-Version: 1.0\n"
@@ -411,9 +411,8 @@
 msgid "Revision %d is a merge, ignoring...\n"
 msgstr ""
 
-#, python-format
-msgid "generating stats: %d%%"
-msgstr ""
+msgid "analyzing"
+msgstr "analyserar"
 
 msgid ""
 "histogram of changes to the repository\n"
@@ -476,11 +475,8 @@
 msgid "file with email aliases"
 msgstr ""
 
-msgid "show progress"
-msgstr ""
-
-msgid "hg churn [-d DATE] [-r REV] [--aliases FILE] [--progress] [FILE]"
-msgstr ""
+msgid "hg churn [-d DATE] [-r REV] [--aliases FILE] [FILE]"
+msgstr "hg churn [-d DATUM] [-r REV] [--aliases FIL] [FIL]"
 
 msgid ""
 "colorize output from some commands\n"
@@ -529,6 +525,15 @@
 "  resolve.resolved = green bold\n"
 "\n"
 "  bookmarks.current = green\n"
+"\n"
+"The color extension will try to detect whether to use ANSI codes or\n"
+"Win32 console APIs, unless it is made explicit::\n"
+"\n"
+"  [color]\n"
+"  mode = ansi\n"
+"\n"
+"Any value other than 'ansi', 'win32', or 'auto' will disable color.\n"
+"\n"
 msgstr ""
 "färglägg utmatning från vissa kommandon\n"
 "\n"
@@ -575,17 +580,26 @@
 "  resolve.resolved = green bold\n"
 "\n"
 "  bookmarks.current = green\n"
+"\n"
+"Utökningen color försöker att upptäcka om ANSI-koder eller APIer för\n"
+"konsolen i Win32 om det inte anges explicit::\n"
+"\n"
+"  [color]\n"
+"  mode = ansi\n"
+"\n"
+"Ett värde skilt från 'ansi', 'win32', eller 'auto' stänger av färg.\n"
+"\n"
+
+#, python-format
+msgid "ignoring unknown color/effect %r (configured in color.%s)\n"
+msgstr "ignorerar okänd färg/effekt %r (konfigurerad i color.%s)\n"
+
+msgid "win32console not found, please install pywin32\n"
+msgstr "win32console hittades inte, installera pywin32\n"
 
 msgid "when to colorize (always, auto, or never)"
 msgstr "när färgläggning ska ske (always, auto eller never)"
 
-msgid "don't colorize output (DEPRECATED)"
-msgstr "färglägg inte utmatning (FÖRLEGAD)"
-
-#, python-format
-msgid "ignoring unknown color/effect %r (configured in color.%s)\n"
-msgstr ""
-
 msgid "import revisions from foreign VCS repositories into Mercurial"
 msgstr ""
 
@@ -2055,9 +2069,6 @@
 "keywords written to %s:\n"
 msgstr ""
 
-msgid "unhooked all commit hooks\n"
-msgstr ""
-
 msgid "hg keyword configuration and expansion example"
 msgstr "exempel på nyckelordskonfiguration och -expansion i hg"
 
@@ -2129,12 +2140,6 @@
 msgid "only show unknown (not tracked) files"
 msgstr "visa bara okända (ospårade) filer"
 
-msgid "show keyword status flags of all files (DEPRECATED)"
-msgstr "visa statusflaggor för alla filer (FÖRLEGAD)"
-
-msgid "only show untracked files (DEPRECATED)"
-msgstr "visa bara ospårade filer (FÖRLEGAD)"
-
 msgid "hg kwfiles [OPTION]... [FILE]..."
 msgstr ""
 
@@ -4417,6 +4422,9 @@
 msgid "invalid format spec '%%%s' in output filename"
 msgstr ""
 
+msgid "searching"
+msgstr "söker"
+
 #, python-format
 msgid "adding %s\n"
 msgstr ""
@@ -4548,12 +4556,8 @@
 msgstr ""
 
 #, python-format
-msgid "%s: %s"
-msgstr ""
-
-#, python-format
 msgid "Found revision %s from %s\n"
-msgstr ""
+msgstr "Hittade revision %s från %s\n"
 
 msgid "revision matching date not found"
 msgstr ""
@@ -4738,8 +4742,10 @@
 "    By default, the revision used is the parent of the working\n"
 "    directory; use -r/--rev to specify a different revision.\n"
 "\n"
-"    To specify the type of archive to create, use -t/--type. Valid\n"
-"    types are:\n"
+"    The archive type is automatically detected based on file\n"
+"    extension (or override using -t/--type).\n"
+"\n"
+"    Valid types are:\n"
 "\n"
 "    :``files``: a directory full of files (default)\n"
 "    :``tar``:   tar archive, uncompressed\n"
@@ -4762,8 +4768,10 @@
 "    Som standard används revisonen för arbetskatalogens förälder; använd\n"
 "    -r/--rev för att specificera en annan revision.\n"
 "\n"
-"    För att definiera vilken typ av arkiv som ska skapas, använd -t/--type.\n"
-"    Giltiga typer är::\n"
+"    Arkivtypen upptäcks automatiskt baserat på filändelsen (eller tvinga\n"
+"    med hjälp av -t/--type).\n"
+"\n"
+"    Giltiga typer är:\n"
 "\n"
 "    :``files``: en katalog fylld med filer (standard)\n"
 "    :``tar``:   tar-arkiv, okomprimerad\n"
@@ -6630,7 +6638,7 @@
 msgstr "inga ändringar behövs för %s\n"
 
 msgid ""
-"roll back the last transaction\n"
+"roll back the last transaction (dangerous)\n"
 "\n"
 "    This command should be used with care. There is only one level of\n"
 "    rollback, and there is no way to undo a rollback. It will also\n"
@@ -6657,7 +6665,7 @@
 "    may fail if a rollback is performed.\n"
 "    "
 msgstr ""
-"återgång från den senaste transaktionen\n"
+"återgång från den senaste transaktionen (farligt)\n"
 "\n"
 "    Detta kommando bör användas med försiktighet. Det finns bara en nivå\n"
 "    av återgång, och det finns inget sätt att ångra en återgång.\n"
@@ -6696,22 +6704,29 @@
 "    "
 
 msgid ""
-"export the repository via HTTP\n"
+"start stand-alone webserver\n"
 "\n"
 "    Start a local HTTP repository browser and pull server.\n"
 "\n"
 "    By default, the server logs accesses to stdout and errors to\n"
 "    stderr. Use the -A/--accesslog and -E/--errorlog options to log to\n"
 "    files.\n"
-"    "
-msgstr ""
-"exportera arkivet via HTTP\n"
+"\n"
+"    To have the server choose a free port number to listen on, specify\n"
+"    a port number of 0; in this case, the server will print the port\n"
+"    number it uses.\n"
+"    "
+msgstr ""
+"starta fristående webbserver\n"
 "\n"
 "    Startar en lokal HTTP-arkivbläddrare och pull-server.\n"
 "\n"
 "    Som standard loggar servern anslutningar till stdout och fel till\n"
 "    stderr. Använd flaggorna -A/--accesslog och -E/--errorlog för att logga\n"
 "    till filer.\n"
+"\n"
+"    För att låta servern välja ett ledigt portnummer att lyssna på, ange 0\n"
+"    som portnummer; då visar servern det portnummer som används.\n"
 "    "
 
 #, python-format
@@ -6805,6 +6820,10 @@
 "    för att hitta inkommande och utgående ändringar. Detta kan ta lång tid.\n"
 "    "
 
+#, python-format
+msgid "parent: %d:%s "
+msgstr "förälder: %d:%s "
+
 msgid " (empty repository)"
 msgstr " (tomt arkiv)"
 
@@ -6812,22 +6831,18 @@
 msgstr " (ingen revision uthämtad)"
 
 #, python-format
-msgid "parent: %d:%s %s\n"
-msgstr "förälder: %d:%s %s\n"
-
-#, python-format
 msgid "branch: %s\n"
 msgstr "gren: %s\n"
 
 #, python-format
+msgid "%d modified"
+msgstr "%d modifierad"
+
+#, python-format
 msgid "%d added"
 msgstr "%d tillagd"
 
 #, python-format
-msgid "%d modified"
-msgstr "%d modifierad"
-
-#, python-format
 msgid "%d removed"
 msgstr "%d borttagen"
 
@@ -6836,14 +6851,14 @@
 msgstr "%d raderad"
 
 #, python-format
+msgid "%d unknown"
+msgstr "%d okänd"
+
+#, python-format
 msgid "%d ignored"
 msgstr "%d ignorerad"
 
 #, python-format
-msgid "%d unknown"
-msgstr "%d okänd"
-
-#, python-format
 msgid "%d unresolved"
 msgstr "%d olöst"
 
@@ -7002,7 +7017,7 @@
 "    "
 
 msgid ""
-"update working directory\n"
+"update working directory (or switch revisions)\n"
 "\n"
 "    Update the repository's working directory to the specified\n"
 "    changeset.\n"
@@ -7038,7 +7053,7 @@
 "    See 'hg help dates' for a list of formats valid for -d/--date.\n"
 "    "
 msgstr ""
-"uppdatera arbetskatalogen\n"
+"uppdatera arbetskatalogen (eller växla mellan revisioner)\n"
 "\n"
 "    Uppdatera arkivets arbetskatalog till den specificerade ändringen.\n"
 "\n"
@@ -9032,8 +9047,16 @@
 msgid "no interrupted transaction available\n"
 msgstr ""
 
-msgid "rolling back last transaction\n"
-msgstr "Ã¥terkallar den senaste transaktionen\n"
+#, python-format
+msgid "rolling back to revision %s (undo %s: %s)\n"
+msgstr "återgår till revisionen %s (ångra %s: %s)\n"
+
+#, python-format
+msgid "rolling back to revision %s (undo %s)\n"
+msgstr "återgår till revisionen %s (ångra %s)\n"
+
+msgid "rolling back unknown transaction\n"
+msgstr "återkallar okänd transaktion\n"
 
 #, python-format
 msgid "Named branch could not be reset, current branch still is: %s\n"
@@ -9127,9 +9150,6 @@
 msgid "queries"
 msgstr "frågor"
 
-msgid "searching"
-msgstr "söker"
-
 msgid "already have changeset "
 msgstr "har redan ändringen "
 
@@ -9463,6 +9483,15 @@
 msgid "Unsupported line endings type: %s"
 msgstr ""
 
+msgid ""
+"internal patcher failed\n"
+"please report details to http://mercurial.selenic.com/bts/\n"
+"or mercurial@selenic.com\n"
+msgstr ""
+"den interna patcharen misslyckades\n"
+"rapportera detaljer till http://mercurial.selenic.com/bts/\n"
+"eller mercurial@selenic.com\n"
+
 #, python-format
 msgid " %d files changed, %d insertions(+), %d deletions(-)\n"
 msgstr ""
@@ -9610,8 +9639,8 @@
 msgstr ""
 
 #, python-format
-msgid "pulling subrepo %s\n"
-msgstr ""
+msgid "pulling subrepo %s from %s\n"
+msgstr "drar subarkivet %s från %s\n"
 
 #, python-format
 msgid "pushing subrepo %s\n"
@@ -9886,12 +9915,9 @@
 msgid "checking changesets\n"
 msgstr "kontrollerar ändringar\n"
 
-msgid "checking"
-msgstr "kontrollerar"
-
 #, python-format
 msgid "unpacking changeset %s"
-msgstr ""
+msgstr "packar upp ändringen %s"
 
 msgid "checking manifests\n"
 msgstr "kontrollerar manifest\n"
@@ -9930,6 +9956,9 @@
 msgid "cannot decode filename '%s'"
 msgstr "kan inte avkoda filnamnet '%s'"
 
+msgid "checking"
+msgstr "kontrollerar"
+
 #, python-format
 msgid "broken revlog! (%s)"
 msgstr "skadad revlog! (%s)"
--- a/mercurial/byterange.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/byterange.py	Tue May 11 17:03:44 2010 -0500
@@ -25,11 +25,6 @@
 import urllib2
 import email.Utils
 
-try:
-    from cStringIO import StringIO
-except ImportError, msg:
-    from StringIO import StringIO
-
 class RangeError(IOError):
     """Error raised when an unsatisfiable range is requested."""
     pass
--- a/mercurial/cmdutil.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/cmdutil.py	Tue May 11 17:03:44 2010 -0500
@@ -10,6 +10,7 @@
 import os, sys, errno, re, glob, tempfile
 import mdiff, bdiff, util, templater, patch, error, encoding, templatekw
 import match as _match
+import similar
 
 revrangesep = ':'
 
@@ -286,45 +287,6 @@
 def matchfiles(repo, files):
     return _match.exact(repo.root, repo.getcwd(), files)
 
-def findrenames(repo, added, removed, threshold):
-    '''find renamed files -- yields (before, after, score) tuples'''
-    copies = {}
-    ctx = repo['.']
-    for r in removed:
-        if r not in ctx:
-            continue
-        fctx = ctx.filectx(r)
-
-        def score(text):
-            if not len(text):
-                return 0.0
-            if not fctx.cmp(text):
-                return 1.0
-            if threshold == 1.0:
-                return 0.0
-            orig = fctx.data()
-            # bdiff.blocks() returns blocks of matching lines
-            # count the number of bytes in each
-            equal = 0
-            alines = mdiff.splitnewlines(text)
-            matches = bdiff.blocks(text, orig)
-            for x1, x2, y1, y2 in matches:
-                for line in alines[x1:x2]:
-                    equal += len(line)
-
-            lengths = len(text) + len(orig)
-            return equal * 2.0 / lengths
-
-        for a in added:
-            bestscore = copies.get(a, (None, threshold))[1]
-            myscore = score(repo.wread(a))
-            if myscore >= bestscore:
-                copies[a] = (r, myscore)
-
-    for dest, v in copies.iteritems():
-        source, score = v
-        yield source, dest, score
-
 def addremove(repo, pats=[], opts={}, dry_run=None, similarity=None):
     if dry_run is None:
         dry_run = opts.get('dry_run')
@@ -357,18 +319,25 @@
             removed.append(abs)
         elif repo.dirstate[abs] == 'a':
             added.append(abs)
-    if not dry_run:
-        repo.remove(deleted)
-        repo.add(unknown)
+    copies = {}
     if similarity > 0:
-        for old, new, score in findrenames(repo, added + unknown,
-                                           removed + deleted, similarity):
+        for old, new, score in similar.findrenames(repo,
+                added + unknown, removed + deleted, similarity):
             if repo.ui.verbose or not m.exact(old) or not m.exact(new):
                 repo.ui.status(_('recording removal of %s as rename to %s '
                                  '(%d%% similar)\n') %
                                (m.rel(old), m.rel(new), score * 100))
-            if not dry_run:
+            copies[new] = old
+
+    if not dry_run:
+        wlock = repo.wlock()
+        try:
+            repo.remove(deleted)
+            repo.add(unknown)
+            for new, old in copies.iteritems():
                 repo.copy(old, new)
+        finally:
+            wlock.release()
 
 def copy(ui, repo, pats, opts, rename=False):
     # called with the repo lock held
@@ -427,6 +396,12 @@
 
         if after:
             if not exists:
+                if rename:
+                    ui.warn(_('%s: not recording move - %s does not exist\n') %
+                            (relsrc, reltarget))
+                else:
+                    ui.warn(_('%s: not recording copy - %s does not exist\n') %
+                            (relsrc, reltarget))
                 return
         elif not dryrun:
             try:
@@ -647,6 +622,70 @@
     if runfn:
         return runfn()
 
+def export(repo, revs, template='hg-%h.patch', fp=None, switch_parent=False,
+           opts=None):
+    '''export changesets as hg patches.'''
+
+    total = len(revs)
+    revwidth = max([len(str(rev)) for rev in revs])
+
+    def single(rev, seqno, fp):
+        ctx = repo[rev]
+        node = ctx.node()
+        parents = [p.node() for p in ctx.parents() if p]
+        branch = ctx.branch()
+        if switch_parent:
+            parents.reverse()
+        prev = (parents and parents[0]) or nullid
+
+        if not fp:
+            fp = make_file(repo, template, node, total=total, seqno=seqno,
+                           revwidth=revwidth, mode='ab')
+        if fp != sys.stdout and hasattr(fp, 'name'):
+            repo.ui.note("%s\n" % fp.name)
+
+        fp.write("# HG changeset patch\n")
+        fp.write("# User %s\n" % ctx.user())
+        fp.write("# Date %d %d\n" % ctx.date())
+        if branch and (branch != 'default'):
+            fp.write("# Branch %s\n" % branch)
+        fp.write("# Node ID %s\n" % hex(node))
+        fp.write("# Parent  %s\n" % hex(prev))
+        if len(parents) > 1:
+            fp.write("# Parent  %s\n" % hex(parents[1]))
+        fp.write(ctx.description().rstrip())
+        fp.write("\n\n")
+
+        for chunk in patch.diff(repo, prev, node, opts=opts):
+            fp.write(chunk)
+
+    for seqno, rev in enumerate(revs):
+        single(rev, seqno + 1, fp)
+
+def diffordiffstat(ui, repo, diffopts, node1, node2, match,
+                   changes=None, stat=False, fp=None):
+    '''show diff or diffstat.'''
+    if fp is None:
+        write = ui.write
+    else:
+        def write(s, **kw):
+            fp.write(s)
+
+    if stat:
+        diffopts.context = 0
+        width = 80
+        if not ui.plain():
+            width = util.termwidth()
+        chunks = patch.diff(repo, node1, node2, match, changes, diffopts)
+        for chunk, label in patch.diffstatui(util.iterlines(chunks),
+                                             width=width,
+                                             git=diffopts.git):
+            write(chunk, label=label)
+    else:
+        for chunk, label in patch.diffui(repo, node1, node2, match,
+                                         changes, diffopts):
+            write(chunk, label=label)
+
 class changeset_printer(object):
     '''show changeset information when templating not requested.'''
 
@@ -682,7 +721,7 @@
         if self.buffered:
             self.ui.pushbuffer()
             self._show(ctx, copies, props)
-            self.hunk[ctx.rev()] = self.ui.popbuffer()
+            self.hunk[ctx.rev()] = self.ui.popbuffer(labeled=True)
         else:
             self._show(ctx, copies, props)
 
@@ -692,7 +731,8 @@
         rev = ctx.rev()
 
         if self.ui.quiet:
-            self.ui.write("%d:%s\n" % (rev, short(changenode)))
+            self.ui.write("%d:%s\n" % (rev, short(changenode)),
+                          label='log.node')
             return
 
         log = self.repo.changelog
@@ -703,63 +743,77 @@
         parents = [(p, hexfunc(log.node(p)))
                    for p in self._meaningful_parentrevs(log, rev)]
 
-        self.ui.write(_("changeset:   %d:%s\n") % (rev, hexfunc(changenode)))
+        self.ui.write(_("changeset:   %d:%s\n") % (rev, hexfunc(changenode)),
+                      label='log.changeset')
 
         branch = ctx.branch()
         # don't show the default branch name
         if branch != 'default':
             branch = encoding.tolocal(branch)
-            self.ui.write(_("branch:      %s\n") % branch)
+            self.ui.write(_("branch:      %s\n") % branch,
+                          label='log.branch')
         for tag in self.repo.nodetags(changenode):
-            self.ui.write(_("tag:         %s\n") % tag)
+            self.ui.write(_("tag:         %s\n") % tag,
+                          label='log.tag')
         for parent in parents:
-            self.ui.write(_("parent:      %d:%s\n") % parent)
+            self.ui.write(_("parent:      %d:%s\n") % parent,
+                          label='log.parent')
 
         if self.ui.debugflag:
             mnode = ctx.manifestnode()
             self.ui.write(_("manifest:    %d:%s\n") %
-                          (self.repo.manifest.rev(mnode), hex(mnode)))
-        self.ui.write(_("user:        %s\n") % ctx.user())
-        self.ui.write(_("date:        %s\n") % date)
+                          (self.repo.manifest.rev(mnode), hex(mnode)),
+                          label='ui.debug log.manifest')
+        self.ui.write(_("user:        %s\n") % ctx.user(),
+                      label='log.user')
+        self.ui.write(_("date:        %s\n") % date,
+                      label='log.date')
 
         if self.ui.debugflag:
             files = self.repo.status(log.parents(changenode)[0], changenode)[:3]
             for key, value in zip([_("files:"), _("files+:"), _("files-:")],
                                   files):
                 if value:
-                    self.ui.write("%-12s %s\n" % (key, " ".join(value)))
+                    self.ui.write("%-12s %s\n" % (key, " ".join(value)),
+                                  label='ui.debug log.files')
         elif ctx.files() and self.ui.verbose:
-            self.ui.write(_("files:       %s\n") % " ".join(ctx.files()))
+            self.ui.write(_("files:       %s\n") % " ".join(ctx.files()),
+                          label='ui.note log.files')
         if copies and self.ui.verbose:
             copies = ['%s (%s)' % c for c in copies]
-            self.ui.write(_("copies:      %s\n") % ' '.join(copies))
+            self.ui.write(_("copies:      %s\n") % ' '.join(copies),
+                          label='ui.note log.copies')
 
         extra = ctx.extra()
         if extra and self.ui.debugflag:
             for key, value in sorted(extra.items()):
                 self.ui.write(_("extra:       %s=%s\n")
-                              % (key, value.encode('string_escape')))
+                              % (key, value.encode('string_escape')),
+                              label='ui.debug log.extra')
 
         description = ctx.description().strip()
         if description:
             if self.ui.verbose:
-                self.ui.write(_("description:\n"))
-                self.ui.write(description)
+                self.ui.write(_("description:\n"),
+                              label='ui.note log.description')
+                self.ui.write(description,
+                              label='ui.note log.description')
                 self.ui.write("\n\n")
             else:
                 self.ui.write(_("summary:     %s\n") %
-                              description.splitlines()[0])
+                              description.splitlines()[0],
+                              label='log.summary')
         self.ui.write("\n")
 
         self.showpatch(changenode)
 
     def showpatch(self, node):
         if self.patch:
+            stat = self.diffopts.get('stat')
+            diffopts = patch.diffopts(self.ui, self.diffopts)
             prev = self.repo.changelog.parents(node)[0]
-            chunks = patch.diff(self.repo, prev, node, match=self.patch,
-                                opts=patch.diffopts(self.ui, self.diffopts))
-            for chunk in chunks:
-                self.ui.write(chunk)
+            diffordiffstat(self.ui, self.repo, diffopts, prev, node,
+                           match=self.patch, stat=stat)
             self.ui.write("\n")
 
     def _meaningful_parentrevs(self, log, rev):
@@ -876,7 +930,7 @@
             msg = _("%s: no key named '%s'")
             raise util.Abort(msg % (self.t.mapfile, inst.args[0]))
         except SyntaxError, inst:
-            raise util.Abort(_('%s: %s') % (self.t.mapfile, inst.args[0]))
+            raise util.Abort('%s: %s' % (self.t.mapfile, inst.args[0]))
 
 def show_changeset(ui, repo, opts, buffered=False, matchfn=False):
     """show one changeset using template or regular display.
@@ -891,7 +945,7 @@
     """
     # options
     patch = False
-    if opts.get('patch'):
+    if opts.get('patch') or opts.get('stat'):
         patch = matchfn or matchall(repo)
 
     tmpl = opts.get('template')
@@ -1044,7 +1098,7 @@
                     fncache.setdefault(rev, [])
                     fncache[rev].append(file_)
                     wanted.add(rev)
-                    if follow and copied:
+                    if copied:
                         copies.append(copied)
     if slowpath:
         if follow:
--- a/mercurial/commands.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/commands.py	Tue May 11 17:03:44 2010 -0500
@@ -11,9 +11,8 @@
 import os, re, sys, difflib, time, tempfile
 import hg, util, revlog, bundlerepo, extensions, copies, error
 import patch, help, mdiff, url, encoding, templatekw
-import archival, changegroup, cmdutil, sshserver, hbisect
-from hgweb import server
-import merge as merge_
+import archival, changegroup, cmdutil, sshserver, hbisect, hgweb, hgweb.server
+import merge as mergemod
 import minirst
 
 # Commands start here, listed alphabetically
@@ -32,7 +31,7 @@
     .. container:: verbose
 
        An example showing how new (unknown) files are added
-       automatically by ``hg add``::
+       automatically by :hg:`add`::
 
          $ ls
          foo.c
@@ -158,8 +157,10 @@
     By default, the revision used is the parent of the working
     directory; use -r/--rev to specify a different revision.
 
-    To specify the type of archive to create, use -t/--type. Valid
-    types are:
+    The archive type is automatically detected based on file
+    extension (or override using -t/--type).
+
+    Valid types are:
 
     :``files``: a directory full of files (default)
     :``tar``:   tar archive, uncompressed
@@ -169,7 +170,7 @@
     :``zip``:   zip archive, compressed using deflate
 
     The exact name of the destination archive or directory is given
-    using a format string; see 'hg help export' for details.
+    using a format string; see :hg:`help export` for details.
 
     Each member added to an archive file has a directory prefix
     prepended. Use -p/--prefix to specify a format string for the
@@ -184,16 +185,32 @@
     dest = cmdutil.make_filename(repo, dest, node)
     if os.path.realpath(dest) == repo.root:
         raise util.Abort(_('repository root cannot be destination'))
-    matchfn = cmdutil.match(repo, [], opts)
-    kind = opts.get('type') or 'files'
+
+    def guess_type():
+        exttypes = {
+            'tar': ['.tar'],
+            'tbz2': ['.tbz2', '.tar.bz2'],
+            'tgz': ['.tgz', '.tar.gz'],
+            'zip': ['.zip'],
+        }
+
+        for type, extensions in exttypes.items():
+            if util.any(dest.endswith(ext) for ext in extensions):
+                return type
+        return None
+
+    kind = opts.get('type') or guess_type() or 'files'
     prefix = opts.get('prefix')
+
     if dest == '-':
         if kind == 'files':
             raise util.Abort(_('cannot archive plain files to stdout'))
         dest = sys.stdout
         if not prefix:
             prefix = os.path.basename(repo.root) + '-%h'
+
     prefix = cmdutil.make_filename(repo, prefix, node)
+    matchfn = cmdutil.match(repo, [], opts)
     archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
                      matchfn, prefix)
 
@@ -212,7 +229,7 @@
     changeset afterwards. This saves you from doing the merge by hand.
     The result of this merge is not committed, as with a normal merge.
 
-    See 'hg help dates' for a list of formats valid for -d/--date.
+    See :hg:`help dates` for a list of formats valid for -d/--date.
     '''
     if rev and node:
         raise util.Abort(_("please specify just one revision"))
@@ -438,8 +455,8 @@
     the parent of the working directory, negating a previous branch
     change.
 
-    Use the command 'hg update' to switch to an existing branch. Use
-    'hg commit --close-branch' to mark this branch as closed.
+    Use the command :hg:`update` to switch to an existing branch. Use
+    :hg:`commit --close-branch` to mark this branch as closed.
     """
 
     if opts.get('clean'):
@@ -467,7 +484,7 @@
     If -a/--active is specified, only show active branches. A branch
     is considered active if it contains repository heads.
 
-    Use the command 'hg update' to switch to an existing branch.
+    Use the command :hg:`update` to switch to an existing branch.
     """
 
     hexfunc = ui.debugflag and hex or short
@@ -619,11 +636,11 @@
     The location of the source is added to the new repository's
     .hg/hgrc file, as the default to be used for future pulls.
 
-    See 'hg help urls' for valid source format details.
+    See :hg:`help urls` for valid source format details.
 
     It is possible to specify an ``ssh://`` URL as the destination, but no
     .hg/hgrc and working directory will be created on the remote side.
-    Please see 'hg help urls' for important details about ``ssh://`` URLs.
+    Please see :hg:`help urls` for important details about ``ssh://`` URLs.
 
     A set of changesets (tags, or branch names) to pull may be specified
     by listing each changeset (tag, or branch name) with -r/--rev.
@@ -687,7 +704,7 @@
     centralized RCS, this operation is a local operation. See hg push
     for a way to actively distribute your changes.
 
-    If a list of files is omitted, all changes reported by "hg status"
+    If a list of files is omitted, all changes reported by :hg:`status`
     will be committed.
 
     If you are committing the result of a merge, do not provide any
@@ -696,7 +713,7 @@
     If no commit message is specified, the configured editor is
     started to prompt you for a message.
 
-    See 'hg help dates' for a list of formats valid for -d/--date.
+    See :hg:`help dates` for a list of formats valid for -d/--date.
     """
     extra = {}
     if opts.get('close_branch'):
@@ -784,6 +801,8 @@
             otables.append(entry[1])
         for t in otables:
             for o in t:
+                if "(DEPRECATED)" in o[3]:
+                    continue
                 if o[0]:
                     options.append('-%s' % o[0])
                 options.append('--%s' % o[1])
@@ -854,6 +873,8 @@
     for each config item.
     """
 
+    for f in util.rcpath():
+        ui.debug(_('read config from: %s\n') % f)
     untrusted = bool(opts.get('untrusted'))
     if values:
         if len([v for v in values if '.' in v]) > 1:
@@ -1131,7 +1152,7 @@
     anyway, probably with undesirable results.
 
     Use the -g/--git option to generate diffs in the git extended diff
-    format. For more information, read 'hg help diffs'.
+    format. For more information, read :hg:`help diffs`.
     """
 
     revs = opts.get('rev')
@@ -1151,21 +1172,9 @@
     if reverse:
         node1, node2 = node2, node1
 
-    if stat:
-        opts['unified'] = '0'
     diffopts = patch.diffopts(ui, opts)
-
     m = cmdutil.match(repo, pats, opts)
-    it = patch.diff(repo, node1, node2, match=m, opts=diffopts)
-    if stat:
-        width = 80
-        if not ui.plain():
-            width = util.termwidth()
-        ui.write(patch.diffstat(util.iterlines(it), width=width,
-                                git=diffopts.git))
-    else:
-        for chunk in it:
-            ui.write(chunk)
+    cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat)
 
 def export(ui, repo, *changesets, **opts):
     """dump the header and diffs for one or more changesets
@@ -1197,7 +1206,7 @@
     diff anyway, probably with undesirable results.
 
     Use the -g/--git option to generate diffs in the git extended diff
-    format. See 'hg help diffs' for more information.
+    format. See :hg:`help diffs` for more information.
 
     With the --switch-parent option, the diff will be against the
     second parent. It can be useful to review a merge.
@@ -1210,7 +1219,7 @@
         ui.note(_('exporting patches:\n'))
     else:
         ui.note(_('exporting patch:\n'))
-    patch.export(repo, revs, template=opts.get('output'),
+    cmdutil.export(repo, revs, template=opts.get('output'),
                  switch_parent=opts.get('switch_parent'),
                  opts=patch.diffopts(ui, opts))
 
@@ -1337,6 +1346,7 @@
             iter = [('', l) for l in states]
         for change, l in iter:
             cols = [fn, str(rev)]
+            before, match, after = None, None, None
             if opts.get('line_number'):
                 cols.append(str(l.linenum))
             if opts.get('all'):
@@ -1351,8 +1361,15 @@
                     continue
                 filerevmatches[c] = 1
             else:
-                cols.append(l.line)
-            ui.write(sep.join(cols), eol)
+                before = l.line[:l.colstart]
+                match = l.line[l.colstart:l.colend]
+                after = l.line[l.colend:]
+            ui.write(sep.join(cols))
+            if before is not None:
+                ui.write(sep + before)
+                ui.write(match, label='grep.match')
+                ui.write(after)
+            ui.write(eol)
             found = True
         return found
 
@@ -1848,7 +1865,7 @@
 
     To read a patch from standard input, use "-" as the patch name. If
     a URL is specified, the patch will be downloaded from it.
-    See 'hg help dates' for a list of formats valid for -d/--date.
+    See :hg:`help dates` for a list of formats valid for -d/--date.
     """
     patches = (patch1,) + patches
 
@@ -2051,7 +2068,7 @@
     If no directory is given, the current directory is used.
 
     It is possible to specify an ``ssh://`` URL as the destination.
-    See 'hg help urls' for more information.
+    See :hg:`help urls` for more information.
     """
     hg.repository(cmdutil.remoteui(ui, opts), dest, create=1)
 
@@ -2106,7 +2123,7 @@
     --follow is set, in which case the working directory parent is
     used as the starting revision.
 
-    See 'hg help dates' for a list of formats valid for -d/--date.
+    See :hg:`help dates` for a list of formats valid for -d/--date.
 
     By default this command prints revision number and changeset id,
     tags, non-trivial parents, user, date and time, and a summary for
@@ -2131,6 +2148,9 @@
     if opts["date"]:
         df = util.matchdate(opts["date"])
 
+    branches = opts.get('branch', []) + opts.get('only_branch', [])
+    opts['branch'] = [repo.lookupbranch(b) for b in branches]
+
     displayer = cmdutil.show_changeset(ui, repo, opts, True, matchfn)
     def prep(ctx, fns):
         rev = ctx.rev()
@@ -2140,7 +2160,7 @@
             return
         if opts.get('only_merges') and len(parents) != 2:
             return
-        if opts.get('only_branch') and ctx.branch() not in opts['only_branch']:
+        if opts.get('branch') and ctx.branch() not in opts['branch']:
             return
         if df and not df(ctx.date()[0]):
             return
@@ -2346,8 +2366,9 @@
     Show definition of symbolic path name NAME. If no name is given,
     show definition of all available names.
 
-    Path names are defined in the [paths] section of /etc/mercurial/hgrc
-    and $HOME/.hgrc. If run inside a repository, .hg/hgrc is used, too.
+    Path names are defined in the [paths] section of
+    ``/etc/mercurial/hgrc`` and ``$HOME/.hgrc``. If run inside a
+    repository, ``.hg/hgrc`` is used, too.
 
     The path names ``default`` and ``default-push`` have a special
     meaning.  When performing a push or pull operation, they are used
@@ -2356,11 +2377,11 @@
     ``default`` will be used for pull; otherwise ``default`` is used
     as the fallback for both.  When cloning a repository, the clone
     source is written as ``default`` in ``.hg/hgrc``.  Note that
-    ``default`` and ``default-push`` apply to all inbound (e.g. ``hg
-    incoming``) and outbound (e.g. ``hg outgoing``, ``hg email`` and
-    ``hg bundle``) operations.
-
-    See 'hg help urls' for more information.
+    ``default`` and ``default-push`` apply to all inbound (e.g.
+    :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
+    :hg:`bundle`) operations.
+
+    See :hg:`help urls` for more information.
     """
     if search:
         for name, path in ui.configitems("paths"):
@@ -2402,7 +2423,7 @@
     where X is the last changeset listed by hg incoming.
 
     If SOURCE is omitted, the 'default' path will be used.
-    See 'hg help urls' for more information.
+    See :hg:`help urls` for more information.
     """
     source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
     other = hg.repository(cmdutil.remoteui(repo, opts), source)
@@ -2438,7 +2459,7 @@
     If -r/--rev is used, the named revision and all its ancestors will
     be pushed to the remote repository.
 
-    Please see 'hg help urls' for important details about ``ssh://``
+    Please see :hg:`help urls` for important details about ``ssh://``
     URLs. If DESTINATION is omitted, a default path will be used.
     """
     dest = ui.expandpath(dest or 'default-push', dest or 'default')
@@ -2592,7 +2613,7 @@
         raise util.Abort(_('no files or directories specified; '
                            'use --all to remerge all files'))
 
-    ms = merge_.mergestate(repo)
+    ms = mergemod.mergestate(repo)
     m = cmdutil.match(repo, pats, opts)
 
     for f in ms:
@@ -2601,7 +2622,9 @@
                 if nostatus:
                     ui.write("%s\n" % f)
                 else:
-                    ui.write("%s %s\n" % (ms[f].upper(), f))
+                    ui.write("%s %s\n" % (ms[f].upper(), f),
+                             label='resolve.' +
+                             {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
             elif mark:
                 ms.mark(f, "r")
             elif unmark:
@@ -2635,8 +2658,8 @@
 
     Using the -r/--rev option, revert the given files or directories
     to their contents as of a specific revision. This can be helpful
-    to "roll back" some or all of an earlier change. See 'hg help
-    dates' for a list of formats valid for -d/--date.
+    to "roll back" some or all of an earlier change. See :hg:`help
+    dates` for a list of formats valid for -d/--date.
 
     Revert modifies the working directory. It does not commit any
     changes, or change the parent of the working directory. If you
@@ -2838,8 +2861,8 @@
     finally:
         wlock.release()
 
-def rollback(ui, repo):
-    """roll back the last transaction
+def rollback(ui, repo, **opts):
+    """roll back the last transaction (dangerous)
 
     This command should be used with care. There is only one level of
     rollback, and there is no way to undo a rollback. It will also
@@ -2865,7 +2888,7 @@
     repository; for example an in-progress pull from the repository
     may fail if a rollback is performed.
     """
-    repo.rollback()
+    repo.rollback(opts.get('dry_run'))
 
 def root(ui, repo):
     """print the root (top) of the current working directory
@@ -2875,7 +2898,7 @@
     ui.write(repo.root + "\n")
 
 def serve(ui, repo, **opts):
-    """export the repository via HTTP
+    """start stand-alone webserver
 
     Start a local HTTP repository browser and pull server. You can use
     this for ad-hoc sharing and browing of repositories. It is
@@ -2891,6 +2914,10 @@
     By default, the server logs accesses to stdout and errors to
     stderr. Use the -A/--accesslog and -E/--errorlog options to log to
     files.
+
+    To have the server choose a free port number to listen on, specify
+    a port number of 0; in this case, the server will print the port
+    number it uses.
     """
 
     if opts["stdio"]:
@@ -2900,25 +2927,36 @@
         s = sshserver.sshserver(ui, repo)
         s.serve_forever()
 
+    # this way we can check if something was given in the command-line
+    if opts.get('port'):
+        opts['port'] = int(opts.get('port'))
+
     baseui = repo and repo.baseui or ui
     optlist = ("name templates style address port prefix ipv6"
-               " accesslog errorlog webdir_conf certificate encoding")
+               " accesslog errorlog certificate encoding")
     for o in optlist.split():
-        if opts.get(o, None):
-            baseui.setconfig("web", o, str(opts[o]))
-            if (repo is not None) and (repo.ui != baseui):
-                repo.ui.setconfig("web", o, str(opts[o]))
-
-    if repo is None and not ui.config("web", "webdir_conf"):
-        raise error.RepoError(_("There is no Mercurial repository here"
-                                " (.hg not found)"))
+        val = opts.get(o, '')
+        if val in (None, ''): # should check against default options instead
+            continue
+        baseui.setconfig("web", o, val)
+        if repo and repo.ui != baseui:
+            repo.ui.setconfig("web", o, val)
+
+    o = opts.get('web_conf') or opts.get('webdir_conf')
+    if not o:
+        if not repo:
+            raise error.RepoError(_("There is no Mercurial repository"
+                                    " here (.hg not found)"))
+        o = repo.root
+
+    app = hgweb.hgweb(o, baseui=ui)
 
     class service(object):
         def init(self):
             util.set_signal_handler()
-            self.httpd = server.create_server(baseui, repo)
-
-            if not ui.verbose:
+            self.httpd = hgweb.server.create_server(ui, app)
+
+            if opts['port'] and not ui.verbose:
                 return
 
             if self.httpd.prefix:
@@ -2939,8 +2977,12 @@
             fqaddr = self.httpd.fqaddr
             if ':' in fqaddr:
                 fqaddr = '[%s]' % fqaddr
-            ui.status(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
-                      (fqaddr, port, prefix, bindaddr, self.httpd.port))
+            if opts['port']:
+                write = ui.status
+            else:
+                write = ui.write
+            write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
+                  (fqaddr, port, prefix, bindaddr, self.httpd.port))
 
         def run(self):
             self.httpd.serve_forever()
@@ -3031,9 +3073,11 @@
                 format = "%%s%s" % end
 
             for f in files:
-                ui.write(format % repo.pathto(f, cwd))
+                ui.write(format % repo.pathto(f, cwd),
+                         label='status.' + state)
                 if f in copy:
-                    ui.write('  %s%s' % (repo.pathto(copy[f], cwd), end))
+                    ui.write('  %s%s' % (repo.pathto(copy[f], cwd), end),
+                             label='status.copied')
 
 def summary(ui, repo, **opts):
     """summarize working directory state
@@ -3048,33 +3092,47 @@
     ctx = repo[None]
     parents = ctx.parents()
     pnode = parents[0].node()
-    tags = repo.tags()
 
     for p in parents:
-        t = ' '.join([t for t in tags if tags[t] == p.node()])
+        # label with log.changeset (instead of log.parent) since this
+        # shows a working directory parent *changeset*:
+        ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
+                 label='log.changeset')
+        ui.write(' '.join(p.tags()), label='log.tag')
         if p.rev() == -1:
             if not len(repo):
-                t += _(' (empty repository)')
+                ui.write(_(' (empty repository)'))
             else:
-                t += _(' (no revision checked out)')
-        ui.write(_('parent: %d:%s %s\n') % (p.rev(), str(p), t))
+                ui.write(_(' (no revision checked out)'))
+        ui.write('\n')
         if p.description():
-            ui.status(' ' + p.description().splitlines()[0].strip() + '\n')
+            ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
+                      label='log.summary')
 
     branch = ctx.branch()
     bheads = repo.branchheads(branch)
     m = _('branch: %s\n') % branch
     if branch != 'default':
-        ui.write(m)
+        ui.write(m, label='log.branch')
     else:
-        ui.status(m)
+        ui.status(m, label='log.branch')
 
     st = list(repo.status(unknown=True))[:6]
-    ms = merge_.mergestate(repo)
+
+    ms = mergemod.mergestate(repo)
     st.append([f for f in ms if ms[f] == 'u'])
-    labels = [_('%d modified'), _('%d added'), _('%d removed'),
-              _('%d deleted'), _('%d unknown'), _('%d ignored'),
-              _('%d unresolved')]
+
+    subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
+    st.append(subs)
+
+    labels = [ui.label(_('%d modified'), 'status.modified'),
+              ui.label(_('%d added'), 'status.added'),
+              ui.label(_('%d removed'), 'status.removed'),
+              ui.label(_('%d deleted'), 'status.deleted'),
+              ui.label(_('%d unknown'), 'status.unknown'),
+              ui.label(_('%d ignored'), 'status.ignored'),
+              ui.label(_('%d unresolved'), 'resolve.unresolved'),
+              ui.label(_('%d subrepos'), 'status.modified')]
     t = []
     for s, l in zip(st, labels):
         if s:
@@ -3087,7 +3145,7 @@
         t += _(' (merge)')
     elif branch != parents[0].branch():
         t += _(' (new branch)')
-    elif (not st[0] and not st[1] and not st[2]):
+    elif (not st[0] and not st[1] and not st[2] and not st[7]):
         t += _(' (clean)')
         cleanworkdir = True
     elif pnode not in bheads:
@@ -3166,7 +3224,10 @@
     necessary. The file '.hg/localtags' is used for local tags (not
     shared among repositories).
 
-    See 'hg help dates' for a list of formats valid for -d/--date.
+    See :hg:`help dates` for a list of formats valid for -d/--date.
+
+    Since tag names have priority over branch names during revision
+    lookup, using an existing branch name as a tag name is discouraged.
     """
 
     rev_ = "."
@@ -3281,7 +3342,7 @@
     return postincoming(ui, repo, modheads, opts.get('update'), None)
 
 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
-    """update working directory
+    """update working directory (or switch revisions)
 
     Update the repository's working directory to the specified
     changeset.
@@ -3308,12 +3369,12 @@
     3. With the -C/--clean option, uncommitted changes are discarded and
        the working directory is updated to the requested changeset.
 
-    Use null as the changeset to remove the working directory (like 'hg
-    clone -U').
-
-    If you want to update just one file to an older changeset, use 'hg revert'.
-
-    See 'hg help dates' for a list of formats valid for -d/--date.
+    Use null as the changeset to remove the working directory (like
+    :hg:`clone -U`).
+
+    If you want to update just one file to an older changeset, use :hg:`revert`.
+
+    See :hg:`help dates` for a list of formats valid for -d/--date.
     """
     if rev and node:
         raise util.Abort(_("please specify just one revision"))
@@ -3420,6 +3481,7 @@
     ('g', 'git', None, _('use git extended diff format')),
     ('l', 'limit', '', _('limit number of changes displayed')),
     ('M', 'no-merges', None, _('do not show merges')),
+    ('', 'stat', None, _('output diffstat-style summary of changes')),
 ] + templateopts
 
 diffopts = [
@@ -3699,8 +3761,10 @@
           ('', 'removed', None, _('include revisions where files were removed')),
           ('m', 'only-merges', None, _('show only merges')),
           ('u', 'user', [], _('revisions committed by user')),
-          ('b', 'only-branch', [],
-            _('show only changesets within the given named branch')),
+          ('', 'only-branch', [],
+            _('show only changesets within the given named branch (DEPRECATED)')),
+          ('b', 'branch', [],
+            _('show changesets within the given named branch')),
           ('P', 'prune', [],
            _('do not display revision or any of its ancestors')),
          ] + logopts + walkopts,
@@ -3786,7 +3850,7 @@
           ('', 'no-backup', None, _('do not save backup copies of files')),
          ] + walkopts + dryrunopts,
          _('[OPTION]... [-r REV] [NAME]...')),
-    "rollback": (rollback, []),
+    "rollback": (rollback, dryrunopts),
     "root": (root, []),
     "^serve":
         (serve,
@@ -3794,15 +3858,18 @@
           ('d', 'daemon', None, _('run server in background')),
           ('', 'daemon-pipefds', '', _('used internally by daemon mode')),
           ('E', 'errorlog', '', _('name of error log file to write to')),
-          ('p', 'port', 0, _('port to listen on (default: 8000)')),
+          # use string type, then we can check if something was passed
+          ('p', 'port', '', _('port to listen on (default: 8000)')),
           ('a', 'address', '',
            _('address to listen on (default: all interfaces)')),
           ('', 'prefix', '',
            _('prefix path to serve from (default: server root)')),
           ('n', 'name', '',
            _('name to show in web pages (default: working directory)')),
-          ('', 'webdir-conf', '', _('name of the webdir config file'
+          ('', 'web-conf', '', _('name of the hgweb config file'
                                     ' (serve more than one repository)')),
+          ('', 'webdir-conf', '', _('name of the hgweb config file'
+                                    ' (DEPRECATED)')),
           ('', 'pid-file', '', _('name of file to write process ID to')),
           ('', 'stdio', None, _('for remote clients')),
           ('t', 'templates', '', _('web templates to use')),
--- a/mercurial/context.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/context.py	Tue May 11 17:03:44 2010 -0500
@@ -7,7 +7,7 @@
 
 from node import nullid, nullrev, short, hex
 from i18n import _
-import ancestor, bdiff, error, util, subrepo
+import ancestor, bdiff, error, util, subrepo, patch
 import os, errno
 
 propertycache = util.propertycache
@@ -204,6 +204,16 @@
     def sub(self, path):
         return subrepo.subrepo(self, path)
 
+    def diff(self, ctx2=None, match=None, **opts):
+        """Returns a diff generator for the given contexts and matcher"""
+        if ctx2 is None:
+            ctx2 = self.p1()
+        if ctx2 is not None and not isinstance(ctx2, changectx):
+            ctx2 = self._repo[ctx2]
+        diffopts = patch.diffopts(self._repo.ui, opts)
+        return patch.diff(self._repo, ctx2.node(), self.node(),
+                          match=match, opts=diffopts)
+
 class filectx(object):
     """A filecontext object makes access to data related to a particular
        filerevision convenient."""
@@ -539,15 +549,14 @@
 class workingctx(changectx):
     """A workingctx object makes access to data related to
     the current working directory convenient.
-    parents - a pair of parent nodeids, or None to use the dirstate.
     date - any valid date string or (unixtime, offset), or None.
     user - username string, or None.
     extra - a dictionary of extra values, or None.
     changes - a list of file lists as returned by localrepo.status()
                or None to use the repository status.
     """
-    def __init__(self, repo, parents=None, text="", user=None, date=None,
-                 extra=None, changes=None):
+    def __init__(self, repo, text="", user=None, date=None, extra=None,
+                 changes=None):
         self._repo = repo
         self._rev = None
         self._node = None
@@ -556,10 +565,15 @@
             self._date = util.parsedate(date)
         if user:
             self._user = user
-        if parents:
-            self._parents = [changectx(self._repo, p) for p in parents]
         if changes:
-            self._status = list(changes)
+            self._status = list(changes[:4])
+            self._unknown = changes[4]
+            self._ignored = changes[5]
+            self._clean = changes[6]
+        else:
+            self._unknown = None
+            self._ignored = None
+            self._clean = None
 
         self._extra = {}
         if extra:
@@ -587,6 +601,9 @@
     def _manifest(self):
         """generate a manifest corresponding to the working directory"""
 
+        if self._unknown is None:
+            self.status(unknown=True)
+
         man = self._parents[0].manifest().copy()
         copied = self._repo.dirstate.copies()
         if len(self._parents) > 1:
@@ -601,7 +618,8 @@
             f = copied.get(f, f)
             return getman(f).flags(f)
         ff = self._repo.dirstate.flagfunc(cf)
-        modified, added, removed, deleted, unknown = self._status[:5]
+        modified, added, removed, deleted = self._status
+        unknown = self._unknown
         for i, l in (("a", added), ("m", modified), ("u", unknown)):
             for f in l:
                 orig = copied.get(f, f)
@@ -619,7 +637,7 @@
 
     @propertycache
     def _status(self):
-        return self._repo.status(unknown=True)
+        return self._repo.status()[:4]
 
     @propertycache
     def _user(self):
@@ -637,6 +655,22 @@
         self._parents = [changectx(self._repo, x) for x in p]
         return self._parents
 
+    def status(self, ignored=False, clean=False, unknown=False):
+        """Explicit status query
+        Unless this method is used to query the working copy status, the
+        _status property will implicitly read the status using its default
+        arguments."""
+        stat = self._repo.status(ignored=ignored, clean=clean, unknown=unknown)
+        self._unknown = self._ignored = self._clean = None
+        if unknown:
+            self._unknown = stat[4]
+        if ignored:
+            self._ignored = stat[5]
+        if clean:
+            self._clean = stat[6]
+        self._status = stat[:4]
+        return stat
+
     def manifest(self):
         return self._manifest
     def user(self):
@@ -657,9 +691,14 @@
     def deleted(self):
         return self._status[3]
     def unknown(self):
-        return self._status[4]
+        assert self._unknown is not None  # must call status first
+        return self._unknown
+    def ignored(self):
+        assert self._ignored is not None  # must call status first
+        return self._ignored
     def clean(self):
-        return self._status[5]
+        assert self._clean is not None  # must call status first
+        return self._clean
     def branch(self):
         return self._extra['branch']
     def extra(self):
@@ -713,7 +752,11 @@
 
     def dirty(self, missing=False):
         "check whether a working directory is modified"
-
+        # check subrepos first
+        for s in self.substate:
+            if self.sub(s).dirty():
+                return True
+        # check current working dir
         return (self.p2() or self.branch() != self.p1().branch() or
                 self.modified() or self.added() or self.removed() or
                 (missing and self.deleted()))
@@ -873,8 +916,10 @@
         return self._status[3]
     def unknown(self):
         return self._status[4]
+    def ignored(self):
+        return self._status[5]
     def clean(self):
-        return self._status[5]
+        return self._status[6]
     def branch(self):
         return self._extra['branch']
     def extra(self):
@@ -890,12 +935,16 @@
         """get a file context from the working directory"""
         return self._filectxfn(self._repo, self, path)
 
+    def commit(self):
+        """commit context to the repo"""
+        return self._repo.commitctx(self)
+
 class memfilectx(object):
     """memfilectx represents an in-memory file to commit.
 
     See memctx for more details.
     """
-    def __init__(self, path, data, islink, isexec, copied):
+    def __init__(self, path, data, islink=False, isexec=False, copied=None):
         """
         path is the normalized file path relative to repository root.
         data is the file content as a string.
--- a/mercurial/dirstate.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/dirstate.py	Tue May 11 17:03:44 2010 -0500
@@ -11,7 +11,6 @@
 import struct, os, stat, errno
 import cStringIO
 
-_unknown = ('?', 0, 0, 0)
 _format = ">cllll"
 propertycache = util.propertycache
 
@@ -286,14 +285,15 @@
         '''Mark a file normal, but possibly dirty.'''
         if self._pl[1] != nullid and f in self._map:
             # if there is a merge going on and the file was either
-            # in state 'm' or dirty before being removed, restore that state.
+            # in state 'm' (-1) or coming from other parent (-2) before
+            # being removed, restore that state.
             entry = self._map[f]
             if entry[0] == 'r' and entry[2] in (-1, -2):
                 source = self._copymap.get(f)
                 if entry[2] == -1:
                     self.merge(f)
                 elif entry[2] == -2:
-                    self.normaldirty(f)
+                    self.otherparent(f)
                 if source:
                     self.copy(source, f)
                 return
@@ -305,8 +305,11 @@
         if f in self._copymap:
             del self._copymap[f]
 
-    def normaldirty(self, f):
-        '''Mark a file normal, but dirty.'''
+    def otherparent(self, f):
+        '''Mark as coming from the other parent, always dirty.'''
+        if self._pl[1] == nullid:
+            raise util.Abort(_("setting %r to other parent "
+                               "only allowed in merges") % f)
         self._dirty = True
         self._addpath(f)
         self._map[f] = ('n', 0, -2, -1)
@@ -327,10 +330,11 @@
         self._droppath(f)
         size = 0
         if self._pl[1] != nullid and f in self._map:
+            # backup the previous state
             entry = self._map[f]
-            if entry[0] == 'm':
+            if entry[0] == 'm': # merge
                 size = -1
-            elif entry[0] == 'n' and entry[2] == -2:
+            elif entry[0] == 'n' and entry[2] == -2: # other parent
                 size = -2
         self._map[f] = ('r', 0, size, 0)
         if size == 0 and f in self._copymap:
@@ -639,7 +643,7 @@
                 if (size >= 0 and
                     (size != st.st_size
                      or ((mode ^ st.st_mode) & 0100 and self._checkexec))
-                    or size == -2
+                    or size == -2 # other parent
                     or fn in self._copymap):
                     madd(fn)
                 elif time != int(st.st_mtime):
--- a/mercurial/dispatch.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/dispatch.py	Tue May 11 17:03:44 2010 -0500
@@ -9,7 +9,7 @@
 import os, sys, atexit, signal, pdb, socket, errno, shlex, time
 import util, commands, hg, fancyopts, extensions, hook, error
 import cmdutil, encoding
-import ui as _ui
+import ui as uimod
 
 def run():
     "run the command in sys.argv"
@@ -18,7 +18,7 @@
 def dispatch(args):
     "run the command specified in args"
     try:
-        u = _ui.ui()
+        u = uimod.ui()
         if '--traceback' in args:
             u.setconfig('ui', 'traceback', 'on')
     except util.Abort, inst:
--- a/mercurial/filelog.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/filelog.py	Tue May 11 17:03:44 2010 -0500
@@ -33,9 +33,7 @@
 
     def add(self, text, meta, transaction, link, p1=None, p2=None):
         if meta or text.startswith('\1\n'):
-            mt = ""
-            if meta:
-                mt = ["%s: %s\n" % (k, v) for k, v in sorted(meta.iteritems())]
+            mt = ["%s: %s\n" % (k, v) for k, v in sorted(meta.iteritems())]
             text = "\1\n%s\1\n%s" % ("".join(mt), text)
         return self.addrevision(text, transaction, link, p1, p2)
 
--- a/mercurial/filemerge.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/filemerge.py	Tue May 11 17:03:44 2010 -0500
@@ -7,7 +7,7 @@
 
 from node import short
 from i18n import _
-import util, simplemerge, match
+import util, simplemerge, match, error
 import os, tempfile, re, filecmp
 
 def _toolstr(ui, tool, part, default=""):
@@ -16,6 +16,9 @@
 def _toolbool(ui, tool, part, default=False):
     return ui.configbool("merge-tools", tool + "." + part, default)
 
+def _toollist(ui, tool, part, default=[]):
+    return ui.configlist("merge-tools", tool + "." + part, default)
+
 _internal = ['internal:' + s
              for s in 'fail local other merge prompt dump'.split()]
 
@@ -176,7 +179,18 @@
     ui.debug("my %s other %s ancestor %s\n" % (fcd, fco, fca))
 
     # do we attempt to simplemerge first?
-    if _toolbool(ui, tool, "premerge", not (binary or symlink)):
+    try:
+        premerge = _toolbool(ui, tool, "premerge", not (binary or symlink))
+    except error.ConfigError:
+        premerge = _toolstr(ui, tool, "premerge").lower()
+        valid = 'keep'.split()
+        if premerge not in valid:
+            _valid = ', '.join(["'" + v + "'" for v in valid])
+            raise error.ConfigError(_("%s.premerge not valid "
+                                      "('%s' is neither boolean nor %s)") %
+                                    (tool, premerge, _valid))
+
+    if premerge:
         r = simplemerge.simplemerge(ui, a, b, c, quiet=True)
         if not r:
             ui.debug(" premerge successful\n")
@@ -184,7 +198,8 @@
             os.unlink(b)
             os.unlink(c)
             return 0
-        util.copyfile(back, a) # restore from backup and try again
+        if premerge != 'keep':
+            util.copyfile(back, a) # restore from backup and try again
 
     env = dict(HG_FILE=fd,
                HG_MY_NODE=short(mynode),
@@ -211,11 +226,20 @@
             lambda x: '"%s"' % util.localpath(replace[x.group()[1:]]), args)
         r = util.system(toolpath + ' ' + args, cwd=repo.root, environ=env)
 
-    if not r and _toolbool(ui, tool, "checkconflicts"):
+    if not r and (_toolbool(ui, tool, "checkconflicts") or
+                  'conflicts' in _toollist(ui, tool, "check")):
         if re.match("^(<<<<<<< .*|=======|>>>>>>> .*)$", fcd.data()):
             r = 1
 
-    if not r and _toolbool(ui, tool, "checkchanged"):
+    checked = False
+    if 'prompt' in _toollist(ui, tool, "check"):
+        checked = True
+        if ui.promptchoice(_("was merge of '%s' successful (yn)?") % fd,
+                           (_("&Yes"), _("&No")), 1):
+            r = 1
+
+    if not r and not checked and (_toolbool(ui, tool, "checkchanged") or
+                                  'changed' in _toollist(ui, tool, "check")):
         if filecmp.cmp(repo.wjoin(fd), back):
             if ui.promptchoice(_(" output file %s appears unchanged\n"
                                  "was merge successful (yn)?") % fd,
--- a/mercurial/graphmod.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/graphmod.py	Tue May 11 17:03:44 2010 -0500
@@ -115,7 +115,7 @@
                 edges.append((ecol, next.index(eid), colors[eid]))
             elif eid == cur:
                 for p in parents:
-                    edges.append((ecol, next.index(p), colors[p]))
+                    edges.append((ecol, next.index(p), color))
 
         # Yield and move on
         yield (cur, type, data, (col, color), edges)
--- a/mercurial/help.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/help.py	Tue May 11 17:03:44 2010 -0500
@@ -25,7 +25,7 @@
             break
 
     start = line[:3]
-    if start == '\"\"\"' or start == "\'\'\'":
+    if start == '"""' or start == "'''":
         line = line[3:]
         while line:
             if line.rstrip().endswith(start):
@@ -97,4 +97,5 @@
      loaddoc('templates')),
     (['urls'], _('URL Paths'), loaddoc('urls')),
     (["extensions"], _("Using additional features"), extshelp),
+    (["hgweb"], _("Configuring hgweb"), loaddoc('hgweb')),
 )
--- a/mercurial/help/config.txt	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/help/config.txt	Tue May 11 17:03:44 2010 -0500
@@ -5,12 +5,13 @@
 
 - ``<repo>\.hg\hgrc``
 - ``%USERPROFILE%\.hgrc``
-- ``%USERPROFILE%\Mercurial.ini``
+- ``%USERPROFILE%\mercurial.ini``
 - ``%HOME%\.hgrc``
-- ``%HOME%\Mercurial.ini``
-- ``C:\Mercurial\Mercurial.ini``
-- ``HKEY_LOCAL_MACHINE\SOFTWARE\Mercurial``
-- ``<install-dir>\Mercurial.ini``
+- ``%HOME%\mercurial.ini``
+- ``C:\mercurial\mercurial.ini`` (unless regkey or hgrc.d\ or mercurial.ini found)
+- ``HKEY_LOCAL_MACHINE\SOFTWARE\Mercurial`` (unless hgrc.d\ or mercurial.ini found)
+- ``<hg.exe-dir>\hgrc.d\*.rc`` (unless mercurial.ini found)
+- ``<hg.exe-dir>\mercurial.ini``
 
 On Unix, these files are read:
 
@@ -29,7 +30,7 @@
   username = Firstname Lastname <firstname.lastname@example.net>
   verbose = True
 
-This above entries will be referred to as ``ui.username`` and
+The above entries will be referred to as ``ui.username`` and
 ``ui.verbose``, respectively. Please see the hgrc man page for a full
 description of the possible configuration values:
 
--- a/mercurial/help/diffs.txt	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/help/diffs.txt	Tue May 11 17:03:44 2010 -0500
@@ -16,7 +16,7 @@
 format.
 
 This means that when generating diffs from a Mercurial repository
-(e.g. with "hg export"), you should be careful about things like file
+(e.g. with :hg:`export`), you should be careful about things like file
 copies and renames or other things mentioned above, because when
 applying a standard diff to a different repository, this extra
 information is lost. Mercurial's internal operations (like push and
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial/help/hgweb.txt	Tue May 11 17:03:44 2010 -0500
@@ -0,0 +1,46 @@
+Mercurial's internal web server, hgweb, can serve either a single
+repository, or a collection of them. In the latter case, a special
+configuration file can be used to specify the repository paths to use
+and global web configuration options.
+
+This file uses the same syntax as hgrc configuration files, but only
+the following sections are recognized:
+
+  - web
+  - paths
+  - collections
+
+The ``web`` section can specify all the settings described in the web
+section of the hgrc documentation.
+
+The ``paths`` section provides mappings of physical repository
+paths to virtual ones. For instance::
+
+  [paths]
+  projects/a = /foo/bar
+  projects/b = /baz/quux
+  web/root = /real/root/*
+  / = /real/root2/*
+  virtual/root2 = /real/root2/**
+
+- The first two entries make two repositories in different directories
+  appear under the same directory in the web interface
+- The third entry maps every Mercurial repository found in '/real/root'
+  into 'web/root'. This format is preferred over the [collections] one,
+  since using absolute paths as configuration keys is not supported on every
+  platform (especially on Windows).
+- The fourth entry is a special case mapping all repositories in
+  '/real/root2' in the root of the virtual directory.
+- The fifth entry recursively finds all repositories under the real
+  root, and maps their relative paths under the virtual root.
+
+The ``collections`` section provides mappings of trees of physical
+repositories paths to virtual ones, though the paths syntax is generally
+preferred. For instance::
+
+  [collections]
+  /foo = /foo
+
+Here, the left side will be stripped off all repositories found in the
+right side. Thus ``/foo/bar`` and ``foo/quux/baz`` will be listed as
+``bar`` and ``quux/baz`` respectively.
--- a/mercurial/help/urls.txt	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/help/urls.txt	Tue May 11 17:03:44 2010 -0500
@@ -7,12 +7,12 @@
   ssh://[user[:pass]@]host[:port]/[path][#revision]
 
 Paths in the local filesystem can either point to Mercurial
-repositories or to bundle files (as created by 'hg bundle' or 'hg
-incoming --bundle').
+repositories or to bundle files (as created by :hg:`bundle` or :hg:`
+incoming --bundle`).
 
 An optional identifier after # indicates a particular branch, tag, or
-changeset to use from the remote repository. See also 'hg help
-revisions'.
+changeset to use from the remote repository. See also :hg:`help
+revisions`.
 
 Some features, such as pushing to http:// and https:// URLs are only
 possible if the feature is explicitly enabled on the remote Mercurial
@@ -47,7 +47,7 @@
   ...
 
 You can then use the alias for any command that uses a URL (for
-example 'hg pull alias1' will be treated as 'hg pull URL1').
+example :hg:`pull alias1` will be treated as :hg:`pull URL1`).
 
 Two path aliases are special because they are used as defaults when
 you do not provide the URL to a command:
--- a/mercurial/hg.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/hg.py	Tue May 11 17:03:44 2010 -0500
@@ -10,8 +10,8 @@
 from lock import release
 import localrepo, bundlerepo, httprepo, sshrepo, statichttprepo
 import lock, util, extensions, error, encoding, node
-import merge as _merge
-import verify as _verify
+import merge as mergemod
+import verify as verifymod
 import errno, os, shutil
 
 def _local(path):
@@ -359,7 +359,7 @@
 
 def update(repo, node):
     """update the working directory to node, merging linear changes"""
-    stats = _merge.update(repo, node, False, False, None)
+    stats = mergemod.update(repo, node, False, False, None)
     _showstats(repo, stats)
     if stats[3]:
         repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
@@ -370,14 +370,14 @@
 
 def clean(repo, node, show_stats=True):
     """forcibly switch the working directory to node, clobbering changes"""
-    stats = _merge.update(repo, node, False, True, None)
+    stats = mergemod.update(repo, node, False, True, None)
     if show_stats:
         _showstats(repo, stats)
     return stats[3] > 0
 
 def merge(repo, node, force=None, remind=True):
     """branch merge with node, resolving changes"""
-    stats = _merge.update(repo, node, True, force, False)
+    stats = mergemod.update(repo, node, True, force, False)
     _showstats(repo, stats)
     if stats[3]:
         repo.ui.status(_("use 'hg resolve' to retry unresolved file merges "
@@ -388,8 +388,8 @@
 
 def revert(repo, node, choose):
     """revert changes to revision in node without updating dirstate"""
-    return _merge.update(repo, node, False, True, choose)[3] > 0
+    return mergemod.update(repo, node, False, True, choose)[3] > 0
 
 def verify(repo):
     """verify the consistency of a repository"""
-    return _verify.verify(repo)
+    return verifymod.verify(repo)
--- a/mercurial/hgweb/__init__.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/hgweb/__init__.py	Tue May 11 17:03:44 2010 -0500
@@ -6,11 +6,26 @@
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 
+import os
 import hgweb_mod, hgwebdir_mod
 
-def hgweb(*args, **kwargs):
-    return hgweb_mod.hgweb(*args, **kwargs)
+def hgweb(config, name=None, baseui=None):
+    '''create an hgweb wsgi object
 
-def hgwebdir(*args, **kwargs):
-    return hgwebdir_mod.hgwebdir(*args, **kwargs)
+    config can be one of:
+    - repo object (single repo view)
+    - path to repo (single repo view)
+    - path to config file (multi-repo view)
+    - dict of virtual:real pairs (multi-repo view)
+    - list of virtual:real tuples (multi-repo view)
+    '''
 
+    if ((isinstance(config, str) and not os.path.isdir(config)) or
+        isinstance(config, dict) or isinstance(config, list)):
+        # create a multi-dir interface
+        return hgwebdir_mod.hgwebdir(config, baseui=baseui)
+    return hgweb_mod.hgweb(config, name=name, baseui=baseui)
+
+def hgwebdir(config, baseui=None):
+    return hgwebdir_mod.hgwebdir(config, baseui=baseui)
+
--- a/mercurial/hgweb/hgweb_mod.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/hgweb/hgweb_mod.py	Tue May 11 17:03:44 2010 -0500
@@ -10,7 +10,6 @@
 from mercurial import ui, hg, hook, error, encoding, templater
 from common import get_mtime, ErrorResponse, permhooks
 from common import HTTP_OK, HTTP_BAD_REQUEST, HTTP_NOT_FOUND, HTTP_SERVER_ERROR
-from common import HTTP_UNAUTHORIZED, HTTP_METHOD_NOT_ALLOWED
 from request import wsgirequest
 import webcommands, protocol, webutil
 
@@ -22,15 +21,18 @@
 }
 
 class hgweb(object):
-    def __init__(self, repo, name=None):
+    def __init__(self, repo, name=None, baseui=None):
         if isinstance(repo, str):
-            u = ui.ui()
-            u.setconfig('ui', 'report_untrusted', 'off')
-            u.setconfig('ui', 'interactive', 'off')
+            if baseui:
+                u = baseui.copy()
+            else:
+                u = ui.ui()
             self.repo = hg.repository(u, repo)
         else:
             self.repo = repo
 
+        self.repo.ui.setconfig('ui', 'report_untrusted', 'off')
+        self.repo.ui.setconfig('ui', 'interactive', 'off')
         hook.redirect(True)
         self.mtime = -1
         self.reponame = name
--- a/mercurial/hgweb/hgwebdir_mod.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/hgweb/hgwebdir_mod.py	Tue May 11 17:03:44 2010 -0500
@@ -195,11 +195,8 @@
                     yield {"type" : i[0], "extension": i[1],
                            "node": nodeid, "url": url}
 
-        sortdefault = None, False
-        def entries(sortcolumn="", descending=False, subdir="", **map):
+        def rawentries(subdir="", **map):
 
-            rows = []
-            parity = paritygen(self.stripecount)
             descend = self.ui.configbool('web', 'descend', True)
             for name, path in self.repos:
 
@@ -251,19 +248,19 @@
                            lastchange=d,
                            lastchange_sort=d[1]-d[0],
                            archives=archivelist(u, "tip", url))
-                if (not sortcolumn or (sortcolumn, descending) == sortdefault):
-                    # fast path for unsorted output
-                    row['parity'] = parity.next()
-                    yield row
-                else:
-                    rows.append((row["%s_sort" % sortcolumn], row))
-            if rows:
-                rows.sort()
-                if descending:
-                    rows.reverse()
-                for key, row in rows:
-                    row['parity'] = parity.next()
-                    yield row
+                yield row
+
+        sortdefault = None, False
+        def entries(sortcolumn="", descending=False, subdir="", **map):
+            rows = rawentries(subdir=subdir, **map)
+
+            if sortcolumn and sortdefault != (sortcolumn, descending):
+                sortkey = '%s_sort' % sortcolumn
+                rows = sorted(rows, key=lambda x: x[sortkey],
+                              reverse=descending)
+            for row, parity in zip(rows, paritygen(self.stripecount)):
+                row['parity'] = parity
+                yield row
 
         self.refresh()
         sortable = ["name", "description", "contact", "lastchange"]
--- a/mercurial/hgweb/server.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/hgweb/server.py	Tue May 11 17:03:44 2010 -0500
@@ -7,9 +7,7 @@
 # GNU General Public License version 2 or any later version.
 
 import os, sys, errno, urllib, BaseHTTPServer, socket, SocketServer, traceback
-from mercurial import hg, util, error
-from hgweb_mod import hgweb
-from hgwebdir_mod import hgwebdir
+from mercurial import util, error
 from mercurial.i18n import _
 
 def _splitURI(uri):
@@ -195,104 +193,85 @@
             self.close_connection = True
             pass
 
-def create_server(ui, repo):
-    use_threads = True
-
-    def openlog(opt, default):
-        if opt and opt != '-':
-            return open(opt, 'a')
-        return default
-
-    if repo is None:
-        myui = ui
+try:
+    from threading import activeCount
+    _mixin = SocketServer.ThreadingMixIn
+except ImportError:
+    if hasattr(os, "fork"):
+        _mixin = SocketServer.ForkingMixIn
     else:
-        myui = repo.ui
-    address = myui.config("web", "address", "")
-    port = int(myui.config("web", "port", 8000))
-    prefix = myui.config("web", "prefix", "")
-    if prefix:
-        prefix = "/" + prefix.strip("/")
-    use_ipv6 = myui.configbool("web", "ipv6")
-    webdir_conf = myui.config("web", "webdir_conf")
-    ssl_cert = myui.config("web", "certificate")
-    accesslog = openlog(myui.config("web", "accesslog", "-"), sys.stdout)
-    errorlog = openlog(myui.config("web", "errorlog", "-"), sys.stderr)
+        class _mixin:
+            pass
+
+def openlog(opt, default):
+    if opt and opt != '-':
+        return open(opt, 'a')
+    return default
 
-    if use_threads:
-        try:
-            from threading import activeCount
-        except ImportError:
-            use_threads = False
+class MercurialHTTPServer(object, _mixin, BaseHTTPServer.HTTPServer):
 
-    if use_threads:
-        _mixin = SocketServer.ThreadingMixIn
-    else:
-        if hasattr(os, "fork"):
-            _mixin = SocketServer.ForkingMixIn
-        else:
-            class _mixin:
-                pass
+    # SO_REUSEADDR has broken semantics on windows
+    if os.name == 'nt':
+        allow_reuse_address = 0
 
-    class MercurialHTTPServer(object, _mixin, BaseHTTPServer.HTTPServer):
+    def __init__(self, ui, app, addr, handler, **kwargs):
+        BaseHTTPServer.HTTPServer.__init__(self, addr, handler, **kwargs)
+        self.daemon_threads = True
+        self.application = app
 
-        # SO_REUSEADDR has broken semantics on windows
-        if os.name == 'nt':
-            allow_reuse_address = 0
+        ssl_cert = ui.config('web', 'certificate')
+        if ssl_cert:
+            try:
+                from OpenSSL import SSL
+                ctx = SSL.Context(SSL.SSLv23_METHOD)
+            except ImportError:
+                raise util.Abort(_("SSL support is unavailable"))
+            ctx.use_privatekey_file(ssl_cert)
+            ctx.use_certificate_file(ssl_cert)
+            sock = socket.socket(self.address_family, self.socket_type)
+            self.socket = SSL.Connection(ctx, sock)
+            self.server_bind()
+            self.server_activate()
 
-        def __init__(self, *args, **kargs):
-            BaseHTTPServer.HTTPServer.__init__(self, *args, **kargs)
-            self.accesslog = accesslog
-            self.errorlog = errorlog
-            self.daemon_threads = True
-            def make_handler():
-                if webdir_conf:
-                    hgwebobj = hgwebdir(webdir_conf, ui)
-                elif repo is not None:
-                    hgwebobj = hgweb(hg.repository(repo.ui, repo.root))
-                else:
-                    raise error.RepoError(_("There is no Mercurial repository"
-                                            " here (.hg not found)"))
-                return hgwebobj
-            self.application = make_handler()
+        prefix = ui.config('web', 'prefix', '')
+        if prefix:
+            prefix = '/' + prefix.strip('/')
+        self.prefix = prefix
 
-            if ssl_cert:
-                try:
-                    from OpenSSL import SSL
-                    ctx = SSL.Context(SSL.SSLv23_METHOD)
-                except ImportError:
-                    raise util.Abort(_("SSL support is unavailable"))
-                ctx.use_privatekey_file(ssl_cert)
-                ctx.use_certificate_file(ssl_cert)
-                sock = socket.socket(self.address_family, self.socket_type)
-                self.socket = SSL.Connection(ctx, sock)
-                self.server_bind()
-                self.server_activate()
+        alog = openlog(ui.config('web', 'accesslog', '-'), sys.stdout)
+        elog = openlog(ui.config('web', 'errorlog', '-'), sys.stderr)
+        self.accesslog = alog
+        self.errorlog = elog
+
+        self.addr, self.port = self.socket.getsockname()[0:2]
+        self.fqaddr = socket.getfqdn(addr[0])
 
-            self.addr, self.port = self.socket.getsockname()[0:2]
-            self.prefix = prefix
-            self.fqaddr = socket.getfqdn(address)
-
-    class IPv6HTTPServer(MercurialHTTPServer):
-        address_family = getattr(socket, 'AF_INET6', None)
+class IPv6HTTPServer(MercurialHTTPServer):
+    address_family = getattr(socket, 'AF_INET6', None)
+    def __init__(self, *args, **kwargs):
+        if self.address_family is None:
+            raise error.RepoError(_('IPv6 is not available on this system'))
+        super(IPv6HTTPServer, self).__init__(*args, **kwargs)
 
-        def __init__(self, *args, **kwargs):
-            if self.address_family is None:
-                raise error.RepoError(_('IPv6 is not available on this system'))
-            super(IPv6HTTPServer, self).__init__(*args, **kwargs)
+def create_server(ui, app):
 
-    if ssl_cert:
+    if ui.config('web', 'certificate'):
         handler = _shgwebhandler
     else:
         handler = _hgwebhandler
 
+    if ui.configbool('web', 'ipv6'):
+        cls = IPv6HTTPServer
+    else:
+        cls = MercurialHTTPServer
+
     # ugly hack due to python issue5853 (for threaded use)
     import mimetypes; mimetypes.init()
 
+    address = ui.config('web', 'address', '')
+    port = int(ui.config('web', 'port', 8000))
     try:
-        if use_ipv6:
-            return IPv6HTTPServer((address, port), handler)
-        else:
-            return MercurialHTTPServer((address, port), handler)
+        return cls(ui, app, (address, port), handler)
     except socket.error, inst:
         raise util.Abort(_("cannot start server at '%s:%d': %s")
                          % (address, port, inst.args[1]))
--- a/mercurial/httprepo.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/httprepo.py	Tue May 11 17:03:44 2010 -0500
@@ -208,6 +208,12 @@
         return util.chunkbuffer(zgenerator(f))
 
     def unbundle(self, cg, heads, source):
+        '''Send cg (a readable file-like object representing the
+        changegroup to push, typically a chunkbuffer object) to the
+        remote server as a bundle. Return an integer response code:
+        non-zero indicates a successful push (see
+        localrepository.addchangegroup()), and zero indicates either
+        error or nothing to push.'''
         # have to stream bundle to a temp file because we do not have
         # http 1.1 chunked transfer.
 
--- a/mercurial/localrepo.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/localrepo.py	Tue May 11 17:03:44 2010 -0500
@@ -11,9 +11,10 @@
 import changelog, dirstate, filelog, manifest, context
 import lock, transaction, store, encoding
 import util, extensions, hook, error
-import match as match_
-import merge as merge_
-import tags as tags_
+import match as matchmod
+import merge as mergemod
+import tags as tagsmod
+import url as urlmod
 from lock import release
 import weakref, stat, errno, os, time, inspect
 propertycache = util.propertycache
@@ -163,9 +164,13 @@
             if c in allchars:
                 raise util.Abort(_('%r cannot be used in a tag name') % c)
 
+        branches = self.branchmap()
         for name in names:
             self.hook('pretag', throw=True, node=hex(node), tag=name,
                       local=local)
+            if name in branches:
+                self.ui.warn(_("warning: tag %s conflicts with existing"
+                " branch name\n") % name)
 
         def writetags(fp, names, munge, prevtags):
             fp.seek(0, 2)
@@ -207,7 +212,7 @@
         if '.hgtags' not in self.dirstate:
             self.add(['.hgtags'])
 
-        m = match_.exact(self.root, '', ['.hgtags'])
+        m = matchmod.exact(self.root, '', ['.hgtags'])
         tagnode = self.commit(message, user, date, extra=extra, match=m)
 
         for name in names:
@@ -268,8 +273,8 @@
         alltags = {}                    # map tag name to (node, hist)
         tagtypes = {}
 
-        tags_.findglobaltags(self.ui, self, alltags, tagtypes)
-        tags_.readlocaltags(self.ui, self, alltags, tagtypes)
+        tagsmod.findglobaltags(self.ui, self, alltags, tagtypes)
+        tagsmod.readlocaltags(self.ui, self, alltags, tagtypes)
 
         # Build the return dicts.  Have to re-encode tag names because
         # the tags module always uses UTF-8 (in order not to lose info
@@ -314,6 +319,8 @@
             self.nodetagscache = {}
             for t, n in self.tags().iteritems():
                 self.nodetagscache.setdefault(n, []).append(t)
+            for tags in self.nodetagscache.itervalues():
+                tags.sort()
         return self.nodetagscache.get(node, [])
 
     def _branchtags(self, partial, lrev):
@@ -410,9 +417,8 @@
         for branch, newnodes in newbranches.iteritems():
             bheads = partial.setdefault(branch, [])
             bheads.extend(newnodes)
-            if len(bheads) < 2:
+            if len(bheads) <= 1:
                 continue
-            newbheads = []
             # starting from tip means fewer passes over reachable
             while newnodes:
                 latest = newnodes.pop()
@@ -420,9 +426,8 @@
                     continue
                 minbhrev = self[min([self[bh].rev() for bh in bheads])].node()
                 reachable = self.changelog.reachable(latest, minbhrev)
+                reachable.remove(latest)
                 bheads = [b for b in bheads if b not in reachable]
-                newbheads.insert(0, latest)
-            bheads.extend(newbheads)
             partial[branch] = bheads
 
     def lookup(self, key):
@@ -456,6 +461,14 @@
             pass
         raise error.RepoLookupError(_("unknown revision '%s'") % key)
 
+    def lookupbranch(self, key, remote=None):
+        repo = remote or self
+        if key in repo.branchmap():
+            return key
+
+        repo = (remote and remote.local()) and remote or self
+        return repo[key].branch()
+
     def local(self):
         return True
 
@@ -503,7 +516,7 @@
             for pat, cmd in self.ui.configitems(filter):
                 if cmd == '!':
                     continue
-                mf = match_.match(self.root, '', [pat])
+                mf = matchmod.match(self.root, '', [pat])
                 fn = None
                 params = cmd
                 for name, filterfn in self._datafilters.iteritems():
@@ -554,7 +567,7 @@
     def wwritedata(self, filename, data):
         return self._filter("decode", filename, data)
 
-    def transaction(self):
+    def transaction(self, desc):
         tr = self._transref and self._transref() or None
         if tr and tr.running():
             return tr.nest()
@@ -571,10 +584,12 @@
             ds = ""
         self.opener("journal.dirstate", "w").write(ds)
         self.opener("journal.branch", "w").write(self.dirstate.branch())
+        self.opener("journal.desc", "w").write("%d\n%s\n" % (len(self), desc))
 
         renames = [(self.sjoin("journal"), self.sjoin("undo")),
                    (self.join("journal.dirstate"), self.join("undo.dirstate")),
-                   (self.join("journal.branch"), self.join("undo.branch"))]
+                   (self.join("journal.branch"), self.join("undo.branch")),
+                   (self.join("journal.desc"), self.join("undo.desc"))]
         tr = transaction.transaction(self.ui.warn, self.sopener,
                                      self.sjoin("journal"),
                                      aftertrans(renames),
@@ -597,13 +612,26 @@
         finally:
             lock.release()
 
-    def rollback(self):
+    def rollback(self, dryrun=False):
         wlock = lock = None
         try:
             wlock = self.wlock()
             lock = self.lock()
             if os.path.exists(self.sjoin("undo")):
-                self.ui.status(_("rolling back last transaction\n"))
+                try:
+                    args = self.opener("undo.desc", "r").read().splitlines()
+                    if len(args) >= 3 and self.ui.verbose:
+                        desc = _("rolling back to revision %s"
+                                 " (undo %s: %s)\n") % (
+                                 args[0], args[1], args[2])
+                    elif len(args) >= 2:
+                        desc = _("rolling back to revision %s (undo %s)\n") % (
+                                 args[0], args[1])
+                except IOError:
+                    desc = _("rolling back unknown transaction\n")
+                self.ui.status(desc)
+                if dryrun:
+                    return
                 transaction.rollback(self.sopener, self.sjoin("undo"),
                                      self.ui.warn)
                 util.rename(self.join("undo.dirstate"), self.join("dirstate"))
@@ -767,7 +795,7 @@
             raise util.Abort('%s: %s' % (f, msg))
 
         if not match:
-            match = match_.always(self.root, '')
+            match = matchmod.always(self.root, '')
 
         if not force:
             vdirs = []
@@ -776,10 +804,10 @@
 
         wlock = self.wlock()
         try:
-            p1, p2 = self.dirstate.parents()
             wctx = self[None]
+            merge = len(wctx.parents()) > 1
 
-            if (not force and p2 != nullid and match and
+            if (not force and merge and match and
                 (match.files() or match.anypats())):
                 raise util.Abort(_('cannot partially commit a merge '
                                    '(do not specify files or patterns)'))
@@ -819,19 +847,18 @@
                     elif f not in self.dirstate:
                         fail(f, _("file not tracked!"))
 
-            if (not force and not extra.get("close") and p2 == nullid
+            if (not force and not extra.get("close") and not merge
                 and not (changes[0] or changes[1] or changes[2])
-                and self[None].branch() == self['.'].branch()):
+                and wctx.branch() == wctx.p1().branch()):
                 return None
 
-            ms = merge_.mergestate(self)
+            ms = mergemod.mergestate(self)
             for f in changes[0]:
                 if f in ms and ms[f] == 'u':
                     raise util.Abort(_("unresolved merge conflicts "
                                                     "(see hg resolve)"))
 
-            cctx = context.workingctx(self, (p1, p2), text, user, date,
-                                      extra, changes)
+            cctx = context.workingctx(self, text, user, date, extra, changes)
             if editor:
                 cctx._text = editor(self, cctx, subs)
             edited = (text != cctx._text)
@@ -840,8 +867,10 @@
             if subs or removedsubs:
                 state = wctx.substate.copy()
                 for s in subs:
-                    self.ui.status(_('committing subrepository %s\n') % s)
-                    sr = wctx.sub(s).commit(cctx._text, user, date)
+                    sub = wctx.sub(s)
+                    self.ui.status(_('committing subrepository %s\n') %
+                        subrepo.relpath(sub))
+                    sr = sub.commit(cctx._text, user, date)
                     state[s] = (state[s][0], sr)
                 subrepo.writestate(self, state)
 
@@ -852,8 +881,9 @@
             msgfile.write(cctx._text)
             msgfile.close()
 
+            p1, p2 = self.dirstate.parents()
+            hookp1, hookp2 = hex(p1), (p2 != nullid and hex(p2) or '')
             try:
-                hookp1, hookp2 = hex(p1), (p2 != nullid and hex(p2) or '')
                 self.hook("precommit", throw=True, parent1=hookp1, parent2=hookp2)
                 ret = self.commitctx(cctx, True)
             except:
@@ -890,7 +920,7 @@
 
         lock = self.lock()
         try:
-            tr = self.transaction()
+            tr = self.transaction("commit")
             trp = weakref.proxy(tr)
 
             # check in files
@@ -996,7 +1026,7 @@
 
         working = ctx2.rev() is None
         parentworking = working and ctx1 == self['.']
-        match = match or match_.always(self.root, self.getcwd())
+        match = match or matchmod.always(self.root, self.getcwd())
         listignored, listclean, listunknown = ignored, clean, unknown
 
         # load earliest manifest first for caching reasons
@@ -1396,7 +1426,7 @@
         self.ui.debug("found new changesets starting at " +
                      " ".join([short(f) for f in fetch]) + "\n")
 
-        self.ui.progress(_('searching'), None, unit=_('queries'))
+        self.ui.progress(_('searching'), None)
         self.ui.debug("%d total queries\n" % reqcnt)
 
         return base.keys(), list(fetch), heads
@@ -1477,6 +1507,13 @@
             lock.release()
 
     def push(self, remote, force=False, revs=None):
+        '''Push outgoing changesets (limited by revs) from the current
+        repository to remote. Return an integer:
+          - 0 means HTTP error *or* nothing to push
+          - 1 means we pushed and remote head count is unchanged *or*
+            we have outgoing changesets but refused to push
+          - other values as described by addchangegroup()
+        '''
         # there are two ways to push to remote repo:
         #
         # addchangegroup assumes local user can lock remote
@@ -1491,11 +1528,18 @@
 
     def prepush(self, remote, force, revs):
         '''Analyze the local and remote repositories and determine which
-        changesets need to be pushed to the remote.  Return a tuple
-        (changegroup, remoteheads).  changegroup is a readable file-like
-        object whose read() returns successive changegroup chunks ready to
-        be sent over the wire.  remoteheads is the list of remote heads.
-        '''
+        changesets need to be pushed to the remote. Return value depends
+        on circumstances:
+
+        If we are not going to push anything, return a tuple (None,
+        outgoing) where outgoing is 0 if there are no outgoing
+        changesets and 1 if there are, but we refuse to push them
+        (e.g. would create new remote heads).
+
+        Otherwise, return a tuple (changegroup, remoteheads), where
+        changegroup is a readable file-like object whose read() returns
+        successive changegroup chunks ready to be sent over the wire and
+        remoteheads is the list of remote heads.'''
         common = {}
         remote_heads = remote.heads()
         inc = self.findincoming(remote, common, remote_heads, force=force)
@@ -1610,17 +1654,26 @@
         return cg, remote_heads
 
     def push_addchangegroup(self, remote, force, revs):
+        '''Push a changegroup by locking the remote and sending the
+        addchangegroup command to it. Used for local and old SSH repos.
+        Return an integer: see push().
+        '''
         lock = remote.lock()
         try:
             ret = self.prepush(remote, force, revs)
             if ret[0] is not None:
                 cg, remote_heads = ret
+                # here, we return an integer indicating remote head count change
                 return remote.addchangegroup(cg, 'push', self.url())
+            # and here we return 0 for "nothing to push" or 1 for
+            # "something to push but I refuse"
             return ret[1]
         finally:
             lock.release()
 
     def push_unbundle(self, remote, force, revs):
+        '''Push a changegroup by unbundling it on the remote.  Used for new
+        SSH and HTTP repos. Return an integer: see push().'''
         # local repo finds heads on server, finds out what revs it
         # must push.  once revs transferred, if server finds it has
         # different heads (someone else won commit/push race), server
@@ -1631,7 +1684,10 @@
             cg, remote_heads = ret
             if force:
                 remote_heads = ['force']
+            # ssh: return remote's addchangegroup()
+            # http: return remote's addchangegroup() or 0 for error
             return remote.unbundle(cg, remote_heads, 'push')
+        # as in push_addchangegroup()
         return ret[1]
 
     def changegroupinfo(self, nodes, source):
@@ -1829,7 +1885,7 @@
                 yield chnk
                 self.ui.progress(_('bundling changes'), cnt, unit=_('chunks'))
                 cnt += 1
-            self.ui.progress(_('bundling changes'), None, unit=_('chunks'))
+            self.ui.progress(_('bundling changes'), None)
 
 
             # Figure out which manifest nodes (of the ones we think might be
@@ -1857,7 +1913,7 @@
                 yield chnk
                 self.ui.progress(_('bundling manifests'), cnt, unit=_('chunks'))
                 cnt += 1
-            self.ui.progress(_('bundling manifests'), None, unit=_('chunks'))
+            self.ui.progress(_('bundling manifests'), None)
 
             # These are no longer needed, dereference and toss the memory for
             # them.
@@ -1906,7 +1962,7 @@
                     del msng_filenode_set[fname]
             # Signal that no more groups are left.
             yield changegroup.closechunk()
-            self.ui.progress(_('bundling files'), None, unit=_('chunks'))
+            self.ui.progress(_('bundling files'), None)
 
             if msng_cl_lst:
                 self.hook('outgoing', node=hex(msng_cl_lst[0]), source=source)
@@ -1958,7 +2014,7 @@
                 self.ui.progress(_('bundling changes'), cnt, unit=_('chunks'))
                 cnt += 1
                 yield chnk
-            self.ui.progress(_('bundling changes'), None, unit=_('chunks'))
+            self.ui.progress(_('bundling changes'), None)
 
             mnfst = self.manifest
             nodeiter = gennodelst(mnfst)
@@ -1967,7 +2023,7 @@
                 self.ui.progress(_('bundling manifests'), cnt, unit=_('chunks'))
                 cnt += 1
                 yield chnk
-            self.ui.progress(_('bundling manifests'), None, unit=_('chunks'))
+            self.ui.progress(_('bundling manifests'), None)
 
             cnt = 0
             for fname in sorted(changedfiles):
@@ -1985,7 +2041,7 @@
                             _('bundling files'), cnt, item=fname, unit=_('chunks'))
                         cnt += 1
                         yield chnk
-            self.ui.progress(_('bundling files'), None, unit=_('chunks'))
+            self.ui.progress(_('bundling files'), None)
 
             yield changegroup.closechunk()
 
@@ -1995,12 +2051,14 @@
         return util.chunkbuffer(gengroup())
 
     def addchangegroup(self, source, srctype, url, emptyok=False):
-        """add changegroup to repo.
+        """Add the changegroup returned by source.read() to this repo.
+        srctype is a string like 'push', 'pull', or 'unbundle'.  url is
+        the URL of the repo where this changegroup is coming from.
 
-        return values:
+        Return an integer summarizing the change to this repo:
         - nothing changed or no source: 0
         - more heads than before: 1+added heads (2..n)
-        - less heads than before: -1-removed heads (-2..-n)
+        - fewer heads than before: -1-removed heads (-2..-n)
         - number of heads stays the same: 1
         """
         def csmap(x):
@@ -2016,6 +2074,7 @@
         self.hook('prechangegroup', throw=True, source=srctype, url=url)
 
         changesets = files = revisions = 0
+        efiles = set()
 
         # write changelog data to temp files so concurrent readers will not see
         # inconsistent view
@@ -2023,7 +2082,7 @@
         cl.delayupdate()
         oldheads = len(cl.heads())
 
-        tr = self.transaction()
+        tr = self.transaction("\n".join([srctype, urlmod.hidepassword(url)]))
         try:
             trp = weakref.proxy(tr)
             # pull off the changeset group
@@ -2033,8 +2092,10 @@
                 step = _('changesets')
                 count = 1
                 ui = self.ui
+                total = None
                 def __call__(self):
-                    self.ui.progress(self.step, self.count, unit=_('chunks'))
+                    self.ui.progress(self.step, self.count, unit=_('chunks'),
+                                     total=self.total)
                     self.count += 1
             pr = prog()
             chunkiter = changegroup.chunkiter(source, progress=pr)
@@ -2042,12 +2103,16 @@
                 raise util.Abort(_("received changelog group is empty"))
             clend = len(cl)
             changesets = clend - clstart
+            for c in xrange(clstart, clend):
+                efiles.update(self[c].files())
+            efiles = len(efiles)
             self.ui.progress(_('changesets'), None)
 
             # pull off the manifest group
             self.ui.status(_("adding manifests\n"))
             pr.step = _('manifests')
             pr.count = 1
+            pr.total = changesets # manifests <= changesets
             chunkiter = changegroup.chunkiter(source, progress=pr)
             # no need to check for empty manifest group here:
             # if the result of the merge of 1 and 2 is the same in 3 and 4,
@@ -2070,14 +2135,16 @@
             self.ui.status(_("adding file changes\n"))
             pr.step = 'files'
             pr.count = 1
+            pr.total = efiles
             while 1:
                 f = changegroup.getchunk(source)
                 if not f:
                     break
                 self.ui.debug("adding %s revisions\n" % f)
+                pr()
                 fl = self.file(f)
                 o = len(fl)
-                chunkiter = changegroup.chunkiter(source, progress=pr)
+                chunkiter = changegroup.chunkiter(source)
                 if fl.addgroup(chunkiter, revmap, trp) is None:
                     raise util.Abort(_("received file revlog group is empty"))
                 revisions += len(fl) - o
--- a/mercurial/mdiff.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/mdiff.py	Tue May 11 17:03:44 2010 -0500
@@ -125,12 +125,12 @@
     else:
         al = splitnewlines(a)
         bl = splitnewlines(b)
-        l = list(bunidiff(a, b, al, bl, "a/" + fn1, "b/" + fn2, opts=opts))
+        l = list(_unidiff(a, b, al, bl, opts=opts))
         if not l:
             return ""
-        # difflib uses a space, rather than a tab
-        l[0] = "%s%s" % (l[0][:-2], datetag(ad))
-        l[1] = "%s%s" % (l[1][:-2], datetag(bd))
+
+        l.insert(0, "--- a/%s%s" % (fn1, datetag(ad)))
+        l.insert(1, "+++ b/%s%s" % (fn2, datetag(bd)))
 
     for ln in xrange(len(l)):
         if l[ln][-1] != '\n':
@@ -141,11 +141,10 @@
 
     return "".join(l)
 
-# somewhat self contained replacement for difflib.unified_diff
+# creates a headerless unified diff
 # t1 and t2 are the text to be diffed
 # l1 and l2 are the text broken up into lines
-# header1 and header2 are the filenames for the diff output
-def bunidiff(t1, t2, l1, l2, header1, header2, opts=defaultopts):
+def _unidiff(t1, t2, l1, l2, opts=defaultopts):
     def contextend(l, len):
         ret = l + opts.context
         if ret > len:
@@ -158,10 +157,7 @@
             return 0
         return ret
 
-    def yieldhunk(hunk, header):
-        if header:
-            for x in header:
-                yield x
+    def yieldhunk(hunk):
         (astart, a2, bstart, b2, delta) = hunk
         aend = contextend(a2, len(l1))
         alen = aend - astart
@@ -184,8 +180,6 @@
         for x in xrange(a2, aend):
             yield ' ' + l1[x]
 
-    header = ["--- %s\t\n" % header1, "+++ %s\t\n" % header2]
-
     if opts.showfunc:
         funcre = re.compile('\w')
 
@@ -236,11 +230,8 @@
                 astart = hunk[1]
                 bstart = hunk[3]
             else:
-                for x in yieldhunk(hunk, header):
+                for x in yieldhunk(hunk):
                     yield x
-                # we only want to yield the header if the files differ, and
-                # we only want to yield it once.
-                header = None
         if prev:
             # we've joined the previous hunk, record the new ending points.
             hunk[1] = a2
@@ -255,7 +246,7 @@
         delta[len(delta):] = ['+' + x for x in new]
 
     if hunk:
-        for x in yieldhunk(hunk, header):
+        for x in yieldhunk(hunk):
             yield x
 
 def patchtext(bin):
--- a/mercurial/merge.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/merge.py	Tue May 11 17:03:44 2010 -0500
@@ -364,7 +364,7 @@
             repo.dirstate.normallookup(f)
         elif m == "g": # get
             if branchmerge:
-                repo.dirstate.normaldirty(f)
+                repo.dirstate.otherparent(f)
             else:
                 repo.dirstate.normal(f)
         elif m == "m": # merge
@@ -491,6 +491,7 @@
 
         ### calculate phase
         action = []
+        wc.status(unknown=True) # prime cache
         if not force:
             _checkunknown(wc, p2)
         if not util.checkcase(repo.path):
@@ -507,8 +508,8 @@
         stats = applyupdates(repo, action, wc, p2)
 
         if not partial:
+            repo.dirstate.setparents(fp1, fp2)
             recordupdates(repo, action, branchmerge)
-            repo.dirstate.setparents(fp1, fp2)
             if not branchmerge and not fastforward:
                 repo.dirstate.setbranch(p2.branch())
     finally:
--- a/mercurial/minirst.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/minirst.py	Tue May 11 17:03:44 2010 -0500
@@ -225,6 +225,8 @@
     return blocks, pruned
 
 
+_sectionre = re.compile(r"""^([-=`:.'"~^_*+#])\1+$""")
+
 def findsections(blocks):
     """Finds sections.
 
@@ -240,18 +242,30 @@
         # +------------------------------+
         if (block['type'] == 'paragraph' and
             len(block['lines']) == 2 and
-            block['lines'][1] == '-' * len(block['lines'][0])):
+            len(block['lines'][0]) == len(block['lines'][1]) and
+            _sectionre.match(block['lines'][1])):
+            block['underline'] = block['lines'][1][0]
             block['type'] = 'section'
+            del block['lines'][1]
     return blocks
 
 
 def inlineliterals(blocks):
     for b in blocks:
-        if b['type'] == 'paragraph':
+        if b['type'] in ('paragraph', 'section'):
             b['lines'] = [l.replace('``', '"') for l in b['lines']]
     return blocks
 
 
+_hgrolere = re.compile(r':hg:`([^`]+)`')
+
+def hgrole(blocks):
+    for b in blocks:
+        if b['type'] in ('paragraph', 'section'):
+            b['lines'] = [_hgrolere.sub(r'"hg \1"', l) for l in b['lines']]
+    return blocks
+
+
 def addmargins(blocks):
     """Adds empty blocks for vertical spacing.
 
@@ -261,7 +275,7 @@
     i = 1
     while i < len(blocks):
         if (blocks[i]['type'] == blocks[i - 1]['type'] and
-            blocks[i]['type'] in ('bullet', 'option', 'field', 'definition')):
+            blocks[i]['type'] in ('bullet', 'option', 'field')):
             i += 1
         else:
             blocks.insert(i, dict(lines=[''], indent=0, type='margin'))
@@ -280,7 +294,8 @@
         indent += '  '
         return indent + ('\n' + indent).join(block['lines'])
     if block['type'] == 'section':
-        return indent + ('\n' + indent).join(block['lines'])
+        underline = len(block['lines'][0]) * block['underline']
+        return "%s%s\n%s%s" % (indent, block['lines'][0],indent, underline)
     if block['type'] == 'definition':
         term = indent + block['lines'][0]
         hang = len(block['lines'][-1]) - len(block['lines'][-1].lstrip())
@@ -289,7 +304,7 @@
         return "%s\n%s" % (term, textwrap.fill(text, width=width,
                                                initial_indent=defindent,
                                                subsequent_indent=defindent))
-    initindent = subindent = indent
+    subindent = indent
     if block['type'] == 'bullet':
         if block['lines'][0].startswith('| '):
             # Remove bullet for line blocks and add no extra
@@ -321,7 +336,7 @@
 
     text = ' '.join(map(str.strip, block['lines']))
     return textwrap.fill(text, width=width,
-                         initial_indent=initindent,
+                         initial_indent=indent,
                          subsequent_indent=subindent)
 
 
@@ -332,10 +347,11 @@
         b['indent'] += indent
     blocks = findliteralblocks(blocks)
     blocks, pruned = prunecontainers(blocks, keep or [])
+    blocks = findsections(blocks)
     blocks = inlineliterals(blocks)
+    blocks = hgrole(blocks)
     blocks = splitparagraphs(blocks)
     blocks = updatefieldlists(blocks)
-    blocks = findsections(blocks)
     blocks = addmargins(blocks)
     text = '\n'.join(formatblock(b, width) for b in blocks)
     if keep is None:
--- a/mercurial/patch.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/patch.py	Tue May 11 17:03:44 2010 -0500
@@ -6,11 +6,12 @@
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 
+import cStringIO, email.Parser, os, re
+import tempfile, zlib
+
 from i18n import _
 from node import hex, nullid, short
 import base85, cmdutil, mdiff, util, diffhelpers, copies
-import cStringIO, email.Parser, os, re
-import sys, tempfile, zlib
 
 gitre = re.compile('diff --git a/(.*) b/(.*)')
 
@@ -302,6 +303,9 @@
         isexec = mode & 0100
         self.mode = (islink, isexec)
 
+    def __repr__(self):
+        return "<patchmeta %s %r>" % (self.op, self.path)
+
 def readgitpatch(lr):
     """extract git-style metadata about patches from <patchname>"""
 
@@ -343,8 +347,6 @@
                 gp.path = line[8:]
             elif line.startswith('deleted file'):
                 gp.op = 'DELETE'
-                # is the deleted file a symlink?
-                gp.setmode(int(line[-6:], 8))
             elif line.startswith('new file mode '):
                 gp.op = 'ADD'
                 gp.setmode(int(line[-6:], 8))
@@ -905,24 +907,25 @@
             return s
     return s[:i]
 
+def pathstrip(path, strip):
+    pathlen = len(path)
+    i = 0
+    if strip == 0:
+        return '', path.rstrip()
+    count = strip
+    while count > 0:
+        i = path.find('/', i)
+        if i == -1:
+            raise PatchError(_("unable to strip away %d of %d dirs from %s") %
+                             (count, strip, path))
+        i += 1
+        # consume '//' in the path
+        while i < pathlen - 1 and path[i] == '/':
+            i += 1
+        count -= 1
+    return path[:i].lstrip(), path[i:].rstrip()
+
 def selectfile(afile_orig, bfile_orig, hunk, strip):
-    def pathstrip(path, count=1):
-        pathlen = len(path)
-        i = 0
-        if count == 0:
-            return '', path.rstrip()
-        while count > 0:
-            i = path.find('/', i)
-            if i == -1:
-                raise PatchError(_("unable to strip away %d dirs from %s") %
-                                 (count, path))
-            i += 1
-            # consume '//' in the path
-            while i < pathlen - 1 and path[i] == '/':
-                i += 1
-            count -= 1
-        return path[:i].lstrip(), path[i:].rstrip()
-
     nulla = afile_orig == "/dev/null"
     nullb = bfile_orig == "/dev/null"
     abase, afile = pathstrip(afile_orig, strip)
@@ -1125,9 +1128,9 @@
     if (empty is None and not gitworkdone) or empty:
         raise NoHunks
 
+
 def applydiff(ui, fp, changed, strip=1, sourcefile=None, eolmode='strict'):
-    """
-    Reads a patch from fp and tries to apply it.
+    """Reads a patch from fp and tries to apply it.
 
     The dict 'changed' is filled in with all of the filenames changed
     by the patch. Returns 0 for a clean patch, -1 if any rejects were
@@ -1136,12 +1139,22 @@
     If 'eolmode' is 'strict', the patch content and patched file are
     read in binary mode. Otherwise, line endings are ignored when
     patching then normalized according to 'eolmode'.
+
+    Callers probably want to call 'updatedir' after this to apply
+    certain categories of changes not done by this function.
     """
+    return _applydiff(
+        ui, fp, patchfile, copyfile,
+        changed, strip=strip, sourcefile=sourcefile, eolmode=eolmode)
+
+
+def _applydiff(ui, fp, patcher, copyfn, changed, strip=1,
+               sourcefile=None, eolmode='strict'):
     rejects = 0
     err = 0
     current_file = None
-    gitpatches = None
-    opener = util.opener(os.getcwd())
+    cwd = os.getcwd()
+    opener = util.opener(cwd)
 
     def closefile():
         if not current_file:
@@ -1153,8 +1166,7 @@
         if state == 'hunk':
             if not current_file:
                 continue
-            current_hunk = values
-            ret = current_file.apply(current_hunk)
+            ret = current_file.apply(values)
             if ret >= 0:
                 changed.setdefault(current_file.fname, None)
                 if ret > 0:
@@ -1164,24 +1176,25 @@
             afile, bfile, first_hunk = values
             try:
                 if sourcefile:
-                    current_file = patchfile(ui, sourcefile, opener,
-                                             eolmode=eolmode)
+                    current_file = patcher(ui, sourcefile, opener,
+                                           eolmode=eolmode)
                 else:
                     current_file, missing = selectfile(afile, bfile,
                                                        first_hunk, strip)
-                    current_file = patchfile(ui, current_file, opener,
-                                             missing, eolmode)
+                    current_file = patcher(ui, current_file, opener,
+                                           missing=missing, eolmode=eolmode)
             except PatchError, err:
                 ui.warn(str(err) + '\n')
-                current_file, current_hunk = None, None
+                current_file = None
                 rejects += 1
                 continue
         elif state == 'git':
-            gitpatches = values
-            cwd = os.getcwd()
-            for gp in gitpatches:
+            for gp in values:
+                gp.path = pathstrip(gp.path, strip - 1)[1]
+                if gp.oldpath:
+                    gp.oldpath = pathstrip(gp.oldpath, strip - 1)[1]
                 if gp.op in ('COPY', 'RENAME'):
-                    copyfile(gp.oldpath, gp.path, cwd)
+                    copyfn(gp.oldpath, gp.path, cwd)
                 changed[gp.path] = gp
         else:
             raise util.Abort(_('unsupported parser state: %s') % state)
@@ -1192,20 +1205,6 @@
         return -1
     return err
 
-def diffopts(ui, opts=None, untrusted=False):
-    def get(key, name=None, getter=ui.configbool):
-        return ((opts and opts.get(key)) or
-                getter('diff', name or key, None, untrusted=untrusted))
-    return mdiff.diffopts(
-        text=opts and opts.get('text'),
-        git=get('git'),
-        nodates=get('nodates'),
-        showfunc=get('show_function', 'showfunc'),
-        ignorews=get('ignore_all_space', 'ignorews'),
-        ignorewsamount=get('ignore_space_change', 'ignorewsamount'),
-        ignoreblanklines=get('ignore_blank_lines', 'ignoreblanklines'),
-        context=get('unified', getter=ui.config))
-
 def updatedir(ui, repo, patches, similarity=0):
     '''Update dirstate after patch application according to metadata'''
     if not patches:
@@ -1240,8 +1239,7 @@
             if gp.op == 'ADD' and not os.path.exists(dst):
                 flags = (isexec and 'x' or '') + (islink and 'l' or '')
                 repo.wwrite(gp.path, '', flags)
-            elif gp.op != 'DELETE':
-                util.set_flags(dst, islink, isexec)
+            util.set_flags(dst, islink, isexec)
     cmdutil.addremove(repo, cfiles, similarity=similarity)
     files = patches.keys()
     files.extend([r for r in removes if r not in files])
@@ -1337,6 +1335,10 @@
             try:
                 return internalpatch(patchname, ui, strip, cwd, files, eolmode)
             except NoHunks:
+                ui.warn(_('internal patcher failed\n'
+                          'please report details to '
+                          'http://mercurial.selenic.com/bts/\n'
+                          'or mercurial@selenic.com\n'))
                 patcher = (util.find_exe('gpatch') or util.find_exe('patch')
                            or 'patch')
                 ui.debug('no valid hunks found; trying with %r instead\n' %
@@ -1393,6 +1395,20 @@
 class GitDiffRequired(Exception):
     pass
 
+def diffopts(ui, opts=None, untrusted=False):
+    def get(key, name=None, getter=ui.configbool):
+        return ((opts and opts.get(key)) or
+                getter('diff', name or key, None, untrusted=untrusted))
+    return mdiff.diffopts(
+        text=opts and opts.get('text'),
+        git=get('git'),
+        nodates=get('nodates'),
+        showfunc=get('show_function', 'showfunc'),
+        ignorews=get('ignore_all_space', 'ignorews'),
+        ignorewsamount=get('ignore_space_change', 'ignorewsamount'),
+        ignoreblanklines=get('ignore_blank_lines', 'ignoreblanklines'),
+        context=get('unified', getter=ui.config))
+
 def diff(repo, node1=None, node2=None, match=None, changes=None, opts=None,
          losedatafn=None):
     '''yields diff of changes to files between two nodes, or node and
@@ -1465,6 +1481,43 @@
     else:
         return difffn(opts, None)
 
+def difflabel(func, *args, **kw):
+    '''yields 2-tuples of (output, label) based on the output of func()'''
+    prefixes = [('diff', 'diff.diffline'),
+                ('copy', 'diff.extended'),
+                ('rename', 'diff.extended'),
+                ('old', 'diff.extended'),
+                ('new', 'diff.extended'),
+                ('deleted', 'diff.extended'),
+                ('---', 'diff.file_a'),
+                ('+++', 'diff.file_b'),
+                ('@@', 'diff.hunk'),
+                ('-', 'diff.deleted'),
+                ('+', 'diff.inserted')]
+
+    for chunk in func(*args, **kw):
+        lines = chunk.split('\n')
+        for i, line in enumerate(lines):
+            if i != 0:
+                yield ('\n', '')
+            stripline = line
+            if line and line[0] in '+-':
+                # highlight trailing whitespace, but only in changed lines
+                stripline = line.rstrip()
+            for prefix, label in prefixes:
+                if stripline.startswith(prefix):
+                    yield (stripline, label)
+                    break
+            else:
+                yield (line, '')
+            if line != stripline:
+                yield (line[len(stripline):], 'diff.trailingwhitespace')
+
+def diffui(*args, **kw):
+    '''like diff(), but yields 2-tuples of (output, label) for ui.write()'''
+    return difflabel(diff, *args, **kw)
+
+
 def _addmodehdr(header, omode, nmode):
     if omode != nmode:
         header.append('old mode %s\n' % omode)
@@ -1568,47 +1621,6 @@
             if text:
                 yield text
 
-def export(repo, revs, template='hg-%h.patch', fp=None, switch_parent=False,
-           opts=None):
-    '''export changesets as hg patches.'''
-
-    total = len(revs)
-    revwidth = max([len(str(rev)) for rev in revs])
-
-    def single(rev, seqno, fp):
-        ctx = repo[rev]
-        node = ctx.node()
-        parents = [p.node() for p in ctx.parents() if p]
-        branch = ctx.branch()
-        if switch_parent:
-            parents.reverse()
-        prev = (parents and parents[0]) or nullid
-
-        if not fp:
-            fp = cmdutil.make_file(repo, template, node, total=total,
-                                   seqno=seqno, revwidth=revwidth,
-                                   mode='ab')
-        if fp != sys.stdout and hasattr(fp, 'name'):
-            repo.ui.note("%s\n" % fp.name)
-
-        fp.write("# HG changeset patch\n")
-        fp.write("# User %s\n" % ctx.user())
-        fp.write("# Date %d %d\n" % ctx.date())
-        if branch and (branch != 'default'):
-            fp.write("# Branch %s\n" % branch)
-        fp.write("# Node ID %s\n" % hex(node))
-        fp.write("# Parent  %s\n" % hex(prev))
-        if len(parents) > 1:
-            fp.write("# Parent  %s\n" % hex(parents[1]))
-        fp.write(ctx.description().rstrip())
-        fp.write("\n\n")
-
-        for chunk in diff(repo, prev, node, opts=opts):
-            fp.write(chunk)
-
-    for seqno, rev in enumerate(revs):
-        single(rev, seqno + 1, fp)
-
 def diffstatdata(lines):
     filename, adds, removes = None, 0, 0
     for line in lines:
@@ -1676,3 +1688,22 @@
                       % (len(stats), totaladds, totalremoves))
 
     return ''.join(output)
+
+def diffstatui(*args, **kw):
+    '''like diffstat(), but yields 2-tuples of (output, label) for
+    ui.write()
+    '''
+
+    for line in diffstat(*args, **kw).splitlines():
+        if line and line[-1] in '+-':
+            name, graph = line.rsplit(' ', 1)
+            yield (name + ' ', '')
+            m = re.search(r'\++', graph)
+            if m:
+                yield (m.group(0), 'diffstat.inserted')
+            m = re.search(r'-+', graph)
+            if m:
+                yield (m.group(0), 'diffstat.deleted')
+        else:
+            yield (line, '')
+        yield ('\n', '')
--- a/mercurial/posix.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/posix.py	Tue May 11 17:03:44 2010 -0500
@@ -7,7 +7,7 @@
 
 from i18n import _
 import osutil
-import os, sys, errno, stat, getpass, pwd, grp, fcntl
+import os, sys, errno, stat, getpass, pwd, grp
 
 posixfile = open
 nulldev = '/dev/null'
@@ -118,6 +118,7 @@
     return st1.st_dev == st2.st_dev
 
 if sys.platform == 'darwin':
+    import fcntl # only needed on darwin, missing on jython
     def realpath(path):
         '''
         Returns the true, canonical file system path equivalent to the given
@@ -258,6 +259,12 @@
     except KeyError:
         return str(gid)
 
+def groupmembers(name):
+    """Return the list of members of the group with the given
+    name, KeyError if the group does not exist.
+    """
+    return list(grp.getgrnam(name).gr_mem)
+
 def spawndetached(args):
     return os.spawnvp(os.P_NOWAIT | getattr(os, 'P_DETACH', 0),
                       args[0], args)
--- a/mercurial/pure/mpatch.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/pure/mpatch.py	Tue May 11 17:03:44 2010 -0500
@@ -112,7 +112,7 @@
         outlen += length
 
     if bin != binend:
-        raise Exception("patch cannot be decoded")
+        raise ValueError("patch cannot be decoded")
 
     outlen += orig - last
     return outlen
--- a/mercurial/pure/osutil.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/pure/osutil.py	Tue May 11 17:03:44 2010 -0500
@@ -6,25 +6,25 @@
 # GNU General Public License version 2 or any later version.
 
 import os
-import stat as _stat
+import stat as statmod
 
 posixfile = open
 
 def _mode_to_kind(mode):
-    if _stat.S_ISREG(mode):
-        return _stat.S_IFREG
-    if _stat.S_ISDIR(mode):
-        return _stat.S_IFDIR
-    if _stat.S_ISLNK(mode):
-        return _stat.S_IFLNK
-    if _stat.S_ISBLK(mode):
-        return _stat.S_IFBLK
-    if _stat.S_ISCHR(mode):
-        return _stat.S_IFCHR
-    if _stat.S_ISFIFO(mode):
-        return _stat.S_IFIFO
-    if _stat.S_ISSOCK(mode):
-        return _stat.S_IFSOCK
+    if statmod.S_ISREG(mode):
+        return statmod.S_IFREG
+    if statmod.S_ISDIR(mode):
+        return statmod.S_IFDIR
+    if statmod.S_ISLNK(mode):
+        return statmod.S_IFLNK
+    if statmod.S_ISBLK(mode):
+        return statmod.S_IFBLK
+    if statmod.S_ISCHR(mode):
+        return statmod.S_IFCHR
+    if statmod.S_ISFIFO(mode):
+        return statmod.S_IFIFO
+    if statmod.S_ISSOCK(mode):
+        return statmod.S_IFSOCK
     return mode
 
 def listdir(path, stat=False, skip=None):
@@ -49,7 +49,7 @@
     names.sort()
     for fn in names:
         st = os.lstat(prefix + fn)
-        if fn == skip and _stat.S_ISDIR(st.st_mode):
+        if fn == skip and statmod.S_ISDIR(st.st_mode):
             return []
         if stat:
             result.append((fn, _mode_to_kind(st.st_mode), st))
--- a/mercurial/repair.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/repair.py	Tue May 11 17:03:44 2010 -0500
@@ -114,7 +114,7 @@
 
     mfst = repo.manifest
 
-    tr = repo.transaction()
+    tr = repo.transaction("strip")
     offset = len(tr.entries)
 
     tr.startgroup()
--- a/mercurial/revlog.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/revlog.py	Tue May 11 17:03:44 2010 -0500
@@ -444,7 +444,10 @@
         i = ''
         try:
             f = self.opener(self.indexfile)
-            i = f.read(_prereadsize)
+            if "nonlazy" in getattr(self.opener, 'options', {}):
+                i = f.read()
+            else:
+                i = f.read(_prereadsize)
             if len(i) > 0:
                 v = struct.unpack(versionformat, i[:4])[0]
         except IOError, inst:
@@ -848,6 +851,32 @@
                 c.append(self.node(r))
         return c
 
+    def descendant(self, start, end):
+        for i in self.descendants(start):
+            if i == end:
+                return True
+            elif i > end:
+                break
+        return False
+
+    def ancestor(self, a, b):
+        """calculate the least common ancestor of nodes a and b"""
+
+        # fast path, check if it is a descendant
+        a, b = self.rev(a), self.rev(b)
+        start, end = sorted((a, b))
+        if self.descendant(start, end):
+            return self.node(start)
+
+        def parents(rev):
+            return [p for p in self.parentrevs(rev) if p != nullrev]
+
+        c = ancestor.ancestor(a, b, parents)
+        if c is None:
+            return nullid
+
+        return self.node(c)
+
     def _match(self, id):
         if isinstance(id, (long, int)):
             # rev
@@ -1122,32 +1151,6 @@
             self._cache = (node, curr, text)
         return node
 
-    def descendant(self, start, end):
-        for i in self.descendants(start):
-            if i == end:
-                return True
-            elif i > end:
-                break
-        return False
-
-    def ancestor(self, a, b):
-        """calculate the least common ancestor of nodes a and b"""
-
-        # fast path, check if it is a descendant
-        a, b = self.rev(a), self.rev(b)
-        start, end = sorted((a, b))
-        if self.descendant(start, end):
-            return self.node(start)
-
-        def parents(rev):
-            return [p for p in self.parentrevs(rev) if p != nullrev]
-
-        c = ancestor.ancestor(a, b, parents)
-        if c is None:
-            return nullid
-
-        return self.node(c)
-
     def group(self, nodelist, lookup, infocollect=None):
         """Calculate a delta group, yielding a sequence of changegroup chunks
         (strings).
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial/similar.py	Tue May 11 17:03:44 2010 -0500
@@ -0,0 +1,103 @@
+# similar.py - mechanisms for finding similar files
+#
+# Copyright 2005-2007 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 i18n import _
+import util
+import mdiff
+import bdiff
+
+def _findexactmatches(repo, added, removed):
+    '''find renamed files that have no changes
+
+    Takes a list of new filectxs and a list of removed filectxs, and yields
+    (before, after) tuples of exact matches.
+    '''
+    numfiles = len(added) + len(removed)
+
+    # Get hashes of removed files.
+    hashes = {}
+    for i, fctx in enumerate(removed):
+        repo.ui.progress(_('searching for exact renames'), i, total=numfiles)
+        h = util.sha1(fctx.data()).digest()
+        hashes[h] = fctx
+
+    # For each added file, see if it corresponds to a removed file.
+    for i, fctx in enumerate(added):
+        repo.ui.progress(_('searching for exact renames'), i + len(removed),
+                total=numfiles)
+        h = util.sha1(fctx.data()).digest()
+        if h in hashes:
+            yield (hashes[h], fctx)
+
+    # Done
+    repo.ui.progress(_('searching for exact renames'), None)
+
+def _findsimilarmatches(repo, added, removed, threshold):
+    '''find potentially renamed files based on similar file content
+
+    Takes a list of new filectxs and a list of removed filectxs, and yields
+    (before, after, score) tuples of partial matches.
+    '''
+    copies = {}
+    for i, r in enumerate(removed):
+        repo.ui.progress(_('searching for similar files'), i, total=len(removed))
+
+        # lazily load text
+        @util.cachefunc
+        def data():
+            orig = r.data()
+            return orig, mdiff.splitnewlines(orig)
+
+        def score(text):
+            orig, lines = data()
+            # bdiff.blocks() returns blocks of matching lines
+            # count the number of bytes in each
+            equal = 0
+            matches = bdiff.blocks(text, orig)
+            for x1, x2, y1, y2 in matches:
+                for line in lines[y1:y2]:
+                    equal += len(line)
+
+            lengths = len(text) + len(orig)
+            return equal * 2.0 / lengths
+
+        for a in added:
+            bestscore = copies.get(a, (None, threshold))[1]
+            myscore = score(a.data())
+            if myscore >= bestscore:
+                copies[a] = (r, myscore)
+    repo.ui.progress(_('searching'), None)
+
+    for dest, v in copies.iteritems():
+        source, score = v
+        yield source, dest, score
+
+def findrenames(repo, added, removed, threshold):
+    '''find renamed files -- yields (before, after, score) tuples'''
+    parentctx = repo['.']
+    workingctx = repo[None]
+
+    # Zero length files will be frequently unrelated to each other, and
+    # tracking the deletion/addition of such a file will probably cause more
+    # harm than good. We strip them out here to avoid matching them later on.
+    addedfiles = set([workingctx[fp] for fp in added
+            if workingctx[fp].size() > 0])
+    removedfiles = set([parentctx[fp] for fp in removed
+            if fp in parentctx and parentctx[fp].size() > 0])
+
+    # Find exact matches.
+    for (a, b) in _findexactmatches(repo,
+            sorted(addedfiles), sorted(removedfiles)):
+        addedfiles.remove(b)
+        yield (a.path(), b.path(), 1.0)
+
+    # If the user requested similar files to be matched, search for them also.
+    if threshold < 1.0:
+        for (a, b, score) in _findsimilarmatches(repo,
+                sorted(addedfiles), sorted(removedfiles), threshold):
+            yield (a.path(), b.path(), score)
+
--- a/mercurial/sshrepo.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/sshrepo.py	Tue May 11 17:03:44 2010 -0500
@@ -217,6 +217,10 @@
         return self.do_cmd("changegroupsubset", bases=bases, heads=heads)
 
     def unbundle(self, cg, heads, source):
+        '''Send cg (a readable file-like object representing the
+        changegroup to push, typically a chunkbuffer object) to the
+        remote server as a bundle. Return an integer indicating the
+        result of the push (see localrepository.addchangegroup()).'''
         d = self.call("unbundle", heads=' '.join(map(hex, heads)))
         if d:
             # remote may send "unsynced changes"
@@ -242,6 +246,9 @@
             self.abort(error.ResponseError(_("unexpected response:"), r))
 
     def addchangegroup(self, cg, source, url):
+        '''Send a changegroup to the remote server.  Return an integer
+        similar to unbundle(). DEPRECATED, since it requires locking the
+        remote.'''
         d = self.call("addchangegroup")
         if d:
             self.abort(error.RepoError(_("push refused: %s") % d))
--- a/mercurial/statichttprepo.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/statichttprepo.py	Tue May 11 17:03:44 2010 -0500
@@ -77,6 +77,7 @@
             return httprangereader(f, urlopener)
         return o
 
+    opener.options = {'nonlazy': 1}
     return opener
 
 class statichttprepository(localrepo.localrepository):
--- a/mercurial/streamclone.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/streamclone.py	Tue May 11 17:03:44 2010 -0500
@@ -6,7 +6,6 @@
 # GNU General Public License version 2 or any later version.
 
 import util, error
-from i18n import _
 
 from mercurial import store
 
--- a/mercurial/subrepo.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/subrepo.py	Tue May 11 17:03:44 2010 -0500
@@ -5,7 +5,7 @@
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 
-import errno, os, re, xml.dom.minidom, shutil
+import errno, os, re, xml.dom.minidom, shutil, urlparse, posixpath
 from i18n import _
 import config, util, node, error
 hg = None
@@ -126,6 +126,14 @@
     # record merged .hgsubstate
     writestate(repo, sm)
 
+def relpath(sub):
+    if not hasattr(sub, '_repo'):
+        return sub._path
+    parent = sub._repo
+    while hasattr(parent, '_subparent'):
+        parent = parent._subparent
+    return sub._repo.root[len(parent.root)+1:]
+
 def _abssource(repo, push=False):
     if hasattr(repo, '_subparent'):
         source = repo._subsource
@@ -135,8 +143,12 @@
         if '://' in parent:
             if parent[-1] == '/':
                 parent = parent[:-1]
-            return parent + '/' + source
-        return os.path.join(parent, repo._subsource)
+            r = urlparse.urlparse(parent + '/' + source)
+            r = urlparse.urlunparse((r[0], r[1],
+                                     posixpath.normpath(r[2]),
+                                     r[3], r[4], r[5]))
+            return r
+        return posixpath.normpath(os.path.join(parent, repo._subsource))
     if push and repo.ui.config('paths', 'default-push'):
         return repo.ui.config('paths', 'default-push', repo.root)
     return repo.ui.config('paths', 'default', repo.root)
@@ -210,7 +222,7 @@
         return w.dirty() # working directory changed
 
     def commit(self, text, user, date):
-        self._repo.ui.debug("committing subrepo %s\n" % self._path)
+        self._repo.ui.debug("committing subrepo %s\n" % relpath(self))
         n = self._repo.commit(text, user, date)
         if not n:
             return self._repo['.'].hex() # different version checked out
@@ -219,7 +231,7 @@
     def remove(self):
         # we can't fully delete the repository as it may contain
         # local-only history
-        self._repo.ui.note(_('removing subrepo %s\n') % self._path)
+        self._repo.ui.note(_('removing subrepo %s\n') % relpath(self))
         hg.clean(self._repo, node.nullid, False)
 
     def _get(self, state):
@@ -228,8 +240,9 @@
             self._repo.lookup(revision)
         except error.RepoError:
             self._repo._subsource = source
-            self._repo.ui.status(_('pulling subrepo %s\n') % self._path)
             srcurl = _abssource(self._repo)
+            self._repo.ui.status(_('pulling subrepo %s from %s\n')
+                                 % (relpath(self), srcurl))
             other = hg.repository(self._repo.ui, srcurl)
             self._repo.pull(other)
 
@@ -245,12 +258,12 @@
         dst = self._repo[state[1]]
         anc = dst.ancestor(cur)
         if anc == cur:
-            self._repo.ui.debug("updating subrepo %s\n" % self._path)
+            self._repo.ui.debug("updating subrepo %s\n" % relpath(self))
             hg.update(self._repo, state[1])
         elif anc == dst:
-            self._repo.ui.debug("skipping subrepo %s\n" % self._path)
+            self._repo.ui.debug("skipping subrepo %s\n" % relpath(self))
         else:
-            self._repo.ui.debug("merging subrepo %s\n" % self._path)
+            self._repo.ui.debug("merging subrepo %s\n" % relpath(self))
             hg.merge(self._repo, state[1], remind=False)
 
     def push(self, force):
@@ -261,8 +274,9 @@
             if not c.sub(s).push(force):
                 return False
 
-        self._repo.ui.status(_('pushing subrepo %s\n') % self._path)
         dsturl = _abssource(self._repo, True)
+        self._repo.ui.status(_('pushing subrepo %s to %s\n') %
+            (relpath(self), dsturl))
         other = hg.repository(self._repo.ui, dsturl)
         return self._repo.push(other, force)
 
--- a/mercurial/tags.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/tags.py	Tue May 11 17:03:44 2010 -0500
@@ -339,4 +339,3 @@
         cachefile.write("%s %s\n" % (hex(node), name))
 
     cachefile.rename()
-    cachefile.close()
--- a/mercurial/templatefilters.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/templatefilters.py	Tue May 11 17:03:44 2010 -0500
@@ -14,15 +14,13 @@
         return "".join([stringify(t) for t in thing if t is not None])
     return str(thing)
 
-agescales = [("second", 1),
-             ("minute", 60),
-             ("hour", 3600),
-             ("day", 3600 * 24),
+agescales = [("year", 3600 * 24 * 365),
+             ("month", 3600 * 24 * 30),
              ("week", 3600 * 24 * 7),
-             ("month", 3600 * 24 * 30),
-             ("year", 3600 * 24 * 365)]
-
-agescales.reverse()
+             ("day", 3600 * 24),
+             ("hour", 3600),
+             ("minute", 60),
+             ("second", 1)]
 
 def age(date):
     '''turn a (timestamp, tzoff) tuple into an age string.'''
--- a/mercurial/templater.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/templater.py	Tue May 11 17:03:44 2010 -0500
@@ -6,12 +6,30 @@
 # GNU General Public License version 2 or any later version.
 
 from i18n import _
-import re, sys, os
+import sys, os
 import util, config, templatefilters
 
 path = ['templates', '../templates']
 stringify = templatefilters.stringify
 
+def _flatten(thing):
+    '''yield a single stream from a possibly nested set of iterators'''
+    if isinstance(thing, str):
+        yield thing
+    elif not hasattr(thing, '__iter__'):
+        if i is not None:
+            yield str(thing)
+    else:
+        for i in thing:
+            if isinstance(i, str):
+                yield i
+            elif not hasattr(i, '__iter__'):
+                if i is not None:
+                    yield str(i)
+            elif i is not None:
+                for j in _flatten(i):
+                    yield j
+
 def parsestring(s, quoted=True):
     '''parse a string using simple c-like syntax.
     string must be in quotes if quoted is True.'''
@@ -42,97 +60,107 @@
     filter uses function to transform value. syntax is
     {key|filter1|filter2|...}.'''
 
-    template_re = re.compile(r'{([\w\|%]+)}')
+    def __init__(self, loader, filters={}, defaults={}):
+        self._loader = loader
+        self._filters = filters
+        self._defaults = defaults
+        self._cache = {}
 
-    def __init__(self, loader, filters={}, defaults={}):
-        self.loader = loader
-        self.filters = filters
-        self.defaults = defaults
-        self.cache = {}
+    def process(self, t, mapping):
+        '''Perform expansion. t is name of map element to expand.
+        mapping contains added elements for use during expansion. Is a
+        generator.'''
+        return _flatten(self._process(self._load(t), mapping))
+
+    def _load(self, t):
+        '''load, parse, and cache a template'''
+        if t not in self._cache:
+            self._cache[t] = self._parse(self._loader(t))
+        return self._cache[t]
 
-    def process(self, t, map):
-        '''Perform expansion. t is name of map element to expand. map contains
-        added elements for use during expansion. Is a generator.'''
-        tmpl = self.loader(t)
-        iters = [self._process(tmpl, map)]
-        while iters:
-            try:
-                item = iters[0].next()
-            except StopIteration:
-                iters.pop(0)
-                continue
-            if isinstance(item, str):
-                yield item
-            elif item is None:
-                yield ''
-            elif hasattr(item, '__iter__'):
-                iters.insert(0, iter(item))
-            else:
-                yield str(item)
+    def _get(self, mapping, key):
+        v = mapping.get(key)
+        if v is None:
+            v = self._defaults.get(key, '')
+        if hasattr(v, '__call__'):
+            v = v(**mapping)
+        return v
 
-    def _format(self, expr, get, map):
-        key, format = expr.split('%')
-        v = get(key)
+    def _filter(self, mapping, parts):
+        filters, val = parts
+        x = self._get(mapping, val)
+        for f in filters:
+            x = f(x)
+        return x
+
+    def _format(self, mapping, args):
+        key, parsed = args
+        v = self._get(mapping, key)
         if not hasattr(v, '__iter__'):
-            raise SyntaxError(_("error expanding '%s%%%s'") % (key, format))
-        lm = map.copy()
+            raise SyntaxError(_("error expanding '%s%%%s'")
+                              % (key, format))
+        lm = mapping.copy()
         for i in v:
             if isinstance(i, dict):
                 lm.update(i)
-                yield self.process(format, lm)
+                yield self._process(parsed, lm)
             else:
                 # v is not an iterable of dicts, this happen when 'key'
                 # has been fully expanded already and format is useless.
                 # If so, return the expanded value.
                 yield i
 
-    def _filter(self, expr, get, map):
-        if expr not in self.cache:
-            parts = expr.split('|')
-            val = parts[0]
-            try:
-                filters = [self.filters[f] for f in parts[1:]]
-            except KeyError, i:
-                raise SyntaxError(_("unknown filter '%s'") % i[0])
-            def apply(get):
-                x = get(val)
-                for f in filters:
-                    x = f(x)
-                return x
-            self.cache[expr] = apply
-        return self.cache[expr](get)
+    def _parse(self, tmpl):
+        '''preparse a template'''
+        parsed = []
+        pos, stop = 0, len(tmpl)
+        while pos < stop:
+            n = tmpl.find('{', pos)
+            if n < 0:
+                parsed.append((None, tmpl[pos:stop]))
+                break
+            if n > 0 and tmpl[n - 1] == '\\':
+                # escaped
+                parsed.append((None, tmpl[pos:n - 1] + "{"))
+                pos = n + 1
+                continue
+            if n > pos:
+                parsed.append((None, tmpl[pos:n]))
 
-    def _process(self, tmpl, map):
-        '''Render a template. Returns a generator.'''
-
-        def get(key):
-            v = map.get(key)
-            if v is None:
-                v = self.defaults.get(key, '')
-            if hasattr(v, '__call__'):
-                v = v(**map)
-            return v
-
-        while tmpl:
-            m = self.template_re.search(tmpl)
-            if not m:
-                yield tmpl
+            pos = n
+            n = tmpl.find('}', pos)
+            if n < 0:
+                # no closing
+                parsed.append((None, tmpl[pos:stop]))
                 break
 
-            start, end = m.span(0)
-            variants = m.groups()
-            expr = variants[0] or variants[1]
-
-            if start:
-                yield tmpl[:start]
-            tmpl = tmpl[end:]
+            expr = tmpl[pos + 1:n]
+            pos = n + 1
 
             if '%' in expr:
-                yield self._format(expr, get, map)
+                key, t = expr.split('%')
+                parsed.append((self._format, (key.strip(),
+                                              self._load(t.strip()))))
             elif '|' in expr:
-                yield self._filter(expr, get, map)
+                parts = expr.split('|')
+                val = parts[0].strip()
+                try:
+                    filters = [self._filters[f.strip()] for f in parts[1:]]
+                except KeyError, i:
+                    raise SyntaxError(_("unknown filter '%s'") % i[0])
+                parsed.append((self._filter, (filters, val)))
             else:
-                yield get(expr)
+                parsed.append((self._get, expr.strip()))
+
+        return parsed
+
+    def _process(self, parsed, mapping):
+        '''Render a template. Returns a generator.'''
+        for f, e in parsed:
+            if f:
+                yield f(mapping, e)
+            else:
+                yield e
 
 engines = {'default': engine}
 
@@ -188,14 +216,14 @@
                               (self.map[t][1], inst.args[1]))
         return self.cache[t]
 
-    def __call__(self, t, **map):
+    def __call__(self, t, **mapping):
         ttype = t in self.map and self.map[t][0] or 'default'
         proc = self.engines.get(ttype)
         if proc is None:
             proc = engines[ttype](self.load, self.filters, self.defaults)
             self.engines[ttype] = proc
 
-        stream = proc.process(t, map)
+        stream = proc.process(t, mapping)
         if self.minchunk:
             stream = util.increasingchunks(stream, min=self.minchunk,
                                            max=self.maxchunk)
--- a/mercurial/templates/gitweb/graph.tmpl	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/templates/gitweb/graph.tmpl	Tue May 11 17:03:44 2010 -0500
@@ -50,7 +50,7 @@
 var graph = new Graph();
 graph.scale({bg_height});
 
-graph.edge = function(x0, y0, x1, y1, color) {
+graph.edge = function(x0, y0, x1, y1, color) \{
 	
 	this.setColor(color, 0.0, 0.65);
 	this.ctx.beginPath();
@@ -65,7 +65,7 @@
 revlink += '</span> _TAGS';
 revlink += '<span class="info">_DATE, by _USER</span></li>';
 
-graph.vertex = function(x, y, color, parity, cur) {
+graph.vertex = function(x, y, color, parity, cur) \{
 	
 	this.ctx.beginPath();
 	color = this.setColor(color, 0.25, 0.75);
@@ -84,17 +84,17 @@
 	item = item.replace(/_DATE/, cur[5]);
 	
 	var tagspan = '';
-	if (cur[7].length || (cur[6][0] != 'default' || cur[6][1])) {
+	if (cur[7].length || (cur[6][0] != 'default' || cur[6][1])) \{
 		tagspan = '<span class="logtags">';
-		if (cur[6][1]) {
+		if (cur[6][1]) \{
 			tagspan += '<span class="branchtag" title="' + cur[6][0] + '">';
 			tagspan += cur[6][0] + '</span> ';
-		} else if (!cur[6][1] && cur[6][0] != 'default') {
+		} else if (!cur[6][1] && cur[6][0] != 'default') \{
 			tagspan += '<span class="inbranchtag" title="' + cur[6][0] + '">';
 			tagspan += cur[6][0] + '</span> ';
 		}
-		if (cur[7].length) {
-			for (var t in cur[7]) {
+		if (cur[7].length) \{
+			for (var t in cur[7]) \{
 				var tag = cur[7][t];
 				tagspan += '<span class="tagtag">' + tag + '</span> ';
 			}
--- a/mercurial/templates/monoblue/graph.tmpl	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/templates/monoblue/graph.tmpl	Tue May 11 17:03:44 2010 -0500
@@ -48,7 +48,7 @@
     var graph = new Graph();
     graph.scale({bg_height});
 
-    graph.edge = function(x0, y0, x1, y1, color) {
+    graph.edge = function(x0, y0, x1, y1, color) \{
 
         this.setColor(color, 0.0, 0.65);
         this.ctx.beginPath();
@@ -62,7 +62,7 @@
     revlink += '<a href="{url}rev/_NODEID{sessionvars%urlparameter}" title="_NODEID">_DESC</a>';
     revlink += '</span>_TAGS<span class="info">_DATE, by _USER</span></li>';
 
-    graph.vertex = function(x, y, color, parity, cur) {
+    graph.vertex = function(x, y, color, parity, cur) \{
 
         this.ctx.beginPath();
         color = this.setColor(color, 0.25, 0.75);
@@ -81,17 +81,17 @@
         item = item.replace(/_DATE/, cur[5]);
 
         var tagspan = '';
-        if (cur[7].length || (cur[6][0] != 'default' || cur[6][1])) {
+        if (cur[7].length || (cur[6][0] != 'default' || cur[6][1])) \{
             tagspan = '<span class="logtags">';
-            if (cur[6][1]) {
+            if (cur[6][1]) \{
                 tagspan += '<span class="branchtag" title="' + cur[6][0] + '">';
                 tagspan += cur[6][0] + '</span> ';
-            } else if (!cur[6][1] && cur[6][0] != 'default') {
+            } else if (!cur[6][1] && cur[6][0] != 'default') \{
                 tagspan += '<span class="inbranchtag" title="' + cur[6][0] + '">';
                 tagspan += cur[6][0] + '</span> ';
             }
-            if (cur[7].length) {
-                for (var t in cur[7]) {
+            if (cur[7].length) \{
+                for (var t in cur[7]) \{
                     var tag = cur[7][t];
                     tagspan += '<span class="tagtag">' + tag + '</span> ';
                 }
--- a/mercurial/templates/paper/graph.tmpl	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/templates/paper/graph.tmpl	Tue May 11 17:03:44 2010 -0500
@@ -59,7 +59,7 @@
 var graph = new Graph();
 graph.scale({bg_height});
 
-graph.edge = function(x0, y0, x1, y1, color) {
+graph.edge = function(x0, y0, x1, y1, color) \{
 	
 	this.setColor(color, 0.0, 0.65);
 	this.ctx.beginPath();
@@ -73,7 +73,7 @@
 revlink += '<a href="{url}rev/_NODEID{sessionvars%urlparameter}" title="_NODEID">_DESC</a>';
 revlink += '</span>_TAGS<span class="info">_DATE, by _USER</span></li>';
 
-graph.vertex = function(x, y, color, parity, cur) {
+graph.vertex = function(x, y, color, parity, cur) \{
 	
 	this.ctx.beginPath();
 	color = this.setColor(color, 0.25, 0.75);
@@ -92,17 +92,17 @@
 	item = item.replace(/_DATE/, cur[5]);
 
 	var tagspan = '';
-	if (cur[7].length || (cur[6][0] != 'default' || cur[6][1])) {
+	if (cur[7].length || (cur[6][0] != 'default' || cur[6][1])) \{
 		tagspan = '<span class="logtags">';
-		if (cur[6][1]) {
+		if (cur[6][1]) \{
 			tagspan += '<span class="branchhead" title="' + cur[6][0] + '">';
 			tagspan += cur[6][0] + '</span> ';
-		} else if (!cur[6][1] && cur[6][0] != 'default') {
+		} else if (!cur[6][1] && cur[6][0] != 'default') \{
 			tagspan += '<span class="branchname" title="' + cur[6][0] + '">';
 			tagspan += cur[6][0] + '</span> ';
 		}
-		if (cur[7].length) {
-			for (var t in cur[7]) {
+		if (cur[7].length) \{
+			for (var t in cur[7]) \{
 				var tag = cur[7][t];
 				tagspan += '<span class="tag">' + tag + '</span> ';
 			}
--- a/mercurial/templates/spartan/graph.tmpl	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/templates/spartan/graph.tmpl	Tue May 11 17:03:44 2010 -0500
@@ -43,7 +43,7 @@
 var graph = new Graph();
 graph.scale({bg_height});
 
-graph.edge = function(x0, y0, x1, y1, color) {
+graph.edge = function(x0, y0, x1, y1, color) \{
 	
 	this.setColor(color, 0.0, 0.65);
 	this.ctx.beginPath();
@@ -57,7 +57,7 @@
 revlink += '<a href="{url}rev/_NODEID{sessionvars%urlparameter}" title="_NODEID">_DESC</a>';
 revlink += '</span><span class="info">_DATE, by _USER</span></li>';
 
-graph.vertex = function(x, y, color, parity, cur) {
+graph.vertex = function(x, y, color, parity, cur) \{
 	
 	this.ctx.beginPath();
 	color = this.setColor(color, 0.25, 0.75);
--- a/mercurial/ui.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/ui.py	Tue May 11 17:03:44 2010 -0500
@@ -154,11 +154,83 @@
 
     def configlist(self, section, name, default=None, untrusted=False):
         """Return a list of comma/space separated strings"""
+
+        def _parse_plain(parts, s, offset):
+            whitespace = False
+            while offset < len(s) and (s[offset].isspace() or s[offset] == ','):
+                whitespace = True
+                offset += 1
+            if offset >= len(s):
+                return None, parts, offset
+            if whitespace:
+                parts.append('')
+            if s[offset] == '"' and not parts[-1]:
+                return _parse_quote, parts, offset + 1
+            elif s[offset] == '"' and parts[-1][-1] == '\\':
+                parts[-1] = parts[-1][:-1] + s[offset]
+                return _parse_plain, parts, offset + 1
+            parts[-1] += s[offset]
+            return _parse_plain, parts, offset + 1
+
+        def _parse_quote(parts, s, offset):
+            if offset < len(s) and s[offset] == '"': # ""
+                parts.append('')
+                offset += 1
+                while offset < len(s) and (s[offset].isspace() or
+                        s[offset] == ','):
+                    offset += 1
+                return _parse_plain, parts, offset
+
+            while offset < len(s) and s[offset] != '"':
+                if (s[offset] == '\\' and offset + 1 < len(s)
+                        and s[offset + 1] == '"'):
+                    offset += 1
+                    parts[-1] += '"'
+                else:
+                    parts[-1] += s[offset]
+                offset += 1
+
+            if offset >= len(s):
+                real_parts = _configlist(parts[-1])
+                if not real_parts:
+                    parts[-1] = '"'
+                else:
+                    real_parts[0] = '"' + real_parts[0]
+                    parts = parts[:-1]
+                    parts.extend(real_parts)
+                return None, parts, offset
+
+            offset += 1
+            while offset < len(s) and s[offset] in [' ', ',']:
+                offset += 1
+
+            if offset < len(s):
+                if offset + 1 == len(s) and s[offset] == '"':
+                    parts[-1] += '"'
+                    offset += 1
+                else:
+                    parts.append('')
+            else:
+                return None, parts, offset
+
+            return _parse_plain, parts, offset
+
+        def _configlist(s):
+            s = s.rstrip(' ,')
+            if not s:
+                return None
+            parser, parts, offset = _parse_plain, [''], 0
+            while parser:
+                parser, parts, offset = parser(parts, s, offset)
+            return parts
+
         result = self.config(section, name, untrusted=untrusted)
         if result is None:
             result = default or []
         if isinstance(result, basestring):
-            result = result.replace(",", " ").split()
+            result = _configlist(result)
+            if result is None:
+                result = default or []
         return result
 
     def has_section(self, section, untrusted=False):
@@ -239,17 +311,42 @@
     def pushbuffer(self):
         self._buffers.append([])
 
-    def popbuffer(self):
+    def popbuffer(self, labeled=False):
+        '''pop the last buffer and return the buffered output
+
+        If labeled is True, any labels associated with buffered
+        output will be handled. By default, this has no effect
+        on the output returned, but extensions and GUI tools may
+        handle this argument and returned styled output. If output
+        is being buffered so it can be captured and parsed or
+        processed, labeled should not be set to True.
+        '''
         return "".join(self._buffers.pop())
 
-    def write(self, *args):
+    def write(self, *args, **opts):
+        '''write args to output
+
+        By default, this method simply writes to the buffer or stdout,
+        but extensions or GUI tools may override this method,
+        write_err(), popbuffer(), and label() to style output from
+        various parts of hg.
+
+        An optional keyword argument, "label", can be passed in.
+        This should be a string containing label names separated by
+        space. Label names take the form of "topic.type". For example,
+        ui.debug() issues a label of "ui.debug".
+
+        When labeling output for a specific command, a label of
+        "cmdname.type" is recommended. For example, status issues
+        a label of "status.modified" for modified files.
+        '''
         if self._buffers:
             self._buffers[-1].extend([str(a) for a in args])
         else:
             for a in args:
                 sys.stdout.write(str(a))
 
-    def write_err(self, *args):
+    def write_err(self, *args, **opts):
         try:
             if not getattr(sys.stdout, 'closed', False):
                 sys.stdout.flush()
@@ -335,17 +432,37 @@
             return getpass.getpass(prompt or _('password: '))
         except EOFError:
             raise util.Abort(_('response expected'))
-    def status(self, *msg):
+    def status(self, *msg, **opts):
+        '''write status message to output (if ui.quiet is False)
+
+        This adds an output label of "ui.status".
+        '''
         if not self.quiet:
-            self.write(*msg)
-    def warn(self, *msg):
-        self.write_err(*msg)
-    def note(self, *msg):
+            opts['label'] = opts.get('label', '') + ' ui.status'
+            self.write(*msg, **opts)
+    def warn(self, *msg, **opts):
+        '''write warning message to output (stderr)
+
+        This adds an output label of "ui.warning".
+        '''
+        opts['label'] = opts.get('label', '') + ' ui.warning'
+        self.write_err(*msg, **opts)
+    def note(self, *msg, **opts):
+        '''write note to output (if ui.verbose is True)
+
+        This adds an output label of "ui.note".
+        '''
         if self.verbose:
-            self.write(*msg)
-    def debug(self, *msg):
+            opts['label'] = opts.get('label', '') + ' ui.note'
+            self.write(*msg, **opts)
+    def debug(self, *msg, **opts):
+        '''write debug message to output (if ui.debugflag is True)
+
+        This adds an output label of "ui.debug".
+        '''
         if self.debugflag:
-            self.write(*msg)
+            opts['label'] = opts.get('label', '') + ' ui.debug'
+            self.write(*msg, **opts)
     def edit(self, text, user):
         (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt",
                                       text=True)
@@ -417,3 +534,15 @@
                      % (topic, item, pos, total, unit, pct))
         else:
             self.debug('%s:%s %s%s\n' % (topic, item, pos, unit))
+
+    def label(self, msg, label):
+        '''style msg based on supplied label
+
+        Like ui.write(), this just returns msg unchanged, but extensions
+        and GUI tools can override it to allow styling output without
+        writing it.
+
+        ui.write(s, 'label') is equivalent to
+        ui.write(ui.label(s, 'label')).
+        '''
+        return msg
--- a/mercurial/util.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/util.py	Tue May 11 17:03:44 2010 -0500
@@ -36,6 +36,13 @@
     _fastsha1 = sha1 = _sha1
     return _sha1(s)
 
+import __builtin__
+
+def fakebuffer(sliceable, offset=0):
+    return sliceable[offset:]
+if not hasattr(__builtin__, 'buffer'):
+    __builtin__.buffer = fakebuffer
+
 import subprocess
 closefds = os.name == 'posix'
 
--- a/mercurial/verify.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/verify.py	Tue May 11 17:03:44 2010 -0500
@@ -122,7 +122,7 @@
     checklog(cl, "changelog", 0)
     total = len(repo)
     for i in repo:
-        ui.progress(_('checking'), i, total=total)
+        ui.progress(_('changesets'), i, total=total)
         n = cl.node(i)
         checkentry(cl, i, n, seen, [i], "changelog")
 
@@ -133,14 +133,14 @@
                 filelinkrevs.setdefault(f, []).append(i)
         except Exception, inst:
             exc(i, _("unpacking changeset %s") % short(n), inst)
-    ui.progress(_('checking'), None)
+    ui.progress(_('changesets'), None)
 
     ui.status(_("checking manifests\n"))
     seen = {}
     checklog(mf, "manifest", 0)
     total = len(mf)
     for i in mf:
-        ui.progress(_('checking'), i, total=total)
+        ui.progress(_('manifests'), i, total=total)
         n = mf.node(i)
         lr = checkentry(mf, i, n, seen, mflinkrevs.get(n, []), "manifest")
         if n in mflinkrevs:
@@ -156,7 +156,7 @@
                     filenodes.setdefault(f, {}).setdefault(fn, lr)
         except Exception, inst:
             exc(lr, _("reading manifest delta %s") % short(n), inst)
-    ui.progress(_('checking'), None)
+    ui.progress(_('manifests'), None)
 
     ui.status(_("crosschecking files in changesets and manifests\n"))
 
--- a/mercurial/win32.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/win32.py	Tue May 11 17:03:44 2010 -0500
@@ -16,7 +16,7 @@
 import win32api
 
 import errno, os, sys, pywintypes, win32con, win32file, win32process
-import winerror, win32gui
+import winerror, win32gui, win32console
 import osutil, encoding
 from win32com.shell import shell, shellcon
 
@@ -189,3 +189,16 @@
 
     pid =  win32process.GetCurrentProcessId()
     win32gui.EnumWindows(callback, pid)
+
+def termwidth_():
+    try:
+        # Query stderr to avoid problems with redirections
+        screenbuf = win32console.GetStdHandle(win32console.STD_ERROR_HANDLE)
+        try:
+            window = screenbuf.GetConsoleScreenBufferInfo()['Window']
+            width = window.Right - window.Left
+            return width
+        finally:
+            screenbuf.Detach()
+    except pywintypes.error:
+        return 79
--- a/mercurial/windows.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/mercurial/windows.py	Tue May 11 17:03:44 2010 -0500
@@ -363,6 +363,10 @@
     # current line but on the new one. Keep room for it.
     return 79
 
+def groupmembers(name):
+    # Don't support groups on Windows for now
+    raise KeyError()
+
 try:
     # override functions with win32 versions if possible
     from win32 import *
--- a/setup.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/setup.py	Tue May 11 17:03:44 2010 -0500
@@ -37,7 +37,6 @@
 import tempfile
 from distutils.core import setup, Extension
 from distutils.dist import Distribution
-from distutils.command.install_data import install_data
 from distutils.command.build import build
 from distutils.command.build_py import build_py
 from distutils.spawn import spawn, find_executable
--- a/tests/get-with-headers.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/get-with-headers.py	Tue May 11 17:03:44 2010 -0500
@@ -3,7 +3,7 @@
 """This does HTTP GET requests given a host:port and path and returns
 a subset of the headers plus the body of the result."""
 
-import httplib, sys, re
+import httplib, sys
 
 try:
     import msvcrt, os
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/helpers.sh	Tue May 11 17:03:44 2010 -0500
@@ -0,0 +1,9 @@
+#/bin/sh
+
+hideport() { sed "s/localhost:$HGPORT/localhost:\$HGPORT/"; }
+
+repr() { python -c "import sys; print repr(sys.stdin.read()).replace('\\n', '\n')" }
+
+hidehex() { python -c 'import sys, re; print re.replace("\b[0-9A-Fa-f]{12,40}", "X" * 12)' }
+
+hidetmp() { sed "s/$HGTMP/\$HGTMP/"; }
\ No newline at end of file
--- a/tests/hghave	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/hghave	Tue May 11 17:03:44 2010 -0500
@@ -120,12 +120,12 @@
 def has_git():
     return matchoutput('git --version 2>&1', r'^git version')
 
-def has_rst2html():
-    for name in ('rst2html', 'rst2html.py'):
-        name = name + ' --version 2>&1'
-        if matchoutput(name, r'^rst2html(?:\.py)? \(Docutils'):
-            return True
-    return False
+def has_docutils():
+    try:
+        from docutils.core import publish_cmdline
+        return True
+    except ImportError:
+        return False
 
 def has_svn():
     return matchoutput('svn --version 2>&1', r'^svn, version') and \
@@ -198,7 +198,7 @@
     "outer-repo": (has_outer_repo, "outer repo"),
     "p4": (has_p4, "Perforce server and client"),
     "pygments": (has_pygments, "Pygments source highlighting library"),
-    "rst2html": (has_rst2html, "Docutils rst2html tool"),
+    "docutils": (has_docutils, "Docutils text processing library"),
     "svn": (has_svn, "subversion client and admin tools"),
     "svn-bindings": (has_svn_bindings, "subversion python bindings"),
     "symlink": (has_symlink, "symbolic links"),
--- a/tests/killdaemons.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/killdaemons.py	Tue May 11 17:03:44 2010 -0500
@@ -1,6 +1,6 @@
 #!/usr/bin/env python
 
-import os, sys, time, errno, signal
+import os, time, errno, signal
 
 # Kill off any leftover daemon processes
 try:
--- a/tests/run-tests.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/run-tests.py	Tue May 11 17:03:44 2010 -0500
@@ -46,9 +46,8 @@
 import errno
 import optparse
 import os
-import signal
+import shutil
 import subprocess
-import shutil
 import signal
 import sys
 import tempfile
@@ -70,6 +69,9 @@
 SKIPPED_PREFIX = 'skipped: '
 FAILED_PREFIX  = 'hghave check failed: '
 PYTHON = sys.executable
+IMPL_PATH = 'PYTHONPATH'
+if 'java' in sys.platform:
+    IMPL_PATH = 'JYTHONPATH'
 
 requiredtools = ["python", "diff", "grep", "unzip", "gunzip", "bunzip2", "sed"]
 
@@ -81,34 +83,43 @@
 
 def parseargs():
     parser = optparse.OptionParser("%prog [options] [tests]")
+
+    # keep these sorted
+    parser.add_option("--blacklist", action="append",
+        help="skip tests listed in the specified blacklist file")
     parser.add_option("-C", "--annotate", action="store_true",
         help="output files annotated with coverage")
     parser.add_option("--child", type="int",
         help="run as child process, summary to given fd")
     parser.add_option("-c", "--cover", action="store_true",
         help="print a test coverage report")
+    parser.add_option("-d", "--debug", action="store_true",
+        help="debug mode: write output of test scripts to console"
+             " rather than capturing and diff'ing it (disables timeout)")
     parser.add_option("-f", "--first", action="store_true",
         help="exit on the first test failure")
+    parser.add_option("--inotify", action="store_true",
+        help="enable inotify extension when running tests")
     parser.add_option("-i", "--interactive", action="store_true",
         help="prompt to accept changed output")
     parser.add_option("-j", "--jobs", type="int",
         help="number of jobs to run in parallel"
              " (default: $%s or %d)" % defaults['jobs'])
-    parser.add_option("-k", "--keywords",
-        help="run tests matching keywords")
     parser.add_option("--keep-tmpdir", action="store_true",
         help="keep temporary directory after running tests")
-    parser.add_option("--tmpdir", type="string",
-        help="run tests in the given temporary directory"
-             " (implies --keep-tmpdir)")
-    parser.add_option("-d", "--debug", action="store_true",
-        help="debug mode: write output of test scripts to console"
-             " rather than capturing and diff'ing it (disables timeout)")
-    parser.add_option("-R", "--restart", action="store_true",
-        help="restart at last error")
+    parser.add_option("-k", "--keywords",
+        help="run tests matching keywords")
+    parser.add_option("-l", "--local", action="store_true",
+        help="shortcut for --with-hg=<testdir>/../hg")
+    parser.add_option("-n", "--nodiff", action="store_true",
+        help="skip showing test changes")
     parser.add_option("-p", "--port", type="int",
         help="port on which servers should listen"
              " (default: $%s or %d)" % defaults['port'])
+    parser.add_option("--pure", action="store_true",
+        help="use pure Python code instead of C extensions")
+    parser.add_option("-R", "--restart", action="store_true",
+        help="restart at last error")
     parser.add_option("-r", "--retest", action="store_true",
         help="retest failed tests")
     parser.add_option("-S", "--noskips", action="store_true",
@@ -116,30 +127,29 @@
     parser.add_option("-t", "--timeout", type="int",
         help="kill errant tests after TIMEOUT seconds"
              " (default: $%s or %d)" % defaults['timeout'])
+    parser.add_option("--tmpdir", type="string",
+        help="run tests in the given temporary directory"
+             " (implies --keep-tmpdir)")
     parser.add_option("-v", "--verbose", action="store_true",
         help="output verbose messages")
-    parser.add_option("-n", "--nodiff", action="store_true",
-        help="skip showing test changes")
+    parser.add_option("--view", type="string",
+        help="external diff viewer")
     parser.add_option("--with-hg", type="string",
         metavar="HG",
         help="test using specified hg script rather than a "
              "temporary installation")
-    parser.add_option("--local", action="store_true",
-        help="shortcut for --with-hg=<testdir>/../hg")
-    parser.add_option("--pure", action="store_true",
-        help="use pure Python code instead of C extensions")
     parser.add_option("-3", "--py3k-warnings", action="store_true",
         help="enable Py3k warnings on Python 2.6+")
-    parser.add_option("--inotify", action="store_true",
-        help="enable inotify extension when running tests")
-    parser.add_option("--blacklist", action="append",
-        help="skip tests listed in the specified blacklist file")
 
     for option, default in defaults.items():
         defaults[option] = int(os.environ.get(*default))
     parser.set_defaults(**defaults)
     (options, args) = parser.parse_args()
 
+    # jython is always pure
+    if 'java' in sys.platform or '__pypy__' in sys.modules:
+        options.pure = True
+
     if options.with_hg:
         if not (os.path.isfile(options.with_hg) and
                 os.access(options.with_hg, os.X_OK)):
@@ -565,6 +575,7 @@
     mark = '.'
 
     skipped = (ret == SKIPPED_STATUS)
+
     # If we're not in --debug mode and reference output file exists,
     # check test output against it.
     if options.debug:
@@ -576,6 +587,13 @@
     else:
         refout = []
 
+    if (ret != 0 or out != refout) and not skipped and not options.debug:
+        # Save errors to a file for diagnosis
+        f = open(err, "wb")
+        for line in out:
+            f.write(line)
+        f.close()
+
     if skipped:
         mark = 's'
         if out is None:                 # debug mode: nothing to parse
@@ -597,7 +615,10 @@
         else:
             fail("output changed")
         if not options.nodiff:
-            showdiff(refout, out, ref, err)
+            if options.view:
+                os.system("%s %s %s" % (options.view, ref, err))
+            else:
+                showdiff(refout, out, ref, err)
         ret = 1
     elif ret:
         mark = '!'
@@ -607,13 +628,6 @@
         sys.stdout.write(mark)
         sys.stdout.flush()
 
-    if ret != 0 and not skipped and not options.debug:
-        # Save errors to a file for diagnosis
-        f = open(err, "wb")
-        for line in out:
-            f.write(line)
-        f.close()
-
     killdaemons()
 
     os.chdir(TESTDIR)
@@ -843,6 +857,7 @@
     os.environ["EMAIL"] = "Foo Bar <foo.bar@example.com>"
     os.environ['CDPATH'] = ''
     os.environ['COLUMNS'] = '80'
+    os.environ['GREP_OPTIONS'] = ''
     os.environ['http_proxy'] = ''
 
     # unset env related to hooks
@@ -914,10 +929,10 @@
         # it, in case external libraries are only available via current
         # PYTHONPATH.  (In particular, the Subversion bindings on OS X
         # are in /opt/subversion.)
-        oldpypath = os.environ.get('PYTHONPATH')
+        oldpypath = os.environ.get(IMPL_PATH)
         if oldpypath:
             pypath.append(oldpypath)
-        os.environ['PYTHONPATH'] = os.pathsep.join(pypath)
+        os.environ[IMPL_PATH] = os.pathsep.join(pypath)
 
     COVERAGE_FILE = os.path.join(TESTDIR, ".coverage")
 
@@ -938,7 +953,7 @@
     vlog("# Using TESTDIR", TESTDIR)
     vlog("# Using HGTMP", HGTMP)
     vlog("# Using PATH", os.environ["PATH"])
-    vlog("# Using PYTHONPATH", os.environ["PYTHONPATH"])
+    vlog("# Using", IMPL_PATH, os.environ[IMPL_PATH])
 
     try:
         if len(tests) > 1 and options.jobs > 1:
--- a/tests/test-acl	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-acl	Tue May 11 17:03:44 2010 -0500
@@ -7,7 +7,7 @@
 
     echo "Pushing as user $user"
     echo 'hgrc = """'
-    sed -e 1,2d b/.hg/hgrc
+    sed -e 1,2d b/.hg/hgrc | grep -v fakegroups.py
     echo '"""'
     if test -f acl.config; then
 	echo 'acl.config = """'
@@ -24,6 +24,30 @@
     echo
 }
 
+init_config()
+{
+cat > fakegroups.py <<EOF
+from hgext import acl
+def fakegetusers(ui, group):
+    try:
+        return acl._getusersorig(ui, group)
+    except:
+        return ["fred", "betty"]
+acl._getusersorig = acl._getusers
+acl._getusers = fakegetusers
+EOF
+
+rm -f acl.config
+cat > $config <<EOF
+[hooks]
+pretxnchangegroup.acl = python:hgext.acl.hook
+[acl]
+sources = push
+[extensions]
+f=$PWD/fakegroups.py
+EOF
+}
+
 hg init a
 cd a
 mkdir foo foo/Bar quux
@@ -111,3 +135,42 @@
 echo 'changegroup.acl = false' >> acl.config
 do_push barney
 
+# asterisk
+
+init_config
+
+echo 'asterisk test'
+echo '[acl.allow]' >> $config
+echo "** = fred" >> $config
+echo "fred is always allowed"
+do_push fred
+
+echo '[acl.deny]' >> $config
+echo "foo/Bar/** = *" >> $config
+echo "no one is allowed inside foo/Bar/"
+do_push fred
+
+# Groups
+
+init_config
+
+echo 'OS-level groups'
+echo '[acl.allow]' >> $config
+echo "** = @group1" >> $config
+echo "@group1 is always allowed"
+do_push fred
+
+echo '[acl.deny]' >> $config
+echo "foo/Bar/** = @group1" >> $config
+echo "@group is allowed inside anything but foo/Bar/"
+do_push fred
+
+echo 'Invalid group'
+# Disable the fakegroups trick to get real failures
+grep -v fakegroups $config > config.tmp
+mv config.tmp $config
+echo '[acl.allow]' >> $config
+echo "** = @unlikelytoexist" >> $config
+do_push fred 2>&1 | grep unlikelytoexist
+
+true
--- a/tests/test-acl.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-acl.out	Tue May 11 17:03:44 2010 -0500
@@ -59,19 +59,19 @@
 changesets: 3 chunks
 add changeset 911600dab2ae
 adding manifests
-manifests: 1 chunks
-manifests: 2 chunks
-manifests: 3 chunks
+manifests: 1/3 chunks (33.33%)
+manifests: 2/3 chunks (66.67%)
+manifests: 3/3 chunks (100.00%)
 adding file changes
 adding foo/Bar/file.txt revisions
-files: 1 chunks
+files: 1/3 chunks (33.33%)
 adding foo/file.txt revisions
-files: 2 chunks
+files: 2/3 chunks (66.67%)
 adding quux/file.py revisions
-files: 3 chunks
+files: 3/3 chunks (100.00%)
 added 3 changesets with 3 changes to 3 files
 updating the branch cache
-rolling back last transaction
+rolling back to revision 1 (undo push)
 0:6675d58eff77
 
 Extension disabled for lack of acl.sources
@@ -129,21 +129,21 @@
 changesets: 3 chunks
 add changeset 911600dab2ae
 adding manifests
-manifests: 1 chunks
-manifests: 2 chunks
-manifests: 3 chunks
+manifests: 1/3 chunks (33.33%)
+manifests: 2/3 chunks (66.67%)
+manifests: 3/3 chunks (100.00%)
 adding file changes
 adding foo/Bar/file.txt revisions
-files: 1 chunks
+files: 1/3 chunks (33.33%)
 adding foo/file.txt revisions
-files: 2 chunks
+files: 2/3 chunks (66.67%)
 adding quux/file.py revisions
-files: 3 chunks
+files: 3/3 chunks (100.00%)
 added 3 changesets with 3 changes to 3 files
 calling hook pretxnchangegroup.acl: hgext.acl.hook
 acl: changes have source "push" - skipping
 updating the branch cache
-rolling back last transaction
+rolling back to revision 1 (undo push)
 0:6675d58eff77
 
 No [acl.allow]/[acl.deny]
@@ -203,25 +203,30 @@
 changesets: 3 chunks
 add changeset 911600dab2ae
 adding manifests
-manifests: 1 chunks
-manifests: 2 chunks
-manifests: 3 chunks
+manifests: 1/3 chunks (33.33%)
+manifests: 2/3 chunks (66.67%)
+manifests: 3/3 chunks (100.00%)
 adding file changes
 adding foo/Bar/file.txt revisions
-files: 1 chunks
+files: 1/3 chunks (33.33%)
 adding foo/file.txt revisions
-files: 2 chunks
+files: 2/3 chunks (66.67%)
 adding quux/file.py revisions
-files: 3 chunks
+files: 3/3 chunks (100.00%)
 added 3 changesets with 3 changes to 3 files
 calling hook pretxnchangegroup.acl: hgext.acl.hook
+acl: acl.allow.branches not enabled
+acl: acl.deny.branches not enabled
 acl: acl.allow not enabled
 acl: acl.deny not enabled
+acl: branch access granted: "ef1ea85a6374" on branch "default"
 acl: allowing changeset ef1ea85a6374
+acl: branch access granted: "f9cafe1212c8" on branch "default"
 acl: allowing changeset f9cafe1212c8
+acl: branch access granted: "911600dab2ae" on branch "default"
 acl: allowing changeset 911600dab2ae
 updating the branch cache
-rolling back last transaction
+rolling back to revision 1 (undo push)
 0:6675d58eff77
 
 Empty [acl.allow]
@@ -282,20 +287,23 @@
 changesets: 3 chunks
 add changeset 911600dab2ae
 adding manifests
-manifests: 1 chunks
-manifests: 2 chunks
-manifests: 3 chunks
+manifests: 1/3 chunks (33.33%)
+manifests: 2/3 chunks (66.67%)
+manifests: 3/3 chunks (100.00%)
 adding file changes
 adding foo/Bar/file.txt revisions
-files: 1 chunks
+files: 1/3 chunks (33.33%)
 adding foo/file.txt revisions
-files: 2 chunks
+files: 2/3 chunks (66.67%)
 adding quux/file.py revisions
-files: 3 chunks
+files: 3/3 chunks (100.00%)
 added 3 changesets with 3 changes to 3 files
 calling hook pretxnchangegroup.acl: hgext.acl.hook
+acl: acl.allow.branches not enabled
+acl: acl.deny.branches not enabled
 acl: acl.allow enabled, 0 entries for user fred
 acl: acl.deny not enabled
+acl: branch access granted: "ef1ea85a6374" on branch "default"
 acl: user fred not allowed on foo/file.txt
 error: pretxnchangegroup.acl hook failed: acl: access denied for changeset ef1ea85a6374
 transaction abort!
@@ -362,22 +370,27 @@
 changesets: 3 chunks
 add changeset 911600dab2ae
 adding manifests
-manifests: 1 chunks
-manifests: 2 chunks
-manifests: 3 chunks
+manifests: 1/3 chunks (33.33%)
+manifests: 2/3 chunks (66.67%)
+manifests: 3/3 chunks (100.00%)
 adding file changes
 adding foo/Bar/file.txt revisions
-files: 1 chunks
+files: 1/3 chunks (33.33%)
 adding foo/file.txt revisions
-files: 2 chunks
+files: 2/3 chunks (66.67%)
 adding quux/file.py revisions
-files: 3 chunks
+files: 3/3 chunks (100.00%)
 added 3 changesets with 3 changes to 3 files
 calling hook pretxnchangegroup.acl: hgext.acl.hook
+acl: acl.allow.branches not enabled
+acl: acl.deny.branches not enabled
 acl: acl.allow enabled, 1 entries for user fred
 acl: acl.deny not enabled
+acl: branch access granted: "ef1ea85a6374" on branch "default"
 acl: allowing changeset ef1ea85a6374
+acl: branch access granted: "f9cafe1212c8" on branch "default"
 acl: allowing changeset f9cafe1212c8
+acl: branch access granted: "911600dab2ae" on branch "default"
 acl: user fred not allowed on quux/file.py
 error: pretxnchangegroup.acl hook failed: acl: access denied for changeset 911600dab2ae
 transaction abort!
@@ -445,20 +458,23 @@
 changesets: 3 chunks
 add changeset 911600dab2ae
 adding manifests
-manifests: 1 chunks
-manifests: 2 chunks
-manifests: 3 chunks
+manifests: 1/3 chunks (33.33%)
+manifests: 2/3 chunks (66.67%)
+manifests: 3/3 chunks (100.00%)
 adding file changes
 adding foo/Bar/file.txt revisions
-files: 1 chunks
+files: 1/3 chunks (33.33%)
 adding foo/file.txt revisions
-files: 2 chunks
+files: 2/3 chunks (66.67%)
 adding quux/file.py revisions
-files: 3 chunks
+files: 3/3 chunks (100.00%)
 added 3 changesets with 3 changes to 3 files
 calling hook pretxnchangegroup.acl: hgext.acl.hook
+acl: acl.allow.branches not enabled
+acl: acl.deny.branches not enabled
 acl: acl.allow enabled, 0 entries for user barney
 acl: acl.deny enabled, 0 entries for user barney
+acl: branch access granted: "ef1ea85a6374" on branch "default"
 acl: user barney not allowed on foo/file.txt
 error: pretxnchangegroup.acl hook failed: acl: access denied for changeset ef1ea85a6374
 transaction abort!
@@ -527,22 +543,27 @@
 changesets: 3 chunks
 add changeset 911600dab2ae
 adding manifests
-manifests: 1 chunks
-manifests: 2 chunks
-manifests: 3 chunks
+manifests: 1/3 chunks (33.33%)
+manifests: 2/3 chunks (66.67%)
+manifests: 3/3 chunks (100.00%)
 adding file changes
 adding foo/Bar/file.txt revisions
-files: 1 chunks
+files: 1/3 chunks (33.33%)
 adding foo/file.txt revisions
-files: 2 chunks
+files: 2/3 chunks (66.67%)
 adding quux/file.py revisions
-files: 3 chunks
+files: 3/3 chunks (100.00%)
 added 3 changesets with 3 changes to 3 files
 calling hook pretxnchangegroup.acl: hgext.acl.hook
+acl: acl.allow.branches not enabled
+acl: acl.deny.branches not enabled
 acl: acl.allow enabled, 1 entries for user fred
 acl: acl.deny enabled, 1 entries for user fred
+acl: branch access granted: "ef1ea85a6374" on branch "default"
 acl: allowing changeset ef1ea85a6374
+acl: branch access granted: "f9cafe1212c8" on branch "default"
 acl: allowing changeset f9cafe1212c8
+acl: branch access granted: "911600dab2ae" on branch "default"
 acl: user fred not allowed on quux/file.py
 error: pretxnchangegroup.acl hook failed: acl: access denied for changeset 911600dab2ae
 transaction abort!
@@ -612,21 +633,25 @@
 changesets: 3 chunks
 add changeset 911600dab2ae
 adding manifests
-manifests: 1 chunks
-manifests: 2 chunks
-manifests: 3 chunks
+manifests: 1/3 chunks (33.33%)
+manifests: 2/3 chunks (66.67%)
+manifests: 3/3 chunks (100.00%)
 adding file changes
 adding foo/Bar/file.txt revisions
-files: 1 chunks
+files: 1/3 chunks (33.33%)
 adding foo/file.txt revisions
-files: 2 chunks
+files: 2/3 chunks (66.67%)
 adding quux/file.py revisions
-files: 3 chunks
+files: 3/3 chunks (100.00%)
 added 3 changesets with 3 changes to 3 files
 calling hook pretxnchangegroup.acl: hgext.acl.hook
+acl: acl.allow.branches not enabled
+acl: acl.deny.branches not enabled
 acl: acl.allow enabled, 1 entries for user fred
 acl: acl.deny enabled, 2 entries for user fred
+acl: branch access granted: "ef1ea85a6374" on branch "default"
 acl: allowing changeset ef1ea85a6374
+acl: branch access granted: "f9cafe1212c8" on branch "default"
 acl: user fred denied on foo/Bar/file.txt
 error: pretxnchangegroup.acl hook failed: acl: access denied for changeset f9cafe1212c8
 transaction abort!
@@ -696,20 +721,23 @@
 changesets: 3 chunks
 add changeset 911600dab2ae
 adding manifests
-manifests: 1 chunks
-manifests: 2 chunks
-manifests: 3 chunks
+manifests: 1/3 chunks (33.33%)
+manifests: 2/3 chunks (66.67%)
+manifests: 3/3 chunks (100.00%)
 adding file changes
 adding foo/Bar/file.txt revisions
-files: 1 chunks
+files: 1/3 chunks (33.33%)
 adding foo/file.txt revisions
-files: 2 chunks
+files: 2/3 chunks (66.67%)
 adding quux/file.py revisions
-files: 3 chunks
+files: 3/3 chunks (100.00%)
 added 3 changesets with 3 changes to 3 files
 calling hook pretxnchangegroup.acl: hgext.acl.hook
+acl: acl.allow.branches not enabled
+acl: acl.deny.branches not enabled
 acl: acl.allow enabled, 0 entries for user barney
 acl: acl.deny enabled, 0 entries for user barney
+acl: branch access granted: "ef1ea85a6374" on branch "default"
 acl: user barney not allowed on foo/file.txt
 error: pretxnchangegroup.acl hook failed: acl: access denied for changeset ef1ea85a6374
 transaction abort!
@@ -781,25 +809,30 @@
 changesets: 3 chunks
 add changeset 911600dab2ae
 adding manifests
-manifests: 1 chunks
-manifests: 2 chunks
-manifests: 3 chunks
+manifests: 1/3 chunks (33.33%)
+manifests: 2/3 chunks (66.67%)
+manifests: 3/3 chunks (100.00%)
 adding file changes
 adding foo/Bar/file.txt revisions
-files: 1 chunks
+files: 1/3 chunks (33.33%)
 adding foo/file.txt revisions
-files: 2 chunks
+files: 2/3 chunks (66.67%)
 adding quux/file.py revisions
-files: 3 chunks
+files: 3/3 chunks (100.00%)
 added 3 changesets with 3 changes to 3 files
 calling hook pretxnchangegroup.acl: hgext.acl.hook
+acl: acl.allow.branches not enabled
+acl: acl.deny.branches not enabled
 acl: acl.allow enabled, 1 entries for user barney
 acl: acl.deny enabled, 0 entries for user barney
+acl: branch access granted: "ef1ea85a6374" on branch "default"
 acl: allowing changeset ef1ea85a6374
+acl: branch access granted: "f9cafe1212c8" on branch "default"
 acl: allowing changeset f9cafe1212c8
+acl: branch access granted: "911600dab2ae" on branch "default"
 acl: allowing changeset 911600dab2ae
 updating the branch cache
-rolling back last transaction
+rolling back to revision 1 (undo push)
 0:6675d58eff77
 
 wilma can change files with a .txt extension
@@ -867,22 +900,27 @@
 changesets: 3 chunks
 add changeset 911600dab2ae
 adding manifests
-manifests: 1 chunks
-manifests: 2 chunks
-manifests: 3 chunks
+manifests: 1/3 chunks (33.33%)
+manifests: 2/3 chunks (66.67%)
+manifests: 3/3 chunks (100.00%)
 adding file changes
 adding foo/Bar/file.txt revisions
-files: 1 chunks
+files: 1/3 chunks (33.33%)
 adding foo/file.txt revisions
-files: 2 chunks
+files: 2/3 chunks (66.67%)
 adding quux/file.py revisions
-files: 3 chunks
+files: 3/3 chunks (100.00%)
 added 3 changesets with 3 changes to 3 files
 calling hook pretxnchangegroup.acl: hgext.acl.hook
+acl: acl.allow.branches not enabled
+acl: acl.deny.branches not enabled
 acl: acl.allow enabled, 1 entries for user wilma
 acl: acl.deny enabled, 0 entries for user wilma
+acl: branch access granted: "ef1ea85a6374" on branch "default"
 acl: allowing changeset ef1ea85a6374
+acl: branch access granted: "f9cafe1212c8" on branch "default"
 acl: allowing changeset f9cafe1212c8
+acl: branch access granted: "911600dab2ae" on branch "default"
 acl: user wilma not allowed on quux/file.py
 error: pretxnchangegroup.acl hook failed: acl: access denied for changeset 911600dab2ae
 transaction abort!
@@ -957,16 +995,16 @@
 changesets: 3 chunks
 add changeset 911600dab2ae
 adding manifests
-manifests: 1 chunks
-manifests: 2 chunks
-manifests: 3 chunks
+manifests: 1/3 chunks (33.33%)
+manifests: 2/3 chunks (66.67%)
+manifests: 3/3 chunks (100.00%)
 adding file changes
 adding foo/Bar/file.txt revisions
-files: 1 chunks
+files: 1/3 chunks (33.33%)
 adding foo/file.txt revisions
-files: 2 chunks
+files: 2/3 chunks (66.67%)
 adding quux/file.py revisions
-files: 3 chunks
+files: 3/3 chunks (100.00%)
 added 3 changesets with 3 changes to 3 files
 calling hook pretxnchangegroup.acl: hgext.acl.hook
 error: pretxnchangegroup.acl hook raised an exception: [Errno 2] No such file or directory: '../acl.config'
@@ -1046,22 +1084,27 @@
 changesets: 3 chunks
 add changeset 911600dab2ae
 adding manifests
-manifests: 1 chunks
-manifests: 2 chunks
-manifests: 3 chunks
+manifests: 1/3 chunks (33.33%)
+manifests: 2/3 chunks (66.67%)
+manifests: 3/3 chunks (100.00%)
 adding file changes
 adding foo/Bar/file.txt revisions
-files: 1 chunks
+files: 1/3 chunks (33.33%)
 adding foo/file.txt revisions
-files: 2 chunks
+files: 2/3 chunks (66.67%)
 adding quux/file.py revisions
-files: 3 chunks
+files: 3/3 chunks (100.00%)
 added 3 changesets with 3 changes to 3 files
 calling hook pretxnchangegroup.acl: hgext.acl.hook
+acl: acl.allow.branches not enabled
+acl: acl.deny.branches not enabled
 acl: acl.allow enabled, 1 entries for user betty
 acl: acl.deny enabled, 0 entries for user betty
+acl: branch access granted: "ef1ea85a6374" on branch "default"
 acl: allowing changeset ef1ea85a6374
+acl: branch access granted: "f9cafe1212c8" on branch "default"
 acl: allowing changeset f9cafe1212c8
+acl: branch access granted: "911600dab2ae" on branch "default"
 acl: user betty not allowed on quux/file.py
 error: pretxnchangegroup.acl hook failed: acl: access denied for changeset 911600dab2ae
 transaction abort!
@@ -1142,24 +1185,380 @@
 changesets: 3 chunks
 add changeset 911600dab2ae
 adding manifests
-manifests: 1 chunks
-manifests: 2 chunks
-manifests: 3 chunks
+manifests: 1/3 chunks (33.33%)
+manifests: 2/3 chunks (66.67%)
+manifests: 3/3 chunks (100.00%)
+adding file changes
+adding foo/Bar/file.txt revisions
+files: 1/3 chunks (33.33%)
+adding foo/file.txt revisions
+files: 2/3 chunks (66.67%)
+adding quux/file.py revisions
+files: 3/3 chunks (100.00%)
+added 3 changesets with 3 changes to 3 files
+calling hook pretxnchangegroup.acl: hgext.acl.hook
+acl: acl.allow.branches not enabled
+acl: acl.deny.branches not enabled
+acl: acl.allow enabled, 1 entries for user barney
+acl: acl.deny enabled, 0 entries for user barney
+acl: branch access granted: "ef1ea85a6374" on branch "default"
+acl: allowing changeset ef1ea85a6374
+acl: branch access granted: "f9cafe1212c8" on branch "default"
+acl: allowing changeset f9cafe1212c8
+acl: branch access granted: "911600dab2ae" on branch "default"
+acl: allowing changeset 911600dab2ae
+updating the branch cache
+rolling back to revision 1 (undo push)
+0:6675d58eff77
+
+asterisk test
+fred is always allowed
+Pushing as user fred
+hgrc = """
+[acl]
+sources = push
+[extensions]
+[acl.allow]
+** = fred
+"""
+pushing to ../b
+searching for changes
+common changesets up to 6675d58eff77
+invalidating branch cache (tip differs)
+3 changesets found
+list of changesets:
+ef1ea85a6374b77d6da9dcda9541f498f2d17df7
+f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
+911600dab2ae7a9baff75958b84fe606851ce955
+adding changesets
+bundling changes: 0 chunks
+bundling changes: 1 chunks
+bundling changes: 2 chunks
+bundling changes: 3 chunks
+bundling changes: 4 chunks
+bundling changes: 5 chunks
+bundling changes: 6 chunks
+bundling changes: 7 chunks
+bundling changes: 8 chunks
+bundling changes: 9 chunks
+bundling manifests: 0 chunks
+bundling manifests: 1 chunks
+bundling manifests: 2 chunks
+bundling manifests: 3 chunks
+bundling manifests: 4 chunks
+bundling manifests: 5 chunks
+bundling manifests: 6 chunks
+bundling manifests: 7 chunks
+bundling manifests: 8 chunks
+bundling manifests: 9 chunks
+bundling files: foo/Bar/file.txt 0 chunks
+bundling files: foo/Bar/file.txt 1 chunks
+bundling files: foo/Bar/file.txt 2 chunks
+bundling files: foo/Bar/file.txt 3 chunks
+bundling files: foo/file.txt 4 chunks
+bundling files: foo/file.txt 5 chunks
+bundling files: foo/file.txt 6 chunks
+bundling files: foo/file.txt 7 chunks
+bundling files: quux/file.py 8 chunks
+bundling files: quux/file.py 9 chunks
+bundling files: quux/file.py 10 chunks
+bundling files: quux/file.py 11 chunks
+changesets: 1 chunks
+add changeset ef1ea85a6374
+changesets: 2 chunks
+add changeset f9cafe1212c8
+changesets: 3 chunks
+add changeset 911600dab2ae
+adding manifests
+manifests: 1/3 chunks (33.33%)
+manifests: 2/3 chunks (66.67%)
+manifests: 3/3 chunks (100.00%)
+adding file changes
+adding foo/Bar/file.txt revisions
+files: 1/3 chunks (33.33%)
+adding foo/file.txt revisions
+files: 2/3 chunks (66.67%)
+adding quux/file.py revisions
+files: 3/3 chunks (100.00%)
+added 3 changesets with 3 changes to 3 files
+calling hook pretxnchangegroup.acl: hgext.acl.hook
+acl: acl.allow.branches not enabled
+acl: acl.deny.branches not enabled
+acl: acl.allow enabled, 1 entries for user fred
+acl: acl.deny not enabled
+acl: branch access granted: "ef1ea85a6374" on branch "default"
+acl: allowing changeset ef1ea85a6374
+acl: branch access granted: "f9cafe1212c8" on branch "default"
+acl: allowing changeset f9cafe1212c8
+acl: branch access granted: "911600dab2ae" on branch "default"
+acl: allowing changeset 911600dab2ae
+updating the branch cache
+rolling back to revision 1 (undo push)
+0:6675d58eff77
+
+no one is allowed inside foo/Bar/
+Pushing as user fred
+hgrc = """
+[acl]
+sources = push
+[extensions]
+[acl.allow]
+** = fred
+[acl.deny]
+foo/Bar/** = *
+"""
+pushing to ../b
+searching for changes
+common changesets up to 6675d58eff77
+invalidating branch cache (tip differs)
+3 changesets found
+list of changesets:
+ef1ea85a6374b77d6da9dcda9541f498f2d17df7
+f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
+911600dab2ae7a9baff75958b84fe606851ce955
+adding changesets
+bundling changes: 0 chunks
+bundling changes: 1 chunks
+bundling changes: 2 chunks
+bundling changes: 3 chunks
+bundling changes: 4 chunks
+bundling changes: 5 chunks
+bundling changes: 6 chunks
+bundling changes: 7 chunks
+bundling changes: 8 chunks
+bundling changes: 9 chunks
+bundling manifests: 0 chunks
+bundling manifests: 1 chunks
+bundling manifests: 2 chunks
+bundling manifests: 3 chunks
+bundling manifests: 4 chunks
+bundling manifests: 5 chunks
+bundling manifests: 6 chunks
+bundling manifests: 7 chunks
+bundling manifests: 8 chunks
+bundling manifests: 9 chunks
+bundling files: foo/Bar/file.txt 0 chunks
+bundling files: foo/Bar/file.txt 1 chunks
+bundling files: foo/Bar/file.txt 2 chunks
+bundling files: foo/Bar/file.txt 3 chunks
+bundling files: foo/file.txt 4 chunks
+bundling files: foo/file.txt 5 chunks
+bundling files: foo/file.txt 6 chunks
+bundling files: foo/file.txt 7 chunks
+bundling files: quux/file.py 8 chunks
+bundling files: quux/file.py 9 chunks
+bundling files: quux/file.py 10 chunks
+bundling files: quux/file.py 11 chunks
+changesets: 1 chunks
+add changeset ef1ea85a6374
+changesets: 2 chunks
+add changeset f9cafe1212c8
+changesets: 3 chunks
+add changeset 911600dab2ae
+adding manifests
+manifests: 1/3 chunks (33.33%)
+manifests: 2/3 chunks (66.67%)
+manifests: 3/3 chunks (100.00%)
 adding file changes
 adding foo/Bar/file.txt revisions
-files: 1 chunks
+files: 1/3 chunks (33.33%)
 adding foo/file.txt revisions
-files: 2 chunks
+files: 2/3 chunks (66.67%)
 adding quux/file.py revisions
-files: 3 chunks
+files: 3/3 chunks (100.00%)
+added 3 changesets with 3 changes to 3 files
+calling hook pretxnchangegroup.acl: hgext.acl.hook
+acl: acl.allow.branches not enabled
+acl: acl.deny.branches not enabled
+acl: acl.allow enabled, 1 entries for user fred
+acl: acl.deny enabled, 1 entries for user fred
+acl: branch access granted: "ef1ea85a6374" on branch "default"
+acl: allowing changeset ef1ea85a6374
+acl: branch access granted: "f9cafe1212c8" on branch "default"
+acl: user fred denied on foo/Bar/file.txt
+error: pretxnchangegroup.acl hook failed: acl: access denied for changeset f9cafe1212c8
+transaction abort!
+rollback completed
+abort: acl: access denied for changeset f9cafe1212c8
+no rollback information available
+0:6675d58eff77
+
+OS-level groups
+@group1 is always allowed
+Pushing as user fred
+hgrc = """
+[acl]
+sources = push
+[extensions]
+[acl.allow]
+** = @group1
+"""
+pushing to ../b
+searching for changes
+common changesets up to 6675d58eff77
+3 changesets found
+list of changesets:
+ef1ea85a6374b77d6da9dcda9541f498f2d17df7
+f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
+911600dab2ae7a9baff75958b84fe606851ce955
+adding changesets
+bundling changes: 0 chunks
+bundling changes: 1 chunks
+bundling changes: 2 chunks
+bundling changes: 3 chunks
+bundling changes: 4 chunks
+bundling changes: 5 chunks
+bundling changes: 6 chunks
+bundling changes: 7 chunks
+bundling changes: 8 chunks
+bundling changes: 9 chunks
+bundling manifests: 0 chunks
+bundling manifests: 1 chunks
+bundling manifests: 2 chunks
+bundling manifests: 3 chunks
+bundling manifests: 4 chunks
+bundling manifests: 5 chunks
+bundling manifests: 6 chunks
+bundling manifests: 7 chunks
+bundling manifests: 8 chunks
+bundling manifests: 9 chunks
+bundling files: foo/Bar/file.txt 0 chunks
+bundling files: foo/Bar/file.txt 1 chunks
+bundling files: foo/Bar/file.txt 2 chunks
+bundling files: foo/Bar/file.txt 3 chunks
+bundling files: foo/file.txt 4 chunks
+bundling files: foo/file.txt 5 chunks
+bundling files: foo/file.txt 6 chunks
+bundling files: foo/file.txt 7 chunks
+bundling files: quux/file.py 8 chunks
+bundling files: quux/file.py 9 chunks
+bundling files: quux/file.py 10 chunks
+bundling files: quux/file.py 11 chunks
+changesets: 1 chunks
+add changeset ef1ea85a6374
+changesets: 2 chunks
+add changeset f9cafe1212c8
+changesets: 3 chunks
+add changeset 911600dab2ae
+adding manifests
+manifests: 1/3 chunks (33.33%)
+manifests: 2/3 chunks (66.67%)
+manifests: 3/3 chunks (100.00%)
+adding file changes
+adding foo/Bar/file.txt revisions
+files: 1/3 chunks (33.33%)
+adding foo/file.txt revisions
+files: 2/3 chunks (66.67%)
+adding quux/file.py revisions
+files: 3/3 chunks (100.00%)
 added 3 changesets with 3 changes to 3 files
 calling hook pretxnchangegroup.acl: hgext.acl.hook
-acl: acl.allow enabled, 1 entries for user barney
-acl: acl.deny enabled, 0 entries for user barney
+acl: acl.allow.branches not enabled
+acl: acl.deny.branches not enabled
+acl: "group1" not defined in [acl.groups]
+acl: acl.allow enabled, 1 entries for user fred
+acl: acl.deny not enabled
+acl: branch access granted: "ef1ea85a6374" on branch "default"
 acl: allowing changeset ef1ea85a6374
+acl: branch access granted: "f9cafe1212c8" on branch "default"
 acl: allowing changeset f9cafe1212c8
+acl: branch access granted: "911600dab2ae" on branch "default"
 acl: allowing changeset 911600dab2ae
 updating the branch cache
-rolling back last transaction
+rolling back to revision 1 (undo push)
 0:6675d58eff77
 
+@group is allowed inside anything but foo/Bar/
+Pushing as user fred
+hgrc = """
+[acl]
+sources = push
+[extensions]
+[acl.allow]
+** = @group1
+[acl.deny]
+foo/Bar/** = @group1
+"""
+pushing to ../b
+searching for changes
+common changesets up to 6675d58eff77
+invalidating branch cache (tip differs)
+3 changesets found
+list of changesets:
+ef1ea85a6374b77d6da9dcda9541f498f2d17df7
+f9cafe1212c8c6fa1120d14a556e18cc44ff8bdd
+911600dab2ae7a9baff75958b84fe606851ce955
+adding changesets
+bundling changes: 0 chunks
+bundling changes: 1 chunks
+bundling changes: 2 chunks
+bundling changes: 3 chunks
+bundling changes: 4 chunks
+bundling changes: 5 chunks
+bundling changes: 6 chunks
+bundling changes: 7 chunks
+bundling changes: 8 chunks
+bundling changes: 9 chunks
+bundling manifests: 0 chunks
+bundling manifests: 1 chunks
+bundling manifests: 2 chunks
+bundling manifests: 3 chunks
+bundling manifests: 4 chunks
+bundling manifests: 5 chunks
+bundling manifests: 6 chunks
+bundling manifests: 7 chunks
+bundling manifests: 8 chunks
+bundling manifests: 9 chunks
+bundling files: foo/Bar/file.txt 0 chunks
+bundling files: foo/Bar/file.txt 1 chunks
+bundling files: foo/Bar/file.txt 2 chunks
+bundling files: foo/Bar/file.txt 3 chunks
+bundling files: foo/file.txt 4 chunks
+bundling files: foo/file.txt 5 chunks
+bundling files: foo/file.txt 6 chunks
+bundling files: foo/file.txt 7 chunks
+bundling files: quux/file.py 8 chunks
+bundling files: quux/file.py 9 chunks
+bundling files: quux/file.py 10 chunks
+bundling files: quux/file.py 11 chunks
+changesets: 1 chunks
+add changeset ef1ea85a6374
+changesets: 2 chunks
+add changeset f9cafe1212c8
+changesets: 3 chunks
+add changeset 911600dab2ae
+adding manifests
+manifests: 1/3 chunks (33.33%)
+manifests: 2/3 chunks (66.67%)
+manifests: 3/3 chunks (100.00%)
+adding file changes
+adding foo/Bar/file.txt revisions
+files: 1/3 chunks (33.33%)
+adding foo/file.txt revisions
+files: 2/3 chunks (66.67%)
+adding quux/file.py revisions
+files: 3/3 chunks (100.00%)
+added 3 changesets with 3 changes to 3 files
+calling hook pretxnchangegroup.acl: hgext.acl.hook
+acl: acl.allow.branches not enabled
+acl: acl.deny.branches not enabled
+acl: "group1" not defined in [acl.groups]
+acl: acl.allow enabled, 1 entries for user fred
+acl: "group1" not defined in [acl.groups]
+acl: acl.deny enabled, 1 entries for user fred
+acl: branch access granted: "ef1ea85a6374" on branch "default"
+acl: allowing changeset ef1ea85a6374
+acl: branch access granted: "f9cafe1212c8" on branch "default"
+acl: user fred denied on foo/Bar/file.txt
+error: pretxnchangegroup.acl hook failed: acl: access denied for changeset f9cafe1212c8
+transaction abort!
+rollback completed
+abort: acl: access denied for changeset f9cafe1212c8
+no rollback information available
+0:6675d58eff77
+
+Invalid group
+** = @unlikelytoexist
+acl: "unlikelytoexist" not defined in [acl.groups]
+error: pretxnchangegroup.acl hook failed: group 'unlikelytoexist' is undefined
+abort: group 'unlikelytoexist' is undefined
--- a/tests/test-archive	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-archive	Tue May 11 17:03:44 2010 -0500
@@ -74,6 +74,20 @@
 hg archive -t tgz -p %b-%h test-%h.tar.gz
 gzip -dc test-$QTIP.tar.gz | tar tf - 2>/dev/null | sed "s/$QTIP/TIP/"
 
+hg archive autodetected_test.tar
+tar tf autodetected_test.tar
+
+# The '-t' should override autodetection
+hg archive -t tar autodetect_override_test.zip
+tar tf autodetect_override_test.zip
+
+for ext in tar tar.gz tgz tar.bz2 tbz2 zip; do
+    hg archive auto_test.$ext
+    if [ -d auto_test.$ext ]; then
+        echo "extension $ext was not autodetected."
+    fi
+done
+
 cat > md5comp.py <<EOF
 try:
     from hashlib import md5
--- a/tests/test-archive.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-archive.out	Tue May 11 17:03:44 2010 -0500
@@ -45,6 +45,14 @@
 test-TIP/bar
 test-TIP/baz/bletch
 test-TIP/foo
+autodetected_test/.hg_archival.txt
+autodetected_test/bar
+autodetected_test/baz/bletch
+autodetected_test/foo
+autodetect_override_test.zip/.hg_archival.txt
+autodetect_override_test.zip/bar
+autodetect_override_test.zip/baz/bletch
+autodetect_override_test.zip/foo
 True
 abort: archive prefix contains illegal components
 Archive:  test.zip
--- a/tests/test-backout.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-backout.out	Tue May 11 17:03:44 2010 -0500
@@ -62,7 +62,7 @@
 # backout with valid parent should be ok
 removing d
 changeset 5:10e5328c8435 backs out changeset 4:b2f3bb92043e
-rolling back last transaction
+rolling back to revision 5 (undo commit)
 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 removing c
 changeset 5:033590168430 backs out changeset 4:b2f3bb92043e
--- a/tests/test-bookmarks	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-bookmarks	Tue May 11 17:03:44 2010 -0500
@@ -14,6 +14,10 @@
 echo % list bookmarks
 hg bookmarks
 
+echo % list bookmarks with color
+hg --config extensions.color= --config color.mode=ansi \
+    bookmarks --color=always
+
 echo a > a
 hg add a
 hg commit -m 0
--- a/tests/test-bookmarks-current	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-bookmarks-current	Tue May 11 17:03:44 2010 -0500
@@ -17,6 +17,10 @@
 echo % list bookmarks
 hg bookmark
 
+echo % list bookmarks with color
+hg --config extensions.color= --config color.mode=ansi \
+    bookmark --color=always
+
 echo % update to bookmark X
 hg update X
 
--- a/tests/test-bookmarks-current.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-bookmarks-current.out	Tue May 11 17:03:44 2010 -0500
@@ -3,6 +3,8 @@
 % set bookmark X
 % list bookmarks
  * X                         -1:000000000000
+% list bookmarks with color
+ * X                         -1:000000000000
 % update to bookmark X
 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
 % list bookmarks
--- a/tests/test-bookmarks-rebase.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-bookmarks-rebase.out	Tue May 11 17:03:44 2010 -0500
@@ -17,9 +17,9 @@
 added 1 changesets with 1 changes to 1 files (-1 heads)
 rebase completed
 changeset:   3:9163974d1cb5
+tag:         one
 tag:         tip
 tag:         two
-tag:         one
 parent:      1:925d80f479bb
 parent:      2:db815d6d32e6
 user:        test
--- a/tests/test-bookmarks.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-bookmarks.out	Tue May 11 17:03:44 2010 -0500
@@ -3,6 +3,8 @@
 % bookmark rev -1
 % list bookmarks
  * X                         -1:000000000000
+% list bookmarks with color
+ * X                         -1:000000000000
 % bookmark X moved to rev 0
  * X                         0:f7b1eb17ad24
 % look up bookmark
--- a/tests/test-bundle-r.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-bundle-r.out	Tue May 11 17:03:44 2010 -0500
@@ -154,7 +154,7 @@
 crosschecking files in changesets and manifests
 checking files
 4 files, 9 changesets, 7 total revisions
-rolling back last transaction
+rolling back to revision 5 (undo pull)
 % should fail
 abort: --base is incompatible with specifying a destination
 abort: repository default-push not found!
@@ -187,7 +187,7 @@
 crosschecking files in changesets and manifests
 checking files
 4 files, 9 changesets, 7 total revisions
-rolling back last transaction
+rolling back to revision 3 (undo unbundle)
 % 2
 2:d62976ca1e50
 adding changesets
@@ -202,7 +202,7 @@
 crosschecking files in changesets and manifests
 checking files
 2 files, 5 changesets, 5 total revisions
-rolling back last transaction
+rolling back to revision 3 (undo unbundle)
 adding changesets
 adding manifests
 adding file changes
@@ -215,7 +215,7 @@
 crosschecking files in changesets and manifests
 checking files
 3 files, 7 changesets, 6 total revisions
-rolling back last transaction
+rolling back to revision 3 (undo unbundle)
 adding changesets
 adding manifests
 adding file changes
--- a/tests/test-bundle.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-bundle.out	Tue May 11 17:03:44 2010 -0500
@@ -37,7 +37,7 @@
 added 9 changesets with 7 changes to 4 files (+1 heads)
 (run 'hg heads' to see heads, 'hg merge' to merge)
 ====== Rollback empty
-rolling back last transaction
+rolling back to revision 0 (undo pull)
 ====== Pull full.hg into empty again (using --cwd)
 pulling from ../full.hg
 requesting all changes
@@ -55,7 +55,7 @@
 searching for changes
 no changes found
 ====== Rollback empty
-rolling back last transaction
+rolling back to revision 0 (undo pull)
 ====== Pull full.hg into empty again (using -R)
 pulling from full.hg
 requesting all changes
@@ -123,7 +123,7 @@
 added 9 changesets with 7 changes to 4 files (+1 heads)
 (run 'hg heads' to see heads, 'hg merge' to merge)
 ====== Rollback empty
-rolling back last transaction
+rolling back to revision 0 (undo pull)
 ====== Log -R bundle:empty+full.hg
 8 7 6 5 4 3 2 1 0 
 ====== Pull full.hg into empty again (using -R; with hook)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-check-code	Tue May 11 17:03:44 2010 -0500
@@ -0,0 +1,26 @@
+#!/bin/sh
+#cd `dirname $0`
+cat > correct.py <<EOF
+def toto(arg1, arg2):
+    del arg2
+    return (5 + 6, 9)
+EOF
+
+cat > wrong.py <<EOF
+def toto( arg1, arg2):
+    del(arg2)
+    return ( 5+6, 9)
+EOF
+
+cat > quote.py <<EOF
+# let's use quote in comments
+(''' ( 4x5 )
+but """\\''' and finally''',
+"""let's fool checkpatch""", '1+2',
+'"""', 42+1, """and
+( 4-1 ) """, "( 1+1 )\" and ")
+a, '\\\\\\\\', "\\\\\\" x-2", "c-1"
+EOF
+
+check_code=`dirname $0`/../contrib/check-code.py
+${check_code} ./wrong.py ./correct.py ./quote.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-check-code.out	Tue May 11 17:03:44 2010 -0500
@@ -0,0 +1,13 @@
+./wrong.py:1:
+ > def toto( arg1, arg2):
+ gratuitous whitespace in () or []
+./wrong.py:2:
+ >     del(arg2)
+ del isn't a function
+./wrong.py:3:
+ >     return ( 5+6, 9)
+ missing whitespace in expression
+ gratuitous whitespace in () or []
+./quote.py:5:
+ > '"""', 42+1, """and
+ missing whitespace in expression
--- a/tests/test-churn	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-churn	Tue May 11 17:03:44 2010 -0500
@@ -52,6 +52,9 @@
 hg rm d/g/f2.txt
 hg ci -Am "removed d/g/f2.txt" -u user1 -d 14:00 d/g/f2.txt
 hg churn --diffstat
+echo % churn --diffstat with color
+hg --config extensions.color= churn --config color.mode=ansi \
+    --diffstat --color=always
 
 echo % changeset number churn
 hg churn -c
--- a/tests/test-churn.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-churn.out	Tue May 11 17:03:44 2010 -0500
@@ -32,6 +32,10 @@
 user1           +3/-1 +++++++++++++++++++++++++++++++++++++++++--------------
 user3           +3/-0 +++++++++++++++++++++++++++++++++++++++++
 user2           +2/-0 +++++++++++++++++++++++++++
+% churn --diffstat with color
+user1           +3/-1 +++++++++++++++++++++++++++++++++++++++++--------------
+user3           +3/-0 +++++++++++++++++++++++++++++++++++++++++
+user2           +2/-0 +++++++++++++++++++++++++++
 % changeset number churn
 user1      4 ***************************************************************
 user3      3 ***********************************************
--- a/tests/test-convert-cvs.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-convert-cvs.out	Tue May 11 17:03:44 2010 -0500
@@ -45,7 +45,7 @@
 2 Initial revision
 1 import
 filtering out empty revision
-rolling back last transaction
+rolling back to revision 1 (undo commit)
 0 ci0
 updating tags
 c
--- a/tests/test-convert-svn-move	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-convert-svn-move	Tue May 11 17:03:44 2010 -0500
@@ -51,3 +51,20 @@
 echo '% try updating'
 hg up -qC default
 cd ..
+
+echo '% test convert progress bar'
+
+echo "progress=" >> $HGRCPATH
+echo "[progress]" >> $HGRCPATH
+echo "assume-tty=1" >> $HGRCPATH
+echo "delay=0" >> $HGRCPATH
+echo "refresh=0" >> $HGRCPATH
+
+cat > filtercr.py <<EOF
+import sys, re
+for line in sys.stdin:
+    line = re.sub(r'\r+[^\n]', lambda m: '\n' + m.group()[-1:], line)
+    sys.stdout.write(line)
+EOF
+
+hg convert svn-repo hg-progress 2>&1 | python filtercr.py
--- a/tests/test-convert-svn-move.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-convert-svn-move.out	Tue May 11 17:03:44 2010 -0500
@@ -80,3 +80,44 @@
 644 @ dlink2
 644 @ dlink3
 % try updating
+% test convert progress bar
+
+scanning [ <=>                                                              ] 1
+scanning [  <=>                                                             ] 2
+scanning [   <=>                                                            ] 3
+scanning [    <=>                                                           ] 4
+                                                                                
+converting [                                                              ] 0/4
+retrieving file [==========>                                              ] 1/5
+retrieving file [=====================>                                   ] 2/5
+retrieving file [=================================>                       ] 3/5
+retrieving file [============================================>            ] 4/5
+retrieving file [========================================================>] 5/5
+                                                                                
+converting [==============>                                               ] 1/4
+scanning paths [                                                          ] 0/1
+                                                                                
+retrieving file [========================================================>] 1/1
+                                                                                
+converting [==============================>                               ] 2/4
+scanning paths [                                                          ] 0/2
+scanning paths [============================>                             ] 1/2
+                                                                                
+retrieving file [=============>                                           ] 1/4
+retrieving file [===========================>                             ] 2/4
+retrieving file [=========================================>               ] 3/4
+retrieving file [========================================================>] 4/4
+                                                                                
+converting [=============================================>                ] 3/4
+scanning paths [                                                          ] 0/1
+                                                                                
+retrieving file [========================================================>] 1/1
+                                                                                
+initializing destination hg-progress repository
+scanning source...
+sorting...
+converting...
+3 initial
+2 clobber symlink
+1 clobber1
+0 clobber2
--- a/tests/test-convert.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-convert.out	Tue May 11 17:03:44 2010 -0500
@@ -103,8 +103,10 @@
         ignore integrity errors when reading. Use it to fix Mercurial
         repositories with missing revlogs, by converting from and to
         Mercurial.
+
     --config convert.hg.saverev=False         (boolean)
         store original revision ID in changeset (forces target IDs to change)
+
     --config convert.hg.startrev=0            (hg revision identifier)
         convert start revision and its descendants
 
@@ -125,25 +127,30 @@
     --config convert.cvsps.cache=True         (boolean)
         Set to False to disable remote log caching, for testing and debugging
         purposes.
+
     --config convert.cvsps.fuzz=60            (integer)
         Specify the maximum time (in seconds) that is allowed between commits
         with identical user and log message in a single changeset. When very
         large files were checked in as part of a changeset then the default
         may not be long enough.
+
     --config convert.cvsps.mergeto='{{mergetobranch ([-\w]+)}}'
         Specify a regular expression to which commit log messages are matched.
         If a match occurs, then the conversion process will insert a dummy
         revision merging the branch on which this log message occurs to the
         branch indicated in the regex.
+
     --config convert.cvsps.mergefrom='{{mergefrombranch ([-\w]+)}}'
         Specify a regular expression to which commit log messages are matched.
         If a match occurs, then the conversion process will add the most
         recent revision on the branch indicated in the regex as the second
         parent of the changeset.
+
     --config hook.cvslog
         Specify a Python function to be called at the end of gathering the CVS
         log. The function is passed a list with the log entries, and can
         modify the entries in-place, or add or delete them.
+
     --config hook.cvschangesets
         Specify a Python function to be called after the changesets are
         calculated from the the CVS log. The function is passed a list with
@@ -170,8 +177,10 @@
 
     --config convert.svn.branches=branches    (directory name)
         specify the directory containing branches
+
     --config convert.svn.tags=tags            (directory name)
         specify the directory containing tags
+
     --config convert.svn.trunk=trunk          (directory name)
         specify the name of the trunk branch
 
@@ -202,8 +211,10 @@
 
     --config convert.hg.clonebranches=False   (boolean)
         dispatch source branches in separate clones.
+
     --config convert.hg.tagsbranch=default    (branch name)
         tag revisions branch name
+
     --config convert.hg.usebranchnames=True   (boolean)
         preserve branch names
 
--- a/tests/test-copy2	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-copy2	Tue May 11 17:03:44 2010 -0500
@@ -19,6 +19,9 @@
 hg st -A
 hg commit -m1
 
+echo "# copy --after to a nonexistant target filename"
+hg cp -A foo dummy
+
 echo "# dry-run; should show that foo is clean"
 hg copy --dry-run foo bar
 hg st -A
--- a/tests/test-copy2.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-copy2.out	Tue May 11 17:03:44 2010 -0500
@@ -11,6 +11,8 @@
 # should print a warning that this is not a real copy; foo is added
 bar has not been committed yet, so no copy data will be stored for foo.
 A foo
+# copy --after to a nonexistant target filename
+foo: not recording copy - dummy does not exist
 # dry-run; should show that foo is clean
 C foo
 # should show copy
--- a/tests/test-debugcomplete.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-debugcomplete.out	Tue May 11 17:03:44 2010 -0500
@@ -143,7 +143,7 @@
 --traceback
 --verbose
 --version
---webdir-conf
+--web-conf
 -6
 -A
 -E
@@ -171,12 +171,12 @@
 export: output, switch-parent, rev, text, git, nodates
 forget: include, exclude
 init: ssh, remotecmd
-log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, prune, patch, git, limit, no-merges, style, template, include, exclude
+log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, style, template, include, exclude
 merge: force, rev, preview
 pull: update, force, rev, branch, ssh, remotecmd
 push: force, rev, branch, ssh, remotecmd
 remove: after, force, include, exclude
-serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, webdir-conf, pid-file, stdio, templates, style, ipv6, certificate
+serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, templates, style, ipv6, certificate
 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude
 summary: remote
 update: clean, check, date, rev
@@ -210,17 +210,17 @@
 help: 
 identify: rev, num, id, branch, tags
 import: strip, base, force, no-commit, exact, import-branch, message, logfile, date, user, similarity
-incoming: force, newest-first, bundle, rev, branch, patch, git, limit, no-merges, style, template, ssh, remotecmd
+incoming: force, newest-first, bundle, rev, branch, patch, git, limit, no-merges, stat, style, template, ssh, remotecmd
 locate: rev, print0, fullpath, include, exclude
 manifest: rev
-outgoing: force, rev, newest-first, branch, patch, git, limit, no-merges, style, template, ssh, remotecmd
+outgoing: force, rev, newest-first, branch, patch, git, limit, no-merges, stat, style, template, ssh, remotecmd
 parents: rev, style, template
 paths: 
 recover: 
 rename: after, force, include, exclude, dry-run
 resolve: all, list, mark, unmark, no-status, include, exclude
 revert: all, date, rev, no-backup, include, exclude, dry-run
-rollback: 
+rollback: dry-run
 root: 
 showconfig: untrusted
 tag: force, local, rev, remove, message, date, user
--- a/tests/test-diff-color.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-diff-color.out	Tue May 11 17:03:44 2010 -0500
@@ -31,7 +31,8 @@
 old mode 100644
 new mode 100755
 1 hunks, 2 lines changed
-examine changes to 'a'? [Ynsfdaq?] @@ -2,7 +2,7 @@
+examine changes to 'a'? [Ynsfdaq?] 
+@@ -2,7 +2,7 @@
  c
  a
  a
@@ -41,13 +42,15 @@
  a
  c
 record this change to 'a'? [Ynsfdaq?] 
-rolling back last transaction
+
+rolling back to revision 1 (undo commit)
 % qrecord
 diff --git a/a b/a
 old mode 100644
 new mode 100755
 1 hunks, 2 lines changed
-examine changes to 'a'? [Ynsfdaq?] @@ -2,7 +2,7 @@
+examine changes to 'a'? [Ynsfdaq?] 
+@@ -2,7 +2,7 @@
  c
  a
  a
@@ -57,3 +60,4 @@
  a
  c
 record this change to 'a'? [Ynsfdaq?] 
+
--- a/tests/test-eolfilename.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-eolfilename.out	Tue May 11 17:03:44 2010 -0500
@@ -15,6 +15,6 @@
 o
 % test issue2039
 ? foo
-bar
+bar
 ? foo
-bar.baz
+bar.baz
--- a/tests/test-fncache.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-fncache.out	Tue May 11 17:03:44 2010 -0500
@@ -54,6 +54,7 @@
 .hg/requires
 .hg/undo
 .hg/undo.branch
+.hg/undo.desc
 .hg/undo.dirstate
 % non fncache repo
 adding tst.d/Foo
@@ -70,4 +71,5 @@
 .hg/store/data/tst.d.hg/_foo.i
 .hg/store/undo
 .hg/undo.branch
+.hg/undo.desc
 .hg/undo.dirstate
--- a/tests/test-gendoc	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-gendoc	Tue May 11 17:03:44 2010 -0500
@@ -1,7 +1,6 @@
 #!/bin/sh
 
-"$TESTDIR/hghave" rst2html || exit 80
-RST2HTML=`which rst2html 2> /dev/null || which rst2html.py`
+"$TESTDIR/hghave" docutils || exit 80
 
 HGENCODING=UTF-8
 export HGENCODING
@@ -14,8 +13,8 @@
     echo "" >> gendoc-$LOCALE.txt
     LC_ALL=$LOCALE python $TESTDIR/../doc/gendoc.py >> gendoc-$LOCALE.txt || exit
 
-    # We run rst2html over the file without adding "--halt warning" to
-    # make it report all errors instead of stopping on the first one.
-    echo "checking for parse errors with rst2html"
-    $RST2HTML gendoc-$LOCALE.txt /dev/null
+    # We call runrst without adding "--halt warning" to make it report
+    # all errors instead of stopping on the first one.
+    echo "checking for parse errors"
+    python $TESTDIR/../doc/runrst html gendoc-$LOCALE.txt /dev/null
 done
--- a/tests/test-gendoc.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-gendoc.out	Tue May 11 17:03:44 2010 -0500
@@ -1,33 +1,33 @@
 
 % extracting documentation from C
-checking for parse errors with rst2html
+checking for parse errors
 
 % extracting documentation from da
-checking for parse errors with rst2html
+checking for parse errors
 
 % extracting documentation from de
-checking for parse errors with rst2html
+checking for parse errors
 
 % extracting documentation from el
-checking for parse errors with rst2html
+checking for parse errors
 
 % extracting documentation from fr
-checking for parse errors with rst2html
+checking for parse errors
 
 % extracting documentation from it
-checking for parse errors with rst2html
+checking for parse errors
 
 % extracting documentation from ja
-checking for parse errors with rst2html
+checking for parse errors
 
 % extracting documentation from pt_BR
-checking for parse errors with rst2html
+checking for parse errors
 
 % extracting documentation from sv
-checking for parse errors with rst2html
+checking for parse errors
 
 % extracting documentation from zh_CN
-checking for parse errors with rst2html
+checking for parse errors
 
 % extracting documentation from zh_TW
-checking for parse errors with rst2html
+checking for parse errors
--- a/tests/test-globalopts.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-globalopts.out	Tue May 11 17:03:44 2010 -0500
@@ -186,9 +186,9 @@
  rename       rename files; equivalent of copy + remove
  resolve      various operations to help finish a merge
  revert       restore individual files or directories to an earlier state
- rollback     roll back the last transaction
+ rollback     roll back the last transaction (dangerous)
  root         print the root (top) of the current working directory
- serve        export the repository via HTTP
+ serve        start stand-alone webserver
  showconfig   show combined config settings from all hgrc files
  status       show changed files in the working directory
  summary      summarize working directory state
@@ -196,7 +196,7 @@
  tags         list repository tags
  tip          show the tip revision
  unbundle     apply one or more changegroup files
- update       update working directory
+ update       update working directory (or switch revisions)
  verify       verify the integrity of the repository
  version      output version and copyright information
 
@@ -212,6 +212,7 @@
  templating   Template Usage
  urls         URL Paths
  extensions   Using additional features
+ hgweb        Configuring hgweb
 
 use "hg -v help" to show aliases and global options
 Mercurial Distributed SCM
@@ -255,9 +256,9 @@
  rename       rename files; equivalent of copy + remove
  resolve      various operations to help finish a merge
  revert       restore individual files or directories to an earlier state
- rollback     roll back the last transaction
+ rollback     roll back the last transaction (dangerous)
  root         print the root (top) of the current working directory
- serve        export the repository via HTTP
+ serve        start stand-alone webserver
  showconfig   show combined config settings from all hgrc files
  status       show changed files in the working directory
  summary      summarize working directory state
@@ -265,7 +266,7 @@
  tags         list repository tags
  tip          show the tip revision
  unbundle     apply one or more changegroup files
- update       update working directory
+ update       update working directory (or switch revisions)
  verify       verify the integrity of the repository
  version      output version and copyright information
 
@@ -281,6 +282,7 @@
  templating   Template Usage
  urls         URL Paths
  extensions   Using additional features
+ hgweb        Configuring hgweb
 
 use "hg -v help" to show aliases and global options
 %% not tested: --debugger
--- a/tests/test-grep	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-grep	Tue May 11 17:03:44 2010 -0500
@@ -21,6 +21,9 @@
 hg grep '**test**'
 echo % simple
 hg grep port port
+echo % simple with color
+hg --config extensions.color= grep --config color.mode=ansi \
+    --color=always port port
 echo % all
 hg grep --traceback --all -nu port port
 echo % other
--- a/tests/test-grep.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-grep.out	Tue May 11 17:03:44 2010 -0500
@@ -4,6 +4,10 @@
 port:4:export
 port:4:vaportight
 port:4:import/export
+% simple with color
+port:4:export
+port:4:vaportight
+port:4:import/export
 % all
 port:4:4:-:spam:import/export
 port:3:4:+:eggs:import/export
--- a/tests/test-help.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-help.out	Tue May 11 17:03:44 2010 -0500
@@ -15,10 +15,10 @@
  pull       pull changes from the specified source
  push       push changes to the specified destination
  remove     remove the specified files on the next commit
- serve      export the repository via HTTP
+ serve      start stand-alone webserver
  status     show changed files in the working directory
  summary    summarize working directory state
- update     update working directory
+ update     update working directory (or switch revisions)
 
 use "hg help" for the full list of commands or "hg -v" for details
  add        add the specified files on the next commit
@@ -34,10 +34,10 @@
  pull       pull changes from the specified source
  push       push changes to the specified destination
  remove     remove the specified files on the next commit
- serve      export the repository via HTTP
+ serve      start stand-alone webserver
  status     show changed files in the working directory
  summary    summarize working directory state
- update     update working directory
+ update     update working directory (or switch revisions)
 Mercurial Distributed SCM
 
 list of commands:
@@ -79,9 +79,9 @@
  rename       rename files; equivalent of copy + remove
  resolve      various operations to help finish a merge
  revert       restore individual files or directories to an earlier state
- rollback     roll back the last transaction
+ rollback     roll back the last transaction (dangerous)
  root         print the root (top) of the current working directory
- serve        export the repository via HTTP
+ serve        start stand-alone webserver
  showconfig   show combined config settings from all hgrc files
  status       show changed files in the working directory
  summary      summarize working directory state
@@ -89,7 +89,7 @@
  tags         list repository tags
  tip          show the tip revision
  unbundle     apply one or more changegroup files
- update       update working directory
+ update       update working directory (or switch revisions)
  verify       verify the integrity of the repository
  version      output version and copyright information
 
@@ -105,6 +105,7 @@
  templating   Template Usage
  urls         URL Paths
  extensions   Using additional features
+ hgweb        Configuring hgweb
 
 use "hg -v help" to show aliases and global options
  add          add the specified files on the next commit
@@ -144,9 +145,9 @@
  rename       rename files; equivalent of copy + remove
  resolve      various operations to help finish a merge
  revert       restore individual files or directories to an earlier state
- rollback     roll back the last transaction
+ rollback     roll back the last transaction (dangerous)
  root         print the root (top) of the current working directory
- serve        export the repository via HTTP
+ serve        start stand-alone webserver
  showconfig   show combined config settings from all hgrc files
  status       show changed files in the working directory
  summary      summarize working directory state
@@ -154,7 +155,7 @@
  tags         list repository tags
  tip          show the tip revision
  unbundle     apply one or more changegroup files
- update       update working directory
+ update       update working directory (or switch revisions)
  verify       verify the integrity of the repository
  version      output version and copyright information
 
@@ -170,6 +171,7 @@
  templating   Template Usage
  urls         URL Paths
  extensions   Using additional features
+ hgweb        Configuring hgweb
 %% test short command list with verbose option
 Mercurial Distributed SCM (version xxx)
 
@@ -206,13 +208,13 @@
  remove, rm:
       remove the specified files on the next commit
  serve:
-      export the repository via HTTP
+      start stand-alone webserver
  status, st:
       show changed files in the working directory
  summary, sum:
       summarize working directory state
  update, up, checkout, co:
-      update working directory
+      update working directory (or switch revisions)
 
 global options:
  -R --repository      repository root directory or name of overlay bundle file
@@ -391,7 +393,7 @@
     with undesirable results.
 
     Use the -g/--git option to generate diffs in the git extended diff format.
-    For more information, read 'hg help diffs'.
+    For more information, read "hg help diffs".
 
 options:
 
@@ -487,10 +489,10 @@
  pull       pull changes from the specified source
  push       push changes to the specified destination
  remove     remove the specified files on the next commit
- serve      export the repository via HTTP
+ serve      start stand-alone webserver
  status     show changed files in the working directory
  summary    summarize working directory state
- update     update working directory
+ update     update working directory (or switch revisions)
 
 use "hg help" for the full list of commands or "hg -v" for details
 hg: unknown command 'skjdfks'
@@ -511,10 +513,10 @@
  pull       pull changes from the specified source
  push       push changes to the specified destination
  remove     remove the specified files on the next commit
- serve      export the repository via HTTP
+ serve      start stand-alone webserver
  status     show changed files in the working directory
  summary    summarize working directory state
- update     update working directory
+ update     update working directory (or switch revisions)
 
 use "hg help" for the full list of commands or "hg -v" for details
 %% test command with no help text
@@ -565,9 +567,9 @@
  rename       rename files; equivalent of copy + remove
  resolve      various operations to help finish a merge
  revert       restore individual files or directories to an earlier state
- rollback     roll back the last transaction
+ rollback     roll back the last transaction (dangerous)
  root         print the root (top) of the current working directory
- serve        export the repository via HTTP
+ serve        start stand-alone webserver
  showconfig   show combined config settings from all hgrc files
  status       show changed files in the working directory
  summary      summarize working directory state
@@ -575,7 +577,7 @@
  tags         list repository tags
  tip          show the tip revision
  unbundle     apply one or more changegroup files
- update       update working directory
+ update       update working directory (or switch revisions)
  verify       verify the integrity of the repository
  version      output version and copyright information
 
@@ -595,6 +597,7 @@
  templating   Template Usage
  urls         URL Paths
  extensions   Using additional features
+ hgweb        Configuring hgweb
 
 use "hg -v help" to show aliases and global options
 %% test list of commands with command with no help text
--- a/tests/test-hgrc.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-hgrc.out	Tue May 11 17:03:44 2010 -0500
@@ -11,6 +11,7 @@
 foo.baz=bif cb
 hg: config error at $HGRCPATH:1: cannot include /no-such-file (No such file or directory)
 % customized hgrc
+read config from: .../.hgrc
 .../.hgrc:13: alias.log=log -g
 .../.hgrc:11: defaults.identify=-n
 .../.hgrc:2: ui.debug=true
@@ -22,6 +23,7 @@
 .../.hgrc:8: ui.style=~/.hgstyle
 .../.hgrc:9: ui.logtemplate={node}
 % plain hgrc
+read config from: .../.hgrc
 none: ui.traceback=True
 none: ui.verbose=False
 none: ui.debug=True
--- a/tests/test-hook.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-hook.out	Tue May 11 17:03:44 2010 -0500
@@ -101,7 +101,7 @@
 adding file changes
 added 1 changesets with 1 changes to 1 files
 (run 'hg update' to get a working copy)
-rolling back last transaction
+rolling back to revision 4 (undo pull)
 preoutgoing hook: HG_SOURCE=pull 
 preoutgoing.forbid hook: HG_SOURCE=pull 
 pulling from ../a
--- a/tests/test-hup.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-hup.out	Tue May 11 17:03:44 2010 -0500
@@ -4,4 +4,4 @@
 transaction abort!
 rollback completed
 killed!
-.hg/00changelog.i .hg/journal.branch .hg/journal.dirstate .hg/requires .hg/store .hg/store/00changelog.i .hg/store/00changelog.i.a
+.hg/00changelog.i .hg/journal.branch .hg/journal.desc .hg/journal.dirstate .hg/requires .hg/store .hg/store/00changelog.i .hg/store/00changelog.i.a
--- a/tests/test-import.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-import.out	Tue May 11 17:03:44 2010 -0500
@@ -182,7 +182,7 @@
 applying ../patch1
 applying ../patch2
 applied 1d4bd90af0e4
-rolling back last transaction
+rolling back to revision 2 (undo commit)
 parent: 1
 % hg import in a subdirectory
 requesting all changes
--- a/tests/test-inherit-mode.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-inherit-mode.out	Tue May 11 17:03:44 2010 -0500
@@ -26,6 +26,7 @@
 00660 ./.hg/store/fncache
 00660 ./.hg/store/undo
 00660 ./.hg/undo.branch
+00660 ./.hg/undo.desc
 00660 ./.hg/undo.dirstate
 00700 ./dir/
 00600 ./dir/bar
@@ -54,4 +55,5 @@
 00660 ../push/.hg/store/fncache
 00660 ../push/.hg/store/undo
 00660 ../push/.hg/undo.branch
+00660 ../push/.hg/undo.desc
 00660 ../push/.hg/undo.dirstate
--- a/tests/test-keyword	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-keyword	Tue May 11 17:03:44 2010 -0500
@@ -5,7 +5,10 @@
 keyword =
 mq =
 notify =
+record =
 transplant =
+[ui]
+interactive = true
 EOF
 
 # demo before [keyword] files are set up
@@ -21,7 +24,7 @@
 
 cat <<EOF >> $HGRCPATH
 [keyword]
-* =
+** =
 b = ignore
 [hooks]
 commit=
@@ -139,12 +142,29 @@
 echo % compare changenodes in a c
 cat a c
 
-echo % qinit -c
-hg qinit -c
+echo % record
+python -c \
+'l=open("a").readlines();l.insert(1,"foo\n");l.append("bar\n");open("a","w").writelines(l);'
+hg record -d '1 10' -m rectest<<EOF
+y
+y
+n
+EOF
+echo
+hg identify
+hg status
+echo % cat modified file
+cat a
+hg diff | grep -v 'b/a'
+hg rollback
+hg update -C
+
+echo % init --mq
+hg init --mq
 echo % qimport
 hg qimport -r tip -n mqtest.diff
-echo % qcommit
-hg qcommit -mqtest
+echo % commit --mq
+hg commit --mq -m mqtest
 echo % keywords should not be expanded in patch
 cat .hg/patches/mqtest.diff
 echo % qpop
@@ -153,6 +173,10 @@
 hg qgoto mqtest.diff
 echo % cat
 cat c
+echo % hg cat
+hg cat c
+echo % keyword should not be expanded in filelog
+hg --config 'extensions.keyword=!' cat c
 echo % qpop and move on
 hg qpop
 
--- a/tests/test-keyword.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-keyword.out	Tue May 11 17:03:44 2010 -0500
@@ -1,6 +1,6 @@
 % hg kwdemo
 [extensions]
-keyword = 
+keyword =
 [keyword]
 demo.txt = 
 [keywordmaps]
@@ -21,7 +21,7 @@
 $Revision: xxxxxxxxxxxx $
 $Source: /TMP/demo.txt,v $
 [extensions]
-keyword = 
+keyword =
 [keyword]
 demo.txt = 
 [keywordmaps]
@@ -132,9 +132,42 @@
 xxx $
 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
 tests for different changenodes
-% qinit -c
+% record
+diff --git a/a b/a
+2 hunks, 2 lines changed
+examine changes to 'a'? [Ynsfdaq?] 
+@@ -1,3 +1,4 @@
+ expand $Id$
++foo
+ do not process $Id:
+ xxx $
+record change 1/2 to 'a'? [Ynsfdaq?] 
+@@ -2,2 +3,3 @@
+ do not process $Id:
+ xxx $
++bar
+record change 2/2 to 'a'? [Ynsfdaq?] 
+
+d17e03c92c97+ tip
+M a
+% cat modified file
+expand $Id: a,v d17e03c92c97 1970/01/01 00:00:01 test $
+foo
+do not process $Id:
+xxx $
+bar
+diff -r d17e03c92c97 a
+--- a/a	Wed Dec 31 23:59:51 1969 -0000
+@@ -2,3 +2,4 @@
+ foo
+ do not process $Id:
+ xxx $
++bar
+rolling back to revision 3 (undo commit)
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+% init --mq
 % qimport
-% qcommit
+% commit --mq
 % keywords should not be expanded in patch
 # HG changeset patch
 # User User Name <user@example.com>
@@ -158,6 +191,12 @@
 % cat
 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
 tests for different changenodes
+% hg cat
+$Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
+tests for different changenodes
+% keyword should not be expanded in filelog
+$Id$
+tests for different changenodes
 % qpop and move on
 popping mqtest.diff
 patch queue now empty
@@ -198,7 +237,7 @@
 +do not process $Id:
 +xxx $
 % rollback
-rolling back last transaction
+rolling back to revision 2 (undo commit)
 % status
 A c
 % update -C
@@ -206,9 +245,9 @@
 % custom keyword expansion
 % try with kwdemo
 [extensions]
-keyword = 
+keyword =
 [keyword]
-* = 
+** = 
 b = ignore
 demo.txt = 
 [keywordmaps]
@@ -266,7 +305,7 @@
 % status
 ? c
 % rollback
-rolling back last transaction
+rolling back to revision 3 (undo commit)
 % status
 R a
 ? c
@@ -308,7 +347,7 @@
 ignore $Id$
 
 % rollback
-rolling back last transaction
+rolling back to revision 3 (undo commit)
 % clean update
 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 % kwexpand/kwshrink on selected files
--- a/tests/test-log	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-log	Tue May 11 17:03:44 2010 -0500
@@ -118,6 +118,13 @@
 echo '% log -d -1'
 hg log -d -1
 
+echo '% log -p -l2 --color=always'
+hg --config extensions.color= --config color.mode=ansi \
+    log -p -l2 --color=always
+
+echo '% log -r tip --stat'
+hg log -r tip --stat
+
 cd ..
 
 hg init usertest
@@ -132,4 +139,46 @@
 hg log -u "user1" -u "user2"
 hg log -u "user3"
 
+cd ..
+
+hg init branches
+cd branches
+
+echo a > a
+hg ci -A -m "commit on default"
+hg branch test
+echo b > b
+hg ci -A -m "commit on test"
+
+hg up default
+echo c > c
+hg ci -A -m "commit on default"
+hg up test
+echo c > c
+hg ci -A -m "commit on test"
+
+echo '% log -b default'
+hg log -b default
+
+echo '% log -b test'
+hg log -b test
+
+echo '% log -b dummy'
+hg log -b dummy
+
+echo '% log -b .'
+hg log -b .
+
+echo '% log -b default -b test'
+hg log -b default -b test
+
+echo '% log -b default -b .'
+hg log -b default -b .
+
+echo '% log -b . -b test'
+hg log -b . -b test
+
+echo '% log -b 2'
+hg log -b 2
+
 exit 0
--- a/tests/test-log.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-log.out	Tue May 11 17:03:44 2010 -0500
@@ -279,6 +279,43 @@
 summary:     r1
 
 % log -d -1
+% log -p -l2 --color=always
+changeset:   6:2404bbcab562
+tag:         tip
+user:        test
+date:        Thu Jan 01 00:00:01 1970 +0000
+summary:     b1.1
+
+diff -r 302e9dd6890d -r 2404bbcab562 b1
+--- a/b1	Thu Jan 01 00:00:01 1970 +0000
++++ b/b1	Thu Jan 01 00:00:01 1970 +0000
+@@ -1,1 +1,2 @@
+ b1
++postm
+
+changeset:   5:302e9dd6890d
+parent:      3:e62f78d544b4
+parent:      4:ddb82e70d1a1
+user:        test
+date:        Thu Jan 01 00:00:01 1970 +0000
+summary:     m12
+
+diff -r e62f78d544b4 -r 302e9dd6890d b2
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/b2	Thu Jan 01 00:00:01 1970 +0000
+@@ -0,0 +1,1 @@
++b2
+
+% log -r tip --stat
+changeset:   6:2404bbcab562
+tag:         tip
+user:        test
+date:        Thu Jan 01 00:00:01 1970 +0000
+summary:     b1.1
+
+ b1 |  1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
 adding a
 adding b
 changeset:   0:29a4c94f1924
@@ -297,3 +334,134 @@
 date:        Thu Jan 01 00:00:00 1970 +0000
 summary:     a
 
+adding a
+marked working directory as branch test
+adding b
+0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+adding c
+created new head
+1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+adding c
+% log -b default
+changeset:   2:c3a4f03cc9a7
+parent:      0:24427303d56f
+user:        test
+date:        Thu Jan 01 00:00:00 1970 +0000
+summary:     commit on default
+
+changeset:   0:24427303d56f
+user:        test
+date:        Thu Jan 01 00:00:00 1970 +0000
+summary:     commit on default
+
+% log -b test
+changeset:   3:f5d8de11c2e2
+branch:      test
+tag:         tip
+parent:      1:d32277701ccb
+user:        test
+date:        Thu Jan 01 00:00:00 1970 +0000
+summary:     commit on test
+
+changeset:   1:d32277701ccb
+branch:      test
+user:        test
+date:        Thu Jan 01 00:00:00 1970 +0000
+summary:     commit on test
+
+% log -b dummy
+abort: unknown revision 'dummy'!
+% log -b .
+changeset:   3:f5d8de11c2e2
+branch:      test
+tag:         tip
+parent:      1:d32277701ccb
+user:        test
+date:        Thu Jan 01 00:00:00 1970 +0000
+summary:     commit on test
+
+changeset:   1:d32277701ccb
+branch:      test
+user:        test
+date:        Thu Jan 01 00:00:00 1970 +0000
+summary:     commit on test
+
+% log -b default -b test
+changeset:   3:f5d8de11c2e2
+branch:      test
+tag:         tip
+parent:      1:d32277701ccb
+user:        test
+date:        Thu Jan 01 00:00:00 1970 +0000
+summary:     commit on test
+
+changeset:   2:c3a4f03cc9a7
+parent:      0:24427303d56f
+user:        test
+date:        Thu Jan 01 00:00:00 1970 +0000
+summary:     commit on default
+
+changeset:   1:d32277701ccb
+branch:      test
+user:        test
+date:        Thu Jan 01 00:00:00 1970 +0000
+summary:     commit on test
+
+changeset:   0:24427303d56f
+user:        test
+date:        Thu Jan 01 00:00:00 1970 +0000
+summary:     commit on default
+
+% log -b default -b .
+changeset:   3:f5d8de11c2e2
+branch:      test
+tag:         tip
+parent:      1:d32277701ccb
+user:        test
+date:        Thu Jan 01 00:00:00 1970 +0000
+summary:     commit on test
+
+changeset:   2:c3a4f03cc9a7
+parent:      0:24427303d56f
+user:        test
+date:        Thu Jan 01 00:00:00 1970 +0000
+summary:     commit on default
+
+changeset:   1:d32277701ccb
+branch:      test
+user:        test
+date:        Thu Jan 01 00:00:00 1970 +0000
+summary:     commit on test
+
+changeset:   0:24427303d56f
+user:        test
+date:        Thu Jan 01 00:00:00 1970 +0000
+summary:     commit on default
+
+% log -b . -b test
+changeset:   3:f5d8de11c2e2
+branch:      test
+tag:         tip
+parent:      1:d32277701ccb
+user:        test
+date:        Thu Jan 01 00:00:00 1970 +0000
+summary:     commit on test
+
+changeset:   1:d32277701ccb
+branch:      test
+user:        test
+date:        Thu Jan 01 00:00:00 1970 +0000
+summary:     commit on test
+
+% log -b 2
+changeset:   2:c3a4f03cc9a7
+parent:      0:24427303d56f
+user:        test
+date:        Thu Jan 01 00:00:00 1970 +0000
+summary:     commit on default
+
+changeset:   0:24427303d56f
+user:        test
+date:        Thu Jan 01 00:00:00 1970 +0000
+summary:     commit on default
+
--- a/tests/test-minirst.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-minirst.py	Tue May 11 17:03:44 2010 -0500
@@ -178,3 +178,22 @@
 debugformat('containers (debug)', containers, 60, keep=['debug'])
 debugformat('containers (verbose debug)', containers, 60,
             keep=['verbose', 'debug'])
+
+roles = """Please see :hg:`add`."""
+debugformat('roles', roles, 60)
+
+
+sections = """
+Title
+=====
+
+Section
+-------
+
+Subsection
+''''''''''
+
+Markup: ``foo`` and :hg:`help`
+------------------------------
+"""
+debugformat('sections', sections, 20)
--- a/tests/test-minirst.py.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-minirst.py.out	Tue May 11 17:03:44 2010 -0500
@@ -25,10 +25,12 @@
 ----------------------------------------------------------------------
 A Term
   Definition. The indented lines make up the definition.
+
 Another Term
     Another definition. The final line in the definition
     determines the indentation, so this will be indented
     with four spaces.
+
   A Nested/Indented Term
     Definition.
 ----------------------------------------------------------------------
@@ -39,6 +41,7 @@
   Definition. The indented
   lines make up the
   definition.
+
 Another Term
     Another definition. The
     final line in the
@@ -46,6 +49,7 @@
     indentation, so this will
     be indented with four
     spaces.
+
   A Nested/Indented Term
     Definition.
 ----------------------------------------------------------------------
@@ -294,3 +298,23 @@
 []
 ----------------------------------------------------------------------
 
+roles formatted to fit within 60 characters:
+----------------------------------------------------------------------
+Please see "hg add".
+----------------------------------------------------------------------
+
+sections formatted to fit within 20 characters:
+----------------------------------------------------------------------
+Title
+=====
+
+Section
+-------
+
+Subsection
+''''''''''
+
+Markup: "foo" and "hg help"
+---------------------------
+----------------------------------------------------------------------
+
--- a/tests/test-mq	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-mq	Tue May 11 17:03:44 2010 -0500
@@ -170,7 +170,9 @@
 COLUMNS=20 hg qseries --config ui.interactive=true -vs
 hg qpop
 hg qseries -vs
+hg sum | grep mq
 hg qpush
+hg sum | grep mq
 
 echo % qapplied
 hg qapplied
@@ -219,6 +221,19 @@
 hg qpop test2.patch-2
 hg qpush test1b.patch+1
 
+echo % qpush --move
+hg qpop -a
+hg qpush --move test2.patch # move to front
+hg qpush --move test1b.patch
+hg qpush --move test.patch # noop move
+hg qseries -v
+hg qpop -a
+hg qpush --move test.patch # cleaning up
+hg qpush --move test1b.patch
+hg qpush --move bogus # nonexistent patch
+hg qpush --move test.patch # already applied
+hg qpush
+
 echo % pop, qapplied, qunapplied
 hg qseries -v
 echo % qapplied -1 test.patch
--- a/tests/test-mq-guards	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-mq-guards	Tue May 11 17:03:44 2010 -0500
@@ -99,6 +99,9 @@
 hg qselect 1 2 3
 echo % list patches and guards
 hg qguard -l
+echo % list patches and guards with color
+hg --config extensions.color= qguard --config color.mode=ansi \
+    -l --color=always
 echo % list series
 hg qseries -v
 echo % list guards
@@ -125,6 +128,8 @@
 echo % should show new.patch and b.patch as Guarded, c.patch as Applied
 echo % and d.patch as Unapplied
 hg qseries -v
+echo % qseries again, but with color
+hg --config extensions.color= qseries -v --color=always
 
 hg qguard d.patch +2
 echo % new.patch, b.patch: Guarded. c.patch: Applied. d.patch: Guarded.
@@ -159,3 +164,5 @@
 echo the guards file was not ignored in the past
 hg qdelete -k b.patch
 hg qseries -m
+echo % hg qseries -m with color
+hg --config extensions.color= qseries -m --color=always
--- a/tests/test-mq-guards.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-mq-guards.out	Tue May 11 17:03:44 2010 -0500
@@ -84,6 +84,10 @@
 a.patch: +1 +2 -3
 b.patch: +2
 c.patch: unguarded
+% list patches and guards with color
+a.patch: +1 +2 -3
+b.patch: +2
+c.patch: unguarded
 % list series
 0 G a.patch
 1 U b.patch
@@ -126,6 +130,11 @@
 1 G b.patch
 2 A c.patch
 3 U d.patch
+% qseries again, but with color
+0 G new.patch
+1 G b.patch
+2 A c.patch
+3 U d.patch
 % new.patch, b.patch: Guarded. c.patch: Applied. d.patch: Guarded.
 0 G new.patch
 1 G b.patch
@@ -206,3 +215,5 @@
 % hg qseries -m: only b.patch should be shown
 the guards file was not ignored in the past
 b.patch
+% hg qseries -m with color
+b.patch
--- a/tests/test-mq-qdiff	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-mq-qdiff	Tue May 11 17:03:44 2010 -0500
@@ -68,3 +68,5 @@
 echo a >> lines
 hg qdiff
 
+echo % qdiff --stat
+hg qdiff --stat
--- a/tests/test-mq-qdiff.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-mq-qdiff.out	Tue May 11 17:03:44 2010 -0500
@@ -122,3 +122,6 @@
  8
  9
 +a
+% qdiff --stat
+ lines |  7 +++++--
+ 1 files changed, 5 insertions(+), 2 deletions(-)
--- a/tests/test-mq-qimport.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-mq-qimport.out	Tue May 11 17:03:44 2010 -0500
@@ -6,10 +6,10 @@
 now at: email
 % hg tip -v
 changeset:   0:1a706973a7d8
+tag:         email
+tag:         qbase
 tag:         qtip
 tag:         tip
-tag:         email
-tag:         qbase
 user:        Username in patch <test@example.net>
 date:        Thu Jan 01 00:00:00 1970 +0000
 files:       x
--- a/tests/test-mq.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-mq.out	Tue May 11 17:03:44 2010 -0500
@@ -151,8 +151,10 @@
 now at: test.patch
 0 A test.patch: foo bar
 1 U test2.patch: 
+mq:     1 applied, 1 unapplied
 applying test2.patch
 now at: test2.patch
+mq:     2 applied
 % qapplied
 test.patch
 test2.patch
@@ -193,6 +195,32 @@
 applying test1b.patch
 applying test2.patch
 now at: test2.patch
+% qpush --move
+popping test2.patch
+popping test1b.patch
+popping test.patch
+patch queue now empty
+applying test2.patch
+now at: test2.patch
+applying test1b.patch
+now at: test1b.patch
+applying test.patch
+now at: test.patch
+0 A test2.patch
+1 A test1b.patch
+2 A test.patch
+popping test.patch
+popping test1b.patch
+popping test2.patch
+patch queue now empty
+applying test.patch
+now at: test.patch
+applying test1b.patch
+now at: test1b.patch
+abort: patch bogus not in series
+abort: cannot push to a previous patch: test.patch
+applying test2.patch
+now at: test2.patch
 % pop, qapplied, qunapplied
 0 A test.patch
 1 A test1b.patch
@@ -357,8 +385,8 @@
 ? foo.rej
 % mq tags
 0 qparent
-1 qbase foo
-2 qtip bar tip
+1 foo qbase
+2 bar qtip tip
 % bad node in status
 popping bar
 now at: foo
@@ -577,10 +605,10 @@
  hello
 +world
 changeset:   1:bf5fc3f07a0a
+tag:         empty
+tag:         qbase
 tag:         qtip
 tag:         tip
-tag:         empty
-tag:         qbase
 user:        test
 date:        Thu Jan 01 00:00:00 1970 +0000
 summary:     imported patch empty
--- a/tests/test-newbranch.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-newbranch.out	Tue May 11 17:03:44 2010 -0500
@@ -62,7 +62,7 @@
 default
 bar
 % test for invalid branch cache
-rolling back last transaction
+rolling back to revision 5 (undo commit)
 changeset:   4:4909a3732169
 branch:      foo
 tag:         tip
--- a/tests/test-notify.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-notify.out	Tue May 11 17:03:44 2010 -0500
@@ -95,10 +95,10 @@
 +a
 (run 'hg update' to get a working copy)
 % fail for config file is missing
-rolling back last transaction
+rolling back to revision 1 (undo pull)
 pull failed
 % pull
-rolling back last transaction
+rolling back to revision 1 (undo pull)
 pulling from ../a
 searching for changes
 adding changesets
@@ -129,7 +129,7 @@
 +a
 (run 'hg update' to get a working copy)
 % pull
-rolling back last transaction
+rolling back to revision 1 (undo pull)
 pulling from ../a
 searching for changes
 adding changesets
--- a/tests/test-patchbomb	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-patchbomb	Tue May 11 17:03:44 2010 -0500
@@ -126,10 +126,23 @@
 hg email --date '1970-1-1 0:1' -n --intro -f quux -t foo -c bar -s test \
   -r 2 | fixheaders
 
+echo "% test --desc without --intro for a single patch"
+echo foo > intro.text
+hg email --date '1970-1-1 0:1' -n --desc intro.text -f quux -t foo -c bar \
+  -s test -r 2 | fixheaders
+
 echo "% test intro for multiple patches"
 hg email --date '1970-1-1 0:1' -n --intro -f quux -t foo -c bar -s test \
   -r 0:1 | fixheaders
 
+echo "% test reply-to via config"
+hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -r 2 \
+  --config patchbomb.reply-to='baz@example.com' | fixheaders
+
+echo "% test reply-to via command line"
+hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -r 2 \
+  --reply-to baz --reply-to fred | fixheaders
+
 echo "% tagging csets"
 hg tag -r0 zero zero.foo
 hg tag -r1 one one.patch
--- a/tests/test-patchbomb.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-patchbomb.out	Tue May 11 17:03:44 2010 -0500
@@ -940,6 +940,52 @@
 @@ -0,0 +1,1 @@
 +c
 
+% test --desc without --intro for a single patch
+This patch series consists of 1 patches.
+
+
+Displaying [PATCH 0 of 1] test ...
+Content-Type: text/plain; charset="us-ascii"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [PATCH 0 of 1] test
+Message-Id: <patchbomb.60@
+User-Agent: Mercurial-patchbomb
+Date: Thu, 01 Jan 1970 00:01:00 +0000
+From: quux
+To: foo
+Cc: bar
+
+foo
+
+Displaying [PATCH 1 of 1] c ...
+Content-Type: text/plain; charset="us-ascii"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [PATCH 1 of 1] c
+X-Mercurial-Node: ff2c9fa2018b15fa74b33363bda9527323e2a99f
+Message-Id: <ff2c9fa2018b15fa74b3.61@
+In-Reply-To: <patchbomb.60@
+References: <patchbomb.60@
+User-Agent: Mercurial-patchbomb
+Date: Thu, 01 Jan 1970 00:01:01 +0000
+From: quux
+To: foo
+Cc: bar
+
+# HG changeset patch
+# User test
+# Date 3 0
+# Node ID ff2c9fa2018b15fa74b33363bda9527323e2a99f
+# Parent  97d72e5f12c7e84f85064aa72e5a297142c36ed9
+c
+
+diff -r 97d72e5f12c7 -r ff2c9fa2018b c
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/c	Thu Jan 01 00:00:03 1970 +0000
+@@ -0,0 +1,1 @@
++c
+
 % test intro for multiple patches
 This patch series consists of 2 patches.
 
@@ -1016,6 +1062,68 @@
 @@ -0,0 +1,1 @@
 +b
 
+% test reply-to via config
+This patch series consists of 1 patches.
+
+
+Displaying [PATCH] test ...
+Content-Type: text/plain; charset="us-ascii"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [PATCH] test
+X-Mercurial-Node: ff2c9fa2018b15fa74b33363bda9527323e2a99f
+Message-Id: <ff2c9fa2018b15fa74b3.60@
+User-Agent: Mercurial-patchbomb
+Date: Thu, 01 Jan 1970 00:01:00 +0000
+From: quux
+To: foo
+Cc: bar
+Reply-To: baz@example.com
+
+# HG changeset patch
+# User test
+# Date 3 0
+# Node ID ff2c9fa2018b15fa74b33363bda9527323e2a99f
+# Parent  97d72e5f12c7e84f85064aa72e5a297142c36ed9
+c
+
+diff -r 97d72e5f12c7 -r ff2c9fa2018b c
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/c	Thu Jan 01 00:00:03 1970 +0000
+@@ -0,0 +1,1 @@
++c
+
+% test reply-to via command line
+This patch series consists of 1 patches.
+
+
+Displaying [PATCH] test ...
+Content-Type: text/plain; charset="us-ascii"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [PATCH] test
+X-Mercurial-Node: ff2c9fa2018b15fa74b33363bda9527323e2a99f
+Message-Id: <ff2c9fa2018b15fa74b3.60@
+User-Agent: Mercurial-patchbomb
+Date: Thu, 01 Jan 1970 00:01:00 +0000
+From: quux
+To: foo
+Cc: bar
+Reply-To: baz, fred
+
+# HG changeset patch
+# User test
+# Date 3 0
+# Node ID ff2c9fa2018b15fa74b33363bda9527323e2a99f
+# Parent  97d72e5f12c7e84f85064aa72e5a297142c36ed9
+c
+
+diff -r 97d72e5f12c7 -r ff2c9fa2018b c
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/c	Thu Jan 01 00:00:03 1970 +0000
+@@ -0,0 +1,1 @@
++c
+
 % tagging csets
 % test inline for single named patch
 This patch series consists of 1 patches.
--- a/tests/test-progress	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-progress	Tue May 11 17:03:44 2010 -0500
@@ -8,6 +8,8 @@
     total = None
     if loops >= 0:
         total = loops
+    if opts.get('total', None):
+        total = int(opts.get('total'))
     loops = abs(loops)
 
     for i in range(loops):
@@ -17,7 +19,8 @@
 commands.norepo += " loop"
 
 cmdtable = {
-    "loop": (loop, [], 'hg loop LOOPS'),
+    "loop": (loop, [('', 'total', '', 'override for total')],
+             'hg loop LOOPS'),
 }
 EOF
 
@@ -55,5 +58,8 @@
 echo '% test format options and indeterminate progress'
 hg -y --config 'progress.format=number item bar' loop -- -2 2>&1 | python filtercr.py
 
+echo "% make sure things don't fall over if count > total"
+hg -y loop --total 4 6 2>&1 | python filtercr.py
+
 echo '% test immediate progress completion'
 hg -y loop 0 2>&1 | python filtercr.py
--- a/tests/test-progress.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-progress.out	Tue May 11 17:03:44 2010 -0500
@@ -17,4 +17,12 @@
 
 0 loop.0               [ <=>                                                  ]
 1 loop.1               [  <=>                                                 ]
+                                                                                
% make sure things don't fall over if count > total
+
+loop [                                                                    ] 0/4
+loop [================>                                                   ] 1/4
+loop [=================================>                                  ] 2/4
+loop [==================================================>                 ] 3/4
+loop [===================================================================>] 4/4
+loop [ <=>                                                                ] 5/4
                                                                                 
% test immediate progress completion
--- a/tests/test-pull	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-pull	Tue May 11 17:03:44 2010 -0500
@@ -11,13 +11,14 @@
 cat hg.pid >> $DAEMON_PIDS
 cd ..
 
-hg clone --pull http://localhost:$HGPORT/ copy | sed -e "s,:$HGPORT/,:\$HGPORT/,"
+hg clone --pull http://foo:bar@localhost:$HGPORT/ copy | sed -e "s,:$HGPORT/,:\$HGPORT/,"
 cd copy
 hg verify
 hg co
 cat foo
 hg manifest --debug
 hg pull | sed -e "s,:$HGPORT/,:\$HGPORT/,"
+hg rollback --dry-run --verbose | sed -e "s,:$HGPORT/,:\$HGPORT/,"
 
 echo % issue 622
 cd ..
--- a/tests/test-pull-r.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-pull-r.out	Tue May 11 17:03:44 2010 -0500
@@ -19,7 +19,7 @@
 abort: unknown revision 'missing'!
 % pull multiple revisions with update
 0:bbd179dfa0a7
-rolling back last transaction
+rolling back to revision 0 (undo pull)
 % pull -r 0
 changeset:   0:bbd179dfa0a7
 tag:         tip
--- a/tests/test-pull.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-pull.out	Tue May 11 17:03:44 2010 -0500
@@ -19,9 +19,10 @@
 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
 foo
 2ed2a3912a0b24502043eae84ee4b279c18b90dd 644   foo
-pulling from http://localhost:$HGPORT/
+pulling from http://foo:***@localhost:$HGPORT/
 searching for changes
 no changes found
+rolling back to revision 0 (undo pull: http://foo:***@localhost:$HGPORT/)
 % issue 622
 pulling from ../test
 requesting all changes
--- a/tests/test-push-http.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-push-http.out	Tue May 11 17:03:44 2010 -0500
@@ -25,7 +25,7 @@
 remote: added 1 changesets with 1 changes to 1 files
 % serve errors
 changegroup hook: HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_URL=remote:http 
-rolling back last transaction
+rolling back to revision 1 (undo serve)
 % expect authorization error: all users denied
 abort: authorization failed
 pushing to http://localhost:$HGPORT/
--- a/tests/test-qrecord.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-qrecord.out	Tue May 11 17:03:44 2010 -0500
@@ -17,10 +17,10 @@
  pull       pull changes from the specified source
  push       push changes to the specified destination
  remove     remove the specified files on the next commit
- serve      export the repository via HTTP
+ serve      start stand-alone webserver
  status     show changed files in the working directory
  summary    summarize working directory state
- update     update working directory
+ update     update working directory (or switch revisions)
 
 use "hg help" for the full list of commands or "hg -v" for details
 % help (mq present)
@@ -28,7 +28,7 @@
 
 interactively record a new patch
 
-    See 'hg help qnew' & 'hg help record' for more information and usage.
+    See "hg help qnew" & "hg help record" for more information and usage.
 
 options:
 
@@ -80,34 +80,40 @@
 % qrecord a.patch
 diff --git a/1.txt b/1.txt
 2 hunks, 4 lines changed
-examine changes to '1.txt'? [Ynsfdaq?] @@ -1,3 +1,3 @@
+examine changes to '1.txt'? [Ynsfdaq?] 
+@@ -1,3 +1,3 @@
  1
 -2
 +2 2
  3
-record change 1/6 to '1.txt'? [Ynsfdaq?] @@ -3,3 +3,3 @@
+record change 1/6 to '1.txt'? [Ynsfdaq?] 
+@@ -3,3 +3,3 @@
  3
 -4
 +4 4
  5
-record change 2/6 to '1.txt'? [Ynsfdaq?] diff --git a/2.txt b/2.txt
+record change 2/6 to '1.txt'? [Ynsfdaq?] 
+diff --git a/2.txt b/2.txt
 1 hunks, 2 lines changed
-examine changes to '2.txt'? [Ynsfdaq?] @@ -1,5 +1,5 @@
+examine changes to '2.txt'? [Ynsfdaq?] 
+@@ -1,5 +1,5 @@
  a
 -b
 +b b
  c
  d
  e
-record change 4/6 to '2.txt'? [Ynsfdaq?] diff --git a/dir/a.txt b/dir/a.txt
+record change 4/6 to '2.txt'? [Ynsfdaq?] 
+diff --git a/dir/a.txt b/dir/a.txt
 1 hunks, 2 lines changed
 examine changes to 'dir/a.txt'? [Ynsfdaq?] 
+
 % after qrecord a.patch 'tip'
 changeset:   1:5d1ca63427ee
+tag:         a.patch
+tag:         qbase
 tag:         qtip
 tag:         tip
-tag:         a.patch
-tag:         qbase
 user:        test
 date:        Thu Jan 01 00:00:00 1970 +0000
 summary:     aaa
@@ -157,27 +163,31 @@
 % qrecord b.patch
 diff --git a/1.txt b/1.txt
 1 hunks, 2 lines changed
-examine changes to '1.txt'? [Ynsfdaq?] @@ -1,5 +1,5 @@
+examine changes to '1.txt'? [Ynsfdaq?] 
+@@ -1,5 +1,5 @@
  1
  2 2
  3
 -4
 +4 4
  5
-record change 1/3 to '1.txt'? [Ynsfdaq?] diff --git a/dir/a.txt b/dir/a.txt
+record change 1/3 to '1.txt'? [Ynsfdaq?] 
+diff --git a/dir/a.txt b/dir/a.txt
 1 hunks, 2 lines changed
-examine changes to 'dir/a.txt'? [Ynsfdaq?] @@ -1,4 +1,4 @@
+examine changes to 'dir/a.txt'? [Ynsfdaq?] 
+@@ -1,4 +1,4 @@
 -hello world
 +hello world!
  
  someone
  up
 record change 3/3 to 'dir/a.txt'? [Ynsfdaq?] 
+
 % after qrecord b.patch 'tip'
 changeset:   2:b056198bf878
+tag:         b.patch
 tag:         qtip
 tag:         tip
-tag:         b.patch
 user:        test
 date:        Thu Jan 01 00:00:00 1970 +0000
 summary:     bbb
--- a/tests/test-rebase-mq-skip.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-rebase-mq-skip.out	Tue May 11 17:03:44 2010 -0500
@@ -13,7 +13,7 @@
 adding file changes
 added 2 changesets with 2 changes to 2 files
 rebase completed
-@  3 P0 tags: p0.patch qtip tip qbase
+@  3 P0 tags: p0.patch qbase qtip tip
 |
 o  2 P1 tags: qparent
 |
--- a/tests/test-rebase-mq.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-rebase-mq.out	Tue May 11 17:03:44 2010 -0500
@@ -1,5 +1,5 @@
 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-@  3 P1 tags: qtip tip f2.patch
+@  3 P1 tags: f2.patch qtip tip
 |
 o  2 P0 tags: f.patch qbase
 |
@@ -34,7 +34,7 @@
 adding file changes
 added 2 changesets with 2 changes to 1 files
 rebase completed
-@  3 P1 tags: qtip tip f2.patch
+@  3 P1 tags: f2.patch qtip tip
 |
 o  2 P0 tags: f.patch qbase
 |
--- a/tests/test-rebase-pull.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-rebase-pull.out	Tue May 11 17:03:44 2010 -0500
@@ -10,7 +10,6 @@
 adding manifests
 adding file changes
 added 1 changesets with 1 changes to 1 files (+1 heads)
-(run 'hg heads' to see heads, 'hg merge' to merge)
 saving bundle to 
 adding branch
 adding changesets
@@ -39,8 +38,8 @@
 adding manifests
 adding file changes
 added 1 changesets with 1 changes to 1 files
-(run 'hg update' to get a working copy)
 nothing to rebase
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 @  2
 |
 
--- a/tests/test-record	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-record	Tue May 11 17:03:44 2010 -0500
@@ -37,6 +37,10 @@
 EOF
 echo; hg tip -p
 
+echo % summary shows we updated to the new cset
+hg summary
+echo
+
 echo % rename empty file
 
 hg mv empty-rw empty-rename
@@ -315,4 +319,3 @@
 y
 EOF
 echo; hg tip -p
-
--- a/tests/test-record.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-record.out	Tue May 11 17:03:44 2010 -0500
@@ -6,7 +6,7 @@
     If a list of files is omitted, all changes reported by "hg status" will be
     candidates for recording.
 
-    See 'hg help dates' for a list of formats valid for -d/--date.
+    See "hg help dates" for a list of formats valid for -d/--date.
 
     You will be prompted for whether to record changes to each modified file,
     and for files with multiple changes, for each change to use. For each
@@ -39,7 +39,8 @@
 % select no files
 diff --git a/empty-rw b/empty-rw
 new file mode 100644
-examine changes to 'empty-rw'? [Ynsfdaq?] no changes to record
+examine changes to 'empty-rw'? [Ynsfdaq?] 
+no changes to record
 
 changeset:   -1:000000000000
 tag:         tip
@@ -50,7 +51,8 @@
 % select files but no hunks
 diff --git a/empty-rw b/empty-rw
 new file mode 100644
-examine changes to 'empty-rw'? [Ynsfdaq?] abort: empty commit message
+examine changes to 'empty-rw'? [Ynsfdaq?] 
+abort: empty commit message
 
 changeset:   -1:000000000000
 tag:         tip
@@ -62,6 +64,7 @@
 diff --git a/empty-rw b/empty-rw
 new file mode 100644
 examine changes to 'empty-rw'? [Ynsfdaq?] 
+
 changeset:   0:c0708cf4e46e
 tag:         tip
 user:        test
@@ -69,11 +72,19 @@
 summary:     empty
 
 
+% summary shows we updated to the new cset
+parent: 0:c0708cf4e46e tip
+ empty
+branch: default
+commit: (clean)
+update: (current)
+
 % rename empty file
 diff --git a/empty-rw b/empty-rename
 rename from empty-rw
 rename to empty-rename
 examine changes to 'empty-rw' and 'empty-rename'? [Ynsfdaq?] 
+
 changeset:   1:d695e8dcb197
 tag:         tip
 user:        test
@@ -86,6 +97,7 @@
 copy from empty-rename
 copy to empty-copy
 examine changes to 'empty-rename' and 'empty-copy'? [Ynsfdaq?] 
+
 changeset:   2:1d4b90bea524
 tag:         tip
 user:        test
@@ -97,6 +109,7 @@
 diff --git a/empty-copy b/empty-copy
 deleted file mode 100644
 examine changes to 'empty-copy'? [Ynsfdaq?] 
+
 changeset:   3:b39a238f01a1
 tag:         tip
 user:        test
@@ -110,6 +123,7 @@
 new file mode 100644
 this is a binary file
 examine changes to 'tip.bundle'? [Ynsfdaq?] 
+
 changeset:   4:ad816da3711e
 tag:         tip
 user:        test
@@ -124,6 +138,7 @@
 diff --git a/tip.bundle b/tip.bundle
 this modifies a binary file (all or nothing)
 examine changes to 'tip.bundle'? [Ynsfdaq?] 
+
 changeset:   5:dccd6f3eb485
 tag:         tip
 user:        test
@@ -140,6 +155,7 @@
 rename to top.bundle
 this modifies a binary file (all or nothing)
 examine changes to 'tip.bundle' and 'top.bundle'? [Ynsfdaq?] 
+
 changeset:   6:7fa44105f5b3
 tag:         tip
 user:        test
@@ -155,6 +171,7 @@
 diff --git a/plain b/plain
 new file mode 100644
 examine changes to 'plain'? [Ynsfdaq?] 
+
 changeset:   7:11fb457c1be4
 tag:         tip
 user:        test
@@ -179,46 +196,55 @@
 % modify end of plain file
 diff --git a/plain b/plain
 1 hunks, 1 lines changed
-examine changes to 'plain'? [Ynsfdaq?] @@ -8,3 +8,4 @@
+examine changes to 'plain'? [Ynsfdaq?] 
+@@ -8,3 +8,4 @@
  8
  9
  10
 +11
-record this change to 'plain'? [Ynsfdaq?] % modify end of plain file, no EOL
+record this change to 'plain'? [Ynsfdaq?] 
+% modify end of plain file, no EOL
 diff --git a/plain b/plain
 1 hunks, 1 lines changed
-examine changes to 'plain'? [Ynsfdaq?] @@ -9,3 +9,4 @@
+examine changes to 'plain'? [Ynsfdaq?] 
+@@ -9,3 +9,4 @@
  9
  10
  11
 +7264f99c5f5ff3261504828afa4fb4d406c3af54
 \ No newline at end of file
-record this change to 'plain'? [Ynsfdaq?] % modify end of plain file, add EOL
+record this change to 'plain'? [Ynsfdaq?] 
+% modify end of plain file, add EOL
 diff --git a/plain b/plain
 1 hunks, 2 lines changed
-examine changes to 'plain'? [Ynsfdaq?] @@ -9,4 +9,4 @@
+examine changes to 'plain'? [Ynsfdaq?] 
+@@ -9,4 +9,4 @@
  9
  10
  11
 -7264f99c5f5ff3261504828afa4fb4d406c3af54
 \ No newline at end of file
 +7264f99c5f5ff3261504828afa4fb4d406c3af54
-record this change to 'plain'? [Ynsfdaq?] % modify beginning, trim end, record both
+record this change to 'plain'? [Ynsfdaq?] 
+% modify beginning, trim end, record both
 diff --git a/plain b/plain
 2 hunks, 4 lines changed
-examine changes to 'plain'? [Ynsfdaq?] @@ -1,4 +1,4 @@
+examine changes to 'plain'? [Ynsfdaq?] 
+@@ -1,4 +1,4 @@
 -1
 +2
  2
  3
  4
-record change 1/2 to 'plain'? [Ynsfdaq?] @@ -8,5 +8,3 @@
+record change 1/2 to 'plain'? [Ynsfdaq?] 
+@@ -8,5 +8,3 @@
  8
  9
  10
 -11
 -7264f99c5f5ff3261504828afa4fb4d406c3af54
 record change 2/2 to 'plain'? [Ynsfdaq?] 
+
 changeset:   11:efca65c9b09e
 tag:         tip
 user:        test
@@ -245,7 +271,8 @@
 % record end
 diff --git a/plain b/plain
 2 hunks, 5 lines changed
-examine changes to 'plain'? [Ynsfdaq?] @@ -1,9 +1,6 @@
+examine changes to 'plain'? [Ynsfdaq?] 
+@@ -1,9 +1,6 @@
 -2
 -2
 -3
@@ -255,7 +282,8 @@
  7
  8
  9
-record change 1/2 to 'plain'? [Ynsfdaq?] @@ -4,7 +1,7 @@
+record change 1/2 to 'plain'? [Ynsfdaq?] 
+@@ -4,7 +1,7 @@
  4
  5
  6
@@ -265,6 +293,7 @@
 -10
 +10.new
 record change 2/2 to 'plain'? [Ynsfdaq?] 
+
 changeset:   12:7d1e66983c15
 tag:         tip
 user:        test
@@ -284,7 +313,8 @@
 % record beginning
 diff --git a/plain b/plain
 1 hunks, 3 lines changed
-examine changes to 'plain'? [Ynsfdaq?] @@ -1,6 +1,3 @@
+examine changes to 'plain'? [Ynsfdaq?] 
+@@ -1,6 +1,3 @@
 -2
 -2
 -3
@@ -292,6 +322,7 @@
  5
  6
 record this change to 'plain'? [Ynsfdaq?] 
+
 changeset:   13:a09fc62a0e61
 tag:         tip
 user:        test
@@ -313,7 +344,8 @@
 % record end
 diff --git a/plain b/plain
 2 hunks, 4 lines changed
-examine changes to 'plain'? [Ynsfdaq?] @@ -1,6 +1,9 @@
+examine changes to 'plain'? [Ynsfdaq?] 
+@@ -1,6 +1,9 @@
 +1
 +2
 +3
@@ -323,7 +355,8 @@
  7
  8
  9
-record change 1/2 to 'plain'? [Ynsfdaq?] @@ -1,7 +4,6 @@
+record change 1/2 to 'plain'? [Ynsfdaq?] 
+@@ -1,7 +4,6 @@
  4
  5
  6
@@ -331,17 +364,20 @@
  8
  9
 -10.new
-record change 2/2 to 'plain'? [Ynsfdaq?] % add to beginning, middle, end
+record change 2/2 to 'plain'? [Ynsfdaq?] 
+% add to beginning, middle, end
 % record beginning, middle
 diff --git a/plain b/plain
 3 hunks, 7 lines changed
-examine changes to 'plain'? [Ynsfdaq?] @@ -1,2 +1,5 @@
+examine changes to 'plain'? [Ynsfdaq?] 
+@@ -1,2 +1,5 @@
 +1
 +2
 +3
  4
  5
-record change 1/3 to 'plain'? [Ynsfdaq?] @@ -1,6 +4,8 @@
+record change 1/3 to 'plain'? [Ynsfdaq?] 
+@@ -1,6 +4,8 @@
  4
  5
 +5.new
@@ -350,7 +386,8 @@
  7
  8
  9
-record change 2/3 to 'plain'? [Ynsfdaq?] @@ -3,4 +8,6 @@
+record change 2/3 to 'plain'? [Ynsfdaq?] 
+@@ -3,4 +8,6 @@
  6
  7
  8
@@ -358,6 +395,7 @@
 +10
 +11
 record change 3/3 to 'plain'? [Ynsfdaq?] 
+
 changeset:   15:7d137997f3a6
 tag:         tip
 user:        test
@@ -382,13 +420,15 @@
 % record end
 diff --git a/plain b/plain
 1 hunks, 2 lines changed
-examine changes to 'plain'? [Ynsfdaq?] @@ -9,3 +9,5 @@
+examine changes to 'plain'? [Ynsfdaq?] 
+@@ -9,3 +9,5 @@
  7
  8
  9
 +10
 +11
 record this change to 'plain'? [Ynsfdaq?] 
+
 changeset:   16:4959e3ff13eb
 tag:         tip
 user:        test
@@ -408,10 +448,12 @@
 adding subdir/a
 diff --git a/subdir/a b/subdir/a
 1 hunks, 1 lines changed
-examine changes to 'subdir/a'? [Ynsfdaq?] @@ -1,1 +1,2 @@
+examine changes to 'subdir/a'? [Ynsfdaq?] 
+@@ -1,1 +1,2 @@
  a
 +a
 record this change to 'subdir/a'? [Ynsfdaq?] 
+
 changeset:   18:40698cd490b2
 tag:         tip
 user:        test
@@ -428,7 +470,8 @@
 % help, quit
 diff --git a/subdir/f1 b/subdir/f1
 1 hunks, 1 lines changed
-examine changes to 'subdir/f1'? [Ynsfdaq?] y - record this change
+examine changes to 'subdir/f1'? [Ynsfdaq?] 
+y - record this change
 n - skip this change
 s - skip remaining changes to this file
 f - record remaining changes to this file
@@ -436,31 +479,38 @@
 a - record all changes to all remaining files
 q - quit, recording no changes
 ? - display help
-examine changes to 'subdir/f1'? [Ynsfdaq?] abort: user quit
+examine changes to 'subdir/f1'? [Ynsfdaq?] 
+abort: user quit
 % skip
 diff --git a/subdir/f1 b/subdir/f1
 1 hunks, 1 lines changed
-examine changes to 'subdir/f1'? [Ynsfdaq?] diff --git a/subdir/f2 b/subdir/f2
+examine changes to 'subdir/f1'? [Ynsfdaq?] 
+diff --git a/subdir/f2 b/subdir/f2
 1 hunks, 1 lines changed
 examine changes to 'subdir/f2'? [Ynsfdaq?] abort: response expected
 % no
 diff --git a/subdir/f1 b/subdir/f1
 1 hunks, 1 lines changed
-examine changes to 'subdir/f1'? [Ynsfdaq?] diff --git a/subdir/f2 b/subdir/f2
+examine changes to 'subdir/f1'? [Ynsfdaq?] 
+diff --git a/subdir/f2 b/subdir/f2
 1 hunks, 1 lines changed
 examine changes to 'subdir/f2'? [Ynsfdaq?] abort: response expected
 % f, quit
 diff --git a/subdir/f1 b/subdir/f1
 1 hunks, 1 lines changed
-examine changes to 'subdir/f1'? [Ynsfdaq?] diff --git a/subdir/f2 b/subdir/f2
+examine changes to 'subdir/f1'? [Ynsfdaq?] 
+diff --git a/subdir/f2 b/subdir/f2
 1 hunks, 1 lines changed
-examine changes to 'subdir/f2'? [Ynsfdaq?] abort: user quit
+examine changes to 'subdir/f2'? [Ynsfdaq?] 
+abort: user quit
 % s, all
 diff --git a/subdir/f1 b/subdir/f1
 1 hunks, 1 lines changed
-examine changes to 'subdir/f1'? [Ynsfdaq?] diff --git a/subdir/f2 b/subdir/f2
+examine changes to 'subdir/f1'? [Ynsfdaq?] 
+diff --git a/subdir/f2 b/subdir/f2
 1 hunks, 1 lines changed
 examine changes to 'subdir/f2'? [Ynsfdaq?] 
+
 changeset:   20:d2d8c25276a8
 tag:         tip
 user:        test
@@ -478,6 +528,7 @@
 diff --git a/subdir/f1 b/subdir/f1
 1 hunks, 1 lines changed
 examine changes to 'subdir/f1'? [Ynsfdaq?] 
+
 changeset:   21:1013f51ce32f
 tag:         tip
 user:        test
@@ -496,11 +547,13 @@
 old mode 100644
 new mode 100755
 1 hunks, 1 lines changed
-examine changes to 'subdir/f1'? [Ynsfdaq?] @@ -1,2 +1,3 @@
+examine changes to 'subdir/f1'? [Ynsfdaq?] 
+@@ -1,2 +1,3 @@
  a
  a
 +a
 record this change to 'subdir/f1'? [Ynsfdaq?] 
+
 changeset:   22:5df857735621
 tag:         tip
 user:        test
@@ -520,12 +573,14 @@
 % preserve execute permission on original
 diff --git a/subdir/f1 b/subdir/f1
 1 hunks, 1 lines changed
-examine changes to 'subdir/f1'? [Ynsfdaq?] @@ -1,3 +1,4 @@
+examine changes to 'subdir/f1'? [Ynsfdaq?] 
+@@ -1,3 +1,4 @@
  a
  a
  a
 +b
 record this change to 'subdir/f1'? [Ynsfdaq?] 
+
 changeset:   23:a4ae36a78715
 tag:         tip
 user:        test
@@ -546,12 +601,14 @@
 old mode 100755
 new mode 100644
 1 hunks, 1 lines changed
-examine changes to 'subdir/f1'? [Ynsfdaq?] @@ -2,3 +2,4 @@
+examine changes to 'subdir/f1'? [Ynsfdaq?] 
+@@ -2,3 +2,4 @@
  a
  a
  b
 +c
 record this change to 'subdir/f1'? [Ynsfdaq?] 
+
 changeset:   24:1460f6e47966
 tag:         tip
 user:        test
@@ -572,12 +629,14 @@
 % with win32ext
 diff --git a/subdir/f1 b/subdir/f1
 1 hunks, 1 lines changed
-examine changes to 'subdir/f1'? [Ynsfdaq?] @@ -3,3 +3,4 @@
+examine changes to 'subdir/f1'? [Ynsfdaq?] 
+@@ -3,3 +3,4 @@
  a
  b
  c
 +d
 record this change to 'subdir/f1'? [Ynsfdaq?] 
+
 changeset:   25:5bacc1f6e9cf
 tag:         tip
 user:        test
--- a/tests/test-rename	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-rename	Tue May 11 17:03:44 2010 -0500
@@ -23,6 +23,9 @@
 hg update -C
 rm d2/c
 
+echo "# rename --after a single file to a nonexistant target filename"
+hg rename --after d1/a dummy
+
 echo "# move a single file to an existing directory"
 hg rename d1/d11/a1 d2
 hg status -C
--- a/tests/test-rename-after-merge.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-rename-after-merge.out	Tue May 11 17:03:44 2010 -0500
@@ -34,7 +34,7 @@
 (branch merge, don't forget to commit)
 % commit issue 1476
 copies:      c2 (c1)
-rolling back last transaction
+rolling back to revision 3 (undo commit)
 2 files updated, 0 files merged, 2 files removed, 0 files unresolved
 % merge heads again
 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
--- a/tests/test-rename.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-rename.out	Tue May 11 17:03:44 2010 -0500
@@ -8,6 +8,8 @@
   d1/d11/a1
 R d1/d11/a1
 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+# rename --after a single file to a nonexistant target filename
+d1/a: not recording move - dummy does not exist
 # move a single file to an existing directory
 A d2/a1
   d1/d11/a1
@@ -170,6 +172,8 @@
 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
 # move --after some files under d1 to d2/d21 (glob)
 moving d1/a to d2/d21/a
+d1/b: not recording move - d2/d21/b does not exist
+d1/ba: not recording move - d2/d21/ba does not exist
 moving d1/d11/a1 to d2/d21/a1
 A d2/d21/a
   d1/a
--- a/tests/test-rollback.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-rollback.out	Tue May 11 17:03:44 2010 -0500
@@ -9,7 +9,7 @@
 date:        Mon Jan 12 13:46:40 1970 +0000
 summary:     test
 
-rolling back last transaction
+rolling back to revision 0 (undo commit)
 checking changesets
 checking manifests
 crosschecking files in changesets and manifests
@@ -18,14 +18,14 @@
 A a
 % Test issue 902
 marked working directory as branch test
-rolling back last transaction
+rolling back to revision 0 (undo commit)
 default
 % Test issue 1635 (commit message saved)
 .hg/last-message.txt:
 test2
 % Test rollback of hg before issue 902 was fixed
 marked working directory as branch test
-rolling back last transaction
+rolling back to revision 0 (undo commit)
 Named branch could not be reset, current branch still is: test
 test
 % rollback by pretxncommit saves commit message (issue 1635)
--- a/tests/test-serve	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-serve	Tue May 11 17:03:44 2010 -0500
@@ -2,8 +2,10 @@
 
 hgserve()
 {
-    hg serve -a localhost -p $HGPORT1 -d --pid-file=hg.pid -E errors.log -v $@ \
-        | sed -e 's/:[0-9][0-9]*//g' -e 's/http:\/\/[^/]*\//http:\/\/localhost\//'
+    hg serve -a localhost -d --pid-file=hg.pid -E errors.log -v $@ \
+        | sed -e "s/:$HGPORT1\\([^0-9]\\)/:HGPORT1\1/g" \
+              -e "s/:$HGPORT2\\([^0-9]\\)/:HGPORT2\1/g" \
+              -e 's/http:\/\/[^/]*\//http:\/\/localhost\//'
     cat hg.pid >> "$DAEMON_PIDS"
     echo % errors
     cat errors.log
@@ -17,6 +19,7 @@
 
 echo '[web]' > .hg/hgrc
 echo 'accesslog = access.log' >> .hg/hgrc
+echo "port = $HGPORT1" >> .hg/hgrc
 
 echo % Without -v
 hg serve -a localhost -p $HGPORT -d --pid-file=hg.pid -E errors.log
@@ -30,6 +33,9 @@
 echo % With -v
 hgserve
 
+echo % With -v and -p HGPORT2
+hgserve -p "$HGPORT2"
+
 echo % With --prefix foo
 hgserve --prefix foo
 
--- a/tests/test-serve.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-serve.out	Tue May 11 17:03:44 2010 -0500
@@ -2,17 +2,20 @@
 access log created - .hg/hgrc respected
 % errors
 % With -v
-listening at http://localhost/ (bound to 127.0.0.1)
+listening at http://localhost/ (bound to 127.0.0.1:HGPORT1)
+% errors
+% With -v and -p HGPORT2
+listening at http://localhost/ (bound to 127.0.0.1:HGPORT2)
 % errors
 % With --prefix foo
-listening at http://localhost/foo/ (bound to 127.0.0.1)
+listening at http://localhost/foo/ (bound to 127.0.0.1:HGPORT1)
 % errors
 % With --prefix /foo
-listening at http://localhost/foo/ (bound to 127.0.0.1)
+listening at http://localhost/foo/ (bound to 127.0.0.1:HGPORT1)
 % errors
 % With --prefix foo/
-listening at http://localhost/foo/ (bound to 127.0.0.1)
+listening at http://localhost/foo/ (bound to 127.0.0.1:HGPORT1)
 % errors
 % With --prefix /foo/
-listening at http://localhost/foo/ (bound to 127.0.0.1)
+listening at http://localhost/foo/ (bound to 127.0.0.1:HGPORT1)
 % errors
--- a/tests/test-status-color	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-status-color	Tue May 11 17:03:44 2010 -0500
@@ -2,6 +2,8 @@
 
 echo "[extensions]" >> $HGRCPATH
 echo "color=" >> $HGRCPATH
+echo "[color]" >> $HGRCPATH
+echo "mode=ansi" >> $HGRCPATH
 
 hg init repo1
 cd repo1
--- a/tests/test-status-inprocess.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-status-inprocess.py	Tue May 11 17:03:44 2010 -0500
@@ -1,5 +1,4 @@
 #!/usr/bin/python
-import os
 from mercurial.ui import ui
 from mercurial.localrepo import localrepository
 from mercurial.commands import add, commit, status
--- a/tests/test-strict.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-strict.out	Tue May 11 17:03:44 2010 -0500
@@ -18,10 +18,10 @@
  pull       pull changes from the specified source
  push       push changes to the specified destination
  remove     remove the specified files on the next commit
- serve      export the repository via HTTP
+ serve      start stand-alone webserver
  status     show changed files in the working directory
  summary    summarize working directory state
- update     update working directory
+ update     update working directory (or switch revisions)
 
 use "hg help" for the full list of commands or "hg -v" for details
 0: a
--- a/tests/test-subrepo	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-subrepo	Tue May 11 17:03:44 2010 -0500
@@ -16,6 +16,7 @@
 hg init s
 echo a > s/a
 hg -R s ci -Ams0
+hg sum
 hg ci -m1
 
 echo % add sub sub
@@ -24,7 +25,9 @@
 echo a > s/ss/a
 hg -R s add s/.hgsub
 hg -R s/ss add s/ss/a
+hg sum
 hg ci -m2
+hg sum
 
 echo % bump sub rev
 echo b > s/a
@@ -78,7 +81,7 @@
 
 echo % clone
 cd ..
-hg clone t tc
+hg clone t tc | sed 's|from .*/sub|from .../sub|g'
 cd tc
 hg debugsub
 
@@ -102,7 +105,8 @@
 echo % pull
 cd ../tc
 hg pull | sed 's/ .*sub/ ...sub/g'
-hg up # should pull t
+# should pull t
+hg up | sed 's|from .*/sub|from .../sub|g'
 cat t/t
 
 echo % bogus subrepo path aborts
@@ -214,7 +218,7 @@
 hg -R repo/s ci -Am0
 echo s = s > repo/.hgsub
 hg -R repo ci -Am1
-hg clone repo repo2
+hg clone repo repo2 | sed 's|from .*/sub|from .../sub|g'
 hg -q -R repo2 pull -u
 echo 1 > repo2/s/a
 hg -R repo2/s ci -m2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-subrepo-deep-nested-change	Tue May 11 17:03:44 2010 -0500
@@ -0,0 +1,57 @@
+#!/bin/sh
+
+echo % Preparing the subrepository 'sub2'
+hg init sub2
+echo sub2 > sub2/sub2
+hg add -R sub2
+hg commit -R sub2 -m "sub2 import"
+
+echo % Preparing the 'sub1' repo which depends on the subrepo 'sub2'
+hg init sub1
+echo sub1 > sub1/sub1
+echo "sub2 = ../sub2" > sub1/.hgsub
+hg clone sub2 sub1/sub2 | sed 's/ .*sub/ ...sub/g'
+hg add -R sub1
+hg commit -R sub1 -m "sub1 import"
+
+echo % Preparing the 'main' repo which depends on the subrepo 'sub1'
+hg init main
+echo main > main/main
+echo "sub1 = ../sub1" > main/.hgsub
+hg clone sub1 main/sub1  | sed 's/ .*sub/ ...sub/g'
+hg add -R main
+hg commit -R main -m "main import"
+
+echo % Cleaning both repositories, just as a clone -U
+hg up -C -R sub2 null
+hg up -C -R sub1 null
+hg up -C -R main null
+rm -rf main/sub1
+rm -rf sub1/sub2
+
+echo % Clone main
+hg clone main cloned | sed 's/ .*sub/ ...sub/g' 
+
+echo % Checking cloned repo ids
+printf "cloned " ; hg id -R cloned
+printf "cloned/sub1 " ; hg id -R cloned/sub1
+printf "cloned/sub1/sub2 " ; hg id -R cloned/sub1/sub2
+
+echo % debugsub output for main and sub1
+hg debugsub -R cloned
+hg debugsub -R cloned/sub1
+
+echo % Modifying deeply nested 'sub2'
+echo modified > cloned/sub1/sub2/sub2
+hg commit -m "deep nested modif should trigger a commit" -R cloned
+
+echo % Checking modified node ids
+printf "cloned " ; hg id -R cloned
+printf "cloned/sub1 " ; hg id -R cloned/sub1
+printf "cloned/sub1/sub2 " ; hg id -R cloned/sub1/sub2
+
+echo % debugsub output for main and sub1
+hg debugsub -R cloned
+hg debugsub -R cloned/sub1
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-subrepo-deep-nested-change.out	Tue May 11 17:03:44 2010 -0500
@@ -0,0 +1,64 @@
+% Preparing the subrepository sub2
+adding sub2/sub2
+% Preparing the sub1 repo which depends on the subrepo sub2
+updating to branch default
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+adding sub1/.hgsub
+adding sub1/sub1
+committing subrepository sub2
+% Preparing the main repo which depends on the subrepo sub1
+updating to branch default
+pulling ...sub2
+requesting all changes
+adding changesets
+adding manifests
+adding file changes
+added 1 changesets with 1 changes to 1 files
+3 files updated, 0 files merged, 0 files removed, 0 files unresolved
+adding main/.hgsub
+adding main/main
+committing subrepository sub1
+% Cleaning both repositories, just as a clone -U
+0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+0 files updated, 0 files merged, 3 files removed, 0 files unresolved
+0 files updated, 0 files merged, 3 files removed, 0 files unresolved
+% Clone main
+updating to branch default
+pulling ...sub1
+requesting all changes
+adding changesets
+adding manifests
+adding file changes
+added 1 changesets with 3 changes to 3 files
+pulling ...sub2
+requesting all changes
+adding changesets
+adding manifests
+adding file changes
+added 1 changesets with 1 changes to 1 files
+3 files updated, 0 files merged, 0 files removed, 0 files unresolved
+% Checking cloned repo ids
+cloned 7f491f53a367 tip
+cloned/sub1 fc3b4ce2696f tip
+cloned/sub1/sub2 c57a0840e3ba tip
+% debugsub output for main and sub1
+path sub1
+ source   ../sub1
+ revision fc3b4ce2696f7741438c79207583768f2ce6b0dd
+path sub2
+ source   ../sub2
+ revision c57a0840e3badd667ef3c3ef65471609acb2ba3c
+% Modifying deeply nested sub2
+committing subrepository sub1
+committing subrepository sub1/sub2
+% Checking modified node ids
+cloned ffe6649062fe tip
+cloned/sub1 2ecb03bf44a9 tip
+cloned/sub1/sub2 53dd3430bcaf tip
+% debugsub output for main and sub1
+path sub1
+ source   ../sub1
+ revision 2ecb03bf44a94e749e8669481dd9069526ce7cb9
+path sub2
+ source   ../sub2
+ revision 53dd3430bcaf5ab4a7c48262bcad6d441f510487
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-subrepo-relative-path	Tue May 11 17:03:44 2010 -0500
@@ -0,0 +1,40 @@
+#!/bin/sh
+
+echo % Preparing the subrepository 'sub'
+hg init sub
+echo sub > sub/sub
+hg add -R sub
+hg commit -R sub -m "sub import"
+
+echo % Preparing the 'main' repo which depends on the subrepo 'sub'
+hg init main
+echo main > main/main
+echo "sub = ../sub" > main/.hgsub
+hg clone sub main/sub | sed 's/ .*sub/ ...sub/g'
+hg add -R main
+hg commit -R main -m "main import"
+
+echo % Cleaning both repositories, just as a clone -U
+hg up -C -R sub null
+hg up -C -R main null
+rm -rf main/sub
+
+echo % Serving them both using hgweb
+printf '[paths]\n/main = main\nsub = sub\n' > webdir.conf
+hg serve --webdir-conf webdir.conf -a localhost -p $HGPORT \
+   -A /dev/null -E /dev/null --pid-file hg.pid -d
+cat hg.pid >> $DAEMON_PIDS
+
+echo % Clone main from hgweb
+hg clone "http://localhost:$HGPORT/main" cloned | sed 's/ .*sub/ ...sub/g' 
+
+echo % Checking cloned repo ids
+hg id -R cloned
+hg id -R cloned/sub
+
+echo % subrepo debug for 'main' clone
+hg debugsub -R cloned
+
+"$TESTDIR/killdaemons.py"
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-subrepo-relative-path.out	Tue May 11 17:03:44 2010 -0500
@@ -0,0 +1,33 @@
+% Preparing the subrepository sub
+adding sub/sub
+% Preparing the main repo which depends on the subrepo sub
+updating to branch default
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+adding main/.hgsub
+adding main/main
+committing subrepository sub
+% Cleaning both repositories, just as a clone -U
+0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+0 files updated, 0 files merged, 3 files removed, 0 files unresolved
+% Serving them both using hgweb
+% Clone main from hgweb
+requesting all changes
+adding changesets
+adding manifests
+adding file changes
+added 1 changesets with 3 changes to 3 files
+updating to branch default
+pulling ...sub
+requesting all changes
+adding changesets
+adding manifests
+adding file changes
+added 1 changesets with 1 changes to 1 files
+3 files updated, 0 files merged, 0 files removed, 0 files unresolved
+% Checking cloned repo ids
+fdfeeb3e979e tip
+863c1745b441 tip
+% subrepo debug for main clone
+path sub
+ source   ../sub
+ revision 863c1745b441bd97a8c4a096e87793073f4fb215
--- a/tests/test-subrepo-svn	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-subrepo-svn	Tue May 11 17:03:44 2010 -0500
@@ -63,7 +63,8 @@
 echo % change file in svn and hg, commit
 echo a >> a
 echo alpha >> s/alpha
-hg commit -m 'Message!' | sed "$filterexternal"
+hg commit -m 'Message!' | sed "$filterexternal" \
+    | sed 's:Sending.*s/alpha:Sending        s/alpha:g'
 hg debugsub | sed "$filterpath"
 
 echo
--- a/tests/test-subrepo.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-subrepo.out	Tue May 11 17:03:44 2010 -0500
@@ -2,10 +2,25 @@
 adding a
 % add first sub
 adding a
+parent: 0:f7b1eb17ad24 tip
+ 0
+branch: default
+commit: 1 added, 1 subrepos
+update: (current)
 committing subrepository s
 % add sub sub
+parent: 1:7cf8cfea66e4 tip
+ 1
+branch: default
+commit: 1 subrepos
+update: (current)
 committing subrepository s
-committing subrepository ss
+committing subrepository s/ss
+parent: 2:df30734270ae tip
+ 2
+branch: default
+commit: (clean)
+update: (current)
 % bump sub rev
 committing subrepository s
 % leave sub dirty
@@ -108,19 +123,19 @@
 >>>>>>> other
 % clone
 updating to branch default
-pulling subrepo s
+pulling subrepo s from .../sub/t/s
 requesting all changes
 adding changesets
 adding manifests
 adding file changes
 added 4 changesets with 5 changes to 3 files
-pulling subrepo ss
+pulling subrepo s/ss from .../sub/t/s/ss
 requesting all changes
 adding changesets
 adding manifests
 adding file changes
 added 1 changesets with 1 changes to 1 files
-pulling subrepo t
+pulling subrepo t from .../sub/t/t
 requesting all changes
 adding changesets
 adding manifests
@@ -136,13 +151,13 @@
 % push
 committing subrepository t
 pushing ...sub/t
-pushing ...subrepo ss
+pushing ...sub/t/s/ss
 searching for changes
 no changes found
-pushing ...subrepo s
+pushing ...sub/t/s
 searching for changes
 no changes found
-pushing ...subrepo t
+pushing ...sub/t/t
 searching for changes
 adding changesets
 adding manifests
@@ -157,23 +172,23 @@
 committing subrepository s
 abort: push creates new remote heads on branch 'default'!
 pushing ...sub/t
-pushing ...subrepo ss
+pushing ...sub/t/s/ss
 searching for changes
 no changes found
-pushing ...subrepo s
+pushing ...sub/t/s
 searching for changes
 (did you forget to merge? use push -f to force)
 pushing ...sub/t
-pushing ...subrepo ss
+pushing ...sub/t/s/ss
 searching for changes
 no changes found
-pushing ...subrepo s
+pushing ...sub/t/s
 searching for changes
 adding changesets
 adding manifests
 adding file changes
 added 1 changesets with 1 changes to 1 files (+1 heads)
-pushing ...subrepo t
+pushing ...sub/t/t
 searching for changes
 no changes found
 searching for changes
@@ -192,7 +207,7 @@
 adding file changes
 added 1 changesets with 1 changes to 1 files
 (run 'hg update' to get a working copy)
-pulling subrepo t
+pulling subrepo t from .../sub/t/t
 searching for changes
 adding changesets
 adding manifests
@@ -260,13 +275,13 @@
 [paths]
 default = $HGTMP/test-subrepo/sub/mercurial/nested_absolute
 [paths]
-default = $HGTMP/test-subrepo/sub/mercurial/main/../nested_relative
+default = $HGTMP/test-subrepo/sub/mercurial/nested_relative
 % issue 1977
 adding a
 adding .hgsub
 committing subrepository s
 updating to branch default
-pulling subrepo s
+pulling subrepo s from .../sub/repo/s
 requesting all changes
 adding changesets
 adding manifests
--- a/tests/test-tag	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-tag	Tue May 11 17:03:44 2010 -0500
@@ -68,3 +68,8 @@
 cat .hgtags
 hg tag -d '1000000 0' newline
 cat .hgtags
+
+echo % tag and branch using same name
+hg branch tag-and-branch-same-name
+hg ci -m"discouraged"
+hg tag tag-and-branch-same-name
--- a/tests/test-tag.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-tag.out	Tue May 11 17:03:44 2010 -0500
@@ -49,9 +49,9 @@
 abort: ':' cannot be used in a tag name
 % cloning local tags
 changeset:   0:0acdaf898367
-tag:         foobar
 tag:         bleah
 tag:         bleah0
+tag:         foobar
 user:        test
 date:        Mon Jan 12 13:46:40 1970 +0000
 summary:     test
@@ -94,3 +94,6 @@
 f68b039e72eacbb2e68b0543e1f6e50990aa2bb5 localnewline
 0acdaf8983679e0aac16e811534eb49d7ee1f2b4 foobar0acdaf8983679e0aac16e811534eb49d7ee1f2b4 foobar
 6ae703d793c8b1f097116869275ecd97b2977a2b newline
+% tag and branch using same name
+marked working directory as branch tag-and-branch-same-name
+warning: tag tag-and-branch-same-name conflicts with existing branch name
--- a/tests/test-tags.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-tags.out	Tue May 11 17:03:44 2010 -0500
@@ -111,7 +111,7 @@
 summary:     Removed tag bar
 
 % rollback undoes tag operation
-rolling back last transaction
+rolling back to revision 5 (undo commit)
 tip                                4:0c192d7d5e6b
 bar                                1:78391a272241
 tip                                4:0c192d7d5e6b
--- a/tests/test-ui-config.py	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-ui-config.py	Tue May 11 17:03:44 2010 -0500
@@ -11,6 +11,19 @@
     'lists.list2=foo bar baz',
     'lists.list3=alice, bob',
     'lists.list4=foo bar baz alice, bob',
+    'lists.list5=abc d"ef"g "hij def"',
+    'lists.list6="hello world", "how are you?"',
+    'lists.list7=Do"Not"Separate',
+    'lists.list8="Do"Separate',
+    'lists.list9="Do\\"NotSeparate"',
+    'lists.list10=string "with extraneous" quotation mark"',
+    'lists.list11=x, y',
+    'lists.list12="x", "y"',
+    'lists.list13=""" key = "x", "y" """',
+    'lists.list14=,,,,     ',
+    'lists.list15=" just with starting quotation',
+    'lists.list16="longer quotation" with "no ending quotation',
+    'lists.list17=this is \\" "not a quotation mark"',
 ])
 
 print repr(testui.configitems('values'))
@@ -36,6 +49,19 @@
 print repr(testui.configlist('lists', 'list3'))
 print repr(testui.configlist('lists', 'list4'))
 print repr(testui.configlist('lists', 'list4', ['foo']))
+print repr(testui.configlist('lists', 'list5'))
+print repr(testui.configlist('lists', 'list6'))
+print repr(testui.configlist('lists', 'list7'))
+print repr(testui.configlist('lists', 'list8'))
+print repr(testui.configlist('lists', 'list9'))
+print repr(testui.configlist('lists', 'list10'))
+print repr(testui.configlist('lists', 'list11'))
+print repr(testui.configlist('lists', 'list12'))
+print repr(testui.configlist('lists', 'list13'))
+print repr(testui.configlist('lists', 'list14'))
+print repr(testui.configlist('lists', 'list15'))
+print repr(testui.configlist('lists', 'list16'))
+print repr(testui.configlist('lists', 'list17'))
 print repr(testui.configlist('lists', 'unknown'))
 print repr(testui.configlist('lists', 'unknown', ''))
 print repr(testui.configlist('lists', 'unknown', 'foo'))
--- a/tests/test-ui-config.py.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-ui-config.py.out	Tue May 11 17:03:44 2010 -0500
@@ -1,5 +1,5 @@
 [('string', 'string value'), ('bool1', 'true'), ('bool2', 'false')]
-[('list1', 'foo'), ('list2', 'foo bar baz'), ('list3', 'alice, bob'), ('list4', 'foo bar baz alice, bob')]
+[('list1', 'foo'), ('list2', 'foo bar baz'), ('list3', 'alice, bob'), ('list4', 'foo bar baz alice, bob'), ('list5', 'abc d"ef"g "hij def"'), ('list6', '"hello world", "how are you?"'), ('list7', 'Do"Not"Separate'), ('list8', '"Do"Separate'), ('list9', '"Do\\"NotSeparate"'), ('list10', 'string "with extraneous" quotation mark"'), ('list11', 'x, y'), ('list12', '"x", "y"'), ('list13', '""" key = "x", "y" """'), ('list14', ',,,,     '), ('list15', '" just with starting quotation'), ('list16', '"longer quotation" with "no ending quotation'), ('list17', 'this is \\" "not a quotation mark"')]
 ---
 'string value'
 'true'
@@ -18,6 +18,19 @@
 ['alice', 'bob']
 ['foo', 'bar', 'baz', 'alice', 'bob']
 ['foo', 'bar', 'baz', 'alice', 'bob']
+['abc', 'd"ef"g', 'hij def']
+['hello world', 'how are you?']
+['Do"Not"Separate']
+['Do', 'Separate']
+['Do"NotSeparate']
+['string', 'with extraneous', 'quotation', 'mark"']
+['x', 'y']
+['x', 'y']
+['', ' key = ', 'x"', 'y', '', '"']
+[]
+['"', 'just', 'with', 'starting', 'quotation']
+['longer quotation', 'with', '"no', 'ending', 'quotation']
+['this', 'is', '"', 'not a quotation mark']
 []
 []
 ['foo']
--- a/tests/test-url-rev.out	Mon Dec 07 12:31:45 2009 +0200
+++ b/tests/test-url-rev.out	Tue May 11 17:03:44 2010 -0500
@@ -75,7 +75,7 @@
 
 
 % rolling back
-rolling back last transaction
+rolling back to revision 2 (undo push)
 % incoming
 2:faba9097cad4
 % pull
@@ -104,7 +104,7 @@
 % no new revs, no update
 0:1f0dee641bb7
 % rollback
-rolling back last transaction
+rolling back to revision 2 (undo pull)
 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 0:1f0dee641bb7
 % pull -u takes us back to branch foo
@@ -116,7 +116,7 @@
 summary:     new head of branch foo
 
 % rollback
-rolling back last transaction
+rolling back to revision 2 (undo pull)
 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 % parents
 0:1f0dee641bb7