changeset 19750:d4ed26beae0e

merge with stable
author Matt Mackall <mpm@selenic.com>
date Wed, 18 Sep 2013 14:52:16 -0500
parents da3808bcfbfa (diff) f2871c30e6a7 (current diff)
children 11fdf9f754b7
files
diffstat 53 files changed, 1390 insertions(+), 563 deletions(-) [+]
line wrap: on
line diff
--- a/contrib/check-code.py	Wed Sep 18 14:40:17 2013 -0400
+++ b/contrib/check-code.py	Wed Sep 18 14:52:16 2013 -0500
@@ -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"),
@@ -285,8 +287,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 +327,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/perf.py	Wed Sep 18 14:40:17 2013 -0400
+++ b/contrib/perf.py	Wed Sep 18 14:52:16 2013 -0500
@@ -171,13 +171,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	Wed Sep 18 14:52:16 2013 -0500
@@ -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	Wed Sep 18 14:40:17 2013 -0400
+++ b/contrib/plan9/hgrc.d/9diff.rc	Wed Sep 18 14:52:16 2013 -0500
@@ -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	Wed Sep 18 14:52:16 2013 -0500
@@ -0,0 +1,4 @@
+# The 9mail to support patchbomb and other email wrappers
+[email]
+method = /bin/mercurial/9mail
+
--- a/hgext/factotum.py	Wed Sep 18 14:40:17 2013 -0400
+++ b/hgext/factotum.py	Wed Sep 18 14:52:16 2013 -0500
@@ -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/histedit.py	Wed Sep 18 14:40:17 2013 -0400
+++ b/hgext/histedit.py	Wed Sep 18 14:52:16 2013 -0500
@@ -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'))
--- a/hgext/largefiles/reposetup.py	Wed Sep 18 14:40:17 2013 -0400
+++ b/hgext/largefiles/reposetup.py	Wed Sep 18 14:52:16 2013 -0500
@@ -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['.']
 
--- a/hgext/mq.py	Wed Sep 18 14:40:17 2013 -0400
+++ b/hgext/mq.py	Wed Sep 18 14:52:16 2013 -0500
@@ -66,6 +66,7 @@
 from mercurial import repair, 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"
@@ -800,6 +801,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,
@@ -975,11 +984,20 @@
         else:
             raise util.Abort(_("local changes found"))
 
