changeset 24951:eeca859cc045

merge with stable
author Matt Mackall <mpm@selenic.com>
date Thu, 07 May 2015 13:47:45 -0500
parents a02d293a1079 (diff) e6e7d1cce04d (current diff)
children 5115d03440f4
files tests/test-command-template.t
diffstat 29 files changed, 383 insertions(+), 253 deletions(-) [+]
line wrap: on
line diff
--- a/contrib/revsetbenchmarks.txt	Wed May 06 09:52:10 2015 -0700
+++ b/contrib/revsetbenchmarks.txt	Thu May 07 13:47:45 2015 -0500
@@ -17,6 +17,7 @@
 # those two `roots(...)` inputs are close to what phase movement use.
 roots((tip~100::) - (tip~100::tip))
 roots((0::) - (0::tip))
+42:68 and roots(42:tip)
 ::p1(p1(tip))::
 public()
 :10000 and public()
--- a/hgext/keyword.py	Wed May 06 09:52:10 2015 -0700
+++ b/hgext/keyword.py	Thu May 07 13:47:45 2015 -0500
@@ -457,9 +457,7 @@
     repo.commit(text=msg)
     ui.status(_('\n\tkeywords expanded\n'))
     ui.write(repo.wread(fn))
-    for root, dirs, files in os.walk(tmpdir):
-        for f in files:
-            util.unlinkpath(repo.vfs.reljoin(root, f))
+    repo.wvfs.rmtree(repo.root)
 
 @command('kwexpand',
     commands.walkopts,
--- a/hgext/rebase.py	Wed May 06 09:52:10 2015 -0700
+++ b/hgext/rebase.py	Thu May 07 13:47:45 2015 -0500
@@ -358,9 +358,9 @@
 
         # Keep track of the current bookmarks in order to reset them later
         currentbookmarks = repo._bookmarks.copy()
-        activebookmark = activebookmark or repo._bookmarkcurrent
+        activebookmark = activebookmark or repo._activebookmark
         if activebookmark:
-            bookmarks.unsetcurrent(repo)
+            bookmarks.deactivate(repo)
 
         extrafn = _makeextrafn(extrafns)
 
@@ -498,7 +498,7 @@
 
         if (activebookmark and
             repo['.'].node() == repo._bookmarks[activebookmark]):
-                bookmarks.setcurrent(repo, activebookmark)
+                bookmarks.activate(repo, activebookmark)
 
     finally:
         release(lock, wlock)
@@ -888,7 +888,7 @@
             repair.strip(repo.ui, repo, strippoints)
 
     if activebookmark:
-        bookmarks.setcurrent(repo, activebookmark)
+        bookmarks.activate(repo, activebookmark)
 
     clearstatus(repo)
     repo.ui.warn(_('rebase aborted\n'))
@@ -1052,7 +1052,7 @@
                 hg.update(repo, dest)
                 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
                     ui.status(_("updating bookmark %s\n")
-                              % repo._bookmarkcurrent)
+                              % repo._activebookmark)
     else:
         if opts.get('tool'):
             raise util.Abort(_('--tool can only be used with --rebase'))
--- a/hgext/shelve.py	Wed May 06 09:52:10 2015 -0700
+++ b/hgext/shelve.py	Thu May 07 13:47:45 2015 -0500
@@ -163,7 +163,7 @@
 
     # we never need the user, so we use a generic user for all shelve operations
     user = 'shelve@localhost'
-    label = repo._bookmarkcurrent or parent.branch() or 'default'
+    label = repo._activebookmark or parent.branch() or 'default'
 
     # slashes aren't allowed in filenames, therefore we rename it
     label = label.replace('/', '_')
--- a/hgext/strip.py	Wed May 06 09:52:10 2015 -0700
+++ b/hgext/strip.py	Thu May 07 13:47:45 2015 -0500
@@ -60,8 +60,8 @@
 
         marks = repo._bookmarks
         if bookmark:
-            if bookmark == repo._bookmarkcurrent:
-                bookmarks.unsetcurrent(repo)
+            if bookmark == repo._activebookmark:
+                bookmarks.deactivate(repo)
             del marks[bookmark]
             marks.write()
             ui.write(_("bookmark '%s' deleted\n") % bookmark)
--- a/mercurial/bookmarks.py	Wed May 06 09:52:10 2015 -0700
+++ b/mercurial/bookmarks.py	Thu May 07 13:47:45 2015 -0500
@@ -83,8 +83,8 @@
 
     def _writerepo(self, repo):
         """Factored out for extensibility"""
-        if repo._bookmarkcurrent not in self:
-            unsetcurrent(repo)
+        if repo._activebookmark not in self:
+            deactivate(repo)
 
         wlock = repo.wlock()
         try:
@@ -106,13 +106,12 @@
         for name, node in self.iteritems():
             fp.write("%s %s\n" % (hex(node), encoding.fromlocal(name)))
 
-def readcurrent(repo):
-    '''Get the current bookmark
-
-    If we use gittish branches we have a current bookmark that
-    we are on. This function returns the name of the bookmark. It
-    is stored in .hg/bookmarks.current
-    '''
+def readactive(repo):
+    """
+    Get the active bookmark. We can have an active bookmark that updates
+    itself as we commit. This function returns the name of that bookmark.
+    It is stored in .hg/bookmarks.current
+    """
     mark = None
     try:
         file = repo.vfs('bookmarks.current')
@@ -129,16 +128,16 @@
         file.close()
     return mark
 
