diff tests/hghave.py @ 53031:e705fec4a03f stable

branching: merging with 7.0 changes Since 6.9.3 was made after 7.0rc0 we need to deal with more branching than usual.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Wed, 05 Mar 2025 23:02:19 +0100
parents d655382584c5
children 771706c5acfb
line wrap: on
line diff
--- a/tests/hghave.py	Wed Mar 05 22:33:11 2025 +0100
+++ b/tests/hghave.py	Wed Mar 05 23:02:19 2025 +0100
@@ -130,11 +130,7 @@
         sys.exit(1)
 
 
-def matchoutput(cmd, regexp, ignorestatus=False):
-    """Return the match object if cmd executes successfully and its output
-    is matched by the supplied regular expression.
-    """
-
+def environ():
     # Tests on Windows have to fake USERPROFILE to point to the test area so
     # that `~` is properly expanded on py3.8+.  However, some tools like black
     # make calls that need the real USERPROFILE in order to run `foo --version`.
@@ -142,6 +138,14 @@
     if os.name == 'nt':
         env = os.environ.copy()
         env['USERPROFILE'] = env['REALUSERPROFILE']
+    return env
+
+
+def matchoutput(cmd, regexp: bytes, ignorestatus: bool = False):
+    """Return the match object if cmd executes successfully and its output
+    is matched by the supplied regular expression.
+    """
+    env = environ()
 
     r = re.compile(regexp)
     p = subprocess.Popen(
@@ -171,7 +175,7 @@
         import breezy.revision
         import breezy.revisionspec
 
-        breezy.revisionspec.RevisionSpec
+        del breezy.revisionspec
         if breezy.__doc__ is None or breezy.version_info[:2] < (3, 1):
             return False
     except (AttributeError, ImportError):
@@ -248,7 +252,7 @@
         os.close(fd)
         os.remove(path)
         return True
-    except (IOError, OSError):
+    except OSError:
         return False
 
 
@@ -265,7 +269,7 @@
             exec_flags_cannot_flip = (os.stat(fn).st_mode & 0o777) == m
         finally:
             os.unlink(fn)
-    except (IOError, OSError):
+    except OSError:
         # we don't care, the user probably won't be able to commit anyway
         return False
     return not (new_file_has_exec or exec_flags_cannot_flip)
@@ -336,7 +340,7 @@
     try:
         import _lsprof
 
-        _lsprof.Profiler  # silence unused import warning
+        del _lsprof  # silence unused import warning
         return True
     except ImportError:
         return False
@@ -345,8 +349,8 @@
 def _gethgversion():
     m = matchoutput('hg --version --quiet 2>&1', br'(\d+)\.(\d+)')
     if not m:
-        return (0, 0)
-    return (int(m.group(1)), int(m.group(2)))
+        return 0, 0
+    return int(m.group(1)), int(m.group(2))
 
 
 _hgversion = None
@@ -382,21 +386,23 @@
 def has_hg08():
     if checks["hg09"][0]():
         return True
-    return matchoutput('hg help annotate 2>&1', '--date')
+    return matchoutput('hg help annotate 2>&1', b'--date')
 
 
 @check("hg07", "Mercurial >= 0.7")
 def has_hg07():
     if checks["hg08"][0]():
         return True
-    return matchoutput('hg --version --quiet 2>&1', 'Mercurial Distributed SCM')
+    return matchoutput(
+        'hg --version --quiet 2>&1', b'Mercurial Distributed SCM'
+    )
 
 
 @check("hg06", "Mercurial >= 0.6")
 def has_hg06():
     if checks["hg07"][0]():
         return True
-    return matchoutput('hg --version --quiet 2>&1', 'Mercurial version')
+    return matchoutput('hg --version --quiet 2>&1', b'Mercurial version')
 
 
 @check("gettext", "GNU Gettext (msgfmt)")
@@ -412,8 +418,8 @@
 def getgitversion():
     m = matchoutput('git --version 2>&1', br'git version (\d+)\.(\d+)')
     if not m:
-        return (0, 0)
-    return (int(m.group(1)), int(m.group(2)))
+        return 0, 0
+    return int(m.group(1)), int(m.group(2))
 
 
 @check("pygit2", "pygit2 Python library")
@@ -421,7 +427,7 @@
     try:
         import pygit2
 
-        pygit2.Oid  # silence unused import
+        del pygit2  # silence unused import
         return True
     except ImportError:
         return False
@@ -450,7 +456,7 @@
     try:
         import docutils.core
 
-        docutils.core.publish_cmdline  # silence unused import
+        del docutils.core  # silence unused import
         return True
     except ImportError:
         return False
@@ -459,8 +465,8 @@
 def getsvnversion():
     m = matchoutput('svn --version --quiet 2>&1', br'^(\d+)\.(\d+)')
     if not m:
-        return (0, 0)
-    return (int(m.group(1)), int(m.group(2)))
+        return 0, 0
+    return int(m.group(1)), int(m.group(2))
 
 
 @checkvers("svn", "subversion client and admin tools >= %s", ('1.3', '1.5'))
@@ -642,7 +648,7 @@
     try:
         import pygments
 
-        pygments.highlight  # silence unused import warning
+        del pygments  # silence unused import warning
         return True
     except ImportError:
         return False
@@ -655,9 +661,9 @@
         v = pygments.__version__
 
         parts = v.split(".")
-        return (int(parts[0]), int(parts[1]))
+        return int(parts[0]), int(parts[1])
     except ImportError:
-        return (0, 0)
+        return 0, 0
 
 
 @checkvers("pygments", "Pygments version >= %s", ('2.5', '2.11', '2.14'))
@@ -677,7 +683,7 @@
     try:
         import ssl
 
-        ssl.CERT_NONE
+        del ssl
         return True
     except ImportError:
         return False
@@ -706,6 +712,13 @@
     return b'tls1.2' in sslutil.supportedprotocols
 
 
+@check("tls1.3", "TLS 1.3 protocol support")
+def has_tls1_3():
+    from mercurial import sslutil
+
+    return b'tls1.3' in sslutil.supportedprotocols
+
+
 @check("windows", "Windows")
 def has_windows():
     return os.name == 'nt'
@@ -756,7 +769,7 @@
     try:
         import curses
 
-        curses.COLOR_BLUE
+        del curses
 
         # Windows doesn't have a `tic` executable, but the windows_curses
         # package is sufficient to run the tests without it.
@@ -800,12 +813,12 @@
 def has_osxpackaging():
     try:
         return (
-            matchoutput('pkgbuild', br'Usage: pkgbuild ', ignorestatus=1)
+            matchoutput('pkgbuild', br'Usage: pkgbuild ', ignorestatus=True)
             and matchoutput(
-                'productbuild', br'Usage: productbuild ', ignorestatus=1
+                'productbuild', br'Usage: productbuild ', ignorestatus=True
             )
-            and matchoutput('lsbom', br'Usage: lsbom', ignorestatus=1)
-            and matchoutput('xar --help', br'Usage: xar', ignorestatus=1)
+            and matchoutput('lsbom', br'Usage: lsbom', ignorestatus=True)
+            and matchoutput('xar --help', br'Usage: xar', ignorestatus=True)
         )
     except ImportError:
         return False
@@ -918,7 +931,7 @@
     try:
         import hypothesis
 
-        hypothesis.given
+        del hypothesis
         return True
     except ImportError:
         return False
@@ -934,7 +947,7 @@
     try:
         import mercurial.zstd
 
-        mercurial.zstd.__version__
+        del mercurial.zstd
         return True
     except ImportError:
         return False
@@ -950,7 +963,7 @@
     try:
         import ensurepip
 
-        ensurepip.bootstrap
+        del ensurepip
         return True
     except ImportError:
         return False
@@ -979,7 +992,7 @@
     try:
         import fuzzywuzzy
 
-        fuzzywuzzy.__version__
+        del fuzzywuzzy
         return True
     except ImportError:
         return False
@@ -1015,65 +1028,6 @@
     return 'HGTESTEXTRAEXTENSIONS' in os.environ
 
 
-def getrepofeatures():
-    """Obtain set of repository features in use.
-
-    HGREPOFEATURES can be used to define or remove features. It contains
-    a space-delimited list of feature strings. Strings beginning with ``-``
-    mean to remove.
-    """
-    # Default list provided by core.
-    features = {
-        'bundlerepo',
-        'revlogstore',
-        'fncache',
-    }
-
-    # Features that imply other features.
-    implies = {
-        'simplestore': ['-revlogstore', '-bundlerepo', '-fncache'],
-    }
-
-    for override in os.environ.get('HGREPOFEATURES', '').split(' '):
-        if not override:
-            continue
-
-        if override.startswith('-'):
-            if override[1:] in features:
-                features.remove(override[1:])
-        else:
-            features.add(override)
-
-            for imply in implies.get(override, []):
-                if imply.startswith('-'):
-                    if imply[1:] in features:
-                        features.remove(imply[1:])
-                else:
-                    features.add(imply)
-
-    return features
-
-
-@check('reporevlogstore', 'repository using the default revlog store')
-def has_reporevlogstore():
-    return 'revlogstore' in getrepofeatures()
-
-
-@check('reposimplestore', 'repository using simple storage extension')
-def has_reposimplestore():
-    return 'simplestore' in getrepofeatures()
-
-
-@check('repobundlerepo', 'whether we can open bundle files as repos')
-def has_repobundlerepo():
-    return 'bundlerepo' in getrepofeatures()
-
-
-@check('repofncache', 'repository has an fncache')
-def has_repofncache():
-    return 'fncache' in getrepofeatures()
-
-
 @check('dirstate-v2', 'using the v2 format of .hg/dirstate')
 def has_dirstate_v2():
     # Keep this logic in sync with `newreporequirements()` in `mercurial/localrepo.py`
@@ -1103,7 +1057,7 @@
     try:
         import vcr
 
-        vcr.VCR
+        del vcr
         return True
     except (ImportError, AttributeError):
         pass
@@ -1118,14 +1072,31 @@
     return matchoutput('emacs --version', b'GNU Emacs 2(4.4|4.5|5|6|7|8|9)')
 
 
-@check('black', 'the black formatter for python >=23.3.0')
+@check(
+    'black', 'the black formatter for python (version set in pyproject.toml)'
+)
 def has_black():
-    blackcmd = 'black --version'
-    version_regex = b'black, (?:version )?([0-9a-b.]+)'
-    version = matchoutput(blackcmd, version_regex)
-    if not version:
+    env = environ()
+
+    # The top level #require statements are evaluated from $TESTTMP, and won't
+    # see the project level pyproject.toml unless executing from the project
+    # directory.
+    cwd = os.getcwd()
+    if 'RUNTESTDIR' in env:
+        cwd = os.path.realpath(f"{env['RUNTESTDIR']}/..")
+
+    try:
+        p = subprocess.Popen(
+            ['black', '--check', '-'],
+            stdin=subprocess.PIPE,
+            cwd=cwd,
+            env=env,
+        )
+    except FileNotFoundError:
         return False
-    return Version(_bytes2sys(version.group(1))) >= Version('23.3.0')
+
+    p.communicate(b'# test\n')
+    return p.returncode == 0
 
 
 @check('pytype', 'the pytype type checker')
@@ -1156,7 +1127,7 @@
     try:
         import _lzma
 
-        _lzma.FORMAT_XZ
+        del _lzma
         return True
     except ImportError:
         return False