+    def localchangedsubreposfound(self, refresh=True):
+        if refresh:
+            raise util.Abort(_("local changed subrepos found, refresh first"))
+        else:
+            raise util.Abort(_("local changed subrepos 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)
+        if not force:
+            if (m or a or r or d):
+                self.localchangesfound(refresh)
+            if self.checksubstate(repo):
+                self.localchangedsubreposfound(refresh)
         return m, a, r, d
 
     _reserved = ('series', 'status', 'guards', '.', '..')
@@ -1450,6 +1468,8 @@
                 self.ui.status(_("popping %s\n") % patch.name)
             del self.applied[start:end]
             self.strip(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:
--- a/hgext/progress.py	Wed Sep 18 14:40:17 2013 -0400
+++ b/hgext/progress.py	Wed Sep 18 14:52:16 2013 -0500
@@ -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/mercurial/bundlerepo.py	Wed Sep 18 14:40:17 2013 -0400
+++ b/mercurial/bundlerepo.py	Wed Sep 18 14:52:16 2013 -0500
@@ -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/cmdutil.py	Wed Sep 18 14:40:17 2013 -0400
+++ b/mercurial/cmdutil.py	Wed Sep 18 14:52:16 2013 -0500
@@ -1172,12 +1172,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	Wed Sep 18 14:40:17 2013 -0400
+++ b/mercurial/commands.py	Wed Sep 18 14:52:16 2013 -0500
@@ -1923,6 +1923,7 @@
     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')
--- a/mercurial/context.py	Wed Sep 18 14:40:17 2013 -0400
+++ b/mercurial/context.py	Wed Sep 18 14:52:16 2013 -0500
@@ -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
@@ -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()
@@ -1129,31 +1188,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 +1199,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,6 +1229,24 @@
     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
     def date(self):
--- a/mercurial/dirstate.py	Wed Sep 18 14:40:17 2013 -0400
+++ b/mercurial/dirstate.py	Wed Sep 18 14:52:16 2013 -0500
@@ -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
@@ -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/dispatch.py	Wed Sep 18 14:40:17 2013 -0400
+++ b/mercurial/dispatch.py	Wed Sep 18 14:52:16 2013 -0500
@@ -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/hgweb/webcommands.py	Wed Sep 18 14:40:17 2013 -0400
+++ b/mercurial/hgweb/webcommands.py	Wed Sep 18 14:52:16 2013 -0500
@@ -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,
+        MODE_KEYWORD: keywordsearch,
+        MODE_REVSET: revsetsearch,
+    }
+
+    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(funcarg):
             count += 1
             n = ctx.node()
             showtags = webutil.showtag(web.repo, tmpl, 'changelogtag', n)
@@ -176,6 +239,9 @@
     morevars['revcount'] = revcount * 2
     morevars['rev'] = query
 
+    mode, funcarg = getsearchmode(query)
+    searchfunc = searchfuncs[mode]
+
     tip = web.repo['tip']
     parity = paritygen(web.stripecount)
 
@@ -188,23 +254,15 @@
     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 +271,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,10 +307,18 @@
 
     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)
 
@@ -617,7 +683,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 +741,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	Wed Sep 18 14:40:17 2013 -0400
+++ b/mercurial/httpclient/__init__.py	Wed Sep 18 14:52:16 2013 -0500
@@ -495,6 +495,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 +644,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/localrepo.py	Wed Sep 18 14:40:17 2013 -0400
+++ b/mercurial/localrepo.py	Wed Sep 18 14:52:16 2013 -0500
@@ -39,6 +39,8 @@
     """propertycache that apply to unfiltered repo only"""
 
     def __get__(self, repo, type=None):
+        if hasunfilteredcache(repo, self.name):
+            return getattr(repo.unfiltered(), self.name)
         return super(unfilteredpropertycache, self).__get__(repo.unfiltered())
 
 class filteredpropertycache(propertycache):
@@ -1457,14 +1459,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['.']
@@ -1561,7 +1557,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
--- a/mercurial/obsolete.py	Wed Sep 18 14:40:17 2013 -0400
+++ b/mercurial/obsolete.py	Wed Sep 18 14:52:16 2013 -0500
@@ -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	Wed Sep 18 14:40:17 2013 -0400
+++ b/mercurial/parsers.c	Wed Sep 18 14:52:16 2013 -0500
@@ -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/pure/parsers.py	Wed Sep 18 14:40:17 2013 -0400
+++ b/mercurial/pure/parsers.py	Wed Sep 18 14:52:16 2013 -0500
@@ -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	Wed Sep 18 14:40:17 2013 -0400
+++ b/mercurial/revlog.py	Wed Sep 18 14:52:16 2013 -0500
@@ -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	Wed Sep 18 14:40:17 2013 -0400
+++ b/mercurial/revset.py	Wed Sep 18 14:52:16 2013 -0500
@@ -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	Wed Sep 18 14:40:17 2013 -0400
+++ b/mercurial/scmutil.py	Wed Sep 18 14:52:16 2013 -0500
@@ -755,7 +755,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/subrepo.py	Wed Sep 18 14:40:17 2013 -0400
+++ b/mercurial/subrepo.py	Wed Sep 18 14:52:16 2013 -0500
@@ -237,6 +237,7 @@
 
     # record merged .hgsubstate
     writestate(repo, sm)
+    return sm
 
 def _updateprompt(ui, sub, dirty, local, remote):
     if dirty:
--- a/mercurial/templatefilters.py	Wed Sep 18 14:40:17 2013 -0400
+++ b/mercurial/templatefilters.py	Wed Sep 18 14:52:16 2013 -0500
@@ -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
--- a/mercurial/templates/paper/fileannotate.tmpl	Wed Sep 18 14:40:17 2013 -0400
+++ b/mercurial/templates/paper/fileannotate.tmpl	Wed Sep 18 14:52:16 2013 -0500
@@ -65,7 +65,6 @@
  <th class="author">children</th>
  <td class="author">{child%filerevchild}</td>
 </tr>
-{changesettag}
 </table>
 
 <div class="overflow">
--- a/mercurial/templates/paper/filecomparison.tmpl	Wed Sep 18 14:40:17 2013 -0400
+++ b/mercurial/templates/paper/filecomparison.tmpl	Wed Sep 18 14:52:16 2013 -0500
@@ -64,7 +64,6 @@
  <th>children</th>
  <td>{child%filerevchild}</td>
 </tr>
-{changesettag}
 </table>
 
 <div class="overflow">
--- a/mercurial/templates/paper/filediff.tmpl	Wed Sep 18 14:40:17 2013 -0400
+++ b/mercurial/templates/paper/filediff.tmpl	Wed Sep 18 14:52:16 2013 -0500
@@ -64,7 +64,6 @@
  <th>children</th>
  <td>{child%filerevchild}</td>
 </tr>
-{changesettag}
 </table>
 
 <div class="overflow">
--- a/mercurial/templates/paper/filerevision.tmpl	Wed Sep 18 14:40:17 2013 -0400
+++ b/mercurial/templates/paper/filerevision.tmpl	Wed Sep 18 14:52:16 2013 -0500
@@ -63,7 +63,6 @@
  <th class="author">children</th>
  <td class="author">{child%filerevchild}</td>
 </tr>
-{changesettag}
 </table>
 
 <div class="overflow">
--- a/mercurial/templates/paper/shortlog.tmpl	Wed Sep 18 14:40:17 2013 -0400
+++ b/mercurial/templates/paper/shortlog.tmpl	Wed Sep 18 14:52:16 2013 -0500
@@ -72,6 +72,18 @@
 | rev {rev}: {changenav%navshort}
 </div>
 
+<script type="text/javascript">
+    ajaxScrollInit(
+            '{url|urlescape}shortlog/%hash%',
+            '{nextentry%"{node}"}', <!-- NEXTHASH
+            /'(\w+)', <!-- NEXTHASH/,
+            '.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	Wed Sep 18 14:40:17 2013 -0400
+++ b/mercurial/templates/paper/shortlogentry.tmpl	Wed Sep 18 14:52:16 2013 -0500
@@ -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/static/mercurial.js	Wed Sep 18 14:40:17 2013 -0400
+++ b/mercurial/templates/static/mercurial.js	Wed Sep 18 14:52:16 2013 -0500
@@ -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,13 @@
 	this.cell = [2, 0];
 	this.columns = 0;
 	this.revlink = '';
-	
+
 	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 +55,7 @@
 	}
 
 	this.setColor = function(color, bg, fg) {
-		
+
 		// Set the colour.
 		//
 		// If color is a string, expect an hexadecimal RGB
@@ -81,11 +81,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 +93,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,44 +125,44 @@
 				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;
-		
+
 	}
 
 }