-def setcurrent(repo, mark):
-    '''Set the name of the bookmark that we are currently on
-
-    Set the name of the bookmark that we are on (hg update <bookmark>).
+def activate(repo, mark):
+    """
+    Set the given bookmark to be 'active', meaning that this bookmark will
+    follow new commits that are made.
     The name is recorded in .hg/bookmarks.current
-    '''
+    """
     if mark not in repo._bookmarks:
         raise AssertionError('bookmark %s does not exist!' % mark)
 
-    current = repo._bookmarkcurrent
+    current = repo._activebookmark
     if current == mark:
         return
 
@@ -149,14 +148,17 @@
         file.close()
     finally:
         wlock.release()
-    repo._bookmarkcurrent = mark
+    repo._activebookmark = mark
 
-def unsetcurrent(repo):
+def deactivate(repo):
+    """
+    Unset the active bookmark in this reposiotry.
+    """
     wlock = repo.wlock()
     try:
         try:
             repo.vfs.unlink('bookmarks.current')
-            repo._bookmarkcurrent = None
+            repo._activebookmark = None
         except OSError, inst:
             if inst.errno != errno.ENOENT:
                 raise
@@ -170,7 +172,7 @@
     parent of the working directory.
     '''
     if not mark:
-        mark = repo._bookmarkcurrent
+        mark = repo._activebookmark
     if not parents:
         parents = [p.node() for p in repo[None].parents()]
     marks = repo._bookmarks
@@ -207,7 +209,7 @@
     check out and where to move the active bookmark from, if needed.'''
     movemarkfrom = None
     if checkout is None:
-        curmark = repo._bookmarkcurrent
+        curmark = repo._activebookmark
         if iscurrent(repo):
             movemarkfrom = repo['.'].node()
         elif curmark:
@@ -219,7 +221,7 @@
     deletefrom = parents
     marks = repo._bookmarks
     update = False
-    cur = repo._bookmarkcurrent
+    cur = repo._activebookmark
     if not cur:
         return False
 
--- a/mercurial/bundlerepo.py	Wed May 06 09:52:10 2015 -0700
+++ b/mercurial/bundlerepo.py	Thu May 07 13:47:45 2015 -0500
@@ -177,11 +177,10 @@
         return manifest.manifest.revision(self, nodeorrev)
 
 class bundlefilelog(bundlerevlog, filelog.filelog):
-    def __init__(self, opener, path, bundle, linkmapper, repo):
+    def __init__(self, opener, path, bundle, linkmapper):
         filelog.filelog.__init__(self, opener, path)
         bundlerevlog.__init__(self, opener, self.indexfile, bundle,
                               linkmapper)
-        self._repo = repo
 
     def baserevision(self, nodeorrev):
         return filelog.filelog.revision(self, nodeorrev)
@@ -322,8 +321,7 @@
 
         if f in self.bundlefilespos:
             self.bundle.seek(self.bundlefilespos[f])
-            return bundlefilelog(self.svfs, f, self.bundle,
-                                 self.changelog.rev, self)
+            return bundlefilelog(self.svfs, f, self.bundle, self.changelog.rev)
         else:
             return filelog.filelog(self.svfs, f)
 
--- a/mercurial/changegroup.py	Wed May 06 09:52:10 2015 -0700
+++ b/mercurial/changegroup.py	Thu May 07 13:47:45 2015 -0500
@@ -304,7 +304,7 @@
     def fileheader(self, fname):
         return chunkheader(len(fname)) + fname
 
-    def group(self, nodelist, revlog, lookup, units=None, reorder=None):
+    def group(self, nodelist, revlog, lookup, units=None):
         """Calculate a delta group, yielding a sequence of changegroup chunks
         (strings).
 
@@ -325,7 +325,7 @@
 
         # for generaldelta revlogs, we linearize the revs; this will both be
         # much quicker and generate a much smaller bundle
-        if (revlog._generaldelta and reorder is not False) or reorder:
+        if (revlog._generaldelta and self._reorder is None) or self._reorder:
             dag = dagutil.revlogdag(revlog)
             revs = set(revlog.rev(n) for n in nodelist)
             revs = dag.linearize(revs)
@@ -347,10 +347,12 @@
             for c in self.revchunk(revlog, curr, prev, linknode):
                 yield c
 
+        if units is not None:
+            self._progress(msgbundling, None)
         yield self.close()
 
     # filter any nodes that claim to be part of the known set
-    def prune(self, revlog, missing, commonrevs, source):
+    def prune(self, revlog, missing, commonrevs):
         rr, rl = revlog.rev, revlog.linkrev
         return [n for n in missing if rl(rr(n)) not in commonrevs]
 
@@ -358,12 +360,8 @@
         '''yield a sequence of changegroup chunks (strings)'''
         repo = self._repo
         cl = self._changelog
-        mf = self._manifest
+        ml = self._manifest
         reorder = self._reorder
-        progress = self._progress
-
-        # for progress output
-        msgbundling = _('bundling')
 
         clrevorder = {}
         mfs = {} # needed manifests
@@ -383,12 +381,10 @@
 
         self._verbosenote(_('uncompressed size of bundle content:\n'))
         size = 0
-        for chunk in self.group(clnodes, cl, lookupcl, units=_('changesets'),
-                                reorder=reorder):
+        for chunk in self.group(clnodes, cl, lookupcl, units=_('changesets')):
             size += len(chunk)
             yield chunk
         self._verbosenote(_('%8.i (changelog)\n') % size)
-        progress(msgbundling, None)
 
         # Callback for the manifest, used to collect linkrevs for filelog
         # revisions.
@@ -396,7 +392,7 @@
         def lookupmf(x):
             clnode = mfs[x]
             if not fastpathlinkrev or reorder:
-                mdata = mf.readfast(x)
+                mdata = ml.readfast(x)
                 for f, n in mdata.iteritems():
                     if f in changedfiles:
                         # record the first changeset introducing this filelog
@@ -407,17 +403,15 @@
                             fclnodes[n] = clnode
             return clnode
 
-        mfnodes = self.prune(mf, mfs, commonrevs, source)
+        mfnodes = self.prune(ml, mfs, commonrevs)
         size = 0
-        for chunk in self.group(mfnodes, mf, lookupmf, units=_('manifests'),
-                                reorder=reorder):
+        for chunk in self.group(mfnodes, ml, lookupmf, units=_('manifests')):
             size += len(chunk)
             yield chunk
         self._verbosenote(_('%8.i (manifests)\n') % size)
-        progress(msgbundling, None)
 
         mfs.clear()
-        needed = set(cl.rev(x) for x in clnodes)
+        clrevs = set(cl.rev(x) for x in clnodes)
 
         def linknodes(filerevlog, fname):
             if fastpathlinkrev and not reorder:
@@ -425,7 +419,7 @@
                 def genfilenodes():
                     for r in filerevlog:
                         linkrev = llr(r)
-                        if linkrev in needed:
+                        if linkrev in clrevs:
                             yield filerevlog.node(r), cl.node(linkrev)
                 return dict(genfilenodes())
             return fnodes.get(fname, {})
@@ -435,15 +429,14 @@
             yield chunk
 
         yield self.close()
-        progress(msgbundling, None)
 
         if clnodes:
             repo.hook('outgoing', node=hex(clnodes[0]), source=source)
 
+    # The 'source' parameter is useful for extensions
     def generatefiles(self, changedfiles, linknodes, commonrevs, source):
         repo = self._repo
         progress = self._progress
-        reorder = self._reorder
         msgbundling = _('bundling')
 
         total = len(changedfiles)
@@ -460,18 +453,18 @@
             def lookupfilelog(x):
                 return linkrevnodes[x]
 
-            filenodes = self.prune(filerevlog, linkrevnodes, commonrevs, source)
+            filenodes = self.prune(filerevlog, linkrevnodes, commonrevs)
             if filenodes:
                 progress(msgbundling, i + 1, item=fname, unit=msgfiles,
                          total=total)
                 h = self.fileheader(fname)
                 size = len(h)
                 yield h
