changeset 33690:658524d45af0

merge with stable
author Augie Fackler <augie@google.com>
date Tue, 01 Aug 2017 10:14:25 -0400
parents 9a944e908ecf (current diff) a72b2db1a6a9 (diff)
children 609606d21765
files contrib/build-linux-wheels.sh
diffstat 33 files changed, 641 insertions(+), 76 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.arcconfig	Tue Aug 01 10:14:25 2017 -0400
@@ -0,0 +1,6 @@
+{
+    "conduit_uri": "https://phab.mercurial-scm.org/api",
+    "repository.callsign": "HG",
+    "arc.land.onto.default": "@",
+    "base": "hg:.^"
+}
--- a/.hgsigs	Tue Jul 18 23:04:08 2017 +0530
+++ b/.hgsigs	Tue Aug 01 10:14:25 2017 -0400
@@ -146,3 +146,4 @@
 bb96d4a497432722623ae60d9bc734a1e360179e 0 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
+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
--- a/.hgtags	Tue Jul 18 23:04:08 2017 +0530
+++ b/.hgtags	Tue Aug 01 10:14:25 2017 -0400
@@ -159,3 +159,4 @@
 bb96d4a497432722623ae60d9bc734a1e360179e 4.2
 c850f0ed54c1d42f9aa079ad528f8127e5775217 4.2.1
 26c49ed51a698ec016d2b4c6b44ca3c3f73cc788 4.2.2
+857876ebaed4e315f63157bd157d6ce553c7ab73 4.3-rc
--- a/Makefile	Tue Jul 18 23:04:08 2017 +0530
+++ b/Makefile	Tue Aug 01 10:14:25 2017 -0400
@@ -14,6 +14,7 @@
 export LANGUAGE=C
 export LC_ALL=C
 TESTFLAGS ?= $(shell echo $$HGTESTFLAGS)
+OSXVERSIONFLAGS ?= $(shell echo $$OSXVERSIONFLAGS)
 
 # Set this to e.g. "mingw32" to use a non-default compiler.
 COMPILER=
@@ -62,7 +63,7 @@
 
 cleanbutpackages:
 	-$(PYTHON) setup.py clean --all # ignore errors from this command
-	find contrib doc hgext hgext3rd i18n mercurial tests \
+	find contrib doc hgext hgext3rd i18n mercurial tests hgdemandimport \
 		\( -name '*.py[cdo]' -o -name '*.so' \) -exec rm -f '{}' ';'
 	rm -f MANIFEST MANIFEST.in hgext/__index__.py tests/*.err
 	rm -f mercurial/__modulepolicy__.py
@@ -185,7 +186,7 @@
 	  PREFIX=/usr/local \
 	  clean install
 	mkdir -p $${OUTPUTDIR:-dist}
-	HGVER=$$((cat build/mercurial/Library/Python/2.7/site-packages/mercurial/__version__.py; echo 'print(version)') | python) && \
+	HGVER=$(shell python contrib/genosxversion.py $(OSXVERSIONFLAGS) build/mercurial/Library/Python/2.7/site-packages/mercurial/__version__.py ) && \
 	OSXVER=$$(sw_vers -productVersion | cut -d. -f1,2) && \
 	pkgbuild --filter \\.DS_Store --root build/mercurial/ \
 	  --identifier org.mercurial-scm.mercurial \
@@ -275,13 +276,13 @@
 
 centos6:
 	mkdir -p packages/centos6
-	contrib/buildrpm
+	contrib/buildrpm --withpython
 	cp rpmbuild/RPMS/*/* packages/centos6
 	cp rpmbuild/SRPMS/* packages/centos6
 
 docker-centos6:
 	mkdir -p packages/centos6
-	contrib/dockerrpm centos6
+	contrib/dockerrpm centos6 --withpython
 
 centos7:
 	mkdir -p packages/centos7
--- a/contrib/build-linux-wheels.sh	Tue Jul 18 23:04:08 2017 +0530
+++ b/contrib/build-linux-wheels.sh	Tue Aug 01 10:14:25 2017 -0400
@@ -3,7 +3,7 @@
 # https://github.com/pypa/python-manylinux-demo/blob/master/travis/build-wheels.sh
 set -e -x
 
-PYTHON_TARGETS=$(ls -d /opt/python/cp2*/bin)
+PYTHON_TARGETS=$(ls -d /opt/python/cp27*/bin)
 
 # Create an user for the tests
 useradd hgbuilder
--- a/contrib/docker/centos6	Tue Jul 18 23:04:08 2017 +0530
+++ b/contrib/docker/centos6	Tue Aug 01 10:14:25 2017 -0400
@@ -7,3 +7,5 @@
 RUN yum install -y tar
 # For creating repo meta data
 RUN yum install -y createrepo
+# For python
+RUN yum install -y readline-devel openssl-devel ncurses-devel zlib-devel bzip2-devel
--- a/contrib/dockerlib.sh	Tue Jul 18 23:04:08 2017 +0530
+++ b/contrib/dockerlib.sh	Tue Aug 01 10:14:25 2017 -0400
@@ -38,5 +38,5 @@
         echo RUN groupadd $DBUILDUSER -g `id -g` -o
         echo RUN useradd $DBUILDUSER -u `id -u` -g $DBUILDUSER -o
     fi
-  ) | $DOCKER build --tag $CONTAINER -
+  ) | $DOCKER build --build-arg http_proxy --build-arg https_proxy --tag $CONTAINER -
 }
--- a/contrib/dockerrpm	Tue Jul 18 23:04:08 2017 +0530
+++ b/contrib/dockerrpm	Tue Aug 01 10:14:25 2017 -0400
@@ -16,10 +16,10 @@
 contrib/buildrpm --rpmbuilddir $RPMBUILDDIR --prepare $*
 
 DSHARED=/mnt/shared
-$DOCKER run -u $DBUILDUSER --rm -v $RPMBUILDDIR:$DSHARED $CONTAINER \
+$DOCKER run -e http_proxy -e https_proxy -u $DBUILDUSER --rm -v $RPMBUILDDIR:$DSHARED $CONTAINER \
     rpmbuild --define "_topdir $DSHARED" -ba $DSHARED/SPECS/mercurial.spec --clean
 