@@ -258,6 +258,7 @@
 					// We want both: date + (age)
 					node.textContent += ' ('+agevalue+')';
 				} else {
+					node.title = node.textContent;
 					node.textContent = agevalue;
 				}
 			}
@@ -297,3 +298,108 @@
 
     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,
+                        nextHash,
+                        nextHashRegex,
+                        containerSelector,
+                        messageFormat) {
+    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;
+
+            if (!nextHash) {
+                return;
+            }
+
+            makeRequest(
+                format(urlFormat, {hash: nextHash}),
+                'GET',
+                function onstart() {
+                },
+                function onsuccess(htmlText) {
+                    var m = htmlText.match(nextHashRegex);
+                    nextHash = m ? m[1] : null;
+
+                    var doc = docFromHTML(htmlText);
+                    var nodes = doc.querySelector(containerSelector).children;
+                    while (nodes.length) {
+                        var node = nodes[0];
+                        node = document.adoptNode(node);
+                        container.appendChild(node);
+                    }
+                    process_dates();
+                },
+                function onerror(errorText) {
+                },
+                function oncomplete() {
+                    updateInitiated = false;
+                    scrollHandler();
+                }
+            );
+        }
+    }
+
+    window.addEventListener('scroll', scrollHandler);
+    window.addEventListener('resize', scrollHandler);
+    scrollHandler();
+}
--- a/mercurial/ui.py	Wed Sep 18 14:40:17 2013 -0400
+++ b/mercurial/ui.py	Wed Sep 18 14:52:16 2013 -0500
@@ -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	Wed Sep 18 14:40:17 2013 -0400
+++ b/mercurial/unionrepo.py	Wed Sep 18 14:52:16 2013 -0500
@@ -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	Wed Sep 18 14:40:17 2013 -0400
+++ b/mercurial/url.py	Wed Sep 18 14:52:16 2013 -0500
@@ -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	Wed Sep 18 14:40:17 2013 -0400
+++ b/mercurial/util.h	Wed Sep 18 14:52:16 2013 -0500
@@ -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
@@ -146,6 +151,17 @@
 #define inline __inline
 #endif
 