-                for chunk in self.group(filenodes, filerevlog, lookupfilelog,
-                                        reorder=reorder):
+                for chunk in self.group(filenodes, filerevlog, lookupfilelog):
                     size += len(chunk)
                     yield chunk
                 self._verbosenote(_('%8.i  %s\n') % (size, fname))
+        progress(msgbundling, None)
 
     def deltaparent(self, revlog, rev, p1, p2, prev):
         return prev
@@ -513,11 +506,13 @@
     version = '02'
     deltaheader = _CHANGEGROUPV2_DELTA_HEADER
 
-    def group(self, nodelist, revlog, lookup, units=None, reorder=None):
-        if (revlog._generaldelta and reorder is not True):
-            reorder = False
-        return super(cg2packer, self).group(nodelist, revlog, lookup,
-                                            units=units, reorder=reorder)
+    def __init__(self, repo, bundlecaps=None):
+        super(cg2packer, self).__init__(repo, bundlecaps)
+        if self._reorder is None:
+            # Since generaldelta is directly supported by cg2, reordering
+            # generally doesn't help, so we disable it by default (treating
+            # bundle.reorder=auto just like bundle.reorder=False).
+            self._reorder = False
 
     def deltaparent(self, revlog, rev, p1, p2, prev):
         dp = revlog.deltaparent(rev)
@@ -788,8 +783,8 @@
         if repo.ui.configbool('server', 'validate', default=False):
             # validate incoming csets have their manifests
             for cset in xrange(clstart, clend):
-                mfest = repo.changelog.read(repo.changelog.node(cset))[0]
-                mfest = repo.manifest.readdelta(mfest)
+                mfnode = repo.changelog.read(repo.changelog.node(cset))[0]
+                mfest = repo.manifest.readdelta(mfnode)
                 # store file nodes we must see
                 for f, n in mfest.iteritems():
                     needfiles.setdefault(f, set()).add(n)
--- a/mercurial/cmdutil.py	Wed May 06 09:52:10 2015 -0700
+++ b/mercurial/cmdutil.py	Thu May 07 13:47:45 2015 -0500
@@ -2480,13 +2480,13 @@
             # First, do a regular commit to record all changes in the working
             # directory (if there are any)
             ui.callhooks = False
-            currentbookmark = repo._bookmarkcurrent
+            currentbookmark = repo._activebookmark
             try:
-                repo._bookmarkcurrent = None
+                repo._activebookmark = None
                 opts['message'] = 'temporary amend commit for %s' % old
                 node = commit(ui, repo, commitfunc, pats, opts)
             finally:
-                repo._bookmarkcurrent = currentbookmark
+                repo._activebookmark = currentbookmark
                 ui.callhooks = True
             ctx = repo[node]
 
@@ -2722,7 +2722,7 @@
     if ctx.branch():
         edittext.append(_("HG: branch '%s'") % ctx.branch())
     if bookmarks.iscurrent(repo):
-        edittext.append(_("HG: bookmark '%s'") % repo._bookmarkcurrent)
+        edittext.append(_("HG: bookmark '%s'") % repo._activebookmark)
     edittext.extend([_("HG: subrepo %s") % s for s in subs])
     edittext.extend([_("HG: added %s") % f for f in added])
     edittext.extend([_("HG: changed %s") % f for f in modified])
--- a/mercurial/commands.py	Wed May 06 09:52:10 2015 -0700
+++ b/mercurial/commands.py	Thu May 07 13:47:45 2015 -0500
@@ -979,8 +979,8 @@
                     if mark not in marks:
                         raise util.Abort(_("bookmark '%s' does not exist") %
                                          mark)
-                    if mark == repo._bookmarkcurrent:
-                        bookmarks.unsetcurrent(repo)
+                    if mark == repo._activebookmark:
+                        bookmarks.deactivate(repo)
                     del marks[mark]
                 marks.write()
 
@@ -994,8 +994,8 @@
                     raise util.Abort(_("bookmark '%s' does not exist") % rename)
                 checkconflict(repo, mark, cur, force)
                 marks[mark] = marks[rename]
-                if repo._bookmarkcurrent == rename and not inactive:
-                    bookmarks.setcurrent(repo, mark)
+                if repo._activebookmark == rename and not inactive:
+                    bookmarks.activate(repo, mark)
                 del marks[rename]
                 marks.write()
 
@@ -1005,8 +1005,8 @@
                     mark = checkformat(mark)
                     if newact is None:
                         newact = mark
-                    if inactive and mark == repo._bookmarkcurrent:
-                        bookmarks.unsetcurrent(repo)
+                    if inactive and mark == repo._activebookmark:
+                        bookmarks.deactivate(repo)
                         return
                     tgt = cur
                     if rev:
@@ -1014,18 +1014,18 @@
                     checkconflict(repo, mark, cur, force, tgt)
                     marks[mark] = tgt
                 if not inactive and cur == marks[newact] and not rev:
-                    bookmarks.setcurrent(repo, newact)
-                elif cur != tgt and newact == repo._bookmarkcurrent:
-                    bookmarks.unsetcurrent(repo)
+                    bookmarks.activate(repo, newact)
+                elif cur != tgt and newact == repo._activebookmark:
+                    bookmarks.deactivate(repo)
                 marks.write()
 
             elif inactive:
                 if len(marks) == 0:
                     ui.status(_("no bookmarks set\n"))
-                elif not repo._bookmarkcurrent:
+                elif not repo._activebookmark:
                     ui.status(_("no active bookmark\n"))
                 else:
-                    bookmarks.unsetcurrent(repo)
+                    bookmarks.deactivate(repo)
         finally:
             wlock.release()
     else: # show bookmarks
@@ -1035,7 +1035,7 @@
         if len(marks) == 0 and not fm:
             ui.status(_("no bookmarks set\n"))
         for bmark, n in sorted(marks.iteritems()):
-            current = repo._bookmarkcurrent
+            current = repo._activebookmark
             if bmark == current:
                 prefix, label = '*', 'bookmarks.current'
             else:
@@ -1506,7 +1506,7 @@
                                match,
                                extra=extra)
 
-        current = repo._bookmarkcurrent
+        current = repo._activebookmark
         marks = old.bookmarks()
         node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
         if node == old.node():
@@ -1519,7 +1519,7 @@
             for bm in marks:
                 newmarks[bm] = node
                 if bm == current:
-                    bookmarks.setcurrent(repo, bm)
+                    bookmarks.activate(repo, bm)
             newmarks.write()
     else:
         def commitfunc(ui, repo, message, match, opts):
