##// END OF EJS Templates
hghave: add pyXY features for Python version numbers...
hghave: add pyXY features for Python version numbers This will allow us to sniff for Python >= versions in tests. Differential Revision: https://phab.mercurial-scm.org/D5088

File last commit:

r41488:1a6a01a2 default
r41488:1a6a01a2 default
Show More
hghave.py
824 lines | 23.8 KiB | text/x-python | PythonLexer
Gregory Szorc
tests: use absolute_import in hghave.py
r27298 from __future__ import absolute_import
Augie Fackler
hghave: use subprocess instead of os.popen...
r26137 import os
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 import re
Yuya Nishihara
cmdserver: add service that listens on unix domain socket and forks process...
r22994 import socket
Augie Fackler
hghave: use subprocess instead of os.popen...
r26137 import stat
import subprocess
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 import sys
import tempfile
tempprefix = 'hg-hghave-'
Matt Mackall
tests: use a decorator for hghave checks
r22093 checks = {
"true": (lambda: True, "yak shaving"),
"false": (lambda: False, "nail clipper"),
}
Matt Harbison
py3: use bytes stdout in hghave.py...
r41039 try:
import msvcrt
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY)
except ImportError:
pass
stdout = getattr(sys.stdout, 'buffer', sys.stdout)
stderr = getattr(sys.stderr, 'buffer', sys.stderr)
Matt Harbison
py3: fix a type error in hghave.has_hardlink...
r39795 if sys.version_info[0] >= 3:
def _bytespath(p):
if p is None:
return p
return p.encode('utf-8')
def _strpath(p):
if p is None:
return p
return p.decode('utf-8')
else:
def _bytespath(p):
return p
_strpath = _bytespath
Matt Mackall
tests: use a decorator for hghave checks
r22093 def check(name, desc):
timeless
hghave: add docstring for check
r28757 """Registers a check function for a feature."""
Matt Mackall
tests: use a decorator for hghave checks
r22093 def decorator(func):
checks[name] = (func, desc)
return func
return decorator
timeless
hghave: add checkvers function
r28758 def checkvers(name, desc, vers):
"""Registers a check function for each of a series of versions.
vers can be a list or an iterator"""
def decorator(func):
def funcv(v):
def f():
return func(v)
return f
for v in vers:
v = str(v)
f = funcv(v)
checks['%s%s' % (name, v.replace('.', ''))] = (f, desc % v)
return func
return decorator
Gregory Szorc
hghave: move feature checking into hghave.py...
r26067 def checkfeatures(features):
result = {
'error': [],
'missing': [],
'skipped': [],
}
for feature in features:
negate = feature.startswith('no-')
if negate:
feature = feature[3:]
if feature not in checks:
result['missing'].append(feature)
continue
check, desc = checks[feature]
try:
available = check()
except Exception:
result['error'].append('hghave check failed: %s' % feature)
continue
if not negate and not available:
result['skipped'].append('missing feature: %s' % desc)
elif negate and available:
result['skipped'].append('system supports %s' % desc)
return result
Gregory Szorc
hghave: remove quiet option...
r26068 def require(features):
Gregory Szorc
hghave: move feature checking into hghave.py...
r26067 """Require that features are available, exiting if not."""
result = checkfeatures(features)
Gregory Szorc
hghave: remove quiet option...
r26068 for missing in result['missing']:
Matt Harbison
py3: use bytes stdout in hghave.py...
r41039 stderr.write(('skipped: unknown feature: %s\n'
% missing).encode('utf-8'))
Gregory Szorc
hghave: remove quiet option...
r26068 for msg in result['skipped']:
Matt Harbison
py3: use bytes stdout in hghave.py...
r41039 stderr.write(('skipped: %s\n' % msg).encode('utf-8'))
Gregory Szorc
hghave: remove quiet option...
r26068 for msg in result['error']:
Matt Harbison
py3: use bytes stdout in hghave.py...
r41039 stderr.write(('%s\n' % msg).encode('utf-8'))
Gregory Szorc
hghave: move feature checking into hghave.py...
r26067
if result['missing']:
sys.exit(2)
if result['skipped'] or result['error']:
sys.exit(1)
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def matchoutput(cmd, regexp, ignorestatus=False):
timeless
hghave.py: fix matchoutput documentation
r27114 """Return the match object if cmd executes successfully and its output
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 is matched by the supplied regular expression.
"""
r = re.compile(regexp)
Martin von Zweigbergk
hghave: let OSError with ENOENT through like any other...
r41402 p = subprocess.Popen(
cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
Matt Harbison
hghave: avoid a deadlock reading the child process's output...
r38205 s = p.communicate()[0]
ret = p.returncode
Augie Fackler
hghave: use subprocess instead of os.popen...
r26137 return (ignorestatus or not ret) and r.search(s)
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("baz", "GNU Arch baz client")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_baz():
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 return matchoutput('baz --version 2>&1', br'baz Bazaar version')
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("bzr", "Canonical's Bazaar client")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_bzr():
try:
import bzrlib
timeless
hghave: make bzr checks stricter...
r29866 import bzrlib.bzrdir
import bzrlib.errors
import bzrlib.revision
Yuya Nishihara
hghave: fix has_bzr() to not try to import RevisionSpec as module...
r29903 import bzrlib.revisionspec
bzrlib.revisionspec.RevisionSpec
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 return bzrlib.__doc__ is not None
Yuya Nishihara
hghave: fix has_bzr() to not try to import RevisionSpec as module...
r29903 except (AttributeError, ImportError):
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 return False
timeless
hghave: use checkvers for bzr114
r28760 @checkvers("bzr", "Canonical's Bazaar client >= %s", (1.14,))
def has_bzr_range(v):
major, minor = v.split('.')[0:2]
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 try:
import bzrlib
return (bzrlib.__doc__ is not None
timeless
hghave: use checkvers for bzr114
r28760 and bzrlib.version_info[:2] >= (int(major), int(minor)))
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 except ImportError:
return False
Yuya Nishihara
hghave: add "chg" flag to skip tests that can't be compatible with chg...
r28880 @check("chg", "running with chg")
def has_chg():
return 'CHGHG' in os.environ
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("cvs", "cvs client/server")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_cvs():
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 re = br'Concurrent Versions System.*?server'
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 return matchoutput('cvs --version 2>&1', re) and not has_msys()
timeless
hghave: update cvs112 description...
r28756 @check("cvs112", "cvs client/server 1.12.* (not cvsnt)")
Bryan O'Sullivan
hghave: introduce a test (unused) for cvs >= 1.12
r18285 def has_cvs112():
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 re = br'Concurrent Versions System \(CVS\) 1.12.*?server'
Bryan O'Sullivan
hghave: introduce a test (unused) for cvs >= 1.12
r18285 return matchoutput('cvs --version 2>&1', re) and not has_msys()
timeless
hghave: add cvsnt...
r28796 @check("cvsnt", "cvsnt client/server")
def has_cvsnt():
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 re = br'Concurrent Versions System \(CVSNT\) (\d+).(\d+).*\(client/server\)'
timeless
hghave: add cvsnt...
r28796 return matchoutput('cvsnt --version 2>&1', re)
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("darcs", "darcs client")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_darcs():
Yuya Nishihara
hghave: check darcs version more strictly...
r30297 return matchoutput('darcs --version', br'\b2\.([2-9]|\d{2})', True)
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("mtn", "monotone client (>= 1.0)")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_mtn():
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 return matchoutput('mtn --version', br'monotone', True) and not matchoutput(
'mtn --version', br'monotone 0\.', True)
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("eol-in-paths", "end-of-lines in paths")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_eol_in_paths():
try:
Mads Kiilerich
tests/hghave: consistently use dir='.', prefix=tempprefix for tempfiles...
r16968 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix, suffix='\n\r')
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 os.close(fd)
os.remove(path)
return True
except (IOError, OSError):
return False
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("execbit", "executable bit")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_executablebit():
try:
EXECFLAGS = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
Mads Kiilerich
tests/hghave: consistently use dir='.', prefix=tempprefix for tempfiles...
r16968 fh, fn = tempfile.mkstemp(dir='.', prefix=tempprefix)
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 try:
os.close(fh)
Gregory Szorc
global: mass rewrite to use modern octal syntax...
r25658 m = os.stat(fn).st_mode & 0o777
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 new_file_has_exec = m & EXECFLAGS
os.chmod(fn, m ^ EXECFLAGS)
Gregory Szorc
global: mass rewrite to use modern octal syntax...
r25658 exec_flags_cannot_flip = ((os.stat(fn).st_mode & 0o777) == m)
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 finally:
os.unlink(fn)
except (IOError, 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)
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("icasefs", "case insensitive file system")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_icasefs():
# Stolen from mercurial.util
Mads Kiilerich
tests/hghave: consistently use dir='.', prefix=tempprefix for tempfiles...
r16968 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix)
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 os.close(fd)
try:
s1 = os.stat(path)
d, b = os.path.split(path)
p2 = os.path.join(d, b.upper())
if path == p2:
p2 = os.path.join(d, b.lower())
try:
s2 = os.stat(p2)
return s2 == s1
except OSError:
return False
finally:
os.remove(path)
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("fifo", "named pipes")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_fifo():
Mads Kiilerich
tests/hghave: test that a fifo actually can be created on the filesystem...
r16969 if getattr(os, "mkfifo", None) is None:
return False
name = tempfile.mktemp(dir='.', prefix=tempprefix)
try:
os.mkfifo(name)
os.unlink(name)
return True
except OSError:
return False
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("killdaemons", 'killdaemons.py support')
Patrick Mezard
test-http-branchmap: enable on Windows...
r17467 def has_killdaemons():
return True
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("cacheable", "cacheable filesystem")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_cacheable_fs():
from mercurial import util
Mads Kiilerich
tests/hghave: consistently use dir='.', prefix=tempprefix for tempfiles...
r16968 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix)
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 os.close(fd)
try:
return util.cachestat(path).cacheable()
finally:
os.remove(path)
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("lsprof", "python lsprof module")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_lsprof():
try:
import _lsprof
Mads Kiilerich
cleanup: make sure we always access members of imported modules...
r22198 _lsprof.Profiler # silence unused import warning
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 return True
except ImportError:
return False
timeless
hghave: add hg06..hg39...
r28761 def gethgversion():
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 m = matchoutput('hg --version --quiet 2>&1', br'(\d+)\.(\d+)')
timeless
hghave: add hg06..hg39...
r28761 if not m:
return (0, 0)
return (int(m.group(1)), int(m.group(2)))
@checkvers("hg", "Mercurial >= %s",
hghave: prefill more version of Mercurial...
r32243 list([(1.0 * x) / 10 for x in range(9, 99)]))
timeless
hghave: add hg06..hg39...
r28761 def has_hg_range(v):
major, minor = v.split('.')[0:2]
return gethgversion() >= (int(major), int(minor))
@check("hg08", "Mercurial >= 0.8")
def has_hg08():
if checks["hg09"][0]():
return True
return matchoutput('hg help annotate 2>&1', '--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')
@check("hg06", "Mercurial >= 0.6")
def has_hg06():
if checks["hg07"][0]():
return True
return matchoutput('hg --version --quiet 2>&1', 'Mercurial version')
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("gettext", "GNU Gettext (msgfmt)")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_gettext():
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 return matchoutput('msgfmt --version', br'GNU gettext-tools')
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("git", "git command line client")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_git():
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 return matchoutput('git --version 2>&1', br'^git version')
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966
Sean Farley
hghave: add has_git_range for testing if git understands ext::sh...
r32901 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)))
Matt Harbison
hghave: add a check for lfs-test-server...
r35137 # https://github.com/git-lfs/lfs-test-server
@check("lfs-test-server", "git-lfs test server")
def has_lfsserver():
exe = 'lfs-test-server'
if has_windows():
exe = 'lfs-test-server.exe'
return any(
os.access(os.path.join(path, exe), os.X_OK)
for path in os.environ["PATH"].split(os.pathsep)
)
Sean Farley
hghave: add has_git_range for testing if git understands ext::sh...
r32901 @checkvers("git", "git client (with ext::sh support) version >= %s", (1.9,))
def has_git_range(v):
major, minor = v.split('.')[0:2]
return getgitversion() >= (int(major), int(minor))
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("docutils", "Docutils text processing library")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_docutils():
try:
Yuya Nishihara
hghave: replace relative import of docutils.core
r28779 import docutils.core
docutils.core.publish_cmdline # silence unused import
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 return True
except ImportError:
return False
def getsvnversion():
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 m = matchoutput('svn --version --quiet 2>&1', br'^(\d+)\.(\d+)')
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 if not m:
return (0, 0)
return (int(m.group(1)), int(m.group(2)))
timeless
hghave: replace has_svn13/has_svn15 with checkvers...
r28759 @checkvers("svn", "subversion client and admin tools >= %s", (1.3, 1.5))
def has_svn_range(v):
major, minor = v.split('.')[0:2]
return getsvnversion() >= (int(major), int(minor))
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("svn", "subversion client and admin tools")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_svn():
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 return matchoutput('svn --version 2>&1', br'^svn, version') and \
matchoutput('svnadmin --version 2>&1', br'^svnadmin, version')
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("svn-bindings", "subversion python bindings")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_svn_bindings():
try:
import svn.core
version = svn.core.SVN_VER_MAJOR, svn.core.SVN_VER_MINOR
if version < (1, 4):
return False
return True
except ImportError:
return False
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("p4", "Perforce server and client")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_p4():
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 return (matchoutput('p4 -V', br'Rev\. P4/') and
matchoutput('p4d -V', br'Rev\. P4D/'))
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("symlink", "symbolic links")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_symlink():
if getattr(os, "symlink", None) is None:
return False
Mads Kiilerich
tests/hghave: consistently use dir='.', prefix=tempprefix for tempfiles...
r16968 name = tempfile.mktemp(dir='.', prefix=tempprefix)
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 try:
os.symlink(".", name)
os.unlink(name)
return True
except (OSError, AttributeError):
return False
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("hardlink", "hardlinks")
Mads Kiilerich
tests: introduce hghave hardlinks...
r16971 def has_hardlink():
from mercurial import util
fh, fn = tempfile.mkstemp(dir='.', prefix=tempprefix)
os.close(fh)
name = tempfile.mktemp(dir='.', prefix=tempprefix)
try:
Matt Harbison
py3: fix a type error in hghave.has_hardlink...
r39795 util.oslink(_bytespath(fn), _bytespath(name))
Matt Mackall
hghave: use try/except/finally
r25090 os.unlink(name)
return True
except OSError:
return False
Mads Kiilerich
tests: introduce hghave hardlinks...
r16971 finally:
os.unlink(fn)
Jun Wu
hghave: add a check about whitelisted filesystem that supports hardlink...
r31576 @check("hardlink-whitelisted", "hardlinks on whitelisted filesystems")
def has_hardlink_whitelisted():
Yuya Nishihara
hghave: use util.getfstype
r31674 from mercurial import util
Yuya Nishihara
statfs: make getfstype() raise OSError...
r31678 try:
Augie Fackler
hghave: fix hardlink-whitelisted check on Python 3...
r36960 fstype = util.getfstype(b'.')
Yuya Nishihara
statfs: make getfstype() raise OSError...
r31678 except OSError:
return False
Jun Wu
hghave: add a check about whitelisted filesystem that supports hardlink...
r31576 return fstype in util._hardlinkfswhitelist
Yuya Nishihara
tests: run "cwd was removed" test only if cwd can actually be removed...
r30230 @check("rmcwd", "can remove current working directory")
def has_rmcwd():
ocwd = os.getcwd()
temp = tempfile.mkdtemp(dir='.', prefix=tempprefix)
try:
os.chdir(temp)
# On Linux, 'rmdir .' isn't allowed, but the other names are okay.
# On Solaris and Windows, the cwd can't be removed by any names.
os.rmdir(os.getcwd())
return True
except OSError:
return False
finally:
os.chdir(ocwd)
Yuya Nishihara
hghave: fix 'rmcwd' to ensure temporary directory is removed...
r30242 # clean up temp dir on platforms where cwd can't be removed
try:
os.rmdir(temp)
except OSError:
pass
Yuya Nishihara
tests: run "cwd was removed" test only if cwd can actually be removed...
r30230
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("tla", "GNU Arch tla client")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_tla():
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 return matchoutput('tla --version 2>&1', br'The GNU Arch Revision')
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("gpg", "gpg client")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_gpg():
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 return matchoutput('gpg --version 2>&1', br'GnuPG')
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966
Yuya Nishihara
test-gpg: start gpg-agent under control of the test runner...
r29790 @check("gpg2", "gpg client v2")
def has_gpg2():
return matchoutput('gpg --version 2>&1', br'GnuPG[^0-9]+2\.')
Yuya Nishihara
test-gpg: start gpg-agent by gpg-connect-agent only if GnuPG v2.1+ detected...
r29873 @check("gpg21", "gpg client v2.1+")
def has_gpg21():
return matchoutput('gpg --version 2>&1', br'GnuPG[^0-9]+2\.(?!0)')
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("unix-permissions", "unix-style permissions")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_unix_permissions():
Mads Kiilerich
tests/hghave: consistently use dir='.', prefix=tempprefix for tempfiles...
r16968 d = tempfile.mkdtemp(dir='.', prefix=tempprefix)
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 try:
fname = os.path.join(d, 'foo')
Gregory Szorc
global: mass rewrite to use modern octal syntax...
r25658 for umask in (0o77, 0o07, 0o22):
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 os.umask(umask)
f = open(fname, 'w')
f.close()
mode = os.stat(fname).st_mode
os.unlink(fname)
Gregory Szorc
global: mass rewrite to use modern octal syntax...
r25658 if mode & 0o777 != ~umask & 0o666:
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 return False
return True
finally:
os.rmdir(d)
Yuya Nishihara
cmdserver: add service that listens on unix domain socket and forks process...
r22994 @check("unix-socket", "AF_UNIX socket family")
def has_unix_socket():
return getattr(socket, 'AF_UNIX', None) is not None
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("root", "root permissions")
Matt Mackall
tests: skip tests that require not having root (issue4089)...
r20008 def has_root():
Simon Heimberg
tests: fix `hghave root` on windows...
r20114 return getattr(os, 'geteuid', None) and os.geteuid() == 0
Matt Mackall
tests: skip tests that require not having root (issue4089)...
r20008
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("pyflakes", "Pyflakes python linter")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_pyflakes():
return matchoutput("sh -c \"echo 'import re' 2>&1 | pyflakes\"",
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 br"<stdin>:1: 're' imported but unused",
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 True)
Pierre-Yves David
test: add a basic 'test-check-pylint.t'...
r31413 @check("pylint", "Pylint python linter")
def has_pylint():
return matchoutput("pylint --help",
br"Usage: pylint",
True)
Augie Fackler
hghave: add a check for clang-format...
r34697 @check("clang-format", "clang-format C code formatter")
def has_clang_format():
Yuya Nishihara
hghave: require clang-format >= 6 due to output change
r38725 m = matchoutput('clang-format --version', br'clang-format version (\d)')
# style changed somewhere between 4.x and 6.x
return m and int(m.group(1)) >= 6
Augie Fackler
hghave: add a check for clang-format...
r34697
av6
tests: use jshint when available to check .js files
r35034 @check("jshint", "JSHint static code analysis tool")
def has_jshint():
return matchoutput("jshint --version 2>&1", br"jshint v")
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("pygments", "Pygments source highlighting library")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_pygments():
try:
import pygments
Mads Kiilerich
cleanup: make sure we always access members of imported modules...
r22198 pygments.highlight # silence unused import warning
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 return True
except ImportError:
return False
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("outer-repo", "outer repo")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_outer_repo():
Mads Kiilerich
tests: hghave outer-repo should be true even if a bad repo is found...
r17016 # failing for other reasons than 'no repo' imply that there is a repo
return not matchoutput('hg root 2>&1',
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 br'abort: no repository found', True)
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966
Gregory Szorc
hghave: change ssl check to just check ssl module...
r28591 @check("ssl", "ssl module available")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_ssl():
try:
import ssl
Gregory Szorc
hghave: change ssl check to just check ssl module...
r28591 ssl.CERT_NONE
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 return True
except ImportError:
return False
Yuya Nishihara
test-https: test basic functions of client certificate authentication...
r25413 @check("sslcontext", "python >= 2.7.9 ssl")
def has_sslcontext():
try:
import ssl
ssl.SSLContext
return True
except (ImportError, AttributeError):
return False
Yuya Nishihara
test-https: enable dummycert test only if Apple python is used (issue4500)...
r24289 @check("defaultcacerts", "can verify SSL certs by system's CA certs store")
def has_defaultcacerts():
Gregory Szorc
sslutil: pass ui to _defaultcacerts...
r29483 from mercurial import sslutil, ui as uimod
Yuya Nishihara
ui: factor out ui.load() to create a ui without loading configs (API)...
r30559 ui = uimod.ui.load()
Gregory Szorc
sslutil: pass ui to _defaultcacerts...
r29483 return sslutil._defaultcacerts(ui) or sslutil._canloaddefaultcerts
Yuya Nishihara
test-https: enable dummycert test only if Apple python is used (issue4500)...
r24289
Gregory Szorc
tests: better testing of loaded certificates...
r29481 @check("defaultcacertsloaded", "detected presence of loaded system CA certs")
def has_defaultcacertsloaded():
import ssl
Gregory Szorc
sslutil: pass ui to _defaultcacerts...
r29483 from mercurial import sslutil, ui as uimod
Gregory Szorc
tests: better testing of loaded certificates...
r29481
if not has_defaultcacerts():
return False
if not has_sslcontext():
return False
Yuya Nishihara
ui: factor out ui.load() to create a ui without loading configs (API)...
r30559 ui = uimod.ui.load()
Gregory Szorc
sslutil: pass ui to _defaultcacerts...
r29483 cafile = sslutil._defaultcacerts(ui)
Gregory Szorc
tests: better testing of loaded certificates...
r29481 ctx = ssl.create_default_context()
if cafile:
ctx.load_verify_locations(cafile=cafile)
else:
ctx.load_default_certs()
return len(ctx.get_ca_certs()) > 0
Gregory Szorc
sslutil: more robustly detect protocol support...
r29601 @check("tls1.2", "TLS 1.2 protocol support")
def has_tls1_2():
from mercurial import sslutil
Gregory Szorc
tests: add b'' when testing for tls1.2...
r41426 return b'tls1.2' in sslutil.supportedprotocols
Gregory Szorc
sslutil: more robustly detect protocol support...
r29601
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("windows", "Windows")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_windows():
return os.name == 'nt'
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("system-sh", "system() uses sh")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_system_sh():
return os.name != 'nt'
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("serve", "platform and python can manage 'hg serve -d'")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_serve():
Matt Harbison
hghave: enable 'serve' on Windows...
r32856 return True
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("test-repo", "running tests from repository")
Matt Mackall
tests: add repository check for pyflakes test...
r21208 def has_test_repo():
t = os.environ["TESTDIR"]
return os.path.isdir(os.path.join(t, "..", ".hg"))
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("tic", "terminfo compiler and curses module")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_tic():
Mads Kiilerich
tests: 'hghave tic' also requires curses support in Python...
r20304 try:
import curses
curses.COLOR_BLUE
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 return matchoutput('test -x "`which tic`"', br'')
Mads Kiilerich
tests: 'hghave tic' also requires curses support in Python...
r20304 except ImportError:
return False
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("msys", "Windows with MSYS")
Adrian Buehlmann
tests/hghave: extract hghave.py...
r16966 def has_msys():
return os.getenv('MSYSTEM')
Matt Mackall
tests: use a decorator for hghave checks
r22093 @check("aix", "AIX")
Jim Hague
tests: AIX can't handle negative date in test-dirstate.t...
r19092 def has_aix():
return sys.platform.startswith("aix")
Mads Kiilerich
ssl: on OS X, use a dummy cert to trick Python/OpenSSL to use system CA certs...
r22575 @check("osx", "OS X")
def has_osx():
return sys.platform == 'darwin'
Augie Fackler
hghave: add check for OS X packaging tools
r29026 @check("osxpackaging", "OS X packaging tools")
def has_osxpackaging():
try:
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 return (matchoutput('pkgbuild', br'Usage: pkgbuild ', ignorestatus=1)
Augie Fackler
hghave: add check for OS X packaging tools
r29026 and matchoutput(
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 'productbuild', br'Usage: productbuild ',
Augie Fackler
hghave: add check for OS X packaging tools
r29026 ignorestatus=1)
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 and matchoutput('lsbom', br'Usage: lsbom', ignorestatus=1)
Augie Fackler
hghave: add check for OS X packaging tools
r29026 and matchoutput(
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 'xar --help', br'Usage: xar', ignorestatus=1))
Augie Fackler
hghave: add check for OS X packaging tools
r29026 except ImportError:
return False
Gregory Szorc
fsmonitor: warn when fsmonitor could be used...
r34886 @check('linuxormacos', 'Linux or MacOS')
def has_linuxormacos():
# This isn't a perfect test for MacOS. But it is sufficient for our needs.
return sys.platform.startswith(('linux', 'darwin'))
Augie Fackler
hghave: add a check for docker support...
r26111 @check("docker", "docker support")
def has_docker():
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 pat = br'A self-sufficient runtime for'
Augie Fackler
hghave: add a check for docker support...
r26111 if matchoutput('docker --help', pat):
if 'linux' not in sys.platform:
# TODO: in theory we should be able to test docker-based
# package creation on non-linux using boot2docker, but in
# practice that requires extra coordination to make sure
# $TESTTEMP is going to be visible at the same path to the
# boot2docker VM. If we figure out how to verify that, we
# can use the following instead of just saying False:
# return 'DOCKER_HOST' in os.environ
return False
return True
return False
Augie Fackler
hghave: add a check for debian packaging tools
r26110 @check("debhelper", "debian packaging tools")
def has_debhelper():
Kyle Lippincott
hghave: fix dpkg --version check to work on recent dpkg versions...
r34395 # Some versions of dpkg say `dpkg', some say 'dpkg' (` vs ' on the first
# quote), so just accept anything in that spot.
Augie Fackler
hghave: add a check for debian packaging tools
r26110 dpkg = matchoutput('dpkg --version',
Kyle Lippincott
hghave: fix dpkg --version check to work on recent dpkg versions...
r34395 br"Debian .dpkg' package management program")
Augie Fackler
hghave: add a check for debian packaging tools
r26110 dh = matchoutput('dh --help',
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 br'dh is a part of debhelper.', ignorestatus=True)
Augie Fackler
hghave: add a check for debian packaging tools
r26110 dh_py2 = matchoutput('dh_python2 --help',
timeless
hghave: matchoutput needs to use bytes for regexp...
r29140 br'other supported Python versions')
Kyle Lippincott
hghave: check for debuild being installed as well...
r34400 # debuild comes from the 'devscripts' package, though you might want
# the 'build-debs' package instead, which has a dependency on devscripts.
debuild = matchoutput('debuild --help',
br'to run debian/rules with given parameter')
return dpkg and dh and dh_py2 and debuild
Augie Fackler
hghave: add a check for debian packaging tools
r26110
Kyle Lippincott
tests: add "have" check for dpkg builddeps...
r34402 @check("debdeps",
"debian build dependencies (run dpkg-checkbuilddeps in contrib/)")
def has_debdeps():
# just check exit status (ignoring output)
Gregory Szorc
packaging: move contrib/debian to contrib/packaging/...
r38029 path = '%s/../contrib/packaging/debian/control' % os.environ['TESTDIR']
Kyle Lippincott
tests: add "have" check for dpkg builddeps...
r34402 return matchoutput('dpkg-checkbuilddeps %s' % path, br'')
timeless
hghave: add demandimport checking
r29867 @check("demandimport", "demandimport enabled")
def has_demandimport():
Saurabh Singh
hghave: disable demandimport when chg is running...
r34841 # chg disables demandimport intentionally for performance wins.
return ((not has_chg()) and os.environ.get('HGDEMANDIMPORT') != 'disable')
timeless
hghave: add demandimport checking
r29867
Gregory Szorc
hghave: add pyXY features for Python version numbers...
r41488 @checkvers("py", "Python >= %s", (2.7, 3.5, 3.6, 3.7, 3.8, 3.9))
def has_python_range(v):
major, minor = v.split('.')[0:2]
py_major, py_minor = sys.version_info.major, sys.version_info.minor
return (py_major, py_minor) >= (int(major), int(minor))
Martijn Pieters
py3: use py3 as the test tag, dropping the k...
r40299 @check("py3", "running with Python 3.x")
def has_py3():
FUJIWARA Katsunori
hghave: add "py3k" feature to check whether test runs with Python 3.x...
r19931 return 3 == sys.version_info[0]
Yuya Nishihara
tests: disable test of buffer overflow in parsers.c if --pure...
r25859
Gregory Szorc
run-tests: add --with-python3 to define a Python 3 interpreter...
r28582 @check("py3exe", "a Python 3.x interpreter is available")
def has_python3exe():
Augie Fackler
hghave: move from requiring the PYTHON3 env var to looking for `python3`...
r39387 return matchoutput('python3 -V', br'^Python 3.(5|6|7|8|9)')
Gregory Szorc
run-tests: add --with-python3 to define a Python 3 interpreter...
r28582
Yuya Nishihara
tests: disable test of buffer overflow in parsers.c if --pure...
r25859 @check("pure", "running with pure Python code")
def has_pure():
timeless
hghave: support HGMODULEPOLICY for pure...
r27702 return any([
os.environ.get("HGMODULEPOLICY") == "py",
os.environ.get("HGTEST_RUN_TESTS_PURE") == "--pure",
])
Augie Fackler
run-tests: add support for marking tests as very slow...
r26109
Kyle Lippincott
tests: hint how to run slow tests when rejecting
r32473 @check("slow", "allow slow tests (use --allow-slow-tests)")
Augie Fackler
run-tests: add support for marking tests as very slow...
r26109 def has_slow():
return os.environ.get('HGTEST_SLOW') == 'slow'
David R. MacIver
testing: add hypothesis fuzz testing...
r26842
timeless
hghave: improve description of Hypothesis
r28383 @check("hypothesis", "Hypothesis automated test generation")
David R. MacIver
testing: add hypothesis fuzz testing...
r26842 def has_hypothesis():
try:
import hypothesis
hypothesis.given
return True
except ImportError:
return False
Augie Fackler
hghave: add a check for unzip(1) that understands symlinks...
r29843
@check("unziplinks", "unzip(1) understands and extracts symlinks")
def unzip_understands_symlinks():
return matchoutput('unzip --help', br'Info-ZIP')
Gregory Szorc
hghave: add check for zstd support...
r30441
@check("zstd", "zstd Python module available")
def has_zstd():
try:
import mercurial.zstd
mercurial.zstd.__version__
return True
except ImportError:
return False
Bryan O'Sullivan
stdio: add Linux-specific tests for error checking
r31964
@check("devfull", "/dev/full special file")
def has_dev_full():
return os.path.exists('/dev/full')
Augie Fackler
hghave: add check for virtualenv
r32726
@check("virtualenv", "Python virtualenv support")
def has_virtualenv():
try:
import virtualenv
virtualenv.ACTIVATE_SH
return True
except ImportError:
return False
Siddharth Agarwal
hghave: add test for whether fsmonitor is enabled...
r32770
@check("fsmonitor", "running tests with fsmonitor")
def has_fsmonitor():
return 'HGFSMONITOR_TESTS' in os.environ
Rishabh Madan
releasenotes: add import check for fuzzywuzzy...
r33660
@check("fuzzywuzzy", "Fuzzy string matching library")
def has_fuzzywuzzy():
try:
import fuzzywuzzy
fuzzywuzzy.__version__
return True
except ImportError:
return False
Augie Fackler
hghave: add test for clang 6 and later...
r35686
@check("clang-libfuzzer", "clang new enough to include libfuzzer")
def has_clang_libfuzzer():
Augie Fackler
hghave: fix up clang-libfuzzer regex to be bytes...
r36677 mat = matchoutput('clang --version', b'clang version (\d)')
Augie Fackler
hghave: add test for clang 6 and later...
r35686 if mat:
# libfuzzer is new in clang 6
return int(mat.group(1)) > 5
return False
Jun Wu
tests: add tests about diff quality...
r36696
Yuya Nishihara
test-fuzz-targets: look for clang-6.0 binary as well...
r38238 @check("clang-6.0", "clang 6.0 with version suffix (libfuzzer included)")
def has_clang60():
return matchoutput('clang-6.0 --version', b'clang version 6\.')
Jun Wu
tests: add tests about diff quality...
r36696 @check("xdiff", "xdiff algorithm")
def has_xdiff():
try:
from mercurial import policy
bdiff = policy.importmod('bdiff')
Augie Fackler
hghave: fix xdiff check on Python 3...
r36959 return bdiff.xdiffblocks(b'', b'') == [(0, 0, 0, 0)]
Augie Fackler
hghave: remove unused "as ex" in exception block...
r36712 except (ImportError, AttributeError):
Jun Wu
tests: add tests about diff quality...
r36696 return False
Gregory Szorc
tests: conditionalize tests based on presence of revlogs for files...
r37356
Gregory Szorc
tests: conditionalize tests based on presence of custom extensions...
r37360 @check('extraextensions', 'whether tests are running with extra extensions')
def has_extraextensions():
return 'HGTESTEXTRAEXTENSIONS' in os.environ
Gregory Szorc
tests: conditionalize tests based on presence of revlogs for files...
r37356 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 = {
Gregory Szorc
tests: disallow using simple store repo with bundlerepo...
r37364 'bundlerepo',
Gregory Szorc
tests: conditionalize tests based on presence of revlogs for files...
r37356 'revlogstore',
Gregory Szorc
simplestore: use a custom store for the simple store repo...
r37433 'fncache',
Gregory Szorc
tests: conditionalize tests based on presence of revlogs for files...
r37356 }
# Features that imply other features.
implies = {
Gregory Szorc
simplestore: use a custom store for the simple store repo...
r37433 'simplestore': ['-revlogstore', '-bundlerepo', '-fncache'],
Gregory Szorc
tests: conditionalize tests based on presence of revlogs for files...
r37356 }
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()
Gregory Szorc
tests: disallow using simple store repo with bundlerepo...
r37364
@check('repobundlerepo', 'whether we can open bundle files as repos')
def has_repobundlerepo():
return 'bundlerepo' in getrepofeatures()
Gregory Szorc
simplestore: use a custom store for the simple store repo...
r37433
@check('repofncache', 'repository has an fncache')
def has_repofncache():
return 'fncache' in getrepofeatures()
Augie Fackler
hghave: add a checker for the vcr HTTP record/replay library...
r39684
Gregory Szorc
sqlitestore: file storage backend using SQLite...
r40362 @check('sqlite', 'sqlite3 module is available')
def has_sqlite():
try:
import sqlite3
Yuya Nishihara
tests: require SQLite 3.8.3+ as sqlitestore relies on "WITH" clause...
r40492 version = sqlite3.sqlite_version_info
Gregory Szorc
sqlitestore: file storage backend using SQLite...
r40362 except ImportError:
return False
Yuya Nishihara
tests: require SQLite 3.8.3+ as sqlitestore relies on "WITH" clause...
r40492 if version < (3, 8, 3):
# WITH clause not supported
return False
Gregory Szorc
sqlitestore: file storage backend using SQLite...
r40362 return matchoutput('sqlite3 -version', b'^3\.\d+')
Augie Fackler
hghave: add a checker for the vcr HTTP record/replay library...
r39684 @check('vcr', 'vcr http mocking library')
def has_vcr():
try:
import vcr
vcr.VCR
return True
except (ImportError, AttributeError):
pass
return False