+#if defined(_MSC_VER) && (_MSC_VER >= 1300)
+static inline uint32_t getbe32(const char *c)
+{
+	return _byteswap_ulong(*(uint32_t *)c);
+}
+#elif GCC_VERSION >= 403
+static inline uint32_t getbe32(const char *c)
+{
+	return __builtin_bswap32(*(uint32_t *)c);
+}
+#else
 static inline uint32_t getbe32(const char *c)
 {
 	const unsigned char *d = (const unsigned char *)c;
@@ -155,7 +171,21 @@
 		(d[2] << 8) |
 		(d[3]));
 }
+#endif
 
+#if defined(_MSC_VER) && (_MSC_VER >= 1300)
+static inline void putbe32(uint32_t x, char *c)
+{
+	x = _byteswap_ulong(x);
+	*(uint32_t *)c = x;
+}
+#elif GCC_VERSION >= 403
+static inline void putbe32(uint32_t x, char *c)
+{
+	x = __builtin_bswap32(x);
+	*(uint32_t *)c = x;
+}
+#else
 static inline void putbe32(uint32_t x, char *c)
 {
 	c[0] = (x >> 24) & 0xff;
@@ -163,5 +193,6 @@
 	c[2] = (x >> 8) & 0xff;
 	c[3] = (x) & 0xff;
 }
+#endif
 
 #endif /* _HG_UTIL_H_ */
--- a/mercurial/util.py	Wed Sep 18 14:40:17 2013 -0400
+++ b/mercurial/util.py	Wed Sep 18 14:52:16 2013 -0500
@@ -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 = {}
@@ -465,7 +469,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	Wed Sep 18 14:40:17 2013 -0400
+++ b/setup.py	Wed Sep 18 14:52:16 2013 -0500
@@ -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/run-tests.py	Wed Sep 18 14:40:17 2013 -0400
+++ b/tests/run-tests.py	Wed Sep 18 14:52:16 2013 -0500
@@ -921,8 +921,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
--- a/tests/test-hgweb-commands.t	Wed Sep 18 14:40:17 2013 -0400
+++ b/tests/test-hgweb-commands.t	Wed Sep 18 14:52:16 2013 -0500
@@ -305,6 +305,18 @@
   | rev 3: <a href="/shortlog/2ef0ac749a14">(0)</a> <a href="/shortlog/tip">tip</a> 
   </div>
   
+  <script type="text/javascript">
+      ajaxScrollInit(
+              '/shortlog/%hash%',
+              '', <!-- NEXTHASH
+              /'(\w+)', <!-- NEXTHASH/,
+              '.bigtable > tbody:nth-of-type(2)',
+              '<tr class="%class%">\
+              <td colspan="3" style="text-align: center;">%text%</td>\
+              </tr>'
+      );
+  </script>
+  
   </div>
   </div>
   
@@ -537,6 +549,153 @@
   </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^"
+  
+  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)^"
+  
+  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)^"
+  
+  
+  $ "$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)^"
+  
+  
+  $ "$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)"
+  
+  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)"
+  
+  
+  $ "$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:"
+  
+  
+
+  $ "$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")"
+  
+  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")"
+  
+  
 
 File-related
 
@@ -637,7 +796,6 @@
    <th class="author">children</th>
    <td class="author"><a href="/file/1d22e65f027e/foo">1d22e65f027e</a> </td>
   </tr>
-  
   </table>
   
   <div class="overflow">
@@ -1256,8 +1414,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-diffs.t	Wed Sep 18 14:40:17 2013 -0400
+++ b/tests/test-hgweb-diffs.t	Wed Sep 18 14:52:16 2013 -0500
@@ -269,7 +269,6 @@
    <th>children</th>
    <td></td>
   </tr>