@@ -4702,9 +4702,9 @@
     if node:
         node = scmutil.revsingle(repo, node).node()
 
-    if not node and repo._bookmarkcurrent:
-        bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
-        curhead = repo[repo._bookmarkcurrent].node()
+    if not node and repo._activebookmark:
+        bmheads = repo.bookmarkheads(repo._activebookmark)
+        curhead = repo[repo._activebookmark].node()
         if len(bmheads) == 2:
             if curhead == bmheads[0]:
                 node = bmheads[1]
@@ -4719,7 +4719,7 @@
                 "please merge with an explicit rev or bookmark"),
                 hint=_("run 'hg heads' to see all heads"))
 
-    if not node and not repo._bookmarkcurrent:
+    if not node and not repo._activebookmark:
         branch = repo[None].branch()
         bheads = repo.branchheads(branch)
         nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
@@ -5049,7 +5049,7 @@
             return 0
         if not ret and not checkout:
             if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
-                ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
+                ui.status(_("updating bookmark %s\n") % repo._activebookmark)
         return ret
     if modheads > 1:
         currentbranchheads = len(repo.branchheads())
@@ -5914,7 +5914,7 @@
         ui.status(m, label='log.branch')
 
     if marks:
-        current = repo._bookmarkcurrent
+        current = repo._activebookmark
         # i18n: column positioning for "hg summary"
         ui.write(_('bookmarks:'), label='log.bookmark')
         if current is not None:
@@ -6405,15 +6405,15 @@
 
     if not ret and movemarkfrom:
         if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
-            ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
+            ui.status(_("updating bookmark %s\n") % repo._activebookmark)
     elif brev in repo._bookmarks:
-        bookmarks.setcurrent(repo, brev)
+        bookmarks.activate(repo, brev)
         ui.status(_("(activating bookmark %s)\n") % brev)
     elif brev:
-        if repo._bookmarkcurrent:
+        if repo._activebookmark:
             ui.status(_("(leaving bookmark %s)\n") %
-                      repo._bookmarkcurrent)
-        bookmarks.unsetcurrent(repo)
+                      repo._activebookmark)
+        bookmarks.deactivate(repo)
 
     return ret
 
--- a/mercurial/context.py	Wed May 06 09:52:10 2015 -0700
+++ b/mercurial/context.py	Thu May 07 13:47:45 2015 -0500
@@ -459,7 +459,7 @@
                 pass
         except (error.FilteredIndexError, error.FilteredLookupError,
                 error.FilteredRepoLookupError):
-            if repo.filtername == 'visible':
+            if repo.filtername.startswith('visible'):
                 msg = _("hidden revision '%s'") % changeid
                 hint = _('use --hidden to access hidden revisions')
                 raise error.FilteredRepoLookupError(msg, hint=hint)
--- a/mercurial/crecord.py	Wed May 06 09:52:10 2015 -0700
+++ b/mercurial/crecord.py	Thu May 07 13:47:45 2015 -0500
@@ -20,7 +20,8 @@
 
 # os.name is one of: 'posix', 'nt', 'dos', 'os2', 'mac', or 'ce'
 if os.name == 'posix':
-    import curses, fcntl, termios
+    import curses
+    import fcntl, termios
 else:
     # I have no idea if wcurses works with crecord...
     try:
--- a/mercurial/hg.py	Wed May 06 09:52:10 2015 -0700
+++ b/mercurial/hg.py	Thu May 07 13:47:45 2015 -0500
@@ -497,7 +497,7 @@
                 destrepo.ui.status(status)
                 _update(destrepo, uprev)
                 if update in destrepo._bookmarks:
-                    bookmarks.setcurrent(destrepo, update)
+                    bookmarks.activate(destrepo, update)
     finally:
         release(srclock, destlock)
         if cleandir is not None:
--- a/mercurial/localrepo.py	Wed May 06 09:52:10 2015 -0700
+++ b/mercurial/localrepo.py	Thu May 07 13:47:45 2015 -0500
@@ -196,7 +196,6 @@
     _basesupported = supportedformats | set(('store', 'fncache', 'shared',
                                              'dotencode'))
     openerreqs = set(('revlogv1', 'generaldelta', 'manifestv2'))
-    requirements = ['revlogv1']
     filtername = None
 
     # a list of (ui, featureset) functions.
@@ -204,9 +203,10 @@
     featuresetupfuncs = set()
 
     def _baserequirements(self, create):
-        return self.requirements[:]
+        return ['revlogv1']
 
     def __init__(self, baseui, path=None, create=False):
+        self.requirements = set()
         self.wvfs = scmutil.vfs(path, expandpath=True, realpath=True)
         self.wopener = self.wvfs
         self.root = self.wvfs.base
@@ -243,14 +243,14 @@
                 if not self.wvfs.exists():
                     self.wvfs.makedirs()
                 self.vfs.makedir(notindexed=True)
-                requirements = self._baserequirements(create)
+                self.requirements.update(self._baserequirements(create))
                 if self.ui.configbool('format', 'usestore', True):
                     self.vfs.mkdir("store")
-                    requirements.append("store")
+                    self.requirements.add("store")
                     if self.ui.configbool('format', 'usefncache', True):
-                        requirements.append("fncache")
+                        self.requirements.add("fncache")
                         if self.ui.configbool('format', 'dotencode', True):
-                            requirements.append('dotencode')
+                            self.requirements.add('dotencode')
                     # create an invalid changelog
                     self.vfs.append(
                         "00changelog.i",
@@ -258,21 +258,20 @@
                         ' dummy changelog to prevent using the old repo layout'
                     )
                 if self.ui.configbool('format', 'generaldelta', False):
-                    requirements.append("generaldelta")
+                    self.requirements.add("generaldelta")
                 if self.ui.configbool('experimental', 'manifestv2', False):
-                    requirements.append("manifestv2")
-                requirements = set(requirements)
+                    self.requirements.add("manifestv2")
             else:
                 raise error.RepoError(_("repository %s not found") % path)
         elif create:
             raise error.RepoError(_("repository %s already exists") % path)
         else:
             try:
-                requirements = scmutil.readrequires(self.vfs, self.supported)
+                self.requirements = scmutil.readrequires(
+                        self.vfs, self.supported)
             except IOError, inst:
                 if inst.errno != errno.ENOENT:
                     raise
-                requirements = set()
 
         self.sharedpath = self.path
         try:
@@ -287,13 +286,14 @@
             if inst.errno != errno.ENOENT:
                 raise
 
-        self.store = store.store(requirements, self.sharedpath, scmutil.vfs)
+        self.store = store.store(
+                self.requirements, self.sharedpath, scmutil.vfs)
         self.spath = self.store.path
         self.svfs = self.store.vfs
         self.sopener = self.svfs
         self.sjoin = self.store.join
         self.vfs.createmode = self.store.createmode