-$DOCKER run -u $DBUILDUSER --rm -v $RPMBUILDDIR:$DSHARED $CONTAINER \
+$DOCKER run -e http_proxy -e https_proxy -u $DBUILDUSER --rm -v $RPMBUILDDIR:$DSHARED $CONTAINER \
     createrepo $DSHARED
 
 cat << EOF > $RPMBUILDDIR/mercurial.repo
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/genosxversion.py	Tue Aug 01 10:14:25 2017 -0400
@@ -0,0 +1,130 @@
+#!/usr/bin/env python2
+from __future__ import absolute_import, print_function
+
+import argparse
+import json
+import os
+import subprocess
+import sys
+
+# Always load hg libraries from the hg we can find on $PATH.
+hglib = json.loads(subprocess.check_output(
+    ['hg', 'debuginstall', '-Tjson']))[0]['hgmodules']
+sys.path.insert(0, os.path.dirname(hglib))
+
+from mercurial import util
+
+ap = argparse.ArgumentParser()
+ap.add_argument('--paranoid',
+                action='store_true',
+                help=("Be paranoid about how version numbers compare and "
+                      "produce something that's more likely to sort "
+                      "reasonably."))
+ap.add_argument('--selftest', action='store_true', help='Run self-tests.')
+ap.add_argument('versionfile', help='Path to a valid mercurial __version__.py')
+
+def paranoidver(ver):
+    """Given an hg version produce something that distutils can sort.
+
+    Some Mac package management systems use distutils code in order to
+    figure out upgrades, which makes life difficult. The test case is
+    a reduced version of code in the Munki tool used by some large
+    organizations to centrally manage OS X packages, which is what
+    inspired this kludge.
+
+    >>> paranoidver('3.4')
+    '3.4.0'
+    >>> paranoidver('3.4.2')
+    '3.4.2'
+    >>> paranoidver('3.0-rc+10')
+    '2.9.9999-rc+10'
+    >>> paranoidver('4.2+483-5d44d7d4076e')
+    '4.2.0+483-5d44d7d4076e'
+    >>> paranoidver('4.2.1+598-48d1e1214d8c')
+    '4.2.1+598-48d1e1214d8c'
+    >>> paranoidver('4.3-rc')
+    '4.2.9999-rc'
+    >>> paranoidver('4.3')
+    '4.3.0'
+    >>> from distutils import version
+    >>> class LossyPaddedVersion(version.LooseVersion):
+    ...     '''Subclass version.LooseVersion to compare things like
+    ...     "10.6" and "10.6.0" as equal'''
+    ...     def __init__(self, s):
+    ...             self.parse(s)
+    ...
+    ...     def _pad(self, version_list, max_length):
+    ...         'Pad a version list by adding extra 0 components to the end'
+    ...         # copy the version_list so we don't modify it
+    ...         cmp_list = list(version_list)
+    ...         while len(cmp_list) < max_length:
+    ...             cmp_list.append(0)
+    ...         return cmp_list
+    ...
+    ...     def __cmp__(self, other):
+    ...         if isinstance(other, str):
+    ...             other = MunkiLooseVersion(other)
+    ...         max_length = max(len(self.version), len(other.version))
+    ...         self_cmp_version = self._pad(self.version, max_length)
+    ...         other_cmp_version = self._pad(other.version, max_length)
+    ...         return cmp(self_cmp_version, other_cmp_version)
+    >>> def testver(older, newer):
+    ...   o = LossyPaddedVersion(paranoidver(older))
+    ...   n = LossyPaddedVersion(paranoidver(newer))
+    ...   return o < n
+    >>> testver('3.4', '3.5')
+    True
+    >>> testver('3.4.0', '3.5-rc')
+    True
+    >>> testver('3.4-rc', '3.5')
+    True
+    >>> testver('3.4-rc+10-deadbeef', '3.5')
+    True
+    >>> testver('3.4.2', '3.5-rc')
+    True
+    >>> testver('3.4.2', '3.5-rc+10-deadbeef')
+    True
+    >>> testver('4.2+483-5d44d7d4076e', '4.2.1+598-48d1e1214d8c')
+    True
+    >>> testver('4.3-rc', '4.3')
+    True
+    >>> testver('4.3', '4.3-rc')
+    False
+    """
+    major, minor, micro, extra = util.versiontuple(ver, n=4)
+    if micro is None:
+        micro = 0
+    if extra:
+        if extra.startswith('rc'):
+            if minor == 0:
+                major -= 1
+                minor = 9
+            else:
+                minor -= 1
+            micro = 9999
+            extra = '-' + extra
+        else:
+            extra = '+' + extra
+    else:
+        extra = ''
+    return '%d.%d.%d%s' % (major, minor, micro, extra)
+
+def main(argv):
+    opts = ap.parse_args(argv[1:])
+    if opts.selftest:
+        import doctest
+        doctest.testmod()
+        return
+    with open(opts.versionfile) as f:
+        for l in f:
+            if l.startswith('version = '):
+                # version number is entire line minus the quotes
+                ver = l[len('version = ') + 1:-2]
+                break
+    if opts.paranoid:
+        print(paranoidver(ver))
+    else:
+        print(ver)
+
+if __name__ == '__main__':
+    main(sys.argv)
--- a/contrib/phabricator.py	Tue Jul 18 23:04:08 2017 +0530
+++ b/contrib/phabricator.py	Tue Aug 01 10:14:25 2017 -0400
@@ -560,7 +560,8 @@
             if k in meta:
                 header += '# %s %s\n' % (_metanamemap[k], meta[k])
 
