changeset 7490:1c1e6fa67377

Merge bookmarks
author David Soria Parra <dsp@php.net>
date Sun, 07 Dec 2008 19:34:07 +0100
parents ecfb683675ed (diff) 9b64589b1112 (current diff)
children b95ff487870e
files
diffstat 215 files changed, 7859 insertions(+), 3795 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Sun Dec 07 19:33:26 2008 +0100
+++ b/.hgignore	Sun Dec 07 19:34:07 2008 +0100
@@ -30,3 +30,4 @@
 
 syntax: regexp
 ^\.pc/
+^\.(pydev)?project
--- a/.hgsigs	Sun Dec 07 19:33:26 2008 +0100
+++ b/.hgsigs	Sun Dec 07 19:34:07 2008 +0100
@@ -7,3 +7,4 @@
 bae2e9c838e90a393bae3973a7850280413e091a 0 iD8DBQBH6DO5ywK+sNU5EO8RAsfrAJ0e4r9c9GF/MJsM7Xjd3NesLRC3+ACffj6+6HXdZf8cswAoFPO+DY00oD0=
 d5cbbe2c49cee22a9fbeb9ea41daa0ac4e26b846 0 iD8DBQBINdwsywK+sNU5EO8RAjIUAKCPmlFJSpsPAAUKF+iNHAwVnwmzeQCdEXrL27CWclXuUKdbQC8De7LICtE=
 d2375bbee6d47e62ba8e415c86e83a465dc4dce9 0 iD8DBQBIo1wpywK+sNU5EO8RAmRNAJ94x3OFt6blbqu/yBoypm/AJ44fuACfUaldXcV5z9tht97hSp22DVTEPGc=
+2a67430f92f15ea5159c26b09ec4839a0c549a26 0 iEYEABECAAYFAkk1hykACgkQywK+sNU5EO85QACeNJNUanjc2tl4wUoPHNuv+lSj0ZMAoIm93wSTc/feyYnO2YCaQ1iyd9Nu
--- a/.hgtags	Sun Dec 07 19:33:26 2008 +0100
+++ b/.hgtags	Sun Dec 07 19:34:07 2008 +0100
@@ -19,3 +19,4 @@
 bae2e9c838e90a393bae3973a7850280413e091a 1.0
 d5cbbe2c49cee22a9fbeb9ea41daa0ac4e26b846 1.0.1
 d2375bbee6d47e62ba8e415c86e83a465dc4dce9 1.0.2
+2a67430f92f15ea5159c26b09ec4839a0c549a26 1.1
--- a/contrib/buildrpm	Sun Dec 07 19:33:26 2008 +0100
+++ b/contrib/buildrpm	Sun Dec 07 19:34:07 2008 +0100
@@ -3,9 +3,16 @@
 # Build a Mercurial RPM in place.
 # Known to work on:
 # - Fedora 9
+# - Fedora 10
 #
 # Bryan O'Sullivan <bos@serpentine.com>
 
+if hg --version > /dev/null 2>&1; then :
+else
+    echo 'hg command not available!' 1>&2
+    exit 1
+fi
+
 root="`hg root 2>/dev/null`"
 specfile=contrib/mercurial.spec
 
--- a/contrib/dumprevlog	Sun Dec 07 19:33:26 2008 +0100
+++ b/contrib/dumprevlog	Sun Dec 07 19:34:07 2008 +0100
@@ -17,7 +17,7 @@
         p = r.parents(n)
         d = r.revision(n)
         print "node:", node.hex(n)
-        print "linkrev:", r.linkrev(n)
+        print "linkrev:", r.linkrev(i)
         print "parents:", node.hex(p[0]), node.hex(p[1])
         print "length:", len(d)
         print "-start-"
--- a/contrib/hgwebdir.fcgi	Sun Dec 07 19:33:26 2008 +0100
+++ b/contrib/hgwebdir.fcgi	Sun Dec 07 19:34:07 2008 +0100
@@ -29,12 +29,28 @@
 # repos, collections of repos in a directory tree, or both.
 #
 # [paths]
-# virtual/path = /real/path
-# virtual/path = /real/path
+# 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]
--- a/contrib/mercurial.spec	Sun Dec 07 19:33:26 2008 +0100
+++ b/contrib/mercurial.spec	Sun Dec 07 19:34:07 2008 +0100
@@ -6,7 +6,7 @@
 Group: Development/Tools
 Source: http://www.selenic.com/mercurial/release/%{name}-%{version}.tar.gz
 URL: http://www.selenic.com/mercurial
-BuildRoot: /tmp/build.%{name}-%{version}-%{release}
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
 
 # From the README:
 #
@@ -28,13 +28,13 @@
 for efficient handling of very large distributed projects.
 
 %prep
-rm -rf $RPM_BUILD_ROOT
 %setup -q
 
 %build
 make all
 
 %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}
 
@@ -55,9 +55,6 @@
 mkdir -p $lisp_dir
 install contrib/mercurial.el $lisp_dir
 
-# We don't want this, do we?
-rm -f $RPM_BUILD_ROOT%{pythonlib}/../mercurial-*-py2.5.egg-info
-
 %clean
 rm -rf $RPM_BUILD_ROOT
 
@@ -65,8 +62,6 @@
 %defattr(-,root,root,-)
 %doc CONTRIBUTORS COPYING doc/README doc/hg*.txt doc/hg*.html doc/ja *.cgi
 %{_mandir}/man?/hg*.gz
-%dir %{pythonlib}
-%dir %{hgext}
 %{_sysconfdir}/bash_completion.d/mercurial.sh
 %{_datadir}/zsh/site-functions/_mercurial
 %{_datadir}/emacs/site-lisp/mercurial.el
@@ -76,12 +71,6 @@
 %{_bindir}/hg-viz
 %{_bindir}/git-rev-tree
 %{_bindir}/mercurial-convert-repo
-%{pythonlib}/templates
-%{pythonlib}/*.py*
-%{pythonlib}/hgweb/*.py*
-%{pythonlib}/*.so
-%{hgext}/*.py*
-%{hgext}/convert/*.py*
-%{hgext}/inotify/*.py*
-%{hgext}/highlight/*.py*
-%{hgext}/inotify/linux/
+%{_libdir}/python%{pythonver}/site-packages/%{name}-*-py2.5.egg-info
+%{pythonlib}
+%{hgext}
--- a/contrib/mergetools.hgrc	Sun Dec 07 19:33:26 2008 +0100
+++ b/contrib/mergetools.hgrc	Sun Dec 07 19:34:07 2008 +0100
@@ -46,5 +46,6 @@
 ecmerge.regkey=Software\Elli\xc3\xa9 Computing\Merge
 ecmerge.gui=True
 
+filemerge.executable=/Developer/Applications/Utilities/FileMerge.app/Contents/MacOS/FileMerge
 filemerge.args=-left $other -right $local -ancestor $base -merge $output
 filemerge.gui=True
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/perf.py	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,117 @@
+# perf.py - performance test routines
+
+from mercurial.i18n import _
+from mercurial import cmdutil, match
+import time, os, sys
+
+def timer(func):
+    results = []
+    begin = time.time()
+    count = 0
+    while 1:
+        ostart = os.times()
+        cstart = time.time()
+        r = func()
+        cstop = time.time()
+        ostop = os.times()
+        count += 1
+        a, b = ostart, ostop
+        results.append((cstop - cstart, b[0] - a[0], b[1]-a[1]))
+        if cstop - begin > 3 and count >= 100:
+            break
+        if cstop - begin > 10 and count >= 3:
+            break
+    if r:
+        sys.stderr.write("! result: %s\n" % r)
+    m = min(results)
+    sys.stderr.write("! wall %f comb %f user %f sys %f (best of %d)\n"
+                     % (m[0], m[1] + m[2], m[1], m[2], count))
+
+def perfwalk(ui, repo, *pats):
+    try:
+        m = cmdutil.match(repo, pats, {})
+        timer(lambda: len(list(repo.dirstate.walk(m, True, False))))
+    except:
+        try:
+            m = cmdutil.match(repo, pats, {})
+            timer(lambda: len([b for a,b,c in repo.dirstate.statwalk([], m)]))
+        except:
+            timer(lambda: len(list(cmdutil.walk(repo, pats, {}))))
+
+def perfstatus(ui, repo, *pats):
+    #m = match.always(repo.root, repo.getcwd())
+    #timer(lambda: sum(map(len, repo.dirstate.status(m, False, False, False))))
+    timer(lambda: sum(map(len, repo.status())))
+
+def perfheads(ui, repo):
+    timer(lambda: len(repo.changelog.heads()))
+
+def perftags(ui, repo):
+    import mercurial.changelog, mercurial.manifest
+    def t():
+        repo.changelog = mercurial.changelog.changelog(repo.sopener)
+        repo.manifest = mercurial.manifest.manifest(repo.sopener)
+        repo.tagscache = None
+        return len(repo.tags())
+    timer(t)
+
+def perfdirstate(ui, repo):
+    "a" in repo.dirstate
+    def d():
+        repo.dirstate.invalidate()
+        "a" in repo.dirstate
+    timer(d)
+
+def perfdirstatedirs(ui, repo):
+    "a" in repo.dirstate
+    def d():
+        "a" in repo.dirstate._dirs
+        del repo.dirstate._dirs
+    timer(d)
+
+def perfmanifest(ui, repo):
+    def d():
+        t = repo.manifest.tip()
+        m = repo.manifest.read(t)
+        repo.manifest.mapcache = None
+        repo.manifest._cache = None
+    timer(d)
+
+def perfindex(ui, repo):
+    import mercurial.changelog
+    def d():
+        t = repo.changelog.tip()
+        repo.changelog = mercurial.changelog.changelog(repo.sopener)
+        repo.changelog._loadindexmap()
+    timer(d)
+
+def perfstartup(ui, repo):
+    cmd = sys.argv[0]
+    def d():
+        os.system("HGRCPATH= %s version -q > /dev/null" % cmd)
+    timer(d)
+
+def perfparents(ui, repo):
+    nl = [repo.changelog.node(i) for i in xrange(1000)]
+    def d():
+        for n in nl:
+            repo.changelog.parents(n)
+    timer(d)
+
+def perflookup(ui, repo, rev):
+    timer(lambda: len(repo.lookup(rev)))
+
+cmdtable = {
+    'perflookup': (perflookup, []),
+    'perfparents': (perfparents, []),
+    'perfstartup': (perfstartup, []),
+    'perfstatus': (perfstatus, []),
+    'perfwalk': (perfwalk, []),
+    'perfmanifest': (perfmanifest, []),
+    'perfindex': (perfindex, []),
+    'perfheads': (perfheads, []),
+    'perftags': (perftags, []),
+    'perfdirstate': (perfdirstate, []),
+    'perfdirstatedirs': (perfdirstate, []),
+}
+
--- a/contrib/zsh_completion	Sun Dec 07 19:33:26 2008 +0100
+++ b/contrib/zsh_completion	Sun Dec 07 19:34:07 2008 +0100
@@ -4,14 +4,13 @@
 # it into your zsh function path (/usr/share/zsh/site-functions for
 # instance)
 #
-# Copyright (C) 2005 Steve Borho
-# Copyright (C) 2006 Brendan Cully <brendan@kublai.com>
+# Copyright (C) 2005-6 Steve Borho
+# Copyright (C) 2006-8 Brendan Cully <brendan@kublai.com>
 #
 # This is free software; you can redistribute it and/or modify it under
 # the terms of the GNU General Public License as published by the Free
 # Software Foundation; either version 2 of the License, or (at your
 # option) any later version.
-#
 
 emulate -LR zsh
 setopt extendedglob
@@ -117,28 +116,54 @@
 _hg_get_commands() {
   typeset -ga _hg_cmd_list
   typeset -gA _hg_alias_list
-  local hline cmd cmdalias
-  _call_program help hg --verbose help | while read -A hline
+  local hline cmd cmdalias helpstate
+  local helpmode=$1
+
+  _call_program help hg --verbose help $helpmode 2>/dev/null | while read -A hline
   do
-    cmd="$hline[1]"
-    case $cmd in
-      *:)
-        cmd=${cmd%:}
-        _hg_cmd_list+=($cmd)
-      ;;
-      *,)
-        cmd=${cmd%,}
-        _hg_cmd_list+=($cmd)
-        integer i=2
-        while (( i <= $#hline ))
-        do
-          cmdalias=${hline[$i]%(:|,)}
-          _hg_cmd_list+=($cmdalias)
-          _hg_alias_list+=($cmdalias $cmd)
-          (( i++ ))
-        done
-      ;;
-    esac
+    if [ "$hline" = "list of commands:" ]
+    then
+      helpstate="commands"
+      continue
+    elif [ "$hline" = "enabled extensions:" ]
+    then
+      helpstate="extensions"
+      continue
+    elif [ "$hline" = "additional help topics:" ]
+    then
+      helpstate="topics"
+      continue
+    fi
+
+    if [ "$helpstate" = commands ]
+    then
+      cmd="$hline[1]"
+      case $cmd in
+        *:)
+          cmd=${cmd%:}
+          _hg_cmd_list+=($cmd)
+        ;;
+        *,)
+          cmd=${cmd%,}
+          _hg_cmd_list+=($cmd)
+          integer i=2
+          while (( i <= $#hline ))
+          do
+            cmdalias=${hline[$i]%(:|,)}
+            _hg_cmd_list+=($cmdalias)
+            _hg_alias_list+=($cmdalias $cmd)
+            (( i++ ))
+          done
+        ;;
+      esac
+    elif [ -z "$helpmode" -a "$helpstate" = extensions ]
+    then
+      cmd="$hline[1]"
+      if [ -n "$cmd" ]
+      then
+        _hg_get_commands $cmd
+      fi
+    fi
   done
 }
 
@@ -203,6 +228,30 @@
   _wanted files expl 'modified files' _multi_parts / status_files
 }
 
+_hg_resolve() {
+  local rstate rpah
+
+  [[ -d $PREFIX ]] || PREFIX=$PREFIX:h
+
+  _hg_cmd resolve -l ./$PREFIX 2> /dev/null | while read rstate rpath
+  do
+    [[ $rstate == 'R' ]] && resolved_files+=($rpath)
+    [[ $rstate == 'U' ]] && unresolved_files+=($rpath)
+  done
+}
+
+_hg_resolved() {
+  typeset -a resolved_files unresolved_files
+  _hg_resolve
+  _wanted files expl 'resolved files' _multi_parts / resolved_files
+}
+
+_hg_unresolved() {
+  typeset -a resolved_files unresolved_files
+  _hg_resolve
+  _wanted files expl 'unresolved files' _multi_parts / unresolved_files
+}
+
 _hg_config() {
     typeset -a items
     items=(${${(%f)"$(_call_program hg hg showconfig)"}%%\=*})
@@ -580,7 +629,27 @@
   '*:file:_hg_files'
 }
 
+_hg_cmd_resolve() {
+  local context state line
+  typeset -A opt_args
+
+  _arguments -s -w : $_hg_global_opts \
+  '(--list -l --mark -m --unmark -u)'{-l,--list}'[list state of files needing merge]:*:merged files:->resolve_files' \
+  '(--mark -m --list -l --unmark -u)'{-m,--mark}'[mark files as resolved]:*:unresolved files:_hg_unresolved' \
+  '(--unmark -u --list -l --mark -m)'{-u,--unmark}'[unmark files as resolved]:*:resolved files:_hg_resolved' \
+  '*:file:_hg_unresolved'
+
+  if [[ $state == 'resolve_files' ]]
+  then
+    _alternative 'files:resolved files:_hg_resolved' \
+      'files:unresolved files:_hg_unresolved'
+  fi
+}
+
 _hg_cmd_revert() {
+  local context state line
+  typeset -A opt_args
+
   _arguments -s -w : $_hg_global_opts $_hg_pat_opts $_hg_dryrun_opts \
   '(--all -a :)'{-a,--all}'[revert all changes when no arguments given]' \
   '(--rev -r)'{-r+,--rev}'[revision to revert to]:revision:_hg_tags' \
--- a/doc/gendoc.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/doc/gendoc.py	Sun Dec 07 19:34:07 2008 +0100
@@ -36,14 +36,21 @@
     attr = table[cmd]
     cmds = cmd.lstrip("^").split("|")
 
-    d['synopsis'] = attr[2]
     d['cmd'] = cmds[0]
     d['aliases'] = cmd.split("|")[1:]
     d['desc'] = get_desc(attr[0].__doc__)
     d['opts'] = list(get_opts(attr[1]))
+
+    s = 'hg ' + cmds[0]
+    if len(attr) > 2:
+        if not attr[2].startswith('hg'):
+            s += attr[2]
+        else:
+            s = attr[2]
+    d['synopsis'] = s
+
     return d
 
-
 def show_doc(ui):
     def bold(s, text=""):
         ui.write("%s\n%s\n%s\n" % (s, "="*len(s), text))
--- a/doc/hgrc.5.txt	Sun Dec 07 19:33:26 2008 +0100
+++ b/doc/hgrc.5.txt	Sun Dec 07 19:34:07 2008 +0100
@@ -676,6 +676,16 @@
     must be present in this list (separated by whitespace or ",").
     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.
   allowzip;;
     (DEPRECATED) Whether to allow .zip downloading of repo revisions.
     Default is false. This feature creates temporary files.
@@ -693,6 +703,18 @@
     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.
+  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 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 served via hgwebdir, denied users will not be able to
+    see it in the list of repositories.  The contents of the deny_read list have
+    priority over (are examined before) the contents of the allow_read list.
   description;;
     Textual description of the repository's purpose or contents.
     Default is "unknown".
--- a/hgext/bugzilla.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/hgext/bugzilla.py	Sun Dec 07 19:34:07 2008 +0100
@@ -291,7 +291,7 @@
             tmpl = templater.parsestring(tmpl, quoted=False)
             t.use_template(tmpl)
         self.ui.pushbuffer()
-        t.show(changenode=ctx.node(), changes=ctx.changeset(),
+        t.show(ctx, changes=ctx.changeset(),
                bug=str(bugid),
                hgweb=self.ui.config('web', 'baseurl'),
                root=self.repo.root,
--- a/hgext/children.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/hgext/children.py	Sun Dec 07 19:34:07 2008 +0100
@@ -28,8 +28,8 @@
         ctx = repo[rev]
 
     displayer = cmdutil.show_changeset(ui, repo, opts)
-    for node in [cp.node() for cp in ctx.children()]:
-        displayer.show(changenode=node)
+    for cctx in ctx.children():
+        displayer.show(cctx)
 
 
 cmdtable = {
--- a/hgext/churn.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/hgext/churn.py	Sun Dec 07 19:34:07 2008 +0100
@@ -63,7 +63,7 @@
         tmpl = maketemplater(ui, repo, tmpl)
         def getkey(ctx):
             ui.pushbuffer()
-            tmpl.show(changenode=ctx.node())
+            tmpl.show(ctx)
             return ui.popbuffer()
 
     count = pct = 0
--- a/hgext/color.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/hgext/color.py	Sun Dec 07 19:34:07 2008 +0100
@@ -16,15 +16,17 @@
 # with this program; if not, write to the Free Software Foundation, Inc.,
 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-'''add color output to the status and qseries commands
+'''add color output to status, qseries, and diff-related commands
 
 This extension modifies the status command to add color to its output to
-reflect file status, and the qseries command to add color to reflect patch
-status (applied, unapplied, missing).  Other effects in addition to color,
-like bold and underlined text, are also available.  Effects are rendered
-with the ECMA-48 SGR control function (aka ANSI escape codes).  This module
-also provides the render_text function, which can be used to add effects to
-any text.
+reflect file status, the qseries command to add color to reflect patch status
+(applied, unapplied, missing), and to diff-related commands to highlight
+additions, removals, diff headers, and trailing whitespace.
+
+Other effects in addition to color, like bold and underlined text, are also
+available.  Effects are rendered with the ECMA-48 SGR control function (aka
+ANSI escape codes).  This module also provides the render_text function,
+which can be used to add effects to any text.
 
 To enable this extension, add this to your .hgrc file:
 [extensions]
@@ -47,70 +49,70 @@
 qseries.applied = blue bold underline
 qseries.unapplied = black bold
 qseries.missing = red bold
+
+diff.diffline = bold
+diff.extended = cyan bold
+diff.file_a = red bold
+diff.file_b = green bold
+diff.hunk = magenta
+diff.deleted = red
+diff.inserted = green
+diff.changed = white
+diff.trailingwhitespace = bold red_background
 '''
 
-import re, sys
+import os, re, sys
 
-from mercurial import commands, cmdutil, extensions
+from mercurial import cmdutil, commands, extensions
 from mercurial.i18n import _
 
 # start and stop parameters for effects
-_effect_params = { 'none': (0, 0),
-                   'black': (30, 39),
-                   'red': (31, 39),
-                   'green': (32, 39),
-                   'yellow': (33, 39),
-                   'blue': (34, 39),
-                   'magenta': (35, 39),
-                   'cyan': (36, 39),
-                   'white': (37, 39),
-                   'bold': (1, 22),
-                   'italic': (3, 23),
-                   'underline': (4, 24),
-                   'inverse': (7, 27),
-                   'black_background': (40, 49),
-                   'red_background': (41, 49),
-                   'green_background': (42, 49),
-                   'yellow_background': (43, 49),
-                   'blue_background': (44, 49),
-                   'purple_background': (45, 49),
-                   'cyan_background': (46, 49),
-                   'white_background': (47, 49), }
+_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}
 
 def render_effects(text, *effects):
     'Wrap text in commands to turn on each effect.'
-    start = [ str(_effect_params['none'][0]) ]
-    stop = []
-    for effect in effects:
-        start.append(str(_effect_params[effect][0]))
-        stop.append(str(_effect_params[effect][1]))
-    stop.append(str(_effect_params['none'][1]))
+    start = [str(_effect_params[e]) for e in ('none',) + effects]
     start = '\033[' + ';'.join(start) + 'm'
-    stop = '\033[' + ';'.join(stop) + 'm'
-    return start + text + stop
+    stop = '\033[' + str(_effect_params['none']) + 'm'
+    return ''.join([start, text, stop])
 
 def colorstatus(orig, ui, repo, *pats, **opts):
     '''run the status command with colored output'''
 
     delimiter = opts['print0'] and '\0' or '\n'
 
-    # run status and capture it's output
+    nostatus = opts.get('no_status')
+    opts['no_status'] = False
+    # run status and capture its output
     ui.pushbuffer()
     retval = orig(ui, repo, *pats, **opts)
     # filter out empty strings
-    lines = [ line for line in ui.popbuffer().split(delimiter) if line ]
+    lines_with_status = [ line for line in ui.popbuffer().split(delimiter) if line ]
 
-    if opts['no_status']:
-        # if --no-status, run the command again without that option to get
-        # output with status abbreviations
-        opts['no_status'] = False
-        ui.pushbuffer()
-        statusfunc(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_with_status = lines
+        lines = lines_with_status
 
     # apply color to output and display it
     for i in xrange(0, len(lines)):
@@ -118,7 +120,7 @@
         effects = _status_effects[status]
         if effects:
             lines[i] = render_effects(lines[i], *effects)
-        sys.stdout.write(lines[i] + delimiter)
+        ui.write(lines[i] + delimiter)
     return retval
 
 _status_abbreviations = { 'M': 'modified',
@@ -159,30 +161,104 @@
             effects = _patch_effects['applied']
         else:
             effects = _patch_effects['unapplied']
-        sys.stdout.write(render_effects(patch, *effects) + '\n')
+        ui.write(render_effects(patch, *effects) + '\n')
     return retval
 
 _patch_effects = { 'applied': ('blue', 'bold', 'underline'),
                    'missing': ('red', 'bold'),
                    'unapplied': ('black', 'bold'), }
 
+def colorwrap(orig, s):
+    '''wrap ui.write for colored diff output'''
+    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'])
+    orig('\n'.join(lines))
+
+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 colordiff(orig, ui, repo, *pats, **opts):
+    '''run the diff command with colored output'''
+    oldwrite = extensions.wrapfunction(ui, 'write', colorwrap)
+    try:
+        orig(ui, repo, *pats, **opts)
+    finally:
+        ui.write = oldwrite
+
+_diff_prefixes = [('diff', 'diffline'),
+                  ('copy', 'extended'),
+                  ('rename', '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 uisetup(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)
     if ui.config('extensions', 'hgext.mq') is not None or \
             ui.config('extensions', 'mq') is not None:
         from hgext import mq
+        _setupcmd(ui, 'qdiff', mq.cmdtable, colordiff, _diff_effects)
         _setupcmd(ui, 'qseries', mq.cmdtable, colorqseries, _patch_effects)
 
 def _setupcmd(ui, cmd, table, func, effectsmap):
     '''patch in command to command table and load effect map'''
-    def nocolor(orig, *args, **kwargs):
-        if kwargs['no_color']:
-            return orig(*args, **kwargs)
-        return func(orig, *args, **kwargs)
+    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()))):
+            return orig(*args, **opts)
+
+        oldshowpatch = extensions.wrapfunction(cmdutil.changeset_printer,
+                                               'showpatch', colorshowpatch)
+        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].append(('', 'no-color', None, _("don't colorize output")))
+    entry[1].extend([
+        ('', 'color', 'auto', _("when to colorize (always, auto, or never)")),
+        ('', 'no-color', None, _("don't colorize output")),
+    ])
 
     for status in effectsmap:
         effects = ui.config('color', cmd + '.' + status)
--- a/hgext/convert/cvs.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/hgext/convert/cvs.py	Sun Dec 07 19:34:07 2008 +0100
@@ -1,6 +1,6 @@
 # CVS conversion code inspired by hg-cvs-import and git-cvsimport
 
-import os, locale, re, socket
+import os, locale, re, socket, errno
 from cStringIO import StringIO
 from mercurial import util
 from mercurial.i18n import _
@@ -103,18 +103,18 @@
                             if maxrev and int(id) > maxrev:
                                 # ignore everything
                                 state = 3
-                        elif l.startswith("Date"):
+                        elif l.startswith("Date:"):
                             date = util.parsedate(l[6:-1], ["%Y/%m/%d %H:%M:%S"])
                             date = util.datestr(date)
-                        elif l.startswith("Branch"):
+                        elif l.startswith("Branch:"):
                             branch = l[8:-1]
                             self.parent[id] = self.lastbranch.get(branch, 'bad')
                             self.lastbranch[branch] = id
-                        elif l.startswith("Ancestor branch"):
+                        elif l.startswith("Ancestor branch:"):
                             ancestor = l[17:-1]
                             # figure out the parent later
                             self.parent[id] = self.lastbranch[ancestor]
-                        elif l.startswith("Author"):
+                        elif l.startswith("Author:"):
                             author = self.recode(l[8:-1])
                         elif l.startswith("Tag:") or l.startswith("Tags:"):
                             t = l[l.index(':')+1:]
@@ -144,11 +144,11 @@
                             if branch == "HEAD":
                                 branch = ""
                             if branch:
-                                latest = None
+                                latest = 0
                                 # the last changeset that contains a base
                                 # file is our parent
                                 for r in oldrevs:
-                                    latest = max(filerevids.get(r, None), latest)
+                                    latest = max(filerevids.get(r, 0), latest)
                                 if latest:
                                     p = [latest]
 
@@ -201,20 +201,27 @@
 
                 if not passw:
                     passw = "A"
-                    pf = open(os.path.expanduser("~/.cvspass"))
-                    for line in pf.read().splitlines():
-                        part1, part2 = line.split(' ', 1)
-                        if part1 == '/1':
-                            # /1 :pserver:user@example.com:2401/cvsroot/foo Ah<Z
-                            part1, part2 = part2.split(' ', 1)
-                            format = format1
-                        else:
-                            # :pserver:user@example.com:/cvsroot/foo Ah<Z
-                            format = format0
-                        if part1 == format:
-                            passw = part2
-                            break
-                    pf.close()
+                    cvspass = os.path.expanduser("~/.cvspass")
+                    try:
+                        pf = open(cvspass)
+                        for line in pf.read().splitlines():
+                            part1, part2 = line.split(' ', 1)
+                            if part1 == '/1':
+                                # /1 :pserver:user@example.com:2401/cvsroot/foo Ah<Z
+                                part1, part2 = part2.split(' ', 1)
+                                format = format1
+                            else:
+                                # :pserver:user@example.com:/cvsroot/foo Ah<Z
+                                format = format0
+                            if part1 == format:
+                                passw = part2
+                                break
+                        pf.close()
+                    except IOError, inst:
+                        if inst.errno != errno.ENOENT:
+                            if not getattr(inst, 'filename', None):
+                                inst.filename = cvspass
+                            raise
 
                 sck = socket.socket()
                 sck.connect((serv, port))
--- a/hgext/convert/subversion.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/hgext/convert/subversion.py	Sun Dec 07 19:34:07 2008 +0100
@@ -32,8 +32,8 @@
 
 from cStringIO import StringIO
 
-from common import NoRepo, commit, converter_source, encodeargs, decodeargs
-from common import commandline, converter_sink, mapfile
+from common import NoRepo, MissingTool, commit, encodeargs, decodeargs
+from common import commandline, converter_source, converter_sink, mapfile
 
 try:
     from svn.core import SubversionException, Pool
@@ -46,6 +46,9 @@
 except ImportError:
     pass
 
+class SvnPathNotFound(Exception):
+    pass
+
 def geturl(path):
     try:
         return svn.client.url_from_path(svn.core.svn_path_canonicalize(path))
@@ -152,7 +155,16 @@
         try:
             SubversionException
         except NameError:
-            raise NoRepo('Subversion python bindings could not be loaded')
+            raise MissingTool(_('Subversion python bindings could not be loaded'))
+
+        try:
+            version = svn.core.SVN_VER_MAJOR, svn.core.SVN_VER_MINOR
+            if version < (1, 4):
+                raise MissingTool(_('Subversion python bindings %d.%d found, '
+                                    '1.4 or later required') % version)
+        except AttributeError:
+            raise MissingTool(_('Subversion python bindings are too old, 1.4 '
+                                'or later required'))
 
         self.encoding = locale.getpreferredencoding()
         self.lastrevs = {}
@@ -414,9 +426,15 @@
                         remainings.append([source, sourcerev, tagname])
                         continue
                     # From revision may be fake, get one with changes
-                    tagid = self.latest(source, sourcerev)
-                    if tagid:
-                        tags[tagname] = tagid
+                    try:
+                        tagid = self.latest(source, sourcerev)
+                        if tagid:
+                            tags[tagname] = tagid
+                    except SvnPathNotFound:
+                        # It happens when we are following directories we assumed
+                        # were copied with their parents but were really created
+                        # in the tag directory.
+                        pass
                 pendings = remainings
                 tagspath = srctagspath
 
@@ -474,7 +492,7 @@
         except SubversionException:
             dirent = None
         if not dirent:
-            raise util.Abort(_('%s not found up to revision %d') % (path, stop))
+            raise SvnPathNotFound(_('%s not found up to revision %d') % (path, stop))
 
         # stat() gives us the previous revision on this line of development, but
         # it might be in *another module*. Fetch the log and detect renames down
@@ -706,12 +724,6 @@
 
         self.child_cset = None
 
-        def isdescendantof(parent, child):
-            if not child or not parent or not child.startswith(parent):
-                return False
-            subpath = child[len(parent):]
-            return len(subpath) > 1 and subpath[0] == '/'
-
         def parselogentry(orig_paths, revnum, author, date, message):
             """Return the parsed commit object or None, and True if
             the revision is a branch root.
@@ -734,21 +746,10 @@
             if root_paths:
                 path, ent = root_paths[-1]
                 if ent.copyfrom_path:
-                    # If dir was moved while one of its file was removed
-                    # the log may look like:
-                    # A /dir   (from /dir:x)
-                    # A /dir/a (from /dir/a:y)
-                    # A /dir/b (from /dir/b:z)
-                    # ...
-                    # for all remaining children.
-                    # Let's take the highest child element from rev as source.
-                    copies = [(p,e) for p,e in orig_paths[:-1]
-                          if isdescendantof(ent.copyfrom_path, e.copyfrom_path)]
-                    fromrev = max([e.copyfrom_rev for p,e in copies] + [ent.copyfrom_rev])
                     branched = True
                     newpath = ent.copyfrom_path + self.module[len(path):]
                     # ent.copyfrom_rev may not be the actual last revision
-                    previd = self.latest(newpath, fromrev)
+                    previd = self.latest(newpath, ent.copyfrom_rev)
                     if previd is not None:
                         prevmodule, prevnum = self.revsplit(previd)[1:]
                         if prevnum >= self.startrev:
@@ -834,7 +835,7 @@
                         latest = self.latest(self.module, firstrevnum - 1)
                         if latest:
                             firstcset.parents.append(latest)
-                except util.Abort:
+                except SvnPathNotFound:
                     pass
         except SubversionException, (inst, num):
             if num == svn.core.SVN_ERR_FS_NO_SUCH_REVISION:
@@ -842,7 +843,6 @@
             raise
 
     def _getfile(self, file, rev):
-        io = StringIO()
         # TODO: ra.get_file transmits the whole file instead of diffs.
         mode = ''
         try:
@@ -850,7 +850,12 @@
             if self.module != new_module:
                 self.module = new_module
                 self.reparent(self.module)
+            io = StringIO()
             info = svn.ra.get_file(self.ra, file, revnum, io)
+            data = io.getvalue()
+            # ra.get_files() seems to keep a reference on the input buffer
+            # preventing collection. Release it explicitely.
+            io.close()
             if isinstance(info, list):
                 info = info[-1]
             mode = ("svn:executable" in info) and 'x' or ''
@@ -861,7 +866,6 @@
             if e.apr_err in notfound: # File not found
                 raise IOError()
             raise
-        data = io.getvalue()
         if mode == 'l':
             link_prefix = "link "
             if data.startswith(link_prefix):
--- a/hgext/graphlog.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/hgext/graphlog.py	Sun Dec 07 19:34:07 2008 +0100
@@ -4,130 +4,112 @@
 #
 # This software may be used and distributed according to the terms of
 # the GNU General Public License, incorporated herein by reference.
-'''show revision graphs in terminal windows'''
+'''show revision graphs in terminal windows
+
+This extension adds a --graph option to the incoming, outgoing and log
+commands. When this options is given, an ascii representation of the
+revision graph is also shown.
+'''
 
 import os
 import sys
 from mercurial.cmdutil import revrange, show_changeset
-from mercurial.commands import templateopts
+from mercurial.commands import templateopts, logopts, remoteopts
 from mercurial.i18n import _
 from mercurial.node import nullrev
 from mercurial.util import Abort, canonpath
-from mercurial import util
-
-def revision_grapher(repo, start_rev, stop_rev):
-    """incremental revision grapher
-
-    This generator function walks through the revision history from
-    revision start_rev to revision stop_rev (which must be less than
-    or equal to start_rev) and for each revision emits tuples with the
-    following elements:
+from mercurial import bundlerepo, changegroup, cmdutil, commands, extensions
+from mercurial import hg, ui, url
 
-      - Current revision.
-      - Current node.
-      - Column of the current node in the set of ongoing edges.
-      - Edges; a list of (col, next_col) indicating the edges between
-        the current node and its parents.
-      - Number of columns (ongoing edges) in the current revision.
-      - The difference between the number of columns (ongoing edges)
-        in the next revision and the number of columns (ongoing edges)
-        in the current revision. That is: -1 means one column removed;
-        0 means no columns added or removed; 1 means one column added.
-    """
-
-    assert start_rev >= stop_rev
-    curr_rev = start_rev
-    revs = []
-    while curr_rev >= stop_rev:
-        node = repo.changelog.node(curr_rev)
-
-        # Compute revs and next_revs.
-        if curr_rev not in revs:
-            # New head.
-            revs.append(curr_rev)
-        rev_index = revs.index(curr_rev)
-        next_revs = revs[:]
+def revisions(repo, start, stop):
+    """cset DAG generator yielding (rev, node, [parents]) tuples
 
-        # Add parents to next_revs.
-        parents = get_rev_parents(repo, curr_rev)
-        parents_to_add = []
-        for parent in parents:
-            if parent not in next_revs:
-                parents_to_add.append(parent)
-        next_revs[rev_index:rev_index + 1] = util.sort(parents_to_add)
-
-        edges = []
-        for parent in parents:
-            edges.append((rev_index, next_revs.index(parent)))
-
-        n_columns_diff = len(next_revs) - len(revs)
-        yield (curr_rev, node, rev_index, edges, len(revs), n_columns_diff)
-
-        revs = next_revs
-        curr_rev -= 1
+    This generator function walks through the revision history from revision
+    start to revision stop (which must be less than or equal to start).
+    """
+    assert start >= stop
+    cur = start
+    while cur >= stop:
+        ctx = repo[cur]
+        parents = [p.rev() for p in ctx.parents() if p.rev() != nullrev]
+        parents.sort()
+        yield (ctx, parents)
+        cur -= 1
 
-def filelog_grapher(repo, path, start_rev, stop_rev):
-    """incremental file log grapher
-
-    This generator function walks through the revision history of a
-    single file from revision start_rev to revision stop_rev (which must
-    be less than or equal to start_rev) and for each revision emits
-    tuples with the following elements:
+def filerevs(repo, path, start, stop):
+    """file cset DAG generator yielding (rev, node, [parents]) tuples
 
-      - Current revision.
-      - Current node.
-      - Column of the current node in the set of ongoing edges.
-      - Edges; a list of (col, next_col) indicating the edges between
-        the current node and its parents.
-      - Number of columns (ongoing edges) in the current revision.
-      - The difference between the number of columns (ongoing edges)
-        in the next revision and the number of columns (ongoing edges)
-        in the current revision. That is: -1 means one column removed;
-        0 means no columns added or removed; 1 means one column added.
+    This generator function walks through the revision history of a single
+    file from revision start to revision stop (which must be less than or
+    equal to start).
     """
-
-    assert start_rev >= stop_rev
-    revs = []
+    assert start >= stop
     filerev = len(repo.file(path)) - 1
     while filerev >= 0:
         fctx = repo.filectx(path, fileid=filerev)
-
-        # Compute revs and next_revs.
-        if filerev not in revs:
-            revs.append(filerev)
-        rev_index = revs.index(filerev)
-        next_revs = revs[:]
-
-        # Add parents to next_revs.
-        parents = [f.filerev() for f in fctx.parents() if f.path() == path]
-        parents_to_add = []
-        for parent in parents:
-            if parent not in next_revs:
-                parents_to_add.append(parent)
-        next_revs[rev_index:rev_index + 1] = util.sort(parents_to_add)
-
-        edges = []
-        for parent in parents:
-            edges.append((rev_index, next_revs.index(parent)))
-
-        changerev = fctx.linkrev()
-        if changerev <= start_rev:
-            node = repo.changelog.node(changerev)
-            n_columns_diff = len(next_revs) - len(revs)
-            yield (changerev, node, rev_index, edges, len(revs), n_columns_diff)
-        if changerev <= stop_rev:
+        parents = [f.linkrev() for f in fctx.parents() if f.path() == path]
+        parents.sort()
+        if fctx.rev() <= start:
+            yield (fctx, parents)
+        if fctx.rev() <= stop:
             break
-        revs = next_revs
         filerev -= 1
 
-def get_rev_parents(repo, rev):
-    return [x for x in repo.changelog.parentrevs(rev) if x != nullrev]
+def grapher(nodes):
+    """grapher for asciigraph on a list of nodes and their parents
+
+    nodes must generate tuples (node, parents, char, lines) where
+     - parents must generate the parents of node, in sorted order,
+       and max length 2,
+     - char is the char to print as the node symbol, and
+     - lines are the lines to display next to the node.
+    """
+    seen = []
+    for node, parents, char, lines in nodes:
+        if node not in seen:
+            seen.append(node)
+        nodeidx = seen.index(node)
+
+        knownparents = []
+        newparents = []
+        for parent in parents:
+            if parent in seen:
+                knownparents.append(parent)
+            else:
+                newparents.append(parent)
+
+        ncols = len(seen)
+        nextseen = seen[:]
+        nextseen[nodeidx:nodeidx + 1] = newparents
+        edges = [(nodeidx, nextseen.index(p)) for p in knownparents]
+
+        if len(newparents) > 0:
+            edges.append((nodeidx, nodeidx))
+        if len(newparents) > 1:
+            edges.append((nodeidx, nodeidx + 1))
+        nmorecols = len(nextseen) - ncols
+        seen = nextseen
+        yield (char, lines, nodeidx, edges, ncols, nmorecols)
 
 def fix_long_right_edges(edges):
     for (i, (start, end)) in enumerate(edges):
         if end > start:
             edges[i] = (start, end + 1)
 
+def get_nodeline_edges_tail(
+        node_index, p_node_index, n_columns, n_columns_diff, p_diff, fix_tail):
+    if fix_tail and n_columns_diff == p_diff and n_columns_diff != 0:
+        # Still going in the same non-vertical direction.
+        if n_columns_diff == -1:
+            start = max(node_index + 1, p_node_index)
+            tail = ["|", " "] * (start - node_index - 1)
+            tail.extend(["/", " "] * (n_columns - start))
+            return tail
+        else:
+            return ["\\", " "] * (n_columns - node_index - 1)
+    else:
+        return ["|", " "] * (n_columns - node_index - 1)
+
 def draw_edges(edges, nodeline, interline):
     for (start, end) in edges:
         if start == end + 1:
@@ -144,24 +126,6 @@
                 if nodeline[i] != "+":
                     nodeline[i] = "-"
 
-def format_line(line, level, logstr):
-    text = "%-*s %s" % (2 * level, "".join(line), logstr)
-    return "%s\n" % text.rstrip()
-
-def get_nodeline_edges_tail(
-        node_index, p_node_index, n_columns, n_columns_diff, p_diff, fix_tail):
-    if fix_tail and n_columns_diff == p_diff and n_columns_diff != 0:
-        # Still going in the same non-vertical direction.
-        if n_columns_diff == -1:
-            start = max(node_index + 1, p_node_index)
-            tail = ["|", " "] * (start - node_index - 1)
-            tail.extend(["/", " "] * (n_columns - start))
-            return tail
-        else:
-            return ["\\", " "] * (n_columns - node_index - 1)
-    else:
-        return ["|", " "] * (n_columns - node_index - 1)
-
 def get_padding_line(ni, n_columns, edges):
     line = []
     line.extend(["|", " "] * ni)
@@ -179,6 +143,108 @@
     line.extend(["|", " "] * (n_columns - ni - 1))
     return line
 
+def ascii(ui, grapher):
+    """prints an ASCII graph of the DAG returned by the grapher
+
+    grapher is a generator that emits tuples with the following elements:
+
+      - Character to use as node's symbol.
+      - List of lines to display as the node's text.
+      - Column of the current node in the set of ongoing edges.
+      - Edges; a list of (col, next_col) indicating the edges between
+        the current node and its parents.
+      - Number of columns (ongoing edges) in the current revision.
+      - The difference between the number of columns (ongoing edges)
+        in the next revision and the number of columns (ongoing edges)
+        in the current revision. That is: -1 means one column removed;
+        0 means no columns added or removed; 1 means one column added.
+    """
+    prev_n_columns_diff = 0
+    prev_node_index = 0
+    for (node_ch, node_lines, node_index, edges, n_columns, n_columns_diff) in grapher:
+
+        assert -2 < n_columns_diff < 2
+        if n_columns_diff == -1:
+            # Transform
+            #
+            #     | | |        | | |
+            #     o | |  into  o---+
+            #     |X /         |/ /
+            #     | |          | |
+            fix_long_right_edges(edges)
+
+        # add_padding_line says whether to rewrite
+        #
+        #     | | | |        | | | |
+        #     | o---+  into  | o---+
+        #     |  / /         |   | |  # <--- padding line
+        #     o | |          |  / /
+        #                    o | |
+        add_padding_line = (len(node_lines) > 2 and
+                            n_columns_diff == -1 and
+                            [x for (x, y) in edges if x + 1 < y])
+
+        # fix_nodeline_tail says whether to rewrite
+        #
+        #     | | o | |        | | o | |
+        #     | | |/ /         | | |/ /
+        #     | o | |    into  | o / /   # <--- fixed nodeline tail
+        #     | |/ /           | |/ /
+        #     o | |            o | |
+        fix_nodeline_tail = len(node_lines) <= 2 and not add_padding_line
+
+        # nodeline is the line containing the node character (typically o)
+        nodeline = ["|", " "] * node_index
+        nodeline.extend([node_ch, " "])
+
+        nodeline.extend(
+            get_nodeline_edges_tail(
+                node_index, prev_node_index, n_columns, n_columns_diff,
+                prev_n_columns_diff, fix_nodeline_tail))
+
+        # shift_interline is the line containing the non-vertical
+        # edges between this entry and the next
+        shift_interline = ["|", " "] * node_index
+        if n_columns_diff == -1:
+            n_spaces = 1
+            edge_ch = "/"
+        elif n_columns_diff == 0:
+            n_spaces = 2
+            edge_ch = "|"
+        else:
+            n_spaces = 3
+            edge_ch = "\\"
+        shift_interline.extend(n_spaces * [" "])
+        shift_interline.extend([edge_ch, " "] * (n_columns - node_index - 1))
+
+        # draw edges from the current node to its parents
+        draw_edges(edges, nodeline, shift_interline)
+
+        # lines is the list of all graph lines to print
+        lines = [nodeline]
+        if add_padding_line:
+            lines.append(get_padding_line(node_index, n_columns, edges))
+        lines.append(shift_interline)
+
+        # make sure that there are as many graph lines as there are
+        # log strings
+        while len(node_lines) < len(lines):
+            node_lines.append("")
+        if len(lines) < len(node_lines):
+            extra_interline = ["|", " "] * (n_columns + n_columns_diff)
+            while len(lines) < len(node_lines):
+                lines.append(extra_interline)
+
+        # print lines
+        indentation_level = max(n_columns, n_columns + n_columns_diff)
+        for (line, logstr) in zip(lines, node_lines):
+            ln = "%-*s %s" % (2 * indentation_level, "".join(line), logstr)
+            ui.write(ln.rstrip() + '\n')
+
+        # ... and start over
+        prev_node_index = node_index
+        prev_n_columns_diff = n_columns_diff
+
 def get_limit(limit_opt):
     if limit_opt:
         try:
@@ -198,6 +264,14 @@
     else:
         return (len(repo) - 1, 0)
 
+def check_unsupported_flags(opts):
+    for op in ["follow", "follow_first", "date", "copies", "keyword", "remove",
+               "only_merges", "user", "only_branch", "prune", "newest_first",
+               "no_merges", "include", "exclude"]:
+        if op in opts and opts[op]:
+            raise Abort(_("--graph option is incompatible with --%s") % op)
+
+
 def graphlog(ui, repo, path=None, **opts):
     """show revision history alongside an ASCII revision graph
 
@@ -208,112 +282,191 @@
     directory.
     """
 
+    check_unsupported_flags(opts)
     limit = get_limit(opts["limit"])
-    (start_rev, stop_rev) = get_revs(repo, opts["rev"])
-    stop_rev = max(stop_rev, start_rev - limit + 1)
-    if start_rev == nullrev:
+    start, stop = get_revs(repo, opts["rev"])
+    stop = max(stop, start - limit + 1)
+    if start == nullrev:
         return
-    cs_printer = show_changeset(ui, repo, opts)
+
     if path:
         path = canonpath(repo.root, os.getcwd(), path)
-    if path:
-        grapher = filelog_grapher(repo, path, start_rev, stop_rev)
+    if path: # could be reset in canonpath
+        revdag = filerevs(repo, path, start, stop)
     else:
-        grapher = revision_grapher(repo, start_rev, stop_rev)
+        revdag = revisions(repo, start, stop)
+
     repo_parents = repo.dirstate.parents()
-    prev_n_columns_diff = 0
-    prev_node_index = 0
+    displayer = show_changeset(ui, repo, opts, buffered=True)
+    def graphabledag():
+        for (ctx, parents) in revdag:
+            # log_strings is the list of all log strings to draw alongside
+            # the graph.
+            displayer.show(ctx)
+            lines = displayer.hunk.pop(ctx.rev()).split("\n")[:-1]
+            char = ctx.node() in repo_parents and '@' or 'o'
+            yield (ctx.rev(), parents, char, lines)
 
-    for (rev, node, node_index, edges, n_columns, n_columns_diff) in grapher:
-        # log_strings is the list of all log strings to draw alongside
-        # the graph.
-        ui.pushbuffer()
-        cs_printer.show(rev, node)
-        log_strings = ui.popbuffer().split("\n")[:-1]
+    ascii(ui, grapher(graphabledag()))
+
+def outgoing_revs(ui, repo, dest, opts):
+    """cset DAG generator yielding (node, [parents]) tuples
 
-        if n_columns_diff == -1:
-            # Transform
-            #
-            #     | | |        | | |
-            #     o | |  into  o---+
-            #     |X /         |/ /
-            #     | |          | |
-            fix_long_right_edges(edges)
+    This generator function walks through the revisions not found
+    in the destination
+    """
+    limit = cmdutil.loglimit(opts)
+    dest, revs, checkout = hg.parseurl(
+        ui.expandpath(dest or 'default-push', dest or 'default'),
+        opts.get('rev'))
+    cmdutil.setremoteconfig(ui, opts)
+    if revs:
+        revs = [repo.lookup(rev) for rev in revs]
+    other = hg.repository(ui, dest)
+    ui.status(_('comparing with %s\n') % url.hidepassword(dest))
+    o = repo.findoutgoing(other, force=opts.get('force'))
+    if not o:
+        ui.status(_("no changes found\n"))
+        return
+    o = repo.changelog.nodesbetween(o, revs)[0]
+    o.reverse()
+    revdict = {}
+    for n in o:
+        revdict[repo.changectx(n).rev()]=True
+    count = 0
+    for n in o:
+        if count >= limit:
+            break
+        ctx = repo.changectx(n)
+        parents = [p.rev() for p in ctx.parents() if p.rev() in revdict]
+        parents.sort()
+        yield (ctx, parents)
+        count += 1
 
-        # add_padding_line says whether to rewrite
-        #
-        #     | | | |        | | | |
-        #     | o---+  into  | o---+
-        #     |  / /         |   | |  # <--- padding line
-        #     o | |          |  / /
-        #                    o | |
-        add_padding_line = (len(log_strings) > 2 and
-                            n_columns_diff == -1 and
-                            [x for (x, y) in edges if x + 1 < y])
+def goutgoing(ui, repo, dest=None, **opts):
+    """show the outgoing changesets alongside an ASCII revision graph
+
+    Print the outgoing changesets alongside a revision graph drawn with
+    ASCII characters.
 
-        # fix_nodeline_tail says whether to rewrite
-        #
-        #     | | o | |        | | o | |
-        #     | | |/ /         | | |/ /
-        #     | o | |    into  | o / /   # <--- fixed nodeline tail
-        #     | |/ /           | |/ /
-        #     o | |            o | |
-        fix_nodeline_tail = len(log_strings) <= 2 and not add_padding_line
+    Nodes printed as an @ character are parents of the working
+    directory.
+    """
+    check_unsupported_flags(opts)
+    revdag = outgoing_revs(ui, repo, dest, opts)
+    repo_parents = repo.dirstate.parents()
+    displayer = show_changeset(ui, repo, opts, buffered=True)
+    def graphabledag():
+        for (ctx, parents) in revdag:
+            # log_strings is the list of all log strings to draw alongside
+            # the graph.
+            displayer.show(ctx)
+            lines = displayer.hunk.pop(ctx.rev()).split("\n")[:-1]
+            char = ctx.node() in repo_parents and '@' or 'o'
+            yield (ctx.rev(), parents, char, lines)
+
+    ascii(ui, grapher(graphabledag()))
+
+def incoming_revs(other, chlist, opts):
+    """cset DAG generator yielding (node, [parents]) tuples
 
-        # nodeline is the line containing the node character (@ or o).
-        nodeline = ["|", " "] * node_index
-        if node in repo_parents:
-            node_ch = "@"
-        else:
-            node_ch = "o"
-        nodeline.extend([node_ch, " "])
+    This generator function walks through the revisions of the destination
+    not found in repo
+    """
+    limit = cmdutil.loglimit(opts)
+    chlist.reverse()
+    revdict = {}
+    for n in chlist:
+        revdict[other.changectx(n).rev()]=True
+    count = 0
+    for n in chlist:
+        if count >= limit:
+            break
+        ctx = other.changectx(n)
+        parents = [p.rev() for p in ctx.parents() if p.rev() in revdict]
+        parents.sort()
+        yield (ctx, parents)
+        count += 1
+
+def gincoming(ui, repo, source="default", **opts):
+    """show the incoming changesets alongside an ASCII revision graph
 
-        nodeline.extend(
-            get_nodeline_edges_tail(
-                node_index, prev_node_index, n_columns, n_columns_diff,
-                prev_n_columns_diff, fix_nodeline_tail))
+    Print the incoming changesets alongside a revision graph drawn with
+    ASCII characters.
+
+    Nodes printed as an @ character are parents of the working
+    directory.
+    """
+
+    check_unsupported_flags(opts)
+    source, revs, checkout = hg.parseurl(ui.expandpath(source), opts.get('rev'))
+    cmdutil.setremoteconfig(ui, opts)
+
+    other = hg.repository(ui, source)
+    ui.status(_('comparing with %s\n') % url.hidepassword(source))
+    if revs:
+        revs = [other.lookup(rev) for rev in revs]
+    incoming = repo.findincoming(other, heads=revs, force=opts["force"])
+    if not incoming:
+        try:
+            os.unlink(opts["bundle"])
+        except:
+            pass
+        ui.status(_("no changes found\n"))
+        return
 
-        # shift_interline is the line containing the non-vertical
-        # edges between this entry and the next.
-        shift_interline = ["|", " "] * node_index
-        if n_columns_diff == -1:
-            n_spaces = 1
-            edge_ch = "/"
-        elif n_columns_diff == 0:
-            n_spaces = 2
-            edge_ch = "|"
-        else:
-            n_spaces = 3
-            edge_ch = "\\"
-        shift_interline.extend(n_spaces * [" "])
-        shift_interline.extend([edge_ch, " "] * (n_columns - node_index - 1))
-
-        # Draw edges from the current node to its parents.
-        draw_edges(edges, nodeline, shift_interline)
+    cleanup = None
+    try:
+        fname = opts["bundle"]
+        if fname or not other.local():
+            # create a bundle (uncompressed if other repo is not local)
+            if revs is None:
+                cg = other.changegroup(incoming, "incoming")
+            else:
+                cg = other.changegroupsubset(incoming, revs, 'incoming')
+            bundletype = other.local() and "HG10BZ" or "HG10UN"
+            fname = cleanup = changegroup.writebundle(cg, fname, bundletype)
+            # keep written bundle?
+            if opts["bundle"]:
+                cleanup = None
+            if not other.local():
+                # use the created uncompressed bundlerepo
+                other = bundlerepo.bundlerepository(ui, repo.root, fname)
 
-        # lines is the list of all graph lines to print.
-        lines = [nodeline]
-        if add_padding_line:
-            lines.append(get_padding_line(node_index, n_columns, edges))
-        lines.append(shift_interline)
+        chlist = other.changelog.nodesbetween(incoming, revs)[0]
+        revdag = incoming_revs(other, chlist, opts)
+        other_parents = []
+        displayer = show_changeset(ui, other, opts, buffered=True)
+        def graphabledag():
+            for (ctx, parents) in revdag:
+                # log_strings is the list of all log strings to draw alongside
+                # the graph.
+                displayer.show(ctx)
+                lines = displayer.hunk.pop(ctx.rev()).split("\n")[:-1]
+                char = ctx.node() in other_parents and '@' or 'o'
+                yield (ctx.rev(), parents, char, lines)
 
-        # Make sure that there are as many graph lines as there are
-        # log strings.
-        while len(log_strings) < len(lines):
-            log_strings.append("")
-        if len(lines) < len(log_strings):
-            extra_interline = ["|", " "] * (n_columns + n_columns_diff)
-            while len(lines) < len(log_strings):
-                lines.append(extra_interline)
+        ascii(ui, grapher(graphabledag()))
+    finally:
+        if hasattr(other, 'close'):
+            other.close()
+        if cleanup:
+            os.unlink(cleanup)
 
-        # Print lines.
-        indentation_level = max(n_columns, n_columns + n_columns_diff)
-        for (line, logstr) in zip(lines, log_strings):
-            ui.write(format_line(line, indentation_level, logstr))
+def uisetup(ui):
+    '''Initialize the extension.'''
+    _wrapcmd(ui, 'log', commands.table, graphlog)
+    _wrapcmd(ui, 'incoming', commands.table, gincoming)
+    _wrapcmd(ui, 'outgoing', commands.table, goutgoing)
 
-        # ...and start over.
-        prev_node_index = node_index
-        prev_n_columns_diff = n_columns_diff
+def _wrapcmd(ui, cmd, table, wrapfn):
+    '''wrap the command'''
+    def graph(orig, *args, **kwargs):
+        if kwargs['graph']:
+            return wrapfn(*args, **kwargs)
+        return orig(*args, **kwargs)
+    entry = extensions.wrapcommand(table, cmd, graph)
+    entry[1].append(('g', 'graph', None, _("show the revision DAG")))
 
 cmdtable = {
     "glog":
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hgext/hgcia.py	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,245 @@
+# Copyright (C) 2007-8 Brendan Cully <brendan@kublai.com>
+# Published under the GNU GPL
+
+"""CIA notification
+
+This is meant to be run as a changegroup or incoming hook.
+To configure it, set the following options in your hgrc:
+
+[cia]
+# your registered CIA user name
+user = foo
+# the name of the project in CIA
+project = foo
+# the module (subproject) (optional)
+#module = foo
+# Append a diffstat to the log message (optional)
+#diffstat = False
+# Template to use for log messages (optional)
+#template = {desc}\n{baseurl}/rev/{node}-- {diffstat}
+# Style to use (optional)
+#style = foo
+# The URL of the CIA notification service (optional)
+# You can use mailto: URLs to send by email, eg
+# mailto:cia@cia.vc
+# Make sure to set email.from if you do this.
+#url = http://cia.vc/
+# print message instead of sending it (optional)
+#test = False
+
+[hooks]
+# one of these:
+changegroup.cia = python:hgcia.hook
+#incoming.cia = python:hgcia.hook
+
+[web]
+# If you want hyperlinks (optional)
+baseurl = http://server/path/to/repo
+"""
+
+from mercurial.i18n import _
+from mercurial.node import *
+from mercurial import cmdutil, patch, templater, util, mail
+import email.Parser
+
+import xmlrpclib
+from xml.sax import saxutils
+
+socket_timeout = 30 # seconds
+try:
+    # set a timeout for the socket so you don't have to wait so looooong
+    # when cia.vc is having problems. requires python >= 2.3:
+    import socket
+    socket.setdefaulttimeout(socket_timeout)
+except:
+    pass
+
+HGCIA_VERSION = '0.1'
+HGCIA_URL = 'http://hg.kublai.com/mercurial/hgcia'
+
+
+class ciamsg(object):
+    """ A CIA message """
+    def __init__(self, cia, ctx):
+        self.cia = cia
+        self.ctx = ctx
+        self.url = self.cia.url
+
+    def fileelem(self, path, uri, action):
+        if uri:
+            uri = ' uri=%s' % saxutils.quoteattr(uri)
+        return '<file%s action=%s>%s</file>' % (
+            uri, saxutils.quoteattr(action), saxutils.escape(path))
+
+    def fileelems(self):
+        n = self.ctx.node()
+        f = self.cia.repo.status(self.ctx.parents()[0].node(), n)
+        url = self.url or ''
+        elems = []
+        for path in f[0]:
+            uri = '%s/diff/%s/%s' % (url, short(n), path)
+            elems.append(self.fileelem(path, url and uri, 'modify'))
+        for path in f[1]:
+            # TODO: copy/rename ?
+            uri = '%s/file/%s/%s' % (url, short(n), path)
+            elems.append(self.fileelem(path, url and uri, 'add'))
+        for path in f[2]:
+            elems.append(self.fileelem(path, '', 'remove'))
+
+        return '\n'.join(elems)
+
+    def sourceelem(self, project, module=None, branch=None):
+        msg = ['<source>', '<project>%s</project>' % saxutils.escape(project)]
+        if module:
+            msg.append('<module>%s</module>' % saxutils.escape(module))
+        if branch:
+            msg.append('<branch>%s</branch>' % saxutils.escape(branch))
+        msg.append('</source>')
+
+        return '\n'.join(msg)
+
+    def diffstat(self):
+        class patchbuf:
+            def __init__(self):
+                self.lines = []
+                # diffstat is stupid
+                self.name = 'cia'
+            def write(self, data):
+                self.lines.append(data)
+            def close(self):
+                pass
+
+        n = self.ctx.node()
+        pbuf = patchbuf()
+        patch.export(self.cia.repo, [n], fp=pbuf)
+        return patch.diffstat(pbuf.lines) or ''
+
+    def logmsg(self):
+        diffstat = self.cia.diffstat and self.diffstat() or ''
+        self.cia.ui.pushbuffer()
+        self.cia.templater.show(self.ctx, changes=self.ctx.changeset(),
+                                url=self.cia.url, diffstat=diffstat)
+        return self.cia.ui.popbuffer()
+
+    def xml(self):
+        n = short(self.ctx.node())
+        src = self.sourceelem(self.cia.project, module=self.cia.module,
+                              branch=self.ctx.branch())
+        # unix timestamp
+        dt = self.ctx.date()
+        timestamp = dt[0]
+
+        author = saxutils.escape(self.ctx.user())
+        rev = '%d:%s' % (self.ctx.rev(), n)
+        log = saxutils.escape(self.logmsg())
+
+        url = self.url and '<url>%s/rev/%s</url>' % (saxutils.escape(self.url),
+                                                     n) or ''
+
+        msg = """
+<message>
+  <generator>
+    <name>Mercurial (hgcia)</name>
+    <version>%s</version>
+    <url>%s</url>
+    <user>%s</user>
+  </generator>
+  %s
+  <body>
+    <commit>
+      <author>%s</author>
+      <version>%s</version>
+      <log>%s</log>
+      %s
+      <files>%s</files>
+    </commit>
+  </body>
+  <timestamp>%d</timestamp>
+</message>
+""" % \
+            (HGCIA_VERSION, saxutils.escape(HGCIA_URL),
+            saxutils.escape(self.cia.user), src, author, rev, log, url,
+            self.fileelems(), timestamp)
+
+        return msg
+
+
+class hgcia(object):
+    """ CIA notification class """
+
+    deftemplate = '{desc}'
+    dstemplate = '{desc}\n-- \n{diffstat}'
+
+    def __init__(self, ui, repo):
+        self.ui = ui
+        self.repo = repo
+
+        self.ciaurl = self.ui.config('cia', 'url', 'http://cia.vc')
+        self.user = self.ui.config('cia', 'user')
+        self.project = self.ui.config('cia', 'project')
+        self.module = self.ui.config('cia', 'module')
+        self.diffstat = self.ui.configbool('cia', 'diffstat')
+        self.emailfrom = self.ui.config('email', 'from')
+        self.dryrun = self.ui.configbool('cia', 'test')
+        self.url = self.ui.config('web', 'baseurl')
+
+        style = self.ui.config('cia', 'style')
+        template = self.ui.config('cia', 'template')
+        if not template:
+            template = self.diffstat and self.dstemplate or self.deftemplate
+        template = templater.parsestring(template, quoted=False)
+        t = cmdutil.changeset_templater(self.ui, self.repo, False, style, False)
+        t.use_template(template)
+        self.templater = t
+
+    def sendrpc(self, msg):
+        srv = xmlrpclib.Server(self.ciaurl)
+        srv.hub.deliver(msg)
+
+    def sendemail(self, address, data):
+        p = email.Parser.Parser()
+        msg = p.parsestr(data)
+        msg['Date'] = util.datestr(format="%a, %d %b %Y %H:%M:%S %1%2")
+        msg['To'] = address
+        msg['From'] = self.emailfrom
+        msg['Subject'] = 'DeliverXML'
+        msg['Content-type'] = 'text/xml'
+        msgtext = msg.as_string(0)
+
+        self.ui.status(_('hgcia: sending update to %s\n') % address)
+        mail.sendmail(self.ui, util.email(self.emailfrom),
+                      [address], msgtext)
+
+
+def hook(ui, repo, hooktype, node=None, url=None, **kwargs):
+    """ send CIA notification """
+    def sendmsg(cia, ctx):
+        msg = ciamsg(cia, ctx).xml()
+        if cia.dryrun:
+            ui.write(msg)
+        elif cia.ciaurl.startswith('mailto:'):
+            if not cia.emailfrom:
+                raise util.Abort(_('email.from must be defined when '
+                                   'sending by email'))
+            cia.sendemail(cia.ciaurl[7:], msg)
+        else:
+            cia.sendrpc(msg)
+
+    n = bin(node)
+    cia = hgcia(ui, repo)
+    if not cia.user:
+        ui.debug(_('cia: no user specified'))
+        return
+    if not cia.project:
+        ui.debug(_('cia: no project specified'))
+        return
+    if hooktype == 'changegroup':
+        start = repo.changelog.rev(n)
+        end = len(repo.changelog)
+        for rev in xrange(start, end):
+            n = repo.changelog.node(rev)
+            ctx = repo.changectx(n)
+            sendmsg(cia, ctx)
+    else:
+        ctx = repo.changectx(n)
+        sendmsg(cia, ctx)
--- a/hgext/inotify/__init__.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/hgext/inotify/__init__.py	Sun Dec 07 19:34:07 2008 +0100
@@ -52,6 +52,8 @@
 
         def status(self, match, ignored, clean, unknown=True):
             files = match.files()
+            if '.' in files:
+                files = []
             try:
                 if not ignored and not self.inotifyserver:
                     result = client.query(ui, repo, files, match, False,
@@ -71,22 +73,24 @@
                     if result is not None:
                         return result
             except (OSError, socket.error), err:
+                autostart = ui.configbool('inotify', 'autostart', True)
+
                 if err[0] == errno.ECONNREFUSED:
                     ui.warn(_('(found dead inotify server socket; '
                                    'removing it)\n'))
                     os.unlink(repo.join('inotify.sock'))
-                if err[0] in (errno.ECONNREFUSED, errno.ENOENT) and \
-                        ui.configbool('inotify', 'autostart', True):
+                if err[0] in (errno.ECONNREFUSED, errno.ENOENT) and autostart:
                     query = None
                     ui.debug(_('(starting inotify server)\n'))
                     try:
-                        server.start(ui, repo)
-                        query = client.query
-                    except server.AlreadyStartedException, inst:
-                        # another process may have started its own
-                        # inotify server while this one was starting.
-                        ui.debug(str(inst))
-                        query = client.query
+                        try:
+                            server.start(ui, repo)
+                            query = client.query
+                        except server.AlreadyStartedException, inst:
+                            # another process may have started its own
+                            # inotify server while this one was starting.
+                            ui.debug(str(inst))
+                            query = client.query
                     except Exception, inst:
                         ui.warn(_('could not start inotify server: '
                                        '%s\n') % inst)
@@ -97,8 +101,9 @@
                         except socket.error, err:
                             ui.warn(_('could not talk to new inotify '
                                            'server: %s\n') % err[-1])
-                elif err[0] == errno.ENOENT:
-                    ui.warn(_('(inotify server not running)\n'))
+                elif err[0] in (errno.ECONNREFUSED, errno.ENOENT):
+                    # silently ignore normal errors if autostart is False
+                    ui.debug(_('(inotify server not running)\n'))
                 else:
                     ui.warn(_('failed to contact inotify server: %s\n')
                              % err[-1])
--- a/hgext/inotify/client.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/hgext/inotify/client.py	Sun Dec 07 19:34:07 2008 +0100
@@ -7,7 +7,6 @@
 # of the GNU General Public License, incorporated herein by reference.
 
 from mercurial.i18n import _
-from mercurial import ui
 import common
 import os, socket, struct
 
--- a/hgext/inotify/server.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/hgext/inotify/server.py	Sun Dec 07 19:34:07 2008 +0100
@@ -7,7 +7,7 @@
 # of the GNU General Public License, incorporated herein by reference.
 
 from mercurial.i18n import _
-from mercurial import osutil, ui, util
+from mercurial import osutil, util
 import common
 import errno, os, select, socket, stat, struct, sys, tempfile, time
 
@@ -15,7 +15,6 @@
     import linux as inotify
     from linux import watcher
 except ImportError:
-    print >> sys.stderr, '*** native support is required for this extension'
     raise
 
 class AlreadyStartedException(Exception): pass
@@ -709,6 +708,26 @@
                 timeobj.handle_timeout()
 
 def start(ui, repo):
+    def closefds(ignore):
+        # (from python bug #1177468)
+        # close all inherited file descriptors
+        # Python 2.4.1 and later use /dev/urandom to seed the random module's RNG
+        # a file descriptor is kept internally as os._urandomfd (created on demand
+        # the first time os.urandom() is called), and should not be closed
+        try:
+            os.urandom(4)
+            urandom_fd = getattr(os, '_urandomfd', None)
+        except AttributeError:
+            urandom_fd = None
+        ignore.append(urandom_fd)
+        for fd in range(3, 256):
+            if fd in ignore:
+                continue
+            try:
+                os.close(fd)
+            except OSError:
+                pass
+
     m = Master(ui, repo)
     sys.stdout.flush()
     sys.stderr.flush()
@@ -717,6 +736,7 @@
     if pid:
         return pid
 
+    closefds([m.server.fileno(), m.watcher.fileno()])
     os.setsid()
 
     fd = os.open('/dev/null', os.O_RDONLY)
--- a/hgext/keyword.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/hgext/keyword.py	Sun Dec 07 19:34:07 2008 +0100
@@ -139,19 +139,13 @@
         self.ct = cmdutil.changeset_templater(self.ui, self.repo,
                                               False, '', False)
 
-    def getnode(self, path, fnode):
-        '''Derives changenode from file path and filenode.'''
-        # used by kwfilelog.read and kwexpand
-        c = self.repo.filectx(path, fileid=fnode)
-        return c.node()
-
-    def substitute(self, data, path, node, subfunc):
+    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])
             self.ui.pushbuffer()
-            self.ct.show(changenode=node, root=self.repo.root, file=path)
+            self.ct.show(ctx, root=self.repo.root, file=path)
             ekw = templatefilters.firstline(self.ui.popbuffer())
             return '$%s: %s $' % (kw, ekw)
         return subfunc(kwsub, data)
@@ -159,8 +153,8 @@
     def expand(self, path, node, data):
         '''Returns data with keywords expanded.'''
         if not self.restrict and self.matcher(path) and not util.binary(data):
-            changenode = self.getnode(path, node)
-            return self.substitute(data, path, changenode, self.re_kw.sub)
+            ctx = self.repo.filectx(path, fileid=node).changectx()
+            return self.substitute(data, path, ctx, self.re_kw.sub)
         return data
 
     def iskwfile(self, path, flagfunc):
@@ -171,14 +165,12 @@
 
     def overwrite(self, node, expand, files):
         '''Overwrites selected files expanding/shrinking keywords.'''
+        ctx = self.repo[node]
+        mf = ctx.manifest()
         if node is not None:     # commit
-            ctx = self.repo[node]
-            mf = ctx.manifest()
             files = [f for f in ctx.files() if f in mf]
             notify = self.ui.debug
         else:                    # kwexpand/kwshrink
-            ctx = self.repo['.']
-            mf = ctx.manifest()
             notify = self.ui.note
         candidates = [f for f in files if self.iskwfile(f, ctx.flags)]
         if candidates:
@@ -190,8 +182,9 @@
                 if util.binary(data):
                     continue
                 if expand:
-                    changenode = node or self.getnode(f, mf[f])
-                    data, found = self.substitute(data, f, changenode,
+                    if node is None:
+                        ctx = self.repo.filectx(f, fileid=mf[f]).changectx()
+                    data, found = self.substitute(data, f, ctx,
                                                   self.re_kw.subn)
                 else:
                     found = self.re_kw.search(data)
@@ -355,8 +348,8 @@
     ui.note(_('unhooked all commit hooks\n'))
     ui.note('hg -R "%s" ci -m "%s"\n' % (tmpdir, msg))
     repo.commit(text=msg)
-    format = ui.verbose and ' in %s' % path or ''
-    demostatus('%s keywords expanded%s' % (kwstatus, format))
+    fmt = ui.verbose and ' in %s' % path or ''
+    demostatus('%s keywords expanded%s' % (kwstatus, fmt))
     ui.write(repo.wread(fn))
     ui.debug(_('\nremoving temporary repo %s\n') % tmpdir)
     shutil.rmtree(tmpdir, ignore_errors=True)
@@ -389,9 +382,9 @@
     if opts.get('all') or opts.get('ignore'):
         kwfstats += (('I', [f for f in files if f not in kwfiles]),)
     for char, filenames in kwfstats:
-        format = (opts.get('all') or ui.verbose) and '%s %%s\n' % char or '%s\n'
+        fmt = (opts.get('all') or ui.verbose) and '%s %%s\n' % char or '%s\n'
         for f in filenames:
-            ui.write(format % repo.pathto(f, cwd))
+            ui.write(fmt % repo.pathto(f, cwd))
 
 def shrink(ui, repo, *pats, **opts):
     '''revert expanded keywords in working directory
@@ -494,10 +487,10 @@
                 del wlock, lock
 
     # monkeypatches
-    def kwpatchfile_init(orig, self, ui, fname, missing=False):
+    def kwpatchfile_init(orig, self, ui, fname, opener, missing=False):
         '''Monkeypatch/wrap patch.patchfile.__init__ to avoid
         rejects or conflicts due to expanded keywords in working dir.'''
-        orig(self, ui, fname, missing)
+        orig(self, ui, fname, opener, missing)
         # shrink keywords read from working dir
         self.lines = kwt.shrinklines(self.fname, self.lines)
 
--- a/hgext/mq.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/hgext/mq.py	Sun Dec 07 19:34:07 2008 +0100
@@ -56,6 +56,67 @@
     def __str__(self):
         return self.rev + ':' + self.name
 
+class patchheader(object):
+    def __init__(self, message, comments, user, date, haspatch):
+        self.message = message
+        self.comments = comments
+        self.user = user
+        self.date = date
+        self.haspatch = haspatch
+
+    def setuser(self, user):
+        if not self.setheader(['From: ', '# User '], user):
+            try:
+                patchheaderat = self.comments.index('# HG changeset patch')
+                self.comments.insert(patchheaderat + 1,'# User ' + user)
+            except ValueError:
+                self.comments = ['From: ' + user, ''] + self.comments
+        self.user = user
+
+    def setdate(self, date):
+        if self.setheader(['# Date '], date):
+            self.date = date
+
+    def setmessage(self, message):
+        if self.comments:
+            self._delmsg()
+        self.message = [message]
+        self.comments += self.message
+
+    def setheader(self, prefixes, new):
+        '''Update all references to a field in the patch header.
+        If none found, add it email style.'''
+        res = False
+        for prefix in prefixes:
+            for i in xrange(len(self.comments)):
+                if self.comments[i].startswith(prefix):
+                    self.comments[i] = prefix + new
+                    res = True
+                    break
+        return res
+
+    def __str__(self):
+        if not self.comments:
+            return ''
+        return '\n'.join(self.comments) + '\n\n'
+
+    def _delmsg(self):
+        '''Remove existing message, keeping the rest of the comments fields.
+        If comments contains 'subject: ', message will prepend
+        the field and a blank line.'''
+        if self.message:
+            subj = 'subject: ' + self.message[0].lower()
+            for i in xrange(len(self.comments)):
+                if subj == self.comments[i].lower():
+                    del self.comments[i]
+                    self.message = self.message[2:]
+                    break
+        ci = 0
+        for mi in xrange(len(self.message)):
+            while self.message[mi] != self.comments[ci]:
+                ci += 1
+            del self.comments[ci]
+
 class queue:
     def __init__(self, ui, path, patchdir=None):
         self.basepath = path
@@ -307,7 +368,7 @@
         if format and format.startswith("tag") and subject:
             message.insert(0, "")
             message.insert(0, subject)
-        return (message, comments, user, date, diffstart > 1)
+        return patchheader(message, comments, user, date, diffstart > 1)
 
     def removeundo(self, repo):
         undo = repo.sjoin('undo')
@@ -351,13 +412,13 @@
         if n == None:
             raise util.Abort(_("repo commit failed"))
         try:
-            message, comments, user, date, patchfound = mergeq.readheaders(patch)
+            ph = mergeq.readheaders(patch)
         except:
             raise util.Abort(_("unable to read %s") % patch)
 
         patchf = self.opener(patch, "w")
+        comments = str(ph)
         if comments:
-            comments = "\n".join(comments) + '\n\n'
             patchf.write(comments)
         self.printdiff(repo, head, n, fp=patchf)
         patchf.close()
@@ -477,12 +538,13 @@
             pf = os.path.join(patchdir, patchname)
 
             try:
-                message, comments, user, date, patchfound = self.readheaders(patchname)
+                ph = self.readheaders(patchname)
             except:
                 self.ui.warn(_("Unable to read %s\n") % patchname)
                 err = 1
                 break
 
+            message = ph.message
             if not message:
                 message = _("imported patch %s\n") % patchname
             else:
@@ -512,7 +574,7 @@
 
             files = patch.updatedir(self.ui, repo, files)
             match = cmdutil.matchfiles(repo, files or [])
-            n = repo.commit(files, message, user, date, match=match,
+            n = repo.commit(files, message, ph.user, ph.date, match=match,
                             force=True)
 
             if n == None:
@@ -522,7 +584,7 @@
                 self.applied.append(statusentry(revlog.hex(n), patchname))
 
             if patcherr:
-                if not patchfound:
+                if not ph.haspatch:
                     self.ui.warn(_("patch %s is empty\n") % patchname)
                     err = 0
                 else:
@@ -824,11 +886,15 @@
         raise util.Abort(_("patch %s not in series") % patch)
 
     def push(self, repo, patch=None, force=False, list=False,
-             mergeq=None):
+             mergeq=None, all=False):
         wlock = repo.wlock()
         if repo.dirstate.parents()[0] != repo.changelog.tip():
             self.ui.status(_("(working directory not at tip)\n"))
 
+        if not self.series:
+            self.ui.warn(_('no patches in series\n'))
+            return 0
+
         try:
             patch = self.lookup(patch)
             # Suppose our series file is: A B C and the current 'top'
@@ -841,26 +907,36 @@
                     if info[0] < len(self.applied) - 1:
                         raise util.Abort(
                             _("cannot push to a previous patch: %s") % patch)
-                    if info[0] < len(self.series) - 1:
-                        self.ui.warn(
-                            _('qpush: %s is already at the top\n') % patch)
+                    self.ui.warn(
+                        _('qpush: %s is already at the top\n') % patch)
+                    return
+                pushable, reason = self.pushable(patch)
+                if not pushable:
+                    if reason:
+                        reason = _('guarded by %r') % reason
                     else:
-                        self.ui.warn(_('all patches are currently applied\n'))
-                    return
+                        reason = _('no matching guards')
+                    self.ui.warn(_("cannot push '%s' - %s\n") % (patch, reason))
+                    return 1
+            elif all:
+                patch = self.series[-1]
+                if self.isapplied(patch):
+                    self.ui.warn(_('all patches are currently applied\n'))
+                    return 0
 
             # Following the above example, starting at 'top' of B:
             # qpush should be performed (pushes C), but a subsequent
             # qpush without an argument is an error (nothing to
             # apply). This allows a loop of "...while hg qpush..." to
             # work as it detects an error when done
-            if self.series_end() == len(self.series):
+            start = self.series_end()
+            if start == len(self.series):
                 self.ui.warn(_('patch series already fully applied\n'))
                 return 1
             if not force:
                 self.check_localchanges(repo)
 
-            self.applied_dirty = 1;
-            start = self.series_end()
+            self.applied_dirty = 1
             if start > 0:
                 self.check_toppatch(repo)
             if not patch:
@@ -1001,6 +1077,8 @@
         if len(self.applied) == 0:
             self.ui.write(_("No patches applied\n"))
             return 1
+        msg = opts.get('msg', '').rstrip()
+        newuser = opts.get('user')
         newdate = opts.get('date')
         if newdate:
             newdate = '%d %d' % util.parsedate(newdate)
@@ -1013,9 +1091,9 @@
                 raise util.Abort(_("cannot refresh a revision with children"))
             cparents = repo.changelog.parents(top)
             patchparent = self.qparents(repo, top)
-            message, comments, user, date, patchfound = self.readheaders(patchfn)
+            ph = self.readheaders(patchfn)
 
-            patchf = self.opener(patchfn, 'r+')
+            patchf = self.opener(patchfn, 'r')
 
             # if the patch was a git patch, refresh it as a git patch
             for line in patchf:
@@ -1023,59 +1101,21 @@
                     self.diffopts().git = True
                     break
 
-            msg = opts.get('msg', '').rstrip()
-            if msg and comments:
-                # Remove existing message, keeping the rest of the comments
-                # fields.
-                # If comments contains 'subject: ', message will prepend
-                # the field and a blank line.
-                if message:
-                    subj = 'subject: ' + message[0].lower()
-                    for i in xrange(len(comments)):
-                        if subj == comments[i].lower():
-                            del comments[i]
-                            message = message[2:]
-                            break
-                ci = 0
-                for mi in xrange(len(message)):
-                    while message[mi] != comments[ci]:
-                        ci += 1
-                    del comments[ci]
+            if msg:
+                ph.setmessage(msg)
+            if newuser:
+                ph.setuser(newuser)
+            if newdate:
+                ph.setdate(newdate)
 
-            def setheaderfield(comments, prefixes, new):
-                # Update all references to a field in the patch header.
-                # If none found, add it email style.
-                res = False
-                for prefix in prefixes:
-                    for i in xrange(len(comments)):
-                        if comments[i].startswith(prefix):
-                            comments[i] = prefix + new
-                            res = True
-                            break
-                return res
-
-            newuser = opts.get('user')
-            if newuser:
-                if not setheaderfield(comments, ['From: ', '# User '], newuser):
-                    try:
-                        patchheaderat = comments.index('# HG changeset patch')
-                        comments.insert(patchheaderat + 1,'# User ' + newuser)
-                    except ValueError:
-                        comments = ['From: ' + newuser, ''] + comments
-                user = newuser
-
-            if newdate:
-                if setheaderfield(comments, ['# Date '], newdate):
-                    date = newdate
-
-            if msg:
-                comments.append(msg)
+            # only commit new patch when write is complete
+            patchf = self.opener(patchfn, 'w', atomictemp=True)
 
             patchf.seek(0)
             patchf.truncate()
 
+            comments = str(ph)
             if comments:
-                comments = "\n".join(comments) + '\n\n'
                 patchf.write(comments)
 
             if opts.get('git'):
@@ -1148,69 +1188,84 @@
                                     changes=c, opts=self.diffopts())
                 for chunk in chunks:
                     patchf.write(chunk)
-                patchf.close()
 
-                repo.dirstate.setparents(*cparents)
-                copies = {}
-                for dst in a:
-                    src = repo.dirstate.copied(dst)
-                    if src is not None:
-                        copies.setdefault(src, []).append(dst)
-                    repo.dirstate.add(dst)
-                # remember the copies between patchparent and tip
-                # this may be slow, so don't do it if we're not tracking copies
-                if self.diffopts().git:
-                    for dst in aaa:
-                        f = repo.file(dst)
-                        src = f.renamed(man[dst])
-                        if src:
-                            copies.setdefault(src[0], []).extend(copies.get(dst, []))
-                            if dst in a:
-                                copies[src[0]].append(dst)
-                        # we can't copy a file created by the patch itself
-                        if dst in copies:
-                            del copies[dst]
-                for src, dsts in copies.iteritems():
-                    for dst in dsts:
-                        repo.dirstate.copy(src, dst)
-                for f in r:
-                    repo.dirstate.remove(f)
-                # if the patch excludes a modified file, mark that
-                # file with mtime=0 so status can see it.
-                mm = []
-                for i in xrange(len(m)-1, -1, -1):
-                    if not matchfn(m[i]):
-                        mm.append(m[i])
-                        del m[i]
-                for f in m:
-                    repo.dirstate.normal(f)
-                for f in mm:
-                    repo.dirstate.normallookup(f)
-                for f in forget:
-                    repo.dirstate.forget(f)
+                try:
+                    copies = {}
+                    for dst in a:
+                        src = repo.dirstate.copied(dst)
+                        # during qfold, the source file for copies may
+                        # be removed. Treat this as a simple add.
+                        if src is not None and src in repo.dirstate:
+                            copies.setdefault(src, []).append(dst)
+                        repo.dirstate.add(dst)
+                    # remember the copies between patchparent and tip
+                    # this may be slow, so don't do it if we're not tracking copies
+                    if self.diffopts().git:
+                        for dst in aaa:
+                            f = repo.file(dst)
+                            src = f.renamed(man[dst])
+                            if src:
+                                copies.setdefault(src[0], []).extend(copies.get(dst, []))
+                                if dst in a:
+                                    copies[src[0]].append(dst)
+                            # we can't copy a file created by the patch itself
+                            if dst in copies:
+                                del copies[dst]
+                    for src, dsts in copies.iteritems():
+                        for dst in dsts:
+                            repo.dirstate.copy(src, dst)
+                    for f in r:
+                        repo.dirstate.remove(f)
+                    # if the patch excludes a modified file, mark that
+                    # file with mtime=0 so status can see it.
+                    mm = []
+                    for i in xrange(len(m)-1, -1, -1):
+                        if not matchfn(m[i]):
+                            mm.append(m[i])
+                            del m[i]
+                    for f in m:
+                        repo.dirstate.normal(f)
+                    for f in mm:
+                        repo.dirstate.normallookup(f)
+                    for f in forget:
+                        repo.dirstate.forget(f)
 
-                if not msg:
-                    if not message:
-                        message = "[mq]: %s\n" % patchfn
+                    if not msg:
+                        if not ph.message:
+                            message = "[mq]: %s\n" % patchfn
+                        else:
+                            message = "\n".join(ph.message)
                     else:
-                        message = "\n".join(message)
-                else:
-                    message = msg
+                        message = msg
+
+                    user = ph.user or changes[1]
 
-                if not user:
-                    user = changes[1]
+                    # assumes strip can roll itself back if interrupted
+                    repo.dirstate.setparents(*cparents)
+                    self.applied.pop()
+                    self.applied_dirty = 1
+                    self.strip(repo, top, update=False,
+                               backup='strip')
+                except:
+                    repo.dirstate.invalidate()
+                    raise
 
-                self.applied.pop()
-                self.applied_dirty = 1
-                self.strip(repo, top, update=False,
-                           backup='strip')
-                n = repo.commit(match.files(), message, user, date, match=match,
-                                force=1)
-                self.applied.append(statusentry(revlog.hex(n), patchfn))
-                self.removeundo(repo)
+                try:
+                    # might be nice to attempt to roll back strip after this
+                    patchf.rename()
+                    n = repo.commit(match.files(), message, user, ph.date,
+                                    match=match, force=1)
+                    self.applied.append(statusentry(revlog.hex(n), patchfn))
+                except:
+                    ctx = repo[cparents[0]]
+                    repo.dirstate.rebuild(ctx.node(), ctx.manifest())
+                    self.save_dirty()
+                    self.ui.warn(_('refresh interrupted while patch was popped! '
+                                   '(revert --all, qpush to recover)\n'))
+                    raise
             else:
                 self.printdiff(repo, patchparent, fp=patchf)
-                patchf.close()
+                patchf.rename()
                 added = repo.status()[1]
                 for a in added:
                     f = repo.wjoin(a)
@@ -1228,6 +1283,7 @@
                 self.push(repo, force=True)
         finally:
             del wlock
+            self.removeundo(repo)
 
     def init(self, repo, create=False):
         if not create and os.path.isdir(self.path):
@@ -1259,7 +1315,8 @@
                 summary=False):
         def displayname(patchname):
             if summary:
-                msg = self.readheaders(patchname)[0]
+                ph = self.readheaders(patchname)
+                msg = ph.message
                 msg = msg and ': ' + msg[0] or ': '
             else:
                 msg = ''
@@ -1528,7 +1585,7 @@
                         text = sys.stdin.read()
                     else:
                         text = url.open(self.ui, filename).read()
-                except IOError:
+                except (OSError, IOError):
                     raise util.Abort(_("unable to read %s") % filename)
                 if not patchname:
                     patchname = normname(os.path.basename(filename))
@@ -1607,7 +1664,7 @@
     An existing changeset may be placed under mq control with --rev
     (e.g. qimport --rev tip -n patch will place tip under mq control).
     With --git, patches imported with --rev will use the git diff
-    format. See the gitdiffs help topic for information on why this is
+    format. See the diffs help topic for information on why this is
     important for preserving rename/copy information and permission changes.
     """
     q = repo.mq
@@ -1774,9 +1831,10 @@
     -e, -m or -l set the patch header as well as the commit message. If none
     is specified, the header is empty and the commit message is '[mq]: PATCH'.
 
-    Use the --git option to keep the patch in the git extended diff format.
-    Read the gitdiffs help topic for more information on why this is
-    important for preserving permission changes and copy/rename information.
+    Use the --git option to keep the patch in the git extended diff
+    format. Read the diffs help topic for more information on why this
+    is important for preserving permission changes and copy/rename
+    information.
     """
     msg = cmdutil.logmessage(opts)
     def getmsg(): return ui.edit(msg, ui.username())
@@ -1803,7 +1861,7 @@
 
     hg add/remove/copy/rename work as usual, though you might want to use
     git-style patches (--git or [diff] git=1) to track copies and renames.
-    See the gitdiffs help topic for more information on the git diff format.
+    See the diffs help topic for more information on the git diff format.
     """
     q = repo.mq
     message = cmdutil.logmessage(opts)
@@ -1814,8 +1872,8 @@
         if message:
             raise util.Abort(_('option "-e" incompatible with "-m" or "-l"'))
         patch = q.applied[-1].name
-        (message, comment, user, date, hasdiff) = q.readheaders(patch)
-        message = ui.edit('\n'.join(message), user or ui.username())
+        ph = q.readheaders(patch)
+        message = ui.edit('\n'.join(ph.message), ph.user or ui.username())
     setupheaderopts(ui, opts)
     ret = q.refresh(repo, pats, msg=message, **opts)
     q.save_dirty()
@@ -1873,7 +1931,9 @@
 
     for p in patches:
         if not message:
-            messages.append(q.readheaders(p)[0])
+            ph = q.readheaders(p)
+            if ph.message:
+                messages.append(ph.message)
         pf = q.join(p)
         (patchsuccess, files, fuzz) = q.patch(repo, pf)
         if not patchsuccess:
@@ -1881,7 +1941,8 @@
         patch.updatedir(ui, repo, files)
 
     if not message:
-        message, comments, user = q.readheaders(parent)[0:3]
+        ph = q.readheaders(parent)
+        message, user = ph.message, ph.user
         for msg in messages:
             message.append('* * *')
             message.extend(msg)
@@ -1964,9 +2025,9 @@
             ui.write('No patches applied\n')
             return 1
         patch = q.lookup('qtip')
-    message = repo.mq.readheaders(patch)[0]
+    ph = repo.mq.readheaders(patch)
 
-    ui.write('\n'.join(message) + '\n')
+    ui.write('\n'.join(ph.message) + '\n')
 
 def lastsavename(path):
     (directory, base) = os.path.split(path)
@@ -2000,11 +2061,6 @@
     q = repo.mq
     mergeq = None
 
-    if opts['all']:
-        if not q.series:
-            ui.warn(_('no patches in series\n'))
-            return 0
-        patch = q.series[-1]
     if opts['merge']:
         if opts['name']:
             newpath = repo.join(opts['name'])
@@ -2016,7 +2072,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)
+                 mergeq=mergeq, all=opts.get('all'))
     return ret
 
 def pop(ui, repo, patch=None, **opts):
--- a/hgext/notify.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/hgext/notify.py	Sun Dec 07 19:34:07 2008 +0100
@@ -165,7 +165,7 @@
     def node(self, node):
         '''format one changeset.'''
 
-        self.t.show(changenode=node, changes=self.repo.changelog.read(node),
+        self.t.show(self.repo[node], changes=self.repo.changelog.read(node),
                     baseurl=self.ui.config('web', 'baseurl'),
                     root=self.repo.root,
                     webroot=self.root)
--- a/hgext/patchbomb.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/hgext/patchbomb.py	Sun Dec 07 19:34:07 2008 +0100
@@ -68,6 +68,119 @@
 from mercurial.i18n import _
 from mercurial.node import bin
 
+class exportee:
+    def __init__(self, container):
+        self.lines = []
+        self.container = container
+        self.name = 'email'
+
+    def write(self, data):
+        self.lines.append(data)
+
+    def close(self):
+        self.container.append(''.join(self.lines).split('\n'))
+        self.lines = []
+
+def prompt(ui, prompt, default=None, rest=': ', empty_ok=False):
+    if not ui.interactive:
+        return default
+    if default:
+        prompt += ' [%s]' % default
+    prompt += rest
+    while True:
+        r = ui.prompt(prompt, default=default)
+        if r:
+            return r
+        if default is not None:
+            return default
+        if empty_ok:
+            return r
+        ui.warn(_('Please enter a valid value.\n'))
+
+def cdiffstat(ui, summary, patchlines):
+    s = patch.diffstat(patchlines)
+    if s:
+        if summary:
+            ui.write(summary, '\n')
+            ui.write(s, '\n')
+        ans = prompt(ui, _('Does the diffstat above look okay? '), 'y')
+        if not ans.lower().startswith('y'):
+            raise util.Abort(_('diffstat rejected'))
+    elif s is None:
+        ui.warn(_('no diffstat information available\n'))
+        s = ''
+    return s
+
+def makepatch(ui, repo, patch, opts, _charsets, idx, total, patchname=None):
+
+    desc = []
+    node = None
+    body = ''
+
+    for line in patch:
+        if line.startswith('#'):
+            if line.startswith('# Node ID'):
+                node = line.split()[-1]
+            continue
+        if line.startswith('diff -r') or line.startswith('diff --git'):
+            break
+        desc.append(line)
+
+    if not patchname and not node:
+        raise ValueError
+
+    if opts.get('attach'):
+        body = ('\n'.join(desc[1:]).strip() or
+                'Patch subject is complete summary.')
+        body += '\n\n\n'
+
+    if opts.get('plain'):
+        while patch and patch[0].startswith('# '):
+            patch.pop(0)
+        if patch:
+            patch.pop(0)
+        while patch and not patch[0].strip():
+            patch.pop(0)
+
+    if opts.get('diffstat'):
+        body += cdiffstat(ui, '\n'.join(desc), patch) + '\n\n'
+
+    if opts.get('attach') or opts.get('inline'):
+        msg = email.MIMEMultipart.MIMEMultipart()
+        if body:
+            msg.attach(mail.mimeencode(ui, body, _charsets, opts.get('test')))
+        p = mail.mimetextpatch('\n'.join(patch), 'x-patch', opts.get('test'))
+        binnode = bin(node)
+        # if node is mq patch, it will have patch file name as tag
+        if not patchname:
+            patchtags = [t for t in repo.nodetags(binnode)
+                         if t.endswith('.patch') or t.endswith('.diff')]
+            if patchtags:
+                patchname = patchtags[0]
+            elif total > 1:
+                patchname = cmdutil.make_filename(repo, '%b-%n.patch',
+                                                  binnode, seqno=idx, total=total)
+            else:
+                patchname = cmdutil.make_filename(repo, '%b.patch', binnode)
+        disposition = 'inline'
+        if opts.get('attach'):
+            disposition = 'attachment'
+        p['Content-Disposition'] = disposition + '; filename=' + patchname
+        msg.attach(p)
+    else:
+        body += '\n'.join(patch)
+        msg = mail.mimetextpatch(body, display=opts.get('test'))
+
+    subj = desc[0].strip().rstrip('. ')
+    if total == 1 and not opts.get('intro'):
+        subj = '[PATCH] ' + (opts.get('subject') or subj)
+    else:
+        tlen = len(str(total))
+        subj = '[PATCH %0*d of %d] %s' % (tlen, idx, total, subj)
+    msg['Subject'] = mail.headencode(ui, subj, _charsets, opts.get('test'))
+    msg['X-Mercurial-Node'] = node
+    return msg, subj
+
 def patchbomb(ui, repo, *revs, **opts):
     '''send changesets by email
 
@@ -113,105 +226,6 @@
 
     _charsets = mail._charsets(ui)
 
-    def prompt(prompt, default = None, rest = ': ', empty_ok = False):
-        if not ui.interactive:
-            return default
-        if default:
-            prompt += ' [%s]' % default
-        prompt += rest
-        while True:
-            r = ui.prompt(prompt, default=default)
-            if r:
-                return r
-            if default is not None:
-                return default
-            if empty_ok:
-                return r
-            ui.warn(_('Please enter a valid value.\n'))
-
-    def confirm(s, denial):
-        if not prompt(s, default = 'y', rest = '? ').lower().startswith('y'):
-            raise util.Abort(denial)
-
-    def cdiffstat(summary, patchlines):
-        s = patch.diffstat(patchlines)
-        if s:
-            if summary:
-                ui.write(summary, '\n')
-                ui.write(s, '\n')
-            confirm(_('Does the diffstat above look okay'),
-                    _('diffstat rejected'))
-        elif s is None:
-            ui.warn(_('No diffstat information available.\n'))
-            s = ''
-        return s
-
-    def makepatch(patch, idx, total):
-        desc = []
-        node = None
-        body = ''
-        for line in patch:
-            if line.startswith('#'):
-                if line.startswith('# Node ID'):
-                    node = line.split()[-1]
-                continue
-            if line.startswith('diff -r') or line.startswith('diff --git'):
-                break
-            desc.append(line)
-        if not node:
-            raise ValueError
-
-        if opts.get('attach'):
-             body = ('\n'.join(desc[1:]).strip() or
-                   'Patch subject is complete summary.')
-             body += '\n\n\n'
-
-        if opts.get('plain'):
-            while patch and patch[0].startswith('# '):
-                patch.pop(0)
-            if patch:
-                patch.pop(0)
-            while patch and not patch[0].strip():
-                patch.pop(0)
-        if opts.get('diffstat'):
-            body += cdiffstat('\n'.join(desc), patch) + '\n\n'
-        if opts.get('attach') or opts.get('inline'):
-            msg = email.MIMEMultipart.MIMEMultipart()
-            if body:
-                msg.attach(mail.mimeencode(ui, body, _charsets,
-                                           opts.get('test')))
-            p = mail.mimetextpatch('\n'.join(patch), 'x-patch',
-                                   opts.get('test'))
-            binnode = bin(node)
-            # if node is mq patch, it will have patch file name as tag
-            patchname = [t for t in repo.nodetags(binnode)
-                         if t.endswith('.patch') or t.endswith('.diff')]
-            if patchname:
-                patchname = patchname[0]
-            elif total > 1:
-                patchname = cmdutil.make_filename(repo, '%b-%n.patch',
-                                                  binnode, idx, total)
-            else:
-                patchname = cmdutil.make_filename(repo, '%b.patch', binnode)
-            disposition = 'inline'
-            if opts.get('attach'):
-                disposition = 'attachment'
-            p['Content-Disposition'] = disposition + '; filename=' + patchname
-            msg.attach(p)
-        else:
-            body += '\n'.join(patch)
-            msg = mail.mimetextpatch(body, display=opts.get('test'))
-
-        subj = desc[0].strip().rstrip('. ')
-        if total == 1:
-            subj = '[PATCH] ' + (opts.get('subject') or subj)
-        else:
-            tlen = len(str(total))
-            subj = '[PATCH %0*d of %d] %s' % (tlen, idx, total, subj)
-        msg['Subject'] = mail.headencode(ui, subj, _charsets, opts.get('test'))
-        msg['X-Mercurial-Node'] = node
-        return msg, subj
-
     def outgoing(dest, revs):
         '''Return the revisions present locally but not in dest'''
         dest = ui.expandpath(dest or 'default-push', dest or 'default')
@@ -243,7 +257,8 @@
         mail.validateconfig(ui)
 
     if not (revs or opts.get('rev')
-            or opts.get('outgoing') or opts.get('bundle')):
+            or opts.get('outgoing') or opts.get('bundle')
+            or opts.get('patches')):
         raise util.Abort(_('specify at least one changeset with -r or -o'))
 
     cmdutil.setremoteconfig(ui, opts)
@@ -285,49 +300,34 @@
             body = ui.edit(body, sender)
         return body
 
-    def getexportmsgs():
-        patches = []
-
-        class exportee:
-            def __init__(self, container):
-                self.lines = []
-                self.container = container
-                self.name = 'email'
-
-            def write(self, data):
-                self.lines.append(data)
-
-            def close(self):
-                self.container.append(''.join(self.lines).split('\n'))
-                self.lines = []
-
-        commands.export(ui, repo, *revs, **{'output': exportee(patches),
-                                            'switch_parent': False,
-                                            'text': None,
-                                            'git': opts.get('git')})
-
+    def getpatchmsgs(patches, patchnames=None):
         jumbo = []
         msgs = []
 
         ui.write(_('This patch series consists of %d patches.\n\n')
                  % len(patches))
 
+        name = None
         for p, i in zip(patches, xrange(len(patches))):
             jumbo.extend(p)
-            msgs.append(makepatch(p, i + 1, len(patches)))
+            if patchnames:
+                name = patchnames[i]
+            msg = makepatch(ui, repo, p, opts, _charsets, i + 1,
+                            len(patches), name)
+            msgs.append(msg)
 
-        if len(patches) > 1:
+        if len(patches) > 1 or opts.get('intro'):
             tlen = len(str(len(patches)))
 
             subj = '[PATCH %0*d of %d] %s' % (
                 tlen, 0, len(patches),
                 opts.get('subject') or
-                prompt('Subject:',
+                prompt(ui, 'Subject:',
                        rest=' [PATCH %0*d of %d] ' % (tlen, 0, len(patches))))
 
             body = ''
             if opts.get('diffstat'):
-                d = cdiffstat(_('Final summary:\n'), jumbo)
+                d = cdiffstat(ui, _('Final summary:\n'), jumbo)
                 if d:
                     body = '\n' + d
 
@@ -341,7 +341,7 @@
 
     def getbundlemsgs(bundle):
         subj = (opts.get('subject')
-                or prompt('Subject:', default='A bundle for your repository'))
+                or prompt(ui, 'Subject:', 'A bundle for your repository'))
 
         body = getdescription('', sender)
         msg = email.MIMEMultipart.MIMEMultipart()
@@ -358,17 +358,25 @@
 
     sender = (opts.get('from') or ui.config('email', 'from') or
               ui.config('patchbomb', 'from') or
-              prompt('From', ui.username()))
+              prompt(ui, 'From', ui.username()))
 
-    if opts.get('bundle'):
+    patches = opts.get('patches')
+    if patches:
+        msgs = getpatchmsgs(patches, opts.get('patchnames'))
+    elif opts.get('bundle'):
         msgs = getbundlemsgs(getbundle(dest))
     else:
-        msgs = getexportmsgs()
+        patches = []
+        commands.export(ui, repo, *revs, **{'output': exportee(patches),
+                                            'switch_parent': False,
+                                            'text': None,
+                                            'git': opts.get('git')})
+        msgs = getpatchmsgs(patches)
 
     def getaddrs(opt, prpt, default = None):
         addrs = opts.get(opt) or (ui.config('email', opt) or
                                   ui.config('patchbomb', opt) or
-                                  prompt(prpt, default = default)).split(',')
+                                  prompt(ui, prpt, default)).split(',')
         return [mail.addressencode(ui, a.strip(), _charsets, opts.get('test'))
                 for a in addrs if a.strip()]
 
@@ -394,6 +402,7 @@
             m['Message-Id'] = genmsgid('patchbomb')
         if parent:
             m['In-Reply-To'] = parent
+            m['References'] = parent
         else:
             parent = m['Message-Id']
         m['Date'] = util.datestr(start_time, "%a, %d %b %Y %H:%M:%S %1%2")
@@ -441,34 +450,40 @@
             generator.flatten(m, 0)
             sendmail(sender, to + bcc + cc, fp.getvalue())
 
-cmdtable = {
-    "email":
-        (patchbomb,
-         [('a', 'attach', None, _('send patches as attachments')),
+emailopts = [
+          ('a', 'attach', None, _('send patches as attachments')),
           ('i', 'inline', None, _('send patches as inline attachments')),
           ('', 'bcc', [], _('email addresses of blind copy recipients')),
           ('c', 'cc', [], _('email addresses of copy recipients')),
           ('d', 'diffstat', None, _('add diffstat output to messages')),
           ('', 'date', '', _('use the given date as the sending date')),
           ('', 'desc', '', _('use the given file as the series description')),
-          ('g', 'git', None, _('use git extended diff format')),
           ('f', 'from', '', _('email address of sender')),
-          ('', 'plain', None, _('omit hg patch header')),
           ('n', 'test', None, _('print messages that would be sent')),
           ('m', 'mbox', '',
            _('write messages to mbox file instead of sending them')),
+          ('s', 'subject', '',
+           _('subject of first message (intro or single patch)')),
+          ('t', 'to', [], _('email addresses of recipients')),
+         ]
+
+
+cmdtable = {
+    "email":
+        (patchbomb,
+         [('g', 'git', None, _('use git extended diff format')),
+          ('', 'plain', None, _('omit hg patch header')),
           ('o', 'outgoing', None,
            _('send changes not found in the target repository')),
           ('b', 'bundle', None,
            _('send changes not in target as a binary bundle')),
           ('r', 'rev', [], _('a revision to send')),
-          ('s', 'subject', '',
-           _('subject of first message (intro or single patch)')),
-          ('t', 'to', [], _('email addresses of recipients')),
           ('', 'force', None,
            _('run even when remote repository is unrelated (with -b)')),
           ('', 'base', [],
            _('a base changeset to specify instead of a destination (with -b)')),
-         ] + commands.remoteopts,
+          ('', 'intro', None,
+           _('send an introduction email for a single patch')),
+         ] + emailopts + commands.remoteopts,
          _('hg email [OPTION]... [DEST]...'))
 }
--- a/hgext/rebase.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/hgext/rebase.py	Sun Dec 07 19:34:07 2008 +0100
@@ -64,6 +64,14 @@
         contf = opts.get('continue')
         abortf = opts.get('abort')
         collapsef = opts.get('collapse', False)
+        extrafn = opts.get('extrafn')
+        if opts.get('keepbranches', None):
+            if extrafn:
+                raise dispatch.ParseError('rebase',
+                        _('cannot use both keepbranches and extrafn'))
+            def extrafn(ctx, extra):
+                extra['branch'] = ctx.branch()
+
         if contf or abortf:
             if contf and abortf:
                 raise dispatch.ParseError('rebase',
@@ -101,14 +109,14 @@
                 storestatus(repo, originalwd, target, state, collapsef,
                                                                 external)
                 rebasenode(repo, rev, target, state, skipped, targetancestors,
-                                                                collapsef)
+                                                       collapsef, extrafn)
         ui.note(_('rebase merging completed\n'))
 
         if collapsef:
             p1, p2 = defineparents(repo, min(state), target,
                                                         state, targetancestors)
             concludenode(repo, rev, p1, external, state, collapsef,
-                                                last=True, skipped=skipped)
+                         last=True, skipped=skipped, extrafn=extrafn)
 
         if 'qtip' in repo.tags():
             updatemq(repo, state, skipped, **opts)
@@ -131,7 +139,8 @@
     finally:
         del lock, wlock
 
-def concludenode(repo, rev, p1, p2, state, collapse, last=False, skipped={}):
+def concludenode(repo, rev, p1, p2, state, collapse, last=False, skipped={},
+                 extrafn=None):
     """Skip commit if collapsing has been required and rev is not the last
     revision, commit otherwise
     """
@@ -155,18 +164,22 @@
         else:
             commitmsg = repo[rev].description()
         # Commit might fail if unresolved files exist
+        extra = {'rebase_source': repo[rev].hex()}
+        if extrafn:
+            extrafn(repo[rev], extra)
         newrev = repo.commit(m+a+r,
                             text=commitmsg,
                             user=repo[rev].user(),
                             date=repo[rev].date(),
-                            extra={'rebase_source': repo[rev].hex()})
+                            extra=extra)
         return newrev
     except util.Abort:
         # Invalidate the previous setparents
         repo.dirstate.invalidate()
         raise
 
-def rebasenode(repo, rev, target, state, skipped, targetancestors, collapse):
+def rebasenode(repo, rev, target, state, skipped, targetancestors, collapse,
+               extrafn):
     'Rebase a single revision'
     repo.ui.debug(_("rebasing %d:%s\n") % (rev, repo[rev]))
 
@@ -195,7 +208,8 @@
         repo.ui.debug(_('resuming interrupted rebase\n'))
 
 
-    newrev = concludenode(repo, rev, p1, p2, state, collapse)
+    newrev = concludenode(repo, rev, p1, p2, state, collapse,
+                          extrafn=extrafn)
 
     # Update the state
     if newrev is not None:
@@ -409,6 +423,7 @@
         (rebase,
         [
         ('', 'keep', False, _('keep original revisions')),
+        ('', 'keepbranches', False, _('keep original branches')),
         ('s', 'source', '', _('rebase from a given revision')),
         ('b', 'base', '', _('rebase from the base of a given revision')),
         ('d', 'dest', '', _('rebase onto a given revision')),
--- a/hgext/transplant.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/hgext/transplant.py	Sun Dec 07 19:34:07 2008 +0100
@@ -398,7 +398,7 @@
     transplants = []
     merges = []
     for node in nodes:
-        displayer.show(changenode=node)
+        displayer.show(repo[node])
         action = None
         while not action:
             action = ui.prompt(_('apply changeset? [ynmpcq?]:'))
@@ -461,13 +461,16 @@
     def getremotechanges(repo, url):
         sourcerepo = ui.expandpath(url)
         source = hg.repository(ui, sourcerepo)
-        incoming = repo.findincoming(source, force=True)
+        common, incoming, rheads = repo.findcommonincoming(source, force=True)
         if not incoming:
             return (source, None, None)
 
         bundle = None
         if not source.local():
-            cg = source.changegroup(incoming, 'incoming')
+            if source.capable('changegroupsubset'):
+                cg = source.changegroupsubset(incoming, rheads, 'incoming')
+            else:
+                cg = source.changegroup(incoming, 'incoming')
             bundle = changegroup.writebundle(cg, None, 'HG10UN')
             source = bundlerepo.bundlerepository(ui, repo.root, bundle)
 
--- a/hgwebdir.cgi	Sun Dec 07 19:33:26 2008 +0100
+++ b/hgwebdir.cgi	Sun Dec 07 19:34:07 2008 +0100
@@ -28,12 +28,28 @@
 # repos, collections of repos in a directory tree, or both.
 #
 # [paths]
-# virtual/path = /real/path
-# virtual/path = /real/path
+# 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]
--- a/mercurial/bundlerepo.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/mercurial/bundlerepo.py	Sun Dec 07 19:34:07 2008 +0100
@@ -13,7 +13,7 @@
 from node import hex, nullid, short
 from i18n import _
 import changegroup, util, os, struct, bz2, zlib, tempfile, shutil, mdiff
-import repo, localrepo, changelog, manifest, filelog, revlog
+import repo, localrepo, changelog, manifest, filelog, revlog, context
 
 class bundlerevlog(revlog.revlog):
     def __init__(self, opener, indexfile, bundlefile,
@@ -213,19 +213,20 @@
             self.changelog = bundlechangelog(self.sopener, self.bundlefile)
             self.manstart = self.bundlefile.tell()
             return self.changelog
-        if name == 'manifest':
+        elif name == 'manifest':
             self.bundlefile.seek(self.manstart)
             self.manifest = bundlemanifest(self.sopener, self.bundlefile,
                                            self.changelog.rev)
             self.filestart = self.bundlefile.tell()
             return self.manifest
-        if name == 'manstart':
+        elif name == 'manstart':
             self.changelog
             return self.manstart
-        if name == 'filestart':
+        elif name == 'filestart':
             self.manifest
             return self.filestart
-        return localrepo.localrepository.__getattr__(self, name)
+        else:
+            raise AttributeError(name)
 
     def url(self):
         return self._url
@@ -267,6 +268,9 @@
     def cancopy(self):
         return False
 
+    def getcwd(self):
+        return os.getcwd() # always outside the repo
+
 def instance(ui, path, create):
     if create:
         raise util.Abort(_('cannot create new bundle repository'))
--- a/mercurial/changelog.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/mercurial/changelog.py	Sun Dec 07 19:34:07 2008 +0100
@@ -179,7 +179,7 @@
 
         user = user.strip()
         if "\n" in user:
-            raise RevlogError(_("username %s contains a newline") % `user`)
+            raise RevlogError(_("username %s contains a newline") % repr(user))
         user, desc = util.fromlocal(user), util.fromlocal(desc)
 
         if date:
--- a/mercurial/cmdutil.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/mercurial/cmdutil.py	Sun Dec 07 19:34:07 2008 +0100
@@ -214,9 +214,12 @@
 
 def make_file(repo, pat, node=None,
               total=None, seqno=None, revwidth=None, mode='wb', pathname=None):
+
+    writable = 'w' in mode or 'a' in mode
+
     if not pat or pat == '-':
-        return 'w' in mode and sys.stdout or sys.stdin
-    if hasattr(pat, 'write') and 'w' in mode:
+        return writable and sys.stdout or sys.stdin
+    if hasattr(pat, 'write') and writable:
         return pat
     if hasattr(pat, 'read') and 'r' in mode:
         return pat
@@ -593,26 +596,24 @@
             return 1
         return 0
 
-    def show(self, rev=0, changenode=None, copies=(), **props):
+    def show(self, ctx, copies=(), **props):
         if self.buffered:
             self.ui.pushbuffer()
-            self._show(rev, changenode, copies, props)
-            self.hunk[rev] = self.ui.popbuffer()
+            self._show(ctx, copies, props)
+            self.hunk[ctx.rev()] = self.ui.popbuffer()
         else:
-            self._show(rev, changenode, copies, props)
+            self._show(ctx, copies, props)
 
-    def _show(self, rev, changenode, copies, props):
+    def _show(self, ctx, copies, props):
         '''show a single changeset or file revision'''
-        log = self.repo.changelog
-        if changenode is None:
-            changenode = log.node(rev)
-        elif not rev:
-            rev = log.rev(changenode)
+        changenode = ctx.node()
+        rev = ctx.rev()
 
         if self.ui.quiet:
             self.ui.write("%d:%s\n" % (rev, short(changenode)))
             return
 
+        log = self.repo.changelog
         changes = log.read(changenode)
         date = util.datestr(changes[2])
         extra = changes[5]
@@ -713,14 +714,12 @@
         '''set template string to use'''
         self.t.cache['changeset'] = t
 
-    def _show(self, rev, changenode, copies, props):
+    def _show(self, ctx, copies, props):
         '''show a single changeset or file revision'''
+        changenode = ctx.node()
+        rev = ctx.rev()
+
         log = self.repo.changelog
-        if changenode is None:
-            changenode = log.node(rev)
-        elif not rev:
-            rev = log.rev(changenode)
-
         changes = log.read(changenode)
 
         def showlist(name, values, plural=None, **args):
@@ -1014,7 +1013,7 @@
                 revs = []
                 for j in xrange(i - window, i + 1):
                     n = filelog.node(j)
-                    revs.append((filelog.linkrev(n),
+                    revs.append((filelog.linkrev(j),
                                  follow and filelog.renamed(n)))
                 revs.reverse()
                 for rev in revs:
@@ -1034,6 +1033,8 @@
                 if node is None:
                     # A zero count may be a directory or deleted file, so
                     # try to find matching entries on the slow path.
+                    if follow:
+                        raise util.Abort(_('cannot follow nonexistent file: "%s"') % file_)
                     slowpath = True
                     break
                 else:
--- a/mercurial/commands.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/mercurial/commands.py	Sun Dec 07 19:34:07 2008 +0100
@@ -9,7 +9,7 @@
 from repo import RepoError, NoCapability
 from i18n import _, gettext
 import os, re, sys
-import hg, util, revlog, bundlerepo, extensions, copies
+import hg, util, revlog, bundlerepo, extensions, copies, context
 import difflib, patch, time, help, mdiff, tempfile, url
 import version
 import archival, changegroup, cmdutil, hgweb.server, sshserver, hbisect
@@ -288,13 +288,13 @@
         if len(nodes) == 1:
             # narrowed it down to a single revision
             ui.write(_("The first %s revision is:\n") % transition)
-            displayer.show(changenode=nodes[0])
+            displayer.show(repo[nodes[0]])
         else:
             # multiple possible revisions
             ui.write(_("Due to skipped revisions, the first "
                        "%s revision could be any of:\n") % transition)
             for n in nodes:
-                displayer.show(changenode=n)
+                displayer.show(repo[n])
 
     def check_state(state, interactive=True):
         if not state['good'] or not state['bad']:
@@ -829,7 +829,7 @@
         except:
             pp = [nullid, nullid]
         ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
-                i, r.start(i), r.length(i), r.base(i), r.linkrev(node),
+                i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
             short(node), short(pp[0]), short(pp[1])))
 
 def debugindexdot(ui, file_):
@@ -1005,7 +1005,7 @@
     probably with undesirable results.
 
     Use the --git option to generate diffs in the git extended diff
-    format. Read the gitdiffs help topic for more information.
+    format. Read the diffs help topic for more information.
     """
     node1, node2 = cmdutil.revpair(repo, opts.get('rev'))
 
@@ -1042,7 +1042,7 @@
     probably with undesirable results.
 
     Use the --git option to generate diffs in the git extended diff
-    format. Read the gitdiffs help topic for more information.
+    format. Read the diffs help topic for more information.
 
     With the --switch-parent option, the diff will be against the second
     parent. It can be useful to review a merge.
@@ -1270,7 +1270,7 @@
         return 1
     displayer = cmdutil.show_changeset(ui, repo, opts)
     for n in heads:
-        displayer.show(changenode=n)
+        displayer.show(repo[n])
 
 def help_(ui, name=None, with_version=False):
     """show help for a given topic or a help overview
@@ -1310,7 +1310,13 @@
             return
 
         # synopsis
-        ui.write("%s\n" % i[2])
+        if len(i) > 2:
+            if i[2].startswith('hg'):
+                ui.write("%s\n" % i[2])
+            else:
+                ui.write('hg %s %s\n' % (aliases[0], i[2]))
+        else:
+            ui.write('hg %s\n' % aliases[0])
 
         # aliases
         if not ui.quiet and len(aliases) > 1:
@@ -1422,7 +1428,7 @@
 
     if name and name != 'shortlist':
         i = None
-        for f in (helpcmd, helptopic, helpext):
+        for f in (helptopic, helpcmd, helpext):
             try:
                 f(name)
                 i = None
@@ -1575,6 +1581,9 @@
     recorded in the patch. This may happen due to character set
     problems or other deficiencies in the text patch format.
 
+    With --similarity, hg will attempt to discover renames and copies
+    in the patch in the same way as 'addremove'.
+
     To read a patch from standard input, use patch name "-".
     See 'hg help dates' for a list of formats valid for -d/--date.
     """
@@ -1584,6 +1593,13 @@
     if date:
         opts['date'] = util.parsedate(date)
 
+    try:
+        sim = float(opts.get('similarity') or 0)
+    except ValueError:
+        raise util.Abort(_('similarity must be a number'))
+    if sim < 0 or sim > 100:
+        raise util.Abort(_('similarity must be between 0 and 100'))
+
     if opts.get('exact') or not opts.get('force'):
         cmdutil.bail_if_changed(repo)
 
@@ -1647,7 +1663,7 @@
                     fuzz = patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
                                        files=files)
                 finally:
-                    files = patch.updatedir(ui, repo, files)
+                    files = patch.updatedir(ui, repo, files, similarity=sim/100.)
                 if not opts.get('no_commit'):
                     n = repo.commit(files, message, opts.get('user') or user,
                                     opts.get('date') or date)
@@ -1684,7 +1700,8 @@
     ui.status(_('comparing with %s\n') % url.hidepassword(source))
     if revs:
         revs = [other.lookup(rev) for rev in revs]
-    incoming = repo.findincoming(other, heads=revs, force=opts["force"])
+    common, incoming, rheads = repo.findcommonincoming(other, heads=revs,
+                                                       force=opts["force"])
     if not incoming:
         try:
             os.unlink(opts["bundle"])
@@ -1698,6 +1715,10 @@
         fname = opts["bundle"]
         if fname or not other.local():
             # create a bundle (uncompressed if other repo is not local)
+
+            if revs is None and other.capable('changegroupsubset'):
+                revs = rheads
+
             if revs is None:
                 cg = other.changegroup(incoming, "incoming")
             else:
@@ -1723,7 +1744,7 @@
             if opts.get('no_merges') and len(parents) == 2:
                 continue
             count += 1
-            displayer.show(changenode=n)
+            displayer.show(other[n])
     finally:
         if hasattr(other, 'close'):
             other.close()
@@ -1833,7 +1854,7 @@
             fl = repo.file(fn)
             for i in fl:
                 node = fl.node(i)
-                lr = fl.linkrev(node)
+                lr = fl.linkrev(i)
                 renamed = fl.renamed(node)
                 rcache[fn][lr] = renamed
                 if renamed:
@@ -1861,7 +1882,6 @@
     displayer = cmdutil.show_changeset(ui, repo, opts, True, matchfn)
     for st, rev, fns in changeiter:
         if st == 'add':
-            changenode = repo.changelog.node(rev)
             parents = [p for p in repo.changelog.parentrevs(rev)
                        if p != nullrev]
             if opts.get('no_merges') and len(parents) == 2:
@@ -1907,7 +1927,7 @@
                     rename = getrenamed(fn, rev)
                     if rename:
                         copies.append((fn, rename[0]))
-            displayer.show(rev, changenode, copies=copies)
+            displayer.show(context.changectx(repo, rev), copies=copies)
         elif st == 'iter':
             if count == limit: break
             if displayer.flush(rev):
@@ -2020,7 +2040,7 @@
         if opts.get('no_merges') and len(parents) == 2:
             continue
         count += 1
-        displayer.show(changenode=n)
+        displayer.show(repo[n])
 
 def parents(ui, repo, file_=None, **opts):
     """show the parents of the working dir or revision
@@ -2053,14 +2073,14 @@
         if not filenodes:
             raise util.Abort(_("'%s' not found in manifest!") % file_)
         fl = repo.file(file_)
-        p = [repo.lookup(fl.linkrev(fn)) for fn in filenodes]
+        p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
     else:
         p = [cp.node() for cp in ctx.parents()]
 
     displayer = cmdutil.show_changeset(ui, repo, opts)
     for n in p:
         if n != nullid:
-            displayer.show(changenode=n)
+            displayer.show(repo[n])
 
 def paths(ui, repo, search=None):
     """show definition of symbolic path names
@@ -2086,7 +2106,7 @@
     if modheads == 0:
         return
     if optupdate:
-        if modheads <= 1 or checkout:
+        if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
             return hg.update(repo, checkout)
         else:
             ui.status(_("not updating, since new heads added\n"))
@@ -2836,7 +2856,7 @@
     that repository becomes the current tip. The "tip" tag is special
     and cannot be renamed or assigned to a different changeset.
     """
-    cmdutil.show_changeset(ui, repo, opts).show(len(repo) - 1)
+    cmdutil.show_changeset(ui, repo, opts).show(repo[len(repo) - 1])
 
 def unbundle(ui, repo, fname1, *fnames, **opts):
     """apply one or more changegroup files
@@ -2998,14 +3018,16 @@
     ('U', 'unified', '', _('number of lines of context to show'))
 ]
 
+similarityopts = [
+    ('s', 'similarity', '',
+           _('guess renamed files by similarity (0<=s<=100)'))
+]
+
 table = {
-    "^add": (add, walkopts + dryrunopts, _('hg add [OPTION]... [FILE]...')),
+    "^add": (add, walkopts + dryrunopts, _('[OPTION]... [FILE]...')),
     "addremove":
-        (addremove,
-         [('s', 'similarity', '',
-           _('guess renamed files by similarity (0<=s<=100)')),
-         ] + walkopts + dryrunopts,
-         _('hg addremove [OPTION]... [FILE]...')),
+        (addremove, similarityopts + walkopts + dryrunopts,
+         _('[OPTION]... [FILE]...')),
     "^annotate|blame":
         (annotate,
          [('r', 'rev', '', _('annotate the specified revision')),
@@ -3018,7 +3040,7 @@
           ('l', 'line-number', None,
            _('show line number at the first appearance'))
          ] + walkopts,
-         _('hg annotate [-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
+         _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
     "archive":
         (archive,
          [('', 'no-decode', None, _('do not pass files through decoders')),
@@ -3026,7 +3048,7 @@
           ('r', 'rev', '', _('revision to distribute')),
           ('t', 'type', '', _('type of distribution to create')),
          ] + walkopts,
-         _('hg archive [OPTION]... DEST')),
+         _('[OPTION]... DEST')),
     "backout":
         (backout,
          [('', 'merge', None,
@@ -3034,7 +3056,7 @@
           ('', 'parent', '', _('parent to choose when backing out merge')),
           ('r', 'rev', '', _('revision to backout')),
          ] + walkopts + commitopts + commitopts2,
-         _('hg backout [OPTION]... [-r] REV')),
+         _('[OPTION]... [-r] REV')),
     "bisect":
         (bisect,
          [('r', 'reset', False, _('reset bisect state')),
@@ -3043,18 +3065,18 @@
           ('s', 'skip', False, _('skip testing changeset')),
           ('c', 'command', '', _('Use command to check changeset state')),
           ('U', 'noupdate', False, _('do not update to target'))],
-         _("hg bisect [-gbsr] [-c CMD] [REV]")),
+         _("[-gbsr] [-c CMD] [REV]")),
     "branch":
         (branch,
          [('f', 'force', None,
            _('set branch name even if it shadows an existing branch')),
           ('C', 'clean', None, _('reset branch name to parent branch name'))],
-         _('hg branch [-fC] [NAME]')),
+         _('[-fC] [NAME]')),
     "branches":
         (branches,
          [('a', 'active', False,
            _('show only branches that have unmerged heads'))],
-         _('hg branches [-a]')),
+         _('[-a]')),
     "bundle":
         (bundle,
          [('f', 'force', None,
@@ -3066,14 +3088,14 @@
           ('a', 'all', None, _('bundle all changesets in the repository')),
           ('t', 'type', 'bzip2', _('bundle compression type to use')),
          ] + remoteopts,
-         _('hg bundle [-f] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
+         _('[-f] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
     "cat":
         (cat,
          [('o', 'output', '', _('print output to file with formatted name')),
           ('r', 'rev', '', _('print the given revision')),
           ('', 'decode', None, _('apply any matching decode filter')),
          ] + walkopts,
-         _('hg cat [OPTION]... FILE...')),
+         _('[OPTION]... FILE...')),
     "^clone":
         (clone,
          [('U', 'noupdate', None,
@@ -3084,70 +3106,67 @@
           ('', 'uncompressed', None,
            _('use uncompressed transfer (fast over LAN)')),
          ] + remoteopts,
-         _('hg clone [OPTION]... SOURCE [DEST]')),
+         _('[OPTION]... SOURCE [DEST]')),
     "^commit|ci":
         (commit,
          [('A', 'addremove', None,
            _('mark new/missing files as added/removed before committing')),
          ] + walkopts + commitopts + commitopts2,
-         _('hg commit [OPTION]... [FILE]...')),
+         _('[OPTION]... [FILE]...')),
     "copy|cp":
         (copy,
          [('A', 'after', None, _('record a copy that has already occurred')),
           ('f', 'force', None,
            _('forcibly copy over an existing managed file')),
          ] + walkopts + dryrunopts,
-         _('hg copy [OPTION]... [SOURCE]... DEST')),
-    "debugancestor": (debugancestor, [],
-                      _('hg debugancestor [INDEX] REV1 REV2')),
-    "debugcheckstate": (debugcheckstate, [], _('hg debugcheckstate')),
+         _('[OPTION]... [SOURCE]... DEST')),
+    "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
+    "debugcheckstate": (debugcheckstate, []),
     "debugcomplete":
         (debugcomplete,
          [('o', 'options', None, _('show the command options'))],
-         _('hg debugcomplete [-o] CMD')),
+         _('[-o] CMD')),
     "debugdate":
         (debugdate,
          [('e', 'extended', None, _('try extended date formats'))],
-         _('hg debugdate [-e] DATE [RANGE]')),
-    "debugdata": (debugdata, [], _('hg debugdata FILE REV')),
-    "debugfsinfo": (debugfsinfo, [], _('hg debugfsinfo [PATH]')),
-    "debugindex": (debugindex, [], _('hg debugindex FILE')),
-    "debugindexdot": (debugindexdot, [], _('hg debugindexdot FILE')),
-    "debuginstall": (debuginstall, [], _('hg debuginstall')),
+         _('[-e] DATE [RANGE]')),
+    "debugdata": (debugdata, [], _('FILE REV')),
+    "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
+    "debugindex": (debugindex, [], _('FILE')),
+    "debugindexdot": (debugindexdot, [], _('FILE')),
+    "debuginstall": (debuginstall, []),
     "debugrawcommit|rawcommit":
         (rawcommit,
          [('p', 'parent', [], _('parent')),
           ('F', 'files', '', _('file list'))
           ] + commitopts + commitopts2,
-         _('hg debugrawcommit [OPTION]... [FILE]...')),
+         _('[OPTION]... [FILE]...')),
     "debugrebuildstate":
         (debugrebuildstate,
          [('r', 'rev', '', _('revision to rebuild to'))],
-         _('hg debugrebuildstate [-r REV] [REV]')),
+         _('[-r REV] [REV]')),
     "debugrename":
         (debugrename,
          [('r', 'rev', '', _('revision to debug'))],
-         _('hg debugrename [-r REV] FILE')),
+         _('[-r REV] FILE')),
     "debugsetparents":
-        (debugsetparents,
-         [],
-         _('hg debugsetparents REV1 [REV2]')),
+        (debugsetparents, [], _('REV1 [REV2]')),
     "debugstate":
         (debugstate,
          [('', 'nodates', None, _('do not display the saved mtime'))],
-         _('hg debugstate [OPTION]...')),
-    "debugwalk": (debugwalk, walkopts, _('hg debugwalk [OPTION]... [FILE]...')),
+         _('[OPTION]...')),
+    "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
     "^diff":
         (diff,
          [('r', 'rev', [], _('revision'))
          ] + diffopts + diffopts2 + walkopts,
-         _('hg diff [OPTION]... [-r REV1 [-r REV2]] [FILE]...')),
+         _('[OPTION]... [-r REV1 [-r REV2]] [FILE]...')),
     "^export":
         (export,
          [('o', 'output', '', _('print output to file with formatted name')),
           ('', 'switch-parent', None, _('diff against the second parent'))
           ] + diffopts,
-         _('hg export [OPTION]... [-o OUTFILESPEC] REV...')),
+         _('[OPTION]... [-o OUTFILESPEC] REV...')),
     "grep":
         (grep,
          [('0', 'print0', None, _('end fields with NUL')),
@@ -3162,13 +3181,13 @@
           ('u', 'user', None, _('list the author (long with -v)')),
           ('d', 'date', None, _('list the date (short with -q)')),
          ] + walkopts,
-         _('hg grep [OPTION]... PATTERN [FILE]...')),
+         _('[OPTION]... PATTERN [FILE]...')),
     "heads":
         (heads,
          [('r', 'rev', '', _('show only heads which are descendants of rev')),
          ] + templateopts,
-         _('hg heads [-r REV] [REV]...')),
-    "help": (help_, [], _('hg help [TOPIC]')),
+         _('[-r REV] [REV]...')),
+    "help": (help_, [], _('[TOPIC]')),
     "identify|id":
         (identify,
          [('r', 'rev', '', _('identify the specified rev')),
@@ -3176,7 +3195,7 @@
           ('i', 'id', None, _('show global revision id')),
           ('b', 'branch', None, _('show branch')),
           ('t', 'tags', None, _('show tags'))],
-         _('hg identify [-nibt] [-r REV] [SOURCE]')),
+         _('[-nibt] [-r REV] [SOURCE]')),
     "import|patch":
         (import_,
          [('p', 'strip', 1,
@@ -3190,8 +3209,8 @@
            _('apply patch to the nodes from which it was generated')),
           ('', 'import-branch', None,
            _('Use any branch information in patch (implied by --exact)'))] +
-         commitopts + commitopts2,
-         _('hg import [OPTION]... PATCH...')),
+         commitopts + commitopts2 + similarityopts,
+         _('[OPTION]... PATCH...')),
     "incoming|in":
         (incoming,
          [('f', 'force', None,
@@ -3201,12 +3220,12 @@
           ('r', 'rev', [],
            _('a specific revision up to which you would like to pull')),
          ] + logopts + remoteopts,
-         _('hg incoming [-p] [-n] [-M] [-f] [-r REV]...'
+         _('[-p] [-n] [-M] [-f] [-r REV]...'
            ' [--bundle FILENAME] [SOURCE]')),
     "^init":
         (init,
          remoteopts,
-         _('hg init [-e CMD] [--remotecmd CMD] [DEST]')),
+         _('[-e CMD] [--remotecmd CMD] [DEST]')),
     "locate":
         (locate,
          [('r', 'rev', '', _('search the repository as it stood at rev')),
@@ -3215,7 +3234,7 @@
           ('f', 'fullpath', None,
            _('print complete paths from the filesystem root')),
          ] + walkopts,
-         _('hg locate [OPTION]... [PATTERN]...')),
+         _('[OPTION]... [PATTERN]...')),
     "^log|history":
         (log,
          [('f', 'follow', None,
@@ -3233,17 +3252,17 @@
             _('show only changesets within the given named branch')),
           ('P', 'prune', [], _('do not display revision or any of its ancestors')),
          ] + logopts + walkopts,
-         _('hg log [OPTION]... [FILE]')),
+         _('[OPTION]... [FILE]')),
     "manifest":
         (manifest,
          [('r', 'rev', '', _('revision to display'))],
-         _('hg manifest [-r REV]')),
+         _('[-r REV]')),
     "^merge":
         (merge,
          [('f', 'force', None, _('force a merge with outstanding changes')),
           ('r', 'rev', '', _('revision to merge')),
              ],
-         _('hg merge [-f] [[-r] REV]')),
+         _('[-f] [[-r] REV]')),
     "outgoing|out":
         (outgoing,
          [('f', 'force', None,
@@ -3252,13 +3271,13 @@
            _('a specific revision up to which you would like to push')),
           ('n', 'newest-first', None, _('show newest record first')),
          ] + logopts + remoteopts,
-         _('hg outgoing [-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
+         _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
     "^parents":
         (parents,
          [('r', 'rev', '', _('show parents from the specified rev')),
          ] + templateopts,
          _('hg parents [-r REV] [FILE]')),
-    "paths": (paths, [], _('hg paths [NAME]')),
+    "paths": (paths, [], _('[NAME]')),
     "^pull":
         (pull,
          [('u', 'update', None,
@@ -3268,35 +3287,35 @@
           ('r', 'rev', [],
            _('a specific revision up to which you would like to pull')),
          ] + remoteopts,
-         _('hg pull [-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
+         _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
     "^push":
         (push,
          [('f', 'force', None, _('force push')),
           ('r', 'rev', [],
            _('a specific revision up to which you would like to push')),
          ] + remoteopts,
-         _('hg push [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
-    "recover": (recover, [], _('hg recover')),
+         _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
+    "recover": (recover, []),
     "^remove|rm":
         (remove,
          [('A', 'after', None, _('record delete for missing files')),
           ('f', 'force', None,
            _('remove (and delete) file even if added or modified')),
          ] + walkopts,
-         _('hg remove [OPTION]... FILE...')),
+         _('[OPTION]... FILE...')),
     "rename|mv":
         (rename,
          [('A', 'after', None, _('record a rename that has already occurred')),
           ('f', 'force', None,
            _('forcibly copy over an existing managed file')),
          ] + walkopts + dryrunopts,
-         _('hg rename [OPTION]... SOURCE... DEST')),
+         _('[OPTION]... SOURCE... DEST')),
     "resolve":
         (resolve,
          [('l', 'list', None, _('list state of files needing merge')),
           ('m', 'mark', None, _('mark files as resolved')),
           ('u', 'unmark', None, _('unmark files as resolved'))],
-          _('hg resolve [OPTION]... [FILE]...')),
+          _('[OPTION]... [FILE]...')),
     "revert":
         (revert,
          [('a', 'all', None, _('revert all changes when no arguments given')),
@@ -3304,9 +3323,9 @@
           ('r', 'rev', '', _('revision to revert to')),
           ('', 'no-backup', None, _('do not save backup copies of files')),
          ] + walkopts + dryrunopts,
-         _('hg revert [OPTION]... [-r REV] [NAME]...')),
-    "rollback": (rollback, [], _('hg rollback')),
-    "root": (root, [], _('hg root')),
+         _('[OPTION]... [-r REV] [NAME]...')),
+    "rollback": (rollback, []),
+    "root": (root, []),
     "^serve":
         (serve,
          [('A', 'accesslog', '', _('name of access log file to write to')),
@@ -3326,11 +3345,11 @@
           ('', 'style', '', _('template style to use')),
           ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
           ('', 'certificate', '', _('SSL certificate file'))],
-         _('hg serve [OPTION]...')),
+         _('[OPTION]...')),
     "showconfig|debugconfig":
         (showconfig,
          [('u', 'untrusted', None, _('show untrusted configuration options'))],
-         _('hg showconfig [-u] [NAME]...')),
+         _('[-u] [NAME]...')),
     "^status|st":
         (status,
          [('A', 'all', None, _('show status of all files')),
@@ -3347,7 +3366,7 @@
            _('end filenames with NUL, for use with xargs')),
           ('', 'rev', [], _('show difference from revision')),
          ] + walkopts,
-         _('hg status [OPTION]... [FILE]...')),
+         _('[OPTION]... [FILE]...')),
     "tag":
         (tag,
          [('f', 'force', None, _('replace existing tag')),
@@ -3357,26 +3376,26 @@
           # -l/--local is already there, commitopts cannot be used
           ('m', 'message', '', _('use <text> as commit message')),
          ] + commitopts2,
-         _('hg tag [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
-    "tags": (tags, [], _('hg tags')),
+         _('[-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
+    "tags": (tags, []),
     "tip":
         (tip,
          [('p', 'patch', None, _('show patch')),
          ] + templateopts,
-         _('hg tip [-p]')),
+         _('[-p]')),
     "unbundle":
         (unbundle,
          [('u', 'update', None,
            _('update to new tip if changesets were unbundled'))],
-         _('hg unbundle [-u] FILE...')),
+         _('[-u] FILE...')),
     "^update|up|checkout|co":
         (update,
          [('C', 'clean', None, _('overwrite locally modified files (no backup)')),
           ('d', 'date', '', _('tipmost revision matching date')),
           ('r', 'rev', '', _('revision'))],
-         _('hg update [-C] [-d DATE] [[-r] REV]')),
-    "verify": (verify, [], _('hg verify')),
-    "version": (version_, [], _('hg version')),
+         _('[-C] [-d DATE] [[-r] REV]')),
+    "verify": (verify, []),
+    "version": (version_, []),
 }
 
 norepo = ("clone init version help debugcomplete debugdata"
--- a/mercurial/context.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/mercurial/context.py	Sun Dec 07 19:34:07 2008 +0100
@@ -9,6 +9,15 @@
 from i18n import _
 import ancestor, bdiff, revlog, util, os, errno
 
+class propertycache(object):
+    def __init__(self, func):
+        self.func = func
+        self.name = func.__name__
+    def __get__(self, obj, type=None):
+        result = self.func(obj)
+        setattr(obj, self.name, result)
+        return result
+
 class changectx(object):
     """A changecontext object makes access to data related to a particular
     changeset convenient."""
@@ -17,8 +26,12 @@
         if changeid == '':
             changeid = '.'
         self._repo = repo
-        self._node = self._repo.lookup(changeid)
-        self._rev = self._repo.changelog.rev(self._node)
+        if isinstance(changeid, (long, int)):
+            self._rev = changeid
+            self._node = self._repo.changelog.node(changeid)
+        else:
+            self._node = self._repo.lookup(changeid)
+            self._rev = self._repo.changelog.rev(self._node)
 
     def __str__(self):
         return short(self.node())
@@ -47,25 +60,24 @@
     def __nonzero__(self):
         return self._rev != nullrev
 
-    def __getattr__(self, name):
-        if name == '_changeset':
-            self._changeset = self._repo.changelog.read(self.node())
-            return self._changeset
-        elif name == '_manifest':
-            self._manifest = self._repo.manifest.read(self._changeset[0])
-            return self._manifest
-        elif name == '_manifestdelta':
-            md = self._repo.manifest.readdelta(self._changeset[0])
-            self._manifestdelta = md
-            return self._manifestdelta
-        elif name == '_parents':
-            p = self._repo.changelog.parents(self._node)
-            if p[1] == nullid:
-                p = p[:-1]
-            self._parents = [changectx(self._repo, x) for x in p]
-            return self._parents
-        else:
-            raise AttributeError(name)
+    def _changeset(self):
+        return self._repo.changelog.read(self.node())
+    _changeset = propertycache(_changeset)
+
+    def _manifest(self):
+        return self._repo.manifest.read(self._changeset[0])
+    _manifest = propertycache(_manifest)
+
+    def _manifestdelta(self):
+        return self._repo.manifest.readdelta(self._changeset[0])
+    _manifestdelta = propertycache(_manifestdelta)
+
+    def _parents(self):
+        p = self._repo.changelog.parentrevs(self._rev)
+        if p[1] == nullrev:
+            p = p[:-1]
+        return [changectx(self._repo, x) for x in p]
+    _parents = propertycache(_parents)
 
     def __contains__(self, key):
         return key in self._manifest
@@ -189,33 +201,35 @@
         if fileid is not None:
             self._fileid = fileid
 
-    def __getattr__(self, name):
-        if name == '_changectx':
-            self._changectx = changectx(self._repo, self._changeid)
-            return self._changectx
-        elif name == '_filelog':
-            self._filelog = self._repo.file(self._path)
-            return self._filelog
-        elif name == '_changeid':
-            if '_changectx' in self.__dict__:
-                self._changeid = self._changectx.rev()
-            else:
-                self._changeid = self._filelog.linkrev(self._filenode)
-            return self._changeid
-        elif name == '_filenode':
-            if '_fileid' in self.__dict__:
-                self._filenode = self._filelog.lookup(self._fileid)
-            else:
-                self._filenode = self._changectx.filenode(self._path)
-            return self._filenode
-        elif name == '_filerev':
-            self._filerev = self._filelog.rev(self._filenode)
-            return self._filerev
-        elif name == '_repopath':
-            self._repopath = self._path
-            return self._repopath
+    def _changectx(self):
+        return changectx(self._repo, self._changeid)
+    _changectx = propertycache(_changectx)
+
+    def _filelog(self):
+        return self._repo.file(self._path)
+    _filelog = propertycache(_filelog)
+
+    def _changeid(self):
+        if '_changectx' in self.__dict__:
+            return self._changectx.rev()
         else:
-            raise AttributeError(name)
+            return self._filelog.linkrev(self._filerev)
+    _changeid = propertycache(_changeid)
+
+    def _filenode(self):
+        if '_fileid' in self.__dict__:
+            return self._filelog.lookup(self._fileid)
+        else:
+            return self._changectx.filenode(self._path)
+    _filenode = propertycache(_filenode)
+
+    def _filerev(self):
+        return self._filelog.rev(self._filenode)
+    _filerev = propertycache(_filerev)
+
+    def _repopath(self):
+        return self._path
+    _repopath = propertycache(_repopath)
 
     def __nonzero__(self):
         try:
@@ -263,9 +277,9 @@
             return self._changectx.rev()
         if '_changeid' in self.__dict__:
             return self._changectx.rev()
-        return self._filelog.linkrev(self._filenode)
+        return self._filelog.linkrev(self._filerev)
 
-    def linkrev(self): return self._filelog.linkrev(self._filenode)
+    def linkrev(self): return self._filelog.linkrev(self._filerev)
     def node(self): return self._changectx.node()
     def user(self): return self._changectx.user()
     def date(self): return self._changectx.date()
@@ -501,29 +515,7 @@
     def __contains__(self, key):
         return self._dirstate[key] not in "?r"
 
-    def __getattr__(self, name):
-        if name == '_status':
-            self._status = self._repo.status(unknown=True)
-            return self._status
-        elif name == '_user':
-            self._user = self._repo.ui.username()
-            return self._user
-        elif name == '_date':
-            self._date = util.makedate()
-            return self._date
-        if name == '_manifest':
-            self._buildmanifest()
-            return self._manifest
-        elif name == '_parents':
-            p = self._repo.dirstate.parents()
-            if p[1] == nullid:
-                p = p[:-1]
-            self._parents = [changectx(self._repo, x) for x in p]
-            return self._parents
-        else:
-            raise AttributeError(name)
-
-    def _buildmanifest(self):
+    def _manifest(self):
         """generate a manifest corresponding to the working directory"""
 
         man = self._parents[0].manifest().copy()
@@ -543,7 +535,28 @@
             if f in man:
                 del man[f]
 
-        self._manifest = man
+        return man
+    _manifest = propertycache(_manifest)
+
+    def _status(self):
+        return self._repo.status(unknown=True)
+    _status = propertycache(_status)
+
+    def _user(self):
+        return self._repo.ui.username()
+    _user = propertycache(_user)
+
+    def _date(self):
+        return util.makedate()
+    _date = propertycache(_date)
+
+    def _parents(self):
+        p = self._repo.dirstate.parents()
+        if p[1] == nullid:
+            p = p[:-1]
+        self._parents = [changectx(self._repo, x) for x in p]
+        return self._parents
+    _parents = propertycache(_parents)
 
     def manifest(self): return self._manifest
 
@@ -618,19 +631,17 @@
         if workingctx:
             self._changectx = workingctx
 
-    def __getattr__(self, name):
-        if name == '_changectx':
-            self._changectx = workingctx(self._repo)
-            return self._changectx
-        elif name == '_repopath':
-            self._repopath = (self._repo.dirstate.copied(self._path)
-                              or self._path)
-            return self._repopath
-        elif name == '_filelog':
-            self._filelog = self._repo.file(self._repopath)
-            return self._filelog
-        else:
-            raise AttributeError(name)
+    def _changectx(self):
+        return workingctx(self._repo)
+    _changectx = propertycache(_changectx)
+
+    def _repopath(self):
+        return self._repo.dirstate.copied(self._path) or self._path
+    _repopath = propertycache(_repopath)
+
+    def _filelog(self):
+        return self._repo.file(self._repopath)
+    _filelog = propertycache(_filelog)
 
     def __nonzero__(self):
         return True
@@ -647,7 +658,7 @@
     def rev(self):
         if '_changectx' in self.__dict__:
             return self._changectx.rev()
-        return self._filelog.linkrev(self._filenode)
+        return self._filelog.linkrev(self._filerev)
 
     def data(self): return self._repo.wread(self._path)
     def renamed(self):
--- a/mercurial/dispatch.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/mercurial/dispatch.py	Sun Dec 07 19:34:07 2008 +0100
@@ -7,7 +7,7 @@
 
 from i18n import _
 from repo import RepoError
-import os, sys, atexit, signal, pdb, traceback, socket, errno, shlex, time
+import os, sys, atexit, signal, pdb, socket, errno, shlex, time
 import util, commands, hg, lock, fancyopts, revlog, version, extensions, hook
 import cmdutil
 import ui as _ui
@@ -90,7 +90,7 @@
             else:
                 raise
     except socket.error, inst:
-        ui.warn(_("abort: %s\n") % inst[-1])
+        ui.warn(_("abort: %s\n") % inst.args[-1])
     except IOError, inst:
         if hasattr(inst, "code"):
             ui.warn(_("abort: %s\n") % inst)
@@ -100,7 +100,7 @@
             except: # it might be anything, for example a string
                 reason = inst.reason
             ui.warn(_("abort: error: %s\n") % reason)
-        elif hasattr(inst, "args") and inst[0] == errno.EPIPE:
+        elif hasattr(inst, "args") and inst.args[0] == errno.EPIPE:
             if ui.debugflag:
                 ui.warn(_("broken pipe\n"))
         elif getattr(inst, "strerror", None):
@@ -116,13 +116,13 @@
         else:
             ui.warn(_("abort: %s\n") % inst.strerror)
     except util.UnexpectedOutput, inst:
-        ui.warn(_("abort: %s") % inst[0])
-        if not isinstance(inst[1], basestring):
-            ui.warn(" %r\n" % (inst[1],))
-        elif not inst[1]:
+        ui.warn(_("abort: %s") % inst.args[0])
+        if not isinstance(inst.args[1], basestring):
+            ui.warn(" %r\n" % (inst.args[1],))
+        elif not inst.args[1]:
             ui.warn(_(" empty string\n"))
         else:
-            ui.warn("\n%r\n" % util.ellipsis(inst[1]))
+            ui.warn("\n%r\n" % util.ellipsis(inst.args[1]))
     except ImportError, inst:
         m = str(inst).split()[-1]
         ui.warn(_("abort: could not import module %s!\n") % m)
@@ -356,9 +356,9 @@
                     raise RepoError(_("There is no Mercurial repository here"
                                       " (.hg not found)"))
                 raise
-        d = lambda: func(ui, repo, *args, **cmdoptions)
-    else:
-        d = lambda: func(ui, *args, **cmdoptions)
+        args.insert(0, repo)
+
+    d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
 
     # run pre-hook, and abort if it fails
     ret = hook.hook(lui, repo, "pre-%s" % cmd, False, args=" ".join(fullargs))
@@ -374,11 +374,7 @@
     def checkargs():
         try:
             return cmdfunc()
-        except TypeError:
-            # was this an argument error?
-            tb = traceback.extract_tb(sys.exc_info()[2])
-            if len(tb) != 2: # no
-                raise
+        except util.SignatureError:
             raise ParseError(cmd, _("invalid arguments"))
 
     if options['profile']:
--- a/mercurial/extensions.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/mercurial/extensions.py	Sun Dec 07 19:34:07 2008 +0100
@@ -96,9 +96,11 @@
 
     origfn = entry[0]
     def wrap(*args, **kwargs):
-        return wrapper(origfn, *args, **kwargs)
+        return util.checksignature(wrapper)(
+            util.checksignature(origfn), *args, **kwargs)
 
     wrap.__doc__ = getattr(origfn, '__doc__')
+    wrap.__module__ = getattr(origfn, '__module__')
 
     newentry = list(entry)
     newentry[0] = wrap
--- a/mercurial/filemerge.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/mercurial/filemerge.py	Sun Dec 07 19:34:07 2008 +0100
@@ -32,8 +32,11 @@
         tmsg = tool
         if pat:
             tmsg += " specified for " + pat
-        if pat and not _findtool(ui, tool): # skip search if not matching
-            ui.warn(_("couldn't find merge tool %s\n") % tmsg)
+        if not _findtool(ui, tool):
+            if pat: # explicitly requested tool deserves a warning
+                ui.warn(_("couldn't find merge tool %s\n") % tmsg)
+            else: # configured but non-existing tools are more silent
+                ui.note(_("couldn't find merge tool %s\n") % tmsg)
         elif symlink and not _toolbool(ui, tool, "symlink"):
             ui.warn(_("tool %s can't handle symlinks\n") % tmsg)
         elif binary and not _toolbool(ui, tool, "binary"):
@@ -71,8 +74,8 @@
         tools.insert(0, (None, uimerge)) # highest priority
     tools.append((None, "hgmerge")) # the old default, if found
     for p,t in tools:
-        toolpath = _findtool(ui, t)
-        if toolpath and check(t, None, symlink, binary):
+        if check(t, None, symlink, binary):
+            toolpath = _findtool(ui, t)
             return (t, '"' + toolpath + '"')
     # internal merge as last resort
     return (not (symlink or binary) and "internal:merge" or None, None)
--- a/mercurial/help.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/mercurial/help.py	Sun Dec 07 19:34:07 2008 +0100
@@ -216,33 +216,36 @@
     gives 3, 4 and 5. Similarly, a range of 4:2 gives 4, 3, and 2.
     ''')),
 
-    (['gitdiffs'], _('Using git Diffs'),
+    (['diffs'], _('Diff Formats'),
      _(r'''
-    In several places, Mercurial supports two separate variations on
-    the unified diff format: normal diffs, as are de facto standardized
-    by GNU's patch utility, and git diffs, invented for the git VCS.
+    Mercurial's default format for showing changes between two versions
+    of a file is compatible with the unified format of GNU diff, which
+    can be used by GNU patch and many other standard tools.
 
-    The git diff format is an addition of some information to the normal
-    diff format, which allows diff to convey changes in file permissions
-    as well as the creation, deletion, renaming and copying of files, as
-    well as diffs for binary files (unsupported by standard diff),
-    operations which are very useful to modern version control systems
-    such as Mercurial, in trying to faithfully replay your changes.
+    While this standard format is often enough, it does not encode the
+    following information:
+
+     - executable status
+     - copy or rename information
+     - changes in binary files
+     - creation or deletion of empty files
 
-    In building Mercurial, we made a choice to support the git diff
-    format, but we haven't made it the default. This is because for a
-    long time, the format for unified diffs we usually use has been
-    defined by GNU patch, and it doesn't (yet) support git's extensions
-    to the diff format. This means that, when extracting diffs from a
-    Mercurial repository (through the diff command, for example), you
-    must be careful about things like file copies and renames (file
-    creation and deletion are mostly handled fine by the traditional
-    diff format, with some rare edge cases for which the git extensions
-    can be used). Mercurial's internal operations (like push and pull)
-    are not affected by these differences, because they use a different,
-    binary format for communicating changes.
+    Mercurial also supports the extended diff format from the git VCS
+    which addresses these limitations. The git diff format is not
+    produced by default because there are very few tools which
+    understand this format.
 
-    To use git diffs, use the --git option for relevant commands, or
-    enable them in a hgrc, setting 'git = True' in the [diff] section.
+    This means that when generating diffs from a Mercurial repository
+    (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
+    pull) are not affected by this, because they use an internal binary
+    format for communicating changes.
+
+    To make Mercurial produce the git extended diff format, use the
+    --git option available for many commands, or set 'git = True' in the
+    [diff] section of your hgrc. You do not need to set this option when
+    importing diffs in this format or using them in the mq extension.
     ''')),
 )
--- a/mercurial/hgweb/hgweb_mod.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/mercurial/hgweb/hgweb_mod.py	Sun Dec 07 19:34:07 2008 +0100
@@ -161,11 +161,13 @@
         # process the web interface request
 
         try:
-
             tmpl = self.templater(req)
             ctype = tmpl('mimetype', encoding=self.encoding)
             ctype = templater.stringify(ctype)
 
+            # check allow_read / deny_read config options
+            self.check_perm(req, None)
+
             if cmd == '':
                 req.form['cmd'] = [tmpl.cache['default']]
                 cmd = req.form['cmd'][0]
@@ -180,20 +182,20 @@
                 content = getattr(webcommands, cmd)(self, req, tmpl)
                 req.respond(HTTP_OK, ctype)
 
-            return ''.join(content),
+            return content
 
         except revlog.LookupError, err:
             req.respond(HTTP_NOT_FOUND, ctype)
             msg = str(err)
             if 'manifest' not in msg:
                 msg = 'revision not found: %s' % err.name
-            return ''.join(tmpl('error', error=msg)),
+            return tmpl('error', error=msg)
         except (RepoError, revlog.RevlogError), inst:
             req.respond(HTTP_SERVER_ERROR, ctype)
-            return ''.join(tmpl('error', error=str(inst))),
+            return tmpl('error', error=str(inst))
         except ErrorResponse, inst:
             req.respond(inst.code, ctype)
-            return ''.join(tmpl('error', error=inst.message)),
+            return tmpl('error', error=inst.message)
 
     def templater(self, req):
 
@@ -226,23 +228,16 @@
         def motd(**map):
             yield self.config("web", "motd", "")
 
-        def sessionvars(**map):
-            fields = []
-            if 'style' in req.form:
-                style = req.form['style'][0]
-                if style != self.config('web', 'style', ''):
-                    fields.append(('style', style))
-
-            separator = req.url[-1] == '?' and ';' or '?'
-            for name, value in fields:
-                yield dict(name=name, value=value, separator=separator)
-                separator = ';'
-
         # figure out which style to use
 
-        style = self.config("web", "style", "")
+        vars = {}
+        style = self.config("web", "style", "paper")
         if 'style' in req.form:
             style = req.form['style'][0]
+            vars['style'] = style
+
+        start = req.url[-1] == '?' and '&' or '?'
+        sessionvars = webutil.sessionvars(vars, start)
         mapfile = style_map(self.templatepath, style)
 
         if not self.reponame:
@@ -278,11 +273,24 @@
 
     def check_perm(self, req, op):
         '''Check permission for operation based on request data (including
-        authentication info. Return true if op allowed, else false.'''
+        authentication info). Return if op allowed, else raise an ErrorResponse
+        exception.'''
+
+        user = req.env.get('REMOTE_USER')
+
+        deny_read = self.configlist('web', 'deny_read')
+        if deny_read and (not user or deny_read == ['*'] or user in deny_read):
+            raise ErrorResponse(HTTP_UNAUTHORIZED, 'read not authorized')
+
+        allow_read = self.configlist('web', 'allow_read')
+        result = (not allow_read) or (allow_read == ['*']) or (user in allow_read)
+        if not result:
+            raise ErrorResponse(HTTP_UNAUTHORIZED, 'read not authorized')
 
         if op == 'pull' and not self.allowpull:
             raise ErrorResponse(HTTP_OK, '')
-        elif op == 'pull':
+        # op is None when checking allow/deny_read permissions for a web-browser request
+        elif op == 'pull' or op is None:
             return
 
         # enforce that you can only push using POST requests
@@ -296,8 +304,6 @@
         if self.configbool('web', 'push_ssl', True) and scheme != 'https':
             raise ErrorResponse(HTTP_OK, 'ssl required')
 
-        user = req.env.get('REMOTE_USER')
-
         deny = self.configlist('web', 'deny_push')
         if deny and (not user or deny == ['*'] or user in deny):
             raise ErrorResponse(HTTP_UNAUTHORIZED, 'push not authorized')
--- a/mercurial/hgweb/hgwebdir_mod.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/mercurial/hgweb/hgwebdir_mod.py	Sun Dec 07 19:34:07 2008 +0100
@@ -25,7 +25,7 @@
         self.parentui = parentui or ui.ui(report_untrusted=False,
                                           interactive = False)
         self.motd = None
-        self.style = None
+        self.style = 'paper'
         self.stripecount = None
         self.repos_sorted = ('name', False)
         self._baseurl = None
@@ -51,7 +51,21 @@
                 if cp.has_option('web', 'baseurl'):
                     self._baseurl = cp.get('web', 'baseurl')
             if cp.has_section('paths'):
-                self.repos.extend(cleannames(cp.items('paths')))
+                paths = cleannames(cp.items('paths'))
+                for prefix, root in paths:
+                    roothead, roottail = os.path.split(root)
+                    if roottail != '*':
+                        self.repos.append((prefix, root))
+                        continue
+                    # "foo = /bar/*" makes every subrepo of /bar/ to be
+                    # mounted as foo/subrepo
+                    roothead = os.path.normpath(roothead)
+                    for path in util.walkrepos(roothead, followsym=True):
+                        path = os.path.normpath(path)
+                        name = util.pconvert(path[len(roothead):]).strip('/')
+                        if prefix:
+                            name = prefix + '/' + name
+                        self.repos.append((name, path))
             if cp.has_section('collections'):
                 for prefix, root in cp.items('collections'):
                     for path in util.walkrepos(root, followsym=True):
@@ -72,6 +86,28 @@
         req = wsgirequest(env, respond)
         return self.run_wsgi(req)
 
+    def read_allowed(self, ui, req):
+        """Check allow_read and deny_read config options of a repo's ui object
+        to determine user permissions.  By default, with neither option set (or
+        both empty), allow all users to read the repo.  There are two ways a
+        user can be denied read access:  (1) deny_read is not empty, and the
+        user is unauthenticated or deny_read contains user (or *), and (2)
+        allow_read is not empty and the user is not in allow_read.  Return True
+        if user is allowed to read the repo, else return False."""
+
+        user = req.env.get('REMOTE_USER')
+
+        deny_read = ui.configlist('web', 'deny_read', default=None, untrusted=True)
+        if deny_read and (not user or deny_read == ['*'] or user in deny_read):
+            return False
+
+        allow_read = ui.configlist('web', 'allow_read', default=None, untrusted=True)
+        # by default, allow reading if no allow_read option has been set
+        if (not allow_read) or (allow_read == ['*']) or (user in allow_read):
+            return True
+
+        return False
+
     def run_wsgi(self, req):
 
         try:
@@ -94,7 +130,7 @@
                 # top-level index
                 elif not virtual:
                     req.respond(HTTP_OK, ctype)
-                    return ''.join(self.makeindex(req, tmpl)),
+                    return self.makeindex(req, tmpl)
 
                 # nested indexes and hgwebs
 
@@ -116,7 +152,7 @@
                     subdir = virtual + '/'
                     if [r for r in repos if r.startswith(subdir)]:
                         req.respond(HTTP_OK, ctype)
-                        return ''.join(self.makeindex(req, tmpl, subdir)),
+                        return self.makeindex(req, tmpl, subdir)
 
                     up = virtual.rfind('/')
                     if up < 0:
@@ -125,11 +161,11 @@
 
                 # prefixes not found
                 req.respond(HTTP_NOT_FOUND, ctype)
-                return ''.join(tmpl("notfound", repo=virtual)),
+                return tmpl("notfound", repo=virtual)
 
             except ErrorResponse, err:
                 req.respond(err.code, ctype)
-                return ''.join(tmpl('error', error=err.message or '')),
+                return tmpl('error', error=err.message or '')
         finally:
             tmpl = None
 
@@ -175,6 +211,9 @@
                 if u.configbool("web", "hidden", untrusted=True):
                     continue
 
+                if not self.read_allowed(u, req):
+                    continue
+
                 parts = [name]
                 if 'PATH_INFO' in req.env:
                     parts.insert(0, req.env['PATH_INFO'].rstrip('/'))
--- a/mercurial/hgweb/webcommands.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/mercurial/hgweb/webcommands.py	Sun Dec 07 19:34:07 2008 +0100
@@ -5,7 +5,7 @@
 # This software may be used and distributed according to the terms
 # of the GNU General Public License, incorporated herein by reference.
 
-import os, mimetypes, re, cgi
+import os, mimetypes, re, cgi, copy
 import webutil
 from mercurial import revlog, archival, templatefilters
 from mercurial.node import short, hex, nullid
@@ -227,6 +227,7 @@
 def changeset(web, req, tmpl):
     ctx = webutil.changectx(web.repo, req)
     showtags = webutil.showtag(web.repo, tmpl, 'changesettag', ctx.node())
+    showbranch = webutil.nodebranchnodefault(ctx)
     parents = ctx.parents()
 
     files = []
@@ -246,6 +247,7 @@
                 parent=webutil.siblings(parents),
                 child=webutil.siblings(ctx.children()),
                 changesettag=showtags,
+                changesetbranch=showbranch,
                 author=ctx.user(),
                 desc=ctx.description(),
                 date=ctx.date(),
@@ -526,13 +528,13 @@
         if not numrevs: # file doesn't exist at all
             raise
         rev = webutil.changectx(web.repo, req).rev()
-        first = fl.linkrev(fl.node(0))
+        first = fl.linkrev(0)
         if rev < first: # current rev is from before file existed
             raise
         frev = numrevs - 1
-        while fl.linkrev(fl.node(frev)) > rev:
+        while fl.linkrev(frev) > rev:
             frev -= 1
-        fctx = web.repo.filectx(f, fl.linkrev(fl.node(frev)))
+        fctx = web.repo.filectx(f, fl.linkrev(frev))
 
     count = fctx.filerev() + 1
     pagelen = web.maxshortchanges
@@ -555,7 +557,11 @@
                          "rename": webutil.renamelink(fctx),
                          "parent": webutil.siblings(fctx.parents()),
                          "child": webutil.siblings(fctx.children()),
-                         "desc": ctx.description()})
+                         "desc": ctx.description(),
+                         "tags": webutil.nodetagsdict(web.repo, ctx.node()),
+                         "branch": webutil.nodebranchnodefault(ctx),
+                         "inbranch": webutil.nodeinbranch(web.repo, ctx),
+                         "branches": webutil.nodebranchdict(web.repo, ctx)})
 
         if limit > 0:
             l = l[:limit]
@@ -619,21 +625,27 @@
     rev = webutil.changectx(web.repo, req).rev()
     bg_height = 39
 
+    revcount = 25
+    if 'revcount' in req.form:
+        revcount = int(req.form.get('revcount', [revcount])[0])
+        tmpl.defaults['sessionvars']['revcount'] = revcount
+
+    lessvars = copy.copy(tmpl.defaults['sessionvars'])
+    lessvars['revcount'] = revcount / 2
+    morevars = copy.copy(tmpl.defaults['sessionvars'])
+    morevars['revcount'] = revcount * 2
+
     max_rev = len(web.repo) - 1
-    revcount = min(max_rev, int(req.form.get('revcount', [25])[0]))
+    revcount = min(max_rev, revcount)
     revnode = web.repo.changelog.node(rev)
     revnode_hex = hex(revnode)
     uprev = min(max_rev, rev + revcount)
     downrev = max(0, rev - revcount)
-    lessrev = max(0, rev - revcount / 2)
-
-    maxchanges = web.maxshortchanges or web.maxchanges
     count = len(web.repo)
-    changenav = webutil.revnavgen(rev, maxchanges, count, web.repo.changectx)
+    changenav = webutil.revnavgen(rev, revcount, count, web.repo.changectx)
 
     tree = list(graphmod.graph(web.repo, rev, downrev))
     canvasheight = (len(tree) + 1) * bg_height - 27;
-
     data = []
     for i, (ctx, vtx, edges) in enumerate(tree):
         node = short(ctx.node())
@@ -646,7 +658,6 @@
         data.append((node, vtx, edges, desc, user, age, branch, ctx.tags()))
 
     return tmpl('graph', rev=rev, revcount=revcount, uprev=uprev,
-                lessrev=lessrev, revcountmore=revcount and 2 * revcount or 1,
-                revcountless=revcount / 2, downrev=downrev,
-                canvasheight=canvasheight, bg_height=bg_height,
-                jsdata=data, node=revnode_hex, changenav=changenav)
+                lessvars=lessvars, morevars=morevars, downrev=downrev,
+                canvasheight=canvasheight, jsdata=data, bg_height=bg_height,
+                node=revnode_hex, changenav=changenav)
--- a/mercurial/hgweb/webutil.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/mercurial/hgweb/webutil.py	Sun Dec 07 19:34:07 2008 +0100
@@ -6,7 +6,7 @@
 # This software may be used and distributed according to the terms
 # of the GNU General Public License, incorporated herein by reference.
 
-import os
+import os, copy
 from mercurial import match, patch
 from mercurial.node import hex, nullid
 from mercurial.repo import RepoError
@@ -126,7 +126,7 @@
         ctx = repo[changeid]
     except RepoError:
         man = repo.manifest
-        ctx = repo[man.linkrev(man.lookup(changeid))]
+        ctx = repo[man.linkrev(man.rev(man.lookup(changeid)))]
 
     return ctx
 
@@ -196,3 +196,19 @@
         block.append(chunk)
     yield tmpl('diffblock', parity=parity.next(),
                lines=prettyprintlines(''.join(block)))
+
+class sessionvars(object):
+    def __init__(self, vars, start='?'):
+        self.start = start
+        self.vars = vars
+    def __getitem__(self, key):
+        return self.vars[key]
+    def __setitem__(self, key, value):
+        self.vars[key] = value
+    def __copy__(self):
+        return sessionvars(copy.copy(self.vars), self.start)
+    def __iter__(self):
+        separator = self.start
+        for key, value in self.vars.iteritems():
+            yield {'name': key, 'value': str(value), 'separator': separator}
+            separator = '&'
--- a/mercurial/hgweb/wsgicgi.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/mercurial/hgweb/wsgicgi.py	Sun Dec 07 19:34:07 2008 +0100
@@ -17,6 +17,9 @@
 
     environ = dict(os.environ.items())
     environ.setdefault('PATH_INFO', '')
+    if '.cgi' in environ['PATH_INFO']:
+        environ['PATH_INFO'] = environ['PATH_INFO'].split('.cgi', 1)[1]
+
     environ['wsgi.input'] = sys.stdin
     environ['wsgi.errors'] = sys.stderr
     environ['wsgi.version'] = (1, 0)
--- a/mercurial/hook.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/mercurial/hook.py	Sun Dec 07 19:34:07 2008 +0100
@@ -96,19 +96,20 @@
         oldstdout = os.dup(sys.__stdout__.fileno())
         os.dup2(sys.__stderr__.fileno(), sys.__stdout__.fileno())
 
-    for hname, cmd in util.sort(ui.configitems('hooks')):
-        if hname.split('.')[0] != name or not cmd:
-            continue
-        if callable(cmd):
-            r = _pythonhook(ui, repo, name, hname, cmd, args, throw) or r
-        elif cmd.startswith('python:'):
-            r = _pythonhook(ui, repo, name, hname, cmd[7:].strip(),
-                            args, throw) or r
-        else:
-            r = _exthook(ui, repo, hname, cmd, args, throw) or r
-
-    if _redirect:
-        os.dup2(oldstdout, sys.__stdout__.fileno())
-        os.close(oldstdout)
+    try:
+        for hname, cmd in util.sort(ui.configitems('hooks')):
+            if hname.split('.')[0] != name or not cmd:
+                continue
+            if callable(cmd):
+                r = _pythonhook(ui, repo, name, hname, cmd, args, throw) or r
+            elif cmd.startswith('python:'):
+                r = _pythonhook(ui, repo, name, hname, cmd[7:].strip(),
+                                args, throw) or r
+            else:
+                r = _exthook(ui, repo, hname, cmd, args, throw) or r
+    finally:
+        if _redirect:
+            os.dup2(oldstdout, sys.__stdout__.fileno())
+            os.close(oldstdout)
 
     return r
--- a/mercurial/httprepo.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/mercurial/httprepo.py	Sun Dec 07 19:34:07 2008 +0100
@@ -148,13 +148,16 @@
             raise util.UnexpectedOutput(_("unexpected response:"), d)
 
     def between(self, pairs):
-        n = " ".join(["-".join(map(hex, p)) for p in pairs])
-        d = self.do_read("between", pairs=n)
-        try:
-            p = [ l and map(bin, l.split(" ")) or [] for l in d.splitlines() ]
-            return p
-        except:
-            raise util.UnexpectedOutput(_("unexpected response:"), d)
+        batch = 8 # avoid giant requests
+        r = []
+        for i in xrange(0, len(pairs), batch):
+            n = " ".join(["-".join(map(hex, p)) for p in pairs[i:i + batch]])
+            d = self.do_read("between", pairs=n)
+            try:
+                r += [ l and map(bin, l.split(" ")) or [] for l in d.splitlines() ]
+            except:
+                raise util.UnexpectedOutput(_("unexpected response:"), d)
+        return r
 
     def changegroup(self, nodes, kind):
         n = " ".join(map(hex, nodes))
--- a/mercurial/localrepo.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/mercurial/localrepo.py	Sun Dec 07 19:34:07 2008 +0100
@@ -437,10 +437,14 @@
             partial[b] = c.node()
 
     def lookup(self, key):
-        if key == '.':
+        if isinstance(key, int):
+            return self.changelog.node(key)
+        elif key == '.':
             return self.dirstate.parents()[0]
         elif key == 'null':
             return nullid
+        elif key == 'tip':
+            return self.changelog.tip()
         n = self.changelog._match(key)
         if n:
             return n
@@ -978,7 +982,7 @@
         else:
             ctx2 = self[node2]
 
-        working = ctx2 == self[None]
+        working = ctx2.rev() is None
         parentworking = working and ctx1 == self['.']
         match = match or match_.always(self.root, self.getcwd())
         listignored, listclean, listunknown = ignored, clean, unknown
@@ -1262,6 +1266,22 @@
         (and so we know that the rest of the nodes are missing in remote, see
         outgoing)
         """
+        return self.findcommonincoming(remote, base, heads, force)[1]
+
+    def findcommonincoming(self, remote, base=None, heads=None, force=False):
+        """Return a tuple (common, missing roots, heads) used to identify
+        missing nodes from remote.
+
+        If base dict is specified, assume that these nodes and their parents
+        exist on the remote side and that no child of a node of base exists
+        in both remote and self.
+        Furthermore base will be updated to include the nodes that exists
+        in self and remote but no children exists in self and remote.
+        If a list of heads is specified, return only nodes which are heads
+        or ancestors of these heads.
+
+        All the ancestors of base are in self and in remote.
+        """
         m = self.changelog.nodemap
         search = []
         fetch = {}
@@ -1276,8 +1296,8 @@
         if self.changelog.tip() == nullid:
             base[nullid] = 1
             if heads != [nullid]:
-                return [nullid]
-            return []
+                return [nullid], [nullid], list(heads)
+            return [nullid], [], []
 
         # assume we're closer to the tip than the root
         # and start by examining the heads
@@ -1290,8 +1310,9 @@
             else:
                 base[h] = 1
 
+        heads = unknown
         if not unknown:
-            return []
+            return base.keys(), [], []
 
         req = dict.fromkeys(unknown)
         reqcnt = 0
@@ -1386,7 +1407,7 @@
 
         self.ui.debug(_("%d total queries\n") % reqcnt)
 
-        return fetch.keys()
+        return base.keys(), fetch.keys(), heads
 
     def findoutgoing(self, remote, base=None, heads=None, force=False):
         """Return list of nodes that are roots of subsets not in remote
@@ -1439,7 +1460,8 @@
     def pull(self, remote, heads=None, force=False):
         lock = self.lock()
         try:
-            fetch = self.findincoming(remote, heads=heads, force=force)
+            common, fetch, rheads = self.findcommonincoming(remote, heads=heads,
+                                                            force=force)
             if fetch == [nullid]:
                 self.ui.status(_("requesting all changes\n"))
 
@@ -1447,10 +1469,13 @@
                 self.ui.status(_("no changes found\n"))
                 return 0
 
+            if heads is None and remote.capable('changegroupsubset'):
+                heads = rheads
+
             if heads is None:
                 cg = remote.changegroup(fetch, 'pull')
             else:
-                if 'changegroupsubset' not in remote.capabilities:
+                if not remote.capable('changegroupsubset'):
                     raise util.Abort(_("Partial pull cannot be done because other repository doesn't support changegroupsubset."))
                 cg = remote.changegroupsubset(fetch, heads, 'pull')
             return self.addchangegroup(cg, 'pull', remote.url())
@@ -1471,11 +1496,11 @@
         return self.push_addchangegroup(remote, force, revs)
 
     def prepush(self, remote, force, revs):
-        base = {}
+        common = {}
         remote_heads = remote.heads()
-        inc = self.findincoming(remote, base, remote_heads, force=force)
+        inc = self.findincoming(remote, common, remote_heads, force=force)
 
-        update, updated_heads = self.findoutgoing(remote, base, remote_heads)
+        update, updated_heads = self.findoutgoing(remote, common, remote_heads)
         if revs is not None:
             msng_cl, bases, heads = self.changelog.nodesbetween(update, revs)
         else:
@@ -1521,7 +1546,8 @@
 
 
         if revs is None:
-            cg = self.changegroup(update, 'push')
+            # use the fast path, no race possible on push
+            cg = self._changegroup(common.keys(), 'push')
         else:
             cg = self.changegroupsubset(update, revs, 'push')
         return cg, remote_heads
@@ -1703,7 +1729,7 @@
                 # If a 'missing' manifest thinks it belongs to a changenode
                 # the recipient is assumed to have, obviously the recipient
                 # must have that manifest.
-                linknode = cl.node(mnfst.linkrev(n))
+                linknode = cl.node(mnfst.linkrev(mnfst.rev(n)))
                 if linknode in has_cl_set:
                     has_mnfst_set[n] = 1
             prune_parents(mnfst, has_mnfst_set, msng_mnfst_set)
@@ -1769,7 +1795,7 @@
             # assume the recipient must have, then the recipient must have
             # that filenode.
             for n in msngset:
-                clnode = cl.node(filerevlog.linkrev(n))
+                clnode = cl.node(filerevlog.linkrev(filerevlog.rev(n)))
                 if clnode in has_cl_set:
                     hasset[n] = 1
             prune_parents(filerevlog, hasset, msngset)
@@ -1892,9 +1918,8 @@
 
         def gennodelst(log):
             for r in log:
-                n = log.node(r)
-                if log.linkrev(n) in revset:
-                    yield n
+                if log.linkrev(r) in revset:
+                    yield log.node(r)
 
         def changed_file_collector(changedfileset):
             def collect_changed_files(clnode):
@@ -1905,7 +1930,7 @@
 
         def lookuprevlink_func(revlog):
             def lookuprevlink(n):
-                return cl.node(revlog.linkrev(n))
+                return cl.node(revlog.linkrev(revlog.rev(n)))
             return lookuprevlink
 
         def gengroup():
--- a/mercurial/manifest.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/mercurial/manifest.py	Sun Dec 07 19:34:07 2008 +0100
@@ -35,7 +35,8 @@
         return mfdict
 
     def readdelta(self, node):
-        return self.parse(mdiff.patchtext(self.delta(node)))
+        r = self.rev(node)
+        return self.parse(mdiff.patchtext(self.revdiff(r - 1, r)))
 
     def read(self, node):
         if node == nullid: return manifestdict() # don't upset local cache
@@ -62,6 +63,8 @@
             while i < lenm and m[i] != c:
                 i += 1
             return i
+        if not s:
+            return (lo, lo)
         lenm = len(m)
         if not hi:
             hi = lenm
--- a/mercurial/mdiff.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/mercurial/mdiff.py	Sun Dec 07 19:34:07 2008 +0100
@@ -160,7 +160,7 @@
         if opts.showfunc:
             # walk backwards from the start of the context
             # to find a line starting with an alphanumeric char.
-            for x in xrange(astart, -1, -1):
+            for x in xrange(astart - 1, -1, -1):
                 t = l1[x].rstrip()
                 if funcre.match(t):
                     func = ' ' + t[:40]
--- a/mercurial/patch.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/mercurial/patch.py	Sun Dec 07 19:34:07 2008 +0100
@@ -228,27 +228,22 @@
 contextdesc = re.compile('(---|\*\*\*) (\d+)(,(\d+))? (---|\*\*\*)')
 
 class patchfile:
-    def __init__(self, ui, fname, missing=False):
+    def __init__(self, ui, fname, opener, missing=False):
         self.fname = fname
+        self.opener = opener
         self.ui = ui
         self.lines = []
         self.exists = False
         self.missing = missing
         if not missing:
             try:
-                fp = file(fname, 'rb')
-                self.lines = fp.readlines()
+                self.lines = self.readlines(fname)
                 self.exists = True
             except IOError:
                 pass
         else:
             self.ui.warn(_("unable to find '%s' for patching\n") % self.fname)
 
-        if not self.exists:
-            dirname = os.path.dirname(fname)
-            if dirname and not os.path.isdir(dirname):
-                os.makedirs(dirname)
-
         self.hash = {}
         self.dirty = 0
         self.offset = 0
@@ -257,6 +252,23 @@
         self.printfile(False)
         self.hunks = 0
 
+    def readlines(self, fname):
+        fp = self.opener(fname, 'r')
+        try:
+            return fp.readlines()
+        finally:
+            fp.close()
+
+    def writelines(self, fname, lines):
+        fp = self.opener(fname, 'w')
+        try:
+            fp.writelines(lines)
+        finally:
+            fp.close()
+
+    def unlink(self, fname):
+        os.unlink(fname)
+
     def printfile(self, warn):
         if self.fileprinted:
             return
@@ -307,35 +319,24 @@
         self.ui.warn(
             _("%d out of %d hunks FAILED -- saving rejects to file %s\n") %
             (len(self.rej), self.hunks, fname))
-        try: os.unlink(fname)
-        except:
-            pass
-        fp = file(fname, 'wb')
-        base = os.path.basename(self.fname)
-        fp.write("--- %s\n+++ %s\n" % (base, base))
-        for x in self.rej:
-            for l in x.hunk:
-                fp.write(l)
-                if l[-1] != '\n':
-                    fp.write("\n\ No newline at end of file\n")
+
+        def rejlines():
+            base = os.path.basename(self.fname)
+            yield "--- %s\n+++ %s\n" % (base, base)
+            for x in self.rej:
+                for l in x.hunk:
+                    yield l
+                    if l[-1] != '\n':
+                        yield "\n\ No newline at end of file\n"
+
+        self.writelines(fname, rejlines())
 
     def write(self, dest=None):
-        if self.dirty:
-            if not dest:
-                dest = self.fname
-            st = None
-            try:
-                st = os.lstat(dest)
-            except OSError, inst:
-                if inst.errno != errno.ENOENT:
-                    raise
-            if st and st.st_nlink > 1:
-                os.unlink(dest)
-            fp = file(dest, 'wb')
-            if st and st.st_nlink > 1:
-                os.chmod(dest, st.st_mode)
-            fp.writelines(self.lines)
-            fp.close()
+        if not self.dirty:
+            return
+        if not dest:
+            dest = self.fname
+        self.writelines(dest, self.lines)
 
     def close(self):
         self.write()
@@ -362,7 +363,7 @@
 
         if isinstance(h, binhunk):
             if h.rmfile():
-                os.unlink(self.fname)
+                self.unlink(self.fname)
             else:
                 self.lines[:] = h.new()
                 self.offset += len(h.new())
@@ -379,7 +380,7 @@
         orig_start = start
         if diffhelpers.testhunk(old, self.lines, start) == 0:
             if h.rmfile():
-                os.unlink(self.fname)
+                self.unlink(self.fname)
             else:
                 self.lines[start : start + h.lena] = h.new()
                 self.offset += h.lenb - h.lena
@@ -938,6 +939,7 @@
     err = 0
     current_file = None
     gitpatches = None
+    opener = util.opener(os.getcwd())
 
     def closefile():
         if not current_file:
@@ -960,11 +962,11 @@
             afile, bfile, first_hunk = values
             try:
                 if sourcefile:
-                    current_file = patchfile(ui, sourcefile)
+                    current_file = patchfile(ui, sourcefile, opener)
                 else:
                     current_file, missing = selectfile(afile, bfile, first_hunk,
                                             strip, reverse)
-                    current_file = patchfile(ui, current_file, missing)
+                    current_file = patchfile(ui, current_file, opener, missing)
             except PatchError, err:
                 ui.warn(str(err) + '\n')
                 current_file, current_hunk = None, None
@@ -1002,7 +1004,7 @@
         ignoreblanklines=get('ignore_blank_lines', 'ignoreblanklines'),
         context=get('unified', getter=ui.config))
 
-def updatedir(ui, repo, patches):
+def updatedir(ui, repo, patches, similarity=0):
     '''Update dirstate after patch application according to metadata'''
     if not patches:
         return
@@ -1026,7 +1028,7 @@
     for src, dst in copies:
         repo.copy(src, dst)
     removes = removes.keys()
-    if removes:
+    if (not similarity) and removes:
         repo.remove(util.sort(removes), True)
     for f in patches:
         gp = patches[f]
@@ -1039,7 +1041,7 @@
                 repo.wwrite(gp.path, '', flags)
             else:
                 util.set_flags(dst, islink, isexec)
-    cmdutil.addremove(repo, cfiles)
+    cmdutil.addremove(repo, cfiles, similarity=similarity)
     files = patches.keys()
     files.extend([r for r in removes if r not in files])
     return util.sort(files)
@@ -1294,7 +1296,8 @@
 
         if not fp:
             fp = cmdutil.make_file(repo, template, node, total=total,
-                                   seqno=seqno, revwidth=revwidth)
+                                   seqno=seqno, revwidth=revwidth,
+                                   mode='ab')
         if fp != sys.stdout and hasattr(fp, 'name'):
             repo.ui.note("%s\n" % fp.name)
 
--- a/mercurial/repair.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/mercurial/repair.py	Sun Dec 07 19:34:07 2008 +0100
@@ -41,8 +41,7 @@
         startrev = count = len(revlog)
         # find the truncation point of the revlog
         for i in xrange(0, count):
-            node = revlog.node(i)
-            lrev = revlog.linkrev(node)
+            lrev = revlog.linkrev(i)
             if lrev >= link:
                 startrev = i + 1
                 break
@@ -51,7 +50,7 @@
         # (we have to manually save these guys)
         for i in xrange(startrev, count):
             node = revlog.node(i)
-            lrev = revlog.linkrev(node)
+            lrev = revlog.linkrev(i)
             if lrev < link:
                 extra.append((node, cl.node(lrev)))
 
--- a/mercurial/revlog.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/mercurial/revlog.py	Sun Dec 07 19:34:07 2008 +0100
@@ -500,11 +500,12 @@
             raise LookupError(node, self.indexfile, _('no node'))
     def node(self, rev):
         return self.index[rev][7]
-    def linkrev(self, node):
-        return self.index[self.rev(node)][4]
+    def linkrev(self, rev):
+        return self.index[rev][4]
     def parents(self, node):
-        d = self.index[self.rev(node)][5:7]
-        return (self.node(d[0]), self.node(d[1]))
+        i = self.index
+        d = i[self.rev(node)]
+        return i[d[5]][7], i[d[6]][7] # map revisions to nodes inline
     def parentrevs(self, rev):
         return self.index[rev][5:7]
     def start(self, rev):
@@ -872,16 +873,16 @@
         if len(id) < 40:
             try:
                 # hex(node)[:...]
-                bin_id = bin(id[:len(id) & ~1]) # grab an even number of digits
-                node = None
-                for n in self.nodemap:
-                    if n.startswith(bin_id) and hex(n).startswith(id):
-                        if node is not None:
-                            raise LookupError(id, self.indexfile,
-                                              _('ambiguous identifier'))
-                        node = n
-                if node is not None:
-                    return node
+                l = len(id) / 2  # grab an even number of digits
+                bin_id = bin(id[:l*2])
+                nl = [n for n in self.nodemap if n[:l] == bin_id]
+                nl = [n for n in nl if hex(n).startswith(id)]
+                if len(nl) > 0:
+                    if len(nl) == 1:
+                        return nl[0]
+                    raise LookupError(id, self.indexfile,
+                                      _('ambiguous identifier'))
+                return None
             except TypeError:
                 pass
 
@@ -941,11 +942,6 @@
 
         return decompress(c)
 
-    def delta(self, node):
-        """return or calculate a delta between a node and its predecessor"""
-        r = self.rev(node)
-        return self.revdiff(r - 1, r)
-
     def revdiff(self, rev1, rev2):
         """return or calculate a delta between two revisions"""
         if rev1 + 1 == rev2 and self.base(rev1) == self.base(rev2):
--- a/mercurial/templater.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/mercurial/templater.py	Sun Dec 07 19:34:07 2008 +0100
@@ -44,7 +44,8 @@
     template_re = re.compile(r"(?:(?:#(?=[\w\|%]+#))|(?:{(?=[\w\|%]+})))"
                              r"(\w+)(?:(?:%(\w+))|((?:\|\w+)*))[#}]")
 
-    def __init__(self, mapfile, filters={}, defaults={}, cache={}):
+    def __init__(self, mapfile, filters={}, defaults={}, cache={},
+                 minchunk=1024, maxchunk=65536):
         '''set up template engine.
         mapfile is name of file to read map definitions from.
         filters is dict of functions. each transforms a value into another.
@@ -55,6 +56,7 @@
         self.base = (mapfile and os.path.dirname(mapfile)) or ''
         self.filters = filters
         self.defaults = defaults
+        self.minchunk, self.maxchunk = minchunk, maxchunk
 
         if not mapfile:
             return
@@ -130,6 +132,13 @@
                 yield v
 
     def __call__(self, t, **map):
+        stream = self.expand(t, **map)
+        if self.minchunk:
+            stream = util.increasingchunks(stream, min=self.minchunk,
+                                           max=self.maxchunk)
+        return stream
+
+    def expand(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._template(t)
--- a/mercurial/transaction.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/mercurial/transaction.py	Sun Dec 07 19:34:07 2008 +0100
@@ -12,7 +12,7 @@
 # of the GNU General Public License, incorporated herein by reference.
 
 from i18n import _
-import os
+import os, errno
 
 class transaction(object):
     def __init__(self, report, opener, journal, after=None, createmode=None):
@@ -102,7 +102,11 @@
         if o:
             opener(f, "a").truncate(int(o))
         else:
-            fn = opener(f).name
-            os.unlink(fn)
+            try:
+                fn = opener(f).name
+                os.unlink(fn)
+            except OSError, inst:
+                if inst.errno != errno.ENOENT:
+                    raise
     os.unlink(file)
 
--- a/mercurial/ui.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/mercurial/ui.py	Sun Dec 07 19:34:07 2008 +0100
@@ -350,7 +350,7 @@
         if not user:
             raise util.Abort(_("Please specify a username."))
         if "\n" in user:
-            raise util.Abort(_("username %s contains a newline\n") % `user`)
+            raise util.Abort(_("username %s contains a newline\n") % repr(user))
         return user
 
     def shortuser(self, user):
@@ -421,7 +421,9 @@
 
         If not interactive -- the default is returned
         """
-        if not self.interactive: return default
+        if not self.interactive:
+            self.note(msg, ' ', default, "\n")
+            return default
         while True:
             try:
                 r = self._readline(msg + ' ')
--- a/mercurial/util.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/mercurial/util.py	Sun Dec 07 19:34:07 2008 +0100
@@ -13,7 +13,7 @@
 """
 
 from i18n import _
-import cStringIO, errno, getpass, re, shutil, sys, tempfile
+import cStringIO, errno, getpass, re, shutil, sys, tempfile, traceback
 import os, stat, threading, time, calendar, ConfigParser, locale, glob, osutil
 import imp
 
@@ -81,6 +81,8 @@
     popen3 = os.popen3
 
 
+_encodingfixup = {'646': 'ascii', 'ANSI_X3.4-1968': 'ascii'}
+
 try:
     _encoding = os.environ.get("HGENCODING")
     if sys.platform == 'darwin' and not _encoding:
@@ -91,6 +93,7 @@
         _encoding = locale.getlocale()[1]
     if not _encoding:
         _encoding = locale.getpreferredencoding() or 'ascii'
+        _encoding = _encodingfixup.get(_encoding, _encoding)
 except locale.Error:
     _encoding = 'ascii'
 _encodingmode = os.environ.get("HGENCODINGMODE", "strict")
@@ -290,6 +293,37 @@
     l.sort()
     return l
 
+def increasingchunks(source, min=1024, max=65536):
+    '''return no less than min bytes per chunk while data remains,
+    doubling min after each chunk until it reaches max'''
+    def log2(x):
+        if not x:
+            return 0
+        i = 0
+        while x:
+            x >>= 1
+            i += 1
+        return i - 1
+
+    buf = []
+    blen = 0
+    for chunk in source:
+        buf.append(chunk)
+        blen += len(chunk)
+        if blen >= min:
+            if min < max:
+                min = min << 1
+                nmin = 1 << log2(blen)
+                if nmin > min:
+                    min = nmin
+                if min > max:
+                    min = max
+            yield ''.join(buf)
+            blen = 0
+            buf = []
+    if buf:
+        yield ''.join(buf)
+
 class Abort(Exception):
     """Raised if a command needs to print an error and exit."""
 
@@ -576,7 +610,7 @@
     if inc:
         dummy, inckinds, dummy = normalizepats(inc, 'glob')
         incmatch = matchfn(inckinds, '(?:/|$)')
-    excmatch = lambda fn: False
+    excmatch = never
     if exc:
         dummy, exckinds, dummy = normalizepats(exc, 'glob')
         excmatch = matchfn(exckinds, '(?:/|$)')
@@ -671,6 +705,21 @@
         if cwd is not None and oldcwd != cwd:
             os.chdir(oldcwd)
 
+class SignatureError(Exception):
+    pass
+
+def checksignature(func):
+    '''wrap a function with code to check for calling errors'''
+    def check(*args, **kwargs):
+        try:
+            return func(*args, **kwargs)
+        except TypeError:
+            if len(traceback.extract_tb(sys.exc_info()[2])) == 1:
+                raise SignatureError
+            raise
+
+    return check
+
 # os.path.lexists is not available on python2.3
 def lexists(filename):
     "test whether a file with this name exists. does not follow symlinks"
--- a/mercurial/util_win32.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/mercurial/util_win32.py	Sun Dec 07 19:34:07 2008 +0100
@@ -19,7 +19,7 @@
 import util
 from win32com.shell import shell,shellcon
 
-class WinError:
+class WinError(Exception):
     winerror_map = {
         winerror.ERROR_ACCESS_DENIED: errno.EACCES,
         winerror.ERROR_ACCOUNT_DISABLED: errno.EACCES,
@@ -245,7 +245,7 @@
 def user_rcpath_win32():
     '''return os-specific hgrc search path to the user dir'''
     userdir = os.path.expanduser('~')
-    if sys.getwindowsversion() != 2 and userdir == '~':
+    if sys.getwindowsversion()[3] != 2 and userdir == '~':
         # We are on win < nt: fetch the APPDATA directory location and use
         # the parent directory as the user home dir.
         appdir = shell.SHGetPathFromIDList(
@@ -292,7 +292,7 @@
             raise WinIOError(err, name)
 
     def __iter__(self):
-        for line in self.read().splitlines(True):
+        for line in self.readlines():
             yield line
 
     def read(self, count=-1):
@@ -311,6 +311,11 @@
         except pywintypes.error, err:
             raise WinIOError(err)
 
+    def readlines(self, sizehint=None):
+        # splitlines() splits on single '\r' while readlines()
+        # does not. cStringIO has a well behaving readlines() and is fast.
+        return cStringIO.StringIO(self.read()).readlines()
+
     def write(self, data):
         try:
             if 'a' in self.mode:
--- a/mercurial/verify.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/mercurial/verify.py	Sun Dec 07 19:34:07 2008 +0100
@@ -70,7 +70,7 @@
             warn(_("warning: `%s' uses revlog format 0") % name)
 
     def checkentry(obj, i, node, seen, linkrevs, f):
-        lr = obj.linkrev(node)
+        lr = obj.linkrev(obj.rev(node))
         if lr < 0 or (havecl and lr not in linkrevs):
             t = "unexpected"
             if lr < 0 or lr >= len(cl):
@@ -135,7 +135,7 @@
                 elif f != "/dev/null":
                     fns = filenodes.setdefault(f, {})
                     if fn not in fns:
-                        fns[fn] = n
+                        fns[fn] = i
         except Exception, inst:
             exc(lr, _("reading manifest delta %s") % short(n), inst)
 
@@ -155,7 +155,8 @@
         for f in util.sort(filenodes):
             if f not in filelinkrevs:
                 try:
-                    lr = min([repo.file(f).linkrev(n) for n in filenodes[f]])
+                    fl = repo.file(f)
+                    lr = min([fl.linkrev(fl.rev(n)) for n in filenodes[f]])
                 except:
                     lr = None
                 err(lr, _("in manifest but not in changeset"), f)
--- a/templates/changelog.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-#header#
-<title>#repo|escape#: changelog</title>
-<link rel="alternate" type="application/atom+xml"
-   href="#url#atom-log" title="Atom feed for #repo|escape#">
-<link rel="alternate" type="application/rss+xml"
-   href="#url#rss-log" title="RSS feed for #repo|escape#">
-</head>
-<body>
-
-<div class="buttons">
-<a href="#url#shortlog/#rev#{sessionvars%urlparameter}">shortlog</a>
-<a href="#url#graph{sessionvars%urlparameter}">graph</a>
-<a href="#url#tags{sessionvars%urlparameter}">tags</a>
-<a href="#url#file/#node|short#{sessionvars%urlparameter}">files</a>
-#archives%archiveentry#
-<a type="application/rss+xml" href="#url#rss-log">rss</a>
-<a type="application/atom+xml" href="#url#atom-log" title="Atom feed for #repo|escape#">atom</a>
-</div>
-
-<h2>changelog for #repo|escape#</h2>
-
-<form action="#url#log">
-{sessionvars%hiddenformentry}
-<p>
-<label for="search1">search:</label>
-<input name="rev" id="search1" type="text" size="30">
-navigate: <small class="navigate">#changenav%naventry#</small>
-</p>
-</form>
-
-#entries%changelogentry#
-
-<form action="#url#log">
-{sessionvars%hiddenformentry}
-<p>
-<label for="search2">search:</label>
-<input name="rev" id="search2" type="text" size="30">
-navigate: <small class="navigate">#changenav%naventry#</small>
-</p>
-</form>
-
-#footer#
--- a/templates/changelogentry.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-<table class="logEntry parity#parity#">
- <tr>
-  <th class="age">#date|age# ago:</th>
-  <th class="firstline">#desc|strip|firstline|escape#</th>
- </tr>
- <tr>
-  <th class="revision">changeset #rev#:</th>
-  <td class="node"><a href="#url#rev/#node|short#{sessionvars%urlparameter}">#node|short#</a></td>
- </tr>
- #parent%changelogparent#
- #child%changelogchild#
- #changelogtag#
- <tr>
-  <th class="author">author:</th>
-  <td class="author">#author|obfuscate#</td>
- </tr>
- <tr>
-  <th class="date">date:</th>
-  <td class="date">#date|date#</td>
- </tr>
- <tr>
-  <th class="files"><a href="#url#file/#node|short#{sessionvars%urlparameter}">files</a>:</th>
-  <td class="files">#files#</td>
- </tr>
-</table>
--- a/templates/changeset.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-#header#
-<title>#repo|escape#: changeset #node|short#</title>
-</head>
-<body>
-
-<div class="buttons">
-<a href="#url#log/#rev#{sessionvars%urlparameter}">changelog</a>
-<a href="#url#shortlog/#rev#{sessionvars%urlparameter}">shortlog</a>
-<a href="#url#graph{sessionvars%urlparameter}">graph</a>
-<a href="#url#tags{sessionvars%urlparameter}">tags</a>
-<a href="#url#file/#node|short#{sessionvars%urlparameter}">files</a>
-<a href="#url#raw-rev/#node|short#">raw</a>
-#archives%archiveentry#
-</div>
-
-<h2>changeset: #desc|strip|escape|firstline#</h2>
-
-<table id="changesetEntry">
-<tr>
- <th class="changeset">changeset #rev#:</th>
- <td class="changeset"><a href="#url#rev/#node|short#{sessionvars%urlparameter}">#node|short#</a></td>
-</tr>
-#parent%changesetparent#
-#child%changesetchild#
-#changesettag#
-<tr>
- <th class="author">author:</th>
- <td class="author">#author|obfuscate#</td>
-</tr>
-<tr>
- <th class="date">date:</th>
- <td class="date">#date|date# (#date|age# ago)</td>
-</tr>
-<tr>
- <th class="files">files:</th>
- <td class="files">#files#</td>
-</tr>
-<tr>
- <th class="description">description:</th>
- <td class="description">#desc|strip|escape|addbreaks#</td>
-</tr>
-</table>
-
-<div id="changesetDiff">
-#diff#
-</div>
-
-#footer#
-
-
--- a/templates/coal/changeset.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-{header}
-<title>{repo|escape}: {node|short}</title>
-</head>
-<body>
-<div class="container">
-<div class="menu">
-<div class="logo">
-<a href="http://www.selenic.com/mercurial/">
-<img src="{staticurl}hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
-</div>
-<ul>
- <li><a href="{url}shortlog/{node|short}{sessionvars%urlparameter}">log</a></li>
- <li><a href="{url}graph/{node|short}{sessionvars%urlparameter}">graph</a></li>
- <li><a href="{url}tags{sessionvars%urlparameter}">tags</a></li>
-</ul>
-<ul>
- <li class="active">changeset</li>
- <li><a href="{url}raw-rev/{node|short}{sessionvars%urlparameter}">raw</a></li>
- <li><a href="{url}file/{node|short}{sessionvars%urlparameter}">browse</a></li>
-</ul>
-<ul>
- {archives%archiveentry}
-</ul>
-</div>
-
-<div class="main">
-
-<h2><a href="{url}">{repo|escape}</a></h2>
-<h3>changeset {rev}:{node|short} {changesettag}</h3>
-
-<form class="search" action="{url}log">
-{sessionvars%hiddenformentry}
-<p><input name="rev" id="search1" type="text" size="30"></p>
-<span>find changesets by author, revision, 
-files, or words in the commit message</span>
-</form>
-
-<div class="description">{desc|strip|escape|addbreaks}</div>
-
-<table id="changesetEntry">
-<tr>
- <th class="author">author</th>
- <td class="author">{author|obfuscate}</td>
-</tr>
-<tr>
- <th class="date">date</th>
- <td class="date">{date|date} ({date|age} ago)</td></tr>
-<tr>
- <th class="author">parents</th>
- <td class="author">{parent%changesetparent}</td>
-</tr>
-<tr>
- <th class="author">children</th>
- <td class="author">{child%changesetchild}</td>
-</tr>
-<tr>
- <th class="files">files</th>
- <td class="files">{files}</td>
-</tr>
-</table>
-
-<div class="overflow">
-<table class="bigtable">
-<tr>
- <th class="lineno">line</th>
- <th class="source">diff</th>
-</tr>
-</table>
-{diff}
-</div>
-
-</div>
-</div>
-{footer}
--- a/templates/coal/error.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-{header}
-<title>{repo|escape}: error</title>
-</head>
-<body>
-
-<div class="container">
-<div class="menu">
-<div class="logo">
-<a href="http://www.selenic.com/mercurial/">
-<img src="{staticurl}hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
-</div>
-<ul>
-<li><a href="{url}log{sessionvars%urlparameter}">log</a></li>
-<li><a href="{url}graph{sessionvars%urlparameter}">graph</a></li>
-<li><a href="{url}tags{sessionvars%urlparameter}">tags</a></li>
-</ul>
-</div>
-
-<div class="main">
-
-<h2><a href="{url}">{repo|escape}</a></h2>
-<h3>error</h3>
-
-<form class="search" action="{url}log">
-{sessionvars%hiddenformentry}
-<p><input name="rev" id="search1" type="text" size="30"></p>
-<span>find changesets by author, revision, 
-files, or words in the commit message</span>
-</form>
-
-<div class="description">
-<p>
-An error occurred while processing your request:
-</p>
-<p>
-{error|escape}
-</p>
-</div>
-</div>
-</div>
-
-{footer}
--- a/templates/coal/fileannotate.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-{header}
-<title>{repo|escape}: {file|escape} annotate</title>
-</head>
-<body>
-
-<div class="container">
-<div class="menu">
-<div class="logo">
-<a href="http://www.selenic.com/mercurial/">
-<img src="{staticurl}hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
-</div>
-<ul>
-<li><a href="{url}shortlog/{node|short}{sessionvars%urlparameter}">log</a></li>
-<li><a href="{url}graph/{node|short}{sessionvars%urlparameter}">graph</a></li>
-<li><a href="{url}tags{sessionvars%urlparameter}">tags</a></li>
-</ul>
-
-<ul>
-<li><a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a></li>
-<li><a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}">browse</a></li>
-</ul>
-<ul>
-<li><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a></li>
-<li><a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a></li>
-<li class="active">annotate</li>
-<li><a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file log</a></li>
-<li><a href="{url}raw-annotate/{node|short}/{file|urlescape}">raw</a></li>
-</ul>
-</div>
-
-<div class="main">
-<h2><a href="{url}">{repo|escape}</a></h2>
-<h3>annotate {file|escape} @ {rev}:{node|short}</h3>
-
-<form class="search" action="{url}log">
-{sessionvars%hiddenformentry}
-<p><input name="rev" id="search1" type="text" size="30"></p>
-<span>find changesets by author, revision, 
-files, or words in the commit message</span>
-</form>
-
-<div class="description">{desc|strip|escape|addbreaks}</div>
-
-<table id="changesetEntry">
-<tr>
- <th class="author">author</th>
- <td class="author">{author|obfuscate}</td>
-</tr>
-<tr>
- <th class="date">date</th>
- <td class="date">{date|date} ({date|age} ago)</td>
-</tr>
-<tr>
- <th class="author">parents</th>
- <td class="author">{parent%filerevparent}</td>
-</tr>
-<tr>
- <th class="author">children</th>
- <td class="author">{child%filerevchild}</td>
-</tr>
-{changesettag}
-</table>
-
-<br/>
-
-<div class="overflow">
-<table class="bigtable">
-<tr>
- <th class="annotate">rev</th>
- <th class="lineno">line</th>
- <th class="line">source</th>
-</tr>
-{annotate%annotateline}
-</table>
-</div>
-</div>
-</div>
-
-{footer}
--- a/templates/coal/filediff.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-{header}
-<title>{repo|escape}: {file|escape} diff</title>
-</head>
-<body>
-
-<div class="container">
-<div class="menu">
-<div class="logo">
-<a href="http://www.selenic.com/mercurial/">
-<img src="{staticurl}hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
-</div>
-<ul>
-<li><a href="{url}shortlog/{node|short}{sessionvars%urlparameter}">log</a></li>
-<li><a href="{url}graph/{node|short}{sessionvars%urlparameter}">graph</a></li>
-<li><a href="{url}tags{sessionvars%urlparameter}">tags</a></li>
-</ul>
-<ul>
-<li><a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a></li>
-<li><a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}">browse</a></li>
-</ul>
-<ul>
-<li><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a></li>
-<li class="active">diff</li>
-<li><a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a></li>
-<li><a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file log</a></li>
-<li><a href="{url}raw-file/{node|short}/{file|urlescape}">raw</a></li>
-</ul>
-</div>
-
-<div class="main">
-<h2><a href="{url}">{repo|escape}</a></h2>
-<h3>diff {file|escape} @ {rev}:{node|short}</h3>
-
-<form class="search" action="{url}log">
-{sessionvars%hiddenformentry}
-<p><input name="rev" id="search1" type="text" size="30"></p>
-<span>find changesets by author, revision, 
-files, or words in the commit message</span>
-</form>
-
-<div class="description">{desc|strip|escape|addbreaks}</div>
-
-<table id="changesetEntry">
-<tr>
- <th>author</th>
- <td>{author|obfuscate}</td>
-</tr>
-<tr>
- <th>date</th>
- <td>{date|date} ({date|age} ago)</td>
-</tr>
-<tr>
- <th>parents</th>
- <td>{parent%filerevparent}</td>
-</tr>
-<tr>
- <th>children</th>
- <td>{child%filerevchild}</td>
-</tr>
-{changesettag}
-</table>
-
-<div class="overflow">
-<table class="bigtable">
-<tr>
- <th class="lineno">line</th>
- <th class="source">diff</th>
-</tr>
-</table>
-
-{diff}
-</div>
-</div>
-</div>
-
-{footer}
--- a/templates/coal/filelog.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-{header}
-<title>{repo|escape}: {file|escape} history</title>
-<link rel="alternate" type="application/atom+xml"
-   href="{url}atom-log/tip/{file|urlescape}" title="Atom feed for {repo|escape}:{file}">
-<link rel="alternate" type="application/rss+xml"
-   href="{url}rss-log/tip/{file|urlescape}" title="RSS feed for {repo|escape}:{file}">
-</head>
-<body>
-
-<div class="container">
-<div class="menu">
-<div class="logo">
-<a href="http://www.selenic.com/mercurial/">
-<img src="{staticurl}hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
-</div>
-<ul>
-<li><a href="{url}shortlog/{node|short}{sessionvars%urlparameter}">log</a></li>
-<li><a href="{url}graph/{node|short}{sessionvars%urlparameter}">graph</a></li>
-<li><a href="{url}tags{sessionvars%urlparameter}">tags</a></li>
-</ul>
-<ul>
-<li><a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a></li>
-<li><a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}">browse</a></li>
-</ul>
-<ul>
-<li><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a></li>
-<li><a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a></li>
-<li><a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a></li>
-<li class="active">file log</li>
-<li><a href="{url}raw-file/{node|short}/{file|urlescape}">raw</a></li>
-</ul>
-</div>
-
-<div class="main">
-<h2><a href="{url}">{repo|escape}</a></h2>
-<h3>log {file|escape}</h3>
-
-<form class="search" action="{url}log">
-{sessionvars%hiddenformentry}
-<p><input name="rev" id="search1" type="text" size="30"></p>
-<span>find changesets by author, revision, 
-files, or words in the commit message</span>
-</form>
-
-<div class="navigate">{nav%filenaventry}</div>
-
-<table class="bigtable">
- <tr> 
-  <th class="age">age</th>
-  <th class="author">author</th>
-  <th class="description">description</th>
- </tr>
-{entries%filelogentry}
-</table>
-
-</div>
-</div>
-
-{footer}
--- a/templates/coal/filelogentry.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
- <tr class="parity{parity}">
-  <td class="age">{date|age}</td>
-  <td class="author">{author|person}</td>
-  <td class="description"><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{desc|strip|firstline|escape}</a></td>
- </tr>
--- a/templates/coal/filerevision.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-{header}
-<title>{repo|escape}: {node|short} {file|escape}</title>
-</head>
-<body>
-
-<div class="container">
-<div class="menu">
-<div class="logo">
-<a href="http://www.selenic.com/mercurial/">
-<img src="{staticurl}hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
-</div>
-<ul>
-<li><a href="{url}shortlog/{node|short}{sessionvars%urlparameter}">log</a></li>
-<li><a href="{url}graph/{node|short}{sessionvars%urlparameter}">graph</a></li>
-<li><a href="{url}tags{sessionvars%urlparameter}">tags</a></li>
-</ul>
-<ul>
-<li><a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a></li>
-<li><a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}">browse</a></li>
-</ul>
-<ul>
-<li class="active">file</li>
-<li><a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a></li>
-<li><a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a></li>
-<li><a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file log</a></li>
-<li><a href="{url}raw-file/{node|short}/{file|urlescape}">raw</a></li>
-</ul>
-</div>
-
-<div class="main">
-<h2><a href="{url}">{repo|escape}</a></h2>
-<h3>view {file|escape} @ {rev}:{node|short}</h3>
-
-<form class="search" action="{url}log">
-{sessionvars%hiddenformentry}
-<p><input name="rev" id="search1" type="text" size="30"></p>
-<span>find changesets by author, revision, 
-files, or words in the commit message</span>
-</form>
-
-<div class="description">{desc|strip|escape|addbreaks}</div>
-
-<table id="changesetEntry">
-<tr>
- <th class="author">author</th>
- <td class="author">{author|obfuscate}</td>
-</tr>
-<tr>
- <th class="date">date</th>
- <td class="date">{date|date} ({date|age} ago)</td>
-</tr>
-<tr>
- <th class="author">parents</th>
- <td class="author">{parent%filerevparent}</td>
-</tr>
-<tr>
- <th class="author">children</th>
- <td class="author">{child%filerevchild}</td>
-</tr>
-{changesettag}
-</table>
-
-<div class="overflow">
-<table class="bigtable">
-<tr>
- <th class="lineno">line</th>
- <th class="source">source</th>
-</tr>
-{text%fileline}
-</table>
-</div>
-</div>
-</div>
-
-{footer}
--- a/templates/coal/footer.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-{motd}
-
-</body>
-</html>
--- a/templates/coal/graph.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,113 +0,0 @@
-{header}
-<title>{repo|escape}: revision graph</title>
-<link rel="alternate" type="application/atom+xml"
-   href="{url}atom-log" title="Atom feed for {repo|escape}: log">
-<link rel="alternate" type="application/rss+xml"
-   href="{url}rss-log" title="RSS feed for {repo|escape}: log">
-<!--[if IE]><script type="text/javascript" src="{staticurl}excanvas.js"></script><![endif]-->
-</head>
-<body>
-
-<div class="container">
-<div class="menu">
-<div class="logo">
-<a href="http://www.selenic.com/mercurial/">
-<img src="{staticurl}hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
-</div>
-<ul>
-<li><a href="{url}shortlog/{node|short}{sessionvars%urlparameter}">log</a></li>
-<li class="active">graph</li>
-<li><a href="{url}tags{sessionvars%urlparameter}">tags</a></li>
-</ul>
-<ul>
-<li><a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a></li>
-<li><a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}">browse</a></li>
-</ul>
-</div>
-
-<div class="main">
-<h2><a href="{url}">{repo|escape}</a></h2>
-<h3>graph</h3>
-
-<form class="search" action="{url}log">
-{sessionvars%hiddenformentry}
-<p><input name="rev" id="search1" type="text" size="30"></p>
-<span>find changesets by author, revision, 
-files, or words in the commit message</span>
-</form>
-
-<div class="navigate">
-<a href="{url}graph/{uprev}{sessionvars%urlparameter}?revcount={revcountless}">less</a>
-<a href="{url}graph/{uprev}{sessionvars%urlparameter}?revcount={revcountmore}">more</a>
-| {changenav%navgraphentry}
-</div>
-
-<noscript>The revision graph only works with JavaScript-enabled browsers.</noscript>
-
-<div id="wrapper">
-<ul id="nodebgs"></ul>
-<canvas id="graph" width="224" height="{canvasheight}"></canvas>
-<ul id="graphnodes"></ul>
-</div>
-
-<script type="text/javascript" src="{staticurl}graph.js"></script>
-<script type="text/javascript">
-<!-- hide script content
-
-var data = {jsdata|json};
-var graph = new Graph();
-graph.scale({bg_height});
-
-graph.edge = function(x0, y0, x1, y1, color) {
-	
-	this.setColor(color, 0.0, 0.65);
-	this.ctx.beginPath();
-	this.ctx.moveTo(x0, y0);
-	this.ctx.lineTo(x1, y1);
-	this.ctx.stroke();
-	
-}
-
-var revlink = '<li style="_STYLE"><span class="desc">';
-revlink += '<a href="{url}rev/_NODEID{sessionvars%urlparameter}" title="_NODEID">_DESC</a>';
-revlink += '</span><span class="tag">_TAGS</span>';
-revlink += '<span class="info">_DATE ago, by _USER</span></li>';
-
-graph.vertex = function(x, y, color, parity, cur) {
-	
-	this.ctx.beginPath();
-	color = this.setColor(color, 0.25, 0.75);
-	this.ctx.arc(x, y, radius, 0, Math.PI * 2, true);
-	this.ctx.fill();
-	
-	var bg = '<li class="bg parity' + parity + '"></li>';
-	var left = (this.columns + 1) * this.bg_height;
-	var nstyle = 'padding-left: ' + left + 'px;';
-	var item = revlink.replace(/_STYLE/, nstyle);
-	item = item.replace(/_PARITY/, 'parity' + parity);
-	item = item.replace(/_NODEID/, cur[0]);
-	item = item.replace(/_NODEID/, cur[0]);
-	item = item.replace(/_DESC/, cur[3]);
-	item = item.replace(/_USER/, cur[4]);
-	item = item.replace(/_DATE/, cur[5]);
-	item = item.replace(/_TAGS/, cur[7].join('&nbsp; '));
-	
-	return [bg, item];
-	
-}
-
-graph.render(data);
-
-// stop hiding script -->
-</script>
-
-<div class="navigate">
-<a href="{url}graph/{uprev}{sessionvars%urlparameter}?revcount={revcountless}">less</a>
-<a href="{url}graph/{uprev}{sessionvars%urlparameter}?revcount={revcountmore}">more</a>
-| {changenav%navgraphentry}
-</div>
-
-</div>
-</div>
-
-{footer}
--- a/templates/coal/index.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-{header}
-<title>Mercurial repositories index</title>
-</head>
-<body>
-
-<div class="container">
-<div class="menu">
-<a href="http://www.selenic.com/mercurial/">
-<img src="{staticurl}hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
-</div>
-<div class="main">
-<h2>Mercurial Repositories</h2>
-
-<table class="bigtable">
-    <tr>
-        <th><a href="?sort={sort_name}">Name</a></th>
-        <th><a href="?sort={sort_description}">Description</a></th>
-        <th><a href="?sort={sort_contact}">Contact</a></th>
-        <th><a href="?sort={sort_lastchange}">Last change</a></th>
-        <th>&nbsp;</th>
-    </tr>
-    {entries%indexentry}
-</table>
-</div>
-</div>
-{footer}
--- a/templates/coal/manifest.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-{header}
-<title>{repo|escape}: {node|short} {path|escape}</title>
-</head>
-<body>
-
-<div class="container">
-<div class="menu">
-<div class="logo">
-<a href="http://www.selenic.com/mercurial/">
-<img src="{staticurl}hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
-</div>
-<ul>
-<li><a href="{url}shortlog/{node|short}{sessionvars%urlparameter}">log</a></li>
-<li><a href="{url}graph/{node|short}{sessionvars%urlparameter}">graph</a></li>
-<li><a href="{url}tags{sessionvars%urlparameter}">tags</a></li>
-</ul>
-<ul>
-<li><a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a></li>
-<li class="active">browse</li>
-</ul>
-<ul>
-{archives%archiveentry}
-</ul>
-</div>
-
-<div class="main">
-<h2><a href="{url}">{repo|escape}</a></h2>
-<h3>directory {path|escape} @ {rev}:{node|short} {tags%changelogtag}</h3>
-
-<form class="search" action="{url}log">
-{sessionvars%hiddenformentry}
-<p><input name="rev" id="search1" type="text" size="30"></p>
-<span>find changesets by author, revision, 
-files, or words in the commit message</span>
-</form>
-
-<table class="bigtable">
-<tr>
-  <th class="name">name</th>
-  <th class="size">size</th>
-  <th class="permissions">permissions</th>
-</tr>
-<tr class="fileline parity{upparity}">
-  <td class="name"><a href="{url}file/{node|short}{up|urlescape}{sessionvars%urlparameter}">[up]</a></td>
-  <td class="size"></td>
-  <td class="permissions">drwxr-xr-x</td>
-</tr>
-{dentries%direntry}
-{fentries%fileentry}
-</table>
-</div>
-</div>
-{footer}
--- a/templates/coal/map	Sun Dec 07 19:33:26 2008 +0100
+++ b/templates/coal/map	Sun Dec 07 19:34:07 2008 +0100
@@ -2,13 +2,13 @@
 
 mimetype = 'text/html; charset={encoding}'
 header = header.tmpl
-footer = footer.tmpl
-search = search.tmpl
+footer = ../paper/footer.tmpl
+search = ../paper/search.tmpl
 
-changelog = shortlog.tmpl
-shortlog = shortlog.tmpl
-shortlogentry = shortlogentry.tmpl
-graph = graph.tmpl
+changelog = ../paper/shortlog.tmpl
+shortlog = ../paper/shortlog.tmpl
+shortlogentry = ../paper/shortlogentry.tmpl
+graph = ../paper/graph.tmpl
 
 naventry = '<a href="{url}log/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
 navshortentry = '<a href="{url}shortlog/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
@@ -18,28 +18,28 @@
 filenodelink = '<a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{file|escape}</a> '
 filenolink = '{file|escape} '
 fileellipses = '...'
-changelogentry = shortlogentry.tmpl
-searchentry = shortlogentry.tmpl
-changeset = changeset.tmpl
-manifest = manifest.tmpl
+changelogentry = ../paper/shortlogentry.tmpl
+searchentry = ../paper/shortlogentry.tmpl
+changeset = ../paper/changeset.tmpl
+manifest = ../paper/manifest.tmpl
 
 direntry = '<tr class="fileline parity{parity}"><td class="name"><a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}"><img src="{staticurl}coal-folder.png"> {basename|escape}/</a> <a href="{url}file/{node|short}{path|urlescape}/{emptydirs|urlescape}{sessionvars%urlparameter}">{emptydirs|escape}</a><td class="size"></td><td class="permissions">drwxr-xr-x</td></tr>'
 fileentry = '<tr class="fileline parity{parity}"><td class="filename"><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}#l1"><img src="{staticurl}coal-file.png"> {basename|escape}</a></td><td class="size">{size}</td><td class="permissions">{permissions|permissions}</td></tr>'
 
-filerevision = filerevision.tmpl
-fileannotate = fileannotate.tmpl
-filediff = filediff.tmpl
-filelog = filelog.tmpl
-fileline = '<tr class="parity{parity}"><td class="lineno"><a href="#{lineid}" id="{lineid}">{linenumber}</a></td><td class="source">{line|escape}</td></tr>'
-filelogentry = filelogentry.tmpl
+filerevision = ../paper/filerevision.tmpl
+fileannotate = ../paper/fileannotate.tmpl
+filediff = ../paper/filediff.tmpl
+filelog = ../paper/filelog.tmpl
+fileline = '<div class="parity{parity} source"><a href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</div>'
+filelogentry = ../paper/filelogentry.tmpl
 
-annotateline = '<tr class="parity{parity}"><td class="annotate"><a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}#{targetline}" title="{node|short}: {desc|escape|firstline}">{author|user}@{rev}</a></td><td class="lineno"><a href="#{lineid}" id="{lineid}">{linenumber}</a></td><td class="source">{line|escape}</td></tr>'
+annotateline = '<tr class="parity{parity}"><td class="annotate"><a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}#{targetline}" title="{node|short}: {desc|escape|firstline}">{author|user}@{rev}</a></td><td class="source"><a href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</td></tr>'
 
-diffblock = '<table class="bigtable parity{parity}">{lines}</table>'
-difflineplus = '<tr><td class="lineno"><a href="#{lineid}" id="{lineid}">{linenumber}</a></td><td class="source plusline">{line|escape}</td></tr>'
-difflineminus = '<tr><td class="lineno"><a href="#{lineid}" id="{lineid}">{linenumber}</a></td><td class="source minusline">{line|escape}</td></tr>'
-difflineat = '<tr><td class="lineno"><a href="#{lineid}" id="{lineid}">{linenumber}</a></td><td class="source atline">{line|escape}</td></tr>'
-diffline = '<tr><td class="lineno"><a href="#{lineid}" id="{lineid}">{linenumber}</a></td><td class="source">{line|escape}</td></tr>'
+diffblock = '<div class="source bottomline parity{parity}">{lines}</div>'
+difflineplus = '<a href="#{lineid}" id="{lineid}">{linenumber}</a> <span class="plusline">{line|escape}</span>'
+difflineminus = '<a href="#{lineid}" id="{lineid}">{linenumber}</a> <span class="minusline">{line|escape}</span>'
+difflineat = '<a href="#{lineid}" id="{lineid}">{linenumber}</a> <span class="atline">{line|escape}</span>'
+diffline = '<a href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}'
 
 changelogparent = '<tr><th class="parent">parent {rev}:</th><td class="parent"><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a></td></tr>'
 
@@ -54,19 +54,21 @@
 changesetchild = '<a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a>'
 changelogchild = '<tr><th class="child">child</th><td class="child"><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a></td></tr>'
 fileannotatechild = '<tr><td class="metatag">child:</td><td><a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></td></tr>'
-tags = tags.tmpl
+tags = ../paper/tags.tmpl
 tagentry = '<tr class="tagEntry parity{parity}"><td><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{tag|escape}</a></td><td class="node">{node|short}</td></tr>'
 changelogtag = '<span class="tag">{name|escape}</span> '
 changesettag = '<span class="tag">{tag|escape}</span> '
+changelogbranchhead = '<span class="branchhead">{name|escape}</span> '
+changelogbranchname = '<span class="branchname">{name|escape}</span> ' 
 filediffparent = '<tr><th class="parent">parent {rev}:</th><td class="parent"><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a></td></tr>'
 filelogparent = '<tr><th>parent {rev}:</th><td><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></td></tr>'
 filediffchild = '<tr><th class="child">child {rev}:</th><td class="child"><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a></td></tr>'
 filelogchild = '<tr><th>child {rev}:</th><td><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></td></tr>'
 indexentry = '<tr class="parity{parity}"><td><a href="{url}{sessionvars%urlparameter}">{name|escape}</a></td><td>{description}</td><td>{contact|obfuscate}</td><td class="age">{lastchange|age} ago</td><td class="indexlinks">{archives%indexarchiveentry}</td></tr>\n'
 indexarchiveentry = '<a href="{url}archive/{node|short}{extension|urlescape}">&nbsp;&darr;{type|escape}</a>'
-index = index.tmpl
+index = ../paper/index.tmpl
 archiveentry = '<li><a href="{url}archive/{node|short}{extension|urlescape}">{type|escape}</a></li>'
-notfound = notfound.tmpl
-error = error.tmpl
+notfound = ../paper/notfound.tmpl
+error = ../paper/error.tmpl
 urlparameter = '{separator}{name}={value|urlescape}'
 hiddenformentry = '<input type="hidden" name="{name}" value="{value|escape}" />'
--- a/templates/coal/notfound.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-{header}
-<title>Mercurial repository not found</title>
-</head>
-<body>
-
-<h2>Mercurial repository not found</h2>
-
-The specified repository "{repo|escape}" is unknown, sorry.
-
-Please go back to the main repository list page.
-
-{footer}
--- a/templates/coal/search.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-{header}
-<title>{repo|escape}: searching for {query|escape}</title>
-</head>
-<body>
-
-<div class="container">
-<div class="menu">
-<div class="logo">
-<a href="http://www.selenic.com/mercurial/">
-<img src="{staticurl}hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
-</div>
-<ul>
-<li><a href="{url}shortlog{sessionvars%urlparameter}">log</a></li>
-<li><a href="{url}graph{sessionvars%urlparameter}">graph</a></li>
-<li><a href="{url}tags{sessionvars%urlparameter}">tags</a></li>
-</ul>
-</div>
-
-<div class="main">
-<h2><a href="{url}">{repo|escape}</a></h2>
-<h3>searching for '{query|escape}'</h3>
-
-<form class="search" action="{url}log">
-{sessionvars%hiddenformentry}
-<p><input name="rev" id="search1" type="text" size="30"></p>
-<span>find changesets by author, revision, 
-files, or words in the commit message</span>
-</form>
-
-<table class="bigtable">
- <tr> 
-  <th class="age">age</th>
-  <th class="author">author</th>
-  <th class="description">description</th>
- </tr>
-{entries}
-</table>
-
-</div>
-</div>
-
-{footer}
--- a/templates/coal/shortlog.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-{header}
-<title>{repo|escape}: log</title>
-<link rel="alternate" type="application/atom+xml"
-   href="{url}atom-log" title="Atom feed for {repo|escape}">
-<link rel="alternate" type="application/rss+xml"
-   href="{url}rss-log" title="RSS feed for {repo|escape}">
-</head>
-<body>
-
-<div class="container">
-<div class="menu">
-<div class="logo">
-<a href="http://www.selenic.com/mercurial/">
-<img src="{staticurl}hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
-</div>
-<ul>
-<li class="active">log</li>
-<li><a href="{url}graph/{node|short}{sessionvars%urlparameter}">graph</a></li>
-<li><a href="{url}tags{sessionvars%urlparameter}">tags</a></li>
-</ul>
-<ul>
-<li><a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a></li>
-<li><a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}">browse</a></li>
-</ul>
-<ul>
-{archives%archiveentry}
-</ul>
-</div>
-
-<div class="main">
-<h2><a href="{url}">{repo|escape}</a></h2>
-<h3>log</h3>
-
-<form class="search" action="{url}log">
-{sessionvars%hiddenformentry}
-<p><input name="rev" id="search1" type="text" size="30"></p>
-<span>find changesets by author, revision,
-files, or words in the commit message</span>
-</form>
-
-<div class="navigate">rev {rev}: {changenav%navshortentry}</div>
-
-<table class="bigtable">
- <tr> 
-  <th class="age">age</th>
-  <th class="author">author</th>
-  <th class="description">description</th>
- </tr>
-{entries%shortlogentry}
-</table>
-
-<div class="navigate">rev {rev}: {changenav%navshortentry}</div>
-</div>
-</div>
-
-{footer}
--- a/templates/coal/shortlogentry.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,5 +0,0 @@
- <tr class="parity{parity}">
-  <td class="age">{date|age}</td>
-  <td class="author">{author|person}</td>
-  <td class="description"><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{desc|strip|firstline|escape}</a>{tags%changelogtag}</td>
- </tr>
--- a/templates/coal/tags.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-{header}
-<title>{repo|escape}: tags</title>
-<link rel="alternate" type="application/atom+xml"
-   href="{url}atom-tags" title="Atom feed for {repo|escape}: tags">
-<link rel="alternate" type="application/rss+xml"
-   href="{url}rss-tags" title="RSS feed for {repo|escape}: tags">
-</head>
-<body>
-
-<div class="container">
-<div class="menu">
-<div class="logo">
-<a href="http://www.selenic.com/mercurial/">
-<img src="{staticurl}hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
-</div>
-<ul>
-<li><a href="{url}shortlog{sessionvars%urlparameter}">log</a></li>
-<li><a href="{url}graph{sessionvars%urlparameter}">graph</a></li>
-<li class="active">tags</li>
-</ul>
-</div>
-
-<div class="main">
-<h2><a href="{url}">{repo|escape}</a></h2>
-<h3>tags</h3>
-
-<form class="search" action="{url}log">
-{sessionvars%hiddenformentry}
-<p><input name="rev" id="search1" type="text" size="30"></p>
-<span>find changesets by author, revision, 
-files, or words in the commit message</span>
-</form>
-
-<table class="bigtable">
-<tr>
- <th>tag</th>
- <th>node</th>
-</tr>
-{entries%tagentry}
-</table>
-</div>
-</div>
-
-{footer}
--- a/templates/error.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-#header#
-<title>Mercurial Error</title>
-</head>
-<body>
-
-<h2>Mercurial Error</h2>
-
-<p>
-An error occurred while processing your request:
-</p>
-<p>
-#error|escape#
-</p>
-
-#footer#
--- a/templates/fileannotate.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-#header#
-<title>#repo|escape#: #file|escape# annotate</title>
-</head>
-<body>
-
-<div class="buttons">
-<a href="#url#log/#rev#{sessionvars%urlparameter}">changelog</a>
-<a href="#url#shortlog/#rev#{sessionvars%urlparameter}">shortlog</a>
-<a href="#url#graph{sessionvars%urlparameter}">graph</a>
-<a href="#url#tags{sessionvars%urlparameter}">tags</a>
-<a href="#url#rev/#node|short#{sessionvars%urlparameter}">changeset</a>
-<a href="#url#file/#node|short##path|urlescape#{sessionvars%urlparameter}">files</a>
-<a href="#url#file/#node|short#/#file|urlescape#{sessionvars%urlparameter}">file</a>
-<a href="#url#log/#node|short#/#file|urlescape#{sessionvars%urlparameter}">revisions</a>
-<a href="#url#raw-annotate/#node|short#/#file|urlescape#">raw</a>
-</div>
-
-<h2>Annotate #file|escape#</h2>
-
-<table>
-<tr>
- <td class="metatag">changeset #rev#:</td>
- <td><a href="#url#rev/#node|short#{sessionvars%urlparameter}">#node|short#</a></td></tr>
-#parent%fileannotateparent#
-#child%fileannotatechild#
-<tr>
- <td class="metatag">author:</td>
- <td>#author|obfuscate#</td></tr>
-<tr>
- <td class="metatag">date:</td>
- <td>#date|date# (#date|age# ago)</td>
-</tr>
-<tr>
- <td class="metatag">permissions:</td>
- <td>#permissions|permissions#</td>
-</tr>
-<tr>
-  <td class="metatag">description:</td>
-  <td>{desc|strip|escape|addbreaks}</td>
-</tr>
-</table>
-
-<br/>
-
-<table cellspacing="0" cellpadding="0">
-#annotate%annotateline#
-</table>
-
-#footer#
--- a/templates/filediff.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-#header#
-<title>#repo|escape#: #file|escape# diff</title>
-</head>
-<body>
-
-<div class="buttons">
-<a href="#url#log/#rev#{sessionvars%urlparameter}">changelog</a>
-<a href="#url#shortlog/#rev#{sessionvars%urlparameter}">shortlog</a>
-<a href="#url#graph{sessionvars%urlparameter}">graph</a>
-<a href="#url#tags{sessionvars%urlparameter}">tags</a>
-<a href="#url#rev/#node|short#{sessionvars%urlparameter}">changeset</a>
-<a href="#url#file/#node|short#/#file|urlescape#{sessionvars%urlparameter}">file</a>
-<a href="#url#log/#node|short#/#file|urlescape#{sessionvars%urlparameter}">revisions</a>
-<a href="#url#annotate/#node|short#/#file|urlescape#{sessionvars%urlparameter}">annotate</a>
-<a href="#url#raw-diff/#node|short#/#file|urlescape#">raw</a>
-</div>
-
-<h2>#file|escape#</h2>
-
-<table id="filediffEntry">
-<tr>
- <th class="revision">revision #rev#:</th>
- <td class="revision"><a href="#url#rev/#node|short#{sessionvars%urlparameter}">#node|short#</a></td>
-</tr>
-#parent%filediffparent#
-#child%filediffchild#
-</table>
-
-<div id="fileDiff">
-#diff#
-</div>
-
-#footer#
-
-
--- a/templates/filelog.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-#header#
-<title>#repo|escape#: #file|escape# history</title>
-<link rel="alternate" type="application/atom+xml"
-   href="#url#atom-log/tip/#file|urlescape#" title="Atom feed for #repo|escape#:#file#">
-<link rel="alternate" type="application/rss+xml"
-   href="#url#rss-log/tip/#file|urlescape#" title="RSS feed for #repo|escape#:#file#">
-</head>
-<body>
-
-<div class="buttons">
-<a href="#url#log{sessionvars%urlparameter}">changelog</a>
-<a href="#url#shortlog{sessionvars%urlparameter}">shortlog</a>
-<a href="#url#graph{sessionvars%urlparameter}">graph</a>
-<a href="#url#tags{sessionvars%urlparameter}">tags</a>
-<a href="#url#file/#node|short#/#file|urlescape#{sessionvars%urlparameter}">file</a>
-<a href="#url#annotate/#node|short#/#file|urlescape#{sessionvars%urlparameter}">annotate</a>
-<a type="application/rss+xml" href="#url#rss-log/tip/#file|urlescape#">rss</a>
-<a type="application/atom+xml" href="#url#atom-log/tip/#file|urlescape#" title="Atom feed for #repo|escape#:#file#">atom</a>
-</div>
-
-<h2>#file|escape# revision history</h2>
-
-<p>navigate: <small class="navigate">{nav%filenaventry}</small></p>
-
-#entries%filelogentry#
-
-#footer#
--- a/templates/filelogentry.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-<table class="logEntry parity#parity#">
- <tr>
-  <th class="age">#date|age# ago:</th>
-  <th class="firstline"><a href="#url#rev/#node|short#{sessionvars%urlparameter}">#desc|strip|firstline|escape#</a></th>
- </tr>
- <tr>
-  <th class="revision">revision #filerev#:</td>
-  <td class="node">
-   <a href="#url#file/#node|short#/#file|urlescape#{sessionvars%urlparameter}">#node|short#</a>
-   <a href="#url#diff/#node|short#/#file|urlescape#{sessionvars%urlparameter}">(diff)</a>
-   <a href="#url#annotate/#node|short#/#file|urlescape#{sessionvars%urlparameter}">(annotate)</a>
-  </td>
- </tr>
- #rename%filelogrename#
- <tr>
-  <th class="author">author:</th>
-  <td class="author">#author|obfuscate#</td>
- </tr>
- <tr>
-  <th class="date">date:</th>
-  <td class="date">#date|date#</td>
- </tr>
-</table>
-
-
--- a/templates/filerevision.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-#header#
-<title>#repo|escape#:#file|escape#</title>
-</head>
-<body>
-
-<div class="buttons">
-<a href="#url#log/#rev#{sessionvars%urlparameter}">changelog</a>
-<a href="#url#shortlog/#rev#{sessionvars%urlparameter}">shortlog</a>
-<a href="#url#graph{sessionvars%urlparameter}">graph</a>
-<a href="#url#tags{sessionvars%urlparameter}">tags</a>
-<a href="#url#rev/#node|short#{sessionvars%urlparameter}">changeset</a>
-<a href="#url#file/#node|short##path|urlescape#{sessionvars%urlparameter}">files</a>
-<a href="#url#log/#node|short#/#file|urlescape#{sessionvars%urlparameter}">revisions</a>
-<a href="#url#annotate/#node|short#/#file|urlescape#{sessionvars%urlparameter}">annotate</a>
-<a href="#url#raw-file/#node|short#/#file|urlescape#">raw</a>
-</div>
-
-<h2>#file|escape#</h2>
-
-<table>
-<tr>
- <td class="metatag">changeset #rev#:</td>
- <td><a href="#url#rev/#node|short#{sessionvars%urlparameter}">#node|short#</a></td></tr>
-#parent%filerevparent#
-#child%filerevchild#
-<tr>
- <td class="metatag">author:</td>
- <td>#author|obfuscate#</td></tr>
-<tr>
- <td class="metatag">date:</td>
- <td>#date|date# (#date|age# ago)</td></tr>
-<tr>
- <td class="metatag">permissions:</td>
- <td>#permissions|permissions#</td></tr>
-<tr>
-  <td class="metatag">description:</td>
-  <td>{desc|strip|escape|addbreaks}</td>
-</tr>
-</table>
-
-<pre>
-#text%fileline#
-</pre>
-
-#footer#
--- a/templates/footer.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,8 +0,0 @@
-#motd#
-<div class="logo">
-<a href="http://www.selenic.com/mercurial/">
-<img src="#staticurl#hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
-</div>
-
-</body>
-</html>
--- a/templates/gitweb/graph.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ b/templates/gitweb/graph.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -4,6 +4,7 @@
    href="{url}atom-log" title="Atom feed for #repo|escape#"/>
 <link rel="alternate" type="application/rss+xml"
    href="{url}rss-log" title="RSS feed for #repo|escape#"/>
+<!--[if IE]><script type="text/javascript" src="{staticurl}excanvas.js"></script><![endif]-->
 </head>
 <body>
 
@@ -25,8 +26,8 @@
 <a href="{url}tags{sessionvars%urlparameter}">tags</a> |
 <a href="{url}file/#node|short#{sessionvars%urlparameter}">files</a>
 <br/>
-<a href="{url}graph/{uprev}{sessionvars%urlparameter}?revcount={revcountless}">less</a>
-<a href="{url}graph/{uprev}{sessionvars%urlparameter}?revcount={revcountmore}">more</a>
+<a href="{url}graph/{rev}{lessvars%urlparameter}">less</a>
+<a href="{url}graph/{rev}{morevars%urlparameter}">more</a>
 | #changenav%navgraphentry#<br/>
 </div>
 
@@ -111,8 +112,8 @@
 </script>
 
 <div class="page_nav">
-<a href="{url}graph/{uprev}{sessionvars%urlparameter}?revcount={revcountless}">less</a>
-<a href="{url}graph/{uprev}{sessionvars%urlparameter}?revcount={revcountmore}">more</a>
+<a href="{url}graph/{rev}{lessvars%urlparameter}">less</a>
+<a href="{url}graph/{rev}{morevars%urlparameter}">more</a>
 | {changenav%navgraphentry}
 </div>
 
--- a/templates/graph.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-#header#
-<title>#repo|escape#: graph</title>
-<link rel="alternate" type="application/atom+xml"
-   href="#url#atom-tags" title="Atom feed for #repo|escape#: tags">
-<link rel="alternate" type="application/rss+xml"
-   href="#url#rss-tags" title="RSS feed for #repo|escape#: tags">
-<!--[if IE]><script type="text/javascript" src="#staticurl#excanvas.js"></script><![endif]-->
-</head>
-<body>
-
-<div class="buttons">
-<a href="#url#log{sessionvars%urlparameter}">changelog</a>
-<a href="#url#shortlog{sessionvars%urlparameter}">shortlog</a>
-<a href="#url#tags{sessionvars%urlparameter}">tags</a>
-<a href="#url#file/#node|short#/{sessionvars%urlparameter}">files</a>
-</div>
-
-<h2>graph</h2>
-
-<form action="#url#log">
-{sessionvars%hiddenformentry}
-<p>
-<label for="search1">search:</label>
-<input name="rev" id="search1" type="text" size="30">
-navigate: <small class="navigate">#changenav%navgraphentry#</small>
-</p>
-</form>
-
-<noscript>The revision graph only works with JavaScript-enabled browsers.</noscript>
-
-<div id="wrapper">
-<ul id="nodebgs"></ul>
-<canvas id="graph" width="224" height="#canvasheight#"></canvas>
-<ul id="graphnodes"></ul>
-</div>
-
-<script type="text/javascript" src="#staticurl#graph.js"></script>
-<script type="text/javascript">
-<!-- hide script content
-
-var data = {jsdata|json};
-var graph = new Graph();
-graph.scale({bg_height});
-
-graph.edge = function(x0, y0, x1, y1, color) {
-	
-	this.setColor(color, 0.0, 0.65);
-	this.ctx.beginPath();
-	this.ctx.moveTo(x0, y0);
-	this.ctx.lineTo(x1, y1);
-	this.ctx.stroke();
-	
-}
-
-var revlink = '<li style="_STYLE"><span class="desc">';
-revlink += '<a href="{url}rev/_NODEID{sessionvars%urlparameter}" title="_NODEID">_DESC</a>';
-revlink += '</span><span class="info">_DATE ago, by _USER</span></li>';
-
-graph.vertex = function(x, y, color, parity, cur) {
-	
-	this.ctx.beginPath();
-	color = this.setColor(color, 0.25, 0.75);
-	this.ctx.arc(x, y, radius, 0, Math.PI * 2, true);
-	this.ctx.fill();
-	
-	var bg = '<li class="bg parity' + parity + '"></li>';
-	var left = (this.columns + 1) * this.bg_height;
-	var nstyle = 'padding-left: ' + left + 'px;';
-	var item = revlink.replace(/_STYLE/, nstyle);
-	item = item.replace(/_PARITY/, 'parity' + parity);
-	item = item.replace(/_NODEID/, cur[0]);
-	item = item.replace(/_NODEID/, cur[0]);
-	item = item.replace(/_DESC/, cur[3]);
-	item = item.replace(/_USER/, cur[4]);
-	item = item.replace(/_DATE/, cur[5]);
-	
-	return [bg, item];
-	
-}
-
-graph.render(data);
-
-// stop hiding script -->
-</script>
-
-<form action="#url#log">
-{sessionvars%hiddenformentry}
-<p>
-<label for="search1">search:</label>
-<input name="rev" id="search1" type="text" size="30">
-navigate: <small class="navigate">#changenav%navgraphentry#</small>
-</p>
-</form>
-
-#footer#
--- a/templates/header.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
-<head>
-<link rel="icon" href="#staticurl#hgicon.png" type="image/png">
-<meta name="robots" content="index, nofollow" />
-<link rel="stylesheet" href="#staticurl#style.css" type="text/css" />
--- a/templates/index.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,19 +0,0 @@
-#header#
-<title>Mercurial repositories index</title>
-</head>
-<body>
-
-<h2>Mercurial Repositories</h2>
-
-<table>
-    <tr>
-        <td><a href="?sort=#sort_name#">Name</a></td>
-        <td><a href="?sort=#sort_description#">Description</a></td>
-        <td><a href="?sort=#sort_contact#">Contact</a></td>
-        <td><a href="?sort=#sort_lastchange#">Last change</a></td>
-        <td>&nbsp;</td>
-    </tr>
-    #entries%indexentry#
-</table>
-
-#footer#
--- a/templates/manifest.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-#header#
-<title>#repo|escape#: files for changeset #node|short#</title>
-</head>
-<body>
-
-<div class="buttons">
-<a href="#url#log/#rev#{sessionvars%urlparameter}">changelog</a>
-<a href="#url#shortlog/#rev#{sessionvars%urlparameter}">shortlog</a>
-<a href="#url#graph{sessionvars%urlparameter}">graph</a>
-<a href="#url#tags{sessionvars%urlparameter}">tags</a>
-<a href="#url#rev/#node|short#{sessionvars%urlparameter}">changeset</a>
-#archives%archiveentry#
-</div>
-
-<h2>files for changeset #node|short#: #path|escape#</h2>
-
-<table cellpadding="0" cellspacing="0">
-<tr class="parity#upparity#">
-  <td><tt>drwxr-xr-x</tt>&nbsp;
-  <td>&nbsp;
-  <td>&nbsp;
-  <td><a href="#url#file/#node|short##up|urlescape#{sessionvars%urlparameter}">[up]</a>
-</tr>
-#dentries%direntry#
-#fentries%fileentry#
-</table>
-#footer#
--- a/templates/map	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-default = 'shortlog'
-mimetype = 'text/html; charset={encoding}'
-header = header.tmpl
-footer = footer.tmpl
-search = search.tmpl
-changelog = changelog.tmpl
-shortlog = shortlog.tmpl
-shortlogentry = shortlogentry.tmpl
-graph = graph.tmpl
-naventry = '<a href="{url}log/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
-navshortentry = '<a href="{url}shortlog/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
-navgraphentry = '<a href="{url}graph/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
-filenaventry = '<a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{label|escape}</a> '
-filedifflink = '<a href="#url#diff/#node|short#/#file|urlescape#{sessionvars%urlparameter}">#file|escape#</a> '
-filenodelink = '<a href="#url#file/#node|short#/#file|urlescape#{sessionvars%urlparameter}">#file|escape#</a> '
-filenolink = '{file|escape} '
-fileellipses = '...'
-changelogentry = changelogentry.tmpl
-searchentry = changelogentry.tmpl
-changeset = changeset.tmpl
-manifest = manifest.tmpl
-direntry = '<tr class="parity#parity#"><td><tt>drwxr-xr-x</tt>&nbsp;<td>&nbsp;<td>&nbsp;<td><a href="#url#file/#node|short##path|urlescape#{sessionvars%urlparameter}">#basename|escape#/</a> <a href="#url#file/#node|short##path|urlescape#/#emptydirs|urlescape#{sessionvars%urlparameter}">#emptydirs|urlescape#</a>'
-fileentry = '<tr class="parity#parity#"><td><tt>#permissions|permissions#</tt>&nbsp;<td align=right><tt class="date">#date|isodate#</tt>&nbsp;<td align=right><tt>#size#</tt>&nbsp;<td><a href="#url#file/#node|short#/#file|urlescape#{sessionvars%urlparameter}">#basename|escape#</a>'
-filerevision = filerevision.tmpl
-fileannotate = fileannotate.tmpl
-filediff = filediff.tmpl
-filelog = filelog.tmpl
-fileline = '<div class="parity#parity#"><a class="lineno" href="##lineid#" id="#lineid#">#linenumber#</a>#line|escape#</div>'
-filelogentry = filelogentry.tmpl
-annotateline = '<tr class="parity#parity#"><td class="annotate"><a href="#url#annotate/#node|short#/#file|urlescape#{sessionvars%urlparameter}#l{targetline}" title="{node|short}: {desc|escape|firstline}">#author|user#@#rev#</a></td><td><a class="lineno" href="##lineid#" id="#lineid#">#linenumber#</a></td><td><pre>#line|escape#</pre></td></tr>'
-difflineplus = '<span class="plusline"><a class="lineno" href="##lineid#" id="#lineid#">#linenumber#</a>#line|escape#</span>'
-difflineminus = '<span class="minusline"><a class="lineno" href="##lineid#" id="#lineid#">#linenumber#</a>#line|escape#</span>'
-difflineat = '<span class="atline"><a class="lineno" href="##lineid#" id="#lineid#">#linenumber#</a>#line|escape#</span>'
-diffline = '<a class="lineno" href="##lineid#" id="#lineid#">#linenumber#</a>#line|escape#'
-changelogparent = '<tr><th class="parent">parent #rev#:</th><td class="parent"><a href="#url#rev/#node|short#{sessionvars%urlparameter}">#node|short#</a></td></tr>'
-changesetparent = '<tr><th class="parent">parent #rev#:</th><td class="parent"><a href="#url#rev/#node|short#{sessionvars%urlparameter}">#node|short#</a></td></tr>'
-filerevparent = '<tr><td class="metatag">parent:</td><td><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{rename%filerename}{node|short}</a></td></tr>'
-filerename = '{file|escape}@'
-filelogrename = '<tr><th>base:</th><td><a href="#url#file/#node|short#/#file|urlescape#{sessionvars%urlparameter}">#file|escape#@#node|short#</a></td></tr>'
-fileannotateparent = '<tr><td class="metatag">parent:</td><td><a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{rename%filerename}{node|short}</a></td></tr>'
-changesetchild = '<tr><th class="child">child #rev#:</th><td class="child"><a href="#url#rev/#node|short#{sessionvars%urlparameter}">#node|short#</a></td></tr>'
-changelogchild = '<tr><th class="child">child #rev#:</th><td class="child"><a href="#url#rev/#node|short#{sessionvars%urlparameter}">#node|short#</a></td></tr>'
-filerevchild = '<tr><td class="metatag">child:</td><td><a href="#url#file/#node|short#/#file|urlescape#{sessionvars%urlparameter}">#node|short#</a></td></tr>'
-fileannotatechild = '<tr><td class="metatag">child:</td><td><a href="#url#annotate/#node|short#/#file|urlescape#{sessionvars%urlparameter}">#node|short#</a></td></tr>'
-tags = tags.tmpl
-tagentry = '<li class="tagEntry parity#parity#"><tt class="node">#node#</tt> <a href="#url#rev/#node|short#{sessionvars%urlparameter}">#tag|escape#</a></li>'
-diffblock = '<pre class="parity#parity#">#lines#</pre>'
-changelogtag = '<tr><th class="tag">tag:</th><td class="tag">#tag|escape#</td></tr>'
-changesettag = '<tr><th class="tag">tag:</th><td class="tag">#tag|escape#</td></tr>'
-filediffparent = '<tr><th class="parent">parent #rev#:</th><td class="parent"><a href="#url#rev/#node|short#{sessionvars%urlparameter}">#node|short#</a></td></tr>'
-filelogparent = '<tr><th>parent #rev#:</th><td><a href="#url#file/#node|short#/#file|urlescape#{sessionvars%urlparameter}">#node|short#</a></td></tr>'
-filediffchild = '<tr><th class="child">child #rev#:</th><td class="child"><a href="#url#rev/#node|short#{sessionvars%urlparameter}">#node|short#</a></td></tr>'
-filelogchild = '<tr><th>child #rev#:</th><td><a href="#url#file/#node|short#/#file|urlescape#{sessionvars%urlparameter}">#node|short#</a></td></tr>'
-indexentry = '<tr class="parity#parity#"><td><a href="#url#{sessionvars%urlparameter}">#name|escape#</a></td><td>#description#</td><td>#contact|obfuscate#</td><td class="age">#lastchange|age# ago</td><td class="indexlinks"><a href="#url#rss-log">RSS</a> <a href="#url#atom-log">Atom</a> #archives%archiveentry#</td></tr>'
-index = index.tmpl
-archiveentry = '<a href="#url#archive/#node|short##extension|urlescape#">#type|escape#</a> '
-notfound = notfound.tmpl
-error = error.tmpl
-urlparameter = '#separator##name#=#value|urlescape#'
-hiddenformentry = '<input type="hidden" name="#name#" value="#value|escape#" />'
--- a/templates/monoblue/graph.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ b/templates/monoblue/graph.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -59,7 +59,7 @@
 
     var revlink = '<li style="_STYLE"><span class="desc">';
     revlink += '<a href="{url}rev/_NODEID{sessionvars%urlparameter}" title="_NODEID">_DESC</a>';
-    revlink += '</span><span class="info">_DATE ago, by _USER</span></li>';
+    revlink += '</span>_TAGS<span class="info">_DATE ago, by _USER</span></li>';
 
     graph.vertex = function(x, y, color, parity, cur) {
 
@@ -79,6 +79,26 @@
         item = item.replace(/_USER/, cur[4]);
         item = item.replace(/_DATE/, cur[5]);
 
+        var tagspan = '';
+        if (cur[7].length || (cur[6][0] != 'default' || cur[6][1])) {
+            tagspan = '<span class="logtags">';
+            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') {
+                tagspan += '<span class="inbranchtag" title="' + cur[6][0] + '">';
+                tagspan += cur[6][0] + '</span> ';
+            }
+            if (cur[7].length) {
+                for (var t in cur[7]) {
+                    var tag = cur[7][t];
+                    tagspan += '<span class="tagtag">' + tag + '</span> ';
+                }
+            }
+            tagspan += '</span>';
+        }
+
+        item = item.replace(/_TAGS/, tagspan); 
         return [bg, item];
 
     }
--- a/templates/monoblue/index.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ b/templates/monoblue/index.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -1,26 +1,39 @@
 #header#
     <title>#repo|escape#: Mercurial repositories index</title>
 </head>
-<body>
-
-<div class="page_header">
-    <a href="http://www.selenic.com/mercurial/" title="Mercurial" style="float: right;">Mercurial</a>
-    Repositories list
-</div>
 
-<table cellspacing="0">
-    <tr>
-        <td><a href="?sort=#sort_name#">Name</a></td>
-        <td><a href="?sort=#sort_description#">Description</a></td>
-        <td><a href="?sort=#sort_contact#">Contact</a></td>
-        <td><a href="?sort=#sort_lastchange#">Last change</a></td>
-        <td>&nbsp;</td>
-        <td>&nbsp;</td>
-    </tr>
-    #entries%indexentry#
-</table>
-<div class="page-footer">
-#motd#
+<body>
+<div id="container">
+    <div class="page-header">
+        <h1>Mercurial Repositories</h1>
+        <ul class="page-nav">
+        </ul>
+    </div>
+    
+    <table cellspacing="0">
+        <tr>
+            <td><a href="?sort=#sort_name#">Name</a></td>
+            <td><a href="?sort=#sort_description#">Description</a></td>
+            <td><a href="?sort=#sort_contact#">Contact</a></td>
+            <td><a href="?sort=#sort_lastchange#">Last change</a></td>
+            <td>&nbsp;</td>
+            <td>&nbsp;</td>
+        </tr>
+        #entries%indexentry#
+    </table>
+    <div class="page-footer">
+        {motd}
+    </div>
+
+    <div id="powered-by">
+        <p><a href="http://www.selenic.com/mercurial/" title="Mercurial"><img src="#staticurl#hglogo.png" width=75 height=90 border=0 alt="mercurial"></a></p>
+    </div>
+
+    <div id="corner-top-left"></div>
+    <div id="corner-top-right"></div>
+    <div id="corner-bottom-left"></div>
+    <div id="corner-bottom-right"></div>
+
 </div>
 </body>
 </html>
--- a/templates/notfound.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,12 +0,0 @@
-#header#
-<title>Mercurial repository not found</title>
-</head>
-<body>
-
-<h2>Mercurial repository not found</h2>
-
-The specified repository "#repo|escape#" is unknown, sorry.
-
-Please go back to the main repository list page.
-
-#footer#
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/paper/changeset.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,70 @@
+{header}
+<title>{repo|escape}: {node|short}</title>
+</head>
+<body>
+<div class="container">
+<div class="menu">
+<div class="logo">
+<a href="http://www.selenic.com/mercurial/">
+<img src="{staticurl}hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
+</div>
+<ul>
+ <li><a href="{url}shortlog/{node|short}{sessionvars%urlparameter}">log</a></li>
+ <li><a href="{url}graph/{node|short}{sessionvars%urlparameter}">graph</a></li>
+ <li><a href="{url}tags{sessionvars%urlparameter}">tags</a></li>
+</ul>
+<ul>
+ <li class="active">changeset</li>
+ <li><a href="{url}raw-rev/{node|short}{sessionvars%urlparameter}">raw</a></li>
+ <li><a href="{url}file/{node|short}{sessionvars%urlparameter}">browse</a></li>
+</ul>
+<ul>
+ {archives%archiveentry}
+</ul>
+</div>
+
+<div class="main">
+
+<h2><a href="{url}{sessionvars%urlparameter}">{repo|escape}</a></h2>
+<h3>changeset {rev}:{node|short} {changesetbranch%changelogbranchname} {changesettag}</h3>
+
+<form class="search" action="{url}log">
+{sessionvars%hiddenformentry}
+<p><input name="rev" id="search1" type="text" size="30"></p>
+<span>find changesets by author, revision,
+files, or words in the commit message</span>
+</form>
+
+<div class="description">{desc|strip|escape|addbreaks}</div>
+
+<table id="changesetEntry">
+<tr>
+ <th class="author">author</th>
+ <td class="author">{author|obfuscate}</td>
+</tr>
+<tr>
+ <th class="date">date</th>
+ <td class="date">{date|date} ({date|age} ago)</td></tr>
+<tr>
+ <th class="author">parents</th>
+ <td class="author">{parent%changesetparent}</td>
+</tr>
+<tr>
+ <th class="author">children</th>
+ <td class="author">{child%changesetchild}</td>
+</tr>
+<tr>
+ <th class="files">files</th>
+ <td class="files">{files}</td>
+</tr>
+</table>
+
+<div class="overflow">
+<div class="sourcefirst">   line diff</div>
+
+{diff}
+</div>
+
+</div>
+</div>
+{footer}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/paper/error.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,42 @@
+{header}
+<title>{repo|escape}: error</title>
+</head>
+<body>
+
+<div class="container">
+<div class="menu">
+<div class="logo">
+<a href="http://www.selenic.com/mercurial/">
+<img src="{staticurl}hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
+</div>
+<ul>
+<li><a href="{url}shortlog{sessionvars%urlparameter}">log</a></li>
+<li><a href="{url}graph{sessionvars%urlparameter}">graph</a></li>
+<li><a href="{url}tags{sessionvars%urlparameter}">tags</a></li>
+</ul>
+</div>
+
+<div class="main">
+
+<h2><a href="{url}{sessionvars%urlparameter}">{repo|escape}</a></h2>
+<h3>error</h3>
+
+<form class="search" action="{url}log">
+{sessionvars%hiddenformentry}
+<p><input name="rev" id="search1" type="text" size="30"></p>
+<span>find changesets by author, revision,
+files, or words in the commit message</span>
+</form>
+
+<div class="description">
+<p>
+An error occurred while processing your request:
+</p>
+<p>
+{error|escape}
+</p>
+</div>
+</div>
+</div>
+
+{footer}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/paper/fileannotate.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,78 @@
+{header}
+<title>{repo|escape}: {file|escape} annotate</title>
+</head>
+<body>
+
+<div class="container">
+<div class="menu">
+<div class="logo">
+<a href="http://www.selenic.com/mercurial/">
+<img src="{staticurl}hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
+</div>
+<ul>
+<li><a href="{url}shortlog/{node|short}{sessionvars%urlparameter}">log</a></li>
+<li><a href="{url}graph/{node|short}{sessionvars%urlparameter}">graph</a></li>
+<li><a href="{url}tags{sessionvars%urlparameter}">tags</a></li>
+</ul>
+
+<ul>
+<li><a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a></li>
+<li><a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}">browse</a></li>
+</ul>
+<ul>
+<li><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a></li>
+<li><a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a></li>
+<li class="active">annotate</li>
+<li><a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file log</a></li>
+<li><a href="{url}raw-annotate/{node|short}/{file|urlescape}">raw</a></li>
+</ul>
+</div>
+
+<div class="main">
+<h2><a href="{url}{sessionvars%urlparameter}">{repo|escape}</a></h2>
+<h3>annotate {file|escape} @ {rev}:{node|short}</h3>
+
+<form class="search" action="{url}log">
+{sessionvars%hiddenformentry}
+<p><input name="rev" id="search1" type="text" size="30"></p>
+<span>find changesets by author, revision,
+files, or words in the commit message</span>
+</form>
+
+<div class="description">{desc|strip|escape|addbreaks}</div>
+
+<table id="changesetEntry">
+<tr>
+ <th class="author">author</th>
+ <td class="author">{author|obfuscate}</td>
+</tr>
+<tr>
+ <th class="date">date</th>
+ <td class="date">{date|date} ({date|age} ago)</td>
+</tr>
+<tr>
+ <th class="author">parents</th>
+ <td class="author">{parent%filerevparent}</td>
+</tr>
+<tr>
+ <th class="author">children</th>
+ <td class="author">{child%filerevchild}</td>
+</tr>
+{changesettag}
+</table>
+
+<br/>
+
+<div class="overflow">
+<table class="bigtable">
+<tr>
+ <th class="annotate">rev</th>
+ <th class="line">&nbsp;&nbsp;line source</th>
+</tr>
+{annotate%annotateline}
+</table>
+</div>
+</div>
+</div>
+
+{footer}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/paper/filediff.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,71 @@
+{header}
+<title>{repo|escape}: {file|escape} diff</title>
+</head>
+<body>
+
+<div class="container">
+<div class="menu">
+<div class="logo">
+<a href="http://www.selenic.com/mercurial/">
+<img src="{staticurl}hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
+</div>
+<ul>
+<li><a href="{url}shortlog/{node|short}{sessionvars%urlparameter}">log</a></li>
+<li><a href="{url}graph/{node|short}{sessionvars%urlparameter}">graph</a></li>
+<li><a href="{url}tags{sessionvars%urlparameter}">tags</a></li>
+</ul>
+<ul>
+<li><a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a></li>
+<li><a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}">browse</a></li>
+</ul>
+<ul>
+<li><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a></li>
+<li class="active">diff</li>
+<li><a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a></li>
+<li><a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file log</a></li>
+<li><a href="{url}raw-file/{node|short}/{file|urlescape}">raw</a></li>
+</ul>
+</div>
+
+<div class="main">
+<h2><a href="{url}{sessionvars%urlparameter}">{repo|escape}</a></h2>
+<h3>diff {file|escape} @ {rev}:{node|short}</h3>
+
+<form class="search" action="{url}log">
+{sessionvars%hiddenformentry}
+<p><input name="rev" id="search1" type="text" size="30"></p>
+<span>find changesets by author, revision,
+files, or words in the commit message</span>
+</form>
+
+<div class="description">{desc|strip|escape|addbreaks}</div>
+
+<table id="changesetEntry">
+<tr>
+ <th>author</th>
+ <td>{author|obfuscate}</td>
+</tr>
+<tr>
+ <th>date</th>
+ <td>{date|date} ({date|age} ago)</td>
+</tr>
+<tr>
+ <th>parents</th>
+ <td>{parent%filerevparent}</td>
+</tr>
+<tr>
+ <th>children</th>
+ <td>{child%filerevchild}</td>
+</tr>
+{changesettag}
+</table>
+
+<div class="overflow">
+<div class="sourcefirst">   line diff</div>
+
+{diff}
+</div>
+</div>
+</div>
+
+{footer}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/paper/filelog.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,59 @@
+{header}
+<title>{repo|escape}: {file|escape} history</title>
+<link rel="alternate" type="application/atom+xml"
+   href="{url}atom-log/tip/{file|urlescape}" title="Atom feed for {repo|escape}:{file}">
+<link rel="alternate" type="application/rss+xml"
+   href="{url}rss-log/tip/{file|urlescape}" title="RSS feed for {repo|escape}:{file}">
+</head>
+<body>
+
+<div class="container">
+<div class="menu">
+<div class="logo">
+<a href="http://www.selenic.com/mercurial/">
+<img src="{staticurl}hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
+</div>
+<ul>
+<li><a href="{url}shortlog/{node|short}{sessionvars%urlparameter}">log</a></li>
+<li><a href="{url}graph/{node|short}{sessionvars%urlparameter}">graph</a></li>
+<li><a href="{url}tags{sessionvars%urlparameter}">tags</a></li>
+</ul>
+<ul>
+<li><a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a></li>
+<li><a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}">browse</a></li>
+</ul>
+<ul>
+<li><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a></li>
+<li><a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a></li>
+<li><a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a></li>
+<li class="active">file log</li>
+<li><a href="{url}raw-file/{node|short}/{file|urlescape}">raw</a></li>
+</ul>
+</div>
+
+<div class="main">
+<h2><a href="{url}{sessionvars%urlparameter}">{repo|escape}</a></h2>
+<h3>log {file|escape}</h3>
+
+<form class="search" action="{url}log">
+{sessionvars%hiddenformentry}
+<p><input name="rev" id="search1" type="text" size="30"></p>
+<span>find changesets by author, revision,
+files, or words in the commit message</span>
+</form>
+
+<div class="navigate">{nav%filenaventry}</div>
+
+<table class="bigtable">
+ <tr>
+  <th class="age">age</th>
+  <th class="author">author</th>
+  <th class="description">description</th>
+ </tr>
+{entries%filelogentry}
+</table>
+
+</div>
+</div>
+
+{footer}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/paper/filelogentry.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,5 @@
+ <tr class="parity{parity}">
+  <td class="age">{date|age}</td>
+  <td class="author">{author|person}</td>
+  <td class="description"><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{desc|strip|firstline|escape}</a>{inbranch%changelogbranchname}{branches%changelogbranchhead}{tags%changelogtag}</td>
+ </tr>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/paper/filerevision.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,71 @@
+{header}
+<title>{repo|escape}: {node|short} {file|escape}</title>
+</head>
+<body>
+
+<div class="container">
+<div class="menu">
+<div class="logo">
+<a href="http://www.selenic.com/mercurial/">
+<img src="{staticurl}hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
+</div>
+<ul>
+<li><a href="{url}shortlog/{node|short}{sessionvars%urlparameter}">log</a></li>
+<li><a href="{url}graph/{node|short}{sessionvars%urlparameter}">graph</a></li>
+<li><a href="{url}tags{sessionvars%urlparameter}">tags</a></li>
+</ul>
+<ul>
+<li><a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a></li>
+<li><a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}">browse</a></li>
+</ul>
+<ul>
+<li class="active">file</li>
+<li><a href="{url}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a></li>
+<li><a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a></li>
+<li><a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file log</a></li>
+<li><a href="{url}raw-file/{node|short}/{file|urlescape}">raw</a></li>
+</ul>
+</div>
+
+<div class="main">
+<h2><a href="{url}{sessionvars%urlparameter}">{repo|escape}</a></h2>
+<h3>view {file|escape} @ {rev}:{node|short}</h3>
+
+<form class="search" action="{url}log">
+{sessionvars%hiddenformentry}
+<p><input name="rev" id="search1" type="text" size="30"></p>
+<span>find changesets by author, revision,
+files, or words in the commit message</span>
+</form>
+
+<div class="description">{desc|strip|escape|addbreaks}</div>
+
+<table id="changesetEntry">
+<tr>
+ <th class="author">author</th>
+ <td class="author">{author|obfuscate}</td>
+</tr>
+<tr>
+ <th class="date">date</th>
+ <td class="date">{date|date} ({date|age} ago)</td>
+</tr>
+<tr>
+ <th class="author">parents</th>
+ <td class="author">{parent%filerevparent}</td>
+</tr>
+<tr>
+ <th class="author">children</th>
+ <td class="author">{child%filerevchild}</td>
+</tr>
+{changesettag}
+</table>
+
+<div class="overflow">
+<div class="sourcefirst"> line source</div>
+{text%fileline}
+<div class="sourcelast"></div>
+</div>
+</div>
+</div>
+
+{footer}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/paper/footer.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,4 @@
+{motd}
+
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/paper/graph.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,131 @@
+{header}
+<title>{repo|escape}: revision graph</title>
+<link rel="alternate" type="application/atom+xml"
+   href="{url}atom-log" title="Atom feed for {repo|escape}: log">
+<link rel="alternate" type="application/rss+xml"
+   href="{url}rss-log" title="RSS feed for {repo|escape}: log">
+<!--[if IE]><script type="text/javascript" src="{staticurl}excanvas.js"></script><![endif]-->
+</head>
+<body>
+
+<div class="container">
+<div class="menu">
+<div class="logo">
+<a href="http://www.selenic.com/mercurial/">
+<img src="{staticurl}hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
+</div>
+<ul>
+<li><a href="{url}shortlog/{node|short}{sessionvars%urlparameter}">log</a></li>
+<li class="active">graph</li>
+<li><a href="{url}tags{sessionvars%urlparameter}">tags</a></li>
+</ul>
+<ul>
+<li><a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a></li>
+<li><a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}">browse</a></li>
+</ul>
+</div>
+
+<div class="main">
+<h2><a href="{url}{sessionvars%urlparameter}">{repo|escape}</a></h2>
+<h3>graph</h3>
+
+<form class="search" action="{url}log">
+{sessionvars%hiddenformentry}
+<p><input name="rev" id="search1" type="text" size="30"></p>
+<span>find changesets by author, revision,
+files, or words in the commit message</span>
+</form>
+
+<div class="navigate">
+<a href="{url}graph/{rev}{lessvars%urlparameter}">less</a>
+<a href="{url}graph/{rev}{morevars%urlparameter}">more</a>
+| rev {rev}: {changenav%navgraphentry}
+</div>
+
+<noscript>The revision graph only works with JavaScript-enabled browsers.</noscript>
+
+<div id="wrapper">
+<ul id="nodebgs"></ul>
+<canvas id="graph" width="224" height="{canvasheight}"></canvas>
+<ul id="graphnodes"></ul>
+</div>
+
+<script type="text/javascript" src="{staticurl}graph.js"></script>
+<script type="text/javascript">
+<!-- hide script content
+
+var data = {jsdata|json};
+var graph = new Graph();
+graph.scale({bg_height});
+
+graph.edge = function(x0, y0, x1, y1, color) {
+	
+	this.setColor(color, 0.0, 0.65);
+	this.ctx.beginPath();
+	this.ctx.moveTo(x0, y0);
+	this.ctx.lineTo(x1, y1);
+	this.ctx.stroke();
+	
+}
+
+var revlink = '<li style="_STYLE"><span class="desc">';
+revlink += '<a href="{url}rev/_NODEID{sessionvars%urlparameter}" title="_NODEID">_DESC</a>';
+revlink += '</span>_TAGS<span class="info">_DATE ago, by _USER</span></li>';
+
+graph.vertex = function(x, y, color, parity, cur) {
+	
+	this.ctx.beginPath();
+	color = this.setColor(color, 0.25, 0.75);
+	this.ctx.arc(x, y, radius, 0, Math.PI * 2, true);
+	this.ctx.fill();
+	
+	var bg = '<li class="bg parity' + parity + '"></li>';
+	var left = (this.columns + 1) * this.bg_height;
+	var nstyle = 'padding-left: ' + left + 'px;';
+	var item = revlink.replace(/_STYLE/, nstyle);
+	item = item.replace(/_PARITY/, 'parity' + parity);
+	item = item.replace(/_NODEID/, cur[0]);
+	item = item.replace(/_NODEID/, cur[0]);
+	item = item.replace(/_DESC/, cur[3]);
+	item = item.replace(/_USER/, cur[4]);
+	item = item.replace(/_DATE/, cur[5]);
+
+	var tagspan = '';
+	if (cur[7].length || (cur[6][0] != 'default' || cur[6][1])) {
+		tagspan = '<span class="logtags">';
+		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') {
+			tagspan += '<span class="branchname" title="' + cur[6][0] + '">';
+			tagspan += cur[6][0] + '</span> ';
+		}
+		if (cur[7].length) {
+			for (var t in cur[7]) {
+				var tag = cur[7][t];
+				tagspan += '<span class="tag">' + tag + '</span> ';
+			}
+		}
+		tagspan += '</span>';
+	}
+	
+	item = item.replace(/_TAGS/, tagspan);
+	return [bg, item];
+	
+}
+
+graph.render(data);
+
+// stop hiding script -->
+</script>
+
+<div class="navigate">
+<a href="{url}graph/{rev}{lessvars%urlparameter}">less</a>
+<a href="{url}graph/{rev}{morevars%urlparameter}">more</a>
+| rev {rev}: {changenav%navgraphentry}
+</div>
+
+</div>
+</div>
+
+{footer}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/paper/index.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,26 @@
+{header}
+<title>Mercurial repositories index</title>
+</head>
+<body>
+
+<div class="container">
+<div class="menu">
+<a href="http://www.selenic.com/mercurial/">
+<img src="{staticurl}hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
+</div>
+<div class="main">
+<h2>Mercurial Repositories</h2>
+
+<table class="bigtable">
+    <tr>
+        <th><a href="?sort={sort_name}">Name</a></th>
+        <th><a href="?sort={sort_description}">Description</a></th>
+        <th><a href="?sort={sort_contact}">Contact</a></th>
+        <th><a href="?sort={sort_lastchange}">Last change</a></th>
+        <th>&nbsp;</th>
+    </tr>
+    {entries%indexentry}
+</table>
+</div>
+</div>
+{footer}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/paper/manifest.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,53 @@
+{header}
+<title>{repo|escape}: {node|short} {path|escape}</title>
+</head>
+<body>
+
+<div class="container">
+<div class="menu">
+<div class="logo">
+<a href="http://www.selenic.com/mercurial/">
+<img src="{staticurl}hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
+</div>
+<ul>
+<li><a href="{url}shortlog/{node|short}{sessionvars%urlparameter}">log</a></li>
+<li><a href="{url}graph/{node|short}{sessionvars%urlparameter}">graph</a></li>
+<li><a href="{url}tags{sessionvars%urlparameter}">tags</a></li>
+</ul>
+<ul>
+<li><a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a></li>
+<li class="active">browse</li>
+</ul>
+<ul>
+{archives%archiveentry}
+</ul>
+</div>
+
+<div class="main">
+<h2><a href="{url}{sessionvars%urlparameter}">{repo|escape}</a></h2>
+<h3>directory {path|escape} @ {rev}:{node|short} {tags%changelogtag}</h3>
+
+<form class="search" action="{url}log">
+{sessionvars%hiddenformentry}
+<p><input name="rev" id="search1" type="text" size="30"></p>
+<span>find changesets by author, revision,
+files, or words in the commit message</span>
+</form>
+
+<table class="bigtable">
+<tr>
+  <th class="name">name</th>
+  <th class="size">size</th>
+  <th class="permissions">permissions</th>
+</tr>
+<tr class="fileline parity{upparity}">
+  <td class="name"><a href="{url}file/{node|short}{up|urlescape}{sessionvars%urlparameter}">[up]</a></td>
+  <td class="size"></td>
+  <td class="permissions">drwxr-xr-x</td>
+</tr>
+{dentries%direntry}
+{fentries%fileentry}
+</table>
+</div>
+</div>
+{footer}
--- a/templates/paper/map	Sun Dec 07 19:33:26 2008 +0100
+++ b/templates/paper/map	Sun Dec 07 19:34:07 2008 +0100
@@ -2,13 +2,13 @@
 
 mimetype = 'text/html; charset={encoding}'
 header = header.tmpl
-footer = ../coal/footer.tmpl
-search = ../coal/search.tmpl
+footer = footer.tmpl
+search = search.tmpl
 
-changelog = ../coal/shortlog.tmpl
-shortlog = ../coal/shortlog.tmpl
-shortlogentry = ../coal/shortlogentry.tmpl
-graph = ../coal/graph.tmpl
+changelog = shortlog.tmpl
+shortlog = shortlog.tmpl
+shortlogentry = shortlogentry.tmpl
+graph = graph.tmpl
 
 naventry = '<a href="{url}log/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
 navshortentry = '<a href="{url}shortlog/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
@@ -18,28 +18,28 @@
 filenodelink = '<a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{file|escape}</a> '
 filenolink = '{file|escape} '
 fileellipses = '...'
-changelogentry = ../coal/shortlogentry.tmpl
-searchentry = ../coal/shortlogentry.tmpl
-changeset = ../coal/changeset.tmpl
-manifest = ../coal/manifest.tmpl
+changelogentry = shortlogentry.tmpl
+searchentry = shortlogentry.tmpl
+changeset = changeset.tmpl
+manifest = manifest.tmpl
 
 direntry = '<tr class="fileline parity{parity}"><td class="name"><a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}"><img src="{staticurl}coal-folder.png"> {basename|escape}/</a> <a href="{url}file/{node|short}{path|urlescape}/{emptydirs|urlescape}{sessionvars%urlparameter}">{emptydirs|escape}</a><td class="size"></td><td class="permissions">drwxr-xr-x</td></tr>'
 fileentry = '<tr class="fileline parity{parity}"><td class="filename"><a href="{url}file/{node|short}/{file|urlescape}#l1{sessionvars%urlparameter}"><img src="{staticurl}coal-file.png"> {basename|escape}</a></td><td class="size">{size}</td><td class="permissions">{permissions|permissions}</td></tr>'
 
-filerevision = ../coal/filerevision.tmpl
-fileannotate = ../coal/fileannotate.tmpl
-filediff = ../coal/filediff.tmpl
-filelog = ../coal/filelog.tmpl
-fileline = '<tr class="parity{parity}"><td class="lineno"><a href="#{lineid}" id="{lineid}">{linenumber}</a></td><td class="source">{line|escape}</td></tr>'
-filelogentry = ../coal/filelogentry.tmpl
+filerevision = filerevision.tmpl
+fileannotate = fileannotate.tmpl
+filediff = filediff.tmpl
+filelog = filelog.tmpl
+fileline = '<div class="parity{parity} source"><a href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</div>'
+filelogentry = filelogentry.tmpl
 
-annotateline = '<tr class="parity{parity}"><td class="annotate"><a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}#{targetline}" title="{node|short}: {desc|escape|firstline}">{author|user}@{rev}</a></td><td class="lineno"><a href="#{lineid}" id="{lineid}">{linenumber}</a></td><td class="source">{line|escape}</td></tr>'
+annotateline = '<tr class="parity{parity}"><td class="annotate"><a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}#{targetline}" title="{node|short}: {desc|escape|firstline}">{author|user}@{rev}</a></td><td class="source"><a href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}</td></tr>'
 
-diffblock = '<table class="bigtable parity{parity}">{lines}</table>'
-difflineplus = '<tr><td class="lineno"><a href="#{lineid}" id="{lineid}">{linenumber}</a></td><td class="source plusline">{line|escape}</td></tr>'
-difflineminus = '<tr><td class="lineno"><a href="#{lineid}" id="{lineid}">{linenumber}</a></td><td class="source minusline">{line|escape}</td></tr>'
-difflineat = '<tr><td class="lineno"><a href="#{lineid}" id="{lineid}">{linenumber}</a></td><td class="source atline">{line|escape}</td></tr>'
-diffline = '<tr><td class="lineno"><a href="#{lineid}" id="{lineid}">{linenumber}</a></td><td class="source">{line|escape}</td></tr>'
+diffblock = '<div class="source bottomline parity{parity}">{lines}</div>'
+difflineplus = '<a href="#{lineid}" id="{lineid}">{linenumber}</a> <span class="plusline">{line|escape}</span>'
+difflineminus = '<a href="#{lineid}" id="{lineid}">{linenumber}</a> <span class="minusline">{line|escape}</span>'
+difflineat = '<a href="#{lineid}" id="{lineid}">{linenumber}</a> <span class="atline">{line|escape}</span>'
+diffline = '<a href="#{lineid}" id="{lineid}">{linenumber}</a> {line|escape}'
 
 changelogparent = '<tr><th class="parent">parent {rev}:</th><td class="parent"><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a></td></tr>'
 
@@ -54,20 +54,21 @@
 changesetchild = '<a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a>'
 changelogchild = '<tr><th class="child">child</th><td class="child"><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a></td></tr>'
 fileannotatechild = '<tr><td class="metatag">child:</td><td><a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></td></tr>'
-tags = ../coal/tags.tmpl
+tags = tags.tmpl
 tagentry = '<tr class="tagEntry parity{parity}"><td><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{tag|escape}</a></td><td class="node">{node|short}</td></tr>'
-changelogtag = '<tr><th class="tag">tag:</th><td class="tag">{tag|escape}</td></tr>'
 changelogtag = '<span class="tag">{name|escape}</span> '
 changesettag = '<span class="tag">{tag|escape}</span> '
+changelogbranchhead = '<span class="branchhead">{name|escape}</span> '
+changelogbranchname = '<span class="branchname">{name|escape}</span> ' 
 filediffparent = '<tr><th class="parent">parent {rev}:</th><td class="parent"><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a></td></tr>'
 filelogparent = '<tr><th>parent {rev}:</th><td><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></td></tr>'
 filediffchild = '<tr><th class="child">child {rev}:</th><td class="child"><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{node|short}</a></td></tr>'
 filelogchild = '<tr><th>child {rev}:</th><td><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{node|short}</a></td></tr>'
 indexentry = '<tr class="parity{parity}"><td><a href="{url}{sessionvars%urlparameter}">{name|escape}</a></td><td>{description}</td><td>{contact|obfuscate}</td><td class="age">{lastchange|age} ago</td><td class="indexlinks">{archives%indexarchiveentry}</td></tr>\n'
 indexarchiveentry = '<a href="{url}archive/{node|short}{extension|urlescape}">&nbsp;&darr;{type|escape}</a>'
-index = ../coal/index.tmpl
+index = index.tmpl
 archiveentry = '<li><a href="{url}archive/{node|short}{extension|urlescape}">{type|escape}</a></li>'
-notfound = ../coal/notfound.tmpl
-error = ../coal/error.tmpl
+notfound = notfound.tmpl
+error = error.tmpl
 urlparameter = '{separator}{name}={value|urlescape}'
 hiddenformentry = '<input type="hidden" name="{name}" value="{value|escape}" />'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/paper/notfound.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,12 @@
+{header}
+<title>Mercurial repository not found</title>
+</head>
+<body>
+
+<h2>Mercurial repository not found</h2>
+
+The specified repository "{repo|escape}" is unknown, sorry.
+
+Please go back to the main repository list page.
+
+{footer}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/paper/search.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,42 @@
+{header}
+<title>{repo|escape}: searching for {query|escape}</title>
+</head>
+<body>
+
+<div class="container">
+<div class="menu">
+<div class="logo">
+<a href="http://www.selenic.com/mercurial/">
+<img src="{staticurl}hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
+</div>
+<ul>
+<li><a href="{url}shortlog{sessionvars%urlparameter}">log</a></li>
+<li><a href="{url}graph{sessionvars%urlparameter}">graph</a></li>
+<li><a href="{url}tags{sessionvars%urlparameter}">tags</a></li>
+</ul>
+</div>
+
+<div class="main">
+<h2><a href="{url}{sessionvars%urlparameter}">{repo|escape}</a></h2>
+<h3>searching for '{query|escape}'</h3>
+
+<form class="search" action="{url}log">
+{sessionvars%hiddenformentry}
+<p><input name="rev" id="search1" type="text" size="30"></p>
+<span>find changesets by author, revision,
+files, or words in the commit message</span>
+</form>
+
+<table class="bigtable">
+ <tr>
+  <th class="age">age</th>
+  <th class="author">author</th>
+  <th class="description">description</th>
+ </tr>
+{entries}
+</table>
+
+</div>
+</div>
+
+{footer}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/paper/shortlog.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,56 @@
+{header}
+<title>{repo|escape}: log</title>
+<link rel="alternate" type="application/atom+xml"
+   href="{url}atom-log" title="Atom feed for {repo|escape}">
+<link rel="alternate" type="application/rss+xml"
+   href="{url}rss-log" title="RSS feed for {repo|escape}">
+</head>
+<body>
+
+<div class="container">
+<div class="menu">
+<div class="logo">
+<a href="http://www.selenic.com/mercurial/">
+<img src="{staticurl}hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
+</div>
+<ul>
+<li class="active">log</li>
+<li><a href="{url}graph/{node|short}{sessionvars%urlparameter}">graph</a></li>
+<li><a href="{url}tags{sessionvars%urlparameter}">tags</a></li>
+</ul>
+<ul>
+<li><a href="{url}rev/{node|short}{sessionvars%urlparameter}">changeset</a></li>
+<li><a href="{url}file/{node|short}{path|urlescape}{sessionvars%urlparameter}">browse</a></li>
+</ul>
+<ul>
+{archives%archiveentry}
+</ul>
+</div>
+
+<div class="main">
+<h2><a href="{url}{sessionvars%urlparameter}">{repo|escape}</a></h2>
+<h3>log</h3>
+
+<form class="search" action="{url}log">
+{sessionvars%hiddenformentry}
+<p><input name="rev" id="search1" type="text" size="30"></p>
+<span>find changesets by author, revision,
+files, or words in the commit message</span>
+</form>
+
+<div class="navigate">rev {rev}: {changenav%navshortentry}</div>
+
+<table class="bigtable">
+ <tr>
+  <th class="age">age</th>
+  <th class="author">author</th>
+  <th class="description">description</th>
+ </tr>
+{entries%shortlogentry}
+</table>
+
+<div class="navigate">rev {rev}: {changenav%navshortentry}</div>
+</div>
+</div>
+
+{footer}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/paper/shortlogentry.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,5 @@
+ <tr class="parity{parity}">
+  <td class="age">{date|age}</td>
+  <td class="author">{author|person}</td>
+  <td class="description"><a href="{url}rev/{node|short}{sessionvars%urlparameter}">{desc|strip|firstline|escape}</a>{inbranch%changelogbranchname}{branches%changelogbranchhead}{tags%changelogtag}</td>
+ </tr>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/paper/tags.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,44 @@
+{header}
+<title>{repo|escape}: tags</title>
+<link rel="alternate" type="application/atom+xml"
+   href="{url}atom-tags" title="Atom feed for {repo|escape}: tags">
+<link rel="alternate" type="application/rss+xml"
+   href="{url}rss-tags" title="RSS feed for {repo|escape}: tags">
+</head>
+<body>
+
+<div class="container">
+<div class="menu">
+<div class="logo">
+<a href="http://www.selenic.com/mercurial/">
+<img src="{staticurl}hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
+</div>
+<ul>
+<li><a href="{url}shortlog{sessionvars%urlparameter}">log</a></li>
+<li><a href="{url}graph{sessionvars%urlparameter}">graph</a></li>
+<li class="active">tags</li>
+</ul>
+</div>
+
+<div class="main">
+<h2><a href="{url}{sessionvars%urlparameter}">{repo|escape}</a></h2>
+<h3>tags</h3>
+
+<form class="search" action="{url}log">
+{sessionvars%hiddenformentry}
+<p><input name="rev" id="search1" type="text" size="30"></p>
+<span>find changesets by author, revision,
+files, or words in the commit message</span>
+</form>
+
+<table class="bigtable">
+<tr>
+ <th>tag</th>
+ <th>node</th>
+</tr>
+{entries%tagentry}
+</table>
+</div>
+</div>
+
+{footer}
--- a/templates/search.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-#header#
-<title>#repo|escape#: searching for #query|escape#</title>
-</head>
-<body>
-
-<div class="buttons">
-<a href="#url#log{sessionvars%urlparameter}">changelog</a>
-<a href="#url#shortlog{sessionvars%urlparameter}">shortlog</a>
-<a href="#url#graph{sessionvars%urlparameter}">graph</a>
-<a href="#url#tags{sessionvars%urlparameter}">tags</a>
-<a href="#url#file/#node|short#{sessionvars%urlparameter}">files</a>
-#archives%archiveentry#
-</div>
-
-<h2>searching for #query|escape#</h2>
-
-<form>
-{sessionvars%hiddenformentry}
-<p>
-search:
-<input name="rev" type="text" width="30" value="#query|escape#">
-</p>
-</form>
-
-#entries#
-
-<form>
-{sessionvars%hiddenformentry}
-<p>
-search:
-<input name="rev" type="text" width="30" value="#query|escape#">
-</p>
-</form>
-
-#footer#
--- a/templates/shortlog.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-#header#
-<title>#repo|escape#: shortlog</title>
-<link rel="alternate" type="application/atom+xml"
-   href="#url#atom-log" title="Atom feed for #repo|escape#">
-<link rel="alternate" type="application/rss+xml"
-   href="#url#rss-log" title="RSS feed for #repo|escape#">
-</head>
-<body>
-
-<div class="buttons">
-<a href="#url#log/#rev#{sessionvars%urlparameter}">changelog</a>
-<a href="#url#graph{sessionvars%urlparameter}">graph</a>
-<a href="#url#tags{sessionvars%urlparameter}">tags</a>
-<a href="#url#file/#node|short#/{sessionvars%urlparameter}">files</a>
-#archives%archiveentry#
-<a type="application/rss+xml" href="#url#rss-log">rss</a>
-<a type="application/rss+xml" href="#url#atom-log" title="Atom feed for #repo|escape#">atom</a>
-</div>
-
-<h2>shortlog for #repo|escape#</h2>
-
-<form action="#url#log">
-{sessionvars%hiddenformentry}
-<p>
-<label for="search1">search:</label>
-<input name="rev" id="search1" type="text" size="30">
-navigate: <small class="navigate">#changenav%navshortentry#</small>
-</p>
-</form>
-
-#entries%shortlogentry#
-
-<form action="#url#log">
-{sessionvars%hiddenformentry}
-<p>
-<label for="search2">search:</label>
-<input name="rev" id="search2" type="text" size="30">
-navigate: <small class="navigate">#changenav%navshortentry#</small>
-</p>
-</form>
-
-#footer#
--- a/templates/shortlogentry.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-<table class="slogEntry parity#parity#">
- <tr>
-  <td class="age">#date|age#</td>
-  <td class="author">#author|person#</td>
-  <td class="node"><a href="#url#rev/#node|short#{sessionvars%urlparameter}">#desc|strip|firstline|escape#</a></td>
- </tr>
-</table>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/spartan/changelog.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,42 @@
+#header#
+<title>#repo|escape#: changelog</title>
+<link rel="alternate" type="application/atom+xml"
+   href="#url#atom-log" title="Atom feed for #repo|escape#">
+<link rel="alternate" type="application/rss+xml"
+   href="#url#rss-log" title="RSS feed for #repo|escape#">
+</head>
+<body>
+
+<div class="buttons">
+<a href="#url#shortlog/#rev#{sessionvars%urlparameter}">shortlog</a>
+<a href="#url#graph{sessionvars%urlparameter}">graph</a>
+<a href="#url#tags{sessionvars%urlparameter}">tags</a>
+<a href="#url#file/#node|short#{sessionvars%urlparameter}">files</a>
+#archives%archiveentry#
+<a type="application/rss+xml" href="#url#rss-log">rss</a>
+<a type="application/atom+xml" href="#url#atom-log" title="Atom feed for #repo|escape#">atom</a>
+</div>
+
+<h2>changelog for #repo|escape#</h2>
+
+<form action="#url#log">
+{sessionvars%hiddenformentry}
+<p>
+<label for="search1">search:</label>
+<input name="rev" id="search1" type="text" size="30">
+navigate: <small class="navigate">#changenav%naventry#</small>
+</p>
+</form>
+
+#entries%changelogentry#
+
+<form action="#url#log">
+{sessionvars%hiddenformentry}
+<p>
+<label for="search2">search:</label>
+<input name="rev" id="search2" type="text" size="30">
+navigate: <small class="navigate">#changenav%naventry#</small>
+</p>
+</form>
+
+#footer#
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/spartan/changelogentry.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,25 @@
+<table class="logEntry parity#parity#">
+ <tr>
+  <th class="age">#date|age# ago:</th>
+  <th class="firstline">#desc|strip|firstline|escape#</th>
+ </tr>
+ <tr>
+  <th class="revision">changeset #rev#:</th>
+  <td class="node"><a href="#url#rev/#node|short#{sessionvars%urlparameter}">#node|short#</a></td>
+ </tr>
+ #parent%changelogparent#
+ #child%changelogchild#
+ #changelogtag#
+ <tr>
+  <th class="author">author:</th>
+  <td class="author">#author|obfuscate#</td>
+ </tr>
+ <tr>
+  <th class="date">date:</th>
+  <td class="date">#date|date#</td>
+ </tr>
+ <tr>
+  <th class="files"><a href="#url#file/#node|short#{sessionvars%urlparameter}">files</a>:</th>
+  <td class="files">#files#</td>
+ </tr>
+</table>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/spartan/changeset.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,50 @@
+#header#
+<title>#repo|escape#: changeset #node|short#</title>
+</head>
+<body>
+
+<div class="buttons">
+<a href="#url#log/#rev#{sessionvars%urlparameter}">changelog</a>
+<a href="#url#shortlog/#rev#{sessionvars%urlparameter}">shortlog</a>
+<a href="#url#graph{sessionvars%urlparameter}">graph</a>
+<a href="#url#tags{sessionvars%urlparameter}">tags</a>
+<a href="#url#file/#node|short#{sessionvars%urlparameter}">files</a>
+<a href="#url#raw-rev/#node|short#">raw</a>
+#archives%archiveentry#
+</div>
+
+<h2>changeset: #desc|strip|escape|firstline#</h2>
+
+<table id="changesetEntry">
+<tr>
+ <th class="changeset">changeset #rev#:</th>
+ <td class="changeset"><a href="#url#rev/#node|short#{sessionvars%urlparameter}">#node|short#</a></td>
+</tr>
+#parent%changesetparent#
+#child%changesetchild#
+#changesettag#
+<tr>
+ <th class="author">author:</th>
+ <td class="author">#author|obfuscate#</td>
+</tr>
+<tr>
+ <th class="date">date:</th>
+ <td class="date">#date|date# (#date|age# ago)</td>
+</tr>
+<tr>
+ <th class="files">files:</th>
+ <td class="files">#files#</td>
+</tr>
+<tr>
+ <th class="description">description:</th>
+ <td class="description">#desc|strip|escape|addbreaks#</td>
+</tr>
+</table>
+
+<div id="changesetDiff">
+#diff#
+</div>
+
+#footer#
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/spartan/error.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,15 @@
+#header#
+<title>Mercurial Error</title>
+</head>
+<body>
+
+<h2>Mercurial Error</h2>
+
+<p>
+An error occurred while processing your request:
+</p>
+<p>
+#error|escape#
+</p>
+
+#footer#
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/spartan/fileannotate.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,49 @@
+#header#
+<title>#repo|escape#: #file|escape# annotate</title>
+</head>
+<body>
+
+<div class="buttons">
+<a href="#url#log/#rev#{sessionvars%urlparameter}">changelog</a>
+<a href="#url#shortlog/#rev#{sessionvars%urlparameter}">shortlog</a>
+<a href="#url#graph{sessionvars%urlparameter}">graph</a>
+<a href="#url#tags{sessionvars%urlparameter}">tags</a>
+<a href="#url#rev/#node|short#{sessionvars%urlparameter}">changeset</a>
+<a href="#url#file/#node|short##path|urlescape#{sessionvars%urlparameter}">files</a>
+<a href="#url#file/#node|short#/#file|urlescape#{sessionvars%urlparameter}">file</a>
+<a href="#url#log/#node|short#/#file|urlescape#{sessionvars%urlparameter}">revisions</a>
+<a href="#url#raw-annotate/#node|short#/#file|urlescape#">raw</a>
+</div>
+
+<h2>Annotate #file|escape#</h2>
+
+<table>
+<tr>
+ <td class="metatag">changeset #rev#:</td>
+ <td><a href="#url#rev/#node|short#{sessionvars%urlparameter}">#node|short#</a></td></tr>
+#parent%fileannotateparent#
+#child%fileannotatechild#
+<tr>
+ <td class="metatag">author:</td>
+ <td>#author|obfuscate#</td></tr>
+<tr>
+ <td class="metatag">date:</td>
+ <td>#date|date# (#date|age# ago)</td>
+</tr>
+<tr>
+ <td class="metatag">permissions:</td>
+ <td>#permissions|permissions#</td>
+</tr>
+<tr>
+  <td class="metatag">description:</td>
+  <td>{desc|strip|escape|addbreaks}</td>
+</tr>
+</table>
+
+<br/>
+
+<table cellspacing="0" cellpadding="0">
+#annotate%annotateline#
+</table>
+
+#footer#
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/spartan/filediff.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,35 @@
+#header#
+<title>#repo|escape#: #file|escape# diff</title>
+</head>
+<body>
+
+<div class="buttons">
+<a href="#url#log/#rev#{sessionvars%urlparameter}">changelog</a>
+<a href="#url#shortlog/#rev#{sessionvars%urlparameter}">shortlog</a>
+<a href="#url#graph{sessionvars%urlparameter}">graph</a>
+<a href="#url#tags{sessionvars%urlparameter}">tags</a>
+<a href="#url#rev/#node|short#{sessionvars%urlparameter}">changeset</a>
+<a href="#url#file/#node|short#/#file|urlescape#{sessionvars%urlparameter}">file</a>
+<a href="#url#log/#node|short#/#file|urlescape#{sessionvars%urlparameter}">revisions</a>
+<a href="#url#annotate/#node|short#/#file|urlescape#{sessionvars%urlparameter}">annotate</a>
+<a href="#url#raw-diff/#node|short#/#file|urlescape#">raw</a>
+</div>
+
+<h2>#file|escape#</h2>
+
+<table id="filediffEntry">
+<tr>
+ <th class="revision">revision #rev#:</th>
+ <td class="revision"><a href="#url#rev/#node|short#{sessionvars%urlparameter}">#node|short#</a></td>
+</tr>
+#parent%filediffparent#
+#child%filediffchild#
+</table>
+
+<div id="fileDiff">
+#diff#
+</div>
+
+#footer#
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/spartan/filelog.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,27 @@
+#header#
+<title>#repo|escape#: #file|escape# history</title>
+<link rel="alternate" type="application/atom+xml"
+   href="#url#atom-log/tip/#file|urlescape#" title="Atom feed for #repo|escape#:#file#">
+<link rel="alternate" type="application/rss+xml"
+   href="#url#rss-log/tip/#file|urlescape#" title="RSS feed for #repo|escape#:#file#">
+</head>
+<body>
+
+<div class="buttons">
+<a href="#url#log{sessionvars%urlparameter}">changelog</a>
+<a href="#url#shortlog{sessionvars%urlparameter}">shortlog</a>
+<a href="#url#graph{sessionvars%urlparameter}">graph</a>
+<a href="#url#tags{sessionvars%urlparameter}">tags</a>
+<a href="#url#file/#node|short#/#file|urlescape#{sessionvars%urlparameter}">file</a>
+<a href="#url#annotate/#node|short#/#file|urlescape#{sessionvars%urlparameter}">annotate</a>
+<a type="application/rss+xml" href="#url#rss-log/tip/#file|urlescape#">rss</a>
+<a type="application/atom+xml" href="#url#atom-log/tip/#file|urlescape#" title="Atom feed for #repo|escape#:#file#">atom</a>
+</div>
+
+<h2>#file|escape# revision history</h2>
+
+<p>navigate: <small class="navigate">{nav%filenaventry}</small></p>
+
+#entries%filelogentry#
+
+#footer#
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/spartan/filelogentry.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,25 @@
+<table class="logEntry parity#parity#">
+ <tr>
+  <th class="age">#date|age# ago:</th>
+  <th class="firstline"><a href="#url#rev/#node|short#{sessionvars%urlparameter}">#desc|strip|firstline|escape#</a></th>
+ </tr>
+ <tr>
+  <th class="revision">revision #filerev#:</td>
+  <td class="node">
+   <a href="#url#file/#node|short#/#file|urlescape#{sessionvars%urlparameter}">#node|short#</a>
+   <a href="#url#diff/#node|short#/#file|urlescape#{sessionvars%urlparameter}">(diff)</a>
+   <a href="#url#annotate/#node|short#/#file|urlescape#{sessionvars%urlparameter}">(annotate)</a>
+  </td>
+ </tr>
+ #rename%filelogrename#
+ <tr>
+  <th class="author">author:</th>
+  <td class="author">#author|obfuscate#</td>
+ </tr>
+ <tr>
+  <th class="date">date:</th>
+  <td class="date">#date|date#</td>
+ </tr>
+</table>
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/spartan/filerevision.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,45 @@
+#header#
+<title>#repo|escape#:#file|escape#</title>
+</head>
+<body>
+
+<div class="buttons">
+<a href="#url#log/#rev#{sessionvars%urlparameter}">changelog</a>
+<a href="#url#shortlog/#rev#{sessionvars%urlparameter}">shortlog</a>
+<a href="#url#graph{sessionvars%urlparameter}">graph</a>
+<a href="#url#tags{sessionvars%urlparameter}">tags</a>
+<a href="#url#rev/#node|short#{sessionvars%urlparameter}">changeset</a>
+<a href="#url#file/#node|short##path|urlescape#{sessionvars%urlparameter}">files</a>
+<a href="#url#log/#node|short#/#file|urlescape#{sessionvars%urlparameter}">revisions</a>
+<a href="#url#annotate/#node|short#/#file|urlescape#{sessionvars%urlparameter}">annotate</a>
+<a href="#url#raw-file/#node|short#/#file|urlescape#">raw</a>
+</div>
+
+<h2>#file|escape#</h2>
+
+<table>
+<tr>
+ <td class="metatag">changeset #rev#:</td>
+ <td><a href="#url#rev/#node|short#{sessionvars%urlparameter}">#node|short#</a></td></tr>
+#parent%filerevparent#
+#child%filerevchild#
+<tr>
+ <td class="metatag">author:</td>
+ <td>#author|obfuscate#</td></tr>
+<tr>
+ <td class="metatag">date:</td>
+ <td>#date|date# (#date|age# ago)</td></tr>
+<tr>
+ <td class="metatag">permissions:</td>
+ <td>#permissions|permissions#</td></tr>
+<tr>
+  <td class="metatag">description:</td>
+  <td>{desc|strip|escape|addbreaks}</td>
+</tr>
+</table>
+
+<pre>
+#text%fileline#
+</pre>
+
+#footer#
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/spartan/footer.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,8 @@
+#motd#
+<div class="logo">
+<a href="http://www.selenic.com/mercurial/">
+<img src="#staticurl#hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
+</div>
+
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/spartan/graph.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,95 @@
+#header#
+<title>#repo|escape#: graph</title>
+<link rel="alternate" type="application/atom+xml"
+   href="#url#atom-tags" title="Atom feed for #repo|escape#: tags">
+<link rel="alternate" type="application/rss+xml"
+   href="#url#rss-tags" title="RSS feed for #repo|escape#: tags">
+<!--[if IE]><script type="text/javascript" src="#staticurl#excanvas.js"></script><![endif]-->
+</head>
+<body>
+
+<div class="buttons">
+<a href="#url#log{sessionvars%urlparameter}">changelog</a>
+<a href="#url#shortlog{sessionvars%urlparameter}">shortlog</a>
+<a href="#url#tags{sessionvars%urlparameter}">tags</a>
+<a href="#url#file/#node|short#/{sessionvars%urlparameter}">files</a>
+</div>
+
+<h2>graph</h2>
+
+<form action="#url#log">
+{sessionvars%hiddenformentry}
+<p>
+<label for="search1">search:</label>
+<input name="rev" id="search1" type="text" size="30">
+navigate: <small class="navigate">#changenav%navgraphentry#</small>
+</p>
+</form>
+
+<noscript>The revision graph only works with JavaScript-enabled browsers.</noscript>
+
+<div id="wrapper">
+<ul id="nodebgs"></ul>
+<canvas id="graph" width="224" height="#canvasheight#"></canvas>
+<ul id="graphnodes"></ul>
+</div>
+
+<script type="text/javascript" src="#staticurl#graph.js"></script>
+<script type="text/javascript">
+<!-- hide script content
+
+var data = {jsdata|json};
+var graph = new Graph();
+graph.scale({bg_height});
+
+graph.edge = function(x0, y0, x1, y1, color) {
+	
+	this.setColor(color, 0.0, 0.65);
+	this.ctx.beginPath();
+	this.ctx.moveTo(x0, y0);
+	this.ctx.lineTo(x1, y1);
+	this.ctx.stroke();
+	
+}
+
+var revlink = '<li style="_STYLE"><span class="desc">';
+revlink += '<a href="{url}rev/_NODEID{sessionvars%urlparameter}" title="_NODEID">_DESC</a>';
+revlink += '</span><span class="info">_DATE ago, by _USER</span></li>';
+
+graph.vertex = function(x, y, color, parity, cur) {
+	
+	this.ctx.beginPath();
+	color = this.setColor(color, 0.25, 0.75);
+	this.ctx.arc(x, y, radius, 0, Math.PI * 2, true);
+	this.ctx.fill();
+	
+	var bg = '<li class="bg parity' + parity + '"></li>';
+	var left = (this.columns + 1) * this.bg_height;
+	var nstyle = 'padding-left: ' + left + 'px;';
+	var item = revlink.replace(/_STYLE/, nstyle);
+	item = item.replace(/_PARITY/, 'parity' + parity);
+	item = item.replace(/_NODEID/, cur[0]);
+	item = item.replace(/_NODEID/, cur[0]);
+	item = item.replace(/_DESC/, cur[3]);
+	item = item.replace(/_USER/, cur[4]);
+	item = item.replace(/_DATE/, cur[5]);
+	
+	return [bg, item];
+	
+}
+
+graph.render(data);
+
+// stop hiding script -->
+</script>
+
+<form action="#url#log">
+{sessionvars%hiddenformentry}
+<p>
+<label for="search1">search:</label>
+<input name="rev" id="search1" type="text" size="30">
+navigate: <small class="navigate">#changenav%navgraphentry#</small>
+</p>
+</form>
+
+#footer#
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/spartan/header.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,6 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<link rel="icon" href="#staticurl#hgicon.png" type="image/png">
+<meta name="robots" content="index, nofollow" />
+<link rel="stylesheet" href="#staticurl#style.css" type="text/css" />
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/spartan/index.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,19 @@
+#header#
+<title>Mercurial repositories index</title>
+</head>
+<body>
+
+<h2>Mercurial Repositories</h2>
+
+<table>
+    <tr>
+        <td><a href="?sort=#sort_name#">Name</a></td>
+        <td><a href="?sort=#sort_description#">Description</a></td>
+        <td><a href="?sort=#sort_contact#">Contact</a></td>
+        <td><a href="?sort=#sort_lastchange#">Last change</a></td>
+        <td>&nbsp;</td>
+    </tr>
+    #entries%indexentry#
+</table>
+
+#footer#
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/spartan/manifest.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,27 @@
+#header#
+<title>#repo|escape#: files for changeset #node|short#</title>
+</head>
+<body>
+
+<div class="buttons">
+<a href="#url#log/#rev#{sessionvars%urlparameter}">changelog</a>
+<a href="#url#shortlog/#rev#{sessionvars%urlparameter}">shortlog</a>
+<a href="#url#graph{sessionvars%urlparameter}">graph</a>
+<a href="#url#tags{sessionvars%urlparameter}">tags</a>
+<a href="#url#rev/#node|short#{sessionvars%urlparameter}">changeset</a>
+#archives%archiveentry#
+</div>
+
+<h2>files for changeset #node|short#: #path|escape#</h2>
+
+<table cellpadding="0" cellspacing="0">
+<tr class="parity#upparity#">
+  <td><tt>drwxr-xr-x</tt>&nbsp;
+  <td>&nbsp;
+  <td>&nbsp;
+  <td><a href="#url#file/#node|short##up|urlescape#{sessionvars%urlparameter}">[up]</a>
+</tr>
+#dentries%direntry#
+#fentries%fileentry#
+</table>
+#footer#
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/spartan/map	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,60 @@
+default = 'shortlog'
+mimetype = 'text/html; charset={encoding}'
+header = header.tmpl
+footer = footer.tmpl
+search = search.tmpl
+changelog = changelog.tmpl
+shortlog = shortlog.tmpl
+shortlogentry = shortlogentry.tmpl
+graph = graph.tmpl
+naventry = '<a href="{url}log/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
+navshortentry = '<a href="{url}shortlog/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
+navgraphentry = '<a href="{url}graph/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
+filenaventry = '<a href="{url}log/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{label|escape}</a> '
+filedifflink = '<a href="#url#diff/#node|short#/#file|urlescape#{sessionvars%urlparameter}">#file|escape#</a> '
+filenodelink = '<a href="#url#file/#node|short#/#file|urlescape#{sessionvars%urlparameter}">#file|escape#</a> '
+filenolink = '{file|escape} '
+fileellipses = '...'
+changelogentry = changelogentry.tmpl
+searchentry = changelogentry.tmpl
+changeset = changeset.tmpl
+manifest = manifest.tmpl
+direntry = '<tr class="parity#parity#"><td><tt>drwxr-xr-x</tt>&nbsp;<td>&nbsp;<td>&nbsp;<td><a href="#url#file/#node|short##path|urlescape#{sessionvars%urlparameter}">#basename|escape#/</a> <a href="#url#file/#node|short##path|urlescape#/#emptydirs|urlescape#{sessionvars%urlparameter}">#emptydirs|urlescape#</a>'
+fileentry = '<tr class="parity#parity#"><td><tt>#permissions|permissions#</tt>&nbsp;<td align=right><tt class="date">#date|isodate#</tt>&nbsp;<td align=right><tt>#size#</tt>&nbsp;<td><a href="#url#file/#node|short#/#file|urlescape#{sessionvars%urlparameter}">#basename|escape#</a>'
+filerevision = filerevision.tmpl
+fileannotate = fileannotate.tmpl
+filediff = filediff.tmpl
+filelog = filelog.tmpl
+fileline = '<div class="parity#parity#"><a class="lineno" href="##lineid#" id="#lineid#">#linenumber#</a>#line|escape#</div>'
+filelogentry = filelogentry.tmpl
+annotateline = '<tr class="parity#parity#"><td class="annotate"><a href="#url#annotate/#node|short#/#file|urlescape#{sessionvars%urlparameter}#l{targetline}" title="{node|short}: {desc|escape|firstline}">#author|user#@#rev#</a></td><td><a class="lineno" href="##lineid#" id="#lineid#">#linenumber#</a></td><td><pre>#line|escape#</pre></td></tr>'
+difflineplus = '<span class="plusline"><a class="lineno" href="##lineid#" id="#lineid#">#linenumber#</a>#line|escape#</span>'
+difflineminus = '<span class="minusline"><a class="lineno" href="##lineid#" id="#lineid#">#linenumber#</a>#line|escape#</span>'
+difflineat = '<span class="atline"><a class="lineno" href="##lineid#" id="#lineid#">#linenumber#</a>#line|escape#</span>'
+diffline = '<a class="lineno" href="##lineid#" id="#lineid#">#linenumber#</a>#line|escape#'
+changelogparent = '<tr><th class="parent">parent #rev#:</th><td class="parent"><a href="#url#rev/#node|short#{sessionvars%urlparameter}">#node|short#</a></td></tr>'
+changesetparent = '<tr><th class="parent">parent #rev#:</th><td class="parent"><a href="#url#rev/#node|short#{sessionvars%urlparameter}">#node|short#</a></td></tr>'
+filerevparent = '<tr><td class="metatag">parent:</td><td><a href="{url}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{rename%filerename}{node|short}</a></td></tr>'
+filerename = '{file|escape}@'
+filelogrename = '<tr><th>base:</th><td><a href="#url#file/#node|short#/#file|urlescape#{sessionvars%urlparameter}">#file|escape#@#node|short#</a></td></tr>'
+fileannotateparent = '<tr><td class="metatag">parent:</td><td><a href="{url}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">{rename%filerename}{node|short}</a></td></tr>'
+changesetchild = '<tr><th class="child">child #rev#:</th><td class="child"><a href="#url#rev/#node|short#{sessionvars%urlparameter}">#node|short#</a></td></tr>'
+changelogchild = '<tr><th class="child">child #rev#:</th><td class="child"><a href="#url#rev/#node|short#{sessionvars%urlparameter}">#node|short#</a></td></tr>'
+filerevchild = '<tr><td class="metatag">child:</td><td><a href="#url#file/#node|short#/#file|urlescape#{sessionvars%urlparameter}">#node|short#</a></td></tr>'
+fileannotatechild = '<tr><td class="metatag">child:</td><td><a href="#url#annotate/#node|short#/#file|urlescape#{sessionvars%urlparameter}">#node|short#</a></td></tr>'
+tags = tags.tmpl
+tagentry = '<li class="tagEntry parity#parity#"><tt class="node">#node#</tt> <a href="#url#rev/#node|short#{sessionvars%urlparameter}">#tag|escape#</a></li>'
+diffblock = '<pre class="parity#parity#">#lines#</pre>'
+changelogtag = '<tr><th class="tag">tag:</th><td class="tag">#tag|escape#</td></tr>'
+changesettag = '<tr><th class="tag">tag:</th><td class="tag">#tag|escape#</td></tr>'
+filediffparent = '<tr><th class="parent">parent #rev#:</th><td class="parent"><a href="#url#rev/#node|short#{sessionvars%urlparameter}">#node|short#</a></td></tr>'
+filelogparent = '<tr><th>parent #rev#:</th><td><a href="#url#file/#node|short#/#file|urlescape#{sessionvars%urlparameter}">#node|short#</a></td></tr>'
+filediffchild = '<tr><th class="child">child #rev#:</th><td class="child"><a href="#url#rev/#node|short#{sessionvars%urlparameter}">#node|short#</a></td></tr>'
+filelogchild = '<tr><th>child #rev#:</th><td><a href="#url#file/#node|short#/#file|urlescape#{sessionvars%urlparameter}">#node|short#</a></td></tr>'
+indexentry = '<tr class="parity#parity#"><td><a href="#url#{sessionvars%urlparameter}">#name|escape#</a></td><td>#description#</td><td>#contact|obfuscate#</td><td class="age">#lastchange|age# ago</td><td class="indexlinks"><a href="#url#rss-log">RSS</a> <a href="#url#atom-log">Atom</a> #archives%archiveentry#</td></tr>'
+index = index.tmpl
+archiveentry = '<a href="#url#archive/#node|short##extension|urlescape#">#type|escape#</a> '
+notfound = notfound.tmpl
+error = error.tmpl
+urlparameter = '#separator##name#=#value|urlescape#'
+hiddenformentry = '<input type="hidden" name="#name#" value="#value|escape#" />'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/spartan/notfound.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,12 @@
+#header#
+<title>Mercurial repository not found</title>
+</head>
+<body>
+
+<h2>Mercurial repository not found</h2>
+
+The specified repository "#repo|escape#" is unknown, sorry.
+
+Please go back to the main repository list page.
+
+#footer#
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/spartan/search.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,35 @@
+#header#
+<title>#repo|escape#: searching for #query|escape#</title>
+</head>
+<body>
+
+<div class="buttons">
+<a href="#url#log{sessionvars%urlparameter}">changelog</a>
+<a href="#url#shortlog{sessionvars%urlparameter}">shortlog</a>
+<a href="#url#graph{sessionvars%urlparameter}">graph</a>
+<a href="#url#tags{sessionvars%urlparameter}">tags</a>
+<a href="#url#file/#node|short#{sessionvars%urlparameter}">files</a>
+#archives%archiveentry#
+</div>
+
+<h2>searching for #query|escape#</h2>
+
+<form>
+{sessionvars%hiddenformentry}
+<p>
+search:
+<input name="rev" type="text" width="30" value="#query|escape#">
+</p>
+</form>
+
+#entries#
+
+<form>
+{sessionvars%hiddenformentry}
+<p>
+search:
+<input name="rev" type="text" width="30" value="#query|escape#">
+</p>
+</form>
+
+#footer#
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/spartan/shortlog.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,42 @@
+#header#
+<title>#repo|escape#: shortlog</title>
+<link rel="alternate" type="application/atom+xml"
+   href="#url#atom-log" title="Atom feed for #repo|escape#">
+<link rel="alternate" type="application/rss+xml"
+   href="#url#rss-log" title="RSS feed for #repo|escape#">
+</head>
+<body>
+
+<div class="buttons">
+<a href="#url#log/#rev#{sessionvars%urlparameter}">changelog</a>
+<a href="#url#graph{sessionvars%urlparameter}">graph</a>
+<a href="#url#tags{sessionvars%urlparameter}">tags</a>
+<a href="#url#file/#node|short#/{sessionvars%urlparameter}">files</a>
+#archives%archiveentry#
+<a type="application/rss+xml" href="#url#rss-log">rss</a>
+<a type="application/rss+xml" href="#url#atom-log" title="Atom feed for #repo|escape#">atom</a>
+</div>
+
+<h2>shortlog for #repo|escape#</h2>
+
+<form action="#url#log">
+{sessionvars%hiddenformentry}
+<p>
+<label for="search1">search:</label>
+<input name="rev" id="search1" type="text" size="30">
+navigate: <small class="navigate">#changenav%navshortentry#</small>
+</p>
+</form>
+
+#entries%shortlogentry#
+
+<form action="#url#log">
+{sessionvars%hiddenformentry}
+<p>
+<label for="search2">search:</label>
+<input name="rev" id="search2" type="text" size="30">
+navigate: <small class="navigate">#changenav%navshortentry#</small>
+</p>
+</form>
+
+#footer#
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/spartan/shortlogentry.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,7 @@
+<table class="slogEntry parity#parity#">
+ <tr>
+  <td class="age">#date|age#</td>
+  <td class="author">#author|person#</td>
+  <td class="node"><a href="#url#rev/#node|short#{sessionvars%urlparameter}">#desc|strip|firstline|escape#</a></td>
+ </tr>
+</table>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/spartan/tags.tmpl	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,25 @@
+#header#
+<title>#repo|escape#: tags</title>
+<link rel="alternate" type="application/atom+xml"
+   href="#url#atom-tags" title="Atom feed for #repo|escape#: tags">
+<link rel="alternate" type="application/rss+xml"
+   href="#url#rss-tags" title="RSS feed for #repo|escape#: tags">
+</head>
+<body>
+
+<div class="buttons">
+<a href="#url#log{sessionvars%urlparameter}">changelog</a>
+<a href="#url#shortlog{sessionvars%urlparameter}">shortlog</a>
+<a href="#url#graph{sessionvars%urlparameter}">graph</a>
+<a href="#url#file/#node|short#/{sessionvars%urlparameter}">files</a>
+<a type="application/rss+xml" href="#url#rss-tags">rss</a>
+<a type="application/atom+xml" href="#url#atom-tags">atom</a>
+</div>
+
+<h2>tags:</h2>
+
+<ul id="tagEntries">
+#entries%tagentry#
+</ul>
+
+#footer#
--- a/templates/static/style-coal.css	Sun Dec 07 19:33:26 2008 +0100
+++ b/templates/static/style-coal.css	Sun Dec 07 19:34:07 2008 +0100
@@ -79,7 +79,7 @@
   width: 190px;
   padding: 5px;
   background: #ffc;
-  font-size: 70%;    
+  font-size: 70%;
   border: 1px solid yellow;
   -moz-border-radius: 5px; /* this works only in camino/firefox */
   -webkit-border-radius: 5px; /* this is just for Safari */
@@ -91,10 +91,10 @@
 .age { white-space:nowrap; }
 .date { white-space:nowrap; }
 .indexlinks { white-space:nowrap; }
-.parity0 { background-color: #f5f5f5; }
+.parity0 { background-color: #f0f0f0; }
 .parity1 { background-color: white; }
 .plusline { color: green; }
-.minusline { color: red; }
+.minusline { color: #dc143c; } /* crimson */
 .atline { color: purple; }
 
 .navigate {
@@ -111,6 +111,30 @@
   vertical-align: baseline;
 }
 
+.branchhead {
+  color: #000;
+  font-size: 80%;
+  font-weight: normal;
+  margin-left: .5em;
+  vertical-align: baseline;
+}
+
+ul#graphnodes .branchhead {
+  font-size: 75%;
+}
+
+.branchname {
+  color: #000;
+  font-size: 60%; 
+  font-weight: normal;
+  margin-left: .5em;
+  vertical-align: baseline;
+}
+
+h3 .branchname {
+  font-size: 80%;
+}
+
 /* Common */
 pre { margin: 0; }
 
@@ -126,7 +150,7 @@
   border-bottom: 1px solid #999;
   border-collapse: collapse;
   font-size: 90%;
-  width: 100%; 
+  width: 100%;
   font-weight: normal;
   text-align: left;
 }
@@ -136,9 +160,9 @@
   vertical-align: top;
 }
 
-.bigtable th { 
+.bigtable th {
   padding: 1px 4px 1px 4px;
-  border-bottom: 1px solid #999; 
+  border-bottom: 1px solid #999;
   font-size: smaller;
 }
 .bigtable tr { border: none; }
@@ -148,24 +172,34 @@
 .bigtable .node { width: 5em; font-family: monospace;}
 .bigtable .lineno { width: 2em; text-align: right;}
 .bigtable .lineno a { color: #999; font-size: smaller; font-family: monospace;}
-.bigtable td.source { font-family: monospace; white-space: pre; }
 .bigtable .permissions { width: 8em; text-align: left;}
 .bigtable .size { width: 5em; text-align: right; }
 .bigtable .annotate { text-align: right; }
 .bigtable td.annotate { font-size: smaller; }
+.bigtable td.source { font-size: inherit; }
+
+.source, .sourcefirst, .sourcelast {
+  font-family: monospace;
+  white-space: pre;
+  font-size: 90%;
+}
+.sourcefirst { border-bottom: 1px solid #999; font-weight: bold; font-size: smaller; }
+.sourcelast { border-top: 1px solid #999; }
+.source a { color: #999; font-size: smaller; font-family: monospace;}
+.bottomline { border-bottom: 1px solid #999; }
 
 .fileline { font-family: monospace; }
 .fileline img { border: 0; }
 
 /* Changeset entry */
-#changesetEntry { 
+#changesetEntry {
   border-collapse: collapse;
   font-size: 90%;
   width: 100%;
   margin-bottom: 1em;
 }
 
-#changesetEntry th { 
+#changesetEntry th {
   padding: 1px 4px 1px 4px;
   width: 4em;
   text-align: right;
--- a/templates/static/style-gitweb.css	Sun Dec 07 19:33:26 2008 +0100
+++ b/templates/static/style-gitweb.css	Sun Dec 07 19:34:07 2008 +0100
@@ -101,7 +101,7 @@
 	margin: 0;
 	top: -0.7em;
 }
- 
+
 ul#graphnodes li, ul#nodebgs li {
 	height: 39px;
 }
--- a/templates/static/style-paper.css	Sun Dec 07 19:33:26 2008 +0100
+++ b/templates/static/style-paper.css	Sun Dec 07 19:34:07 2008 +0100
@@ -82,10 +82,10 @@
 .age { white-space:nowrap; }
 .date { white-space:nowrap; }
 .indexlinks { white-space:nowrap; }
-.parity0 { background-color: #f5f5f5; }
+.parity0 { background-color: #f0f0f0; }
 .parity1 { background-color: white; }
 .plusline { color: green; }
-.minusline { color: red; }
+.minusline { color: #dc143c; } /* crimson */
 .atline { color: purple; }
 
 .navigate {
@@ -102,6 +102,30 @@
   vertical-align: baseline;
 }
 
+.branchhead {
+  color: #000;
+  font-size: 80%;
+  font-weight: normal;
+  margin-left: .5em;
+  vertical-align: baseline;
+}
+
+ul#graphnodes .branchhead {
+  font-size: 75%;
+}
+
+.branchname {
+  color: #000;
+  font-size: 60%; 
+  font-weight: normal;
+  margin-left: .5em;
+  vertical-align: baseline;
+}
+
+h3 .branchname {
+  font-size: 80%;
+}
+
 /* Common */
 pre { margin: 0; }
 
@@ -117,7 +141,7 @@
   border-bottom: 1px solid #999;
   border-collapse: collapse;
   font-size: 90%;
-  width: 100%; 
+  width: 100%;
   font-weight: normal;
   text-align: left;
 }
@@ -127,9 +151,9 @@
   vertical-align: top;
 }
 
-.bigtable th { 
+.bigtable th {
   padding: 1px 4px 1px 4px;
-  border-bottom: 1px solid #999; 
+  border-bottom: 1px solid #999;
   font-size: smaller;
 }
 .bigtable tr { border: none; }
@@ -137,26 +161,34 @@
 .bigtable .author { width: 12em; }
 .bigtable .description { }
 .bigtable .node { width: 5em; font-family: monospace;}
-.bigtable .lineno { width: 2em; text-align: right;}
-.bigtable .lineno a { color: #999; font-size: smaller; font-family: monospace;}
-.bigtable td.source { font-family: monospace; white-space: pre; }
 .bigtable .permissions { width: 8em; text-align: left;}
 .bigtable .size { width: 5em; text-align: right; }
 .bigtable .annotate { text-align: right; }
 .bigtable td.annotate { font-size: smaller; }
+.bigtable td.source { font-size: inherit; }
+
+.source, .sourcefirst, .sourcelast {
+  font-family: monospace;
+  white-space: pre;
+  font-size: 90%;
+}
+.sourcefirst { border-bottom: 1px solid #999; font-weight: bold; font-size: smaller; }
+.sourcelast { border-top: 1px solid #999; }
+.source a { color: #999; font-size: smaller; font-family: monospace;}
+.bottomline { border-bottom: 1px solid #999; }
 
 .fileline { font-family: monospace; }
 .fileline img { border: 0; }
 
 /* Changeset entry */
-#changesetEntry { 
+#changesetEntry {
   border-collapse: collapse;
   font-size: 90%;
   width: 100%;
   margin-bottom: 1em;
 }
 
-#changesetEntry th { 
+#changesetEntry th {
   padding: 1px 4px 1px 4px;
   width: 4em;
   text-align: right;
@@ -194,7 +226,7 @@
 	margin: 0;
 	top: -0.7em;
 }
- 
+
 ul#graphnodes li, ul#nodebgs li {
 	height: 39px;
 }
--- a/templates/static/style.css	Sun Dec 07 19:33:26 2008 +0100
+++ b/templates/static/style.css	Sun Dec 07 19:34:07 2008 +0100
@@ -84,7 +84,7 @@
 	margin: 0;
 	top: -0.7em;
 }
- 
+
 ul#graphnodes li, ul#nodebgs li {
 	height: 39px;
 }
--- a/templates/tags.tmpl	Sun Dec 07 19:33:26 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-#header#
-<title>#repo|escape#: tags</title>
-<link rel="alternate" type="application/atom+xml"
-   href="#url#atom-tags" title="Atom feed for #repo|escape#: tags">
-<link rel="alternate" type="application/rss+xml"
-   href="#url#rss-tags" title="RSS feed for #repo|escape#: tags">
-</head>
-<body>
-
-<div class="buttons">
-<a href="#url#log{sessionvars%urlparameter}">changelog</a>
-<a href="#url#shortlog{sessionvars%urlparameter}">shortlog</a>
-<a href="#url#graph{sessionvars%urlparameter}">graph</a>
-<a href="#url#file/#node|short#/{sessionvars%urlparameter}">files</a>
-<a type="application/rss+xml" href="#url#rss-tags">rss</a>
-<a type="application/atom+xml" href="#url#atom-tags">atom</a>
-</div>
-
-<h2>tags:</h2>
-
-<ul id="tagEntries">
-#entries%tagentry#
-</ul>
-
-#footer#
--- a/tests/hghave	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/hghave	Sun Dec 07 19:34:07 2008 +0100
@@ -154,6 +154,9 @@
     except ImportError:
         return False
 
+def has_outer_repo():
+    return matchoutput('hg root 2>&1', r'')
+
 checks = {
     "baz": (has_baz, "GNU Arch baz client"),
     "bzr": (has_bzr, "Canonical's Bazaar client"),
@@ -169,6 +172,7 @@
     "inotify": (has_inotify, "inotify extension support"),
     "lsprof": (has_lsprof, "python lsprof module"),
     "mtn": (has_mtn, "monotone client (> 0.31)"),
+    "outer-repo": (has_outer_repo, "outer repo"),
     "pygments": (has_pygments, "Pygments source highlighting library"),
     "svn": (has_svn, "subversion client and admin tools"),
     "svn-bindings": (has_svn_bindings, "subversion python bindings"),
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/killdaemons.py	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,25 @@
+#!/usr/bin/env python
+
+import os, sys, time, errno, signal
+
+# Kill off any leftover daemon processes
+try:
+    fp = file(os.environ['DAEMON_PIDS'])
+    for line in fp:
+        try:
+            pid = int(line)
+        except ValueError:
+            continue
+        try:
+            os.kill(pid, 0)
+            os.kill(pid, signal.SIGTERM)
+            for i in range(10):
+                time.sleep(0.05)
+                os.kill(pid, 0)
+            os.kill(pid, signal.SIGKILL)
+        except OSError, err:
+            if err.errno != errno.ESRCH:
+                raise
+    fp.close()
+except IOError:
+    pass
--- a/tests/run-tests.py	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/run-tests.py	Sun Dec 07 19:34:07 2008 +0100
@@ -63,6 +63,8 @@
     help="run tests in the given temporary directory")
 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("--with-hg", type="string",
     help="test existing install at given location")
 
@@ -71,6 +73,7 @@
 parser.set_defaults(**defaults)
 (options, args) = parser.parse_args()
 verbose = options.verbose
+nodiff = options.nodiff
 coverage = options.cover or options.cover_stdlib or options.annotate
 python = sys.executable
 
@@ -308,7 +311,8 @@
 
     def fail(msg):
         fails.append((test, msg))
-        print "\nERROR: %s %s" % (test, msg)
+        if not nodiff:
+            print "\nERROR: %s %s" % (test, msg)
         return None
 
     vlog("# Test", test)
@@ -374,6 +378,8 @@
     if options.timeout > 0:
         signal.alarm(0)
 
+    mark = '.'
+
     skipped = (ret == SKIPPED_STATUS)
     # If reference output file exists, check test output against it
     if os.path.exists(ref):
@@ -383,22 +389,26 @@
     else:
         ref_out = []
     if skipped:
+        mark = 's'
         missing = extract_missing_features(out)
         if not missing:
             missing = ['irrelevant']
         skip(missing[-1])
     elif out != ref_out:
+        mark = '!'
         if ret:
             fail("output changed and returned error code %d" % ret)
         else:
             fail("output changed")
-        show_diff(ref_out, out)
+            if not nodiff:
+                show_diff(ref_out, out)
         ret = 1
     elif ret:
+        mark = '!'
         fail("returned error code %d" % ret)
 
     if not verbose:
-        sys.stdout.write(skipped and 's' or '.')
+        sys.stdout.write(mark)
         sys.stdout.flush()
 
     if ret != 0 and not skipped:
@@ -449,6 +459,7 @@
 os.environ['LANG'] = os.environ['LC_ALL'] = 'C'
 os.environ['TZ'] = 'GMT'
 os.environ["EMAIL"] = "Foo Bar <foo.bar@example.com>"
+os.environ['CDPATH'] = ''
 
 TESTDIR = os.environ["TESTDIR"] = os.getcwd()
 HGTMP = os.environ['HGTMP'] = tempfile.mkdtemp('', 'hgtests.', options.tmpdir)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/svn/branches.svndump	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,415 @@
+SVN-fs-dump-format-version: 2
+
+UUID: 7b60030a-5a1f-4344-a009-73f0c1c2adf2
+
+Revision-number: 0
+Prop-content-length: 56
+Content-length: 56
+
+K 8
+svn:date
+V 27
+2008-12-06T12:47:52.296168Z
+PROPS-END
+
+Revision-number: 1
+Prop-content-length: 112
+Content-length: 112
+
+K 7
+svn:log
+V 10
+init projA
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T12:47:52.342238Z
+PROPS-END
+
+Node-path: branches
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: tags
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: trunk
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Revision-number: 2
+Prop-content-length: 106
+Content-length: 106
+
+K 7
+svn:log
+V 5
+hello
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T12:47:53.190046Z
+PROPS-END
+
+Node-path: branches/notinbranch
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 2
+Text-content-md5: e29311f6f1bf1af907f9ef9f44b8328b
+Content-length: 12
+
+PROPS-END
+d
+
+
+Node-path: trunk/a
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 2
+Text-content-md5: 60b725f10c9c85c70d97880dfe8191b3
+Content-length: 12
+
+PROPS-END
+a
+
+
+Node-path: trunk/b
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 2
+Text-content-md5: 3b5d5c3712955042212316173ccf37be
+Content-length: 12
+
+PROPS-END
+b
+
+
+Node-path: trunk/c
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 2
+Text-content-md5: 2cd6ee2c70b0bde53fbe6cac3c8b8bb1
+Content-length: 12
+
+PROPS-END
+c
+
+
+Revision-number: 3
+Prop-content-length: 124
+Content-length: 124
+
+K 7
+svn:log
+V 22
+branch trunk, remove c
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T12:47:55.188535Z
+PROPS-END
+
+Node-path: branches/old
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 1
+Node-copyfrom-path: trunk
+Prop-content-length: 34
+Content-length: 34
+
+K 13
+svn:mergeinfo
+V 0
+
+PROPS-END
+
+
+Node-path: branches/old/a
+Node-kind: file
+Node-action: add
+Node-copyfrom-rev: 2
+Node-copyfrom-path: trunk/a
+Text-copy-source-md5: 60b725f10c9c85c70d97880dfe8191b3
+
+
+Node-path: branches/old/b
+Node-kind: file
+Node-action: add
+Node-copyfrom-rev: 2
+Node-copyfrom-path: trunk/b
+Text-copy-source-md5: 3b5d5c3712955042212316173ccf37be
+
+
+Revision-number: 4
+Prop-content-length: 109
+Content-length: 109
+
+K 7
+svn:log
+V 8
+change a
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T12:47:57.146347Z
+PROPS-END
+
+Node-path: trunk/a
+Node-kind: file
+Node-action: change
+Text-content-length: 4
+Text-content-md5: 0d227f1abf8c2932d342e9b99cc957eb
+Content-length: 4
+
+a
+a
+
+
+Revision-number: 5
+Prop-content-length: 109
+Content-length: 109
+
+K 7
+svn:log
+V 8
+change b
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T12:47:58.150124Z
+PROPS-END
+
+Node-path: branches/old/b
+Node-kind: file
+Node-action: change
+Text-content-length: 4
+Text-content-md5: 06ac26ed8b614fc0b141e4542aa067c2
+Content-length: 4
+
+b
+b
+
+
+Revision-number: 6
+Prop-content-length: 119
+Content-length: 119
+
+K 7
+svn:log
+V 17
+move and update c
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T12:48:00.161336Z
+PROPS-END
+
+Node-path: branches/old/c
+Node-kind: file
+Node-action: add
+Node-copyfrom-rev: 3
+Node-copyfrom-path: trunk/b
+Text-copy-source-md5: 3b5d5c3712955042212316173ccf37be
+Prop-content-length: 34
+Text-content-length: 4
+Text-content-md5: 33cb6785d50937d8d307ebb66d6259a7
+Content-length: 38
+
+K 13
+svn:mergeinfo
+V 0
+
+PROPS-END
+b
+c
+
+
+Node-path: trunk/b
+Node-action: delete
+
+
+Revision-number: 7
+Prop-content-length: 116
+Content-length: 116
+
+K 7
+svn:log
+V 14
+change b again
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T12:48:01.153724Z
+PROPS-END
+
+Node-path: branches/old/b
+Node-kind: file
+Node-action: change
+Text-content-length: 6
+Text-content-md5: cdcfb41554e2d092c13f5e6839e63577
+Content-length: 6
+
+b
+b
+b
+
+
+Revision-number: 8
+Prop-content-length: 114
+Content-length: 114
+
+K 7
+svn:log
+V 12
+move to old2
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T12:48:04.150915Z
+PROPS-END
+
+Node-path: branches/old2
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 7
+Node-copyfrom-path: branches/old
+
+
+Node-path: branches/old
+Node-action: delete
+
+
+Revision-number: 9
+Prop-content-length: 118
+Content-length: 118
+
+K 7
+svn:log
+V 16
+move back to old
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T12:48:06.149560Z
+PROPS-END
+
+Node-path: branches/old
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 8
+Node-copyfrom-path: branches/old2
+
+
+Node-path: branches/old2
+Node-action: delete
+
+
+Revision-number: 10
+Prop-content-length: 118
+Content-length: 118
+
+K 7
+svn:log
+V 16
+last change to a
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T12:48:07.268498Z
+PROPS-END
+
+Node-path: trunk/a
+Node-kind: file
+Node-action: change
+Text-content-length: 2
+Text-content-md5: 60b725f10c9c85c70d97880dfe8191b3
+Content-length: 2
+
+a
+
+
+Revision-number: 11
+Prop-content-length: 126
+Content-length: 126
+
+K 7
+svn:log
+V 24
+branch trunk@1 into old3
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T12:48:09.151702Z
+PROPS-END
+
+Node-path: branches/old3
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 1
+Node-copyfrom-path: trunk
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/svn/move.svndump	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,401 @@
+SVN-fs-dump-format-version: 2
+
+UUID: 0682b859-320d-4a69-a164-a7cab5695072
+
+Revision-number: 0
+Prop-content-length: 56
+Content-length: 56
+
+K 8
+svn:date
+V 27
+2008-12-06T13:33:36.768573Z
+PROPS-END
+
+Revision-number: 1
+Prop-content-length: 112
+Content-length: 112
+
+K 7
+svn:log
+V 10
+init projA
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T13:33:37.083146Z
+PROPS-END
+
+Node-path: trunk
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: trunk/a
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 2
+Text-content-md5: 60b725f10c9c85c70d97880dfe8191b3
+Content-length: 12
+
+PROPS-END
+a
+
+
+Node-path: trunk/d1
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: trunk/d1/b
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 2
+Text-content-md5: 3b5d5c3712955042212316173ccf37be
+Content-length: 12
+
+PROPS-END
+b
+
+
+Node-path: trunk/d1/c
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 2
+Text-content-md5: 2cd6ee2c70b0bde53fbe6cac3c8b8bb1
+Content-length: 12
+
+PROPS-END
+c
+
+
+Node-path: trunk/d2
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: trunk/d2/d
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 2
+Text-content-md5: e29311f6f1bf1af907f9ef9f44b8328b
+Content-length: 12
+
+PROPS-END
+d
+
+
+Revision-number: 2
+Prop-content-length: 118
+Content-length: 118
+
+K 7
+svn:log
+V 16
+commitbeforemove
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T13:33:38.152773Z
+PROPS-END
+
+Node-path: trunk/a
+Node-kind: file
+Node-action: change
+Text-content-length: 4
+Text-content-md5: 0d227f1abf8c2932d342e9b99cc957eb
+Content-length: 4
+
+a
+a
+
+
+Node-path: trunk/d1/c
+Node-kind: file
+Node-action: change
+Text-content-length: 4
+Text-content-md5: 63fad9092ad37713ebe26b3193f89c41
+Content-length: 4
+
+c
+c
+
+
+Revision-number: 3
+Prop-content-length: 112
+Content-length: 112
+
+K 7
+svn:log
+V 10
+movedtrunk
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T13:33:39.146388Z
+PROPS-END
+
+Node-path: subproject
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 2
+Node-copyfrom-path: trunk
+
+
+Node-path: trunk
+Node-action: delete
+
+
+Revision-number: 4
+Prop-content-length: 113
+Content-length: 113
+
+K 7
+svn:log
+V 11
+createtrunk
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T13:33:40.179944Z
+PROPS-END
+
+Node-path: subproject/trunk
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Revision-number: 5
+Prop-content-length: 116
+Content-length: 116
+
+K 7
+svn:log
+V 14
+createbranches
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T13:33:41.184505Z
+PROPS-END
+
+Node-path: subproject/branches
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Revision-number: 6
+Prop-content-length: 107
+Content-length: 107
+
+K 7
+svn:log
+V 6
+moved1
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T13:33:42.153312Z
+PROPS-END
+
+Node-path: subproject/trunk/d1
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 5
+Node-copyfrom-path: subproject/d1
+
+
+Node-path: subproject/d1
+Node-action: delete
+
+
+Revision-number: 7
+Prop-content-length: 107
+Content-length: 107
+
+K 7
+svn:log
+V 6
+moved2
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T13:33:42.206313Z
+PROPS-END
+
+Node-path: subproject/trunk/d2
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 6
+Node-copyfrom-path: subproject/d2
+
+
+Node-path: subproject/d2
+Node-action: delete
+
+
+Revision-number: 8
+Prop-content-length: 119
+Content-length: 119
+
+K 7
+svn:log
+V 17
+changeb and rm d2
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T13:33:43.182355Z
+PROPS-END
+
+Node-path: subproject/trunk/d1/b
+Node-kind: file
+Node-action: change
+Text-content-length: 4
+Text-content-md5: 06ac26ed8b614fc0b141e4542aa067c2
+Content-length: 4
+
+b
+b
+
+
+Node-path: subproject/trunk/d2
+Node-action: delete
+
+
+Revision-number: 9
+Prop-content-length: 113
+Content-length: 113
+
+K 7
+svn:log
+V 11
+moved1again
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T13:33:44.153682Z
+PROPS-END
+
+Node-path: subproject/branches/d1
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 8
+Node-copyfrom-path: subproject/trunk/d1
+
+
+Node-path: subproject/trunk/d1
+Node-action: delete
+
+
+Revision-number: 10
+Prop-content-length: 118
+Content-length: 118
+
+K 7
+svn:log
+V 16
+copyfilefrompast
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T13:33:44.298011Z
+PROPS-END
+
+Node-path: subproject/trunk/d
+Node-kind: file
+Node-action: add
+Node-copyfrom-rev: 7
+Node-copyfrom-path: subproject/trunk/d2/d
+Text-copy-source-md5: e29311f6f1bf1af907f9ef9f44b8328b
+
+
+Revision-number: 11
+Prop-content-length: 117
+Content-length: 117
+
+K 7
+svn:log
+V 15
+copydirfrompast
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T13:33:44.349920Z
+PROPS-END
+
+Node-path: subproject/trunk/d2
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 7
+Node-copyfrom-path: subproject/trunk/d2
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/svn/startrev.svndump	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,240 @@
+SVN-fs-dump-format-version: 2
+
+UUID: c731c652-65e9-4325-a17e-fed96a319f22
+
+Revision-number: 0
+Prop-content-length: 56
+Content-length: 56
+
+K 8
+svn:date
+V 27
+2008-12-06T13:44:21.642421Z
+PROPS-END
+
+Revision-number: 1
+Prop-content-length: 112
+Content-length: 112
+
+K 7
+svn:log
+V 10
+init projA
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T13:44:21.759281Z
+PROPS-END
+
+Node-path: branches
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: tags
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: trunk
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Revision-number: 2
+Prop-content-length: 109
+Content-length: 109
+
+K 7
+svn:log
+V 8
+createab
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T13:44:22.179257Z
+PROPS-END
+
+Node-path: trunk/a
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 2
+Text-content-md5: 60b725f10c9c85c70d97880dfe8191b3
+Content-length: 12
+
+PROPS-END
+a
+
+
+Node-path: trunk/b
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 2
+Text-content-md5: 3b5d5c3712955042212316173ccf37be
+Content-length: 12
+
+PROPS-END
+b
+
+
+Revision-number: 3
+Prop-content-length: 108
+Content-length: 108
+
+K 7
+svn:log
+V 7
+removeb
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T13:44:23.176546Z
+PROPS-END
+
+Node-path: trunk/b
+Node-action: delete
+
+
+Revision-number: 4
+Prop-content-length: 109
+Content-length: 109
+
+K 7
+svn:log
+V 8
+changeaa
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T13:44:25.147151Z
+PROPS-END
+
+Node-path: trunk/a
+Node-kind: file
+Node-action: change
+Text-content-length: 4
+Text-content-md5: 0d227f1abf8c2932d342e9b99cc957eb
+Content-length: 4
+
+a
+a
+
+
+Revision-number: 5
+Prop-content-length: 119
+Content-length: 119
+
+K 7
+svn:log
+V 17
+branch, changeaaa
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T13:44:28.158475Z
+PROPS-END
+
+Node-path: branches/branch1
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 4
+Node-copyfrom-path: trunk
+Prop-content-length: 34
+Content-length: 34
+
+K 13
+svn:mergeinfo
+V 0
+
+PROPS-END
+
+
+Node-path: branches/branch1/a
+Node-kind: file
+Node-action: change
+Text-content-length: 6
+Text-content-md5: 7d4ebf8f298d22fc349a91725b00af1c
+Content-length: 6
+
+a
+a
+a
+
+
+Revision-number: 6
+Prop-content-length: 117
+Content-length: 117
+
+K 7
+svn:log
+V 15
+addc,changeaaaa
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T13:44:29.180655Z
+PROPS-END
+
+Node-path: branches/branch1/a
+Node-kind: file
+Node-action: change
+Text-content-length: 8
+Text-content-md5: d12178e74d8774e34361e0a08d1fd2b7
+Content-length: 8
+
+a
+a
+a
+a
+
+
+Node-path: branches/branch1/c
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 2
+Text-content-md5: 2cd6ee2c70b0bde53fbe6cac3c8b8bb1
+Content-length: 12
+
+PROPS-END
+c
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/svn/svndump-branches.sh	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,70 @@
+#!/bin/sh
+#
+# Use this script to generate branches.svndump
+#
+
+mkdir temp
+cd temp
+
+mkdir project-orig
+cd project-orig
+mkdir trunk
+mkdir branches
+mkdir tags
+cd ..
+
+svnadmin create svn-repo
+svnurl=file://`pwd`/svn-repo
+svn import project-orig $svnurl -m "init projA"
+
+svn co $svnurl project
+cd project
+echo a > trunk/a
+echo b > trunk/b
+echo c > trunk/c
+# Add a file within branches, used to confuse branch detection
+echo d > branches/notinbranch
+svn add trunk/a trunk/b trunk/c branches/notinbranch
+svn ci -m hello
+
+# Branch to old
+svn copy trunk branches/old
+svn rm branches/old/c
+svn ci -m "branch trunk, remove c"
+svn up
+
+# Update trunk
+echo a >> trunk/a
+svn ci -m "change a"
+
+# Update old branch
+echo b >> branches/old/b
+svn ci -m "change b"
+
+# Create a cross-branch revision
+svn move trunk/b branches/old/c
+echo c >> branches/old/c
+svn ci -m "move and update c"
+
+# Update old branch again
+echo b >> branches/old/b
+svn ci -m "change b again"
+
+# Move back and forth between branch of similar names
+# This used to generate fake copy records
+svn up
+svn move branches/old branches/old2
+svn ci -m "move to old2"
+svn move branches/old2 branches/old
+svn ci -m "move back to old"
+
+# Update trunk again
+echo a > trunk/a
+svn ci -m "last change to a"
+
+# Branch again from a converted revision
+svn copy -r 1 $svnurl/trunk branches/old3
+svn ci -m "branch trunk@1 into old3"
+cd ..
+
+svnadmin dump svn-repo > ../branches.svndump
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/svn/svndump-move.sh	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,62 @@
+#!/bin/sh
+#
+# Use this script to generate move.svndump
+#
+
+mkdir temp
+cd temp
+
+mkdir project-orig
+cd project-orig
+mkdir trunk
+echo a > trunk/a
+mkdir trunk/d1
+mkdir trunk/d2
+echo b > trunk/d1/b
+echo c > trunk/d1/c
+echo d > trunk/d2/d
+cd ..
+
+svnadmin create svn-repo
+svnurl=file://`pwd`/svn-repo
+svn import project-orig $svnurl -m "init projA"
+
+svn co $svnurl project
+cd project
+# Build a module renaming chain which used to confuse the converter.
+# Update svn repository
+echo a >> trunk/a
+echo c >> trunk/d1/c
+svn ci -m commitbeforemove
+svn mv $svnurl/trunk $svnurl/subproject -m movedtrunk
+svn up
+mkdir subproject/trunk
+svn add subproject/trunk
+svn ci -m createtrunk
+mkdir subproject/branches
+svn add subproject/branches
+svn ci -m createbranches
+svn mv $svnurl/subproject/d1 $svnurl/subproject/trunk/d1 -m moved1
+svn mv $svnurl/subproject/d2 $svnurl/subproject/trunk/d2 -m moved2
+svn up
+echo b >> subproject/trunk/d1/b
+
+svn rm subproject/trunk/d2
+svn ci -m "changeb and rm d2"
+svn mv $svnurl/subproject/trunk/d1 $svnurl/subproject/branches/d1 -m moved1again
+
+if svn help copy | grep 'SRC\[@REV\]' > /dev/null 2>&1; then
+    # SVN >= 1.5 replaced the -r REV syntax with @REV
+    # Copy a file from a past revision
+    svn copy $svnurl/subproject/trunk/d2/d@7 $svnurl/subproject/trunk -m copyfilefrompast
+    # Copy a directory from a past revision
+    svn copy $svnurl/subproject/trunk/d2@7 $svnurl/subproject/trunk -m copydirfrompast
+else
+    # Copy a file from a past revision
+    svn copy -r 7 $svnurl/subproject/trunk/d2/d $svnurl/subproject/trunk -m copyfilefrompast
+    # Copy a directory from a past revision
+    svn copy -r 7 $svnurl/subproject/trunk/d2 $svnurl/subproject/trunk -m copydirfrompast
+fi
+cd ..
+
+svnadmin dump svn-repo > ../move.svndump
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/svn/svndump-startrev.sh	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,45 @@
+#!/bin/sh
+#
+# Use this script to generate startrev.svndump
+#
+
+mkdir temp
+cd temp
+
+mkdir project-orig
+cd project-orig
+mkdir trunk
+mkdir branches
+mkdir tags
+cd ..
+
+svnadmin create svn-repo
+svnurl=file://`pwd`/svn-repo
+svn import project-orig $svnurl -m "init projA"
+
+svn co $svnurl project
+cd project
+echo a > trunk/a
+echo b > trunk/b
+svn add trunk/a trunk/b
+svn ci -m createab
+svn rm trunk/b
+svn ci -m removeb
+svn up
+echo a >> trunk/a
+svn ci -m changeaa
+
+# Branch
+svn up
+svn copy trunk branches/branch1
+echo a >> branches/branch1/a
+svn ci -m "branch, changeaaa"
+
+echo a >> branches/branch1/a
+echo c > branches/branch1/c
+svn add branches/branch1/c
+svn ci -m "addc,changeaaaa"
+svn up
+cd ..
+
+svnadmin dump svn-repo > ../startrev.svndump
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/svn/svndump-tags.sh	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,49 @@
+#!/bin/sh
+#
+# Use this script to generate tags.svndump
+#
+
+mkdir temp
+cd temp
+
+mkdir project-orig
+cd project-orig
+mkdir trunk
+mkdir branches
+mkdir tags
+mkdir unrelated
+cd ..
+
+svnadmin create svn-repo
+svnurl=file://`pwd`/svn-repo
+svn import project-orig $svnurl -m "init projA"
+
+svn co $svnurl project
+cd project
+echo a > trunk/a
+svn add trunk/a
+svn ci -m adda
+echo a >> trunk/a
+svn ci -m changea
+echo a >> trunk/a
+svn ci -m changea2
+# Add an unrelated commit to test that tags are bound to the
+# correct "from" revision and not a dummy one
+echo a >> unrelated/dummy
+svn add unrelated/dummy
+svn ci -m unrelatedchange
+# Tag current revision
+svn up
+svn copy trunk tags/trunk.v1
+svn copy trunk tags/trunk.badtag
+svn ci -m "tagging trunk.v1 trunk.badtag"
+echo a >> trunk/a
+svn ci -m changea3
+# Fix the bad tag
+# trunk.badtag should not show in converted tags
+svn up
+svn mv tags/trunk.badtag tags/trunk.goodtag
+svn ci -m "fix trunk.badtag"
+cd ..
+
+svnadmin dump svn-repo > ../tags.svndump
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/svn/tags.svndump	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,295 @@
+SVN-fs-dump-format-version: 2
+
+UUID: 65371b91-a2cf-4cb1-a047-08b28c3b4c40
+
+Revision-number: 0
+Prop-content-length: 56
+Content-length: 56
+
+K 8
+svn:date
+V 27
+2008-12-06T13:50:23.869747Z
+PROPS-END
+
+Revision-number: 1
+Prop-content-length: 112
+Content-length: 112
+
+K 7
+svn:log
+V 10
+init projA
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T13:50:23.944361Z
+PROPS-END
+
+Node-path: branches
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: tags
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: trunk
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Node-path: unrelated
+Node-kind: dir
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+
+Revision-number: 2
+Prop-content-length: 105
+Content-length: 105
+
+K 7
+svn:log
+V 4
+adda
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T13:50:25.174397Z
+PROPS-END
+
+Node-path: trunk/a
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 2
+Text-content-md5: 60b725f10c9c85c70d97880dfe8191b3
+Content-length: 12
+
+PROPS-END
+a
+
+
+Revision-number: 3
+Prop-content-length: 108
+Content-length: 108
+
+K 7
+svn:log
+V 7
+changea
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T13:50:26.148468Z
+PROPS-END
+
+Node-path: trunk/a
+Node-kind: file
+Node-action: change
+Text-content-length: 4
+Text-content-md5: 0d227f1abf8c2932d342e9b99cc957eb
+Content-length: 4
+
+a
+a
+
+
+Revision-number: 4
+Prop-content-length: 109
+Content-length: 109
+
+K 7
+svn:log
+V 8
+changea2
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T13:50:27.147988Z
+PROPS-END
+
+Node-path: trunk/a
+Node-kind: file
+Node-action: change
+Text-content-length: 6
+Text-content-md5: 7d4ebf8f298d22fc349a91725b00af1c
+Content-length: 6
+
+a
+a
+a
+
+
+Revision-number: 5
+Prop-content-length: 117
+Content-length: 117
+
+K 7
+svn:log
+V 15
+unrelatedchange
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T13:50:28.174989Z
+PROPS-END
+
+Node-path: unrelated/dummy
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Text-content-length: 2
+Text-content-md5: 60b725f10c9c85c70d97880dfe8191b3
+Content-length: 12
+
+PROPS-END
+a
+
+
+Revision-number: 6
+Prop-content-length: 131
+Content-length: 131
+
+K 7
+svn:log
+V 29
+tagging trunk.v1 trunk.badtag
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T13:50:32.157783Z
+PROPS-END
+
+Node-path: tags/trunk.badtag
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 5
+Node-copyfrom-path: trunk
+Prop-content-length: 34
+Content-length: 34
+
+K 13
+svn:mergeinfo
+V 0
+
+PROPS-END
+
+
+Node-path: tags/trunk.v1
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 5
+Node-copyfrom-path: trunk
+Prop-content-length: 34
+Content-length: 34
+
+K 13
+svn:mergeinfo
+V 0
+
+PROPS-END
+
+
+Revision-number: 7
+Prop-content-length: 109
+Content-length: 109
+
+K 7
+svn:log
+V 8
+changea3
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T13:50:33.145803Z
+PROPS-END
+
+Node-path: trunk/a
+Node-kind: file
+Node-action: change
+Text-content-length: 8
+Text-content-md5: d12178e74d8774e34361e0a08d1fd2b7
+Content-length: 8
+
+a
+a
+a
+a
+
+
+Revision-number: 8
+Prop-content-length: 118
+Content-length: 118
+
+K 7
+svn:log
+V 16
+fix trunk.badtag
+K 10
+svn:author
+V 7
+pmezard
+K 8
+svn:date
+V 27
+2008-12-06T13:50:36.153842Z
+PROPS-END
+
+Node-path: tags/trunk.goodtag
+Node-kind: dir
+Node-action: add
+Node-copyfrom-rev: 7
+Node-copyfrom-path: tags/trunk.badtag
+
+
+Node-path: tags/trunk.badtag
+Node-action: delete
+
+
--- a/tests/test-archive	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-archive	Sun Dec 07 19:34:07 2008 +0100
@@ -24,7 +24,7 @@
     echo % $3 and $4 disallowed should both give 403
     "$TESTDIR/get-with-headers.py" localhost:$HGPORT "/archive/tip.$3" | head -n 1
     "$TESTDIR/get-with-headers.py" localhost:$HGPORT "/archive/tip.$4" | head -n 1
-    kill `cat hg.pid`
+    "$TESTDIR/killdaemons.py"
     cat errors.log
     cp .hg/hgrc-base .hg/hgrc
 }
@@ -63,6 +63,8 @@
 http_proxy= python getarchive.py "$TIP" zip > archive.zip
 unzip -t archive.zip | sed "s/$QTIP/TIP/"
 
+"$TESTDIR/killdaemons.py"
+
 hg archive -t tar test.tar
 tar tf test.tar
 
--- a/tests/test-bdiff	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-bdiff	Sun Dec 07 19:34:07 2008 +0100
@@ -9,13 +9,13 @@
     if d:
         c = mpatch.patches(a, [d])
     if c != b:
-        print "***", `a`, `b`
+        print "***", repr(a), repr(b)
         print "bad:"
-        print `c`[:200]
-        print `d`
+        print repr(c)[:200]
+        print repr(d)
 
 def test(a, b):
-    print "***", `a`, `b`
+    print "***", repr(a), repr(b)
     test1(a, b)
     test1(b, a)
 
--- a/tests/test-convert-cvs-branch	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-convert-cvs-branch	Sun Dec 07 19:34:07 2008 +0100
@@ -28,8 +28,9 @@
 
 mkdir src
 cd src
-echo "1" > a > b
-cvscall import -m "init" src v0 r0
+echo "1" > a
+echo "1" > b
+cvscall import -m "init" src v0 r0 | sort
 cd ..
 cvscall co src
 cd src
--- a/tests/test-convert-cvs-branch.out	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-convert-cvs-branch.out	Sun Dec 07 19:34:07 2008 +0100
@@ -1,10 +1,10 @@
 % create cvs repository
 % Create a new project
+
+
 N src/a
 N src/b
-
 No conflicts created by this import
-
 cvs checkout: Updating src
 U src/a
 U src/b
--- a/tests/test-convert-darcs	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-convert-darcs	Sun Dec 07 19:34:07 2008 +0100
@@ -1,6 +1,12 @@
 #!/bin/sh
 
 "$TESTDIR/hghave" darcs || exit 80
+if darcs --version 2>&1 | grep '^2\.' > /dev/null; then
+    # FIXME: darcs 2 will fail with
+    ### Abort: timeout after 180 seconds.
+    echo 'skipped: test currently disabled for darcs 2'
+    exit 80
+fi
 
 echo "[extensions]" >> $HGRCPATH
 echo "convert=" >> $HGRCPATH
--- a/tests/test-convert-svn-branches	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-convert-svn-branches	Sun Dec 07 19:34:07 2008 +0100
@@ -12,6 +12,7 @@
 echo "hgext.graphlog =" >> $HGRCPATH
 
 svnadmin create svn-repo
+cat "$TESTDIR/svn/branches.svndump" | svnadmin load svn-repo > /dev/null
 
 svnpath=`pwd | fix_path`
 # SVN wants all paths to start with a slash. Unfortunately,
@@ -20,73 +21,10 @@
 if [ $? -ne 0 ]; then
     svnpath='/'$svnpath
 fi
-
-echo % initial svn import
-mkdir projA
-cd projA
-mkdir trunk
-mkdir branches
-mkdir tags
-cd ..
-
-svnurl=file://$svnpath/svn-repo/projA
-svn import -m "init projA" projA $svnurl | fix_path
-
-echo % update svn repository
-svn co $svnurl A | fix_path
-cd A
-echo a > trunk/a
-echo b > trunk/b
-echo c > trunk/c
-# Add a file within branches, used to confuse branch detection
-echo d > branches/notinbranch
-svn add trunk/a trunk/b trunk/c branches/notinbranch
-svn ci -m hello
-
-echo % branch to old
-svn copy trunk branches/old
-svn rm branches/old/c
-svn ci -m "branch trunk, remove c"
-svn up
-
-echo % update trunk
-"$TESTDIR/svn-safe-append.py" a trunk/a
-svn ci -m "change a"
-
-echo % update old branch
-"$TESTDIR/svn-safe-append.py" b branches/old/b
-svn ci -m "change b"
-
-echo % create a cross-branch revision
-svn move trunk/b branches/old/c
-"$TESTDIR/svn-safe-append.py" c branches/old/c
-svn ci -m "move and update c"
-
-echo % update old branch again
-"$TESTDIR/svn-safe-append.py" b branches/old/b
-svn ci -m "change b again"
-
-echo % move back and forth between branch of similar names
-# This used to generate fake copy records
-svn up
-svn move branches/old branches/old2
-svn ci -m "move to old2"
-svn move branches/old2 branches/old
-svn ci -m "move back to old"
-
-echo % update trunk again
-"$TESTDIR/svn-safe-append.py" a trunk/a
-svn ci -m "last change to a"
-cd ..
+svnurl=file://$svnpath/svn-repo
 
 echo % convert trunk and branches
-hg convert --datesort $svnurl A-hg
-
-echo % branch again from a converted revision
-cd A
-svn copy -r 1 $svnurl/trunk branches/old3
-svn ci -m "branch trunk@1 into old3"
-cd ..
+hg convert --datesort -r 10 $svnurl A-hg
 
 echo % convert again
 hg convert --datesort $svnurl A-hg
--- a/tests/test-convert-svn-branches.out	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-convert-svn-branches.out	Sun Dec 07 19:34:07 2008 +0100
@@ -1,77 +1,3 @@
-% initial svn import
-Adding         projA/trunk
-Adding         projA/branches
-Adding         projA/tags
-
-Committed revision 1.
-% update svn repository
-A    A/trunk
-A    A/branches
-A    A/tags
-Checked out revision 1.
-A         trunk/a
-A         trunk/b
-A         trunk/c
-A         branches/notinbranch
-Adding         branches/notinbranch
-Adding         trunk/a
-Adding         trunk/b
-Adding         trunk/c
-Transmitting file data ....
-Committed revision 2.
-% branch to old
-A         branches/old
-D         branches/old/c
-Adding         branches/old
-Adding         branches/old/a
-Adding         branches/old/b
-Deleting       branches/old/c
-
-Committed revision 3.
-At revision 3.
-% update trunk
-Sending        trunk/a
-Transmitting file data .
-Committed revision 4.
-% update old branch
-Sending        branches/old/b
-Transmitting file data .
-Committed revision 5.
-% create a cross-branch revision
-A         branches/old/c
-D         trunk/b
-Adding         branches/old/c
-Deleting       trunk/b
-Transmitting file data .
-Committed revision 6.
-% update old branch again
-Sending        branches/old/b
-Transmitting file data .
-Committed revision 7.
-% move back and forth between branch of similar names
-At revision 7.
-A         branches/old2
-D         branches/old/a
-D         branches/old/b
-D         branches/old/c
-D         branches/old
-Deleting       branches/old
-Adding         branches/old2
-
-Committed revision 8.
-A         branches/old
-D         branches/old2/a
-D         branches/old2/b
-D         branches/old2/c
-D         branches/old2
-Adding         branches/old
-Deleting       branches/old2
-
-Committed revision 9.
-% update trunk again
-Sending        trunk/a
-Transmitting file data .
-Committed revision 10.
 % convert trunk and branches
 initializing destination A-hg repository
 scanning source...
@@ -88,12 +14,6 @@
 2 move to old2
 1 move back to old
 0 last change to a
-% branch again from a converted revision
-Checked out revision 1.
-A         branches/old3
-Adding         branches/old3
-
-Committed revision 11.
 % convert again
 scanning source...
 sorting...
@@ -117,8 +37,8 @@
 | | |
 | o |  branch= 3 change a files: a
 | | |
-| | o  branch=old 2 branch trunk, remove c files:
-| |/
++---o  branch=old 2 branch trunk, remove c files: a b
+| |
 | o  branch= 1 hello files: a b c
 |/
 o  branch= 0 init projA files:
--- a/tests/test-convert-svn-move	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-convert-svn-move	Sun Dec 07 19:34:07 2008 +0100
@@ -12,6 +12,7 @@
 echo "hgext.graphlog =" >> $HGRCPATH
 
 svnadmin create svn-repo
+cat "$TESTDIR/svn/move.svndump" | svnadmin load svn-repo > /dev/null
 
 svnpath=`pwd | fix_path`
 # SVN wants all paths to start with a slash. Unfortunately,
@@ -20,58 +21,7 @@
 if [ $? -ne 0 ]; then
     svnpath='/'$svnpath
 fi
-
-echo % initial svn import
-mkdir projA
-cd projA
-mkdir trunk
-echo a > trunk/a
-mkdir trunk/d1
-mkdir trunk/d2
-echo b > trunk/d1/b
-echo c > trunk/d1/c
-echo d > trunk/d2/d
-cd ..
-
-svnurl=file://$svnpath/svn-repo/projA
-svn import -m "init projA" projA $svnurl | fix_path
-
-# Build a module renaming chain which used to confuse the converter.
-echo % update svn repository
-svn co $svnurl A | fix_path
-cd A
-"$TESTDIR/svn-safe-append.py" a trunk/a
-"$TESTDIR/svn-safe-append.py" c trunk/d1/c
-svn ci -m commitbeforemove
-svn mv $svnurl/trunk $svnurl/subproject -m movedtrunk
-svn up
-mkdir subproject/trunk
-svn add subproject/trunk
-svn ci -m createtrunk
-mkdir subproject/branches
-svn add subproject/branches
-svn ci -m createbranches
-svn mv $svnurl/subproject/d1 $svnurl/subproject/trunk/d1 -m moved1
-svn mv $svnurl/subproject/d2 $svnurl/subproject/trunk/d2 -m moved2
-svn up
-"$TESTDIR/svn-safe-append.py" b subproject/trunk/d1/b
-svn rm subproject/trunk/d2
-svn ci -m "changeb and rm d2"
-svn mv $svnurl/subproject/trunk/d1 $svnurl/subproject/branches/d1 -m moved1again
-
-if svn help copy | grep 'SRC\[@REV\]' > /dev/null 2>&1; then
-    # SVN >= 1.5 replaced the -r REV syntax with @REV
-    echo % copy a file from a past revision
-    svn copy $svnurl/subproject/trunk/d2/d@7 $svnurl/subproject/trunk -m copyfilefrompast
-    echo % copy a directory from a past revision
-    svn copy $svnurl/subproject/trunk/d2@7 $svnurl/subproject/trunk -m copydirfrompast
-else
-    echo % copy a file from a past revision
-    svn copy -r 7 $svnurl/subproject/trunk/d2/d $svnurl/subproject/trunk -m copyfilefrompast
-    echo % copy a directory from a past revision
-    svn copy -r 7 $svnurl/subproject/trunk/d2 $svnurl/subproject/trunk -m copydirfrompast
-fi
-cd ..
+svnurl=file://$svnpath/svn-repo
 
 echo % convert trunk and branches
 hg convert --datesort $svnurl/subproject A-hg
--- a/tests/test-convert-svn-move.out	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-convert-svn-move.out	Sun Dec 07 19:34:07 2008 +0100
@@ -1,71 +1,3 @@
-% initial svn import
-Adding         projA/trunk
-Adding         projA/trunk/a
-Adding         projA/trunk/d1
-Adding         projA/trunk/d1/b
-Adding         projA/trunk/d1/c
-Adding         projA/trunk/d2
-Adding         projA/trunk/d2/d
-
-Committed revision 1.
-% update svn repository
-A    A/trunk
-A    A/trunk/a
-A    A/trunk/d1
-A    A/trunk/d1/b
-A    A/trunk/d1/c
-A    A/trunk/d2
-A    A/trunk/d2/d
-Checked out revision 1.
-Sending        trunk/a
-Sending        trunk/d1/c
-Transmitting file data ..
-Committed revision 2.
-
-Committed revision 3.
-D    trunk
-A    subproject
-A    subproject/a
-A    subproject/d1
-A    subproject/d1/b
-A    subproject/d1/c
-A    subproject/d2
-A    subproject/d2/d
-Updated to revision 3.
-A         subproject/trunk
-Adding         subproject/trunk
-
-Committed revision 4.
-A         subproject/branches
-Adding         subproject/branches
-
-Committed revision 5.
-
-Committed revision 6.
-
-Committed revision 7.
-A    subproject/trunk/d1
-A    subproject/trunk/d1/b
-A    subproject/trunk/d1/c
-A    subproject/trunk/d2
-A    subproject/trunk/d2/d
-D    subproject/d1
-D    subproject/d2
-Updated to revision 7.
-D         subproject/trunk/d2/d
-D         subproject/trunk/d2
-Sending        subproject/trunk/d1/b
-Deleting       subproject/trunk/d2
-Transmitting file data .
-Committed revision 8.
-
-Committed revision 9.
-% copy a file from a past revision
-
-Committed revision 10.
-% copy a directory from a past revision
-
-Committed revision 11.
 % convert trunk and branches
 initializing destination A-hg repository
 scanning source...
--- a/tests/test-convert-svn-sink	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-convert-svn-sink	Sun Dec 07 19:34:07 2008 +0100
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-"$TESTDIR/hghave" svn svn-bindings || exit 80
+"$TESTDIR/hghave" svn svn-bindings no-outer-repo || exit 80
 
 fixpath()
 {
--- a/tests/test-convert-svn-startrev	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-convert-svn-startrev	Sun Dec 07 19:34:07 2008 +0100
@@ -12,6 +12,7 @@
 echo "hgext.graphlog =" >> $HGRCPATH
 
 svnadmin create svn-repo
+cat "$TESTDIR/svn/startrev.svndump" | svnadmin load svn-repo > /dev/null
 
 svnpath=`pwd | fix_path`
 # SVN wants all paths to start with a slash. Unfortunately,
@@ -20,43 +21,7 @@
 if [ $? -ne 0 ]; then
     svnpath='/'$svnpath
 fi
-
-echo % initial svn import
-mkdir projA
-cd projA
-mkdir trunk
-mkdir branches
-mkdir tags
-cd ..
-
-svnurl=file://$svnpath/svn-repo/projA
-svn import -m "init projA" projA $svnurl | fix_path
-
-echo % update svn repository
-svn co $svnurl A | fix_path
-cd A
-echo a > trunk/a
-echo b > trunk/b
-svn add trunk/a trunk/b
-svn ci -m createab
-svn rm trunk/b
-svn ci -m removeb
-svn up
-"$TESTDIR/svn-safe-append.py" a trunk/a
-svn ci -m changeaa
-
-echo % branch
-svn up
-svn copy trunk branches/branch1
-"$TESTDIR/svn-safe-append.py" a branches/branch1/a
-svn ci -m "branch, changeaaa"
-
-"$TESTDIR/svn-safe-append.py" a branches/branch1/a
-echo c > branches/branch1/c
-svn add branches/branch1/c
-svn ci -m "addc,changeaaaa"
-svn up
-cd ..
+svnurl=file://$svnpath/svn-repo
 
 convert()
 {
--- a/tests/test-convert-svn-startrev.out	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-convert-svn-startrev.out	Sun Dec 07 19:34:07 2008 +0100
@@ -1,41 +1,3 @@
-% initial svn import
-Adding         projA/trunk
-Adding         projA/branches
-Adding         projA/tags
-
-Committed revision 1.
-% update svn repository
-A    A/trunk
-A    A/branches
-A    A/tags
-Checked out revision 1.
-A         trunk/a
-A         trunk/b
-Adding         trunk/a
-Adding         trunk/b
-Transmitting file data ..
-Committed revision 2.
-D         trunk/b
-Deleting       trunk/b
-
-Committed revision 3.
-At revision 3.
-Sending        trunk/a
-Transmitting file data .
-Committed revision 4.
-% branch
-At revision 4.
-A         branches/branch1
-Adding         branches/branch1
-Sending        branches/branch1/a
-Transmitting file data .
-Committed revision 5.
-A         branches/branch1/c
-Sending        branches/branch1/a
-Adding         branches/branch1/c
-Transmitting file data ..
-Committed revision 6.
-At revision 6.
 % convert before branching point
 initializing destination A-r3-hg repository
 scanning source...
--- a/tests/test-convert-svn-tags	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-convert-svn-tags	Sun Dec 07 19:34:07 2008 +0100
@@ -12,6 +12,7 @@
 echo "hgext.graphlog =" >> $HGRCPATH
 
 svnadmin create svn-repo
+cat "$TESTDIR/svn/tags.svndump" | svnadmin load svn-repo > /dev/null
 
 svnpath=`pwd | fix_path`
 # SVN wants all paths to start with a slash. Unfortunately,
@@ -20,47 +21,7 @@
 if [ $? -ne 0 ]; then
     svnpath='/'$svnpath
 fi
-
-echo % initial svn import
-mkdir projA
-cd projA
-mkdir trunk
-mkdir branches
-mkdir tags
-mkdir unrelated
-cd ..
-
-svnurl=file://$svnpath/svn-repo/projA
-svn import -m "init projA" projA $svnurl | fix_path | sort
-
-echo % update svn repository
-svn co $svnurl A | fix_path
-cd A
-echo a > trunk/a
-svn add trunk/a
-svn ci -m adda
-"$TESTDIR/svn-safe-append.py" a trunk/a
-svn ci -m changea
-"$TESTDIR/svn-safe-append.py" a trunk/a
-svn ci -m changea2
-# Add an unrelated commit to test that tags are bound to the
-# correct "from" revision and not a dummy one
-"$TESTDIR/svn-safe-append.py" a unrelated/dummy
-svn add unrelated/dummy
-svn ci -m unrelatedchange
-echo % tag current revision
-svn up
-svn copy trunk tags/trunk.v1
-svn copy trunk tags/trunk.badtag
-svn ci -m "tagging trunk.v1 trunk.badtag"
-"$TESTDIR/svn-safe-append.py" a trunk/a
-svn ci -m changea3
-echo % fix the bad tag
-# trunk.badtag should not show in converted tags
-svn up
-svn mv tags/trunk.badtag tags/trunk.goodtag
-svn ci -m "fix trunk.badtag"
-cd ..
+svnurl=file://$svnpath/svn-repo
 
 echo % convert
 hg convert --datesort $svnurl A-hg
--- a/tests/test-convert-svn-tags.out	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-convert-svn-tags.out	Sun Dec 07 19:34:07 2008 +0100
@@ -1,50 +1,3 @@
-% initial svn import
-
-Adding         projA/branches
-Adding         projA/tags
-Adding         projA/trunk
-Adding         projA/unrelated
-Committed revision 1.
-% update svn repository
-A    A/trunk
-A    A/unrelated
-A    A/branches
-A    A/tags
-Checked out revision 1.
-A         trunk/a
-Adding         trunk/a
-Transmitting file data .
-Committed revision 2.
-Sending        trunk/a
-Transmitting file data .
-Committed revision 3.
-Sending        trunk/a
-Transmitting file data .
-Committed revision 4.
-A         unrelated/dummy
-Adding         unrelated/dummy
-Transmitting file data .
-Committed revision 5.
-% tag current revision
-At revision 5.
-A         tags/trunk.v1
-A         tags/trunk.badtag
-Adding         tags/trunk.badtag
-Adding         tags/trunk.v1
-
-Committed revision 6.
-Sending        trunk/a
-Transmitting file data .
-Committed revision 7.
-% fix the bad tag
-At revision 7.
-A         tags/trunk.goodtag
-D         tags/trunk.badtag/a
-D         tags/trunk.badtag
-Deleting       tags/trunk.badtag
-Adding         tags/trunk.goodtag
-
-Committed revision 8.
 % convert
 initializing destination A-hg repository
 scanning source...
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-diff-color	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+echo "[extensions]" >> $HGRCPATH
+echo "color=" >> $HGRCPATH
+
+hg init repo
+cd repo
+cat > a <<EOF
+c
+c
+a
+a
+b
+a
+a
+c
+c
+EOF
+hg ci -Am adda
+cat > a <<EOF
+c
+c
+a
+a
+dd
+a
+a
+c
+c
+EOF
+
+echo '% default context'
+hg diff --nodates --color=always
+
+echo '% --unified=2'
+hg diff --nodates -U 2  --color=always
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-diff-color.out	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,25 @@
+adding a
+% default context
+diff -r cf9f4ba66af2 a
+--- a/a
++++ b/a
+@@ -2,7 +2,7 @@
+ c
+ a
+ a
+-b
++dd
+ a
+ a
+ c
+% --unified=2
+diff -r cf9f4ba66af2 a
+--- a/a
++++ b/a
+@@ -3,5 +3,5 @@
+ a
+ a
+-b
++dd
+ a
+ a
--- a/tests/test-diff-unified	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-diff-unified	Sun Dec 07 19:34:07 2008 +0100
@@ -44,6 +44,15 @@
 echo '% invalid diff.unified'
 hg --config diff.unified=foo diff --nodates
 
-exit 0
+echo % test off-by-one error with diff -p
+hg init diffp
+cd diffp
+echo a > a
+hg ci -Ama
+rm a
+echo b > a
+echo a >> a
+echo c >> a
+hg diff -U0 -p --nodates
 
-
+exit 0
--- a/tests/test-diff-unified.out	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-diff-unified.out	Sun Dec 07 19:34:07 2008 +0100
@@ -47,3 +47,12 @@
  a
 % invalid diff.unified
 abort: diff context lines count must be an integer, not 'foo'
+% test off-by-one error with diff -p
+adding a
+diff -r cb9a9f314b8b a
+--- a/a
++++ b/a
+@@ -1,0 +1,1 @@
++b
+@@ -2,0 +3,1 @@ a
++c
--- a/tests/test-dispatch	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-dispatch	Sun Dec 07 19:34:07 2008 +0100
@@ -1,6 +1,8 @@
 #!/bin/sh
 # test command parsing and dispatch
 
+"$TESTDIR/hghave" no-outer-repo || exit 80
+
 hg init a
 cd a
 echo a > a
--- a/tests/test-export	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-export	Sun Dec 07 19:34:07 2008 +0100
@@ -13,3 +13,9 @@
     echo "# foo-$out.patch"
     hg export -v -o "foo-$out.patch" 2:tip
 done
+
+echo "# exporting 4 changesets to a file"
+hg export -o export_internal 1 2 3 4
+grep HG export_internal | wc -l | sed -e 's/^ *//'
+echo "# exporting 4 changesets to a file"
+hg export 1 2 3 4 | grep HG | wc -l | sed -e 's/^ *//'
--- a/tests/test-export.out	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-export.out	Sun Dec 07 19:34:07 2008 +0100
@@ -58,3 +58,7 @@
 foo-09.patch
 foo-10.patch
 foo-11.patch
+# exporting 4 changesets to a file
+4
+# exporting 4 changesets to a file
+4
--- a/tests/test-extension	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-extension	Sun Dec 07 19:34:07 2008 +0100
@@ -1,6 +1,8 @@
 #!/bin/sh
 # Test basic extension support
 
+"$TESTDIR/hghave" no-outer-repo || exit 80
+
 cat > foobar.py <<EOF
 import os
 from mercurial import commands
--- a/tests/test-fetch	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-fetch	Sun Dec 07 19:34:07 2008 +0100
@@ -37,6 +37,7 @@
 hg --cwd c fetch -d '4 0' -m 'automated merge' ../a
 ls c
 
+netstat -tnap 2>/dev/null | grep $HGPORT | grep LISTEN
 hg --cwd a serve -a localhost -p $HGPORT -d --pid-file=hg.pid
 cat a/hg.pid >> "$DAEMON_PIDS"
 
@@ -169,4 +170,6 @@
 hg -R n2 parents --template '{rev}\n'
 rm -fr n1 n2
 
+"$TESTDIR/killdaemons.py"
+
 true
--- a/tests/test-fetch.out	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-fetch.out	Sun Dec 07 19:34:07 2008 +0100
@@ -100,7 +100,7 @@
 adding changesets
 adding manifests
 adding file changes
-added 1 changesets with 1 changes to 2 files
+added 1 changesets with 1 changes to 1 files
 % parent should be 2 (no automatic update)
 2
 
--- a/tests/test-globalopts	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-globalopts	Sun Dec 07 19:34:07 2008 +0100
@@ -1,5 +1,7 @@
 #!/bin/sh
 
+"$TESTDIR/hghave" no-outer-repo || exit 80
+
 hg init a
 cd a
 echo a > a
--- a/tests/test-globalopts.out	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-globalopts.out	Sun Dec 07 19:34:07 2008 +0100
@@ -205,7 +205,7 @@
  environment  Environment Variables
  revisions    Specifying Single Revisions
  multirevs    Specifying Multiple Revisions
- gitdiffs     Using git Diffs
+ diffs        Diff Formats
 
 use "hg -v help" to show aliases and global options
 Mercurial Distributed SCM
@@ -268,7 +268,7 @@
  environment  Environment Variables
  revisions    Specifying Single Revisions
  multirevs    Specifying Multiple Revisions
- gitdiffs     Using git Diffs
+ diffs        Diff Formats
 
 use "hg -v help" to show aliases and global options
 %% not tested: --debugger
--- a/tests/test-glog	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-glog	Sun Dec 07 19:34:07 2008 +0100
@@ -70,6 +70,8 @@
 # |/
 # o  (0) root
 
+"$TESTDIR/hghave" no-outer-repo || exit 80
+
 set -e
 
 commit()
@@ -151,3 +153,16 @@
 hg glog -l1 repo/0
 hg glog -l1 repo/missing
 
+echo % file log with revs != cset revs
+hg init flog
+cd flog
+echo one >one
+hg add one
+hg commit -mone
+echo two >two
+hg add two
+hg commit -mtwo
+echo more >two
+hg commit -mmore
+hg glog two
+
--- a/tests/test-glog.out	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-glog.out	Sun Dec 07 19:34:07 2008 +0100
@@ -369,3 +369,15 @@
    date:        Thu Jan 01 00:00:00 1970 +0000
    summary:     (0) root
 
+% file log with revs != cset revs
+@  changeset:   2:12c28321755b
+|  tag:         tip
+|  user:        test
+|  date:        Thu Jan 01 00:00:00 1970 +0000
+|  summary:     more
+|
+o  changeset:   1:5ac72c0599bf
+   user:        test
+   date:        Thu Jan 01 00:00:00 1970 +0000
+   summary:     two
+
--- a/tests/test-help.out	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-help.out	Sun Dec 07 19:34:07 2008 +0100
@@ -96,7 +96,7 @@
  environment  Environment Variables
  revisions    Specifying Single Revisions
  multirevs    Specifying Multiple Revisions
- gitdiffs     Using git Diffs
+ diffs        Diff Formats
 
 use "hg -v help" to show aliases and global options
  add          add the specified files on the next commit
@@ -155,7 +155,7 @@
  environment  Environment Variables
  revisions    Specifying Single Revisions
  multirevs    Specifying Multiple Revisions
- gitdiffs     Using git Diffs
+ diffs        Diff Formats
 hg add [OPTION]... [FILE]...
 
 add the specified files on the next commit
@@ -216,7 +216,7 @@
     probably with undesirable results.
 
     Use the --git option to generate diffs in the git extended diff
-    format. Read the gitdiffs help topic for more information.
+    format. Read the diffs help topic for more information.
 
 options:
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-hgcia	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+cat >> $HGRCPATH <<EOF
+[extensions]
+hgcia=
+
+[hooks]
+changegroup.cia = python:hgext.hgcia.hook
+
+[cia]
+user = testuser
+project = testproject
+test = True
+EOF
+
+hg init src
+hg init cia
+
+cd src
+echo foo > foo
+hg ci -Amfoo
+
+hg push ../cia
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-hgcia.out	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,30 @@
+adding foo
+pushing to ../cia
+searching for changes
+adding changesets
+adding manifests
+adding file changes
+added 1 changesets with 1 changes to 1 files
+
+<message>
+  <generator>
+    <name>Mercurial (hgcia)</name>
+    <version>0.1</version>
+    <url>http://hg.kublai.com/mercurial/hgcia</url>
+    <user>testuser</user>
+  </generator>
+  <source>
+<project>testproject</project>
+<branch>default</branch>
+</source>
+  <body>
+    <commit>
+      <author>test</author>
+      <version>0:e63c23eaa88a</version>
+      <log>foo</log>
+      
+      <files><file action="add">foo</file></files>
+    </commit>
+  </body>
+  <timestamp>0</timestamp>
+</message>
--- a/tests/test-hgweb	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-hgweb	Sun Dec 07 19:34:07 2008 +0100
@@ -7,7 +7,7 @@
 echo foo > da/foo
 echo foo > foo
 hg ci -Ambase -d '0 0'
-hg serve -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
+hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
 cat hg.pid >> $DAEMON_PIDS
 echo % manifest
 ("$TESTDIR/get-with-headers.py" localhost:$HGPORT '/file/tip/?style=raw')
@@ -31,7 +31,7 @@
 "$TESTDIR/get-with-headers.py" localhost:$HGPORT '/diff/tip/bork?style=raw'
 
 echo % stop and restart
-kill `cat hg.pid`
+"$TESTDIR/killdaemons.py"
 hg serve -p $HGPORT -d --pid-file=hg.pid -A access.log
 cat hg.pid >> $DAEMON_PIDS
 # Test the access/error files are opened in append mode
Binary file tests/test-hgweb-commands.out has changed
--- a/tests/test-hgweb-descend-empties.out	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-hgweb-descend-empties.out	Sun Dec 07 19:34:07 2008 +0100
@@ -7,43 +7,66 @@
 % manifest with descending
 200 Script output follows
 
+<!-- quirksmode -->
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <html>
 <head>
 <link rel="icon" href="/static/hgicon.png" type="image/png">
 <meta name="robots" content="index, nofollow" />
-<link rel="stylesheet" href="/static/style.css" type="text/css" />
+<link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
 
-<title>test: files for changeset 9087c84a0f5d</title>
+<title>test: 9087c84a0f5d /</title>
 </head>
 <body>
 
-<div class="buttons">
-<a href="/log/0">changelog</a>
-<a href="/shortlog/0">shortlog</a>
-<a href="/graph">graph</a>
-<a href="/tags">tags</a>
-<a href="/rev/9087c84a0f5d">changeset</a>
-
-</div>
-
-<h2>files for changeset 9087c84a0f5d: /</h2>
-
-<table cellpadding="0" cellspacing="0">
-<tr class="parity0">
-  <td><tt>drwxr-xr-x</tt>&nbsp;
-  <td>&nbsp;
-  <td>&nbsp;
-  <td><a href="/file/9087c84a0f5d/">[up]</a>
-</tr>
-<tr class="parity1"><td><tt>drwxr-xr-x</tt>&nbsp;<td>&nbsp;<td>&nbsp;<td><a href="/file/9087c84a0f5d/a1">a1/</a> <a href="/file/9087c84a0f5d/a1/a2/a3/a4">a2/a3/a4</a><tr class="parity0"><td><tt>drwxr-xr-x</tt>&nbsp;<td>&nbsp;<td>&nbsp;<td><a href="/file/9087c84a0f5d/b1">b1/</a> <a href="/file/9087c84a0f5d/b1/b2">b2</a><tr class="parity1"><td><tt>drwxr-xr-x</tt>&nbsp;<td>&nbsp;<td>&nbsp;<td><a href="/file/9087c84a0f5d/d1">d1/</a> <a href="/file/9087c84a0f5d/d1/d2">d2</a>
-
-</table>
-
+<div class="container">
+<div class="menu">
 <div class="logo">
 <a href="http://www.selenic.com/mercurial/">
 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
 </div>
+<ul>
+<li><a href="/shortlog/9087c84a0f5d">log</a></li>
+<li><a href="/graph/9087c84a0f5d">graph</a></li>
+<li><a href="/tags">tags</a></li>
+</ul>
+<ul>
+<li><a href="/rev/9087c84a0f5d">changeset</a></li>
+<li class="active">browse</li>
+</ul>
+<ul>
+
+</ul>
+</div>
+
+<div class="main">
+<h2><a href="/">test</a></h2>
+<h3>directory / @ 0:9087c84a0f5d <span class="tag">tip</span> </h3>
+
+<form class="search" action="/log">
+
+<p><input name="rev" id="search1" type="text" size="30"></p>
+<span>find changesets by author, revision,
+files, or words in the commit message</span>
+</form>
+
+<table class="bigtable">
+<tr>
+  <th class="name">name</th>
+  <th class="size">size</th>
+  <th class="permissions">permissions</th>
+</tr>
+<tr class="fileline parity0">
+  <td class="name"><a href="/file/9087c84a0f5d/">[up]</a></td>
+  <td class="size"></td>
+  <td class="permissions">drwxr-xr-x</td>
+</tr>
+<tr class="fileline parity1"><td class="name"><a href="/file/9087c84a0f5d/a1"><img src="/static/coal-folder.png"> a1/</a> <a href="/file/9087c84a0f5d/a1/a2/a3/a4">a2/a3/a4</a><td class="size"></td><td class="permissions">drwxr-xr-x</td></tr><tr class="fileline parity0"><td class="name"><a href="/file/9087c84a0f5d/b1"><img src="/static/coal-folder.png"> b1/</a> <a href="/file/9087c84a0f5d/b1/b2">b2</a><td class="size"></td><td class="permissions">drwxr-xr-x</td></tr><tr class="fileline parity1"><td class="name"><a href="/file/9087c84a0f5d/d1"><img src="/static/coal-folder.png"> d1/</a> <a href="/file/9087c84a0f5d/d1/d2">d2</a><td class="size"></td><td class="permissions">drwxr-xr-x</td></tr>
+
+</table>
+</div>
+</div>
+
 
 </body>
 </html>
--- a/tests/test-hgweb-diffs	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-hgweb-diffs	Sun Dec 07 19:34:07 2008 +0100
@@ -20,7 +20,7 @@
 "$TESTDIR/get-with-headers.py" localhost:$HGPORT '/diff/tip/a'
 
 echo % set up hgweb with git diffs
-kill `cat hg.pid`
+"$TESTDIR/killdaemons.py"
 hg serve --config 'diff.git=1' -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
 cat hg.pid >> $DAEMON_PIDS
 
--- a/tests/test-hgweb-diffs.out	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-hgweb-diffs.out	Sun Dec 07 19:34:07 2008 +0100
@@ -6,267 +6,367 @@
 % revision
 200 Script output follows
 
+<!-- quirksmode -->
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <html>
 <head>
 <link rel="icon" href="/static/hgicon.png" type="image/png">
 <meta name="robots" content="index, nofollow" />
-<link rel="stylesheet" href="/static/style.css" type="text/css" />
+<link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
 
-<title>test: changeset 0cd96de13884</title>
+<title>test: 0cd96de13884</title>
 </head>
 <body>
-
-<div class="buttons">
-<a href="/log/0">changelog</a>
-<a href="/shortlog/0">shortlog</a>
-<a href="/graph">graph</a>
-<a href="/tags">tags</a>
-<a href="/file/0cd96de13884">files</a>
-<a href="/raw-rev/0cd96de13884">raw</a>
-
-</div>
-
-<h2>changeset: a</h2>
-
-<table id="changesetEntry">
-<tr>
- <th class="changeset">changeset 0:</th>
- <td class="changeset"><a href="/rev/0cd96de13884">0cd96de13884</a></td>
-</tr>
-
-<tr><th class="child">child 1:</th><td class="child"><a href="/rev/78e4ebad7cdf">78e4ebad7cdf</a></td></tr>
-
-<tr>
- <th class="author">author:</th>
- <td class="author">&#116;&#101;&#115;&#116;</td>
-</tr>
-<tr>
- <th class="date">date:</th>
- <td class="date">Thu Jan 01 00:00:00 1970 +0000 (38 years ago)</td>
-</tr>
-<tr>
- <th class="files">files:</th>
- <td class="files"><a href="/file/0cd96de13884/a">a</a> <a href="/file/0cd96de13884/b">b</a> </td>
-</tr>
-<tr>
- <th class="description">description:</th>
- <td class="description">a</td>
-</tr>
-</table>
-
-<div id="changesetDiff">
-<pre class="parity0"><span class="minusline"><a class="lineno" href="#l1.1" id="l1.1">     1.1</a>--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
-</span><span class="plusline"><a class="lineno" href="#l1.2" id="l1.2">     1.2</a>+++ b/a	Thu Jan 01 00:00:00 1970 +0000
-</span><span class="atline"><a class="lineno" href="#l1.3" id="l1.3">     1.3</a>@@ -0,0 +1,1 @@
-</span><span class="plusline"><a class="lineno" href="#l1.4" id="l1.4">     1.4</a>+a
-</span></pre><pre class="parity1"><span class="minusline"><a class="lineno" href="#l2.1" id="l2.1">     2.1</a>--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
-</span><span class="plusline"><a class="lineno" href="#l2.2" id="l2.2">     2.2</a>+++ b/b	Thu Jan 01 00:00:00 1970 +0000
-</span><span class="atline"><a class="lineno" href="#l2.3" id="l2.3">     2.3</a>@@ -0,0 +1,1 @@
-</span><span class="plusline"><a class="lineno" href="#l2.4" id="l2.4">     2.4</a>+b
-</span></pre>
-</div>
-
-
+<div class="container">
+<div class="menu">
 <div class="logo">
 <a href="http://www.selenic.com/mercurial/">
 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
 </div>
+<ul>
+ <li><a href="/shortlog/0cd96de13884">log</a></li>
+ <li><a href="/graph/0cd96de13884">graph</a></li>
+ <li><a href="/tags">tags</a></li>
+</ul>
+<ul>
+ <li class="active">changeset</li>
+ <li><a href="/raw-rev/0cd96de13884">raw</a></li>
+ <li><a href="/file/0cd96de13884">browse</a></li>
+</ul>
+<ul>
+ 
+</ul>
+</div>
+
+<div class="main">
+
+<h2><a href="/">test</a></h2>
+<h3>changeset 0:0cd96de13884  </h3>
+
+<form class="search" action="/log">
+
+<p><input name="rev" id="search1" type="text" size="30"></p>
+<span>find changesets by author, revision,
+files, or words in the commit message</span>
+</form>
+
+<div class="description">a</div>
+
+<table id="changesetEntry">
+<tr>
+ <th class="author">author</th>
+ <td class="author">&#116;&#101;&#115;&#116;</td>
+</tr>
+<tr>
+ <th class="date">date</th>
+ <td class="date">Thu Jan 01 00:00:00 1970 +0000 (38 years ago)</td></tr>
+<tr>
+ <th class="author">parents</th>
+ <td class="author"></td>
+</tr>
+<tr>
+ <th class="author">children</th>
+ <td class="author"><a href="/rev/78e4ebad7cdf">78e4ebad7cdf</a></td>
+</tr>
+<tr>
+ <th class="files">files</th>
+ <td class="files"><a href="/file/0cd96de13884/a">a</a> <a href="/file/0cd96de13884/b">b</a> </td>
+</tr>
+</table>
+
+<div class="overflow">
+<div class="sourcefirst">   line diff</div>
+
+<div class="source bottomline parity0"><a href="#l1.1" id="l1.1">     1.1</a> <span class="minusline">--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+</span><a href="#l1.2" id="l1.2">     1.2</a> <span class="plusline">+++ b/a	Thu Jan 01 00:00:00 1970 +0000
+</span><a href="#l1.3" id="l1.3">     1.3</a> <span class="atline">@@ -0,0 +1,1 @@
+</span><a href="#l1.4" id="l1.4">     1.4</a> <span class="plusline">+a
+</span></div><div class="source bottomline parity1"><a href="#l2.1" id="l2.1">     2.1</a> <span class="minusline">--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+</span><a href="#l2.2" id="l2.2">     2.2</a> <span class="plusline">+++ b/b	Thu Jan 01 00:00:00 1970 +0000
+</span><a href="#l2.3" id="l2.3">     2.3</a> <span class="atline">@@ -0,0 +1,1 @@
+</span><a href="#l2.4" id="l2.4">     2.4</a> <span class="plusline">+b
+</span></div>
+</div>
+
+</div>
+</div>
+
 
 </body>
 </html>
 
-
-
 % diff removed file
 200 Script output follows
 
+<!-- quirksmode -->
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <html>
 <head>
 <link rel="icon" href="/static/hgicon.png" type="image/png">
 <meta name="robots" content="index, nofollow" />
-<link rel="stylesheet" href="/static/style.css" type="text/css" />
+<link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
 
 <title>test: a diff</title>
 </head>
 <body>
 
-<div class="buttons">
-<a href="/log/1">changelog</a>
-<a href="/shortlog/1">shortlog</a>
-<a href="/graph">graph</a>
-<a href="/tags">tags</a>
-<a href="/rev/78e4ebad7cdf">changeset</a>
-<a href="/file/78e4ebad7cdf/a">file</a>
-<a href="/log/78e4ebad7cdf/a">revisions</a>
-<a href="/annotate/78e4ebad7cdf/a">annotate</a>
-<a href="/raw-diff/78e4ebad7cdf/a">raw</a>
-</div>
-
-<h2>a</h2>
-
-<table id="filediffEntry">
-<tr>
- <th class="revision">revision 1:</th>
- <td class="revision"><a href="/rev/78e4ebad7cdf">78e4ebad7cdf</a></td>
-</tr>
-
-
-</table>
-
-<div id="fileDiff">
-<pre class="parity0"><span class="minusline"><a class="lineno" href="#l1.1" id="l1.1">     1.1</a>--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
-</span><span class="plusline"><a class="lineno" href="#l1.2" id="l1.2">     1.2</a>+++ b/a	Thu Jan 01 00:00:00 1970 +0000
-</span><span class="atline"><a class="lineno" href="#l1.3" id="l1.3">     1.3</a>@@ -0,0 +1,1 @@
-</span><span class="plusline"><a class="lineno" href="#l1.4" id="l1.4">     1.4</a>+a
-</span></pre>
-</div>
-
-
+<div class="container">
+<div class="menu">
 <div class="logo">
 <a href="http://www.selenic.com/mercurial/">
 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
 </div>
+<ul>
+<li><a href="/shortlog/78e4ebad7cdf">log</a></li>
+<li><a href="/graph/78e4ebad7cdf">graph</a></li>
+<li><a href="/tags">tags</a></li>
+</ul>
+<ul>
+<li><a href="/rev/78e4ebad7cdf">changeset</a></li>
+<li><a href="/file/78e4ebad7cdf">browse</a></li>
+</ul>
+<ul>
+<li><a href="/file/78e4ebad7cdf/a">file</a></li>
+<li class="active">diff</li>
+<li><a href="/annotate/78e4ebad7cdf/a">annotate</a></li>
+<li><a href="/log/78e4ebad7cdf/a">file log</a></li>
+<li><a href="/raw-file/78e4ebad7cdf/a">raw</a></li>
+</ul>
+</div>
+
+<div class="main">
+<h2><a href="/">test</a></h2>
+<h3>diff a @ 1:78e4ebad7cdf</h3>
+
+<form class="search" action="/log">
+
+<p><input name="rev" id="search1" type="text" size="30"></p>
+<span>find changesets by author, revision,
+files, or words in the commit message</span>
+</form>
+
+<div class="description">b</div>
+
+<table id="changesetEntry">
+<tr>
+ <th>author</th>
+ <td>&#116;&#101;&#115;&#116;</td>
+</tr>
+<tr>
+ <th>date</th>
+ <td>Thu Jan 01 00:00:00 1970 +0000 (38 years ago)</td>
+</tr>
+<tr>
+ <th>parents</th>
+ <td></td>
+</tr>
+<tr>
+ <th>children</th>
+ <td></td>
+</tr>
+
+</table>
+
+<div class="overflow">
+<div class="sourcefirst">   line diff</div>
+
+<div class="source bottomline parity0"><a href="#l1.1" id="l1.1">     1.1</a> <span class="minusline">--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+</span><a href="#l1.2" id="l1.2">     1.2</a> <span class="plusline">+++ b/a	Thu Jan 01 00:00:00 1970 +0000
+</span><a href="#l1.3" id="l1.3">     1.3</a> <span class="atline">@@ -0,0 +1,1 @@
+</span><a href="#l1.4" id="l1.4">     1.4</a> <span class="plusline">+a
+</span></div>
+</div>
+</div>
+</div>
+
+
 
 </body>
 </html>
 
-
-
 % set up hgweb with git diffs
 % revision
 200 Script output follows
 
+<!-- quirksmode -->
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <html>
 <head>
 <link rel="icon" href="/static/hgicon.png" type="image/png">
 <meta name="robots" content="index, nofollow" />
-<link rel="stylesheet" href="/static/style.css" type="text/css" />
+<link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
 
-<title>test: changeset 0cd96de13884</title>
+<title>test: 0cd96de13884</title>
 </head>
 <body>
-
-<div class="buttons">
-<a href="/log/0">changelog</a>
-<a href="/shortlog/0">shortlog</a>
-<a href="/graph">graph</a>
-<a href="/tags">tags</a>
-<a href="/file/0cd96de13884">files</a>
-<a href="/raw-rev/0cd96de13884">raw</a>
-
-</div>
-
-<h2>changeset: a</h2>
-
-<table id="changesetEntry">
-<tr>
- <th class="changeset">changeset 0:</th>
- <td class="changeset"><a href="/rev/0cd96de13884">0cd96de13884</a></td>
-</tr>
-
-<tr><th class="child">child 1:</th><td class="child"><a href="/rev/78e4ebad7cdf">78e4ebad7cdf</a></td></tr>
-
-<tr>
- <th class="author">author:</th>
- <td class="author">&#116;&#101;&#115;&#116;</td>
-</tr>
-<tr>
- <th class="date">date:</th>
- <td class="date">Thu Jan 01 00:00:00 1970 +0000 (38 years ago)</td>
-</tr>
-<tr>
- <th class="files">files:</th>
- <td class="files"><a href="/file/0cd96de13884/a">a</a> <a href="/file/0cd96de13884/b">b</a> </td>
-</tr>
-<tr>
- <th class="description">description:</th>
- <td class="description">a</td>
-</tr>
-</table>
-
-<div id="changesetDiff">
-<pre class="parity0"><a class="lineno" href="#l1.1" id="l1.1">     1.1</a>new file mode 100644
-<span class="minusline"><a class="lineno" href="#l1.2" id="l1.2">     1.2</a>--- /dev/null
-</span><span class="plusline"><a class="lineno" href="#l1.3" id="l1.3">     1.3</a>+++ b/a
-</span><span class="atline"><a class="lineno" href="#l1.4" id="l1.4">     1.4</a>@@ -0,0 +1,1 @@
-</span><span class="plusline"><a class="lineno" href="#l1.5" id="l1.5">     1.5</a>+a
-</span></pre><pre class="parity1"><a class="lineno" href="#l2.1" id="l2.1">     2.1</a>new file mode 100644
-<span class="minusline"><a class="lineno" href="#l2.2" id="l2.2">     2.2</a>--- /dev/null
-</span><span class="plusline"><a class="lineno" href="#l2.3" id="l2.3">     2.3</a>+++ b/b
-</span><span class="atline"><a class="lineno" href="#l2.4" id="l2.4">     2.4</a>@@ -0,0 +1,1 @@
-</span><span class="plusline"><a class="lineno" href="#l2.5" id="l2.5">     2.5</a>+b
-</span></pre>
-</div>
-
-
+<div class="container">
+<div class="menu">
 <div class="logo">
 <a href="http://www.selenic.com/mercurial/">
 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
 </div>
+<ul>
+ <li><a href="/shortlog/0cd96de13884">log</a></li>
+ <li><a href="/graph/0cd96de13884">graph</a></li>
+ <li><a href="/tags">tags</a></li>
+</ul>
+<ul>
+ <li class="active">changeset</li>
+ <li><a href="/raw-rev/0cd96de13884">raw</a></li>
+ <li><a href="/file/0cd96de13884">browse</a></li>
+</ul>
+<ul>
+ 
+</ul>
+</div>
+
+<div class="main">
+
+<h2><a href="/">test</a></h2>
+<h3>changeset 0:0cd96de13884  </h3>
+
+<form class="search" action="/log">
+
+<p><input name="rev" id="search1" type="text" size="30"></p>
+<span>find changesets by author, revision,
+files, or words in the commit message</span>
+</form>
+
+<div class="description">a</div>
+
+<table id="changesetEntry">
+<tr>
+ <th class="author">author</th>
+ <td class="author">&#116;&#101;&#115;&#116;</td>
+</tr>
+<tr>
+ <th class="date">date</th>
+ <td class="date">Thu Jan 01 00:00:00 1970 +0000 (38 years ago)</td></tr>
+<tr>
+ <th class="author">parents</th>
+ <td class="author"></td>
+</tr>
+<tr>
+ <th class="author">children</th>
+ <td class="author"><a href="/rev/78e4ebad7cdf">78e4ebad7cdf</a></td>
+</tr>
+<tr>
+ <th class="files">files</th>
+ <td class="files"><a href="/file/0cd96de13884/a">a</a> <a href="/file/0cd96de13884/b">b</a> </td>
+</tr>
+</table>
+
+<div class="overflow">
+<div class="sourcefirst">   line diff</div>
+
+<div class="source bottomline parity0"><a href="#l1.1" id="l1.1">     1.1</a> new file mode 100644
+<a href="#l1.2" id="l1.2">     1.2</a> <span class="minusline">--- /dev/null
+</span><a href="#l1.3" id="l1.3">     1.3</a> <span class="plusline">+++ b/a
+</span><a href="#l1.4" id="l1.4">     1.4</a> <span class="atline">@@ -0,0 +1,1 @@
+</span><a href="#l1.5" id="l1.5">     1.5</a> <span class="plusline">+a
+</span></div><div class="source bottomline parity1"><a href="#l2.1" id="l2.1">     2.1</a> new file mode 100644
+<a href="#l2.2" id="l2.2">     2.2</a> <span class="minusline">--- /dev/null
+</span><a href="#l2.3" id="l2.3">     2.3</a> <span class="plusline">+++ b/b
+</span><a href="#l2.4" id="l2.4">     2.4</a> <span class="atline">@@ -0,0 +1,1 @@
+</span><a href="#l2.5" id="l2.5">     2.5</a> <span class="plusline">+b
+</span></div>
+</div>
+
+</div>
+</div>
+
 
 </body>
 </html>
 
-
-
 % diff removed file
 200 Script output follows
 
+<!-- quirksmode -->
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <html>
 <head>
 <link rel="icon" href="/static/hgicon.png" type="image/png">
 <meta name="robots" content="index, nofollow" />
-<link rel="stylesheet" href="/static/style.css" type="text/css" />
+<link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
 
 <title>test: a diff</title>
 </head>
 <body>
 
-<div class="buttons">
-<a href="/log/1">changelog</a>
-<a href="/shortlog/1">shortlog</a>
-<a href="/graph">graph</a>
-<a href="/tags">tags</a>
-<a href="/rev/78e4ebad7cdf">changeset</a>
-<a href="/file/78e4ebad7cdf/a">file</a>
-<a href="/log/78e4ebad7cdf/a">revisions</a>
-<a href="/annotate/78e4ebad7cdf/a">annotate</a>
-<a href="/raw-diff/78e4ebad7cdf/a">raw</a>
-</div>
-
-<h2>a</h2>
-
-<table id="filediffEntry">
-<tr>
- <th class="revision">revision 1:</th>
- <td class="revision"><a href="/rev/78e4ebad7cdf">78e4ebad7cdf</a></td>
-</tr>
-
-
-</table>
-
-<div id="fileDiff">
-<pre class="parity0"><a class="lineno" href="#l1.1" id="l1.1">     1.1</a>new file mode 100755
-<span class="minusline"><a class="lineno" href="#l1.2" id="l1.2">     1.2</a>--- /dev/null
-</span><span class="plusline"><a class="lineno" href="#l1.3" id="l1.3">     1.3</a>+++ b/a
-</span><span class="atline"><a class="lineno" href="#l1.4" id="l1.4">     1.4</a>@@ -0,0 +1,1 @@
-</span><span class="plusline"><a class="lineno" href="#l1.5" id="l1.5">     1.5</a>+a
-</span></pre>
-</div>
-
-
+<div class="container">
+<div class="menu">
 <div class="logo">
 <a href="http://www.selenic.com/mercurial/">
 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
 </div>
+<ul>
+<li><a href="/shortlog/78e4ebad7cdf">log</a></li>
+<li><a href="/graph/78e4ebad7cdf">graph</a></li>
+<li><a href="/tags">tags</a></li>
+</ul>
+<ul>
+<li><a href="/rev/78e4ebad7cdf">changeset</a></li>
+<li><a href="/file/78e4ebad7cdf">browse</a></li>
+</ul>
+<ul>
+<li><a href="/file/78e4ebad7cdf/a">file</a></li>
+<li class="active">diff</li>
+<li><a href="/annotate/78e4ebad7cdf/a">annotate</a></li>
+<li><a href="/log/78e4ebad7cdf/a">file log</a></li>
+<li><a href="/raw-file/78e4ebad7cdf/a">raw</a></li>
+</ul>
+</div>
+
+<div class="main">
+<h2><a href="/">test</a></h2>
+<h3>diff a @ 1:78e4ebad7cdf</h3>
+
+<form class="search" action="/log">
+
+<p><input name="rev" id="search1" type="text" size="30"></p>
+<span>find changesets by author, revision,
+files, or words in the commit message</span>
+</form>
+
+<div class="description">b</div>
+
+<table id="changesetEntry">
+<tr>
+ <th>author</th>
+ <td>&#116;&#101;&#115;&#116;</td>
+</tr>
+<tr>
+ <th>date</th>
+ <td>Thu Jan 01 00:00:00 1970 +0000 (38 years ago)</td>
+</tr>
+<tr>
+ <th>parents</th>
+ <td></td>
+</tr>
+<tr>
+ <th>children</th>
+ <td></td>
+</tr>
+
+</table>
+
+<div class="overflow">
+<div class="sourcefirst">   line diff</div>
+
+<div class="source bottomline parity0"><a href="#l1.1" id="l1.1">     1.1</a> new file mode 100755
+<a href="#l1.2" id="l1.2">     1.2</a> <span class="minusline">--- /dev/null
+</span><a href="#l1.3" id="l1.3">     1.3</a> <span class="plusline">+++ b/a
+</span><a href="#l1.4" id="l1.4">     1.4</a> <span class="atline">@@ -0,0 +1,1 @@
+</span><a href="#l1.5" id="l1.5">     1.5</a> <span class="plusline">+a
+</span></div>
+</div>
+</div>
+</div>
+
+
 
 </body>
 </html>
 
-
-
 % errors
--- a/tests/test-hgweb-filelog.out	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-hgweb-filelog.out	Sun Dec 07 19:34:07 2008 +0100
@@ -60,12 +60,13 @@
 % tip - two revisions
 200 Script output follows
 
+<!-- quirksmode -->
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <html>
 <head>
 <link rel="icon" href="/static/hgicon.png" type="image/png">
 <meta name="robots" content="index, nofollow" />
-<link rel="stylesheet" href="/static/style.css" type="text/css" />
+<link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
 
 <title>test: a history</title>
 <link rel="alternate" type="application/atom+xml"
@@ -75,78 +76,66 @@
 </head>
 <body>
 
-<div class="buttons">
-<a href="/log">changelog</a>
-<a href="/shortlog">shortlog</a>
-<a href="/graph">graph</a>
-<a href="/tags">tags</a>
-<a href="/file/01de2d66a28d/a">file</a>
-<a href="/annotate/01de2d66a28d/a">annotate</a>
-<a type="application/rss+xml" href="/rss-log/tip/a">rss</a>
-<a type="application/atom+xml" href="/atom-log/tip/a" title="Atom feed for test:a">atom</a>
-</div>
-
-<h2>a revision history</h2>
-
-<p>navigate: <small class="navigate"><a href="/log/5ed941583260/a">(0)</a> <a href="/log/tip/a">tip</a> </small></p>
-
-<table class="logEntry parity0">
- <tr>
-  <th class="age">38 years ago:</th>
-  <th class="firstline"><a href="/rev/01de2d66a28d">second a</a></th>
- </tr>
- <tr>
-  <th class="revision">revision 1:</td>
-  <td class="node">
-   <a href="/file/01de2d66a28d/a">01de2d66a28d</a>
-   <a href="/diff/01de2d66a28d/a">(diff)</a>
-   <a href="/annotate/01de2d66a28d/a">(annotate)</a>
-  </td>
- </tr>
- 
- <tr>
-  <th class="author">author:</th>
-  <td class="author">&#116;&#101;&#115;&#116;</td>
- </tr>
- <tr>
-  <th class="date">date:</th>
-  <td class="date">Thu Jan 01 00:00:00 1970 +0000</td>
- </tr>
-</table>
-
-
-<table class="logEntry parity1">
- <tr>
-  <th class="age">38 years ago:</th>
-  <th class="firstline"><a href="/rev/5ed941583260">first a</a></th>
- </tr>
- <tr>
-  <th class="revision">revision 0:</td>
-  <td class="node">
-   <a href="/file/5ed941583260/a">5ed941583260</a>
-   <a href="/diff/5ed941583260/a">(diff)</a>
-   <a href="/annotate/5ed941583260/a">(annotate)</a>
-  </td>
- </tr>
- 
- <tr>
-  <th class="author">author:</th>
-  <td class="author">&#116;&#101;&#115;&#116;</td>
- </tr>
- <tr>
-  <th class="date">date:</th>
-  <td class="date">Thu Jan 01 00:00:00 1970 +0000</td>
- </tr>
-</table>
-
-
-
-
-
+<div class="container">
+<div class="menu">
 <div class="logo">
 <a href="http://www.selenic.com/mercurial/">
 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
 </div>
+<ul>
+<li><a href="/shortlog/01de2d66a28d">log</a></li>
+<li><a href="/graph/01de2d66a28d">graph</a></li>
+<li><a href="/tags">tags</a></li>
+</ul>
+<ul>
+<li><a href="/rev/01de2d66a28d">changeset</a></li>
+<li><a href="/file/01de2d66a28d">browse</a></li>
+</ul>
+<ul>
+<li><a href="/file/01de2d66a28d/a">file</a></li>
+<li><a href="/diff/01de2d66a28d/a">diff</a></li>
+<li><a href="/annotate/01de2d66a28d/a">annotate</a></li>
+<li class="active">file log</li>
+<li><a href="/raw-file/01de2d66a28d/a">raw</a></li>
+</ul>
+</div>
+
+<div class="main">
+<h2><a href="/">test</a></h2>
+<h3>log a</h3>
+
+<form class="search" action="/log">
+
+<p><input name="rev" id="search1" type="text" size="30"></p>
+<span>find changesets by author, revision,
+files, or words in the commit message</span>
+</form>
+
+<div class="navigate"><a href="/log/5ed941583260/a">(0)</a> <a href="/log/tip/a">tip</a> </div>
+
+<table class="bigtable">
+ <tr>
+  <th class="age">age</th>
+  <th class="author">author</th>
+  <th class="description">description</th>
+ </tr>
+ <tr class="parity0">
+  <td class="age">38 years</td>
+  <td class="author">test</td>
+  <td class="description"><a href="/rev/01de2d66a28d">second a</a></td>
+ </tr>
+ <tr class="parity1">
+  <td class="age">38 years</td>
+  <td class="author">test</td>
+  <td class="description"><a href="/rev/5ed941583260">first a</a></td>
+ </tr>
+
+</table>
+
+</div>
+</div>
+
+
 
 </body>
 </html>
@@ -154,12 +143,96 @@
 % second version - two revisions
 200 Script output follows
 
+<!-- quirksmode -->
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <html>
 <head>
 <link rel="icon" href="/static/hgicon.png" type="image/png">
 <meta name="robots" content="index, nofollow" />
-<link rel="stylesheet" href="/static/style.css" type="text/css" />
+<link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
+
+<title>test: a history</title>
+<link rel="alternate" type="application/atom+xml"
+   href="/atom-log/tip/a" title="Atom feed for test:a">
+<link rel="alternate" type="application/rss+xml"
+   href="/rss-log/tip/a" title="RSS feed for test:a">
+</head>
+<body>
+
+<div class="container">
+<div class="menu">
+<div class="logo">
+<a href="http://www.selenic.com/mercurial/">
+<img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
+</div>
+<ul>
+<li><a href="/shortlog/01de2d66a28d">log</a></li>
+<li><a href="/graph/01de2d66a28d">graph</a></li>
+<li><a href="/tags">tags</a></li>
+</ul>
+<ul>
+<li><a href="/rev/01de2d66a28d">changeset</a></li>
+<li><a href="/file/01de2d66a28d">browse</a></li>
+</ul>
+<ul>
+<li><a href="/file/01de2d66a28d/a">file</a></li>
+<li><a href="/diff/01de2d66a28d/a">diff</a></li>
+<li><a href="/annotate/01de2d66a28d/a">annotate</a></li>
+<li class="active">file log</li>
+<li><a href="/raw-file/01de2d66a28d/a">raw</a></li>
+</ul>
+</div>
+
+<div class="main">
+<h2><a href="/">test</a></h2>
+<h3>log a</h3>
+
+<form class="search" action="/log">
+
+<p><input name="rev" id="search1" type="text" size="30"></p>
+<span>find changesets by author, revision,
+files, or words in the commit message</span>
+</form>
+
+<div class="navigate"><a href="/log/5ed941583260/a">(0)</a> <a href="/log/tip/a">tip</a> </div>
+
+<table class="bigtable">
+ <tr>
+  <th class="age">age</th>
+  <th class="author">author</th>
+  <th class="description">description</th>
+ </tr>
+ <tr class="parity0">
+  <td class="age">38 years</td>
+  <td class="author">test</td>
+  <td class="description"><a href="/rev/01de2d66a28d">second a</a></td>
+ </tr>
+ <tr class="parity1">
+  <td class="age">38 years</td>
+  <td class="author">test</td>
+  <td class="description"><a href="/rev/5ed941583260">first a</a></td>
+ </tr>
+
+</table>
+
+</div>
+</div>
+
+
+
+</body>
+</html>
+
+% first deleted - one revision
+200 Script output follows
+
+<!-- quirksmode -->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+<link rel="icon" href="/static/hgicon.png" type="image/png">
+<meta name="robots" content="index, nofollow" />
+<link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
 
 <title>test: a history</title>
 <link rel="alternate" type="application/atom+xml"
@@ -169,91 +242,75 @@
 </head>
 <body>
 
-<div class="buttons">
-<a href="/log">changelog</a>
-<a href="/shortlog">shortlog</a>
-<a href="/graph">graph</a>
-<a href="/tags">tags</a>
-<a href="/file/01de2d66a28d/a">file</a>
-<a href="/annotate/01de2d66a28d/a">annotate</a>
-<a type="application/rss+xml" href="/rss-log/tip/a">rss</a>
-<a type="application/atom+xml" href="/atom-log/tip/a" title="Atom feed for test:a">atom</a>
-</div>
-
-<h2>a revision history</h2>
-
-<p>navigate: <small class="navigate"><a href="/log/5ed941583260/a">(0)</a> <a href="/log/tip/a">tip</a> </small></p>
-
-<table class="logEntry parity0">
- <tr>
-  <th class="age">38 years ago:</th>
-  <th class="firstline"><a href="/rev/01de2d66a28d">second a</a></th>
- </tr>
- <tr>
-  <th class="revision">revision 1:</td>
-  <td class="node">
-   <a href="/file/01de2d66a28d/a">01de2d66a28d</a>
-   <a href="/diff/01de2d66a28d/a">(diff)</a>
-   <a href="/annotate/01de2d66a28d/a">(annotate)</a>
-  </td>
- </tr>
- 
- <tr>
-  <th class="author">author:</th>
-  <td class="author">&#116;&#101;&#115;&#116;</td>
- </tr>
- <tr>
-  <th class="date">date:</th>
-  <td class="date">Thu Jan 01 00:00:00 1970 +0000</td>
- </tr>
-</table>
-
-
-<table class="logEntry parity1">
- <tr>
-  <th class="age">38 years ago:</th>
-  <th class="firstline"><a href="/rev/5ed941583260">first a</a></th>
- </tr>
- <tr>
-  <th class="revision">revision 0:</td>
-  <td class="node">
-   <a href="/file/5ed941583260/a">5ed941583260</a>
-   <a href="/diff/5ed941583260/a">(diff)</a>
-   <a href="/annotate/5ed941583260/a">(annotate)</a>
-  </td>
- </tr>
- 
- <tr>
-  <th class="author">author:</th>
-  <td class="author">&#116;&#101;&#115;&#116;</td>
- </tr>
- <tr>
-  <th class="date">date:</th>
-  <td class="date">Thu Jan 01 00:00:00 1970 +0000</td>
- </tr>
-</table>
-
-
-
-
-
+<div class="container">
+<div class="menu">
 <div class="logo">
 <a href="http://www.selenic.com/mercurial/">
 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
 </div>
+<ul>
+<li><a href="/shortlog/5ed941583260">log</a></li>
+<li><a href="/graph/5ed941583260">graph</a></li>
+<li><a href="/tags">tags</a></li>
+</ul>
+<ul>
+<li><a href="/rev/5ed941583260">changeset</a></li>
+<li><a href="/file/5ed941583260">browse</a></li>
+</ul>
+<ul>
+<li><a href="/file/5ed941583260/a">file</a></li>
+<li><a href="/diff/5ed941583260/a">diff</a></li>
+<li><a href="/annotate/5ed941583260/a">annotate</a></li>
+<li class="active">file log</li>
+<li><a href="/raw-file/5ed941583260/a">raw</a></li>
+</ul>
+</div>
+
+<div class="main">
+<h2><a href="/">test</a></h2>
+<h3>log a</h3>
+
+<form class="search" action="/log">
+
+<p><input name="rev" id="search1" type="text" size="30"></p>
+<span>find changesets by author, revision,
+files, or words in the commit message</span>
+</form>
+
+<div class="navigate"><a href="/log/5ed941583260/a">(0)</a> <a href="/log/tip/a">tip</a> </div>
+
+<table class="bigtable">
+ <tr>
+  <th class="age">age</th>
+  <th class="author">author</th>
+  <th class="description">description</th>
+ </tr>
+ <tr class="parity0">
+  <td class="age">38 years</td>
+  <td class="author">test</td>
+  <td class="description"><a href="/rev/5ed941583260">first a</a></td>
+ </tr>
+
+</table>
+
+</div>
+</div>
+
+
 
 </body>
 </html>
 
-% first deleted - one revision
+% first version - one revision
 200 Script output follows
 
+<!-- quirksmode -->
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <html>
 <head>
 <link rel="icon" href="/static/hgicon.png" type="image/png">
 <meta name="robots" content="index, nofollow" />
-<link rel="stylesheet" href="/static/style.css" type="text/css" />
+<link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
 
 <title>test: a history</title>
 <link rel="alternate" type="application/atom+xml"
@@ -263,122 +320,61 @@
 </head>
 <body>
 
-<div class="buttons">
-<a href="/log">changelog</a>
-<a href="/shortlog">shortlog</a>
-<a href="/graph">graph</a>
-<a href="/tags">tags</a>
-<a href="/file/5ed941583260/a">file</a>
-<a href="/annotate/5ed941583260/a">annotate</a>
-<a type="application/rss+xml" href="/rss-log/tip/a">rss</a>
-<a type="application/atom+xml" href="/atom-log/tip/a" title="Atom feed for test:a">atom</a>
-</div>
-
-<h2>a revision history</h2>
-
-<p>navigate: <small class="navigate"><a href="/log/5ed941583260/a">(0)</a> <a href="/log/tip/a">tip</a> </small></p>
-
-<table class="logEntry parity0">
- <tr>
-  <th class="age">38 years ago:</th>
-  <th class="firstline"><a href="/rev/5ed941583260">first a</a></th>
- </tr>
- <tr>
-  <th class="revision">revision 0:</td>
-  <td class="node">
-   <a href="/file/5ed941583260/a">5ed941583260</a>
-   <a href="/diff/5ed941583260/a">(diff)</a>
-   <a href="/annotate/5ed941583260/a">(annotate)</a>
-  </td>
- </tr>
- 
- <tr>
-  <th class="author">author:</th>
-  <td class="author">&#116;&#101;&#115;&#116;</td>
- </tr>
- <tr>
-  <th class="date">date:</th>
-  <td class="date">Thu Jan 01 00:00:00 1970 +0000</td>
- </tr>
-</table>
-
-
-
-
-
+<div class="container">
+<div class="menu">
 <div class="logo">
 <a href="http://www.selenic.com/mercurial/">
 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
 </div>
-
-</body>
-</html>
-
-% first version - one revision
-200 Script output follows
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
-<head>
-<link rel="icon" href="/static/hgicon.png" type="image/png">
-<meta name="robots" content="index, nofollow" />
-<link rel="stylesheet" href="/static/style.css" type="text/css" />
-
-<title>test: a history</title>
-<link rel="alternate" type="application/atom+xml"
-   href="/atom-log/tip/a" title="Atom feed for test:a">
-<link rel="alternate" type="application/rss+xml"
-   href="/rss-log/tip/a" title="RSS feed for test:a">
-</head>
-<body>
-
-<div class="buttons">
-<a href="/log">changelog</a>
-<a href="/shortlog">shortlog</a>
-<a href="/graph">graph</a>
-<a href="/tags">tags</a>
-<a href="/file/5ed941583260/a">file</a>
-<a href="/annotate/5ed941583260/a">annotate</a>
-<a type="application/rss+xml" href="/rss-log/tip/a">rss</a>
-<a type="application/atom+xml" href="/atom-log/tip/a" title="Atom feed for test:a">atom</a>
+<ul>
+<li><a href="/shortlog/5ed941583260">log</a></li>
+<li><a href="/graph/5ed941583260">graph</a></li>
+<li><a href="/tags">tags</a></li>
+</ul>
+<ul>
+<li><a href="/rev/5ed941583260">changeset</a></li>
+<li><a href="/file/5ed941583260">browse</a></li>
+</ul>
+<ul>
+<li><a href="/file/5ed941583260/a">file</a></li>
+<li><a href="/diff/5ed941583260/a">diff</a></li>
+<li><a href="/annotate/5ed941583260/a">annotate</a></li>
+<li class="active">file log</li>
+<li><a href="/raw-file/5ed941583260/a">raw</a></li>
+</ul>
 </div>
 
-<h2>a revision history</h2>
+<div class="main">
+<h2><a href="/">test</a></h2>
+<h3>log a</h3>
 
-<p>navigate: <small class="navigate"><a href="/log/5ed941583260/a">(0)</a> <a href="/log/tip/a">tip</a> </small></p>
+<form class="search" action="/log">
 
-<table class="logEntry parity0">
- <tr>
-  <th class="age">38 years ago:</th>
-  <th class="firstline"><a href="/rev/5ed941583260">first a</a></th>
- </tr>
+<p><input name="rev" id="search1" type="text" size="30"></p>
+<span>find changesets by author, revision,
+files, or words in the commit message</span>
+</form>
+
+<div class="navigate"><a href="/log/5ed941583260/a">(0)</a> <a href="/log/tip/a">tip</a> </div>
+
+<table class="bigtable">
  <tr>
-  <th class="revision">revision 0:</td>
-  <td class="node">
-   <a href="/file/5ed941583260/a">5ed941583260</a>
-   <a href="/diff/5ed941583260/a">(diff)</a>
-   <a href="/annotate/5ed941583260/a">(annotate)</a>
-  </td>
+  <th class="age">age</th>
+  <th class="author">author</th>
+  <th class="description">description</th>
  </tr>
- 
- <tr>
-  <th class="author">author:</th>
-  <td class="author">&#116;&#101;&#115;&#116;</td>
+ <tr class="parity0">
+  <td class="age">38 years</td>
+  <td class="author">test</td>
+  <td class="description"><a href="/rev/5ed941583260">first a</a></td>
  </tr>
- <tr>
-  <th class="date">date:</th>
-  <td class="date">Thu Jan 01 00:00:00 1970 +0000</td>
- </tr>
+
 </table>
 
-
-
+</div>
+</div>
 
 
-<div class="logo">
-<a href="http://www.selenic.com/mercurial/">
-<img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
-</div>
 
 </body>
 </html>
@@ -386,31 +382,55 @@
 % before addition - error
 404 Not Found
 
+<!-- quirksmode -->
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <html>
 <head>
 <link rel="icon" href="/static/hgicon.png" type="image/png">
 <meta name="robots" content="index, nofollow" />
-<link rel="stylesheet" href="/static/style.css" type="text/css" />
+<link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
 
-<title>Mercurial Error</title>
+<title>test: error</title>
 </head>
 <body>
 
-<h2>Mercurial Error</h2>
+<div class="container">
+<div class="menu">
+<div class="logo">
+<a href="http://www.selenic.com/mercurial/">
+<img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
+</div>
+<ul>
+<li><a href="/shortlog">log</a></li>
+<li><a href="/graph">graph</a></li>
+<li><a href="/tags">tags</a></li>
+</ul>
+</div>
 
+<div class="main">
+
+<h2><a href="/">test</a></h2>
+<h3>error</h3>
+
+<form class="search" action="/log">
+
+<p><input name="rev" id="search1" type="text" size="30"></p>
+<span>find changesets by author, revision,
+files, or words in the commit message</span>
+</form>
+
+<div class="description">
 <p>
 An error occurred while processing your request:
 </p>
 <p>
 a@6563da9dcf87: not found in manifest
 </p>
+</div>
+</div>
+</div>
 
 
-<div class="logo">
-<a href="http://www.selenic.com/mercurial/">
-<img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
-</div>
 
 </body>
 </html>
--- a/tests/test-hgweb-removed.out	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-hgweb-removed.out	Sun Dec 07 19:34:07 2008 +0100
@@ -4,127 +4,177 @@
 % revision
 200 Script output follows
 
+<!-- quirksmode -->
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <html>
 <head>
 <link rel="icon" href="/static/hgicon.png" type="image/png">
 <meta name="robots" content="index, nofollow" />
-<link rel="stylesheet" href="/static/style.css" type="text/css" />
+<link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
 
-<title>test: changeset c78f6c5cbea9</title>
+<title>test: c78f6c5cbea9</title>
 </head>
 <body>
-
-<div class="buttons">
-<a href="/log/1">changelog</a>
-<a href="/shortlog/1">shortlog</a>
-<a href="/graph">graph</a>
-<a href="/tags">tags</a>
-<a href="/file/c78f6c5cbea9">files</a>
-<a href="/raw-rev/c78f6c5cbea9">raw</a>
-
-</div>
-
-<h2>changeset: del</h2>
-
-<table id="changesetEntry">
-<tr>
- <th class="changeset">changeset 1:</th>
- <td class="changeset"><a href="/rev/c78f6c5cbea9">c78f6c5cbea9</a></td>
-</tr>
-<tr><th class="parent">parent 0:</th><td class="parent"><a href="/rev/cb9a9f314b8b">cb9a9f314b8b</a></td></tr>
-
-<tr><th class="tag">tag:</th><td class="tag">tip</td></tr>
-<tr>
- <th class="author">author:</th>
- <td class="author">&#116;&#101;&#115;&#116;</td>
-</tr>
-<tr>
- <th class="date">date:</th>
- <td class="date">Thu Jan 01 00:00:00 1970 +0000 (38 years ago)</td>
-</tr>
-<tr>
- <th class="files">files:</th>
- <td class="files">a </td>
-</tr>
-<tr>
- <th class="description">description:</th>
- <td class="description">del</td>
-</tr>
-</table>
-
-<div id="changesetDiff">
-<pre class="parity0"><span class="minusline"><a class="lineno" href="#l1.1" id="l1.1">     1.1</a>--- a/a	Thu Jan 01 00:00:00 1970 +0000
-</span><span class="plusline"><a class="lineno" href="#l1.2" id="l1.2">     1.2</a>+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
-</span><span class="atline"><a class="lineno" href="#l1.3" id="l1.3">     1.3</a>@@ -1,1 +0,0 @@
-</span><span class="minusline"><a class="lineno" href="#l1.4" id="l1.4">     1.4</a>-a
-</span></pre>
-</div>
-
-
+<div class="container">
+<div class="menu">
 <div class="logo">
 <a href="http://www.selenic.com/mercurial/">
 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
 </div>
+<ul>
+ <li><a href="/shortlog/c78f6c5cbea9">log</a></li>
+ <li><a href="/graph/c78f6c5cbea9">graph</a></li>
+ <li><a href="/tags">tags</a></li>
+</ul>
+<ul>
+ <li class="active">changeset</li>
+ <li><a href="/raw-rev/c78f6c5cbea9">raw</a></li>
+ <li><a href="/file/c78f6c5cbea9">browse</a></li>
+</ul>
+<ul>
+ 
+</ul>
+</div>
+
+<div class="main">
+
+<h2><a href="/">test</a></h2>
+<h3>changeset 1:c78f6c5cbea9  <span class="tag">tip</span> </h3>
+
+<form class="search" action="/log">
+
+<p><input name="rev" id="search1" type="text" size="30"></p>
+<span>find changesets by author, revision,
+files, or words in the commit message</span>
+</form>
+
+<div class="description">del</div>
+
+<table id="changesetEntry">
+<tr>
+ <th class="author">author</th>
+ <td class="author">&#116;&#101;&#115;&#116;</td>
+</tr>
+<tr>
+ <th class="date">date</th>
+ <td class="date">Thu Jan 01 00:00:00 1970 +0000 (38 years ago)</td></tr>
+<tr>
+ <th class="author">parents</th>
+ <td class="author"><a href="/rev/cb9a9f314b8b">cb9a9f314b8b</a> </td>
+</tr>
+<tr>
+ <th class="author">children</th>
+ <td class="author"></td>
+</tr>
+<tr>
+ <th class="files">files</th>
+ <td class="files">a </td>
+</tr>
+</table>
+
+<div class="overflow">
+<div class="sourcefirst">   line diff</div>
+
+<div class="source bottomline parity0"><a href="#l1.1" id="l1.1">     1.1</a> <span class="minusline">--- a/a	Thu Jan 01 00:00:00 1970 +0000
+</span><a href="#l1.2" id="l1.2">     1.2</a> <span class="plusline">+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
+</span><a href="#l1.3" id="l1.3">     1.3</a> <span class="atline">@@ -1,1 +0,0 @@
+</span><a href="#l1.4" id="l1.4">     1.4</a> <span class="minusline">-a
+</span></div>
+</div>
+
+</div>
+</div>
+
 
 </body>
 </html>
 
-
-
 % diff removed file
 200 Script output follows
 
+<!-- quirksmode -->
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <html>
 <head>
 <link rel="icon" href="/static/hgicon.png" type="image/png">
 <meta name="robots" content="index, nofollow" />
-<link rel="stylesheet" href="/static/style.css" type="text/css" />
+<link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
 
 <title>test: a diff</title>
 </head>
 <body>
 
-<div class="buttons">
-<a href="/log/1">changelog</a>
-<a href="/shortlog/1">shortlog</a>
-<a href="/graph">graph</a>
-<a href="/tags">tags</a>
-<a href="/rev/c78f6c5cbea9">changeset</a>
-<a href="/file/c78f6c5cbea9/a">file</a>
-<a href="/log/c78f6c5cbea9/a">revisions</a>
-<a href="/annotate/c78f6c5cbea9/a">annotate</a>
-<a href="/raw-diff/c78f6c5cbea9/a">raw</a>
-</div>
-
-<h2>a</h2>
-
-<table id="filediffEntry">
-<tr>
- <th class="revision">revision 1:</th>
- <td class="revision"><a href="/rev/c78f6c5cbea9">c78f6c5cbea9</a></td>
-</tr>
-<tr><th class="parent">parent 0:</th><td class="parent"><a href="/rev/cb9a9f314b8b">cb9a9f314b8b</a></td></tr>
-
-</table>
-
-<div id="fileDiff">
-<pre class="parity0"><span class="minusline"><a class="lineno" href="#l1.1" id="l1.1">     1.1</a>--- a/a	Thu Jan 01 00:00:00 1970 +0000
-</span><span class="plusline"><a class="lineno" href="#l1.2" id="l1.2">     1.2</a>+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
-</span><span class="atline"><a class="lineno" href="#l1.3" id="l1.3">     1.3</a>@@ -1,1 +0,0 @@
-</span><span class="minusline"><a class="lineno" href="#l1.4" id="l1.4">     1.4</a>-a
-</span></pre>
-</div>
-
-
+<div class="container">
+<div class="menu">
 <div class="logo">
 <a href="http://www.selenic.com/mercurial/">
 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
 </div>
+<ul>
+<li><a href="/shortlog/c78f6c5cbea9">log</a></li>
+<li><a href="/graph/c78f6c5cbea9">graph</a></li>
+<li><a href="/tags">tags</a></li>
+</ul>
+<ul>
+<li><a href="/rev/c78f6c5cbea9">changeset</a></li>
+<li><a href="/file/c78f6c5cbea9">browse</a></li>
+</ul>
+<ul>
+<li><a href="/file/c78f6c5cbea9/a">file</a></li>
+<li class="active">diff</li>
+<li><a href="/annotate/c78f6c5cbea9/a">annotate</a></li>
+<li><a href="/log/c78f6c5cbea9/a">file log</a></li>
+<li><a href="/raw-file/c78f6c5cbea9/a">raw</a></li>
+</ul>
+</div>
+
+<div class="main">
+<h2><a href="/">test</a></h2>
+<h3>diff a @ 1:c78f6c5cbea9</h3>
+
+<form class="search" action="/log">
+
+<p><input name="rev" id="search1" type="text" size="30"></p>
+<span>find changesets by author, revision,
+files, or words in the commit message</span>
+</form>
+
+<div class="description">del</div>
+
+<table id="changesetEntry">
+<tr>
+ <th>author</th>
+ <td>&#116;&#101;&#115;&#116;</td>
+</tr>
+<tr>
+ <th>date</th>
+ <td>Thu Jan 01 00:00:00 1970 +0000 (38 years ago)</td>
+</tr>
+<tr>
+ <th>parents</th>
+ <td><a href="/file/cb9a9f314b8b/a">cb9a9f314b8b</a> </td>
+</tr>
+<tr>
+ <th>children</th>
+ <td></td>
+</tr>
+
+</table>
+
+<div class="overflow">
+<div class="sourcefirst">   line diff</div>
+
+<div class="source bottomline parity0"><a href="#l1.1" id="l1.1">     1.1</a> <span class="minusline">--- a/a	Thu Jan 01 00:00:00 1970 +0000
+</span><a href="#l1.2" id="l1.2">     1.2</a> <span class="plusline">+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
+</span><a href="#l1.3" id="l1.3">     1.3</a> <span class="atline">@@ -1,1 +0,0 @@
+</span><a href="#l1.4" id="l1.4">     1.4</a> <span class="minusline">-a
+</span></div>
+</div>
+</div>
+</div>
+
+
 
 </body>
 </html>
 
-
-
--- a/tests/test-hgweb.out	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-hgweb.out	Sun Dec 07 19:34:07 2008 +0100
@@ -21,31 +21,55 @@
 % should give a 404 - static file that does not exist
 404 Not Found
 
+<!-- quirksmode -->
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <html>
 <head>
 <link rel="icon" href="/static/hgicon.png" type="image/png">
 <meta name="robots" content="index, nofollow" />
-<link rel="stylesheet" href="/static/style.css" type="text/css" />
+<link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
 
-<title>Mercurial Error</title>
+<title>test: error</title>
 </head>
 <body>
 
-<h2>Mercurial Error</h2>
+<div class="container">
+<div class="menu">
+<div class="logo">
+<a href="http://www.selenic.com/mercurial/">
+<img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
+</div>
+<ul>
+<li><a href="/shortlog">log</a></li>
+<li><a href="/graph">graph</a></li>
+<li><a href="/tags">tags</a></li>
+</ul>
+</div>
 
+<div class="main">
+
+<h2><a href="/">test</a></h2>
+<h3>error</h3>
+
+<form class="search" action="/log">
+
+<p><input name="rev" id="search1" type="text" size="30"></p>
+<span>find changesets by author, revision,
+files, or words in the commit message</span>
+</form>
+
+<div class="description">
 <p>
 An error occurred while processing your request:
 </p>
 <p>
 Not Found
 </p>
+</div>
+</div>
+</div>
 
 
-<div class="logo">
-<a href="http://www.selenic.com/mercurial/">
-<img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
-</div>
 
 </body>
 </html>
@@ -67,31 +91,55 @@
 error: bork@2ef0ac749a14: not found in manifest
 404 Not Found
 
+<!-- quirksmode -->
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <html>
 <head>
 <link rel="icon" href="/static/hgicon.png" type="image/png">
 <meta name="robots" content="index, nofollow" />
-<link rel="stylesheet" href="/static/style.css" type="text/css" />
+<link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
 
-<title>Mercurial Error</title>
+<title>test: error</title>
 </head>
 <body>
 
-<h2>Mercurial Error</h2>
+<div class="container">
+<div class="menu">
+<div class="logo">
+<a href="http://www.selenic.com/mercurial/">
+<img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
+</div>
+<ul>
+<li><a href="/shortlog">log</a></li>
+<li><a href="/graph">graph</a></li>
+<li><a href="/tags">tags</a></li>
+</ul>
+</div>
 
+<div class="main">
+
+<h2><a href="/">test</a></h2>
+<h3>error</h3>
+
+<form class="search" action="/log">
+
+<p><input name="rev" id="search1" type="text" size="30"></p>
+<span>find changesets by author, revision,
+files, or words in the commit message</span>
+</form>
+
+<div class="description">
 <p>
 An error occurred while processing your request:
 </p>
 <p>
 bork@2ef0ac749a14: not found in manifest
 </p>
+</div>
+</div>
+</div>
 
 
-<div class="logo">
-<a href="http://www.selenic.com/mercurial/">
-<img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
-</div>
 
 </body>
 </html>
@@ -208,7 +256,7 @@
 	margin: 0;
 	top: -0.7em;
 }
- 
+
 ul#graphnodes li, ul#nodebgs li {
 	height: 39px;
 }
--- a/tests/test-hgwebdir	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-hgwebdir	Sun Dec 07 19:34:07 2008 +0100
@@ -51,6 +51,7 @@
 [paths]
 t/a/=$root/a
 b=$root/b
+coll=$root/*
 EOF
 
 hg serve -p $HGPORT1 -d --pid-file=hg.pid --webdir-conf paths.conf \
@@ -66,6 +67,9 @@
 "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/t/a/?style=atom' \
 	| sed "s/http:\/\/[^/]*\//http:\/\/127.0.0.1\//"
 "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/t/a/file/tip/a?style=raw'
+# Test [paths] '*' extension
+"$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/coll/?style=raw'
+"$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/coll/a/file/tip/a?style=raw'
 
 cat > collections.conf <<EOF
 [collections]
--- a/tests/test-hgwebdir.out	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-hgwebdir.out	Sun Dec 07 19:34:07 2008 +0100
@@ -30,6 +30,10 @@
 
 
 /b/
+/coll/a/
+/coll/b/
+/coll/b/d/
+/coll/c/
 /t/a/
 
 200 Script output follows
@@ -103,6 +107,17 @@
 200 Script output follows
 
 a
+200 Script output follows
+
+
+/coll/a/
+/coll/b/
+/coll/b/d/
+/coll/c/
+
+200 Script output follows
+
+a
 % should succeed
 200 Script output follows
 
--- a/tests/test-highlight.out	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-highlight.out	Sun Dec 07 19:34:07 2008 +0100
@@ -4,62 +4,85 @@
 % hgweb filerevision, html
 200 Script output follows
 
+<!-- quirksmode -->
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <html>
 <head>
 <link rel="icon" href="/static/hgicon.png" type="image/png">
 <meta name="robots" content="index, nofollow" />
-<link rel="stylesheet" href="/static/style.css" type="text/css" />
+<link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
 
 <link rel="stylesheet" href="/highlightcss" type="text/css" />
-<title>test:get-with-headers.py</title>
+<title>test: 7697c52ca9b0 get-with-headers.py</title>
 </head>
 <body>
 
-<div class="buttons">
-<a href="/log/0">changelog</a>
-<a href="/shortlog/0">shortlog</a>
-<a href="/graph">graph</a>
-<a href="/tags">tags</a>
-<a href="/rev/7697c52ca9b0">changeset</a>
-<a href="/file/7697c52ca9b0/">files</a>
-<a href="/log/7697c52ca9b0/get-with-headers.py">revisions</a>
-<a href="/annotate/7697c52ca9b0/get-with-headers.py">annotate</a>
-<a href="/raw-file/7697c52ca9b0/get-with-headers.py">raw</a>
-</div>
-
-<h2>get-with-headers.py</h2>
-
-<table>
-<tr>
- <td class="metatag">changeset 0:</td>
- <td><a href="/rev/7697c52ca9b0">7697c52ca9b0</a></td></tr>
-
-
-<tr>
- <td class="metatag">author:</td>
- <td>&#116;&#101;&#115;&#116;</td></tr>
-<tr>
- <td class="metatag">date:</td>
- <td>Thu Jan 01 00:00:00 1970 +0000 (long ago)</td></tr>
-<tr>
- <td class="metatag">permissions:</td>
- <td>-rwxr-xr-x</td></tr>
-<tr>
-  <td class="metatag">description:</td>
-  <td>a</td>
-</tr>
-</table>
-
-<pre>
-<div class="parity0"><a class="lineno" href="#l1" id="l1">     1</a><span class="c">#!/usr/bin/env python</span></div><div class="parity1"><a class="lineno" href="#l2" id="l2">     2</a></div><div class="parity0"><a class="lineno" href="#l3" id="l3">     3</a><span class="n">__doc__</span> <span class="o">=</span> <span class="s">&quot;&quot;&quot;This does HTTP get requests given a host:port and path and returns</span></div><div class="parity1"><a class="lineno" href="#l4" id="l4">     4</a><span class="s">a subset of the headers plus the body of the result.&quot;&quot;&quot;</span></div><div class="parity0"><a class="lineno" href="#l5" id="l5">     5</a></div><div class="parity1"><a class="lineno" href="#l6" id="l6">     6</a><span class="kn">import</span> <span class="nn">httplib</span><span class="o">,</span> <span class="nn">sys</span></div><div class="parity0"><a class="lineno" href="#l7" id="l7">     7</a></div><div class="parity1"><a class="lineno" href="#l8" id="l8">     8</a><span class="kn">try</span><span class="p">:</span></div><div class="parity0"><a class="lineno" href="#l9" id="l9">     9</a>    <span class="kn">import</span> <span class="nn">msvcrt</span><span class="o">,</span> <span class="nn">os</span></div><div class="parity1"><a class="lineno" href="#l10" id="l10">    10</a>    <span class="n">msvcrt</span><span class="o">.</span><span class="n">setmode</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">fileno</span><span class="p">(),</span> <span class="n">os</span><span class="o">.</span><span class="n">O_BINARY</span><span class="p">)</span></div><div class="parity0"><a class="lineno" href="#l11" id="l11">    11</a>    <span class="n">msvcrt</span><span class="o">.</span><span class="n">setmode</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="o">.</span><span class="n">fileno</span><span class="p">(),</span> <span class="n">os</span><span class="o">.</span><span class="n">O_BINARY</span><span class="p">)</span></div><div class="parity1"><a class="lineno" href="#l12" id="l12">    12</a><span class="kn">except</span> <span class="ne">ImportError</span><span class="p">:</span></div><div class="parity0"><a class="lineno" href="#l13" id="l13">    13</a>    <span class="kn">pass</span></div><div class="parity1"><a class="lineno" href="#l14" id="l14">    14</a></div><div class="parity0"><a class="lineno" href="#l15" id="l15">    15</a><span class="n">headers</span> <span class="o">=</span> <span class="p">[</span><span class="n">h</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="kn">for</span> <span class="n">h</span> <span class="ow">in</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mf">3</span><span class="p">:]]</span></div><div class="parity1"><a class="lineno" href="#l16" id="l16">    16</a><span class="n">conn</span> <span class="o">=</span> <span class="n">httplib</span><span class="o">.</span><span class="n">HTTPConnection</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mf">1</span><span class="p">])</span></div><div class="parity0"><a class="lineno" href="#l17" id="l17">    17</a><span class="n">conn</span><span class="o">.</span><span class="n">request</span><span class="p">(</span><span class="s">&quot;GET&quot;</span><span class="p">,</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mf">2</span><span class="p">])</span></div><div class="parity1"><a class="lineno" href="#l18" id="l18">    18</a><span class="n">response</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">getresponse</span><span class="p">()</span></div><div class="parity0"><a class="lineno" href="#l19" id="l19">    19</a><span class="kn">print</span> <span class="n">response</span><span class="o">.</span><span class="n">status</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">reason</span></div><div class="parity1"><a class="lineno" href="#l20" id="l20">    20</a><span class="kn">for</span> <span class="n">h</span> <span class="ow">in</span> <span class="n">headers</span><span class="p">:</span></div><div class="parity0"><a class="lineno" href="#l21" id="l21">    21</a>    <span class="kn">if</span> <span class="n">response</span><span class="o">.</span><span class="n">getheader</span><span class="p">(</span><span class="n">h</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span></div><div class="parity1"><a class="lineno" href="#l22" id="l22">    22</a>        <span class="kn">print</span> <span class="s">&quot;</span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">h</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">getheader</span><span class="p">(</span><span class="n">h</span><span class="p">))</span></div><div class="parity0"><a class="lineno" href="#l23" id="l23">    23</a><span class="kn">print</span></div><div class="parity1"><a class="lineno" href="#l24" id="l24">    24</a><span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">read</span><span class="p">())</span></div><div class="parity0"><a class="lineno" href="#l25" id="l25">    25</a></div><div class="parity1"><a class="lineno" href="#l26" id="l26">    26</a><span class="kn">if</span> <span class="mf">200</span> <span class="o">&lt;=</span> <span class="n">response</span><span class="o">.</span><span class="n">status</span> <span class="o">&lt;=</span> <span class="mf">299</span><span class="p">:</span></div><div class="parity0"><a class="lineno" href="#l27" id="l27">    27</a>    <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mf">0</span><span class="p">)</span></div><div class="parity1"><a class="lineno" href="#l28" id="l28">    28</a><span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mf">1</span><span class="p">)</span></div>
-</pre>
-
-
+<div class="container">
+<div class="menu">
 <div class="logo">
 <a href="http://www.selenic.com/mercurial/">
 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
 </div>
+<ul>
+<li><a href="/shortlog/7697c52ca9b0">log</a></li>
+<li><a href="/graph/7697c52ca9b0">graph</a></li>
+<li><a href="/tags">tags</a></li>
+</ul>
+<ul>
+<li><a href="/rev/7697c52ca9b0">changeset</a></li>
+<li><a href="/file/7697c52ca9b0/">browse</a></li>
+</ul>
+<ul>
+<li class="active">file</li>
+<li><a href="/diff/7697c52ca9b0/get-with-headers.py">diff</a></li>
+<li><a href="/annotate/7697c52ca9b0/get-with-headers.py">annotate</a></li>
+<li><a href="/log/7697c52ca9b0/get-with-headers.py">file log</a></li>
+<li><a href="/raw-file/7697c52ca9b0/get-with-headers.py">raw</a></li>
+</ul>
+</div>
+
+<div class="main">
+<h2><a href="/">test</a></h2>
+<h3>view get-with-headers.py @ 0:7697c52ca9b0</h3>
+
+<form class="search" action="/log">
+
+<p><input name="rev" id="search1" type="text" size="30"></p>
+<span>find changesets by author, revision,
+files, or words in the commit message</span>
+</form>
+
+<div class="description">a</div>
+
+<table id="changesetEntry">
+<tr>
+ <th class="author">author</th>
+ <td class="author">&#116;&#101;&#115;&#116;</td>
+</tr>
+<tr>
+ <th class="date">date</th>
+ <td class="date">Thu Jan 01 00:00:00 1970 +0000 (long ago)</td>
+</tr>
+<tr>
+ <th class="author">parents</th>
+ <td class="author"></td>
+</tr>
+<tr>
+ <th class="author">children</th>
+ <td class="author"></td>
+</tr>
+
+</table>
+
+<div class="overflow">
+<div class="sourcefirst"> line source</div>
+<div class="parity0 source"><a href="#l1" id="l1">     1</a> <span class="c">#!/usr/bin/env python</span></div><div class="parity1 source"><a href="#l2" id="l2">     2</a> </div><div class="parity0 source"><a href="#l3" id="l3">     3</a> <span class="n">__doc__</span> <span class="o">=</span> <span class="s">&quot;&quot;&quot;This does HTTP get requests given a host:port and path and returns</span></div><div class="parity1 source"><a href="#l4" id="l4">     4</a> <span class="s">a subset of the headers plus the body of the result.&quot;&quot;&quot;</span></div><div class="parity0 source"><a href="#l5" id="l5">     5</a> </div><div class="parity1 source"><a href="#l6" id="l6">     6</a> <span class="kn">import</span> <span class="nn">httplib</span><span class="o">,</span> <span class="nn">sys</span></div><div class="parity0 source"><a href="#l7" id="l7">     7</a> </div><div class="parity1 source"><a href="#l8" id="l8">     8</a> <span class="kn">try</span><span class="p">:</span></div><div class="parity0 source"><a href="#l9" id="l9">     9</a>     <span class="kn">import</span> <span class="nn">msvcrt</span><span class="o">,</span> <span class="nn">os</span></div><div class="parity1 source"><a href="#l10" id="l10">    10</a>     <span class="n">msvcrt</span><span class="o">.</span><span class="n">setmode</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">fileno</span><span class="p">(),</span> <span class="n">os</span><span class="o">.</span><span class="n">O_BINARY</span><span class="p">)</span></div><div class="parity0 source"><a href="#l11" id="l11">    11</a>     <span class="n">msvcrt</span><span class="o">.</span><span class="n">setmode</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="o">.</span><span class="n">fileno</span><span class="p">(),</span> <span class="n">os</span><span class="o">.</span><span class="n">O_BINARY</span><span class="p">)</span></div><div class="parity1 source"><a href="#l12" id="l12">    12</a> <span class="kn">except</span> <span class="ne">ImportError</span><span class="p">:</span></div><div class="parity0 source"><a href="#l13" id="l13">    13</a>     <span class="kn">pass</span></div><div class="parity1 source"><a href="#l14" id="l14">    14</a> </div><div class="parity0 source"><a href="#l15" id="l15">    15</a> <span class="n">headers</span> <span class="o">=</span> <span class="p">[</span><span class="n">h</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="kn">for</span> <span class="n">h</span> <span class="ow">in</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mf">3</span><span class="p">:]]</span></div><div class="parity1 source"><a href="#l16" id="l16">    16</a> <span class="n">conn</span> <span class="o">=</span> <span class="n">httplib</span><span class="o">.</span><span class="n">HTTPConnection</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mf">1</span><span class="p">])</span></div><div class="parity0 source"><a href="#l17" id="l17">    17</a> <span class="n">conn</span><span class="o">.</span><span class="n">request</span><span class="p">(</span><span class="s">&quot;GET&quot;</span><span class="p">,</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mf">2</span><span class="p">])</span></div><div class="parity1 source"><a href="#l18" id="l18">    18</a> <span class="n">response</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">getresponse</span><span class="p">()</span></div><div class="parity0 source"><a href="#l19" id="l19">    19</a> <span class="kn">print</span> <span class="n">response</span><span class="o">.</span><span class="n">status</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">reason</span></div><div class="parity1 source"><a href="#l20" id="l20">    20</a> <span class="kn">for</span> <span class="n">h</span> <span class="ow">in</span> <span class="n">headers</span><span class="p">:</span></div><div class="parity0 source"><a href="#l21" id="l21">    21</a>     <span class="kn">if</span> <span class="n">response</span><span class="o">.</span><span class="n">getheader</span><span class="p">(</span><span class="n">h</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span></div><div class="parity1 source"><a href="#l22" id="l22">    22</a>         <span class="kn">print</span> <span class="s">&quot;</span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">h</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">getheader</span><span class="p">(</span><span class="n">h</span><span class="p">))</span></div><div class="parity0 source"><a href="#l23" id="l23">    23</a> <span class="kn">print</span></div><div class="parity1 source"><a href="#l24" id="l24">    24</a> <span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">read</span><span class="p">())</span></div><div class="parity0 source"><a href="#l25" id="l25">    25</a> </div><div class="parity1 source"><a href="#l26" id="l26">    26</a> <span class="kn">if</span> <span class="mf">200</span> <span class="o">&lt;=</span> <span class="n">response</span><span class="o">.</span><span class="n">status</span> <span class="o">&lt;=</span> <span class="mf">299</span><span class="p">:</span></div><div class="parity0 source"><a href="#l27" id="l27">    27</a>     <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mf">0</span><span class="p">)</span></div><div class="parity1 source"><a href="#l28" id="l28">    28</a> <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mf">1</span><span class="p">)</span></div>
+<div class="sourcelast"></div>
+</div>
+</div>
+</div>
+
+
 
 </body>
 </html>
@@ -67,62 +90,85 @@
 % hgweb filerevision, html
 200 Script output follows
 
+<!-- quirksmode -->
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <html>
 <head>
 <link rel="icon" href="/static/hgicon.png" type="image/png">
 <meta name="robots" content="index, nofollow" />
-<link rel="stylesheet" href="/static/style.css" type="text/css" />
+<link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
 
 <link rel="stylesheet" href="/highlightcss" type="text/css" />
-<title>test:isolatin</title>
+<title>test: 7697c52ca9b0 isolatin</title>
 </head>
 <body>
 
-<div class="buttons">
-<a href="/log/0">changelog</a>
-<a href="/shortlog/0">shortlog</a>
-<a href="/graph">graph</a>
-<a href="/tags">tags</a>
-<a href="/rev/7697c52ca9b0">changeset</a>
-<a href="/file/7697c52ca9b0/">files</a>
-<a href="/log/7697c52ca9b0/isolatin">revisions</a>
-<a href="/annotate/7697c52ca9b0/isolatin">annotate</a>
-<a href="/raw-file/7697c52ca9b0/isolatin">raw</a>
-</div>
-
-<h2>isolatin</h2>
-
-<table>
-<tr>
- <td class="metatag">changeset 0:</td>
- <td><a href="/rev/7697c52ca9b0">7697c52ca9b0</a></td></tr>
-
-
-<tr>
- <td class="metatag">author:</td>
- <td>&#116;&#101;&#115;&#116;</td></tr>
-<tr>
- <td class="metatag">date:</td>
- <td>Thu Jan 01 00:00:00 1970 +0000 (long ago)</td></tr>
-<tr>
- <td class="metatag">permissions:</td>
- <td>-rw-r--r--</td></tr>
-<tr>
-  <td class="metatag">description:</td>
-  <td>a</td>
-</tr>
-</table>
-
-<pre>
-<div class="parity0"><a class="lineno" href="#l1" id="l1">     1</a>h?bsch</div>
-</pre>
-
-
+<div class="container">
+<div class="menu">
 <div class="logo">
 <a href="http://www.selenic.com/mercurial/">
 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
 </div>
+<ul>
+<li><a href="/shortlog/7697c52ca9b0">log</a></li>
+<li><a href="/graph/7697c52ca9b0">graph</a></li>
+<li><a href="/tags">tags</a></li>
+</ul>
+<ul>
+<li><a href="/rev/7697c52ca9b0">changeset</a></li>
+<li><a href="/file/7697c52ca9b0/">browse</a></li>
+</ul>
+<ul>
+<li class="active">file</li>
+<li><a href="/diff/7697c52ca9b0/isolatin">diff</a></li>
+<li><a href="/annotate/7697c52ca9b0/isolatin">annotate</a></li>
+<li><a href="/log/7697c52ca9b0/isolatin">file log</a></li>
+<li><a href="/raw-file/7697c52ca9b0/isolatin">raw</a></li>
+</ul>
+</div>
+
+<div class="main">
+<h2><a href="/">test</a></h2>
+<h3>view isolatin @ 0:7697c52ca9b0</h3>
+
+<form class="search" action="/log">
+
+<p><input name="rev" id="search1" type="text" size="30"></p>
+<span>find changesets by author, revision,
+files, or words in the commit message</span>
+</form>
+
+<div class="description">a</div>
+
+<table id="changesetEntry">
+<tr>
+ <th class="author">author</th>
+ <td class="author">&#116;&#101;&#115;&#116;</td>
+</tr>
+<tr>
+ <th class="date">date</th>
+ <td class="date">Thu Jan 01 00:00:00 1970 +0000 (long ago)</td>
+</tr>
+<tr>
+ <th class="author">parents</th>
+ <td class="author"></td>
+</tr>
+<tr>
+ <th class="author">children</th>
+ <td class="author"></td>
+</tr>
+
+</table>
+
+<div class="overflow">
+<div class="sourcefirst"> line source</div>
+<div class="parity0 source"><a href="#l1" id="l1">     1</a> h?bsch</div>
+<div class="sourcelast"></div>
+</div>
+</div>
+</div>
+
+
 
 </body>
 </html>
@@ -130,66 +176,92 @@
 % hgweb fileannotate, html
 200 Script output follows
 
+<!-- quirksmode -->
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <html>
 <head>
 <link rel="icon" href="/static/hgicon.png" type="image/png">
 <meta name="robots" content="index, nofollow" />
-<link rel="stylesheet" href="/static/style.css" type="text/css" />
+<link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
 
 <link rel="stylesheet" href="/highlightcss" type="text/css" />
 <title>test: get-with-headers.py annotate</title>
 </head>
 <body>
 
-<div class="buttons">
-<a href="/log/0">changelog</a>
-<a href="/shortlog/0">shortlog</a>
-<a href="/graph">graph</a>
-<a href="/tags">tags</a>
-<a href="/rev/7697c52ca9b0">changeset</a>
-<a href="/file/7697c52ca9b0/">files</a>
-<a href="/file/7697c52ca9b0/get-with-headers.py">file</a>
-<a href="/log/7697c52ca9b0/get-with-headers.py">revisions</a>
-<a href="/raw-annotate/7697c52ca9b0/get-with-headers.py">raw</a>
+<div class="container">
+<div class="menu">
+<div class="logo">
+<a href="http://www.selenic.com/mercurial/">
+<img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
+</div>
+<ul>
+<li><a href="/shortlog/7697c52ca9b0">log</a></li>
+<li><a href="/graph/7697c52ca9b0">graph</a></li>
+<li><a href="/tags">tags</a></li>
+</ul>
+
+<ul>
+<li><a href="/rev/7697c52ca9b0">changeset</a></li>
+<li><a href="/file/7697c52ca9b0/">browse</a></li>
+</ul>
+<ul>
+<li><a href="/file/7697c52ca9b0/get-with-headers.py">file</a></li>
+<li><a href="/diff/7697c52ca9b0/get-with-headers.py">diff</a></li>
+<li class="active">annotate</li>
+<li><a href="/log/7697c52ca9b0/get-with-headers.py">file log</a></li>
+<li><a href="/raw-annotate/7697c52ca9b0/get-with-headers.py">raw</a></li>
+</ul>
 </div>
 
-<h2>Annotate get-with-headers.py</h2>
+<div class="main">
+<h2><a href="/">test</a></h2>
+<h3>annotate get-with-headers.py @ 0:7697c52ca9b0</h3>
 
-<table>
-<tr>
- <td class="metatag">changeset 0:</td>
- <td><a href="/rev/7697c52ca9b0">7697c52ca9b0</a></td></tr>
+<form class="search" action="/log">
 
+<p><input name="rev" id="search1" type="text" size="30"></p>
+<span>find changesets by author, revision,
+files, or words in the commit message</span>
+</form>
 
+<div class="description">a</div>
+
+<table id="changesetEntry">
 <tr>
- <td class="metatag">author:</td>
- <td>&#116;&#101;&#115;&#116;</td></tr>
-<tr>
- <td class="metatag">date:</td>
- <td>Thu Jan 01 00:00:00 1970 +0000 (long ago)</td>
+ <th class="author">author</th>
+ <td class="author">&#116;&#101;&#115;&#116;</td>
 </tr>
 <tr>
- <td class="metatag">permissions:</td>
- <td>-rwxr-xr-x</td>
+ <th class="date">date</th>
+ <td class="date">Thu Jan 01 00:00:00 1970 +0000 (long ago)</td>
 </tr>
 <tr>
-  <td class="metatag">description:</td>
-  <td>a</td>
+ <th class="author">parents</th>
+ <td class="author"></td>
 </tr>
+<tr>
+ <th class="author">children</th>
+ <td class="author"></td>
+</tr>
+
 </table>
 
 <br/>
 
-<table cellspacing="0" cellpadding="0">
-<tr class="parity0"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#l1" title="7697c52ca9b0: a">test@0</a></td><td><a class="lineno" href="#l1" id="l1">     1</a></td><td><pre><span class="c">#!/usr/bin/env python</span></pre></td></tr><tr class="parity1"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#l2" title="7697c52ca9b0: a">test@0</a></td><td><a class="lineno" href="#l2" id="l2">     2</a></td><td><pre></pre></td></tr><tr class="parity0"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#l3" title="7697c52ca9b0: a">test@0</a></td><td><a class="lineno" href="#l3" id="l3">     3</a></td><td><pre><span class="n">__doc__</span> <span class="o">=</span> <span class="s">&quot;&quot;&quot;This does HTTP get requests given a host:port and path and returns</span></pre></td></tr><tr class="parity1"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#l4" title="7697c52ca9b0: a">test@0</a></td><td><a class="lineno" href="#l4" id="l4">     4</a></td><td><pre><span class="s">a subset of the headers plus the body of the result.&quot;&quot;&quot;</span></pre></td></tr><tr class="parity0"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#l5" title="7697c52ca9b0: a">test@0</a></td><td><a class="lineno" href="#l5" id="l5">     5</a></td><td><pre></pre></td></tr><tr class="parity1"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#l6" title="7697c52ca9b0: a">test@0</a></td><td><a class="lineno" href="#l6" id="l6">     6</a></td><td><pre><span class="kn">import</span> <span class="nn">httplib</span><span class="o">,</span> <span class="nn">sys</span></pre></td></tr><tr class="parity0"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#l7" title="7697c52ca9b0: a">test@0</a></td><td><a class="lineno" href="#l7" id="l7">     7</a></td><td><pre></pre></td></tr><tr class="parity1"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#l8" title="7697c52ca9b0: a">test@0</a></td><td><a class="lineno" href="#l8" id="l8">     8</a></td><td><pre><span class="kn">try</span><span class="p">:</span></pre></td></tr><tr class="parity0"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#l9" title="7697c52ca9b0: a">test@0</a></td><td><a class="lineno" href="#l9" id="l9">     9</a></td><td><pre>    <span class="kn">import</span> <span class="nn">msvcrt</span><span class="o">,</span> <span class="nn">os</span></pre></td></tr><tr class="parity1"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#l10" title="7697c52ca9b0: a">test@0</a></td><td><a class="lineno" href="#l10" id="l10">    10</a></td><td><pre>    <span class="n">msvcrt</span><span class="o">.</span><span class="n">setmode</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">fileno</span><span class="p">(),</span> <span class="n">os</span><span class="o">.</span><span class="n">O_BINARY</span><span class="p">)</span></pre></td></tr><tr class="parity0"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#l11" title="7697c52ca9b0: a">test@0</a></td><td><a class="lineno" href="#l11" id="l11">    11</a></td><td><pre>    <span class="n">msvcrt</span><span class="o">.</span><span class="n">setmode</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="o">.</span><span class="n">fileno</span><span class="p">(),</span> <span class="n">os</span><span class="o">.</span><span class="n">O_BINARY</span><span class="p">)</span></pre></td></tr><tr class="parity1"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#l12" title="7697c52ca9b0: a">test@0</a></td><td><a class="lineno" href="#l12" id="l12">    12</a></td><td><pre><span class="kn">except</span> <span class="ne">ImportError</span><span class="p">:</span></pre></td></tr><tr class="parity0"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#l13" title="7697c52ca9b0: a">test@0</a></td><td><a class="lineno" href="#l13" id="l13">    13</a></td><td><pre>    <span class="kn">pass</span></pre></td></tr><tr class="parity1"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#l14" title="7697c52ca9b0: a">test@0</a></td><td><a class="lineno" href="#l14" id="l14">    14</a></td><td><pre></pre></td></tr><tr class="parity0"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#l15" title="7697c52ca9b0: a">test@0</a></td><td><a class="lineno" href="#l15" id="l15">    15</a></td><td><pre><span class="n">headers</span> <span class="o">=</span> <span class="p">[</span><span class="n">h</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="kn">for</span> <span class="n">h</span> <span class="ow">in</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mf">3</span><span class="p">:]]</span></pre></td></tr><tr class="parity1"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#l16" title="7697c52ca9b0: a">test@0</a></td><td><a class="lineno" href="#l16" id="l16">    16</a></td><td><pre><span class="n">conn</span> <span class="o">=</span> <span class="n">httplib</span><span class="o">.</span><span class="n">HTTPConnection</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mf">1</span><span class="p">])</span></pre></td></tr><tr class="parity0"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#l17" title="7697c52ca9b0: a">test@0</a></td><td><a class="lineno" href="#l17" id="l17">    17</a></td><td><pre><span class="n">conn</span><span class="o">.</span><span class="n">request</span><span class="p">(</span><span class="s">&quot;GET&quot;</span><span class="p">,</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mf">2</span><span class="p">])</span></pre></td></tr><tr class="parity1"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#l18" title="7697c52ca9b0: a">test@0</a></td><td><a class="lineno" href="#l18" id="l18">    18</a></td><td><pre><span class="n">response</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">getresponse</span><span class="p">()</span></pre></td></tr><tr class="parity0"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#l19" title="7697c52ca9b0: a">test@0</a></td><td><a class="lineno" href="#l19" id="l19">    19</a></td><td><pre><span class="kn">print</span> <span class="n">response</span><span class="o">.</span><span class="n">status</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">reason</span></pre></td></tr><tr class="parity1"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#l20" title="7697c52ca9b0: a">test@0</a></td><td><a class="lineno" href="#l20" id="l20">    20</a></td><td><pre><span class="kn">for</span> <span class="n">h</span> <span class="ow">in</span> <span class="n">headers</span><span class="p">:</span></pre></td></tr><tr class="parity0"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#l21" title="7697c52ca9b0: a">test@0</a></td><td><a class="lineno" href="#l21" id="l21">    21</a></td><td><pre>    <span class="kn">if</span> <span class="n">response</span><span class="o">.</span><span class="n">getheader</span><span class="p">(</span><span class="n">h</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span></pre></td></tr><tr class="parity1"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#l22" title="7697c52ca9b0: a">test@0</a></td><td><a class="lineno" href="#l22" id="l22">    22</a></td><td><pre>        <span class="kn">print</span> <span class="s">&quot;</span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">h</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">getheader</span><span class="p">(</span><span class="n">h</span><span class="p">))</span></pre></td></tr><tr class="parity0"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#l23" title="7697c52ca9b0: a">test@0</a></td><td><a class="lineno" href="#l23" id="l23">    23</a></td><td><pre><span class="kn">print</span></pre></td></tr><tr class="parity1"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#l24" title="7697c52ca9b0: a">test@0</a></td><td><a class="lineno" href="#l24" id="l24">    24</a></td><td><pre><span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">read</span><span class="p">())</span></pre></td></tr><tr class="parity0"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#l25" title="7697c52ca9b0: a">test@0</a></td><td><a class="lineno" href="#l25" id="l25">    25</a></td><td><pre></pre></td></tr><tr class="parity1"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#l26" title="7697c52ca9b0: a">test@0</a></td><td><a class="lineno" href="#l26" id="l26">    26</a></td><td><pre><span class="kn">if</span> <span class="mf">200</span> <span class="o">&lt;=</span> <span class="n">response</span><span class="o">.</span><span class="n">status</span> <span class="o">&lt;=</span> <span class="mf">299</span><span class="p">:</span></pre></td></tr><tr class="parity0"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#l27" title="7697c52ca9b0: a">test@0</a></td><td><a class="lineno" href="#l27" id="l27">    27</a></td><td><pre>    <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mf">0</span><span class="p">)</span></pre></td></tr><tr class="parity1"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#l28" title="7697c52ca9b0: a">test@0</a></td><td><a class="lineno" href="#l28" id="l28">    28</a></td><td><pre><span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mf">1</span><span class="p">)</span></pre></td></tr>
+<div class="overflow">
+<table class="bigtable">
+<tr>
+ <th class="annotate">rev</th>
+ <th class="line">&nbsp;&nbsp;line source</th>
+</tr>
+<tr class="parity0"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#1" title="7697c52ca9b0: a">test@0</a></td><td class="source"><a href="#l1" id="l1">     1</a> <span class="c">#!/usr/bin/env python</span></td></tr><tr class="parity1"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#2" title="7697c52ca9b0: a">test@0</a></td><td class="source"><a href="#l2" id="l2">     2</a> </td></tr><tr class="parity0"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#3" title="7697c52ca9b0: a">test@0</a></td><td class="source"><a href="#l3" id="l3">     3</a> <span class="n">__doc__</span> <span class="o">=</span> <span class="s">&quot;&quot;&quot;This does HTTP get requests given a host:port and path and returns</span></td></tr><tr class="parity1"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#4" title="7697c52ca9b0: a">test@0</a></td><td class="source"><a href="#l4" id="l4">     4</a> <span class="s">a subset of the headers plus the body of the result.&quot;&quot;&quot;</span></td></tr><tr class="parity0"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#5" title="7697c52ca9b0: a">test@0</a></td><td class="source"><a href="#l5" id="l5">     5</a> </td></tr><tr class="parity1"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#6" title="7697c52ca9b0: a">test@0</a></td><td class="source"><a href="#l6" id="l6">     6</a> <span class="kn">import</span> <span class="nn">httplib</span><span class="o">,</span> <span class="nn">sys</span></td></tr><tr class="parity0"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#7" title="7697c52ca9b0: a">test@0</a></td><td class="source"><a href="#l7" id="l7">     7</a> </td></tr><tr class="parity1"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#8" title="7697c52ca9b0: a">test@0</a></td><td class="source"><a href="#l8" id="l8">     8</a> <span class="kn">try</span><span class="p">:</span></td></tr><tr class="parity0"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#9" title="7697c52ca9b0: a">test@0</a></td><td class="source"><a href="#l9" id="l9">     9</a>     <span class="kn">import</span> <span class="nn">msvcrt</span><span class="o">,</span> <span class="nn">os</span></td></tr><tr class="parity1"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#10" title="7697c52ca9b0: a">test@0</a></td><td class="source"><a href="#l10" id="l10">    10</a>     <span class="n">msvcrt</span><span class="o">.</span><span class="n">setmode</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">fileno</span><span class="p">(),</span> <span class="n">os</span><span class="o">.</span><span class="n">O_BINARY</span><span class="p">)</span></td></tr><tr class="parity0"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#11" title="7697c52ca9b0: a">test@0</a></td><td class="source"><a href="#l11" id="l11">    11</a>     <span class="n">msvcrt</span><span class="o">.</span><span class="n">setmode</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="o">.</span><span class="n">fileno</span><span class="p">(),</span> <span class="n">os</span><span class="o">.</span><span class="n">O_BINARY</span><span class="p">)</span></td></tr><tr class="parity1"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#12" title="7697c52ca9b0: a">test@0</a></td><td class="source"><a href="#l12" id="l12">    12</a> <span class="kn">except</span> <span class="ne">ImportError</span><span class="p">:</span></td></tr><tr class="parity0"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#13" title="7697c52ca9b0: a">test@0</a></td><td class="source"><a href="#l13" id="l13">    13</a>     <span class="kn">pass</span></td></tr><tr class="parity1"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#14" title="7697c52ca9b0: a">test@0</a></td><td class="source"><a href="#l14" id="l14">    14</a> </td></tr><tr class="parity0"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#15" title="7697c52ca9b0: a">test@0</a></td><td class="source"><a href="#l15" id="l15">    15</a> <span class="n">headers</span> <span class="o">=</span> <span class="p">[</span><span class="n">h</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="kn">for</span> <span class="n">h</span> <span class="ow">in</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mf">3</span><span class="p">:]]</span></td></tr><tr class="parity1"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#16" title="7697c52ca9b0: a">test@0</a></td><td class="source"><a href="#l16" id="l16">    16</a> <span class="n">conn</span> <span class="o">=</span> <span class="n">httplib</span><span class="o">.</span><span class="n">HTTPConnection</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mf">1</span><span class="p">])</span></td></tr><tr class="parity0"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#17" title="7697c52ca9b0: a">test@0</a></td><td class="source"><a href="#l17" id="l17">    17</a> <span class="n">conn</span><span class="o">.</span><span class="n">request</span><span class="p">(</span><span class="s">&quot;GET&quot;</span><span class="p">,</span> <span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mf">2</span><span class="p">])</span></td></tr><tr class="parity1"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#18" title="7697c52ca9b0: a">test@0</a></td><td class="source"><a href="#l18" id="l18">    18</a> <span class="n">response</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">getresponse</span><span class="p">()</span></td></tr><tr class="parity0"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#19" title="7697c52ca9b0: a">test@0</a></td><td class="source"><a href="#l19" id="l19">    19</a> <span class="kn">print</span> <span class="n">response</span><span class="o">.</span><span class="n">status</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">reason</span></td></tr><tr class="parity1"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#20" title="7697c52ca9b0: a">test@0</a></td><td class="source"><a href="#l20" id="l20">    20</a> <span class="kn">for</span> <span class="n">h</span> <span class="ow">in</span> <span class="n">headers</span><span class="p">:</span></td></tr><tr class="parity0"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#21" title="7697c52ca9b0: a">test@0</a></td><td class="source"><a href="#l21" id="l21">    21</a>     <span class="kn">if</span> <span class="n">response</span><span class="o">.</span><span class="n">getheader</span><span class="p">(</span><span class="n">h</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span></td></tr><tr class="parity1"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#22" title="7697c52ca9b0: a">test@0</a></td><td class="source"><a href="#l22" id="l22">    22</a>         <span class="kn">print</span> <span class="s">&quot;</span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">h</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">getheader</span><span class="p">(</span><span class="n">h</span><span class="p">))</span></td></tr><tr class="parity0"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#23" title="7697c52ca9b0: a">test@0</a></td><td class="source"><a href="#l23" id="l23">    23</a> <span class="kn">print</span></td></tr><tr class="parity1"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#24" title="7697c52ca9b0: a">test@0</a></td><td class="source"><a href="#l24" id="l24">    24</a> <span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">read</span><span class="p">())</span></td></tr><tr class="parity0"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#25" title="7697c52ca9b0: a">test@0</a></td><td class="source"><a href="#l25" id="l25">    25</a> </td></tr><tr class="parity1"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#26" title="7697c52ca9b0: a">test@0</a></td><td class="source"><a href="#l26" id="l26">    26</a> <span class="kn">if</span> <span class="mf">200</span> <span class="o">&lt;=</span> <span class="n">response</span><span class="o">.</span><span class="n">status</span> <span class="o">&lt;=</span> <span class="mf">299</span><span class="p">:</span></td></tr><tr class="parity0"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#27" title="7697c52ca9b0: a">test@0</a></td><td class="source"><a href="#l27" id="l27">    27</a>     <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mf">0</span><span class="p">)</span></td></tr><tr class="parity1"><td class="annotate"><a href="/annotate/7697c52ca9b0/get-with-headers.py#28" title="7697c52ca9b0: a">test@0</a></td><td class="source"><a href="#l28" id="l28">    28</a> <span class="n">sys</span><span class="o">.</span><span class="n">exit</span><span class="p">(</span><span class="mf">1</span><span class="p">)</span></td></tr>
 </table>
+</div>
+</div>
+</div>
 
 
-<div class="logo">
-<a href="http://www.selenic.com/mercurial/">
-<img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial"></a>
-</div>
 
 </body>
 </html>
--- a/tests/test-http-proxy.out	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-http-proxy.out	Sun Dec 07 19:34:07 2008 +0100
@@ -62,13 +62,17 @@
 XXX "GET http://localhost:/?cmd=stream_out HTTP/1.1" - -
 XXX "GET http://localhost:/?pairs=0000000000000000000000000000000000000000-0000000000000000000000000000000000000000&cmd=between HTTP/1.1" - -
 XXX "GET http://localhost:/?cmd=heads HTTP/1.1" - -
-XXX "GET http://localhost:/?cmd=changegroup&roots=0000000000000000000000000000000000000000 HTTP/1.1" - -
+XXX "GET http://localhost:/?cmd=capabilities HTTP/1.1" - -
+XXX "GET http://localhost:/?bases=0000000000000000000000000000000000000000&cmd=changegroupsubset&heads=83180e7845de420a1bb46896fd5fe05294f8d629 HTTP/1.1" - -
 XXX "GET http://localhost:/?pairs=0000000000000000000000000000000000000000-0000000000000000000000000000000000000000&cmd=between HTTP/1.1" - -
 XXX "GET http://localhost:/?cmd=heads HTTP/1.1" - -
-XXX "GET http://localhost:/?cmd=changegroup&roots=0000000000000000000000000000000000000000 HTTP/1.1" - -
+XXX "GET http://localhost:/?cmd=capabilities HTTP/1.1" - -
+XXX "GET http://localhost:/?bases=0000000000000000000000000000000000000000&cmd=changegroupsubset&heads=83180e7845de420a1bb46896fd5fe05294f8d629 HTTP/1.1" - -
 XXX "GET http://localhost:/?pairs=0000000000000000000000000000000000000000-0000000000000000000000000000000000000000&cmd=between HTTP/1.1" - -
 XXX "GET http://localhost:/?cmd=heads HTTP/1.1" - -
-XXX "GET http://localhost:/?cmd=changegroup&roots=0000000000000000000000000000000000000000 HTTP/1.1" - -
+XXX "GET http://localhost:/?cmd=capabilities HTTP/1.1" - -
+XXX "GET http://localhost:/?bases=0000000000000000000000000000000000000000&cmd=changegroupsubset&heads=83180e7845de420a1bb46896fd5fe05294f8d629 HTTP/1.1" - -
 XXX "GET http://localhost:/?pairs=0000000000000000000000000000000000000000-0000000000000000000000000000000000000000&cmd=between HTTP/1.1" - -
 XXX "GET http://localhost:/?cmd=heads HTTP/1.1" - -
-XXX "GET http://localhost:/?cmd=changegroup&roots=0000000000000000000000000000000000000000 HTTP/1.1" - -
+XXX "GET http://localhost:/?cmd=capabilities HTTP/1.1" - -
+XXX "GET http://localhost:/?bases=0000000000000000000000000000000000000000&cmd=changegroupsubset&heads=83180e7845de420a1bb46896fd5fe05294f8d629 HTTP/1.1" - -
--- a/tests/test-import	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-import	Sun Dec 07 19:34:07 2008 +0100
@@ -285,3 +285,31 @@
 rename to bar
 EOF
 cd ..
+
+echo '% test import with similarity (issue295)'
+hg init sim
+cd sim
+echo 'this is a test' > a
+hg ci -Ama
+cat > ../rename.diff <<EOF
+diff --git a/a b/a
+deleted file mode 100644
+--- a/a
++++ /dev/null
+@@ -1,1 +0,0 @@
+-this is a test
+diff --git a/b b/b
+new file mode 100644
+--- /dev/null
++++ b/b
+@@ -0,0 +1,2 @@
++this is a test
++foo
+EOF
+hg import --no-commit -v -s 1 ../rename.diff
+hg st -C
+hg revert -a
+rm b
+hg import --no-commit -v -s 100 ../rename.diff
+hg st -C
+cd ..
--- a/tests/test-import.out	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-import.out	Sun Dec 07 19:34:07 2008 +0100
@@ -273,3 +273,23 @@
 % test paths outside repo root
 applying patch from stdin
 abort: ../outside/foo not under root
+% test import with similarity (issue295)
+adding a
+applying ../rename.diff
+patching file a
+patching file b
+removing a
+adding b
+recording removal of a as rename to b (88% similar)
+A b
+  a
+R a
+undeleting a
+forgetting b
+applying ../rename.diff
+patching file a
+patching file b
+removing a
+adding b
+A b
+R a
--- a/tests/test-inotify	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-inotify	Sun Dec 07 19:34:07 2008 +0100
@@ -27,4 +27,12 @@
 echo % all
 hg status -A
 
+echo '% path patterns'
+echo x > dir/x
+hg status .
+hg status dir
+cd dir
+hg status .
+cd ..
+
 kill `cat hg.pid`
--- a/tests/test-inotify.out	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-inotify.out	Sun Dec 07 19:34:07 2008 +0100
@@ -27,3 +27,8 @@
 C dir/x
 C dir/y
 C e
+% path patterns
+M dir/x
+? hg.pid
+M dir/x
+M x
--- a/tests/test-log.out	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-log.out	Sun Dec 07 19:34:07 2008 +0100
@@ -5,7 +5,7 @@
 summary:     a
 
 % -f, directory
-abort: can only follow copies/renames for explicit file names
+abort: cannot follow nonexistent file: "dir"
 % -f, but no args
 changeset:   4:b30c444c7c84
 tag:         tip
--- a/tests/test-merge-types.out	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-merge-types.out	Sun Dec 07 19:34:07 2008 +0100
@@ -5,6 +5,8 @@
  overwrite None partial False
  ancestor c334dc3be0da local 521a1e40188f+ remote 3574f3e69b1c
   searching for copies back to rev 1
+ conflicting flags for a
+(n)one, e(x)ec or sym(l)ink? n
  a: update permissions -> e
 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
 (branch merge, don't forget to commit)
@@ -15,6 +17,8 @@
  overwrite None partial False
  ancestor c334dc3be0da local 3574f3e69b1c+ remote 521a1e40188f
   searching for copies back to rev 1
+ conflicting flags for a
+(n)one, e(x)ec or sym(l)ink? n
  a: remote is newer -> g
 getting a
 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
--- a/tests/test-mq-guards	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-mq-guards	Sun Dec 07 19:34:07 2008 +0100
@@ -39,6 +39,9 @@
 hg qguard
 hg qpop
 
+echo % should fail
+hg qpush a.patch
+
 hg qguard a.patch
 echo % should push b.patch
 hg qpush
--- a/tests/test-mq-guards.out	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-mq-guards.out	Sun Dec 07 19:34:07 2008 +0100
@@ -10,6 +10,8 @@
 % should print +a
 a.patch: +a
 Patch queue now empty
+% should fail
+cannot push 'a.patch' - guarded by ['+a']
 a.patch: +a
 % should push b.patch
 applying b.patch
--- a/tests/test-mq-qimport	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-mq-qimport	Sun Dec 07 19:34:07 2008 +0100
@@ -25,7 +25,7 @@
 cd repo
 
 echo % qimport non-existing-file
-hg qimport non-existing-file 2>&1 | sed -e 's/\(No such file or directory:\) .*/\1/'
+hg qimport non-existing-file
 
 echo % import URL
 echo foo >> foo
--- a/tests/test-mq-qimport.out	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-mq-qimport.out	Sun Dec 07 19:34:07 2008 +0100
@@ -1,5 +1,5 @@
 % qimport non-existing-file
-abort: No such file or directory:
+abort: unable to read non-existing-file
 % import URL
 adding url.diff to series file
 url.diff
--- a/tests/test-mq.out	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-mq.out	Sun Dec 07 19:34:07 2008 +0100
@@ -227,7 +227,7 @@
 patch series already fully applied
   qpush fails
   % does nothing and succeeds
-all patches are currently applied
+qpush: test2.patch is already at the top
   qpush test2.patch succeeds
 % strip
 adding x
--- a/tests/test-patchbomb	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-patchbomb	Sun Dec 07 19:34:07 2008 +0100
@@ -4,6 +4,7 @@
 {
     sed -e 's/\(Message-Id:.*@\).*/\1/'  \
         -e 's/\(In-Reply-To:.*@\).*/\1/' \
+        -e 's/\(References:.*@\).*/\1/'  \
         -e 's/===.*/===/'
 }
 
@@ -39,32 +40,78 @@
 description
 EOF
 
-echo % test bundle and description
+echo "% test bundle and description"
 hg email --date '1970-1-1 0:3' -n -f quux -t foo \
     -c bar -s test -r tip -b --desc description | \
     fixheaders
 
-echo % utf-8 patch
+echo "% utf-8 patch"
 python -c 'fp = open("utf", "wb"); fp.write("h\xC3\xB6mma!\n"); fp.close();'
 hg commit -A -d '4 0' -m 'charset=utf-8; content-transfer-encoding: base64'
 
-echo % no mime encoding for email --test
+echo "% no mime encoding for email --test"
 hg email --date '1970-1-1 0:4' -f quux -t foo -c bar -r tip -n | fixheaders > mailtest
-echo % md5sum of 8-bit output
+echo "% md5sum of 8-bit output"
 $TESTDIR/md5sum.py mailtest
 rm mailtest
 
-echo % mime encoded mbox
+echo "% mime encoded mbox"
 hg email --date '1970-1-1 0:4' -f quux -t foo -c bar -r tip -m mbox
 cat mbox | fixheaders
 rm mbox
 
-echo % iso-8859-1 patch
+echo "% iso-8859-1 patch"
 python -c 'fp = open("isolatin", "wb"); fp.write("h\xF6mma!\n"); fp.close();'
 hg commit -A -d '5 0' -m 'charset=us-ascii; content-transfer-encoding: 8bit'
 
-echo % fake ascii mbox
+echo "% fake ascii mbox"
 hg email --date '1970-1-1 0:5' -f quux -t foo -c bar -r tip -m mbox
 fixheaders < mbox > mboxfix
-echo % md5sum of 8-bit output
+echo "% md5sum of 8-bit output"
 $TESTDIR/md5sum.py mboxfix
+
+echo "% test diffstat for single patch"
+hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -d -y 2 | \
+  fixheaders
+
+echo "% test diffstat for multiple patches"
+hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -d -y 0:1 | \
+  fixheaders
+
+echo "% test inline for single patch"
+hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -i 2 | \
+  fixheaders
+
+echo "% test inline for multiple patches"
+hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -i 0:1 | \
+  fixheaders
+
+echo "% test attach for single patch"
+hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -a 2 | \
+  fixheaders
+
+echo "% test attach for multiple patches"
+hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -a 0:1 | \
+  fixheaders
+
+echo "% test intro for single patch"
+hg email --date '1970-1-1 0:1' -n --intro -f quux -t foo -c bar -s test 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 0:1 | \
+  fixheaders
+
+echo "% tagging csets"
+hg tag -r0 zero zero.foo
+hg tag -r1 one one.patch
+hg tag -r2 two two.diff
+
+echo "% test inline for single named patch"
+hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -i 2 | \
+  fixheaders
+
+echo "% test inline for multiple named/unnamed patches"
+hg email --date '1970-1-1 0:1' -n -f quux -t foo -c bar -s test -i 0:1 | \
+  fixheaders
+
--- a/tests/test-patchbomb.out	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-patchbomb.out	Sun Dec 07 19:34:07 2008 +0100
@@ -54,6 +54,7 @@
 X-Mercurial-Node: 8580ff50825a50c8f716709acdf8de0deddcd6ab
 Message-Id: <8580ff50825a50c8f716.121@
 In-Reply-To: <patchbomb.120@
+References: <patchbomb.120@
 Date: Thu, 01 Jan 1970 00:02:01 +0000
 From: quux
 To: foo
@@ -80,6 +81,7 @@
 X-Mercurial-Node: 97d72e5f12c7e84f85064aa72e5a297142c36ed9
 Message-Id: <97d72e5f12c7e84f8506.122@
 In-Reply-To: <patchbomb.120@
+References: <patchbomb.120@
 Date: Thu, 01 Jan 1970 00:02:02 +0000
 From: quux
 To: foo
@@ -189,3 +191,639 @@
 Writing [PATCH] charset=us-ascii; content-transfer-encoding: 8bit ...
 % md5sum of 8-bit output
 90fae277a4a85255e8262174fcefb59f  mboxfix
+% test diffstat for single patch
+This patch series consists of 1 patches.
+
+c
+
+files patched: 1
+
+
+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@
+Date: Thu, 01 Jan 1970 00:01:00 +0000
+From: quux
+To: foo
+Cc: bar
+
+files patched: 1
+
+
+# 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 diffstat for multiple patches
+This patch series consists of 2 patches.
+
+a
+
+files patched: 1
+
+b
+
+files patched: 1
+
+Final summary:
+
+files patched: 2
+
+
+Write the introductory message for the patch series.
+
+
+Displaying [PATCH 0 of 2] test ...
+Content-Type: text/plain; charset="us-ascii"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [PATCH 0 of 2] test
+Message-Id: <patchbomb.60@
+Date: Thu, 01 Jan 1970 00:01:00 +0000
+From: quux
+To: foo
+Cc: bar
+
+
+files patched: 2
+
+Displaying [PATCH 1 of 2] a ...
+Content-Type: text/plain; charset="us-ascii"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [PATCH 1 of 2] a
+X-Mercurial-Node: 8580ff50825a50c8f716709acdf8de0deddcd6ab
+Message-Id: <8580ff50825a50c8f716.61@
+In-Reply-To: <patchbomb.60@
+References: <patchbomb.60@
+Date: Thu, 01 Jan 1970 00:01:01 +0000
+From: quux
+To: foo
+Cc: bar
+
+files patched: 1
+
+
+# HG changeset patch
+# User test
+# Date 1 0
+# Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
+# Parent  0000000000000000000000000000000000000000
+a
+
+diff -r 000000000000 -r 8580ff50825a a
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/a	Thu Jan 01 00:00:01 1970 +0000
+@@ -0,0 +1,1 @@
++a
+
+Displaying [PATCH 2 of 2] b ...
+Content-Type: text/plain; charset="us-ascii"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [PATCH 2 of 2] b
+X-Mercurial-Node: 97d72e5f12c7e84f85064aa72e5a297142c36ed9
+Message-Id: <97d72e5f12c7e84f8506.62@
+In-Reply-To: <patchbomb.60@
+References: <patchbomb.60@
+Date: Thu, 01 Jan 1970 00:01:02 +0000
+From: quux
+To: foo
+Cc: bar
+
+files patched: 1
+
+
+# HG changeset patch
+# User test
+# Date 2 0
+# Node ID 97d72e5f12c7e84f85064aa72e5a297142c36ed9
+# Parent  8580ff50825a50c8f716709acdf8de0deddcd6ab
+b
+
+diff -r 8580ff50825a -r 97d72e5f12c7 b
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/b	Thu Jan 01 00:00:02 1970 +0000
+@@ -0,0 +1,1 @@
++b
+
+% test inline for single patch
+This patch series consists of 1 patches.
+
+
+Displaying [PATCH] test ...
+Content-Type: multipart/mixed; boundary="===
+MIME-Version: 1.0
+Subject: [PATCH] test
+X-Mercurial-Node: ff2c9fa2018b15fa74b33363bda9527323e2a99f
+Message-Id: <ff2c9fa2018b15fa74b3.60@
+Date: Thu, 01 Jan 1970 00:01:00 +0000
+From: quux
+To: foo
+Cc: bar
+
+--===
+Content-Type: text/x-patch; charset="us-ascii"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Content-Disposition: inline; filename=t2.patch
+
+# 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 inline for multiple patches
+This patch series consists of 2 patches.
+
+
+Write the introductory message for the patch series.
+
+
+Displaying [PATCH 0 of 2] test ...
+Content-Type: text/plain; charset="us-ascii"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [PATCH 0 of 2] test
+Message-Id: <patchbomb.60@
+Date: Thu, 01 Jan 1970 00:01:00 +0000
+From: quux
+To: foo
+Cc: bar
+
+
+Displaying [PATCH 1 of 2] a ...
+Content-Type: multipart/mixed; boundary="===
+MIME-Version: 1.0
+Subject: [PATCH 1 of 2] a
+X-Mercurial-Node: 8580ff50825a50c8f716709acdf8de0deddcd6ab
+Message-Id: <8580ff50825a50c8f716.61@
+In-Reply-To: <patchbomb.60@
+References: <patchbomb.60@
+Date: Thu, 01 Jan 1970 00:01:01 +0000
+From: quux
+To: foo
+Cc: bar
+
+--===
+Content-Type: text/x-patch; charset="us-ascii"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Content-Disposition: inline; filename=t2-1.patch
+
+# HG changeset patch
+# User test
+# Date 1 0
+# Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
+# Parent  0000000000000000000000000000000000000000
+a
+
+diff -r 000000000000 -r 8580ff50825a a
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/a	Thu Jan 01 00:00:01 1970 +0000
+@@ -0,0 +1,1 @@
++a
+
+--===
+Displaying [PATCH 2 of 2] b ...
+Content-Type: multipart/mixed; boundary="===
+MIME-Version: 1.0
+Subject: [PATCH 2 of 2] b
+X-Mercurial-Node: 97d72e5f12c7e84f85064aa72e5a297142c36ed9
+Message-Id: <97d72e5f12c7e84f8506.62@
+In-Reply-To: <patchbomb.60@
+References: <patchbomb.60@
+Date: Thu, 01 Jan 1970 00:01:02 +0000
+From: quux
+To: foo
+Cc: bar
+
+--===
+Content-Type: text/x-patch; charset="us-ascii"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Content-Disposition: inline; filename=t2-2.patch
+
+# HG changeset patch
+# User test
+# Date 2 0
+# Node ID 97d72e5f12c7e84f85064aa72e5a297142c36ed9
+# Parent  8580ff50825a50c8f716709acdf8de0deddcd6ab
+b
+
+diff -r 8580ff50825a -r 97d72e5f12c7 b
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/b	Thu Jan 01 00:00:02 1970 +0000
+@@ -0,0 +1,1 @@
++b
+
+--===
+% test attach for single patch
+This patch series consists of 1 patches.
+
+
+Displaying [PATCH] test ...
+Content-Type: multipart/mixed; boundary="===
+MIME-Version: 1.0
+Subject: [PATCH] test
+X-Mercurial-Node: ff2c9fa2018b15fa74b33363bda9527323e2a99f
+Message-Id: <ff2c9fa2018b15fa74b3.60@
+Date: Thu, 01 Jan 1970 00:01:00 +0000
+From: quux
+To: foo
+Cc: bar
+
+--===
+Content-Type: text/plain; charset="us-ascii"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+
+Patch subject is complete summary.
+
+
+
+--===
+Content-Type: text/x-patch; charset="us-ascii"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Content-Disposition: attachment; filename=t2.patch
+
+# 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 attach for multiple patches
+This patch series consists of 2 patches.
+
+
+Write the introductory message for the patch series.
+
+
+Displaying [PATCH 0 of 2] test ...
+Content-Type: text/plain; charset="us-ascii"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [PATCH 0 of 2] test
+Message-Id: <patchbomb.60@
+Date: Thu, 01 Jan 1970 00:01:00 +0000
+From: quux
+To: foo
+Cc: bar
+
+
+Displaying [PATCH 1 of 2] a ...
+Content-Type: multipart/mixed; boundary="===
+MIME-Version: 1.0
+Subject: [PATCH 1 of 2] a
+X-Mercurial-Node: 8580ff50825a50c8f716709acdf8de0deddcd6ab
+Message-Id: <8580ff50825a50c8f716.61@
+In-Reply-To: <patchbomb.60@
+References: <patchbomb.60@
+Date: Thu, 01 Jan 1970 00:01:01 +0000
+From: quux
+To: foo
+Cc: bar
+
+--===
+Content-Type: text/plain; charset="us-ascii"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+
+Patch subject is complete summary.
+
+
+
+--===
+Content-Type: text/x-patch; charset="us-ascii"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Content-Disposition: attachment; filename=t2-1.patch
+
+# HG changeset patch
+# User test
+# Date 1 0
+# Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
+# Parent  0000000000000000000000000000000000000000
+a
+
+diff -r 000000000000 -r 8580ff50825a a
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/a	Thu Jan 01 00:00:01 1970 +0000
+@@ -0,0 +1,1 @@
++a
+
+--===
+Displaying [PATCH 2 of 2] b ...
+Content-Type: multipart/mixed; boundary="===
+MIME-Version: 1.0
+Subject: [PATCH 2 of 2] b
+X-Mercurial-Node: 97d72e5f12c7e84f85064aa72e5a297142c36ed9
+Message-Id: <97d72e5f12c7e84f8506.62@
+In-Reply-To: <patchbomb.60@
+References: <patchbomb.60@
+Date: Thu, 01 Jan 1970 00:01:02 +0000
+From: quux
+To: foo
+Cc: bar
+
+--===
+Content-Type: text/plain; charset="us-ascii"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+
+Patch subject is complete summary.
+
+
+
+--===
+Content-Type: text/x-patch; charset="us-ascii"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Content-Disposition: attachment; filename=t2-2.patch
+
+# HG changeset patch
+# User test
+# Date 2 0
+# Node ID 97d72e5f12c7e84f85064aa72e5a297142c36ed9
+# Parent  8580ff50825a50c8f716709acdf8de0deddcd6ab
+b
+
+diff -r 8580ff50825a -r 97d72e5f12c7 b
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/b	Thu Jan 01 00:00:02 1970 +0000
+@@ -0,0 +1,1 @@
++b
+
+--===
+% test intro for single patch
+This patch series consists of 1 patches.
+
+
+Write the introductory message for the patch series.
+
+
+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@
+Date: Thu, 01 Jan 1970 00:01:00 +0000
+From: quux
+To: foo
+Cc: bar
+
+
+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@
+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.
+
+
+Write the introductory message for the patch series.
+
+
+Displaying [PATCH 0 of 2] test ...
+Content-Type: text/plain; charset="us-ascii"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [PATCH 0 of 2] test
+Message-Id: <patchbomb.60@
+Date: Thu, 01 Jan 1970 00:01:00 +0000
+From: quux
+To: foo
+Cc: bar
+
+
+Displaying [PATCH 1 of 2] a ...
+Content-Type: text/plain; charset="us-ascii"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [PATCH 1 of 2] a
+X-Mercurial-Node: 8580ff50825a50c8f716709acdf8de0deddcd6ab
+Message-Id: <8580ff50825a50c8f716.61@
+In-Reply-To: <patchbomb.60@
+References: <patchbomb.60@
+Date: Thu, 01 Jan 1970 00:01:01 +0000
+From: quux
+To: foo
+Cc: bar
+
+# HG changeset patch
+# User test
+# Date 1 0
+# Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
+# Parent  0000000000000000000000000000000000000000
+a
+
+diff -r 000000000000 -r 8580ff50825a a
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/a	Thu Jan 01 00:00:01 1970 +0000
+@@ -0,0 +1,1 @@
++a
+
+Displaying [PATCH 2 of 2] b ...
+Content-Type: text/plain; charset="us-ascii"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [PATCH 2 of 2] b
+X-Mercurial-Node: 97d72e5f12c7e84f85064aa72e5a297142c36ed9
+Message-Id: <97d72e5f12c7e84f8506.62@
+In-Reply-To: <patchbomb.60@
+References: <patchbomb.60@
+Date: Thu, 01 Jan 1970 00:01:02 +0000
+From: quux
+To: foo
+Cc: bar
+
+# HG changeset patch
+# User test
+# Date 2 0
+# Node ID 97d72e5f12c7e84f85064aa72e5a297142c36ed9
+# Parent  8580ff50825a50c8f716709acdf8de0deddcd6ab
+b
+
+diff -r 8580ff50825a -r 97d72e5f12c7 b
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/b	Thu Jan 01 00:00:02 1970 +0000
+@@ -0,0 +1,1 @@
++b
+
+% tagging csets
+% test inline for single named patch
+This patch series consists of 1 patches.
+
+
+Displaying [PATCH] test ...
+Content-Type: multipart/mixed; boundary="===
+MIME-Version: 1.0
+Subject: [PATCH] test
+X-Mercurial-Node: ff2c9fa2018b15fa74b33363bda9527323e2a99f
+Message-Id: <ff2c9fa2018b15fa74b3.60@
+Date: Thu, 01 Jan 1970 00:01:00 +0000
+From: quux
+To: foo
+Cc: bar
+
+--===
+Content-Type: text/x-patch; charset="us-ascii"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Content-Disposition: inline; filename=two.diff
+
+# 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 inline for multiple named/unnamed patches
+This patch series consists of 2 patches.
+
+
+Write the introductory message for the patch series.
+
+
+Displaying [PATCH 0 of 2] test ...
+Content-Type: text/plain; charset="us-ascii"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: [PATCH 0 of 2] test
+Message-Id: <patchbomb.60@
+Date: Thu, 01 Jan 1970 00:01:00 +0000
+From: quux
+To: foo
+Cc: bar
+
+
+Displaying [PATCH 1 of 2] a ...
+Content-Type: multipart/mixed; boundary="===
+MIME-Version: 1.0
+Subject: [PATCH 1 of 2] a
+X-Mercurial-Node: 8580ff50825a50c8f716709acdf8de0deddcd6ab
+Message-Id: <8580ff50825a50c8f716.61@
+In-Reply-To: <patchbomb.60@
+References: <patchbomb.60@
+Date: Thu, 01 Jan 1970 00:01:01 +0000
+From: quux
+To: foo
+Cc: bar
+
+--===
+Content-Type: text/x-patch; charset="us-ascii"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Content-Disposition: inline; filename=t2-1.patch
+
+# HG changeset patch
+# User test
+# Date 1 0
+# Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
+# Parent  0000000000000000000000000000000000000000
+a
+
+diff -r 000000000000 -r 8580ff50825a a
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/a	Thu Jan 01 00:00:01 1970 +0000
+@@ -0,0 +1,1 @@
++a
+
+--===
+Displaying [PATCH 2 of 2] b ...
+Content-Type: multipart/mixed; boundary="===
+MIME-Version: 1.0
+Subject: [PATCH 2 of 2] b
+X-Mercurial-Node: 97d72e5f12c7e84f85064aa72e5a297142c36ed9
+Message-Id: <97d72e5f12c7e84f8506.62@
+In-Reply-To: <patchbomb.60@
+References: <patchbomb.60@
+Date: Thu, 01 Jan 1970 00:01:02 +0000
+From: quux
+To: foo
+Cc: bar
+
+--===
+Content-Type: text/x-patch; charset="us-ascii"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Content-Disposition: inline; filename=one.patch
+
+# HG changeset patch
+# User test
+# Date 2 0
+# Node ID 97d72e5f12c7e84f85064aa72e5a297142c36ed9
+# Parent  8580ff50825a50c8f716709acdf8de0deddcd6ab
+b
+
+diff -r 8580ff50825a -r 97d72e5f12c7 b
+--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
++++ b/b	Thu Jan 01 00:00:02 1970 +0000
+@@ -0,0 +1,1 @@
++b
+
+--===
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-pull-branch	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,75 @@
+#!/bin/sh
+
+hg init t
+cd t
+echo 1 > foo
+hg ci -Am1 # 0
+hg branch branchA
+echo a1 > foo
+hg ci -ma1 # 1
+
+cd ..
+hg init tt
+cd tt
+hg pull ../t
+hg up branchA
+
+cd ../t
+echo a2 > foo
+hg ci -ma2 # 2
+echo % create branch B
+hg up 0
+hg branch branchB
+echo b1 > foo
+hg ci -mb1 # 3
+
+cd ../tt
+echo % a new branch is there
+hg pull -u ../t
+
+echo % develop both branch
+cd ../t
+hg up branchA
+echo a3 > foo
+hg ci -ma3 # 4
+hg up branchB
+echo b2 > foo
+hg ci -mb2 # 5
+
+cd ../tt
+echo % should succeed, no new heads
+hg pull -u ../t
+
+echo % add an head on other branch
+cd ../t
+hg up branchA
+echo a4 > foo
+hg ci -ma4 # 6
+hg up branchB
+echo b3.1 > foo
+hg ci -m b3.1 # 7
+hg up 5
+echo b3.2 > foo
+hg ci -m b3.2 # 8
+
+cd ../tt
+echo % should succeed only one head on our branch
+hg pull -u ../t
+
+cd ../t
+hg up -C branchA
+echo a5.1 > foo
+hg ci -ma5.1 # 9
+hg up 6
+echo a5.2 > foo
+hg ci -ma5.2 # 10
+hg up 7
+echo b4.1 > foo
+hg ci -m b4.1 # 11
+hg up -C 8
+echo b4.2 > foo
+hg ci -m b4.2 # 12
+
+cd ../tt
+echo % should fail new head in our branch
+hg pull -u ../t
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-pull-branch.out	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,60 @@
+adding foo
+marked working directory as branch branchA
+pulling from ../t
+requesting all changes
+adding changesets
+adding manifests
+adding file changes
+added 2 changesets with 2 changes to 1 files
+(run 'hg update' to get a working copy)
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+% create branch B
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+marked working directory as branch branchB
+created new head
+% a new branch is there
+pulling from ../t
+searching for changes
+adding changesets
+adding manifests
+adding file changes
+added 2 changesets with 2 changes to 1 files (+1 heads)
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+% develop both branch
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+% should succeed, no new heads
+pulling from ../t
+searching for changes
+adding changesets
+adding manifests
+adding file changes
+added 2 changesets with 2 changes to 1 files
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+% add an head on other branch
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+created new head
+% should succeed only one head on our branch
+pulling from ../t
+searching for changes
+adding changesets
+adding manifests
+adding file changes
+added 3 changesets with 3 changes to 1 files (+1 heads)
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+created new head
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+% should fail new head in our branch
+pulling from ../t
+searching for changes
+adding changesets
+adding manifests
+adding file changes
+added 4 changesets with 4 changes to 1 files (+1 heads)
+not updating, since new heads added
+(run 'hg heads' to see heads, 'hg merge' to merge)
--- a/tests/test-push-warn.out	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-push-warn.out	Sun Dec 07 19:34:07 2008 +0100
@@ -22,7 +22,7 @@
 adding changesets
 adding manifests
 adding file changes
-added 2 changesets with 1 changes to 2 files
+added 2 changesets with 1 changes to 1 files
 adding foo
 updating working directory
 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-rebase-keep-branch	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+echo "[extensions]" >> $HGRCPATH
+echo "graphlog=" >> $HGRCPATH
+echo "rebase=" >> $HGRCPATH
+
+addcommit () {
+    echo $1 > $1
+    hg add $1
+    hg commit -d "${2} 0" -u test -m $1
+}
+
+hg init a
+cd a
+addcommit "c1" 0
+addcommit "c2" 1
+
+addcommit "l1" 2
+addcommit "l2" 3
+
+hg update -C 1
+hg branch 'notdefault'
+addcommit "r1" 4
+hg glog --template '{rev}:{desc}:{branches}\n'
+
+echo
+echo '% Rebase a branch while preserving the branch name'
+hg update -C 3
+hg rebase -b 4 -d 3 --keepbranches 2>&1 | sed 's/\(saving bundle to \).*/\1/'
+hg glog --template '{rev}:{desc}:{branches}\n'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-rebase-keep-branch.out	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,33 @@
+0 files updated, 0 files merged, 2 files removed, 0 files unresolved
+marked working directory as branch notdefault
+created new head
+@  4:r1:notdefault
+|
+| o  3:l2:
+| |
+| o  2:l1:
+|/
+o  1:c2:
+|
+o  0:c1:
+
+
+% Rebase a branch while preserving the branch name
+2 files updated, 0 files merged, 1 files removed, 0 files unresolved
+saving bundle to 
+adding branch
+adding changesets
+adding manifests
+adding file changes
+added 1 changesets with 1 changes to 1 files
+rebase completed
+@  4:r1:notdefault
+|
+o  3:l2:
+|
+o  2:l1:
+|
+o  1:c2:
+|
+o  0:c1:
+
--- a/tests/test-rebase-parameters.out	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-rebase-parameters.out	Sun Dec 07 19:34:07 2008 +0100
@@ -15,15 +15,16 @@
 
 options:
 
-    --keep      keep original revisions
- -s --source    rebase from a given revision
- -b --base      rebase from the base of a given revision
- -d --dest      rebase onto a given revision
-    --collapse  collapse the rebased revisions
- -c --continue  continue an interrupted rebase
- -a --abort     abort an interrupted rebase
-    --style     display using template map file
-    --template  display with template
+    --keep          keep original revisions
+    --keepbranches  keep original branches
+ -s --source        rebase from a given revision
+ -b --base          rebase from the base of a given revision
+ -d --dest          rebase onto a given revision
+    --collapse      collapse the rebased revisions
+ -c --continue      continue an interrupted rebase
+ -a --abort         abort an interrupted rebase
+    --style         display using template map file
+    --template      display with template
 
 use "hg -v help rebase" to show global options
 
@@ -42,15 +43,16 @@
 
 options:
 
-    --keep      keep original revisions
- -s --source    rebase from a given revision
- -b --base      rebase from the base of a given revision
- -d --dest      rebase onto a given revision
-    --collapse  collapse the rebased revisions
- -c --continue  continue an interrupted rebase
- -a --abort     abort an interrupted rebase
-    --style     display using template map file
-    --template  display with template
+    --keep          keep original revisions
+    --keepbranches  keep original branches
+ -s --source        rebase from a given revision
+ -b --base          rebase from the base of a given revision
+ -d --dest          rebase onto a given revision
+    --collapse      collapse the rebased revisions
+ -c --continue      continue an interrupted rebase
+ -a --abort         abort an interrupted rebase
+    --style         display using template map file
+    --template      display with template
 
 use "hg -v help rebase" to show global options
 
@@ -69,15 +71,16 @@
 
 options:
 
-    --keep      keep original revisions
- -s --source    rebase from a given revision
- -b --base      rebase from the base of a given revision
- -d --dest      rebase onto a given revision
-    --collapse  collapse the rebased revisions
- -c --continue  continue an interrupted rebase
- -a --abort     abort an interrupted rebase
-    --style     display using template map file
-    --template  display with template
+    --keep          keep original revisions
+    --keepbranches  keep original branches
+ -s --source        rebase from a given revision
+ -b --base          rebase from the base of a given revision
+ -d --dest          rebase onto a given revision
+    --collapse      collapse the rebased revisions
+ -c --continue      continue an interrupted rebase
+ -a --abort         abort an interrupted rebase
+    --style         display using template map file
+    --template      display with template
 
 use "hg -v help rebase" to show global options
 
@@ -96,15 +99,16 @@
 
 options:
 
-    --keep      keep original revisions
- -s --source    rebase from a given revision
- -b --base      rebase from the base of a given revision
- -d --dest      rebase onto a given revision
-    --collapse  collapse the rebased revisions
- -c --continue  continue an interrupted rebase
- -a --abort     abort an interrupted rebase
-    --style     display using template map file
-    --template  display with template
+    --keep          keep original revisions
+    --keepbranches  keep original branches
+ -s --source        rebase from a given revision
+ -b --base          rebase from the base of a given revision
+ -d --dest          rebase onto a given revision
+    --collapse      collapse the rebased revisions
+ -c --continue      continue an interrupted rebase
+ -a --abort         abort an interrupted rebase
+    --style         display using template map file
+    --template      display with template
 
 use "hg -v help rebase" to show global options
 
--- a/tests/test-rename-merge2.out	Sun Dec 07 19:33:26 2008 +0100
+++ b/tests/test-rename-merge2.out	Sun Dec 07 19:34:07 2008 +0100
@@ -455,6 +455,8 @@
   searching for copies back to rev 1
  b: versions differ -> m
  rev: versions differ -> m
+remote changed a which local deleted
+use (c)hanged version or leave (d)eleted? c
  a: prompt recreating -> g
 preserving b for resolve of b
 preserving rev for resolve of rev
@@ -480,6 +482,8 @@
  overwrite None partial False
  ancestor 924404dff337 local 0b76e65c8289+ remote e03727d2d66b
   searching for copies back to rev 1
+ local changed a which remote deleted
+use (c)hanged version or (d)elete? c
  b: versions differ -> m
  rev: versions differ -> m
 preserving b for resolve of b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-status-color	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,97 @@
+#!/bin/sh
+
+echo "[extensions]" >> $HGRCPATH
+echo "color=" >> $HGRCPATH
+
+hg init repo1
+cd repo1
+mkdir a b a/1 b/1 b/2
+touch in_root a/in_a b/in_b a/1/in_a_1 b/1/in_b_1 b/2/in_b_2
+echo "hg status in repo root:"
+hg status --color=always
+echo "hg status . in repo root:"
+hg status --color=always .
+for dir in a b a/1 b/1 b/2; do
+    echo "hg status in $dir:"
+    hg status --color=always --cwd "$dir"
+    echo "hg status . in $dir:"
+    hg status --color=always --cwd "$dir" .
+    echo "hg status .. in $dir:"
+    hg status --color=always --cwd "$dir" ..
+done
+cd ..
+
+hg init repo2
+cd repo2
+touch modified removed deleted ignored
+echo "^ignored$" > .hgignore
+hg ci -A -m 'initial checkin' -d "1000000 0"
+touch modified added unknown ignored
+hg add added
+hg remove removed
+rm deleted
+echo "hg status:"
+hg status --color=always
+echo "hg status modified added removed deleted unknown never-existed ignored:"
+hg status --color=always modified added removed deleted unknown never-existed ignored
+hg copy modified copied
+echo "hg status -C:"
+hg status --color=always -C
+echo "hg status -A:"
+hg status --color=always -A
+echo "^ignoreddir$" > .hgignore
+mkdir ignoreddir
+touch ignoreddir/file
+echo "hg status ignoreddir/file:"
+hg status --color=always ignoreddir/file
+echo "hg status -i ignoreddir/file:"
+hg status --color=always -i ignoreddir/file
+cd ..
+
+# check 'status -q' and some combinations
+hg init repo3
+cd repo3
+touch modified removed deleted ignored
+echo "^ignored$" > .hgignore
+hg commit -A -m 'initial checkin'
+touch added unknown ignored
+hg add added
+echo "test" >> modified
+hg remove removed
+rm deleted
+hg copy modified copied
+
+# Run status with 2 different flags.
+# Check if result is the same or different.
+# If result is not as expected, raise error
+assert() {
+    hg status --color=always $1 > ../a
+    hg status --color=always $2 > ../b
+    out=`diff ../a ../b`
+    if [ $? -ne 0 ]; then
+        out=1
+    else
+        out=0
+    fi
+    if [ $3 -eq 0 ]; then
+        df="same"
+    else
+        df="different"
+    fi
+    if [ $out -ne $3 ]; then
+        echo "Error on $1 and $2, should be $df."
+    fi
+}
+
+# assert flag1 flag2 [0-same | 1-different]
+assert "-q" "-mard"      0
+assert "-A" "-marduicC"  0
+assert "-qA" "-mardcC"   0
+assert "-qAui" "-A"      0
+assert "-qAu" "-marducC" 0
+assert "-qAi" "-mardicC" 0
+assert "-qu" "-u"        0
+assert "-q" "-u"         1
+assert "-m" "-a"         1
+assert "-r" "-d"         1
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-status-color.out	Sun Dec 07 19:34:07 2008 +0100
@@ -0,0 +1,126 @@
+hg status in repo root:
+? a/1/in_a_1
+? a/in_a
+? b/1/in_b_1
+? b/2/in_b_2
+? b/in_b
+? in_root
+hg status . in repo root:
+? a/1/in_a_1
+? a/in_a
+? b/1/in_b_1
+? b/2/in_b_2
+? b/in_b
+? in_root
+hg status in a:
+? a/1/in_a_1
+? a/in_a
+? b/1/in_b_1
+? b/2/in_b_2
+? b/in_b
+? in_root
+hg status . in a:
+? 1/in_a_1
+? in_a
+hg status .. in a:
+? 1/in_a_1
+? in_a
+? ../b/1/in_b_1
+? ../b/2/in_b_2
+? ../b/in_b
+? ../in_root
+hg status in b:
+? a/1/in_a_1
+? a/in_a
+? b/1/in_b_1
+? b/2/in_b_2
+? b/in_b
+? in_root
+hg status . in b:
+? 1/in_b_1
+? 2/in_b_2
+? in_b
+hg status .. in b:
+? ../a/1/in_a_1
+? ../a/in_a
+? 1/in_b_1
+? 2/in_b_2
+? in_b
+? ../in_root
+hg status in a/1:
+? a/1/in_a_1
+? a/in_a
+? b/1/in_b_1
+? b/2/in_b_2
+? b/in_b
+? in_root
+hg status . in a/1:
+? in_a_1
+hg status .. in a/1:
+? in_a_1
+? ../in_a
+hg status in b/1:
+? a/1/in_a_1
+? a/in_a
+? b/1/in_b_1
+? b/2/in_b_2
+? b/in_b
+? in_root
+hg status . in b/1:
+? in_b_1
+hg status .. in b/1:
+? in_b_1
+? ../2/in_b_2
+? ../in_b
+hg status in b/2:
+? a/1/in_a_1
+? a/in_a
+? b/1/in_b_1
+? b/2/in_b_2
+? b/in_b
+? in_root
+hg status . in b/2:
+? in_b_2
+hg status .. in b/2:
+? ../1/in_b_1
+? in_b_2
+? ../in_b
+adding .hgignore
+adding deleted
+adding modified
+adding removed
+hg status:
+A added
+R removed
+! deleted
+? unknown
+hg status modified added removed deleted unknown never-existed ignored:
+never-existed: No such file or directory
+A added
+R removed
+! deleted
+? unknown
+hg status -C:
+A added
+A copied
+  modified
+R removed
+! deleted
+? unknown
+hg status -A:
+A added
+A copied
+  modified
+R removed
+! deleted
+? unknown
+I ignored
+C .hgignore
+C modified
+hg status ignoreddir/file:
+hg status -i ignoreddir/file:
+I ignoreddir/file
+adding .hgignore
+adding deleted
+adding modified
+adding removed