-        self._applyrequirements(requirements)
+        self._applyopenerreqs()
         if create:
             self._writerequirements()
 
@@ -336,9 +336,8 @@
             caps.add('bundle2=' + urllib.quote(capsblob))
         return caps
 
-    def _applyrequirements(self, requirements):
-        self.requirements = requirements
-        self.svfs.options = dict((r, 1) for r in requirements
+    def _applyopenerreqs(self):
+        self.svfs.options = dict((r, 1) for r in self.requirements
                                            if r in self.openerreqs)
         chunkcachesize = self.ui.configint('format', 'chunkcachesize')
         if chunkcachesize is not None:
@@ -354,10 +353,7 @@
             self.svfs.options['usetreemanifest'] = usetreemanifest
 
     def _writerequirements(self):
-        reqfile = self.vfs("requires", "w")
-        for r in sorted(self.requirements):
-            reqfile.write("%s\n" % r)
-        reqfile.close()
+        scmutil.writerequires(self.vfs, self.requirements)
 
     def _checknested(self, path):
         """Determine if path is a legal nested repository."""
@@ -419,8 +415,8 @@
         return bookmarks.bmstore(self)
 
     @repofilecache('bookmarks.current')
-    def _bookmarkcurrent(self):
-        return bookmarks.readcurrent(self)
+    def _activebookmark(self):
+        return bookmarks.readactive(self)
 
     def bookmarkheads(self, bookmark):
         name = bookmark.split('@', 1)[0]
@@ -1754,7 +1750,7 @@
         """
         return util.hooks()
 
-    def stream_in(self, remote, requirements):
+    def stream_in(self, remote, remotereqs):
         lock = self.lock()
         try:
             # Save remote branchmap. We will use it later
@@ -1827,10 +1823,11 @@
                             util.bytecount(total_bytes / elapsed)))
 
             # new requirements = old non-format requirements +
-            #                    new format-related
+            #                    new format-related remote requirements
             # requirements from the streamed-in repository
-            requirements.update(set(self.requirements) - self.supportedformats)
-            self._applyrequirements(requirements)
+            self.requirements = remotereqs | (
+                    self.requirements - self.supportedformats)
+            self._applyopenerreqs()
             self._writerequirements()
 
             if rbranchmap:
--- a/mercurial/manifest.py	Wed May 06 09:52:10 2015 -0700
+++ b/mercurial/manifest.py	Thu May 07 13:47:45 2015 -0500
@@ -793,7 +793,13 @@
         return self._newmanifest(d)
 
     def readfast(self, node):
-        '''use the faster of readdelta or read'''
+        '''use the faster of readdelta or read
+
+        This will return a manifest which is either only the files
+        added/modified relative to p1, or all files in the
+        manifest. Which one is returned depends on the codepath used
+        to retrieve the data.
+        '''
         r = self.rev(node)
         deltaparent = self.deltaparent(r)
         if deltaparent != revlog.nullrev and deltaparent in self.parentrevs(r):
--- a/mercurial/obsolete.py	Wed May 06 09:52:10 2015 -0700
+++ b/mercurial/obsolete.py	Thu May 07 13:47:45 2015 -0500
@@ -1110,13 +1110,17 @@
 @cachefor('unstable')
 def _computeunstableset(repo):
     """the set of non obsolete revisions with obsolete parents"""
-    # revset is not efficient enough here
-    # we do (obsolete()::) - obsolete() by hand
-    obs = getrevs(repo, 'obsolete')
-    if not obs:
-        return set()
-    cl = repo.changelog
-    return set(r for r in cl.descendants(obs) if r not in obs)
+    revs = [(ctx.rev(), ctx) for ctx in
+            repo.set('(not public()) and (not obsolete())')]
+    revs.sort(key=lambda x:x[0])
+    unstable = set()
+    for rev, ctx in revs:
+        # A rev is unstable if one of its parent is obsolete or unstable
+        # this works since we traverse following growing rev order
+        if util.any((x.obsolete() or (x.rev() in unstable))
+                for x in ctx.parents()):
+            unstable.add(rev)
+    return unstable
 
 @cachefor('suspended')
 def _computesuspendedset(repo):
@@ -1139,19 +1143,18 @@
     public = phases.public
     cl = repo.changelog
     torev = cl.nodemap.get
-    obs = getrevs(repo, 'obsolete')
-    for rev in repo:
+    for ctx in repo.set('(not public()) and (not obsolete())'):
+        rev = ctx.rev()
         # We only evaluate mutable, non-obsolete revision
-        if (public < phase(repo, rev)) and (rev not in obs):
-            node = cl.node(rev)
-            # (future) A cache of precursors may worth if split is very common
-            for pnode in allprecursors(repo.obsstore, [node],
-                                       ignoreflags=bumpedfix):
-                prev = torev(pnode) # unfiltered! but so is phasecache
-                if (prev is not None) and (phase(repo, prev) <= public):
-                    # we have a public precursors
-                    bumped.add(rev)
-                    break # Next draft!
+        node = ctx.node()
+        # (future) A cache of precursors may worth if split is very common
+        for pnode in allprecursors(repo.obsstore, [node],
+                                   ignoreflags=bumpedfix):
+            prev = torev(pnode) # unfiltered! but so is phasecache
+            if (prev is not None) and (phase(repo, prev) <= public):
+                # we have a public precursors
+                bumped.add(rev)
+                break # Next draft!
     return bumped
 
 @cachefor('divergent')
--- a/mercurial/revset.py	Wed May 06 09:52:10 2015 -0700
+++ b/mercurial/revset.py	Thu May 07 13:47:45 2015 -0500
@@ -25,23 +25,25 @@
     cl = repo.changelog
 
     def iterate():
-        revqueue, revsnode = None, None
+        revs.sort(reverse=True)
+        irevs = iter(revs)
         h = []
-
-        revs.sort(reverse=True)
-        revqueue = util.deque(revs)
-        if revqueue:
-            revsnode = revqueue.popleft()
-            heapq.heappush(h, -revsnode)
+        try:
+            inputrev = irevs.next()
+            heapq.heappush(h, -inputrev)
+        except StopIteration:
+            return
 
         seen = set()
         while h:
             current = -heapq.heappop(h)
+            if current == inputrev:
+                try:
+                    inputrev = irevs.next()
+                    heapq.heappush(h, -inputrev)
+                except StopIteration:
+                    pass
             if current not in seen:
-                if revsnode and current == revsnode:
-                    if revqueue:
-                        revsnode = revqueue.popleft()
-                        heapq.heappush(h, -revsnode)
                 seen.add(current)
                 yield current
                 for parent in cl.parentrevs(current)[:cut]:
@@ -334,11 +336,6 @@
         return baseset([x])
     return baseset()
 
-def symbolset(repo, subset, x):
-    if x in symbols:
-        raise error.ParseError(_("can't use %s here") % x)
-    return stringset(repo, subset, x)
-
 def rangeset(repo, subset, x, y):
     m = getset(repo, fullreposet(repo), x)
     n = getset(repo, fullreposet(repo), y)
@@ -1684,7 +1681,7 @@
     Changesets in set with no parent changeset in set.
     """
     s = getset(repo, fullreposet(repo), x)
-    subset = baseset([r for r in s if r in subset])
+    subset = subset & s# baseset([r for r in s if r in subset])
     cs = _children(repo, subset, s)
     return subset - cs
 
@@ -2088,7 +2085,7 @@
     "range": rangeset,
     "dagrange": dagrange,
     "string": stringset,
-    "symbol": symbolset,
+    "symbol": stringset,
     "and": andset,
     "or": orset,
     "not": notset,
@@ -3142,7 +3139,12 @@
                 self.__contains__ = self._desccontains
 
     def __nonzero__(self):
-        for r in self:
+        # Do not use 'for r in self' because it will enforce the iteration
+        # order (default ascending), possibly unrolling a whole descending
+        # iterator.
+        if self._genlist:
+            return True
+        for r in self._consumegen():
             return True
         return False
 
--- a/mercurial/scmutil.py	Wed May 06 09:52:10 2015 -0700
+++ b/mercurial/scmutil.py	Thu May 07 13:47:45 2015 -0500
@@ -1011,6 +1011,12 @@
                    " for more information"))
     return requirements
 
