changeset 18867:c7e8b143e086

Merge with stable.
author Augie Fackler <raf@durin42.com>
date Wed, 03 Apr 2013 13:03:50 -0500
parents 835e9dfd1e49 (diff) 930d54b1fd29 (current diff)
children cafa447a7d3b
files
diffstat 189 files changed, 4681 insertions(+), 1859 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Tue Apr 02 16:03:10 2013 +0200
+++ b/Makefile	Wed Apr 03 13:03:50 2013 -0500
@@ -94,6 +94,9 @@
 test-%:
 	cd tests && $(PYTHON) run-tests.py $(TESTFLAGS) $@
 
+check-code:
+	hg manifest | xargs python contrib/check-code.py
+
 update-pot: i18n/hg.pot
 
 i18n/hg.pot: $(PYFILES) $(DOCFILES)
--- a/contrib/bash_completion	Tue Apr 02 16:03:10 2013 +0200
+++ b/contrib/bash_completion	Wed Apr 03 13:03:50 2013 -0500
@@ -1,4 +1,4 @@
-# bash completion for the Mercurial distributed SCM
+# bash completion for the Mercurial distributed SCM -*- sh -*-
 
 # Docs:
 #
@@ -80,26 +80,20 @@
     done
 }
 
-_hg_status()
+_hg_debugpathcomplete()
 {
-    local files="$(_hg_cmd status -n$1 .)"
+    local files="$(_hg_cmd debugpathcomplete $1 "$cur")"
     local IFS=$'\n'
     compopt -o filenames 2>/dev/null
     COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$files' -- "$cur"))
 }
 
-_hg_tags()
+_hg_status()
 {
-    local tags="$(_hg_cmd tags -q)"
+    local files="$(_hg_cmd status -n$1 "glob:$cur**")"
     local IFS=$'\n'
-    COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$tags' -- "$cur"))
-}
-
-_hg_branches()
-{
-    local branches="$(_hg_cmd branches -q)"
-    local IFS=$'\n'
-    COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$branches' -- "$cur"))
+    compopt -o filenames 2>/dev/null
+    COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$files' -- "$cur"))
 }
 
 _hg_bookmarks()
@@ -111,9 +105,9 @@
 
 _hg_labels()
 {
-    _hg_tags
-    _hg_branches
-    _hg_bookmarks
+    local labels="$(_hg_cmd debuglabelcomplete "$cur")"
+    local IFS=$'\n'
+    COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$labels' -- "$cur"))
 }
 
 # this is "kind of" ugly...
@@ -235,7 +229,7 @@
 	    fi
 	    _hg_labels
 	;;
-	manifest|update)
+	manifest|update|up|checkout|co)
 	    _hg_labels
 	;;
 	pull|push|outgoing|incoming)
@@ -251,20 +245,20 @@
 	merge)
 	    _hg_labels
 	;;
-	commit|record)
+	commit|ci|record)
 	    _hg_status "mar"
 	;;
-	remove)
-	    _hg_status "d"
+	remove|rm)
+	    _hg_debugpathcomplete -n
 	;;
 	forget)
-	    _hg_status "a"
+	    _hg_debugpathcomplete -fa
 	;;
 	diff)
 	    _hg_status "mar"
 	;;
 	revert)
-	    _hg_status "mard"
+	    _hg_debugpathcomplete
 	;;
 	clone)
 	    local count=$(_hg_count_non_option)
@@ -294,13 +288,6 @@
 # Completion for commands provided by extensions
 
 # bookmarks
-_hg_bookmarks()
-{
-    local bookmarks="$(_hg_cmd bookmarks --quiet )"
-    local IFS=$'\n'
-    COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$bookmarks' -- "$cur"))
-}
-
 _hg_cmd_bookmarks()
 {
     if [[ "$prev" = @(-d|--delete|-m|--rename) ]]; then
--- a/contrib/check-code.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/contrib/check-code.py	Wed Apr 03 13:03:50 2013 -0500
@@ -80,6 +80,7 @@
     (r'^diff.*-\w*N', "don't use 'diff -N'"),
     (r'\$PWD|\${PWD}', "don't use $PWD, use `pwd`"),
     (r'^([^"\'\n]|("[^"\n]*")|(\'[^\'\n]*\'))*\^', "^ must be quoted"),
+    (r'kill (`|\$\()', "don't use kill, use killdaemons.py")
   ]
 ]
 
@@ -88,6 +89,7 @@
     (r"<<(\S+)((.|\n)*?\n\1)", rephere),
 ]
 
+winglobmsg = "use (glob) to match Windows paths too"
 uprefix = r"^  \$ "
 utestpats = [
   [
@@ -100,11 +102,16 @@
      "explicit exit code checks unnecessary"),
     (uprefix + r'set -e', "don't use set -e"),
     (uprefix + r'\s', "don't indent commands, use > for continued lines"),
-    (r'^  saved backup bundle to \$TESTTMP.*\.hg$',
-     "use (glob) to match Windows paths too"),
+    (r'^  saved backup bundle to \$TESTTMP.*\.hg$', winglobmsg),
+    (r'^  changeset .* references (corrupted|missing) \$TESTTMP/.*[^)]$',
+     winglobmsg),
+    (r'^  pulling from \$TESTTMP/.*[^)]$', winglobmsg, '\$TESTTMP/unix-repo$'),
   ],
   # warnings
-  []
+  [
+    (r'^  [^*?/\n]* \(glob\)$',
+     "warning: glob match with no glob character (?*/)"),
+  ]
 ]
 
 for i in [0, 1]:
@@ -212,7 +219,7 @@
     (r'(?i)descendent', "the proper spelling is descendAnt"),
     (r'\.debug\(\_', "don't mark debug messages for translation"),
     (r'\.strip\(\)\.split\(\)', "no need to strip before splitting"),
-    (r'^\s*except\s*:', "warning: naked except clause", r'#.*re-raises'),
+    (r'^\s*except\s*:', "naked except clause", r'#.*re-raises'),
     (r':\n(    )*( ){1,3}[^ ]', "must indent 4 spaces"),
     (r'ui\.(status|progress|write|note|warn)\([\'\"]x',
      "missing _() in ui message (use () to hide false-positives)"),
--- a/contrib/hgk	Tue Apr 02 16:03:10 2013 +0200
+++ b/contrib/hgk	Wed Apr 03 13:03:50 2013 -0500
@@ -30,6 +30,8 @@
     interp alias {} ttk::label {} label
     interp alias {} ttk::scrollbar {} scrollbar
     interp alias {} ttk::optionMenu {} tk_optionMenu
+
+    proc updatepalette {} {}
 } else {
     proc ::ttk::optionMenu {w varName firstValue args} {
         upvar #0 $varName var
@@ -46,6 +48,11 @@
         }
         return $w.menu
     }
+    proc updatepalette {} {
+        catch {
+            tk_setPalette background [ttk::style lookup client -background]
+        }
+    }
 }
 
 if {[tk windowingsystem] eq "win32"} {
@@ -120,6 +127,7 @@
 
 }
 
+updatepalette
 
 # Unify right mouse button handling.
 # See "mouse buttons on macintosh" thread on comp.lang.tcl
@@ -139,6 +147,18 @@
     }
 }
 
+proc popupify {w} {
+    wm resizable $w 0 0
+    wm withdraw $w
+    update
+    set x [expr {([winfo screenwidth .]-[winfo reqwidth $w])/2}]
+    set y [expr {([winfo screenheight .]-[winfo reqheight $w])/2}]
+    wm geometry  $w +$x+$y
+    wm transient $w .
+    wm deiconify $w
+    wm resizable $w 1 1
+}
+
 proc getcommits {rargs} {
     global commits commfd phase canv mainfont env
     global startmsecs nextupdate ncmupdate
@@ -380,11 +400,11 @@
 	}
     }
     if {$audate != {}} {
-	set audate [clock format $audate -format "%Y-%m-%d %H:%M:%S"]
+	set audate [clock format $audate]
     }
     if {$comdate != {}} {
 	set cdate($id) $comdate
-	set comdate [clock format $comdate -format "%Y-%m-%d %H:%M:%S"]
+	set comdate [clock format $comdate]
     }
     set commitinfo($id) [list $headline $auname $audate \
 			     $comname $comdate $comment $rev $branch $bookmark]
@@ -436,16 +456,13 @@
             exit 2
         }
     }
-    regsub -all "\r\n" $tags "\n" tags
-
-    set lines [split $tags "\n"]
-    foreach f $lines {
-	regexp {(\S+)$} $f full
-	regsub {\s+(\S+)$} $f "" direct
-	set sha [split $full ':']
-	set tag [lindex $sha 1]
-	lappend tagids($direct) $tag
-	lappend idtags($tag) $direct
+
+    foreach {tag rev} $tags {
+        # we use foreach as Tcl8.4 doesn't support lassign
+        foreach {- id} [split $rev :] {
+            lappend tagids($tag) $id
+            lappend idtags($id) $tag
+        }
     }
 
     set status [catch {exec $env(HG) --config ui.report_untrusted=false heads} heads]
@@ -455,9 +472,8 @@
             exit 2
         }
     }
-    regsub -all "\r\n" $heads "\n" heads
-
-    set lines [split $heads "\n"]
+
+    set lines [split $heads \r\n]
     foreach f $lines {
         set match ""
         regexp {changeset:\s+(\S+):(\S+)$} $f match id sha
@@ -529,6 +545,7 @@
     ttk::button $w.ok -text OK -command "destroy $w"
     pack $w.ok -side bottom -fill x
     bind $w <Visibility> "grab $w; focus $w"
+    popupify $w
     tkwait window $w
 }
 
@@ -642,7 +659,7 @@
 			  findtype Exact IgnCase Regexp]
     set findloc "All fields"
     ttk::optionMenu .ctop.top.bar.findloc findloc "All fields" Headline \
-	Comments Author Committer Files Pickaxe
+	Comments Author Files Pickaxe
     pack .ctop.top.bar.findloc -side right
     pack .ctop.top.bar.findtype -side right
     # for making sure type==Exact whenever loc==Pickaxe
@@ -949,6 +966,7 @@
     pack $w.m -side top -fill x -padx 20 -pady 20
     ttk::button $w.ok -text Close -command "destroy $w"
     pack $w.ok -side bottom
+    popupify $w
 }
 
 set aunextcolor 0
@@ -1929,7 +1947,7 @@
 	set oldsel $selectedline
     }
     set didsel 0
-    set fldtypes {Headline Author Date Committer CDate Comment}
+    set fldtypes {Headline Author Date CDate Comment}
     for {set l 0} {$l < $numcommits} {incr l} {
 	set id $lineid($l)
 	set info $commitinfo($id)
@@ -2471,12 +2489,12 @@
     $ctext mark set fmark.0 0.0
     $ctext mark gravity fmark.0 left
     set info $commitinfo($id)
-    $ctext insert end "Revision: [lindex $info 6]\n"
+    $ctext insert end "Changeset: [lindex $info 6]\n"
     if {[llength [lindex $info 7]] > 0} {
         $ctext insert end "Branch: [lindex $info 7]\n"
     }
-    $ctext insert end "Author: [lindex $info 1]  [lindex $info 2]\n"
-    $ctext insert end "Committer: [lindex $info 3]  [lindex $info 4]\n"
+    $ctext insert end "User: [lindex $info 1]\n"
+    $ctext insert end "Date: [lindex $info 2]\n"
     if {[info exists idbookmarks($id)]} {
 	$ctext insert end "Bookmarks:"
 	foreach bookmark $idbookmarks($id) {
@@ -3601,7 +3619,7 @@
     $ctext tag bind link0 <1> [list selbyid $id]
     set info $commitinfo($id)
     $ctext insert end "\n\t[lindex $info 0]\n"
-    $ctext insert end "\tAuthor:\t[lindex $info 1]\n"
+    $ctext insert end "\tUser:\t[lindex $info 1]\n"
     $ctext insert end "\tDate:\t[lindex $info 2]\n"
     if {[info exists children($id)]} {
 	$ctext insert end "\nChildren:"
@@ -3613,7 +3631,7 @@
 	    $ctext insert end $child [list link link$i]
 	    $ctext tag bind link$i <1> [list selbyid $child]
 	    $ctext insert end "\n\t[lindex $info 0]"
-	    $ctext insert end "\n\tAuthor:\t[lindex $info 1]"
+	    $ctext insert end "\n\tUser:\t[lindex $info 1]"
 	    $ctext insert end "\n\tDate:\t[lindex $info 2]\n"
 	}
     }
@@ -3720,13 +3738,11 @@
     set patchtop $top
     catch {destroy $top}
     toplevel $top
-    ttk::label $top.title -text "Generate patch"
-    grid $top.title - -pady 10
     ttk::label $top.from -text "From:"
     ttk::entry $top.fromsha1 -width 40
     $top.fromsha1 insert 0 $oldid
     $top.fromsha1 conf -state readonly
-    grid $top.from $top.fromsha1 -sticky w
+    grid $top.from $top.fromsha1 -sticky w -pady {10 0}
     ttk::entry $top.fromhead -width 60
     $top.fromhead insert 0 $oldhead
     $top.fromhead conf -state readonly
@@ -3755,6 +3771,8 @@
     grid columnconfigure $top.buts 1 -weight 1 -uniform a
     grid $top.buts - -pady 10 -sticky ew
     focus $top.fname
+    popupify $top
+    wm title $top "Generate a patch"
 }
 
 proc mkpatchrev {} {
@@ -3800,13 +3818,11 @@
     set mktagtop $top
     catch {destroy $top}
     toplevel $top
-    ttk::label $top.title -text "Create tag"
-    grid $top.title - -pady 10
     ttk::label $top.id -text "ID:"
     ttk::entry $top.sha1 -width 40
     $top.sha1 insert 0 $rowmenuid
     $top.sha1 conf -state readonly
-    grid $top.id $top.sha1 -sticky w
+    grid $top.id $top.sha1 -sticky w -pady {10 0}
     ttk::entry $top.head -width 60
     $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
     $top.head conf -state readonly
@@ -3822,6 +3838,8 @@
     grid columnconfigure $top.buts 1 -weight 1 -uniform a
     grid $top.buts - -pady 10 -sticky ew
     focus $top.tag
+    popupify $top
+    wm title $top "Create a tag"
 }
 
 proc domktag {} {
@@ -3880,13 +3898,11 @@
     set wrcomtop $top
     catch {destroy $top}
     toplevel $top
-    ttk::label $top.title -text "Write commit to file"
-    grid $top.title - -pady 10
     ttk::label $top.id -text "ID:"
     ttk::entry $top.sha1 -width 40
     $top.sha1 insert 0 $rowmenuid
     $top.sha1 conf -state readonly
-    grid $top.id $top.sha1 -sticky w
+    grid $top.id $top.sha1 -sticky w -pady {10 0}
     ttk::entry $top.head -width 60
     $top.head insert 0 [lindex $commitinfo($rowmenuid) 0]
     $top.head conf -state readonly
@@ -3906,6 +3922,8 @@
     grid columnconfigure $top.buts 1 -weight 1 -uniform a
     grid $top.buts - -pady 10 -sticky ew
     focus $top.fname
+    popupify $top
+    wm title $top "Write commit to a file"
 }
 
 proc wrcomgo {} {
--- a/contrib/perf.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/contrib/perf.py	Wed Apr 03 13:03:50 2013 -0500
@@ -2,7 +2,7 @@
 '''helper extension to measure performance'''
 
 from mercurial import cmdutil, scmutil, util, match, commands, obsolete
-from mercurial import repoview, branchmap
+from mercurial import repoview, branchmap, merge
 import time, os, sys
 
 cmdtable = {}
@@ -99,6 +99,15 @@
             rev in s
     timer(d)
 
+@command('perfdirs')
+def perfdirs(ui, repo):
+    dirstate = repo.dirstate
+    'a' in dirstate
+    def d():
+        dirstate.dirs()
+        del dirstate._dirs
+    timer(d)
+
 @command('perfdirstate')
 def perfdirstate(ui, repo):
     "a" in repo.dirstate
@@ -124,6 +133,22 @@
         ds.write()
     timer(d)
 
+@command('perfmergecalculate',
+         [('r', 'rev', '.', 'rev to merge against')])
+def perfmergecalculate(ui, repo, rev):
+    wctx = repo[None]
+    rctx = scmutil.revsingle(repo, rev, rev)
+    ancestor = wctx.ancestor(rctx)
+    # we don't want working dir files to be stat'd in the benchmark, so prime
+    # that cache
+    wctx.dirty()
+    def d():
+        # acceptremote is True because we don't want prompts in the middle of
+        # our benchmark
+        merge.calculateupdates(repo, wctx, rctx, ancestor, False, False, False,
+                               acceptremote=True)
+    timer(d)
+
 @command('perfmanifest')
 def perfmanifest(ui, repo):
     def d():
@@ -268,7 +293,7 @@
 def perfrevset(ui, repo, expr, clear=False):
     """benchmark the execution time of a revset
 
-    Use the --clean option if need to evaluate the impact of build volative
+    Use the --clean option if need to evaluate the impact of build volatile
     revisions set cache on the revset execution. Volatile cache hold filtered
     and obsolete related cache."""
     def d():
@@ -361,6 +386,3 @@
     finally:
         branchmap.read = oldread
         branchmap.branchcache.write = oldwrite
-
-
-
--- a/doc/gendoc.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/doc/gendoc.py	Wed Apr 03 13:03:50 2013 -0500
@@ -5,6 +5,7 @@
 sys.path.append(os.path.join('..', 'mercurial', 'pure'))
 from mercurial import demandimport; demandimport.enable()
 from mercurial import encoding
+from mercurial import minirst
 from mercurial.commands import table, globalopts
 from mercurial.i18n import _
 from mercurial.help import helptable
@@ -63,28 +64,15 @@
 
     return d
 
-def section(ui, s):
-    ui.write("%s\n%s\n\n" % (s, "\"" * encoding.colwidth(s)))
-
-def subsection(ui, s):
-    ui.write("%s\n%s\n\n" % (s, '=' * encoding.colwidth(s)))
-
-def subsubsection(ui, s):
-    ui.write("%s\n%s\n\n" % (s, "-" * encoding.colwidth(s)))
-
-def subsubsubsection(ui, s):
-    ui.write("%s\n%s\n\n" % (s, "." * encoding.colwidth(s)))
-
-
 def show_doc(ui):
     # print options
-    section(ui, _("Options"))
+    ui.write(minirst.section(_("Options")))
     for optstr, desc in get_opts(globalopts):
         ui.write("%s\n    %s\n\n" % (optstr, desc))
 
     # print cmds
-    section(ui, _("Commands"))
-    commandprinter(ui, table, subsection)
+    ui.write(minirst.section(_("Commands")))
+    commandprinter(ui, table, minirst.subsection)
 
     # print topics
     for names, sec, doc in helptable:
@@ -95,13 +83,13 @@
         for name in names:
             ui.write(".. _%s:\n" % name)
         ui.write("\n")
-        section(ui, sec)
+        ui.write(minirst.section(sec))
         if util.safehasattr(doc, '__call__'):
             doc = doc()
         ui.write(doc)
         ui.write("\n")
 
-    section(ui, _("Extensions"))
+    ui.write(minirst.section(_("Extensions")))
     ui.write(_("This section contains help for extensions that are "
                "distributed together with Mercurial. Help for other "
                "extensions is available in the help system."))
@@ -113,12 +101,12 @@
 
     for extensionname in sorted(allextensionnames()):
         mod = extensions.load(None, extensionname, None)
-        subsection(ui, extensionname)
+        ui.write(minirst.subsection(extensionname))
         ui.write("%s\n\n" % mod.__doc__)
         cmdtable = getattr(mod, 'cmdtable', None)
         if cmdtable:
-            subsubsection(ui, _('Commands'))
-            commandprinter(ui, cmdtable, subsubsubsection)
+            ui.write(minirst.subsubsection(_('Commands')))
+            commandprinter(ui, cmdtable, minirst.subsubsubsection)
 
 def commandprinter(ui, cmdtable, sectionfunc):
     h = {}
@@ -133,7 +121,7 @@
         if f.startswith("debug"):
             continue
         d = get_cmd(h[f], cmdtable)
-        sectionfunc(ui, d['cmd'])
+        ui.write(sectionfunc(d['cmd']))
         # synopsis
         ui.write("::\n\n")
         synopsislines = d['synopsis'].splitlines()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hgext/blackbox.py	Wed Apr 03 13:03:50 2013 -0500
@@ -0,0 +1,119 @@
+# blackbox.py - log repository events to a file for post-mortem debugging
+#
+# Copyright 2010 Nicolas Dumazet
+# Copyright 2013 Facebook, Inc.
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+
+"""log repository events to a blackbox for debugging
+
+Logs event information to .hg/blackbox.log to help debug and diagnose problems.
+The events that get logged can be configured via the blackbox.track config key.
+Examples:
+
+  [blackbox]
+  track = *
+
+  [blackbox]
+  track = command, commandfinish, commandexception, exthook, pythonhook
+
+  [blackbox]
+  track = incoming
+
+"""
+
+from mercurial import util, cmdutil
+from mercurial.i18n import _
+import os, re
+
+cmdtable = {}
+command = cmdutil.command(cmdtable)
+testedwith = 'internal'
+lastblackbox = None
+
+def wrapui(ui):
+    class blackboxui(ui.__class__):
+        @util.propertycache
+        def track(self):
+            return ui.configlist('blackbox', 'track', ['*'])
+
+        def log(self, event, *msg, **opts):
+            global lastblackbox
+            super(blackboxui, self).log(event, *msg, **opts)
+
+            if not '*' in self.track and not event in self.track:
+                return
+
+            if util.safehasattr(self, '_blackbox'):
+                blackbox = self._blackbox
+            elif util.safehasattr(self, '_bbopener'):
+                try:
+                    self._blackbox = self._bbopener('blackbox.log', 'a')
+                except (IOError, OSError), err:
+                    self.debug('warning: cannot write to blackbox.log: %s\n' %
+                               err.strerror)
+                    del self._bbopener
+                    self._blackbox = None
+                blackbox = self._blackbox
+            else:
+                # certain ui instances exist outside the context of
+                # a repo, so just default to the last blackbox that
+                # was seen.
+                blackbox = lastblackbox
+
+            if blackbox:
+                date = util.datestr(None, '%Y/%m/%d %H:%M:%S')
+                user = util.getuser()
+                formattedmsg = msg[0] % msg[1:]
+                try:
+                    blackbox.write('%s %s> %s' % (date, user, formattedmsg))
+                except IOError, err:
+                    self.debug('warning: cannot write to blackbox.log: %s\n' %
+                               err.strerror)
+                lastblackbox = blackbox
+
+        def setrepo(self, repo):
+            self._bbopener = repo.opener
+
+    ui.__class__ = blackboxui
+
+def uisetup(ui):
+    wrapui(ui)
+
+def reposetup(ui, repo):
+    # During 'hg pull' a httppeer repo is created to represent the remote repo.
+    # It doesn't have a .hg directory to put a blackbox in, so we don't do
+    # the blackbox setup for it.
+    if not repo.local():
+        return
+
+    ui.setrepo(repo)
+
+@command('^blackbox',
+    [('l', 'limit', 10, _('the number of events to show')),
+    ],
+    _('hg blackbox [OPTION]...'))
+def blackbox(ui, repo, *revs, **opts):
+    '''view the recent repository events
+    '''
+
+    if not os.path.exists(repo.join('blackbox.log')):
+        return
+
+    limit = opts.get('limit')
+    blackbox = repo.opener('blackbox.log', 'r')
+    lines = blackbox.read().split('\n')
+
+    count = 0
+    output = []
+    for line in reversed(lines):
+        if count >= limit:
+            break
+
+        # count the commands by matching lines like: 2013/01/23 19:13:36 root>
+        if re.match('^\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} .*> .*', line):
+            count += 1
+        output.append(line)
+
+    ui.status('\n'.join(reversed(output)))
--- a/hgext/color.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/hgext/color.py	Wed Apr 03 13:03:50 2013 -0500
@@ -379,7 +379,6 @@
     return repo.ui.label(thing, label)
 
 def uisetup(ui):
-    global _terminfo_params
     if ui.plain():
         return
     def colorcmd(orig, ui_, opts, cmd, cmdfunc):
--- a/hgext/convert/__init__.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/hgext/convert/__init__.py	Wed Apr 03 13:03:50 2013 -0500
@@ -61,6 +61,10 @@
     --sourcesort  try to preserve source revisions order, only
                   supported by Mercurial sources.
 
+    --closesort   try to move closed revisions as close as possible
+                  to parent branches, only supported by Mercurial
+                  sources.
+
     If ``REVMAP`` isn't given, it will be put in a default location
     (``<dest>/.hg/shamap`` by default). The ``REVMAP`` is a simple
     text file that maps each source commit ID to the destination ID
@@ -318,7 +322,8 @@
            _('change branch names while converting'), _('FILE')),
           ('', 'branchsort', None, _('try to sort changesets by branches')),
           ('', 'datesort', None, _('try to sort changesets by date')),
-          ('', 'sourcesort', None, _('preserve source changesets order'))],
+          ('', 'sourcesort', None, _('preserve source changesets order')),
+          ('', 'closesort', None, _('try to reorder closed revisions'))],
          _('hg convert [OPTION]... SOURCE [DEST [REVMAP]]')),
     "debugsvnlog":
         (debugsvnlog,
--- a/hgext/convert/common.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/hgext/convert/common.py	Wed Apr 03 13:03:50 2013 -0500
@@ -145,6 +145,11 @@
         """
         return False
 
+    def hasnativeclose(self):
+        """Return true if this source has ability to close branch.
+        """
+        return False
+
     def lookuprev(self, rev):
         """If rev is a meaningful revision reference in source, return
         the referenced identifier in the same format used by getcommit().
--- a/hgext/convert/convcmd.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/hgext/convert/convcmd.py	Wed Apr 03 13:03:50 2013 -0500
@@ -227,6 +227,14 @@
                 return sorted(nodes, key=keyfn)[0]
             return picknext
 
+        def makeclosesorter():
+            """Close order sort."""
+            keyfn = lambda n: ('close' not in self.commitcache[n].extra,
+                               self.commitcache[n].sortkey)
+            def picknext(nodes):
+                return sorted(nodes, key=keyfn)[0]
+            return picknext
+
         def makedatesorter():
             """Sort revisions by date."""
             dates = {}
@@ -246,6 +254,8 @@
             picknext = makedatesorter()
         elif sortmode == 'sourcesort':
             picknext = makesourcesorter()
+        elif sortmode == 'closesort':
+            picknext = makeclosesorter()
         else:
             raise util.Abort(_('unknown sort mode: %s') % sortmode)
 
@@ -446,13 +456,15 @@
             shutil.rmtree(path, True)
         raise
 
-    sortmodes = ('branchsort', 'datesort', 'sourcesort')
+    sortmodes = ('branchsort', 'datesort', 'sourcesort', 'closesort')
     sortmode = [m for m in sortmodes if opts.get(m)]
     if len(sortmode) > 1:
         raise util.Abort(_('more than one sort mode specified'))
     sortmode = sortmode and sortmode[0] or defaultsort
     if sortmode == 'sourcesort' and not srcc.hasnativeorder():
         raise util.Abort(_('--sourcesort is not supported by this data source'))
+    if sortmode == 'closesort' and not srcc.hasnativeclose():
+        raise util.Abort(_('--closesort is not supported by this data source'))
 
     fmap = opts.get('filemap')
     if fmap:
--- a/hgext/convert/cvsps.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/hgext/convert/cvsps.py	Wed Apr 03 13:03:50 2013 -0500
@@ -508,9 +508,15 @@
 
     ui.status(_('creating changesets\n'))
 
+    # try to order commitids by date
+    mindate = {}
+    for e in log:
+        if e.commitid:
+            mindate[e.commitid] = min(e.date, mindate.get(e.commitid))
+
     # Merge changesets
-    log.sort(key=lambda x: (x.commitid, x.comment, x.author, x.branch, x.date,
-                            x.branchpoints))
+    log.sort(key=lambda x: (mindate.get(x.commitid), x.commitid, x.comment,
+                            x.author, x.branch, x.date, x.branchpoints))
 
     changesets = []
     files = set()
--- a/hgext/convert/git.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/hgext/convert/git.py	Wed Apr 03 13:03:50 2013 -0500
@@ -6,6 +6,7 @@
 # GNU General Public License version 2 or any later version.
 
 import os
+import subprocess
 from mercurial import util, config
 from mercurial.node import hex, nullid
 from mercurial.i18n import _
@@ -29,13 +30,15 @@
     # cannot remove environment variable. Just assume none have
     # both issues.
     if util.safehasattr(os, 'unsetenv'):
-        def gitopen(self, s, noerr=False):
+        def gitopen(self, s, err=None):
             prevgitdir = os.environ.get('GIT_DIR')
             os.environ['GIT_DIR'] = self.path
             try:
-                if noerr:
+                if err == subprocess.PIPE:
                     (stdin, stdout, stderr) = util.popen3(s)
                     return stdout
+                elif err == subprocess.STDOUT:
+                    return self.popen_with_stderr(s)
                 else:
                     return util.popen(s, 'rb')
             finally:
@@ -44,13 +47,25 @@
                 else:
                     os.environ['GIT_DIR'] = prevgitdir
     else:
-        def gitopen(self, s, noerr=False):
-            if noerr:
+        def gitopen(self, s, err=None):
+            if err == subprocess.PIPE:
                 (sin, so, se) = util.popen3('GIT_DIR=%s %s' % (self.path, s))
                 return so
+            elif err == subprocess.STDOUT:
+                    return self.popen_with_stderr(s)
             else:
                 return util.popen('GIT_DIR=%s %s' % (self.path, s), 'rb')
 
+    def popen_with_stderr(self, s):
+        p = subprocess.Popen(s, shell=True, bufsize=-1,
+                             close_fds=util.closefds,
+                             stdin=subprocess.PIPE,
+                             stdout=subprocess.PIPE,
+                             stderr=subprocess.STDOUT,
+                             universal_newlines=False,
+                             env=None)
+        return p.stdout
+
     def gitread(self, s):
         fh = self.gitopen(s)
         data = fh.read()
@@ -209,12 +224,15 @@
     def gettags(self):
         tags = {}
         alltags = {}
-        fh = self.gitopen('git ls-remote --tags "%s"' % self.path)
+        fh = self.gitopen('git ls-remote --tags "%s"' % self.path,
+                          err=subprocess.STDOUT)
         prefix = 'refs/tags/'
 
         # Build complete list of tags, both annotated and bare ones
         for line in fh:
             line = line.strip()
+            if line.startswith("error:") or line.startswith("fatal:"):
+                raise util.Abort(_('cannot read tags from %s') % self.path)
             node, tag = line.split(None, 1)
             if not tag.startswith(prefix):
                 continue
@@ -266,7 +284,7 @@
         # Origin heads
         for reftype in gitcmd:
             try:
-                fh = self.gitopen(gitcmd[reftype], noerr=True)
+                fh = self.gitopen(gitcmd[reftype], err=subprocess.PIPE)
                 for line in fh:
                     line = line.strip()
                     rev, name = line.split(None, 1)
--- a/hgext/convert/hg.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/hgext/convert/hg.py	Wed Apr 03 13:03:50 2013 -0500
@@ -386,6 +386,9 @@
     def hasnativeorder(self):
         return True
 
+    def hasnativeclose(self):
+        return True
+
     def lookuprev(self, rev):
         try:
             return hex(self.repo.lookup(rev))
--- a/hgext/factotum.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/hgext/factotum.py	Wed Apr 03 13:03:50 2013 -0500
@@ -47,8 +47,8 @@
 
 from mercurial.i18n import _
 from mercurial.url import passwordmgr
-from mercurial import httpconnection, urllib2, util
-import os
+from mercurial import httpconnection, util
+import os, urllib2
 
 ERRMAX = 128
 
--- a/hgext/hgk.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/hgext/hgk.py	Wed Apr 03 13:03:50 2013 -0500
@@ -114,7 +114,8 @@
     if committer != '':
         ui.write(("committer %s %s %s\n" % (committer, int(date[0]), date[1])))
     ui.write(("revision %d\n" % ctx.rev()))
-    ui.write(("branch %s\n\n" % ctx.branch()))
+    ui.write(("branch %s\n" % ctx.branch()))
+    ui.write(("phase %s\n\n" % ctx.phasestr()))
 
     if prefix != "":
         ui.write("%s%s\n" % (prefix,
--- a/hgext/histedit.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/hgext/histedit.py	Wed Apr 03 13:03:50 2013 -0500
@@ -179,7 +179,7 @@
 def commitfuncfor(repo, src):
     """Build a commit function for the replacement of <src>
 
-    This function ensure we apply the same treatement to all changesets.
+    This function ensure we apply the same treatment to all changesets.
 
     - Add a 'histedit_source' entry in extra.
 
@@ -498,8 +498,8 @@
         keep = opts.get('keep', False)
         revs = between(repo, parent, topmost, keep)
         if not revs:
-            ui.warn(_('nothing to edit\n'))
-            return 1
+            raise util.Abort(_('%s is not an ancestor of working directory') %
+                             node.short(parent))
 
         ctxs = [repo[r] for r in revs]
         rules = opts.get('commands', '')
@@ -583,7 +583,7 @@
     if not newchildren:
         # `parentctxnode` should match but no result. This means that
         # currentnode is not a descendant from parentctxnode.
-        msg = _('working directory parent is not a descendant of %s')
+        msg = _('%s is not an ancestor of working directory')
         hint = _('update to %s or descendant and run "hg histedit '
                  '--continue" again') % parentctx
         raise util.Abort(msg % parentctx, hint=hint)
@@ -626,7 +626,7 @@
                                      newchildren)
         replacements.extend(repl)
     elif newchildren:
-        # otherwize update "parentctx" before proceding to further operation
+        # otherwise update "parentctx" before proceeding to further operation
         parentctx = repo[newchildren[-1]]
     return parentctx, replacements
 
--- a/hgext/keyword.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/hgext/keyword.py	Wed Apr 03 13:03:50 2013 -0500
@@ -384,7 +384,7 @@
     fn = 'demo.txt'
     tmpdir = tempfile.mkdtemp('', 'kwdemo.')
     ui.note(_('creating temporary repository at %s\n') % tmpdir)
-    repo = localrepo.localrepository(ui, tmpdir, True)
+    repo = localrepo.localrepository(repo.baseui, tmpdir, True)
     ui.setconfig('keyword', fn, '')
     svn = ui.configbool('keywordset', 'svn')
     # explicitly set keywordset for demo output
--- a/hgext/largefiles/__init__.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/hgext/largefiles/__init__.py	Wed Apr 03 13:03:50 2013 -0500
@@ -41,11 +41,24 @@
 enabled for this to work.
 
 When you pull a changeset that affects largefiles from a remote
-repository, Mercurial behaves as normal. However, when you update to
-such a revision, any largefiles needed by that revision are downloaded
-and cached (if they have never been downloaded before). This means
-that network access may be required to update to changesets you have
-not previously updated to.
+repository, the largefiles for the changeset won't be pulled down.
+Instead, when you later update to such a revision, any largefiles
+needed by that revision are downloaded and cached (if they have
+never been downloaded before).  This means that network access may
+be required to update to changesets you have previously updated to.
+
+If you know you are pulling from a non-default location and want to
+ensure that you will have the largefiles needed to merge or rebase
+with new heads that you are pulling, then you can pull with the
+--cache-largefiles flag to pre-emptively download any largefiles
+that are new in the heads you are pulling.
+
+The one exception to the "largefiles won't be pulled until you update
+to a revision that changes them" rule is when you pull new heads.
+Because you could be pulling new heads (that you may later want to
+merge with) from a non-default location (that Mercurial won't know
+about later), when you pull new heads, largefiles revisions for those
+heads are downloaded and cached locally.
 
 If you already have large files tracked by Mercurial without the
 largefiles extension, you will need to convert your repository in
--- a/hgext/largefiles/basestore.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/hgext/largefiles/basestore.py	Wed Apr 03 13:03:50 2013 -0500
@@ -43,7 +43,8 @@
         raise NotImplementedError('abstract method')
 
     def exists(self, hashes):
-        '''Check to see if the store contains the given hashes.'''
+        '''Check to see if the store contains the given hashes. Given an
+        iterable of hashes it returns a mapping from hash to bool.'''
         raise NotImplementedError('abstract method')
 
     def get(self, files):
@@ -98,10 +99,10 @@
         '''Verify the existence (and, optionally, contents) of every big
         file revision referenced by every changeset in revs.
         Return 0 if all is well, non-zero on any errors.'''
-        write = self.ui.write
         failed = False
 
-        write(_('searching %d changesets for largefiles\n') % len(revs))
+        self.ui.status(_('searching %d changesets for largefiles\n') %
+                       len(revs))
         verified = set()                # set of (filename, filenode) tuples
 
         for rev in revs:
@@ -115,12 +116,13 @@
         numrevs = len(verified)
         numlfiles = len(set([fname for (fname, fnode) in verified]))
         if contents:
-            write(_('verified contents of %d revisions of %d largefiles\n')
-                  % (numrevs, numlfiles))
+            self.ui.status(
+                _('verified contents of %d revisions of %d largefiles\n')
+                % (numrevs, numlfiles))
         else:
-            write(_('verified existence of %d revisions of %d largefiles\n')
-                  % (numrevs, numlfiles))
-
+            self.ui.status(
+                _('verified existence of %d revisions of %d largefiles\n')
+                % (numrevs, numlfiles))
         return int(failed)
 
     def _getfile(self, tmpfile, filename, hash):
@@ -133,6 +135,11 @@
 
     def _verifyfile(self, cctx, cset, contents, standin, verified):
         '''Perform the actual verification of a file in the store.
+        'cset' is only used in warnings.
+        'contents' controls verification of content hash.
+        'standin' is the standin path of the largefile to verify.
+        'verified' is maintained as a set of already verified files.
+        Returns _true_ if it is a standin and any problems are found!
         '''
         raise NotImplementedError('abstract method')
 
--- a/hgext/largefiles/lfcommands.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/hgext/largefiles/lfcommands.py	Wed Apr 03 13:03:50 2013 -0500
@@ -368,9 +368,9 @@
     ui.progress(_('uploading largefiles'), None)
 
 def verifylfiles(ui, repo, all=False, contents=False):
-    '''Verify that every big file revision in the current changeset
+    '''Verify that every largefile revision in the current changeset
     exists in the central store.  With --contents, also verify that
-    the contents of each big file revision are correct (SHA-1 hash
+    the contents of each local largefile file revision are correct (SHA-1 hash
     matches the revision ID).  With --all, check every changeset in
     this repository.'''
     if all:
--- a/hgext/largefiles/localstore.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/hgext/largefiles/localstore.py	Wed Apr 03 13:03:50 2013 -0500
@@ -63,23 +63,19 @@
             return False
 
         expecthash = fctx.data()[0:40]
+        storepath = lfutil.storepath(self.remote, expecthash)
         verified.add(key)
         if not lfutil.instore(self.remote, expecthash):
             self.ui.warn(
-                _('changeset %s: %s missing\n'
-                  '  (looked for hash %s)\n')
-                % (cset, filename, expecthash))
+                _('changeset %s: %s references missing %s\n')
+                % (cset, filename, storepath))
             return True                 # failed
 
         if contents:
-            storepath = lfutil.storepath(self.remote, expecthash)
             actualhash = lfutil.hashfile(storepath)
             if actualhash != expecthash:
                 self.ui.warn(
-                    _('changeset %s: %s: contents differ\n'
-                      '  (%s:\n'
-                      '  expected hash %s,\n'
-                      '  but got %s)\n')
-                    % (cset, filename, storepath, expecthash, actualhash))
+                    _('changeset %s: %s references corrupted %s\n')
+                    % (cset, filename, storepath))
                 return True             # failed
         return False
--- a/hgext/largefiles/overrides.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/hgext/largefiles/overrides.py	Wed Apr 03 13:03:50 2013 -0500
@@ -34,6 +34,7 @@
                 manifest)
         m._files = filter(notlfile, m._files)
         m._fmap = set(m._files)
+        m._always = False
         origmatchfn = m.matchfn
         m.matchfn = lambda f: notlfile(f) and origmatchfn(f) or None
         return m
@@ -251,6 +252,7 @@
         standins = [lfutil.standin(f) for f in m._files]
         m._files.extend(standins)
         m._fmap = set(m._files)
+        m._always = False
         origmatchfn = m.matchfn
         def lfmatchfn(f):
             lf = lfutil.splitstandin(f)
@@ -274,7 +276,7 @@
     contents = opts.pop('lfc', False)
 
     result = orig(ui, repo, *pats, **opts)
-    if large:
+    if large or all or contents:
         result = result or lfcommands.verifylfiles(ui, repo, all, contents)
     return result
 
@@ -360,29 +362,35 @@
 # Finally, the merge.applyupdates function will then take care of
 # writing the files into the working copy and lfcommands.updatelfiles
 # will update the largefiles.
-def overridemanifestmerge(origfn, repo, p1, p2, pa, overwrite, partial):
-    actions = origfn(repo, p1, p2, pa, overwrite, partial)
+def overridemanifestmerge(origfn, repo, p1, p2, pa, branchmerge, force,
+                          partial, acceptremote=False):
+    overwrite = force and not branchmerge
+    actions = origfn(repo, p1, p2, pa, branchmerge, force, partial,
+                     acceptremote)
     processed = []
 
     for action in actions:
         if overwrite:
             processed.append(action)
             continue
-        f, m = action[:2]
+        f, m, args, msg = action
 
         choices = (_('&Largefile'), _('&Normal file'))
-        if m == "g" and lfutil.splitstandin(f) in p1 and f in p2:
+
+        splitstandin = lfutil.splitstandin(f)
+        if (m == "g" and splitstandin is not None and
+            splitstandin in p1 and f in p2):
             # Case 1: normal file in the working copy, largefile in
             # the second parent
-            lfile = lfutil.splitstandin(f)
+            lfile = splitstandin
             standin = f
             msg = _('%s has been turned into a largefile\n'
                     'use (l)argefile or keep as (n)ormal file?') % lfile
             if repo.ui.promptchoice(msg, choices, 0) == 0:
-                processed.append((lfile, "r"))
-                processed.append((standin, "g", p2.flags(standin)))
+                processed.append((lfile, "r", None, msg))
+                processed.append((standin, "g", (p2.flags(standin),), msg))
             else:
-                processed.append((standin, "r"))
+                processed.append((standin, "r", None, msg))
         elif m == "g" and lfutil.standin(f) in p1 and f in p2:
             # Case 2: largefile in the working copy, normal file in
             # the second parent
@@ -391,10 +399,10 @@
             msg = _('%s has been turned into a normal file\n'
                     'keep as (l)argefile or use (n)ormal file?') % lfile
             if repo.ui.promptchoice(msg, choices, 0) == 0:
-                processed.append((lfile, "r"))
+                processed.append((lfile, "r", None, msg))
             else:
-                processed.append((standin, "r"))
-                processed.append((lfile, "g", p2.flags(lfile)))
+                processed.append((standin, "r", None, msg))
+                processed.append((lfile, "g", (p2.flags(lfile),), msg))
         else:
             processed.append(action)
 
@@ -513,6 +521,7 @@
                 lfile = lambda f: lfutil.standin(f) in manifest
                 m._files = [lfutil.standin(f) for f in m._files if lfile(f)]
                 m._fmap = set(m._files)
+                m._always = False
                 origmatchfn = m.matchfn
                 m.matchfn = lambda f: (lfutil.isstandin(f) and
                                     (f in manifest) and
@@ -619,6 +628,7 @@
                 m._files = [tostandin(f) for f in m._files]
                 m._files = [f for f in m._files if f is not None]
                 m._fmap = set(m._files)
+                m._always = False
                 origmatchfn = m.matchfn
                 def matchfn(f):
                     if lfutil.isstandin(f):
@@ -724,18 +734,21 @@
         repo.lfpullsource = source
         oldheads = lfutil.getcurrentheads(repo)
         result = orig(ui, repo, source, **opts)
-        # If we do not have the new largefiles for any new heads we pulled, we
-        # will run into a problem later if we try to merge or rebase with one of
-        # these heads, so cache the largefiles now directly into the system
-        # cache.
-        ui.status(_("caching new largefiles\n"))
-        numcached = 0
-        heads = lfutil.getcurrentheads(repo)
-        newheads = set(heads).difference(set(oldheads))
-        for head in newheads:
-            (cached, missing) = lfcommands.cachelfiles(ui, repo, head)
-            numcached += len(cached)
-        ui.status(_("%d largefiles cached\n") % numcached)
+        if opts.get('cache_largefiles'):
+            # If you are pulling from a remote location that is not your
+            # default location, you may want to cache largefiles for new heads
+            # that have been pulled, so you can easily merge or rebase with
+            # them later
+            numcached = 0
+            heads = lfutil.getcurrentheads(repo)
+            newheads = set(heads).difference(set(oldheads))
+            if len(newheads) > 0:
+                ui.status(_("caching largefiles for %s heads\n") %
+                          len(newheads))
+            for head in newheads:
+                (cached, missing) = lfcommands.cachelfiles(ui, repo, head)
+                numcached += len(cached)
+            ui.status(_("%d largefiles cached\n") % numcached)
     if opts.get('all_largefiles'):
         revspostpull = len(repo)
         revs = []
@@ -762,17 +775,6 @@
         sourcerepo, destrepo = result
         repo = destrepo.local()
 
-        # The .hglf directory must exist for the standin matcher to match
-        # anything (which listlfiles uses for each rev), and .hg/largefiles is
-        # assumed to exist by the code that caches the downloaded file.  These
-        # directories exist if clone updated to any rev.  (If the repo does not
-        # have largefiles, download never gets to the point of needing
-        # .hg/largefiles, and the standin matcher won't match anything anyway.)
-        if 'largefiles' in repo.requirements:
-            if opts.get('noupdate'):
-                util.makedirs(repo.wjoin(lfutil.shortname))
-                util.makedirs(repo.join(lfutil.longname))
-
         # Caching is implicitly limited to 'rev' option, since the dest repo was
         # truncated at that point.  The user may expect a download count with
         # this option, so attempt whether or not this is a largefile repo.
--- a/hgext/largefiles/remotestore.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/hgext/largefiles/remotestore.py	Wed Apr 03 13:03:50 2013 -0500
@@ -29,7 +29,7 @@
             _('remotestore: put %s to remote store %s') % (source, self.url))
 
     def exists(self, hashes):
-        return self._verify(hashes)
+        return dict((h, s == 0) for (h, s) in self._stat(hashes).iteritems())
 
     def sendfile(self, filename, hash):
         self.ui.debug('remotestore: sendfile(%s, %s)\n' % (filename, hash))
@@ -76,9 +76,6 @@
             infile = lfutil.limitreader(infile, length)
         return lfutil.copyandhash(lfutil.blockstream(infile), tmpfile)
 
-    def _verify(self, hashes):
-        return dict((h, s == 0) for (h, s) in self._stat(hashes).iteritems())
-
     def _verifyfile(self, cctx, cset, contents, standin, verified):
         filename = lfutil.splitstandin(standin)
         if not filename:
--- a/hgext/largefiles/reposetup.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/hgext/largefiles/reposetup.py	Wed Apr 03 13:03:50 2013 -0500
@@ -446,7 +446,7 @@
             the largefiles.
             So we do the following:
             For directories that only have largefiles as matches,
-            we explicitly add the largefiles to the matchlist and remove
+            we explicitly add the largefiles to the match list and remove
             the directory.
             In other cases, we leave the match list unmodified.
             '''
--- a/hgext/largefiles/uisetup.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/hgext/largefiles/uisetup.py	Wed Apr 03 13:03:50 2013 -0500
@@ -52,11 +52,12 @@
     entry = extensions.wrapcommand(commands.table, 'verify',
                                    overrides.overrideverify)
 
-    verifyopt = [('', 'large', None, _('verify largefiles')),
+    verifyopt = [('', 'large', None,
+                  _('verify that all largefiles in current revision exists')),
                  ('', 'lfa', None,
-                     _('verify all revisions of largefiles not just current')),
+                  _('verify largefiles in all revisions, not just current')),
                  ('', 'lfc', None,
-                     _('verify largefile contents not just existence'))]
+                  _('verify local largefile contents, not just existence'))]
     entry[1].extend(verifyopt)
 
     entry = extensions.wrapcommand(commands.table, 'debugstate',
@@ -78,7 +79,9 @@
     entry = extensions.wrapcommand(commands.table, 'pull',
                                    overrides.overridepull)
     pullopt = [('', 'all-largefiles', None,
-                 _('download all pulled versions of largefiles'))]
+                 _('download all pulled versions of largefiles')),
+               ('', 'cache-largefiles', None,
+                 _('caches new largefiles in all pulled heads'))]
     entry[1].extend(pullopt)
     entry = extensions.wrapcommand(commands.table, 'clone',
                                    overrides.overrideclone)
--- a/hgext/mq.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/hgext/mq.py	Wed Apr 03 13:03:50 2013 -0500
@@ -282,7 +282,7 @@
     if phase is not None:
         backup = repo.ui.backupconfig('phases', 'new-commit')
     # Marking the repository as committing an mq patch can be used
-    # to optimize operations like _branchtags().
+    # to optimize operations like branchtags().
     repo._committingpatch = True
     try:
         if phase is not None:
@@ -1571,7 +1571,7 @@
             r = list(dd)
             a = list(aa)
 
-            # create 'match' that includes the files to be recommited.
+            # create 'match' that includes the files to be recommitted.
             # apply matchfn via repo.status to ensure correct case handling.
             cm, ca, cr, cd = repo.status(patchparent, match=matchfn)[:4]
             allmatches = set(cm + ca + cr + cd)
@@ -3037,7 +3037,22 @@
         wlock = repo.wlock()
         try:
             urev = repo.mq.qparents(repo, revs[0])
-            repo.dirstate.rebuild(urev, repo[urev].manifest())
+            uctx = repo[urev]
+
+            # only reset the dirstate for files that would actually change
+            # between the working context and uctx
+            descendantrevs = repo.revs("%s::." % uctx.rev())
+            changedfiles = []
+            for rev in descendantrevs:
+                # blindy reset the files, regardless of what actually changed
+                changedfiles.extend(repo[rev].files())
+
+            # reset files that only changed in the dirstate too
+            dirstate = repo.dirstate
+            dirchanges = [f for f in dirstate if dirstate[f] != 'n']
+            changedfiles.extend(dirchanges)
+
+            repo.dirstate.rebuild(urev, uctx.manifest(), changedfiles)
             repo.dirstate.write()
             update = False
         finally:
@@ -3454,6 +3469,12 @@
                              % short(mqtags[-1][0]))
                 return result
 
+            # do not add fake tags for filtered revisions
+            included = self.changelog.hasnode
+            mqtags = [mqt for mqt in mqtags if included(mqt[0])]
+            if not mqtags:
+                return result
+
             mqtags.append((mqtags[-1][0], 'qtip'))
             mqtags.append((mqtags[0][0], 'qbase'))
             mqtags.append((self.changelog.parents(mqtags[0][0])[0], 'qparent'))
--- a/hgext/pager.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/hgext/pager.py	Wed Apr 03 13:03:50 2013 -0500
@@ -94,6 +94,8 @@
 
     @atexit.register
     def killpager():
+        if util.safehasattr(signal, "SIGINT"):
+            signal.signal(signal.SIGINT, signal.SIG_IGN)
         pager.stdin.close()
         os.dup2(stdout, sys.stdout.fileno())
         os.dup2(stderr, sys.stderr.fileno())
--- a/hgext/rebase.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/hgext/rebase.py	Wed Apr 03 13:03:50 2013 -0500
@@ -699,8 +699,8 @@
         # If we have multiple roots, we may have "hole" in the rebase set.
         # Rebase roots that descend from those "hole" should not be detached as
         # other root are. We use the special `revignored` to inform rebase that
-        # the revision should be ignored but that `defineparent` should search
-        # a rebase destination that make sense regarding rebaset topology.
+        # the revision should be ignored but that `defineparents` should search
+        # a rebase destination that make sense regarding rebased topology.
         rebasedomain = set(repo.revs('%ld::%ld', rebaseset, rebaseset))
         for ignored in set(rebasedomain) - set(rebaseset):
             state[ignored] = revignored
--- a/hgext/relink.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/hgext/relink.py	Wed Apr 03 13:03:50 2013 -0500
@@ -41,7 +41,7 @@
     if (not util.safehasattr(util, 'samefile') or
         not util.safehasattr(util, 'samedevice')):
         raise util.Abort(_('hardlinks are not supported on this system'))
-    src = hg.repository(ui, ui.expandpath(origin or 'default-relink',
+    src = hg.repository(repo.baseui, ui.expandpath(origin or 'default-relink',
                                           origin or 'default'))
     ui.status(_('relinking %s to %s\n') % (src.store.path, repo.store.path))
     if repo.root == src.root:
--- a/hgext/share.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/hgext/share.py	Wed Apr 03 13:03:50 2013 -0500
@@ -59,7 +59,7 @@
         lock and lock.release()
 
     # update store, spath, sopener and sjoin of repo
-    repo.__init__(ui, repo.root)
+    repo.__init__(repo.baseui, repo.root)
 
 cmdtable = {
     "share":
--- a/mercurial/bdiff.c	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/bdiff.c	Wed Apr 03 13:03:50 2013 -0500
@@ -347,6 +347,11 @@
 	if (!PyArg_ParseTuple(args, "s#s#:bdiff", &sa, &la, &sb, &lb))
 		return NULL;
 
+	if (la > UINT_MAX || lb > UINT_MAX) {
+		PyErr_SetString(PyExc_ValueError, "bdiff inputs too large");
+		return NULL;
+	}
+
 	_save = PyEval_SaveThread();
 	an = splitlines(sa, la, &al);
 	bn = splitlines(sb, lb, &bl);
@@ -381,18 +386,9 @@
 	for (h = l.next; h; h = h->next) {
 		if (h->a1 != la || h->b1 != lb) {
 			len = bl[h->b1].l - bl[lb].l;
-
-#define checkputbe32(__x, __c) \
-	if (__x > UINT_MAX) { \
-		PyErr_SetString(PyExc_ValueError, \
-		                "bdiff: value too large for putbe32"); \
-		goto nomem; \
-	} \
-	putbe32((uint32_t)(__x), __c);
-
-			checkputbe32(al[la].l - al->l, rb);
-			checkputbe32(al[h->a1].l - al->l, rb + 4);
-			checkputbe32(len, rb + 8);
+			putbe32((uint32_t)(al[la].l - al->l), rb);
+			putbe32((uint32_t)(al[h->a1].l - al->l), rb + 4);
+			putbe32((uint32_t)len, rb + 8);
 			memcpy(rb + 12, bl[lb].l, len);
 			rb += 12 + len;
 		}
--- a/mercurial/bookmarks.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/bookmarks.py	Wed Apr 03 13:03:50 2013 -0500
@@ -221,14 +221,13 @@
     finally:
         w.release()
 
-def updatefromremote(ui, repo, remote, path):
+def updatefromremote(ui, repo, remotemarks, path):
     ui.debug("checking for updated bookmarks\n")
-    rb = remote.listkeys('bookmarks')
     changed = False
     localmarks = repo._bookmarks
-    for k in sorted(rb):
+    for k in sorted(remotemarks):
         if k in localmarks:
-            nr, nl = rb[k], localmarks[k]
+            nr, nl = remotemarks[k], localmarks[k]
             if nr in repo:
                 cr = repo[nr]
                 cl = repo[nl]
@@ -257,9 +256,9 @@
                     localmarks[n] = cr.node()
                     changed = True
                     ui.warn(_("divergent bookmark %s stored as %s\n") % (k, n))
-        elif rb[k] in repo:
+        elif remotemarks[k] in repo:
             # add remote bookmarks for changes we already have
-            localmarks[k] = repo[rb[k]].node()
+            localmarks[k] = repo[remotemarks[k]].node()
             changed = True
             ui.status(_("adding remote bookmark %s\n") % k)
 
--- a/mercurial/branchmap.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/branchmap.py	Wed Apr 03 13:03:50 2013 -0500
@@ -95,7 +95,7 @@
     def _hashfiltered(self, repo):
         """build hash of revision filtered in the current cache
 
-        Tracking tipnode and tiprev is not enough to ensure validaty of the
+        Tracking tipnode and tiprev is not enough to ensure validity of the
         cache as they do not help to distinct cache that ignored various
         revision bellow tiprev.
 
@@ -114,9 +114,9 @@
         return key
 
     def validfor(self, repo):
-        """Is the cache content valide regarding a repo
+        """Is the cache content valid regarding a repo
 
-        - False when cached tipnode are unknown or if we detect a strip.
+        - False when cached tipnode is unknown or if we detect a strip.
         - True when cache is up to date or a subset of current repo."""
         try:
             return ((self.tipnode == repo.changelog.node(self.tiprev))
--- a/mercurial/bundlerepo.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/bundlerepo.py	Wed Apr 03 13:03:50 2013 -0500
@@ -22,18 +22,15 @@
         # How it works:
         # To retrieve a revision, we need to know the offset of the revision in
         # the bundle (an unbundle object). We store this offset in the index
-        # (start).
-        #
-        # basemap is indexed with revisions coming from the bundle, and it
-        # maps to the revision that is the base of the corresponding delta.
+        # (start). The base of the delta is stored in the base field.
         #
         # To differentiate a rev in the bundle from a rev in the revlog, we
-        # check revision against basemap.
+        # check revision against repotiprev.
         opener = scmutil.readonlyvfs(opener)
         revlog.revlog.__init__(self, opener, indexfile)
         self.bundle = bundle
-        self.basemap = {} # mapping rev to delta base rev
         n = len(self)
+        self.repotiprev = n - 1
         chain = None
         self.bundlerevs = set() # used by 'bundle()' revset expression
         while True:
@@ -68,9 +65,8 @@
 
             baserev = self.rev(deltabase)
             # start, size, full unc. size, base (unused), link, p1, p2, node
-            e = (revlog.offset_type(start, 0), size, -1, -1, link,
+            e = (revlog.offset_type(start, 0), size, -1, baserev, link,
                  self.rev(p1), self.rev(p2), node)
-            self.basemap[n] = baserev
             self.index.insert(-1, e)
             self.nodemap[node] = n
             self.bundlerevs.add(n)
@@ -78,22 +74,22 @@
             n += 1
 
     def _chunk(self, rev):
-        # Warning: in case of bundle, the diff is against self.basemap,
-        # not against rev - 1
+        # Warning: in case of bundle, the diff is against what we stored as
+        # delta base, not against rev - 1
         # XXX: could use some caching
-        if rev not in self.basemap:
+        if rev <= self.repotiprev:
             return revlog.revlog._chunk(self, rev)
         self.bundle.seek(self.start(rev))
         return self.bundle.read(self.length(rev))
 
     def revdiff(self, rev1, rev2):
         """return or calculate a delta between two revisions"""
-        if rev1 in self.basemap and rev2 in self.basemap:
+        if rev1 > self.repotiprev and rev2 > self.repotiprev:
             # hot path for bundle
-            revb = self.basemap[rev2]
+            revb = self.index[rev2][3]
             if revb == rev1:
                 return self._chunk(rev2)
-        elif rev1 not in self.basemap and rev2 not in self.basemap:
+        elif rev1 <= self.repotiprev and rev2 <= self.repotiprev:
             return revlog.revlog.revdiff(self, rev1, rev2)
 
         return mdiff.textdiff(self.revision(self.node(rev1)),
@@ -117,12 +113,12 @@
         chain = []
         iterrev = rev
         # reconstruct the revision if it is from a changegroup
-        while iterrev in self.basemap:
+        while iterrev > self.repotiprev:
             if self._cache and self._cache[1] == iterrev:
                 text = self._cache[2]
                 break
             chain.append(iterrev)
-            iterrev = self.basemap[iterrev]
+            iterrev = self.index[iterrev][3]
         if text is None:
             text = revlog.revlog.revision(self, iterrev)
 
@@ -364,7 +360,8 @@
             bundle = None
         if not localrepo:
             # use the created uncompressed bundlerepo
-            localrepo = bundlerepo = bundlerepository(ui, repo.root, fname)
+            localrepo = bundlerepo = bundlerepository(repo.baseui, repo.root,
+                                                      fname)
             # this repo contains local and other now, so filter out local again
             common = repo.heads()
     if localrepo:
--- a/mercurial/byterange.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/byterange.py	Wed Apr 03 13:03:50 2013 -0500
@@ -238,7 +238,6 @@
                    unquote, addclosehook, addinfourl
 import ftplib
 import socket
-import sys
 import mimetypes
 import email
 
@@ -320,7 +319,7 @@
             headers = email.message_from_string(headers)
             return addinfourl(fp, headers, req.get_full_url())
         except ftplib.all_errors, msg:
-            raise IOError('ftp error', msg), sys.exc_info()[2]
+            raise IOError('ftp error', msg)
 
     def connect_ftp(self, user, passwd, host, port, dirs):
         fw = ftpwrapper(user, passwd, host, port, dirs)
@@ -350,7 +349,7 @@
             try:
                 self.ftp.nlst(file)
             except ftplib.error_perm, reason:
-                raise IOError('ftp error', reason), sys.exc_info()[2]
+                raise IOError('ftp error', reason)
             # Restore the transfer mode!
             self.ftp.voidcmd(cmd)
             # Try to retrieve as a file
@@ -364,7 +363,7 @@
                     fp = RangeableFileObject(fp, (rest,''))
                     return (fp, retrlen)
                 elif not str(reason).startswith('550'):
-                    raise IOError('ftp error', reason), sys.exc_info()[2]
+                    raise IOError('ftp error', reason)
         if not conn:
             # Set transfer mode to ASCII!
             self.ftp.voidcmd('TYPE A')
--- a/mercurial/changelog.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/changelog.py	Wed Apr 03 13:03:50 2013 -0500
@@ -183,7 +183,7 @@
         """filtered version of revlog.rev"""
         r = super(changelog, self).rev(node)
         if r in self.filteredrevs:
-            raise error.LookupError(node, self.indexfile, _('no node'))
+            raise error.LookupError(hex(node), self.indexfile, _('no node'))
         return r
 
     def node(self, rev):
--- a/mercurial/cmdutil.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/cmdutil.py	Wed Apr 03 13:03:50 2013 -0500
@@ -12,6 +12,7 @@
 import match as matchmod
 import subrepo, context, repair, graphmod, revset, phases, obsolete
 import changelog
+import bookmarks
 import lock as lockmod
 
 def parsealiases(cmd):
@@ -169,7 +170,8 @@
                          inst.args[0])
 
 def makefileobj(repo, pat, node=None, desc=None, total=None,
-                seqno=None, revwidth=None, mode='wb', pathname=None):
+                seqno=None, revwidth=None, mode='wb', modemap={},
+                pathname=None):
 
     writable = mode not in ('r', 'rb')
 
@@ -195,9 +197,11 @@
         return pat
     if util.safehasattr(pat, 'read') and 'r' in mode:
         return pat
-    return open(makefilename(repo, pat, node, desc, total, seqno, revwidth,
-                              pathname),
-                mode)
+    fn = makefilename(repo, pat, node, desc, total, seqno, revwidth, pathname)
+    mode = modemap.get(fn, mode)
+    if mode == 'wb':
+        modemap[fn] = 'ab'
+    return open(fn, mode)
 
 def openrevlog(repo, cmd, file_, opts):
     """opens the changelog, manifest, a filelog or a given revlog"""
@@ -538,6 +542,7 @@
 
     total = len(revs)
     revwidth = max([len(str(rev)) for rev in revs])
+    filemode = {}
 
     def single(rev, seqno, fp):
         ctx = repo[rev]
@@ -553,7 +558,8 @@
             desc_lines = ctx.description().rstrip().split('\n')
             desc = desc_lines[0]    #Commit always has a first line.
             fp = makefileobj(repo, template, node, desc=desc, total=total,
-                             seqno=seqno, revwidth=revwidth, mode='ab')
+                             seqno=seqno, revwidth=revwidth, mode='wb',
+                             modemap=filemode)
             if fp != template:
                 shouldclose = True
         if fp and fp != sys.stdout and util.safehasattr(fp, 'name'):
@@ -569,6 +575,7 @@
         write("# HG changeset patch\n")
         write("# User %s\n" % ctx.user())
         write("# Date %d %d\n" % ctx.date())
+        write("#      %s\n" % util.datestr(ctx.date()))
         if branch and branch != 'default':
             write("# Branch %s\n" % branch)
         write("# Node ID %s\n" % hex(node))
@@ -1203,6 +1210,13 @@
             if ff.match(x):
                 wanted.discard(x)
 
+    # Choose a small initial window if we will probably only visit a
+    # few commits.
+    limit = loglimit(opts)
+    windowsize = 8
+    if limit:
+        windowsize = min(limit, windowsize)
+
     # Now that wanted is correctly initialized, we can iterate over the
     # revision range, yielding only revisions in wanted.
     def iterate():
@@ -1214,7 +1228,7 @@
             def want(rev):
                 return rev in wanted
 
-        for i, window in increasingwindows(0, len(revs)):
+        for i, window in increasingwindows(0, len(revs), windowsize):
             nrevs = [rev for rev in revs[i:i + window] if want(rev)]
             for rev in sorted(nrevs):
                 fns = fncache.get(rev)
@@ -1576,10 +1590,13 @@
     forgot.extend(forget)
     return bad, forgot
 
-def duplicatecopies(repo, rev, p1):
-    "Reproduce copies found in the source revision in the dirstate for grafts"
-    for dst, src in copies.pathcopies(repo[p1], repo[rev]).iteritems():
-        repo.dirstate.copy(src, dst)
+def duplicatecopies(repo, rev, fromrev):
+    '''reproduce copies from fromrev to rev in the dirstate'''
+    for dst, src in copies.pathcopies(repo[fromrev], repo[rev]).iteritems():
+        # copies.pathcopies returns backward renames, so dst might not
+        # actually be in the dirstate
+        if repo.dirstate[dst] in "nma":
+            repo.dirstate.copy(src, dst)
 
 def commit(ui, repo, commitfunc, pats, opts):
     '''commit the specified files or all outstanding changes'''
@@ -1793,6 +1810,8 @@
         edittext.append(_("HG: branch merge"))
     if ctx.branch():
         edittext.append(_("HG: branch '%s'") % ctx.branch())
+    if bookmarks.iscurrent(repo):
+        edittext.append(_("HG: bookmark '%s'") % repo._bookmarkcurrent)
     edittext.extend([_("HG: subrepo %s") % s for s in subs])
     edittext.extend([_("HG: added %s") % f for f in added])
     edittext.extend([_("HG: changed %s") % f for f in modified])
@@ -1812,6 +1831,52 @@
 
     return text
 
+def commitstatus(repo, node, branch, bheads=None, opts={}):
+    ctx = repo[node]
+    parents = ctx.parents()
+
+    if (not opts.get('amend') and bheads and node not in bheads and not
+        [x for x in parents if x.node() in bheads and x.branch() == branch]):
+        repo.ui.status(_('created new head\n'))
+        # The message is not printed for initial roots. For the other
+        # changesets, it is printed in the following situations:
+        #
+        # Par column: for the 2 parents with ...
+        #   N: null or no parent
+        #   B: parent is on another named branch
+        #   C: parent is a regular non head changeset
+        #   H: parent was a branch head of the current branch
+        # Msg column: whether we print "created new head" message
+        # In the following, it is assumed that there already exists some
+        # initial branch heads of the current branch, otherwise nothing is
+        # printed anyway.
+        #
+        # Par Msg Comment
+        # N N  y  additional topo root
+        #
+        # B N  y  additional branch root
+        # C N  y  additional topo head
+        # H N  n  usual case
+        #
+        # B B  y  weird additional branch root
+        # C B  y  branch merge
+        # H B  n  merge with named branch
+        #
+        # C C  y  additional head from merge
+        # C H  n  merge with a head
+        #
+        # H H  n  head merge: head count decreases
+
+    if not opts.get('close_branch'):
+        for r in parents:
+            if r.closesbranch() and r.branch() == branch:
+                repo.ui.status(_('reopening closed branch head %d\n') % r)
+
+    if repo.ui.debugflag:
+        repo.ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
+    elif repo.ui.verbose:
+        repo.ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
+
 def revert(ui, repo, ctx, parents, *pats, **opts):
     parent, p2 = parents
     node = ctx.node()
--- a/mercurial/commands.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/commands.py	Wed Apr 03 13:03:50 2013 -0500
@@ -7,9 +7,9 @@
 
 from node import hex, bin, nullid, nullrev, short
 from lock import release
-from i18n import _, gettext
+from i18n import _
 import os, re, difflib, time, tempfile, errno
-import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
+import hg, scmutil, util, revlog, copies, error, bookmarks
 import patch, help, encoding, templatekw, discovery
 import archival, changegroup, cmdutil, hbisect
 import sshserver, hgweb, hgweb.server, commandserver
@@ -456,14 +456,11 @@
     wlock = repo.wlock()
     try:
         branch = repo.dirstate.branch()
+        bheads = repo.branchheads(branch)
         hg.clean(repo, node, show_stats=False)
         repo.dirstate.setbranch(branch)
-        revert_opts = opts.copy()
-        revert_opts['date'] = None
-        revert_opts['all'] = True
-        revert_opts['rev'] = hex(parent)
-        revert_opts['no_backup'] = None
-        revert(ui, repo, **revert_opts)
+        rctx = scmutil.revsingle(repo, hex(parent))
+        cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
         if not opts.get('merge') and op1 != node:
             try:
                 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
@@ -471,13 +468,18 @@
             finally:
                 ui.setconfig('ui', 'forcemerge', '')
 
-        commit_opts = opts.copy()
-        commit_opts['addremove'] = False
-        if not commit_opts['message'] and not commit_opts['logfile']:
+        e = cmdutil.commiteditor
+        if not opts['message'] and not opts['logfile']:
             # we don't translate commit messages
-            commit_opts['message'] = "Backed out changeset %s" % short(node)
-            commit_opts['force_editor'] = True
-        commit(ui, repo, **commit_opts)
+            opts['message'] = "Backed out changeset %s" % short(node)
+            e = cmdutil.commitforceeditor
+
+        def commitfunc(ui, repo, message, match, opts):
+            return repo.commit(message, opts.get('user'), opts.get('date'),
+                               match, editor=e)
+        newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
+        cmdutil.commitstatus(repo, newnode, branch, bheads)
+
         def nice(node):
             return '%d:%s' % (repo.changelog.rev(node), short(node))
         ui.status(_('changeset %s backs out changeset %s\n') %
@@ -806,8 +808,18 @@
         scmutil.checknewlabel(repo, mark, 'bookmark')
         return mark
 
-    def checkconflict(repo, mark, force=False):
+    def checkconflict(repo, mark, force=False, target=None):
         if mark in marks and not force:
+            if target:
+                if marks[mark] == target and target == cur:
+                    # re-activating a bookmark
+                    return
+                anc = repo.changelog.ancestors([repo[target].rev()])
+                bmctx = repo[marks[mark]]
+                if bmctx.rev() in anc:
+                    ui.status(_("moving bookmark '%s' forward from %s\n") %
+                              (mark, short(bmctx.node())))
+                    return
             raise util.Abort(_("bookmark '%s' already exists "
                                "(use -f to force)") % mark)
         if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
@@ -850,13 +862,15 @@
         if inactive and mark == repo._bookmarkcurrent:
             bookmarks.setcurrent(repo, None)
             return
-        checkconflict(repo, mark, force)
+        tgt = cur
         if rev:
-            marks[mark] = scmutil.revsingle(repo, rev).node()
-        else:
-            marks[mark] = cur
+            tgt = scmutil.revsingle(repo, rev).node()
+        checkconflict(repo, mark, force, tgt)
+        marks[mark] = tgt
         if not inactive and cur == marks[mark]:
             bookmarks.setcurrent(repo, mark)
+        elif cur != tgt and mark == repo._bookmarkcurrent:
+            bookmarks.setcurrent(repo, None)
         marks.write()
 
     # Same message whether trying to deactivate the current bookmark (-i
@@ -1361,50 +1375,7 @@
                 ui.status(_("nothing changed\n"))
             return 1
 
-    ctx = repo[node]
-    parents = ctx.parents()
-
-    if (not opts.get('amend') and bheads and node not in bheads and not
-        [x for x in parents if x.node() in bheads and x.branch() == branch]):
-        ui.status(_('created new head\n'))
-        # The message is not printed for initial roots. For the other
-        # changesets, it is printed in the following situations:
-        #
-        # Par column: for the 2 parents with ...
-        #   N: null or no parent
-        #   B: parent is on another named branch
-        #   C: parent is a regular non head changeset
-        #   H: parent was a branch head of the current branch
-        # Msg column: whether we print "created new head" message
-        # In the following, it is assumed that there already exists some
-        # initial branch heads of the current branch, otherwise nothing is
-        # printed anyway.
-        #
-        # Par Msg Comment
-        # N N  y  additional topo root
-        #
-        # B N  y  additional branch root
-        # C N  y  additional topo head
-        # H N  n  usual case
-        #
-        # B B  y  weird additional branch root
-        # C B  y  branch merge
-        # H B  n  merge with named branch
-        #
-        # C C  y  additional head from merge
-        # C H  n  merge with a head
-        #
-        # H H  n  head merge: head count decreases
-
-    if not opts.get('close_branch'):
-        for r in parents:
-            if r.closesbranch() and r.branch() == branch:
-                ui.status(_('reopening closed branch head %d\n') % r)
-
-    if ui.debugflag:
-        ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
-    elif ui.verbose:
-        ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
+    cmdutil.commitstatus(repo, node, branch, bheads, opts)
 
 @command('copy|cp',
     [('A', 'after', None, _('record a copy that has already occurred')),
@@ -2101,6 +2072,22 @@
     flags = repo.known([bin(s) for s in ids])
     ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
 
+@command('debuglabelcomplete', [], _('LABEL...'))
+def debuglabelcomplete(ui, repo, *args):
+    '''complete "labels" - tags, open branch names, bookmark names'''
+
+    labels = set()
+    labels.update(t[0] for t in repo.tagslist())
+    labels.update(repo[n].branch() for n in repo.heads())
+    labels.update(repo._bookmarks.keys())
+    completions = set()
+    if not args:
+        args = ['']
+    for a in args:
+        completions.update(l for l in labels if l.startswith(a))
+    ui.write('\n'.join(sorted(completions)))
+    ui.write('\n')
+
 @command('debugobsolete',
         [('', 'flags', 0, _('markers flag')),
         ] + commitopts2,
@@ -2150,6 +2137,75 @@
                                          sorted(m.metadata().items()))))
             ui.write('\n')
 
+@command('debugpathcomplete',
+         [('f', 'full', None, _('complete an entire path')),
+          ('n', 'normal', None, _('show only normal files')),
+          ('a', 'added', None, _('show only added files')),
+          ('r', 'removed', None, _('show only removed files'))],
+         _('FILESPEC...'))
+def debugpathcomplete(ui, repo, *specs, **opts):
+    '''complete part or all of a tracked path
+
+    This command supports shells that offer path name completion. It
+    currently completes only files already known to the dirstate.
+
+    Completion extends only to the next path segment unless
+    --full is specified, in which case entire paths are used.'''
+
+    def complete(path, acceptable):
+        dirstate = repo.dirstate
+        spec = os.path.normpath(os.path.join(os.getcwd(), path))
+        rootdir = repo.root + os.sep
+        if spec != repo.root and not spec.startswith(rootdir):
+            return [], []
+        if os.path.isdir(spec):
+            spec += '/'
+        spec = spec[len(rootdir):]
+        fixpaths = os.sep != '/'
+        if fixpaths:
+            spec = spec.replace(os.sep, '/')
+        speclen = len(spec)
+        fullpaths = opts['full']
+        files, dirs = set(), set()
+        adddir, addfile = dirs.add, files.add
+        for f, st in dirstate.iteritems():
+            if f.startswith(spec) and st[0] in acceptable:
+                if fixpaths:
+                    f = f.replace('/', os.sep)
+                if fullpaths:
+                    addfile(f)
+                    continue
+                s = f.find(os.sep, speclen)
+                if s >= 0:
+                    adddir(f[:s + 1])
+                else:
+                    addfile(f)
+        return files, dirs
+
+    acceptable = ''
+    if opts['normal']:
+        acceptable += 'nm'
+    if opts['added']:
+        acceptable += 'a'
+    if opts['removed']:
+        acceptable += 'r'
+    cwd = repo.getcwd()
+    if not specs:
+        specs = ['.']
+
+    files, dirs = set(), set()
+    for spec in specs:
+        f, d = complete(spec, acceptable or 'nmar')
+        files.update(f)
+        dirs.update(d)
+    if not files and len(dirs) == 1:
+        # force the shell to consider a completion that matches one
+        # directory and zero files to be ambiguous
+        dirs.add(iter(dirs).next() + '.')
+    files.update(dirs)
+    ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
+    ui.write('\n')
+
 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
     '''access the pushkey key/value protocol
@@ -3001,7 +3057,7 @@
     if opts.get('ignore_case'):
         reflags |= re.I
     try:
-        regexp = re.compile(pattern, reflags)
+        regexp = util.compilere(pattern, reflags)
     except re.error, inst:
         ui.warn(_("grep: invalid match pattern: %s\n") % inst)
         return 1
@@ -3255,7 +3311,7 @@
      ('k', 'keyword', '', _('show topics matching keyword')),
      ],
     _('[-ec] [TOPIC]'))
-def help_(ui, name=None, unknowncmd=False, full=True, **opts):
+def help_(ui, name=None, **opts):
     """show help for a given topic or a help overview
 
     With no arguments, print a list of commands with short help messages.
@@ -3268,291 +3324,9 @@
 
     textwidth = min(ui.termwidth(), 80) - 2
 
-    def helpcmd(name):
-        try:
-            aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
-        except error.AmbiguousCommand, inst:
-            # py3k fix: except vars can't be used outside the scope of the
-            # except block, nor can be used inside a lambda. python issue4617
-            prefix = inst.args[0]
-            select = lambda c: c.lstrip('^').startswith(prefix)
-            rst = helplist(select)
-            return rst
-
-        rst = []
-
-        # check if it's an invalid alias and display its error if it is
-        if getattr(entry[0], 'badalias', False):
-            if not unknowncmd:
-                ui.pushbuffer()
-                entry[0](ui)
-                rst.append(ui.popbuffer())
-            return rst
-
-        # synopsis
-        if len(entry) > 2:
-            if entry[2].startswith('hg'):
-                rst.append("%s\n" % entry[2])
-            else:
-                rst.append('hg %s %s\n' % (aliases[0], entry[2]))
-        else:
-            rst.append('hg %s\n' % aliases[0])
-        # aliases
-        if full and not ui.quiet and len(aliases) > 1:
-            rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
-        rst.append('\n')
-
-        # description
-        doc = gettext(entry[0].__doc__)
-        if not doc:
-            doc = _("(no help text available)")
-        if util.safehasattr(entry[0], 'definition'):  # aliased command
-            if entry[0].definition.startswith('!'):  # shell alias
-                doc = _('shell alias for::\n\n    %s') % entry[0].definition[1:]
-            else:
-                doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
-        doc = doc.splitlines(True)
-        if ui.quiet or not full:
-            rst.append(doc[0])
-        else:
-            rst.extend(doc)
-        rst.append('\n')
-
-        # check if this command shadows a non-trivial (multi-line)
-        # extension help text
-        try:
-            mod = extensions.find(name)
-            doc = gettext(mod.__doc__) or ''
-            if '\n' in doc.strip():
-                msg = _('use "hg help -e %s" to show help for '
-                        'the %s extension') % (name, name)
-                rst.append('\n%s\n' % msg)
-        except KeyError:
-            pass
-
-        # options
-        if not ui.quiet and entry[1]:
-            rst.append('\n%s\n\n' % _("options:"))
-            rst.append(help.optrst(entry[1], ui.verbose))
-
-        if ui.verbose:
-            rst.append('\n%s\n\n' % _("global options:"))
-            rst.append(help.optrst(globalopts, ui.verbose))
-
-        if not ui.verbose:
-            if not full:
-                rst.append(_('\nuse "hg help %s" to show the full help text\n')
-                           % name)
-            elif not ui.quiet:
-                omitted = _('use "hg -v help %s" to show more complete'
-                            ' help and the global options') % name
-                notomitted = _('use "hg -v help %s" to show'
-                               ' the global options') % name
-                help.indicateomitted(rst, omitted, notomitted)
-
-        return rst
-
-
-    def helplist(select=None):
-        # list of commands
-        if name == "shortlist":
-            header = _('basic commands:\n\n')
-        else:
-            header = _('list of commands:\n\n')
-
-        h = {}
-        cmds = {}
-        for c, e in table.iteritems():
-            f = c.split("|", 1)[0]
-            if select and not select(f):
-                continue
-            if (not select and name != 'shortlist' and
-                e[0].__module__ != __name__):
-                continue
-            if name == "shortlist" and not f.startswith("^"):
-                continue
-            f = f.lstrip("^")
-            if not ui.debugflag and f.startswith("debug"):
-                continue
-            doc = e[0].__doc__
-            if doc and 'DEPRECATED' in doc and not ui.verbose:
-                continue
-            doc = gettext(doc)
-            if not doc:
-                doc = _("(no help text available)")
-            h[f] = doc.splitlines()[0].rstrip()
-            cmds[f] = c.lstrip("^")
-
-        rst = []
-        if not h:
-            if not ui.quiet:
-                rst.append(_('no commands defined\n'))
-            return rst
-
-        if not ui.quiet:
-            rst.append(header)
-        fns = sorted(h)
-        for f in fns:
-            if ui.verbose:
-                commands = cmds[f].replace("|",", ")
-                rst.append(" :%s: %s\n" % (commands, h[f]))
-            else:
-                rst.append(' :%s: %s\n' % (f, h[f]))
-
-        if not name:
-            exts = help.listexts(_('enabled extensions:'), extensions.enabled())
-            if exts:
-                rst.append('\n')
-                rst.extend(exts)
-
-            rst.append(_("\nadditional help topics:\n\n"))
-            topics = []
-            for names, header, doc in help.helptable:
-                topics.append((names[0], header))
-            for t, desc in topics:
-                rst.append(" :%s: %s\n" % (t, desc))
-
-        optlist = []
-        if not ui.quiet:
-            if ui.verbose:
-                optlist.append((_("global options:"), globalopts))
-                if name == 'shortlist':
-                    optlist.append((_('use "hg help" for the full list '
-                                           'of commands'), ()))
-            else:
-                if name == 'shortlist':
-                    msg = _('use "hg help" for the full list of commands '
-                            'or "hg -v" for details')
-                elif name and not full:
-                    msg = _('use "hg help %s" to show the full help '
-                            'text') % name
-                else:
-                    msg = _('use "hg -v help%s" to show builtin aliases and '
-                            'global options') % (name and " " + name or "")
-                optlist.append((msg, ()))
-
-        if optlist:
-            for title, options in optlist:
-                rst.append('\n%s\n' % title)
-                if options:
-                    rst.append('\n%s\n' % help.optrst(options, ui.verbose))
-        return rst
-
-    def helptopic(name):
-        for names, header, doc in help.helptable:
-            if name in names:
-                break
-        else:
-            raise error.UnknownCommand(name)
-
-        rst = ["%s\n\n" % header]
-        # description
-        if not doc:
-            rst.append("    %s\n" % _("(no help text available)"))
-        if util.safehasattr(doc, '__call__'):
-            rst += ["    %s\n" % l for l in doc().splitlines()]
-
-        if not ui.verbose:
-            omitted = (_('use "hg help -v %s" to show more complete help') %
-                       name)
-            help.indicateomitted(rst, omitted)
-
-        try:
-            cmdutil.findcmd(name, table)
-            rst.append(_('\nuse "hg help -c %s" to see help for '
-                       'the %s command\n') % (name, name))
-        except error.UnknownCommand:
-            pass
-        return rst
-
-    def helpext(name):
-        try:
-            mod = extensions.find(name)
-            doc = gettext(mod.__doc__) or _('no help text available')
-        except KeyError:
-            mod = None
-            doc = extensions.disabledext(name)
-            if not doc:
-                raise error.UnknownCommand(name)
-
-        if '\n' not in doc:
-            head, tail = doc, ""
-        else:
-            head, tail = doc.split('\n', 1)
-        rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
-        if tail:
-            rst.extend(tail.splitlines(True))
-            rst.append('\n')
-
-        if not ui.verbose:
-            omitted = (_('use "hg help -v %s" to show more complete help') %
-                       name)
-            help.indicateomitted(rst, omitted)
-
-        if mod:
-            try:
-                ct = mod.cmdtable
-            except AttributeError:
-                ct = {}
-            modcmds = set([c.split('|', 1)[0] for c in ct])
-            rst.extend(helplist(modcmds.__contains__))
-        else:
-            rst.append(_('use "hg help extensions" for information on enabling '
-                       'extensions\n'))
-        return rst
-
-    def helpextcmd(name):
-        cmd, ext, mod = extensions.disabledcmd(ui, name,
-                                               ui.configbool('ui', 'strict'))
-        doc = gettext(mod.__doc__).splitlines()[0]
-
-        rst = help.listexts(_("'%s' is provided by the following "
-                              "extension:") % cmd, {ext: doc}, indent=4)
-        rst.append('\n')
-        rst.append(_('use "hg help extensions" for information on enabling '
-                   'extensions\n'))
-        return rst
-
-
-    rst = []
-    kw = opts.get('keyword')
-    if kw:
-        matches = help.topicmatch(kw)
-        for t, title in (('topics', _('Topics')),
-                         ('commands', _('Commands')),
-                         ('extensions', _('Extensions')),
-                         ('extensioncommands', _('Extension Commands'))):
-            if matches[t]:
-                rst.append('%s:\n\n' % title)
-                rst.extend(minirst.maketable(sorted(matches[t]), 1))
-                rst.append('\n')
-    elif name and name != 'shortlist':
-        i = None
-        if unknowncmd:
-            queries = (helpextcmd,)
-        elif opts.get('extension'):
-            queries = (helpext,)
-        elif opts.get('command'):
-            queries = (helpcmd,)
-        else:
-            queries = (helptopic, helpcmd, helpext, helpextcmd)
-        for f in queries:
-            try:
-                rst = f(name)
-                i = None
-                break
-            except error.UnknownCommand, inst:
-                i = inst
-        if i:
-            raise i
-    else:
-        # program name
-        if not ui.quiet:
-            rst = [_("Mercurial Distributed SCM\n"), '\n']
-        rst.extend(helplist())
-
     keep = ui.verbose and ['verbose'] or []
-    text = ''.join(rst)
+    text = help.help_(ui, name, **opts)
+
     formatted, pruned = minirst.format(text, textwidth, keep=keep)
     if 'verbose' in pruned:
         keep.append('omitted')
@@ -3814,7 +3588,6 @@
 
     def checkexact(repo, n, nodeid):
         if opts.get('exact') and hex(n) != nodeid:
-            repo.rollback()
             raise util.Abort(_('patch is damaged or loses information'))
 
     def tryone(ui, hunk, parents):
@@ -4257,10 +4030,10 @@
         displayer.show(ctx, copies=copies, matchfn=revmatchfn)
 
     for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
+        if displayer.flush(ctx.rev()):
+            count += 1
         if count == limit:
             break
-        if displayer.flush(ctx.rev()):
-            count += 1
     displayer.close()
 
 @command('manifest',
@@ -4723,14 +4496,15 @@
     ui.status(_('pulling from %s\n') % util.hidepassword(source))
     revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
 
+    remotebookmarks = other.listkeys('bookmarks')
+
     if opts.get('bookmark'):
         if not revs:
             revs = []
-        rb = other.listkeys('bookmarks')
         for b in opts['bookmark']:
-            if b not in rb:
+            if b not in remotebookmarks:
                 raise util.Abort(_('remote bookmark %s not found!') % b)
-            revs.append(rb[b])
+            revs.append(remotebookmarks[b])
 
     if revs:
         try:
@@ -4741,7 +4515,7 @@
             raise util.Abort(err)
 
     modheads = repo.pull(other, heads=revs, force=opts.get('force'))
-    bookmarks.updatefromremote(ui, repo, other, source)
+    bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
     if checkout:
         checkout = str(repo.changelog.rev(other.lookup(checkout)))
     repo._subtoppath = source
@@ -4757,7 +4531,7 @@
         for b in opts['bookmark']:
             # explicit pull overrides local bookmark if any
             ui.status(_("importing bookmark %s\n") % b)
-            marks[b] = repo[rb[b]].node()
+            marks[b] = repo[remotebookmarks[b]].node()
         marks.write()
 
     return ret
@@ -5318,9 +5092,9 @@
         if not repo:
             raise error.RepoError(_("there is no Mercurial repository"
                                     " here (.hg not found)"))
-        o = repo.root
-
-    app = hgweb.hgweb(o, baseui=ui)
+        o = repo
+
+    app = hgweb.hgweb(o, baseui=baseui)
 
     class service(object):
         def init(self):
@@ -5577,12 +5351,11 @@
         # i18n: column positioning for "hg summary"
         ui.write(_('bookmarks:'), label='log.bookmark')
         if current is not None:
-            try:
-                marks.remove(current)
+            if current in marks:
                 ui.write(' *' + current, label='bookmarks.current')
-            except ValueError:
-                # current bookmark not in parent ctx marks
-                pass
+                marks.remove(current)
+            else:
+                ui.write(' [%s]' % current, label='bookmarks.current')
         for m in marks:
             ui.write(' ' + m, label='log.bookmark')
         ui.write('\n', label='log.bookmark')
--- a/mercurial/context.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/context.py	Wed Apr 03 13:03:50 2013 -0500
@@ -426,12 +426,12 @@
             # repository is filtered this may lead to `filectx` trying to build
             # `changectx` for filtered revision. In such case we fallback to
             # creating `changectx` on the unfiltered version of the reposition.
-            # This fallback should not be an issue because`changectx` from
-            # `filectx` are not used in complexe operation that care about
+            # This fallback should not be an issue because `changectx` from
+            # `filectx` are not used in complex operations that care about
             # filtering.
             #
             # This fallback is a cheap and dirty fix that prevent several
-            # crash. It does not ensure the behavior is correct. However the
+            # crashes. It does not ensure the behavior is correct. However the
             # behavior was not correct before filtering either and "incorrect
             # behavior" is seen as better as "crash"
             #
@@ -1138,6 +1138,22 @@
             finally:
                 wlock.release()
 
+    def markcommitted(self, node):
+        """Perform post-commit cleanup necessary after commiting this workingctx
+
+        Specifically, this updates backing stores this working context
+        wraps to reflect the fact that the changes reflected by this
+        workingctx have been committed.  For example, it marks
+        modified and added files as normal in the dirstate.
+
+        """
+
+        for f in self.modified() + self.added():
+            self._repo.dirstate.normal(f)
+        for f in self.removed():
+            self._repo.dirstate.drop(f)
+        self._repo.dirstate.setparents(node)
+
     def dirs(self):
         return set(self._repo.dirstate.dirs())
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial/dicthelpers.py	Wed Apr 03 13:03:50 2013 -0500
@@ -0,0 +1,55 @@
+# dicthelpers.py - helper routines for Python dicts
+#
+# Copyright 2013 Facebook
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+
+def diff(d1, d2, default=None):
+    '''Return all key-value pairs that are different between d1 and d2.
+
+    This includes keys that are present in one dict but not the other, and
+    keys whose values are different. The return value is a dict with values
+    being pairs of values from d1 and d2 respectively, and missing values
+    represented as default.'''
+    res = {}
+    if d1 is d2:
+        # same dict, so diff is empty
+        return res
+
+    for k1, v1 in d1.iteritems():
+        if k1 in d2:
+            v2 = d2[k1]
+            if v1 != v2:
+                res[k1] = (v1, v2)
+        else:
+            res[k1] = (v1, default)
+
+    for k2 in d2:
+        if k2 not in d1:
+            res[k2] = (default, d2[k2])
+
+    return res
+
+def join(d1, d2, default=None):
+    '''Return all key-value pairs from both d1 and d2.
+
+    This is akin to an outer join in relational algebra. The return value is a
+    dict with values being pairs of values from d1 and d2 respectively, and
+    missing values represented as default.'''
+    res = {}
+
+    for k1, v1 in d1.iteritems():
+        if k1 in d2:
+            res[k1] = (v1, d2[k1])
+        else:
+            res[k1] = (v1, default)
+
+    if d1 is d2:
+        return res
+
+    for k2 in d2:
+        if k2 not in d1:
+            res[k2] = (default, d2[k2])
+
+    return res
--- a/mercurial/dirstate.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/dirstate.py	Wed Apr 03 13:03:50 2013 -0500
@@ -9,10 +9,8 @@
 from node import nullid
 from i18n import _
 import scmutil, util, ignore, osutil, parsers, encoding
-import struct, os, stat, errno
-import cStringIO
+import os, stat, errno, gc
 
-_format = ">cllll"
 propertycache = util.propertycache
 filecache = scmutil.filecache
 _rangemask = 0x7fffffff
@@ -225,6 +223,9 @@
         for x in sorted(self._map):
             yield x
 
+    def iteritems(self):
+        return self._map.iteritems()
+
     def parents(self):
         return [self._validate(p) for p in self._pl]
 
@@ -287,7 +288,23 @@
         if not st:
             return
 
-        p = parsers.parse_dirstate(self._map, self._copymap, st)
+        # Python's garbage collector triggers a GC each time a certain number
+        # of container objects (the number being defined by
+        # gc.get_threshold()) are allocated. parse_dirstate creates a tuple
+        # for each file in the dirstate. The C version then immediately marks
+        # them as not to be tracked by the collector. However, this has no
+        # effect on when GCs are triggered, only on what objects the GC looks
+        # into. This means that O(number of files) GCs are unavoidable.
+        # Depending on when in the process's lifetime the dirstate is parsed,
+        # this can get very expensive. As a workaround, disable GC while
+        # parsing the dirstate.
+        gcenabled = gc.isenabled()
+        gc.disable()
+        try:
+            p = parsers.parse_dirstate(self._map, self._copymap, st)
+        finally:
+            if gcenabled:
+                gc.enable()
         if not self._dirtypl:
             self._pl = p
 
@@ -484,13 +501,18 @@
         self._lastnormaltime = 0
         self._dirty = True
 
-    def rebuild(self, parent, files):
+    def rebuild(self, parent, allfiles, changedfiles=None):
+        changedfiles = changedfiles or allfiles
+        oldmap = self._map
         self.clear()
-        for f in files:
-            if 'x' in files.flags(f):
-                self._map[f] = ('n', 0777, -1, 0)
+        for f in allfiles:
+            if f not in changedfiles:
+                self._map[f] = oldmap[f]
             else:
-                self._map[f] = ('n', 0666, -1, 0)
+                if 'x' in allfiles.flags(f):
+                    self._map[f] = ('n', 0777, -1, 0)
+                else:
+                    self._map[f] = ('n', 0666, -1, 0)
         self._pl = (parent, nullid)
         self._dirty = True
 
@@ -508,38 +530,7 @@
         # use the modification time of the newly created temporary file as the
         # filesystem's notion of 'now'
         now = util.fstat(st).st_mtime
-        copymap = self._copymap
-        try:
-            finish(parsers.pack_dirstate(self._map, copymap, self._pl, now))
-            return
-        except AttributeError:
-            pass
-
-        now = int(now)
-        cs = cStringIO.StringIO()
-        pack = struct.pack
-        write = cs.write
-        write("".join(self._pl))
-        for f, e in self._map.iteritems():
-            if e[0] == 'n' and e[3] == now:
-                # The file was last modified "simultaneously" with the current
-                # write to dirstate (i.e. within the same second for file-
-                # systems with a granularity of 1 sec). This commonly happens
-                # for at least a couple of files on 'update'.
-                # The user could change the file without changing its size
-                # within the same second. Invalidate the file's stat data in
-                # dirstate, forcing future 'status' calls to compare the
-                # contents of the file. This prevents mistakenly treating such
-                # files as clean.
-                e = (e[0], 0, -1, -1)   # mark entry as 'unset'
-                self._map[f] = e
-
-            if f in copymap:
-                f = "%s\0%s" % (f, copymap[f])
-            e = pack(_format, e[0], e[1], e[2], e[3], len(f))
-            write(e)
-            write(f)
-        finish(cs.getvalue())
+        finish(parsers.pack_dirstate(self._map, self._copymap, self._pl, now))
 
     def _dirignore(self, f):
         if f == '.':
@@ -589,6 +580,7 @@
             dirignore = util.always
 
         matchfn = match.matchfn
+        matchalways = match.always()
         badfn = match.bad
         dmap = self._map
         normpath = util.normpath
@@ -696,26 +688,53 @@
                         if not ignore(nf):
                             match.dir(nf)
                             wadd(nf)
-                        if nf in dmap and matchfn(nf):
+                        if nf in dmap and (matchalways or matchfn(nf)):
                             results[nf] = None
                     elif kind == regkind or kind == lnkkind:
                         if nf in dmap:
-                            if matchfn(nf):
+                            if matchalways or matchfn(nf):
                                 results[nf] = st
-                        elif matchfn(nf) and not ignore(nf):
+                        elif (matchalways or matchfn(nf)) and not ignore(nf):
                             results[nf] = st
-                    elif nf in dmap and matchfn(nf):
+                    elif nf in dmap and (matchalways or matchfn(nf)):
                         results[nf] = None
 
+        for s in subrepos:
+            del results[s]
+        del results['.hg']
+
         # step 3: report unseen items in the dmap hash
         if not skipstep3 and not exact:
-            visit = sorted([f for f in dmap if f not in results and matchfn(f)])
-            nf = iter(visit).next
-            for st in util.statfiles([join(i) for i in visit]):
-                results[nf()] = st
-        for s in subrepos:
-            del results[s]
-        del results['.hg']
+            if not results and matchalways:
+                visit = dmap.keys()
+            else:
+                visit = [f for f in dmap if f not in results and matchfn(f)]
+            visit.sort()
+
+            if unknown:
+                # unknown == True means we walked the full directory tree above.
+                # So if a file is not seen it was either a) not matching matchfn
+                # b) ignored, c) missing, or d) under a symlink directory.
+                audit_path = scmutil.pathauditor(self._root)
+
+                for nf in iter(visit):
+                    # Report ignored items in the dmap as long as they are not
+                    # under a symlink directory.
+                    if ignore(nf) and audit_path.check(nf):
+                        try:
+                            results[nf] = lstat(join(nf))
+                        except OSError:
+                            # file doesn't exist
+                            results[nf] = None
+                    else:
+                        # It's either missing or under a symlink directory
+                        results[nf] = None
+            else:
+                # We may not have walked the full directory tree above,
+                # so stat everything we missed.
+                nf = iter(visit).next
+                for st in util.statfiles([join(i) for i in visit]):
+                    results[nf()] = st
         return results
 
     def status(self, match, subrepos, ignored, clean, unknown):
--- a/mercurial/dispatch.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/dispatch.py	Wed Apr 03 13:03:50 2013 -0500
@@ -247,6 +247,7 @@
                     (_("** Mercurial Distributed SCM (version %s)\n") % myver) +
                     (_("** Extensions loaded: %s\n") %
                      ", ".join([x[0] for x in extensions.extensions()])))
+        ui.log("commandexception", "%s\n%s\n", warning, traceback.format_exc())
         ui.warn(warning)
         raise
 
@@ -333,7 +334,7 @@
         self.cmdname = cmd = args.pop(0)
         args = map(util.expandpath, args)
 
-        for invalidarg in ("--cwd", "-R", "--repository", "--repo"):
+        for invalidarg in ("--cwd", "-R", "--repository", "--repo", "--config"):
             if _earlygetopt([invalidarg], args):
                 def fn(ui, *args):
                     ui.warn(_("error in definition for alias '%s': %s may only "
@@ -736,18 +737,25 @@
         ui.warn(_("warning: --repository ignored\n"))
 
     msg = ' '.join(' ' in a and repr(a) or a for a in fullargs)
-    ui.log("command", msg + "\n")
+    ui.log("command", '%s\n', msg)
     d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
+    starttime = time.time()
+    ret = None
     try:
-        return runcommand(lui, repo, cmd, fullargs, ui, options, d,
-                          cmdpats, cmdoptions)
+        ret = runcommand(lui, repo, cmd, fullargs, ui, options, d,
+                         cmdpats, cmdoptions)
+        return ret
     finally:
+        duration = time.time() - starttime
+        ui.log("commandfinish", "%s exited %s after %0.2f seconds\n",
+               cmd, ret, duration)
         if repo and repo != req.repo:
             repo.close()
 
 def lsprofile(ui, func, fp):
     format = ui.config('profiling', 'format', default='text')
     field = ui.config('profiling', 'sort', default='inlinetime')
+    limit = ui.configint('profiling', 'limit', default=30)
     climit = ui.configint('profiling', 'nested', default=5)
 
     if format not in ['text', 'kcachegrind']:
@@ -776,7 +784,7 @@
             # format == 'text'
             stats = lsprof.Stats(p.getstats())
             stats.sort(field)
-            stats.pprint(limit=30, file=fp, climit=climit)
+            stats.pprint(limit=limit, file=fp, climit=climit)
 
 def statprofile(ui, func, fp):
     try:
--- a/mercurial/extensions.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/extensions.py	Wed Apr 03 13:03:50 2013 -0500
@@ -11,7 +11,7 @@
 
 _extensions = {}
 _order = []
-_ignore = ['hbisect', 'bookmarks', 'parentrevspec']
+_ignore = ['hbisect', 'bookmarks', 'parentrevspec', 'interhg']
 
 def extensions():
     for name in _order:
@@ -50,7 +50,6 @@
             raise
 
 def load(ui, name, path):
-    # unused ui argument kept for backwards compatibility
     if name.startswith('hgext.') or name.startswith('hgext/'):
         shortname = name[6:]
     else:
--- a/mercurial/fileset.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/fileset.py	Wed Apr 03 13:03:50 2013 -0500
@@ -353,6 +353,29 @@
 
     return s
 
+def eol(mctx, x):
+    """``eol(style)``
+    File contains newlines of the given style (dos, unix, mac). Binary
+    files are excluded, files with mixed line endings match multiple
+    styles.
+    """
+
+    # i18n: "encoding" is a keyword
+    enc = getstring(x, _("encoding requires an encoding name"))
+
+    s = []
+    for f in mctx.existing():
+        d = mctx.ctx[f].data()
+        if util.binary(d):
+            continue
+        if (enc == 'dos' or enc == 'win') and '\r\n' in d:
+            s.append(f)
+        elif enc == 'unix' and re.search('(?<!\r)\n', d):
+            s.append(f)
+        elif enc == 'mac' and re.search('\r(?!\n)', d):
+            s.append(f)
+    return s
+
 def copied(mctx, x):
     """``copied()``
     File that is recorded as being copied.
@@ -395,6 +418,7 @@
     'copied': copied,
     'deleted': deleted,
     'encoding': encoding,
+    'eol': eol,
     'exec': exec_,
     'grep': grep,
     'ignored': ignored,
--- a/mercurial/help.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/help.py	Wed Apr 03 13:03:50 2013 -0500
@@ -6,9 +6,10 @@
 # GNU General Public License version 2 or any later version.
 
 from i18n import gettext, _
-import itertools, sys, os
+import itertools, sys, os, error
 import extensions, revset, fileset, templatekw, templatefilters, filemerge
 import encoding, util, minirst
+import cmdutil
 
 def listexts(header, exts, indent=1):
     '''return a text listing of the given extensions'''
@@ -206,3 +207,298 @@
 addtopicsymbols('revsets', '.. predicatesmarker', revset.symbols)
 addtopicsymbols('templates', '.. keywordsmarker', templatekw.dockeywords)
 addtopicsymbols('templates', '.. filtersmarker', templatefilters.filters)
+
+def help_(ui, name, unknowncmd=False, full=True, **opts):
+    '''
+    Generate the help for 'name' as unformatted restructured text. If
+    'name' is None, describe the commands available.
+    '''
+
+    import commands # avoid cycle
+
+    def helpcmd(name):
+        try:
+            aliases, entry = cmdutil.findcmd(name, commands.table,
+                                             strict=unknowncmd)
+        except error.AmbiguousCommand, inst:
+            # py3k fix: except vars can't be used outside the scope of the
+            # except block, nor can be used inside a lambda. python issue4617
+            prefix = inst.args[0]
+            select = lambda c: c.lstrip('^').startswith(prefix)
+            rst = helplist(select)
+            return rst
+
+        rst = []
+
+        # check if it's an invalid alias and display its error if it is
+        if getattr(entry[0], 'badalias', False):
+            if not unknowncmd:
+                ui.pushbuffer()
+                entry[0](ui)
+                rst.append(ui.popbuffer())
+            return rst
+
+        # synopsis
+        if len(entry) > 2:
+            if entry[2].startswith('hg'):
+                rst.append("%s\n" % entry[2])
+            else:
+                rst.append('hg %s %s\n' % (aliases[0], entry[2]))
+        else:
+            rst.append('hg %s\n' % aliases[0])
+        # aliases
+        if full and not ui.quiet and len(aliases) > 1:
+            rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
+        rst.append('\n')
+
+        # description
+        doc = gettext(entry[0].__doc__)
+        if not doc:
+            doc = _("(no help text available)")
+        if util.safehasattr(entry[0], 'definition'):  # aliased command
+            if entry[0].definition.startswith('!'):  # shell alias
+                doc = _('shell alias for::\n\n    %s') % entry[0].definition[1:]
+            else:
+                doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
+        doc = doc.splitlines(True)
+        if ui.quiet or not full:
+            rst.append(doc[0])
+        else:
+            rst.extend(doc)
+        rst.append('\n')
+
+        # check if this command shadows a non-trivial (multi-line)
+        # extension help text
+        try:
+            mod = extensions.find(name)
+            doc = gettext(mod.__doc__) or ''
+            if '\n' in doc.strip():
+                msg = _('use "hg help -e %s" to show help for '
+                        'the %s extension') % (name, name)
+                rst.append('\n%s\n' % msg)
+        except KeyError:
+            pass
+
+        # options
+        if not ui.quiet and entry[1]:
+            rst.append('\n%s\n\n' % _("options:"))
+            rst.append(optrst(entry[1], ui.verbose))
+
+        if ui.verbose:
+            rst.append('\n%s\n\n' % _("global options:"))
+            rst.append(optrst(commands.globalopts, ui.verbose))
+
+        if not ui.verbose:
+            if not full:
+                rst.append(_('\nuse "hg help %s" to show the full help text\n')
+                           % name)
+            elif not ui.quiet:
+                omitted = _('use "hg -v help %s" to show more complete'
+                            ' help and the global options') % name
+                notomitted = _('use "hg -v help %s" to show'
+                               ' the global options') % name
+                indicateomitted(rst, omitted, notomitted)
+
+        return rst
+
+
+    def helplist(select=None):
+        # list of commands
+        if name == "shortlist":
+            header = _('basic commands:\n\n')
+        else:
+            header = _('list of commands:\n\n')
+
+        h = {}
+        cmds = {}
+        for c, e in commands.table.iteritems():
+            f = c.split("|", 1)[0]
+            if select and not select(f):
+                continue
+            if (not select and name != 'shortlist' and
+                e[0].__module__ != commands.__name__):
+                continue
+            if name == "shortlist" and not f.startswith("^"):
+                continue
+            f = f.lstrip("^")
+            if not ui.debugflag and f.startswith("debug"):
+                continue
+            doc = e[0].__doc__
+            if doc and 'DEPRECATED' in doc and not ui.verbose:
+                continue
+            doc = gettext(doc)
+            if not doc:
+                doc = _("(no help text available)")
+            h[f] = doc.splitlines()[0].rstrip()
+            cmds[f] = c.lstrip("^")
+
+        rst = []
+        if not h:
+            if not ui.quiet:
+                rst.append(_('no commands defined\n'))
+            return rst
+
+        if not ui.quiet:
+            rst.append(header)
+        fns = sorted(h)
+        for f in fns:
+            if ui.verbose:
+                commacmds = cmds[f].replace("|",", ")
+                rst.append(" :%s: %s\n" % (commacmds, h[f]))
+            else:
+                rst.append(' :%s: %s\n' % (f, h[f]))
+
+        if not name:
+            exts = listexts(_('enabled extensions:'), extensions.enabled())
+            if exts:
+                rst.append('\n')
+                rst.extend(exts)
+
+            rst.append(_("\nadditional help topics:\n\n"))
+            topics = []
+            for names, header, doc in helptable:
+                topics.append((names[0], header))
+            for t, desc in topics:
+                rst.append(" :%s: %s\n" % (t, desc))
+
+        optlist = []
+        if not ui.quiet:
+            if ui.verbose:
+                optlist.append((_("global options:"), commands.globalopts))
+                if name == 'shortlist':
+                    optlist.append((_('use "hg help" for the full list '
+                                           'of commands'), ()))
+            else:
+                if name == 'shortlist':
+                    msg = _('use "hg help" for the full list of commands '
+                            'or "hg -v" for details')
+                elif name and not full:
+                    msg = _('use "hg help %s" to show the full help '
+                            'text') % name
+                else:
+                    msg = _('use "hg -v help%s" to show builtin aliases and '
+                            'global options') % (name and " " + name or "")
+                optlist.append((msg, ()))
+
+        if optlist:
+            for title, options in optlist:
+                rst.append('\n%s\n' % title)
+                if options:
+                    rst.append('\n%s\n' % optrst(options, ui.verbose))
+        return rst
+
+    def helptopic(name):
+        for names, header, doc in helptable:
+            if name in names:
+                break
+        else:
+            raise error.UnknownCommand(name)
+
+        rst = [minirst.section(header)]
+
+        # description
+        if not doc:
+            rst.append("    %s\n" % _("(no help text available)"))
+        if util.safehasattr(doc, '__call__'):
+            rst += ["    %s\n" % l for l in doc().splitlines()]
+
+        if not ui.verbose:
+            omitted = (_('use "hg help -v %s" to show more complete help') %
+                       name)
+            indicateomitted(rst, omitted)
+
+        try:
+            cmdutil.findcmd(name, commands.table)
+            rst.append(_('\nuse "hg help -c %s" to see help for '
+                       'the %s command\n') % (name, name))
+        except error.UnknownCommand:
+            pass
+        return rst
+
+    def helpext(name):
+        try:
+            mod = extensions.find(name)
+            doc = gettext(mod.__doc__) or _('no help text available')
+        except KeyError:
+            mod = None
+            doc = extensions.disabledext(name)
+            if not doc:
+                raise error.UnknownCommand(name)
+
+        if '\n' not in doc:
+            head, tail = doc, ""
+        else:
+            head, tail = doc.split('\n', 1)
+        rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
+        if tail:
+            rst.extend(tail.splitlines(True))
+            rst.append('\n')
+
+        if not ui.verbose:
+            omitted = (_('use "hg help -v %s" to show more complete help') %
+                       name)
+            indicateomitted(rst, omitted)
+
+        if mod:
+            try:
+                ct = mod.cmdtable
+            except AttributeError:
+                ct = {}
+            modcmds = set([c.split('|', 1)[0] for c in ct])
+            rst.extend(helplist(modcmds.__contains__))
+        else:
+            rst.append(_('use "hg help extensions" for information on enabling '
+                       'extensions\n'))
+        return rst
+
+    def helpextcmd(name):
+        cmd, ext, mod = extensions.disabledcmd(ui, name,
+                                               ui.configbool('ui', 'strict'))
+        doc = gettext(mod.__doc__).splitlines()[0]
+
+        rst = listexts(_("'%s' is provided by the following "
+                              "extension:") % cmd, {ext: doc}, indent=4)
+        rst.append('\n')
+        rst.append(_('use "hg help extensions" for information on enabling '
+                   'extensions\n'))
+        return rst
+
+
+    rst = []
+    kw = opts.get('keyword')
+    if kw:
+        matches = topicmatch(kw)
+        for t, title in (('topics', _('Topics')),
+                         ('commands', _('Commands')),
+                         ('extensions', _('Extensions')),
+                         ('extensioncommands', _('Extension Commands'))):
+            if matches[t]:
+                rst.append('%s:\n\n' % title)
+                rst.extend(minirst.maketable(sorted(matches[t]), 1))
+                rst.append('\n')
+    elif name and name != 'shortlist':
+        i = None
+        if unknowncmd:
+            queries = (helpextcmd,)
+        elif opts.get('extension'):
+            queries = (helpext,)
+        elif opts.get('command'):
+            queries = (helpcmd,)
+        else:
+            queries = (helptopic, helpcmd, helpext, helpextcmd)
+        for f in queries:
+            try:
+                rst = f(name)
+                i = None
+                break
+            except error.UnknownCommand, inst:
+                i = inst
+        if i:
+            raise i
+    else:
+        # program name
+        if not ui.quiet:
+            rst = [_("Mercurial Distributed SCM\n"), '\n']
+        rst.extend(helplist())
+
+    return ''.join(rst)
--- a/mercurial/help/config.txt	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/help/config.txt	Wed Apr 03 13:03:50 2013 -0500
@@ -745,7 +745,7 @@
 For example::
 
     [hostfingerprints]
-    hg.intevation.org = 38:76:52:7c:87:26:9a:8f:4a:f8:d3:de:08:45:3b:ea:d6:4b:ee:cc
+    hg.intevation.org = 44:ed:af:1f:97:11:b6:01:7a:48:45:fc:10:3c:b7:f9:d4:89:2a:9d
 
 This feature is only supported when using Python 2.6 or later.
 
@@ -996,10 +996,13 @@
     ``inlinetime``.
     Default: inlinetime.
 
+``limit``
+    Number of lines to show. Specific to the ``ls`` instrumenting profiler.
+    Default: 30.
+
 ``nested``
-    Show at most this number of lines of drill-down info in a tree structure
-    after each main entry. This can help explain the difference between Total
-    and Inline.
+    Show at most this number of lines of drill-down info after each main entry.
+    This can help explain the difference between Total and Inline.
     Specific to the ``ls`` instrumenting profiler.
     Default: 5.
 
@@ -1459,3 +1462,48 @@
 
 ``templates``
     Where to find the HTML templates. Default is install path.
+
+``websub``
+----------
+
+Web substitution filter definition. You can use this section to
+define a set of regular expression substitution patterns which
+let you automatically modify the hgweb server output.
+
+The default hgweb templates only apply these substitution patterns
+on the revision description fields. You can apply them anywhere
+you want when you create your own templates by adding calls to the
+"websub" filter (usually after calling the "escape" filter).
+
+This can be used, for example, to convert issue references to links
+to your issue tracker, or to convert "markdown-like" syntax into
+HTML (see the examples below).
+
+Each entry in this section names a substitution filter.
+The value of each entry defines the substitution expression itself.
+The websub expressions follow the old interhg extension syntax,
+which in turn imitates the Unix sed replacement syntax::
+
+    pattername = s/SEARCH_REGEX/REPLACE_EXPRESSION/[i]
+
+You can use any separator other than "/". The final "i" is optional
+and indicates that the search must be case insensitive.
+
+Examples::
+
+    [websub]
+    issues = s|issue(\d+)|<a href="http://bts.example.org/issue\1">issue\1</a>|i
+    italic = s/\b_(\S+)_\b/<i>\1<\/i>/
+    bold = s/\*\b(\S+)\b\*/<b>\1<\/b>/
+
+``worker``
+----------
+
+Parallel master/worker configuration. We currently perform working
+directory updates in parallel on Unix-like systems, which greatly
+helps performance.
+
+``numcpus``
+    Number of CPUs to use for parallel operations. Default is 4 or the
+    number of CPUs on the system, whichever is larger. A zero or
+    negative value is treated as ``use the default``.
--- a/mercurial/help/dates.txt	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/help/dates.txt	Wed Apr 03 13:03:50 2013 -0500
@@ -18,6 +18,9 @@
 - ``12-6``
 - ``12/6``
 - ``12/6/6`` (Dec 6 2006)
+- ``today`` (midnight)
+- ``yesterday`` (midnight)
+- ``now`` - right now
 
 Lastly, there is Mercurial's internal format:
 
--- a/mercurial/help/templates.txt	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/help/templates.txt	Wed Apr 03 13:03:50 2013 -0500
@@ -44,19 +44,23 @@
 
 In addition to filters, there are some basic built-in functions:
 
+- date(date[, fmt])
+
+- fill(text[, width])
+
+- get(dict, key)
+
 - if(expr, then[, else])
 
 - ifeq(expr, expr, then[, else])
 
-- sub(pat, repl, expr)
-
 - join(list, sep)
 
 - label(label, expr)
 
-- date(date[, fmt])
+- sub(pat, repl, expr)
 
-- fill(text[, width])
+- rstdoc(text, style)
 
 Also, for any expression that returns a list, there is a list operator:
 
--- a/mercurial/hgweb/common.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/hgweb/common.py	Wed Apr 03 13:03:50 2013 -0500
@@ -129,7 +129,7 @@
     for part in parts:
         if (part in ('', os.curdir, os.pardir) or
             os.sep in part or os.altsep is not None and os.altsep in part):
-            return ""
+            return
     fpath = os.path.join(*parts)
     if isinstance(directory, str):
         directory = [directory]
@@ -144,7 +144,6 @@
         data = fp.read()
         fp.close()
         req.respond(HTTP_OK, ct, body=data)
-        return ""
     except TypeError:
         raise ErrorResponse(HTTP_SERVER_ERROR, 'illegal filename')
     except OSError, err:
--- a/mercurial/hgweb/hgweb_mod.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/hgweb/hgweb_mod.py	Wed Apr 03 13:03:50 2013 -0500
@@ -8,11 +8,13 @@
 
 import os
 from mercurial import ui, hg, hook, error, encoding, templater, util, repoview
+from mercurial.templatefilters import websub
+from mercurial.i18n import _
 from common import get_stat, ErrorResponse, permhooks, caching
 from common import HTTP_OK, HTTP_NOT_MODIFIED, HTTP_BAD_REQUEST
 from common import HTTP_NOT_FOUND, HTTP_SERVER_ERROR
 from request import wsgirequest
-import webcommands, protocol, webutil
+import webcommands, protocol, webutil, re
 
 perms = {
     'changegroup': 'pull',
@@ -63,7 +65,9 @@
 
         self.repo = self._getview(self.repo)
         self.repo.ui.setconfig('ui', 'report_untrusted', 'off')
+        self.repo.baseui.setconfig('ui', 'report_untrusted', 'off')
         self.repo.ui.setconfig('ui', 'nontty', 'true')
+        self.repo.baseui.setconfig('ui', 'nontty', 'true')
         hook.redirect(True)
         self.mtime = -1
         self.size = -1
@@ -73,6 +77,7 @@
         # a repo owner may set web.templates in .hg/hgrc to get any file
         # readable by the user running the CGI script
         self.templatepath = self.config('web', 'templates')
+        self.websubtable = self.loadwebsub()
 
     # The CGI scripts are often run by a user different from the repo owner.
     # Trust the settings from the .hg/hgrc files by default.
@@ -98,16 +103,14 @@
             return repo.filtered('served')
 
     def refresh(self, request=None):
-        if request:
-            self.repo.ui.environ = request.env
         st = get_stat(self.repo.spath)
         # compare changelog size in addition to mtime to catch
         # rollbacks made less than a second ago
         if st.st_mtime != self.mtime or st.st_size != self.size:
             self.mtime = st.st_mtime
             self.size = st.st_size
-            self.repo = hg.repository(self.repo.ui, self.repo.root)
-            self.repo = self._getview(self.repo)
+            r = hg.repository(self.repo.baseui, self.repo.root)
+            self.repo = self._getview(r)
             self.maxchanges = int(self.config("web", "maxchanges", 10))
             self.stripecount = int(self.config("web", "stripes", 1))
             self.maxshortchanges = int(self.config("web", "maxshortchanges",
@@ -116,6 +119,8 @@
             self.allowpull = self.configbool("web", "allowpull", True)
             encoding.encoding = self.config("web", "encoding",
                                             encoding.encoding)
+        if request:
+            self.repo.ui.environ = request.env
 
     def run(self):
         if not os.environ.get('GATEWAY_INTERFACE', '').startswith("CGI/1."):
@@ -259,6 +264,47 @@
                 return ['']
             return tmpl('error', error=inst.message)
 
+    def loadwebsub(self):
+        websubtable = []
+        websubdefs = self.repo.ui.configitems('websub')
+        # we must maintain interhg backwards compatibility
+        websubdefs += self.repo.ui.configitems('interhg')
+        for key, pattern in websubdefs:
+            # grab the delimiter from the character after the "s"
+            unesc = pattern[1]
+            delim = re.escape(unesc)
+
+            # identify portions of the pattern, taking care to avoid escaped
+            # delimiters. the replace format and flags are optional, but
+            # delimiters are required.
+            match = re.match(
+                r'^s%s(.+)(?:(?<=\\\\)|(?<!\\))%s(.*)%s([ilmsux])*$'
+                % (delim, delim, delim), pattern)
+            if not match:
+                self.repo.ui.warn(_("websub: invalid pattern for %s: %s\n")
+                                  % (key, pattern))
+                continue
+
+            # we need to unescape the delimiter for regexp and format
+            delim_re = re.compile(r'(?<!\\)\\%s' % delim)
+            regexp = delim_re.sub(unesc, match.group(1))
+            format = delim_re.sub(unesc, match.group(2))
+
+            # the pattern allows for 6 regexp flags, so set them if necessary
+            flagin = match.group(3)
+            flags = 0
+            if flagin:
+                for flag in flagin.upper():
+                    flags |= re.__dict__[flag]
+
+            try:
+                regexp = re.compile(regexp, flags)
+                websubtable.append((regexp, format))
+            except re.error:
+                self.repo.ui.warn(_("websub: invalid regexp for %s: %s\n")
+                                  % (key, regexp))
+        return websubtable
+
     def templater(self, req):
 
         # determine scheme, port and server name
@@ -312,9 +358,13 @@
                              or req.env.get('REPO_NAME')
                              or req.url.strip('/') or self.repo.root)
 
+        def websubfilter(text):
+            return websub(text, self.websubtable)
+
         # create the templater
 
         tmpl = templater.templater(mapfile,
+                                   filters={"websub": websubfilter},
                                    defaults={"url": req.url,
                                              "logourl": logourl,
                                              "logoimg": logoimg,
--- a/mercurial/hgweb/hgwebdir_mod.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/hgweb/hgwebdir_mod.py	Wed Apr 03 13:03:50 2013 -0500
@@ -197,7 +197,8 @@
                         if isinstance(tp, str):
                             tp = [tp]
                         static = [os.path.join(p, 'static') for p in tp]
-                    return (staticfile(static, fname, req),)
+                    staticfile(static, fname, req)
+                    return []
 
                 # top-level index
                 elif not virtual:
--- a/mercurial/hgweb/webcommands.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/hgweb/webcommands.py	Wed Apr 03 13:03:50 2013 -0500
@@ -89,6 +89,7 @@
                 author=fctx.user(),
                 date=fctx.date(),
                 desc=fctx.description(),
+                extra=fctx.extra(),
                 branch=webutil.nodebranchnodefault(fctx),
                 parent=webutil.parents(fctx),
                 child=webutil.children(fctx),
@@ -162,6 +163,7 @@
                        child=webutil.children(ctx),
                        changelogtag=showtags,
                        desc=ctx.description(),
+                       extra=ctx.extra(),
                        date=ctx.date(),
                        files=files,
                        rev=ctx.rev(),
@@ -216,6 +218,7 @@
                       "child": webutil.children(ctx, i + 1),
                       "changelogtag": showtags,
                       "desc": ctx.description(),
+                      "extra": ctx.extra(),
                       "date": ctx.date(),
                       "files": files,
                       "rev": i,
@@ -299,6 +302,7 @@
                 changesetbranch=showbranch,
                 author=ctx.user(),
                 desc=ctx.description(),
+                extra=ctx.extra(),
                 date=ctx.date(),
                 files=files,
                 diffsummary=lambda **x: webutil.diffsummary(diffstatgen),
@@ -531,6 +535,7 @@
                 parity=parity.next(),
                 author=ctx.user(),
                 desc=ctx.description(),
+                extra=ctx.extra(),
                 date=ctx.date(),
                 rev=i,
                 node=hn,
@@ -590,6 +595,7 @@
                 rev=ctx.rev(),
                 date=ctx.date(),
                 desc=ctx.description(),
+                extra=ctx.extra(),
                 author=ctx.user(),
                 rename=rename,
                 branch=webutil.nodebranchnodefault(ctx),
@@ -651,6 +657,7 @@
                 rev=ctx.rev(),
                 date=ctx.date(),
                 desc=ctx.description(),
+                extra=ctx.extra(),
                 author=ctx.user(),
                 rename=rename,
                 branch=webutil.nodebranchnodefault(ctx),
@@ -689,6 +696,7 @@
                    "rev": f.rev(),
                    "author": f.user(),
                    "desc": f.description(),
+                   "extra": f.extra(),
                    "file": f.path(),
                    "targetline": targetline,
                    "line": l,
@@ -705,6 +713,7 @@
                 author=fctx.user(),
                 date=fctx.date(),
                 desc=fctx.description(),
+                extra=fctx.extra(),
                 rename=webutil.renamelink(fctx),
                 branch=webutil.nodebranchnodefault(fctx),
                 parent=webutil.parents(fctx),
@@ -770,6 +779,7 @@
                       "parent": webutil.parents(iterfctx),
                       "child": webutil.children(iterfctx),
                       "desc": iterfctx.description(),
+                      "extra": iterfctx.extra(),
                       "tags": webutil.nodetagsdict(repo, iterfctx.node()),
                       "bookmarks": webutil.nodebookmarksdict(
                           repo, iterfctx.node()),
@@ -806,6 +816,19 @@
     if cnode == key or key == 'tip':
         arch_version = short(cnode)
     name = "%s-%s" % (reponame, arch_version)
+
+    ctx = webutil.changectx(web.repo, req)
+    pats = []
+    file = req.form.get('file', None)
+    if file:
+        file = file[0]
+        patandfile = file.split(':')
+        if len(patandfile) > 1 and patandfile[0].lower() in ('glob', 'relglob',
+                'path', 'relpath', 're', 'relre', 'set'):
+            msg = 'Archive pattern not allowed: %s' % file
+            raise ErrorResponse(HTTP_FORBIDDEN, msg)
+        pats = ['path:' + file]
+
     mimetype, artype, extension, encoding = web.archive_specs[type_]
     headers = [
         ('Content-Disposition', 'attachment; filename=%s%s' % (name, extension))
@@ -815,9 +838,9 @@
     req.headers.extend(headers)
     req.respond(HTTP_OK, mimetype)
 
-    ctx = webutil.changectx(web.repo, req)
+    matchfn = scmutil.match(ctx, pats, default='path')
     archival.archive(web.repo, req, cnode, artype, prefix=name,
-                     matchfn=scmutil.match(ctx, []),
+                     matchfn=matchfn,
                      subrepos=web.configbool("web", "archivesubrepos"))
     return []
 
@@ -832,7 +855,8 @@
         if isinstance(tp, str):
             tp = [tp]
         static = [os.path.join(p, 'static') for p in tp]
-    return [staticfile(static, fname, req)]
+    staticfile(static, fname, req)
+    return []
 
 def graph(web, req, tmpl):
 
@@ -982,11 +1006,9 @@
                     othercommands=othercommands, title='Index')
 
     u = webutil.wsgiui()
-    u.pushbuffer()
     u.verbose = True
     try:
-        commands.help_(u, topicname)
+        doc = helpmod.help_(u, topicname)
     except error.UnknownCommand:
         raise ErrorResponse(HTTP_NOT_FOUND)
-    doc = u.popbuffer()
     return tmpl('help', topic=topicname, doc=doc)
--- a/mercurial/hook.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/hook.py	Wed Apr 03 13:03:50 2013 -0500
@@ -6,7 +6,7 @@
 # GNU General Public License version 2 or any later version.
 
 from i18n import _
-import os, sys
+import os, sys, time, types
 import extensions, util, demandimport
 
 def _pythonhook(ui, repo, name, hname, funcname, args, throw):
@@ -20,6 +20,8 @@
     be run as hooks without wrappers to convert return values.'''
 
     ui.note(_("calling hook %s: %s\n") % (hname, funcname))
+    starttime = time.time()
+
     obj = funcname
     if not util.safehasattr(obj, '__call__'):
         d = funcname.rfind('.')
@@ -92,6 +94,12 @@
             return True
     finally:
         sys.stdout, sys.stderr, sys.stdin = old
+        duration = time.time() - starttime
+        readablefunc = funcname
+        if isinstance(funcname, types.FunctionType):
+            readablefunc = funcname.__module__ + "." + funcname.__name__
+        ui.log('pythonhook', 'pythonhook-%s: %s finished in %0.2f seconds\n',
+               name, readablefunc, duration)
     if r:
         if throw:
             raise util.Abort(_('%s hook failed') % hname)
@@ -101,6 +109,7 @@
 def _exthook(ui, repo, name, cmd, args, throw):
     ui.note(_("running hook %s: %s\n") % (name, cmd))
 
+    starttime = time.time()
     env = {}
     for k, v in args.iteritems():
         if util.safehasattr(v, '__call__'):
@@ -121,6 +130,10 @@
         r = util.system(cmd, environ=env, cwd=cwd, out=ui)
     else:
         r = util.system(cmd, environ=env, cwd=cwd, out=ui.fout)
+
+    duration = time.time() - starttime
+    ui.log('exthook', 'exthook-%s: %s finished in %0.2f seconds\n',
+           name, cmd, duration)
     if r:
         desc, r = util.explainexit(r)
         if throw:
--- a/mercurial/httppeer.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/httppeer.py	Wed Apr 03 13:03:50 2013 -0500
@@ -145,13 +145,14 @@
             raise error.OutOfBandError(resp.read())
         # accept old "text/plain" and "application/hg-changegroup" for now
         if not (proto.startswith('application/mercurial-') or
-                proto.startswith('text/plain') or
+                (proto.startswith('text/plain')
+                 and not resp.headers.get('content-length')) or
                 proto.startswith('application/hg-changegroup')):
             self.ui.debug("requested URL: '%s'\n" % util.hidepassword(cu))
             raise error.RepoError(
                 _("'%s' does not appear to be an hg repository:\n"
                   "---%%<--- (%s)\n%s\n---%%<---\n")
-                % (safeurl, proto or 'no content-type', resp.read()))
+                % (safeurl, proto or 'no content-type', resp.read(1024)))
 
         if proto.startswith('application/mercurial-'):
             try:
--- a/mercurial/localrepo.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/localrepo.py	Wed Apr 03 13:03:50 2013 -0500
@@ -49,7 +49,7 @@
 
 
 def hasunfilteredcache(repo, name):
-    """check if an repo and a unfilteredproperty cached value for <name>"""
+    """check if a repo has an unfilteredpropertycache value for <name>"""
     return name in vars(repo.unfiltered())
 
 def unfilteredmethod(orig):
@@ -310,13 +310,13 @@
     def unfiltered(self):
         """Return unfiltered version of the repository
 
-        Intended to be ovewritten by filtered repo."""
+        Intended to be overwritten by filtered repo."""
         return self
 
     def filtered(self, name):
         """Return a filtered version of a repository"""
         # build a new class with the mixin and the current class
-        # (possibily subclass of the repo)
+        # (possibly subclass of the repo)
         class proxycls(repoview.repoview, self.unfiltered().__class__):
             pass
         return proxycls(self, name)
@@ -966,7 +966,7 @@
             delattr(self.unfiltered(), 'dirstate')
 
     def invalidate(self):
-        unfiltered = self.unfiltered() # all filecaches are stored on unfiltered
+        unfiltered = self.unfiltered() # all file caches are stored unfiltered
         for k in self._filecache:
             # dirstate is invalidated separately in invalidatedirstate()
             if k == 'dirstate':
@@ -1234,12 +1234,14 @@
                     elif f not in self.dirstate:
                         fail(f, _("file not tracked!"))
 
+            cctx = context.workingctx(self, text, user, date, extra, changes)
+
             if (not force and not extra.get("close") and not merge
-                and not (changes[0] or changes[1] or changes[2])
+                and not cctx.files()
                 and wctx.branch() == wctx.p1().branch()):
                 return None
 
-            if merge and changes[3]:
+            if merge and cctx.deleted():
                 raise util.Abort(_("cannot commit merge with missing files"))
 
             ms = mergemod.mergestate(self)
@@ -1248,7 +1250,6 @@
                     raise util.Abort(_("unresolved merge conflicts "
                                        "(see hg help resolve)"))
 
-            cctx = context.workingctx(self, text, user, date, extra, changes)
             if editor:
                 cctx._text = editor(self, cctx, subs)
             edited = (text != cctx._text)
@@ -1282,11 +1283,7 @@
 
             # update bookmarks, dirstate and mergestate
             bookmarks.update(self, [p1, p2], ret)
-            for f in changes[0] + changes[1]:
-                self.dirstate.normal(f)
-            for f in changes[2]:
-                self.dirstate.drop(f)
-            self.dirstate.setparents(ret)
+            cctx.markcommitted(ret)
             ms.reset()
         finally:
             wlock.release()
@@ -1401,12 +1398,6 @@
         '''Inform the repository that nodes have been destroyed.
         Intended for use by strip and rollback, so there's a common
         place for anything that has to be done after destroying history.
-
-        If you know the branchheadcache was uptodate before nodes were removed
-        and you also know the set of candidate new heads that may have resulted
-        from the destruction, you can set newheadnodes.  This will enable the
-        code to update the branchheads cache, rather than having future code
-        decide it's invalid and regenerating it from scratch.
         '''
         # When one tries to:
         # 1) destroy nodes thus calling this method (e.g. strip)
@@ -1420,7 +1411,7 @@
         self._phasecache.write()
 
         # update the 'served' branch cache to help read only server process
-        # Thanks to branchcach collaboration this is done from the nearest
+        # Thanks to branchcache collaboration this is done from the nearest
         # filtered subset and it is expected to be fast.
         branchmap.updatecache(self.filtered('served'))
 
@@ -1544,12 +1535,12 @@
 
             modified, added, clean = [], [], []
             withflags = mf1.withflags() | mf2.withflags()
-            for fn in mf2:
+            for fn, mf2node in mf2.iteritems():
                 if fn in mf1:
                     if (fn not in deleted and
                         ((fn in withflags and mf1.flags(fn) != mf2.flags(fn)) or
-                         (mf1[fn] != mf2[fn] and
-                          (mf2[fn] or ctx1[fn].cmp(ctx2[fn]))))):
+                         (mf1[fn] != mf2node and
+                          (mf2node or ctx1[fn].cmp(ctx2[fn]))))):
                         modified.append(fn)
                     elif listclean:
                         clean.append(fn)
@@ -2411,6 +2402,12 @@
                     for n in added:
                         self.hook("incoming", node=hex(n), source=srctype,
                                   url=url)
+
+                    newheads = [h for h in self.heads() if h not in oldheads]
+                    self.ui.log("incoming",
+                                "%s incoming changes - new heads: %s\n",
+                                len(added),
+                                ', '.join([hex(c[:6]) for c in newheads]))
                 self._afterlock(runhooks)
 
         finally:
--- a/mercurial/lsprof.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/lsprof.py	Wed Apr 03 13:03:50 2013 -0500
@@ -50,9 +50,9 @@
             ccount = 0
             if climit and e.calls:
                 for se in e.calls:
-                    file.write(cols % ("+%s" % se.callcount, se.reccallcount,
+                    file.write(cols % (se.callcount, se.reccallcount,
                                        se.totaltime, se.inlinetime,
-                                       "+%s" % label(se.code)))
+                                       "    %s" % label(se.code)))
                     count += 1
                     ccount += 1
                     if limit is not None and count == limit:
--- a/mercurial/manifest.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/manifest.py	Wed Apr 03 13:03:50 2013 -0500
@@ -6,7 +6,7 @@
 # GNU General Public License version 2 or any later version.
 
 from i18n import _
-import mdiff, parsers, error, revlog, util
+import mdiff, parsers, error, revlog, util, dicthelpers
 import array, struct
 
 class manifestdict(dict):
@@ -25,10 +25,13 @@
         self._flags[f] = flags
     def copy(self):
         return manifestdict(self, dict.copy(self._flags))
+    def flagsdiff(self, d2):
+        return dicthelpers.diff(self._flags, d2._flags, "")
 
 class manifest(revlog.revlog):
     def __init__(self, opener):
-        self._mancache = None
+        # we expect to deal with not more than three revs at a time in merge
+        self._mancache = util.lrucachedict(3)
         revlog.revlog.__init__(self, opener, "00manifest.i")
 
     def parse(self, lines):
@@ -51,12 +54,12 @@
     def read(self, node):
         if node == revlog.nullid:
             return manifestdict() # don't upset local cache
-        if self._mancache and self._mancache[0] == node:
-            return self._mancache[1]
+        if node in self._mancache:
+            return self._mancache[node][0]
         text = self.revision(node)
         arraytext = array.array('c', text)
         mapping = self.parse(text)
-        self._mancache = (node, mapping, arraytext)
+        self._mancache[node] = (mapping, arraytext)
         return mapping
 
     def _search(self, m, s, lo=0, hi=None):
@@ -102,8 +105,9 @@
     def find(self, node, f):
         '''look up entry for a single file efficiently.
         return (node, flags) pair if found, (None, None) if not.'''
-        if self._mancache and self._mancache[0] == node:
-            return self._mancache[1].get(f), self._mancache[1].flags(f)
+        if node in self._mancache:
+            mapping = self._mancache[node][0]
+            return mapping.get(f), mapping.flags(f)
         text = self.revision(node)
         start, end = self._search(text, f)
         if start == end:
@@ -143,7 +147,7 @@
 
         # if we're using the cache, make sure it is valid and
         # parented by the same node we're diffing against
-        if not (changed and self._mancache and p1 and self._mancache[0] == p1):
+        if not (changed and p1 and (p1 in self._mancache)):
             files = sorted(map)
             checkforbidden(files)
 
@@ -156,7 +160,7 @@
             cachedelta = None
         else:
             added, removed = changed
-            addlist = self._mancache[2]
+            addlist = self._mancache[p1][1]
 
             checkforbidden(added)
             # combine the changed lists into one list for sorting
@@ -208,6 +212,6 @@
             text = util.buffer(arraytext)
 
         n = self.addrevision(text, transaction, link, p1, p2, cachedelta)
-        self._mancache = (n, map, arraytext)
+        self._mancache[n] = (map, arraytext)
 
         return n
--- a/mercurial/match.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/match.py	Wed Apr 03 13:03:50 2013 -0500
@@ -62,6 +62,7 @@
         self._files = []
         self._anypats = bool(include or exclude)
         self._ctx = ctx
+        self._always = False
 
         if include:
             pats = _normalize(include, 'glob', root, cwd, auditor)
@@ -103,6 +104,7 @@
                     m = lambda f: not em(f)
                 else:
                     m = lambda f: True
+                    self._always = True
 
         self.matchfn = m
         self._fmap = set(self._files)
@@ -130,7 +132,7 @@
     def anypats(self):
         return self._anypats
     def always(self):
-        return False
+        return self._always
 
 class exact(match):
     def __init__(self, root, cwd, files):
@@ -139,8 +141,7 @@
 class always(match):
     def __init__(self, root, cwd):
         match.__init__(self, root, cwd, [])
-    def always(self):
-        return True
+        self._always = True
 
 class narrowmatcher(match):
     """Adapt a matcher to work on a subdirectory only.
@@ -175,6 +176,7 @@
         self._cwd = matcher._cwd
         self._path = path
         self._matcher = matcher
+        self._always = matcher._always
 
         self._files = [f[len(path) + 1:] for f in matcher._files
                        if f.startswith(path + "/")]
--- a/mercurial/merge.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/merge.py	Wed Apr 03 13:03:50 2013 -0500
@@ -7,7 +7,7 @@
 
 from node import nullid, nullrev, hex, bin
 from i18n import _
-import error, util, filemerge, copies, subrepo
+import error, util, filemerge, copies, subrepo, worker, dicthelpers
 import errno, os, shutil
 
 class mergestate(object):
@@ -176,146 +176,226 @@
     state = branchmerge and 'r' or 'f'
     for f in wctx.deleted():
         if f not in mctx:
-            actions.append((f, state))
+            actions.append((f, state, None, "forget deleted"))
 
     if not branchmerge:
         for f in wctx.removed():
             if f not in mctx:
-                actions.append((f, "f"))
+                actions.append((f, "f", None, "forget removed"))
 
     return actions
 
-def manifestmerge(repo, p1, p2, pa, overwrite, partial):
+def manifestmerge(repo, wctx, p2, pa, branchmerge, force, partial,
+                  acceptremote=False):
     """
     Merge p1 and p2 with ancestor pa and generate merge action list
 
-    overwrite = whether we clobber working files
+    branchmerge and force are as passed in to update
     partial = function to filter file lists
+    acceptremote = accept the incoming changes without prompting
     """
 
-    def act(msg, m, f, *args):
-        repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m))
-        actions.append((f, m) + args)
-
+    overwrite = force and not branchmerge
     actions, copy, movewithdir = [], {}, {}
 
+    followcopies = False
     if overwrite:
-        pa = p1
+        pa = wctx
     elif pa == p2: # backwards
-        pa = p1.p1()
+        pa = wctx.p1()
+    elif not branchmerge and not wctx.dirty(missing=True):
+        pass
     elif pa and repo.ui.configbool("merge", "followcopies", True):
-        ret = copies.mergecopies(repo, p1, p2, pa)
+        followcopies = True
+
+    # manifests fetched in order are going to be faster, so prime the caches
+    [x.manifest() for x in
+     sorted(wctx.parents() + [p2, pa], key=lambda x: x.rev())]
+
+    if followcopies:
+        ret = copies.mergecopies(repo, wctx, p2, pa)
         copy, movewithdir, diverge, renamedelete = ret
         for of, fl in diverge.iteritems():
-            act("divergent renames", "dr", of, fl)
+            actions.append((of, "dr", (fl,), "divergent renames"))
         for of, fl in renamedelete.iteritems():
-            act("rename and delete", "rd", of, fl)
+            actions.append((of, "rd", (fl,), "rename and delete"))
 
     repo.ui.note(_("resolving manifests\n"))
-    repo.ui.debug(" overwrite: %s, partial: %s\n"
-                  % (bool(overwrite), bool(partial)))
-    repo.ui.debug(" ancestor: %s, local: %s, remote: %s\n" % (pa, p1, p2))
+    repo.ui.debug(" branchmerge: %s, force: %s, partial: %s\n"
+                  % (bool(branchmerge), bool(force), bool(partial)))
+    repo.ui.debug(" ancestor: %s, local: %s, remote: %s\n" % (pa, wctx, p2))
 
-    m1, m2, ma = p1.manifest(), p2.manifest(), pa.manifest()
+    m1, m2, ma = wctx.manifest(), p2.manifest(), pa.manifest()
     copied = set(copy.values())
     copied.update(movewithdir.values())
 
     if '.hgsubstate' in m1:
         # check whether sub state is modified
-        for s in sorted(p1.substate):
-            if p1.sub(s).dirty():
+        for s in sorted(wctx.substate):
+            if wctx.sub(s).dirty():
                 m1['.hgsubstate'] += "+"
                 break
 
+    aborts, prompts = [], []
     # Compare manifests
-    visit = m1.iteritems()
-    if repo.ui.debugflag:
-        visit = sorted(visit)
-    for f, n in visit:
+    fdiff = dicthelpers.diff(m1, m2)
+    flagsdiff = m1.flagsdiff(m2)
+    diff12 = dicthelpers.join(fdiff, flagsdiff)
+
+    for f, (n12, fl12) in diff12.iteritems():
+        if n12:
+            n1, n2 = n12
+        else: # file contents didn't change, but flags did
+            n1 = n2 = m1[f]
+        if fl12:
+            fl1, fl2 = fl12
+        else: # flags didn't change, file contents did
+            fl1 = fl2 = m1.flags(f)
+
         if partial and not partial(f):
             continue
-        if f in m2:
-            n2 = m2[f]
-            fl1, fl2, fla = m1.flags(f), m2.flags(f), ma.flags(f)
+        if n1 and n2:
+            fla = ma.flags(f)
             nol = 'l' not in fl1 + fl2 + fla
             a = ma.get(f, nullid)
-            if n == n2 and fl1 == fl2:
-                pass # same - keep local
-            elif n2 == a and fl2 == fla:
+            if n2 == a and fl2 == fla:
                 pass # remote unchanged - keep local
-            elif n == a and fl1 == fla: # local unchanged - use remote
-                if n == n2: # optimization: keep local content
-                    act("update permissions", "e", f, fl2)
+            elif n1 == a and fl1 == fla: # local unchanged - use remote
+                if n1 == n2: # optimization: keep local content
+                    actions.append((f, "e", (fl2,), "update permissions"))
                 else:
-                    act("remote is newer", "g", f, fl2)
+                    actions.append((f, "g", (fl2,), "remote is newer"))
             elif nol and n2 == a: # remote only changed 'x'
-                act("update permissions", "e", f, fl2)
-            elif nol and n == a: # local only changed 'x'
-                act("remote is newer", "g", f, fl1)
+                actions.append((f, "e", (fl2,), "update permissions"))
+            elif nol and n1 == a: # local only changed 'x'
+                actions.append((f, "g", (fl1,), "remote is newer"))
             else: # both changed something
-                act("versions differ", "m", f, f, f, False)
+                actions.append((f, "m", (f, f, False), "versions differ"))
         elif f in copied: # files we'll deal with on m2 side
             pass
-        elif f in movewithdir: # directory rename
+        elif n1 and f in movewithdir: # directory rename
             f2 = movewithdir[f]
-            act("remote renamed directory to " + f2, "d", f, None, f2,
-                m1.flags(f))
-        elif f in copy:
+            actions.append((f, "d", (None, f2, fl1),
+                            "remote renamed directory to " + f2))
+        elif n1 and f in copy:
             f2 = copy[f]
-            act("local copied/moved to " + f2, "m", f, f2, f, False)
-        elif f in ma: # clean, a different, no remote
-            if n != ma[f]:
-                if repo.ui.promptchoice(
-                    _(" local changed %s which remote deleted\n"
-                      "use (c)hanged version or (d)elete?") % f,
-                    (_("&Changed"), _("&Delete")), 0):
-                    act("prompt delete", "r", f)
-                else:
-                    act("prompt keep", "a", f)
-            elif n[20:] == "a": # added, no remote
-                act("remote deleted", "f", f)
+            actions.append((f, "m", (f2, f, False),
+                            "local copied/moved to " + f2))
+        elif n1 and f in ma: # clean, a different, no remote
+            if n1 != ma[f]:
+                prompts.append((f, "cd")) # prompt changed/deleted
+            elif n1[20:] == "a": # added, no remote
+                actions.append((f, "f", None, "remote deleted"))
             else:
-                act("other deleted", "r", f)
-
-    visit = m2.iteritems()
-    if repo.ui.debugflag:
-        visit = sorted(visit)
-    for f, n in visit:
-        if partial and not partial(f):
-            continue
-        if f in m1 or f in copied: # files already visited
-            continue
-        if f in movewithdir:
+                actions.append((f, "r", None, "other deleted"))
+        elif n2 and f in movewithdir:
             f2 = movewithdir[f]
-            act("local renamed directory to " + f2, "d", None, f, f2,
-                m2.flags(f))
-        elif f in copy:
+            actions.append((None, "d", (f, f2, fl2),
+                            "local renamed directory to " + f2))
+        elif n2 and f in copy:
             f2 = copy[f]
             if f2 in m2:
-                act("remote copied to " + f, "m",
-                    f2, f, f, False)
+                actions.append((f2, "m", (f, f, False),
+                                "remote copied to " + f))
+            else:
+                actions.append((f2, "m", (f, f, True),
+                                "remote moved to " + f))
+        elif n2 and f not in ma:
+            # local unknown, remote created: the logic is described by the
+            # following table:
+            #
+            # force  branchmerge  different  |  action
+            #   n         *           n      |    get
+            #   n         *           y      |   abort
+            #   y         n           *      |    get
+            #   y         y           n      |    get
+            #   y         y           y      |   merge
+            #
+            # Checking whether the files are different is expensive, so we
+            # don't do that when we can avoid it.
+            if force and not branchmerge:
+                actions.append((f, "g", (fl2,), "remote created"))
             else:
-                act("remote moved to " + f, "m",
-                    f2, f, f, True)
-        elif f not in ma:
-            if (not overwrite
-                and _checkunknownfile(repo, p1, p2, f)):
-                act("remote differs from untracked local",
-                    "m", f, f, f, False)
+                different = _checkunknownfile(repo, wctx, p2, f)
+                if force and branchmerge and different:
+                    actions.append((f, "m", (f, f, False),
+                                    "remote differs from untracked local"))
+                elif not force and different:
+                    aborts.append((f, "ud"))
+                else:
+                    actions.append((f, "g", (fl2,), "remote created"))
+        elif n2 and n2 != ma[f]:
+            prompts.append((f, "dc")) # prompt deleted/changed
+
+    for f, m in sorted(aborts):
+        if m == "ud":
+            repo.ui.warn(_("%s: untracked file differs\n") % f)
+        else: assert False, m
+    if aborts:
+        raise util.Abort(_("untracked files in working directory differ "
+                           "from files in requested revision"))
+
+    for f, m in sorted(prompts):
+        if m == "cd":
+            if acceptremote:
+                actions.append((f, "r", None, "remote delete"))
+            elif repo.ui.promptchoice(
+                _("local changed %s which remote deleted\n"
+                  "use (c)hanged version or (d)elete?") % f,
+                (_("&Changed"), _("&Delete")), 0):
+                actions.append((f, "r", None, "prompt delete"))
             else:
-                act("remote created", "g", f, m2.flags(f))
-        elif n != ma[f]:
-            if repo.ui.promptchoice(
+                actions.append((f, "a", None, "prompt keep"))
+        elif m == "dc":
+            if acceptremote:
+                actions.append((f, "g", (m2.flags(f),), "remote recreating"))
+            elif repo.ui.promptchoice(
                 _("remote changed %s which local deleted\n"
                   "use (c)hanged version or leave (d)eleted?") % f,
                 (_("&Changed"), _("&Deleted")), 0) == 0:
-                act("prompt recreating", "g", f, m2.flags(f))
-
+                actions.append((f, "g", (m2.flags(f),), "prompt recreating"))
+        else: assert False, m
     return actions
 
 def actionkey(a):
     return a[1] == "r" and -1 or 0, a
 
+def getremove(repo, mctx, overwrite, args):
+    """apply usually-non-interactive updates to the working directory
+
+    mctx is the context to be merged into the working copy
+
+    yields tuples for progress updates
+    """
+    verbose = repo.ui.verbose
+    unlink = util.unlinkpath
+    wjoin = repo.wjoin
+    fctx = mctx.filectx
+    wwrite = repo.wwrite
+    audit = repo.wopener.audit
+    i = 0
+    for arg in args:
+        f = arg[0]
+        if arg[1] == 'r':
+            if verbose:
+                repo.ui.note(_("removing %s\n") % f)
+            audit(f)
+            try:
+                unlink(wjoin(f), ignoremissing=True)
+            except OSError, inst:
+                repo.ui.warn(_("update failed to remove %s: %s!\n") %
+                             (f, inst.strerror))
+        else:
+            if verbose:
+                repo.ui.note(_("getting %s\n") % f)
+            wwrite(f, fctx(f).data(), arg[2][0])
+        if i == 100:
+            yield i, f
+            i = 0
+        i += 1
+    if i > 0:
+        yield i, f
+
 def applyupdates(repo, actions, wctx, mctx, actx, overwrite):
     """apply the merge action list to the working directory
 
@@ -335,12 +415,13 @@
 
     # prescan for merges
     for a in actions:
-        f, m = a[:2]
+        f, m, args, msg = a
+        repo.ui.debug(" %s: %s -> %s\n" % (f, msg, m))
         if m == "m": # merge
-            f2, fd, move = a[2:]
+            f2, fd, move = args
             if fd == '.hgsubstate': # merged internally
                 continue
-            repo.ui.debug("preserving %s for resolve of %s\n" % (f, fd))
+            repo.ui.debug("  preserving %s for resolve of %s\n" % (f, fd))
             fcl = wctx[f]
             fco = mctx[f2]
             if mctx == actx: # backwards, use working dir parent as ancestor
@@ -366,27 +447,39 @@
             util.unlinkpath(repo.wjoin(f))
 
     numupdates = len(actions)
-    for i, a in enumerate(actions):
-        f, m = a[:2]
-        repo.ui.progress(_('updating'), i + 1, item=f, total=numupdates,
+    workeractions = [a for a in actions if a[1] in 'gr']
+    updated = len([a for a in workeractions if a[1] == 'g'])
+    removed = len([a for a in workeractions if a[1] == 'r'])
+    actions = [a for a in actions if a[1] not in 'gr']
+
+    hgsub = [a[1] for a in workeractions if a[0] == '.hgsubstate']
+    if hgsub and hgsub[0] == 'r':
+        subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
+
+    z = 0
+    prog = worker.worker(repo.ui, 0.001, getremove, (repo, mctx, overwrite),
+                         workeractions)
+    for i, item in prog:
+        z += i
+        repo.ui.progress(_('updating'), z, item=item, total=numupdates,
                          unit=_('files'))
-        if m == "r": # remove
-            repo.ui.note(_("removing %s\n") % f)
-            audit(f)
-            if f == '.hgsubstate': # subrepo states need updating
-                subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
-            try:
-                util.unlinkpath(repo.wjoin(f), ignoremissing=True)
-            except OSError, inst:
-                repo.ui.warn(_("update failed to remove %s: %s!\n") %
-                             (f, inst.strerror))
-            removed += 1
-        elif m == "m": # merge
+
+    if hgsub and hgsub[0] == 'g':
+        subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
+
+    _updating = _('updating')
+    _files = _('files')
+    progress = repo.ui.progress
+
+    for i, a in enumerate(actions):
+        f, m, args, msg = a
+        progress(_updating, z + i + 1, item=f, total=numupdates, unit=_files)
+        if m == "m": # merge
+            f2, fd, move = args
             if fd == '.hgsubstate': # subrepo states need updating
                 subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx),
                                  overwrite)
                 continue
-            f2, fd, move = a[2:]
             audit(fd)
             r = ms.resolve(fd, wctx, mctx)
             if r is not None and r > 0:
@@ -396,15 +489,8 @@
                     updated += 1
                 else:
                     merged += 1
-        elif m == "g": # get
-            flags = a[2]
-            repo.ui.note(_("getting %s\n") % f)
-            repo.wwrite(f, mctx.filectx(f).data(), flags)
-            updated += 1
-            if f == '.hgsubstate': # subrepo states need updating
-                subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
         elif m == "d": # directory rename
-            f2, fd, flags = a[2:]
+            f2, fd, flags = args
             if f:
                 repo.ui.note(_("moving %s to %s\n") % (f, fd))
                 audit(f)
@@ -415,28 +501,29 @@
                 repo.wwrite(fd, mctx.filectx(f2).data(), flags)
             updated += 1
         elif m == "dr": # divergent renames
-            fl = a[2]
+            fl, = args
             repo.ui.warn(_("note: possible conflict - %s was renamed "
                            "multiple times to:\n") % f)
             for nf in fl:
                 repo.ui.warn(" %s\n" % nf)
         elif m == "rd": # rename and delete
-            fl = a[2]
+            fl, = args
             repo.ui.warn(_("note: possible conflict - %s was deleted "
                            "and renamed to:\n") % f)
             for nf in fl:
                 repo.ui.warn(" %s\n" % nf)
         elif m == "e": # exec
-            flags = a[2]
+            flags, = args
             audit(f)
             util.setflags(repo.wjoin(f), 'l' in flags, 'x' in flags)
             updated += 1
     ms.commit()
-    repo.ui.progress(_('updating'), None, total=numupdates, unit=_('files'))
+    progress(_updating, None, total=numupdates, unit=_files)
 
     return updated, merged, removed, unresolved
 
-def calculateupdates(repo, tctx, mctx, ancestor, branchmerge, force, partial):
+def calculateupdates(repo, tctx, mctx, ancestor, branchmerge, force, partial,
+                     acceptremote=False):
     "Calculate the actions needed to merge mctx into tctx"
     actions = []
     folding = not util.checkcase(repo.path)
@@ -447,21 +534,19 @@
             _checkcollision(mctx, None)
         else:
             _checkcollision(mctx, (tctx, ancestor))
-    if not force:
-        _checkunknown(repo, tctx, mctx)
+    actions += manifestmerge(repo, tctx, mctx,
+                             ancestor,
+                             branchmerge, force,
+                             partial, acceptremote)
     if tctx.rev() is None:
         actions += _forgetremoved(tctx, mctx, branchmerge)
-    actions += manifestmerge(repo, tctx, mctx,
-                             ancestor,
-                             force and not branchmerge,
-                             partial)
     return actions
 
 def recordupdates(repo, actions, branchmerge):
     "record merge actions to the dirstate"
 
     for a in actions:
-        f, m = a[:2]
+        f, m, args, msg = a
         if m == "r": # remove
             if branchmerge:
                 repo.dirstate.remove(f)
@@ -480,7 +565,7 @@
             else:
                 repo.dirstate.normal(f)
         elif m == "m": # merge
-            f2, fd, move = a[2:]
+            f2, fd, move = args
             if branchmerge:
                 # We've done a branch merge, mark this file as merged
                 # so that we properly record the merger later
@@ -503,7 +588,7 @@
                 if move:
                     repo.dirstate.drop(f)
         elif m == "d": # directory rename
-            f2, fd, flag = a[2:]
+            f2, fd, flag = args
             if not f2 and f not in repo.dirstate:
                 # untracked file moved
                 continue
@@ -528,10 +613,11 @@
     branchmerge = whether to merge between branches
     force = whether to force branch merging or file overwriting
     partial = a function to filter file lists (dirstate not updated)
-    mergeancestor = if false, merging with an ancestor (fast-forward)
-      is only allowed between different named branches. This flag
-      is used by rebase extension as a temporary fix and should be
-      avoided in general.
+    mergeancestor = whether it is merging with an ancestor. If true,
+      we should accept the incoming changes for any prompts that occur.
+      If false, merging with an ancestor (fast-forward) is only allowed
+      between different named branches. This flag is used by rebase extension
+      as a temporary fix and should be avoided in general.
 
     The table below shows all the behaviors of the update command
     given the -c and -C or no options, whether the working directory
@@ -619,7 +705,7 @@
 
         ### calculate phase
         actions = calculateupdates(repo, wc, p2, pa,
-                                   branchmerge, force, partial)
+                                   branchmerge, force, partial, mergeancestor)
 
         ### apply phase
         if not branchmerge: # just jump to the new rev
--- a/mercurial/minirst.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/minirst.py	Wed Apr 03 13:03:50 2013 -0500
@@ -22,6 +22,20 @@
 import util, encoding
 from i18n import _
 
+import cgi
+
+def section(s):
+    return "%s\n%s\n\n" % (s, "\"" * encoding.colwidth(s))
+
+def subsection(s):
+    return "%s\n%s\n\n" % (s, '=' * encoding.colwidth(s))
+
+def subsubsection(s):
+    return "%s\n%s\n\n" % (s, "-" * encoding.colwidth(s))
+
+def subsubsubsection(s):
+    return "%s\n%s\n\n" % (s, "." * encoding.colwidth(s))
+
 def replace(text, substs):
     '''
     Apply a list of (find, replace) pairs to a text.
@@ -512,6 +526,9 @@
     headernest = ''
     listnest = []
 
+    def escape(s):
+        return cgi.escape(s, True)
+
     def openlist(start, level):
         if not listnest or listnest[-1][0] != start:
             listnest.append((start, level))
@@ -525,37 +542,38 @@
         lines = b['lines']
 
         if btype == 'admonition':
-            admonition = _admonitiontitles[b['admonitiontitle']]
-            text = ' '.join(map(str.strip, lines))
+            admonition = escape(_admonitiontitles[b['admonitiontitle']])
+            text = escape(' '.join(map(str.strip, lines)))
             out.append('<p>\n<b>%s</b> %s\n</p>\n' % (admonition, text))
         elif btype == 'paragraph':
-            out.append('<p>\n%s\n</p>\n' % '\n'.join(lines))
+            out.append('<p>\n%s\n</p>\n' % escape('\n'.join(lines)))
         elif btype == 'margin':
             pass
         elif btype == 'literal':
-            out.append('<pre>\n%s\n</pre>\n' % '\n'.join(lines))
+            out.append('<pre>\n%s\n</pre>\n' % escape('\n'.join(lines)))
         elif btype == 'section':
             i = b['underline']
             if i not in headernest:
                 headernest += i
             level = headernest.index(i) + 1
-            out.append('<h%d>%s</h%d>\n' % (level, lines[0], level))
+            out.append('<h%d>%s</h%d>\n' % (level, escape(lines[0]), level))
         elif btype == 'table':
             table = b['table']
-            t = []
+            out.append('<table>\n')
             for row in table:
-                l = []
-                for v in zip(row):
-                    if not t:
-                        l.append('<th>%s</th>' % v)
-                    else:
-                        l.append('<td>%s</td>' % v)
-                t.append(' <tr>%s</tr>\n' % ''.join(l))
-            out.append('<table>\n%s</table>\n' % ''.join(t))
+                out.append('<tr>')
+                for v in row:
+                    out.append('<td>')
+                    out.append(escape(v))
+                    out.append('</td>')
+                    out.append('\n')
+                out.pop()
+                out.append('</tr>\n')
+            out.append('</table>\n')
         elif btype == 'definition':
             openlist('dl', level)
-            term = lines[0]
-            text = ' '.join(map(str.strip, lines[1:]))
+            term = escape(lines[0])
+            text = escape(' '.join(map(str.strip, lines[1:])))
             out.append(' <dt>%s\n <dd>%s\n' % (term, text))
         elif btype == 'bullet':
             bullet, head = lines[0].split(' ', 1)
@@ -563,16 +581,16 @@
                 openlist('ul', level)
             else:
                 openlist('ol', level)
-            out.append(' <li> %s\n' % ' '.join([head] + lines[1:]))
+            out.append(' <li> %s\n' % escape(' '.join([head] + lines[1:])))
         elif btype == 'field':
             openlist('dl', level)
-            key = b['key']
-            text = ' '.join(map(str.strip, lines))
+            key = escape(b['key'])
+            text = escape(' '.join(map(str.strip, lines)))
             out.append(' <dt>%s\n <dd>%s\n' % (key, text))
         elif btype == 'option':
             openlist('dl', level)
-            opt = b['optstr']
-            desc = ' '.join(map(str.strip, lines))
+            opt = escape(b['optstr'])
+            desc = escape(' '.join(map(str.strip, lines)))
             out.append(' <dt>%s\n <dd>%s\n' % (opt, desc))
 
         # close lists if indent level of next block is lower
--- a/mercurial/obsolete.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/obsolete.py	Wed Apr 03 13:03:50 2013 -0500
@@ -46,7 +46,7 @@
     (A, (C, C))
 
   We use a single marker to distinct the "split" case from the "divergence"
-  case. If two independants operation rewrite the same changeset A in to A' and
+  case. If two independents operation rewrite the same changeset A in to A' and
   A'' when have an error case: divergent rewriting. We can detect it because
   two markers will be created independently:
 
@@ -129,8 +129,9 @@
 #
 # But by transitivity Ad is also a successors of A. To avoid having Ad marked
 # as bumped too, we add the `bumpedfix` flag to the marker. <A', (Ad,)>.
-# This flag mean that the successors are an interdiff that fix the bumped
-# situation, breaking the transitivity of "bumped" here.
+# This flag mean that the successors express the changes between the public and
+# bumped version and fix the situation, breaking the transitivity of
+# "bumped" here.
 bumpedfix = 1
 
 def _readmarkers(data):
@@ -510,7 +511,7 @@
             #     In such a situation, we arbitrary set the successors sets of
             #     the node to nothing (node pruned) to break the cycle.
             #
-            #     If no break was encountered we proceeed to phase 2.
+            #     If no break was encountered we proceed to phase 2.
             #
             # Phase 2 computes successors sets of CURRENT (case 4); see details
             # in phase 2 itself.
@@ -551,13 +552,13 @@
                 # successors sets of all its "successors" node.
                 #
                 # Each different marker is a divergence in the obsolescence
-                # history. It contributes successors sets dictinct from other
+                # history. It contributes successors sets distinct from other
                 # markers.
                 #
                 # Within a marker, a successor may have divergent successors
                 # sets. In such a case, the marker will contribute multiple
                 # divergent successors sets. If multiple successors have
-                # divergents successors sets, a cartesian product is used.
+                # divergent successors sets, a cartesian product is used.
                 #
                 # At the end we post-process successors sets to remove
                 # duplicated entry and successors set that are strict subset of
--- a/mercurial/parsers.c	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/parsers.c	Wed Apr 03 13:03:50 2013 -0500
@@ -326,7 +326,8 @@
 		if (getintat(v, 3, &mtime) == -1)
 			goto bail;
 		if (*s == 'n' && mtime == (uint32_t)now) {
-			/* See dirstate.py:write for why we do this. */
+			/* See pure/parsers.py:pack_dirstate for why we do
+			 * this. */
 			if (PyDict_SetItem(map, k, dirstate_unset) == -1)
 				goto bail;
 			mode = 0, size = -1, mtime = -1;
--- a/mercurial/patch.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/patch.py	Wed Apr 03 13:03:50 2013 -0500
@@ -314,7 +314,7 @@
     gitpatches = []
     for line in lr:
         line = line.rstrip(' \r\n')
-        if line.startswith('diff --git'):
+        if line.startswith('diff --git a/'):
             m = gitre.match(line)
             if m:
                 if gp:
@@ -1211,7 +1211,7 @@
                 emitfile = False
                 yield 'file', (afile, bfile, h, gp and gp.copy() or None)
             yield 'hunk', h
-        elif x.startswith('diff --git'):
+        elif x.startswith('diff --git a/'):
             m = gitre.match(x.rstrip(' \r\n'))
             if not m:
                 continue
@@ -1756,6 +1756,8 @@
                     else:
                         header.append('deleted file mode %s\n' %
                                       gitmode[man1.flags(f)])
+                        if util.binary(to):
+                            dodiff = 'binary'
                 elif not to or util.binary(to):
                     # regular diffs cannot represent empty file deletion
                     losedatafn(f)
@@ -1813,7 +1815,7 @@
             addresult()
             # set numbers to 0 anyway when starting new file
             adds, removes, isbinary = 0, 0, False
-            if line.startswith('diff --git'):
+            if line.startswith('diff --git a/'):
                 filename = gitre.search(line).group(1)
             elif line.startswith('diff -r'):
                 # format: "diff -r ... -r ... filename"
--- a/mercurial/pure/parsers.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/pure/parsers.py	Wed Apr 03 13:03:50 2013 -0500
@@ -7,7 +7,7 @@
 
 from mercurial.node import bin, nullid
 from mercurial import util
-import struct, zlib
+import struct, zlib, cStringIO
 
 _pack = struct.pack
 _unpack = struct.unpack
@@ -87,3 +87,29 @@
             copymap[f] = c
         dmap[f] = e[:4]
     return parents
+
+def pack_dirstate(dmap, copymap, pl, now):
+    now = int(now)
+    cs = cStringIO.StringIO()
+    write = cs.write
+    write("".join(pl))
+    for f, e in dmap.iteritems():
+        if e[0] == 'n' and e[3] == now:
+            # The file was last modified "simultaneously" with the current
+            # write to dirstate (i.e. within the same second for file-
+            # systems with a granularity of 1 sec). This commonly happens
+            # for at least a couple of files on 'update'.
+            # The user could change the file without changing its size
+            # within the same second. Invalidate the file's stat data in
+            # dirstate, forcing future 'status' calls to compare the
+            # contents of the file. This prevents mistakenly treating such
+            # files as clean.
+            e = (e[0], 0, -1, -1)   # mark entry as 'unset'
+            dmap[f] = e
+
+        if f in copymap:
+            f = "%s\0%s" % (f, copymap[f])
+        e = _pack(">cllll", e[0], e[1], e[2], e[3], len(f))
+        write(e)
+        write(f)
+    return cs.getvalue()
--- a/mercurial/repair.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/repair.py	Wed Apr 03 13:03:50 2013 -0500
@@ -119,6 +119,7 @@
     if backup == "all":
         backupfile = _bundle(repo, stripbases, cl.heads(), node, topic)
         repo.ui.status(_("saved backup bundle to %s\n") % backupfile)
+        repo.ui.log("backupbundle", "saved backup bundle to %s\n", backupfile)
     if saveheads or savebases:
         # do not compress partial bundle if we remove it from disk later
         chgrpfile = _bundle(repo, savebases, saveheads, node, 'temp',
--- a/mercurial/repoview.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/repoview.py	Wed Apr 03 13:03:50 2013 -0500
@@ -149,7 +149,7 @@
         repoview.method() --> repo.__class__.method(repoview)
 
     The inheritance has to be done dynamically because `repo` can be of any
-    subclasses of `localrepo`. Eg: `bundlerepo` or `httprepo`.
+    subclasses of `localrepo`. Eg: `bundlerepo` or `statichttprepo`.
     """
 
     def __init__(self, repo, filtername):
@@ -158,7 +158,7 @@
         object.__setattr__(self, '_clcachekey', None)
         object.__setattr__(self, '_clcache', None)
 
-    # not a cacheproperty on purpose we shall implement a proper cache later
+    # not a propertycache on purpose we shall implement a proper cache later
     @property
     def changelog(self):
         """return a filtered version of the changeset
@@ -210,7 +210,7 @@
     def __delattr__(self, attr):
         return delattr(self._unfilteredrepo, attr)
 
-    # The `requirement` attribut is initialiazed during __init__. But
+    # The `requirements` attribute is initialized during __init__. But
     # __getattr__ won't be called as it also exists on the class. We need
     # explicit forwarding to main repo here
     @property
--- a/mercurial/revlog.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/revlog.py	Wed Apr 03 13:03:50 2013 -0500
@@ -91,6 +91,14 @@
         return bin[1:]
     raise RevlogError(_("unknown compression type %r") % t)
 
+# index v0:
+#  4 bytes: offset
+#  4 bytes: compressed length
+#  4 bytes: base rev
+#  4 bytes: link rev
+# 32 bytes: parent 1 nodeid
+# 32 bytes: parent 2 nodeid
+# 32 bytes: nodeid
 indexformatv0 = ">4l20s20s20s"
 v0shaoffset = 56
 
--- a/mercurial/revset.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/revset.py	Wed Apr 03 13:03:50 2013 -0500
@@ -277,20 +277,32 @@
     return checkstatus(repo, subset, pat, 1)
 
 def ancestor(repo, subset, x):
-    """``ancestor(single, single)``
-    Greatest common ancestor of the two changesets.
+    """``ancestor(*changeset)``
+    Greatest common ancestor of the changesets.
+
+    Accepts 0 or more changesets.
+    Will return empty list when passed no args.
+    Greatest common ancestor of a single changeset is that changeset.
     """
     # i18n: "ancestor" is a keyword
-    l = getargs(x, 2, 2, _("ancestor requires two arguments"))
-    r = list(repo)
-    a = getset(repo, r, l[0])
-    b = getset(repo, r, l[1])
-    if len(a) != 1 or len(b) != 1:
-        # i18n: "ancestor" is a keyword
-        raise error.ParseError(_("ancestor arguments must be single revisions"))
-    an = [repo[a[0]].ancestor(repo[b[0]]).rev()]
+    l = getlist(x)
+    rl = list(repo)
+    anc = None
 
-    return [r for r in an if r in subset]
+    # (getset(repo, rl, i) for i in l) generates a list of lists
+    rev = repo.changelog.rev
+    ancestor = repo.changelog.ancestor
+    node = repo.changelog.node
+    for revs in (getset(repo, rl, i) for i in l):
+        for r in revs:
+            if anc is None:
+                anc = r
+            else:
+                anc = rev(ancestor(node(anc), node(r)))
+
+    if anc is not None and anc in subset:
+        return [anc]
+    return []
 
 def _ancestors(repo, subset, x, followfirst=False):
     args = getset(repo, list(repo), x)
@@ -1484,8 +1496,6 @@
             s = set([repo[tn].rev()])
         else:
             s = set([cl.rev(n) for t, n in repo.tagslist() if matcher(t)])
-            if not s:
-                raise util.Abort(_("no tags exist that match '%s'") % pattern)
     else:
         s = set([cl.rev(n) for t, n in repo.tagslist() if t != 'tip'])
     return [r for r in subset if r in s]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial/scmposix.py	Wed Apr 03 13:03:50 2013 -0500
@@ -0,0 +1,32 @@
+import sys, os
+import osutil
+
+def _rcfiles(path):
+    rcs = [os.path.join(path, 'hgrc')]
+    rcdir = os.path.join(path, 'hgrc.d')
+    try:
+        rcs.extend([os.path.join(rcdir, f)
+                    for f, kind in osutil.listdir(rcdir)
+                    if f.endswith(".rc")])
+    except OSError:
+        pass
+    return rcs
+
+def systemrcpath():
+    path = []
+    if sys.platform == 'plan9':
+        root = 'lib/mercurial'
+    else:
+        root = 'etc/mercurial'
+    # old mod_python does not set sys.argv
+    if len(getattr(sys, 'argv', [])) > 0:
+        p = os.path.dirname(os.path.dirname(sys.argv[0]))
+        path.extend(_rcfiles(os.path.join(p, root)))
+    path.extend(_rcfiles('/' + root))
+    return path
+
+def userrcpath():
+    if sys.platform == 'plan9':
+        return [os.environ['home'] + '/lib/hgrc']
+    else:
+        return [os.path.expanduser('~/.hgrc')]
--- a/mercurial/scmutil.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/scmutil.py	Wed Apr 03 13:03:50 2013 -0500
@@ -9,7 +9,15 @@
 from mercurial.node import nullrev
 import util, error, osutil, revset, similar, encoding, phases
 import match as matchmod
-import os, errno, re, stat, sys, glob
+import os, errno, re, stat, glob
+
+if os.name == 'nt':
+    import scmwindows as scmplatform
+else:
+    import scmposix as scmplatform
+
+systemrcpath = scmplatform.systemrcpath
+userrcpath = scmplatform.userrcpath
 
 def nochangesfound(ui, repo, excluded=None):
     '''Report no changes for push/pull, excluded is None or a list of
@@ -38,6 +46,11 @@
     for c in (':', '\0', '\n', '\r'):
         if c in lbl:
             raise util.Abort(_("%r cannot be used in a name") % c)
+    try:
+        int(lbl)
+        raise util.Abort(_("a %s cannot have an integer as its name") % kind)
+    except ValueError:
+        pass
 
 def checkfilename(f):
     '''Check that the filename f is an acceptable filename for a tracked file'''
@@ -179,6 +192,13 @@
         # want to add "foo/bar/baz" before checking if there's a "foo/.hg"
         self.auditeddir.update(prefixes)
 
+    def check(self, path):
+        try:
+            self(path)
+            return True
+        except (OSError, util.Abort):
+            return False
+
 class abstractvfs(object):
     """Abstract base class; cannot be instantiated"""
 
@@ -294,8 +314,7 @@
             # to a directory. Let the posixfile() call below raise IOError.
             if basename:
                 if atomictemp:
-                    if not os.path.isdir(dirname):
-                        util.makedirs(dirname, self.createmode)
+                    util.ensuredirs(dirname, self.createmode)
                     return util.atomictempfile(f, mode, self.createmode)
                 try:
                     if 'w' in mode:
@@ -313,8 +332,7 @@
                     if e.errno != errno.ENOENT:
                         raise
                     nlink = 0
-                    if not os.path.isdir(dirname):
-                        util.makedirs(dirname, self.createmode)
+                    util.ensuredirs(dirname, self.createmode)
                 if nlink > 0:
                     if self._trustnlink is None:
                         self._trustnlink = nlink > 1 or util.checknlink(f)
@@ -333,9 +351,7 @@
         except OSError:
             pass
 
-        dirname = os.path.dirname(linkname)
-        if not os.path.exists(dirname):
-            util.makedirs(dirname, self.createmode)
+        util.ensuredirs(os.path.dirname(linkname), self.createmode)
 
         if self._cansymlink:
             try:
@@ -523,84 +539,6 @@
             _rcpath = osrcpath()
     return _rcpath
 
-if os.name != 'nt':
-
-    def rcfiles(path):
-        rcs = [os.path.join(path, 'hgrc')]
-        rcdir = os.path.join(path, 'hgrc.d')
-        try:
-            rcs.extend([os.path.join(rcdir, f)
-                        for f, kind in osutil.listdir(rcdir)
-                        if f.endswith(".rc")])
-        except OSError:
-            pass
-        return rcs
-
-    def systemrcpath():
-        path = []
-        if sys.platform == 'plan9':
-            root = 'lib/mercurial'
-        else:
-            root = 'etc/mercurial'
-        # old mod_python does not set sys.argv
-        if len(getattr(sys, 'argv', [])) > 0:
-            p = os.path.dirname(os.path.dirname(sys.argv[0]))
-            path.extend(rcfiles(os.path.join(p, root)))
-        path.extend(rcfiles('/' + root))
-        return path
-
-    def userrcpath():
-        if sys.platform == 'plan9':
-            return [os.environ['home'] + '/lib/hgrc']
-        else:
-            return [os.path.expanduser('~/.hgrc')]
-
-else:
-
-    import _winreg
-
-    def systemrcpath():
-        '''return default os-specific hgrc search path'''
-        rcpath = []
-        filename = util.executablepath()
-        # Use mercurial.ini found in directory with hg.exe
-        progrc = os.path.join(os.path.dirname(filename), 'mercurial.ini')
-        if os.path.isfile(progrc):
-            rcpath.append(progrc)
-            return rcpath
-        # Use hgrc.d found in directory with hg.exe
-        progrcd = os.path.join(os.path.dirname(filename), 'hgrc.d')
-        if os.path.isdir(progrcd):
-            for f, kind in osutil.listdir(progrcd):
-                if f.endswith('.rc'):
-                    rcpath.append(os.path.join(progrcd, f))
-            return rcpath
-        # else look for a system rcpath in the registry
-        value = util.lookupreg('SOFTWARE\\Mercurial', None,
-                               _winreg.HKEY_LOCAL_MACHINE)
-        if not isinstance(value, str) or not value:
-            return rcpath
-        value = util.localpath(value)
-        for p in value.split(os.pathsep):
-            if p.lower().endswith('mercurial.ini'):
-                rcpath.append(p)
-            elif os.path.isdir(p):
-                for f, kind in osutil.listdir(p):
-                    if f.endswith('.rc'):
-                        rcpath.append(os.path.join(p, f))
-        return rcpath
-
-    def userrcpath():
-        '''return os-specific hgrc search path to the user dir'''
-        home = os.path.expanduser('~')
-        path = [os.path.join(home, 'mercurial.ini'),
-                os.path.join(home, '.hgrc')]
-        userprofile = os.environ.get('USERPROFILE')
-        if userprofile:
-            path.append(os.path.join(userprofile, 'mercurial.ini'))
-            path.append(os.path.join(userprofile, '.hgrc'))
-        return path
-
 def revsingle(repo, revspec, default='.'):
     if not revspec:
         return repo[default]
@@ -737,30 +675,33 @@
     rejected = []
     m.bad = lambda x, y: rejected.append(x)
 
-    for abs in repo.walk(m):
-        target = repo.wjoin(abs)
-        good = True
-        try:
-            audit_path(abs)
-        except (OSError, util.Abort):
-            good = False
-        rel = m.rel(abs)
-        exact = m.exact(abs)
-        if good and abs not in repo.dirstate:
+    ctx = repo[None]
+    dirstate = repo.dirstate
+    walkresults = dirstate.walk(m, sorted(ctx.substate), True, False)
+    for abs, st in walkresults.iteritems():
+        dstate = dirstate[abs]
+        if dstate == '?' and audit_path.check(abs):
             unknown.append(abs)
-            if repo.ui.verbose or not exact:
-                repo.ui.status(_('adding %s\n') % ((pats and rel) or abs))
-        elif (repo.dirstate[abs] != 'r' and
-              (not good or not os.path.lexists(target) or
-               (os.path.isdir(target) and not os.path.islink(target)))):
+        elif dstate != 'r' and not st:
             deleted.append(abs)
-            if repo.ui.verbose or not exact:
-                repo.ui.status(_('removing %s\n') % ((pats and rel) or abs))
         # for finding renames
-        elif repo.dirstate[abs] == 'r':
+        elif dstate == 'r':
             removed.append(abs)
-        elif repo.dirstate[abs] == 'a':
+        elif dstate == 'a':
             added.append(abs)
+
+    unknownset = set(unknown)
+    toprint = unknownset.copy()
+    toprint.update(deleted)
+    for abs in sorted(toprint):
+        if repo.ui.verbose or not m.exact(abs):
+            rel = m.rel(abs)
+            if abs in unknownset:
+                status = _('adding %s\n') % ((pats and rel) or abs)
+            else:
+                status = _('removing %s\n') % ((pats and rel) or abs)
+            repo.ui.status(status)
+
     copies = {}
     if similarity > 0:
         for old, new, score in similar.findrenames(repo,
@@ -787,49 +728,6 @@
             return 1
     return 0
 
-def updatedir(ui, repo, patches, similarity=0):
-    '''Update dirstate after patch application according to metadata'''
-    if not patches:
-        return []
-    copies = []
-    removes = set()
-    cfiles = patches.keys()
-    cwd = repo.getcwd()
-    if cwd:
-        cfiles = [util.pathto(repo.root, cwd, f) for f in patches.keys()]
-    for f in patches:
-        gp = patches[f]
-        if not gp:
-            continue
-        if gp.op == 'RENAME':
-            copies.append((gp.oldpath, gp.path))
-            removes.add(gp.oldpath)
-        elif gp.op == 'COPY':
-            copies.append((gp.oldpath, gp.path))
-        elif gp.op == 'DELETE':
-            removes.add(gp.path)
-
-    wctx = repo[None]
-    for src, dst in copies:
-        dirstatecopy(ui, repo, wctx, src, dst, cwd=cwd)
-    if (not similarity) and removes:
-        wctx.remove(sorted(removes), True)
-
-    for f in patches:
-        gp = patches[f]
-        if gp and gp.mode:
-            islink, isexec = gp.mode
-            dst = repo.wjoin(gp.path)
-            # patch won't create empty files
-            if gp.op == 'ADD' and not os.path.lexists(dst):
-                flags = (isexec and 'x' or '') + (islink and 'l' or '')
-                repo.wwrite(gp.path, '', flags)
-            util.setflags(dst, islink, isexec)
-    addremove(repo, cfiles, similarity=similarity)
-    files = patches.keys()
-    files.extend([r for r in removes if r not in files])
-    return sorted(files)
-
 def dirstatecopy(ui, repo, wctx, src, dst, dryrun=False, cwd=None):
     """Update the dirstate to reflect the intent of copying src to dst. For
     different reasons it might not end with dst being marked as copied from src.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial/scmwindows.py	Wed Apr 03 13:03:50 2013 -0500
@@ -0,0 +1,46 @@
+import os
+import osutil
+import util
+import _winreg
+
+def systemrcpath():
+    '''return default os-specific hgrc search path'''
+    rcpath = []
+    filename = util.executablepath()
+    # Use mercurial.ini found in directory with hg.exe
+    progrc = os.path.join(os.path.dirname(filename), 'mercurial.ini')
+    if os.path.isfile(progrc):
+        rcpath.append(progrc)
+        return rcpath
+    # Use hgrc.d found in directory with hg.exe
+    progrcd = os.path.join(os.path.dirname(filename), 'hgrc.d')
+    if os.path.isdir(progrcd):
+        for f, kind in osutil.listdir(progrcd):
+            if f.endswith('.rc'):
+                rcpath.append(os.path.join(progrcd, f))
+        return rcpath
+    # else look for a system rcpath in the registry
+    value = util.lookupreg('SOFTWARE\\Mercurial', None,
+                           _winreg.HKEY_LOCAL_MACHINE)
+    if not isinstance(value, str) or not value:
+        return rcpath
+    value = util.localpath(value)
+    for p in value.split(os.pathsep):
+        if p.lower().endswith('mercurial.ini'):
+            rcpath.append(p)
+        elif os.path.isdir(p):
+            for f, kind in osutil.listdir(p):
+                if f.endswith('.rc'):
+                    rcpath.append(os.path.join(p, f))
+    return rcpath
+
+def userrcpath():
+    '''return os-specific hgrc search path to the user dir'''
+    home = os.path.expanduser('~')
+    path = [os.path.join(home, 'mercurial.ini'),
+            os.path.join(home, '.hgrc')]
+    userprofile = os.environ.get('USERPROFILE')
+    if userprofile:
+        path.append(os.path.join(userprofile, 'mercurial.ini'))
+        path.append(os.path.join(userprofile, '.hgrc'))
+    return path
--- a/mercurial/sshpeer.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/sshpeer.py	Wed Apr 03 13:03:50 2013 -0500
@@ -70,7 +70,10 @@
                 (_serverquote(remotecmd), _serverquote(self.path))))
         ui.note(_('running %s\n') % cmd)
         cmd = util.quotecommand(cmd)
-        self.pipeo, self.pipei, self.pipee = util.popen3(cmd)
+
+        # while self.subprocess isn't used, having it allows the subprocess to
+        # to clean up correctly later
+        self.pipeo, self.pipei, self.pipee, self.subprocess = util.popen4(cmd)
 
         # skip any noise generated by remote shell
         self._callstream("hello")
--- a/mercurial/subrepo.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/subrepo.py	Wed Apr 03 13:03:50 2013 -0500
@@ -547,9 +547,10 @@
             else:
                 self._repo.ui.status(_('pulling subrepo %s from %s\n')
                                      % (subrelpath(self), srcurl))
+                remotebookmarks = other.listkeys('bookmarks')
                 self._repo.pull(other)
-                bookmarks.updatefromremote(self._repo.ui, self._repo, other,
-                                           srcurl)
+                bookmarks.updatefromremote(self._repo.ui, self._repo,
+                                           remotebookmarks, srcurl)
 
     @annotatesubrepoerror
     def get(self, state, overwrite=False):
--- a/mercurial/templatefilters.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/templatefilters.py	Wed Apr 03 13:03:50 2013 -0500
@@ -392,6 +392,15 @@
     "xmlescape": xmlescape,
 }
 
+def websub(text, websubtable):
+    """:websub: Any text. Only applies to hgweb. Applies the regular
+    expression replacements defined in the websub section.
+    """
+    if websubtable:
+        for regexp, format in websubtable:
+            text = regexp.sub(format, text)
+    return text
+
 def fillfunc(context, mapping, args):
     if not (1 <= len(args) <= 2):
         raise error.ParseError(_("fill expects one or two arguments"))
--- a/mercurial/templatekw.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/templatekw.py	Wed Apr 03 13:03:50 2013 -0500
@@ -244,8 +244,8 @@
                 copies.append((fn, rename[0]))
 
     c = [{'name': x[0], 'source': x[1]} for x in copies]
-    return showlist('file_copy', c, plural='file_copies',
-                    element='file', **args)
+    f = _showlist('file_copy', c, plural='file_copies', **args)
+    return _hybrid(f, c)
 
 # showfilecopiesswitch() displays file copies only if copy records are
 # provided before calling the templater, usually with a --copies
@@ -256,8 +256,8 @@
     """
     copies = args['revcache'].get('copies') or []
     c = [{'name': x[0], 'source': x[1]} for x in copies]
-    return showlist('file_copy', c, plural='file_copies',
-                    element='file', **args)
+    f = _showlist('file_copy', c, plural='file_copies', **args)
+    return _hybrid(f, c)
 
 def showfiledels(**args):
     """:file_dels: List of strings. Files removed by this changeset."""
--- a/mercurial/templater.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/templater.py	Wed Apr 03 13:03:50 2013 -0500
@@ -9,6 +9,7 @@
 import sys, os, re
 import util, config, templatefilters, parser, error
 import types
+import minirst
 
 # template parsing
 
@@ -207,6 +208,19 @@
         f = context._filters[n]
         return (runfilter, (args[0][0], args[0][1], f))
 
+def get(context, mapping, args):
+    if len(args) != 2:
+        # i18n: "get" is a keyword
+        raise error.ParseError(_("get() expects two arguments"))
+
+    dictarg = args[0][0](context, mapping, args[0][1])
+    if not util.safehasattr(dictarg, 'get'):
+        # i18n: "get" is a keyword
+        raise error.ParseError(_("get() expects a dict as first argument"))
+
+    key = args[1][0](context, mapping, args[1][1])
+    yield dictarg.get(key)
+
 def join(context, mapping, args):
     if not (1 <= len(args) <= 2):
         # i18n: "join" is a keyword
@@ -274,6 +288,16 @@
     t = stringify(args[1][0](context, mapping, args[1][1]))
     yield runtemplate(context, mapping, compiletemplate(t, context))
 
+def rstdoc(context, mapping, args):
+    if len(args) != 2:
+        # i18n: "rstdoc" is a keyword
+        raise error.ParseError(_("rstdoc expects two arguments"))
+
+    text = stringify(args[0][0](context, mapping, args[0][1]))
+    style = stringify(args[1][0](context, mapping, args[1][1]))
+
+    return minirst.format(text, style=style)
+
 methods = {
     "string": lambda e, c: (runstring, e[1]),
     "symbol": lambda e, c: (runsymbol, e[1]),
@@ -285,11 +309,13 @@
     }
 
 funcs = {
+    "get": get,
     "if": if_,
     "ifeq": ifeq,
     "join": join,
+    "label": label,
+    "rstdoc": rstdoc,
     "sub": sub,
-    "label": label,
 }
 
 # template engine
--- a/mercurial/templates/coal/map	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/templates/coal/map	Wed Apr 03 13:03:50 2013 -0500
@@ -13,7 +13,14 @@
 help = ../paper/help.tmpl
 helptopics = ../paper/helptopics.tmpl
 
-helpentry = '<tr><td><a href="{url|urlescape}help/{topic|escape}{sessionvars%urlparameter}">{topic|escape}</a></td><td>{summary|escape}</td></tr>'
+helpentry = '
+  <tr><td>
+    <a href="{url|urlescape}help/{topic|escape}{sessionvars%urlparameter}">
+      {topic|escape}
+    </a>
+  </td><td>
+    {summary|escape}
+  </td></tr>'
 
 naventry = '<a href="{url|urlescape}log/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
 navshortentry = '<a href="{url|urlescape}shortlog/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
@@ -217,7 +224,7 @@
 index = ../paper/index.tmpl
 archiveentry = '
   <li>
-    <a href="{url|urlescape}archive/{node|short}{extension|urlescape}">{type|escape}</a>
+    <a href="{url|urlescape}archive/{node|short}{extension|urlescape}{ifeq(path,'/','',path|urlescape)}">{type|escape}</a>
   </li>'
 notfound = ../paper/notfound.tmpl
 error = ../paper/error.tmpl
--- a/mercurial/templates/gitweb/changelogentry.tmpl	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/templates/gitweb/changelogentry.tmpl	Wed Apr 03 13:03:50 2013 -0500
@@ -8,7 +8,7 @@
 <i>{author|obfuscate} [{date|rfc822date}] rev {rev}</i><br/>
 </div>
 <div class="log_body">
-{desc|strip|escape|addbreaks|nonempty}
+{desc|strip|escape|websub|addbreaks|nonempty}
 <br/>
 <br/>
 </div>
--- a/mercurial/templates/gitweb/changeset.tmpl	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/templates/gitweb/changeset.tmpl	Wed Apr 03 13:03:50 2013 -0500
@@ -41,7 +41,7 @@
 </table></div>
 
 <div class="page_body">
-{desc|strip|escape|addbreaks|nonempty}
+{desc|strip|escape|websub|addbreaks|nonempty}
 </div>
 <div class="list_head"></div>
 <div class="title_text">
--- a/mercurial/templates/gitweb/fileannotate.tmpl	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/templates/gitweb/fileannotate.tmpl	Wed Apr 03 13:03:50 2013 -0500
@@ -56,7 +56,7 @@
 </div>
 
 <div class="page_path">
-{desc|strip|escape|addbreaks|nonempty}
+{desc|strip|escape|websub|addbreaks|nonempty}
 </div>
 <div class="page_body">
 <table>
--- a/mercurial/templates/gitweb/filerevision.tmpl	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/templates/gitweb/filerevision.tmpl	Wed Apr 03 13:03:50 2013 -0500
@@ -56,7 +56,7 @@
 </div>
 
 <div class="page_path">
-{desc|strip|escape|addbreaks|nonempty}
+{desc|strip|escape|websub|addbreaks|nonempty}
 </div>
 
 <div class="page_body">
--- a/mercurial/templates/gitweb/help.tmpl	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/templates/gitweb/help.tmpl	Wed Apr 03 13:03:50 2013 -0500
@@ -27,8 +27,8 @@
 
 <div class="title">&nbsp;</div>
 
-<pre>
-{doc|escape}
-</pre>
+<div id="doc">
+{rstdoc(doc, "html")}
+</div>
 
 {footer}
--- a/mercurial/templates/gitweb/map	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/templates/gitweb/map	Wed Apr 03 13:03:50 2013 -0500
@@ -11,7 +11,14 @@
 help = help.tmpl
 helptopics = helptopics.tmpl
 
-helpentry = '<tr><td><a href="{url|urlescape}help/{topic|escape}{sessionvars%urlparameter}">{topic|escape}</a></td><td>{summary|escape}</td></tr>'
+helpentry = '
+  <tr><td>
+    <a href="{url|urlescape}help/{topic|escape}{sessionvars%urlparameter}">
+      {topic|escape}
+    </a>
+  </td><td>
+    {summary|escape}
+  </td></tr>'
 
 naventry = '<a href="{url|urlescape}log/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
 navshortentry = '<a href="{url|urlescape}shortlog/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
@@ -282,7 +289,7 @@
     <td class="link">
       <a href="{url|urlescape}file/{node|short}/{file|urlescape}{sessionvars%urlparameter}">file</a>&nbsp;|&nbsp;<a href="{url|urlescape}diff/{node|short}/{file|urlescape}{sessionvars%urlparameter}">diff</a>&nbsp;|&nbsp;<a href="{url|urlescape}annotate/{node|short}/{file|urlescape}{sessionvars%urlparameter}">annotate</a> {rename%filelogrename}</td>
     </tr>'
-archiveentry = ' | <a href="{url|urlescape}archive/{node|short}{extension}">{type|escape}</a> '
+archiveentry = ' | <a href="{url|urlescape}archive/{node|short}{extension}{ifeq(path,'/','',path|urlescape)}">{type|escape}</a> '
 indexentry = '
   <tr class="parity{parity}">
     <td>
--- a/mercurial/templates/monoblue/changelogentry.tmpl	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/templates/monoblue/changelogentry.tmpl	Wed Apr 03 13:03:50 2013 -0500
@@ -2,5 +2,5 @@
 <ul class="changelog-entry">
     <li class="age">{date|rfc822date}</li>
     <li>by <span class="name">{author|obfuscate}</span> <span class="revdate">[{date|rfc822date}] rev {rev}</span></li>
-    <li class="description">{desc|strip|escape|addbreaks|nonempty}</li>
+    <li class="description">{desc|strip|escape|websub|addbreaks|nonempty}</li>
 </ul>
--- a/mercurial/templates/monoblue/changeset.tmpl	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/templates/monoblue/changeset.tmpl	Wed Apr 03 13:03:50 2013 -0500
@@ -52,7 +52,7 @@
         {child%changesetchild}
     </dl>
 
-    <p class="description">{desc|strip|escape|addbreaks|nonempty}</p>
+    <p class="description">{desc|strip|escape|websub|addbreaks|nonempty}</p>
 
     <table>
     {files}
--- a/mercurial/templates/monoblue/fileannotate.tmpl	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/templates/monoblue/fileannotate.tmpl	Wed Apr 03 13:03:50 2013 -0500
@@ -57,7 +57,7 @@
         <dd>{permissions|permissions}</dd>
     </dl>
 
-    <p class="description">{desc|strip|escape|addbreaks|nonempty}</p>
+    <p class="description">{desc|strip|escape|websub|addbreaks|nonempty}</p>
 
     <table class="annotated">
     {annotate%annotateline}
--- a/mercurial/templates/monoblue/filerevision.tmpl	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/templates/monoblue/filerevision.tmpl	Wed Apr 03 13:03:50 2013 -0500
@@ -57,7 +57,7 @@
         <dd>{permissions|permissions}</dd>
     </dl>
 
-    <p class="description">{desc|strip|escape|addbreaks|nonempty}</p>
+    <p class="description">{desc|strip|escape|websub|addbreaks|nonempty}</p>
 
     <div class="source">
     {text%fileline}
--- a/mercurial/templates/monoblue/help.tmpl	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/templates/monoblue/help.tmpl	Wed Apr 03 13:03:50 2013 -0500
@@ -31,8 +31,8 @@
     </div>
 
     <h2 class="no-link no-border">branches</h2>
-    <pre>
-    {doc|escape}
-    </pre>
+    <div id="doc">
+    {rstdoc(doc, "html")}
+    </div>
 
 {footer}
--- a/mercurial/templates/monoblue/map	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/templates/monoblue/map	Wed Apr 03 13:03:50 2013 -0500
@@ -11,7 +11,14 @@
 help = help.tmpl
 helptopics = helptopics.tmpl
 
-helpentry = '<tr><td><a href="{url|urlescape}help/{topic|escape}{sessionvars%urlparameter}">{topic|escape}</a></td><td>{summary|escape}</td></tr>'
+helpentry = '
+  <tr><td>
+    <a href="{url|urlescape}help/{topic|escape}{sessionvars%urlparameter}">
+      {topic|escape}
+    </a>
+  </td><td>
+    {summary|escape}
+  </td></tr>'
 
 naventry = '<a href="{url|urlescape}log/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
 navshortentry = '<a href="{url|urlescape}shortlog/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
@@ -238,7 +245,7 @@
       {rename%filelogrename}
     </td>
   </tr>'
-archiveentry = '<li><a href="{url|urlescape}archive/{node|short}{extension}">{type|escape}</a></li>'
+archiveentry = '<li><a href="{url|urlescape}archive/{node|short}{extension}{ifeq(path,'/','',path|urlescape)}">{type|escape}</a></li>'
 indexentry = '
   <tr class="parity{parity}">
     <td><a href="{url|urlescape}{sessionvars%urlparameter}">{name|escape}</a></td>
--- a/mercurial/templates/paper/changeset.tmpl	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/templates/paper/changeset.tmpl	Wed Apr 03 13:03:50 2013 -0500
@@ -40,7 +40,7 @@
 files, or words in the commit message</div>
 </form>
 
-<div class="description">{desc|strip|escape|nonempty}</div>
+<div class="description">{desc|strip|escape|websub|nonempty}</div>
 
 <table id="changesetEntry">
 <tr>
--- a/mercurial/templates/paper/fileannotate.tmpl	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/templates/paper/fileannotate.tmpl	Wed Apr 03 13:03:50 2013 -0500
@@ -46,7 +46,7 @@
 files, or words in the commit message</div>
 </form>
 
-<div class="description">{desc|strip|escape|nonempty}</div>
+<div class="description">{desc|strip|escape|websub|nonempty}</div>
 
 <table id="changesetEntry">
 <tr>
--- a/mercurial/templates/paper/filecomparison.tmpl	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/templates/paper/filecomparison.tmpl	Wed Apr 03 13:03:50 2013 -0500
@@ -45,7 +45,7 @@
 files, or words in the commit message</div>
 </form>
 
-<div class="description">{desc|strip|escape|nonempty}</div>
+<div class="description">{desc|strip|escape|websub|nonempty}</div>
 
 <table id="changesetEntry">
 <tr>
--- a/mercurial/templates/paper/filediff.tmpl	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/templates/paper/filediff.tmpl	Wed Apr 03 13:03:50 2013 -0500
@@ -45,7 +45,7 @@
 files, or words in the commit message</div>
 </form>
 
-<div class="description">{desc|strip|escape|nonempty}</div>
+<div class="description">{desc|strip|escape|websub|nonempty}</div>
 
 <table id="changesetEntry">
 <tr>
--- a/mercurial/templates/paper/filerevision.tmpl	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/templates/paper/filerevision.tmpl	Wed Apr 03 13:03:50 2013 -0500
@@ -44,7 +44,7 @@
 files, or words in the commit message</div>
 </form>
 
-<div class="description">{desc|strip|escape|nonempty}</div>
+<div class="description">{desc|strip|escape|websub|nonempty}</div>
 
 <table id="changesetEntry">
 <tr>
--- a/mercurial/templates/paper/help.tmpl	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/templates/paper/help.tmpl	Wed Apr 03 13:03:50 2013 -0500
@@ -31,9 +31,9 @@
 <div id="hint">find changesets by author, revision,
 files, or words in the commit message</div>
 </form>
-<pre>
-{doc|escape}
-</pre>
+<div id="doc">
+{rstdoc(doc, "html")}
+</div>
 </div>
 </div>
 
--- a/mercurial/templates/paper/map	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/templates/paper/map	Wed Apr 03 13:03:50 2013 -0500
@@ -12,7 +12,14 @@
 help = help.tmpl
 helptopics = helptopics.tmpl
 
-helpentry = '<tr><td><a href="{url|urlescape}help/{topic|escape}{sessionvars%urlparameter}">{topic|escape}</a></td><td>{summary|escape}</td></tr>'
+helpentry = '
+  <tr><td>
+    <a href="{url|urlescape}help/{topic|escape}{sessionvars%urlparameter}">
+      {topic|escape}
+    </a>
+  </td><td>
+    {summary|escape}
+  </td></tr>'
 
 naventry = '<a href="{url|urlescape}log/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
 navshortentry = '<a href="{url|urlescape}shortlog/{node|short}{sessionvars%urlparameter}">{label|escape}</a> '
@@ -225,7 +232,7 @@
 index = index.tmpl
 archiveentry = '
   <li>
-    <a href="{url|urlescape}archive/{node|short}{extension|urlescape}">{type|escape}</a>
+    <a href="{url|urlescape}archive/{node|short}{extension|urlescape}{ifeq(path,'/','',path|urlescape)}">{type|escape}</a>
   </li>'
 notfound = notfound.tmpl
 error = error.tmpl
--- a/mercurial/templates/spartan/changeset.tmpl	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/templates/spartan/changeset.tmpl	Wed Apr 03 13:03:50 2013 -0500
@@ -39,7 +39,7 @@
 </tr>
 <tr>
  <th class="description">description:</th>
- <td class="description">{desc|strip|escape|addbreaks|nonempty}</td>
+ <td class="description">{desc|strip|escape|websub|addbreaks|nonempty}</td>
 </tr>
 </table>
 
--- a/mercurial/templates/spartan/fileannotate.tmpl	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/templates/spartan/fileannotate.tmpl	Wed Apr 03 13:03:50 2013 -0500
@@ -38,7 +38,7 @@
 </tr>
 <tr>
   <td class="metatag">description:</td>
-  <td>{desc|strip|escape|addbreaks|nonempty}</td>
+  <td>{desc|strip|escape|websub|addbreaks|nonempty}</td>
 </tr>
 </table>
 
--- a/mercurial/templates/spartan/filerevision.tmpl	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/templates/spartan/filerevision.tmpl	Wed Apr 03 13:03:50 2013 -0500
@@ -36,7 +36,7 @@
  <td>{permissions|permissions}</td></tr>
 <tr>
   <td class="metatag">description:</td>
-  <td>{desc|strip|escape|addbreaks|nonempty}</td>
+  <td>{desc|strip|escape|websub|addbreaks|nonempty}</td>
 </tr>
 </table>
 
--- a/mercurial/templates/static/style-coal.css	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/templates/static/style-coal.css	Wed Apr 03 13:03:50 2013 -0500
@@ -191,7 +191,7 @@
 }
 .bigtable tr { border: none; }
 .bigtable .age { width: 6em; }
-.bigtable .author { width: 12em; }
+.bigtable .author { width: 15em; }
 .bigtable .description { }
 .bigtable .description .base { font-size: 70%; float: right; line-height: 1.66; }
 .bigtable .node { width: 5em; font-family: monospace;}
--- a/mercurial/templates/static/style-paper.css	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/templates/static/style-paper.css	Wed Apr 03 13:03:50 2013 -0500
@@ -188,7 +188,7 @@
 }
 .bigtable tr { border: none; }
 .bigtable .age { width: 7em; }
-.bigtable .author { width: 12em; }
+.bigtable .author { width: 15em; }
 .bigtable .description { }
 .bigtable .description .base { font-size: 70%; float: right; line-height: 1.66; }
 .bigtable .node { width: 5em; font-family: monospace;}
--- a/mercurial/ui.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/ui.py	Wed Apr 03 13:03:50 2013 -0500
@@ -739,7 +739,7 @@
         else:
             self.debug('%s:%s %s%s\n' % (topic, item, pos, unit))
 
-    def log(self, service, message):
+    def log(self, service, *msg, **opts):
         '''hook for logging facility extensions
 
         service should be a readily-identifiable subsystem, which will
--- a/mercurial/util.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/mercurial/util.py	Wed Apr 03 13:03:50 2013 -0500
@@ -129,13 +129,17 @@
     return p.stdin, p.stdout
 
 def popen3(cmd, env=None, newlines=False):
+    stdin, stdout, stderr, p = popen4(cmd, env, newlines)
+    return stdin, stdout, stderr
+
+def popen4(cmd, env=None, newlines=False):
     p = subprocess.Popen(cmd, shell=True, bufsize=-1,
                          close_fds=closefds,
                          stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                          stderr=subprocess.PIPE,
                          universal_newlines=newlines,
                          env=env)
-    return p.stdin, p.stdout, p.stderr
+    return p.stdin, p.stdout, p.stderr, p
 
 def version():
     """Return version information if available."""
@@ -211,6 +215,31 @@
                     del self[i]
                     break
 
+class lrucachedict(object):
+    '''cache most recent gets from or sets to this dictionary'''
+    def __init__(self, maxsize):
+        self._cache = {}
+        self._maxsize = maxsize
+        self._order = deque()
+
+    def __getitem__(self, key):
+        value = self._cache[key]
+        self._order.remove(key)
+        self._order.append(key)
+        return value
+
+    def __setitem__(self, key, value):
+        if key not in self._cache:
+            if len(self._cache) >= self._maxsize:
+                del self._cache[self._order.popleft()]
+        else:
+            self._order.remove(key)
+        self._cache[key] = value
+        self._order.append(key)
+
+    def __contains__(self, key):
+        return key in self._cache
+
 def lrucachefunc(func):
     '''cache most recent results of function calls'''
     cache = {}
@@ -633,10 +662,12 @@
 except ImportError:
     _re2 = False
 
-def compilere(pat):
+def compilere(pat, flags=0):
     '''Compile a regular expression, using re2 if possible
 
-    For best performance, use only re2-compatible regexp features.'''
+    For best performance, use only re2-compatible regexp features. The
+    only flags from the re module that are re2-compatible are
+    IGNORECASE and MULTILINE.'''
     global _re2
     if _re2 is None:
         try:
@@ -644,12 +675,16 @@
             _re2 = True
         except ImportError:
             _re2 = False
-    if _re2:
+    if _re2 and (flags & ~(re.IGNORECASE | re.MULTILINE)) == 0:
+        if flags & re.IGNORECASE:
+            pat = '(?i)' + pat
+        if flags & re.MULTILINE:
+            pat = '(?m)' + pat
         try:
             return re2.compile(pat)
         except re2.error:
             pass
-    return re.compile(pat)
+    return re.compile(pat, flags)
 
 _fspathcache = {}
 def fspath(name, root):
@@ -855,6 +890,23 @@
     if mode is not None:
         os.chmod(name, mode)
 
+def ensuredirs(name, mode=None):
+    """race-safe recursive directory creation"""
+    if os.path.isdir(name):
+        return
+    parent = os.path.dirname(os.path.abspath(name))
+    if parent != name:
+        ensuredirs(parent, mode)
+    try:
+        os.mkdir(name)
+    except OSError, err:
+        if err.errno == errno.EEXIST and os.path.isdir(name):
+            # someone else seems to have won a directory creation race
+            return
+        raise
+    if mode is not None:
+        os.chmod(name, mode)
+
 def readfile(path):
     fp = open(path, 'rb')
     try:
@@ -1027,6 +1079,20 @@
 
     The date may be a "unixtime offset" string or in one of the specified
     formats. If the date already is a (unixtime, offset) tuple, it is returned.
+
+    >>> parsedate(' today ') == parsedate(\
+                                  datetime.date.today().strftime('%b %d'))
+    True
+    >>> parsedate( 'yesterday ') == parsedate((datetime.date.today() -\
+                                               datetime.timedelta(days=1)\
+                                              ).strftime('%b %d'))
+    True
+    >>> now, tz = makedate()
+    >>> strnow, strtz = parsedate('now')
+    >>> (strnow - now) < 1
+    True
+    >>> tz == strtz
+    True
     """
     if not date:
         return 0, 0
@@ -1035,6 +1101,15 @@
     if not formats:
         formats = defaultdateformats
     date = date.strip()
+
+    if date == _('now'):
+        return makedate()
+    if date == _('today'):
+        date = datetime.date.today().strftime('%b %d')
+    elif date == _('yesterday'):
+        date = (datetime.date.today() -
+                datetime.timedelta(days=1)).strftime('%b %d')
+
     try:
         when, offset = map(int, date.split(' '))
     except ValueError:
@@ -1203,7 +1278,18 @@
     except (UnicodeDecodeError, UnicodeEncodeError):
         return _ellipsis(text, maxlength)[0]
 
-_byteunits = (
+def unitcountfn(*unittable):
+    '''return a function that renders a readable count of some quantity'''
+
+    def go(count):
+        for multiplier, divisor, format in unittable:
+            if count >= divisor * multiplier:
+                return format % (count / float(divisor))
+        return unittable[-1][2] % count
+
+    return go
+
+bytecount = unitcountfn(
     (100, 1 << 30, _('%.0f GB')),
     (10, 1 << 30, _('%.1f GB')),
     (1, 1 << 30, _('%.2f GB')),
@@ -1216,14 +1302,6 @@
     (1, 1, _('%.0f bytes')),
     )
 
-def bytecount(nbytes):
-    '''return byte count formatted as readable string, with units'''
-
-    for multiplier, divisor, format in _byteunits:
-        if nbytes >= divisor * multiplier:
-            return format % (nbytes / float(divisor))
-    return _byteunits[-1][2] % nbytes
-
 def uirepr(s):
     # Avoid double backslash in Windows path repr()
     return repr(s).replace('\\\\', '\\')
@@ -1804,3 +1882,46 @@
         return fd.isatty()
     except AttributeError:
         return False
+
+timecount = unitcountfn(
+    (1, 1e3, _('%.0f s')),
+    (100, 1, _('%.1f s')),
+    (10, 1, _('%.2f s')),
+    (1, 1, _('%.3f s')),
+    (100, 0.001, _('%.1f ms')),
+    (10, 0.001, _('%.2f ms')),
+    (1, 0.001, _('%.3f ms')),
+    (100, 0.000001, _('%.1f us')),
+    (10, 0.000001, _('%.2f us')),
+    (1, 0.000001, _('%.3f us')),
+    (100, 0.000000001, _('%.1f ns')),
+    (10, 0.000000001, _('%.2f ns')),
+    (1, 0.000000001, _('%.3f ns')),
+    )
+
+_timenesting = [0]
+
+def timed(func):
+    '''Report the execution time of a function call to stderr.
+
+    During development, use as a decorator when you need to measure
+    the cost of a function, e.g. as follows:
+
+    @util.timed
+    def foo(a, b, c):
+        pass
+    '''
+
+    def wrapper(*args, **kwargs):
+        start = time.time()
+        indent = 2
+        _timenesting[0] += indent
+        try:
+            return func(*args, **kwargs)
+        finally:
+            elapsed = time.time() - start
+            _timenesting[0] -= indent
+            sys.stderr.write('%s%s: %s\n' %
+                             (' ' * _timenesting[0], func.__name__,
+                              timecount(elapsed)))
+    return wrapper
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial/worker.py	Wed Apr 03 13:03:50 2013 -0500
@@ -0,0 +1,155 @@
+# worker.py - master-slave parallelism support
+#
+# Copyright 2013 Facebook, Inc.
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+
+from i18n import _
+import os, signal, sys, threading, util
+
+def countcpus():
+    '''try to count the number of CPUs on the system'''
+
+    # posix
+    try:
+        n = int(os.sysconf('SC_NPROCESSORS_ONLN'))
+        if n > 0:
+            return n
+    except (AttributeError, ValueError):
+        pass
+
+    # windows
+    try:
+        n = int(os.environ['NUMBER_OF_PROCESSORS'])
+        if n > 0:
+            return n
+    except (KeyError, ValueError):
+        pass
+
+    return 1
+
+def _numworkers(ui):
+    s = ui.config('worker', 'numcpus')
+    if s:
+        try:
+            n = int(s)
+            if n >= 1:
+                return n
+        except ValueError:
+            raise util.Abort(_('number of cpus must be an integer'))
+    return min(max(countcpus(), 4), 32)
+
+if os.name == 'posix':
+    _startupcost = 0.01
+else:
+    _startupcost = 1e30
+
+def worthwhile(ui, costperop, nops):
+    '''try to determine whether the benefit of multiple processes can
+    outweigh the cost of starting them'''
+    linear = costperop * nops
+    workers = _numworkers(ui)
+    benefit = linear - (_startupcost * workers + linear / workers)
+    return benefit >= 0.15
+
+def worker(ui, costperarg, func, staticargs, args):
+    '''run a function, possibly in parallel in multiple worker
+    processes.
+
+    returns a progress iterator
+
+    costperarg - cost of a single task
+
+    func - function to run
+
+    staticargs - arguments to pass to every invocation of the function
+
+    args - arguments to split into chunks, to pass to individual
+    workers
+    '''
+    if worthwhile(ui, costperarg, len(args)):
+        return _platformworker(ui, func, staticargs, args)
+    return func(*staticargs + (args,))
+
+def _posixworker(ui, func, staticargs, args):
+    rfd, wfd = os.pipe()
+    workers = _numworkers(ui)
+    oldhandler = signal.getsignal(signal.SIGINT)
+    signal.signal(signal.SIGINT, signal.SIG_IGN)
+    pids, problem = [], [0]
+    for pargs in partition(args, workers):
+        pid = os.fork()
+        if pid == 0:
+            signal.signal(signal.SIGINT, oldhandler)
+            try:
+                os.close(rfd)
+                for i, item in func(*(staticargs + (pargs,))):
+                    os.write(wfd, '%d %s\n' % (i, item))
+                os._exit(0)
+            except KeyboardInterrupt:
+                os._exit(255)
+        pids.append(pid)
+    pids.reverse()
+    os.close(wfd)
+    fp = os.fdopen(rfd, 'rb', 0)
+    def killworkers():
+        # if one worker bails, there's no good reason to wait for the rest
+        for p in pids:
+            try:
+                os.kill(p, signal.SIGTERM)
+            except OSError, err:
+                if err.errno != errno.ESRCH:
+                    raise
+    def waitforworkers():
+        for _ in pids:
+            st = _exitstatus(os.wait()[1])
+            if st and not problem:
+                problem[0] = st
+                killworkers()
+    t = threading.Thread(target=waitforworkers)
+    t.start()
+    def cleanup():
+        signal.signal(signal.SIGINT, oldhandler)
+        t.join()
+        status = problem[0]
+        if status:
+            if status < 0:
+                os.kill(os.getpid(), -status)
+            sys.exit(status)
+    try:
+        for line in fp:
+            l = line.split(' ', 1)
+            yield int(l[0]), l[1][:-1]
+    except: # re-raises
+        killworkers()
+        cleanup()
+        raise
+    cleanup()
+
+def _posixexitstatus(code):
+    '''convert a posix exit status into the same form returned by
+    os.spawnv
+
+    returns None if the process was stopped instead of exiting'''
+    if os.WIFEXITED(code):
+        return os.WEXITSTATUS(code)
+    elif os.WIFSIGNALED(code):
+        return -os.WTERMSIG(code)
+
+if os.name != 'nt':
+    _platformworker = _posixworker
+    _exitstatus = _posixexitstatus
+
+def partition(lst, nslices):
+    '''partition a list into N slices of equal size'''
+    n = len(lst)
+    chunk, slop = n / nslices, n % nslices
+    end = 0
+    for i in xrange(nslices):
+        start = end
+        end = start + chunk
+        if slop:
+            end += 1
+            slop -= 1
+        yield lst[start:end]
--- a/tests/run-tests.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/run-tests.py	Wed Apr 03 13:03:50 2013 -0500
@@ -52,6 +52,7 @@
 import sys
 import tempfile
 import time
+import random
 import re
 import threading
 import killdaemons as killmod
@@ -540,6 +541,13 @@
 def globmatch(el, l):
     # The only supported special characters are * and ? plus / which also
     # matches \ on windows. Escaping of these caracters is supported.
+    if el + '\n' == l:
+        if os.name == 'nt':
+            # matching on "/" is not needed for this line
+            iolock.acquire()
+            print "\nInfo, unnecessary glob: %s (glob)" % el
+            iolock.release()
+        return True
     i, n = 0, len(el)
     res = ''
     while i < n:
@@ -622,6 +630,7 @@
         script.append('set -x\n')
     if os.getenv('MSYSTEM'):
         script.append('alias pwd="pwd -W"\n')
+    n = 0
     for n, l in enumerate(t):
         if not l.endswith('\n'):
             l += '\n'
@@ -1235,8 +1244,7 @@
         checktools()
 
         if len(args) == 0:
-            args = os.listdir(".")
-        args.sort()
+            args = sorted(os.listdir("."))
 
     tests = args
 
@@ -1252,7 +1260,11 @@
     os.environ['no_proxy'] = ''
     os.environ['NO_PROXY'] = ''
     os.environ['TERM'] = 'xterm'
-    os.environ['PYTHONHASHSEED'] = os.environ.get('PYTHONHASHSEED', 'random')
+    if 'PYTHONHASHSEED' not in os.environ:
+        # use a random python hash seed all the time
+        # we do the randomness ourself to know what seed is used
+        os.environ['PYTHONHASHSEED'] = str(random.getrandbits(32))
+        print 'python hash seed:', os.environ['PYTHONHASHSEED']
 
     # unset env related to hooks
     for k in os.environ.keys():
@@ -1264,6 +1276,9 @@
         # can't remove on solaris
         os.environ['HG'] = ''
         del os.environ['HG']
+    if 'HGPROF' in os.environ:
+        os.environ['HGPROF'] = ''
+        del os.environ['HGPROF']
 
     global TESTDIR, HGTMP, INST, BINDIR, PYTHONDIR, COVERAGE_FILE
     TESTDIR = os.environ["TESTDIR"] = os.getcwd()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/silenttestrunner.py	Wed Apr 03 13:03:50 2013 -0500
@@ -0,0 +1,18 @@
+import unittest, sys
+
+def main(modulename):
+    '''run the tests found in module, printing nothing when all tests pass'''
+    module = sys.modules[modulename]
+    suite = unittest.defaultTestLoader.loadTestsFromModule(module)
+    results = unittest.TestResult()
+    suite.run(results)
+    if results.errors or results.failures:
+        for tc, exc in results.errors:
+            print 'ERROR:', tc
+            print
+            sys.stdout.write(exc)
+        for tc, exc in results.failures:
+            print 'FAIL:', tc
+            print
+            sys.stdout.write(exc)
+        sys.exit(1)
--- a/tests/test-alias.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-alias.t	Wed Apr 03 13:03:50 2013 -0500
@@ -17,6 +17,7 @@
   > no-R = status -R elsewhere
   > no--repo = status --repo elsewhere
   > no--repository = status --repository elsewhere
+  > no--config = status --config a.config=1
   > mylog = log
   > lognull = log -r null
   > shortlog = log --template '{rev} {node|short} | {date|isodate}\n'
@@ -106,6 +107,8 @@
   error in definition for alias 'no--repository': --repository may only be given on the command line
   $ hg help no--repository
   error in definition for alias 'no--repository': --repository may only be given on the command line
+  $ hg no--config
+  error in definition for alias 'no--config': --config may only be given on the command line
 
 optional repository
 
@@ -181,6 +184,7 @@
   # HG changeset patch
   # User test
   # Date 0 0
+  #      Thu Jan 01 00:00:00 1970 +0000
   # Node ID e63c23eaa88ae77967edcf4ea194d31167c478b0
   # Parent  0000000000000000000000000000000000000000
   foo
@@ -224,7 +228,7 @@
   2
 
   $ hg tglog
-  @  1:7e7f92de180e: 'bar'
+  @  1:042423737847: 'bar'
   |
   o  0:e63c23eaa88a: 'foo'
   
@@ -237,15 +241,15 @@
       idalias idaliaslong idaliasshell identify import incoming init
   [255]
   $ hg id
-  7e7f92de180e tip
+  042423737847 tip
   $ hg ida
   hg: command 'ida' is ambiguous:
       idalias idaliaslong idaliasshell
   [255]
   $ hg idalias
-  7e7f92de180e tip
+  042423737847 tip
   $ hg idaliasl
-  7e7f92de180e tip
+  042423737847 tip
   $ hg idaliass
   test
   $ hg parentsshell
--- a/tests/test-archive.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-archive.t	Wed Apr 03 13:03:50 2013 -0500
@@ -69,10 +69,18 @@
   >     msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
   > except ImportError:
   >     pass
-  > node, archive = sys.argv[1:]
-  > f = urllib2.urlopen('http://127.0.0.1:%s/?cmd=archive;node=%s;type=%s'
-  >                     % (os.environ['HGPORT'], node, archive))
-  > sys.stdout.write(f.read())
+  > if len(sys.argv) <= 3:
+  >     node, archive = sys.argv[1:]
+  >     requeststr = 'cmd=archive;node=%s;type=%s' % (node, archive)
+  > else:
+  >     node, archive, file = sys.argv[1:]
+  >     requeststr = 'cmd=archive;node=%s;type=%s;file=%s' % (node, archive, file)
+  > try:
+  >     f = urllib2.urlopen('http://127.0.0.1:%s/?%s'
+  >                     % (os.environ['HGPORT'], requeststr))
+  >     sys.stdout.write(f.read())
+  > except urllib2.HTTPError, e:
+  >     sys.stderr.write(str(e) + '\n')
   > EOF
   $ python getarchive.py "$TIP" gz | gunzip | tar tf - 2>/dev/null
   test-archive-2c0277f05ed4/.hg_archival.txt
@@ -93,6 +101,18 @@
       testing: test-archive-2c0277f05ed4/foo   OK
   No errors detected in compressed data of archive.zip.
 
+test that we can download single directories and files
+
+  $ python getarchive.py "$TIP" gz baz | gunzip | tar tf - 2>/dev/null
+  test-archive-2c0277f05ed4/baz/bletch
+  $ python getarchive.py "$TIP" gz foo | gunzip | tar tf - 2>/dev/null
+  test-archive-2c0277f05ed4/foo
+
+test that we reject unsafe patterns
+
+  $ python getarchive.py "$TIP" gz relre:baz
+  HTTP Error 403: Archive pattern not allowed: relre:baz
+
   $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
 
   $ hg archive -t tar test.tar
--- a/tests/test-atomictempfile.py	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-atomictempfile.py	Wed Apr 03 13:03:50 2013 -0500
@@ -1,48 +1,42 @@
 import os
 import glob
+import unittest
+import silenttestrunner
+
 from mercurial.util import atomictempfile
 
-# basic usage
-def test1_simple():
-    if os.path.exists('foo'):
-        os.remove('foo')
-    file = atomictempfile('foo')
-    (dir, basename) = os.path.split(file._tempname)
-    assert not os.path.isfile('foo')
-    assert basename in glob.glob('.foo-*')
+class testatomictempfile(unittest.TestCase):
+    def test1_simple(self):
+        if os.path.exists('foo'):
+            os.remove('foo')
+        file = atomictempfile('foo')
+        (dir, basename) = os.path.split(file._tempname)
+        self.assertFalse(os.path.isfile('foo'))
+        self.assertTrue(basename in glob.glob('.foo-*'))
 
-    file.write('argh\n')
-    file.close()
+        file.write('argh\n')
+        file.close()
 
-    assert os.path.isfile('foo')
-    assert basename not in glob.glob('.foo-*')
-    print 'OK'
+        self.assertTrue(os.path.isfile('foo'))
+        self.assertTrue(basename not in glob.glob('.foo-*'))
 
-# discard() removes the temp file without making the write permanent
-def test2_discard():
-    if os.path.exists('foo'):
-        os.remove('foo')
-    file = atomictempfile('foo')
-    (dir, basename) = os.path.split(file._tempname)
-
-    file.write('yo\n')
-    file.discard()
+    # discard() removes the temp file without making the write permanent
+    def test2_discard(self):
+        if os.path.exists('foo'):
+            os.remove('foo')
+        file = atomictempfile('foo')
+        (dir, basename) = os.path.split(file._tempname)
 
-    assert not os.path.isfile('foo')
-    assert basename not in os.listdir('.')
-    print 'OK'
+        file.write('yo\n')
+        file.discard()
 
-# if a programmer screws up and passes bad args to atomictempfile, they
-# get a plain ordinary TypeError, not infinite recursion
-def test3_oops():
-    try:
-        file = atomictempfile()
-    except TypeError:
-        print "OK"
-    else:
-        print "expected TypeError"
+        self.assertFalse(os.path.isfile('foo'))
+        self.assertTrue(basename not in os.listdir('.'))
+
+    # if a programmer screws up and passes bad args to atomictempfile, they
+    # get a plain ordinary TypeError, not infinite recursion
+    def test3_oops(self):
+        self.assertRaises(TypeError, atomictempfile)
 
 if __name__ == '__main__':
-    test1_simple()
-    test2_discard()
-    test3_oops()
+    silenttestrunner.main(__name__)
--- a/tests/test-atomictempfile.py.out	Tue Apr 02 16:03:10 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-OK
-OK
-OK
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-blackbox.t	Wed Apr 03 13:03:50 2013 -0500
@@ -0,0 +1,135 @@
+setup
+  $ cat > mock.py <<EOF
+  > from mercurial import util
+  > 
+  > def makedate():
+  >     return 0, 0
+  > def getuser():
+  >     return 'bob'
+  > # mock the date and user apis so the output is always the same
+  > def uisetup(ui):
+  >     util.makedate = makedate
+  >     util.getuser = getuser
+  > EOF
+  $ cat >> $HGRCPATH <<EOF
+  > [extensions]
+  > blackbox=
+  > mock=`pwd`/mock.py
+  > mq=
+  > EOF
+  $ hg init blackboxtest
+  $ cd blackboxtest
+
+command, exit codes, and duration
+
+  $ echo a > a
+  $ hg add a
+  $ hg blackbox
+  1970/01/01 00:00:00 bob> add a
+  1970/01/01 00:00:00 bob> add exited 0 after * seconds (glob)
+
+incoming change tracking
+
+create two heads to verify that we only see one change in the log later
+  $ hg commit -ma
+  $ hg up null
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ echo b > b
+  $ hg commit -Amb
+  adding b
+  created new head
+
+clone, commit, pull
+  $ hg clone . ../blackboxtest2
+  updating to branch default
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ echo c > c
+  $ hg commit -Amc
+  adding c
+  $ cd ../blackboxtest2
+  $ hg pull
+  pulling from $TESTTMP/blackboxtest (glob)
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  (run 'hg update' to get a working copy)
+  $ hg blackbox -l 3
+  1970/01/01 00:00:00 bob> pull
+  1970/01/01 00:00:00 bob> 1 incoming changes - new heads: d02f48003e62
+  1970/01/01 00:00:00 bob> pull exited None after * seconds (glob)
+
+we must not cause a failure if we cannot write to the log
+
+  $ hg rollback
+  repository tip rolled back to revision 1 (undo pull)
+  $ chmod 000 .hg/blackbox.log
+  $ hg --debug incoming
+  warning: cannot write to blackbox.log: Permission denied
+  comparing with $TESTTMP/blackboxtest (glob)
+  query 1; heads
+  searching for changes
+  all local heads known remotely
+  changeset:   2:d02f48003e62c24e2659d97d30f2a83abe5d5d51
+  tag:         tip
+  phase:       draft
+  parent:      1:6563da9dcf87b1949716e38ff3e3dfaa3198eb06
+  parent:      -1:0000000000000000000000000000000000000000
+  manifest:    2:ab9d46b053ebf45b7996f2922b9893ff4b63d892
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  files+:      c
+  extra:       branch=default
+  description:
+  c
+  
+  
+  $ hg pull
+  pulling from $TESTTMP/blackboxtest (glob)
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  (run 'hg update' to get a working copy)
+
+a failure reading from the log is fine
+
+  $ hg blackbox -l 3
+  abort: Permission denied: $TESTTMP/blackboxtest2/.hg/blackbox.log
+  [255]
+
+  $ chmod 600 .hg/blackbox.log
+
+backup bundles get logged
+
+  $ touch d
+  $ hg commit -Amd
+  adding d
+  created new head
+  $ hg strip tip
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  saved backup bundle to $TESTTMP/blackboxtest2/.hg/strip-backup/*-backup.hg (glob)
+  $ hg blackbox -l 3
+  1970/01/01 00:00:00 bob> strip tip
+  1970/01/01 00:00:00 bob> saved backup bundle to $TESTTMP/blackboxtest2/.hg/strip-backup/*-backup.hg (glob)
+  1970/01/01 00:00:00 bob> strip exited 0 after * seconds (glob)
+
+extension and python hooks - use the eol extension for a pythonhook
+
+  $ echo '[extensions]' >> .hg/hgrc
+  $ echo 'eol=' >> .hg/hgrc
+  $ echo '[hooks]' >> .hg/hgrc
+  $ echo 'update = echo hooked' >> .hg/hgrc
+  $ hg update
+  hooked
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg blackbox -l 4
+  1970/01/01 00:00:00 bob> update
+  1970/01/01 00:00:00 bob> pythonhook-preupdate: hgext.eol.preupdate finished in * seconds (glob)
+  1970/01/01 00:00:00 bob> exthook-update: echo hooked finished in * seconds (glob)
+  1970/01/01 00:00:00 bob> update exited False after * seconds (glob)
+
+cleanup
+  $ cd ..
--- a/tests/test-bookmarks-pushpull.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-bookmarks-pushpull.t	Wed Apr 03 13:03:50 2013 -0500
@@ -204,6 +204,39 @@
      Y                         3:f6fc62dde3c0
      Z                         1:0d2164f0ce0d
 
+update a bookmark in the middle of a client pulling changes
+
+  $ cd ..
+  $ hg clone -q a pull-race
+  $ hg clone -q pull-race pull-race2
+  $ cd pull-race
+  $ hg up -q Y
+  $ echo c4 > f2
+  $ hg ci -Am4
+  $ echo c5 > f3
+  $ cat <<EOF > .hg/hgrc
+  > [hooks]
+  > outgoing.makecommit = hg ci -Am5; echo committed in pull-race
+  > EOF
+  $ cd ../pull-race2
+  $ hg pull
+  pulling from $TESTTMP/pull-race (glob)
+  searching for changes
+  adding changesets
+  adding f3
+  committed in pull-race
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  updating bookmark Y
+  (run 'hg update' to get a working copy)
+  $ hg book
+   * @                         1:0d2164f0ce0d
+     X                         1:0d2164f0ce0d
+     Y                         4:b0a5eff05604
+     Z                         1:0d2164f0ce0d
+  $ cd ../b
+
 diverging a remote bookmark fails
 
   $ hg up -q 4e3505fd9583
--- a/tests/test-bookmarks.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-bookmarks.t	Wed Apr 03 13:03:50 2013 -0500
@@ -239,8 +239,8 @@
 
 bookmark with existing name
 
-  $ hg bookmark Z
-  abort: bookmark 'Z' already exists (use -f to force)
+  $ hg bookmark X2
+  abort: bookmark 'X2' already exists (use -f to force)
   [255]
 
   $ hg bookmark -m Y Z
@@ -257,6 +257,12 @@
   abort: a bookmark cannot have the name of an existing branch
   [255]
 
+bookmark with integer name
+
+  $ hg bookmark 10
+  abort: a bookmark cannot have an integer as its name
+  [255]
+
 incompatible options
 
   $ hg bookmark -m Y -d Z
@@ -273,7 +279,21 @@
 
 force bookmark with existing name
 
-  $ hg bookmark -f Z
+  $ hg bookmark -f X2
+
+force bookmark back to where it was, should deactivate it
+
+  $ hg bookmark -fr1 X2
+  $ hg bookmarks
+     X2                        1:925d80f479bb
+     Y                         2:db815d6d32e6
+     Z                         0:f7b1eb17ad24
+     x  y                      2:db815d6d32e6
+
+forward bookmark to descendant without --force
+
+  $ hg bookmark Z
+  moving bookmark 'Z' forward from f7b1eb17ad24
 
 list bookmarks
 
@@ -348,9 +368,14 @@
   $ hg bookmarks
      X2                        1:925d80f479bb
      Y                         2:db815d6d32e6
-   * Z                         2:db815d6d32e6
+     Z                         2:db815d6d32e6
      x  y                      2:db815d6d32e6
 
+activate bookmark on working dir parent without --force
+
+  $ hg bookmark --inactive Z
+  $ hg bookmark Z
+
 test clone
 
   $ hg bookmark -r 2 -i @
@@ -461,6 +486,13 @@
 
 update to current bookmark if it's not the parent
 
+  $ hg summary
+  parent: 2:db815d6d32e6 
+   2
+  branch: default
+  bookmarks: [Z] Y x  y
+  commit: 1 added, 1 unknown (new branch head)
+  update: 2 new changesets (update)
   $ hg update
   updating to active bookmark Z
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
--- a/tests/test-check-code-hg.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-check-code-hg.t	Wed Apr 03 13:03:50 2013 -0500
@@ -1,6 +1,6 @@
   $ check_code="$TESTDIR"/../contrib/check-code.py
   $ cd "$TESTDIR"/..
-  $ if hg identify -q > /dev/null; then :
+  $ if hg identify -q > /dev/null 2>&1; then :
   > else
   >     echo "skipped: not a Mercurial working dir" >&2
   >     exit 80
@@ -8,4 +8,6 @@
 
 New errors are not allowed. Warnings are strongly discouraged.
 
-  $ hg manifest | xargs "$check_code" --warnings --nolineno --per-file=0
+  $ hg manifest 2>/dev/null \
+  >   | xargs "$check_code" --warnings --nolineno --per-file=0 \
+  >   || false
--- a/tests/test-check-code.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-check-code.t	Wed Apr 03 13:03:50 2013 -0500
@@ -163,13 +163,13 @@
    object comparison with literal
   [1]
 
-  $ cat > warning.py <<EOF
+  $ cat > for-nolineno.py <<EOF
   > except:
   > EOF
-  $ "$check_code" warning.py --warning --nolineno
-  warning.py:0:
+  $ "$check_code" for-nolineno.py --nolineno
+  for-nolineno.py:0:
    > except:
-   warning: naked except clause
+   naked except clause
   [1]
 
   $ cat > raise-format.py <<EOF
--- a/tests/test-command-template.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-command-template.t	Wed Apr 03 13:03:50 2013 -0500
@@ -43,6 +43,9 @@
   $ hg mv second fourth
   $ hg commit -m third -d "2020-01-01 10:01"
 
+  $ hg log --template '{file_copies % "{source} -> {name}\n"}' -r .
+  second -> fourth
+
 Quoting for ui.logtemplate
 
   $ hg tip --config "ui.logtemplate={rev}\n"
--- a/tests/test-commit.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-commit.t	Wed Apr 03 13:03:50 2013 -0500
@@ -263,6 +263,7 @@
   $ cd commitmsg
   $ echo changed > changed
   $ echo removed > removed
+  $ hg book currentbookmark
   $ hg ci -qAm init
 
   $ hg rm removed
@@ -277,6 +278,7 @@
   HG: --
   HG: user: test
   HG: branch 'default'
+  HG: bookmark 'currentbookmark'
   HG: added added
   HG: changed changed
   HG: removed removed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-completion.t	Wed Apr 03 13:03:50 2013 -0500
@@ -0,0 +1,336 @@
+Show all commands except debug commands
+  $ hg debugcomplete
+  add
+  addremove
+  annotate
+  archive
+  backout
+  bisect
+  bookmarks
+  branch
+  branches
+  bundle
+  cat
+  clone
+  commit
+  copy
+  diff
+  export
+  forget
+  graft
+  grep
+  heads
+  help
+  identify
+  import
+  incoming
+  init
+  locate
+  log
+  manifest
+  merge
+  outgoing
+  parents
+  paths
+  phase
+  pull
+  push
+  recover
+  remove
+  rename
+  resolve
+  revert
+  rollback
+  root
+  serve
+  showconfig
+  status
+  summary
+  tag
+  tags
+  tip
+  unbundle
+  update
+  verify
+  version
+
+Show all commands that start with "a"
+  $ hg debugcomplete a
+  add
+  addremove
+  annotate
+  archive
+
+Do not show debug commands if there are other candidates
+  $ hg debugcomplete d
+  diff
+
+Show debug commands if there are no other candidates
+  $ hg debugcomplete debug
+  debugancestor
+  debugbuilddag
+  debugbundle
+  debugcheckstate
+  debugcommands
+  debugcomplete
+  debugconfig
+  debugdag
+  debugdata
+  debugdate
+  debugdiscovery
+  debugfileset
+  debugfsinfo
+  debuggetbundle
+  debugignore
+  debugindex
+  debugindexdot
+  debuginstall
+  debugknown
+  debuglabelcomplete
+  debugobsolete
+  debugpathcomplete
+  debugpushkey
+  debugpvec
+  debugrebuildstate
+  debugrename
+  debugrevlog
+  debugrevspec
+  debugsetparents
+  debugstate
+  debugsub
+  debugsuccessorssets
+  debugwalk
+  debugwireargs
+
+Do not show the alias of a debug command if there are other candidates
+(this should hide rawcommit)
+  $ hg debugcomplete r
+  recover
+  remove
+  rename
+  resolve
+  revert
+  rollback
+  root
+Show the alias of a debug command if there are no other candidates
+  $ hg debugcomplete rawc
+  
+
+Show the global options
+  $ hg debugcomplete --options | sort
+  --config
+  --cwd
+  --debug
+  --debugger
+  --encoding
+  --encodingmode
+  --help
+  --hidden
+  --noninteractive
+  --profile
+  --quiet
+  --repository
+  --time
+  --traceback
+  --verbose
+  --version
+  -R
+  -h
+  -q
+  -v
+  -y
+
+Show the options for the "serve" command
+  $ hg debugcomplete --options serve | sort
+  --accesslog
+  --address
+  --certificate
+  --cmdserver
+  --config
+  --cwd
+  --daemon
+  --daemon-pipefds
+  --debug
+  --debugger
+  --encoding
+  --encodingmode
+  --errorlog
+  --help
+  --hidden
+  --ipv6
+  --name
+  --noninteractive
+  --pid-file
+  --port
+  --prefix
+  --profile
+  --quiet
+  --repository
+  --stdio
+  --style
+  --templates
+  --time
+  --traceback
+  --verbose
+  --version
+  --web-conf
+  -6
+  -A
+  -E
+  -R
+  -a
+  -d
+  -h
+  -n
+  -p
+  -q
+  -t
+  -v
+  -y
+
+Show an error if we use --options with an ambiguous abbreviation
+  $ hg debugcomplete --options s
+  hg: command 's' is ambiguous:
+      serve showconfig status summary
+  [255]
+
+Show all commands + options
+  $ hg debugcommands
+  add: include, exclude, subrepos, dry-run
+  annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, ignore-all-space, ignore-space-change, ignore-blank-lines, include, exclude
+  clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd, insecure
+  commit: addremove, close-branch, amend, include, exclude, message, logfile, date, user, subrepos
+  diff: rev, change, text, git, nodates, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, include, exclude, subrepos
+  export: output, switch-parent, rev, text, git, nodates
+  forget: include, exclude
+  init: ssh, remotecmd, insecure
+  log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
+  merge: force, rev, preview, tool
+  pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
+  push: force, rev, bookmark, branch, new-branch, ssh, remotecmd, insecure
+  remove: after, force, include, exclude
+  serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate
+  status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude, subrepos
+  summary: remote
+  update: clean, check, date, rev
+  addremove: similarity, include, exclude, dry-run
+  archive: no-decode, prefix, rev, type, subrepos, include, exclude
+  backout: merge, parent, rev, tool, include, exclude, message, logfile, date, user
+  bisect: reset, good, bad, skip, extend, command, noupdate
+  bookmarks: force, rev, delete, rename, inactive
+  branch: force, clean
+  branches: active, closed
+  bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
+  cat: output, rev, decode, include, exclude
+  copy: after, force, include, exclude, dry-run
+  debugancestor: 
+  debugbuilddag: mergeable-file, overwritten-file, new-file
+  debugbundle: all
+  debugcheckstate: 
+  debugcommands: 
+  debugcomplete: options
+  debugdag: tags, branches, dots, spaces
+  debugdata: changelog, manifest
+  debugdate: extended
+  debugdiscovery: old, nonheads, ssh, remotecmd, insecure
+  debugfileset: rev
+  debugfsinfo: 
+  debuggetbundle: head, common, type
+  debugignore: 
+  debugindex: changelog, manifest, format
+  debugindexdot: 
+  debuginstall: 
+  debugknown: 
+  debuglabelcomplete: 
+  debugobsolete: flags, date, user
+  debugpathcomplete: full, normal, added, removed
+  debugpushkey: 
+  debugpvec: 
+  debugrebuildstate: rev
+  debugrename: rev
+  debugrevlog: changelog, manifest, dump
+  debugrevspec: 
+  debugsetparents: 
+  debugstate: nodates, datesort
+  debugsub: rev
+  debugsuccessorssets: 
+  debugwalk: include, exclude
+  debugwireargs: three, four, five, ssh, remotecmd, insecure
+  graft: rev, continue, edit, log, currentdate, currentuser, date, user, tool, dry-run
+  grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude
+  heads: rev, topo, active, closed, style, template
+  help: extension, command, keyword
+  identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure
+  import: strip, base, edit, force, no-commit, bypass, exact, import-branch, message, logfile, date, user, similarity
+  incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
+  locate: rev, print0, fullpath, include, exclude
+  manifest: rev, all
+  outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
+  parents: rev, style, template
+  paths: 
+  phase: public, draft, secret, force, rev
+  recover: 
+  rename: after, force, include, exclude, dry-run
+  resolve: all, list, mark, unmark, no-status, tool, include, exclude
+  revert: all, date, rev, no-backup, include, exclude, dry-run
+  rollback: dry-run, force
+  root: 
+  showconfig: untrusted
+  tag: force, local, rev, remove, edit, message, date, user
+  tags: 
+  tip: patch, git, style, template
+  unbundle: update
+  verify: 
+  version: 
+
+  $ hg init a
+  $ cd a
+  $ echo fee > fee
+  $ hg ci -q -Amfee
+  $ hg tag fee
+  $ mkdir fie
+  $ echo dead > fie/dead
+  $ echo live > fie/live
+  $ hg bookmark fo
+  $ hg branch -q fie
+  $ hg ci -q -Amfie
+  $ echo fo > fo
+  $ hg branch -qf default
+  $ hg ci -q -Amfo
+  $ echo Fum > Fum
+  $ hg ci -q -AmFum
+  $ hg bookmark Fum
+
+Test debugpathcomplete
+
+  $ hg debugpathcomplete f
+  fee
+  fie/
+  fo
+  $ hg debugpathcomplete -f f
+  fee
+  fie/dead
+  fie/live
+  fo
+
+  $ hg rm Fum
+  $ hg debugpathcomplete -r F
+  Fum
+
+If one directory and no files match, give an ambiguous answer
+
+  $ hg debugpathcomplete fi
+  fie/
+  fie/.
+
+Test debuglabelcomplete
+
+  $ hg debuglabelcomplete
+  Fum
+  default
+  fee
+  fo
+  tip
+  $ hg debuglabelcomplete f
+  fee
+  fo
--- a/tests/test-convert-datesort.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-convert-datesort.t	Wed Apr 03 13:03:50 2013 -0500
@@ -38,6 +38,26 @@
   2 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ echo b >> b
   $ hg ci -m b1 -d '9 0'
+  $ hg up -C 0
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ echo c >> c
+  $ hg branch branchc
+  marked working directory as branch branchc
+  (branches are permanent and global, did you want a bookmark?)
+  $ hg ci -Am c0 -d '10 0'
+  adding c
+  $ hg up -C brancha
+  1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ hg ci --close-branch -m a7x -d '11 0'
+  $ hg up -C branchb
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg ci --close-branch -m b2x -d '12 0'
+  $ hg up -C branchc
+  1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ hg merge branchb
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  (branch merge, don't forget to commit)
+  $ hg ci -m c1 -d '13 0'
   $ cd ..
 
 convert with datesort
@@ -47,27 +67,39 @@
   scanning source...
   sorting...
   converting...
-  8 a0
-  7 a1
-  6 a2
-  5 a3
-  4 a4
-  3 b0
-  2 a5
-  1 a6
-  0 b1
+  12 a0
+  11 a1
+  10 a2
+  9 a3
+  8 a4
+  7 b0
+  6 a5
+  5 a6
+  4 b1
+  3 c0
+  2 a7x
+  1 b2x
+  0 c1
 
 graph converted repo
 
   $ hg -R t-datesort glog --template '{rev} "{desc}"\n'
-  o  8 "b1"
-  |
-  | o  7 "a6"
+  o    12 "c1"
+  |\
+  | o  11 "b2x"
   | |
-  | o  6 "a5"
-  | |
-  o |  5 "b0"
-  | |
+  | | o  10 "a7x"
+  | | |
+  o | |  9 "c0"
+  | | |
+  | o |  8 "b1"
+  | | |
+  | | o  7 "a6"
+  | | |
+  | | o  6 "a5"
+  | | |
+  | o |  5 "b0"
+  |/ /
   | o  4 "a4"
   | |
   | o  3 "a3"
@@ -86,29 +118,41 @@
   scanning source...
   sorting...
   converting...
-  8 a0
-  7 a1
-  6 a2
-  5 a3
-  4 b0
-  3 a4
-  2 a5
-  1 a6
-  0 b1
+  12 a0
+  11 a1
+  10 a2
+  9 a3
+  8 b0
+  7 a4
+  6 a5
+  5 a6
+  4 b1
+  3 c0
+  2 a7x
+  1 b2x
+  0 c1
 
 graph converted repo
 
   $ hg -R t-sourcesort glog --template '{rev} "{desc}"\n'
-  o  8 "b1"
-  |
-  | o  7 "a6"
+  o    12 "c1"
+  |\
+  | o  11 "b2x"
   | |
-  | o  6 "a5"
-  | |
-  | o  5 "a4"
-  | |
-  o |  4 "b0"
-  | |
+  | | o  10 "a7x"
+  | | |
+  o | |  9 "c0"
+  | | |
+  | o |  8 "b1"
+  | | |
+  | | o  7 "a6"
+  | | |
+  | | o  6 "a5"
+  | | |
+  | | o  5 "a4"
+  | | |
+  | o |  4 "b0"
+  |/ /
   | o  3 "a3"
   | |
   | o  2 "a2"
@@ -117,3 +161,54 @@
   |/
   o  0 "a0"
   
+
+convert with closesort
+
+  $ hg convert --closesort t t-closesort
+  initializing destination t-closesort repository
+  scanning source...
+  sorting...
+  converting...
+  12 a0
+  11 a1
+  10 a2
+  9 a3
+  8 b0
+  7 a4
+  6 a5
+  5 a6
+  4 a7x
+  3 b1
+  2 b2x
+  1 c0
+  0 c1
+
+graph converted repo
+
+  $ hg -R t-closesort glog --template '{rev} "{desc}"\n'
+  o    12 "c1"
+  |\
+  | o  11 "c0"
+  | |
+  o |  10 "b2x"
+  | |
+  o |  9 "b1"
+  | |
+  | | o  8 "a7x"
+  | | |
+  | | o  7 "a6"
+  | | |
+  | | o  6 "a5"
+  | | |
+  | | o  5 "a4"
+  | | |
+  o | |  4 "b0"
+  |/ /
+  | o  3 "a3"
+  | |
+  | o  2 "a2"
+  | |
+  | o  1 "a1"
+  |/
+  o  0 "a0"
+  
--- a/tests/test-convert-git.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-convert-git.t	Wed Apr 03 13:03:50 2013 -0500
@@ -281,24 +281,6 @@
   abort: --sourcesort is not supported by this data source
   [255]
 
-damage git repository and convert again
-
-  $ cat > damage.py <<EOF
-  > import os
-  > import stat
-  > for root, dirs, files in os.walk('git-repo4/.git/objects'):
-  >     if files:
-  >         path = os.path.join(root, files[0])
-  >         if os.name == 'nt':
-  >             os.chmod(path, stat.S_IWUSR)
-  >         os.remove(path)
-  >         break
-  > EOF
-  $ python damage.py
-  $ hg convert git-repo4 git-repo4-broken-hg 2>&1 | \
-  >     grep 'abort:' | sed 's/abort:.*/abort:/g'
-  abort:
-
 test sub modules
 
   $ mkdir git-repo5
@@ -345,3 +327,32 @@
   $ cd git-repo5
   $ cat foo
   sub
+
+  $ cd ../..
+
+damaged git repository tests:
+In case the hard-coded hashes change, the following commands can be used to
+list the hashes and their corresponding types in the repository:
+cd git-repo4/.git/objects
+find . -type f | cut -c 3- | sed 's_/__' | xargs -n 1 -t git cat-file -t
+cd ../../..
+
+damage git repository by renaming a commit object
+  $ COMMIT_OBJ=1c/0ce3c5886f83a1d78a7b517cdff5cf9ca17bdd
+  $ mv git-repo4/.git/objects/$COMMIT_OBJ git-repo4/.git/objects/$COMMIT_OBJ.tmp
+  $ hg convert git-repo4 git-repo4-broken-hg 2>&1 | grep 'abort:'
+  abort: cannot read tags from git-repo4/.git
+  $ mv git-repo4/.git/objects/$COMMIT_OBJ.tmp git-repo4/.git/objects/$COMMIT_OBJ
+damage git repository by renaming a blob object
+
+  $ BLOB_OBJ=8b/137891791fe96927ad78e64b0aad7bded08bdc
+  $ mv git-repo4/.git/objects/$BLOB_OBJ git-repo4/.git/objects/$BLOB_OBJ.tmp
+  $ hg convert git-repo4 git-repo4-broken-hg 2>&1 | grep 'abort:'
+  abort: cannot read 'blob' object at 8b137891791fe96927ad78e64b0aad7bded08bdc
+  $ mv git-repo4/.git/objects/$BLOB_OBJ.tmp git-repo4/.git/objects/$BLOB_OBJ
+damage git repository by renaming a tree object
+
+  $ TREE_OBJ=72/49f083d2a63a41cc737764a86981eb5f3e4635
+  $ mv git-repo4/.git/objects/$TREE_OBJ git-repo4/.git/objects/$TREE_OBJ.tmp
+  $ hg convert git-repo4 git-repo4-broken-hg 2>&1 | grep 'abort:'
+  abort: cannot read changes in 1c0ce3c5886f83a1d78a7b517cdff5cf9ca17bdd
--- a/tests/test-convert.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-convert.t	Wed Apr 03 13:03:50 2013 -0500
@@ -46,6 +46,8 @@
                     larger than the same ones generated by --branchsort.
       --sourcesort  try to preserve source revisions order, only supported by
                     Mercurial sources.
+      --closesort   try to move closed revisions as close as possible to parent
+                    branches, only supported by Mercurial sources.
   
       If "REVMAP" isn't given, it will be put in a default location
       ("<dest>/.hg/shamap" by default). The "REVMAP" is a simple text file that
@@ -268,6 +270,7 @@
       --branchsort       try to sort changesets by branches
       --datesort         try to sort changesets by date
       --sourcesort       preserve source changesets order
+      --closesort        try to reorder closed revisions
   
   use "hg -v help convert" to show the global options
   $ hg init a
--- a/tests/test-copy-move-merge.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-copy-move-merge.t	Wed Apr 03 13:03:50 2013 -0500
@@ -29,12 +29,12 @@
      src: 'a' -> dst: 'c' *
     checking for directory renames
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: b8bf91eeebbc, local: add3f11052fa+, remote: 17c05bb7fcb6
    a: remote moved to b -> m
+    preserving a for resolve of b
    a: remote moved to c -> m
-  preserving a for resolve of b
-  preserving a for resolve of c
+    preserving a for resolve of c
   removing a
   updating: a 1/2 files (50.00%)
   picked tool 'internal:merge' for b (binary False symlink False)
--- a/tests/test-debugcomplete.t	Tue Apr 02 16:03:10 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,280 +0,0 @@
-Show all commands except debug commands
-  $ hg debugcomplete
-  add
-  addremove
-  annotate
-  archive
-  backout
-  bisect
-  bookmarks
-  branch
-  branches
-  bundle
-  cat
-  clone
-  commit
-  copy
-  diff
-  export
-  forget
-  graft
-  grep
-  heads
-  help
-  identify
-  import
-  incoming
-  init
-  locate
-  log
-  manifest
-  merge
-  outgoing
-  parents
-  paths
-  phase
-  pull
-  push
-  recover
-  remove
-  rename
-  resolve
-  revert
-  rollback
-  root
-  serve
-  showconfig
-  status
-  summary
-  tag
-  tags
-  tip
-  unbundle
-  update
-  verify
-  version
-
-Show all commands that start with "a"
-  $ hg debugcomplete a
-  add
-  addremove
-  annotate
-  archive
-
-Do not show debug commands if there are other candidates
-  $ hg debugcomplete d
-  diff
-
-Show debug commands if there are no other candidates
-  $ hg debugcomplete debug
-  debugancestor
-  debugbuilddag
-  debugbundle
-  debugcheckstate
-  debugcommands
-  debugcomplete
-  debugconfig
-  debugdag
-  debugdata
-  debugdate
-  debugdiscovery
-  debugfileset
-  debugfsinfo
-  debuggetbundle
-  debugignore
-  debugindex
-  debugindexdot
-  debuginstall
-  debugknown
-  debugobsolete
-  debugpushkey
-  debugpvec
-  debugrebuildstate
-  debugrename
-  debugrevlog
-  debugrevspec
-  debugsetparents
-  debugstate
-  debugsub
-  debugsuccessorssets
-  debugwalk
-  debugwireargs
-
-Do not show the alias of a debug command if there are other candidates
-(this should hide rawcommit)
-  $ hg debugcomplete r
-  recover
-  remove
-  rename
-  resolve
-  revert
-  rollback
-  root
-Show the alias of a debug command if there are no other candidates
-  $ hg debugcomplete rawc
-  
-
-Show the global options
-  $ hg debugcomplete --options | sort
-  --config
-  --cwd
-  --debug
-  --debugger
-  --encoding
-  --encodingmode
-  --help
-  --hidden
-  --noninteractive
-  --profile
-  --quiet
-  --repository
-  --time
-  --traceback
-  --verbose
-  --version
-  -R
-  -h
-  -q
-  -v
-  -y
-
-Show the options for the "serve" command
-  $ hg debugcomplete --options serve | sort
-  --accesslog
-  --address
-  --certificate
-  --cmdserver
-  --config
-  --cwd
-  --daemon
-  --daemon-pipefds
-  --debug
-  --debugger
-  --encoding
-  --encodingmode
-  --errorlog
-  --help
-  --hidden
-  --ipv6
-  --name
-  --noninteractive
-  --pid-file
-  --port
-  --prefix
-  --profile
-  --quiet
-  --repository
-  --stdio
-  --style
-  --templates
-  --time
-  --traceback
-  --verbose
-  --version
-  --web-conf
-  -6
-  -A
-  -E
-  -R
-  -a
-  -d
-  -h
-  -n
-  -p
-  -q
-  -t
-  -v
-  -y
-
-Show an error if we use --options with an ambiguous abbreviation
-  $ hg debugcomplete --options s
-  hg: command 's' is ambiguous:
-      serve showconfig status summary
-  [255]
-
-Show all commands + options
-  $ hg debugcommands
-  add: include, exclude, subrepos, dry-run
-  annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, ignore-all-space, ignore-space-change, ignore-blank-lines, include, exclude
-  clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd, insecure
-  commit: addremove, close-branch, amend, include, exclude, message, logfile, date, user, subrepos
-  diff: rev, change, text, git, nodates, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, include, exclude, subrepos
-  export: output, switch-parent, rev, text, git, nodates
-  forget: include, exclude
-  init: ssh, remotecmd, insecure
-  log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
-  merge: force, rev, preview, tool
-  pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
-  push: force, rev, bookmark, branch, new-branch, ssh, remotecmd, insecure
-  remove: after, force, include, exclude
-  serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate
-  status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude, subrepos
-  summary: remote
-  update: clean, check, date, rev
-  addremove: similarity, include, exclude, dry-run
-  archive: no-decode, prefix, rev, type, subrepos, include, exclude
-  backout: merge, parent, rev, tool, include, exclude, message, logfile, date, user
-  bisect: reset, good, bad, skip, extend, command, noupdate
-  bookmarks: force, rev, delete, rename, inactive
-  branch: force, clean
-  branches: active, closed
-  bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
-  cat: output, rev, decode, include, exclude
-  copy: after, force, include, exclude, dry-run
-  debugancestor: 
-  debugbuilddag: mergeable-file, overwritten-file, new-file
-  debugbundle: all
-  debugcheckstate: 
-  debugcommands: 
-  debugcomplete: options
-  debugdag: tags, branches, dots, spaces
-  debugdata: changelog, manifest
-  debugdate: extended
-  debugdiscovery: old, nonheads, ssh, remotecmd, insecure
-  debugfileset: rev
-  debugfsinfo: 
-  debuggetbundle: head, common, type
-  debugignore: 
-  debugindex: changelog, manifest, format
-  debugindexdot: 
-  debuginstall: 
-  debugknown: 
-  debugobsolete: flags, date, user
-  debugpushkey: 
-  debugpvec: 
-  debugrebuildstate: rev
-  debugrename: rev
-  debugrevlog: changelog, manifest, dump
-  debugrevspec: 
-  debugsetparents: 
-  debugstate: nodates, datesort
-  debugsub: rev
-  debugsuccessorssets: 
-  debugwalk: include, exclude
-  debugwireargs: three, four, five, ssh, remotecmd, insecure
-  graft: rev, continue, edit, log, currentdate, currentuser, date, user, tool, dry-run
-  grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude
-  heads: rev, topo, active, closed, style, template
-  help: extension, command, keyword
-  identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure
-  import: strip, base, edit, force, no-commit, bypass, exact, import-branch, message, logfile, date, user, similarity
-  incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
-  locate: rev, print0, fullpath, include, exclude
-  manifest: rev, all
-  outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
-  parents: rev, style, template
-  paths: 
-  phase: public, draft, secret, force, rev
-  recover: 
-  rename: after, force, include, exclude, dry-run
-  resolve: all, list, mark, unmark, no-status, tool, include, exclude
-  revert: all, date, rev, no-backup, include, exclude, dry-run
-  rollback: dry-run, force
-  root: 
-  showconfig: untrusted
-  tag: force, local, rev, remove, edit, message, date, user
-  tags: 
-  tip: patch, git, style, template
-  unbundle: update
-  verify: 
-  version: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-dicthelpers.py	Wed Apr 03 13:03:50 2013 -0500
@@ -0,0 +1,53 @@
+from mercurial.dicthelpers import diff, join
+import unittest
+import silenttestrunner
+
+class testdicthelpers(unittest.TestCase):
+    def test_dicthelpers(self):
+        # empty dicts
+        self.assertEqual(diff({}, {}), {})
+        self.assertEqual(join({}, {}), {})
+
+        d1 = {}
+        d1['a'] = 'foo'
+        d1['b'] = 'bar'
+        d1['c'] = 'baz'
+
+        # same identity
+        self.assertEqual(diff(d1, d1), {})
+        self.assertEqual(join(d1, d1), {'a': ('foo', 'foo'),
+                                        'b': ('bar', 'bar'),
+                                        'c': ('baz', 'baz')})
+
+        # vs empty
+        self.assertEqual(diff(d1, {}), {'a': ('foo', None),
+                                        'b': ('bar', None),
+                                        'c': ('baz', None)})
+        self.assertEqual(diff(d1, {}), {'a': ('foo', None),
+                                        'b': ('bar', None),
+                                        'c': ('baz', None)})
+
+        d2 = {}
+        d2['a'] = 'foo2'
+        d2['b'] = 'bar'
+        d2['d'] = 'quux'
+
+        self.assertEqual(diff(d1, d2), {'a': ('foo', 'foo2'),
+                                        'c': ('baz', None),
+                                        'd': (None, 'quux')})
+        self.assertEqual(join(d1, d2), {'a': ('foo', 'foo2'),
+                                        'b': ('bar', 'bar'),
+                                        'c': ('baz', None),
+                                        'd': (None, 'quux')})
+
+        # with default argument
+        self.assertEqual(diff(d1, d2, 123), {'a': ('foo', 'foo2'),
+                                             'c': ('baz', 123),
+                                             'd': (123, 'quux')})
+        self.assertEqual(join(d1, d2, 456), {'a': ('foo', 'foo2'),
+                                             'b': ('bar', 'bar'),
+                                             'c': ('baz', 456),
+                                             'd': (456, 'quux')})
+
+if __name__ == '__main__':
+    silenttestrunner.main(__name__)
--- a/tests/test-diff-color.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-diff-color.t	Wed Apr 03 13:03:50 2013 -0500
@@ -152,7 +152,7 @@
    c
    c
   \x1b[0;32m+aa\x1b[0m (esc)
-  \x1b[0;1mdiff --git a/sub/b b/sub/b\x1b[0m (glob) (esc)
+  \x1b[0;1mdiff --git a/sub/b b/sub/b\x1b[0m (esc)
   \x1b[0;31;1m--- a/sub/b\x1b[0m (esc)
   \x1b[0;32;1m+++ b/sub/b\x1b[0m (esc)
   \x1b[0;35m@@ -1,1 +1,2 @@\x1b[0m (esc)
--- a/tests/test-diff-upgrade.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-diff-upgrade.t	Wed Apr 03 13:03:50 2013 -0500
@@ -200,7 +200,11 @@
   % git=auto: git diff for rmbinary
   diff --git a/rmbinary b/rmbinary
   deleted file mode 100644
-  Binary file rmbinary has changed
+  index f76dd238ade08917e6712764a16a22005a50573d..0000000000000000000000000000000000000000
+  GIT binary patch
+  literal 0
+  Hc$@<O00001
+  
   
   % git=auto: git diff for bintoregular
   diff --git a/bintoregular b/bintoregular
@@ -210,6 +214,7 @@
   Uc$`bh%qz(+N=+}#Ni5<5043uE82|tP
   
 
+
 git=warn: regular diff with data loss warnings
 
   $ hg autodiff --git=warn
--- a/tests/test-double-merge.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-double-merge.t	Wed Apr 03 13:03:50 2013 -0500
@@ -33,12 +33,12 @@
      src: 'foo' -> dst: 'bar' *
     checking for directory renames
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: e6dc8efe11cc, local: 6a0df1dad128+, remote: 484bf6903104
+   foo: remote copied to bar -> m
+    preserving foo for resolve of bar
    foo: versions differ -> m
-   foo: remote copied to bar -> m
-  preserving foo for resolve of bar
-  preserving foo for resolve of foo
+    preserving foo for resolve of foo
   updating: foo 1/2 files (50.00%)
   picked tool 'internal:merge' for bar (binary False symlink False)
   merging foo and bar to bar
--- a/tests/test-export.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-export.t	Wed Apr 03 13:03:50 2013 -0500
@@ -91,13 +91,28 @@
   foo-foo_10.patch
   foo-foo_11.patch
 
+Doing it again clobbers the files rather than appending:
+  $ hg export -v -o "foo-%m.patch" 2:3
+  exporting patches:
+  foo-foo_2.patch
+  foo-foo_3.patch
+  $ grep HG foo-foo_2.patch | wc -l
+  \s*1 (re)
+  $ grep HG foo-foo_3.patch | wc -l
+  \s*1 (re)
+
 Exporting 4 changesets to a file:
 
   $ hg export -o export_internal 1 2 3 4
   $ grep HG export_internal | wc -l
   \s*4 (re)
 
-Exporting 4 changesets to a file:
+Doing it again clobbers the file rather than appending:
+  $ hg export -o export_internal 1 2 3 4
+  $ grep HG export_internal | wc -l
+  \s*4 (re)
+
+Exporting 4 changesets to stdout:
 
   $ hg export 1 2 3 4 | grep HG | wc -l
   \s*4 (re)
@@ -108,6 +123,7 @@
   # HG changeset patch
   # User test
   # Date 0 0
+  #      Thu Jan 01 00:00:00 1970 +0000
   # Node ID 5f17a83f5fbd9414006a5e563eab4c8a00729efd
   # Parent  747d3c68f8ec44bb35816bfcd59aeb50b9654c2f
   foo-10
@@ -154,6 +170,7 @@
   # HG changeset patch
   # User test
   # Date 0 0
+  #      Thu Jan 01 00:00:00 1970 +0000
   # Node ID * (glob)
   # Parent * (glob)
    !"#$%&(,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
--- a/tests/test-extension.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-extension.t	Wed Apr 03 13:03:50 2013 -0500
@@ -112,7 +112,8 @@
   > wsgicgi.launch(application)
   > EOF
 
-  $ SCRIPT_NAME='/' SERVER_PORT='80' SERVER_NAME='localhost' python hgweb.cgi \
+  $ REQUEST_METHOD='GET' PATH_INFO='/' SCRIPT_NAME='' QUERY_STRING='' \
+  >    SERVER_PORT='80' SERVER_NAME='localhost' python hgweb.cgi \
   >    | grep '^[0-9]) ' # ignores HTML output
   1) foo imported
   1) bar imported
@@ -352,6 +353,7 @@
 
   $ hg help multirevs
   Specifying Multiple Revisions
+  """""""""""""""""""""""""""""
   
       When Mercurial accepts more than one revision, they may be specified
       individually, or provided as a topologically continuous range, separated
--- a/tests/test-fileset.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-fileset.t	Wed Apr 03 13:03:50 2013 -0500
@@ -226,3 +226,21 @@
   b2
   c1
 
+  >>> open('dos', 'wb').write("dos\r\n")
+  >>> open('mixed', 'wb').write("dos\r\nunix\n")
+  >>> open('mac', 'wb').write("mac\r")
+  $ hg add dos mixed mac
+
+  $ fileset 'eol(dos)'
+  dos
+  mixed
+  $ fileset 'eol(unix)'
+  .hgsub
+  .hgsubstate
+  a1
+  b1
+  b2
+  c1
+  mixed
+  $ fileset 'eol(mac)'
+  mac
--- a/tests/test-graft.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-graft.t	Wed Apr 03 13:03:50 2013 -0500
@@ -84,6 +84,7 @@
   # HG changeset patch
   # User foo
   # Date 0 0
+  #      Thu Jan 01 00:00:00 1970 +0000
   # Node ID ef0ef43d49e79e81ddafdc7997401ba0041efc82
   # Parent  68795b066622ca79a25816a662041d8f78f3cd9e
   2
@@ -134,10 +135,10 @@
      src: 'a' -> dst: 'b' *
     checking for directory renames
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: True, partial: False
    ancestor: 68795b066622, local: ef0ef43d49e7+, remote: 5d205f8b35b6
    b: local copied/moved to a -> m
-  preserving b for resolve of b
+    preserving b for resolve of b
   updating: b 1/1 files (100.00%)
   picked tool 'internal:merge' for b (binary False symlink False)
   merging b and a to b
@@ -147,22 +148,22 @@
   grafting revision 5
     searching for copies back to rev 1
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: True, partial: False
    ancestor: 4c60f11aa304, local: 6b9e5368ca4e+, remote: 97f8bfe72746
    e: remote is newer -> g
+  getting e
   updating: e 1/1 files (100.00%)
-  getting e
   e
   grafting revision 4
     searching for copies back to rev 1
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: True, partial: False
    ancestor: 4c60f11aa304, local: 1905859650ec+, remote: 9c233e8e184d
    d: remote is newer -> g
    e: versions differ -> m
-  preserving e for resolve of e
+    preserving e for resolve of e
+  getting d
   updating: d 1/2 files (50.00%)
-  getting d
   updating: e 2/2 files (100.00%)
   picked tool 'internal:merge' for e (binary False symlink False)
   merging e
@@ -324,6 +325,7 @@
   # HG changeset patch
   # User bar
   # Date 0 0
+  #      Thu Jan 01 00:00:00 1970 +0000
   # Node ID 64ecd9071ce83c6e62f538d8ce7709d53f32ebf7
   # Parent  4bdb9a9d0b84ffee1d30f0dfc7744cade17aa19c
   1
@@ -351,6 +353,7 @@
   # HG changeset patch
   # User test
   # Date 0 0
+  #      Thu Jan 01 00:00:00 1970 +0000
   # Node ID 2e80e1351d6ed50302fe1e05f8bd1d4d412b6e11
   # Parent  e5a51ae854a8bbaaf25cc5c6a57ff46042dadbb4
   2
--- a/tests/test-help.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-help.t	Wed Apr 03 13:03:50 2013 -0500
@@ -712,6 +712,7 @@
 
   $ hg help revs
   Specifying Single Revisions
+  """""""""""""""""""""""""""
   
       Mercurial supports several ways to specify individual revisions.
   
@@ -857,6 +858,7 @@
   no commands defined
   $ hg help topic-containing-verbose
   This is the topic to test omit indicating.
+  """"""""""""""""""""""""""""""""""""""""""
   
       This paragraph is never omitted (for topic).
   
@@ -865,6 +867,7 @@
   use "hg help -v topic-containing-verbose" to show more complete help
   $ hg help -v topic-containing-verbose
   This is the topic to test omit indicating.
+  """"""""""""""""""""""""""""""""""""""""""
   
       This paragraph is never omitted (for topic).
   
@@ -876,3 +879,989 @@
 
   $ cd "$TESTDIR"/../doc
   $ python check-seclevel.py
+  $ cd $TESTTMP
+
+#if serve
+
+Test the help pages in hgweb.
+
+Dish up an empty repo; serve it cold.
+
+  $ hg init "$TESTTMP/test"
+  $ hg serve -R "$TESTTMP/test" -n test -p $HGPORT -d --pid-file=hg.pid
+  $ cat hg.pid >> $DAEMON_PIDS
+
+  $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT "help"
+  200 Script output follows
+  
+  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
+  <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" />
+  <script type="text/javascript" src="/static/mercurial.js"></script>
+  
+  <title>Help: Index</title>
+  </head>
+  <body>
+  
+  <div class="container">
+  <div class="menu">
+  <div class="logo">
+  <a href="http://mercurial.selenic.com/">
+  <img src="/static/hglogo.png" 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>
+  <li><a href="/bookmarks">bookmarks</a></li>
+  <li><a href="/branches">branches</a></li>
+  </ul>
+  <ul>
+  <li class="active">help</li>
+  </ul>
+  </div>
+  
+  <div class="main">
+  <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
+  <form class="search" action="/log">
+  
+  <p><input name="rev" id="search1" type="text" size="30" /></p>
+  <div id="hint">find changesets by author, revision,
+  files, or words in the commit message</div>
+  </form>
+  <table class="bigtable">
+  <tr><td colspan="2"><h2><a name="main" href="#topics">Topics</a></h2></td></tr>
+  
+  <tr><td>
+  <a href="/help/config">
+  config
+  </a>
+  </td><td>
+  Configuration Files
+  </td></tr>
+  <tr><td>
+  <a href="/help/dates">
+  dates
+  </a>
+  </td><td>
+  Date Formats
+  </td></tr>
+  <tr><td>
+  <a href="/help/diffs">
+  diffs
+  </a>
+  </td><td>
+  Diff Formats
+  </td></tr>
+  <tr><td>
+  <a href="/help/environment">
+  environment
+  </a>
+  </td><td>
+  Environment Variables
+  </td></tr>
+  <tr><td>
+  <a href="/help/extensions">
+  extensions
+  </a>
+  </td><td>
+  Using Additional Features
+  </td></tr>
+  <tr><td>
+  <a href="/help/filesets">
+  filesets
+  </a>
+  </td><td>
+  Specifying File Sets
+  </td></tr>
+  <tr><td>
+  <a href="/help/glossary">
+  glossary
+  </a>
+  </td><td>
+  Glossary
+  </td></tr>
+  <tr><td>
+  <a href="/help/hgignore">
+  hgignore
+  </a>
+  </td><td>
+  Syntax for Mercurial Ignore Files
+  </td></tr>
+  <tr><td>
+  <a href="/help/hgweb">
+  hgweb
+  </a>
+  </td><td>
+  Configuring hgweb
+  </td></tr>
+  <tr><td>
+  <a href="/help/merge-tools">
+  merge-tools
+  </a>
+  </td><td>
+  Merge Tools
+  </td></tr>
+  <tr><td>
+  <a href="/help/multirevs">
+  multirevs
+  </a>
+  </td><td>
+  Specifying Multiple Revisions
+  </td></tr>
+  <tr><td>
+  <a href="/help/patterns">
+  patterns
+  </a>
+  </td><td>
+  File Name Patterns
+  </td></tr>
+  <tr><td>
+  <a href="/help/phases">
+  phases
+  </a>
+  </td><td>
+  Working with Phases
+  </td></tr>
+  <tr><td>
+  <a href="/help/revisions">
+  revisions
+  </a>
+  </td><td>
+  Specifying Single Revisions
+  </td></tr>
+  <tr><td>
+  <a href="/help/revsets">
+  revsets
+  </a>
+  </td><td>
+  Specifying Revision Sets
+  </td></tr>
+  <tr><td>
+  <a href="/help/subrepos">
+  subrepos
+  </a>
+  </td><td>
+  Subrepositories
+  </td></tr>
+  <tr><td>
+  <a href="/help/templating">
+  templating
+  </a>
+  </td><td>
+  Template Usage
+  </td></tr>
+  <tr><td>
+  <a href="/help/urls">
+  urls
+  </a>
+  </td><td>
+  URL Paths
+  </td></tr>
+  <tr><td>
+  <a href="/help/topic-containing-verbose">
+  topic-containing-verbose
+  </a>
+  </td><td>
+  This is the topic to test omit indicating.
+  </td></tr>
+  
+  <tr><td colspan="2"><h2><a name="main" href="#main">Main Commands</a></h2></td></tr>
+  
+  <tr><td>
+  <a href="/help/add">
+  add
+  </a>
+  </td><td>
+  add the specified files on the next commit
+  </td></tr>
+  <tr><td>
+  <a href="/help/annotate">
+  annotate
+  </a>
+  </td><td>
+  show changeset information by line for each file
+  </td></tr>
+  <tr><td>
+  <a href="/help/clone">
+  clone
+  </a>
+  </td><td>
+  make a copy of an existing repository
+  </td></tr>
+  <tr><td>
+  <a href="/help/commit">
+  commit
+  </a>
+  </td><td>
+  commit the specified files or all outstanding changes
+  </td></tr>
+  <tr><td>
+  <a href="/help/diff">
+  diff
+  </a>
+  </td><td>
+  diff repository (or selected files)
+  </td></tr>
+  <tr><td>
+  <a href="/help/export">
+  export
+  </a>
+  </td><td>
+  dump the header and diffs for one or more changesets
+  </td></tr>
+  <tr><td>
+  <a href="/help/forget">
+  forget
+  </a>
+  </td><td>
+  forget the specified files on the next commit
+  </td></tr>
+  <tr><td>
+  <a href="/help/init">
+  init
+  </a>
+  </td><td>
+  create a new repository in the given directory
+  </td></tr>
+  <tr><td>
+  <a href="/help/log">
+  log
+  </a>
+  </td><td>
+  show revision history of entire repository or files
+  </td></tr>
+  <tr><td>
+  <a href="/help/merge">
+  merge
+  </a>
+  </td><td>
+  merge working directory with another revision
+  </td></tr>
+  <tr><td>
+  <a href="/help/pull">
+  pull
+  </a>
+  </td><td>
+  pull changes from the specified source
+  </td></tr>
+  <tr><td>
+  <a href="/help/push">
+  push
+  </a>
+  </td><td>
+  push changes to the specified destination
+  </td></tr>
+  <tr><td>
+  <a href="/help/remove">
+  remove
+  </a>
+  </td><td>
+  remove the specified files on the next commit
+  </td></tr>
+  <tr><td>
+  <a href="/help/serve">
+  serve
+  </a>
+  </td><td>
+  start stand-alone webserver
+  </td></tr>
+  <tr><td>
+  <a href="/help/status">
+  status
+  </a>
+  </td><td>
+  show changed files in the working directory
+  </td></tr>
+  <tr><td>
+  <a href="/help/summary">
+  summary
+  </a>
+  </td><td>
+  summarize working directory state
+  </td></tr>
+  <tr><td>
+  <a href="/help/update">
+  update
+  </a>
+  </td><td>
+  update working directory (or switch revisions)
+  </td></tr>
+  
+  <tr><td colspan="2"><h2><a name="other" href="#other">Other Commands</a></h2></td></tr>
+  
+  <tr><td>
+  <a href="/help/addremove">
+  addremove
+  </a>
+  </td><td>
+  add all new files, delete all missing files
+  </td></tr>
+  <tr><td>
+  <a href="/help/archive">
+  archive
+  </a>
+  </td><td>
+  create an unversioned archive of a repository revision
+  </td></tr>
+  <tr><td>
+  <a href="/help/backout">
+  backout
+  </a>
+  </td><td>
+  reverse effect of earlier changeset
+  </td></tr>
+  <tr><td>
+  <a href="/help/bisect">
+  bisect
+  </a>
+  </td><td>
+  subdivision search of changesets
+  </td></tr>
+  <tr><td>
+  <a href="/help/bookmarks">
+  bookmarks
+  </a>
+  </td><td>
+  track a line of development with movable markers
+  </td></tr>
+  <tr><td>
+  <a href="/help/branch">
+  branch
+  </a>
+  </td><td>
+  set or show the current branch name
+  </td></tr>
+  <tr><td>
+  <a href="/help/branches">
+  branches
+  </a>
+  </td><td>
+  list repository named branches
+  </td></tr>
+  <tr><td>
+  <a href="/help/bundle">
+  bundle
+  </a>
+  </td><td>
+  create a changegroup file
+  </td></tr>
+  <tr><td>
+  <a href="/help/cat">
+  cat
+  </a>
+  </td><td>
+  output the current or given revision of files
+  </td></tr>
+  <tr><td>
+  <a href="/help/copy">
+  copy
+  </a>
+  </td><td>
+  mark files as copied for the next commit
+  </td></tr>
+  <tr><td>
+  <a href="/help/graft">
+  graft
+  </a>
+  </td><td>
+  copy changes from other branches onto the current branch
+  </td></tr>
+  <tr><td>
+  <a href="/help/grep">
+  grep
+  </a>
+  </td><td>
+  search for a pattern in specified files and revisions
+  </td></tr>
+  <tr><td>
+  <a href="/help/heads">
+  heads
+  </a>
+  </td><td>
+  show current repository heads or show branch heads
+  </td></tr>
+  <tr><td>
+  <a href="/help/help">
+  help
+  </a>
+  </td><td>
+  show help for a given topic or a help overview
+  </td></tr>
+  <tr><td>
+  <a href="/help/identify">
+  identify
+  </a>
+  </td><td>
+  identify the working copy or specified revision
+  </td></tr>
+  <tr><td>
+  <a href="/help/import">
+  import
+  </a>
+  </td><td>
+  import an ordered set of patches
+  </td></tr>
+  <tr><td>
+  <a href="/help/incoming">
+  incoming
+  </a>
+  </td><td>
+  show new changesets found in source
+  </td></tr>
+  <tr><td>
+  <a href="/help/locate">
+  locate
+  </a>
+  </td><td>
+  locate files matching specific patterns
+  </td></tr>
+  <tr><td>
+  <a href="/help/manifest">
+  manifest
+  </a>
+  </td><td>
+  output the current or given revision of the project manifest
+  </td></tr>
+  <tr><td>
+  <a href="/help/nohelp">
+  nohelp
+  </a>
+  </td><td>
+  (no help text available)
+  </td></tr>
+  <tr><td>
+  <a href="/help/outgoing">
+  outgoing
+  </a>
+  </td><td>
+  show changesets not found in the destination
+  </td></tr>
+  <tr><td>
+  <a href="/help/parents">
+  parents
+  </a>
+  </td><td>
+  show the parents of the working directory or revision
+  </td></tr>
+  <tr><td>
+  <a href="/help/paths">
+  paths
+  </a>
+  </td><td>
+  show aliases for remote repositories
+  </td></tr>
+  <tr><td>
+  <a href="/help/phase">
+  phase
+  </a>
+  </td><td>
+  set or show the current phase name
+  </td></tr>
+  <tr><td>
+  <a href="/help/recover">
+  recover
+  </a>
+  </td><td>
+  roll back an interrupted transaction
+  </td></tr>
+  <tr><td>
+  <a href="/help/rename">
+  rename
+  </a>
+  </td><td>
+  rename files; equivalent of copy + remove
+  </td></tr>
+  <tr><td>
+  <a href="/help/resolve">
+  resolve
+  </a>
+  </td><td>
+  redo merges or set/view the merge status of files
+  </td></tr>
+  <tr><td>
+  <a href="/help/revert">
+  revert
+  </a>
+  </td><td>
+  restore files to their checkout state
+  </td></tr>
+  <tr><td>
+  <a href="/help/rollback">
+  rollback
+  </a>
+  </td><td>
+  roll back the last transaction (dangerous)
+  </td></tr>
+  <tr><td>
+  <a href="/help/root">
+  root
+  </a>
+  </td><td>
+  print the root (top) of the current working directory
+  </td></tr>
+  <tr><td>
+  <a href="/help/showconfig">
+  showconfig
+  </a>
+  </td><td>
+  show combined config settings from all hgrc files
+  </td></tr>
+  <tr><td>
+  <a href="/help/tag">
+  tag
+  </a>
+  </td><td>
+  add one or more tags for the current or given revision
+  </td></tr>
+  <tr><td>
+  <a href="/help/tags">
+  tags
+  </a>
+  </td><td>
+  list repository tags
+  </td></tr>
+  <tr><td>
+  <a href="/help/tip">
+  tip
+  </a>
+  </td><td>
+  show the tip revision
+  </td></tr>
+  <tr><td>
+  <a href="/help/unbundle">
+  unbundle
+  </a>
+  </td><td>
+  apply one or more changegroup files
+  </td></tr>
+  <tr><td>
+  <a href="/help/verify">
+  verify
+  </a>
+  </td><td>
+  verify the integrity of the repository
+  </td></tr>
+  <tr><td>
+  <a href="/help/version">
+  version
+  </a>
+  </td><td>
+  output version and copyright information
+  </td></tr>
+  </table>
+  </div>
+  </div>
+  
+  <script type="text/javascript">process_dates()</script>
+  
+  
+  </body>
+  </html>
+  
+
+  $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT "help/add"
+  200 Script output follows
+  
+  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
+  <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" />
+  <script type="text/javascript" src="/static/mercurial.js"></script>
+  
+  <title>Help: add</title>
+  </head>
+  <body>
+  
+  <div class="container">
+  <div class="menu">
+  <div class="logo">
+  <a href="http://mercurial.selenic.com/">
+  <img src="/static/hglogo.png" 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>
+  <li><a href="/bookmarks">bookmarks</a></li>
+  <li><a href="/branches">branches</a></li>
+  </ul>
+  <ul>
+   <li class="active"><a href="/help">help</a></li>
+  </ul>
+  </div>
+  
+  <div class="main">
+  <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
+  <h3>Help: add</h3>
+  
+  <form class="search" action="/log">
+  
+  <p><input name="rev" id="search1" type="text" size="30" /></p>
+  <div id="hint">find changesets by author, revision,
+  files, or words in the commit message</div>
+  </form>
+  <div id="doc">
+  <p>
+  hg add [OPTION]... [FILE]...
+  </p>
+  <p>
+  add the specified files on the next commit
+  </p>
+  <p>
+  Schedule files to be version controlled and added to the
+  repository.
+  </p>
+  <p>
+  The files will be added to the repository at the next commit. To
+  undo an add before that, see &quot;hg forget&quot;.
+  </p>
+  <p>
+  If no names are given, add all files to the repository.
+  </p>
+  <p>
+  Returns 0 if all files are successfully added.
+  </p>
+  <p>
+  options:
+  </p>
+  <table>
+  <tr><td>-I</td>
+  <td>--include PATTERN [+]</td>
+  <td>include names matching the given patterns</td></tr>
+  <tr><td>-X</td>
+  <td>--exclude PATTERN [+]</td>
+  <td>exclude names matching the given patterns</td></tr>
+  <tr><td>-S</td>
+  <td>--subrepos</td>
+  <td>recurse into subrepositories</td></tr>
+  <tr><td>-n</td>
+  <td>--dry-run</td>
+  <td>do not perform actions, just print output</td></tr>
+  </table>
+  <p>
+  [+] marked option can be specified multiple times
+  </p>
+  <p>
+  global options:
+  </p>
+  <table>
+  <tr><td>-R</td>
+  <td>--repository REPO</td>
+  <td>repository root directory or name of overlay bundle file</td></tr>
+  <tr><td></td>
+  <td>--cwd DIR</td>
+  <td>change working directory</td></tr>
+  <tr><td>-y</td>
+  <td>--noninteractive</td>
+  <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
+  <tr><td>-q</td>
+  <td>--quiet</td>
+  <td>suppress output</td></tr>
+  <tr><td>-v</td>
+  <td>--verbose</td>
+  <td>enable additional output</td></tr>
+  <tr><td></td>
+  <td>--config CONFIG [+]</td>
+  <td>set/override config option (use 'section.name=value')</td></tr>
+  <tr><td></td>
+  <td>--debug</td>
+  <td>enable debugging output</td></tr>
+  <tr><td></td>
+  <td>--debugger</td>
+  <td>start debugger</td></tr>
+  <tr><td></td>
+  <td>--encoding ENCODE</td>
+  <td>set the charset encoding (default: ascii)</td></tr>
+  <tr><td></td>
+  <td>--encodingmode MODE</td>
+  <td>set the charset encoding mode (default: strict)</td></tr>
+  <tr><td></td>
+  <td>--traceback</td>
+  <td>always print a traceback on exception</td></tr>
+  <tr><td></td>
+  <td>--time</td>
+  <td>time how long the command takes</td></tr>
+  <tr><td></td>
+  <td>--profile</td>
+  <td>print command execution profile</td></tr>
+  <tr><td></td>
+  <td>--version</td>
+  <td>output version information and exit</td></tr>
+  <tr><td>-h</td>
+  <td>--help</td>
+  <td>display help and exit</td></tr>
+  <tr><td></td>
+  <td>--hidden</td>
+  <td>consider hidden changesets</td></tr>
+  </table>
+  <p>
+  [+] marked option can be specified multiple times
+  </p>
+  
+  </div>
+  </div>
+  </div>
+  
+  <script type="text/javascript">process_dates()</script>
+  
+  
+  </body>
+  </html>
+  
+
+  $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT "help/remove"
+  200 Script output follows
+  
+  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
+  <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" />
+  <script type="text/javascript" src="/static/mercurial.js"></script>
+  
+  <title>Help: remove</title>
+  </head>
+  <body>
+  
+  <div class="container">
+  <div class="menu">
+  <div class="logo">
+  <a href="http://mercurial.selenic.com/">
+  <img src="/static/hglogo.png" 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>
+  <li><a href="/bookmarks">bookmarks</a></li>
+  <li><a href="/branches">branches</a></li>
+  </ul>
+  <ul>
+   <li class="active"><a href="/help">help</a></li>
+  </ul>
+  </div>
+  
+  <div class="main">
+  <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
+  <h3>Help: remove</h3>
+  
+  <form class="search" action="/log">
+  
+  <p><input name="rev" id="search1" type="text" size="30" /></p>
+  <div id="hint">find changesets by author, revision,
+  files, or words in the commit message</div>
+  </form>
+  <div id="doc">
+  <p>
+  hg remove [OPTION]... FILE...
+  </p>
+  <p>
+  aliases: rm
+  </p>
+  <p>
+  remove the specified files on the next commit
+  </p>
+  <p>
+  Schedule the indicated files for removal from the current branch.
+  </p>
+  <p>
+  This command schedules the files to be removed at the next commit.
+  To undo a remove before that, see &quot;hg revert&quot;. To undo added
+  files, see &quot;hg forget&quot;.
+  </p>
+  <p>
+  Returns 0 on success, 1 if any warnings encountered.
+  </p>
+  <p>
+  options:
+  </p>
+  <table>
+  <tr><td>-A</td>
+  <td>--after</td>
+  <td>record delete for missing files</td></tr>
+  <tr><td>-f</td>
+  <td>--force</td>
+  <td>remove (and delete) file even if added or modified</td></tr>
+  <tr><td>-I</td>
+  <td>--include PATTERN [+]</td>
+  <td>include names matching the given patterns</td></tr>
+  <tr><td>-X</td>
+  <td>--exclude PATTERN [+]</td>
+  <td>exclude names matching the given patterns</td></tr>
+  </table>
+  <p>
+  [+] marked option can be specified multiple times
+  </p>
+  <p>
+  global options:
+  </p>
+  <table>
+  <tr><td>-R</td>
+  <td>--repository REPO</td>
+  <td>repository root directory or name of overlay bundle file</td></tr>
+  <tr><td></td>
+  <td>--cwd DIR</td>
+  <td>change working directory</td></tr>
+  <tr><td>-y</td>
+  <td>--noninteractive</td>
+  <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
+  <tr><td>-q</td>
+  <td>--quiet</td>
+  <td>suppress output</td></tr>
+  <tr><td>-v</td>
+  <td>--verbose</td>
+  <td>enable additional output</td></tr>
+  <tr><td></td>
+  <td>--config CONFIG [+]</td>
+  <td>set/override config option (use 'section.name=value')</td></tr>
+  <tr><td></td>
+  <td>--debug</td>
+  <td>enable debugging output</td></tr>
+  <tr><td></td>
+  <td>--debugger</td>
+  <td>start debugger</td></tr>
+  <tr><td></td>
+  <td>--encoding ENCODE</td>
+  <td>set the charset encoding (default: ascii)</td></tr>
+  <tr><td></td>
+  <td>--encodingmode MODE</td>
+  <td>set the charset encoding mode (default: strict)</td></tr>
+  <tr><td></td>
+  <td>--traceback</td>
+  <td>always print a traceback on exception</td></tr>
+  <tr><td></td>
+  <td>--time</td>
+  <td>time how long the command takes</td></tr>
+  <tr><td></td>
+  <td>--profile</td>
+  <td>print command execution profile</td></tr>
+  <tr><td></td>
+  <td>--version</td>
+  <td>output version information and exit</td></tr>
+  <tr><td>-h</td>
+  <td>--help</td>
+  <td>display help and exit</td></tr>
+  <tr><td></td>
+  <td>--hidden</td>
+  <td>consider hidden changesets</td></tr>
+  </table>
+  <p>
+  [+] marked option can be specified multiple times
+  </p>
+  
+  </div>
+  </div>
+  </div>
+  
+  <script type="text/javascript">process_dates()</script>
+  
+  
+  </body>
+  </html>
+  
+
+  $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT "help/revisions"
+  200 Script output follows
+  
+  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
+  <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" />
+  <script type="text/javascript" src="/static/mercurial.js"></script>
+  
+  <title>Help: revisions</title>
+  </head>
+  <body>
+  
+  <div class="container">
+  <div class="menu">
+  <div class="logo">
+  <a href="http://mercurial.selenic.com/">
+  <img src="/static/hglogo.png" 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>
+  <li><a href="/bookmarks">bookmarks</a></li>
+  <li><a href="/branches">branches</a></li>
+  </ul>
+  <ul>
+   <li class="active"><a href="/help">help</a></li>
+  </ul>
+  </div>
+  
+  <div class="main">
+  <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
+  <h3>Help: revisions</h3>
+  
+  <form class="search" action="/log">
+  
+  <p><input name="rev" id="search1" type="text" size="30" /></p>
+  <div id="hint">find changesets by author, revision,
+  files, or words in the commit message</div>
+  </form>
+  <div id="doc">
+  <h1>Specifying Single Revisions</h1>
+  <p>
+  Mercurial supports several ways to specify individual revisions.
+  </p>
+  <p>
+  A plain integer is treated as a revision number. Negative integers are
+  treated as sequential offsets from the tip, with -1 denoting the tip,
+  -2 denoting the revision prior to the tip, and so forth.
+  </p>
+  <p>
+  A 40-digit hexadecimal string is treated as a unique revision
+  identifier.
+  </p>
+  <p>
+  A hexadecimal string less than 40 characters long is treated as a
+  unique revision identifier and is referred to as a short-form
+  identifier. A short-form identifier is only valid if it is the prefix
+  of exactly one full-length identifier.
+  </p>
+  <p>
+  Any other string is treated as a bookmark, tag, or branch name. A
+  bookmark is a movable pointer to a revision. A tag is a permanent name
+  associated with a revision. A branch name denotes the tipmost revision
+  of that branch. Bookmark, tag, and branch names must not contain the &quot;:&quot;
+  character.
+  </p>
+  <p>
+  The reserved name &quot;tip&quot; always identifies the most recent revision.
+  </p>
+  <p>
+  The reserved name &quot;null&quot; indicates the null revision. This is the
+  revision of an empty repository, and the parent of revision 0.
+  </p>
+  <p>
+  The reserved name &quot;.&quot; indicates the working directory parent. If no
+  working directory is checked out, it is equivalent to null. If an
+  uncommitted merge is in progress, &quot;.&quot; is the revision of the first
+  parent.
+  </p>
+  
+  </div>
+  </div>
+  </div>
+  
+  <script type="text/javascript">process_dates()</script>
+  
+  
+  </body>
+  </html>
+  
+
+  $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
+
+#endif
--- a/tests/test-hgk.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-hgk.t	Wed Apr 03 13:03:50 2013 -0500
@@ -13,6 +13,7 @@
   author test 0 0
   revision 0
   branch default
+  phase draft
   
   adda
 
--- a/tests/test-hgweb-no-path-info.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-hgweb-no-path-info.t	Wed Apr 03 13:03:50 2013 -0500
@@ -39,6 +39,7 @@
   >     'wsgi.multiprocess': False,
   >     'wsgi.run_once': False,
   >     'REQUEST_METHOD': 'GET',
+  >     'PATH_INFO': '/',
   >     'SCRIPT_NAME': '',
   >     'SERVER_NAME': '127.0.0.1',
   >     'SERVER_PORT': os.environ['HGPORT'],
@@ -49,6 +50,7 @@
   >     content = app(env, startrsp)
   >     sys.stdout.write(output.getvalue())
   >     sys.stdout.write(''.join(content))
+  >     getattr(content, 'close', lambda : None)()
   >     print '---- ERRORS'
   >     print errors.getvalue()
   > 
@@ -101,7 +103,7 @@
   [('Content-Type', 'text/plain; charset=ascii')]
   ---- DATA
   
-  repo/
+  /repo/
   
   ---- ERRORS
   
--- a/tests/test-hgweb-no-request-uri.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-hgweb-no-request-uri.t	Wed Apr 03 13:03:50 2013 -0500
@@ -49,6 +49,7 @@
   >     content = app(env, startrsp)
   >     sys.stdout.write(output.getvalue())
   >     sys.stdout.write(''.join(content))
+  >     getattr(content, 'close', lambda : None)()
   >     print '---- ERRORS'
   >     print errors.getvalue()
   > 
--- a/tests/test-hgweb-raw.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-hgweb-raw.t	Wed Apr 03 13:03:50 2013 -0500
@@ -19,7 +19,7 @@
   $ cat hg.pid >> $DAEMON_PIDS
   $ ("$TESTDIR/get-with-headers.py" localhost:$HGPORT '?f=bf0ff59095c9;file=sub/some%20text%25.txt;style=raw' content-type content-length content-disposition) >getoutput.txt
 
-  $ while kill `cat hg.pid` 2>/dev/null; do sleep 0; done
+  $ "$TESTDIR/killdaemons.py" hg.pid
 
   $ cat getoutput.txt
   200 Script output follows
@@ -40,7 +40,7 @@
 
   $ cat hg.pid >> $DAEMON_PIDS
   $ ("$TESTDIR/get-with-headers.py" localhost:$HGPORT '?f=bf0ff59095c9;file=sub/some%20text%25.txt;style=raw' content-type content-length content-disposition) >getoutput.txt
-  $ while kill `cat hg.pid` 2>/dev/null; do sleep 0; done
+  $ "$TESTDIR/killdaemons.py" hg.pid
 
   $ cat getoutput.txt
   200 Script output follows
--- a/tests/test-histedit-edit.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-histedit-edit.t	Wed Apr 03 13:03:50 2013 -0500
@@ -73,7 +73,7 @@
   $ hg up 0
   0 files updated, 0 files merged, 3 files removed, 0 files unresolved
   $ HGEDITOR='echo foobaz > ' hg histedit --continue
-  abort: working directory parent is not a descendant of 055a42cdd887
+  abort: 055a42cdd887 is not an ancestor of working directory
   (update to 055a42cdd887 or descendant and run "hg histedit --continue" again)
   [255]
   $ hg up 3
--- a/tests/test-histedit-fold.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-histedit-fold.t	Wed Apr 03 13:03:50 2013 -0500
@@ -295,6 +295,7 @@
   # HG changeset patch
   # User test
   # Date 0 0
+  #      Thu Jan 01 00:00:00 1970 +0000
   # Node ID 10c647b2cdd54db0603ecb99b2ff5ce66d5a5323
   # Parent  0189ba417d34df9dda55f88b637dcae9917b5964
   +4
--- a/tests/test-histedit-revspec.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-histedit-revspec.t	Wed Apr 03 13:03:50 2013 -0500
@@ -65,5 +65,5 @@
   $ hg up 2
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg histedit -r 4
-  nothing to edit
-  [1]
+  abort: 08d98a8350f3 is not an ancestor of working directory
+  [255]
--- a/tests/test-hook.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-hook.t	Wed Apr 03 13:03:50 2013 -0500
@@ -198,7 +198,6 @@
   listkeys hook: HG_NAMESPACE=bookmarks HG_VALUES={'bar': '0000000000000000000000000000000000000000', 'foo': '0000000000000000000000000000000000000000'}
   no changes found
   listkeys hook: HG_NAMESPACE=phases HG_VALUES={'cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b': '1', 'publishing': 'True'}
-  listkeys hook: HG_NAMESPACE=bookmarks HG_VALUES={'bar': '0000000000000000000000000000000000000000', 'foo': '0000000000000000000000000000000000000000'}
   adding remote bookmark bar
   importing bookmark bar
   $ cd ../a
@@ -232,6 +231,7 @@
   abort: prelistkeys hook exited with status 1
   [255]
   $ cd ../a
+  $ rm .hg/hgrc
 
 prechangegroup hook can prevent incoming changes
 
--- a/tests/test-https.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-https.t	Wed Apr 03 13:03:50 2013 -0500
@@ -106,7 +106,7 @@
 
 #if windows
   $ hg serve -p $HGPORT --certificate=$PRIV 2>&1
-  abort: cannot start server at ':$HGPORT': (glob)
+  abort: cannot start server at ':$HGPORT':
   [255]
 #else
   $ hg serve -p $HGPORT --certificate=$PRIV 2>&1
@@ -233,11 +233,13 @@
   (check hostfingerprint configuration)
   [255]
 
+
 - ignores that certificate doesn't match hostname
   $ hg -R copy-pull id https://127.0.0.1:$HGPORT/
   5fed3813f7f5
 
-  $ while kill `cat hg1.pid` 2>/dev/null; do sleep 0; done
+HGPORT1 is reused below for tinyproxy tests. Kill that server.
+  $ "$TESTDIR/killdaemons.py" hg1.pid
 
 Prepare for connecting through proxy
 
--- a/tests/test-import-merge.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-import-merge.t	Wed Apr 03 13:03:50 2013 -0500
@@ -113,3 +113,41 @@
   $ hg strip --no-backup tip
 
   $ cd ..
+
+Test that --exact on a bad header doesn't corrupt the repo (issue3616)
+
+  $ hg init repo3
+  $ cd repo3
+  $ echo a>a
+  $ hg ci -Aqm0
+  $ echo a>>a
+  $ hg ci -m1
+  $ echo a>>a
+  $ hg ci -m2
+  $ echo a>a
+  $ echo b>>a
+  $ echo a>>a
+  $ hg ci -m3
+  $ hg export 2 | head -7 > ../a.patch
+  $ hg export tip | tail -n +8 >> ../a.patch
+
+  $ cd ..
+  $ hg clone -qr0 repo3 repo3-clone
+  $ cd repo3-clone
+  $ hg pull -qr1 ../repo3
+
+  $ hg import --exact ../a.patch
+  applying ../a.patch
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  patching file a
+  Hunk #1 succeeded at 1 with fuzz 1 (offset -1 lines).
+  transaction abort!
+  rollback completed
+  abort: patch is damaged or loses information
+  [255]
+  $ hg verify
+  checking changesets
+  checking manifests
+  crosschecking files in changesets and manifests
+  checking files
+  1 files, 2 changesets, 2 total revisions
--- a/tests/test-import.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-import.t	Wed Apr 03 13:03:50 2013 -0500
@@ -34,7 +34,7 @@
   $ hg --cwd b import ../exported-tip.patch
   applying ../exported-tip.patch
 
-message and committer should be same
+message and committer and date should be same
 
   $ hg --cwd b tip
   changeset:   1:1d4bd90af0e4
@@ -853,6 +853,7 @@
   # HG changeset patch
   # User User B
   # Date 0 0
+  #      Thu Jan 01 00:00:00 1970 +0000
   # Node ID eb56ab91903632294ac504838508cb370c0901d2
   # Parent  0000000000000000000000000000000000000000
   from: tricky!
--- a/tests/test-inotify-debuginotify.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-inotify-debuginotify.t	Wed Apr 03 13:03:50 2013 -0500
@@ -38,4 +38,4 @@
   directories being watched:
     /
     .hg/
-  $ kill `cat hg.pid`
+  $ "$TESTDIR/killdaemons.py" hg.pid
--- a/tests/test-inotify-issue1371.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-inotify-issue1371.t	Wed Apr 03 13:03:50 2013 -0500
@@ -41,4 +41,4 @@
 
 Are we able to kill the service? if not, the service died on some error
 
-  $ kill `cat hg.pid`
+  $ "$TESTDIR/killdaemons.py" hg.pid
--- a/tests/test-inotify-issue1542.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-inotify-issue1542.t	Wed Apr 03 13:03:50 2013 -0500
@@ -33,4 +33,4 @@
 
 Are we able to kill the service? if not, the service died on some error
 
-  $ kill `cat hg.pid`
+  $ "$TESTDIR/killdaemons.py" hg.pid
--- a/tests/test-inotify-issue1556.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-inotify-issue1556.t	Wed Apr 03 13:03:50 2013 -0500
@@ -28,4 +28,4 @@
 
 Are we able to kill the service? if not, the service died on some error
 
-  $ kill `cat hg.pid`
+  $ "$TESTDIR/killdaemons.py" hg.pid
--- a/tests/test-inotify-lookup.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-inotify-lookup.t	Wed Apr 03 13:03:50 2013 -0500
@@ -11,4 +11,4 @@
   $ hg st
   $ cat a
   a
-  $ kill `cat .hg/inotify.pid`
+  $ "$TESTDIR/killdaemons.py" .hg/inotify.pid
--- a/tests/test-inotify.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-inotify.t	Wed Apr 03 13:03:50 2013 -0500
@@ -32,7 +32,7 @@
 
 make sure that pidfile worked. Output should be silent.
 
-  $ kill `cat ../hg2.pid`
+  $ "$TESTDIR/killdaemons.py" ../hg2.pid
   $ cd ../repo1
 
 inserve
@@ -157,7 +157,7 @@
 build/x & build/y shouldn't appear in "hg st"
 
   $ hg st
-  $ kill `cat hg.pid`
+  $ "$TESTDIR/killdaemons.py" hg.pid
 
   $ cd ..
 
@@ -179,4 +179,4 @@
   abort: inotify-server: cannot start: socket is already bound
   [255]
 
-  $ kill `cat hg3.pid`
+  $ "$TESTDIR/killdaemons.py" hg3.pid
--- a/tests/test-interhg.t	Tue Apr 02 16:03:10 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-  $ "$TESTDIR/hghave" serve || exit 80
-
-  $ hg init test
-  $ cd test
-
-  $ cat > .hg/hgrc <<EOF
-  > [extensions]
-  > interhg =
-  > 
-  > [interhg]
-  > issues = s|Issue(\d+)|<a href="http://bts.example.org/issue\1">Issue\1</a>|
-  > 
-  > # yes, 'x' is a weird delimiter...
-  > markbugs = sxbugx<i class="\x">bug</i>x
-  > EOF
-
-  $ touch foo
-  $ hg add foo
-  $ hg commit -d '1 0' -m 'Issue123: fixed the bug!'
-
-  $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
-  $ cat hg.pid >> $DAEMON_PIDS
-
-log
-
-  $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT '' | grep bts
-    <td class="description"><a href="/rev/1b0e7ece6bd6"><a href="http://bts.example.org/issue123">Issue123</a>: fixed the <i class="x">bug</i>!</a><span class="branchhead">default</span> <span class="tag">tip</span> </td>
-
-errors
-
-  $ cat errors.log
-
-  $ cd ..
--- a/tests/test-issue1175.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-issue1175.t	Wed Apr 03 13:03:50 2013 -0500
@@ -44,6 +44,7 @@
   # HG changeset patch
   # User test
   # Date 0 0
+  #      Thu Jan 01 00:00:00 1970 +0000
   # Node ID 732aafbecb501a198b3cc9323ad3899ff04ccf95
   # Parent  1d1625283f71954f21d14c3d44d0ad3c019c597f
   5
--- a/tests/test-issue1802.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-issue1802.t	Wed Apr 03 13:03:50 2013 -0500
@@ -55,7 +55,7 @@
     unmatched files in local:
      b
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: a03b0deabf2b, local: d6fa54f68ae1+, remote: 2d8bcf2dda39
    a: update permissions -> e
   updating: a 1/1 files (100.00%)
--- a/tests/test-issue522.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-issue522.t	Wed Apr 03 13:03:50 2013 -0500
@@ -29,11 +29,11 @@
     unmatched files in local:
      bar
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: bbd179dfa0a7, local: 71766447bdbb+, remote: 4d9e78aaceee
    foo: remote is newer -> g
+  getting foo
   updating: foo 1/1 files (100.00%)
-  getting foo
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
 
--- a/tests/test-issue672.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-issue672.t	Wed Apr 03 13:03:50 2013 -0500
@@ -32,14 +32,13 @@
      src: '1' -> dst: '1a' 
     checking for directory renames
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: 81f4b099af3d, local: c64f439569a9+, remote: c12dcd37c90a
    1: other deleted -> r
    1a: remote created -> g
-  updating: 1 1/2 files (50.00%)
   removing 1
+  getting 1a
   updating: 1a 2/2 files (100.00%)
-  getting 1a
   1 files updated, 0 files merged, 1 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
 
@@ -63,10 +62,10 @@
      src: '1' -> dst: '1a' *
     checking for directory renames
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: c64f439569a9, local: e327dca35ac8+, remote: 746e9549ea96
    1a: local copied/moved to 1 -> m
-  preserving 1a for resolve of 1a
+    preserving 1a for resolve of 1a
   updating: 1a 1/1 files (100.00%)
   picked tool 'internal:merge' for 1a (binary False symlink False)
   merging 1a and 1 to 1a
@@ -86,10 +85,10 @@
      src: '1' -> dst: '1a' *
     checking for directory renames
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: c64f439569a9, local: 746e9549ea96+, remote: e327dca35ac8
    1: remote moved to 1a -> m
-  preserving 1 for resolve of 1a
+    preserving 1 for resolve of 1a
   removing 1
   updating: 1 1/1 files (100.00%)
   picked tool 'internal:merge' for 1a (binary False symlink False)
--- a/tests/test-keyword.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-keyword.t	Wed Apr 03 13:03:50 2013 -0500
@@ -528,6 +528,7 @@
   # HG changeset patch
   # User User Name <user@example.com>
   # Date 1 0
+  #      Thu Jan 01 00:00:01 1970 +0000
   # Node ID 40a904bbbe4cd4ab0a1f28411e35db26341a40ad
   # Parent  ef63ca68695bc9495032c6fda1350c71e6d256e9
   cndiff
--- a/tests/test-largefiles-cache.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-largefiles-cache.t	Wed Apr 03 13:03:50 2013 -0500
@@ -40,8 +40,6 @@
   adding file changes
   added 2 changesets with 1 changes to 1 files
   (run 'hg update' to get a working copy)
-  caching new largefiles
-  0 largefiles cached
 
 Update working directory to "tip", which requires largefile("large"),
 but there is no cache file for it.  So, hg must treat it as
@@ -83,8 +81,6 @@
   adding file changes
   added 1 changesets with 1 changes to 1 files
   (run 'hg update' to get a working copy)
-  caching new largefiles
-  1 largefiles cached
 
 #if unix-permissions
 
--- a/tests/test-largefiles.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-largefiles.t	Wed Apr 03 13:03:50 2013 -0500
@@ -883,9 +883,7 @@
   adding file changes
   added 6 changesets with 16 changes to 8 files
   (run 'hg update' to get a working copy)
-  caching new largefiles
-  3 largefiles cached
-  3 additional largefiles cached
+  6 additional largefiles cached
   $ cd ..
 
 Rebasing between two repositories does not revert largefiles to old
@@ -969,8 +967,6 @@
   adding file changes
   added 1 changesets with 2 changes to 2 files (+1 heads)
   (run 'hg heads' to see heads, 'hg merge' to merge)
-  caching new largefiles
-  0 largefiles cached
   $ hg rebase
   Invoking status precommit hook
   M sub/normal4
@@ -1205,20 +1201,14 @@
   checking files
   10 files, 10 changesets, 28 total revisions
   searching 1 changesets for largefiles
-  changeset 9:598410d3eb9a: sub/large4 missing
-    (looked for hash e166e74c7303192238d60af5a9c4ce9bef0b7928)
+  changeset 9:598410d3eb9a: sub/large4 references missing $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 (glob)
   verified existence of 3 revisions of 3 largefiles
   [1]
 
 - introduce corruption and make sure that it is caught when checking content:
   $ echo '5 cents' > $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928
   $ hg verify -q --large --lfc
-  searching 1 changesets for largefiles
-  changeset 9:598410d3eb9a: sub/large4: contents differ
-    ($TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928: (glob)
-    expected hash e166e74c7303192238d60af5a9c4ce9bef0b7928,
-    but got 1f19b76d5b3cad1472c87efb42b582c97e040060)
-  verified contents of 3 revisions of 3 largefiles
+  changeset 9:598410d3eb9a: sub/large4 references corrupted $TESTTMP/d/.hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 (glob)
   [1]
 
 - cleanup
@@ -1226,37 +1216,17 @@
 
 - verifying all revisions will fail because we didn't clone all largefiles to d:
   $ echo 'T-shirt' > $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4
-  $ hg verify -q --large --lfa --lfc
-  searching 10 changesets for largefiles
-  changeset 0:30d30fe6a5be: large1 missing
-    (looked for hash 4669e532d5b2c093a78eca010077e708a071bb64)
-  changeset 0:30d30fe6a5be: sub/large2 missing
-    (looked for hash 1deebade43c8c498a3c8daddac0244dc55d1331d)
-  changeset 1:ce8896473775: large1 missing
-    (looked for hash 5f78770c0e77ba4287ad6ef3071c9bf9c379742f)
-  changeset 1:ce8896473775: sub/large2: contents differ
-    ($TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4: (glob)
-    expected hash eb7338044dc27f9bc59b8dd5a246b065ead7a9c4,
-    but got cfef678f24d3e339944138ecdd8fd85ca21d820f)
-  changeset 3:9e8fbc4bce62: large1: contents differ
-    ($TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4: (glob)
-    expected hash eb7338044dc27f9bc59b8dd5a246b065ead7a9c4,
-    but got cfef678f24d3e339944138ecdd8fd85ca21d820f)
-  changeset 4:74c02385b94c: large3: contents differ
-    ($TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4: (glob)
-    expected hash eb7338044dc27f9bc59b8dd5a246b065ead7a9c4,
-    but got cfef678f24d3e339944138ecdd8fd85ca21d820f)
-  changeset 4:74c02385b94c: sub/large4: contents differ
-    ($TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4: (glob)
-    expected hash eb7338044dc27f9bc59b8dd5a246b065ead7a9c4,
-    but got cfef678f24d3e339944138ecdd8fd85ca21d820f)
-  changeset 5:9d5af5072dbd: large3 missing
-    (looked for hash baaf12afde9d8d67f25dab6dced0d2bf77dba47c)
-  changeset 5:9d5af5072dbd: sub/large4 missing
-    (looked for hash aeb2210d19f02886dde00dac279729a48471e2f9)
-  changeset 6:4355d653f84f: large3 missing
-    (looked for hash 7838695e10da2bb75ac1156565f40a2595fa2fa0)
-  verified contents of 15 revisions of 6 largefiles
+  $ hg verify -q --lfa --lfc
+  changeset 0:30d30fe6a5be: large1 references missing $TESTTMP/d/.hg/largefiles/4669e532d5b2c093a78eca010077e708a071bb64 (glob)
+  changeset 0:30d30fe6a5be: sub/large2 references missing $TESTTMP/d/.hg/largefiles/1deebade43c8c498a3c8daddac0244dc55d1331d (glob)
+  changeset 1:ce8896473775: large1 references missing $TESTTMP/d/.hg/largefiles/5f78770c0e77ba4287ad6ef3071c9bf9c379742f (glob)
+  changeset 1:ce8896473775: sub/large2 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
+  changeset 3:9e8fbc4bce62: large1 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
+  changeset 4:74c02385b94c: large3 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
+  changeset 4:74c02385b94c: sub/large4 references corrupted $TESTTMP/d/.hg/largefiles/eb7338044dc27f9bc59b8dd5a246b065ead7a9c4 (glob)
+  changeset 5:9d5af5072dbd: large3 references missing $TESTTMP/d/.hg/largefiles/baaf12afde9d8d67f25dab6dced0d2bf77dba47c (glob)
+  changeset 5:9d5af5072dbd: sub/large4 references missing $TESTTMP/d/.hg/largefiles/aeb2210d19f02886dde00dac279729a48471e2f9 (glob)
+  changeset 6:4355d653f84f: large3 references missing $TESTTMP/d/.hg/largefiles/7838695e10da2bb75ac1156565f40a2595fa2fa0 (glob)
   [1]
 
 - cleanup
@@ -1323,8 +1293,6 @@
   pulling from $TESTTMP/d (glob)
   searching for changes
   no changes found
-  caching new largefiles
-  0 largefiles cached
   0 additional largefiles cached
 
 Merging does not revert to old versions of largefiles and also check
@@ -1354,7 +1322,8 @@
   $ hg commit -m "Modify large4 to test merge"
   Invoking status precommit hook
   M sub/large4
-  $ hg pull ../e
+# Test --cache-largefiles flag
+  $ hg pull --cache-largefiles ../e
   pulling from ../e
   searching for changes
   adding changesets
@@ -1362,7 +1331,7 @@
   adding file changes
   added 2 changesets with 4 changes to 4 files (+1 heads)
   (run 'hg heads' to see heads, 'hg merge' to merge)
-  caching new largefiles
+  caching largefiles for 1 heads
   2 largefiles cached
   $ hg merge
   merging sub/large4
@@ -1730,8 +1699,6 @@
   [1]
   $ mv 02a439e5c31c526465ab1a0ca1f431f76b827b90 empty/.hg/largefiles/
   $ hg -R http-clone -q verify --large --lfa
-  searching 1 changesets for largefiles
-  verified existence of 1 revisions of 1 largefiles
 
 largefiles pulled on update - a largefile missing on the server:
   $ mv empty/.hg/largefiles/02a439e5c31c526465ab1a0ca1f431f76b827b90 .
@@ -1767,11 +1734,11 @@
   $ mv 02a439e5c31c526465ab1a0ca1f431f76b827b90 empty/.hg/largefiles/
   $ hg -R http-clone --debug up --config largefiles.usercache=http-clone-usercache
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: False, force: False, partial: False
    ancestor: 000000000000, local: 000000000000+, remote: cf03e5bb9936
    .hglf/f1: remote created -> g
+  getting .hglf/f1
   updating: .hglf/f1 1/1 files (100.00%)
-  getting .hglf/f1
   getting changed largefiles
   using http://localhost:$HGPORT2/
   sending capabilities command
--- a/tests/test-lfconvert.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-lfconvert.t	Wed Apr 03 13:03:50 2013 -0500
@@ -317,18 +317,12 @@
   checking files
   8 files, 7 changesets, 12 total revisions
   searching 7 changesets for largefiles
-  changeset 0:d4892ec57ce2: large missing
-    (looked for hash 2e000fa7e85759c7f4c254d4d9c33ef481e459a7)
-  changeset 1:334e5237836d: sub/maybelarge.dat missing
-    (looked for hash 34e163be8e43c5631d8b92e9c43ab0bf0fa62b9c)
-  changeset 2:261ad3f3f037: stuff/maybelarge.dat missing
-    (looked for hash 34e163be8e43c5631d8b92e9c43ab0bf0fa62b9c)
-  changeset 3:55759520c76f: sub/maybelarge.dat missing
-    (looked for hash 76236b6a2c6102826c61af4297dd738fb3b1de38)
-  changeset 5:9cc5aa7204f0: stuff/maybelarge.dat missing
-    (looked for hash 76236b6a2c6102826c61af4297dd738fb3b1de38)
-  changeset 6:17126745edfd: anotherlarge missing
-    (looked for hash 3b71f43ff30f4b15b5cd85dd9e95ebc7e84eb5a3)
+  changeset 0:d4892ec57ce2: large references missing $TESTTMP/largefiles-repo-hg/.hg/largefiles/2e000fa7e85759c7f4c254d4d9c33ef481e459a7 (glob)
+  changeset 1:334e5237836d: sub/maybelarge.dat references missing $TESTTMP/largefiles-repo-hg/.hg/largefiles/34e163be8e43c5631d8b92e9c43ab0bf0fa62b9c (glob)
+  changeset 2:261ad3f3f037: stuff/maybelarge.dat references missing $TESTTMP/largefiles-repo-hg/.hg/largefiles/34e163be8e43c5631d8b92e9c43ab0bf0fa62b9c (glob)
+  changeset 3:55759520c76f: sub/maybelarge.dat references missing $TESTTMP/largefiles-repo-hg/.hg/largefiles/76236b6a2c6102826c61af4297dd738fb3b1de38 (glob)
+  changeset 5:9cc5aa7204f0: stuff/maybelarge.dat references missing $TESTTMP/largefiles-repo-hg/.hg/largefiles/76236b6a2c6102826c61af4297dd738fb3b1de38 (glob)
+  changeset 6:17126745edfd: anotherlarge references missing $TESTTMP/largefiles-repo-hg/.hg/largefiles/3b71f43ff30f4b15b5cd85dd9e95ebc7e84eb5a3 (glob)
   verified existence of 6 revisions of 4 largefiles
   [1]
   $ hg -R largefiles-repo-hg showconfig paths
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-lrucachedict.py	Wed Apr 03 13:03:50 2013 -0500
@@ -0,0 +1,35 @@
+from mercurial import util
+
+def printifpresent(d, xs):
+    for x in xs:
+        present = x in d
+        print "'%s' in d: %s" % (x, present)
+        if present:
+            print "d['%s']: %s" % (x, d[x])
+
+def test_lrucachedict():
+    d = util.lrucachedict(4)
+    d['a'] = 'va'
+    d['b'] = 'vb'
+    d['c'] = 'vc'
+    d['d'] = 'vd'
+
+    # all of these should be present
+    printifpresent(d, ['a', 'b', 'c', 'd'])
+
+    # 'a' should be dropped because it was least recently used
+    d['e'] = 've'
+    printifpresent(d, ['a', 'b', 'c', 'd', 'e'])
+
+    # touch entries in some order (get or set).
+    d['e']
+    d['c'] = 'vc2'
+    d['d']
+    d['b'] = 'vb2'
+
+    # 'e' should be dropped now
+    d['f'] = 'vf'
+    printifpresent(d, ['b', 'c', 'd', 'e', 'f'])
+
+if __name__ == '__main__':
+    test_lrucachedict()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-lrucachedict.py.out	Wed Apr 03 13:03:50 2013 -0500
@@ -0,0 +1,26 @@
+'a' in d: True
+d['a']: va
+'b' in d: True
+d['b']: vb
+'c' in d: True
+d['c']: vc
+'d' in d: True
+d['d']: vd
+'a' in d: False
+'b' in d: True
+d['b']: vb
+'c' in d: True
+d['c']: vc
+'d' in d: True
+d['d']: vd
+'e' in d: True
+d['e']: ve
+'b' in d: True
+d['b']: vb2
+'c' in d: True
+d['c']: vc2
+'d' in d: True
+d['d']: vd
+'e' in d: False
+'f' in d: True
+d['f']: vf
--- a/tests/test-merge-commit.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-merge-commit.t	Wed Apr 03 13:03:50 2013 -0500
@@ -69,10 +69,10 @@
   $ hg --debug merge 3
     searching for copies back to rev 1
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: 0f2ff26688b9, local: 2263c1be0967+, remote: 0555950ead28
    bar: versions differ -> m
-  preserving bar for resolve of bar
+    preserving bar for resolve of bar
   updating: bar 1/1 files (100.00%)
   picked tool 'internal:merge' for bar (binary False symlink False)
   merging bar
@@ -156,10 +156,10 @@
   $ hg --debug merge 3
     searching for copies back to rev 1
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: 0f2ff26688b9, local: 2263c1be0967+, remote: 3ffa6b9e35f0
    bar: versions differ -> m
-  preserving bar for resolve of bar
+    preserving bar for resolve of bar
   updating: bar 1/1 files (100.00%)
   picked tool 'internal:merge' for bar (binary False symlink False)
   merging bar
--- a/tests/test-merge-prompt.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-merge-prompt.t	Wed Apr 03 13:03:50 2013 -0500
@@ -42,7 +42,7 @@
 Non-interactive merge:
 
   $ hg merge -y
-   local changed file1 which remote deleted
+  local changed file1 which remote deleted
   use (c)hanged version or (d)elete? c
   remote changed file2 which local deleted
   use (c)hanged version or leave (d)eleted? c
@@ -70,7 +70,7 @@
   > c
   > d
   > EOF
-   local changed file1 which remote deleted
+  local changed file1 which remote deleted
   use (c)hanged version or (d)elete? remote changed file2 which local deleted
   use (c)hanged version or leave (d)eleted? 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
@@ -97,11 +97,11 @@
   > baz
   > c
   > EOF
-   local changed file1 which remote deleted
+  local changed file1 which remote deleted
   use (c)hanged version or (d)elete? unrecognized response
-   local changed file1 which remote deleted
+  local changed file1 which remote deleted
   use (c)hanged version or (d)elete? unrecognized response
-   local changed file1 which remote deleted
+  local changed file1 which remote deleted
   use (c)hanged version or (d)elete? remote changed file2 which local deleted
   use (c)hanged version or leave (d)eleted? unrecognized response
   remote changed file2 which local deleted
@@ -126,7 +126,7 @@
   $ hg merge --config ui.interactive=true <<EOF
   > d
   > EOF
-   local changed file1 which remote deleted
+  local changed file1 which remote deleted
   use (c)hanged version or (d)elete? remote changed file2 which local deleted
   use (c)hanged version or leave (d)eleted? abort: response expected
   [255]
--- a/tests/test-merge-types.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-merge-types.t	Wed Apr 03 13:03:50 2013 -0500
@@ -32,10 +32,10 @@
   $ hg merge --debug
     searching for copies back to rev 1
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: c334dc3be0da, local: 521a1e40188f+, remote: 3574f3e69b1c
    a: versions differ -> m
-  preserving a for resolve of a
+    preserving a for resolve of a
   updating: a 1/1 files (100.00%)
   picked tool 'internal:merge' for a (binary False symlink True)
   merging a
@@ -65,10 +65,10 @@
   $ hg merge --debug
     searching for copies back to rev 1
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: c334dc3be0da, local: 3574f3e69b1c+, remote: 521a1e40188f
    a: versions differ -> m
-  preserving a for resolve of a
+    preserving a for resolve of a
   updating: a 1/1 files (100.00%)
   picked tool 'internal:merge' for a (binary False symlink True)
   merging a
@@ -99,10 +99,10 @@
   $ HGMERGE= hg up -y --debug
     searching for copies back to rev 2
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: False, force: False, partial: False
    ancestor: c334dc3be0da, local: c334dc3be0da+, remote: 521a1e40188f
    a: versions differ -> m
-  preserving a for resolve of a
+    preserving a for resolve of a
   updating: a 1/1 files (100.00%)
   (couldn't find merge tool hgmerge|tool hgmerge can't handle symlinks) (re)
   picked tool 'internal:prompt' for a (binary False symlink True)
--- a/tests/test-merge7.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-merge7.t	Wed Apr 03 13:03:50 2013 -0500
@@ -81,10 +81,10 @@
   $ hg merge --debug
     searching for copies back to rev 1
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: 96b70246a118, local: 50c3a7e29886+, remote: 40d11a4173a8
    test.txt: versions differ -> m
-  preserving test.txt for resolve of test.txt
+    preserving test.txt for resolve of test.txt
   updating: test.txt 1/1 files (100.00%)
   picked tool 'internal:merge' for test.txt (binary False symlink False)
   merging test.txt
--- a/tests/test-minirst.py.out	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-minirst.py.out	Wed Apr 03 13:03:50 2013 -0500
@@ -605,7 +605,7 @@
 html format:
 ----------------------------------------------------------------------
 <p>
-Please see "hg add".
+Please see &quot;hg add&quot;.
 </p>
 ----------------------------------------------------------------------
 
@@ -645,7 +645,7 @@
 <h1>Title</h1>
 <h2>Section</h2>
 <h3>Subsection</h3>
-<h2>Markup: "foo" and "hg help"</h2>
+<h2>Markup: &quot;foo&quot; and &quot;hg help&quot;</h2>
 ----------------------------------------------------------------------
 
 == admonitions ==
@@ -758,9 +758,15 @@
 html format:
 ----------------------------------------------------------------------
 <table>
- <tr><th>a</th><th>b</th><th>c</th></tr>
- <tr><td>1</td><td>2</td><td>3</td></tr>
- <tr><td>foo</td><td>bar</td><td>baz this list is very very very long man</td></tr>
+<tr><td>a</td>
+<td>b</td>
+<td>c</td></tr>
+<tr><td>1</td>
+<td>2</td>
+<td>3</td></tr>
+<tr><td>foo</td>
+<td>bar</td>
+<td>baz this list is very very very long man</td></tr>
 </table>
 ----------------------------------------------------------------------
 
--- a/tests/test-mq-strip.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-mq-strip.t	Wed Apr 03 13:03:50 2013 -0500
@@ -420,6 +420,25 @@
   $ hg status
   M bar
   ? b
+
+Strip adds, removes, modifies with --keep
+
+  $ touch b
+  $ hg add b
+  $ hg commit -mb
+  $ touch c
+  $ hg add c
+  $ hg rm bar
+  $ hg commit -mc
+  $ echo b > b
+  $ echo d > d
+  $ hg strip --keep tip
+  saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
+  $ hg status
+  M b
+  ! bar
+  ? c
+  ? d
   $ cd ..
 
 stripping many nodes on a complex graph (issue3299)
--- a/tests/test-mq.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-mq.t	Wed Apr 03 13:03:50 2013 -0500
@@ -1555,4 +1555,25 @@
   1: secret
   2: secret
 
+Test that secret mq patch does not break hgweb
+
+  $ cat > hgweb.cgi <<HGWEB
+  > from mercurial import demandimport; demandimport.enable()
+  > from mercurial.hgweb import hgweb
+  > from mercurial.hgweb import wsgicgi
+  > import cgitb
+  > cgitb.enable()
+  > app = hgweb('.', 'test')
+  > wsgicgi.launch(app)
+  > HGWEB
+  $ . "$TESTDIR/cgienv"
+#if msys
+  $ PATH_INFO=//tags; export PATH_INFO
+#else
+  $ PATH_INFO=/tags; export PATH_INFO
+#endif
+  $ QUERY_STRING='style=raw'
+  $ python hgweb.cgi | grep '^tip'
+  tip	[0-9a-f]{40} (re)
+
   $ cd ..
--- a/tests/test-obsolete-divergent.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-obsolete-divergent.t	Wed Apr 03 13:03:50 2013 -0500
@@ -1,6 +1,6 @@
 Test file dedicated to testing the divergent troubles from obsolete changeset.
 
-This is the most complexe troubles from far so we isolate it in a dedicated
+This is the most complex troubles from far so we isolate it in a dedicated
 file.
 
 Enable obsolete
@@ -294,7 +294,7 @@
       e442cfc57690
   $ hg log -r 'divergent()'
 
-Check more complexe obsolescence graft (with divergence)
+Check more complex obsolescence graft (with divergence)
 
   $ mkcommit B_0; hg up 0
   0 files updated, 0 files merged, 2 files removed, 0 files unresolved
--- a/tests/test-obsolete.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-obsolete.t	Wed Apr 03 13:03:50 2013 -0500
@@ -752,7 +752,7 @@
 
 check that web.view config option:
 
-  $ kill `cat hg.pid`
+  $ "$TESTDIR/killdaemons.py" hg.pid
   $ cat >> .hg/hgrc << EOF
   > [web]
   > view=all
@@ -761,7 +761,7 @@
   $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
   $ "$TESTDIR/get-with-headers.py" --headeronly localhost:$HGPORT 'rev/67'
   200 Script output follows
-  $ kill `cat hg.pid`
+  $ "$TESTDIR/killdaemons.py" hg.pid
 
 Checking _enable=False warning if obsolete marker exists
 
--- a/tests/test-parse-date.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-parse-date.t	Wed Apr 03 13:03:50 2013 -0500
@@ -234,3 +234,25 @@
   Sat Apr 15 13:30:00 2006 +0000
   Wed Feb 01 13:00:30 2006 -0500
   Wed Feb 01 13:00:30 2006 +0000
+
+Test issue 3764 (interpreting 'today' and 'yesterday')
+  $ echo "hello" >> a
+  >>> import datetime
+  >>> today = datetime.date.today().strftime("%b %d")
+  >>> yesterday = (datetime.date.today() - datetime.timedelta(days=1)).strftime("%b %d")
+  >>> dates = open('dates', 'w')
+  >>> dates.write(today + '\n')
+  >>> dates.write(yesterday)
+  >>> dates.close()
+  $ hg ci -d "`sed -n '1p' dates`" -m "today is a good day to code"
+  $ hg log -d today --template '{desc}\n'
+  today is a good day to code
+  $ echo "goodbye" >> a
+  $ hg ci -d "`sed -n '2p' dates`" -m "the time traveler's code"
+  $ hg log -d yesterday --template '{desc}\n'
+  the time traveler's code
+  $ echo "foo" >> a
+  $ hg commit -d now -m 'Explicitly committed now.'
+  $ hg log -d today --template '{desc}\n'
+  Explicitly committed now.
+  today is a good day to code
--- a/tests/test-patchbomb.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-patchbomb.t	Wed Apr 03 13:03:50 2013 -0500
@@ -27,6 +27,7 @@
   # HG changeset patch
   # User test
   # Date 1 0
+  #      Thu Jan 01 00:00:01 1970 +0000
   # Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
   # Parent  0000000000000000000000000000000000000000
   a
@@ -98,6 +99,7 @@
   # HG changeset patch
   # User test
   # Date 1 0
+  #      Thu Jan 01 00:00:01 1970 +0000
   # Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
   # Parent  0000000000000000000000000000000000000000
   a
@@ -126,6 +128,7 @@
   # HG changeset patch
   # User test
   # Date 2 0
+  #      Thu Jan 01 00:00:02 1970 +0000
   # Node ID 97d72e5f12c7e84f85064aa72e5a297142c36ed9
   # Parent  8580ff50825a50c8f716709acdf8de0deddcd6ab
   b
@@ -258,6 +261,7 @@
   # HG changeset patch
   # User test
   # Date 4 0
+  #      Thu Jan 01 00:00:04 1970 +0000
   # Node ID 909a00e13e9d78b575aeee23dddbada46d5a143f
   # Parent  ff2c9fa2018b15fa74b33363bda9527323e2a99f
   utf-8 content
@@ -297,21 +301,23 @@
   To: foo
   Cc: bar
   
-  IyBIRyBjaGFuZ2VzZXQgcGF0Y2gKIyBVc2VyIHRlc3QKIyBEYXRlIDQgMAojIE5vZGUgSUQgOTA5
-  YTAwZTEzZTlkNzhiNTc1YWVlZTIzZGRkYmFkYTQ2ZDVhMTQzZgojIFBhcmVudCAgZmYyYzlmYTIw
-  MThiMTVmYTc0YjMzMzYzYmRhOTUyNzMyM2UyYTk5Zgp1dGYtOCBjb250ZW50CgpkaWZmIC1yIGZm
-  MmM5ZmEyMDE4YiAtciA5MDlhMDBlMTNlOWQgZGVzY3JpcHRpb24KLS0tIC9kZXYvbnVsbAlUaHUg
-  SmFuIDAxIDAwOjAwOjAwIDE5NzAgKzAwMDAKKysrIGIvZGVzY3JpcHRpb24JVGh1IEphbiAwMSAw
-  MDowMDowNCAxOTcwICswMDAwCkBAIC0wLDAgKzEsMyBAQAorYSBtdWx0aWxpbmUKKworZGVzY3Jp
-  cHRpb24KZGlmZiAtciBmZjJjOWZhMjAxOGIgLXIgOTA5YTAwZTEzZTlkIHV0ZgotLS0gL2Rldi9u
-  dWxsCVRodSBKYW4gMDEgMDA6MDA6MDAgMTk3MCArMDAwMAorKysgYi91dGYJVGh1IEphbiAwMSAw
-  MDowMDowNCAxOTcwICswMDAwCkBAIC0wLDAgKzEsMSBAQAoraMO2bW1hIQo=
+  IyBIRyBjaGFuZ2VzZXQgcGF0Y2gKIyBVc2VyIHRlc3QKIyBEYXRlIDQgMAojICAgICAgVGh1IEph
+  biAwMSAwMDowMDowNCAxOTcwICswMDAwCiMgTm9kZSBJRCA5MDlhMDBlMTNlOWQ3OGI1NzVhZWVl
+  MjNkZGRiYWRhNDZkNWExNDNmCiMgUGFyZW50ICBmZjJjOWZhMjAxOGIxNWZhNzRiMzMzNjNiZGE5
+  NTI3MzIzZTJhOTlmCnV0Zi04IGNvbnRlbnQKCmRpZmYgLXIgZmYyYzlmYTIwMThiIC1yIDkwOWEw
+  MGUxM2U5ZCBkZXNjcmlwdGlvbgotLS0gL2Rldi9udWxsCVRodSBKYW4gMDEgMDA6MDA6MDAgMTk3
+  MCArMDAwMAorKysgYi9kZXNjcmlwdGlvbglUaHUgSmFuIDAxIDAwOjAwOjA0IDE5NzAgKzAwMDAK
+  QEAgLTAsMCArMSwzIEBACithIG11bHRpbGluZQorCitkZXNjcmlwdGlvbgpkaWZmIC1yIGZmMmM5
+  ZmEyMDE4YiAtciA5MDlhMDBlMTNlOWQgdXRmCi0tLSAvZGV2L251bGwJVGh1IEphbiAwMSAwMDow
+  MDowMCAxOTcwICswMDAwCisrKyBiL3V0ZglUaHUgSmFuIDAxIDAwOjAwOjA0IDE5NzAgKzAwMDAK
+  QEAgLTAsMCArMSwxIEBACitow7ZtbWEhCg==
   
   
   $ python -c 'print open("mbox").read().split("\n\n")[1].decode("base64")'
   # HG changeset patch
   # User test
   # Date 4 0
+  #      Thu Jan 01 00:00:04 1970 +0000
   # Node ID 909a00e13e9d78b575aeee23dddbada46d5a143f
   # Parent  ff2c9fa2018b15fa74b33363bda9527323e2a99f
   utf-8 content
@@ -357,6 +363,7 @@
   # HG changeset patch
   # User test
   # Date 4 0
+  #      Thu Jan 01 00:00:04 1970 +0000
   # Node ID a2ea8fc83dd8b93cfd86ac97b28287204ab806e1
   # Parent  909a00e13e9d78b575aeee23dddbada46d5a143f
   long line
@@ -407,6 +414,7 @@
   # HG changeset patch
   # User test
   # Date 4 0
+  #      Thu Jan 01 00:00:04 1970 +0000
   # Node ID a2ea8fc83dd8b93cfd86ac97b28287204ab806e1
   # Parent  909a00e13e9d78b575aeee23dddbada46d5a143f
   long line
@@ -465,6 +473,7 @@
   # HG changeset patch
   # User test
   # Date 5 0
+  #      Thu Jan 01 00:00:05 1970 +0000
   # Node ID 240fb913fc1b7ff15ddb9f33e73d82bf5277c720
   # Parent  a2ea8fc83dd8b93cfd86ac97b28287204ab806e1
   isolatin 8-bit encoding
@@ -513,6 +522,7 @@
   # HG changeset patch
   # User test
   # Date 3 0
+  #      Thu Jan 01 00:00:03 1970 +0000
   # Node ID ff2c9fa2018b15fa74b33363bda9527323e2a99f
   # Parent  97d72e5f12c7e84f85064aa72e5a297142c36ed9
   c
@@ -590,6 +600,7 @@
   # HG changeset patch
   # User test
   # Date 1 0
+  #      Thu Jan 01 00:00:01 1970 +0000
   # Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
   # Parent  0000000000000000000000000000000000000000
   a
@@ -622,6 +633,7 @@
   # HG changeset patch
   # User test
   # Date 2 0
+  #      Thu Jan 01 00:00:02 1970 +0000
   # Node ID 97d72e5f12c7e84f85064aa72e5a297142c36ed9
   # Parent  8580ff50825a50c8f716709acdf8de0deddcd6ab
   b
@@ -659,6 +671,7 @@
   # HG changeset patch
   # User test
   # Date 3 0
+  #      Thu Jan 01 00:00:03 1970 +0000
   # Node ID ff2c9fa2018b15fa74b33363bda9527323e2a99f
   # Parent  97d72e5f12c7e84f85064aa72e5a297142c36ed9
   c
@@ -698,6 +711,7 @@
   # HG changeset patch
   # User test
   # Date 4 0
+  #      Thu Jan 01 00:00:04 1970 +0000
   # Node ID a2ea8fc83dd8b93cfd86ac97b28287204ab806e1
   # Parent  909a00e13e9d78b575aeee23dddbada46d5a143f
   long line
@@ -771,6 +785,7 @@
   # HG changeset patch
   # User test
   # Date 1 0
+  #      Thu Jan 01 00:00:01 1970 +0000
   # Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
   # Parent  0000000000000000000000000000000000000000
   a
@@ -805,6 +820,7 @@
   # HG changeset patch
   # User test
   # Date 2 0
+  #      Thu Jan 01 00:00:02 1970 +0000
   # Node ID 97d72e5f12c7e84f85064aa72e5a297142c36ed9
   # Parent  8580ff50825a50c8f716709acdf8de0deddcd6ab
   b
@@ -839,6 +855,7 @@
   # HG changeset patch
   # User test
   # Date 4 0
+  #      Thu Jan 01 00:00:04 1970 +0000
   # Node ID a2ea8fc83dd8b93cfd86ac97b28287204ab806e1
   # Parent  909a00e13e9d78b575aeee23dddbada46d5a143f
   long line
@@ -902,6 +919,7 @@
   # HG changeset patch
   # User test
   # Date 3 0
+  #      Thu Jan 01 00:00:03 1970 +0000
   # Node ID ff2c9fa2018b15fa74b33363bda9527323e2a99f
   # Parent  97d72e5f12c7e84f85064aa72e5a297142c36ed9
   c
@@ -949,6 +967,7 @@
   # HG changeset patch
   # User test
   # Date 4 0
+  #      Thu Jan 01 00:00:04 1970 +0000
   # Node ID a2ea8fc83dd8b93cfd86ac97b28287204ab806e1
   # Parent  909a00e13e9d78b575aeee23dddbada46d5a143f
   long line
@@ -1002,6 +1021,7 @@
   # HG changeset patch
   # User test
   # Date 3 0
+  #      Thu Jan 01 00:00:03 1970 +0000
   # Node ID ff2c9fa2018b15fa74b33363bda9527323e2a99f
   # Parent  97d72e5f12c7e84f85064aa72e5a297142c36ed9
   c
@@ -1021,6 +1041,7 @@
   # HG changeset patch
   # User test
   # Date 3 0
+  #      Thu Jan 01 00:00:03 1970 +0000
   # Node ID ff2c9fa2018b15fa74b33363bda9527323e2a99f
   # Parent  97d72e5f12c7e84f85064aa72e5a297142c36ed9
   c
@@ -1087,6 +1108,7 @@
   # HG changeset patch
   # User test
   # Date 1 0
+  #      Thu Jan 01 00:00:01 1970 +0000
   # Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
   # Parent  0000000000000000000000000000000000000000
   a
@@ -1130,6 +1152,7 @@
   # HG changeset patch
   # User test
   # Date 2 0
+  #      Thu Jan 01 00:00:02 1970 +0000
   # Node ID 97d72e5f12c7e84f85064aa72e5a297142c36ed9
   # Parent  8580ff50825a50c8f716709acdf8de0deddcd6ab
   b
@@ -1173,6 +1196,7 @@
   # HG changeset patch
   # User test
   # Date 4 0
+  #      Thu Jan 01 00:00:04 1970 +0000
   # Node ID a2ea8fc83dd8b93cfd86ac97b28287204ab806e1
   # Parent  909a00e13e9d78b575aeee23dddbada46d5a143f
   long line
@@ -1241,6 +1265,7 @@
   # HG changeset patch
   # User test
   # Date 3 0
+  #      Thu Jan 01 00:00:03 1970 +0000
   # Node ID ff2c9fa2018b15fa74b33363bda9527323e2a99f
   # Parent  97d72e5f12c7e84f85064aa72e5a297142c36ed9
   c
@@ -1291,6 +1316,7 @@
   # HG changeset patch
   # User test
   # Date 3 0
+  #      Thu Jan 01 00:00:03 1970 +0000
   # Node ID ff2c9fa2018b15fa74b33363bda9527323e2a99f
   # Parent  97d72e5f12c7e84f85064aa72e5a297142c36ed9
   c
@@ -1342,6 +1368,7 @@
   # HG changeset patch
   # User test
   # Date 1 0
+  #      Thu Jan 01 00:00:01 1970 +0000
   # Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
   # Parent  0000000000000000000000000000000000000000
   a
@@ -1370,6 +1397,7 @@
   # HG changeset patch
   # User test
   # Date 2 0
+  #      Thu Jan 01 00:00:02 1970 +0000
   # Node ID 97d72e5f12c7e84f85064aa72e5a297142c36ed9
   # Parent  8580ff50825a50c8f716709acdf8de0deddcd6ab
   b
@@ -1404,6 +1432,7 @@
   # HG changeset patch
   # User test
   # Date 3 0
+  #      Thu Jan 01 00:00:03 1970 +0000
   # Node ID ff2c9fa2018b15fa74b33363bda9527323e2a99f
   # Parent  97d72e5f12c7e84f85064aa72e5a297142c36ed9
   c
@@ -1438,6 +1467,7 @@
   # HG changeset patch
   # User test
   # Date 3 0
+  #      Thu Jan 01 00:00:03 1970 +0000
   # Node ID ff2c9fa2018b15fa74b33363bda9527323e2a99f
   # Parent  97d72e5f12c7e84f85064aa72e5a297142c36ed9
   c
@@ -1480,6 +1510,7 @@
   # HG changeset patch
   # User test
   # Date 3 0
+  #      Thu Jan 01 00:00:03 1970 +0000
   # Node ID ff2c9fa2018b15fa74b33363bda9527323e2a99f
   # Parent  97d72e5f12c7e84f85064aa72e5a297142c36ed9
   c
@@ -1536,6 +1567,7 @@
   # HG changeset patch
   # User test
   # Date 1 0
+  #      Thu Jan 01 00:00:01 1970 +0000
   # Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
   # Parent  0000000000000000000000000000000000000000
   a
@@ -1570,6 +1602,7 @@
   # HG changeset patch
   # User test
   # Date 2 0
+  #      Thu Jan 01 00:00:02 1970 +0000
   # Node ID 97d72e5f12c7e84f85064aa72e5a297142c36ed9
   # Parent  8580ff50825a50c8f716709acdf8de0deddcd6ab
   b
@@ -1607,6 +1640,7 @@
   # HG changeset patch
   # User test
   # Date 0 0
+  #      Thu Jan 01 00:00:00 1970 +0000
   # Node ID 7aead2484924c445ad8ce2613df91f52f9e502ed
   # Parent  045ca29b1ea20e4940411e695e20e521f2f0f98e
   Added tag two, two.diff for changeset ff2c9fa2018b
@@ -1646,6 +1680,7 @@
   # HG changeset patch
   # User test
   # Date 1 0
+  #      Thu Jan 01 00:00:01 1970 +0000
   # Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
   # Parent  0000000000000000000000000000000000000000
   a
@@ -1674,6 +1709,7 @@
   # HG changeset patch
   # User test
   # Date 2 0
+  #      Thu Jan 01 00:00:02 1970 +0000
   # Node ID 97d72e5f12c7e84f85064aa72e5a297142c36ed9
   # Parent  8580ff50825a50c8f716709acdf8de0deddcd6ab
   b
@@ -1728,6 +1764,7 @@
   # HG changeset patch
   # User test
   # Date 1 0
+  #      Thu Jan 01 00:00:01 1970 +0000
   # Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
   # Parent  0000000000000000000000000000000000000000
   a
@@ -1756,6 +1793,7 @@
   # HG changeset patch
   # User test
   # Date 2 0
+  #      Thu Jan 01 00:00:02 1970 +0000
   # Node ID 97d72e5f12c7e84f85064aa72e5a297142c36ed9
   # Parent  8580ff50825a50c8f716709acdf8de0deddcd6ab
   b
@@ -1789,6 +1827,7 @@
   # HG changeset patch
   # User test
   # Date 3 0
+  #      Thu Jan 01 00:00:03 1970 +0000
   # Node ID ff2c9fa2018b15fa74b33363bda9527323e2a99f
   # Parent  97d72e5f12c7e84f85064aa72e5a297142c36ed9
   c
@@ -1840,6 +1879,7 @@
   # HG changeset patch
   # User test
   # Date 1 0
+  #      Thu Jan 01 00:00:01 1970 +0000
   # Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
   # Parent  0000000000000000000000000000000000000000
   a
@@ -1868,6 +1908,7 @@
   # HG changeset patch
   # User test
   # Date 2 0
+  #      Thu Jan 01 00:00:02 1970 +0000
   # Node ID 97d72e5f12c7e84f85064aa72e5a297142c36ed9
   # Parent  8580ff50825a50c8f716709acdf8de0deddcd6ab
   b
@@ -1901,6 +1942,7 @@
   # HG changeset patch
   # User test
   # Date 3 0
+  #      Thu Jan 01 00:00:03 1970 +0000
   # Node ID ff2c9fa2018b15fa74b33363bda9527323e2a99f
   # Parent  97d72e5f12c7e84f85064aa72e5a297142c36ed9
   c
@@ -1952,6 +1994,7 @@
   # HG changeset patch
   # User test
   # Date 1 0
+  #      Thu Jan 01 00:00:01 1970 +0000
   # Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
   # Parent  0000000000000000000000000000000000000000
   a
@@ -1980,6 +2023,7 @@
   # HG changeset patch
   # User test
   # Date 2 0
+  #      Thu Jan 01 00:00:02 1970 +0000
   # Node ID 97d72e5f12c7e84f85064aa72e5a297142c36ed9
   # Parent  8580ff50825a50c8f716709acdf8de0deddcd6ab
   b
@@ -2017,6 +2061,7 @@
   # HG changeset patch
   # User test
   # Date 1 0
+  #      Thu Jan 01 00:00:01 1970 +0000
   # Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
   # Parent  0000000000000000000000000000000000000000
   a
@@ -2056,6 +2101,7 @@
   # HG changeset patch
   # User test
   # Date 1 0
+  #      Thu Jan 01 00:00:01 1970 +0000
   # Node ID 8580ff50825a50c8f716709acdf8de0deddcd6ab
   # Parent  0000000000000000000000000000000000000000
   a
@@ -2144,6 +2190,7 @@
   # HG changeset patch
   # User test
   # Date 3 0
+  #      Thu Jan 01 00:00:03 1970 +0000
   # Node ID ff2c9fa2018b15fa74b33363bda9527323e2a99f
   # Parent  97d72e5f12c7e84f85064aa72e5a297142c36ed9
   c
@@ -2171,6 +2218,7 @@
   # HG changeset patch
   # User test
   # Date 4 0
+  #      Thu Jan 01 00:00:04 1970 +0000
   # Node ID 909a00e13e9d78b575aeee23dddbada46d5a143f
   # Parent  ff2c9fa2018b15fa74b33363bda9527323e2a99f
   utf-8 content
@@ -2205,6 +2253,7 @@
   # HG changeset patch
   # User test
   # Date 4 0
+  #      Thu Jan 01 00:00:04 1970 +0000
   # Node ID a2ea8fc83dd8b93cfd86ac97b28287204ab806e1
   # Parent  909a00e13e9d78b575aeee23dddbada46d5a143f
   long line
@@ -2248,6 +2297,7 @@
   # HG changeset patch
   # User test
   # Date 5 0
+  #      Thu Jan 01 00:00:05 1970 +0000
   # Node ID 240fb913fc1b7ff15ddb9f33e73d82bf5277c720
   # Parent  a2ea8fc83dd8b93cfd86ac97b28287204ab806e1
   isolatin 8-bit encoding
@@ -2275,6 +2325,7 @@
   # HG changeset patch
   # User test
   # Date 0 0
+  #      Thu Jan 01 00:00:00 1970 +0000
   # Node ID 5d5ef15dfe5e7bd3a4ee154b5fff76c7945ec433
   # Parent  240fb913fc1b7ff15ddb9f33e73d82bf5277c720
   Added tag zero, zero.foo for changeset 8580ff50825a
@@ -2303,6 +2354,7 @@
   # HG changeset patch
   # User test
   # Date 4 0
+  #      Thu Jan 01 00:00:04 1970 +0000
   # Branch test
   # Node ID 2f9fa9b998c5fe3ac2bd9a2b14bfcbeecbc7c268
   # Parent  97d72e5f12c7e84f85064aa72e5a297142c36ed9
@@ -2338,6 +2390,7 @@
   # HG changeset patch
   # User test
   # Date 4 0
+  #      Thu Jan 01 00:00:04 1970 +0000
   # Branch test
   # Node ID 2f9fa9b998c5fe3ac2bd9a2b14bfcbeecbc7c268
   # Parent  97d72e5f12c7e84f85064aa72e5a297142c36ed9
--- a/tests/test-progress.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-progress.t	Wed Apr 03 13:03:50 2013 -0500
@@ -167,6 +167,7 @@
 
   $ hg -y loop 8
   \r (no-eol) (esc)
+  loop [====>                                     ] 1/8 1m18s\r (no-eol) (esc)
   loop [=========>                                ] 2/8 1m07s\r (no-eol) (esc)
   loop [===============>                            ] 3/8 56s\r (no-eol) (esc)
   loop [=====================>                      ] 4/8 45s\r (no-eol) (esc)
@@ -203,6 +204,7 @@
 Time estimates should not fail when there's no end point:
   $ hg -y loop -- -4
   \r (no-eol) (esc)
-  loop [ <=>                                              ] 2\r (no-eol) (esc)
-  loop [  <=>                                             ] 3\r (no-eol) (esc)
+  loop [ <=>                                              ] 1\r (no-eol) (esc)
+  loop [  <=>                                             ] 2\r (no-eol) (esc)
+  loop [   <=>                                            ] 3\r (no-eol) (esc)
                                                               \r (no-eol) (esc)
--- a/tests/test-pull-http.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-pull-http.t	Wed Apr 03 13:03:50 2013 -0500
@@ -58,7 +58,6 @@
 
   $ req
   pulling from http://localhost:$HGPORT/
-  searching for changes
   abort: authorization failed
   % serve errors
 
--- a/tests/test-rebase-collapse.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-rebase-collapse.t	Wed Apr 03 13:03:50 2013 -0500
@@ -496,15 +496,15 @@
   $ hg ci -Am 'A'
   adding a
 
-  $ hg branch '1'
-  marked working directory as branch 1
+  $ hg branch 'one'
+  marked working directory as branch one
   (branches are permanent and global, did you want a bookmark?)
   $ echo 'b' > b
   $ hg ci -Am 'B'
   adding b
 
-  $ hg branch '2'
-  marked working directory as branch 2
+  $ hg branch 'two'
+  marked working directory as branch two
   (branches are permanent and global, did you want a bookmark?)
   $ echo 'c' > c
   $ hg ci -Am 'C'
@@ -518,9 +518,9 @@
   $ hg tglog
   @  3: 'D'
   |
-  | o  2: 'C' 2
+  | o  2: 'C' two
   | |
-  | o  1: 'B' 1
+  | o  1: 'B' one
   |/
   o  0: 'A'
   
@@ -546,9 +546,9 @@
   |/
   o  3: 'D'
   |
-  | o  2: 'C' 2
+  | o  2: 'C' two
   | |
-  | o  1: 'B' 1
+  | o  1: 'B' one
   |/
   o  0: 'A'
   
@@ -559,9 +559,9 @@
   |
   o  3: 'D'
   |
-  | o  2: 'C' 2
+  | o  2: 'C' two
   | |
-  | o  1: 'B' 1
+  | o  1: 'B' one
   |/
   o  0: 'A'
   
@@ -569,6 +569,7 @@
   # HG changeset patch
   # User user1
   # Date 0 0
+  #      Thu Jan 01 00:00:00 1970 +0000
   # Node ID f338eb3c2c7cc5b5915676a2376ba7ac558c5213
   # Parent  41acb9dca9eb976e84cd21fcb756b4afa5a35c09
   E
@@ -718,6 +719,30 @@
 
   $ cd ..
 
+Test collapsing changes that add then remove a file
 
+  $ hg init collapseaddremove
+  $ cd collapseaddremove
 
+  $ touch base
+  $ hg commit -Am base
+  adding base
+  $ touch a
+  $ hg commit -Am a
+  adding a
+  $ hg rm a
+  $ touch b
+  $ hg commit -Am b
+  adding b
+  $ hg rebase -d 0 -r "1::2" --collapse -m collapsed
+  saved backup bundle to $TESTTMP/collapseaddremove/.hg/strip-backup/*-backup.hg (glob)
+  $ hg tglog
+  @  1: 'collapsed'
+  |
+  o  0: 'base'
+  
+  $ hg manifest
+  b
+  base
 
+  $ cd ..
--- a/tests/test-rebase-detach.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-rebase-detach.t	Wed Apr 03 13:03:50 2013 -0500
@@ -326,8 +326,6 @@
   $ hg ci -m "J"
 
   $ hg rebase -s 8 -d 7 --collapse --config ui.merge=internal:other
-  remote changed E which local deleted
-  use (c)hanged version or leave (d)eleted? c
   saved backup bundle to $TESTTMP/a6/.hg/strip-backup/*-backup.hg (glob)
 
   $ hg tglog
--- a/tests/test-rebase-mq.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-rebase-mq.t	Wed Apr 03 13:03:50 2013 -0500
@@ -102,6 +102,7 @@
   # HG changeset patch
   # User test
   # Date ?????????? ? (glob)
+  #      * (glob)
   # Node ID ???????????????????????????????????????? (glob)
   # Parent  bac9ed9960d8992bcad75864a879fa76cadaf1b0
   P0
@@ -124,6 +125,7 @@
   # HG changeset patch
   # User test
   # Date ?????????? ? (glob)
+  #      * (glob)
   # Node ID ???????????????????????????????????????? (glob)
   # Parent  ???????????????????????????????????????? (glob)
   P1
@@ -209,6 +211,7 @@
   # HG changeset patch
   # User test
   # Date ?????????? ? (glob)
+  #      * (glob)
   # Node ID ???????????????????????????????????????? (glob)
   # Parent  bac9ed9960d8992bcad75864a879fa76cadaf1b0
   P0 (git)
@@ -224,6 +227,7 @@
   # HG changeset patch
   # User test
   # Date ?????????? ? (glob)
+  #      * (glob)
   # Node ID ???????????????????????????????????????? (glob)
   # Parent  ???????????????????????????????????????? (glob)
   P1
--- a/tests/test-rebase-scenario-global.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-rebase-scenario-global.t	Wed Apr 03 13:03:50 2013 -0500
@@ -564,7 +564,7 @@
   
   $ cd ..
 
-More complexe rebase with multiple roots
+More complex rebase with multiple roots
 each root have a different common ancestor with the destination and this is a detach
 
 (setup)
--- a/tests/test-rename-dir-merge.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-rename-dir-merge.t	Wed Apr 03 13:03:50 2013 -0500
@@ -37,23 +37,20 @@
      discovered dir src: 'a/' -> dst: 'b/'
      pending file src: 'a/c' -> dst: 'b/c'
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: f9b20c0d4c51, local: ce36d17b18fb+, remote: 397f8b00a740
    a/a: other deleted -> r
    a/b: other deleted -> r
    a/c: remote renamed directory to b/c -> d
    b/a: remote created -> g
    b/b: remote created -> g
-  updating: a/a 1/5 files (20.00%)
   removing a/a
-  updating: a/b 2/5 files (40.00%)
   removing a/b
-  updating: a/c 3/5 files (60.00%)
+  getting b/a
+  getting b/b
+  updating: b/b 4/5 files (80.00%)
+  updating: a/c 5/5 files (100.00%)
   moving a/c to b/c
-  updating: b/a 4/5 files (80.00%)
-  getting b/a
-  updating: b/b 5/5 files (100.00%)
-  getting b/b
   3 files updated, 0 files merged, 2 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
 
@@ -88,7 +85,7 @@
      discovered dir src: 'a/' -> dst: 'b/'
      pending file src: 'a/c' -> dst: 'b/c'
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: f9b20c0d4c51, local: 397f8b00a740+, remote: ce36d17b18fb
    None: local renamed directory to b/c -> d
   updating:None 1/1 files (100.00%)
--- a/tests/test-rename-merge1.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-rename-merge1.t	Wed Apr 03 13:03:50 2013 -0500
@@ -33,25 +33,25 @@
      src: 'a2' -> dst: 'b2' !
      src: 'a2' -> dst: 'c2' !
     checking for directory renames
-   a2: divergent renames -> dr
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: af1939970a1c, local: 044f8520aeeb+, remote: 85c198ef2f6c
    a: remote moved to b -> m
+    preserving a for resolve of b
+   a2: divergent renames -> dr
    b2: remote created -> g
-  preserving a for resolve of b
   removing a
-  updating: a 1/3 files (33.33%)
+  getting b2
+  updating: b2 1/3 files (33.33%)
+  updating: a 2/3 files (66.67%)
   picked tool 'internal:merge' for b (binary False symlink False)
   merging a and b to b
   my b@044f8520aeeb+ other b@85c198ef2f6c ancestor a@af1939970a1c
    premerge successful
-  updating: a2 2/3 files (66.67%)
+  updating: a2 3/3 files (100.00%)
   note: possible conflict - a2 was renamed multiple times to:
    c2
    b2
-  updating: b2 3/3 files (100.00%)
-  getting b2
   1 files updated, 1 files merged, 0 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
 
@@ -178,16 +178,16 @@
     all copies found (* = to merge, ! = divergent, % = renamed and deleted):
      src: 'file' -> dst: 'newfile' %
     checking for directory renames
+  resolving manifests
+   branchmerge: True, force: False, partial: False
+   ancestor: 19d7f95df299, local: 0084274f6b67+, remote: 5d32493049f0
    file: rename and delete -> rd
-  resolving manifests
-   overwrite: False, partial: False
-   ancestor: 19d7f95df299, local: 0084274f6b67+, remote: 5d32493049f0
    newfile: remote created -> g
-  updating: file 1/2 files (50.00%)
+  getting newfile
+  updating: newfile 1/2 files (50.00%)
+  updating: file 2/2 files (100.00%)
   note: possible conflict - file was deleted and renamed to:
    newfile
-  updating: newfile 2/2 files (100.00%)
-  getting newfile
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
   $ hg status
--- a/tests/test-rename-merge2.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-rename-merge2.t	Wed Apr 03 13:03:50 2013 -0500
@@ -84,12 +84,12 @@
      src: 'a' -> dst: 'b' *
     checking for directory renames
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: 924404dff337, local: e300d1c794ec+, remote: 4ce40f5aca24
+   a: remote copied to b -> m
+    preserving a for resolve of b
    rev: versions differ -> m
-   a: remote copied to b -> m
-  preserving a for resolve of b
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
   updating: a 1/2 files (50.00%)
   picked tool 'python ../merge' for b (binary False symlink False)
   merging a and b to b
@@ -119,15 +119,15 @@
      src: 'a' -> dst: 'b' *
     checking for directory renames
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: 924404dff337, local: 86a2aa42fc76+, remote: f4db7e329e71
    a: remote is newer -> g
    b: local copied/moved to a -> m
+    preserving b for resolve of b
    rev: versions differ -> m
-  preserving b for resolve of b
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
+  getting a
   updating: a 1/3 files (33.33%)
-  getting a
   updating: b 2/3 files (66.67%)
   picked tool 'python ../merge' for b (binary False symlink False)
   merging b and a to b
@@ -157,12 +157,12 @@
      src: 'a' -> dst: 'b' *
     checking for directory renames
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: 924404dff337, local: e300d1c794ec+, remote: bdb19105162a
+   a: remote moved to b -> m
+    preserving a for resolve of b
    rev: versions differ -> m
-   a: remote moved to b -> m
-  preserving a for resolve of b
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
   removing a
   updating: a 1/2 files (50.00%)
   picked tool 'python ../merge' for b (binary False symlink False)
@@ -192,12 +192,12 @@
      src: 'a' -> dst: 'b' *
     checking for directory renames
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: 924404dff337, local: 02963e448370+, remote: f4db7e329e71
    b: local copied/moved to a -> m
+    preserving b for resolve of b
    rev: versions differ -> m
-  preserving b for resolve of b
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
   updating: b 1/2 files (50.00%)
   picked tool 'python ../merge' for b (binary False symlink False)
   merging b and a to b
@@ -226,13 +226,13 @@
      src: 'a' -> dst: 'b' 
     checking for directory renames
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: 924404dff337, local: 94b33a1b7f2d+, remote: 4ce40f5aca24
-   rev: versions differ -> m
    b: remote created -> g
-  preserving rev for resolve of rev
+   rev: versions differ -> m
+    preserving rev for resolve of rev
+  getting b
   updating: b 1/2 files (50.00%)
-  getting b
   updating: rev 2/2 files (100.00%)
   picked tool 'python ../merge' for rev (binary False symlink False)
   merging rev
@@ -256,10 +256,10 @@
      src: 'a' -> dst: 'b' 
     checking for directory renames
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 97c705ade336
    rev: versions differ -> m
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
   updating: rev 1/1 files (100.00%)
   picked tool 'python ../merge' for rev (binary False symlink False)
   merging rev
@@ -283,16 +283,15 @@
      src: 'a' -> dst: 'b' 
     checking for directory renames
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: 924404dff337, local: 94b33a1b7f2d+, remote: bdb19105162a
    a: other deleted -> r
+   b: remote created -> g
    rev: versions differ -> m
-   b: remote created -> g
-  preserving rev for resolve of rev
-  updating: a 1/3 files (33.33%)
+    preserving rev for resolve of rev
   removing a
+  getting b
   updating: b 2/3 files (66.67%)
-  getting b
   updating: rev 3/3 files (100.00%)
   picked tool 'python ../merge' for rev (binary False symlink False)
   merging rev
@@ -315,10 +314,10 @@
      src: 'a' -> dst: 'b' 
     checking for directory renames
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: 924404dff337, local: 02963e448370+, remote: 97c705ade336
    rev: versions differ -> m
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
   updating: rev 1/1 files (100.00%)
   picked tool 'python ../merge' for rev (binary False symlink False)
   merging rev
@@ -336,12 +335,12 @@
   --------------
     searching for copies back to rev 1
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: 924404dff337, local: 62e7bf090eba+, remote: 49b6d8032493
    b: versions differ -> m
+    preserving b for resolve of b
    rev: versions differ -> m
-  preserving b for resolve of b
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
   updating: b 1/2 files (50.00%)
   picked tool 'python ../merge' for b (binary False symlink False)
   merging b
@@ -373,19 +372,19 @@
      src: 'a' -> dst: 'b' !
      src: 'a' -> dst: 'c' !
     checking for directory renames
-   a: divergent renames -> dr
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: 924404dff337, local: 02963e448370+, remote: fe905ef2c33e
-   rev: versions differ -> m
+   a: divergent renames -> dr
    c: remote created -> g
-  preserving rev for resolve of rev
-  updating: a 1/3 files (33.33%)
+   rev: versions differ -> m
+    preserving rev for resolve of rev
+  getting c
+  updating: c 1/3 files (33.33%)
+  updating: a 2/3 files (66.67%)
   note: possible conflict - a was renamed multiple times to:
    b
    c
-  updating: c 2/3 files (66.67%)
-  getting c
   updating: rev 3/3 files (100.00%)
   picked tool 'python ../merge' for rev (binary False symlink False)
   merging rev
@@ -404,12 +403,12 @@
   --------------
     searching for copies back to rev 1
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: 924404dff337, local: 86a2aa42fc76+, remote: af30c7647fc7
    b: versions differ -> m
+    preserving b for resolve of b
    rev: versions differ -> m
-  preserving b for resolve of b
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
   updating: b 1/2 files (50.00%)
   picked tool 'python ../merge' for b (binary False symlink False)
   merging b
@@ -432,15 +431,15 @@
   --------------
     searching for copies back to rev 1
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: 924404dff337, local: 59318016310c+, remote: bdb19105162a
    a: other deleted -> r
    b: versions differ -> m
+    preserving b for resolve of b
    rev: versions differ -> m
-  preserving b for resolve of b
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
+  removing a
   updating: a 1/3 files (33.33%)
-  removing a
   updating: b 2/3 files (66.67%)
   picked tool 'python ../merge' for b (binary False symlink False)
   merging b
@@ -462,15 +461,15 @@
   --------------
     searching for copies back to rev 1
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 8dbce441892a
    a: remote is newer -> g
    b: versions differ -> m
+    preserving b for resolve of b
    rev: versions differ -> m
-  preserving b for resolve of b
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
+  getting a
   updating: a 1/3 files (33.33%)
-  getting a
   updating: b 2/3 files (66.67%)
   picked tool 'python ../merge' for b (binary False symlink False)
   merging b
@@ -493,15 +492,15 @@
   --------------
     searching for copies back to rev 1
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: 924404dff337, local: 59318016310c+, remote: bdb19105162a
    a: other deleted -> r
    b: versions differ -> m
+    preserving b for resolve of b
    rev: versions differ -> m
-  preserving b for resolve of b
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
+  removing a
   updating: a 1/3 files (33.33%)
-  removing a
   updating: b 2/3 files (66.67%)
   picked tool 'python ../merge' for b (binary False symlink False)
   merging b
@@ -523,15 +522,15 @@
   --------------
     searching for copies back to rev 1
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: 924404dff337, local: 86a2aa42fc76+, remote: 8dbce441892a
    a: remote is newer -> g
    b: versions differ -> m
+    preserving b for resolve of b
    rev: versions differ -> m
-  preserving b for resolve of b
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
+  getting a
   updating: a 1/3 files (33.33%)
-  getting a
   updating: b 2/3 files (66.67%)
   picked tool 'python ../merge' for b (binary False symlink False)
   merging b
@@ -554,12 +553,12 @@
   --------------
     searching for copies back to rev 1
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: 924404dff337, local: 0b76e65c8289+, remote: 4ce40f5aca24
    b: versions differ -> m
+    preserving b for resolve of b
    rev: versions differ -> m
-  preserving b for resolve of b
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
   updating: b 1/2 files (50.00%)
   picked tool 'python ../merge' for b (binary False symlink False)
   merging b
@@ -582,17 +581,17 @@
   --------------
     searching for copies back to rev 1
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: 924404dff337, local: 02963e448370+, remote: 8dbce441892a
-   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
+   b: versions differ -> m
+    preserving b for resolve of b
+   rev: versions differ -> m
+    preserving rev for resolve of rev
+  getting a
   updating: a 1/3 files (33.33%)
-  getting a
   updating: b 2/3 files (66.67%)
   picked tool 'python ../merge' for b (binary False symlink False)
   merging b
@@ -615,15 +614,15 @@
   --------------
     searching for copies back to rev 1
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: 924404dff337, local: 0b76e65c8289+, remote: bdb19105162a
-   local changed a which remote deleted
+  local changed a which remote deleted
   use (c)hanged version or (d)elete? c
    a: prompt keep -> a
    b: versions differ -> m
+    preserving b for resolve of b
    rev: versions differ -> m
-  preserving b for resolve of b
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
   updating: a 1/3 files (33.33%)
   updating: b 2/3 files (66.67%)
   picked tool 'python ../merge' for b (binary False symlink False)
@@ -652,12 +651,12 @@
      src: 'a' -> dst: 'b' *
     checking for directory renames
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: 924404dff337, local: e300d1c794ec+, remote: 49b6d8032493
+   a: remote moved to b -> m
+    preserving a for resolve of b
    rev: versions differ -> m
-   a: remote moved to b -> m
-  preserving a for resolve of b
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
   removing a
   updating: a 1/2 files (50.00%)
   picked tool 'python ../merge' for b (binary False symlink False)
@@ -686,12 +685,12 @@
      src: 'a' -> dst: 'b' *
     checking for directory renames
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: 924404dff337, local: 62e7bf090eba+, remote: f4db7e329e71
    b: local copied/moved to a -> m
+    preserving b for resolve of b
    rev: versions differ -> m
-  preserving b for resolve of b
-  preserving rev for resolve of rev
+    preserving rev for resolve of rev
   updating: b 1/2 files (50.00%)
   picked tool 'python ../merge' for b (binary False symlink False)
   merging b and a to b
@@ -724,20 +723,20 @@
      src: 'a' -> dst: 'b' *
     checking for directory renames
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: 924404dff337, local: 02963e448370+, remote: 2b958612230f
    b: local copied/moved to a -> m
-   rev: versions differ -> m
+    preserving b for resolve of b
    c: remote created -> g
-  preserving b for resolve of b
-  preserving rev for resolve of rev
-  updating: b 1/3 files (33.33%)
+   rev: versions differ -> m
+    preserving rev for resolve of rev
+  getting c
+  updating: c 1/3 files (33.33%)
+  updating: b 2/3 files (66.67%)
   picked tool 'python ../merge' for b (binary False symlink False)
   merging b and a to b
   my b@02963e448370+ other a@2b958612230f ancestor a@924404dff337
    premerge successful
-  updating: c 2/3 files (66.67%)
-  getting c
   updating: rev 3/3 files (100.00%)
   picked tool 'python ../merge' for rev (binary False symlink False)
   merging rev
--- a/tests/test-revset.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-revset.t	Wed Apr 03 13:03:50 2013 -0500
@@ -218,17 +218,29 @@
   $ log 'date(2005) and 1::'
   4
 
+ancestor can accept 0 or more arguments
+
+  $ log 'ancestor()'
   $ log 'ancestor(1)'
-  hg: parse error: ancestor requires two arguments
-  [255]
+  1
   $ log 'ancestor(4,5)'
   1
   $ log 'ancestor(4,5) and 4'
+  $ log 'ancestor(0,0,1,3)'
+  0
+  $ log 'ancestor(3,1,5,3,5,1)'
+  1
+  $ log 'ancestor(0,1,3,5)'
+  0
+  $ log 'ancestor(1,2,3,4,5)'
+  1
   $ log 'ancestors(5)'
   0
   1
   3
   5
+  $ log 'ancestor(ancestors(5))'
+  0
   $ log 'author(bob)'
   2
   $ log 'author("re:bob|test")'
@@ -425,8 +437,6 @@
   $ log 'tag("literal:1.0")'
   6
   $ log 'tag("re:0..*")'
-  abort: no tags exist that match '0..*'
-  [255]
 
   $ log 'tag(unknown)'
   abort: tag 'unknown' does not exist
--- a/tests/test-serve.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-serve.t	Wed Apr 03 13:03:50 2013 -0500
@@ -9,12 +9,7 @@
   >    cat hg.pid >> "$DAEMON_PIDS"
   >    echo % errors
   >    cat errors.log
-  >    if [ "$KILLQUIETLY" = "Y" ]; then
-  >        kill `cat hg.pid` 2>/dev/null
-  >    else
-  >        kill `cat hg.pid`
-  >    fi
-  >    while kill -0 `cat hg.pid` 2>/dev/null; do sleep 0; done
+  >    "$TESTDIR/killdaemons.py" hg.pid
   > }
 
   $ hg init test
--- a/tests/test-subrepo.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-subrepo.t	Wed Apr 03 13:03:50 2013 -0500
@@ -203,20 +203,19 @@
   $ hg merge 6 --debug # test change
     searching for copies back to rev 2
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: 1f14a2e2d3ec, local: f0d2028bf86d+, remote: 1831e14459c4
    .hgsubstate: versions differ -> m
   updating: .hgsubstate 1/1 files (100.00%)
   subrepo merge f0d2028bf86d+ 1831e14459c4 1f14a2e2d3ec
     subrepo t: other changed, get t:6747d179aa9a688023c4b0cad32e4c92bb7f34ad:hg
   getting subrepo t
-    searching for copies back to rev 1
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: False, force: False, partial: False
    ancestor: 60ca1237c194, local: 60ca1237c194+, remote: 6747d179aa9a
    t: remote is newer -> g
+  getting t
   updating: t 1/1 files (100.00%)
-  getting t
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
   $ hg debugsub
@@ -232,7 +231,7 @@
   $ HGMERGE=internal:merge hg merge --debug 7 # test conflict
     searching for copies back to rev 2
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: 1831e14459c4, local: e45c8b14af55+, remote: f94576341bcf
    .hgsubstate: versions differ -> m
   updating: .hgsubstate 1/1 files (100.00%)
@@ -241,10 +240,10 @@
   merging subrepo t
     searching for copies back to rev 2
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: False, partial: False
    ancestor: 6747d179aa9a, local: 20a0db6fbf6c+, remote: 7af322bc1198
    t: versions differ -> m
-  preserving t for resolve of t
+    preserving t for resolve of t
   updating: t 1/1 files (100.00%)
   picked tool 'internal:merge' for t (binary False symlink False)
   merging t
@@ -270,9 +269,9 @@
   $ cd ..
   $ hg clone t tc
   updating to branch default
-  cloning subrepo s from $TESTTMP/t/s (glob)
+  cloning subrepo s from $TESTTMP/t/s
   cloning subrepo s/ss from $TESTTMP/t/s/ss (glob)
-  cloning subrepo t from $TESTTMP/t/t (glob)
+  cloning subrepo t from $TESTTMP/t/t
   3 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ cd tc
   $ hg debugsub
@@ -293,10 +292,10 @@
   pushing subrepo s/ss to $TESTTMP/t/s/ss (glob)
   searching for changes
   no changes found
-  pushing subrepo s to $TESTTMP/t/s (glob)
+  pushing subrepo s to $TESTTMP/t/s
   searching for changes
   no changes found
-  pushing subrepo t to $TESTTMP/t/t (glob)
+  pushing subrepo t to $TESTTMP/t/t
   searching for changes
   adding changesets
   adding manifests
@@ -318,7 +317,7 @@
   pushing subrepo s/ss to $TESTTMP/t/s/ss (glob)
   searching for changes
   no changes found
-  pushing subrepo s to $TESTTMP/t/s (glob)
+  pushing subrepo s to $TESTTMP/t/s
   searching for changes
   abort: push creates new remote head 12a213df6fa9! (in subrepo s)
   (did you forget to merge? use push -f to force)
@@ -328,13 +327,13 @@
   pushing subrepo s/ss to $TESTTMP/t/s/ss (glob)
   searching for changes
   no changes found
-  pushing subrepo s to $TESTTMP/t/s (glob)
+  pushing subrepo s to $TESTTMP/t/s
   searching for changes
   adding changesets
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
-  pushing subrepo t to $TESTTMP/t/t (glob)
+  pushing subrepo t to $TESTTMP/t/t
   searching for changes
   no changes found
   searching for changes
@@ -367,7 +366,7 @@
 should pull t
 
   $ hg up
-  pulling subrepo t from $TESTTMP/t/t (glob)
+  pulling subrepo t from $TESTTMP/t/t
   searching for changes
   adding changesets
   adding manifests
@@ -573,7 +572,7 @@
   adding .hgsub
   $ hg clone repo repo2
   updating to branch default
-  cloning subrepo s from $TESTTMP/repo/s (glob)
+  cloning subrepo s from $TESTTMP/repo/s
   2 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg -q -R repo2 pull -u
   $ echo 1 > repo2/s/a
--- a/tests/test-symlinks.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-symlinks.t	Wed Apr 03 13:03:50 2013 -0500
@@ -149,6 +149,10 @@
   adding foo/a
   $ mv foo bar
   $ ln -s bar foo
+  $ hg status
+  ! foo/a
+  ? bar/a
+  ? foo
 
 now addremove should remove old files
 
--- a/tests/test-up-local-change.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-up-local-change.t	Wed Apr 03 13:03:50 2013 -0500
@@ -44,17 +44,17 @@
     unmatched files in other:
      b
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: False, force: False, partial: False
    ancestor: c19d34741b0a, local: c19d34741b0a+, remote: 1e71731e6fbb
    a: versions differ -> m
+    preserving a for resolve of a
    b: remote created -> g
-  preserving a for resolve of a
-  updating: a 1/2 files (50.00%)
+  getting b
+  updating: b 1/2 files (50.00%)
+  updating: a 2/2 files (100.00%)
   picked tool 'true' for a (binary False symlink False)
   merging a
   my a@c19d34741b0a+ other a@1e71731e6fbb ancestor a@c19d34741b0a
-  updating: b 2/2 files (100.00%)
-  getting b
   1 files updated, 1 files merged, 0 files removed, 0 files unresolved
   $ hg parents
   changeset:   1:1e71731e6fbb
@@ -65,13 +65,13 @@
   
   $ hg --debug up 0
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: False, force: False, partial: False
    ancestor: 1e71731e6fbb, local: 1e71731e6fbb+, remote: c19d34741b0a
-   a: versions differ -> m
    b: other deleted -> r
-  preserving a for resolve of a
+   a: versions differ -> m
+    preserving a for resolve of a
+  removing b
   updating: b 1/2 files (50.00%)
-  removing b
   updating: a 2/2 files (100.00%)
   picked tool 'true' for a (binary False symlink False)
   merging a
@@ -98,17 +98,17 @@
     unmatched files in other:
      b
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: False, force: False, partial: False
    ancestor: c19d34741b0a, local: c19d34741b0a+, remote: 1e71731e6fbb
    a: versions differ -> m
+    preserving a for resolve of a
    b: remote created -> g
-  preserving a for resolve of a
-  updating: a 1/2 files (50.00%)
+  getting b
+  updating: b 1/2 files (50.00%)
+  updating: a 2/2 files (100.00%)
   picked tool 'true' for a (binary False symlink False)
   merging a
   my a@c19d34741b0a+ other a@1e71731e6fbb ancestor a@c19d34741b0a
-  updating: b 2/2 files (100.00%)
-  getting b
   1 files updated, 1 files merged, 0 files removed, 0 files unresolved
   $ hg parents
   changeset:   1:1e71731e6fbb
@@ -176,12 +176,12 @@
   $ hg --debug merge -f
     searching for copies back to rev 1
   resolving manifests
-   overwrite: False, partial: False
+   branchmerge: True, force: True, partial: False
    ancestor: c19d34741b0a, local: 1e71731e6fbb+, remote: 83c51d0caff4
    a: versions differ -> m
+    preserving a for resolve of a
    b: versions differ -> m
-  preserving a for resolve of a
-  preserving b for resolve of b
+    preserving b for resolve of b
   updating: a 1/2 files (50.00%)
   picked tool 'true' for a (binary False symlink False)
   merging a
--- a/tests/test-update-reverse.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-update-reverse.t	Wed Apr 03 13:03:50 2013 -0500
@@ -66,17 +66,15 @@
 
   $ hg update --debug -C 1
   resolving manifests
-   overwrite: True, partial: False
+   branchmerge: False, force: True, partial: False
    ancestor: 91ebc10ed028+, local: 91ebc10ed028+, remote: 71a760306caf
    side1: other deleted -> r
    side2: other deleted -> r
    main: remote created -> g
-  updating: side1 1/3 files (33.33%)
   removing side1
-  updating: side2 2/3 files (66.67%)
   removing side2
+  getting main
   updating: main 3/3 files (100.00%)
-  getting main
   1 files updated, 0 files merged, 2 files removed, 0 files unresolved
 
   $ ls
--- a/tests/test-walk.t	Tue Apr 02 16:03:10 2013 +0200
+++ b/tests/test-walk.t	Wed Apr 03 13:03:50 2013 -0500
@@ -155,7 +155,7 @@
   abort: path 'mammals/.hg' is inside nested repo 'mammals' (glob)
   [255]
   $ hg debugwalk ../.hg
-  abort: path contains illegal component: .hg (glob)
+  abort: path contains illegal component: .hg
   [255]
   $ cd ..
 
@@ -187,10 +187,10 @@
   abort: beans/../.. not under root '$TESTTMP/t' (glob)
   [255]
   $ hg debugwalk .hg
-  abort: path contains illegal component: .hg (glob)
+  abort: path contains illegal component: .hg
   [255]
   $ hg debugwalk beans/../.hg
-  abort: path contains illegal component: .hg (glob)
+  abort: path contains illegal component: .hg
   [255]
   $ hg debugwalk beans/../.hg/data
   abort: path contains illegal component: .hg/data (glob)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-websub.t	Wed Apr 03 13:03:50 2013 -0500
@@ -0,0 +1,36 @@
+  $ "$TESTDIR/hghave" serve || exit 80
+
+  $ hg init test
+  $ cd test
+
+  $ cat > .hg/hgrc <<EOF
+  > [extensions]
+  > # this is only necessary to check that the mapping from
+  > # interhg to websub works
+  > interhg =
+  > 
+  > [websub]
+  > issues = s|Issue(\d+)|<a href="http://bts.example.org/issue\1">Issue\1</a>|
+  > 
+  > [interhg]
+  > # check that we maintain some interhg backwards compatibility...
+  > # yes, 'x' is a weird delimiter...
+  > markbugs = sxbugx<i class="\x">bug</i>x
+  > EOF
+
+  $ touch foo
+  $ hg add foo
+  $ hg commit -d '1 0' -m 'Issue123: fixed the bug!'
+
+  $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
+  $ cat hg.pid >> $DAEMON_PIDS
+
+log
+
+  $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT "rev/tip" | grep bts
+  <div class="description"><a href="http://bts.example.org/issue123">Issue123</a>: fixed the <i class="x">bug</i>!</div>
+errors
+
+  $ cat errors.log
+
+  $ cd ..