-  
   </table>
   
   <div class="overflow">
@@ -538,7 +537,6 @@
    <th>children</th>
    <td></td>
   </tr>
-  
   </table>
   
   <div class="overflow">
@@ -638,7 +636,6 @@
    <th>children</th>
    <td></td>
   </tr>
-  
   </table>
   
   <div class="overflow">
@@ -760,7 +757,6 @@
    <th>children</th>
    <td></td>
   </tr>
-  
   </table>
   
   <div class="overflow">
@@ -884,7 +880,6 @@
    <th>children</th>
    <td></td>
   </tr>
-  
   </table>
   
   <div class="overflow">
--- a/tests/test-hgweb-empty.t	Wed Sep 18 14:40:17 2013 -0400
+++ b/tests/test-hgweb-empty.t	Wed Sep 18 14:52:16 2013 -0500
@@ -90,6 +90,18 @@
   | rev -1: 
   </div>
   
+  <script type="text/javascript">
+      ajaxScrollInit(
+              '/shortlog/%hash%',
+              '', <!-- NEXTHASH
+              /'(\w+)', <!-- NEXTHASH/,
+              '.bigtable > tbody:nth-of-type(2)',
+              '<tr class="%class%">\
+              <td colspan="3" style="text-align: center;">%text%</td>\
+              </tr>'
+      );
+  </script>
+  
   </div>
   </div>
   
@@ -185,6 +197,18 @@
   | rev -1: 
   </div>
   
+  <script type="text/javascript">
+      ajaxScrollInit(
+              '/shortlog/%hash%',
+              '', <!-- NEXTHASH
+              /'(\w+)', <!-- NEXTHASH/,
+              '.bigtable > tbody:nth-of-type(2)',
+              '<tr class="%class%">\
+              <td colspan="3" style="text-align: center;">%text%</td>\
+              </tr>'
+      );
+  </script>
+  
   </div>
   </div>
   
--- a/tests/test-hgweb-removed.t	Wed Sep 18 14:40:17 2013 -0400
+++ b/tests/test-hgweb-removed.t	Wed Sep 18 14:52:16 2013 -0500
@@ -213,7 +213,6 @@
    <th>children</th>
    <td></td>
   </tr>
-  
   </table>
   
   <div class="overflow">
--- a/tests/test-highlight.t	Wed Sep 18 14:40:17 2013 -0400
+++ b/tests/test-highlight.t	Wed Sep 18 14:52:16 2013 -0500
@@ -132,7 +132,6 @@
    <th class="author">children</th>
    <td class="author"></td>
   </tr>
-  
   </table>
   
   <div class="overflow">
@@ -264,7 +263,6 @@
    <th class="author">children</th>
    <td class="author"></td>
   </tr>
-  
   </table>
   
   <div class="overflow">
--- a/tests/test-import-merge.t	Wed Sep 18 14:40:17 2013 -0400
+++ b/tests/test-import-merge.t	Wed Sep 18 14:52:16 2013 -0500
@@ -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-lrucachedict.py	Wed Sep 18 14:40:17 2013 -0400
+++ b/tests/test-lrucachedict.py	Wed Sep 18 14:52:16 2013 -0500
@@ -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	Wed Sep 18 14:40:17 2013 -0400
+++ b/tests/test-lrucachedict.py.out	Wed Sep 18 14:52:16 2013 -0500
@@ -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-mq-subrepo.t	Wed Sep 18 14:40:17 2013 -0400
+++ b/tests/test-mq-subrepo.t	Wed Sep 18 14:52:16 2013 -0500
@@ -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,56 @@
   $ 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
+  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-parse-date.t	Wed Sep 18 14:40:17 2013 -0400
+++ b/tests/test-parse-date.t	Wed Sep 18 14:52:16 2013 -0500
@@ -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-progress.t	Wed Sep 18 14:40:17 2013 -0400
+++ b/tests/test-progress.t	Wed Sep 18 14:52:16 2013 -0500
@@ -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-symlink-placeholder.t	Wed Sep 18 14:40:17 2013 -0400
+++ b/tests/test-symlink-placeholder.t	Wed Sep 18 14:52:16 2013 -0500
@@ -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')