+def writerequires(opener, requirements):
+    reqfile = opener("requires", "w")
+    for r in sorted(requirements):
+        reqfile.write("%s\n" % r)
+    reqfile.close()
+
 class filecachesubentry(object):
     def __init__(self, path, stat):
         self.path = path
--- a/mercurial/subrepo.py	Wed May 06 09:52:10 2015 -0700
+++ b/mercurial/subrepo.py	Thu May 07 13:47:45 2015 -0500
@@ -1711,7 +1711,7 @@
         modified, added, removed = [], [], []
         self._gitupdatestat()
         if rev2:
-            command = ['diff-tree', rev1, rev2]
+            command = ['diff-tree', '-r', rev1, rev2]
         else:
             command = ['diff-index', rev1]
         out = self._gitcommand(command)
--- a/mercurial/templatekw.py	Wed May 06 09:52:10 2015 -0700
+++ b/mercurial/templatekw.py	Thu May 07 13:47:45 2015 -0500
@@ -210,7 +210,7 @@
     """
     repo = args['ctx']._repo
     bookmarks = args['ctx'].bookmarks()
-    current = repo._bookmarkcurrent
+    current = repo._activebookmark
     makemap = lambda v: {'bookmark': v, 'current': current}
     f = _showlist('bookmark', bookmarks, **args)
     return _hybrid(f, bookmarks, makemap, lambda x: x['bookmark'])
@@ -227,7 +227,7 @@
     import bookmarks as bookmarks # to avoid circular import issues
     repo = args['repo']
     if bookmarks.iscurrent(repo):
-        current = repo._bookmarkcurrent
+        current = repo._activebookmark
         if current in args['ctx'].bookmarks():
             return current
     return ''
--- a/mercurial/templates/map-cmdline.phases	Wed May 06 09:52:10 2015 -0700
+++ b/mercurial/templates/map-cmdline.phases	Thu May 07 13:47:45 2015 -0500
@@ -1,73 +1,3 @@
-# Base templates. Due to name clashes with existing keywords, we have
-# to replace some keywords with 'lkeyword', for 'labelled keyword'
+%include map-cmdline.default
 changeset = '{cset}{branches}{bookmarks}{tags}{lphase}{parents}{user}{ldate}{summary}\n'
-changeset_quiet = '{lnode}'
 changeset_verbose = '{cset}{branches}{bookmarks}{tags}{lphase}{parents}{user}{ldate}{lfiles}{lfile_copies_switch}{description}\n'
-changeset_debug = '{fullcset}{branches}{bookmarks}{tags}{lphase}{parents}{manifest}{user}{ldate}{lfile_mods}{lfile_adds}{lfile_dels}{lfile_copies_switch}{extras}{description}\n'
-
-# File templates
-lfiles = '{if(files,
-               label("ui.note log.files",
-                     "files:       {files}\n"))}'
-
-lfile_mods = '{if(file_mods,
-                  label("ui.debug log.files",
-                        "files:       {file_mods}\n"))}'
-
-lfile_adds = '{if(file_adds,
-                  label("ui.debug log.files",
-                        "files+:      {file_adds}\n"))}'
-
-lfile_dels = '{if(file_dels,
-                  label("ui.debug log.files",
-                        "files-:      {file_dels}\n"))}'
-
-lfile_copies_switch = '{if(file_copies_switch,
-                           label("ui.note log.copies",
-                                 "copies:     {file_copies_switch
-                                               % ' {name} ({source})'}\n"))}'
-
-# General templates
-cset = '{label("log.changeset changeset.{phase}",
-               "changeset:   {rev}:{node|short}")}\n'
-
-lphase = '{label("log.phase",
-                 "phase:       {phase}")}\n'
-
-fullcset = '{label("log.changeset changeset.{phase}",
-                   "changeset:   {rev}:{node}")}\n'
-
-parent = '{label("log.parent changeset.{phase}",
-                  "parent:      {rev}:{node|formatnode}")}\n'
-
-lnode = '{label("log.node",
-                "{rev}:{node|short}")}\n'
-
-manifest = '{label("ui.debug log.manifest",
-                   "manifest:    {rev}:{node}")}\n'
-
-branch = '{label("log.branch",
-                 "branch:      {branch}")}\n'
-
-tag = '{label("log.tag",
-              "tag:         {tag}")}\n'
-
-bookmark = '{label("log.bookmark",
-                   "bookmark:    {bookmark}")}\n'
-
-user = '{label("log.user",
-               "user:        {author}")}\n'
-
-summary = '{if(desc|strip, "{label('log.summary',
-                                   'summary:     {desc|firstline}')}\n")}'
-
-ldate = '{label("log.date",
-                "date:        {date|date}")}\n'
-
-extra = '{label("ui.debug log.extra",
-                "extra:       {key}={value|stringescape}")}\n'
-
-description = '{if(desc|strip, "{label('ui.note log.description',
-                                       'description:')}
-                                {label('ui.note log.description',
-                                       '{desc|strip}')}\n\n")}'
--- a/mercurial/windows.py	Wed May 06 09:52:10 2015 -0700
+++ b/mercurial/windows.py	Thu May 07 13:47:45 2015 -0500
@@ -162,6 +162,18 @@
 _quotere = None
 _needsshellquote = None
 def shellquote(s):
+    r"""
+    >>> shellquote(r'C:\Users\xyz')
+    '"C:\\Users\\xyz"'
+    >>> shellquote(r'C:\Users\xyz/mixed')
+    '"C:\\Users\\xyz/mixed"'
+    >>> # Would be safe not to quote too, since it is all double backslashes
+    >>> shellquote(r'C:\\Users\\xyz')
+    '"C:\\\\Users\\\\xyz"'
+    >>> # But this must be quoted
+    >>> shellquote(r'C:\\Users\\xyz/abc')
+    '"C:\\\\Users\\\\xyz/abc"'
+    """
     global _quotere
     if _quotere is None:
         _quotere = re.compile(r'(\\*)("|\\$)')
--- a/setup.py	Wed May 06 09:52:10 2015 -0700
+++ b/setup.py	Thu May 07 13:47:45 2015 -0500
@@ -408,11 +408,12 @@
                 # Persist executable bit (apply it to group and other if user
                 # has it)
                 if st[stat.ST_MODE] & stat.S_IXUSR:
-                    setmode = 0755
+                    setmode = int('0755', 8)
                 else:
-                    setmode = 0644
-                os.chmod(dst, (stat.S_IMODE(st[stat.ST_MODE]) & ~0777) |
-                         setmode)
+                    setmode = int('0644', 8)
+                m = stat.S_IMODE(st[stat.ST_MODE])
+                m = (m & ~int('0777', 8)) | setmode
+                os.chmod(dst, m)
         file_util.copy_file = copyfileandsetmode
         try:
             install_lib.run(self)
--- a/tests/run-tests.py	Wed May 06 09:52:10 2015 -0700
+++ b/tests/run-tests.py	Thu May 07 13:47:45 2015 -0500
@@ -620,7 +620,7 @@
                 f.write(line)
             f.close()
 
-        vlog("# Ret was:", self._ret)
+        vlog("# Ret was:", self._ret, '(%s)' % self.name)
 
     def _run(self, env):
         # This should be implemented in child classes to run tests.
--- a/tests/test-command-template.t	Wed May 06 09:52:10 2015 -0700
+++ b/tests/test-command-template.t	Thu May 07 13:47:45 2015 -0500
@@ -95,7 +95,7 @@
   8
 
 Add a commit with empty description, to ensure that the templates
-following below omit it properly.
+below will omit the description line.
 
   $ echo c >> c
   $ hg add c
@@ -108,32 +108,52 @@
   $ hg log --style default > style.out
   $ cmp log.out style.out || diff -u log.out style.out
   $ hg log -T phases > phases.out
-  $ diff -u log.out phases.out | grep "phase:"
+  $ diff -U 0 log.out phases.out | grep -v '^---\|^+++'
+  @@ -2,0 +3 @@
   +phase:       draft
+  @@ -6,0 +8 @@
   +phase:       draft
+  @@ -11,0 +14 @@
   +phase:       draft
+  @@ -17,0 +21 @@
   +phase:       draft
+  @@ -24,0 +29 @@
   +phase:       draft
+  @@ -31,0 +37 @@
   +phase:       draft
+  @@ -36,0 +43 @@
   +phase:       draft
+  @@ -41,0 +49 @@
   +phase:       draft
+  @@ -46,0 +55 @@
   +phase:       draft
+  @@ -51,0 +61 @@
   +phase:       draft
 
   $ hg log -v > log.out
   $ hg log -v --style default > style.out
   $ cmp log.out style.out || diff -u log.out style.out
   $ hg log -v -T phases > phases.out
-  $ diff -u log.out phases.out | grep phase:
+  $ diff -U 0 log.out phases.out | grep -v '^---\|^+++'
+  @@ -2,0 +3 @@
   +phase:       draft
+  @@ -7,0 +9 @@
   +phase:       draft
+  @@ -15,0 +18 @@
   +phase:       draft
+  @@ -24,0 +28 @@
   +phase:       draft
+  @@ -33,0 +38 @@
   +phase:       draft
+  @@ -43,0 +49 @@
   +phase:       draft
+  @@ -50,0 +57 @@
   +phase:       draft
+  @@ -58,0 +66 @@
   +phase:       draft
+  @@ -66,0 +75 @@
   +phase:       draft
+  @@ -77,0 +87 @@
   +phase:       draft
 
   $ hg log -q > log.out
@@ -160,32 +180,52 @@
   $ hg --color=debug log --style default > style.out
   $ cmp log.out style.out || diff -u log.out style.out
   $ hg --color=debug log -T phases > phases.out
-  $ diff -u log.out phases.out | grep phase:
+  $ diff -U 0 log.out phases.out | grep -v '^---\|^+++'
+  @@ -2,0 +3 @@
   +[log.phase|phase:       draft]
+  @@ -6,0 +8 @@
   +[log.phase|phase:       draft]
+  @@ -11,0 +14 @@
   +[log.phase|phase:       draft]
+  @@ -17,0 +21 @@
   +[log.phase|phase:       draft]
+  @@ -24,0 +29 @@
   +[log.phase|phase:       draft]
+  @@ -31,0 +37 @@
   +[log.phase|phase:       draft]
+  @@ -36,0 +43 @@
   +[log.phase|phase:       draft]
+  @@ -41,0 +49 @@
   +[log.phase|phase:       draft]
+  @@ -46,0 +55 @@
   +[log.phase|phase:       draft]
+  @@ -51,0 +61 @@
   +[log.phase|phase:       draft]
 
   $ hg --color=debug -v log > log.out
   $ hg --color=debug -v log --style default > style.out
   $ cmp log.out style.out || diff -u log.out style.out
   $ hg --color=debug -v log -T phases > phases.out
-  $ diff -u log.out phases.out | grep phase:
+  $ diff -U 0 log.out phases.out | grep -v '^---\|^+++'
+  @@ -2,0 +3 @@
   +[log.phase|phase:       draft]
+  @@ -7,0 +9 @@
   +[log.phase|phase:       draft]
+  @@ -15,0 +18 @@
   +[log.phase|phase:       draft]
+  @@ -24,0 +28 @@
   +[log.phase|phase:       draft]
+  @@ -33,0 +38 @@
   +[log.phase|phase:       draft]
+  @@ -43,0 +49 @@
   +[log.phase|phase:       draft]
+  @@ -50,0 +57 @@
   +[log.phase|phase:       draft]
+  @@ -58,0 +66 @@
   +[log.phase|phase:       draft]
+  @@ -66,0 +75 @@
   +[log.phase|phase:       draft]
+  @@ -77,0 +87 @@
   +[log.phase|phase:       draft]
 
   $ hg --color=debug -q log > log.out
--- a/tests/test-manifestv2.t	Wed May 06 09:52:10 2015 -0700
+++ b/tests/test-manifestv2.t	Thu May 07 13:47:45 2015 -0500
@@ -1,4 +1,69 @@
-Check that entry is added to .hg/requires
+Create repo with old manifest
+
+  $ hg init existing
+  $ cd existing
+  $ echo footext > foo
+  $ hg add foo
+  $ hg commit -m initial
+
+We're using v1, so no manifestv2 entry is in requires yet.
+
+  $ grep manifestv2 .hg/requires
+  [1]
+
+Let's clone this with manifestv2 enabled to switch to the new format for
+future commits.
+
+  $ cd ..
+  $ hg clone --pull existing new --config experimental.manifestv2=1
+  requesting all changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  updating to branch default
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ cd new
+
+Check that entry was added to .hg/requires.
+
+  $ grep manifestv2 .hg/requires
+  manifestv2
+
+Make a new commit.
+
+  $ echo newfootext > foo
+  $ hg commit -m new
+
+Check that the manifest actually switched to v2.
+
+  $ hg debugdata -m 0
+  foo\x0021e958b1dca695a60ee2e9cf151753204ee0f9e9 (esc)
+
+  $ hg debugdata -m 1
+  \x00 (esc)
+  \x00foo\x00 (esc)
+  I\xab\x7f\xb8(\x83\xcas\x15\x9d\xc2\xd3\xd3:5\x08\xbad5_ (esc)
+
+Check that manifestv2 is used if the requirement is present, even if it's
+disabled in the config.
+
+  $ echo newerfootext > foo
+  $ hg --config experimental.manifestv2=False commit -m newer
+
+  $ hg debugdata -m 2
+  \x00 (esc)
+  \x00foo\x00 (esc)
+  \xa6\xb1\xfb\xef]\x91\xa1\x19`\xf3.#\x90S\xf8\x06 \xe2\x19\x00 (esc)
+
+Check that we can still read v1 manifests.
+
+  $ hg files -r 0
+  foo
+
+  $ cd ..
+
+Check that entry is added to .hg/requires on repo creation
 
   $ hg --config experimental.manifestv2=True init repo
   $ cd repo
--- a/tests/test-module-imports.t	Wed May 06 09:52:10 2015 -0700
+++ b/tests/test-module-imports.t	Thu May 07 13:47:45 2015 -0500
@@ -21,9 +21,6 @@
 these may expose other cycles.
 
   $ hg locate 'mercurial/**.py' | sed 's-\\-/-g' | xargs python "$import_checker"
-  mercurial/crecord.py mixed imports
-     stdlib:    fcntl, termios
-     relative:  curses
   mercurial/dispatch.py mixed imports
      stdlib:    commands
      relative:  error, extensions, fancyopts, hg, hook, util
--- a/tests/test-revset.t	Wed May 06 09:52:10 2015 -0700
+++ b/tests/test-revset.t	Thu May 07 13:47:45 2015 -0500
@@ -1,5 +1,27 @@
   $ HGENCODING=utf-8
   $ export HGENCODING
+  $ cat > testrevset.py << EOF
+  > import mercurial.revset
+  > 
+  > baseset = mercurial.revset.baseset
+  > 
+  > def r3232(repo, subset, x):
+  >     """"simple revset that return [3,2,3,2]
+  > 
+  >     revisions duplicated on purpose.
+  >     """
+  >     if 3 not in subset:
+  >        if 2 in subset:
+  >            return baseset([2,2])
+  >        return baseset()
+  >     return baseset([3,3,2,2])
+  > 
+  > mercurial.revset.symbols['r3232'] = r3232
+  > EOF
+  $ cat >> $HGRCPATH << EOF
+  > [extensions]
+  > testrevset=$TESTTMP/testrevset.py
+  > EOF
 
   $ try() {
   >   hg debugrevspec --debug "$@"
@@ -281,7 +303,7 @@
   hg: parse error: date requires a string
   [255]
   $ log 'date'
-  hg: parse error: can't use date here
+  abort: unknown revision 'date'!
   [255]
   $ log 'date('
   hg: parse error at 5: not a prefix: end
@@ -289,11 +311,40 @@
   $ log 'date(tip)'
   abort: invalid date: 'tip'
   [255]
-  $ log '"date"'
+  $ log '0:date'
+  abort: unknown revision 'date'!
+  [255]
+  $ log '::"date"'
   abort: unknown revision 'date'!
   [255]
+  $ hg book date -r 4
+  $ log '0:date'
+  0
+  1
+  2
+  3
+  4
+  $ log '::date'
+  0
+  1
+  2
+  4
+  $ log '::"date"'
+  0
+  1
+  2
+  4
   $ log 'date(2005) and 1::'
   4
+  $ hg book -d date
+
+Test that symbols only get parsed as functions if there's an opening
+parenthesis.
+
+  $ hg book only -r 9
+  $ log 'only(only)'   # Outer "only" is a function, inner "only" is the bookmark
+  8
+  9
 
 ancestor can accept 0 or more arguments
 
@@ -311,6 +362,9 @@
   0
   $ log 'ancestor(1,2,3,4,5)'
   1
+
+test ancestors
+
   $ log 'ancestors(5)'
   0
   1
@@ -318,6 +372,12 @@
   5
   $ log 'ancestor(ancestors(5))'
   0
+  $ log '::r3232()'
+  0
+  1
+  2
+  3
+
   $ log 'author(bob)'
   2
   $ log 'author("re:bob|test")'
--- a/tests/test-subrepo-git.t	Wed May 06 09:52:10 2015 -0700
+++ b/tests/test-subrepo-git.t	Thu May 07 13:47:45 2015 -0500
@@ -1105,5 +1105,21 @@
   ? s/c.c
   ? s/cpp.cpp
   ? s/foobar.orig
+  $ hg revert --all -q
+
+make sure we show changed files, rather than changed subtrees
+  $ mkdir s/foo
+  $ touch s/foo/bwuh
+  $ hg add s/foo/bwuh
+  $ hg commit -S -m "add bwuh"
+  committing subrepository s
+  $ hg status -S --change .
+  M .hgsubstate
+  A s/foo/bwuh
+  ? s/barfoo
+  ? s/c.c
+  ? s/cpp.cpp
+  ? s/foobar.orig
+  ? s/snake.python.orig
 
   $ cd ..