merge default into stable for 2.8 freeze stable 2.8-rc
authorMatt Mackall <mpm@selenic.com>
Sun, 20 Oct 2013 16:43:11 -0700
branchstable
changeset 19937 1596f2d8f242
parent 19914 f91e932b2cfe (current diff)
parent 19936 8179eb28983b (diff)
child 19938 6e479520f465
merge default into stable for 2.8 freeze
tests/test-mq-strip.t
--- a/contrib/check-code.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/contrib/check-code.py	Sun Oct 20 16:43:11 2013 -0700
@@ -61,11 +61,13 @@
     (r'pushd|popd', "don't use 'pushd' or 'popd', use 'cd'"),
     (r'\W\$?\(\([^\)\n]*\)\)', "don't use (()) or $(()), use 'expr'"),
     (r'grep.*-q', "don't use 'grep -q', redirect to /dev/null"),
+    (r'(?<!hg )grep.*-a', "don't use 'grep -a', use in-line python"),
     (r'sed.*-i', "don't use 'sed -i', use a temporary file"),
     (r'\becho\b.*\\n', "don't use 'echo \\n', use printf"),
     (r'echo -n', "don't use 'echo -n', use printf"),
     (r'(^| )wc[^|]*$\n(?!.*\(re\))', "filter wc output"),
     (r'head -c', "don't use 'head -c', use 'dd'"),
+    (r'tail -n', "don't use the '-n' option to tail, just use '-<num>'"),
     (r'sha1sum', "don't use sha1sum, use $TESTDIR/md5sum.py"),
     (r'ls.*-\w*R', "don't use 'ls -R', use 'find'"),
     (r'printf.*[^\\]\\([1-9]|0\d)', "don't use 'printf \NNN', use Python"),
@@ -118,7 +120,7 @@
     (uprefix + r'.*\|\| echo.*(fail|error)',
      "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"),
+    (uprefix + r'(\s|fi\b|done\b)', "use > for continued lines"),
     (r'^  saved backup bundle to \$TESTTMP.*\.hg$', winglobmsg),
     (r'^  changeset .* references (corrupted|missing) \$TESTTMP/.*[^)]$',
      winglobmsg),
@@ -160,6 +162,9 @@
      "tuple parameter unpacking not available in Python 3+"),
     (r'lambda\s*\(.*,.*\)',
      "tuple parameter unpacking not available in Python 3+"),
+    (r'import (.+,[^.]+\.[^.]+|[^.]+\.[^.]+,)',
+     '2to3 can\'t always rewrite "import qux, foo.bar", '
+     'use "import foo.bar" on its own line instead.'),
     (r'(?<!def)\s+(cmp)\(', "cmp is not available in Python 3+"),
     (r'\breduce\s*\(.*', "reduce is not available in Python 3+"),
     (r'\.has_key\b', "dict.has_key is not available in Python 3+"),
@@ -221,6 +226,8 @@
      "missing whitespace around operator"),
     (r'[^^+=*/!<>&| %-](\s=|=\s)[^= ]',
      "wrong whitespace around ="),
+    (r'\([^()]*( =[^=]|[^<>!=]= )',
+     "no whitespace around = for named parameters"),
     (r'raise Exception', "don't raise generic exceptions"),
     (r'raise [^,(]+, (\([^\)]+\)|[^,\(\)]+)$',
      "don't use old-style two-argument raise, use Exception(message)"),
@@ -285,8 +292,9 @@
     (r'(while|if|do|for)\(', "use space after while/if/do/for"),
     (r'return\(', "return is not a function"),
     (r' ;', "no space before ;"),
+    (r'[)][{]', "space between ) and {"),
     (r'\w+\* \w+', "use int *foo, not int* foo"),
-    (r'\([^\)]+\) \w+', "use (int)foo, not (int) foo"),
+    (r'\W\([^\)]+\) \w+', "use (int)foo, not (int) foo"),
     (r'\w+ (\+\+|--)', "use foo++, not foo ++"),
     (r'\w,\w', "missing whitespace after ,"),
     (r'^[^#]\w[+/*]\w', "missing whitespace in expression"),
@@ -324,7 +332,7 @@
 checks = [
     ('python', r'.*\.(py|cgi)$', pyfilters, pypats),
     ('test script', r'(.*/)?test-[^.~]*$', testfilters, testpats),
-    ('c', r'.*\.c$', cfilters, cpats),
+    ('c', r'.*\.[ch]$', cfilters, cpats),
     ('unified test', r'.*\.t$', utestfilters, utestpats),
     ('layering violation repo in revlog', r'mercurial/revlog\.py', pyfilters,
      inrevlogpats),
--- a/contrib/debugshell.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/contrib/debugshell.py	Sun Oct 20 16:43:11 2013 -0700
@@ -1,20 +1,52 @@
 # debugshell extension
 """a python shell with repo, changelog & manifest objects"""
 
+import sys
 import mercurial
 import code
 
-def debugshell(ui, repo, **opts):
+def pdb(ui, repo, msg, **opts):
     objects = {
         'mercurial': mercurial,
         'repo': repo,
         'cl': repo.changelog,
         'mf': repo.manifest,
     }
+
+    code.interact(msg, local=objects)
+
+def ipdb(ui, repo, msg, **opts):
+    import IPython
+
+    cl = repo.changelog
+    mf = repo.manifest
+    cl, mf # use variables to appease pyflakes
+
+    IPython.embed()
+
+def debugshell(ui, repo, **opts):
     bannermsg = "loaded repo : %s\n" \
                 "using source: %s" % (repo.root,
                                       mercurial.__path__[0])
-    code.interact(bannermsg, local=objects)
+
+    pdbmap = {
+        'pdb'  : 'code',
+        'ipdb' : 'IPython'
+    }
+
+    debugger = ui.config("ui", "debugger")
+    if not debugger:
+        debugger = 'pdb'
+
+    # if IPython doesn't exist, fallback to code.interact
+    try:
+        __import__(pdbmap[debugger])
+    except ImportError:
+        ui.warn("%s debugger specified but %s module was not found\n"
+                % (debugger, pdbmap[debugger]))
+        debugger = 'pdb'
+
+    getattr(sys.modules[__name__], debugger)(ui, repo, bannermsg, **opts)
 
 cmdtable = {
     "debugshell|dbsh": (debugshell, [])
--- a/contrib/hgfixes/fix_bytesmod.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/contrib/hgfixes/fix_bytesmod.py	Sun Oct 20 16:43:11 2013 -0700
@@ -58,6 +58,6 @@
         else:
             args = [formatstr, Comma().clone(), data]
 
-        call = Call(Name('bytesformatter', prefix = ' '), args)
+        call = Call(Name('bytesformatter', prefix=' '), args)
         return call
 
--- a/contrib/perf.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/contrib/perf.py	Sun Oct 20 16:43:11 2013 -0700
@@ -87,7 +87,8 @@
 
 @command('perftags')
 def perftags(ui, repo):
-    import mercurial.changelog, mercurial.manifest
+    import mercurial.changelog
+    import mercurial.manifest
     def t():
         repo.changelog = mercurial.changelog.changelog(repo.sopener)
         repo.manifest = mercurial.manifest.manifest(repo.sopener)
@@ -171,13 +172,14 @@
         copies.pathcopies(ctx1, ctx2)
     timer(d)
 
-@command('perfmanifest')
-def perfmanifest(ui, repo):
+@command('perfmanifest', [], 'REV')
+def perfmanifest(ui, repo, rev):
+    ctx = scmutil.revsingle(repo, rev, rev)
+    t = ctx.manifestnode()
     def d():
-        t = repo.manifest.tip()
+        repo.manifest._mancache.clear()
+        repo.manifest._cache = None
         repo.manifest.read(t)
-        repo.manifest.mapcache = None
-        repo.manifest._cache = None
     timer(d)
 
 @command('perfchangeset')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/plan9/9mail	Sun Oct 20 16:43:11 2013 -0700
@@ -0,0 +1,26 @@
+#!/bin/rc
+# 9mail - Mercurial email wrapper for upas/marshal
+
+fn usage {
+	echo >[1=2] usage: mercurial/9mail -f from to [cc]
+	exit usage
+}
+
+from=()
+cc=()
+to=()
+
+switch($1){
+case -f
+	from=$2
+case *
+	usage
+}
+
+to=($3)
+if(~ $#* 4)
+	cc=(-C $4)
+
+upasname=$from
+upas/marshal $cc $to
+
--- a/contrib/plan9/hgrc.d/9diff.rc	Sat Oct 19 14:20:31 2013 -0700
+++ b/contrib/plan9/hgrc.d/9diff.rc	Sun Oct 20 16:43:11 2013 -0700
@@ -4,4 +4,4 @@
 extdiff =
 
 [extdiff]
-9diff = 9diff -cm $parent $child $root
+9diff = /bin/mercurial/9diff -cm $parent $child $root
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/plan9/hgrc.d/9mail.rc	Sun Oct 20 16:43:11 2013 -0700
@@ -0,0 +1,4 @@
+# The 9mail to support patchbomb and other email wrappers
+[email]
+method = /bin/mercurial/9mail
+
--- a/hgext/acl.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/hgext/acl.py	Sun Oct 20 16:43:11 2013 -0700
@@ -284,8 +284,8 @@
 
     cfg = ui.config('acl', 'config')
     if cfg:
-        ui.readconfig(cfg, sections = ['acl.groups', 'acl.allow.branches',
-        'acl.deny.branches', 'acl.allow', 'acl.deny'])
+        ui.readconfig(cfg, sections=['acl.groups', 'acl.allow.branches',
+            'acl.deny.branches', 'acl.allow', 'acl.deny'])
 
     allowbranches = buildmatch(ui, None, user, 'acl.allow.branches')
     denybranches = buildmatch(ui, None, user, 'acl.deny.branches')
--- a/hgext/color.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/hgext/color.py	Sun Oct 20 16:43:11 2013 -0700
@@ -63,6 +63,10 @@
   rebase.rebased = blue
   rebase.remaining = red bold
 
+  shelve.age = cyan
+  shelve.newest = green bold
+  shelve.name = blue bold
+
   histedit.remaining = red bold
 
 The available effects in terminfo mode are 'blink', 'bold', 'dim',
@@ -259,6 +263,9 @@
            'rebase.remaining': 'red bold',
            'resolve.resolved': 'green bold',
            'resolve.unresolved': 'red bold',
+           'shelve.age': 'cyan',
+           'shelve.newest': 'green bold',
+           'shelve.name': 'blue bold',
            'status.added': 'green bold',
            'status.clean': 'none',
            'status.copied': 'none',
--- a/hgext/convert/__init__.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/hgext/convert/__init__.py	Sun Oct 20 16:43:11 2013 -0700
@@ -155,8 +155,7 @@
         (forces target IDs to change). It takes a boolean argument and
         defaults to False.
 
-    :convert.hg.startrev: convert start revision and its descendants.
-        It takes a hg revision identifier and defaults to 0.
+    :convert.hg.revs: revset specifying the source revisions to convert.
 
     CVS Source
     ##########
@@ -311,7 +310,7 @@
           ('d', 'dest-type', '',
            _('destination repository type'), _('TYPE')),
           ('r', 'rev', '',
-           _('import up to target revision REV'), _('REV')),
+           _('import up to source revision REV'), _('REV')),
           ('A', 'authormap', '',
            _('remap usernames using this file'), _('FILE')),
           ('', 'filemap', '',
--- a/hgext/convert/convcmd.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/hgext/convert/convcmd.py	Sun Oct 20 16:43:11 2013 -0700
@@ -516,10 +516,7 @@
         destc.setfilemapmode(True)
 
     if not revmapfile:
-        try:
-            revmapfile = destc.revmapfile()
-        except Exception:
-            revmapfile = os.path.join(destc, "map")
+        revmapfile = destc.revmapfile()
 
     c = converter(ui, srcc, destc, revmapfile, opts)
     c.convert(sortmode)
--- a/hgext/convert/filemap.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/hgext/convert/filemap.py	Sun Oct 20 16:43:11 2013 -0700
@@ -7,7 +7,7 @@
 import posixpath
 import shlex
 from mercurial.i18n import _
-from mercurial import util
+from mercurial import util, error
 from common import SKIPREV, converter_source
 
 def rpairs(name):
@@ -195,12 +195,19 @@
         self.seenchildren.clear()
         for rev, wanted, arg in self.convertedorder:
             if rev not in self.origparents:
-                self.origparents[rev] = self.getcommit(rev).parents
+                try:
+                    self.origparents[rev] = self.getcommit(rev).parents
+                except error.RepoLookupError:
+                    self.ui.debug("unknown revmap source: %s\n" % rev)
+                    continue
             if arg is not None:
                 self.children[arg] = self.children.get(arg, 0) + 1
 
         for rev, wanted, arg in self.convertedorder:
-            parents = self.origparents[rev]
+            try:
+                parents = self.origparents[rev]
+            except KeyError:
+                continue # unknown revmap source
             if wanted:
                 self.mark_wanted(rev, parents)
             else:
@@ -231,8 +238,8 @@
                 continue
             self.seenchildren[r] = self.seenchildren.get(r, 0) + 1
             if self.seenchildren[r] == self.children[r]:
-                del self.wantedancestors[r]
-                del self.parentmap[r]
+                self.wantedancestors.pop(r, None)
+                self.parentmap.pop(r, None)
                 del self.seenchildren[r]
                 if self._rebuilt:
                     del self.children[r]
@@ -281,7 +288,11 @@
         # of wanted ancestors of its parents. Plus rev itself.
         wrev = set()
         for p in parents:
-            wrev.update(self.wantedancestors[p])
+            if p in self.wantedancestors:
+                wrev.update(self.wantedancestors[p])
+            else:
+                self.ui.warn(_('warning: %s parent %s is missing\n') %
+                             (rev, p))
         wrev.add(rev)
         self.wantedancestors[rev] = wrev
 
@@ -398,3 +409,6 @@
 
     def getbookmarks(self):
         return self.base.getbookmarks()
+
+    def converted(self, rev, sinkrev):
+        self.base.converted(rev, sinkrev)
--- a/hgext/convert/hg.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/hgext/convert/hg.py	Sun Oct 20 16:43:11 2013 -0700
@@ -21,7 +21,7 @@
 import os, time, cStringIO
 from mercurial.i18n import _
 from mercurial.node import bin, hex, nullid
-from mercurial import hg, util, context, bookmarks, error
+from mercurial import hg, util, context, bookmarks, error, scmutil
 
 from common import NoRepo, commit, converter_source, converter_sink
 
@@ -252,19 +252,37 @@
         self.convertfp = None
         # Restrict converted revisions to startrev descendants
         startnode = ui.config('convert', 'hg.startrev')
-        if startnode is not None:
-            try:
-                startnode = self.repo.lookup(startnode)
-            except error.RepoError:
-                raise util.Abort(_('%s is not a valid start revision')
-                                 % startnode)
-            startrev = self.repo.changelog.rev(startnode)
-            children = {startnode: 1}
-            for rev in self.repo.changelog.descendants([startrev]):
-                children[self.repo.changelog.node(rev)] = 1
-            self.keep = children.__contains__
+        hgrevs = ui.config('convert', 'hg.revs')
+        if hgrevs is None:
+            if startnode is not None:
+                try:
+                    startnode = self.repo.lookup(startnode)
+                except error.RepoError:
+                    raise util.Abort(_('%s is not a valid start revision')
+                                     % startnode)
+                startrev = self.repo.changelog.rev(startnode)
+                children = {startnode: 1}
+                for r in self.repo.changelog.descendants([startrev]):
+                    children[self.repo.changelog.node(r)] = 1
+                self.keep = children.__contains__
+            else:
+                self.keep = util.always
+            if rev:
+                self._heads = [self.repo[rev].node()]
+            else:
+                self._heads = self.repo.heads()
         else:
-            self.keep = util.always
+            if rev or startnode is not None:
+                raise util.Abort(_('hg.revs cannot be combined with '
+                                   'hg.startrev or --rev'))
+            nodes = set()
+            parents = set()
+            for r in scmutil.revrange(self.repo, [hgrevs]):
+                ctx = self.repo[r]
+                nodes.add(ctx.node())
+                parents.update(p.node() for p in ctx.parents())
+            self.keep = nodes.__contains__
+            self._heads = nodes - parents
 
     def changectx(self, rev):
         if self.lastrev != rev:
@@ -276,11 +294,7 @@
         return [p for p in ctx.parents() if p and self.keep(p.node())]
 
     def getheads(self):
-        if self.rev:
-            heads = [self.repo[self.rev].node()]
-        else:
-            heads = self.repo.heads()
-        return [hex(h) for h in heads if self.keep(h)]
+        return [hex(h) for h in self._heads if self.keep(h)]
 
     def getfile(self, name, rev):
         try:
--- a/hgext/convert/subversion.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/hgext/convert/subversion.py	Sun Oct 20 16:43:11 2013 -0700
@@ -2,7 +2,8 @@
 #
 # Copyright(C) 2007 Daniel Holth et al
 
-import os, re, sys, tempfile, urllib, urllib2, xml.dom.minidom
+import os, re, sys, tempfile, urllib, urllib2
+import xml.dom.minidom
 import cPickle as pickle
 
 from mercurial import strutil, scmutil, util, encoding
--- a/hgext/factotum.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/hgext/factotum.py	Sun Oct 20 16:43:11 2013 -0700
@@ -101,7 +101,7 @@
         user, passwd = auth.get('username'), auth.get('password')
     if not user or not passwd:
         if not prefix:
-            prefix = '*'
+            prefix = realm.split(' ')[0].lower()
         params = 'service=%s prefix=%s' % (_service, prefix)
         if user:
             params = '%s user=%s' % (params, user)
--- a/hgext/highlight/__init__.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/hgext/highlight/__init__.py	Sun Oct 20 16:43:11 2013 -0700
@@ -50,7 +50,7 @@
 
 def generate_css(web, req, tmpl):
     pg_style = web.config('web', 'pygments_style', 'colorful')
-    fmter = highlight.HtmlFormatter(style = pg_style)
+    fmter = highlight.HtmlFormatter(style=pg_style)
     req.respond(common.HTTP_OK, 'text/css')
     return ['/* pygments_style = %s */\n\n' % pg_style,
             fmter.get_style_defs('')]
--- a/hgext/histedit.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/hgext/histedit.py	Sun Oct 20 16:43:11 2013 -0700
@@ -419,10 +419,6 @@
     if revs:
         revs = [repo.lookup(rev) for rev in revs]
 
-    # hexlify nodes from outgoing, because we're going to parse
-    # parent[0] using revsingle below, and if the binary hash
-    # contains special revset characters like ":" the revset
-    # parser can choke.
     outgoing = discovery.findcommonoutgoing(repo, other, revs, force=force)
     if not outgoing.missing:
         raise util.Abort(_('no outgoing ancestors'))
@@ -519,7 +515,6 @@
 
     if goal == 'continue':
         (parentctxnode, rules, keep, topmost, replacements) = readstate(repo)
-        currentparent, wantnull = repo.dirstate.parents()
         parentctx = repo[parentctxnode]
         parentctx, repl = bootstrapcontinue(ui, repo, parentctx, rules, opts)
         replacements.extend(repl)
--- a/hgext/inotify/server.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/hgext/inotify/server.py	Sun Oct 20 16:43:11 2013 -0700
@@ -451,8 +451,9 @@
         runargs = util.hgcmd() + sys.argv[1:]
 
     pidfile = ui.config('inotify', 'pidfile')
-    if opts['daemon'] and pidfile is not None and 'pid-file' not in runargs:
-        runargs.append("--pid-file=%s" % pidfile)
+    opts.setdefault('pid_file', '')
+    if opts['daemon'] and pidfile is not None and not opts['pid_file']:
+        opts['pid_file'] = pidfile
 
     service = service()
     logfile = ui.config('inotify', 'log')
--- a/hgext/largefiles/__init__.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/hgext/largefiles/__init__.py	Sun Oct 20 16:43:11 2013 -0700
@@ -105,16 +105,23 @@
 command.
 '''
 
-from mercurial import commands
+from mercurial import commands, localrepo
 
 import lfcommands
 import reposetup
-import uisetup
+import uisetup as uisetupmod
 
 testedwith = 'internal'
 
 reposetup = reposetup.reposetup
-uisetup = uisetup.uisetup
+
+def featuresetup(ui, supported):
+    # don't die on seeing a repo with the largefiles requirement
+    supported |= set(['largefiles'])
+
+def uisetup(ui):
+    localrepo.localrepository.featuresetupfuncs.add(featuresetup)
+    uisetupmod.uisetup(ui)
 
 commands.norepo += " lfconvert"
 
--- a/hgext/largefiles/basestore.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/hgext/largefiles/basestore.py	Sun Oct 20 16:43:11 2013 -0700
@@ -59,8 +59,6 @@
         missing = []
         ui = self.ui
 
-        util.makedirs(lfutil.storepath(self.repo, ''))
-
         at = 0
         available = self.exists(set(hash for (_filename, hash) in files))
         for filename, hash in files:
@@ -75,32 +73,44 @@
                 missing.append(filename)
                 continue
 
-            storefilename = lfutil.storepath(self.repo, hash)
-            tmpfile = util.atomictempfile(storefilename + '.tmp',
-                                          createmode=self.repo.store.createmode)
-
-            try:
-                hhash = self._getfile(tmpfile, filename, hash)
-            except StoreError, err:
-                ui.warn(err.longmessage())
-                hhash = ""
-            tmpfile.close()
-
-            if hhash != hash:
-                if hhash != "":
-                    ui.warn(_('%s: data corruption (expected %s, got %s)\n')
-                            % (filename, hash, hhash))
-                util.unlink(storefilename + '.tmp')
+            if self._gethash(filename, hash):
+                success.append((filename, hash))
+            else:
                 missing.append(filename)
-                continue
-
-            util.rename(storefilename + '.tmp', storefilename)
-            lfutil.linktousercache(self.repo, hash)
-            success.append((filename, hhash))
 
         ui.progress(_('getting largefiles'), None)
         return (success, missing)
 
+    def _gethash(self, filename, hash):
+        """Get file with the provided hash and store it in the local repo's
+        store and in the usercache.
+        filename is for informational messages only.
+        """
+        util.makedirs(lfutil.storepath(self.repo, ''))
+        storefilename = lfutil.storepath(self.repo, hash)
+
+        tmpname = storefilename + '.tmp'
+        tmpfile = util.atomictempfile(tmpname,
+                                      createmode=self.repo.store.createmode)
+
+        try:
+            gothash = self._getfile(tmpfile, filename, hash)
+        except StoreError, err:
+            self.ui.warn(err.longmessage())
+            gothash = ""
+        tmpfile.close()
+
+        if gothash != hash:
+            if gothash != "":
+                self.ui.warn(_('%s: data corruption (expected %s, got %s)\n')
+                             % (filename, hash, gothash))
+            util.unlink(tmpname)
+            return False
+
+        util.rename(tmpname, storefilename)
+        lfutil.linktousercache(self.repo, hash)
+        return True
+
     def verify(self, revs, contents=False):
         '''Verify the existence (and, optionally, contents) of every big
         file revision referenced by every changeset in revs.
--- a/hgext/largefiles/overrides.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/hgext/largefiles/overrides.py	Sun Oct 20 16:43:11 2013 -0700
@@ -315,7 +315,7 @@
                     lfdirstate.normal(lfile)
             lfdirstate.write()
             if mod:
-                raise util.Abort(_('uncommitted local changes'))
+                raise util.Abort(_('uncommitted changes'))
         # XXX handle removed differently
         if not opts['clean']:
             for lfile in unsure + modified + added:
@@ -717,7 +717,6 @@
                 ui.debug('--update and --rebase are not compatible, ignoring '
                          'the update flag\n')
             del opts['rebase']
-            cmdutil.bailifchanged(repo)
             origpostincoming = commands.postincoming
             def _dummy(*args, **kwargs):
                 pass
@@ -947,7 +946,7 @@
     modified, added, removed, deleted = repo.status()[:4]
     repo.lfstatus = False
     if modified or added or removed or deleted:
-        raise util.Abort(_('outstanding uncommitted changes'))
+        raise util.Abort(_('uncommitted changes'))
 
 # Fetch doesn't use cmdutil.bailifchanged so override it to add the check
 def overridefetch(orig, ui, repo, *pats, **opts):
@@ -955,7 +954,7 @@
     modified, added, removed, deleted = repo.status()[:4]
     repo.lfstatus = False
     if modified or added or removed or deleted:
-        raise util.Abort(_('outstanding uncommitted changes'))
+        raise util.Abort(_('uncommitted changes'))
     return orig(ui, repo, *pats, **opts)
 
 def overrideforget(orig, ui, repo, *pats, **opts):
--- a/hgext/largefiles/proto.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/hgext/largefiles/proto.py	Sun Oct 20 16:43:11 2013 -0700
@@ -5,6 +5,7 @@
 
 import os
 import urllib2
+import re
 
 from mercurial import error, httppeer, util, wireproto
 from mercurial.wireproto import batchable, future
@@ -166,9 +167,11 @@
         args['cmds'] = args['cmds'].replace('heads ', 'lheads ')
     return ssholdcallstream(self, cmd, **args)
 
+headsre = re.compile(r'(^|;)heads\b')
+
 def httprepocallstream(self, cmd, **args):
     if cmd == 'heads' and self.capable('largefiles'):
         cmd = 'lheads'
     if cmd == 'batch' and self.capable('largefiles'):
-        args['cmds'] = args['cmds'].replace('heads ', 'lheads ')
+        args['cmds'] = headsre.sub('lheads', args['cmds'])
     return httpoldcallstream(self, cmd, **args)
--- a/hgext/largefiles/reposetup.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/hgext/largefiles/reposetup.py	Sun Oct 20 16:43:11 2013 -0700
@@ -10,8 +10,7 @@
 import copy
 import os
 
-from mercurial import context, error, manifest, match as match_, util, \
-    discovery
+from mercurial import error, manifest, match as match_, util, discovery
 from mercurial import node as node_
 from mercurial.i18n import _
 from mercurial import localrepo
@@ -92,14 +91,8 @@
             else:
                 # some calls in this function rely on the old version of status
                 self.lfstatus = False
-                if isinstance(node1, context.changectx):
-                    ctx1 = node1
-                else:
-                    ctx1 = self[node1]
-                if isinstance(node2, context.changectx):
-                    ctx2 = node2
-                else:
-                    ctx2 = self[node2]
+                ctx1 = self[node1]
+                ctx2 = self[node2]
                 working = ctx2.rev() is None
                 parentworking = working and ctx1 == self['.']
 
@@ -414,6 +407,14 @@
                 wlock.release()
 
         def push(self, remote, force=False, revs=None, newbranch=False):
+            if remote.local():
+                missing = set(self.requirements) - remote.local().supported
+                if missing:
+                    msg = _("required features are not"
+                            " supported in the destination:"
+                            " %s") % (', '.join(sorted(missing)))
+                    raise util.Abort(msg)
+
             outgoing = discovery.findcommonoutgoing(repo, remote.peer(),
                                                     force=force)
             if outgoing.missing:
--- a/hgext/largefiles/uisetup.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/hgext/largefiles/uisetup.py	Sun Oct 20 16:43:11 2013 -0700
@@ -9,7 +9,7 @@
 '''setup for largefiles extension: uisetup'''
 
 from mercurial import archival, cmdutil, commands, extensions, filemerge, hg, \
-    httppeer, localrepo, merge, scmutil, sshpeer, wireproto, revset
+    httppeer, merge, scmutil, sshpeer, wireproto, revset
 from mercurial.i18n import _
 from mercurial.hgweb import hgweb_mod, webcommands
 from mercurial.subrepo import hgsubrepo
@@ -152,9 +152,6 @@
     sshpeer.sshpeer._callstream = proto.sshrepocallstream
     httppeer.httppeer._callstream = proto.httprepocallstream
 
-    # don't die on seeing a repo with the largefiles requirement
-    localrepo.localrepository.supported |= set(['largefiles'])
-
     # override some extensions' stuff as well
     for name, module in extensions.extensions():
         if name == 'fetch':
--- a/hgext/mq.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/hgext/mq.py	Sun Oct 20 16:43:11 2013 -0700
@@ -57,15 +57,19 @@
 make them behave as if --keep-changes were passed, and non-conflicting
 local changes will be tolerated and preserved. If incompatible options
 such as -f/--force or --exact are passed, this setting is ignored.
+
+This extension used to provide a strip command. This command now lives
+in the strip extension.
 '''
 
 from mercurial.i18n import _
 from mercurial.node import bin, hex, short, nullid, nullrev
 from mercurial.lock import release
 from mercurial import commands, cmdutil, hg, scmutil, util, revset
-from mercurial import repair, extensions, error, phases, bookmarks
+from mercurial import extensions, error, phases
 from mercurial import patch as patchmod
 from mercurial import localrepo
+from mercurial import subrepo
 import os, re, errno, shutil
 
 commands.norepo += " qclone"
@@ -76,6 +80,22 @@
 command = cmdutil.command(cmdtable)
 testedwith = 'internal'
 
+# force load strip extension formely included in mq and import some utility
+try:
+    stripext = extensions.find('strip')
+except KeyError:
+    # note: load is lazy so we could avoid the try-except,
+    # but I (marmoute) prefer this explicite code.
+    class dummyui(object):
+        def debug(self, msg):
+            pass
+    stripext = extensions.load(dummyui(), 'strip', '')
+
+strip = stripext.strip
+checksubstate = stripext.checksubstate
+checklocalchanges = stripext.checklocalchanges
+
+
 # Patch names looks like unix-file names.
 # They must be joinable with queue directory and result in the patch path.
 normname = util.normpath
@@ -282,15 +302,11 @@
             phase = phases.secret
     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().
-    repo._committingpatch = True
     try:
         if phase is not None:
             repo.ui.setconfig('phases', 'new-commit', phase)
         return repo.commit(*args, **kwargs)
     finally:
-        repo._committingpatch = False
         if phase is not None:
             repo.ui.restoreconfig(backup)
 
@@ -331,6 +347,7 @@
         except error.ConfigError:
             self.gitmode = ui.config('mq', 'git', 'auto').lower()
         self.plainmode = ui.configbool('mq', 'plain', False)
+        self.checkapplied = True
 
     @util.propertycache
     def applied(self):
@@ -606,7 +623,7 @@
 
         # apply failed, strip away that rev and merge.
         hg.clean(repo, head)
-        self.strip(repo, [n], update=False, backup='strip')
+        strip(self.ui, repo, [n], update=False, backup='strip')
 
         ctx = repo[rev]
         ret = hg.merge(repo, rev)
@@ -631,6 +648,14 @@
         return (0, n)
 
     def qparents(self, repo, rev=None):
+        """return the mq handled parent or p1
+
+        In some case where mq get himself in being the parent of a merge the
+        paappropriate parent may be p2.
+        (eg: an in progress merge started with mq disabled)
+
+        If no parent are managed by mq, p1 is returned.
+        """
         if rev is None:
             (p1, p2) = repo.dirstate.parents()
             if p2 == nullid:
@@ -800,6 +825,14 @@
                 p1, p2 = repo.dirstate.parents()
                 repo.setparents(p1, merge)
 
+            if all_files and '.hgsubstate' in all_files:
+                wctx = repo['.']
+                mctx = actx = repo[None]
+                overwrite = False
+                mergedsubstate = subrepo.submerge(repo, wctx, mctx, actx,
+                    overwrite)
+                files += mergedsubstate.keys()
+
             match = scmutil.matchfiles(repo, files or [])
             oldtip = repo['tip']
             n = newcommit(repo, None, message, ph.user, ph.date, match=match,
@@ -940,23 +973,6 @@
             return top, patch
         return None, None
 
-    def checksubstate(self, repo, baserev=None):
-        '''return list of subrepos at a different revision than substate.
-        Abort if any subrepos have uncommitted changes.'''
-        inclsubs = []
-        wctx = repo[None]
-        if baserev:
-            bctx = repo[baserev]
-        else:
-            bctx = wctx.parents()[0]
-        for s in sorted(wctx.substate):
-            if wctx.sub(s).dirty(True):
-                raise util.Abort(
-                    _("uncommitted changes in subrepository %s") % s)
-            elif s not in bctx.substate or bctx.sub(s).dirty():
-                inclsubs.append(s)
-        return inclsubs
-
     def putsubstate2changes(self, substatestate, changes):
         for files in changes[:3]:
             if '.hgsubstate' in files:
@@ -969,18 +985,14 @@
         else: # modified
             changes[0].append('.hgsubstate')
 
-    def localchangesfound(self, refresh=True):
+    def checklocalchanges(self, repo, force=False, refresh=True):
+        excsuffix = ''
         if refresh:
-            raise util.Abort(_("local changes found, refresh first"))
-        else:
-            raise util.Abort(_("local changes found"))
-
-    def checklocalchanges(self, repo, force=False, refresh=True):
-        cmdutil.checkunfinished(repo)
-        m, a, r, d = repo.status()[:4]
-        if (m or a or r or d) and not force:
-            self.localchangesfound(refresh)
-        return m, a, r, d
+            excsuffix = ', refresh first'
+            # plain versions for i18n tool to detect them
+            _("local changes found, refresh first")
+            _("local changed subrepos found, refresh first")
+        return checklocalchanges(repo, force, excsuffix)
 
     _reserved = ('series', 'status', 'guards', '.', '..')
     def checkreservedname(self, name):
@@ -1021,7 +1033,7 @@
         diffopts = self.diffopts({'git': opts.get('git')})
         if opts.get('checkname', True):
             self.checkpatchname(patchfn)
-        inclsubs = self.checksubstate(repo)
+        inclsubs = checksubstate(repo)
         if inclsubs:
             inclsubs.append('.hgsubstate')
             substatestate = repo.dirstate['.hgsubstate']
@@ -1111,22 +1123,6 @@
         finally:
             release(wlock)
 
-    def strip(self, repo, revs, update=True, backup="all", force=None):
-        wlock = lock = None
-        try:
-            wlock = repo.wlock()
-            lock = repo.lock()
-
-            if update:
-                self.checklocalchanges(repo, force=force, refresh=False)
-                urev = self.qparents(repo, revs[0])
-                hg.clean(repo, urev)
-                repo.dirstate.write()
-
-            repair.strip(self.ui, repo, revs, backup)
-        finally:
-            release(lock, wlock)
-
     def isapplied(self, patch):
         """returns (index, rev, patch)"""
         for i, a in enumerate(self.applied):
@@ -1208,9 +1204,7 @@
         diffopts = self.diffopts()
         wlock = repo.wlock()
         try:
-            heads = []
-            for b, ls in repo.branchmap().iteritems():
-                heads += ls
+            heads = [h for hs in repo.branchmap().itervalues() for h in hs]
             if not heads:
                 heads = [nullid]
             if repo.dirstate.p1() not in heads and not exact:
@@ -1435,7 +1429,7 @@
 
                 tobackup = set(a + m + r) & tobackup
                 if keepchanges and tobackup:
-                    self.localchangesfound()
+                    raise util.Abort(_("local changes found, refresh first"))
                 self.backup(repo, tobackup)
 
                 for f in a:
@@ -1449,7 +1443,9 @@
             for patch in reversed(self.applied[start:end]):
                 self.ui.status(_("popping %s\n") % patch.name)
             del self.applied[start:end]
-            self.strip(repo, [rev], update=False, backup='strip')
+            strip(self.ui, repo, [rev], update=False, backup='strip')
+            for s, state in repo['.'].substate.items():
+                repo['.'].sub(s).get(state)
             if self.applied:
                 self.ui.write(_("now at: %s\n") % self.applied[-1].name)
             else:
@@ -1493,7 +1489,7 @@
             cparents = repo.changelog.parents(top)
             patchparent = self.qparents(repo, top)
 
-            inclsubs = self.checksubstate(repo, hex(patchparent))
+            inclsubs = checksubstate(repo, hex(patchparent))
             if inclsubs:
                 inclsubs.append('.hgsubstate')
                 substatestate = repo.dirstate['.hgsubstate']
@@ -1650,8 +1646,7 @@
                 repo.setparents(*cparents)
                 self.applied.pop()
                 self.applieddirty = True
-                self.strip(repo, [top], update=False,
-                           backup='strip')
+                strip(self.ui, repo, [top], update=False, backup='strip')
             except: # re-raises
                 repo.dirstate.invalidate()
                 raise
@@ -1823,7 +1818,7 @@
                     update = True
                 else:
                     update = False
-                self.strip(repo, [rev], update=update, backup='strip')
+                strip(self.ui, repo, [rev], update=update, backup='strip')
         if qpp:
             self.ui.warn(_("saved queue repository parents: %s %s\n") %
                          (short(qpp[0]), short(qpp[1])))
@@ -2304,7 +2299,7 @@
         if qbase:
             ui.note(_('stripping applied patches from destination '
                       'repository\n'))
-            repo.mq.strip(repo, [qbase], update=False, backup=None)
+            strip(ui, repo, [qbase], update=False, backup=None)
         if not opts.get('noupdate'):
             ui.note(_('updating destination repository\n'))
             hg.update(repo, repo.changelog.tip())
@@ -2919,158 +2914,6 @@
         q.savedirty()
     return 0
 
-@command("strip",
-         [
-          ('r', 'rev', [], _('strip specified revision (optional, '
-                               'can specify revisions without this '
-                               'option)'), _('REV')),
-          ('f', 'force', None, _('force removal of changesets, discard '
-                                 'uncommitted changes (no backup)')),
-          ('b', 'backup', None, _('bundle only changesets with local revision'
-                                  ' number greater than REV which are not'
-                                  ' descendants of REV (DEPRECATED)')),
-          ('', 'no-backup', None, _('no backups')),
-          ('', 'nobackup', None, _('no backups (DEPRECATED)')),
-          ('n', '', None, _('ignored  (DEPRECATED)')),
-          ('k', 'keep', None, _("do not modify working copy during strip")),
-          ('B', 'bookmark', '', _("remove revs only reachable from given"
-                                  " bookmark"))],
-          _('hg strip [-k] [-f] [-n] [-B bookmark] [-r] REV...'))
-def strip(ui, repo, *revs, **opts):
-    """strip changesets and all their descendants from the repository
-
-    The strip command removes the specified changesets and all their
-    descendants. If the working directory has uncommitted changes, the
-    operation is aborted unless the --force flag is supplied, in which
-    case changes will be discarded.
-
-    If a parent of the working directory is stripped, then the working
-    directory will automatically be updated to the most recent
-    available ancestor of the stripped parent after the operation
-    completes.
-
-    Any stripped changesets are stored in ``.hg/strip-backup`` as a
-    bundle (see :hg:`help bundle` and :hg:`help unbundle`). They can
-    be restored by running :hg:`unbundle .hg/strip-backup/BUNDLE`,
-    where BUNDLE is the bundle file created by the strip. Note that
-    the local revision numbers will in general be different after the
-    restore.
-
-    Use the --no-backup option to discard the backup bundle once the
-    operation completes.
-
-    Strip is not a history-rewriting operation and can be used on
-    changesets in the public phase. But if the stripped changesets have
-    been pushed to a remote repository you will likely pull them again.
-
-    Return 0 on success.
-    """
-    backup = 'all'
-    if opts.get('backup'):
-        backup = 'strip'
-    elif opts.get('no_backup') or opts.get('nobackup'):
-        backup = 'none'
-
-    cl = repo.changelog
-    revs = list(revs) + opts.get('rev')
-    revs = set(scmutil.revrange(repo, revs))
-
-    if opts.get('bookmark'):
-        mark = opts.get('bookmark')
-        marks = repo._bookmarks
-        if mark not in marks:
-            raise util.Abort(_("bookmark '%s' not found") % mark)
-
-        # If the requested bookmark is not the only one pointing to a
-        # a revision we have to only delete the bookmark and not strip
-        # anything. revsets cannot detect that case.
-        uniquebm = True
-        for m, n in marks.iteritems():
-            if m != mark and n == repo[mark].node():
-                uniquebm = False
-                break
-        if uniquebm:
-            rsrevs = repo.revs("ancestors(bookmark(%s)) - "
-                               "ancestors(head() and not bookmark(%s)) - "
-                               "ancestors(bookmark() and not bookmark(%s))",
-                               mark, mark, mark)
-            revs.update(set(rsrevs))
-        if not revs:
-            del marks[mark]
-            marks.write()
-            ui.write(_("bookmark '%s' deleted\n") % mark)
-
-    if not revs:
-        raise util.Abort(_('empty revision set'))
-
-    descendants = set(cl.descendants(revs))
-    strippedrevs = revs.union(descendants)
-    roots = revs.difference(descendants)
-
-    update = False
-    # if one of the wdir parent is stripped we'll need
-    # to update away to an earlier revision
-    for p in repo.dirstate.parents():
-        if p != nullid and cl.rev(p) in strippedrevs:
-            update = True
-            break
-
-    rootnodes = set(cl.node(r) for r in roots)
-
-    q = repo.mq
-    if q.applied:
-        # refresh queue state if we're about to strip
-        # applied patches
-        if cl.rev(repo.lookup('qtip')) in strippedrevs:
-            q.applieddirty = True
-            start = 0
-            end = len(q.applied)
-            for i, statusentry in enumerate(q.applied):
-                if statusentry.node in rootnodes:
-                    # if one of the stripped roots is an applied
-                    # patch, only part of the queue is stripped
-                    start = i
-                    break
-            del q.applied[start:end]
-            q.savedirty()
-
-    revs = sorted(rootnodes)
-    if update and opts.get('keep'):
-        wlock = repo.wlock()
-        try:
-            urev = repo.mq.qparents(repo, revs[0])
-            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:
-                # blindly 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:
-            wlock.release()
-
-    if opts.get('bookmark'):
-        if mark == repo._bookmarkcurrent:
-            bookmarks.setcurrent(repo, None)
-        del marks[mark]
-        marks.write()
-        ui.write(_("bookmark '%s' deleted\n") % mark)
-
-    repo.mq.strip(repo, revs, backup=backup, update=update,
-                  force=opts.get('force'))
-
-    return 0
 
 @command("qselect",
          [('n', 'none', None, _('disable all guards')),
@@ -3420,7 +3263,7 @@
             return queue(self.ui, self.baseui, self.path)
 
         def abortifwdirpatched(self, errmsg, force=False):
-            if self.mq.applied and not force:
+            if self.mq.applied and self.mq.checkapplied and not force:
                 parents = self.dirstate.parents()
                 patches = [s.node for s in self.mq.applied]
                 if parents[0] in patches or parents[1] in patches:
@@ -3436,7 +3279,7 @@
                                               editor, extra)
 
         def checkpush(self, force, revs):
-            if self.mq.applied and not force:
+            if self.mq.applied and self.mq.checkapplied and not force:
                 outapplied = [e.node for e in self.mq.applied]
                 if revs:
                     # Assume applied patches have no non-patch descendants and
--- a/hgext/notify.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/hgext/notify.py	Sun Oct 20 16:43:11 2013 -0700
@@ -133,9 +133,13 @@
 
 '''
 
+import email, socket, time
+# On python2.4 you have to import this by name or they fail to
+# load. This was not a problem on Python 2.7.
+import email.Parser
 from mercurial.i18n import _
 from mercurial import patch, cmdutil, templater, util, mail
-import email.Parser, email.Errors, fnmatch, socket, time
+import fnmatch
 
 testedwith = 'internal'
 
--- a/hgext/patchbomb.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/hgext/patchbomb.py	Sun Oct 20 16:43:11 2013 -0700
@@ -46,8 +46,12 @@
 '''
 
 import os, errno, socket, tempfile, cStringIO
-import email.MIMEMultipart, email.MIMEBase
-import email.Utils, email.Encoders, email.Generator
+import email
+# On python2.4 you have to import these by name or they fail to
+# load. This was not a problem on Python 2.7.
+import email.Generator
+import email.MIMEMultipart
+
 from mercurial import cmdutil, commands, hg, mail, patch, util
 from mercurial import scmutil
 from mercurial.i18n import _
--- a/hgext/progress.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/hgext/progress.py	Sun Oct 20 16:43:11 2013 -0700
@@ -239,6 +239,13 @@
             # this one are also closed
             if topic in self.topics:
                 self.topics = self.topics[:self.topics.index(topic)]
+                # reset the last topic to the one we just unwound to,
+                # so that higher-level topics will be stickier than
+                # lower-level topics
+                if self.topics:
+                    self.lasttopic = self.topics[-1]
+                else:
+                    self.lasttopic = None
         else:
             if topic not in self.topics:
                 self.starttimes[topic] = now
--- a/hgext/rebase.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/hgext/rebase.py	Sun Oct 20 16:43:11 2013 -0700
@@ -29,6 +29,25 @@
 command = cmdutil.command(cmdtable)
 testedwith = 'internal'
 
+def _savegraft(ctx, extra):
+    s = ctx.extra().get('source', None)
+    if s is not None:
+        extra['source'] = s
+
+def _savebranch(ctx, extra):
+    extra['branch'] = ctx.branch()
+
+def _makeextrafn(copiers):
+    """make an extrafn out of the given copy-functions.
+
+    A copy function takes a context and an extra dict, and mutates the
+    extra dict as needed based on the given context.
+    """
+    def extrafn(ctx, extra):
+        for c in copiers:
+            c(ctx, extra)
+    return extrafn
+
 @command('rebase',
     [('s', 'source', '',
      _('rebase from the specified changeset'), _('REV')),
@@ -136,7 +155,10 @@
         abortf = opts.get('abort')
         collapsef = opts.get('collapse', False)
         collapsemsg = cmdutil.logmessage(ui, opts)
-        extrafn = opts.get('extrafn') # internal, used by e.g. hgsubversion
+        e = opts.get('extrafn') # internal, used by e.g. hgsubversion
+        extrafns = [_savegraft]
+        if e:
+            extrafns = [e]
         keepf = opts.get('keep', False)
         keepbranchesf = opts.get('keepbranches', False)
         # keepopen is not meant for use on the command line, but by
@@ -240,9 +262,10 @@
                     external = checkexternal(repo, state, targetancestors)
 
         if keepbranchesf:
-            assert not extrafn, 'cannot use both keepbranches and extrafn'
-            def extrafn(ctx, extra):
-                extra['branch'] = ctx.branch()
+            # insert _savebranch at the start of extrafns so if
+            # there's a user-provided extrafn it can clobber branch if
+            # desired
+            extrafns.insert(0, _savebranch)
             if collapsef:
                 branches = set()
                 for rev in state:
@@ -262,6 +285,8 @@
         if activebookmark:
             bookmarks.unsetcurrent(repo)
 
+        extrafn = _makeextrafn(extrafns)
+
         sortedstate = sorted(state)
         total = len(sortedstate)
         pos = 0
@@ -334,6 +359,13 @@
             # this should probably be cleaned up
             targetnode = repo[target].node()
 
+        # restore original working directory
+        # (we do this before stripping)
+        newwd = state.get(originalwd, originalwd)
+        if newwd not in [c.rev() for c in repo[None].parents()]:
+            ui.note(_("update back to initial working directory parent\n"))
+            hg.updaterepo(repo, newwd, False)
+
         if not keepf:
             collapsedas = None
             if collapsef:
@@ -350,7 +382,7 @@
             ui.note(_("%d revisions have been skipped\n") % len(skipped))
 
         if (activebookmark and
-            repo['tip'].node() == repo._bookmarks[activebookmark]):
+            repo['.'].node() == repo._bookmarks[activebookmark]):
                 bookmarks.setcurrent(repo, activebookmark)
 
     finally:
@@ -780,7 +812,6 @@
                      'the update flag\n')
 
         movemarkfrom = repo['.'].node()
-        cmdutil.bailifchanged(repo)
         revsprepull = len(repo)
         origpostincoming = commands.postincoming
         def _dummy(*args, **kwargs):
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hgext/shelve.py	Sun Oct 20 16:43:11 2013 -0700
@@ -0,0 +1,633 @@
+# shelve.py - save/restore working directory state
+#
+# 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.
+
+"""save and restore changes to the working directory
+
+The "hg shelve" command saves changes made to the working directory
+and reverts those changes, resetting the working directory to a clean
+state.
+
+Later on, the "hg unshelve" command restores the changes saved by "hg
+shelve". Changes can be restored even after updating to a different
+parent, in which case Mercurial's merge machinery will resolve any
+conflicts if necessary.
+
+You can have more than one shelved change outstanding at a time; each
+shelved change has a distinct name. For details, see the help for "hg
+shelve".
+"""
+
+from mercurial.i18n import _
+from mercurial.node import nullid, bin, hex
+from mercurial import changegroup, cmdutil, scmutil, phases
+from mercurial import error, hg, mdiff, merge, patch, repair, util
+from mercurial import templatefilters
+from mercurial import lock as lockmod
+import errno
+
+cmdtable = {}
+command = cmdutil.command(cmdtable)
+testedwith = 'internal'
+
+class shelvedfile(object):
+    """Helper for the file storing a single shelve
+
+    Handles common functions on shelve files (.hg/.files/.patch) using
+    the vfs layer"""
+    def __init__(self, repo, name, filetype=None):
+        self.repo = repo
+        self.name = name
+        self.vfs = scmutil.vfs(repo.join('shelved'))
+        if filetype:
+            self.fname = name + '.' + filetype
+        else:
+            self.fname = name
+
+    def exists(self):
+        return self.vfs.exists(self.fname)
+
+    def filename(self):
+        return self.vfs.join(self.fname)
+
+    def unlink(self):
+        util.unlink(self.filename())
+
+    def stat(self):
+        return self.vfs.stat(self.fname)
+
+    def opener(self, mode='rb'):
+        try:
+            return self.vfs(self.fname, mode)
+        except IOError, err:
+            if err.errno != errno.ENOENT:
+                raise
+            if mode[0] in 'wa':
+                try:
+                    self.vfs.mkdir()
+                    return self.vfs(self.fname, mode)
+                except IOError, err:
+                    if err.errno != errno.EEXIST:
+                        raise
+            elif mode[0] == 'r':
+                raise util.Abort(_("shelved change '%s' not found") %
+                                 self.name)
+
+class shelvedstate(object):
+    """Handle persistence during unshelving operations.
+
+    Handles saving and restoring a shelved state. Ensures that different
+    versions of a shelved state are possible and handles them appropriately.
+    """
+    _version = 1
+    _filename = 'shelvedstate'
+
+    @classmethod
+    def load(cls, repo):
+        fp = repo.opener(cls._filename)
+        try:
+            version = int(fp.readline().strip())
+
+            if version != cls._version:
+                raise util.Abort(_('this version of shelve is incompatible '
+                                   'with the version used in this repo'))
+            name = fp.readline().strip()
+            parents = [bin(h) for h in fp.readline().split()]
+            stripnodes = [bin(h) for h in fp.readline().split()]
+        finally:
+            fp.close()
+
+        obj = cls()
+        obj.name = name
+        obj.parents = parents
+        obj.stripnodes = stripnodes
+
+        return obj
+
+    @classmethod
+    def save(cls, repo, name, stripnodes):
+        fp = repo.opener(cls._filename, 'wb')
+        fp.write('%i\n' % cls._version)
+        fp.write('%s\n' % name)
+        fp.write('%s\n' % ' '.join([hex(p) for p in repo.dirstate.parents()]))
+        fp.write('%s\n' % ' '.join([hex(n) for n in stripnodes]))
+        fp.close()
+
+    @classmethod
+    def clear(cls, repo):
+        util.unlinkpath(repo.join(cls._filename), ignoremissing=True)
+
+def createcmd(ui, repo, pats, opts):
+    """subcommand that creates a new shelve"""
+
+    def publicancestors(ctx):
+        """Compute the heads of the public ancestors of a commit.
+
+        Much faster than the revset heads(ancestors(ctx) - draft())"""
+        seen = set()
+        visit = util.deque()
+        visit.append(ctx)
+        while visit:
+            ctx = visit.popleft()
+            for parent in ctx.parents():
+                rev = parent.rev()
+                if rev not in seen:
+                    seen.add(rev)
+                    if parent.mutable():
+                        visit.append(parent)
+                    else:
+                        yield parent.node()
+
+    wctx = repo[None]
+    parents = wctx.parents()
+    if len(parents) > 1:
+        raise util.Abort(_('cannot shelve while merging'))
+    parent = parents[0]
+
+    # we never need the user, so we use a generic user for all shelve operations
+    user = 'shelve@localhost'
+    label = repo._bookmarkcurrent or parent.branch() or 'default'
+
+    # slashes aren't allowed in filenames, therefore we rename it
+    origlabel, label = label, label.replace('/', '_')
+
+    def gennames():
+        yield label
+        for i in xrange(1, 100):
+            yield '%s-%02d' % (label, i)
+
+    shelvedfiles = []
+
+    def commitfunc(ui, repo, message, match, opts):
+        # check modified, added, removed, deleted only
+        for flist in repo.status(match=match)[:4]:
+            shelvedfiles.extend(flist)
+        hasmq = util.safehasattr(repo, 'mq')
+        if hasmq:
+            saved, repo.mq.checkapplied = repo.mq.checkapplied, False
+        try:
+            return repo.commit(message, user, opts.get('date'), match)
+        finally:
+            if hasmq:
+                repo.mq.checkapplied = saved
+
+    if parent.node() != nullid:
+        desc = parent.description().split('\n', 1)[0]
+    else:
+        desc = '(empty repository)'
+
+    if not opts['message']:
+        opts['message'] = desc
+
+    name = opts['name']
+
+    wlock = lock = tr = bms = None
+    try:
+        wlock = repo.wlock()
+        lock = repo.lock()
+
+        bms = repo._bookmarks.copy()
+        # use an uncommited transaction to generate the bundle to avoid
+        # pull races. ensure we don't print the abort message to stderr.
+        tr = repo.transaction('commit', report=lambda x: None)
+
+        if name:
+            if shelvedfile(repo, name, 'hg').exists():
+                raise util.Abort(_("a shelved change named '%s' already exists")
+                                 % name)
+        else:
+            for n in gennames():
+                if not shelvedfile(repo, n, 'hg').exists():
+                    name = n
+                    break
+            else:
+                raise util.Abort(_("too many shelved changes named '%s'") %
+                                 label)
+
+        # ensure we are not creating a subdirectory or a hidden file
+        if '/' in name or '\\' in name:
+            raise util.Abort(_('shelved change names may not contain slashes'))
+        if name.startswith('.'):
+            raise util.Abort(_("shelved change names may not start with '.'"))
+
+        node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
+
+        if not node:
+            stat = repo.status(match=scmutil.match(repo[None], pats, opts))
+            if stat[3]:
+                ui.status(_("nothing changed (%d missing files, see "
+                            "'hg status')\n") % len(stat[3]))
+            else:
+                ui.status(_("nothing changed\n"))
+            return 1
+
+        phases.retractboundary(repo, phases.secret, [node])
+
+        fp = shelvedfile(repo, name, 'files').opener('wb')
+        fp.write('\0'.join(shelvedfiles))
+
+        bases = list(publicancestors(repo[node]))
+        cg = repo.changegroupsubset(bases, [node], 'shelve')
+        changegroup.writebundle(cg, shelvedfile(repo, name, 'hg').filename(),
+                                'HG10UN')
+        cmdutil.export(repo, [node],
+                       fp=shelvedfile(repo, name, 'patch').opener('wb'),
+                       opts=mdiff.diffopts(git=True))
+
+
+        if ui.formatted():
+            desc = util.ellipsis(desc, ui.termwidth())
+        ui.status(_('shelved as %s\n') % name)
+        hg.update(repo, parent.node())
+    finally:
+        if bms:
+            # restore old bookmarks
+            repo._bookmarks.update(bms)
+            repo._bookmarks.write()
+        if tr:
+            tr.abort()
+        lockmod.release(lock, wlock)
+
+def cleanupcmd(ui, repo):
+    """subcommand that deletes all shelves"""
+
+    wlock = None
+    try:
+        wlock = repo.wlock()
+        for (name, _) in repo.vfs.readdir('shelved'):
+            suffix = name.rsplit('.', 1)[-1]
+            if suffix in ('hg', 'files', 'patch'):
+                shelvedfile(repo, name).unlink()
+    finally:
+        lockmod.release(wlock)
+
+def deletecmd(ui, repo, pats):
+    """subcommand that deletes a specific shelve"""
+    if not pats:
+        raise util.Abort(_('no shelved changes specified!'))
+    wlock = None
+    try:
+        wlock = repo.wlock()
+        try:
+            for name in pats:
+                for suffix in 'hg files patch'.split():
+                    shelvedfile(repo, name, suffix).unlink()
+        except OSError, err:
+            if err.errno != errno.ENOENT:
+                raise
+            raise util.Abort(_("shelved change '%s' not found") % name)
+    finally:
+        lockmod.release(wlock)
+
+def listshelves(repo):
+    """return all shelves in repo as list of (time, filename)"""
+    try:
+        names = repo.vfs.readdir('shelved')
+    except OSError, err:
+        if err.errno != errno.ENOENT:
+            raise
+        return []
+    info = []
+    for (name, _) in names:
+        pfx, sfx = name.rsplit('.', 1)
+        if not pfx or sfx != 'patch':
+            continue
+        st = shelvedfile(repo, name).stat()
+        info.append((st.st_mtime, shelvedfile(repo, pfx).filename()))
+    return sorted(info, reverse=True)
+
+def listcmd(ui, repo, pats, opts):
+    """subcommand that displays the list of shelves"""
+    pats = set(pats)
+    width = 80
+    if not ui.plain():
+        width = ui.termwidth()
+    namelabel = 'shelve.newest'
+    for mtime, name in listshelves(repo):
+        sname = util.split(name)[1]
+        if pats and sname not in pats:
+            continue
+        ui.write(sname, label=namelabel)
+        namelabel = 'shelve.name'
+        if ui.quiet:
+            ui.write('\n')
+            continue
+        ui.write(' ' * (16 - len(sname)))
+        used = 16
+        age = '(%s)' % templatefilters.age(util.makedate(mtime), abbrev=True)
+        ui.write(age, label='shelve.age')
+        ui.write(' ' * (12 - len(age)))
+        used += 12
+        fp = open(name + '.patch', 'rb')
+        try:
+            while True:
+                line = fp.readline()
+                if not line:
+                    break
+                if not line.startswith('#'):
+                    desc = line.rstrip()
+                    if ui.formatted():
+                        desc = util.ellipsis(desc, width - used)
+                    ui.write(desc)
+                    break
+            ui.write('\n')
+            if not (opts['patch'] or opts['stat']):
+                continue
+            difflines = fp.readlines()
+            if opts['patch']:
+                for chunk, label in patch.difflabel(iter, difflines):
+                    ui.write(chunk, label=label)
+            if opts['stat']:
+                for chunk, label in patch.diffstatui(difflines, width=width,
+                                                     git=True):
+                    ui.write(chunk, label=label)
+        finally:
+            fp.close()
+
+def readshelvedfiles(repo, basename):
+    """return the list of files touched in a shelve"""
+    fp = shelvedfile(repo, basename, 'files').opener()
+    return fp.read().split('\0')
+
+def checkparents(repo, state):
+    """check parent while resuming an unshelve"""
+    if state.parents != repo.dirstate.parents():
+        raise util.Abort(_('working directory parents do not match unshelve '
+                           'state'))
+
+def unshelveabort(ui, repo, state, opts):
+    """subcommand that abort an in-progress unshelve"""
+    wlock = repo.wlock()
+    lock = None
+    try:
+        checkparents(repo, state)
+        lock = repo.lock()
+        merge.mergestate(repo).reset()
+        if opts['keep']:
+            repo.setparents(repo.dirstate.parents()[0])
+        else:
+            revertfiles = readshelvedfiles(repo, state.name)
+            wctx = repo.parents()[0]
+            cmdutil.revert(ui, repo, wctx, [wctx.node(), nullid],
+                           *revertfiles, **{'no_backup': True})
+            # fix up the weird dirstate states the merge left behind
+            mf = wctx.manifest()
+            dirstate = repo.dirstate
+            for f in revertfiles:
+                if f in mf:
+                    dirstate.normallookup(f)
+                else:
+                    dirstate.drop(f)
+            dirstate._pl = (wctx.node(), nullid)
+            dirstate._dirty = True
+        repair.strip(ui, repo, state.stripnodes, backup='none', topic='shelve')
+        shelvedstate.clear(repo)
+        ui.warn(_("unshelve of '%s' aborted\n") % state.name)
+    finally:
+        lockmod.release(lock, wlock)
+
+def unshelvecleanup(ui, repo, name, opts):
+    """remove related files after an unshelve"""
+    if not opts['keep']:
+        for filetype in 'hg files patch'.split():
+            shelvedfile(repo, name, filetype).unlink()
+
+def finishmerge(ui, repo, ms, stripnodes, name, opts):
+    # Reset the working dir so it's no longer in a merge state.
+    dirstate = repo.dirstate
+    dirstate.setparents(dirstate._pl[0])
+    shelvedstate.clear(repo)
+
+def unshelvecontinue(ui, repo, state, opts):
+    """subcommand to continue an in-progress unshelve"""
+    # We're finishing off a merge. First parent is our original
+    # parent, second is the temporary "fake" commit we're unshelving.
+    wlock = repo.wlock()
+    lock = None
+    try:
+        checkparents(repo, state)
+        ms = merge.mergestate(repo)
+        if [f for f in ms if ms[f] == 'u']:
+            raise util.Abort(
+                _("unresolved conflicts, can't continue"),
+                hint=_("see 'hg resolve', then 'hg unshelve --continue'"))
+        finishmerge(ui, repo, ms, state.stripnodes, state.name, opts)
+        lock = repo.lock()
+        repair.strip(ui, repo, state.stripnodes, backup='none', topic='shelve')
+        unshelvecleanup(ui, repo, state.name, opts)
+        ui.status(_("unshelve of '%s' complete\n") % state.name)
+    finally:
+        lockmod.release(lock, wlock)
+
+@command('unshelve',
+         [('a', 'abort', None,
+           _('abort an incomplete unshelve operation')),
+          ('c', 'continue', None,
+           _('continue an incomplete unshelve operation')),
+          ('', 'keep', None,
+           _('keep shelve after unshelving'))],
+         _('hg unshelve [SHELVED]'))
+def unshelve(ui, repo, *shelved, **opts):
+    """restore a shelved change to the working directory
+
+    This command accepts an optional name of a shelved change to
+    restore. If none is given, the most recent shelved change is used.
+
+    If a shelved change is applied successfully, the bundle that
+    contains the shelved changes is deleted afterwards.
+
+    Since you can restore a shelved change on top of an arbitrary
+    commit, it is possible that unshelving will result in a conflict
+    between your changes and the commits you are unshelving onto. If
+    this occurs, you must resolve the conflict, then use
+    ``--continue`` to complete the unshelve operation. (The bundle
+    will not be deleted until you successfully complete the unshelve.)
+
+    (Alternatively, you can use ``--abort`` to abandon an unshelve
+    that causes a conflict. This reverts the unshelved changes, and
+    does not delete the bundle.)
+    """
+    abortf = opts['abort']
+    continuef = opts['continue']
+    if not abortf and not continuef:
+        cmdutil.checkunfinished(repo)
+
+    if abortf or continuef:
+        if abortf and continuef:
+            raise util.Abort(_('cannot use both abort and continue'))
+        if shelved:
+            raise util.Abort(_('cannot combine abort/continue with '
+                               'naming a shelved change'))
+
+        try:
+            state = shelvedstate.load(repo)
+        except IOError, err:
+            if err.errno != errno.ENOENT:
+                raise
+            raise util.Abort(_('no unshelve operation underway'))
+
+        if abortf:
+            return unshelveabort(ui, repo, state, opts)
+        elif continuef:
+            return unshelvecontinue(ui, repo, state, opts)
+    elif len(shelved) > 1:
+        raise util.Abort(_('can only unshelve one change at a time'))
+    elif not shelved:
+        shelved = listshelves(repo)
+        if not shelved:
+            raise util.Abort(_('no shelved changes to apply!'))
+        basename = util.split(shelved[0][1])[1]
+        ui.status(_("unshelving change '%s'\n") % basename)
+    else:
+        basename = shelved[0]
+
+    shelvedfiles = readshelvedfiles(repo, basename)
+
+    m, a, r, d = repo.status()[:4]
+    unsafe = set(m + a + r + d).intersection(shelvedfiles)
+    if unsafe:
+        ui.warn(_('the following shelved files have been modified:\n'))
+        for f in sorted(unsafe):
+            ui.warn('  %s\n' % f)
+        ui.warn(_('you must commit, revert, or shelve your changes before you '
+                  'can proceed\n'))
+        raise util.Abort(_('cannot unshelve due to local changes\n'))
+
+    wlock = lock = tr = None
+    try:
+        lock = repo.lock()
+
+        tr = repo.transaction('unshelve', report=lambda x: None)
+        oldtiprev = len(repo)
+        try:
+            fp = shelvedfile(repo, basename, 'hg').opener()
+            gen = changegroup.readbundle(fp, fp.name)
+            repo.addchangegroup(gen, 'unshelve', 'bundle:' + fp.name)
+            nodes = [ctx.node() for ctx in repo.set('%d:', oldtiprev)]
+            phases.retractboundary(repo, phases.secret, nodes)
+            tr.close()
+        finally:
+            fp.close()
+
+        tip = repo['tip']
+        wctx = repo['.']
+        ancestor = tip.ancestor(wctx)
+
+        wlock = repo.wlock()
+
+        if ancestor.node() != wctx.node():
+            conflicts = hg.merge(repo, tip.node(), force=True, remind=False)
+            ms = merge.mergestate(repo)
+            stripnodes = [repo.changelog.node(rev)
+                          for rev in xrange(oldtiprev, len(repo))]
+            if conflicts:
+                shelvedstate.save(repo, basename, stripnodes)
+                # Fix up the dirstate entries of files from the second
+                # parent as if we were not merging, except for those
+                # with unresolved conflicts.
+                parents = repo.parents()
+                revertfiles = set(parents[1].files()).difference(ms)
+                cmdutil.revert(ui, repo, parents[1],
+                               (parents[0].node(), nullid),
+                               *revertfiles, **{'no_backup': True})
+                raise error.InterventionRequired(
+                    _("unresolved conflicts (see 'hg resolve', then "
+                      "'hg unshelve --continue')"))
+            finishmerge(ui, repo, ms, stripnodes, basename, opts)
+        else:
+            parent = tip.parents()[0]
+            hg.update(repo, parent.node())
+            cmdutil.revert(ui, repo, tip, repo.dirstate.parents(), *tip.files(),
+                           **{'no_backup': True})
+
+        prevquiet = ui.quiet
+        ui.quiet = True
+        try:
+            repo.rollback(force=True)
+        finally:
+            ui.quiet = prevquiet
+
+        unshelvecleanup(ui, repo, basename, opts)
+    finally:
+        if tr:
+            tr.release()
+        lockmod.release(lock, wlock)
+
+@command('shelve',
+         [('A', 'addremove', None,
+           _('mark new/missing files as added/removed before shelving')),
+          ('', 'cleanup', None,
+           _('delete all shelved changes')),
+          ('', 'date', '',
+           _('shelve with the specified commit date'), _('DATE')),
+          ('d', 'delete', None,
+           _('delete the named shelved change(s)')),
+          ('l', 'list', None,
+           _('list current shelves')),
+          ('m', 'message', '',
+           _('use text as shelve message'), _('TEXT')),
+          ('n', 'name', '',
+           _('use the given name for the shelved commit'), _('NAME')),
+          ('p', 'patch', None,
+           _('show patch')),
+          ('', 'stat', None,
+           _('output diffstat-style summary of changes'))],
+         _('hg shelve'))
+def shelvecmd(ui, repo, *pats, **opts):
+    '''save and set aside changes from the working directory
+
+    Shelving takes files that "hg status" reports as not clean, saves
+    the modifications to a bundle (a shelved change), and reverts the
+    files so that their state in the working directory becomes clean.
+
+    To restore these changes to the working directory, using "hg
+    unshelve"; this will work even if you switch to a different
+    commit.
+
+    When no files are specified, "hg shelve" saves all not-clean
+    files. If specific files or directories are named, only changes to
+    those files are shelved.
+
+    Each shelved change has a name that makes it easier to find later.
+    The name of a shelved change defaults to being based on the active
+    bookmark, or if there is no active bookmark, the current named
+    branch.  To specify a different name, use ``--name``.
+
+    To see a list of existing shelved changes, use the ``--list``
+    option. For each shelved change, this will print its name, age,
+    and description; use ``--patch`` or ``--stat`` for more details.
+
+    To delete specific shelved changes, use ``--delete``. To delete
+    all shelved changes, use ``--cleanup``.
+    '''
+    cmdutil.checkunfinished(repo)
+
+    def checkopt(opt, incompatible):
+        if opts[opt]:
+            for i in incompatible.split():
+                if opts[i]:
+                    raise util.Abort(_("options '--%s' and '--%s' may not be "
+                                       "used together") % (opt, i))
+            return True
+    if checkopt('cleanup', 'addremove delete list message name patch stat'):
+        if pats:
+            raise util.Abort(_("cannot specify names when using '--cleanup'"))
+        return cleanupcmd(ui, repo)
+    elif checkopt('delete', 'addremove cleanup list message name patch stat'):
+        return deletecmd(ui, repo, pats)
+    elif checkopt('list', 'addremove cleanup delete message name'):
+        return listcmd(ui, repo, pats, opts)
+    else:
+        for i in ('patch', 'stat'):
+            if opts[i]:
+                raise util.Abort(_("option '--%s' may not be "
+                                   "used when shelving a change") % (i,))
+        return createcmd(ui, repo, pats, opts)
+
+def extsetup(ui):
+    cmdutil.unfinishedstates.append(
+        [shelvedstate._filename, False, True, _('unshelve already in progress'),
+         _("use 'hg unshelve --continue' or 'hg unshelve --abort'")])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hgext/strip.py	Sun Oct 20 16:43:11 2013 -0700
@@ -0,0 +1,217 @@
+"""strip changesets and their descendents from history
+
+This extension allows to strip changesets and all their descendants from the
+repository. See the command help for details.
+"""
+from mercurial.i18n import _
+from mercurial.node import nullid
+from mercurial.lock import release
+from mercurial import cmdutil, hg, scmutil, util
+from mercurial import repair, bookmarks
+
+cmdtable = {}
+command = cmdutil.command(cmdtable)
+testedwith = 'internal'
+
+def checksubstate(repo, baserev=None):
+    '''return list of subrepos at a different revision than substate.
+    Abort if any subrepos have uncommitted changes.'''
+    inclsubs = []
+    wctx = repo[None]
+    if baserev:
+        bctx = repo[baserev]
+    else:
+        bctx = wctx.parents()[0]
+    for s in sorted(wctx.substate):
+        if wctx.sub(s).dirty(True):
+            raise util.Abort(
+                _("uncommitted changes in subrepository %s") % s)
+        elif s not in bctx.substate or bctx.sub(s).dirty():
+            inclsubs.append(s)
+    return inclsubs
+
+def checklocalchanges(repo, force=False, excsuffix=''):
+    cmdutil.checkunfinished(repo)
+    m, a, r, d = repo.status()[:4]
+    if not force:
+        if (m or a or r or d):
+            _("local changes found") # i18n tool detection
+            raise util.Abort(_("local changes found" + excsuffix))
+        if checksubstate(repo):
+            _("local changed subrepos found") # i18n tool detection
+            raise util.Abort(_("local changed subrepos found" + excsuffix))
+    return m, a, r, d
+
+def strip(ui, repo, revs, update=True, backup="all", force=None):
+    wlock = lock = None
+    try:
+        wlock = repo.wlock()
+        lock = repo.lock()
+
+        if update:
+            checklocalchanges(repo, force=force)
+            urev, p2 = repo.changelog.parents(revs[0])
+            if p2 != nullid and p2 in [x.node for x in repo.mq.applied]:
+                urev = p2
+            hg.clean(repo, urev)
+            repo.dirstate.write()
+
+        repair.strip(ui, repo, revs, backup)
+    finally:
+        release(lock, wlock)
+
+
+@command("strip",
+         [
+          ('r', 'rev', [], _('strip specified revision (optional, '
+                               'can specify revisions without this '
+                               'option)'), _('REV')),
+          ('f', 'force', None, _('force removal of changesets, discard '
+                                 'uncommitted changes (no backup)')),
+          ('b', 'backup', None, _('bundle only changesets with local revision'
+                                  ' number greater than REV which are not'
+                                  ' descendants of REV (DEPRECATED)')),
+          ('', 'no-backup', None, _('no backups')),
+          ('', 'nobackup', None, _('no backups (DEPRECATED)')),
+          ('n', '', None, _('ignored  (DEPRECATED)')),
+          ('k', 'keep', None, _("do not modify working copy during strip")),
+          ('B', 'bookmark', '', _("remove revs only reachable from given"
+                                  " bookmark"))],
+          _('hg strip [-k] [-f] [-n] [-B bookmark] [-r] REV...'))
+def stripcmd(ui, repo, *revs, **opts):
+    """strip changesets and all their descendants from the repository
+
+    The strip command removes the specified changesets and all their
+    descendants. If the working directory has uncommitted changes, the
+    operation is aborted unless the --force flag is supplied, in which
+    case changes will be discarded.
+
+    If a parent of the working directory is stripped, then the working
+    directory will automatically be updated to the most recent
+    available ancestor of the stripped parent after the operation
+    completes.
+
+    Any stripped changesets are stored in ``.hg/strip-backup`` as a
+    bundle (see :hg:`help bundle` and :hg:`help unbundle`). They can
+    be restored by running :hg:`unbundle .hg/strip-backup/BUNDLE`,
+    where BUNDLE is the bundle file created by the strip. Note that
+    the local revision numbers will in general be different after the
+    restore.
+
+    Use the --no-backup option to discard the backup bundle once the
+    operation completes.
+
+    Strip is not a history-rewriting operation and can be used on
+    changesets in the public phase. But if the stripped changesets have
+    been pushed to a remote repository you will likely pull them again.
+
+    Return 0 on success.
+    """
+    backup = 'all'
+    if opts.get('backup'):
+        backup = 'strip'
+    elif opts.get('no_backup') or opts.get('nobackup'):
+        backup = 'none'
+
+    cl = repo.changelog
+    revs = list(revs) + opts.get('rev')
+    revs = set(scmutil.revrange(repo, revs))
+
+    if opts.get('bookmark'):
+        mark = opts.get('bookmark')
+        marks = repo._bookmarks
+        if mark not in marks:
+            raise util.Abort(_("bookmark '%s' not found") % mark)
+
+        # If the requested bookmark is not the only one pointing to a
+        # a revision we have to only delete the bookmark and not strip
+        # anything. revsets cannot detect that case.
+        uniquebm = True
+        for m, n in marks.iteritems():
+            if m != mark and n == repo[mark].node():
+                uniquebm = False
+                break
+        if uniquebm:
+            rsrevs = repo.revs("ancestors(bookmark(%s)) - "
+                               "ancestors(head() and not bookmark(%s)) - "
+                               "ancestors(bookmark() and not bookmark(%s))",
+                               mark, mark, mark)
+            revs.update(set(rsrevs))
+        if not revs:
+            del marks[mark]
+            marks.write()
+            ui.write(_("bookmark '%s' deleted\n") % mark)
+
+    if not revs:
+        raise util.Abort(_('empty revision set'))
+
+    descendants = set(cl.descendants(revs))
+    strippedrevs = revs.union(descendants)
+    roots = revs.difference(descendants)
+
+    update = False
+    # if one of the wdir parent is stripped we'll need
+    # to update away to an earlier revision
+    for p in repo.dirstate.parents():
+        if p != nullid and cl.rev(p) in strippedrevs:
+            update = True
+            break
+
+    rootnodes = set(cl.node(r) for r in roots)
+
+    q = getattr(repo, 'mq', None)
+    if q is not None and q.applied:
+        # refresh queue state if we're about to strip
+        # applied patches
+        if cl.rev(repo.lookup('qtip')) in strippedrevs:
+            q.applieddirty = True
+            start = 0
+            end = len(q.applied)
+            for i, statusentry in enumerate(q.applied):
+                if statusentry.node in rootnodes:
+                    # if one of the stripped roots is an applied
+                    # patch, only part of the queue is stripped
+                    start = i
+                    break
+            del q.applied[start:end]
+            q.savedirty()
+
+    revs = sorted(rootnodes)
+    if update and opts.get('keep'):
+        wlock = repo.wlock()
+        try:
+            urev, p2 = repo.changelog.parents(revs[0])
+            if (util.safehasattr(repo, 'mq') and p2 != nullid
+                and p2 in [x.node for x in repo.mq.applied]):
+                urev = p2
+            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:
+                # blindly 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:
+            wlock.release()
+
+    if opts.get('bookmark'):
+        if mark == repo._bookmarkcurrent:
+            bookmarks.setcurrent(repo, None)
+        del marks[mark]
+        marks.write()
+        ui.write(_("bookmark '%s' deleted\n") % mark)
+
+    strip(ui, repo, revs, backup=backup, update=update, force=opts.get('force'))
+
+    return 0
--- a/i18n/de.po	Sat Oct 19 14:20:31 2013 -0700
+++ b/i18n/de.po	Sun Oct 20 16:43:11 2013 -0700
@@ -758,7 +758,7 @@
 msgstr ""
 "bugzilla.regexp\n"
 "  Regulärer Ausdruck, der auf die zu aktualisierende Bug-ID in der\n"
-"  Versionsmeldung passt. Er muss eine `<ids>`` benannte Gruppe \"()\"\n"
+"  Versionsmeldung passt. Er muss eine ``<ids>`` benannte Gruppe \"()\"\n"
 "  enthalten, die auf die Bug-IDs getrennt durch Nicht-Zahlen-Zeichen\n"
 "  passt. Außerdem kann er eine ``<hours>`` benannte Gruppe mit einer\n"
 "  Fließkommazahl enthalten, die die Zahl der Arbeitsstunden für den\n"
@@ -3391,7 +3391,7 @@
 "sind, werden nicht verändert. Zusätzlich kann ``native`` als Alias für\n"
 "die Voreinstellung des jeweiligen Systems verwendet werden: ``LF`` unter "
 "Unix\n"
-"(inkl. Mac OS X) und ``CRLF`` unter Windows. Beachten Sie, dass ``BIN ``\n"
+"(inkl. Mac OS X) und ``CRLF`` unter Windows. Beachten Sie, dass ``BIN``\n"
 "(nichts ändern) Mercurials Standardverhalten ist; es dient nur dazu,\n"
 "um ein späteres, allgemeineres Muster zu überschreiben."
 
@@ -3414,7 +3414,7 @@
 "behandelt werden. Der Wert kann auf ``CRLF`` oder ``LF`` gesetzt werden.\n"
 "Die Voreinstellung ist ``LF``. Zum Beispiel bedeutet dies, dass unter\n"
 "Windows Dateien, die als ``native`` (standardmäßig ``CRLF``)\n"
-" gespeichert werden sollen, nach ``LF`` konvertiert werden, bevor sie im\n"
+"gespeichert werden sollen, nach ``LF`` konvertiert werden, bevor sie im\n"
 "Archiv abgelegt werden. Dateien, die als ``LF``, ``CRLF`` oder ``BIN``\n"
 "in ``[patterns]`` angeben wurden, werden immer ungeändert ins Archiv\n"
 "übernommen."
@@ -7768,7 +7768,7 @@
 "    current patch header, separated by a line of ``* * *``."
 msgstr ""
 "    Die Kopfzeilen der einzelnen Patches werden den den Kopf des aktuellen\n"
-"    Patches angehängt, getrennt mit einer Zeile aus '* * *'."
+"    Patches angehängt, getrennt mit einer Zeile aus ``* * *``."
 
 #: hgext/mq.py:2537
 msgid "qfold requires at least one patch name"
@@ -8077,7 +8077,7 @@
 #: hgext/mq.py:2927
 msgid "force removal of changesets, discard uncommitted changes (no backup)"
 msgstr ""
-"erzwingt Entfernung von Änderungssätzen und unversionierten Änderungen\n"
+"erzwingt Entfernung von Änderungssätzen und unversionierten Änderungen "
 "(keine Sicherheitskopie)"
 
 #: hgext/mq.py:2929
@@ -9308,7 +9308,7 @@
 "    Der Schalter -i/--inline erzeugt einen Inline-Anhang. Ein Patch\n"
 "    kann sowohl als Nachrichtentext als auch als normaler oder \n"
 "    Inline-Anhang eingebunden werden, indem die Schalter\n"
-"     -a/--attach und  -i/--inline mit dem  --body - Schalter\n"
+"    -a/--attach und  -i/--inline mit dem  --body - Schalter\n"
 "    kombiniert werden."
 
 #: hgext/patchbomb.py:213
@@ -9340,7 +9340,7 @@
 msgstr ""
 "    Alternativ werden die Nachrichten mit der Option -m/--mbox in eine\n"
 "    Datei geschrieben, die von jedem Emailprogramm, welches das UNIX-mbox-\n"
-"    Format unterstützt, geprüft werden, zum Beispiel mit mutt::"
+"    Format unterstützt, geprüft werden, zum Beispiel mit mutt."
 
 #: hgext/patchbomb.py:227
 msgid ""
@@ -12417,7 +12417,7 @@
 #: mercurial/commands.py:590
 msgid "      See :hg:`help revsets` for more about the `bisect()` keyword."
 msgstr ""
-"      Siehe :hg:`help revsets' für mehr Infos über den bisect() Schlüssel."
+"      Siehe :hg:`help revsets` für mehr Infos über den bisect() Schlüssel."
 
 #: mercurial/commands.py:610
 msgid "The first good revision is:\n"
@@ -16072,7 +16072,7 @@
 "      (Reihen). Die Dateizustände sind Hinzugefügt (A), Unverändert (C),\n"
 "      Verändert (M) und Fehlend (!) (wie von :hg:`status` angezeigt). Die\n"
 "      Aktionen sind Warnen, Entfernen (aus dem Zweig) und Löschen\n"
-"      (von der Festplatte)::"
+"      (von der Festplatte):"
 
 #: mercurial/commands.py:4765
 msgid ""
--- a/i18n/it.po	Sat Oct 19 14:20:31 2013 -0700
+++ b/i18n/it.po	Sun Oct 20 16:43:11 2013 -0700
@@ -9381,7 +9381,7 @@
 "directory strip option for patch. This has the same meaning as the "
 "corresponding patch option"
 msgstr ""
-"opzione di rimozione della directory per patch. Questa ha lo stesso\n"
+"opzione di rimozione della directory per patch. Questa ha lo stesso "
 "significato dell'opzione corrispondente di patch"
 
 msgid "PATH"
--- a/i18n/ja.po	Sat Oct 19 14:20:31 2013 -0700
+++ b/i18n/ja.po	Sun Oct 20 16:43:11 2013 -0700
@@ -7248,7 +7248,7 @@
 "changesets sent to another repository::"
 msgstr ""
 ":hg:`help extensions` にならって、 本エクステンションを有効にした上で、\n"
-"実行したいフックを登録してください。 `incoming`` および ``changegroup``\n"
+"実行したいフックを登録してください。 ``incoming`` および ``changegroup``\n"
 "フックは履歴の取り込みで、 ``outgoing`` は履歴の反映の際に実行されます::"
 
 msgid ""
@@ -9109,10 +9109,10 @@
 
 msgid ""
 "    - transplant all changes up to REV on top of your current revision::"
-msgstr "      - REV までの全リビジョンを、現リビジョン上に移植::"
+msgstr "    - REV までの全リビジョンを、現リビジョン上に移植::"
 
 msgid "        hg transplant --branch REV --all"
-msgstr "          hg transplant --branch REV --all"
+msgstr "        hg transplant --branch REV --all"
 
 msgid ""
 "    You can optionally mark selected transplanted changesets as merge\n"
@@ -13693,7 +13693,7 @@
 "      In the printed list, ``U`` = unresolved and ``R`` = resolved."
 msgstr ""
 "    - :hg:`resolve -l`: 衝突が検出されたファイルの解消状況を表示します。\n"
-"      一覧表示において `U`` は未解消(Unresolved)を、\n"
+"      一覧表示において ``U`` は未解消(Unresolved)を、\n"
 "      ``R`` は解消済み(Resolved)を意味します。"
 
 msgid ""
--- a/i18n/pt_BR.po	Sat Oct 19 14:20:31 2013 -0700
+++ b/i18n/pt_BR.po	Sun Oct 20 16:43:11 2013 -0700
@@ -794,8 +794,8 @@
 "  Default ``changeset {node|short} in repo {root} refers to bug\n"
 "  {bug}.\\ndetails:\\n\\t{desc|tabindent}``"
 msgstr ""
-"  O valor padrão é ``changeset {node|short} in repo {root} refers ``\n"
-"  'to bug {bug}.\\ndetails:\\n\\t{desc|tabindent}``"
+"  O valor padrão é ``changeset {node|short} in repo {root} refers\n"
+"  to bug {bug}.\\ndetails:\\n\\t{desc|tabindent}``"
 
 msgid ""
 "bugzilla.strip\n"
@@ -6500,9 +6500,9 @@
 "    to current user and date to current date."
 msgstr ""
 "    -u/--user e -d/--date podem ser usados para definir o usuário\n"
-"     e data pedidos, respectivamente. -U/--currentuser e\n"
-"     -D/--currentdate definem o usuário para o usuário atual e a\n"
-"     data para a data atual."
+"    e data pedidos, respectivamente. -U/--currentuser e\n"
+"    -D/--currentdate definem o usuário para o usuário atual e a\n"
+"    data para a data atual."
 
 msgid ""
 "    -e/--edit, -m/--message or -l/--logfile set the patch header as\n"
--- a/i18n/ro.po	Sat Oct 19 14:20:31 2013 -0700
+++ b/i18n/ro.po	Sun Oct 20 16:43:11 2013 -0700
@@ -4862,7 +4862,7 @@
 
 msgid "run even when remote repository is unrelated (with -b/--bundle)"
 msgstr ""
-"execută chiar când depozitul la distanță este neînrudit\n"
+"execută chiar când depozitul la distanță este neînrudit "
 "(cu -b/--bundle)"
 
 msgid "a base changeset to specify instead of a destination (with -b/--bundle)"
@@ -6627,7 +6627,7 @@
 
 msgid "follow copies/renames and list the filename (DEPRECATED)"
 msgstr ""
-"urmărește copierile/redenumirile și afișează numele\n"
+"urmărește copierile/redenumirile și afișează numele "
 "fișierului (ÎNVECHIT)"
 
 msgid "don't follow copies and renames"
@@ -7255,7 +7255,7 @@
 "    de modificări (etichete sau nume de ramuri) cu -r/--rev.\n"
 "    Dacă se folosește -r/--rev, depozitul clonat va conține numai un subset\n"
 "    al seturilor de modificări ale depozitului sursă. Numai colecția de\n"
-"     seturi de modificări definite de toate opțiunile -r/--rev (inclusiv "
+"    seturi de modificări definite de toate opțiunile -r/--rev (inclusiv "
 "toți\n"
 "    strămoșii) va fi adusă (pulled) in depozitul destinație.\n"
 "    Nici un set de modificări ulterior (inclusiv etichete ulterioare) nu se\n"
@@ -8341,7 +8341,7 @@
 
 msgid "use any branch information in patch (implied by --exact)"
 msgstr ""
-"folosește orice informație despre ramură din patch\n"
+"folosește orice informație despre ramură din patch "
 "(implicat de --exact)"
 
 msgid "[OPTION]... PATCH..."
@@ -8425,7 +8425,7 @@
 
 msgid "a remote changeset intended to be added"
 msgstr ""
-"un set de modificări la distanță care se intenționează a fi\n"
+"un set de modificări la distanță care se intenționează a fi "
 "adăugat"
 
 msgid "compare bookmarks"
@@ -8559,7 +8559,7 @@
 
 msgid "show only changesets within the given named branch (DEPRECATED)"
 msgstr ""
-"afișează doar seturile de modificări din interiorul ramurii denumite\n"
+"afișează doar seturile de modificări din interiorul ramurii denumite "
 "specificate (ÎNVECHIT)"
 
 msgid "show changesets within the given named branch"
@@ -8673,7 +8673,7 @@
 
 msgid "review revisions to merge (no merge is performed)"
 msgstr ""
-"treci în revistă reviziile de fuzionat (nu se execută\n"
+"treci în revistă reviziile de fuzionat (nu se execută "
 "nicio fuziune)"
 
 msgid "[-P] [-f] [[-r] REV]"
@@ -8889,7 +8889,7 @@
 
 msgid "update to new branch head if changesets were pulled"
 msgstr ""
-"actualizează la noul capăt de ramură, dacă au fost preluate\n"
+"actualizează la noul capăt de ramură, dacă au fost preluate "
 "seturi de modificări"
 
 msgid "run even when remote repository is unrelated"
@@ -9889,7 +9889,7 @@
 
 msgid "update to new branch head if changesets were unbundled"
 msgstr ""
-"actualizează la noul capăt de ramură, dacă au fost despachetate\n"
+"actualizează la noul capăt de ramură, dacă au fost despachetate "
 "(unbundled) seturi de modificări"
 
 msgid "[-u] FILE..."
--- a/i18n/ru.po	Sat Oct 19 14:20:31 2013 -0700
+++ b/i18n/ru.po	Sun Oct 20 16:43:11 2013 -0700
@@ -177,7 +177,7 @@
 "POT-Creation-Date: 2013-10-07 16:00+0400\n"
 "PO-Revision-Date: 2011-05-12 23:48+0400\n"
 "Last-Translator: Alexander Sauta <demosito@gmail.com>\n"
-"Language-Team: LANGUAGE TEAM <E-MAIL@ADDRESS or HOME PAGE>\n"
+"Language-Team: Russian\n"
 "Language: ru\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
@@ -963,8 +963,7 @@
 "  {bug}.\\ndetails:\\n\\t{desc|tabindent}``"
 msgstr ""
 "  По умолчанию ``набор изменений {node|short} в хранилище {root}\n"
-"  относится к багу {bug}.\\nДетали:\\n\n"
-"\t{desc|tabindent}"
+"  относится к багу {bug}.\\nДетали:\\n\\t{desc|tabindent}``"
 
 msgid ""
 "bugzilla.strip\n"
@@ -2262,13 +2261,13 @@
 "    ``svn://хранилище/путь`` преобразуется в одну ветку. Если\n"
 "    ``svn://хранилище/путь/trunk`` существует, он заменяет ветку\n"
 "    ``default``. Если ``svn://хранилище/путь/branches`` существует,\n"
-"     его подкаталоги перечисляются как возможные ветки. Если\n"
-"     ``svn://хранилище/путь/tags`` существует, в нем ищутся\n"
-"     метки, ссылающиеся на конвертируемые ветки. Значения по умолчанию\n"
-"     для ``trunk``, ``branches`` и ``tags`` могут быть изменены\n"
-"     нижеперечисленными параметрами. Установите их в пути относительно\n"
-"     URL источника или оставьте пустыми чтобы отключить автоматическое\n"
-"     определение."
+"    его подкаталоги перечисляются как возможные ветки. Если\n"
+"    ``svn://хранилище/путь/tags`` существует, в нем ищутся\n"
+"    метки, ссылающиеся на конвертируемые ветки. Значения по умолчанию\n"
+"    для ``trunk``, ``branches`` и ``tags`` могут быть изменены\n"
+"    нижеперечисленными параметрами. Установите их в пути относительно\n"
+"    URL источника или оставьте пустыми чтобы отключить автоматическое\n"
+"    определение."
 
 msgid "    The following options can be set with ``--config``:"
 msgstr "    Следующие параметры могут быть заданы в ``--config``:"
@@ -3556,7 +3555,7 @@
 
 msgid "pull changes from a remote repository, merge new changes if needed."
 msgstr ""
-"затягивает изменения из отдалённого хранилища, проводит слияние\n"
+"затягивает изменения из отдалённого хранилища, проводит слияние "
 "при необходимости."
 
 msgid ""
@@ -4113,7 +4112,7 @@
 "is as follows, assuming the following history::"
 msgstr ""
 "Это расширение добавляет в Mercurial одну команду: histedit.\n"
-"Ниже приводится пример использования для следующей истории:"
+"Ниже приводится пример использования для следующей истории::"
 
 msgid ""
 " @  3[tip]   7c2fd3b9020c   2009-04-27 18:04 -0500   durin42\n"
@@ -4299,7 +4298,7 @@
 msgid ""
 "The ``message`` operation will give you a chance to revise a commit\n"
 "message without changing the contents. It's a shortcut for doing\n"
-"``edit`` immediately followed by `hg histedit --continue``."
+"``edit`` immediately followed by ``hg histedit --continue``."
 msgstr ""
 "Операция ``message`` позволит вам исправить сообщение фиксации без\n"
 "изменения содержимого ревизии. Это сокращенный вариант выполнения\n"
@@ -5254,7 +5253,7 @@
 "Если вы просто хотите убедиться, что у вас будут все большие файлы,\n"
 "необходимые для слияния или перебазирования с новыми головными ревизиями,\n"
 "которые вы затягиваете, вы можете выполнить pull с `--lfrev \"head(pulled"
-"())\".\n"
+"())\"`.\n"
 "Это позволит заранее загрузить все большие файлы, являющиеся новыми в "
 "головных\n"
 "ревизиях, которые вы затягиваете."
@@ -5409,7 +5408,7 @@
 
 # does this require a translation?
 msgid "    .. container:: verbose"
-msgstr "    .. container:: подробный"
+msgstr "    .. container:: verbose"
 
 msgid "      Some examples:"
 msgstr "      Несколько примеров::"
@@ -7333,7 +7332,7 @@
 msgstr ""
 "    Это может быть особенно полезным, если ваши изменения были наложены\n"
 "    в вышестоящем (upstream) хранилище, или вы как раз собираетесь\n"
-"     протолкнуть туда ваши изменения."
+"    протолкнуть туда ваши изменения."
 
 msgid "warning: uncommitted changes in the working directory\n"
 msgstr "внимание: незафиксированные изменения в рабочем каталоге\n"
@@ -10570,7 +10569,7 @@
 "    (можно переопределить с помощью -t/--type)."
 
 msgid "      Examples:"
-msgstr "      Примеры::"
+msgstr "      Примеры:"
 
 msgid "      - create a zip file containing the 1.0 release::"
 msgstr "      - создать zip-файл, содержащий релиз 1.0::"
@@ -11019,7 +11018,7 @@
 "    the bookmarks extension must be enabled."
 msgstr ""
 "    Закладки могут передаваться между хранилищами с помощью команд\n"
-"    push и pull (см. :hg:`help push` и :hg:`help pull). Для этого\n"
+"    push и pull (см. :hg:`help push` и :hg:`help pull`). Для этого\n"
 "    необходимо, чтобы отдалённое и локальное хранилище поддерживали\n"
 "    закладки. Для Mercurial версий меньше 1.8 это означает, что\n"
 "    должно быть включено расширение bookmarks.\n"
@@ -11396,7 +11395,7 @@
 "branch.\n"
 "    Клон будет содержать только заданные ревизии и их предков. Эти "
 "параметры\n"
-"    (равно как и `clone ист#рев назн') подразумевают --pull, даже для "
+"    (равно как и 'clone ист#рев назн') подразумевают --pull, даже для "
 "локальных\n"
 "    исходных хранилищ. Обратите внимание, что при задании метки, клон будет\n"
 "    включать в себя помеченный набор изменений, но не набор изменений,\n"
@@ -14658,7 +14657,7 @@
 msgid "      - get a NUL separated list of added files, suitable for xargs::"
 msgstr ""
 "      - показать разделенный символом NUL список добавленных файлов\n"
-"       для использования с xargs::"
+"        для использования с xargs::"
 
 msgid "          hg status -an0"
 msgstr "          hg status -an0"
@@ -15629,7 +15628,7 @@
 "``internal:dump``\n"
 "Создает три версии файла для слияния: локальную, из хранилища и\n"
 "   базовую. Эти файлы можно использовать для слияния вручную. Если\n"
-"   файл называется `a.txt``, то эти файлы будут называться ``a.txt.local``,\n"
+"   файл называется ``a.txt``, то эти файлы будут называться ``a.txt.local``,\n"
 "   ``a.txt.other`` и ``a.txt.base`` соответственно и будут находиться\n"
 "   в том же каталоге, что и ``a.txt``."
 
--- a/i18n/sv.po	Sat Oct 19 14:20:31 2013 -0700
+++ b/i18n/sv.po	Sun Oct 20 16:43:11 2013 -0700
@@ -8055,7 +8055,7 @@
 msgstr ""
 "    Nya filer ignoreras om de överrensstämmer något av mönstren i\n"
 "    ``.hgignore``. Precis som med add, kommer ändringarna att träda i kraft\n"
-"     vid nästa arkivering."
+"    vid nästa arkivering."
 
 msgid ""
 "    Use the -s/--similarity option to detect renamed files. This\n"
@@ -9788,7 +9788,7 @@
 "    given using a format string. The formatting rules are as follows:"
 msgstr ""
 "    Utmatning kan vara till en fil, och då anges namnet på filen med en\n"
-"    formatsträng. Formateringsreglerna är som följer::"
+"    formatsträng. Formateringsreglerna är som följer:"
 
 msgid ""
 "    :``%%``: literal \"%\" character\n"
--- a/i18n/zh_TW.po	Sat Oct 19 14:20:31 2013 -0700
+++ b/i18n/zh_TW.po	Sun Oct 20 16:43:11 2013 -0700
@@ -7346,7 +7346,7 @@
 msgstr ""
 
 msgid "    :hg:`resolve` must be used to resolve unresolved files."
-msgstr "hg `resolve`必須使用在解決未解決的檔案."
+msgstr "    hg `resolve` 必須使用在解決未解決的檔案."
 
 msgid ""
 "    To undo an uncommitted merge, use :hg:`update --clean .` which\n"
--- a/mercurial/bookmarks.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/bookmarks.py	Sun Oct 20 16:43:11 2013 -0700
@@ -8,7 +8,7 @@
 from mercurial.i18n import _
 from mercurial.node import hex
 from mercurial import encoding, error, util, obsolete
-import errno, os
+import errno
 
 class bmstore(dict):
     """Storage for bookmarks.
@@ -70,7 +70,7 @@
 
             # touch 00changelog.i so hgweb reloads bookmarks (no lock needed)
             try:
-                os.utime(repo.sjoin('00changelog.i'), None)
+                repo.svfs.utime('00changelog.i', None)
             except OSError:
                 pass
 
@@ -126,7 +126,7 @@
     wlock = repo.wlock()
     try:
         try:
-            util.unlink(repo.join('bookmarks.current'))
+            repo.vfs.unlink('bookmarks.current')
             repo._bookmarkcurrent = None
         except OSError, inst:
             if inst.errno != errno.ENOENT:
--- a/mercurial/branchmap.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/branchmap.py	Sun Oct 20 16:43:11 2013 -0700
@@ -198,20 +198,7 @@
                 self.tipnode = cl.node(tiprev)
                 self.tiprev = tiprev
 
-        # There may be branches that cease to exist when the last commit in the
-        # branch was stripped.  This code filters them out.  Note that the
-        # branch that ceased to exist may not be in newbranches because
-        # newbranches is the set of candidate heads, which when you strip the
-        # last commit in a branch will be the parent branch.
-        droppednodes = []
-        for branch in self.keys():
-            nodes = [head for head in self[branch]
-                     if cl.hasnode(head)]
-            if not nodes:
-                droppednodes.extend(nodes)
-                del self[branch]
-        if ((not self.validfor(repo)) or (self.tipnode in droppednodes)):
-
+        if not self.validfor(repo):
             # cache key are not valid anymore
             self.tipnode = nullid
             self.tiprev = nullrev
--- a/mercurial/bundlerepo.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/bundlerepo.py	Sun Oct 20 16:43:11 2013 -0700
@@ -120,7 +120,7 @@
             chain.append(iterrev)
             iterrev = self.index[iterrev][3]
         if text is None:
-            text = revlog.revlog.revision(self, iterrev)
+            text = self.baserevision(iterrev)
 
         while chain:
             delta = self._chunk(chain.pop())
@@ -130,6 +130,12 @@
         self._cache = (node, rev, text)
         return text
 
+    def baserevision(self, nodeorrev):
+        # Revlog subclasses may override 'revision' method to modify format of
+        # content retrieved from revlog. To use bundlerevlog with such class one
+        # needs to override 'baserevision' and make more specific call here.
+        return revlog.revlog.revision(self, nodeorrev)
+
     def addrevision(self, text, transaction, link, p1=None, p2=None, d=None):
         raise NotImplementedError
     def addgroup(self, revs, linkmapper, transaction):
@@ -146,12 +152,21 @@
         bundlerevlog.__init__(self, opener, self.indexfile, bundle,
                               linkmapper)
 
+    def baserevision(self, nodeorrev):
+        # Although changelog doesn't override 'revision' method, some extensions
+        # may replace this class with another that does. Same story with
+        # manifest and filelog classes.
+        return changelog.changelog.revision(self, nodeorrev)
+
 class bundlemanifest(bundlerevlog, manifest.manifest):
     def __init__(self, opener, bundle, linkmapper):
         manifest.manifest.__init__(self, opener)
         bundlerevlog.__init__(self, opener, self.indexfile, bundle,
                               linkmapper)
 
+    def baserevision(self, nodeorrev):
+        return manifest.manifest.revision(self, nodeorrev)
+
 class bundlefilelog(bundlerevlog, filelog.filelog):
     def __init__(self, opener, path, bundle, linkmapper, repo):
         filelog.filelog.__init__(self, opener, path)
@@ -159,6 +174,9 @@
                               linkmapper)
         self._repo = repo
 
+    def baserevision(self, nodeorrev):
+        return filelog.filelog.revision(self, nodeorrev)
+
     def _file(self, f):
         self._repo.file(f)
 
--- a/mercurial/changelog.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/changelog.py	Sun Oct 20 16:43:11 2013 -0700
@@ -59,11 +59,12 @@
 class appender(object):
     '''the changelog index must be updated last on disk, so we use this class
     to delay writes to it'''
-    def __init__(self, fp, buf):
+    def __init__(self, vfs, name, mode, buf):
         self.data = buf
+        fp = vfs(name, mode)
         self.fp = fp
         self.offset = fp.tell()
-        self.size = util.fstat(fp).st_size
+        self.size = vfs.fstat(fp).st_size
 
     def end(self):
         return self.size + len("".join(self.data))
@@ -114,7 +115,7 @@
         if divert:
             return opener(name + ".a", mode.replace('a', 'w'))
         # otherwise, divert to memory
-        return appender(opener(name, mode), buf)
+        return appender(opener, name, mode, buf)
     return o
 
 class changelog(revlog.revlog):
@@ -224,10 +225,10 @@
         self.opener = self._realopener
         # move redirected index data back into place
         if self._divert:
-            nfile = self.opener(self.indexfile + ".a")
-            n = nfile.name
+            tmpname = self.indexfile + ".a"
+            nfile = self.opener.open(tmpname)
             nfile.close()
-            util.rename(n, n[:-2])
+            self.opener.rename(tmpname, self.indexfile)
         elif self._delaybuf:
             fp = self.opener(self.indexfile, 'a')
             fp.write("".join(self._delaybuf))
--- a/mercurial/cmdutil.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/cmdutil.py	Sun Oct 20 16:43:11 2013 -0700
@@ -84,7 +84,7 @@
         raise util.Abort(_('outstanding uncommitted merge'))
     modified, added, removed, deleted = repo.status()[:4]
     if modified or added or removed or deleted:
-        raise util.Abort(_("outstanding uncommitted changes"))
+        raise util.Abort(_('uncommitted changes'))
     ctx = repo[None]
     for s in sorted(ctx.substate):
         if ctx.sub(s).dirty():
@@ -468,6 +468,13 @@
     runargs=None, appendpid=False):
     '''Run a command as a service.'''
 
+    def writepid(pid):
+        if opts['pid_file']:
+            mode = appendpid and 'a' or 'w'
+            fp = open(opts['pid_file'], mode)
+            fp.write(str(pid) + '\n')
+            fp.close()
+
     if opts['daemon'] and not opts['daemon_pipefds']:
         # Signal child process startup with file removal
         lockfd, lockpath = tempfile.mkstemp(prefix='hg-service-')
@@ -490,6 +497,7 @@
             pid = util.rundetached(runargs, condfn)
             if pid < 0:
                 raise util.Abort(_('child process failed to start'))
+            writepid(pid)
         finally:
             try:
                 os.unlink(lockpath)
@@ -504,11 +512,8 @@
     if initfn:
         initfn()
 
-    if opts['pid_file']:
-        mode = appendpid and 'a' or 'w'
-        fp = open(opts['pid_file'], mode)
-        fp.write(str(os.getpid()) + '\n')
-        fp.close()
+    if not opts['daemon']:
+        writepid(os.getpid())
 
     if opts['daemon_pipefds']:
         lockpath = opts['daemon_pipefds']
@@ -928,7 +933,7 @@
     regular display via changeset_printer() is done.
     """
     # options
-    patch = False
+    patch = None
     if opts.get('patch') or opts.get('stat'):
         patch = scmutil.matchall(repo)
 
@@ -1172,12 +1177,34 @@
                                'filenames'))
 
         # The slow path checks files modified in every changeset.
-        for i in sorted(revs):
-            ctx = change(i)
-            matches = filter(match, ctx.files())
-            if matches:
-                fncache[i] = matches
-                wanted.add(i)
+        # This is really slow on large repos, so compute the set lazily.
+        class lazywantedset(object):
+            def __init__(self):
+                self.set = set()
+                self.revs = set(revs)
+
+            # No need to worry about locality here because it will be accessed
+            # in the same order as the increasing window below.
+            def __contains__(self, value):
+                if value in self.set:
+                    return True
+                elif not value in self.revs:
+                    return False
+                else:
+                    self.revs.discard(value)
+                    ctx = change(value)
+                    matches = filter(match, ctx.files())
+                    if matches:
+                        fncache[value] = matches
+                        self.set.add(value)
+                        return True
+                    return False
+
+            def discard(self, value):
+                self.revs.discard(value)
+                self.set.discard(value)
+
+        wanted = lazywantedset()
 
     class followfilter(object):
         def __init__(self, onlyfirst=False):
--- a/mercurial/commands.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/commands.py	Sun Oct 20 16:43:11 2013 -0700
@@ -12,7 +12,8 @@
 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
+import sshserver, hgweb, commandserver
+from hgweb import server as hgweb_server
 import merge as mergemod
 import minirst, revset, fileset
 import dagparser, context, simplemerge, graphmod
@@ -1807,7 +1808,7 @@
     [('c', 'changelog', False, _('open changelog')),
      ('m', 'manifest', False, _('open manifest'))],
     _('-c|-m|FILE REV'))
-def debugdata(ui, repo, file_, rev = None, **opts):
+def debugdata(ui, repo, file_, rev=None, **opts):
     """dump the contents of a data file revision"""
     if opts.get('changelog') or opts.get('manifest'):
         file_, rev = None, file_
@@ -1918,11 +1919,12 @@
         ui.write("%s\n" % f)
 
 @command('debugfsinfo', [], _('[PATH]'))
-def debugfsinfo(ui, path = "."):
+def debugfsinfo(ui, path="."):
     """show information detected about current filesystem"""
     util.writefile('.debugfsinfo', '')
     ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
     ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
+    ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
     ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
                                 and 'yes' or 'no'))
     os.unlink('.debugfsinfo')
@@ -1972,7 +1974,7 @@
      ('m', 'manifest', False, _('open manifest')),
      ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
     _('[-f FORMAT] -c|-m|FILE'))
-def debugindex(ui, repo, file_ = None, **opts):
+def debugindex(ui, repo, file_=None, **opts):
     """dump the contents of an index file"""
     r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
     format = opts.get('format', 0)
@@ -2353,7 +2355,7 @@
      ('m', 'manifest', False, _('open manifest')),
      ('d', 'dump', False, _('dump index data'))],
      _('-c|-m|FILE'))
-def debugrevlog(ui, repo, file_ = None, **opts):
+def debugrevlog(ui, repo, file_=None, **opts):
     """show data and statistics about a revlog"""
     r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
 
@@ -3019,11 +3021,12 @@
         if n in ids:
             r = repo[n].rev()
             if r in revs:
-                ui.warn(_('skipping already grafted revision %s\n') % r)
+                ui.warn(_('skipping revision %s (already grafted to %s)\n')
+                        % (r, rev))
                 revs.remove(r)
             elif ids[n] in revs:
                 ui.warn(_('skipping already grafted revision %s '
-                            '(same origin %d)\n') % (ids[n], r))
+                            '(%s also has origin %d)\n') % (ids[n], rev, r))
                 revs.remove(ids[n])
         elif ctx.hex() in ids:
             r = ids[ctx.hex()]
@@ -4525,6 +4528,8 @@
             ret = hg.update(repo, checkout)
         except util.Abort, inst:
             ui.warn(_("not updating: %s\n") % str(inst))
+            if inst.hint:
+                ui.warn(_("(%s)\n") % inst.hint)
             return 0
         if not ret and not checkout:
             if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
@@ -4646,8 +4651,10 @@
     branch that is not present at the destination. This allows you to
     only create a new branch without forcing other changes.
 
-    Use -f/--force to override the default behavior and push all
-    changesets on all branches.
+    .. note::
+      Extra care should be used with the -f/--force option,
+      which will push all new heads on all branches, an action which will
+      almost always cause confusion for collaborators.
 
     If -r/--rev is used, the specified revision and all its ancestors
     will be pushed to the remote repository.
@@ -5178,47 +5185,51 @@
         o = repo
 
     app = hgweb.hgweb(o, baseui=baseui)
-
-    class service(object):
-        def init(self):
-            util.setsignalhandler()
-            self.httpd = hgweb.server.create_server(ui, app)
-
-            if opts['port'] and not ui.verbose:
-                return
-
-            if self.httpd.prefix:
-                prefix = self.httpd.prefix.strip('/') + '/'
-            else:
-                prefix = ''
-
-            port = ':%d' % self.httpd.port
-            if port == ':80':
-                port = ''
-
-            bindaddr = self.httpd.addr
-            if bindaddr == '0.0.0.0':
-                bindaddr = '*'
-            elif ':' in bindaddr: # IPv6
-                bindaddr = '[%s]' % bindaddr
-
-            fqaddr = self.httpd.fqaddr
-            if ':' in fqaddr:
-                fqaddr = '[%s]' % fqaddr
-            if opts['port']:
-                write = ui.status
-            else:
-                write = ui.write
-            write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
-                  (fqaddr, port, prefix, bindaddr, self.httpd.port))
-
-        def run(self):
-            self.httpd.serve_forever()
-
-    service = service()
-
+    service = httpservice(ui, app, opts)
     cmdutil.service(opts, initfn=service.init, runfn=service.run)
 
+class httpservice(object):
+    def __init__(self, ui, app, opts):
+        self.ui = ui
+        self.app = app
+        self.opts = opts
+
+    def init(self):
+        util.setsignalhandler()
+        self.httpd = hgweb_server.create_server(self.ui, self.app)
+
+        if self.opts['port'] and not self.ui.verbose:
+            return
+
+        if self.httpd.prefix:
+            prefix = self.httpd.prefix.strip('/') + '/'
+        else:
+            prefix = ''
+
+        port = ':%d' % self.httpd.port
+        if port == ':80':
+            port = ''
+
+        bindaddr = self.httpd.addr
+        if bindaddr == '0.0.0.0':
+            bindaddr = '*'
+        elif ':' in bindaddr: # IPv6
+            bindaddr = '[%s]' % bindaddr
+
+        fqaddr = self.httpd.fqaddr
+        if ':' in fqaddr:
+            fqaddr = '[%s]' % fqaddr
+        if self.opts['port']:
+            write = self.ui.status
+        else:
+            write = self.ui.write
+        write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
+              (fqaddr, port, prefix, bindaddr, self.httpd.port))
+
+    def run(self):
+        self.httpd.serve_forever()
+
+
 @command('showconfig|debugconfig',
     [('u', 'untrusted', None, _('show untrusted configuration options'))],
     _('[-u] [NAME]...'))
@@ -5846,7 +5857,7 @@
     if check:
         c = repo[None]
         if c.dirty(merge=False, branch=False, missing=True):
-            raise util.Abort(_("uncommitted local changes"))
+            raise util.Abort(_("uncommitted changes"))
         if rev is None:
             rev = repo[repo[None].branch()].rev()
         mergemod._checkunknown(repo, repo[None], repo[rev])
--- a/mercurial/context.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/context.py	Sun Oct 20 16:43:11 2013 -0700
@@ -16,11 +16,197 @@
 
 propertycache = util.propertycache
 
-class changectx(object):
+class basectx(object):
+    """A basectx object represents the common logic for its children:
+    changectx: read-only context that is already present in the repo,
+    workingctx: a context that represents the working directory and can
+                be committed,
+    memctx: a context that represents changes in-memory and can also
+            be committed."""
+    def __new__(cls, repo, changeid='', *args, **kwargs):
+        if isinstance(changeid, basectx):
+            return changeid
+
+        o = super(basectx, cls).__new__(cls)
+
+        o._repo = repo
+        o._rev = nullrev
+        o._node = nullid
+
+        return o
+
+    def __str__(self):
+        return short(self.node())
+
+    def __int__(self):
+        return self.rev()
+
+    def __repr__(self):
+        return "<%s %s>" % (type(self).__name__, str(self))
+
+    def __eq__(self, other):
+        try:
+            return type(self) == type(other) and self._rev == other._rev
+        except AttributeError:
+            return False
+
+    def __ne__(self, other):
+        return not (self == other)
+
+    def __contains__(self, key):
+        return key in self._manifest
+
+    def __getitem__(self, key):
+        return self.filectx(key)
+
+    def __iter__(self):
+        for f in sorted(self._manifest):
+            yield f
+
+    @propertycache
+    def substate(self):
+        return subrepo.state(self, self._repo.ui)
+
+    def rev(self):
+        return self._rev
+    def node(self):
+        return self._node
+    def hex(self):
+        return hex(self.node())
+    def manifest(self):
+        return self._manifest
+    def phasestr(self):
+        return phases.phasenames[self.phase()]
+    def mutable(self):
+        return self.phase() > phases.public
+
+    def obsolete(self):
+        """True if the changeset is obsolete"""
+        return self.rev() in obsmod.getrevs(self._repo, 'obsolete')
+
+    def extinct(self):
+        """True if the changeset is extinct"""
+        return self.rev() in obsmod.getrevs(self._repo, 'extinct')
+
+    def unstable(self):
+        """True if the changeset is not obsolete but it's ancestor are"""
+        return self.rev() in obsmod.getrevs(self._repo, 'unstable')
+
+    def bumped(self):
+        """True if the changeset try to be a successor of a public changeset
+
+        Only non-public and non-obsolete changesets may be bumped.
+        """
+        return self.rev() in obsmod.getrevs(self._repo, 'bumped')
+
+    def divergent(self):
+        """Is a successors of a changeset with multiple possible successors set
+
+        Only non-public and non-obsolete changesets may be divergent.
+        """
+        return self.rev() in obsmod.getrevs(self._repo, 'divergent')
+
+    def troubled(self):
+        """True if the changeset is either unstable, bumped or divergent"""
+        return self.unstable() or self.bumped() or self.divergent()
+
+    def troubles(self):
+        """return the list of troubles affecting this changesets.
+
+        Troubles are returned as strings. possible values are:
+        - unstable,
+        - bumped,
+        - divergent.
+        """
+        troubles = []
+        if self.unstable():
+            troubles.append('unstable')
+        if self.bumped():
+            troubles.append('bumped')
+        if self.divergent():
+            troubles.append('divergent')
+        return troubles
+
+    def parents(self):
+        """return contexts for each parent changeset"""
+        return self._parents
+
+    def p1(self):
+        return self._parents[0]
+
+    def p2(self):
+        if len(self._parents) == 2:
+            return self._parents[1]
+        return changectx(self._repo, -1)
+
+    def _fileinfo(self, path):
+        if '_manifest' in self.__dict__:
+            try:
+                return self._manifest[path], self._manifest.flags(path)
+            except KeyError:
+                raise error.ManifestLookupError(self._node, path,
+                                                _('not found in manifest'))
+        if '_manifestdelta' in self.__dict__ or path in self.files():
+            if path in self._manifestdelta:
+                return (self._manifestdelta[path],
+                        self._manifestdelta.flags(path))
+        node, flag = self._repo.manifest.find(self._changeset[0], path)
+        if not node:
+            raise error.ManifestLookupError(self._node, path,
+                                            _('not found in manifest'))
+
+        return node, flag
+
+    def filenode(self, path):
+        return self._fileinfo(path)[0]
+
+    def flags(self, path):
+        try:
+            return self._fileinfo(path)[1]
+        except error.LookupError:
+            return ''
+
+    def sub(self, path):
+        return subrepo.subrepo(self, path)
+
+    def match(self, pats=[], include=None, exclude=None, default='glob'):
+        r = self._repo
+        return matchmod.match(r.root, r.getcwd(), pats,
+                              include, exclude, default,
+                              auditor=r.auditor, ctx=self)
+
+    def diff(self, ctx2=None, match=None, **opts):
+        """Returns a diff generator for the given contexts and matcher"""
+        if ctx2 is None:
+            ctx2 = self.p1()
+        if ctx2 is not None:
+            ctx2 = self._repo[ctx2]
+        diffopts = patch.diffopts(self._repo.ui, opts)
+        return patch.diff(self._repo, ctx2.node(), self.node(),
+                          match=match, opts=diffopts)
+
+    @propertycache
+    def _dirs(self):
+        return scmutil.dirs(self._manifest)
+
+    def dirs(self):
+        return self._dirs
+
+    def dirty(self):
+        return False
+
+class changectx(basectx):
     """A changecontext object makes access to data related to a particular
-    changeset convenient."""
+    changeset convenient. It represents a read-only context already presnt in
+    the repo."""
     def __init__(self, repo, changeid=''):
         """changeid is a revision number, node, or tag"""
+
+        # since basectx.__new__ already took care of copying the object, we
+        # don't need to do anything in __init__, so we just exit here
+        if isinstance(changeid, basectx):
+            return
+
         if changeid == '':
             changeid = '.'
         self._repo = repo
@@ -114,30 +300,12 @@
         raise error.RepoLookupError(
             _("unknown revision '%s'") % changeid)
 
-    def __str__(self):
-        return short(self.node())
-
-    def __int__(self):
-        return self.rev()
-
-    def __repr__(self):
-        return "<changectx %s>" % str(self)
-
     def __hash__(self):
         try:
             return hash(self._rev)
         except AttributeError:
             return id(self)
 
-    def __eq__(self, other):
-        try:
-            return self._rev == other._rev
-        except AttributeError:
-            return False
-
-    def __ne__(self, other):
-        return not (self == other)
-
     def __nonzero__(self):
         return self._rev != nullrev
 
@@ -160,33 +328,11 @@
             p = p[:-1]
         return [changectx(self._repo, x) for x in p]
 
-    @propertycache
-    def substate(self):
-        return subrepo.state(self, self._repo.ui)
-
-    def __contains__(self, key):
-        return key in self._manifest
-
-    def __getitem__(self, key):
-        return self.filectx(key)
-
-    def __iter__(self):
-        for f in sorted(self._manifest):
-            yield f
-
     def changeset(self):
         return self._changeset
-    def manifest(self):
-        return self._manifest
     def manifestnode(self):
         return self._changeset[0]
 
-    def rev(self):
-        return self._rev
-    def node(self):
-        return self._node
-    def hex(self):
-        return hex(self._node)
     def user(self):
         return self._changeset[1]
     def date(self):
@@ -207,25 +353,9 @@
         return self._repo.nodebookmarks(self._node)
     def phase(self):
         return self._repo._phasecache.phase(self._repo, self._rev)
-    def phasestr(self):
-        return phases.phasenames[self.phase()]
-    def mutable(self):
-        return self.phase() > phases.public
     def hidden(self):
         return self._rev in repoview.filterrevs(self._repo, 'visible')
 
-    def parents(self):
-        """return contexts for each parent changeset"""
-        return self._parents
-
-    def p1(self):
-        return self._parents[0]
-
-    def p2(self):
-        if len(self._parents) == 2:
-            return self._parents[1]
-        return changectx(self._repo, -1)
-
     def children(self):
         """return contexts for each child changeset"""
         c = self._repo.changelog.children(self._node)
@@ -239,80 +369,6 @@
         for d in self._repo.changelog.descendants([self._rev]):
             yield changectx(self._repo, d)
 
-    def obsolete(self):
-        """True if the changeset is obsolete"""
-        return self.rev() in obsmod.getrevs(self._repo, 'obsolete')
-
-    def extinct(self):
-        """True if the changeset is extinct"""
-        return self.rev() in obsmod.getrevs(self._repo, 'extinct')
-
-    def unstable(self):
-        """True if the changeset is not obsolete but it's ancestor are"""
-        return self.rev() in obsmod.getrevs(self._repo, 'unstable')
-
-    def bumped(self):
-        """True if the changeset try to be a successor of a public changeset
-
-        Only non-public and non-obsolete changesets may be bumped.
-        """
-        return self.rev() in obsmod.getrevs(self._repo, 'bumped')
-
-    def divergent(self):
-        """Is a successors of a changeset with multiple possible successors set
-
-        Only non-public and non-obsolete changesets may be divergent.
-        """
-        return self.rev() in obsmod.getrevs(self._repo, 'divergent')
-
-    def troubled(self):
-        """True if the changeset is either unstable, bumped or divergent"""
-        return self.unstable() or self.bumped() or self.divergent()
-
-    def troubles(self):
-        """return the list of troubles affecting this changesets.
-
-        Troubles are returned as strings. possible values are:
-        - unstable,
-        - bumped,
-        - divergent.
-        """
-        troubles = []
-        if self.unstable():
-            troubles.append('unstable')
-        if self.bumped():
-            troubles.append('bumped')
-        if self.divergent():
-            troubles.append('divergent')
-        return troubles
-
-    def _fileinfo(self, path):
-        if '_manifest' in self.__dict__:
-            try:
-                return self._manifest[path], self._manifest.flags(path)
-            except KeyError:
-                raise error.ManifestLookupError(self._node, path,
-                                                _('not found in manifest'))
-        if '_manifestdelta' in self.__dict__ or path in self.files():
-            if path in self._manifestdelta:
-                return (self._manifestdelta[path],
-                        self._manifestdelta.flags(path))
-        node, flag = self._repo.manifest.find(self._changeset[0], path)
-        if not node:
-            raise error.ManifestLookupError(self._node, path,
-                                            _('not found in manifest'))
-
-        return node, flag
-
-    def filenode(self, path):
-        return self._fileinfo(path)[0]
-
-    def flags(self, path):
-        try:
-            return self._fileinfo(path)[1]
-        except error.LookupError:
-            return ''
-
     def filectx(self, path, fileid=None, filelog=None):
         """get a file context from this changeset"""
         if fileid is None:
@@ -353,83 +409,15 @@
             if match.bad(fn, _('no such file in rev %s') % self) and match(fn):
                 yield fn
 
-    def sub(self, path):
-        return subrepo.subrepo(self, path)
-
-    def match(self, pats=[], include=None, exclude=None, default='glob'):
-        r = self._repo
-        return matchmod.match(r.root, r.getcwd(), pats,
-                              include, exclude, default,
-                              auditor=r.auditor, ctx=self)
-
-    def diff(self, ctx2=None, match=None, **opts):
-        """Returns a diff generator for the given contexts and matcher"""
-        if ctx2 is None:
-            ctx2 = self.p1()
-        if ctx2 is not None and not isinstance(ctx2, changectx):
-            ctx2 = self._repo[ctx2]
-        diffopts = patch.diffopts(self._repo.ui, opts)
-        return patch.diff(self._repo, ctx2.node(), self.node(),
-                          match=match, opts=diffopts)
-
-    @propertycache
-    def _dirs(self):
-        return scmutil.dirs(self._manifest)
-
-    def dirs(self):
-        return self._dirs
-
-    def dirty(self):
-        return False
-
-class filectx(object):
-    """A filecontext object makes access to data related to a particular
-       filerevision convenient."""
-    def __init__(self, repo, path, changeid=None, fileid=None,
-                 filelog=None, changectx=None):
-        """changeid can be a changeset revision, node, or tag.
-           fileid can be a file revision or node."""
-        self._repo = repo
-        self._path = path
-
-        assert (changeid is not None
-                or fileid is not None
-                or changectx is not None), \
-                ("bad args: changeid=%r, fileid=%r, changectx=%r"
-                 % (changeid, fileid, changectx))
-
-        if filelog is not None:
-            self._filelog = filelog
-
-        if changeid is not None:
-            self._changeid = changeid
-        if changectx is not None:
-            self._changectx = changectx
-        if fileid is not None:
-            self._fileid = fileid
-
-    @propertycache
-    def _changectx(self):
-        try:
-            return changectx(self._repo, self._changeid)
-        except error.RepoLookupError:
-            # Linkrev may point to any revision in the repository.  When the
-            # 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 complex operations that care about
-            # filtering.
-            #
-            # This fallback is a cheap and dirty fix that prevent several
-            # 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"
-            #
-            # Linkrevs have several serious troubles with filtering that are
-            # complicated to solve. Proper handling of the issue here should be
-            # considered when solving linkrev issue are on the table.
-            return changectx(self._repo.unfiltered(), self._changeid)
+class basefilectx(object):
+    """A filecontext object represents the common logic for its children:
+    filectx: read-only access to a filerevision that is already present
+             in the repo,
+    workingfilectx: a filecontext that represents files from the working
+                    directory,
+    memfilectx: a filecontext that represents files in-memory."""
+    def __new__(cls, repo, path, *args, **kwargs):
+        return super(basefilectx, cls).__new__(cls)
 
     @propertycache
     def _filelog(self):
@@ -468,10 +456,10 @@
             return False
 
     def __str__(self):
-        return "%s@%s" % (self.path(), short(self.node()))
+        return "%s@%s" % (self.path(), self._changectx)
 
     def __repr__(self):
-        return "<filectx %s>" % str(self)
+        return "<%s %s>" % (type(self).__name__, str(self))
 
     def __hash__(self):
         try:
@@ -481,7 +469,7 @@
 
     def __eq__(self, other):
         try:
-            return (self._path == other._path
+            return (type(self) == type(other) and self._path == other._path
                     and self._filenode == other._filenode)
         except AttributeError:
             return False
@@ -489,12 +477,6 @@
     def __ne__(self, other):
         return not (self == other)
 
-    def filectx(self, fileid):
-        '''opens an arbitrary revision of the file without
-        opening a new filelog'''
-        return filectx(self._repo, self._path, fileid=fileid,
-                       filelog=self._filelog)
-
     def filerev(self):
         return self._filerev
     def filenode(self):
@@ -510,7 +492,7 @@
     def node(self):
         return self._changectx.node()
     def hex(self):
-        return hex(self.node())
+        return self._changectx.hex()
     def user(self):
         return self._changectx.user()
     def date(self):
@@ -532,12 +514,8 @@
     def changectx(self):
         return self._changectx
 
-    def data(self):
-        return self._filelog.read(self._filenode)
     def path(self):
         return self._path
-    def size(self):
-        return self._filelog.size(self._filerev)
 
     def isbinary(self):
         try:
@@ -560,31 +538,6 @@
 
         return True
 
-    def renamed(self):
-        """check if file was actually renamed in this changeset revision
-
-        If rename logged in file revision, we report copy for changeset only
-        if file revisions linkrev points back to the changeset in question
-        or both changeset parents contain different file revisions.
-        """
-
-        renamed = self._filelog.renamed(self._filenode)
-        if not renamed:
-            return renamed
-
-        if self.rev() == self.linkrev():
-            return renamed
-
-        name = self.path()
-        fnode = self._filenode
-        for p in self._changectx.parents():
-            try:
-                if fnode == p.filenode(name):
-                    return None
-            except error.LookupError:
-                pass
-        return renamed
-
     def parents(self):
         p = self._path
         fl = self._filelog
@@ -606,12 +559,6 @@
             return p[1]
         return filectx(self._repo, self._path, fileid=-1, filelog=self._filelog)
 
-    def children(self):
-        # hard for renames
-        c = self._filelog.children(self._filenode)
-        return [filectx(self._repo, self._path, fileid=x,
-                        filelog=self._filelog) for x in c]
-
     def annotate(self, follow=False, linenumber=None, diffopts=None):
         '''returns a list of tuples of (ctx, line) for each line
         in the file, where ctx is the filectx of the node where
@@ -783,15 +730,100 @@
             self._copycache[sc2] = copies.pathcopies(c2)
         return self._copycache[sc2]
 
-class workingctx(changectx):
-    """A workingctx object makes access to data related to
-    the current working directory convenient.
-    date - any valid date string or (unixtime, offset), or None.
-    user - username string, or None.
-    extra - a dictionary of extra values, or None.
-    changes - a list of file lists as returned by localrepo.status()
-               or None to use the repository status.
-    """
+class filectx(basefilectx):
+    """A filecontext object makes access to data related to a particular
+       filerevision convenient."""
+    def __init__(self, repo, path, changeid=None, fileid=None,
+                 filelog=None, changectx=None):
+        """changeid can be a changeset revision, node, or tag.
+           fileid can be a file revision or node."""
+        self._repo = repo
+        self._path = path
+
+        assert (changeid is not None
+                or fileid is not None
+                or changectx is not None), \
+                ("bad args: changeid=%r, fileid=%r, changectx=%r"
+                 % (changeid, fileid, changectx))
+
+        if filelog is not None:
+            self._filelog = filelog
+
+        if changeid is not None:
+            self._changeid = changeid
+        if changectx is not None:
+            self._changectx = changectx
+        if fileid is not None:
+            self._fileid = fileid
+
+    @propertycache
+    def _changectx(self):
+        try:
+            return changectx(self._repo, self._changeid)
+        except error.RepoLookupError:
+            # Linkrev may point to any revision in the repository.  When the
+            # 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 complex operations that care about
+            # filtering.
+            #
+            # This fallback is a cheap and dirty fix that prevent several
+            # 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"
+            #
+            # Linkrevs have several serious troubles with filtering that are
+            # complicated to solve. Proper handling of the issue here should be
+            # considered when solving linkrev issue are on the table.
+            return changectx(self._repo.unfiltered(), self._changeid)
+
+    def filectx(self, fileid):
+        '''opens an arbitrary revision of the file without
+        opening a new filelog'''
+        return filectx(self._repo, self._path, fileid=fileid,
+                       filelog=self._filelog)
+
+    def data(self):
+        return self._filelog.read(self._filenode)
+    def size(self):
+        return self._filelog.size(self._filerev)
+
+    def renamed(self):
+        """check if file was actually renamed in this changeset revision
+
+        If rename logged in file revision, we report copy for changeset only
+        if file revisions linkrev points back to the changeset in question
+        or both changeset parents contain different file revisions.
+        """
+
+        renamed = self._filelog.renamed(self._filenode)
+        if not renamed:
+            return renamed
+
+        if self.rev() == self.linkrev():
+            return renamed
+
+        name = self.path()
+        fnode = self._filenode
+        for p in self._changectx.parents():
+            try:
+                if fnode == p.filenode(name):
+                    return None
+            except error.LookupError:
+                pass
+        return renamed
+
+    def children(self):
+        # hard for renames
+        c = self._filelog.children(self._filenode)
+        return [filectx(self._repo, self._path, fileid=x,
+                        filelog=self._filelog) for x in c]
+
+class committablectx(basectx):
+    """A committablectx object provides common functionality for a context that
+    wants the ability to commit, e.g. workingctx or memctx."""
     def __init__(self, repo, text="", user=None, date=None, extra=None,
                  changes=None):
         self._repo = repo
@@ -827,9 +859,6 @@
     def __str__(self):
         return str(self._parents[0]) + "+"
 
-    def __repr__(self):
-        return "<workingctx %s>" % str(self)
-
     def __nonzero__(self):
         return True
 
@@ -904,12 +933,6 @@
 
         return man
 
-    def __iter__(self):
-        d = self._repo.dirstate
-        for f in d:
-            if d[f] != 'r':
-                yield f
-
     @propertycache
     def _status(self):
         return self._repo.status()[:4]
@@ -922,13 +945,6 @@
     def _date(self):
         return util.makedate()
 
-    @propertycache
-    def _parents(self):
-        p = self._repo.dirstate.parents()
-        if p[1] == nullid:
-            p = p[:-1]
-        return [changectx(self._repo, x) for x in p]
-
     def status(self, ignored=False, clean=False, unknown=False):
         """Explicit status query
         Unless this method is used to query the working copy status, the
@@ -945,8 +961,6 @@
         self._status = stat[:4]
         return stat
 
-    def manifest(self):
-        return self._manifest
     def user(self):
         return self._user or self._repo.ui.username()
     def date(self):
@@ -1016,11 +1030,6 @@
         except OSError:
             return ''
 
-    def filectx(self, path, filelog=None):
-        """get a file context from the working directory"""
-        return workingfilectx(self._repo, path, workingctx=self,
-                              filelog=filelog)
-
     def ancestor(self, c2):
         """return the ancestor context of self and c2"""
         return self._parents[0].ancestor(c2) # punt on two parents for now
@@ -1029,6 +1038,61 @@
         return sorted(self._repo.dirstate.walk(match, sorted(self.substate),
                                                True, False))
 
+    def ancestors(self):
+        for a in self._repo.changelog.ancestors(
+            [p.rev() for p in self._parents]):
+            yield changectx(self._repo, a)
+
+    def markcommitted(self, node):
+        """Perform post-commit cleanup necessary after committing this ctx
+
+        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 self._repo.dirstate.dirs()
+
+class workingctx(committablectx):
+    """A workingctx object makes access to data related to
+    the current working directory convenient.
+    date - any valid date string or (unixtime, offset), or None.
+    user - username string, or None.
+    extra - a dictionary of extra values, or None.
+    changes - a list of file lists as returned by localrepo.status()
+               or None to use the repository status.
+    """
+    def __init__(self, repo, text="", user=None, date=None, extra=None,
+                 changes=None):
+        super(workingctx, self).__init__(repo, text, user, date, extra, changes)
+
+    def __iter__(self):
+        d = self._repo.dirstate
+        for f in d:
+            if d[f] != 'r':
+                yield f
+
+    @propertycache
+    def _parents(self):
+        p = self._repo.dirstate.parents()
+        if p[1] == nullid:
+            p = p[:-1]
+        return [changectx(self._repo, x) for x in p]
+
+    def filectx(self, path, filelog=None):
+        """get a file context from the working directory"""
+        return workingfilectx(self._repo, path, workingctx=self,
+                              filelog=filelog)
+
     def dirty(self, missing=False, merge=True, branch=True):
         "check whether a working directory is modified"
         # check subrepos first
@@ -1047,11 +1111,11 @@
         ui, ds = self._repo.ui, self._repo.dirstate
         try:
             rejected = []
+            lstat = self._repo.wvfs.lstat
             for f in list:
                 scmutil.checkportable(ui, join(f))
-                p = self._repo.wjoin(f)
                 try:
-                    st = os.lstat(p)
+                    st = lstat(f)
                 except OSError:
                     ui.warn(_("%s does not exist!\n") % join(f))
                     rejected.append(f)
@@ -1065,7 +1129,7 @@
                 if not (stat.S_ISREG(st.st_mode) or stat.S_ISLNK(st.st_mode)):
                     ui.warn(_("%s not added: only files and symlinks "
                               "supported currently\n") % join(f))
-                    rejected.append(p)
+                    rejected.append(f)
                 elif ds[f] in 'amn':
                     ui.warn(_("%s already tracked!\n") % join(f))
                 elif ds[f] == 'r':
@@ -1093,11 +1157,6 @@
         finally:
             wlock.release()
 
-    def ancestors(self):
-        for a in self._repo.changelog.ancestors(
-            [p.rev() for p in self._parents]):
-            yield changectx(self._repo, a)
-
     def undelete(self, list):
         pctxs = self.parents()
         wlock = self._repo.wlock()
@@ -1114,10 +1173,14 @@
             wlock.release()
 
     def copy(self, source, dest):
-        p = self._repo.wjoin(dest)
-        if not os.path.lexists(p):
+        try:
+            st = self._repo.wvfs.lstat(dest)
+        except OSError, err:
+            if err.errno != errno.ENOENT:
+                raise
             self._repo.ui.warn(_("%s does not exist!\n") % dest)
-        elif not (os.path.isfile(p) or os.path.islink(p)):
+            return
+        if not (stat.S_ISREG(st.st_mode) or stat.S_ISLNK(st.st_mode)):
             self._repo.ui.warn(_("copy failed: %s is not a file or a "
                                  "symbolic link\n") % dest)
         else:
@@ -1129,31 +1192,10 @@
             finally:
                 wlock.release()
 
-    def markcommitted(self, node):
-        """Perform post-commit cleanup necessary after committing this ctx
-
-        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 self._repo.dirstate.dirs()
-
-class workingfilectx(filectx):
-    """A workingfilectx object makes access to data related to a particular
-       file in the working directory convenient."""
-    def __init__(self, repo, path, filelog=None, workingctx=None):
-        """changeid can be a changeset revision, node, or tag.
-           fileid can be a file revision or node."""
+class committablefilectx(basefilectx):
+    """A committablefilectx provides common functionality for a file context
+    that wants the ability to commit, e.g. workingfilectx or memfilectx."""
+    def __init__(self, repo, path, filelog=None, ctx=None):
         self._repo = repo
         self._path = path
         self._changeid = None
@@ -1161,30 +1203,12 @@
 
         if filelog is not None:
             self._filelog = filelog
-        if workingctx:
-            self._changectx = workingctx
-
-    @propertycache
-    def _changectx(self):
-        return workingctx(self._repo)
+        if ctx:
+            self._changectx = ctx
 
     def __nonzero__(self):
         return True
 
-    def __str__(self):
-        return "%s@%s" % (self.path(), self._changectx)
-
-    def __repr__(self):
-        return "<workingfilectx %s>" % str(self)
-
-    def data(self):
-        return self._repo.wread(self._path)
-    def renamed(self):
-        rp = self._repo.dirstate.copied(self._path)
-        if not rp:
-            return None
-        return rp, self._changectx._parents[0]._manifest.get(rp, nullid)
-
     def parents(self):
         '''return parent filectxs, following copies if necessary'''
         def filenode(ctx, path):
@@ -1209,12 +1233,30 @@
     def children(self):
         return []
 
+class workingfilectx(committablefilectx):
+    """A workingfilectx object makes access to data related to a particular
+       file in the working directory convenient."""
+    def __init__(self, repo, path, filelog=None, workingctx=None):
+        super(workingfilectx, self).__init__(repo, path, filelog, workingctx)
+
+    @propertycache
+    def _changectx(self):
+        return workingctx(self._repo)
+
+    def data(self):
+        return self._repo.wread(self._path)
+    def renamed(self):
+        rp = self._repo.dirstate.copied(self._path)
+        if not rp:
+            return None
+        return rp, self._changectx._parents[0]._manifest.get(rp, nullid)
+
     def size(self):
-        return os.lstat(self._repo.wjoin(self._path)).st_size
+        return self._repo.wvfs.lstat(self._path).st_size
     def date(self):
         t, tz = self._changectx.date()
         try:
-            return (int(os.lstat(self._repo.wjoin(self._path)).st_mtime), tz)
+            return (int(self._repo.wvfs.lstat(self._path).st_mtime), tz)
         except OSError, err:
             if err.errno != errno.ENOENT:
                 raise
--- a/mercurial/demandimport.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/demandimport.py	Sun Oct 20 16:43:11 2013 -0700
@@ -38,24 +38,40 @@
 else:
     _import = _origimport
 
+def _hgextimport(importfunc, name, globals, *args):
+    try:
+        return importfunc(name, globals, *args)
+    except ImportError:
+        if not globals:
+            raise
+        # extensions are loaded with "hgext_" prefix
+        hgextname = 'hgext_%s' % name
+        nameroot = hgextname.split('.', 1)[0]
+        contextroot = globals.get('__name__', '').split('.', 1)[0]
+        if nameroot != contextroot:
+            raise
+        # retry to import with "hgext_" prefix
+        return importfunc(hgextname, globals, *args)
+
 class _demandmod(object):
     """module demand-loader and proxy"""
-    def __init__(self, name, globals, locals):
+    def __init__(self, name, globals, locals, level=-1):
         if '.' in name:
             head, rest = name.split('.', 1)
             after = [rest]
         else:
             head = name
             after = []
-        object.__setattr__(self, "_data", (head, globals, locals, after))
+        object.__setattr__(self, "_data",
+                           (head, globals, locals, after, level))
         object.__setattr__(self, "_module", None)
     def _extend(self, name):
         """add to the list of submodules to load"""
         self._data[3].append(name)
     def _load(self):
         if not self._module:
-            head, globals, locals, after = self._data
-            mod = _origimport(head, globals, locals)
+            head, globals, locals, after, level = self._data
+            mod = _hgextimport(_import, head, globals, locals, None, level)
             # load submodules
             def subload(mod, p):
                 h, t = p, None
@@ -92,7 +108,7 @@
 def _demandimport(name, globals=None, locals=None, fromlist=None, level=-1):
     if not locals or name in ignore or fromlist == ('*',):
         # these cases we can't really delay
-        return _import(name, globals, locals, fromlist, level)
+        return _hgextimport(_import, name, globals, locals, fromlist, level)
     elif not fromlist:
         # import a [as b]
         if '.' in name: # a.b
@@ -105,13 +121,13 @@
                 if isinstance(locals[base], _demandmod):
                     locals[base]._extend(rest)
                 return locals[base]
-        return _demandmod(name, globals, locals)
+        return _demandmod(name, globals, locals, level)
     else:
         if level != -1:
             # from . import b,c,d or from .a import b,c,d
             return _origimport(name, globals, locals, fromlist, level)
         # from a import b,c,d
-        mod = _origimport(name, globals, locals)
+        mod = _hgextimport(_origimport, name, globals, locals)
         # recurse down the module chain
         for comp in name.split('.')[1:]:
             if getattr(mod, comp, nothing) is nothing:
--- a/mercurial/dirstate.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/dirstate.py	Sun Oct 20 16:43:11 2013 -0700
@@ -801,12 +801,9 @@
         mexact = match.exact
         dirignore = self._dirignore
         checkexec = self._checkexec
-        checklink = self._checklink
         copymap = self._copymap
         lastnormaltime = self._lastnormaltime
 
-        lnkkind = stat.S_IFLNK
-
         # We need to do full walks when either
         # - we're listing all clean files, or
         # - match.traversedir does something, because match.traversedir should
@@ -818,7 +815,7 @@
                 if (listignored or mexact(fn)) and dirignore(fn):
                     if listignored:
                         iadd(fn)
-                elif listunknown:
+                else:
                     uadd(fn)
                 continue
 
@@ -827,20 +824,14 @@
             if not st and state in "nma":
                 dadd(fn)
             elif state == 'n':
-                # The "mode & lnkkind != lnkkind or self._checklink"
-                # lines are an expansion of "islink => checklink"
-                # where islink means "is this a link?" and checklink
-                # means "can we check links?".
                 mtime = int(st.st_mtime)
                 if (size >= 0 and
                     ((size != st.st_size and size != st.st_size & _rangemask)
                      or ((mode ^ st.st_mode) & 0100 and checkexec))
-                    and (mode & lnkkind != lnkkind or checklink)
                     or size == -2 # other parent
                     or fn in copymap):
                     madd(fn)
-                elif ((time != mtime and time != mtime & _rangemask)
-                      and (mode & lnkkind != lnkkind or checklink)):
+                elif time != mtime and time != mtime & _rangemask:
                     ladd(fn)
                 elif mtime == lastnormaltime:
                     # fn may have been changed in the same timeslot without
--- a/mercurial/discovery.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/discovery.py	Sun Oct 20 16:43:11 2013 -0700
@@ -269,13 +269,12 @@
     allfuturecommon = set(c.node() for c in repo.set('%ld', outgoing.common))
     allfuturecommon.update(allmissing)
     for branch, heads in sorted(headssum.iteritems()):
-        if heads[0] is None:
-            # Maybe we should abort if we push more that one head
-            # for new branches ?
-            continue
         candidate_newhs = set(heads[1])
         # add unsynced data
-        oldhs = set(heads[0])
+        if heads[0] is None:
+            oldhs = set()
+        else:
+            oldhs = set(heads[0])
         oldhs.update(heads[2])
         candidate_newhs.update(heads[2])
         dhs = None
@@ -310,7 +309,16 @@
             newhs = candidate_newhs
         if [h for h in heads[2] if h not in discardedheads]:
             unsynced = True
-        if len(newhs) > len(oldhs):
+        if heads[0] is None:
+            if 1 < len(newhs):
+                dhs = list(newhs)
+                if error is None:
+                    error = (_("push creates multiple headed new branch '%s'")
+                             % (branch))
+                    hint = _("merge or"
+                             " see \"hg help push\" for details about"
+                             " pushing new heads")
+        elif len(newhs) > len(oldhs):
             # strip updates to existing remote heads from the new heads list
             dhs = sorted(newhs - bookmarkedheads - oldhs)
         if dhs:
@@ -322,11 +330,13 @@
                     error = _("push creates new remote head %s!"
                               ) % short(dhs[0])
                 if heads[2]: # unsynced
-                    hint = _("you should pull and merge or "
-                             "use push -f to force")
+                    hint = _("pull and merge or"
+                             " see \"hg help push\" for details about"
+                             " pushing new heads")
                 else:
-                    hint = _("did you forget to merge? "
-                             "use push -f to force")
+                    hint = _("merge or"
+                             " see \"hg help push\" for details about"
+                             " pushing new heads")
             if branch is not None:
                 repo.ui.note(_("new remote heads on branch '%s'\n") % branch)
             for h in dhs:
--- a/mercurial/dispatch.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/dispatch.py	Sun Oct 20 16:43:11 2013 -0700
@@ -88,11 +88,47 @@
 
     try:
         try:
+            debugger = 'pdb'
+            debugtrace = {
+                'pdb' : pdb.set_trace
+            }
+            debugmortem = {
+                'pdb' : pdb.post_mortem
+            }
+
+            # read --config before doing anything else
+            # (e.g. to change trust settings for reading .hg/hgrc)
+            cfgs = _parseconfig(req.ui, _earlygetopt(['--config'], req.args))
+
+            if req.repo:
+                # copy configs that were passed on the cmdline (--config) to
+                # the repo ui
+                for cfg in cfgs:
+                    req.repo.ui.setconfig(*cfg)
+
+            debugger = ui.config("ui", "debugger")
+            if not debugger:
+                debugger = 'pdb'
+
+            try:
+                debugmod = __import__(debugger)
+            except ImportError:
+                debugmod = pdb
+
+            debugtrace[debugger] = debugmod.set_trace
+            debugmortem[debugger] = debugmod.post_mortem
+
             # enter the debugger before command execution
             if '--debugger' in req.args:
                 ui.warn(_("entering debugger - "
                         "type c to continue starting hg or h for help\n"))
-                pdb.set_trace()
+
+                if (debugger != 'pdb' and
+                    debugtrace[debugger] == debugtrace['pdb']):
+                    ui.warn(_("%s debugger specified "
+                              "but its module was not found\n") % debugger)
+
+                debugtrace[debugger]()
             try:
                 return _dispatch(req)
             finally:
@@ -101,7 +137,7 @@
             # enter the debugger when we hit an exception
             if '--debugger' in req.args:
                 traceback.print_exc()
-                pdb.post_mortem(sys.exc_info()[2])
+                debugmortem[debugger](sys.exc_info()[2])
             ui.traceback()
             raise
 
@@ -619,10 +655,6 @@
     args = req.args
     ui = req.ui
 
-    # read --config before doing anything else
-    # (e.g. to change trust settings for reading .hg/hgrc)
-    cfgs = _parseconfig(ui, _earlygetopt(['--config'], args))
-
     # check for cwd
     cwd = _earlygetopt(['--cwd'], args)
     if cwd:
@@ -699,10 +731,6 @@
     if req.repo:
         uis.add(req.repo.ui)
 
-        # copy configs that were passed on the cmdline (--config) to the repo ui
-        for cfg in cfgs:
-            req.repo.ui.setconfig(*cfg)
-
     if options['verbose'] or options['debug'] or options['quiet']:
         for opt in ('verbose', 'debug', 'quiet'):
             val = str(bool(options[opt]))
--- a/mercurial/extensions.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/extensions.py	Sun Oct 20 16:43:11 2013 -0700
@@ -13,10 +13,18 @@
 _order = []
 _ignore = ['hbisect', 'bookmarks', 'parentrevspec', 'interhg']
 
-def extensions():
+def extensions(ui=None):
+    if ui:
+        def enabled(name):
+            for format in ['%s', 'hgext.%s']:
+                conf = ui.config('extensions', format % name)
+                if conf is not None and not conf.startswith('!'):
+                    return True
+    else:
+        enabled = lambda name: True
     for name in _order:
         module = _extensions[name]
-        if module:
+        if module and enabled(name):
             yield name, module
 
 def find(name):
--- a/mercurial/hg.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/hg.py	Sun Oct 20 16:43:11 2013 -0700
@@ -101,7 +101,7 @@
     """return a repository object for the specified path"""
     obj = _peerlookup(path).instance(ui, path, create)
     ui = getattr(obj, "ui", ui)
-    for name, module in extensions.extensions():
+    for name, module in extensions.extensions(ui):
         hook = getattr(module, 'reposetup', None)
         if hook:
             hook(ui, obj)
--- a/mercurial/hgweb/hgweb_mod.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/hgweb/hgweb_mod.py	Sun Oct 20 16:43:11 2013 -0700
@@ -331,12 +331,6 @@
 
         # some functions for the templater
 
-        def header(**map):
-            yield tmpl('header', encoding=encoding.encoding, **map)
-
-        def footer(**map):
-            yield tmpl("footer", **map)
-
         def motd(**map):
             yield self.config("web", "motd", "")
 
@@ -373,8 +367,7 @@
                                              "staticurl": staticurl,
                                              "urlbase": urlbase,
                                              "repo": self.reponame,
-                                             "header": header,
-                                             "footer": footer,
+                                             "encoding": encoding.encoding,
                                              "motd": motd,
                                              "sessionvars": sessionvars,
                                              "pathdef": makebreadcrumb(req.url),
--- a/mercurial/hgweb/hgwebdir_mod.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/hgweb/hgwebdir_mod.py	Sun Oct 20 16:43:11 2013 -0700
@@ -408,12 +408,6 @@
 
     def templater(self, req):
 
-        def header(**map):
-            yield tmpl('header', encoding=encoding.encoding, **map)
-
-        def footer(**map):
-            yield tmpl("footer", **map)
-
         def motd(**map):
             if self.motd is not None:
                 yield self.motd
@@ -448,8 +442,7 @@
             staticurl += '/'
 
         tmpl = templater.templater(mapfile,
-                                   defaults={"header": header,
-                                             "footer": footer,
+                                   defaults={"encoding": encoding.encoding,
                                              "motd": motd,
                                              "url": url,
                                              "logourl": logourl,
--- a/mercurial/hgweb/webcommands.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/hgweb/webcommands.py	Sun Oct 20 16:43:11 2013 -0700
@@ -9,13 +9,15 @@
 import webutil
 from mercurial import error, encoding, archival, templater, templatefilters
 from mercurial.node import short, hex, nullid
-from mercurial.util import binary
+from mercurial import util
 from common import paritygen, staticfile, get_contact, ErrorResponse
 from common import HTTP_OK, HTTP_FORBIDDEN, HTTP_NOT_FOUND
 from mercurial import graphmod, patch
 from mercurial import help as helpmod
 from mercurial import scmutil
 from mercurial.i18n import _
+from mercurial.error import ParseError, RepoLookupError, Abort
+from mercurial import revset
 
 # __all__ is populated with the allowed commands. Be sure to add to it if
 # you're adding a new command, or the new command won't work.
@@ -57,7 +59,7 @@
     if guessmime:
         mt = mimetypes.guess_type(path)[0]
         if mt is None:
-            mt = binary(text) and 'application/binary' or 'text/plain'
+            mt = util.binary(text) and 'application/binary' or 'text/plain'
     if mt.startswith('text/'):
         mt += '; charset="%s"' % encoding.encoding
 
@@ -69,7 +71,7 @@
     text = fctx.data()
     parity = paritygen(web.stripecount)
 
-    if binary(text):
+    if util.binary(text):
         mt = mimetypes.guess_type(f)[0] or 'application/octet-stream'
         text = '(binary:%s)' % mt
 
@@ -109,9 +111,14 @@
             raise inst
 
 def _search(web, req, tmpl):
+    MODE_REVISION = 'rev'
+    MODE_KEYWORD = 'keyword'
+    MODE_REVSET = 'revset'
 
-    def changelist(**map):
-        count = 0
+    def revsearch(ctx):
+        yield ctx
+
+    def keywordsearch(query):
         lower = encoding.lower
         qw = lower(query).split()
 
@@ -137,6 +144,62 @@
             if miss:
                 continue
 
+            yield ctx
+
+    def revsetsearch(revs):
+        for r in revs:
+            yield web.repo[r]
+
+    searchfuncs = {
+        MODE_REVISION: (revsearch, _('exact revision search')),
+        MODE_KEYWORD: (keywordsearch, _('literal keyword search')),
+        MODE_REVSET: (revsetsearch, _('revset expression search')),
+    }
+
+    def getsearchmode(query):
+        try:
+            ctx = web.repo[query]
+        except (error.RepoError, error.LookupError):
+            # query is not an exact revision pointer, need to
+            # decide if it's a revset expession or keywords
+            pass
+        else:
+            return MODE_REVISION, ctx
+
+        revdef = 'reverse(%s)' % query
+        try:
+            tree, pos = revset.parse(revdef)
+        except ParseError:
+            # can't parse to a revset tree
+            return MODE_KEYWORD, query
+
+        if revset.depth(tree) <= 2:
+            # no revset syntax used
+            return MODE_KEYWORD, query
+
+        if util.any((token, (value or '')[:3]) == ('string', 're:')
+                    for token, value, pos in revset.tokenize(revdef)):
+            return MODE_KEYWORD, query
+
+        funcsused = revset.funcsused(tree)
+        if not funcsused.issubset(revset.safesymbols):
+            return MODE_KEYWORD, query
+
+        mfunc = revset.match(web.repo.ui, revdef)
+        try:
+            revs = mfunc(web.repo, list(web.repo))
+            return MODE_REVSET, revs
+            # ParseError: wrongly placed tokens, wrongs arguments, etc
+            # RepoLookupError: no such revision, e.g. in 'revision:'
+            # Abort: bookmark/tag not exists
+            # LookupError: ambiguous identifier, e.g. in '(bc)' on a large repo
+        except (ParseError, RepoLookupError, Abort, LookupError):
+            return MODE_KEYWORD, query
+
+    def changelist(**map):
+        count = 0
+
+        for ctx in searchfunc[0](funcarg):
             count += 1
             n = ctx.node()
             showtags = webutil.showtag(web.repo, tmpl, 'changelogtag', n)
@@ -176,35 +239,45 @@
     morevars['revcount'] = revcount * 2
     morevars['rev'] = query
 
+    mode, funcarg = getsearchmode(query)
+
+    if 'forcekw' in req.form:
+        showforcekw = ''
+        showunforcekw = searchfuncs[mode][1]
+        mode = MODE_KEYWORD
+        funcarg = query
+    else:
+        if mode != MODE_KEYWORD:
+            showforcekw = searchfuncs[MODE_KEYWORD][1]
+        else:
+            showforcekw = ''
+        showunforcekw = ''
+
+    searchfunc = searchfuncs[mode]
+
     tip = web.repo['tip']
     parity = paritygen(web.stripecount)
 
     return tmpl('search', query=query, node=tip.hex(),
                 entries=changelist, archives=web.archivelist("tip"),
-                morevars=morevars, lessvars=lessvars)
+                morevars=morevars, lessvars=lessvars,
+                modedesc=searchfunc[1],
+                showforcekw=showforcekw, showunforcekw=showunforcekw)
 
 def changelog(web, req, tmpl, shortlog=False):
 
     query = ''
     if 'node' in req.form:
         ctx = webutil.changectx(web.repo, req)
+    elif 'rev' in req.form:
+        return _search(web, req, tmpl)
     else:
-        if 'rev' in req.form:
-            query = req.form['rev'][0]
-            hi = query
-        else:
-            hi = 'tip'
-        try:
-            ctx = web.repo[hi]
-        except (error.RepoError, error.LookupError):
-            return _search(web, req, tmpl) # XXX redirect to 404 page?
+        ctx = web.repo['tip']
 
-    def changelist(latestonly, **map):
+    def changelist():
         revs = []
         if pos != -1:
             revs = web.repo.changelog.revs(pos, 0)
-        if latestonly:
-            revs = (revs.next(),)
         curcount = 0
         for i in revs:
             ctx = web.repo[i]
@@ -213,7 +286,7 @@
             files = webutil.listfilediffs(tmpl, ctx.files(), n, web.maxfiles)
 
             curcount += 1
-            if curcount > revcount:
+            if curcount > revcount + 1:
                 break
             yield {"parity": parity.next(),
                    "author": ctx.user(),
@@ -249,15 +322,23 @@
 
     changenav = webutil.revnav(web.repo).gen(pos, revcount, count)
 
+    entries = list(changelist())
+    latestentry = entries[:1]
+    if len(entries) > revcount:
+        nextentry = entries[-1:]
+        entries = entries[:-1]
+    else:
+        nextentry = []
+
     return tmpl(shortlog and 'shortlog' or 'changelog', changenav=changenav,
                 node=ctx.hex(), rev=pos, changesets=count,
-                entries=lambda **x: changelist(latestonly=False, **x),
-                latestentry=lambda **x: changelist(latestonly=True, **x),
+                entries=entries,
+                latestentry=latestentry, nextentry=nextentry,
                 archives=web.archivelist("tip"), revcount=revcount,
                 morevars=morevars, lessvars=lessvars, query=query)
 
 def shortlog(web, req, tmpl):
-    return changelog(web, req, tmpl, shortlog = True)
+    return changelog(web, req, tmpl, shortlog=True)
 
 def changeset(web, req, tmpl):
     ctx = webutil.changectx(web.repo, req)
@@ -617,7 +698,7 @@
         context = parsecontext(web.config('web', 'comparisoncontext', '5'))
 
     def filelines(f):
-        if binary(f.data()):
+        if util.binary(f.data()):
             mt = mimetypes.guess_type(f.path())[0]
             if not mt:
                 mt = 'application/octet-stream'
@@ -675,7 +756,7 @@
 
     def annotate(**map):
         last = None
-        if binary(fctx.data()):
+        if util.binary(fctx.data()):
             mt = (mimetypes.guess_type(fctx.path())[0]
                   or 'application/octet-stream')
             lines = enumerate([((fctx.filectx(fctx.filerev()), 1),
--- a/mercurial/httpclient/__init__.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/httpclient/__init__.py	Sun Oct 20 16:43:11 2013 -0700
@@ -292,7 +292,7 @@
     def __init__(self, host, port=None, use_ssl=None, ssl_validator=None,
                  timeout=TIMEOUT_DEFAULT,
                  continue_timeout=TIMEOUT_ASSUME_CONTINUE,
-                 proxy_hostport=None, **ssl_opts):
+                 proxy_hostport=None, ssl_wrap_socket=None, **ssl_opts):
         """Create a new HTTPConnection.
 
         Args:
@@ -307,12 +307,23 @@
                    "100 Continue" response. Default is TIMEOUT_ASSUME_CONTINUE.
           proxy_hostport: Optional. Tuple of (host, port) to use as an http
                        proxy for the connection. Default is to not use a proxy.
+          ssl_wrap_socket: Optional function to use for wrapping
+            sockets. If unspecified, the one from the ssl module will
+            be used if available, or something that's compatible with
+            it if on a Python older than 2.6.
+
+        Any extra keyword arguments to this function will be provided
+        to the ssl_wrap_socket method. If no ssl
         """
         if port is None and host.count(':') == 1 or ']:' in host:
             host, port = host.rsplit(':', 1)
             port = int(port)
             if '[' in host:
                 host = host[1:-1]
+        if ssl_wrap_socket is not None:
+            self._ssl_wrap_socket = ssl_wrap_socket
+        else:
+            self._ssl_wrap_socket = socketutil.wrap_socket
         if use_ssl is None and port is None:
             use_ssl = False
             port = 80
@@ -387,7 +398,7 @@
             sock.setblocking(1)
             logger.debug('wrapping socket for ssl with options %r',
                          self.ssl_opts)
-            sock = socketutil.wrap_socket(sock, **self.ssl_opts)
+            sock = self._ssl_wrap_socket(sock, **self.ssl_opts)
             if self._ssl_validator:
                 self._ssl_validator(sock)
         sock.setblocking(0)
@@ -495,6 +506,10 @@
             else:
                 raise BadRequestData('body has no __len__() nor read()')
 
+        # If we're reusing the underlying socket, there are some
+        # conditions where we'll want to retry, so make a note of the
+        # state of self.sock
+        fresh_socket = self.sock is None
         self._connect()
         outgoing_headers = self._buildheaders(
             method, path, hdrs, self.http_version)
@@ -640,6 +655,26 @@
         # the whole request
         if response is None:
             response = self.response_class(self.sock, self.timeout, method)
+            if not fresh_socket:
+                if not response._select():
+                    # This means the response failed to get any response
+                    # data at all, and in all probability the socket was
+                    # closed before the server even saw our request. Try
+                    # the request again on a fresh socket.
+                    logging.debug('response._select() failed during request().'
+                                  ' Assuming request needs to be retried.')
+                    self.sock = None
+                    # Call this method explicitly to re-try the
+                    # request. We don't use self.request() because
+                    # some tools (notably Mercurial) expect to be able
+                    # to subclass and redefine request(), and they
+                    # don't have the same argspec as we do.
+                    #
+                    # TODO restructure sending of requests to avoid
+                    # this recursion
+                    return HTTPConnection.request(
+                        self, method, path, body=body, headers=headers,
+                        expect_continue=expect_continue)
         data_left = bool(outgoing_headers or body)
         if data_left:
             logger.info('stopped sending request early, '
--- a/mercurial/httpconnection.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/httpconnection.py	Sun Oct 20 16:43:11 2013 -0700
@@ -275,14 +275,13 @@
             if '[' in host:
                 host = host[1:-1]
 
-        if keyfile:
-            kwargs['keyfile'] = keyfile
-        if certfile:
-            kwargs['certfile'] = certfile
+        kwargs['keyfile'] = keyfile
+        kwargs['certfile'] = certfile
 
         kwargs.update(sslutil.sslkwargs(self.ui, host))
 
         con = HTTPConnection(host, port, use_ssl=True,
+                             ssl_wrap_socket=sslutil.ssl_wrap_socket,
                              ssl_validator=sslutil.validator(self.ui, host),
                              **kwargs)
         return con
--- a/mercurial/keepalive.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/keepalive.py	Sun Oct 20 16:43:11 2013 -0700
@@ -499,7 +499,7 @@
         data, self._rbuf = self._rbuf[:i], self._rbuf[i:]
         return data
 
-    def readlines(self, sizehint = 0):
+    def readlines(self, sizehint=0):
         total = 0
         list = []
         while True:
--- a/mercurial/localrepo.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/localrepo.py	Sun Oct 20 16:43:11 2013 -0700
@@ -147,12 +147,16 @@
 class localrepository(object):
 
     supportedformats = set(('revlogv1', 'generaldelta'))
-    supported = supportedformats | set(('store', 'fncache', 'shared',
-                                        'dotencode'))
+    _basesupported = supportedformats | set(('store', 'fncache', 'shared',
+                                             'dotencode'))
     openerreqs = set(('revlogv1', 'generaldelta'))
     requirements = ['revlogv1']
     filtername = None
 
+    # a list of (ui, featureset) functions.
+    # only functions defined in module of enabled extensions are invoked
+    featuresetupfuncs = set()
+
     def _baserequirements(self, create):
         return self.requirements[:]
 
@@ -177,6 +181,16 @@
         except IOError:
             pass
 
+        if self.featuresetupfuncs:
+            self.supported = set(self._basesupported) # use private copy
+            extmods = set(m.__name__ for n, m
+                          in extensions.extensions(self.ui))
+            for setupfunc in self.featuresetupfuncs:
+                if setupfunc.__module__ in extmods:
+                    setupfunc(self.ui, self.supported)
+        else:
+            self.supported = self._basesupported
+
         if not self.vfs.isdir():
             if create:
                 if not self.wvfs.exists():
@@ -804,7 +818,7 @@
     def wwritedata(self, filename, data):
         return self._filter(self._decodefilterpats, filename, data)
 
-    def transaction(self, desc):
+    def transaction(self, desc, report=None):
         tr = self._transref and self._transref() or None
         if tr and tr.running():
             return tr.nest()
@@ -816,8 +830,8 @@
 
         self._writejournal(desc)
         renames = [(vfs, x, undoname(x)) for vfs, x in self._journalfiles()]
-
-        tr = transaction.transaction(self.ui.warn, self.sopener,
+        rp = report and report or self.ui.warn
+        tr = transaction.transaction(rp, self.sopener,
                                      self.sjoin("journal"),
                                      aftertrans(renames),
                                      self.store.createmode)
@@ -1460,14 +1474,8 @@
                     del mf[fn]
             return mf
 
-        if isinstance(node1, context.changectx):
-            ctx1 = node1
-        else:
-            ctx1 = self[node1]
-        if isinstance(node2, context.changectx):
-            ctx2 = node2
-        else:
-            ctx2 = self[node2]
+        ctx1 = self[node1]
+        ctx2 = self[node2]
 
         working = ctx2.rev() is None
         parentworking = working and ctx1 == self['.']
@@ -1564,7 +1572,7 @@
             for f in modified:
                 if ctx2.flags(f) == 'l':
                     d = ctx2[f].data()
-                    if len(d) >= 1024 or '\n' in d or util.binary(d):
+                    if d == '' or len(d) >= 1024 or '\n' in d or util.binary(d):
                         self.ui.debug('ignoring suspect symlink placeholder'
                                       ' "%s"\n' % f)
                         continue
@@ -1656,6 +1664,14 @@
         return r
 
     def pull(self, remote, heads=None, force=False):
+        if remote.local():
+            missing = set(remote.requirements) - self.supported
+            if missing:
+                msg = _("required features are not"
+                        " supported in the destination:"
+                        " %s") % (', '.join(sorted(missing)))
+                raise util.Abort(msg)
+
         # don't open transaction for nothing or you break future useful
         # rollback call
         tr = None
@@ -1756,6 +1772,14 @@
             we have outgoing changesets but refused to push
           - other values as described by addchangegroup()
         '''
+        if remote.local():
+            missing = set(self.requirements) - remote.local().supported
+            if missing:
+                msg = _("required features are not"
+                        " supported in the destination:"
+                        " %s") % (', '.join(sorted(missing)))
+                raise util.Abort(msg)
+
         # there are two ways to push to remote repo:
         #
         # addchangegroup assumes local user can lock remote
@@ -2210,6 +2234,12 @@
                     # In other case we can safely update cache on disk.
                     branchmap.updatecache(self.filtered('served'))
                 def runhooks():
+                    # These hooks run when the lock releases, not when the
+                    # transaction closes. So it's possible for the changelog
+                    # to have changed since we last saw it.
+                    if clstart >= len(self):
+                        return
+
                     # forcefully update the on-disk branch cache
                     self.ui.debug("updating the branch cache\n")
                     self.hook("changegroup", node=hex(cl.node(clstart)),
--- a/mercurial/lock.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/lock.py	Sun Oct 20 16:43:11 2013 -0700
@@ -100,7 +100,7 @@
         """
         try:
             locker = util.readlock(self.f)
-        except OSError, why:
+        except (OSError, IOError), why:
             if why.errno == errno.ENOENT:
                 return None
             raise
--- a/mercurial/mail.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/mail.py	Sun Oct 20 16:43:11 2013 -0700
@@ -8,7 +8,11 @@
 from i18n import _
 import util, encoding, sslutil
 import os, smtplib, socket, quopri, time, sys
-import email.Header, email.MIMEText, email.Utils
+import email
+# On python2.4 you have to import these by name or they fail to
+# load. This was not a problem on Python 2.7.
+import email.Header
+import email.MIMEText
 
 _oldheaderinit = email.Header.Header.__init__
 def _unifiedheaderinit(self, *args, **kw):
--- a/mercurial/match.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/match.py	Sun Oct 20 16:43:11 2013 -0700
@@ -140,7 +140,7 @@
 
 class exact(match):
     def __init__(self, root, cwd, files):
-        match.__init__(self, root, cwd, files, exact = True)
+        match.__init__(self, root, cwd, files, exact=True)
 
 class always(match):
     def __init__(self, root, cwd):
--- a/mercurial/merge.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/merge.py	Sun Oct 20 16:43:11 2013 -0700
@@ -656,19 +656,21 @@
     -c  -C  dirty  rev  |  linear   same  cross
      n   n    n     n   |    ok     (1)     x
      n   n    n     y   |    ok     ok     ok
-     n   n    y     *   |   merge   (2)    (2)
+     n   n    y     n   |   merge   (2)    (2)
+     n   n    y     y   |   merge   (3)    (3)
      n   y    *     *   |    ---  discard  ---
-     y   n    y     *   |    ---    (3)    ---
+     y   n    y     *   |    ---    (4)    ---
      y   n    n     *   |    ---    ok     ---
-     y   y    *     *   |    ---    (4)    ---
+     y   y    *     *   |    ---    (5)    ---
 
     x = can't happen
     * = don't-care
-    1 = abort: crosses branches (use 'hg merge' or 'hg update -c')
-    2 = abort: crosses branches (use 'hg merge' to merge or
-                 use 'hg update -C' to discard changes)
-    3 = abort: uncommitted local changes
-    4 = incompatible options (checked in commands.py)
+    1 = abort: not a linear update (merge or update --check to force update)
+    2 = abort: uncommitted changes (commit and merge, or update --clean to
+                 discard changes)
+    3 = abort: uncommitted changes (commit or update --clean to discard changes)
+    4 = abort: uncommitted changes (checked in commands.py)
+    5 = incompatible options (checked in commands.py)
 
     Return the same tuple as applyupdates().
     """
@@ -709,14 +711,20 @@
                                      hint=_("use 'hg update' "
                                             "or check 'hg heads'"))
             if not force and (wc.files() or wc.deleted()):
-                raise util.Abort(_("outstanding uncommitted changes"),
+                raise util.Abort(_("uncommitted changes"),
                                  hint=_("use 'hg status' to list changes"))
             for s in sorted(wc.substate):
                 if wc.sub(s).dirty():
-                    raise util.Abort(_("outstanding uncommitted changes in "
+                    raise util.Abort(_("uncommitted changes in "
                                        "subrepository '%s'") % s)
 
         elif not overwrite:
+            if p1 == p2: # no-op update
+                # call the hooks and exit early
+                repo.hook('preupdate', throw=True, parent1=xp2, parent2='')
+                repo.hook('update', parent1=xp2, parent2='', error=0)
+                return 0, 0, 0, 0
+
             if pa not in (p1, p2):  # nolinear
                 dirty = wc.dirty(missing=True)
                 if dirty or onode is None:
@@ -727,13 +735,18 @@
                     if repo[node].node() in foreground:
                         pa = p1  # allow updating to successors
                     elif dirty:
-                        msg = _("crosses branches (merge branches or use"
-                                " --clean to discard changes)")
-                        raise util.Abort(msg)
+                        msg = _("uncommitted changes")
+                        if onode is None:
+                            hint = _("commit and merge, or update --clean to"
+                                     " discard changes")
+                        else:
+                            hint = _("commit or update --clean to discard"
+                                     " changes")
+                        raise util.Abort(msg, hint=hint)
                     else:  # node is none
-                        msg = _("crosses branches (merge branches or update"
-                                " --check to force update)")
-                        raise util.Abort(msg)
+                        msg = _("not a linear update")
+                        hint = _("merge or update --check to force update")
+                        raise util.Abort(msg, hint=hint)
                 else:
                     # Allow jumping branches if clean and specific rev given
                     pa = p1
--- a/mercurial/obsolete.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/obsolete.py	Sun Oct 20 16:43:11 2013 -0700
@@ -371,7 +371,7 @@
         lock.release()
 
 def syncpush(repo, remote):
-    """utility function to push bookmark to a remote
+    """utility function to push obsolete markers to a remote
 
     Exist mostly to allow overridding for experimentation purpose"""
     if (_enabled and repo.obsstore and
@@ -387,7 +387,7 @@
             repo.ui.warn(msg)
 
 def syncpull(repo, remote, gettransaction):
-    """utility function to pull bookmark to a remote
+    """utility function to pull obsolete markers from a remote
 
     The `gettransaction` is function that return the pull transaction, creating
     one if necessary. We return the transaction to inform the calling code that
--- a/mercurial/parsers.c	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/parsers.c	Sun Oct 20 16:43:11 2013 -0700
@@ -14,16 +14,32 @@
 
 #include "util.h"
 
+static int8_t hextable[256] = {
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1, /* 0-9 */
+	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* A-F */
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* a-f */
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+};
+
 static inline int hexdigit(const char *p, Py_ssize_t off)
 {
-	char c = p[off];
+	int8_t val = hextable[(unsigned char)p[off]];
 
-	if (c >= '0' && c <= '9')
-		return c - '0';
-	if (c >= 'a' && c <= 'f')
-		return c - 'a' + 10;
-	if (c >= 'A' && c <= 'F')
-		return c - 'A' + 10;
+	if (val >= 0) {
+		return val;
+	}
 
 	PyErr_SetString(PyExc_ValueError, "input contains non-hex character");
 	return 0;
@@ -61,7 +77,7 @@
 static PyObject *parse_manifest(PyObject *self, PyObject *args)
 {
 	PyObject *mfdict, *fdict;
-	char *str, *cur, *start, *zero;
+	char *str, *start, *end;
 	int len;
 
 	if (!PyArg_ParseTuple(args, "O!O!s#:parse_manifest",
@@ -70,30 +86,34 @@
 			      &str, &len))
 		goto quit;
 
-	for (start = cur = str, zero = NULL; cur < str + len; cur++) {
+	start = str;
+	end = str + len;
+	while (start < end) {
 		PyObject *file = NULL, *node = NULL;
 		PyObject *flags = NULL;
+		char *zero = NULL, *newline = NULL;
 		ptrdiff_t nlen;
 
-		if (!*cur) {
-			zero = cur;
-			continue;
-		}
-		else if (*cur != '\n')
-			continue;
-
+		zero = memchr(start, '\0', end - start);
 		if (!zero) {
 			PyErr_SetString(PyExc_ValueError,
 					"manifest entry has no separator");
 			goto quit;
 		}
 
+		newline = memchr(zero + 1, '\n', end - (zero + 1));
+		if (!newline) {
+			PyErr_SetString(PyExc_ValueError,
+					"manifest contains trailing garbage");
+			goto quit;
+		}
+
 		file = PyBytes_FromStringAndSize(start, zero - start);
 
 		if (!file)
 			goto bail;
 
-		nlen = cur - zero - 1;
+		nlen = newline - zero - 1;
 
 		node = unhexlify(zero + 1, nlen > 40 ? 40 : (int)nlen);
 		if (!node)
@@ -112,8 +132,7 @@
 		if (PyDict_SetItem(mfdict, file, node) == -1)
 			goto bail;
 
-		start = cur + 1;
-		zero = NULL;
+		start = newline + 1;
 
 		Py_XDECREF(flags);
 		Py_XDECREF(node);
@@ -126,12 +145,6 @@
 		goto quit;
 	}
 
-	if (len > 0 && *(cur - 1) != '\n') {
-		PyErr_SetString(PyExc_ValueError,
-				"manifest contains trailing garbage");
-		goto quit;
-	}
-
 	Py_INCREF(Py_None);
 	return Py_None;
 quit:
@@ -142,8 +155,8 @@
 {
 	PyObject *dmap, *cmap, *parents = NULL, *ret = NULL;
 	PyObject *fname = NULL, *cname = NULL, *entry = NULL;
-	char *str, *cur, *end, *cpos;
-	int state, mode, size, mtime;
+	char state, *str, *cur, *end, *cpos;
+	int mode, size, mtime;
 	unsigned int flen;
 	int len;
 
@@ -330,7 +343,7 @@
 			 * this. */
 			if (PyDict_SetItem(map, k, dirstate_unset) == -1)
 				goto bail;
-			mode = 0, size = -1, mtime = -1;
+			mtime = -1;
 		}
 		putbe32(mode, p);
 		putbe32(size, p + 4);
@@ -524,11 +537,12 @@
 			      uncomp_len, base_rev, link_rev,
 			      parent_1, parent_2, c_node_id, 20);
 
-	if (entry)
+	if (entry) {
 		PyObject_GC_UnTrack(entry);
+		Py_INCREF(entry);
+	}
 
 	self->cache[pos] = entry;
-	Py_INCREF(entry);
 
 	return entry;
 }
@@ -1195,14 +1209,19 @@
 	long sp;
 	bitmask *seen;
 
+	if (gca == NULL)
+		return PyErr_NoMemory();
+
 	for (i = 0; i < revcount; i++) {
 		if (revs[i] > maxrev)
 			maxrev = revs[i];
 	}
 
 	seen = calloc(sizeof(*seen), maxrev + 1);
-	if (seen == NULL)
+	if (seen == NULL) {
+		Py_DECREF(gca);
 		return PyErr_NoMemory();
+	}
 
 	for (i = 0; i < revcount; i++)
 		seen[revs[i]] = 1ull << i;
--- a/mercurial/patch.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/patch.py	Sun Oct 20 16:43:11 2013 -0700
@@ -6,8 +6,12 @@
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 
-import cStringIO, email.Parser, os, errno, re, posixpath
+import cStringIO, email, os, errno, re, posixpath
 import tempfile, zlib, shutil
+# On python2.4 you have to import these by name or they fail to
+# load. This was not a problem on Python 2.7.
+import email.Generator
+import email.Parser
 
 from i18n import _
 from node import hex, short
--- a/mercurial/pure/parsers.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/pure/parsers.py	Sun Oct 20 16:43:11 2013 -0700
@@ -100,11 +100,11 @@
             # 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
+            # within the same second. Invalidate the file's mtime 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'
+            # contents of the file if the size is the same. This prevents
+            # mistakenly treating such files as clean.
+            e = (e[0], e[1], e[2], -1)
             dmap[f] = e
 
         if f in copymap:
--- a/mercurial/revlog.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/revlog.py	Sun Oct 20 16:43:11 2013 -0700
@@ -14,7 +14,7 @@
 # import stuff from node for others to import from revlog
 from node import bin, hex, nullid, nullrev
 from i18n import _
-import ancestor, mdiff, parsers, error, util
+import ancestor, mdiff, parsers, error, util, templatefilters
 import struct, zlib, errno
 
 _pack = struct.pack
@@ -845,16 +845,43 @@
 
     def _chunkraw(self, startrev, endrev):
         start = self.start(startrev)
-        length = self.end(endrev) - start
+        end = self.end(endrev)
         if self._inline:
             start += (startrev + 1) * self._io.size
+            end += (endrev + 1) * self._io.size
+        length = end - start
         return self._getchunk(start, length)
 
     def _chunk(self, rev):
         return decompress(self._chunkraw(rev, rev))
 
-    def _chunkbase(self, rev):
-        return self._chunk(rev)
+    def _chunks(self, revs):
+        '''faster version of [self._chunk(rev) for rev in revs]
+
+        Assumes that revs is in ascending order.'''
+        if not revs:
+            return []
+        start = self.start
+        length = self.length
+        inline = self._inline
+        iosize = self._io.size
+        buffer = util.buffer
+
+        l = []
+        ladd = l.append
+
+        # preload the cache
+        self._chunkraw(revs[0], revs[-1])
+        offset, data = self._chunkcache
+
+        for rev in revs:
+            chunkstart = start(rev)
+            if inline:
+                chunkstart += (rev + 1) * iosize
+            chunklength = length(rev)
+            ladd(decompress(buffer(data, chunkstart - offset, chunklength)))
+
+        return l
 
     def _chunkclear(self):
         self._chunkcache = (0, '')
@@ -919,21 +946,22 @@
             else:
                 iterrev -= 1
             e = index[iterrev]
-        chain.reverse()
-        base = iterrev
 
         if iterrev == cachedrev:
             # cache hit
             text = self._cache[2]
+        else:
+            chain.append(iterrev)
+        chain.reverse()
 
         # drop cache to save memory
         self._cache = None
 
-        self._chunkraw(base, rev)
+        bins = self._chunks(chain)
         if text is None:
-            text = str(self._chunkbase(base))
+            text = str(bins[0])
+            bins = bins[1:]
 
-        bins = [self._chunk(r) for r in chain]
         text = mdiff.patches(text, bins)
 
         text = self._checkhash(text, node, rev)
@@ -943,10 +971,16 @@
 
     def _checkhash(self, text, node, rev):
         p1, p2 = self.parents(node)
+        self.checkhash(text, p1, p2, node, rev)
+        return text
+
+    def checkhash(self, text, p1, p2, node, rev=None):
         if node != hash(text, p1, p2):
-            raise RevlogError(_("integrity check failed on %s:%d")
-                              % (self.indexfile, rev))
-        return text
+            revornode = rev
+            if revornode is None:
+                revornode = templatefilters.short(hex(node))
+            raise RevlogError(_("integrity check failed on %s:%s")
+                % (self.indexfile, revornode))
 
     def checkinlinesize(self, tr, fp=None):
         if not self._inline or (self.start(-2) + self.length(-2)) < _maxinline:
@@ -987,7 +1021,8 @@
         tr.replace(self.indexfile, trindex * self._io.size)
         self._chunkclear()
 
-    def addrevision(self, text, transaction, link, p1, p2, cachedelta=None):
+    def addrevision(self, text, transaction, link, p1, p2, cachedelta=None,
+                    node=None):
         """add a revision to the log
 
         text - the revision data to add
@@ -995,11 +1030,14 @@
         link - the linkrev data to add
         p1, p2 - the parent nodeids of the revision
         cachedelta - an optional precomputed delta
+        node - nodeid of revision; typically node is not specified, and it is
+            computed by default as hash(text, p1, p2), however subclasses might
+            use different hashing method (and override checkhash() in such case)
         """
         if link == nullrev:
             raise RevlogError(_("attempted to add linkrev -1 to %s")
                               % self.indexfile)
-        node = hash(text, p1, p2)
+        node = node or hash(text, p1, p2)
         if node in self.nodemap:
             return node
 
@@ -1063,9 +1101,7 @@
             ifh.flush()
             basetext = self.revision(self.node(cachedelta[0]))
             btext[0] = mdiff.patch(basetext, cachedelta[1])
-            chk = hash(btext[0], p1, p2)
-            if chk != node:
-                raise RevlogError(_("consistency error in delta"))
+            self.checkhash(btext[0], p1, p2, node)
             return btext[0]
 
         def builddelta(rev):
--- a/mercurial/revset.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/revset.py	Sun Oct 20 16:43:11 2013 -0700
@@ -1599,6 +1599,75 @@
     "_list": _list,
 }
 
+# symbols which can't be used for a DoS attack for any given input
+# (e.g. those which accept regexes as plain strings shouldn't be included)
+# functions that just return a lot of changesets (like all) don't count here
+safesymbols = set([
+    "adds",
+    "all",
+    "ancestor",
+    "ancestors",
+    "_firstancestors",
+    "author",
+    "bisect",
+    "bisected",
+    "bookmark",
+    "branch",
+    "branchpoint",
+    "bumped",
+    "bundle",
+    "children",
+    "closed",
+    "converted",
+    "date",
+    "desc",
+    "descendants",
+    "_firstdescendants",
+    "destination",
+    "divergent",
+    "draft",
+    "extinct",
+    "extra",
+    "file",
+    "filelog",
+    "first",
+    "follow",
+    "_followfirst",
+    "head",
+    "heads",
+    "hidden",
+    "id",
+    "keyword",
+    "last",
+    "limit",
+    "_matchfiles",
+    "max",
+    "merge",
+    "min",
+    "modifies",
+    "obsolete",
+    "origin",
+    "outgoing",
+    "p1",
+    "p2",
+    "parents",
+    "present",
+    "public",
+    "remote",
+    "removes",
+    "rev",
+    "reverse",
+    "roots",
+    "sort",
+    "secret",
+    "matching",
+    "tag",
+    "tagged",
+    "user",
+    "unstable",
+    "_list",
+])
+
 methods = {
     "range": rangeset,
     "dagrange": dagrange,
@@ -1935,5 +2004,22 @@
     output = '\n'.join(('  '*l + s) for l, s in lines)
     return output
 
+def depth(tree):
+    if isinstance(tree, tuple):
+        return max(map(depth, tree)) + 1
+    else:
+        return 0
+
+def funcsused(tree):
+    if not isinstance(tree, tuple) or tree[0] in ('string', 'symbol'):
+        return set()
+    else:
+        funcs = set()
+        for s in tree[1:]:
+            funcs |= funcsused(s)
+        if tree[0] == 'func':
+            funcs.add(tree[1][1])
+        return funcs
+
 # tell hggettext to extract docstrings from these functions:
 i18nfunctions = symbols.values()
--- a/mercurial/scmutil.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/scmutil.py	Sun Oct 20 16:43:11 2013 -0700
@@ -217,6 +217,10 @@
                 raise
         return ""
 
+    def open(self, path, mode="r", text=False, atomictemp=False):
+        self.open = self.__call__
+        return self.__call__(path, mode, text, atomictemp)
+
     def read(self, path):
         fp = self(path, 'rb')
         try:
@@ -241,12 +245,18 @@
     def exists(self, path=None):
         return os.path.exists(self.join(path))
 
+    def fstat(self, fp):
+        return util.fstat(fp)
+
     def isdir(self, path=None):
         return os.path.isdir(self.join(path))
 
     def islink(self, path=None):
         return os.path.islink(self.join(path))
 
+    def lstat(self, path=None):
+        return os.lstat(self.join(path))
+
     def makedir(self, path=None, notindexed=True):
         return util.makedir(self.join(path), notindexed)
 
@@ -271,6 +281,12 @@
     def stat(self, path=None):
         return os.stat(self.join(path))
 
+    def unlink(self, path=None):
+        return util.unlink(self.join(path))
+
+    def utime(self, path=None, t=None):
+        return os.utime(self.join(path), t)
+
 class vfs(abstractvfs):
     '''Operate files relative to a base directory
 
@@ -755,7 +771,8 @@
 
     ctx = repo[None]
     dirstate = repo.dirstate
-    walkresults = dirstate.walk(matcher, sorted(ctx.substate), True, False)
+    walkresults = dirstate.walk(matcher, sorted(ctx.substate), True, False,
+                                full=False)
     for abs, st in walkresults.iteritems():
         dstate = dirstate[abs]
         if dstate == '?' and audit_path.check(abs):
--- a/mercurial/sslutil.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/sslutil.py	Sun Oct 20 16:43:11 2013 -0700
@@ -14,10 +14,13 @@
     # avoid using deprecated/broken FakeSocket in python 2.6
     import ssl
     CERT_REQUIRED = ssl.CERT_REQUIRED
-    def ssl_wrap_socket(sock, keyfile, certfile,
+    PROTOCOL_SSLv23 = ssl.PROTOCOL_SSLv23
+    PROTOCOL_TLSv1 = ssl.PROTOCOL_TLSv1
+    def ssl_wrap_socket(sock, keyfile, certfile, ssl_version=PROTOCOL_TLSv1,
                 cert_reqs=ssl.CERT_NONE, ca_certs=None):
         sslsocket = ssl.wrap_socket(sock, keyfile, certfile,
-                cert_reqs=cert_reqs, ca_certs=ca_certs)
+                                    cert_reqs=cert_reqs, ca_certs=ca_certs,
+                                    ssl_version=ssl_version)
         # check if wrap_socket failed silently because socket had been closed
         # - see http://bugs.python.org/issue13721
         if not sslsocket.cipher():
@@ -26,9 +29,12 @@
 except ImportError:
     CERT_REQUIRED = 2
 
+    PROTOCOL_SSLv23 = 2
+    PROTOCOL_TLSv1 = 3
+
     import socket, httplib
 
-    def ssl_wrap_socket(sock, key_file, cert_file,
+    def ssl_wrap_socket(sock, keyfile, certfile, ssl_version=PROTOCOL_TLSv1,
                         cert_reqs=CERT_REQUIRED, ca_certs=None):
         if not util.safehasattr(socket, 'ssl'):
             raise util.Abort(_('Python SSL support not found'))
@@ -36,7 +42,7 @@
             raise util.Abort(_(
                 'certificate checking requires Python 2.6'))
 
-        ssl = socket.ssl(sock, key_file, cert_file)
+        ssl = socket.ssl(sock, keyfile, certfile)
         return httplib.FakeSocket(sock, ssl)
 
 def _verifycert(cert, hostname):
@@ -84,15 +90,22 @@
 
 def sslkwargs(ui, host):
     cacerts = ui.config('web', 'cacerts')
+    forcetls = ui.configbool('ui', 'tls', default=True)
+    if forcetls:
+        ssl_version = PROTOCOL_TLSv1
+    else:
+        ssl_version = PROTOCOL_SSLv23
     hostfingerprint = ui.config('hostfingerprints', host)
+    kws = {'ssl_version': ssl_version,
+           }
     if cacerts and not hostfingerprint:
         cacerts = util.expandpath(cacerts)
         if not os.path.exists(cacerts):
             raise util.Abort(_('could not find web.cacerts: %s') % cacerts)
-        return {'ca_certs': cacerts,
-                'cert_reqs': CERT_REQUIRED,
-                }
-    return {}
+        kws.update({'ca_certs': cacerts,
+                    'cert_reqs': CERT_REQUIRED,
+                    })
+    return kws
 
 class validator(object):
     def __init__(self, ui, host):
--- a/mercurial/statichttprepo.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/statichttprepo.py	Sun Oct 20 16:43:11 2013 -0700
@@ -89,6 +89,8 @@
         return False
 
 class statichttprepository(localrepo.localrepository):
+    supported = localrepo.localrepository._basesupported
+
     def __init__(self, ui, path):
         self._url = path
         self.ui = ui
--- a/mercurial/store.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/store.py	Sun Oct 20 16:43:11 2013 -0700
@@ -344,12 +344,12 @@
         '''Checks if the store contains path'''
         path = "/".join(("data", path))
         # file?
-        if os.path.exists(self.join(path + ".i")):
+        if self.vfs.exists(path + ".i"):
             return True
         # dir?
         if not path.endswith("/"):
             path = path + "/"
-        return os.path.exists(self.join(path))
+        return self.vfs.exists(path)
 
 class encodedstore(basicstore):
     def __init__(self, path, vfstype):
--- a/mercurial/subrepo.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/subrepo.py	Sun Oct 20 16:43:11 2013 -0700
@@ -5,7 +5,8 @@
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 
-import errno, os, re, xml.dom.minidom, shutil, posixpath, sys
+import errno, os, re, shutil, posixpath, sys
+import xml.dom.minidom
 import stat, subprocess, tarfile
 from i18n import _
 import config, scmutil, util, node, error, cmdutil, bookmarks, match as matchmod
@@ -201,9 +202,24 @@
                 wctx.sub(s).get(r, overwrite)
                 sm[s] = r
             else:
-                debug(s, "both sides changed, merge with", r)
-                wctx.sub(s).merge(r)
-                sm[s] = l
+                debug(s, "both sides changed")
+                option = repo.ui.promptchoice(
+                    _(' subrepository %s diverged (local revision: %s, '
+                      'remote revision: %s)\n'
+                      '(M)erge, keep (l)ocal or keep (r)emote?'
+                      '$$ &Merge $$ &Local $$ &Remote')
+                    % (s, l[1][:12], r[1][:12]), 0)
+                if option == 0:
+                    wctx.sub(s).merge(r)
+                    sm[s] = l
+                    debug(s, "merge with", r)
+                elif option == 1:
+                    sm[s] = l
+                    debug(s, "keep local subrepo revision", l)
+                else:
+                    wctx.sub(s).get(r, overwrite)
+                    sm[s] = r
+                    debug(s, "get remote subrepo revision", r)
         elif ld == a: # remote removed, local unchanged
             debug(s, "remote removed, remove")
             wctx.sub(s).remove()
@@ -237,6 +253,7 @@
 
     # record merged .hgsubstate
     writestate(repo, sm)
+    return sm
 
 def _updateprompt(ui, sub, dirty, local, remote):
     if dirty:
--- a/mercurial/templatefilters.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/templatefilters.py	Sun Oct 20 16:43:11 2013 -0700
@@ -15,15 +15,15 @@
     """
     return text.replace('\n', '<br/>\n')
 
-agescales = [("year", 3600 * 24 * 365),
-             ("month", 3600 * 24 * 30),
-             ("week", 3600 * 24 * 7),
-             ("day", 3600 * 24),
-             ("hour", 3600),
-             ("minute", 60),
-             ("second", 1)]
+agescales = [("year", 3600 * 24 * 365, 'Y'),
+             ("month", 3600 * 24 * 30, 'M'),
+             ("week", 3600 * 24 * 7, 'W'),
+             ("day", 3600 * 24, 'd'),
+             ("hour", 3600, 'h'),
+             ("minute", 60, 'm'),
+             ("second", 1, 's')]
 
-def age(date):
+def age(date, abbrev=False):
     """:age: Date. Returns a human-readable date/time difference between the
     given date/time and the current date/time.
     """
@@ -32,7 +32,9 @@
         if c == 1:
             return t
         return t + "s"
-    def fmt(t, c):
+    def fmt(t, c, a):
+        if abbrev:
+            return "%d%s" % (c, a)
         return "%d %s" % (c, plural(t, c))
 
     now = time.time()
@@ -48,12 +50,12 @@
         if delta > agescales[0][1] * 2:
             return util.shortdate(date)
 
-    for t, s in agescales:
+    for t, s, a in agescales:
         n = delta // s
         if n >= 2 or s == 1:
             if future:
-                return '%s from now' % fmt(t, n)
-            return '%s ago' % fmt(t, n)
+                return '%s from now' % fmt(t, n, a)
+            return '%s ago' % fmt(t, n, a)
 
 def basename(path):
     """:basename: Any text. Treats the text as a path, and returns the last
@@ -99,7 +101,7 @@
 para_re = None
 space_re = None
 
-def fill(text, width, initindent = '', hangindent = ''):
+def fill(text, width, initindent='', hangindent=''):
     '''fill many paragraphs with optional indentation.'''
     global para_re, space_re
     if para_re is None:
--- a/mercurial/templater.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/templater.py	Sun Oct 20 16:43:11 2013 -0700
@@ -139,7 +139,12 @@
 def runsymbol(context, mapping, key):
     v = mapping.get(key)
     if v is None:
-        v = context._defaults.get(key, '')
+        v = context._defaults.get(key)
+    if v is None:
+        try:
+            v = context.process(key, mapping)
+        except TemplateNotFound:
+            v = ''
     if util.safehasattr(v, '__call__'):
         return v(**mapping)
     if isinstance(v, types.GeneratorType):
@@ -449,6 +454,9 @@
             stylelist.append(split[1])
     return ", ".join(sorted(stylelist))
 
+class TemplateNotFound(util.Abort):
+    pass
+
 class templater(object):
 
     def __init__(self, mapfile, filters={}, defaults={}, cache={},
@@ -500,7 +508,8 @@
             try:
                 self.cache[t] = util.readfile(self.map[t][1])
             except KeyError, inst:
-                raise util.Abort(_('"%s" not in template map') % inst.args[0])
+                raise TemplateNotFound(_('"%s" not in template map') %
+                                       inst.args[0])
             except IOError, inst:
                 raise IOError(inst.args[0], _('template file %s: %s') %
                               (self.map[t][1], inst.args[1]))
--- a/mercurial/templates/paper/bookmarks.tmpl	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/templates/paper/bookmarks.tmpl	Sun Oct 20 16:43:11 2013 -0700
@@ -38,8 +38,7 @@
 <form class="search" action="{url|urlescape}log">
 {sessionvars%hiddenformentry}
 <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>
+<div id="hint">{searchhint}</div>
 </form>
 
 <table class="bigtable">
--- a/mercurial/templates/paper/branches.tmpl	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/templates/paper/branches.tmpl	Sun Oct 20 16:43:11 2013 -0700
@@ -38,8 +38,7 @@
 <form class="search" action="{url|urlescape}log">
 {sessionvars%hiddenformentry}
 <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>
+<div id="hint">{searchhint}</div>
 </form>
 
 <table class="bigtable">
--- a/mercurial/templates/paper/changeset.tmpl	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/templates/paper/changeset.tmpl	Sun Oct 20 16:43:11 2013 -0700
@@ -36,8 +36,7 @@
 <form class="search" action="{url|urlescape}log">
 {sessionvars%hiddenformentry}
 <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>
+<div id="hint">{searchhint}</div>
 </form>
 
 <div class="description">{desc|strip|escape|websub|nonempty}</div>
--- a/mercurial/templates/paper/error.tmpl	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/templates/paper/error.tmpl	Sun Oct 20 16:43:11 2013 -0700
@@ -29,8 +29,7 @@
 <form class="search" action="{url|urlescape}log">
 {sessionvars%hiddenformentry}
 <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>
+<div id="hint">{searchhint}</div>
 </form>
 
 <div class="description">
--- a/mercurial/templates/paper/fileannotate.tmpl	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/templates/paper/fileannotate.tmpl	Sun Oct 20 16:43:11 2013 -0700
@@ -42,8 +42,7 @@
 <form class="search" action="{url|urlescape}log">
 {sessionvars%hiddenformentry}
 <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>
+<div id="hint">{searchhint}</div>
 </form>
 
 <div class="description">{desc|strip|escape|websub|nonempty}</div>
@@ -65,7 +64,6 @@
  <th class="author">children</th>
  <td class="author">{child%filerevchild}</td>
 </tr>
-{changesettag}
 </table>
 
 <div class="overflow">
--- a/mercurial/templates/paper/filecomparison.tmpl	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/templates/paper/filecomparison.tmpl	Sun Oct 20 16:43:11 2013 -0700
@@ -41,8 +41,7 @@
 <form class="search" action="{url|urlescape}log">
 <p>{sessionvars%hiddenformentry}</p>
 <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>
+<div id="hint">{searchhint}</div>
 </form>
 
 <div class="description">{desc|strip|escape|websub|nonempty}</div>
@@ -64,7 +63,6 @@
  <th>children</th>
  <td>{child%filerevchild}</td>
 </tr>
-{changesettag}
 </table>
 
 <div class="overflow">
--- a/mercurial/templates/paper/filediff.tmpl	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/templates/paper/filediff.tmpl	Sun Oct 20 16:43:11 2013 -0700
@@ -41,8 +41,7 @@
 <form class="search" action="{url|urlescape}log">
 <p>{sessionvars%hiddenformentry}</p>
 <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>
+<div id="hint">{searchhint}</div>
 </form>
 
 <div class="description">{desc|strip|escape|websub|nonempty}</div>
@@ -64,7 +63,6 @@
  <th>children</th>
  <td>{child%filerevchild}</td>
 </tr>
-{changesettag}
 </table>
 
 <div class="overflow">
--- a/mercurial/templates/paper/filelog.tmpl	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/templates/paper/filelog.tmpl	Sun Oct 20 16:43:11 2013 -0700
@@ -49,8 +49,7 @@
 <form class="search" action="{url|urlescape}log">
 {sessionvars%hiddenformentry}
 <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>
+<div id="hint">{searchhint}</div>
 </form>
 
 <div class="navigate">
--- a/mercurial/templates/paper/filerevision.tmpl	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/templates/paper/filerevision.tmpl	Sun Oct 20 16:43:11 2013 -0700
@@ -40,8 +40,7 @@
 <form class="search" action="{url|urlescape}log">
 {sessionvars%hiddenformentry}
 <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>
+<div id="hint">{searchhint}</div>
 </form>
 
 <div class="description">{desc|strip|escape|websub|nonempty}</div>
@@ -63,7 +62,6 @@
  <th class="author">children</th>
  <td class="author">{child%filerevchild}</td>
 </tr>
-{changesettag}
 </table>
 
 <div class="overflow">
--- a/mercurial/templates/paper/graph.tmpl	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/templates/paper/graph.tmpl	Sun Oct 20 16:43:11 2013 -0700
@@ -43,8 +43,7 @@
 <form class="search" action="{url|urlescape}log">
 {sessionvars%hiddenformentry}
 <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>
+<div id="hint">{searchhint}</div>
 </form>
 
 <div class="navigate">
@@ -123,6 +122,17 @@
 | rev {rev}: {changenav%navgraph}
 </div>
 
+<script type="text/javascript">
+    ajaxScrollInit(
+            '{url|urlescape}graph/{rev}?revcount=%next%',
+            {revcount}+60,
+            function (htmlText, previousVal) \{ return previousVal + 60; },
+            '#wrapper',
+            '<div class="%class%" style="text-align: center;">%text%</div>',
+            'graph'
+    );
+</script>
+
 </div>
 </div>
 
--- a/mercurial/templates/paper/help.tmpl	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/templates/paper/help.tmpl	Sun Oct 20 16:43:11 2013 -0700
@@ -28,8 +28,7 @@
 <form class="search" action="{url|urlescape}log">
 {sessionvars%hiddenformentry}
 <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>
+<div id="hint">{searchhint}</div>
 </form>
 <div id="doc">
 {rstdoc(doc, "html")}
--- a/mercurial/templates/paper/helptopics.tmpl	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/templates/paper/helptopics.tmpl	Sun Oct 20 16:43:11 2013 -0700
@@ -26,8 +26,7 @@
 <form class="search" action="{url|urlescape}log">
 {sessionvars%hiddenformentry}
 <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>
+<div id="hint">{searchhint}</div>
 </form>
 <table class="bigtable">
 <tr><td colspan="2"><h2><a name="main" href="#topics">Topics</a></h2></td></tr>
--- a/mercurial/templates/paper/manifest.tmpl	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/templates/paper/manifest.tmpl	Sun Oct 20 16:43:11 2013 -0700
@@ -35,8 +35,7 @@
 <form class="search" action="{url|urlescape}log">
 {sessionvars%hiddenformentry}
 <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>
+<div id="hint">{searchhint}</div>
 </form>
 
 <table class="bigtable">
--- a/mercurial/templates/paper/map	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/templates/paper/map	Sun Oct 20 16:43:11 2013 -0700
@@ -243,3 +243,6 @@
 urlparameter = '{separator}{name}={value|urlescape}'
 hiddenformentry = '<input type="hidden" name="{name}" value="{value|escape}" />'
 breadcrumb = '&gt; <a href="{url|urlescape}">{name|escape}</a> '
+
+searchhint = 'Find changesets by keywords (author, files, the commit message), revision
+  number or hash, or <a href="{url|urlescape}help/revsets">revset expression</a>.'
--- a/mercurial/templates/paper/search.tmpl	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/templates/paper/search.tmpl	Sun Oct 20 16:43:11 2013 -0700
@@ -23,11 +23,18 @@
 <h2 class="breadcrumb"><a href="/">Mercurial</a> {pathdef%breadcrumb}</h2>
 <h3>searching for '{query|escape}'</h3>
 
+<p>
+Assuming {modedesc}.
+{if(showforcekw, '<a href="{url|urlescape}log?rev={query|urlescape}&forcekw=1">
+Use {showforcekw}</a> instead.')}
+{if(showunforcekw, '<a href="{url|urlescape}log?rev={query|urlescape}">
+Use {showunforcekw}</a> instead.')}
+</p>
+
 <form class="search" action="{url|urlescape}log">
 {sessionvars%hiddenformentry}
 <p><input name="rev" id="search1" type="text" size="30" value="{query|escape}"></p>
-<div id="hint">find changesets by author, revision,
-files, or words in the commit message</div>
+<div id="hint">{searchhint}</div>
 </form>
 
 <div class="navigate">
--- a/mercurial/templates/paper/shortlog.tmpl	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/templates/paper/shortlog.tmpl	Sun Oct 20 16:43:11 2013 -0700
@@ -45,8 +45,7 @@
 <form class="search" action="{url|urlescape}log">
 {sessionvars%hiddenformentry}
 <p><input name="rev" id="search1" type="text" size="30" value="{query|escape}" /></p>
-<div id="hint">find changesets by author, revision,
-files, or words in the commit message</div>
+<div id="hint">{searchhint}</div>
 </form>
 
 <div class="navigate">
@@ -72,6 +71,21 @@
 | rev {rev}: {changenav%navshort}
 </div>
 
+<script type="text/javascript">
+    ajaxScrollInit(
+            '{url|urlescape}shortlog/%next%',
+            '{nextentry%"{node}"}', <!-- NEXTHASH
+            function (htmlText, previousVal) \{
+                var m = htmlText.match(/'(\w+)', <!-- NEXTHASH/);
+                return m ? m[1] : null;
+            },
+            '.bigtable > tbody:nth-of-type(2)',
+            '<tr class="%class%">\
+            <td colspan="3" style="text-align: center;">%text%</td>\
+            </tr>'
+    );
+</script>
+
 </div>
 </div>
 
--- a/mercurial/templates/paper/shortlogentry.tmpl	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/templates/paper/shortlogentry.tmpl	Sun Oct 20 16:43:11 2013 -0700
@@ -1,5 +1,5 @@
  <tr>
   <td class="age">{date|rfc822date}</td>
   <td class="author">{author|person}</td>
-  <td class="description"><a href="{url|urlescape}rev/{node|short}{sessionvars%urlparameter}">{desc|strip|firstline|escape|nonempty}</a>{inbranch%changelogbranchname}{branches%changelogbranchhead}{tags % '<span class="tag">{name|escape}</span> '}{bookmarks % '<span class="tag">{name|escape}</span> '}</td>
+  <td class="description"><a href="{url|urlescape}rev/{node|short}{sessionvars%urlparameter}">{desc|strip|firstline|escape|nonempty}</a>{inbranch%changelogbranchname}{branches%changelogbranchhead}{tags%changelogtag}{bookmarks%changelogtag}</td>
  </tr>
--- a/mercurial/templates/paper/tags.tmpl	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/templates/paper/tags.tmpl	Sun Oct 20 16:43:11 2013 -0700
@@ -37,8 +37,7 @@
 <form class="search" action="{url|urlescape}log">
 {sessionvars%hiddenformentry}
 <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>
+<div id="hint">{searchhint}</div>
 </form>
 
 <table class="bigtable">
--- a/mercurial/templates/raw/changelog.tmpl	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/templates/raw/changelog.tmpl	Sun Oct 20 16:43:11 2013 -0700
@@ -1,5 +1,5 @@
 {header}
-# HG shortlog
+# HG changelog
 # Node ID {node}
 
 {entries%changelogentry}
--- a/mercurial/templates/raw/search.tmpl	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/templates/raw/search.tmpl	Sun Oct 20 16:43:11 2013 -0700
@@ -2,5 +2,6 @@
 # HG changesets search
 # Node ID {node}
 # Query "{query}"
+# Mode {modedesc}
 
 {entries%changelogentry}
--- a/mercurial/templates/static/mercurial.js	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/templates/static/mercurial.js	Sun Oct 20 16:43:11 2013 -0700
@@ -23,7 +23,7 @@
 ];
 
 function Graph() {
-	
+
 	this.canvas = document.getElementById('graph');
 	if (window.G_vmlCanvasManager) this.canvas = window.G_vmlCanvasManager.initElement(this.canvas);
 	this.ctx = this.canvas.getContext('2d');
@@ -35,13 +35,21 @@
 	this.cell = [2, 0];
 	this.columns = 0;
 	this.revlink = '';
-	
+
+	this.reset = function() {
+		this.bg = [0, 4];
+		this.cell = [2, 0];
+		this.columns = 0;
+		document.getElementById('nodebgs').innerHTML = '';
+		document.getElementById('graphnodes').innerHTML = '';
+	}
+
 	this.scale = function(height) {
 		this.bg_height = height;
 		this.box_size = Math.floor(this.bg_height / 1.2);
 		this.cell_height = this.box_size;
 	}
-	
+
 	function colorPart(num) {
 		num *= 255
 		num = num < 0 ? 0 : num;
@@ -55,7 +63,7 @@
 	}
 
 	this.setColor = function(color, bg, fg) {
-		
+
 		// Set the colour.
 		//
 		// If color is a string, expect an hexadecimal RGB
@@ -81,11 +89,11 @@
 		this.ctx.strokeStyle = s;
 		this.ctx.fillStyle = s;
 		return s;
-		
+
 	}
 
 	this.edge = function(x0, y0, x1, y1, color, width) {
-		
+
 		this.setColor(color, 0.0, 0.65);
 		if(width >= 0)
 			 this.ctx.lineWidth = width;
@@ -93,28 +101,28 @@
 		this.ctx.moveTo(x0, y0);
 		this.ctx.lineTo(x1, y1);
 		this.ctx.stroke();
-		
+
 	}
 
 	this.render = function(data) {
-		
+
 		var backgrounds = '';
 		var nodedata = '';
-		
+
 		for (var i in data) {
-			
+
 			var parity = i % 2;
 			this.cell[1] += this.bg_height;
 			this.bg[1] += this.bg_height;
-			
+
 			var cur = data[i];
 			var node = cur[1];
 			var edges = cur[2];
 			var fold = false;
-			
+
 			var prevWidth = this.ctx.lineWidth;
 			for (var j in edges) {
-				
+
 				line = edges[j];
 				start = line[0];
 				end = line[1];
@@ -125,50 +133,50 @@
 				var branchcolor = line[4];
 				if(branchcolor)
 					color = branchcolor;
-				
+
 				if (end > this.columns || start > this.columns) {
 					this.columns += 1;
 				}
-				
+
 				if (start == this.columns && start > end) {
 					var fold = true;
 				}
-				
+
 				x0 = this.cell[0] + this.box_size * start + this.box_size / 2;
 				y0 = this.bg[1] - this.bg_height / 2;
 				x1 = this.cell[0] + this.box_size * end + this.box_size / 2;
 				y1 = this.bg[1] + this.bg_height / 2;
-				
+
 				this.edge(x0, y0, x1, y1, color, width);
-				
+
 			}
 			this.ctx.lineWidth = prevWidth;
-			
+
 			// Draw the revision node in the right column
-			
+
 			column = node[0]
 			color = node[1]
-			
+
 			radius = this.box_size / 8;
 			x = this.cell[0] + this.box_size * column + this.box_size / 2;
 			y = this.bg[1] - this.bg_height / 2;
 			var add = this.vertex(x, y, color, parity, cur);
 			backgrounds += add[0];
 			nodedata += add[1];
-			
+
 			if (fold) this.columns -= 1;
-			
+
 		}
-		
+
 		document.getElementById('nodebgs').innerHTML += backgrounds;
 		document.getElementById('graphnodes').innerHTML += nodedata;
-		
+
 	}
 
 }
 
 
-process_dates = (function(document, RegExp, Math, isNaN, Date, _false, _true){
+function process_dates(parentSelector){
 
 	// derived from code from mercurial/templatefilter.py
 
@@ -219,9 +227,9 @@
 
 		var delta = Math.floor((now.getTime() - once.getTime()) / 1000);
 
-		var future = _false;
+		var future = false;
 		if (delta < 0){
-			future = _true;
+			future = true;
 			delta = -delta;
 			if (delta > (30 * scales.year)){
 				return "in the distant future";
@@ -245,25 +253,21 @@
 		}
 	}
 
-	return function(){
-		var nodes = document.getElementsByTagName('*');
-		var ageclass = new RegExp('\\bage\\b');
-		var dateclass = new RegExp('\\bdate\\b');
-		for (var i=0; i<nodes.length; ++i){
-			var node = nodes[i];
-			var classes = node.className;
-			if (ageclass.test(classes)){
-				var agevalue = age(node.textContent);
-				if (dateclass.test(classes)){
-					// We want both: date + (age)
-					node.textContent += ' ('+agevalue+')';
-				} else {
-					node.textContent = agevalue;
-				}
-			}
+	var nodes = document.querySelectorAll((parentSelector || '') + ' .age');
+	var dateclass = new RegExp('\\bdate\\b');
+	for (var i=0; i<nodes.length; ++i){
+		var node = nodes[i];
+		var classes = node.className;
+		var agevalue = age(node.textContent);
+		if (dateclass.test(classes)){
+			// We want both: date + (age)
+			node.textContent += ' ('+agevalue+')';
+		} else {
+			node.title = node.textContent;
+			node.textContent = agevalue;
 		}
 	}
-})(document, RegExp, Math, isNaN, Date, false, true)
+}
 
 function toggleDiffstat() {
     var curdetails = document.getElementById('diffstatdetails').style.display;
@@ -297,3 +301,142 @@
 
     setLinewrap(!getLinewrap());
 }
+
+function format(str, replacements) {
+    return str.replace(/%(\w+)%/g, function(match, p1) {
+        return String(replacements[p1]);
+    });
+}
+
+function makeRequest(url, method, onstart, onsuccess, onerror, oncomplete) {
+    xfr = new XMLHttpRequest();
+    xfr.onreadystatechange = function() {
+        if (xfr.readyState === 4) {
+            try {
+                if (xfr.status === 200) {
+                    onsuccess(xfr.responseText);
+                } else {
+                    throw 'server error';
+                }
+            } catch (e) {
+                onerror(e);
+            } finally {
+                oncomplete();
+            }
+        }
+    };
+
+    xfr.open(method, url);
+    xfr.send();
+    onstart();
+    return xfr;
+}
+
+function removeByClassName(className) {
+    var nodes = document.getElementsByClassName(className);
+    while (nodes.length) {
+        nodes[0].parentNode.removeChild(nodes[0]);
+    }
+}
+
+function docFromHTML(html) {
+    var doc = document.implementation.createHTMLDocument('');
+    doc.documentElement.innerHTML = html;
+    return doc;
+}
+
+function appendFormatHTML(element, formatStr, replacements) {
+    element.insertAdjacentHTML('beforeend', format(formatStr, replacements));
+}
+
+function ajaxScrollInit(urlFormat,
+                        nextPageVar,
+                        nextPageVarGet,
+                        containerSelector,
+                        messageFormat,
+                        mode) {
+    updateInitiated = false;
+    container = document.querySelector(containerSelector);
+
+    function scrollHandler() {
+        if (updateInitiated) {
+            return;
+        }
+
+        var scrollHeight = document.documentElement.scrollHeight;
+        var clientHeight = document.documentElement.clientHeight;
+        var scrollTop = document.body.scrollTop
+            || document.documentElement.scrollTop;
+
+        if (scrollHeight - (scrollTop + clientHeight) < 50) {
+            updateInitiated = true;
+            removeByClassName('scroll-loading-error');
+            container.lastElementChild.classList.add('scroll-separator');
+
+            if (!nextPageVar) {
+                var message = {
+                    class: 'scroll-loading-info',
+                    text: 'No more entries'
+                };
+                appendFormatHTML(container, messageFormat, message);
+                return;
+            }
+
+            makeRequest(
+                format(urlFormat, {next: nextPageVar}),
+                'GET',
+                function onstart() {
+                    var message = {
+                        class: 'scroll-loading',
+                        text: 'Loading...'
+                    };
+                    appendFormatHTML(container, messageFormat, message);
+                },
+                function onsuccess(htmlText) {
+                    if (mode == 'graph') {
+                        var addHeight = htmlText.match(/^<canvas id="graph".*height="(\d+)"><\/canvas>$/m)[1];
+                        addHeight = parseInt(addHeight);
+                        graph.canvas.height = addHeight;
+
+                        var dataStr = htmlText.match(/^\s*var data = (.*);$/m)[1];
+                        var data = JSON.parse(dataStr)
+                        if (data.length < nextPageVar) {
+                            nextPageVar = undefined;
+                        }
+                        graph.reset();
+                        graph.render(data);
+                    } else {
+                        var doc = docFromHTML(htmlText);
+                        var nodes = doc.querySelector(containerSelector).children;
+                        var curClass = 'c' + Date.now();
+                        while (nodes.length) {
+                            var node = nodes[0];
+                            node = document.adoptNode(node);
+                            node.classList.add(curClass);
+                            container.appendChild(node);
+                        }
+                        process_dates('.' + curClass);
+                    }
+
+                    nextPageVar = nextPageVarGet(htmlText, nextPageVar);
+                },
+                function onerror(errorText) {
+                    var message = {
+                        class: 'scroll-loading-error',
+                        text: 'Error: ' + errorText
+                    };
+                    appendFormatHTML(container, messageFormat, message);
+                },
+                function oncomplete() {
+                    removeByClassName('scroll-loading');
+                    updateInitiated = false;
+                    scrollHandler();
+                }
+            );
+        }
+    }
+
+    window.addEventListener('scroll', scrollHandler);
+    window.addEventListener('resize', scrollHandler);
+    scrollHandler();
+}
--- a/mercurial/templates/static/style-paper.css	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/templates/static/style-paper.css	Sun Oct 20 16:43:11 2013 -0700
@@ -382,3 +382,27 @@
 .breadcrumb a {
     color: blue;
 }
+
+.scroll-loading {
+  -webkit-animation: change_color 1s linear 0s infinite alternate;
+  -moz-animation: change_color 1s linear 0s infinite alternate;
+  -o-animation: change_color 1s linear 0s infinite alternate;
+  animation: change_color 1s linear 0s infinite alternate;
+}
+
+@-webkit-keyframes change_color {
+  from { background-color: #A0CEFF; } to {  }
+}
+@-moz-keyframes change_color {
+  from { background-color: #A0CEFF; } to {  }
+}
+@-o-keyframes change_color {
+  from { background-color: #A0CEFF; } to {  }
+}
+@keyframes change_color {
+  from { background-color: #A0CEFF; } to {  }
+}
+
+.scroll-loading-error {
+    background-color: #FFCCCC !important;
+}
--- a/mercurial/ui.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/ui.py	Sun Oct 20 16:43:11 2013 -0700
@@ -176,7 +176,7 @@
             alternates = [name]
 
         for n in alternates:
-            value = self._data(untrusted).get(section, name, None)
+            value = self._data(untrusted).get(section, n, None)
             if value is not None:
                 name = n
                 break
@@ -184,10 +184,11 @@
             value = default
 
         if self.debugflag and not untrusted and self._reportuntrusted:
-            uvalue = self._ucfg.get(section, name)
-            if uvalue is not None and uvalue != value:
-                self.debug("ignoring untrusted configuration option "
-                           "%s.%s = %s\n" % (section, name, uvalue))
+            for n in alternates:
+                uvalue = self._ucfg.get(section, n)
+                if uvalue is not None and uvalue != value:
+                    self.debug("ignoring untrusted configuration option "
+                               "%s.%s = %s\n" % (section, n, uvalue))
         return value
 
     def configpath(self, section, name, default=None, untrusted=False):
--- a/mercurial/unionrepo.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/unionrepo.py	Sun Oct 20 16:43:11 2013 -0700
@@ -70,7 +70,7 @@
                 self.revlog2.rev(self.node(rev1)),
                 self.revlog2.rev(self.node(rev2)))
         elif rev1 <= self.repotiprev and rev2 <= self.repotiprev:
-            return revlog.revlog.revdiff(self, rev1, rev2)
+            return self.baserevdiff(rev1, rev2)
 
         return mdiff.textdiff(self.revision(self.node(rev1)),
                               self.revision(self.node(rev2)))
@@ -93,10 +93,20 @@
             text = self.revlog2.revision(node)
             self._cache = (node, rev, text)
         else:
-            text = revlog.revlog.revision(self, rev)
+            text = self.baserevision(rev)
             # already cached
         return text
 
+    def baserevision(self, nodeorrev):
+        # Revlog subclasses may override 'revision' method to modify format of
+        # content retrieved from revlog. To use unionrevlog with such class one
+        # needs to override 'baserevision' and make more specific call here.
+        return revlog.revlog.revision(self, nodeorrev)
+
+    def baserevdiff(self, rev1, rev2):
+        # Exists for the same purpose as baserevision.
+        return revlog.revlog.revdiff(self, rev1, rev2)
+
     def addrevision(self, text, transaction, link, p1=None, p2=None, d=None):
         raise NotImplementedError
     def addgroup(self, revs, linkmapper, transaction):
@@ -114,6 +124,15 @@
         unionrevlog.__init__(self, opener, self.indexfile, changelog2,
                              linkmapper)
 
+    def baserevision(self, nodeorrev):
+        # Although changelog doesn't override 'revision' method, some extensions
+        # may replace this class with another that does. Same story with
+        # manifest and filelog classes.
+        return changelog.changelog.revision(self, nodeorrev)
+
+    def baserevdiff(self, rev1, rev2):
+        return changelog.changelog.revdiff(self, rev1, rev2)
+
 class unionmanifest(unionrevlog, manifest.manifest):
     def __init__(self, opener, opener2, linkmapper):
         manifest.manifest.__init__(self, opener)
@@ -121,6 +140,12 @@
         unionrevlog.__init__(self, opener, self.indexfile, manifest2,
                              linkmapper)
 
+    def baserevision(self, nodeorrev):
+        return manifest.manifest.revision(self, nodeorrev)
+
+    def baserevdiff(self, rev1, rev2):
+        return manifest.manifest.revdiff(self, rev1, rev2)
+
 class unionfilelog(unionrevlog, filelog.filelog):
     def __init__(self, opener, path, opener2, linkmapper, repo):
         filelog.filelog.__init__(self, opener, path)
@@ -129,6 +154,12 @@
                              linkmapper)
         self._repo = repo
 
+    def baserevision(self, nodeorrev):
+        return filelog.filelog.revision(self, nodeorrev)
+
+    def baserevdiff(self, rev1, rev2):
+        return filelog.filelog.revdiff(self, rev1, rev2)
+
     def _file(self, f):
         self._repo.file(f)
 
--- a/mercurial/url.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/url.py	Sun Oct 20 16:43:11 2013 -0700
@@ -108,8 +108,13 @@
 
     def proxy_open(self, req, proxy, type_):
         host = req.get_host().split(':')[0]
-        if host in self.no_list:
-            return None
+        for e in self.no_list:
+            if host == e:
+                return None
+            if e.startswith('*.') and host.endswith(e[2:]):
+                return None
+            if e.startswith('.') and host.endswith(e[1:]):
+                return None
 
         # work around a bug in Python < 2.4.2
         # (it leaves a "\n" at the end of Proxy-authorization headers)
--- a/mercurial/util.h	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/util.h	Sun Oct 20 16:43:11 2013 -0700
@@ -121,7 +121,12 @@
 #ifdef _MSC_VER
 /* msvc 6.0 has problems */
 #define inline __inline
+typedef signed char int8_t;
+typedef short int16_t;
+typedef long int32_t;
+typedef __int64 int64_t;
 typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
 typedef unsigned long uint32_t;
 typedef unsigned __int64 uint64_t;
 #else
--- a/mercurial/util.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/mercurial/util.py	Sun Oct 20 16:43:11 2013 -0700
@@ -242,6 +242,10 @@
     def __contains__(self, key):
         return key in self._cache
 
+    def clear(self):
+        self._cache.clear()
+        self._order = deque()
+
 def lrucachefunc(func):
     '''cache most recent results of function calls'''
     cache = {}
@@ -466,7 +470,8 @@
         return str(val)
     origcmd = cmd
     cmd = quotecommand(cmd)
-    if sys.platform == 'plan9':
+    if sys.platform == 'plan9' and (sys.version_info[0] == 2
+                                    and sys.version_info[1] < 7):
         # subprocess kludge to work around issues in half-baked Python
         # ports, notably bichued/python:
         if not cwd is None:
--- a/setup.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/setup.py	Sun Oct 20 16:43:11 2013 -0700
@@ -423,14 +423,21 @@
 
 pymodules = []
 
+common_depends = ['mercurial/util.h']
+
 extmodules = [
-    Extension('mercurial.base85', ['mercurial/base85.c']),
-    Extension('mercurial.bdiff', ['mercurial/bdiff.c']),
-    Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c']),
-    Extension('mercurial.mpatch', ['mercurial/mpatch.c']),
+    Extension('mercurial.base85', ['mercurial/base85.c'],
+              depends=common_depends),
+    Extension('mercurial.bdiff', ['mercurial/bdiff.c'],
+              depends=common_depends),
+    Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c'],
+              depends=common_depends),
+    Extension('mercurial.mpatch', ['mercurial/mpatch.c'],
+              depends=common_depends),
     Extension('mercurial.parsers', ['mercurial/dirs.c',
                                     'mercurial/parsers.c',
-                                    'mercurial/pathencode.c']),
+                                    'mercurial/pathencode.c'],
+              depends=common_depends),
     ]
 
 osutil_ldflags = []
@@ -443,7 +450,8 @@
     pymodules.append('mercurial.pure.osutil')
 else:
     extmodules.append(Extension('mercurial.osutil', ['mercurial/osutil.c'],
-                                extra_link_args=osutil_ldflags))
+                                extra_link_args=osutil_ldflags,
+                                depends=common_depends))
 
 # the -mno-cygwin option has been deprecated for years
 Mingw32CCompiler = cygwinccompiler.Mingw32CCompiler
@@ -467,7 +475,8 @@
     if hasfunction(cc, 'inotify_add_watch'):
         inotify = Extension('hgext.inotify.linux._inotify',
                             ['hgext/inotify/linux/_inotify.c'],
-                            ['mercurial'])
+                            ['mercurial'],
+                            depends=common_depends)
         inotify.optional = True
         extmodules.append(inotify)
         packages.extend(['hgext.inotify', 'hgext.inotify.linux'])
--- a/tests/filterpyflakes.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/filterpyflakes.py	Sun Oct 20 16:43:11 2013 -0700
@@ -46,6 +46,6 @@
         continue
     lines.append((msgtype, line))
 
-for msgtype, line in sorted(lines, key = makekey):
+for msgtype, line in sorted(lines, key=makekey):
     sys.stdout.write(line)
 print
--- a/tests/get-with-headers.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/get-with-headers.py	Sun Oct 20 16:43:11 2013 -0700
@@ -43,8 +43,9 @@
             print "%s: %s" % (h, response.getheader(h))
     if not headeronly:
         print
-        data = response.read()
-        sys.stdout.write(data)
+        if response.status != 500:
+            data = response.read()
+            sys.stdout.write(data)
 
         if twice and response.getheader('ETag', None):
             tag = response.getheader('ETag')
--- a/tests/hghave.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/hghave.py	Sun Oct 20 16:43:11 2013 -0700
@@ -277,6 +277,14 @@
 def has_aix():
     return sys.platform.startswith("aix")
 
+def has_absimport():
+    import __future__
+    from mercurial import util
+    return util.safehasattr(__future__, "absolute_import")
+
+def has_py3k():
+    return 3 == sys.version_info[0]
+
 checks = {
     "true": (lambda: True, "yak shaving"),
     "false": (lambda: False, "nail clipper"),
@@ -318,4 +326,6 @@
     "windows": (has_windows, "Windows"),
     "msys": (has_msys, "Windows with MSYS"),
     "aix": (has_aix, "AIX"),
+    "absimport": (has_absimport, "absolute_import in __future__"),
+    "py3k": (has_py3k, "running with Python 3.x"),
 }
--- a/tests/run-tests.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/run-tests.py	Sun Oct 20 16:43:11 2013 -0700
@@ -341,6 +341,7 @@
     hgrc.write('[defaults]\n')
     hgrc.write('backout = -d "0 0"\n')
     hgrc.write('commit = -d "0 0"\n')
+    hgrc.write('shelve = --date "0 0"\n')
     hgrc.write('tag = -d "0 0"\n')
     if options.inotify:
         hgrc.write('[extensions]\n')
@@ -460,6 +461,9 @@
     if options.compiler:
         compiler = '--compiler ' + options.compiler
     pure = options.pure and "--pure" or ""
+    py3 = ''
+    if sys.version_info[0] == 3:
+        py3 = '--c2to3'
 
     # Run installer in hg root
     script = os.path.realpath(sys.argv[0])
@@ -472,11 +476,11 @@
         # least on Windows for now, deal with .pydistutils.cfg bugs
         # when they happen.
         nohome = ''
-    cmd = ('%(exe)s setup.py %(pure)s clean --all'
+    cmd = ('%(exe)s setup.py %(py3)s %(pure)s clean --all'
            ' build %(compiler)s --build-base="%(base)s"'
            ' install --force --prefix="%(prefix)s" --install-lib="%(libdir)s"'
            ' --install-scripts="%(bindir)s" %(nohome)s >%(logfile)s 2>&1'
-           % dict(exe=sys.executable, pure=pure, compiler=compiler,
+           % dict(exe=sys.executable, py3=py3, pure=pure, compiler=compiler,
                   base=os.path.join(HGTMP, "build"),
                   prefix=INST, libdir=PYTHONDIR, bindir=BINDIR,
                   nohome=nohome, logfile=installerrs))
@@ -758,21 +762,19 @@
     addsalt(n + 1, False)
 
     # Write out the script and execute it
-    fd, name = tempfile.mkstemp(suffix='hg-tst')
-    try:
-        for l in script:
-            os.write(fd, l)
-        os.close(fd)
+    name = wd + '.sh'
+    f = open(name, 'w')
+    for l in script:
+        f.write(l)
+    f.close()
 
-        cmd = '%s "%s"' % (options.shell, name)
-        vlog("# Running", cmd)
-        exitcode, output = run(cmd, wd, options, replacements, env)
-        # do not merge output if skipped, return hghave message instead
-        # similarly, with --debug, output is None
-        if exitcode == SKIPPED_STATUS or output is None:
-            return exitcode, output
-    finally:
-        os.remove(name)
+    cmd = '%s "%s"' % (options.shell, name)
+    vlog("# Running", cmd)
+    exitcode, output = run(cmd, wd, options, replacements, env)
+    # do not merge output if skipped, return hghave message instead
+    # similarly, with --debug, output is None
+    if exitcode == SKIPPED_STATUS or output is None:
+        return exitcode, output
 
     # Merge the script output back into a unified test
 
@@ -921,8 +923,10 @@
                 else:
                     return ignore("doesn't match keyword")
 
+    if not lctest.startswith("test-"):
+        return skip("not a test file")
     for ext, func, out in testtypes:
-        if lctest.startswith("test-") and lctest.endswith(ext):
+        if lctest.endswith(ext):
             runner = func
             ref = os.path.join(TESTDIR, test + out)
             break
@@ -1043,7 +1047,7 @@
     if _hgpath is not None:
         return _hgpath
 
-    cmd = '%s -c "import mercurial; print mercurial.__path__[0]"'
+    cmd = '%s -c "import mercurial; print (mercurial.__path__[0])"'
     pipe = os.popen(cmd % PYTHON)
     try:
         _hgpath = pipe.read().strip()
--- a/tests/test-archive.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-archive.t	Sun Oct 20 16:43:11 2013 -0700
@@ -209,8 +209,7 @@
   test-2c0277f05ed4/foo
 
   $ hg archive -r 0 -t tar rev-%r.tar
-  $ if [ -f rev-0.tar ]; then
-  $ fi
+  $ [ -f rev-0.tar ]
 
 test .hg_archival.txt
 
--- a/tests/test-bookmarks-pushpull.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-bookmarks-pushpull.t	Sun Oct 20 16:43:11 2013 -0700
@@ -275,7 +275,7 @@
   pushing to http://localhost:$HGPORT2/
   searching for changes
   abort: push creates new remote head c922c0139ca0!
-  (did you forget to merge? use push -f to force)
+  (merge or see "hg help push" for details about pushing new heads)
   [255]
   $ hg -R ../a book
      @                         1:0d2164f0ce0d
@@ -291,7 +291,7 @@
   pushing to http://localhost:$HGPORT2/
   searching for changes
   abort: push creates new remote head c922c0139ca0!
-  (did you forget to merge? use push -f to force)
+  (merge or see "hg help push" for details about pushing new heads)
   [255]
   $ hg -R ../a book
      @                         1:0d2164f0ce0d
--- a/tests/test-casecollision-merge.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-casecollision-merge.t	Sun Oct 20 16:43:11 2013 -0700
@@ -293,7 +293,7 @@
   [255]
 
   $ hg update --check
-  abort: uncommitted local changes
+  abort: uncommitted changes
   [255]
 
   $ hg update --clean
--- a/tests/test-command-template.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-command-template.t	Sun Oct 20 16:43:11 2013 -0700
@@ -500,6 +500,28 @@
   1
   0
 
+Missing non-standard names give no error (backward compatibility):
+
+  $ echo "changeset = '{c}'" > t
+  $ hg log --style ./t
+
+Defining non-standard name works:
+
+  $ cat <<EOF > t
+  > changeset = '{c}'
+  > c = q
+  > EOF
+  $ hg log --style ./t
+  8
+  7
+  6
+  5
+  4
+  3
+  2
+  1
+  0
+
 ui.style works:
 
   $ echo '[ui]' > .hg/hgrc
--- a/tests/test-commandserver.py.out	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-commandserver.py.out	Sun Oct 20 16:43:11 2013 -0700
@@ -73,6 +73,7 @@
 bundle.mainreporoot=$TESTTMP
 defaults.backout=-d "0 0"
 defaults.commit=-d "0 0"
+defaults.shelve=--date "0 0"
 defaults.tag=-d "0 0"
 ui.slash=True
 ui.interactive=False
@@ -81,6 +82,7 @@
  runcommand -R foo showconfig ui defaults
 defaults.backout=-d "0 0"
 defaults.commit=-d "0 0"
+defaults.shelve=--date "0 0"
 defaults.tag=-d "0 0"
 ui.slash=True
 ui.interactive=False
--- a/tests/test-convert-filemap.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-convert-filemap.t	Sun Oct 20 16:43:11 2013 -0700
@@ -88,6 +88,32 @@
   copied renamed from foo:2ed2a3912a0b24502043eae84ee4b279c18b90dd
 
   $ cd ..
+
+
+Test interaction with startrev and verify that changing it is handled properly:
+
+  $ > empty
+  $ hg convert --filemap empty source movingstart --config convert.hg.startrev=3 -r4
+  initializing destination movingstart repository
+  scanning source...
+  sorting...
+  converting...
+  1 3: change bar quux
+  0 4: first merge; change bar baz
+  $ hg convert --filemap empty source movingstart
+  scanning source...
+  sorting...
+  converting...
+  3 5: change bar baz quux
+  2 6: change foo baz
+  1 7: second merge; change bar
+  warning: af455ce4166b3c9c88e6309c2b9332171dcea595 parent 61e22ca76c3b3e93df20338c4e02ce286898e825 is missing
+  warning: cf908b3eeedc301c9272ebae931da966d5b326c7 parent 59e1ab45c888289513b7354484dac8a88217beab is missing
+  0 8: change foo
+
+
+splitrepo tests
+
   $ splitrepo()
   > {
   >     msg="$1"
@@ -384,6 +410,32 @@
   o  0 "addb" files: b
   
 
+Test rebuilding of map with unknown revisions in shamap - it used to crash
+
+  $ cd branchpruning
+  $ hg up -r 2
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ hg merge 4
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  (branch merge, don't forget to commit)
+  $ hg ci -m 'merging something'
+  $ cd ..
+  $ echo "53792d18237d2b64971fa571936869156655338d 6d955580116e82c4b029bd30f321323bae71a7f0" >> branchpruning-hg2/.hg/shamap
+  $ hg convert --filemap branchpruning/filemap branchpruning branchpruning-hg2 --debug
+  run hg source pre-conversion action
+  run hg sink pre-conversion action
+  scanning source...
+  scanning: 1 revisions
+  sorting...
+  converting...
+  0 merging something
+  source: 2503605b178fe50e8fbbb0e77b97939540aa8c87
+  converting: 0/1 revisions (0.00%)
+  unknown revmap source: 53792d18237d2b64971fa571936869156655338d
+  run hg sink post-conversion action
+  run hg source post-conversion action
+
+
 filemap rename undoing revision rename
 
   $ hg init renameundo
--- a/tests/test-convert-hg-sink.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-convert-hg-sink.t	Sun Oct 20 16:43:11 2013 -0700
@@ -122,3 +122,271 @@
   tip                                2:6f4fd1df87fb
   some-tag                           0:ba8636729451
   $ cd ..
+
+
+Test cases for hg-hg roundtrip
+
+Helper
+
+  $ glog()
+  > {
+  >     hg log -G --template '{rev} {node|short} "{desc}" files: {files}\n' $*
+  > }
+
+Create a tricky source repo
+
+  $ hg init source
+  $ cd source
+
+  $ echo 0 > 0
+  $ hg ci -Aqm '0: add 0'
+  $ echo a > a
+  $ mkdir dir
+  $ echo b > dir/b
+  $ hg ci -qAm '1: add a and dir/b'
+  $ echo c > dir/c
+  $ hg ci -qAm '2: add dir/c'
+  $ hg copy a e
+  $ echo b >> b
+  $ hg ci -qAm '3: copy a to e, change b'
+  $ hg up -qr -3
+  $ echo a >> a
+  $ hg ci -qAm '4: change a'
+  $ hg merge
+  merging a and e to e
+  2 files updated, 1 files merged, 0 files removed, 0 files unresolved
+  (branch merge, don't forget to commit)
+  $ hg copy b dir/d
+  $ hg ci -qAm '5: merge 2 and 3, copy b to dir/d'
+  $ echo a >> a
+  $ hg ci -qAm '6: change a'
+
+  $ hg mani
+  0
+  a
+  b
+  dir/b
+  dir/c
+  dir/d
+  e
+  $ glog
+  @  6 0613c8e59a3d "6: change a" files: a
+  |
+  o    5 717e9b37cdb7 "5: merge 2 and 3, copy b to dir/d" files: dir/d e
+  |\
+  | o  4 86a55cb968d5 "4: change a" files: a
+  | |
+  o |  3 0e6e235919dd "3: copy a to e, change b" files: b e
+  | |
+  o |  2 0394b0d5e4f7 "2: add dir/c" files: dir/c
+  |/
+  o  1 333546584845 "1: add a and dir/b" files: a dir/b
+  |
+  o  0 d1a24e2ebd23 "0: add 0" files: 0
+  
+  $ cd ..
+
+Convert excluding rev 0 and dir/ (and thus rev2):
+
+  $ cat << EOF > filemap
+  > exclude dir
+  > EOF
+
+  $ hg convert --filemap filemap source dest --config convert.hg.revs=1::
+  initializing destination dest repository
+  scanning source...
+  sorting...
+  converting...
+  5 1: add a and dir/b
+  4 2: add dir/c
+  3 3: copy a to e, change b
+  2 4: change a
+  1 5: merge 2 and 3, copy b to dir/d
+  0 6: change a
+
+Verify that conversion skipped rev 2:
+
+  $ glog -R dest
+  o  4 78814e84a217 "6: change a" files: a
+  |
+  o    3 f7cff662c5e5 "5: merge 2 and 3, copy b to dir/d" files: e
+  |\
+  | o  2 ab40a95b0072 "4: change a" files: a
+  | |
+  o |  1 bd51f17597bf "3: copy a to e, change b" files: b e
+  |/
+  o  0 a4a1dae0fe35 "1: add a and dir/b" files: 0 a
+  
+
+Verify mapping correct in both directions:
+
+  $ cat source/.hg/shamap
+  a4a1dae0fe3514cefd9b8541b7abbc8f44f946d5 333546584845f70c4cfecb992341aaef0e708166
+  bd51f17597bf32268e68a560b206898c3960cda2 0e6e235919dd8e9285ba8eb5adf703af9ad99378
+  ab40a95b00725307e79c2fd271000aa8af9759f4 86a55cb968d51770cba2a1630d6cc637b574580a
+  f7cff662c5e581e6f3f1a85ffdd2bcb35825f6ba 717e9b37cdb7eb9917ca8e30aa3f986e6d5b177d
+  78814e84a217894517c2de392b903ed05e6871a4 0613c8e59a3ddb9789072ef52f1ed13496489bb4
+  $ cat dest/.hg/shamap
+  333546584845f70c4cfecb992341aaef0e708166 a4a1dae0fe3514cefd9b8541b7abbc8f44f946d5
+  0394b0d5e4f761ced559fd0bbdc6afc16cb3f7d1 a4a1dae0fe3514cefd9b8541b7abbc8f44f946d5
+  0e6e235919dd8e9285ba8eb5adf703af9ad99378 bd51f17597bf32268e68a560b206898c3960cda2
+  86a55cb968d51770cba2a1630d6cc637b574580a ab40a95b00725307e79c2fd271000aa8af9759f4
+  717e9b37cdb7eb9917ca8e30aa3f986e6d5b177d f7cff662c5e581e6f3f1a85ffdd2bcb35825f6ba
+  0613c8e59a3ddb9789072ef52f1ed13496489bb4 78814e84a217894517c2de392b903ed05e6871a4
+
+Verify meta data converted correctly:
+
+  $ hg -R dest log -r 1 --debug -p --git
+  changeset:   1:bd51f17597bf32268e68a560b206898c3960cda2
+  phase:       draft
+  parent:      0:a4a1dae0fe3514cefd9b8541b7abbc8f44f946d5
+  parent:      -1:0000000000000000000000000000000000000000
+  manifest:    1:040c72ed9b101773c24ac314776bfc846943781f
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  files+:      b e
+  extra:       branch=default
+  description:
+  3: copy a to e, change b
+  
+  
+  diff --git a/b b/b
+  new file mode 100644
+  --- /dev/null
+  +++ b/b
+  @@ -0,0 +1,1 @@
+  +b
+  diff --git a/a b/e
+  copy from a
+  copy to e
+  
+Verify files included and excluded correctly:
+
+  $ hg -R dest manifest -r tip
+  0
+  a
+  b
+  e
+
+
+Make changes in dest and convert back:
+
+  $ hg -R dest up -q
+  $ echo dest > dest/dest
+  $ hg -R dest ci -Aqm 'change in dest'
+  $ hg -R dest tip
+  changeset:   5:a2e0e3cc6d1d
+  tag:         tip
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     change in dest
+  
+
+(converting merges back after using a filemap will probably cause chaos so we
+exclude merges.)
+
+  $ hg convert dest source --config convert.hg.revs='!merge()'
+  scanning source...
+  sorting...
+  converting...
+  0 change in dest
+
+Verify the conversion back:
+
+  $ hg -R source log --debug -r tip
+  changeset:   7:e6d364a69ff1248b2099e603b0c145504cade6f0
+  tag:         tip
+  phase:       draft
+  parent:      6:0613c8e59a3ddb9789072ef52f1ed13496489bb4
+  parent:      -1:0000000000000000000000000000000000000000
+  manifest:    7:aa3e9542f3b76d4f1f1b2e9c7ce9dbb48b6a95ec
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  files+:      dest
+  extra:       branch=default
+  description:
+  change in dest
+  
+  
+Files that had been excluded are still present:
+
+  $ hg -R source manifest -r tip
+  0
+  a
+  b
+  dest
+  dir/b
+  dir/c
+  dir/d
+  e
+
+More source changes
+
+  $ cd source
+  $ echo 1 >> a
+  $ hg ci -m '8: source first branch'
+  created new head
+  $ hg up -qr -2
+  $ echo 2 >> a
+  $ hg ci -m '9: source second branch'
+  $ hg merge -q --tool internal:local
+  $ hg ci -m '10: source merge'
+  $ echo >> a
+  $ hg ci -m '11: source change'
+
+  $ hg mani
+  0
+  a
+  b
+  dest
+  dir/b
+  dir/c
+  dir/d
+  e
+
+  $ glog -r 6:
+  @  11 0c8927d1f7f4 "11: source change" files: a
+  |
+  o    10 9ccb7ee8d261 "10: source merge" files: a
+  |\
+  | o  9 f131b1518dba "9: source second branch" files: a
+  | |
+  o |  8 669cf0e74b50 "8: source first branch" files: a
+  | |
+  | o  7 e6d364a69ff1 "change in dest" files: dest
+  |/
+  o  6 0613c8e59a3d "6: change a" files: a
+  |
+  $ cd ..
+
+  $ hg convert --filemap filemap source dest --config convert.hg.revs=3:
+  scanning source...
+  sorting...
+  converting...
+  3 8: source first branch
+  2 9: source second branch
+  1 10: source merge
+  0 11: source change
+
+  $ glog -R dest
+  o  9 8432d597b263 "11: source change" files: a
+  |
+  o    8 632ffacdcd6f "10: source merge" files: a
+  |\
+  | o  7 049cfee90ee6 "9: source second branch" files: a
+  | |
+  o |  6 9b6845e036e5 "8: source first branch" files: a
+  | |
+  | @  5 a2e0e3cc6d1d "change in dest" files: dest
+  |/
+  o  4 78814e84a217 "6: change a" files: a
+  |
+  o    3 f7cff662c5e5 "5: merge 2 and 3, copy b to dir/d" files: e
+  |\
+  | o  2 ab40a95b0072 "4: change a" files: a
+  | |
+  o |  1 bd51f17597bf "3: copy a to e, change b" files: b e
+  |/
+  o  0 a4a1dae0fe35 "1: add a and dir/b" files: 0 a
+  
+  $ cd ..
--- a/tests/test-convert-hg-startrev.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-convert-hg-startrev.t	Sun Oct 20 16:43:11 2013 -0700
@@ -183,3 +183,23 @@
   b
   $ hg -q verify
   $ cd ..
+
+Convert from revset in convert.hg.revs
+
+  $ hg convert --config convert.hg.revs='3:4+0' source revsetrepo
+  initializing destination revsetrepo repository
+  scanning source...
+  sorting...
+  converting...
+  2 0: add a b f
+  1 3: change a
+  0 4: merge 2 and 3
+
+  $ glog revsetrepo
+  o  2 "4: merge 2 and 3" files: b c d e f
+  |
+  o  1 "3: change a" files: a
+  |
+  o  0 "0: add a b f" files: a b f
+  
+  $ cd ..
--- a/tests/test-convert.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-convert.t	Sun Oct 20 16:43:11 2013 -0700
@@ -135,9 +135,8 @@
                     store original revision ID in changeset (forces target IDs
                     to change). It takes a boolean argument and defaults to
                     False.
-      convert.hg.startrev
-                    convert start revision and its descendants. It takes a hg
-                    revision identifier and defaults to 0.
+      convert.hg.revs
+                    revset specifying the source revisions to convert.
   
       CVS Source
       ##########
@@ -262,7 +261,7 @@
   
    -s --source-type TYPE source repository type
    -d --dest-type TYPE   destination repository type
-   -r --rev REV          import up to target revision REV
+   -r --rev REV          import up to source revision REV
    -A --authormap FILE   remap usernames using this file
       --filemap FILE     remap file names using contents of file
       --splicemap FILE   splice synthesized history into place
--- a/tests/test-empty.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-empty.t	Sun Oct 20 16:43:11 2013 -0700
@@ -42,8 +42,6 @@
   0 files, 0 changesets, 0 total revisions
   $ ls .hg
   00changelog.i
-  branch
-  dirstate
   hgrc
   requires
   store
--- a/tests/test-extension.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-extension.t	Sun Oct 20 16:43:11 2013 -0700
@@ -129,6 +129,136 @@
   $ echo 'foo = !' >> $HGRCPATH
   $ echo 'bar = !' >> $HGRCPATH
 
+Check "from __future__ import absolute_import" support for external libraries
+
+  $ mkdir $TESTTMP/libroot
+  $ echo "s = 'libroot/ambig.py'" > $TESTTMP/libroot/ambig.py
+  $ mkdir $TESTTMP/libroot/mod
+  $ touch $TESTTMP/libroot/mod/__init__.py
+  $ echo "s = 'libroot/mod/ambig.py'" > $TESTTMP/libroot/mod/ambig.py
+
+#if absimport
+  $ cat > $TESTTMP/libroot/mod/ambigabs.py <<EOF
+  > from __future__ import absolute_import
+  > import ambig # should load "libroot/ambig.py"
+  > s = ambig.s
+  > EOF
+  $ cat > loadabs.py <<EOF
+  > import mod.ambigabs as ambigabs
+  > def extsetup():
+  >     print 'ambigabs.s=%s' % ambigabs.s
+  > EOF
+  $ (PYTHONPATH=$PYTHONPATH:$TESTTMP/libroot; hg --config extensions.loadabs=loadabs.py root)
+  ambigabs.s=libroot/ambig.py
+  $TESTTMP/a
+#endif
+
+#if no-py3k
+  $ cat > $TESTTMP/libroot/mod/ambigrel.py <<EOF
+  > import ambig # should load "libroot/mod/ambig.py"
+  > s = ambig.s
+  > EOF
+  $ cat > loadrel.py <<EOF
+  > import mod.ambigrel as ambigrel
+  > def extsetup():
+  >     print 'ambigrel.s=%s' % ambigrel.s
+  > EOF
+  $ (PYTHONPATH=$PYTHONPATH:$TESTTMP/libroot; hg --config extensions.loadrel=loadrel.py root)
+  ambigrel.s=libroot/mod/ambig.py
+  $TESTTMP/a
+#endif
+
+Check absolute/relative import of extension specific modules
+
+  $ mkdir $TESTTMP/extroot
+  $ cat > $TESTTMP/extroot/bar.py <<EOF
+  > s = 'this is extroot.bar'
+  > EOF
+  $ mkdir $TESTTMP/extroot/sub1
+  $ cat > $TESTTMP/extroot/sub1/__init__.py <<EOF
+  > s = 'this is extroot.sub1.__init__'
+  > EOF
+  $ cat > $TESTTMP/extroot/sub1/baz.py <<EOF
+  > s = 'this is extroot.sub1.baz'
+  > EOF
+  $ cat > $TESTTMP/extroot/__init__.py <<EOF
+  > s = 'this is extroot.__init__'
+  > import foo
+  > def extsetup(ui):
+  >     ui.write('(extroot) ', foo.func(), '\n')
+  > EOF
+
+  $ cat > $TESTTMP/extroot/foo.py <<EOF
+  > # test absolute import
+  > buf = []
+  > def func():
+  >     # "not locals" case
+  >     import extroot.bar
+  >     buf.append('import extroot.bar in func(): %s' % extroot.bar.s)
+  > 
+  >     return '\n(extroot) '.join(buf)
+  > 
+  > # "fromlist == ('*',)" case
+  > from extroot.bar import *
+  > buf.append('from extroot.bar import *: %s' % s)
+  > 
+  > # "not fromlist" and "if '.' in name" case
+  > import extroot.sub1.baz
+  > buf.append('import extroot.sub1.baz: %s' % extroot.sub1.baz.s)
+  > 
+  > # "not fromlist" and NOT "if '.' in name" case
+  > import extroot
+  > buf.append('import extroot: %s' % extroot.s)
+  > 
+  > # NOT "not fromlist" and NOT "level != -1" case
+  > from extroot.bar import s
+  > buf.append('from extroot.bar import s: %s' % s)
+  > EOF
+  $ hg --config extensions.extroot=$TESTTMP/extroot root
+  (extroot) from extroot.bar import *: this is extroot.bar
+  (extroot) import extroot.sub1.baz: this is extroot.sub1.baz
+  (extroot) import extroot: this is extroot.__init__
+  (extroot) from extroot.bar import s: this is extroot.bar
+  (extroot) import extroot.bar in func(): this is extroot.bar
+  $TESTTMP/a
+
+#if no-py3k
+  $ rm -f $TESTTMP/extroot/foo.*
+  $ cat > $TESTTMP/extroot/foo.py <<EOF
+  > # test relative import
+  > buf = []
+  > def func():
+  >     # "not locals" case
+  >     import bar
+  >     buf.append('import bar in func(): %s' % bar.s)
+  > 
+  >     return '\n(extroot) '.join(buf)
+  > 
+  > # "fromlist == ('*',)" case
+  > from bar import *
+  > buf.append('from bar import *: %s' % s)
+  > 
+  > # "not fromlist" and "if '.' in name" case
+  > import sub1.baz
+  > buf.append('import sub1.baz: %s' % sub1.baz.s)
+  > 
+  > # "not fromlist" and NOT "if '.' in name" case
+  > import sub1
+  > buf.append('import sub1: %s' % sub1.s)
+  > 
+  > # NOT "not fromlist" and NOT "level != -1" case
+  > from bar import s
+  > buf.append('from bar import s: %s' % s)
+  > EOF
+  $ hg --config extensions.extroot=$TESTTMP/extroot root
+  (extroot) from bar import *: this is extroot.bar
+  (extroot) import sub1.baz: this is extroot.sub1.baz
+  (extroot) import sub1: this is extroot.sub1.__init__
+  (extroot) from bar import s: this is extroot.bar
+  (extroot) import bar in func(): this is extroot.bar
+  $TESTTMP/a
+#endif
+
   $ cd ..
 
 hide outer repo
@@ -406,17 +536,21 @@
   > EOF
   $ echo "debugissue811 = $debugpath" >> $HGRCPATH
   $ echo "mq=" >> $HGRCPATH
+  $ echo "strip=" >> $HGRCPATH
   $ echo "hgext.mq=" >> $HGRCPATH
   $ echo "hgext/mq=" >> $HGRCPATH
 
 Show extensions:
+(note that mq force load strip, also checking it's not loaded twice)
 
   $ hg debugextensions
   debugissue811
+  strip
   mq
 
 Disabled extension commands:
 
+  $ ORGHGRCPATH=$HGRCPATH
   $ HGRCPATH=
   $ export HGRCPATH
   $ hg help email
@@ -573,3 +707,134 @@
   ** Python * (glob)
   ** Mercurial Distributed SCM (*) (glob)
   ** Extensions loaded: throw
+
+Restore HGRCPATH
+
+  $ HGRCPATH=$ORGHGRCPATH
+  $ export HGRCPATH
+
+Commands handling multiple repositories at a time should invoke only
+"reposetup()" of extensions enabling in the target repository.
+
+  $ mkdir reposetup-test
+  $ cd reposetup-test
+
+  $ cat > $TESTTMP/reposetuptest.py <<EOF
+  > from mercurial import extensions
+  > def reposetup(ui, repo):
+  >     ui.write('reposetup() for %s\n' % (repo.root))
+  > EOF
+  $ hg init src
+  $ echo a > src/a
+  $ hg -R src commit -Am '#0 at src/a'
+  adding a
+  $ echo '[extensions]' >> src/.hg/hgrc
+  $ echo '# enable extension locally' >> src/.hg/hgrc
+  $ echo "reposetuptest = $TESTTMP/reposetuptest.py" >> src/.hg/hgrc
+  $ hg -R src status
+  reposetup() for $TESTTMP/reposetup-test/src
+
+  $ hg clone -U src clone-dst1
+  reposetup() for $TESTTMP/reposetup-test/src
+  $ hg init push-dst1
+  $ hg -q -R src push push-dst1
+  reposetup() for $TESTTMP/reposetup-test/src
+  $ hg init pull-src1
+  $ hg -q -R pull-src1 pull src
+  reposetup() for $TESTTMP/reposetup-test/src
+
+  $ echo '[extensions]' >> $HGRCPATH
+  $ echo '# disable extension globally and explicitly' >> $HGRCPATH
+  $ echo 'reposetuptest = !' >> $HGRCPATH
+  $ hg clone -U src clone-dst2
+  reposetup() for $TESTTMP/reposetup-test/src
+  $ hg init push-dst2
+  $ hg -q -R src push push-dst2
+  reposetup() for $TESTTMP/reposetup-test/src
+  $ hg init pull-src2
+  $ hg -q -R pull-src2 pull src
+  reposetup() for $TESTTMP/reposetup-test/src
+
+  $ echo '[extensions]' >> $HGRCPATH
+  $ echo '# enable extension globally' >> $HGRCPATH
+  $ echo "reposetuptest = $TESTTMP/reposetuptest.py" >> $HGRCPATH
+  $ hg clone -U src clone-dst3
+  reposetup() for $TESTTMP/reposetup-test/src
+  reposetup() for $TESTTMP/reposetup-test/clone-dst3
+  $ hg init push-dst3
+  reposetup() for $TESTTMP/reposetup-test/push-dst3
+  $ hg -q -R src push push-dst3
+  reposetup() for $TESTTMP/reposetup-test/src
+  reposetup() for $TESTTMP/reposetup-test/push-dst3
+  $ hg init pull-src3
+  reposetup() for $TESTTMP/reposetup-test/pull-src3
+  $ hg -q -R pull-src3 pull src
+  reposetup() for $TESTTMP/reposetup-test/pull-src3
+  reposetup() for $TESTTMP/reposetup-test/src
+
+  $ echo '[extensions]' >> src/.hg/hgrc
+  $ echo '# disable extension locally' >> src/.hg/hgrc
+  $ echo 'reposetuptest = !' >> src/.hg/hgrc
+  $ hg clone -U src clone-dst4
+  reposetup() for $TESTTMP/reposetup-test/clone-dst4
+  $ hg init push-dst4
+  reposetup() for $TESTTMP/reposetup-test/push-dst4
+  $ hg -q -R src push push-dst4
+  reposetup() for $TESTTMP/reposetup-test/push-dst4
+  $ hg init pull-src4
+  reposetup() for $TESTTMP/reposetup-test/pull-src4
+  $ hg -q -R pull-src4 pull src
+  reposetup() for $TESTTMP/reposetup-test/pull-src4
+
+disabling in command line overlays with all configuration
+  $ hg --config extensions.reposetuptest=! clone -U src clone-dst5
+  $ hg --config extensions.reposetuptest=! init push-dst5
+  $ hg --config extensions.reposetuptest=! -q -R src push push-dst5
+  $ hg --config extensions.reposetuptest=! init pull-src5
+  $ hg --config extensions.reposetuptest=! -q -R pull-src5 pull src
+
+  $ echo '[extensions]' >> $HGRCPATH
+  $ echo '# disable extension globally and explicitly' >> $HGRCPATH
+  $ echo 'reposetuptest = !' >> $HGRCPATH
+  $ hg init parent
+  $ hg init parent/sub1
+  $ echo 1 > parent/sub1/1
+  $ hg -R parent/sub1 commit -Am '#0 at parent/sub1'
+  adding 1
+  $ hg init parent/sub2
+  $ hg init parent/sub2/sub21
+  $ echo 21 > parent/sub2/sub21/21
+  $ hg -R parent/sub2/sub21 commit -Am '#0 at parent/sub2/sub21'
+  adding 21
+  $ cat > parent/sub2/.hgsub <<EOF
+  > sub21 = sub21
+  > EOF
+  $ hg -R parent/sub2 commit -Am '#0 at parent/sub2'
+  adding .hgsub
+  $ hg init parent/sub3
+  $ echo 3 > parent/sub3/3
+  $ hg -R parent/sub3 commit -Am '#0 at parent/sub3'
+  adding 3
+  $ cat > parent/.hgsub <<EOF
+  > sub1 = sub1
+  > sub2 = sub2
+  > sub3 = sub3
+  > EOF
+  $ hg -R parent commit -Am '#0 at parent'
+  adding .hgsub
+  $ echo '[extensions]' >> parent/.hg/hgrc
+  $ echo '# enable extension locally' >> parent/.hg/hgrc
+  $ echo "reposetuptest = $TESTTMP/reposetuptest.py" >> parent/.hg/hgrc
+  $ cp parent/.hg/hgrc parent/sub2/.hg/hgrc
+  $ hg -R parent status -S -A
+  reposetup() for $TESTTMP/reposetup-test/parent
+  reposetup() for $TESTTMP/reposetup-test/parent/sub2
+  C .hgsub
+  C .hgsubstate
+  C sub1/1
+  C sub2/.hgsub
+  C sub2/.hgsubstate
+  C sub2/sub21/21
+  C sub3/3
+
+  $ cd ..
--- a/tests/test-gendoc.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-gendoc.t	Sun Oct 20 16:43:11 2013 -0700
@@ -9,7 +9,11 @@
   >     echo "% extracting documentation from $LOCALE"
   >     echo ".. -*- coding: utf-8 -*-" > gendoc-$LOCALE.txt
   >     echo "" >> gendoc-$LOCALE.txt
-  >     LC_ALL=$LOCALE python "$TESTDIR/../doc/gendoc.py" >> gendoc-$LOCALE.txt 2> /dev/null || exit
+  >     LANGUAGE=$LOCALE python "$TESTDIR/../doc/gendoc.py" >> gendoc-$LOCALE.txt 2> /dev/null || exit
+  > 
+  >     if [ $LOCALE != C ]; then
+  >         cmp -s gendoc-C.txt gendoc-$LOCALE.txt && echo '** NOTHING TRANSLATED **'
+  >     fi
   > 
   >     # We call runrst without adding "--halt warning" to make it report
   >     # all errors instead of stopping on the first one.
--- a/tests/test-generaldelta.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-generaldelta.t	Sun Oct 20 16:43:11 2013 -0700
@@ -18,6 +18,6 @@
   $ cd ..
   $ regsize=`du -s -b repo/.hg/store/00manifest.i | cut -f 1`
   $ gdsize=`du -s -b gdrepo/.hg/store/00manifest.i | cut -f 1`
-  $ if [ $regsize -gt $gdsize ]; then
+  $ if [ $regsize -lt $gdsize ]; then
   >   echo 'generaldelta increased size of a revlog!'
   > fi
--- a/tests/test-graft.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-graft.t	Sun Oct 20 16:43:11 2013 -0700
@@ -71,7 +71,7 @@
   $ hg up -q 0
   $ echo foo > a
   $ hg graft 1
-  abort: outstanding uncommitted changes
+  abort: uncommitted changes
   [255]
   $ hg revert a
 
@@ -117,7 +117,7 @@
 
   $ hg graft 1 5 4 3 'merge()' 2 -n
   skipping ungraftable merge revision 6
-  skipping already grafted revision 2
+  skipping revision 2 (already grafted to 7)
   grafting revision 1
   grafting revision 5
   grafting revision 4
@@ -126,7 +126,7 @@
   $ hg graft 1 5 4 3 'merge()' 2 --debug
   skipping ungraftable merge revision 6
   scanning for duplicate grafts
-  skipping already grafted revision 2
+  skipping revision 2 (already grafted to 7)
   grafting revision 1
     searching for copies back to rev 1
     unmatched files in local:
@@ -196,9 +196,9 @@
 
   $ hg graft 1 5 4 3 'merge()' 2
   skipping ungraftable merge revision 6
-  skipping already grafted revision 2
-  skipping already grafted revision 1
-  skipping already grafted revision 5
+  skipping revision 2 (already grafted to 7)
+  skipping revision 1 (already grafted to 8)
+  skipping revision 5 (already grafted to 9)
   grafting revision 4
   merging e
   warning: conflicts during merge.
@@ -314,18 +314,18 @@
 Disallow grafting already grafted csets with the same origin onto each other
   $ hg up -q 13
   $ hg graft 2
-  skipping already grafted revision 2
+  skipping revision 2 (already grafted to 13)
   [255]
   $ hg graft 7
-  skipping already grafted revision 7 (same origin 2)
+  skipping already grafted revision 7 (13 also has origin 2)
   [255]
 
   $ hg up -q 7
   $ hg graft 2
-  skipping already grafted revision 2
+  skipping revision 2 (already grafted to 7)
   [255]
   $ hg graft tip
-  skipping already grafted revision 13 (same origin 2)
+  skipping already grafted revision 13 (7 also has origin 2)
   [255]
 
 Graft with --log
--- a/tests/test-help.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-help.t	Sun Oct 20 16:43:11 2013 -0700
@@ -930,8 +930,8 @@
   <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>
+  <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+  number or hash, or <a href="/help/revsets">revset expression</a>.</div>
   </form>
   <table class="bigtable">
   <tr><td colspan="2"><h2><a name="main" href="#topics">Topics</a></h2></td></tr>
@@ -1490,8 +1490,8 @@
   <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>
+  <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+  number or hash, or <a href="/help/revsets">revset expression</a>.</div>
   </form>
   <div id="doc">
   <p>
@@ -1656,8 +1656,8 @@
   <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>
+  <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+  number or hash, or <a href="/help/revsets">revset expression</a>.</div>
   </form>
   <div id="doc">
   <p>
@@ -1852,8 +1852,8 @@
   <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>
+  <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+  number or hash, or <a href="/help/revsets">revset expression</a>.</div>
   </form>
   <div id="doc">
   <h1>Specifying Single Revisions</h1>
--- a/tests/test-hgweb-commands.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-hgweb-commands.t	Sun Oct 20 16:43:11 2013 -0700
@@ -258,8 +258,8 @@
   <form class="search" action="/log">
   
   <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
-  <div id="hint">find changesets by author, revision,
-  files, or words in the commit message</div>
+  <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+  number or hash, or <a href="/help/revsets">revset expression</a>.</div>
   </form>
   
   <div class="navigate">
@@ -305,6 +305,21 @@
   | rev 3: <a href="/shortlog/2ef0ac749a14">(0)</a> <a href="/shortlog/tip">tip</a> 
   </div>
   
+  <script type="text/javascript">
+      ajaxScrollInit(
+              '/shortlog/%next%',
+              '', <!-- NEXTHASH
+              function (htmlText, previousVal) {
+                  var m = htmlText.match(/'(\w+)', <!-- NEXTHASH/);
+                  return m ? m[1] : null;
+              },
+              '.bigtable > tbody:nth-of-type(2)',
+              '<tr class="%class%">\
+              <td colspan="3" style="text-align: center;">%text%</td>\
+              </tr>'
+      );
+  </script>
+  
   </div>
   </div>
   
@@ -362,8 +377,8 @@
   <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>
+  <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+  number or hash, or <a href="/help/revsets">revset expression</a>.</div>
   </form>
   
   <div class="description">base</div>
@@ -495,11 +510,17 @@
   <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
   <h3>searching for 'base'</h3>
   
+  <p>
+  Assuming literal keyword search.
+  
+  
+  </p>
+  
   <form class="search" action="/log">
   
   <p><input name="rev" id="search1" type="text" size="30" value="base"></p>
-  <div id="hint">find changesets by author, revision,
-  files, or words in the commit message</div>
+  <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+  number or hash, or <a href="/help/revsets">revset expression</a>.</div>
   </form>
   
   <div class="navigate">
@@ -537,6 +558,162 @@
   </body>
   </html>
   
+  $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=stable&style=raw' | grep 'revision:'
+  revision:    2
+
+Search with revset syntax
+
+  $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=tip^&style=raw'
+  200 Script output follows
+  
+  
+  # HG changesets search
+  # Node ID cad8025a2e87f88c06259790adfa15acb4080123
+  # Query "tip^"
+  # Mode revset expression search
+  
+  changeset:   1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe
+  revision:    2
+  user:        test
+  date:        Thu, 01 Jan 1970 00:00:00 +0000
+  summary:     branch
+  branch:      stable
+  
+  
+  $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=last(all(),2)^&style=raw'
+  200 Script output follows
+  
+  
+  # HG changesets search
+  # Node ID cad8025a2e87f88c06259790adfa15acb4080123
+  # Query "last(all(),2)^"
+  # Mode revset expression search
+  
+  changeset:   1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe
+  revision:    2
+  user:        test
+  date:        Thu, 01 Jan 1970 00:00:00 +0000
+  summary:     branch
+  branch:      stable
+  
+  changeset:   a4f92ed23982be056b9852de5dfe873eaac7f0de
+  revision:    1
+  user:        test
+  date:        Thu, 01 Jan 1970 00:00:00 +0000
+  summary:     Added tag 1.0 for changeset 2ef0ac749a14
+  branch:      default
+  
+  
+  $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=last(all(,2)^&style=raw'
+  200 Script output follows
+  
+  
+  # HG changesets search
+  # Node ID cad8025a2e87f88c06259790adfa15acb4080123
+  # Query "last(all(,2)^"
+  # Mode literal keyword search
+  
+  
+  $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=last(al(),2)^&style=raw'
+  200 Script output follows
+  
+  
+  # HG changesets search
+  # Node ID cad8025a2e87f88c06259790adfa15acb4080123
+  # Query "last(al(),2)^"
+  # Mode literal keyword search
+  
+  
+  $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=bookmark(anotherthing)&style=raw'
+  200 Script output follows
+  
+  
+  # HG changesets search
+  # Node ID cad8025a2e87f88c06259790adfa15acb4080123
+  # Query "bookmark(anotherthing)"
+  # Mode revset expression search
+  
+  changeset:   2ef0ac749a14e4f57a5a822464a0902c6f7f448f
+  revision:    0
+  user:        test
+  date:        Thu, 01 Jan 1970 00:00:00 +0000
+  summary:     base
+  tag:         1.0
+  bookmark:    anotherthing
+  
+  
+  $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=bookmark(abc)&style=raw'
+  200 Script output follows
+  
+  
+  # HG changesets search
+  # Node ID cad8025a2e87f88c06259790adfa15acb4080123
+  # Query "bookmark(abc)"
+  # Mode literal keyword search
+  
+  
+  $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=deadbeef:&style=raw'
+  200 Script output follows
+  
+  
+  # HG changesets search
+  # Node ID cad8025a2e87f88c06259790adfa15acb4080123
+  # Query "deadbeef:"
+  # Mode literal keyword search
+  
+  
+
+  $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=user("test")&style=raw'
+  200 Script output follows
+  
+  
+  # HG changesets search
+  # Node ID cad8025a2e87f88c06259790adfa15acb4080123
+  # Query "user("test")"
+  # Mode revset expression search
+  
+  changeset:   cad8025a2e87f88c06259790adfa15acb4080123
+  revision:    3
+  user:        test
+  date:        Thu, 01 Jan 1970 00:00:00 +0000
+  summary:     branch commit with null character: \x00 (esc)
+  branch:      unstable
+  tag:         tip
+  bookmark:    something
+  
+  changeset:   1d22e65f027e5a0609357e7d8e7508cd2ba5d2fe
+  revision:    2
+  user:        test
+  date:        Thu, 01 Jan 1970 00:00:00 +0000
+  summary:     branch
+  branch:      stable
+  
+  changeset:   a4f92ed23982be056b9852de5dfe873eaac7f0de
+  revision:    1
+  user:        test
+  date:        Thu, 01 Jan 1970 00:00:00 +0000
+  summary:     Added tag 1.0 for changeset 2ef0ac749a14
+  branch:      default
+  
+  changeset:   2ef0ac749a14e4f57a5a822464a0902c6f7f448f
+  revision:    0
+  user:        test
+  date:        Thu, 01 Jan 1970 00:00:00 +0000
+  summary:     base
+  tag:         1.0
+  bookmark:    anotherthing
+  
+  
+  $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'log?rev=user("re:test")&style=raw'
+  200 Script output follows
+  
+  
+  # HG changesets search
+  # Node ID cad8025a2e87f88c06259790adfa15acb4080123
+  # Query "user("re:test")"
+  # Mode literal keyword search
+  
+  
 
 File-related
 
@@ -614,8 +791,8 @@
   <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>
+  <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+  number or hash, or <a href="/help/revsets">revset expression</a>.</div>
   </form>
   
   <div class="description">Added tag 1.0 for changeset 2ef0ac749a14</div>
@@ -637,7 +814,6 @@
    <th class="author">children</th>
    <td class="author"><a href="/file/1d22e65f027e/foo">1d22e65f027e</a> </td>
   </tr>
-  
   </table>
   
   <div class="overflow">
@@ -1256,8 +1432,10 @@
 
 Graph json escape of multibyte character
 
-  $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'graph/' \
-  >     | grep -a '^var data ='
+  $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT 'graph/' > out
+  >>> for line in open("out"):
+  ...     if line.startswith("var data ="):
+  ...         print line,
   var data = [["061dd13ba3c3", [0, 1], [[0, 0, 1, -1, ""]], "\\u80fd", "test", "1970-01-01", ["unstable", true], ["tip"], ["something"]], ["cad8025a2e87", [0, 1], [[0, 0, 1, 3, "FF0000"]], "branch commit with null character: \x00", "test", "1970-01-01", ["unstable", false], [], []], ["1d22e65f027e", [0, 1], [[0, 0, 1, 3, ""]], "branch", "test", "1970-01-01", ["stable", true], [], []], ["a4f92ed23982", [0, 1], [[0, 0, 1, 3, ""]], "Added tag 1.0 for changeset 2ef0ac749a14", "test", "1970-01-01", ["default", true], [], []], ["2ef0ac749a14", [0, 1], [], "base", "test", "1970-01-01", ["default", false], ["1.0"], ["anotherthing"]]]; (esc)
 
 capabilities
--- a/tests/test-hgweb-descend-empties.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-hgweb-descend-empties.t	Sun Oct 20 16:43:11 2013 -0700
@@ -76,8 +76,8 @@
   <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>
+  <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+  number or hash, or <a href="/help/revsets">revset expression</a>.</div>
   </form>
   
   <table class="bigtable">
--- a/tests/test-hgweb-diffs.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-hgweb-diffs.t	Sun Oct 20 16:43:11 2013 -0700
@@ -84,8 +84,8 @@
   <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>
+  <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+  number or hash, or <a href="/help/revsets">revset expression</a>.</div>
   </form>
   
   <div class="description">a</div>
@@ -246,8 +246,8 @@
   <form class="search" action="/log">
   <p></p>
   <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>
+  <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+  number or hash, or <a href="/help/revsets">revset expression</a>.</div>
   </form>
   
   <div class="description">b</div>
@@ -269,7 +269,6 @@
    <th>children</th>
    <td></td>
   </tr>
-  
   </table>
   
   <div class="overflow">
@@ -349,8 +348,8 @@
   <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>
+  <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+  number or hash, or <a href="/help/revsets">revset expression</a>.</div>
   </form>
   
   <div class="description">a</div>
@@ -515,8 +514,8 @@
   <form class="search" action="/log">
   <p></p>
   <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>
+  <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+  number or hash, or <a href="/help/revsets">revset expression</a>.</div>
   </form>
   
   <div class="description">b</div>
@@ -538,7 +537,6 @@
    <th>children</th>
    <td></td>
   </tr>
-  
   </table>
   
   <div class="overflow">
@@ -615,8 +613,8 @@
   <form class="search" action="/log">
   <p></p>
   <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>
+  <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+  number or hash, or <a href="/help/revsets">revset expression</a>.</div>
   </form>
   
   <div class="description">a</div>
@@ -638,7 +636,6 @@
    <th>children</th>
    <td></td>
   </tr>
-  
   </table>
   
   <div class="overflow">
@@ -737,8 +734,8 @@
   <form class="search" action="/log">
   <p></p>
   <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>
+  <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+  number or hash, or <a href="/help/revsets">revset expression</a>.</div>
   </form>
   
   <div class="description">c</div>
@@ -760,7 +757,6 @@
    <th>children</th>
    <td></td>
   </tr>
-  
   </table>
   
   <div class="overflow">
@@ -861,8 +857,8 @@
   <form class="search" action="/log">
   <p></p>
   <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>
+  <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+  number or hash, or <a href="/help/revsets">revset expression</a>.</div>
   </form>
   
   <div class="description">d</div>
@@ -884,7 +880,6 @@
    <th>children</th>
    <td></td>
   </tr>
-  
   </table>
   
   <div class="overflow">
--- a/tests/test-hgweb-empty.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-hgweb-empty.t	Sun Oct 20 16:43:11 2013 -0700
@@ -63,8 +63,8 @@
   <form class="search" action="/log">
   
   <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
-  <div id="hint">find changesets by author, revision,
-  files, or words in the commit message</div>
+  <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+  number or hash, or <a href="/help/revsets">revset expression</a>.</div>
   </form>
   
   <div class="navigate">
@@ -90,6 +90,21 @@
   | rev -1: 
   </div>
   
+  <script type="text/javascript">
+      ajaxScrollInit(
+              '/shortlog/%next%',
+              '', <!-- NEXTHASH
+              function (htmlText, previousVal) {
+                  var m = htmlText.match(/'(\w+)', <!-- NEXTHASH/);
+                  return m ? m[1] : null;
+              },
+              '.bigtable > tbody:nth-of-type(2)',
+              '<tr class="%class%">\
+              <td colspan="3" style="text-align: center;">%text%</td>\
+              </tr>'
+      );
+  </script>
+  
   </div>
   </div>
   
@@ -158,8 +173,8 @@
   <form class="search" action="/log">
   
   <p><input name="rev" id="search1" type="text" size="30" value="" /></p>
-  <div id="hint">find changesets by author, revision,
-  files, or words in the commit message</div>
+  <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+  number or hash, or <a href="/help/revsets">revset expression</a>.</div>
   </form>
   
   <div class="navigate">
@@ -185,6 +200,21 @@
   | rev -1: 
   </div>
   
+  <script type="text/javascript">
+      ajaxScrollInit(
+              '/shortlog/%next%',
+              '', <!-- NEXTHASH
+              function (htmlText, previousVal) {
+                  var m = htmlText.match(/'(\w+)', <!-- NEXTHASH/);
+                  return m ? m[1] : null;
+              },
+              '.bigtable > tbody:nth-of-type(2)',
+              '<tr class="%class%">\
+              <td colspan="3" style="text-align: center;">%text%</td>\
+              </tr>'
+      );
+  </script>
+  
   </div>
   </div>
   
@@ -249,8 +279,8 @@
   <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>
+  <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+  number or hash, or <a href="/help/revsets">revset expression</a>.</div>
   </form>
   
   <div class="navigate">
@@ -329,6 +359,17 @@
   | rev -1: 
   </div>
   
+  <script type="text/javascript">
+      ajaxScrollInit(
+              '/graph/-1?revcount=%next%',
+              60+60,
+              function (htmlText, previousVal) { return previousVal + 60; },
+              '#wrapper',
+              '<div class="%class%" style="text-align: center;">%text%</div>',
+              'graph'
+      );
+  </script>
+  
   </div>
   </div>
   
@@ -385,8 +426,8 @@
   <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>
+  <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+  number or hash, or <a href="/help/revsets">revset expression</a>.</div>
   </form>
   
   <table class="bigtable">
--- a/tests/test-hgweb-filelog.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-hgweb-filelog.t	Sun Oct 20 16:43:11 2013 -0700
@@ -170,8 +170,8 @@
   <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>
+  <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+  number or hash, or <a href="/help/revsets">revset expression</a>.</div>
   </form>
   
   <div class="navigate">
@@ -279,8 +279,8 @@
   <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>
+  <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+  number or hash, or <a href="/help/revsets">revset expression</a>.</div>
   </form>
   
   <div class="navigate">
@@ -388,8 +388,8 @@
   <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>
+  <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+  number or hash, or <a href="/help/revsets">revset expression</a>.</div>
   </form>
   
   <div class="navigate">
@@ -492,8 +492,8 @@
   <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>
+  <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+  number or hash, or <a href="/help/revsets">revset expression</a>.</div>
   </form>
   
   <div class="navigate">
@@ -576,8 +576,8 @@
   <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>
+  <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+  number or hash, or <a href="/help/revsets">revset expression</a>.</div>
   </form>
   
   <div class="description">
--- a/tests/test-hgweb-removed.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-hgweb-removed.t	Sun Oct 20 16:43:11 2013 -0700
@@ -65,8 +65,8 @@
   <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>
+  <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+  number or hash, or <a href="/help/revsets">revset expression</a>.</div>
   </form>
   
   <div class="description">del</div>
@@ -190,8 +190,8 @@
   <form class="search" action="/log">
   <p></p>
   <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>
+  <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+  number or hash, or <a href="/help/revsets">revset expression</a>.</div>
   </form>
   
   <div class="description">del</div>
@@ -213,7 +213,6 @@
    <th>children</th>
    <td></td>
   </tr>
-  
   </table>
   
   <div class="overflow">
--- a/tests/test-hgweb.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-hgweb.t	Sun Oct 20 16:43:11 2013 -0700
@@ -81,8 +81,8 @@
   <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>
+  <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+  number or hash, or <a href="/help/revsets">revset expression</a>.</div>
   </form>
   
   <div class="description">
@@ -171,8 +171,8 @@
   <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>
+  <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+  number or hash, or <a href="/help/revsets">revset expression</a>.</div>
   </form>
   
   <div class="description">
@@ -249,8 +249,8 @@
   <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>
+  <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+  number or hash, or <a href="/help/revsets">revset expression</a>.</div>
   </form>
   
   <table class="bigtable">
--- a/tests/test-highlight.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-highlight.t	Sun Oct 20 16:43:11 2013 -0700
@@ -109,8 +109,8 @@
   <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>
+  <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+  number or hash, or <a href="/help/revsets">revset expression</a>.</div>
   </form>
   
   <div class="description">a</div>
@@ -132,7 +132,6 @@
    <th class="author">children</th>
    <td class="author"></td>
   </tr>
-  
   </table>
   
   <div class="overflow">
@@ -241,8 +240,8 @@
   <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>
+  <div id="hint">Find changesets by keywords (author, files, the commit message), revision
+  number or hash, or <a href="/help/revsets">revset expression</a>.</div>
   </form>
   
   <div class="description">a</div>
@@ -264,7 +263,6 @@
    <th class="author">children</th>
    <td class="author"></td>
   </tr>
-  
   </table>
   
   <div class="overflow">
--- a/tests/test-histedit-obsolete.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-histedit-obsolete.t	Sun Oct 20 16:43:11 2013 -0700
@@ -148,6 +148,7 @@
 stabilise
 
   $ hg rebase  -r 'unstable()' -d .
+  $ hg up tip -q
 
 Test dropping of changeset on the top of the stack
 -------------------------------------------------------
--- a/tests/test-import-merge.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-import-merge.t	Sun Oct 20 16:43:11 2013 -0700
@@ -129,7 +129,9 @@
   $ echo a>>a
   $ hg ci -m3
   $ hg export 2 | head -7 > ../a.patch
-  $ hg export tip | tail -n +8 >> ../a.patch
+  $ hg export tip > out
+  >>> apatch = open("../a.patch", "a")
+  >>> apatch.write("".join(open("out").readlines()[7:]))
 
   $ cd ..
   $ hg clone -qr0 repo3 repo3-clone
--- a/tests/test-issue1502.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-issue1502.t	Sun Oct 20 16:43:11 2013 -0700
@@ -19,7 +19,8 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
-  not updating: crosses branches (merge branches or update --check to force update)
+  not updating: not a linear update
+  (merge or update --check to force update)
 
   $ hg -R foo1 book branchy
   $ hg -R foo1 book
--- a/tests/test-largefiles.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-largefiles.t	Sun Oct 20 16:43:11 2013 -0700
@@ -1104,7 +1104,7 @@
 
 "update --check" refuses to update with uncommitted changes.
   $ hg update --check 8
-  abort: uncommitted local changes
+  abort: uncommitted changes
   [255]
 
 "update --clean" leaves correct largefiles in working copy, even when there is
@@ -2191,3 +2191,64 @@
   
 
   $ cd ..
+
+Check whether "largefiles" feature is supported only in repositories
+enabling largefiles extension.
+
+  $ mkdir individualenabling
+  $ cd individualenabling
+
+  $ hg init enabledlocally
+  $ echo large > enabledlocally/large
+  $ hg -R enabledlocally add --large enabledlocally/large
+  $ hg -R enabledlocally commit -m '#0'
+  Invoking status precommit hook
+  A large
+
+  $ hg init notenabledlocally
+  $ echo large > notenabledlocally/large
+  $ hg -R notenabledlocally add --large notenabledlocally/large
+  $ hg -R notenabledlocally commit -m '#0'
+  Invoking status precommit hook
+  A large
+
+  $ cat >> $HGRCPATH <<EOF
+  > [extensions]
+  > # disable globally
+  > largefiles=!
+  > EOF
+  $ cat >> enabledlocally/.hg/hgrc <<EOF
+  > [extensions]
+  > # enable locally
+  > largefiles=
+  > EOF
+  $ hg -R enabledlocally root
+  $TESTTMP/individualenabling/enabledlocally
+  $ hg -R notenabledlocally root
+  abort: unknown repository format: requires features 'largefiles' (upgrade Mercurial)!
+  [255]
+
+  $ hg init push-dst
+  $ hg -R enabledlocally push push-dst
+  pushing to push-dst
+  abort: required features are not supported in the destination: largefiles
+  [255]
+
+  $ hg init pull-src
+  $ hg -R pull-src pull enabledlocally
+  pulling from enabledlocally
+  abort: required features are not supported in the destination: largefiles
+  [255]
+
+  $ hg clone enabledlocally clone-dst
+  abort: unknown repository format: requires features 'largefiles' (upgrade Mercurial)!
+  [255]
+  $ test -d clone-dst
+  [1]
+  $ hg clone --pull enabledlocally clone-pull-dst
+  abort: required features are not supported in the destination: largefiles
+  [255]
+  $ test -d clone-pull-dst
+  [1]
+
+  $ cd ..
--- a/tests/test-lrucachedict.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-lrucachedict.py	Sun Oct 20 16:43:11 2013 -0700
@@ -31,5 +31,8 @@
     d['f'] = 'vf'
     printifpresent(d, ['b', 'c', 'd', 'e', 'f'])
 
+    d.clear()
+    printifpresent(d, ['b', 'c', 'd', 'e', 'f'])
+
 if __name__ == '__main__':
     test_lrucachedict()
--- a/tests/test-lrucachedict.py.out	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-lrucachedict.py.out	Sun Oct 20 16:43:11 2013 -0700
@@ -24,3 +24,8 @@
 'e' in d: False
 'f' in d: True
 d['f']: vf
+'b' in d: False
+'c' in d: False
+'d' in d: False
+'e' in d: False
+'f' in d: False
--- a/tests/test-merge-force.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-merge-force.t	Sun Oct 20 16:43:11 2013 -0700
@@ -19,7 +19,7 @@
 Should fail, since there are deleted files:
 
   $ hg merge
-  abort: outstanding uncommitted changes
+  abort: uncommitted changes
   (use 'hg status' to list changes)
   [255]
 
--- a/tests/test-merge-subrepos.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-merge-subrepos.t	Sun Oct 20 16:43:11 2013 -0700
@@ -21,5 +21,5 @@
 Should fail, since there are added files to subrepo:
 
   $ hg merge
-  abort: outstanding uncommitted changes in subrepository 'subrepo'
+  abort: uncommitted changes in subrepository 'subrepo'
   [255]
--- a/tests/test-merge1.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-merge1.t	Sun Oct 20 16:43:11 2013 -0700
@@ -140,7 +140,7 @@
   $ echo This is file b22 > b
 merge fails
   $ hg merge 2
-  abort: outstanding uncommitted changes
+  abort: uncommitted changes
   (use 'hg status' to list changes)
   [255]
 merge expected!
@@ -177,7 +177,7 @@
   $ echo This is file b33 > b
 merge of b should fail
   $ hg merge 2
-  abort: outstanding uncommitted changes
+  abort: uncommitted changes
   (use 'hg status' to list changes)
   [255]
 merge of b expected
--- a/tests/test-merge5.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-merge5.t	Sun Oct 20 16:43:11 2013 -0700
@@ -14,11 +14,12 @@
   $ hg update 1
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg update
-  abort: crosses branches (merge branches or update --check to force update)
+  abort: not a linear update
+  (merge or update --check to force update)
   [255]
   $ rm b
   $ hg update -c
-  abort: uncommitted local changes
+  abort: uncommitted changes
   [255]
   $ hg revert b
   $ hg update -c
@@ -32,7 +33,8 @@
 Should abort:
 
   $ hg update -y 1
-  abort: crosses branches (merge branches or use --clean to discard changes)
+  abort: uncommitted changes
+  (commit or update --clean to discard changes)
   [255]
   $ mv c a
 
--- a/tests/test-mq-qpush-exact.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-mq-qpush-exact.t	Sun Oct 20 16:43:11 2013 -0700
@@ -243,6 +243,7 @@
   +cp1
   $ hg qpop -aqf
   patch queue now empty
+  $ hg forget fp1
   $ rm fp1
   $ rm fp1.rej
 
--- a/tests/test-mq-strip.t	Sat Oct 19 14:20:31 2013 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,503 +0,0 @@
-  $ echo "[extensions]" >> $HGRCPATH
-  $ echo "mq=" >> $HGRCPATH
-  $ echo "graphlog=" >> $HGRCPATH
-
-  $ restore() {
-  >     hg unbundle -q .hg/strip-backup/*
-  >     rm .hg/strip-backup/*
-  > }
-  $ teststrip() {
-  >     hg up -C $1
-  >     echo % before update $1, strip $2
-  >     hg parents
-  >     hg --traceback strip $2
-  >     echo % after update $1, strip $2
-  >     hg parents
-  >     restore
-  > }
-
-  $ hg init test
-  $ cd test
-
-  $ echo foo > bar
-  $ hg ci -Ama
-  adding bar
-
-  $ echo more >> bar
-  $ hg ci -Amb
-
-  $ echo blah >> bar
-  $ hg ci -Amc
-
-  $ hg up 1
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ echo blah >> bar
-  $ hg ci -Amd
-  created new head
-
-  $ echo final >> bar
-  $ hg ci -Ame
-
-  $ hg log
-  changeset:   4:443431ffac4f
-  tag:         tip
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     e
-  
-  changeset:   3:65bd5f99a4a3
-  parent:      1:ef3a871183d7
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     d
-  
-  changeset:   2:264128213d29
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     c
-  
-  changeset:   1:ef3a871183d7
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     b
-  
-  changeset:   0:9ab35a2d17cb
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     a
-  
-
-  $ teststrip 4 4
-  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  % before update 4, strip 4
-  changeset:   4:443431ffac4f
-  tag:         tip
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     e
-  
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
-  % after update 4, strip 4
-  changeset:   3:65bd5f99a4a3
-  tag:         tip
-  parent:      1:ef3a871183d7
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     d
-  
-  $ teststrip 4 3
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  % before update 4, strip 3
-  changeset:   4:443431ffac4f
-  tag:         tip
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     e
-  
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
-  % after update 4, strip 3
-  changeset:   1:ef3a871183d7
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     b
-  
-  $ teststrip 1 4
-  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  % before update 1, strip 4
-  changeset:   1:ef3a871183d7
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     b
-  
-  saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
-  % after update 1, strip 4
-  changeset:   1:ef3a871183d7
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     b
-  
-  $ teststrip 4 2
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  % before update 4, strip 2
-  changeset:   4:443431ffac4f
-  tag:         tip
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     e
-  
-  saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
-  % after update 4, strip 2
-  changeset:   3:443431ffac4f
-  tag:         tip
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     e
-  
-  $ teststrip 4 1
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  % before update 4, strip 1
-  changeset:   4:264128213d29
-  tag:         tip
-  parent:      1:ef3a871183d7
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     c
-  
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
-  % after update 4, strip 1
-  changeset:   0:9ab35a2d17cb
-  tag:         tip
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     a
-  
-  $ teststrip null 4
-  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
-  % before update null, strip 4
-  saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
-  % after update null, strip 4
-
-  $ hg log
-  changeset:   4:264128213d29
-  tag:         tip
-  parent:      1:ef3a871183d7
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     c
-  
-  changeset:   3:443431ffac4f
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     e
-  
-  changeset:   2:65bd5f99a4a3
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     d
-  
-  changeset:   1:ef3a871183d7
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     b
-  
-  changeset:   0:9ab35a2d17cb
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     a
-  
-
-  $ hg up -C 2
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ hg merge 4
-  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  (branch merge, don't forget to commit)
-
-before strip of merge parent
-
-  $ hg parents
-  changeset:   2:65bd5f99a4a3
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     d
-  
-  changeset:   4:264128213d29
-  tag:         tip
-  parent:      1:ef3a871183d7
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     c
-  
-  $ hg strip 4
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
-
-after strip of merge parent
-
-  $ hg parents
-  changeset:   1:ef3a871183d7
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     b
-  
-  $ restore
-
-  $ hg up
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ hg glog
-  @  changeset:   4:264128213d29
-  |  tag:         tip
-  |  parent:      1:ef3a871183d7
-  |  user:        test
-  |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  summary:     c
-  |
-  | o  changeset:   3:443431ffac4f
-  | |  user:        test
-  | |  date:        Thu Jan 01 00:00:00 1970 +0000
-  | |  summary:     e
-  | |
-  | o  changeset:   2:65bd5f99a4a3
-  |/   user:        test
-  |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    summary:     d
-  |
-  o  changeset:   1:ef3a871183d7
-  |  user:        test
-  |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  summary:     b
-  |
-  o  changeset:   0:9ab35a2d17cb
-     user:        test
-     date:        Thu Jan 01 00:00:00 1970 +0000
-     summary:     a
-  
-
-2 is parent of 3, only one strip should happen
-
-  $ hg strip "roots(2)" 3
-  saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
-  $ hg glog
-  @  changeset:   2:264128213d29
-  |  tag:         tip
-  |  user:        test
-  |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  summary:     c
-  |
-  o  changeset:   1:ef3a871183d7
-  |  user:        test
-  |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  summary:     b
-  |
-  o  changeset:   0:9ab35a2d17cb
-     user:        test
-     date:        Thu Jan 01 00:00:00 1970 +0000
-     summary:     a
-  
-  $ restore
-  $ hg glog
-  o  changeset:   4:443431ffac4f
-  |  tag:         tip
-  |  user:        test
-  |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  summary:     e
-  |
-  o  changeset:   3:65bd5f99a4a3
-  |  parent:      1:ef3a871183d7
-  |  user:        test
-  |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  summary:     d
-  |
-  | @  changeset:   2:264128213d29
-  |/   user:        test
-  |    date:        Thu Jan 01 00:00:00 1970 +0000
-  |    summary:     c
-  |
-  o  changeset:   1:ef3a871183d7
-  |  user:        test
-  |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  summary:     b
-  |
-  o  changeset:   0:9ab35a2d17cb
-     user:        test
-     date:        Thu Jan 01 00:00:00 1970 +0000
-     summary:     a
-  
-
-2 different branches: 2 strips
-
-  $ hg strip 2 4
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
-  $ hg glog
-  o  changeset:   2:65bd5f99a4a3
-  |  tag:         tip
-  |  user:        test
-  |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  summary:     d
-  |
-  @  changeset:   1:ef3a871183d7
-  |  user:        test
-  |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  summary:     b
-  |
-  o  changeset:   0:9ab35a2d17cb
-     user:        test
-     date:        Thu Jan 01 00:00:00 1970 +0000
-     summary:     a
-  
-  $ restore
-
-2 different branches and a common ancestor: 1 strip
-
-  $ hg strip 1 "2|4"
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
-  $ restore
-
-stripping an empty revset
-
-  $ hg strip "1 and not 1"
-  abort: empty revision set
-  [255]
-
-remove branchy history for qimport tests
-
-  $ hg strip 3
-  saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
-
-
-strip of applied mq should cleanup status file
-
-  $ hg up -C 3
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ echo fooagain >> bar
-  $ hg ci -mf
-  $ hg qimport -r tip:2
-
-applied patches before strip
-
-  $ hg qapplied
-  2.diff
-  3.diff
-  4.diff
-
-stripping revision in queue
-
-  $ hg strip 3
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
-
-applied patches after stripping rev in queue
-
-  $ hg qapplied
-  2.diff
-
-stripping ancestor of queue
-
-  $ hg strip 1
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
-
-applied patches after stripping ancestor of queue
-
-  $ hg qapplied
-
-Verify strip protects against stripping wc parent when there are uncommited mods
-
-  $ echo b > b
-  $ hg add b
-  $ hg ci -m 'b'
-  $ hg log --graph
-  @  changeset:   1:7519abd79d14
-  |  tag:         tip
-  |  user:        test
-  |  date:        Thu Jan 01 00:00:00 1970 +0000
-  |  summary:     b
-  |
-  o  changeset:   0:9ab35a2d17cb
-     user:        test
-     date:        Thu Jan 01 00:00:00 1970 +0000
-     summary:     a
-  
-
-  $ echo c > b
-  $ echo c > bar
-  $ hg strip tip
-  abort: local changes found
-  [255]
-  $ hg strip tip --keep
-  saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
-  $ hg log --graph
-  @  changeset:   0:9ab35a2d17cb
-     tag:         tip
-     user:        test
-     date:        Thu Jan 01 00:00:00 1970 +0000
-     summary:     a
-  
-  $ hg status
-  M bar
-  ? b
-
-Strip adds, removes, modifies with --keep
-
-  $ touch b
-  $ hg add b
-  $ hg commit -mb
-  $ touch c
-
-... with a clean working dir
-
-  $ hg add c
-  $ hg rm bar
-  $ hg commit -mc
-  $ hg status
-  $ hg strip --keep tip
-  saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
-  $ hg status
-  ! bar
-  ? c
-
-... with a dirty working dir
-
-  $ hg add c
-  $ hg rm bar
-  $ hg commit -mc
-  $ hg status
-  $ 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)
-
-  $ hg init issue3299
-  $ cd issue3299
-  $ hg debugbuilddag '@a.:a@b.:b.:x<a@a.:a<b@b.:b<a@a.:a'
-  $ hg strip 'not ancestors(x)'
-  saved backup bundle to $TESTTMP/issue3299/.hg/strip-backup/*-backup.hg (glob)
-
-test hg strip -B bookmark
-
-  $ cd ..
-  $ hg init bookmarks
-  $ cd bookmarks
-  $ hg debugbuilddag '..<2.*1/2:m<2+3:c<m+3:a<2.:b'
-  $ hg bookmark -r 'a' 'todelete'
-  $ hg bookmark -r 'b' 'B'
-  $ hg bookmark -r 'b' 'nostrip'
-  $ hg bookmark -r 'c' 'delete'
-  $ hg up -C todelete
-  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ hg strip -B nostrip
-  bookmark 'nostrip' deleted
-  abort: empty revision set
-  [255]
-  $ hg strip -B todelete
-  bookmark 'todelete' deleted
-  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  saved backup bundle to $TESTTMP/bookmarks/.hg/strip-backup/*-backup.hg (glob)
-  $ hg id -ir dcbb326fdec2
-  abort: unknown revision 'dcbb326fdec2'!
-  [255]
-  $ hg id -ir d62d843c9a01
-  d62d843c9a01
-  $ hg bookmarks
-     B                         9:ff43616e5d0f
-     delete                    6:2702dd0c91e7
-  $ hg strip -B delete
-  bookmark 'delete' deleted
-  saved backup bundle to $TESTTMP/bookmarks/.hg/strip-backup/*-backup.hg (glob)
-  $ hg id -ir 6:2702dd0c91e7
-  abort: unknown revision '2702dd0c91e7'!
-  [255]
-
-  $ cd ..
--- a/tests/test-mq-subrepo.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-mq-subrepo.t	Sun Oct 20 16:43:11 2013 -0700
@@ -213,6 +213,7 @@
 
 
 handle subrepos safely on qpush/qpop
+(and we cannot qpop / qpush with a modified subrepo)
 
   $ mkrepo repo-2499-qpush
   $ mksubrepo sub
@@ -220,31 +221,58 @@
   $ hg -R sub ci -m0sub
   $ echo sub = sub > .hgsub
   $ hg add .hgsub
-  $ hg qnew -m0 0.diff
+  $ hg commit -m0
   $ hg debugsub
   path sub
    source   sub
    revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
+  $ echo foo > ./sub/a
+  $ hg -R sub commit -m foo
+  $ hg commit -m1
+  $ hg qimport -r "0:tip"
+  $ hg -R sub id --id
+  aa037b301eba
 
 qpop
+  $ hg -R sub update 0000
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
   $ hg qpop
-  popping 0.diff
-  patch queue now empty
-  $ hg status -AS
-  $ hg debugsub
-
-qpush
-  $ hg qpush
-  applying 0.diff
+  abort: local changed subrepos found, refresh first
+  [255]
+  $ hg revert sub
+  reverting subrepo sub
+  adding sub/a
+  $ hg qpop
+  popping 1.diff
   now at: 0.diff
   $ hg status -AS
   C .hgsub
   C .hgsubstate
   C sub/a
-  $ hg debugsub
-  path sub
-   source   sub
-   revision b2fdb12cd82b021c3b7053d67802e77b6eeaee31
+  $ hg -R sub id --id
+  b2fdb12cd82b
+
+qpush
+  $ hg -R sub update 0000
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ hg qpush
+  abort: local changed subrepos found, refresh first
+  [255]
+  $ hg revert sub
+  reverting subrepo sub
+  adding sub/a
+  $ hg qpush
+  applying 1.diff
+   subrepository sub diverged (local revision: b2fdb12cd82b, remote revision: aa037b301eba)
+  (M)erge, keep (l)ocal or keep (r)emote? m
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  now at: 1.diff
+  $ hg status -AS
+  C .hgsub
+  C .hgsubstate
+  C sub/a
+  $ hg -R sub id --id
+  aa037b301eba
 
   $ cd ..
 
--- a/tests/test-mq.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-mq.t	Sun Oct 20 16:43:11 2013 -0700
@@ -67,6 +67,9 @@
   changes will be tolerated and preserved. If incompatible options such as
   -f/--force or --exact are passed, this setting is ignored.
   
+  This extension used to provide a strip command. This command now lives in the
+  strip extension.
+  
   list of commands:
   
    qapplied      print the patches already applied
@@ -91,7 +94,6 @@
    qseries       print the entire series file
    qtop          print the name of the current patch
    qunapplied    print the patches not yet applied
-   strip         strip changesets and all their descendants from the repository
   
   use "hg -v help mq" to show builtin aliases and global options
 
--- a/tests/test-obsolete-checkheads.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-obsolete-checkheads.t	Sun Oct 20 16:43:11 2013 -0700
@@ -98,7 +98,7 @@
   pushing to $TESTTMP/remote (glob)
   searching for changes
   abort: push creates new remote head 71e3228bffe1!
-  (did you forget to merge? use push -f to force)
+  (merge or see "hg help push" for details about pushing new heads)
   [255]
 
 old head is now public (public remote version)
@@ -127,7 +127,7 @@
 #   pushing to $TESTTMP/remote
 #   searching for changes
 #   abort: push creates new remote head 71e3228bffe1!
-#   (did you forget to merge? use push -f to force)
+#   (merge or see "hg help push" for details about pushing new heads)
 #   [255]
 
 old head is obsolete but replacement is not pushed
@@ -158,7 +158,7 @@
   pushing to $TESTTMP/remote (glob)
   searching for changes
   abort: push creates new remote head d7d41ccbd4de!
-  (did you forget to merge? use push -f to force)
+  (merge or see "hg help push" for details about pushing new heads)
   [255]
 
 
--- a/tests/test-parse-date.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-parse-date.t	Sun Oct 20 16:43:11 2013 -0700
@@ -242,7 +242,7 @@
   >>> yesterday = (datetime.date.today() - datetime.timedelta(days=1)).strftime("%b %d")
   >>> dates = open('dates', 'w')
   >>> dates.write(today + '\n')
-  >>> dates.write(yesterday)
+  >>> dates.write(yesterday + '\n')
   >>> dates.close()
   $ hg ci -d "`sed -n '1p' dates`" -m "today is a good day to code"
   $ hg log -d today --template '{desc}\n'
--- a/tests/test-phases-exchange.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-phases-exchange.t	Sun Oct 20 16:43:11 2013 -0700
@@ -844,7 +844,7 @@
   pushing to ../mu
   searching for changes
   abort: push creates new remote head 435b5d83910c!
-  (did you forget to merge? use push -f to force)
+  (merge or see "hg help push" for details about pushing new heads)
   [255]
   $ hg push -fr 435b5d83910c ../mu # because the push will create new visible head
   pushing to ../mu
--- a/tests/test-progress.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-progress.t	Sun Oct 20 16:43:11 2013 -0700
@@ -1,6 +1,14 @@
 
   $ cat > loop.py <<EOF
   > from mercurial import commands
+  > import time
+  > class incrementingtime(object):
+  >     def __init__(self):
+  >         self._time = 0.0
+  >     def __call__(self):
+  >         self._time += 0.25
+  >         return self._time
+  > time.time = incrementingtime()
   > 
   > def loop(ui, loops, **opts):
   >     loops = int(loops)
@@ -19,9 +27,14 @@
   >         if opts.get('parallel'):
   >             ui.progress('other', i, 'other.%d' % i, 'othernum', total)
   >         if nested:
-  >             for j in range(2):
-  >                 ui.progress('nested', j, 'nested.%d' % j, 'nestnum', 2)
-  >             ui.progress('nested', None, 'nested.done', 'nestnum', 2)
+  >             nested_steps = 2
+  >             if i and i % 4 == 0:
+  >                 nested_steps = 5
+  >             for j in range(nested_steps):
+  >                 ui.progress(
+  >                   'nested', j, 'nested.%d' % j, 'nestnum', nested_steps)
+  >             ui.progress(
+  >               'nested', None, 'nested.done', 'nestnum', nested_steps)
   >     ui.progress('loop', None, 'loop.done', 'loopnum', total)
   > 
   > commands.norepo += " loop"
@@ -69,6 +82,24 @@
   loop [===============================>                ] 2/3\r (no-eol) (esc)
                                                               \r (no-eol) (esc)
 
+Test nested long-lived topic which has the same name as a short-lived
+peer. We shouldn't get stuck showing the short-lived inner steps, and
+should go back to skipping the inner steps when the slow nested step
+finishes.
+
+  $ hg -y loop 7 --nested
+  \r (no-eol) (esc)
+  loop [                                                ] 0/7\r (no-eol) (esc)
+  loop [=====>                                          ] 1/7\r (no-eol) (esc)
+  loop [============>                                   ] 2/7\r (no-eol) (esc)
+  loop [===================>                            ] 3/7\r (no-eol) (esc)
+  loop [==========================>                     ] 4/7\r (no-eol) (esc)
+  nested [==========================>                   ] 3/5\r (no-eol) (esc)
+  nested [===================================>          ] 4/5\r (no-eol) (esc)
+  loop [=================================>              ] 5/7\r (no-eol) (esc)
+  loop [========================================>       ] 6/7\r (no-eol) (esc)
+                                                              \r (no-eol) (esc)
+
 
   $ hg --config progress.changedelay=0 -y loop 3 --nested
   \r (no-eol) (esc)
--- a/tests/test-pull-update.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-pull-update.t	Sun Oct 20 16:43:11 2013 -0700
@@ -25,7 +25,8 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
-  not updating: crosses branches (merge branches or update --check to force update)
+  not updating: not a linear update
+  (merge or update --check to force update)
 
   $ cd ../tt
 
@@ -38,7 +39,8 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
-  not updating: crosses branches (merge branches or update --check to force update)
+  not updating: not a linear update
+  (merge or update --check to force update)
 
   $ HGMERGE=true hg merge
   merging foo
--- a/tests/test-push-warn.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-push-warn.t	Sun Oct 20 16:43:11 2013 -0700
@@ -26,7 +26,7 @@
   pushing to ../a
   searching for changes
   abort: push creates new remote head 1e108cc5548c!
-  (you should pull and merge or use push -f to force)
+  (pull and merge or see "hg help push" for details about pushing new heads)
   [255]
 
   $ hg push --debug ../a
@@ -41,7 +41,7 @@
   new remote heads on branch 'default'
   new remote head 1e108cc5548c
   abort: push creates new remote head 1e108cc5548c!
-  (you should pull and merge or use push -f to force)
+  (pull and merge or see "hg help push" for details about pushing new heads)
   [255]
 
   $ hg pull ../a
@@ -57,7 +57,7 @@
   pushing to ../a
   searching for changes
   abort: push creates new remote head 1e108cc5548c!
-  (did you forget to merge? use push -f to force)
+  (merge or see "hg help push" for details about pushing new heads)
   [255]
 
   $ hg merge
@@ -110,7 +110,7 @@
   pushing to ../c
   searching for changes
   abort: push creates new remote head 6346d66eb9f5!
-  (did you forget to merge? use push -f to force)
+  (merge or see "hg help push" for details about pushing new heads)
   [255]
 
   $ hg push -r 2 ../c
@@ -123,7 +123,7 @@
   pushing to ../c
   searching for changes
   abort: push creates new remote head a5dda829a167!
-  (did you forget to merge? use push -f to force)
+  (merge or see "hg help push" for details about pushing new heads)
   [255]
 
   $ hg push -v -r 3 -r 4 ../c
@@ -133,7 +133,7 @@
   new remote head a5dda829a167
   new remote head ee8fbc7a0295
   abort: push creates new remote head a5dda829a167!
-  (did you forget to merge? use push -f to force)
+  (merge or see "hg help push" for details about pushing new heads)
   [255]
 
   $ hg push -v -f -r 3 -r 4 ../c
@@ -263,7 +263,7 @@
   pushing to ../f
   searching for changes
   abort: push creates new remote head 0b715ef6ff8f on branch 'a'!
-  (did you forget to merge? use push -f to force)
+  (merge or see "hg help push" for details about pushing new heads)
   [255]
 
 Push replacement head on existing branches:
@@ -354,6 +354,29 @@
   adding file changes
   added 1 changesets with 1 changes to 1 files
 
+Pushing muliple headed new branch:
+
+  $ echo 14 > foo
+  $ hg -q branch f
+  $ hg -q ci -m 14
+  $ echo 15 > foo
+  $ hg -q ci -m 15
+  $ hg -q up 14
+  $ echo 16 > foo
+  $ hg -q ci -m 16
+  $ hg push --branch f --new-branch ../f
+  pushing to ../f
+  searching for changes
+  abort: push creates multiple headed new branch 'f'
+  (merge or see "hg help push" for details about pushing new heads)
+  [255]
+  $ hg push --branch f --new-branch --force ../f
+  pushing to ../f
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 3 changesets with 3 changes to 1 files (+1 heads)
 
 Checking prepush logic does not allow silently pushing
 multiple new heads:
@@ -386,7 +409,7 @@
   pushing to h
   searching for changes
   abort: push creates new remote head 97bd0c84d346!
-  (you should pull and merge or use push -f to force)
+  (pull and merge or see "hg help push" for details about pushing new heads)
   [255]
 
 
@@ -458,7 +481,7 @@
   pushing to ../l
   searching for changes
   abort: push creates new remote head 451211cc22b0 on branch 'a'!
-  (did you forget to merge? use push -f to force)
+  (merge or see "hg help push" for details about pushing new heads)
   [255]
 
   $ cd ..
@@ -713,14 +736,14 @@
   pushing to inner
   searching for changes
   abort: push creates new remote head 7d0f4fb6cf04 on branch 'A'!
-  (did you forget to merge? use push -f to force)
+  (merge or see "hg help push" for details about pushing new heads)
   [255]
 
   $ hg push inner -r4 -r5
   pushing to inner
   searching for changes
   abort: push creates new remote head 7d0f4fb6cf04 on branch 'A'!
-  (did you forget to merge? use push -f to force)
+  (merge or see "hg help push" for details about pushing new heads)
   [255]
 
   $ hg in inner
--- a/tests/test-rebase-bookmarks.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-rebase-bookmarks.t	Sun Oct 20 16:43:11 2013 -0700
@@ -119,18 +119,24 @@
   saved backup bundle to $TESTTMP/a3/.hg/strip-backup/*-backup.hg (glob)
 
   $ hg tglog
-  @  3: 'C' bookmarks: Y Z
+  o  3: 'C' bookmarks: Y Z
   |
-  o  2: 'B' bookmarks: X
+  @  2: 'B' bookmarks: X
   |
   o  1: 'D' bookmarks: W
   |
   o  0: 'A' bookmarks:
   
+  $ hg bookmarks
+     W                         1:41acb9dca9eb
+   * X                         2:e926fccfa8ec
+     Y                         3:3d5fa227f4b5
+     Z                         3:3d5fa227f4b5
+
 rebase --continue with bookmarks present (issue3802)
 
   $ hg up 2
-  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ echo 'C' > c
   $ hg add c
   $ hg ci -m 'other C'
--- a/tests/test-rebase-cache.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-rebase-cache.t	Sun Oct 20 16:43:11 2013 -0700
@@ -121,11 +121,11 @@
   0: 'A' 
 
   $ hg tglog
-  @  8: 'E' branch3
+  o  8: 'E' branch3
   |
   o  7: 'D' branch3
   |
-  o  6: 'F' branch3
+  @  6: 'F' branch3
   |
   o  5: 'branch3' branch3
   |
--- a/tests/test-rebase-check-restore.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-rebase-check-restore.t	Sun Oct 20 16:43:11 2013 -0700
@@ -80,11 +80,11 @@
   $ hg rebase --continue
 
   $ hg tglog
-  @  7:secret 'C'
+  o  7:secret 'C'
   |
   o  6:draft 'B'
   |
-  | o  5:draft 'F' notdefault
+  | @  5:draft 'F' notdefault
   | |
   o |  4:draft 'E'
   | |
--- a/tests/test-rebase-collapse.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-rebase-collapse.t	Sun Oct 20 16:43:11 2013 -0700
@@ -57,11 +57,11 @@
   saved backup bundle to $TESTTMP/a1/.hg/strip-backup/*-backup.hg (glob)
 
   $ hg tglogp
-  @  5:secret 'Collapsed revision
+  o  5:secret 'Collapsed revision
   |  * B
   |  * C
   |  * D'
-  o  4:draft 'H'
+  @  4:draft 'H'
   |
   | o  3:draft 'G'
   |/|
@@ -71,7 +71,7 @@
   |/
   o  0:draft 'A'
   
-  $ hg manifest
+  $ hg manifest --rev tip
   A
   B
   C
@@ -92,10 +92,10 @@
   saved backup bundle to $TESTTMP/a2/.hg/strip-backup/*-backup.hg (glob)
 
   $ hg tglog
-  @  6: 'Collapsed revision
+  o  6: 'Collapsed revision
   |  * E
   |  * G'
-  o  5: 'H'
+  @  5: 'H'
   |
   o  4: 'F'
   |
@@ -107,7 +107,7 @@
   |/
   o  0: 'A'
   
-  $ hg manifest
+  $ hg manifest --rev tip
   A
   E
   F
@@ -128,9 +128,9 @@
   saved backup bundle to $TESTTMP/a3/.hg/strip-backup/*-backup.hg (glob)
 
   $ hg tglog
-  @  6: 'custom message'
+  o  6: 'custom message'
   |
-  o  5: 'H'
+  @  5: 'H'
   |
   o  4: 'F'
   |
@@ -142,7 +142,7 @@
   |/
   o  0: 'A'
   
-  $ hg manifest
+  $ hg manifest --rev tip
   A
   E
   F
@@ -235,11 +235,11 @@
   saved backup bundle to $TESTTMP/b1/.hg/strip-backup/*-backup.hg (glob)
 
   $ hg tglog
-  @    5: 'Collapsed revision
+  o    5: 'Collapsed revision
   |\   * E
   | |  * F
   | |  * G'
-  | o  4: 'H'
+  | @  4: 'H'
   | |
   o |    3: 'D'
   |\ \
@@ -249,7 +249,7 @@
   |/
   o  0: 'A'
   
-  $ hg manifest
+  $ hg manifest --rev tip
   A
   C
   D
@@ -384,12 +384,12 @@
   saved backup bundle to $TESTTMP/c1/.hg/strip-backup/*-backup.hg (glob)
 
   $ hg tglog
-  @    5: 'Collapsed revision
+  o    5: 'Collapsed revision
   |\   * E
   | |  * F
   | |  * G
   | |  * H'
-  | o  4: 'I'
+  | @  4: 'I'
   | |
   o |    3: 'D'
   |\ \
@@ -399,7 +399,7 @@
   |/
   o  0: 'A'
   
-  $ hg manifest
+  $ hg manifest --rev tip
   A
   C
   D
@@ -407,6 +407,7 @@
   G
   I
 
+  $ hg up tip -q
   $ cat E
   F
 
@@ -472,16 +473,16 @@
   saved backup bundle to $TESTTMP/d1/.hg/strip-backup/*-backup.hg (glob)
 
   $ hg tglog
-  @  2: 'Collapsed revision
+  o  2: 'Collapsed revision
   |  * B
   |  * C
   |  * D
   |  * E'
-  o  1: 'F'
+  @  1: 'F'
   |
   o  0: 'A'
   
-  $ hg manifest
+  $ hg manifest --rev tip
   A
   B
   C
@@ -611,12 +612,13 @@
   merging f and c to c
   saved backup bundle to $TESTTMP/copies/.hg/strip-backup/*-backup.hg (glob)
   $ hg st
-  $ hg st --copies --change .
+  $ hg st --copies --change tip
   A d
     a
   A g
     b
   R b
+  $ hg up tip -q
   $ cat c
   c
   c
@@ -648,7 +650,7 @@
 
   $ hg rebase --collapse -b . -d 0
   saved backup bundle to $TESTTMP/copies/.hg/strip-backup/*-backup.hg (glob)
-  $ hg st --change . --copies
+  $ hg st --change tip --copies
   M a
   M c
   A d
@@ -656,6 +658,7 @@
   A g
     b
   R b
+  $ hg up tip -q
   $ cat a
   a
   a
@@ -737,11 +740,11 @@
   $ 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  1: 'collapsed'
   |
-  o  0: 'base'
+  @  0: 'base'
   
-  $ hg manifest
+  $ hg manifest --rev tip
   b
   base
 
--- a/tests/test-rebase-detach.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-rebase-detach.t	Sun Oct 20 16:43:11 2013 -0700
@@ -52,9 +52,9 @@
   saved backup bundle to $TESTTMP/a1/.hg/strip-backup/*-backup.hg (glob)
 
   $ hg log -G --template "{rev}:{phase} '{desc}' {branches}\n"
-  @  7:secret 'D'
+  o  7:secret 'D'
   |
-  o  6:draft 'H'
+  @  6:draft 'H'
   |
   | o  5:draft 'G'
   |/|
@@ -68,7 +68,7 @@
   |/
   o  0:draft 'A'
   
-  $ hg manifest
+  $ hg manifest --rev tip
   A
   D
   F
@@ -103,11 +103,11 @@
   saved backup bundle to $TESTTMP/a2/.hg/strip-backup/*-backup.hg (glob)
 
   $ hg tglog
-  @  7: 'D'
+  o  7: 'D'
   |
   o  6: 'C'
   |
-  o  5: 'H'
+  @  5: 'H'
   |
   | o  4: 'G'
   |/|
@@ -119,7 +119,7 @@
   |/
   o  0: 'A'
   
-  $ hg manifest
+  $ hg manifest --rev tip
   A
   C
   D
@@ -155,13 +155,13 @@
   saved backup bundle to $TESTTMP/a3/.hg/strip-backup/*-backup.hg (glob)
 
   $ hg tglog
-  @  7: 'D'
+  o  7: 'D'
   |
   o  6: 'C'
   |
   o  5: 'B'
   |
-  o  4: 'H'
+  @  4: 'H'
   |
   | o  3: 'G'
   |/|
@@ -171,7 +171,7 @@
   |/
   o  0: 'A'
   
-  $ hg manifest
+  $ hg manifest --rev tip
   A
   B
   C
@@ -209,10 +209,10 @@
   saved backup bundle to $TESTTMP/a4/.hg/strip-backup/*-backup.hg (glob)
 
   $ hg  log -G --template "{rev}:{phase} '{desc}' {branches}\n"
-  @  6:secret 'Collapsed revision
+  o  6:secret 'Collapsed revision
   |  * C
   |  * D'
-  o  5:draft 'H'
+  @  5:draft 'H'
   |
   | o  4:draft 'G'
   |/|
@@ -224,7 +224,7 @@
   |/
   o  0:draft 'A'
   
-  $ hg manifest
+  $ hg manifest --rev tip
   A
   C
   D
@@ -268,13 +268,13 @@
   saved backup bundle to $TESTTMP/a5/.hg/strip-backup/*-backup.hg (glob)
 
   $ hg tglog
-  @  8: 'D'
+  o  8: 'D'
   |
   o  7: 'C'
   |
   o  6: 'B'
   |
-  o  5: 'extra branch'
+  @  5: 'extra branch'
   
   o  4: 'H'
   |
@@ -290,13 +290,13 @@
   $ hg rebase -d 5 -s 7
   saved backup bundle to $TESTTMP/a5/.hg/strip-backup/13547172c9c0-backup.hg (glob)
   $ hg tglog
-  @  8: 'D'
+  o  8: 'D'
   |
   o  7: 'C'
   |
   | o  6: 'B'
   |/
-  o  5: 'extra branch'
+  @  5: 'extra branch'
   
   o  4: 'H'
   |
@@ -329,11 +329,11 @@
   saved backup bundle to $TESTTMP/a6/.hg/strip-backup/*-backup.hg (glob)
 
   $ hg tglog
-  @  8: 'Collapsed revision
+  o  8: 'Collapsed revision
   |  * I
   |  * Merge
   |  * J'
-  o  7: 'H'
+  @  7: 'H'
   |
   | o  6: 'G'
   |/|
@@ -350,7 +350,7 @@
   o  0: 'A'
   
 
-  $ hg parents
+  $ hg log --rev tip
   changeset:   8:9472f4b1d736
   tag:         tip
   user:        test
--- a/tests/test-rebase-interruptions.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-rebase-interruptions.t	Sun Oct 20 16:43:11 2013 -0700
@@ -110,13 +110,13 @@
   warning: new changesets detected on source branch, not stripping
 
   $ hg tglogp
-  @  7:draft 'C'
+  o  7:draft 'C'
   |
   | o  6:secret 'Extra'
   | |
   o |  5:draft 'B'
   | |
-  o |  4:draft 'E'
+  @ |  4:draft 'E'
   | |
   o |  3:draft 'D'
   | |
--- a/tests/test-rebase-named-branches.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-rebase-named-branches.t	Sun Oct 20 16:43:11 2013 -0700
@@ -147,7 +147,7 @@
   saved backup bundle to $TESTTMP/a1/.hg/strip-backup/*-backup.hg (glob)
 
   $ hg tglog
-  @  9: 'dev-two named branch' dev-two
+  o  9: 'dev-two named branch' dev-two
   |
   o  8: 'H'
   |
@@ -155,7 +155,7 @@
   |/|
   o |  6: 'F'
   | |
-  o |  5: 'dev-one named branch' dev-one
+  @ |  5: 'dev-one named branch' dev-one
   | |
   | o  4: 'E'
   | |
@@ -171,7 +171,7 @@
   saved backup bundle to $TESTTMP/a1/.hg/strip-backup/*-backup.hg (glob)
 
   $ hg tglog
-  @  8: 'dev-two named branch' dev-two
+  o  8: 'dev-two named branch' dev-two
   |
   o  7: 'H'
   |
@@ -187,7 +187,7 @@
   | |
   | o  1: 'B'
   |/
-  o  0: 'A'
+  @  0: 'A'
   
 
 Rebasing descendant onto ancestor across different named branches
@@ -196,7 +196,7 @@
   saved backup bundle to $TESTTMP/a1/.hg/strip-backup/*-backup.hg (glob)
 
   $ hg tglog
-  @  8: 'D'
+  o  8: 'D'
   |
   o  7: 'C'
   |
@@ -212,7 +212,7 @@
   | |
   | o  1: 'E'
   |/
-  o  0: 'A'
+  @  0: 'A'
   
   $ hg rebase -s 4 -d 5
   abort: source is ancestor of destination
@@ -222,7 +222,7 @@
   saved backup bundle to $TESTTMP/a1/.hg/strip-backup/*-backup.hg (glob)
 
   $ hg tglog
-  @  8: 'D'
+  o  8: 'D'
   |
   o  7: 'C'
   |
@@ -238,6 +238,6 @@
   | |
   | o  1: 'E'
   |/
-  o  0: 'A'
+  @  0: 'A'
   
   $ cd ..
--- a/tests/test-rebase-newancestor.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-rebase-newancestor.t	Sun Oct 20 16:43:11 2013 -0700
@@ -44,11 +44,11 @@
   saved backup bundle to $TESTTMP/repo/.hg/strip-backup/*-backup.hg (glob)
 
   $ hg tglog
-  @  3: 'C'
+  o  3: 'C'
   |
   o  2: 'B'
   |
-  o  1: 'AD'
+  @  1: 'AD'
   |
   o  0: 'A'
   
--- a/tests/test-rebase-obsolete.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-rebase-obsolete.t	Sun Oct 20 16:43:11 2013 -0700
@@ -126,9 +126,9 @@
   grafting revision 3
   $ hg rebase  -s 42ccdea3bb16 -d .
   $ hg log -G
-  @  10:5ae4c968c6ac C
+  o  10:5ae4c968c6ac C
   |
-  o  9:08483444fef9 D
+  @  9:08483444fef9 D
   |
   o  8:8877864f1edb B
   |
@@ -143,9 +143,9 @@
   o  0:cd010b8cd998 A
   
   $ hg log --hidden -G
-  @  10:5ae4c968c6ac C
+  o  10:5ae4c968c6ac C
   |
-  o  9:08483444fef9 D
+  @  9:08483444fef9 D
   |
   o  8:8877864f1edb B
   |
@@ -178,9 +178,9 @@
   42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {'date': '*', 'user': 'test'} (glob)
   5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 5ae4c968c6aca831df823664e706c9d4aa34473d 0 {'date': '*', 'user': 'test'} (glob)
   32af7686d403cf45b5d95f2d70cebea587ac806a 0 {'date': '*', 'user': 'test'} (glob)
-  08483444fef91d6224f6655ee586a65d263ad34c cbc07f26687521cecfc9a141bf5ecfc0fd2b8531 0 {'date': '* *', 'user': 'test'} (glob)
+  08483444fef91d6224f6655ee586a65d263ad34c 4596109a6a4328c398bde3a4a3b6737cfade3003 0 {'date': '* *', 'user': 'test'} (glob)
   $ hg log -G
-  @  11:cbc07f266875 D
+  @  11:4596109a6a43 D
   |
   | o  10:5ae4c968c6ac C
   | |
@@ -203,17 +203,17 @@
   42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 {'date': '* *', 'user': 'test'} (glob)
   5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 5ae4c968c6aca831df823664e706c9d4aa34473d 0 {'date': '* *', 'user': 'test'} (glob)
   32af7686d403cf45b5d95f2d70cebea587ac806a 0 {'date': '* *', 'user': 'test'} (glob)
-  08483444fef91d6224f6655ee586a65d263ad34c cbc07f26687521cecfc9a141bf5ecfc0fd2b8531 0 {'date': '* *', 'user': 'test'} (glob)
-  8877864f1edb05d0e07dc4ba77b67a80a7b86672 b1861c79d66ec3aa1b607ac3c9fb819e38b12238 0 {'date': '* *', 'user': 'test'} (glob)
+  08483444fef91d6224f6655ee586a65d263ad34c 4596109a6a4328c398bde3a4a3b6737cfade3003 0 {'date': '* *', 'user': 'test'} (glob)
+  8877864f1edb05d0e07dc4ba77b67a80a7b86672 462a34d07e599b87ea08676a449373fe4e2e1347 0 {'date': '* *', 'user': 'test'} (glob)
   08483444fef91d6224f6655ee586a65d263ad34c 0 {'date': '* *', 'user': 'test'} (glob)
-  5ae4c968c6aca831df823664e706c9d4aa34473d dd4be135457a404ce5541de427ae1d98a28f4acd 0 {'date': '* *', 'user': 'test'} (glob)
+  5ae4c968c6aca831df823664e706c9d4aa34473d 98f6af4ee9539e14da4465128f894c274900b6e5 0 {'date': '* *', 'user': 'test'} (glob)
   $ hg log --rev 'divergent()'
   $ hg log -G
-  @  13:dd4be135457a C
+  o  13:98f6af4ee953 C
   |
-  o  12:b1861c79d66e B
+  o  12:462a34d07e59 B
   |
-  o  11:cbc07f266875 D
+  @  11:4596109a6a43 D
   |
   o  7:02de42196ebe H
   |
@@ -225,7 +225,22 @@
   |/
   o  0:cd010b8cd998 A
   
-
+  $ hg log --style default --debug -r 4596109a6a4328c398bde3a4a3b6737cfade3003
+  changeset:   11:4596109a6a4328c398bde3a4a3b6737cfade3003
+  phase:       draft
+  parent:      7:02de42196ebee42ef284b6780a87cdc96e8eaab6
+  parent:      -1:0000000000000000000000000000000000000000
+  manifest:    11:a91006e3a02f1edf631f7018e6e5684cf27dd905
+  user:        Nicolas Dumazet <nicdumz.commits@gmail.com>
+  date:        Sat Apr 30 15:24:48 2011 +0200
+  files+:      D
+  extra:       branch=default
+  extra:       rebase_source=08483444fef91d6224f6655ee586a65d263ad34c
+  extra:       source=32af7686d403cf45b5d95f2d70cebea587ac806a
+  description:
+  D
+  
+  
   $ cd ..
 
 collapse rebase
@@ -237,9 +252,9 @@
   $ cd collapse
   $ hg rebase  -s 42ccdea3bb16 -d eea13746799a --collapse
   $ hg log -G
-  @  8:4dc2197e807b Collapsed revision
+  o  8:4dc2197e807b Collapsed revision
   |
-  | o  7:02de42196ebe H
+  | @  7:02de42196ebe H
   | |
   o |  6:eea13746799a G
   |\|
@@ -250,9 +265,9 @@
   o  0:cd010b8cd998 A
   
   $ hg log --hidden -G
-  @  8:4dc2197e807b Collapsed revision
+  o  8:4dc2197e807b Collapsed revision
   |
-  | o  7:02de42196ebe H
+  | @  7:02de42196ebe H
   | |
   o |  6:eea13746799a G
   |\|
@@ -268,7 +283,7 @@
   |/
   o  0:cd010b8cd998 A
   
-  $ hg id --debug
+  $ hg id --debug -r tip
   4dc2197e807bae9817f09905b50ab288be2dbbcf tip
   $ hg debugobsolete
   42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 4dc2197e807bae9817f09905b50ab288be2dbbcf 0 {'date': '*', 'user': 'test'} (glob)
@@ -290,13 +305,13 @@
   $ hg rebase -s 5fddd98957c8 -d eea13746799a
   $ hg rebase -s 42ccdea3bb16 -d 02de42196ebe
   $ hg log -G
-  @  10:7c6027df6a99 B
+  o  10:7c6027df6a99 B
   |
   | o  9:cf44d2f5a9f4 D
   | |
   | o  8:e273c5e7d2d2 C
   | |
-  o |  7:02de42196ebe H
+  @ |  7:02de42196ebe H
   | |
   | o  6:eea13746799a G
   |/|
@@ -307,13 +322,13 @@
   o  0:cd010b8cd998 A
   
   $ hg log --hidden -G
-  @  10:7c6027df6a99 B
+  o  10:7c6027df6a99 B
   |
   | o  9:cf44d2f5a9f4 D
   | |
   | o  8:e273c5e7d2d2 C
   | |
-  o |  7:02de42196ebe H
+  @ |  7:02de42196ebe H
   | |
   | o  6:eea13746799a G
   |/|
@@ -341,7 +356,7 @@
   9:cf44d2f5a9f4 D (no-eol)
   $ hg rebase -r 8
   $ hg log -G
-  @  11:0d8f238b634c C
+  o  11:0d8f238b634c C
   |
   o  10:7c6027df6a99 B
   |
@@ -349,7 +364,7 @@
   | |
   | x  8:e273c5e7d2d2 C
   | |
-  o |  7:02de42196ebe H
+  @ |  7:02de42196ebe H
   | |
   | o  6:eea13746799a G
   |/|
@@ -366,11 +381,11 @@
 
   $ hg rebase --dest 4 --rev '7+11+9'
   $ hg log -G
-  @  14:1e8370e38cca C
+  o  14:1e8370e38cca C
   |
   | o  13:102b4c1d889b D
   | |
-  o |  12:bfe264faf697 H
+  @ |  12:bfe264faf697 H
   |/
   | o  10:7c6027df6a99 B
   | |
--- a/tests/test-rebase-parameters.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-rebase-parameters.t	Sun Oct 20 16:43:11 2013 -0700
@@ -197,11 +197,11 @@
   saved backup bundle to $TESTTMP/a4/.hg/strip-backup/*-backup.hg (glob)
 
   $ hg tglog
-  @  8: 'D'
+  o  8: 'D'
   |
   o  7: 'C'
   |
-  o  6: 'I'
+  @  6: 'I'
   |
   o  5: 'H'
   |
@@ -257,13 +257,13 @@
   saved backup bundle to $TESTTMP/a6/.hg/strip-backup/*-backup.hg (glob)
 
   $ hg tglog
-  @  8: 'D'
+  o  8: 'D'
   |
   o  7: 'C'
   |
   o  6: 'B'
   |
-  o  5: 'I'
+  @  5: 'I'
   |
   o  4: 'H'
   |
@@ -287,11 +287,11 @@
   saved backup bundle to $TESTTMP/a7/.hg/strip-backup/*-backup.hg (glob)
 
   $ hg tglog
-  @  8: 'D'
+  o  8: 'D'
   |
   o  7: 'C'
   |
-  | o  6: 'I'
+  | @  6: 'I'
   |/
   o  5: 'H'
   |
@@ -317,13 +317,13 @@
   saved backup bundle to $TESTTMP/a8/.hg/strip-backup/*-backup.hg (glob)
 
   $ hg tglog
-  @  8: 'D'
+  o  8: 'D'
   |
   o  7: 'C'
   |
   o  6: 'B'
   |
-  | o  5: 'I'
+  | @  5: 'I'
   |/
   o  4: 'H'
   |
@@ -347,11 +347,11 @@
   saved backup bundle to $TESTTMP/a9/.hg/strip-backup/*-backup.hg (glob)
 
   $ hg tglog
-  @  8: 'D'
+  o  8: 'D'
   |
   o  7: 'C'
   |
-  o  6: 'I'
+  @  6: 'I'
   |
   o  5: 'H'
   |
--- a/tests/test-rebase-scenario-global.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-rebase-scenario-global.t	Sun Oct 20 16:43:11 2013 -0700
@@ -52,9 +52,9 @@
   saved backup bundle to $TESTTMP/a1/.hg/strip-backup/*-backup.hg (glob)
 
   $ hg tglog
-  @  7: 'D'
+  o  7: 'D'
   |
-  o  6: 'H'
+  @  6: 'H'
   |
   | o  5: 'G'
   |/|
@@ -80,9 +80,9 @@
   saved backup bundle to $TESTTMP/a2/.hg/strip-backup/*-backup.hg (glob)
 
   $ hg tglog
-  @  7: 'D'
+  o  7: 'D'
   |
-  | o  6: 'H'
+  | @  6: 'H'
   |/
   | o  5: 'G'
   |/|
@@ -108,9 +108,9 @@
   saved backup bundle to $TESTTMP/a3/.hg/strip-backup/*-backup.hg (glob)
 
   $ hg tglog
-  @  6: 'E'
+  o  6: 'E'
   |
-  o  5: 'H'
+  @  5: 'H'
   |
   o  4: 'F'
   |
@@ -160,9 +160,9 @@
   saved backup bundle to $TESTTMP/a5/.hg/strip-backup/*-backup.hg (glob)
 
   $ hg tglog
-  @    7: 'G'
+  o    7: 'G'
   |\
-  | o  6: 'H'
+  | @  6: 'H'
   | |
   | o  5: 'F'
   | |
@@ -256,11 +256,11 @@
   $ hg rebase -d 0 -s 2
   saved backup bundle to $TESTTMP/a7/.hg/strip-backup/5fddd98957c8-backup.hg (glob)
   $ hg tglog
-  @  7: 'D'
+  o  7: 'D'
   |
   o  6: 'C'
   |
-  | o  5: 'H'
+  | @  5: 'H'
   | |
   | | o  4: 'G'
   | |/|
@@ -360,7 +360,7 @@
   [255]
   $ hg rebase -r '2::8' -d 1 --keep
   $ hg tglog
-  @  13: 'I'
+  o  13: 'I'
   |
   o  12: 'H'
   |
@@ -401,7 +401,7 @@
   [255]
   $ hg rebase -r '3::8' -d 1 --keep
   $ hg tglog
-  @  12: 'I'
+  o  12: 'I'
   |
   o  11: 'H'
   |
@@ -440,7 +440,7 @@
   [255]
   $ hg rebase -r '3::7' -d 1 --keep
   $ hg tglog
-  @  11: 'H'
+  o  11: 'H'
   |
   o  10: 'G'
   |
@@ -477,7 +477,7 @@
   [255]
   $ hg rebase -r '3::(7+5)' -d 1 --keep
   $ hg tglog
-  @  13: 'H'
+  o  13: 'H'
   |
   o  12: 'G'
   |
@@ -517,7 +517,7 @@
   $ hg rebase -r '6::' -d 2
   saved backup bundle to $TESTTMP/ah5/.hg/strip-backup/3d8a618087a7-backup.hg (glob)
   $ hg tglog
-  @  8: 'I'
+  o  8: 'I'
   |
   o  7: 'H'
   |
@@ -547,7 +547,7 @@
   $ hg rebase -r '(4+6)::' -d 1
   saved backup bundle to $TESTTMP/ah6/.hg/strip-backup/3d8a618087a7-backup.hg (glob)
   $ hg tglog
-  @  8: 'I'
+  o  8: 'I'
   |
   o  7: 'H'
   |
--- a/tests/test-requires.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-requires.t	Sun Oct 20 16:43:11 2013 -0700
@@ -15,5 +15,55 @@
   $ hg tip
   abort: unknown repository format: requires features 'indoor-pool', 'outdoor-pool' (upgrade Mercurial)!
   [255]
+  $ cd ..
+
+Test checking between features supported locally and ones required in
+another repository of push/pull/clone on localhost:
+
+  $ mkdir supported-locally
+  $ cd supported-locally
+
+  $ hg init supported
+  $ echo a > supported/a
+  $ hg -R supported commit -Am '#0 at supported'
+  adding a
+
+  $ echo 'featuresetup-test' >> supported/.hg/requires
+  $ cat > $TESTTMP/supported-locally/supportlocally.py <<EOF
+  > from mercurial import localrepo, extensions
+  > def featuresetup(ui, supported):
+  >     for name, module in extensions.extensions(ui):
+  >         if __name__ == module.__name__:
+  >             # support specific feature locally
+  >             supported |= set(['featuresetup-test'])
+  >             return
+  > def uisetup(ui):
+  >     localrepo.localrepository.featuresetupfuncs.add(featuresetup)
+  > EOF
+  $ cat > supported/.hg/hgrc <<EOF
+  > [extensions]
+  > # enable extension locally
+  > supportlocally = $TESTTMP/supported-locally/supportlocally.py
+  > EOF
+  $ hg -R supported status
+
+  $ hg init push-dst
+  $ hg -R supported push push-dst
+  pushing to push-dst
+  abort: required features are not supported in the destination: featuresetup-test
+  [255]
+
+  $ hg init pull-src
+  $ hg -R pull-src pull supported
+  pulling from supported
+  abort: required features are not supported in the destination: featuresetup-test
+  [255]
+
+  $ hg clone supported clone-dst
+  abort: unknown repository format: requires features 'featuresetup-test' (upgrade Mercurial)!
+  [255]
+  $ hg clone --pull supported clone-dst
+  abort: required features are not supported in the destination: featuresetup-test
+  [255]
 
   $ cd ..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-shelve.t	Sun Oct 20 16:43:11 2013 -0700
@@ -0,0 +1,484 @@
+  $ echo "[extensions]" >> $HGRCPATH
+  $ echo "mq=" >> $HGRCPATH
+  $ echo "shelve=" >> $HGRCPATH
+  $ echo "[defaults]" >> $HGRCPATH
+  $ echo "diff = --nodates --git" >> $HGRCPATH
+  $ echo "qnew = --date '0 0'" >> $HGRCPATH
+
+  $ hg init repo
+  $ cd repo
+  $ mkdir a b
+  $ echo a > a/a
+  $ echo b > b/b
+  $ echo c > c
+  $ echo d > d
+  $ echo x > x
+  $ hg addremove -q
+
+shelving in an empty repo should be possible
+
+  $ hg shelve
+  shelved as default
+  0 files updated, 0 files merged, 5 files removed, 0 files unresolved
+
+  $ hg unshelve
+  unshelving change 'default'
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 5 changes to 5 files
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+  $ hg commit -q -m 'initial commit'
+
+  $ hg shelve
+  nothing changed
+  [1]
+
+create an mq patch - shelving should work fine with a patch applied
+
+  $ echo n > n
+  $ hg add n
+  $ hg commit n -m second
+  $ hg qnew second.patch
+
+shelve a change that we will delete later
+
+  $ echo a >> a/a
+  $ hg shelve
+  shelved as default
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+set up some more complex changes to shelve
+
+  $ echo a >> a/a
+  $ hg mv b b.rename
+  moving b/b to b.rename/b (glob)
+  $ hg cp c c.copy
+  $ hg status -C
+  M a/a
+  A b.rename/b
+    b/b
+  A c.copy
+    c
+  R b/b
+
+prevent some foot-shooting
+
+  $ hg shelve -n foo/bar
+  abort: shelved change names may not contain slashes
+  [255]
+  $ hg shelve -n .baz
+  abort: shelved change names may not start with '.'
+  [255]
+
+the common case - no options or filenames
+
+  $ hg shelve
+  shelved as default-01
+  2 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  $ hg status -C
+
+ensure that our shelved changes exist
+
+  $ hg shelve -l
+  default-01      (*)    [mq]: second.patch (glob)
+  default         (*)    [mq]: second.patch (glob)
+
+  $ hg shelve -l -p default
+  default         (*)    [mq]: second.patch (glob)
+  
+  diff --git a/a/a b/a/a
+  --- a/a/a
+  +++ b/a/a
+  @@ -1,1 +1,2 @@
+   a
+  +a
+
+delete our older shelved change
+
+  $ hg shelve -d default
+  $ hg qfinish -a -q
+
+local edits should prevent a shelved change from applying
+
+  $ echo e>>a/a
+  $ hg unshelve
+  unshelving change 'default-01'
+  the following shelved files have been modified:
+    a/a
+  you must commit, revert, or shelve your changes before you can proceed
+  abort: cannot unshelve due to local changes
+  
+  [255]
+
+  $ hg revert -C a/a
+
+apply it and make sure our state is as expected
+
+  $ hg unshelve
+  unshelving change 'default-01'
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 3 changes to 8 files
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg status -C
+  M a/a
+  A b.rename/b
+    b/b
+  A c.copy
+    c
+  R b/b
+  $ hg shelve -l
+
+  $ hg unshelve
+  abort: no shelved changes to apply!
+  [255]
+  $ hg unshelve foo
+  abort: shelved change 'foo' not found
+  [255]
+
+named shelves, specific filenames, and "commit messages" should all work
+
+  $ hg status -C
+  M a/a
+  A b.rename/b
+    b/b
+  A c.copy
+    c
+  R b/b
+  $ hg shelve -q -n wibble -m wat a
+
+expect "a" to no longer be present, but status otherwise unchanged
+
+  $ hg status -C
+  A b.rename/b
+    b/b
+  A c.copy
+    c
+  R b/b
+  $ hg shelve -l --stat
+  wibble          (*)    wat (glob)
+   a/a |  1 +
+   1 files changed, 1 insertions(+), 0 deletions(-)
+
+and now "a/a" should reappear
+
+  $ hg unshelve -q wibble
+  $ hg status -C
+  M a/a
+  A b.rename/b
+    b/b
+  A c.copy
+    c
+  R b/b
+
+cause unshelving to result in a merge with 'a' conflicting
+
+  $ hg shelve -q
+  $ echo c>>a/a
+  $ hg commit -m second
+  $ hg tip --template '{files}\n'
+  a/a
+
+add an unrelated change that should be preserved
+
+  $ mkdir foo
+  $ echo foo > foo/foo
+  $ hg add foo/foo
+
+force a conflicted merge to occur
+
+  $ hg unshelve
+  unshelving change 'default'
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 3 changes to 8 files (+1 heads)
+  merging a/a
+  warning: conflicts during merge.
+  merging a/a incomplete! (edit conflicts, then use 'hg resolve --mark')
+  2 files updated, 0 files merged, 1 files removed, 1 files unresolved
+  use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
+  unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
+  [1]
+
+ensure that we have a merge with unresolved conflicts
+
+  $ hg heads -q
+  4:cebf2b8de087
+  3:2e69b451d1ea
+  $ hg parents -q
+  3:2e69b451d1ea
+  4:cebf2b8de087
+  $ hg status
+  M a/a
+  M b.rename/b
+  M c.copy
+  A foo/foo
+  R b/b
+  ? a/a.orig
+  $ hg diff
+  diff --git a/a/a b/a/a
+  --- a/a/a
+  +++ b/a/a
+  @@ -1,2 +1,6 @@
+   a
+  +<<<<<<< local
+   c
+  +=======
+  +a
+  +>>>>>>> other
+  diff --git a/b.rename/b b/b.rename/b
+  --- /dev/null
+  +++ b/b.rename/b
+  @@ -0,0 +1,1 @@
+  +b
+  diff --git a/b/b b/b/b
+  deleted file mode 100644
+  --- a/b/b
+  +++ /dev/null
+  @@ -1,1 +0,0 @@
+  -b
+  diff --git a/c.copy b/c.copy
+  --- /dev/null
+  +++ b/c.copy
+  @@ -0,0 +1,1 @@
+  +c
+  diff --git a/foo/foo b/foo/foo
+  new file mode 100644
+  --- /dev/null
+  +++ b/foo/foo
+  @@ -0,0 +1,1 @@
+  +foo
+  $ hg resolve -l
+  U a/a
+
+  $ hg shelve
+  abort: unshelve already in progress
+  (use 'hg unshelve --continue' or 'hg unshelve --abort')
+  [255]
+
+abort the unshelve and be happy
+
+  $ hg status
+  M a/a
+  M b.rename/b
+  M c.copy
+  A foo/foo
+  R b/b
+  ? a/a.orig
+  $ hg unshelve -a
+  unshelve of 'default' aborted
+  $ hg heads -q
+  3:2e69b451d1ea
+  $ hg parents
+  changeset:   3:2e69b451d1ea
+  tag:         tip
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     second
+  
+  $ hg resolve -l
+  $ hg status
+  A foo/foo
+  ? a/a.orig
+
+try to continue with no unshelve underway
+
+  $ hg unshelve -c
+  abort: no unshelve operation underway
+  [255]
+  $ hg status
+  A foo/foo
+  ? a/a.orig
+
+redo the unshelve to get a conflict
+
+  $ hg unshelve -q
+  warning: conflicts during merge.
+  merging a/a incomplete! (edit conflicts, then use 'hg resolve --mark')
+  unresolved conflicts (see 'hg resolve', then 'hg unshelve --continue')
+  [1]
+
+attempt to continue
+
+  $ hg unshelve -c
+  abort: unresolved conflicts, can't continue
+  (see 'hg resolve', then 'hg unshelve --continue')
+  [255]
+
+  $ hg revert -r . a/a
+  $ hg resolve -m a/a
+
+  $ hg unshelve -c
+  unshelve of 'default' complete
+
+ensure the repo is as we hope
+
+  $ hg parents
+  changeset:   3:2e69b451d1ea
+  tag:         tip
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     second
+  
+  $ hg heads -q
+  3:2e69b451d1ea
+
+  $ hg status -C
+  M b.rename/b
+    b/b
+  M c.copy
+    c
+  A foo/foo
+  R b/b
+  ? a/a.orig
+
+there should be no shelves left
+
+  $ hg shelve -l
+
+#if execbit
+
+ensure that metadata-only changes are shelved
+
+  $ chmod +x a/a
+  $ hg shelve -q -n execbit a/a
+  $ hg status a/a
+  $ hg unshelve -q execbit
+  $ hg status a/a
+  M a/a
+  $ hg revert a/a
+
+#endif
+
+#if symlink
+
+  $ rm a/a
+  $ ln -s foo a/a
+  $ hg shelve -q -n symlink a/a
+  $ hg status a/a
+  $ hg unshelve -q symlink
+  $ hg status a/a
+  M a/a
+  $ hg revert a/a
+
+#endif
+
+set up another conflict between a commit and a shelved change
+
+  $ hg revert -q -C -a
+  $ echo a >> a/a
+  $ hg shelve -q
+  $ echo x >> a/a
+  $ hg ci -m 'create conflict'
+  $ hg add foo/foo
+
+if we resolve a conflict while unshelving, the unshelve should succeed
+
+  $ HGMERGE=true hg unshelve
+  unshelving change 'default'
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 6 files (+1 heads)
+  merging a/a
+  0 files updated, 1 files merged, 0 files removed, 0 files unresolved
+  $ hg parents -q
+  4:33f7f61e6c5e
+  $ hg shelve -l
+  $ hg status
+  A foo/foo
+  $ cat a/a
+  a
+  c
+  x
+
+test keep and cleanup
+
+  $ hg shelve
+  shelved as default
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ hg shelve --list
+  default         (*)    create conflict (glob)
+  $ hg unshelve --keep
+  unshelving change 'default'
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 7 files
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg shelve --list
+  default         (*)    create conflict (glob)
+  $ hg shelve --cleanup
+  $ hg shelve --list
+
+test bookmarks
+
+  $ hg bookmark test
+  $ hg bookmark
+   * test                      4:33f7f61e6c5e
+  $ hg shelve
+  shelved as test
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ hg bookmark
+   * test                      4:33f7f61e6c5e
+  $ hg unshelve
+  unshelving change 'test'
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 7 files
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg bookmark
+   * test                      4:33f7f61e6c5e
+
+shelve should still work even if mq is disabled
+
+  $ hg --config extensions.mq=! shelve
+  shelved as test
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ hg --config extensions.mq=! shelve --list
+  test            (1s ago)    create conflict
+  $ hg --config extensions.mq=! unshelve
+  unshelving change 'test'
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 7 files
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+shelve should leave dirstate clean (issue 4055)
+
+  $ cd ..
+  $ hg init shelverebase
+  $ cd shelverebase
+  $ printf 'x\ny\n' > x
+  $ echo z > z
+  $ hg commit -Aqm xy
+  $ echo z >> x
+  $ hg commit -Aqm z
+  $ hg up 0
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ printf 'a\nx\ny\nz\n' > x
+  $ hg commit -Aqm xyz
+  $ echo c >> z
+  $ hg shelve
+  shelved as default
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg rebase -d 1 --config extensions.rebase=
+  merging x
+  saved backup bundle to $TESTTMP/shelverebase/.hg/strip-backup/323bfa07f744-backup.hg (glob)
+  $ hg unshelve
+  unshelving change 'default'
+  adding changesets
+  adding manifests
+  adding file changes
+  added 2 changesets with 2 changes to 2 files (+1 heads)
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg status
+  M z
+
+  $ cd ..
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-strip.t	Sun Oct 20 16:43:11 2013 -0700
@@ -0,0 +1,504 @@
+  $ echo "[extensions]" >> $HGRCPATH
+  $ echo "strip=" >> $HGRCPATH
+  $ echo "graphlog=" >> $HGRCPATH
+
+  $ restore() {
+  >     hg unbundle -q .hg/strip-backup/*
+  >     rm .hg/strip-backup/*
+  > }
+  $ teststrip() {
+  >     hg up -C $1
+  >     echo % before update $1, strip $2
+  >     hg parents
+  >     hg --traceback strip $2
+  >     echo % after update $1, strip $2
+  >     hg parents
+  >     restore
+  > }
+
+  $ hg init test
+  $ cd test
+
+  $ echo foo > bar
+  $ hg ci -Ama
+  adding bar
+
+  $ echo more >> bar
+  $ hg ci -Amb
+
+  $ echo blah >> bar
+  $ hg ci -Amc
+
+  $ hg up 1
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ echo blah >> bar
+  $ hg ci -Amd
+  created new head
+
+  $ echo final >> bar
+  $ hg ci -Ame
+
+  $ hg log
+  changeset:   4:443431ffac4f
+  tag:         tip
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     e
+  
+  changeset:   3:65bd5f99a4a3
+  parent:      1:ef3a871183d7
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     d
+  
+  changeset:   2:264128213d29
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     c
+  
+  changeset:   1:ef3a871183d7
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     b
+  
+  changeset:   0:9ab35a2d17cb
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     a
+  
+
+  $ teststrip 4 4
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  % before update 4, strip 4
+  changeset:   4:443431ffac4f
+  tag:         tip
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     e
+  
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
+  % after update 4, strip 4
+  changeset:   3:65bd5f99a4a3
+  tag:         tip
+  parent:      1:ef3a871183d7
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     d
+  
+  $ teststrip 4 3
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  % before update 4, strip 3
+  changeset:   4:443431ffac4f
+  tag:         tip
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     e
+  
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
+  % after update 4, strip 3
+  changeset:   1:ef3a871183d7
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     b
+  
+  $ teststrip 1 4
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  % before update 1, strip 4
+  changeset:   1:ef3a871183d7
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     b
+  
+  saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
+  % after update 1, strip 4
+  changeset:   1:ef3a871183d7
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     b
+  
+  $ teststrip 4 2
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  % before update 4, strip 2
+  changeset:   4:443431ffac4f
+  tag:         tip
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     e
+  
+  saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
+  % after update 4, strip 2
+  changeset:   3:443431ffac4f
+  tag:         tip
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     e
+  
+  $ teststrip 4 1
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  % before update 4, strip 1
+  changeset:   4:264128213d29
+  tag:         tip
+  parent:      1:ef3a871183d7
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     c
+  
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
+  % after update 4, strip 1
+  changeset:   0:9ab35a2d17cb
+  tag:         tip
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     a
+  
+  $ teststrip null 4
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  % before update null, strip 4
+  saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
+  % after update null, strip 4
+
+  $ hg log
+  changeset:   4:264128213d29
+  tag:         tip
+  parent:      1:ef3a871183d7
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     c
+  
+  changeset:   3:443431ffac4f
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     e
+  
+  changeset:   2:65bd5f99a4a3
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     d
+  
+  changeset:   1:ef3a871183d7
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     b
+  
+  changeset:   0:9ab35a2d17cb
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     a
+  
+
+  $ hg up -C 2
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg merge 4
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  (branch merge, don't forget to commit)
+
+before strip of merge parent
+
+  $ hg parents
+  changeset:   2:65bd5f99a4a3
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     d
+  
+  changeset:   4:264128213d29
+  tag:         tip
+  parent:      1:ef3a871183d7
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     c
+  
+  $ hg strip 4
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
+
+after strip of merge parent
+
+  $ hg parents
+  changeset:   1:ef3a871183d7
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     b
+  
+  $ restore
+
+  $ hg up
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg glog
+  @  changeset:   4:264128213d29
+  |  tag:         tip
+  |  parent:      1:ef3a871183d7
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     c
+  |
+  | o  changeset:   3:443431ffac4f
+  | |  user:        test
+  | |  date:        Thu Jan 01 00:00:00 1970 +0000
+  | |  summary:     e
+  | |
+  | o  changeset:   2:65bd5f99a4a3
+  |/   user:        test
+  |    date:        Thu Jan 01 00:00:00 1970 +0000
+  |    summary:     d
+  |
+  o  changeset:   1:ef3a871183d7
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     b
+  |
+  o  changeset:   0:9ab35a2d17cb
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     a
+  
+
+2 is parent of 3, only one strip should happen
+
+  $ hg strip "roots(2)" 3
+  saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
+  $ hg glog
+  @  changeset:   2:264128213d29
+  |  tag:         tip
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     c
+  |
+  o  changeset:   1:ef3a871183d7
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     b
+  |
+  o  changeset:   0:9ab35a2d17cb
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     a
+  
+  $ restore
+  $ hg glog
+  o  changeset:   4:443431ffac4f
+  |  tag:         tip
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     e
+  |
+  o  changeset:   3:65bd5f99a4a3
+  |  parent:      1:ef3a871183d7
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     d
+  |
+  | @  changeset:   2:264128213d29
+  |/   user:        test
+  |    date:        Thu Jan 01 00:00:00 1970 +0000
+  |    summary:     c
+  |
+  o  changeset:   1:ef3a871183d7
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     b
+  |
+  o  changeset:   0:9ab35a2d17cb
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     a
+  
+
+2 different branches: 2 strips
+
+  $ hg strip 2 4
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
+  $ hg glog
+  o  changeset:   2:65bd5f99a4a3
+  |  tag:         tip
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     d
+  |
+  @  changeset:   1:ef3a871183d7
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     b
+  |
+  o  changeset:   0:9ab35a2d17cb
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     a
+  
+  $ restore
+
+2 different branches and a common ancestor: 1 strip
+
+  $ hg strip 1 "2|4"
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
+  $ restore
+
+stripping an empty revset
+
+  $ hg strip "1 and not 1"
+  abort: empty revision set
+  [255]
+
+remove branchy history for qimport tests
+
+  $ hg strip 3
+  saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
+
+
+strip of applied mq should cleanup status file
+
+  $ echo "mq=" >> $HGRCPATH
+  $ hg up -C 3
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ echo fooagain >> bar
+  $ hg ci -mf
+  $ hg qimport -r tip:2
+
+applied patches before strip
+
+  $ hg qapplied
+  2.diff
+  3.diff
+  4.diff
+
+stripping revision in queue
+
+  $ hg strip 3
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
+
+applied patches after stripping rev in queue
+
+  $ hg qapplied
+  2.diff
+
+stripping ancestor of queue
+
+  $ hg strip 1
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
+
+applied patches after stripping ancestor of queue
+
+  $ hg qapplied
+
+Verify strip protects against stripping wc parent when there are uncommited mods
+
+  $ echo b > b
+  $ hg add b
+  $ hg ci -m 'b'
+  $ hg log --graph
+  @  changeset:   1:7519abd79d14
+  |  tag:         tip
+  |  user:        test
+  |  date:        Thu Jan 01 00:00:00 1970 +0000
+  |  summary:     b
+  |
+  o  changeset:   0:9ab35a2d17cb
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     a
+  
+
+  $ echo c > b
+  $ echo c > bar
+  $ hg strip tip
+  abort: local changes found
+  [255]
+  $ hg strip tip --keep
+  saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
+  $ hg log --graph
+  @  changeset:   0:9ab35a2d17cb
+     tag:         tip
+     user:        test
+     date:        Thu Jan 01 00:00:00 1970 +0000
+     summary:     a
+  
+  $ hg status
+  M bar
+  ? b
+
+Strip adds, removes, modifies with --keep
+
+  $ touch b
+  $ hg add b
+  $ hg commit -mb
+  $ touch c
+
+... with a clean working dir
+
+  $ hg add c
+  $ hg rm bar
+  $ hg commit -mc
+  $ hg status
+  $ hg strip --keep tip
+  saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
+  $ hg status
+  ! bar
+  ? c
+
+... with a dirty working dir
+
+  $ hg add c
+  $ hg rm bar
+  $ hg commit -mc
+  $ hg status
+  $ 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)
+
+  $ hg init issue3299
+  $ cd issue3299
+  $ hg debugbuilddag '@a.:a@b.:b.:x<a@a.:a<b@b.:b<a@a.:a'
+  $ hg strip 'not ancestors(x)'
+  saved backup bundle to $TESTTMP/issue3299/.hg/strip-backup/*-backup.hg (glob)
+
+test hg strip -B bookmark
+
+  $ cd ..
+  $ hg init bookmarks
+  $ cd bookmarks
+  $ hg debugbuilddag '..<2.*1/2:m<2+3:c<m+3:a<2.:b'
+  $ hg bookmark -r 'a' 'todelete'
+  $ hg bookmark -r 'b' 'B'
+  $ hg bookmark -r 'b' 'nostrip'
+  $ hg bookmark -r 'c' 'delete'
+  $ hg up -C todelete
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg strip -B nostrip
+  bookmark 'nostrip' deleted
+  abort: empty revision set
+  [255]
+  $ hg strip -B todelete
+  bookmark 'todelete' deleted
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  saved backup bundle to $TESTTMP/bookmarks/.hg/strip-backup/*-backup.hg (glob)
+  $ hg id -ir dcbb326fdec2
+  abort: unknown revision 'dcbb326fdec2'!
+  [255]
+  $ hg id -ir d62d843c9a01
+  d62d843c9a01
+  $ hg bookmarks
+     B                         9:ff43616e5d0f
+     delete                    6:2702dd0c91e7
+  $ hg strip -B delete
+  bookmark 'delete' deleted
+  saved backup bundle to $TESTTMP/bookmarks/.hg/strip-backup/*-backup.hg (glob)
+  $ hg id -ir 6:2702dd0c91e7
+  abort: unknown revision '2702dd0c91e7'!
+  [255]
+
+  $ cd ..
--- a/tests/test-subrepo-git.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-subrepo-git.t	Sun Oct 20 16:43:11 2013 -0700
@@ -155,6 +155,8 @@
   added 1 changesets with 1 changes to 1 files (+1 heads)
   (run 'hg heads' to see heads, 'hg merge' to merge)
   $ hg merge 2>/dev/null
+   subrepository s diverged (local revision: 796959400868, remote revision: aa84837ccfbd)
+  (M)erge, keep (l)ocal or keep (r)emote? m
   pulling subrepo s from $TESTTMP/gitroot
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
@@ -462,6 +464,8 @@
   da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
   $ cd ..
   $ hg update 4
+   subrepository s diverged (local revision: da5f5b1d8ffc, remote revision: aa84837ccfbd)
+  (M)erge, keep (l)ocal or keep (r)emote? m
    subrepository sources for s differ
   use (l)ocal source (da5f5b1) or (r)emote source (aa84837)?
    l
@@ -487,6 +491,8 @@
   HEAD is now at aa84837... f
   $ cd ..
   $ hg update 1
+   subrepository s diverged (local revision: 32a343883b74, remote revision: da5f5b1d8ffc)
+  (M)erge, keep (l)ocal or keep (r)emote? m
    subrepository sources for s differ (in checked out version)
   use (l)ocal source (32a3438) or (r)emote source (da5f5b1)?
    l
@@ -508,6 +514,8 @@
   $ hg id -n
   1+
   $ hg update 7
+   subrepository s diverged (local revision: 32a343883b74, remote revision: 32a343883b74)
+  (M)erge, keep (l)ocal or keep (r)emote? m
    subrepository sources for s differ
   use (l)ocal source (32a3438) or (r)emote source (32a3438)?
    l
--- a/tests/test-subrepo-svn.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-subrepo-svn.t	Sun Oct 20 16:43:11 2013 -0700
@@ -319,6 +319,8 @@
   2M
   $ cd ..
   $ hg update tip
+   subrepository s diverged (local revision: 2, remote revision: 3)
+  (M)erge, keep (l)ocal or keep (r)emote? m
    subrepository sources for s differ
   use (l)ocal source (2) or (r)emote source (3)?
    l
@@ -349,6 +351,8 @@
   $ svn update -qr 1
   $ cd ..
   $ hg update 1
+   subrepository s diverged (local revision: 3, remote revision: 2)
+  (M)erge, keep (l)ocal or keep (r)emote? m
    subrepository sources for s differ (in checked out version)
   use (l)ocal source (1) or (r)emote source (2)?
    l
@@ -371,6 +375,8 @@
   $ hg id -n
   1+
   $ hg update tip
+   subrepository s diverged (local revision: 3, remote revision: 3)
+  (M)erge, keep (l)ocal or keep (r)emote? m
    subrepository sources for s differ
   use (l)ocal source (1) or (r)emote source (3)?
    l
@@ -404,6 +410,8 @@
   $ svn update -qr 2
   $ cd ..
   $ hg update 1
+   subrepository s diverged (local revision: 3, remote revision: 2)
+  (M)erge, keep (l)ocal or keep (r)emote? m
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg id -n
   1+
@@ -477,7 +485,8 @@
 This is surprising, but is also correct based on the current code:
   $ echo "updating should (maybe) fail" > obstruct/other
   $ hg co tip
-  abort: crosses branches (merge branches or use --clean to discard changes)
+  abort: uncommitted changes
+  (commit or update --clean to discard changes)
   [255]
 
 Point to a Subversion branch which has since been deleted and recreated
--- a/tests/test-subrepo.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-subrepo.t	Sun Oct 20 16:43:11 2013 -0700
@@ -236,7 +236,9 @@
    .hgsubstate: versions differ -> m
   updating: .hgsubstate 1/1 files (100.00%)
   subrepo merge e45c8b14af55+ f94576341bcf 1831e14459c4
-    subrepo t: both sides changed, merge with t:7af322bc1198a32402fe903e0b7ebcfc5c9bf8f4:hg
+    subrepo t: both sides changed 
+   subrepository t diverged (local revision: 20a0db6fbf6c, remote revision: 7af322bc1198)
+  (M)erge, keep (l)ocal or keep (r)emote? m
   merging subrepo t
     searching for copies back to rev 2
   resolving manifests
@@ -252,6 +254,7 @@
   merging t incomplete! (edit conflicts, then use 'hg resolve --mark')
   0 files updated, 0 files merged, 0 files removed, 1 files unresolved
   use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
+    subrepo t: merge with t:7af322bc1198a32402fe903e0b7ebcfc5c9bf8f4:hg
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
 
@@ -314,7 +317,7 @@
   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)
+  (merge or see "hg help push" for details about pushing new heads)
   [255]
   $ hg push -f
   pushing to $TESTTMP/t (glob)
@@ -620,6 +623,8 @@
   $ hg up 5
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg merge 4    # try to merge default into br again
+   subrepository s diverged (local revision: f8f13b33206e, remote revision: a3f9062a4f88)
+  (M)erge, keep (l)ocal or keep (r)emote? m
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
   $ cd ..
@@ -711,7 +716,7 @@
   $ hg -R repo2 ci -m3
   $ hg -q -R repo2 push
   abort: push creates new remote head cc505f09a8b2! (in subrepo s)
-  (did you forget to merge? use push -f to force)
+  (merge or see "hg help push" for details about pushing new heads)
   [255]
   $ hg -R repo update
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
@@ -922,9 +927,13 @@
   $ hg -R t id
   e95bcfa18a35+
   $ hg update tip
+   subrepository s diverged (local revision: fc627a69481f, remote revision: 12a213df6fa9)
+  (M)erge, keep (l)ocal or keep (r)emote? m
    subrepository sources for s differ
   use (l)ocal source (fc627a69481f) or (r)emote source (12a213df6fa9)?
    l
+   subrepository t diverged (local revision: e95bcfa18a35, remote revision: 52c0adc0515a)
+  (M)erge, keep (l)ocal or keep (r)emote? m
    subrepository sources for t differ
   use (l)ocal source (e95bcfa18a35) or (r)emote source (52c0adc0515a)?
    l
@@ -953,6 +962,10 @@
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ cd ..
   $ hg update 10
+   subrepository s diverged (local revision: 12a213df6fa9, remote revision: fc627a69481f)
+  (M)erge, keep (l)ocal or keep (r)emote? m
+   subrepository t diverged (local revision: 52c0adc0515a, remote revision: 20a0db6fbf6c)
+  (M)erge, keep (l)ocal or keep (r)emote? m
    subrepository sources for t differ (in checked out version)
   use (l)ocal source (7af322bc1198) or (r)emote source (20a0db6fbf6c)?
    l
@@ -976,9 +989,13 @@
   $ hg -R t id
   7af322bc1198+
   $ hg update tip
+   subrepository s diverged (local revision: 12a213df6fa9, remote revision: 12a213df6fa9)
+  (M)erge, keep (l)ocal or keep (r)emote? m
    subrepository sources for s differ
   use (l)ocal source (02dcf1d70411) or (r)emote source (12a213df6fa9)?
    l
+   subrepository t diverged (local revision: 52c0adc0515a, remote revision: 52c0adc0515a)
+  (M)erge, keep (l)ocal or keep (r)emote? m
    subrepository sources for t differ
   use (l)ocal source (7af322bc1198) or (r)emote source (52c0adc0515a)?
    l
@@ -1006,6 +1023,8 @@
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ cd ..
   $ hg update 11
+   subrepository s diverged (local revision: 12a213df6fa9, remote revision: fc627a69481f)
+  (M)erge, keep (l)ocal or keep (r)emote? m
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg id -n
--- a/tests/test-symlink-placeholder.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-symlink-placeholder.t	Sun Oct 20 16:43:11 2013 -0700
@@ -41,6 +41,13 @@
   a (no-eol)
   $ hg --config extensions.n=$TESTTMP/nolink.py st --debug
 
+Empty placeholder:
+
+  $ rm b
+  $ touch b
+  $ hg --config extensions.n=$TESTTMP/nolink.py st --debug
+  ignoring suspect symlink placeholder "b"
+
 Write binary data to the placeholder:
 
   >>> open('b', 'w').write('this is a binary\0')
--- a/tests/test-trusted.py	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-trusted.py	Sun Oct 20 16:43:11 2013 -0700
@@ -145,7 +145,7 @@
 f.write('[foobar]\n')
 f.write('baz = quux\n')
 f.close()
-u.readconfig(filename, sections = ['foobar'])
+u.readconfig(filename, sections=['foobar'])
 print u.config('foobar', 'baz')
 
 print
--- a/tests/test-up-local-change.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-up-local-change.t	Sun Oct 20 16:43:11 2013 -0700
@@ -167,10 +167,11 @@
   summary:     2
   
   $ hg --debug up
-  abort: crosses branches (merge branches or use --clean to discard changes)
+  abort: uncommitted changes
+  (commit and merge, or update --clean to discard changes)
   [255]
   $ hg --debug merge
-  abort: outstanding uncommitted changes
+  abort: uncommitted changes
   (use 'hg status' to list changes)
   [255]
   $ hg --debug merge -f
--- a/tests/test-update-branches.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-update-branches.t	Sun Oct 20 16:43:11 2013 -0700
@@ -94,7 +94,8 @@
   parent=5
 
   $ norevtest 'none clean same'   clean 2
-  abort: crosses branches (merge branches or update --check to force update)
+  abort: not a linear update
+  (merge or update --check to force update)
   parent=2
 
 
@@ -122,22 +123,32 @@
   M sub/suba
 
   $ revtest 'none dirty same'   dirty 2 3
-  abort: crosses branches (merge branches or use --clean to discard changes)
+  abort: uncommitted changes
+  (commit or update --clean to discard changes)
   parent=2
   M foo
 
   $ revtest 'none dirtysub same'   dirtysub 2 3
-  abort: crosses branches (merge branches or use --clean to discard changes)
+  abort: uncommitted changes
+  (commit or update --clean to discard changes)
   parent=2
   M sub/suba
 
   $ revtest 'none dirty cross'  dirty 3 4
-  abort: crosses branches (merge branches or use --clean to discard changes)
+  abort: uncommitted changes
+  (commit or update --clean to discard changes)
   parent=3
   M foo
 
+  $ norevtest 'none dirty cross'  dirty 2
+  abort: uncommitted changes
+  (commit and merge, or update --clean to discard changes)
+  parent=2
+  M foo
+
   $ revtest 'none dirtysub cross'  dirtysub 3 4
-  abort: crosses branches (merge branches or use --clean to discard changes)
+  abort: uncommitted changes
+  (commit or update --clean to discard changes)
   parent=3
   M sub/suba
 
@@ -146,12 +157,12 @@
   parent=2
 
   $ revtest '-c dirty linear'   dirty 1 2 -c
-  abort: uncommitted local changes
+  abort: uncommitted changes
   parent=1
   M foo
 
   $ revtest '-c dirtysub linear'   dirtysub 1 2 -c
-  abort: uncommitted local changes
+  abort: uncommitted changes
   parent=1
   M sub/suba
 
@@ -222,5 +233,6 @@
   $ hg up --quiet 0
   $ hg up --quiet 2
   $ hg up 5
-  abort: crosses branches (merge branches or use --clean to discard changes)
+  abort: uncommitted changes
+  (commit or update --clean to discard changes)
   [255]
--- a/tests/test-update-issue1456.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-update-issue1456.t	Sun Oct 20 16:43:11 2013 -0700
@@ -18,7 +18,7 @@
 
   $ echo dirty > foo
   $ hg up -c
-  abort: uncommitted local changes
+  abort: uncommitted changes
   [255]
   $ hg up -q
   $ cat foo
--- a/tests/test-walk.t	Sat Oct 19 14:20:31 2013 -0700
+++ b/tests/test-walk.t	Sun Oct 20 16:43:11 2013 -0700
@@ -3,11 +3,11 @@
   $ mkdir -p beans
   $ for b in kidney navy turtle borlotti black pinto; do
   >     echo $b > beans/$b
-  $ done
+  > done
   $ mkdir -p mammals/Procyonidae
   $ for m in cacomistle coatimundi raccoon; do
   >     echo $m > mammals/Procyonidae/$m
-  $ done
+  > done
   $ echo skunk > mammals/skunk
   $ echo fennel > fennel
   $ echo fenugreek > fenugreek