changeset 24942:8174d27576a3

merge with stable
author Matt Mackall <mpm@selenic.com>
date Wed, 06 May 2015 16:56:28 -0500
parents 9c1942635c1f (diff) 5bc506ee87d2 (current diff)
children 3e39f67ef663
files
diffstat 19 files changed, 301 insertions(+), 189 deletions(-) [+]
line wrap: on
line diff
--- a/contrib/revsetbenchmarks.txt	Tue May 05 11:15:17 2015 -0700
+++ b/contrib/revsetbenchmarks.txt	Wed May 06 16:56:28 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	Tue May 05 11:15:17 2015 -0700
+++ b/hgext/keyword.py	Wed May 06 16:56:28 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/mercurial/bundlerepo.py	Tue May 05 11:15:17 2015 -0700
+++ b/mercurial/bundlerepo.py	Wed May 06 16:56:28 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	Tue May 05 11:15:17 2015 -0700
+++ b/mercurial/changegroup.py	Wed May 06 16:56:28 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/context.py	Tue May 05 11:15:17 2015 -0700
+++ b/mercurial/context.py	Wed May 06 16:56:28 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	Tue May 05 11:15:17 2015 -0700
+++ b/mercurial/crecord.py	Wed May 06 16:56:28 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/localrepo.py	Tue May 05 11:15:17 2015 -0700
+++ b/mercurial/localrepo.py	Wed May 06 16:56:28 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."""
@@ -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	Tue May 05 11:15:17 2015 -0700
+++ b/mercurial/manifest.py	Wed May 06 16:56:28 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	Tue May 05 11:15:17 2015 -0700
+++ b/mercurial/obsolete.py	Wed May 06 16:56:28 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	Tue May 05 11:15:17 2015 -0700
+++ b/mercurial/revset.py	Wed May 06 16:56:28 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	Tue May 05 11:15:17 2015 -0700
+++ b/mercurial/scmutil.py	Wed May 06 16:56:28 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/templates/map-cmdline.phases	Tue May 05 11:15:17 2015 -0700
+++ b/mercurial/templates/map-cmdline.phases	Wed May 06 16:56:28 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	Tue May 05 11:15:17 2015 -0700
+++ b/mercurial/windows.py	Wed May 06 16:56:28 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	Tue May 05 11:15:17 2015 -0700
+++ b/setup.py	Wed May 06 16:56:28 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	Tue May 05 11:15:17 2015 -0700
+++ b/tests/run-tests.py	Wed May 06 16:56:28 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	Tue May 05 11:15:17 2015 -0700
+++ b/tests/test-command-template.t	Wed May 06 16:56:28 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	Tue May 05 11:15:17 2015 -0700
+++ b/tests/test-manifestv2.t	Wed May 06 16:56:28 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	Tue May 05 11:15:17 2015 -0700
+++ b/tests/test-module-imports.t	Wed May 06 16:56:28 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	Tue May 05 11:15:17 2015 -0700
+++ b/tests/test-revset.t	Wed May 06 16:56:28 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")'