-        write(('%s%s\n%s') % (header, desc, body))
+        content = '%s%s\n%s' % (header, desc, body)
+        write(encoding.unitolocal(content))
 
 @command('phabread',
          [('', 'stack', False, _('read dependencies'))],
--- a/contrib/python3-whitelist	Tue Jul 18 23:04:08 2017 +0530
+++ b/contrib/python3-whitelist	Tue Aug 01 10:14:25 2017 -0400
@@ -24,7 +24,6 @@
 test-lrucachedict.py
 test-manifest.py
 test-merge-default.t
-test-merge-subrepos.t
 test-merge2.t
 test-merge5.t
 test-revlog-packentry.t
--- a/contrib/wix/dist.wxs	Tue Jul 18 23:04:08 2017 +0530
+++ b/contrib/wix/dist.wxs	Tue Aug 01 10:14:25 2017 -0400
@@ -19,12 +19,14 @@
           <File Name="mercurial.cext.osutil.pyd" />
           <File Name="mercurial.cext.parsers.pyd" />
           <File Name="mercurial.zstd.pyd" />
+          <File Name="hgext.fsmonitor.pywatchman.bser.pyd" />
           <File Name="pyexpat.pyd" />
           <File Name="bz2.pyd" />
           <File Name="select.pyd" />
           <File Name="unicodedata.pyd" />
           <File Name="_ctypes.pyd" />
           <File Name="_elementtree.pyd" />
+          <File Name="_testcapi.pyd" />
           <File Name="_hashlib.pyd" />
           <File Name="_socket.pyd" />
           <File Name="_ssl.pyd" />
--- a/contrib/wix/guids.wxi	Tue Jul 18 23:04:08 2017 +0530
+++ b/contrib/wix/guids.wxi	Tue Aug 01 10:14:25 2017 -0400
@@ -10,7 +10,7 @@
 
   <!-- dist.wxs -->
   <?define dist.guid = {CE405FE6-CD1E-4873-9C9A-7683AE5A3D90} ?>
-  <?define lib.guid = {91D53B14-E924-432A-ACA2-65F9B3F7C56A} ?>
+  <?define lib.guid = {877633b5-0b7e-4b46-8f1c-224a61733297} ?>
 
   <!-- doc.wxs -->
   <?define doc.hg.1.html.guid = {AAAA3FDA-EDC5-4220-B59D-D342722358A2} ?>
--- a/hgext/commitextras.py	Tue Jul 18 23:04:08 2017 +0530
+++ b/hgext/commitextras.py	Tue Aug 01 10:14:25 2017 -0400
@@ -9,6 +9,8 @@
 
 from __future__ import absolute_import
 
+import re
+
 from mercurial.i18n import _
 from mercurial import (
     commands,
@@ -52,6 +54,13 @@
                                 "KEY=VALUE format")
                         raise error.Abort(msg % raw)
                     k, v = raw.split('=', 1)
+                    if not k:
+                        msg = _("unable to parse '%s', keys can't be empty")
+                        raise error.Abort(msg % raw)
+                    if re.search('[^\w-]', k):
+                        msg = _("keys can only contain ascii letters, digits,"
+                                " '_' and '-'")
+                        raise error.Abort(msg)
                     if k in usedinternally:
                         msg = _("key '%s' is used internally, can't be set "
                                 "manually")
--- a/hgext/rebase.py	Tue Jul 18 23:04:08 2017 +0530
+++ b/hgext/rebase.py	Tue Aug 01 10:14:25 2017 -0400
@@ -512,7 +512,8 @@
             collapsedas = None
             if self.collapsef:
                 collapsedas = newnode
-            clearrebased(ui, repo, self.state, self.skipped, collapsedas)
+            clearrebased(ui, repo, self.dest, self.state, self.skipped,
+                         collapsedas)
 
         clearstatus(repo)
         clearcollapsemsg(repo)
@@ -897,6 +898,58 @@
         copies.duplicatecopies(repo, rev, p1rev, skiprev=dest)
     return stats
 
+def adjustdest(repo, rev, dest, state):
+    """adjust rebase destination given the current rebase state
+
+    rev is what is being rebased. Return a list of two revs, which are the
+    adjusted destinations for rev's p1 and p2, respectively. If a parent is
+    nullrev, return dest without adjustment for it.
+
+    For example, when doing rebase -r B+E -d F, rebase will first move B to B1,
+    and E's destination will be adjusted from F to B1.
+
+        B1 <- written during rebasing B
+        |
+        F <- original destination of B, E
+        |
+        | E <- rev, which is being rebased
+        | |
+        | D <- prev, one parent of rev being checked
+        | |
+        | x <- skipped, ex. no successor or successor in (::dest)
+        | |
+        | C
+        | |
+        | B <- rebased as B1
+        |/
+        A
+
+    Another example about merge changeset, rebase -r C+G+H -d K, rebase will
+    first move C to C1, G to G1, and when it's checking H, the adjusted
+    destinations will be [C1, G1].
+
+            H       C1 G1
+           /|       | /
+          F G       |/
+        K | |  ->   K
+        | C D       |
+        | |/        |
+        | B         | ...
+        |/          |/
+        A           A
+    """
+    result = []
+    for prev in repo.changelog.parentrevs(rev):
+        adjusted = dest
+        if prev != nullrev:
+            # pick already rebased revs from state
+            source = [s for s, d in state.items() if d > 0]
+            candidate = repo.revs('max(%ld and (::%d))', source, prev).first()
+            if candidate is not None:
+                adjusted = state[candidate]
+        result.append(adjusted)
+    return result
+
 def nearestrebased(repo, rev, state):
     """return the nearest ancestors of rev in the rebase result"""
     rebased = [r for r in state if state[r] > nullmerge]
@@ -1301,12 +1354,21 @@
             state[r] = revprecursor
     return originalwd, dest.rev(), state
 
-def clearrebased(ui, repo, state, skipped, collapsedas=None):
+def clearrebased(ui, repo, dest, state, skipped, collapsedas=None):
     """dispose of rebased revision at the end of the rebase
 
     If `collapsedas` is not None, the rebase was a collapse whose result if the
     `collapsedas` node."""
     tonode = repo.changelog.node
+    # Move bookmark of skipped nodes to destination. This cannot be handled
+    # by scmutil.cleanupnodes since it will treat rev as removed (no successor)
+    # and move bookmark backwards.
+    bmchanges = [(name, tonode(max(adjustdest(repo, rev, dest, state))))
+                 for rev in skipped
+                 for name in repo.nodebookmarks(tonode(rev))]
+    if bmchanges:
+        with repo.transaction('rebase') as tr:
+            repo._bookmarks.applychanges(repo, tr, bmchanges)
     mapping = {}
     for rev, newrev in sorted(state.items()):
         if newrev >= 0 and newrev != rev:
--- a/mercurial/match.py	Tue Jul 18 23:04:08 2017 +0530
+++ b/mercurial/match.py	Tue Aug 01 10:14:25 2017 -0400
@@ -363,6 +363,9 @@
     def prefix(self):
         return True
 
+    def visitdir(self, dir):
+        return False
+
     def __repr__(self):
         return '<nevermatcher>'
 
--- a/mercurial/patch.py	Tue Jul 18 23:04:08 2017 +0530
+++ b/mercurial/patch.py	Tue Aug 01 10:14:25 2017 -0400
@@ -2569,7 +2569,7 @@
 
     if relroot != '' and (repo.ui.configbool('devel', 'all-warnings')
                           or repo.ui.configbool('devel', 'check-relroot')):
-        for f in modified + added + removed + copy.keys() + copy.values():
+        for f in modified + added + removed + list(copy) + list(copy.values()):
             if f is not None and not f.startswith(relroot):
                 raise AssertionError(
                     "file %s doesn't start with relroot %s" % (f, relroot))
--- a/mercurial/statichttprepo.py	Tue Jul 18 23:04:08 2017 +0530
+++ b/mercurial/statichttprepo.py	Tue Aug 01 10:14:25 2017 -0400
@@ -182,6 +182,10 @@
     def peer(self):
         return statichttppeer(self)
 
+    def wlock(self, wait=True):
+        raise error.LockUnavailable(0, _('lock not available'), 'lock',
+                                    _('cannot lock static-http repository'))
+
     def lock(self, wait=True):
         raise error.Abort(_('cannot lock static-http repository'))
 
--- a/mercurial/ui.py	Tue Jul 18 23:04:08 2017 +0530
+++ b/mercurial/ui.py	Tue Aug 01 10:14:25 2017 -0400
@@ -648,7 +648,7 @@
             if default is _unset:
                 default = 0
             value = default
-        if not isinstance(value, str):
+        if not isinstance(value, bytes):
             return value
         try:
             return util.sizetoint(value)
--- a/setup.py	Tue Jul 18 23:04:08 2017 +0530
+++ b/setup.py	Tue Aug 01 10:14:25 2017 -0400
@@ -4,10 +4,28 @@
 # 'python setup.py install', or
 # 'python setup.py --help' for more options
 
+import os
+
+supportedpy = '~= 2.7'
+if os.environ.get('HGALLOWPYTHON3', ''):
+    # Mercurial will never work on Python 3 before 3.5 due to a lack
+    # of % formatting on bytestrings, and can't work on 3.6.0 or 3.6.1
+    # due to a bug in % formatting in bytestrings.
+    #
+    # TODO: when we actually work on Python 3, use this string as the
+    # actual supportedpy string.
+    supportedpy = ','.join([
+        '>=2.7',
+        '!=3.0.*',
+        '!=3.1.*',
+        '!=3.2.*',
+        '!=3.3.*',
+        '!=3.4.*',
+        '!=3.6.0',
+        '!=3.6.1',
+    ])
+
 import sys, platform
-if sys.version_info < (2, 7, 0, 'final'):
-    raise SystemExit('Mercurial requires Python 2.7 or later.')
-
 if sys.version_info[0] >= 3:
     printf = eval('print')
     libdir_escape = 'unicode_escape'
@@ -18,6 +36,33 @@
         end = kwargs.get('end', '\n')
         f.write(b' '.join(args) + end)
 
+# Attempt to guide users to a modern pip - this means that 2.6 users
+# should have a chance of getting a 4.2 release, and when we ratchet
+# the version requirement forward again hopefully everyone will get
+# something that works for them.
+if sys.version_info < (2, 7, 0, 'final'):
+    pip_message = ('This may be due to an out of date pip. '
+                   'Make sure you have pip >= 9.0.1.')
+    try:
+        import pip
+        pip_version = tuple([int(x) for x in pip.__version__.split('.')[:3]])
+        if pip_version < (9, 0, 1) :
+            pip_message = (
+                'Your pip version is out of date, please install '
+                'pip >= 9.0.1. pip {} detected.'.format(pip.__version__))
+        else:
+            # pip is new enough - it must be something else
+            pip_message = ''
+    except Exception:
+        pass
+    error = """
+Mercurial does not support Python older than 2.7.
+Python {py} detected.
+{pip}
+""".format(py=sys.version_info, pip=pip_message)
+    printf(error, file=sys.stderr)
+    sys.exit(1)
+
 # Solaris Python packaging brain damage
 try:
     import hashlib
@@ -58,7 +103,7 @@
 ispypy = "PyPy" in sys.version
 
 import ctypes
-import os, stat, subprocess, time
+import stat, subprocess, time
 import re
 import shutil
 import tempfile
@@ -66,7 +111,8 @@
 # We have issues with setuptools on some platforms and builders. Until
 # those are resolved, setuptools is opt-in except for platforms where
 # we don't have issues.
-if os.name == 'nt' or 'FORCE_SETUPTOOLS' in os.environ:
+issetuptools = (os.name == 'nt' or 'FORCE_SETUPTOOLS' in os.environ)
+if issetuptools:
     from setuptools import setup
 else:
     from distutils.core import setup
@@ -156,21 +202,25 @@
     def run(self, args):
         cmd = self.cmd + args
         returncode, out, err = runcmd(cmd, self.env)
-        # If root is executing setup.py, but the repository is owned by
-        # another user (as in "sudo python setup.py install") we will get
-        # trust warnings since the .hg/hgrc file is untrusted. That is
-        # fine, we don't want to load it anyway.  Python may warn about
-        # a missing __init__.py in mercurial/locale, we also ignore that.
-        err = [e for e in err.splitlines()
-               if not e.startswith(b'not trusting file') \
-                  and not e.startswith(b'warning: Not importing') \
-                  and not e.startswith(b'obsolete feature not enabled')]
+        err = filterhgerr(err)
         if err or returncode != 0:
             printf("stderr from '%s':" % (' '.join(cmd)), file=sys.stderr)
-            printf(b'\n'.join([b'  ' + e for e in err]), file=sys.stderr)
+            printf(err, file=sys.stderr)
             return ''
         return out
 
+def filterhgerr(err):
+    # If root is executing setup.py, but the repository is owned by
+    # another user (as in "sudo python setup.py install") we will get
+    # trust warnings since the .hg/hgrc file is untrusted. That is
+    # fine, we don't want to load it anyway.  Python may warn about
+    # a missing __init__.py in mercurial/locale, we also ignore that.
+    err = [e for e in err.splitlines()
+           if (not e.startswith(b'not trusting file')
+               and not e.startswith(b'warning: Not importing')
+               and not e.startswith(b'obsolete feature not enabled'))]
+    return b'\n'.join(b'  ' + e for e in err)
+
 def findhg():
     """Try to figure out how we should invoke hg for examining the local
     repository contents.
@@ -194,7 +244,7 @@
         retcode, out, err = runcmd(hgcmd + check_cmd, hgenv)
     except EnvironmentError:
         retcode = -1
-    if retcode == 0:
+    if retcode == 0 and not filterhgerr(err):
         return hgcommand(hgcmd, hgenv)
 
     # Fall back to trying the local hg installation.
@@ -206,7 +256,7 @@
         retcode, out, err = runcmd(hgcmd + check_cmd, hgenv)
     except EnvironmentError:
         retcode = -1
-    if retcode == 0:
+    if retcode == 0 and not filterhgerr(err):
         return hgcommand(hgcmd, hgenv)
 
     raise SystemExit('Unable to find a working hg binary to extract the '
@@ -533,7 +583,7 @@
         # Screen out egg related commands to prevent egg generation.  But allow
         # mercurial.egg-info generation, since that is part of modern
         # packaging.
-        excl = {'bdist_egg'}
+        excl = set(['bdist_egg'])
         return filter(lambda x: x not in excl, install.get_sub_commands(self))
 
 class hginstalllib(install_lib):
@@ -798,6 +848,8 @@
 
 extra = {}
 
+if issetuptools:
+    extra['python_requires'] = supportedpy
 if py2exeloaded:
     extra['console'] = [
         {'script':'hg',
@@ -885,7 +937,12 @@
       package_data=packagedata,
       cmdclass=cmdclass,
       distclass=hgdist,
-      options={'py2exe': {'packages': ['hgdemandimport', 'hgext', 'email']},
+      options={'py2exe': {'packages': ['hgdemandimport', 'hgext', 'email',
+                                       # implicitly imported per module policy
+                                       # (cffi wouldn't be used as a frozen exe)
+                                       'mercurial.cext',
+                                       #'mercurial.cffi',
+                                       'mercurial.pure']},
                'bdist_mpkg': {'zipdist': False,
                               'license': 'COPYING',
                               'readme': 'contrib/macosx/Readme.html',
--- a/tests/run-tests.py	Tue Jul 18 23:04:08 2017 +0530
+++ b/tests/run-tests.py	Tue Aug 01 10:14:25 2017 -0400
@@ -96,6 +96,8 @@
         import pygments.lexers as lexers
         import pygments.formatters as formatters
         pygmentspresent = True
+        difflexer = lexers.DiffLexer()
+        terminal256formatter = formatters.Terminal256Formatter()
     except ImportError:
         pass
 
@@ -267,7 +269,7 @@
     parser.add_option("-c", "--cover", action="store_true",
         help="print a test coverage report")
     parser.add_option("--color", choices=["always", "auto", "never"],
-                      default="auto",
+                      default=os.environ.get('HGRUNTESTSCOLOR', 'auto'),
                       help="colorisation: always|auto|never (default: auto)")
     parser.add_option("-d", "--debug", action="store_true",
         help="debug mode: write output of test scripts to console"
@@ -1651,10 +1653,9 @@
                     self.stream.write('\n')
                     for line in lines:
                         if self.color:
-                            line = pygments.highlight(
-                                    line,
-                                    lexers.DiffLexer(),
-                                    formatters.Terminal256Formatter())
+                            line = pygments.highlight(line,
+                                                      difflexer,
+                                                      terminal256formatter)
                         if PYTHON3:
                             self.stream.flush()
                             self.stream.buffer.write(line)
--- a/tests/test-check-code.t	Tue Jul 18 23:04:08 2017 +0530
+++ b/tests/test-check-code.t	Tue Aug 01 10:14:25 2017 -0400
@@ -36,6 +36,7 @@
 Prevent adding new files in the root directory accidentally.
 
   $ testrepohg files 'glob:*'
+  .arcconfig
   .editorconfig
   .hgignore
   .hgsigs
--- a/tests/test-commandserver.t	Tue Jul 18 23:04:08 2017 +0530
+++ b/tests/test-commandserver.t	Tue Aug 01 10:14:25 2017 -0400
@@ -234,7 +234,9 @@
   *** runcommand --config hooks.pre-identify=python:hook.hook id
   eff892de26ec tip
 
+Clean hook cached version
   $ rm hook.py*
+  $ rm -Rf __pycache__
 
   $ echo a >> a
   >>> import os
--- a/tests/test-commit.t	Tue Jul 18 23:04:08 2017 +0530
+++ b/tests/test-commit.t	Tue Aug 01 10:14:25 2017 -0400
@@ -103,6 +103,7 @@
   $ hg commit -m commit-15 baz
   abort: baz: file not tracked!
   [255]
+  $ rm baz
 #endif
 
   $ touch quux
@@ -129,18 +130,22 @@
   $ echo "[extensions]" >> $HGRCPATH
   $ echo "commitextras=" >> $HGRCPATH
   $ hg status
-  ? baz
   ? quux
-  $ hg add baz
+  $ hg add quux
+  $ hg commit -m "adding internal used extras" --extra amend_source=hash
+  abort: key 'amend_source' is used internally, can't be set manually
+  [255]
+  $ hg commit -m "special chars in extra" --extra id@phab=214
+  abort: keys can only contain ascii letters, digits, '_' and '-'
+  [255]
+  $ hg commit -m "empty key" --extra =value
+  abort: unable to parse '=value', keys can't be empty
+  [255]
   $ hg commit -m "adding extras" --extra sourcehash=foo --extra oldhash=bar
   $ hg log -r . -T '{extras % "{extra}\n"}'
   branch=default
   oldhash=bar
   sourcehash=foo
-  $ hg add quux
-  $ hg commit -m "adding internal used extras" --extra amend_source=hash
-  abort: key 'amend_source' is used internally, can't be set manually
-  [255]
 
 Make sure we do not obscure unknown requires file entries (issue2649)
 
--- a/tests/test-devel-warnings.t	Tue Jul 18 23:04:08 2017 +0530
+++ b/tests/test-devel-warnings.t	Tue Aug 01 10:14:25 2017 -0400
@@ -129,7 +129,7 @@
   $ hg commit -m a
   $ hg stripintr 2>&1 | egrep -v '^(\*\*|  )'
   Traceback (most recent call last):
-  mercurial.error.ProgrammingError: cannot strip from inside a transaction
+  *ProgrammingError: cannot strip from inside a transaction (glob)
 
   $ hg oldanddeprecated
   devel-warn: foorbar is deprecated, go shopping
@@ -187,7 +187,7 @@
   ** Extensions loaded: * (glob)
   ** ProgrammingError: transaction requires locking
   Traceback (most recent call last):
-  mercurial.error.ProgrammingError: transaction requires locking
+  *ProgrammingError: transaction requires locking (glob)
 
   $ hg programmingerror 2>&1 | egrep -v '^  '
   ** Unknown exception encountered with possibly-broken third-party extension buggylocking
@@ -200,7 +200,7 @@
   ** ProgrammingError: something went wrong
   ** (try again)
   Traceback (most recent call last):
-  mercurial.error.ProgrammingError: something went wrong
+  *ProgrammingError: something went wrong (glob)
 
 Old style deprecation warning
 
--- a/tests/test-dirstate-race.t	Tue Jul 18 23:04:08 2017 +0530
+++ b/tests/test-dirstate-race.t	Tue Aug 01 10:14:25 2017 -0400
@@ -204,12 +204,16 @@
   $ hg commit -m c4
   created new head
 
-Configure a merge tool that runs status in the middle of the rebase.
+Configure a merge tool that runs status in the middle of the rebase. The goal of
+the status call is to trigger a potential bug if fsmonitor's state is written
+even though the wlock is held by another process. The output of 'hg status' in
+the merge tool goes to /dev/null because we're more interested in the results of
+'hg status' run after the rebase.
 
   $ cat >> $TESTTMP/mergetool-race.sh << EOF
   > echo "custom merge tool"
   > printf "c2\nc3\nc4\n" > \$1
-  > hg --cwd "$TESTTMP/repo" status
+  > hg --cwd "$TESTTMP/repo" status > /dev/null
   > echo "custom merge tool end"
   > EOF
   $ cat >> $HGRCPATH << EOF
@@ -220,14 +224,10 @@
   > test.args=$TESTTMP/mergetool-race.sh \$output
   > EOF
 
-BROKEN: the "M b" line should not be there
   $ hg rebase -s . -d 3 --tool test
   rebasing 4:b08445fd6b2a "c4" (tip)
   merging a
   custom merge tool
-  M a
-  M b
-  ? a.orig
   custom merge tool end
   saved backup bundle to $TESTTMP/repo/.hg/strip-backup/* (glob)
 
--- a/tests/test-fncache.t	Tue Jul 18 23:04:08 2017 +0530
+++ b/tests/test-fncache.t	Tue Aug 01 10:14:25 2017 -0400
@@ -270,7 +270,11 @@
   > cmdtable = {}
   > 
   > EOF
+
+Clean cached version
   $ rm -f "${extpath}c"
+  $ rm -Rf "`dirname $extpath`/__pycache__"
+
   $ touch z
   $ hg ci -qAm z
   transaction abort!
@@ -305,7 +309,11 @@
   > cmdtable = {}
   > 
   > EOF
+
+Clean cached versions
   $ rm -f "${extpath}c"
+  $ rm -Rf "`dirname $extpath`/__pycache__"
+
   $ hg up -q 1
   $ touch z
   $ hg ci -qAm z 2>/dev/null
--- a/tests/test-https.t	Tue Jul 18 23:04:08 2017 +0530
+++ b/tests/test-https.t	Tue Aug 01 10:14:25 2017 -0400
@@ -605,14 +605,12 @@
 
   $ hg serve -p $HGPORT --certificate=/missing/certificate \
   > --config devel.servercafile=$PRIV --config devel.serverrequirecert=true
-  abort: referenced certificate file (*/missing/certificate) does not exist (glob) (windows !)
-  abort: referenced certificate file (/missing/certificate) does not exist (no-windows !)
+  abort: referenced certificate file (*/missing/certificate) does not exist (glob)
   [255]
 
   $ hg serve -p $HGPORT --certificate=$PRIV \
   > --config devel.servercafile=/missing/cafile --config devel.serverrequirecert=true
-  abort: referenced certificate file (*/missing/cafile) does not exist (glob) (windows !)
-  abort: referenced certificate file (/missing/cafile) does not exist (no-windows !)
+  abort: referenced certificate file (*/missing/cafile) does not exist (glob)
   [255]
 
 Start hgweb that requires client certificates:
@@ -657,14 +655,12 @@
 Missing certficate and key files result in error
 
   $ hg id https://localhost:$HGPORT/ --config auth.l.cert=/missing/cert
-  abort: certificate file (*/missing/cert) does not exist; cannot connect to localhost (glob) (windows !)
-  abort: certificate file (/missing/cert) does not exist; cannot connect to localhost (no-windows !)
+  abort: certificate file (*/missing/cert) does not exist; cannot connect to localhost (glob)
   (restore missing file or fix references in Mercurial config)
   [255]
 
   $ hg id https://localhost:$HGPORT/ --config auth.l.key=/missing/key
-  abort: certificate file (*/missing/key) does not exist; cannot connect to localhost (glob) (windows !)
-  abort: certificate file (/missing/key) does not exist; cannot connect to localhost (no-windows !)
+  abort: certificate file (*/missing/key) does not exist; cannot connect to localhost (glob)
   (restore missing file or fix references in Mercurial config)
   [255]
 
--- a/tests/test-mac-packages.t	Tue Jul 18 23:04:08 2017 +0530
+++ b/tests/test-mac-packages.t	Tue Aug 01 10:14:25 2017 -0400
@@ -9,6 +9,7 @@
   $ export KEEPMPKG
 
   $ cd "$TESTDIR"/..
+  $ contrib/genosxversion.py --selftest ignoredarg
   $ make osx > "$OUTPUTDIR/build.log" 2>&1
   $ cd "$OUTPUTDIR"
   $ ls -d *.pkg
@@ -27,6 +28,12 @@
 Spot-check some randomly selected files:
   $ grep bdiff boms.txt | cut -d '	' -f 1,2,3
   ./Library/Python/2.7/site-packages/mercurial/cext/bdiff.so	100755	0/0
+  ./Library/Python/2.7/site-packages/mercurial/cffi/bdiff.py	100644	0/0
+  ./Library/Python/2.7/site-packages/mercurial/cffi/bdiff.pyc	100644	0/0
+  ./Library/Python/2.7/site-packages/mercurial/cffi/bdiff.pyo	100644	0/0
+  ./Library/Python/2.7/site-packages/mercurial/cffi/bdiffbuild.py	100644	0/0
+  ./Library/Python/2.7/site-packages/mercurial/cffi/bdiffbuild.pyc	100644	0/0
+  ./Library/Python/2.7/site-packages/mercurial/cffi/bdiffbuild.pyo	100644	0/0
   ./Library/Python/2.7/site-packages/mercurial/pure/bdiff.py	100644	0/0
   ./Library/Python/2.7/site-packages/mercurial/pure/bdiff.pyc	100644	0/0
   ./Library/Python/2.7/site-packages/mercurial/pure/bdiff.pyo	100644	0/0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-match.py	Tue Aug 01 10:14:25 2017 -0400
@@ -0,0 +1,19 @@
+from __future__ import absolute_import
+
+import unittest
+
+import silenttestrunner
+
+from mercurial import (
+    match as matchmod,
+)
+
+class NeverMatcherTests(unittest.TestCase):
+
+    def testVisitdir(self):
+        m = matchmod.nevermatcher('', '')
+        self.assertFalse(m.visitdir('.'))
+        self.assertFalse(m.visitdir('dir'))
+
+if __name__ == '__main__':
+    silenttestrunner.main(__name__)
--- a/tests/test-profile.t	Tue Jul 18 23:04:08 2017 +0530
+++ b/tests/test-profile.t	Tue Aug 01 10:14:25 2017 -0400
@@ -4,21 +4,22 @@
   $ hg init a
   $ cd a
 
+Function to check that statprof ran
+  $ statprofran () {
+  >   egrep 'Sample count:|No samples recorded' > /dev/null
+  > }
 
 test --profile
 
-  $ hg st --profile 2>&1 | grep Sample
-  Sample count: \d+ (re)
+  $ hg st --profile 2>&1 | statprofran
 
 Abreviated version
 
-  $ hg st --prof 2>&1 | grep Sample
-  Sample count: \d+ (re)
+  $ hg st --prof 2>&1 | statprofran
 
 In alias
 
-  $ hg --config "alias.profst=status --profile" profst 2>&1 | grep Sample
-  Sample count: \d+ (re)
+  $ hg --config "alias.profst=status --profile" profst 2>&1 | statprofran
 
 #if lsprof
 
@@ -81,26 +82,22 @@
 statistical profiler works
 
   $ hg --profile sleep 2>../out
-  $ grep Sample ../out
-  Sample count: \d+ (re)
+  $ cat ../out | statprofran
 
 Various statprof formatters work
 
   $ hg --profile --config profiling.statformat=byline sleep 2>../out
   $ head -n 1 ../out
     %   cumulative      self          
-  $ grep Sample ../out
-  Sample count: \d+ (re)
+  $ cat ../out | statprofran
 
   $ hg --profile --config profiling.statformat=bymethod sleep 2>../out
   $ head -n 1 ../out
     %   cumulative      self          
-  $ grep Sample ../out
-  Sample count: \d+ (re)
+  $ cat ../out | statprofran
 
   $ hg --profile --config profiling.statformat=hotpath sleep 2>../out
-  $ grep Sample ../out
-  Sample count: \d+ (re)
+  $ cat ../out | statprofran
 
   $ hg --profile --config profiling.statformat=json sleep 2>../out
   $ cat ../out
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-rebase-emptycommit.t	Tue Aug 01 10:14:25 2017 -0400
@@ -0,0 +1,202 @@
+  $ cat >> $HGRCPATH<<EOF
+  > [extensions]
+  > rebase=
+  > drawdag=$TESTDIR/drawdag.py
+  > EOF
+
+  $ hg init non-merge
+  $ cd non-merge
+  $ hg debugdrawdag<<'EOS'
+  >   F
+  >   |
+  >   E
+  >   |
+  >   D
+  >   |
+  > B C
+  > |/
+  > A
+  > EOS
+
+  $ for i in C D E F; do
+  >   hg bookmark -r $i -i BOOK-$i
+  > done
+
+  $ hg debugdrawdag<<'EOS'
+  > E
+  > |
+  > D
+  > |
+  > B
+  > EOS
+
+  $ hg log -G -T '{rev} {desc} {bookmarks}'
+  o  7 E
+  |
+  o  6 D
+  |
+  | o  5 F BOOK-F
+  | |
+  | o  4 E BOOK-E
+  | |
+  | o  3 D BOOK-D
+  | |
+  | o  2 C BOOK-C
+  | |
+  o |  1 B
+  |/
+  o  0 A
+  
+With --keep, bookmark should not move
+
+  $ hg rebase -r 3+4 -d E --keep
+  rebasing 3:e7b3f00ed42e "D" (BOOK-D)
+  note: rebase of 3:e7b3f00ed42e created no changes to commit
+  rebasing 4:69a34c08022a "E" (BOOK-E)
+  note: rebase of 4:69a34c08022a created no changes to commit
+  $ hg log -G -T '{rev} {desc} {bookmarks}'
+  o  7 E
+  |
+  o  6 D
+  |
+  | o  5 F BOOK-F
+  | |
+  | o  4 E BOOK-E
+  | |
+  | o  3 D BOOK-D
+  | |
+  | o  2 C BOOK-C
+  | |
+  o |  1 B
+  |/
+  o  0 A
+  
+Bookmark is usually an indication of a head. For changes that are introduced by
+an ancestor of bookmark B, after moving B to B-NEW, the changes are ideally
+still introduced by an ancestor of changeset on B-NEW. In the below case,
+"BOOK-D", and "BOOK-E" include changes introduced by "C".
+
+  $ hg rebase -s 2 -d E
+  rebasing 2:dc0947a82db8 "C" (C BOOK-C)
+  rebasing 3:e7b3f00ed42e "D" (BOOK-D)
+  note: rebase of 3:e7b3f00ed42e created no changes to commit
+  rebasing 4:69a34c08022a "E" (BOOK-E)
+  note: rebase of 4:69a34c08022a created no changes to commit
+  rebasing 5:6b2aeab91270 "F" (F BOOK-F)
+  saved backup bundle to $TESTTMP/non-merge/.hg/strip-backup/dc0947a82db8-52bb4973-rebase.hg (glob)
+  $ hg log -G -T '{rev} {desc} {bookmarks}'
+  o  5 F BOOK-F
+  |
+  o  4 C BOOK-C BOOK-D BOOK-E
+  |
+  o  3 E
+  |
+  o  2 D
+  |
+  o  1 B
+  |
+  o  0 A
+  
+Merge and its ancestors all become empty
+
+  $ hg init $TESTTMP/merge1
+  $ cd $TESTTMP/merge1
+
+  $ hg debugdrawdag<<'EOS'
+  >     E
+  >    /|
+  > B C D
+  >  \|/
+  >   A
+  > EOS
+
+  $ for i in C D E; do
+  >   hg bookmark -r $i -i BOOK-$i
+  > done
+
+  $ hg debugdrawdag<<'EOS'
+  > H
+  > |
+  > D
+  > |
+  > C
+  > |
+  > B
+  > EOS
+
+  $ hg rebase -r '(A::)-(B::)-A' -d H
+  rebasing 2:dc0947a82db8 "C" (BOOK-C)
+  note: rebase of 2:dc0947a82db8 created no changes to commit
+  rebasing 3:b18e25de2cf5 "D" (BOOK-D)
+  note: rebase of 3:b18e25de2cf5 created no changes to commit
+  rebasing 4:86a1f6686812 "E" (E BOOK-E)
+  note: rebase of 4:86a1f6686812 created no changes to commit
+  saved backup bundle to $TESTTMP/merge1/.hg/strip-backup/b18e25de2cf5-1fd0a4ba-rebase.hg (glob)
+
+  $ hg log -G -T '{rev} {desc} {bookmarks}'
+  o  4 H BOOK-C BOOK-D BOOK-E
+  |
+  o  3 D
+  |
+  o  2 C
+  |
+  o  1 B
+  |
+  o  0 A
+  
+Part of ancestors of a merge become empty
+
+  $ hg init $TESTTMP/merge2
+  $ cd $TESTTMP/merge2
+
+  $ hg debugdrawdag<<'EOS'
+  >     G
+  >    /|
+  >   E F
+  >   | |
+  > B C D
+  >  \|/
+  >   A
+  > EOS
+
+  $ for i in C D E F G; do
+  >   hg bookmark -r $i -i BOOK-$i
+  > done
+
+  $ hg debugdrawdag<<'EOS'
+  > H
+  > |
+  > F
+  > |
+  > C
+  > |
+  > B
+  > EOS
+
+  $ hg rebase -r '(A::)-(B::)-A' -d H
+  rebasing 2:dc0947a82db8 "C" (BOOK-C)
+  note: rebase of 2:dc0947a82db8 created no changes to commit
+  rebasing 3:b18e25de2cf5 "D" (D BOOK-D)
+  rebasing 4:03ca77807e91 "E" (E BOOK-E)
+  rebasing 5:ad6717a6a58e "F" (BOOK-F)
+  note: rebase of 5:ad6717a6a58e created no changes to commit
+  rebasing 6:c58e8bdac1f4 "G" (G BOOK-G)
+  saved backup bundle to $TESTTMP/merge2/.hg/strip-backup/b18e25de2cf5-2d487005-rebase.hg (glob)
+
+  $ hg log -G -T '{rev} {desc} {bookmarks}'
+  o    7 G BOOK-G
+  |\
+  | o  6 E BOOK-E
+  | |
+  o |  5 D BOOK-D BOOK-F
+  |/
+  o  4 H BOOK-C
+  |
+  o  3 F
+  |
+  o  2 C
+  |
+  o  1 B
+  |
+  o  0 A
+  
--- a/tests/test-static-http.t	Tue Jul 18 23:04:08 2017 +0530
+++ b/tests/test-static-http.t	Tue Aug 01 10:14:25 2017 -0400
@@ -156,4 +156,53 @@
   $ hg clone static-http://localhost:$HGPORT/notarepo local3
   abort: 'http://localhost:$HGPORT/notarepo' does not appear to be an hg repository!
   [255]
+
+Clone with tags and branches works
+
+  $ hg init remote-with-names
+  $ cd remote-with-names
+  $ echo 0 > foo
+  $ hg -q commit -A -m initial
+  $ echo 1 > foo
+  $ hg commit -m 'commit 1'
+  $ hg -q up 0
+  $ hg branch mybranch
+  marked working directory as branch mybranch
+  (branches are permanent and global, did you want a bookmark?)
+  $ echo 2 > foo
+  $ hg commit -m 'commit 2 (mybranch)'
+  $ hg tag -r 1 'default-tag'
+  $ hg tag -r 2 'branch-tag'
+
+  $ cd ..
+
+  $ hg clone static-http://localhost:$HGPORT/remote-with-names local-with-names
+  requesting all changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 5 changesets with 5 changes to 2 files (+1 heads)
+  updating to branch default
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+Clone a specific branch works
+
+  $ hg clone -r mybranch static-http://localhost:$HGPORT/remote-with-names local-with-names-branch
+  adding changesets
+  adding manifests
+  adding file changes
+  added 4 changesets with 4 changes to 2 files
+  updating to branch mybranch
+  2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+Clone a specific tag works
+
+  $ hg clone -r default-tag static-http://localhost:$HGPORT/remote-with-names local-with-names-tag
+  adding changesets
+  adding manifests
+  adding file changes
+  added 2 changesets with 2 changes to 1 files
+  updating to branch default
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
   $ killdaemons.py