##// END OF EJS Templates
hghave: support HGMODULEPOLICY for pure...
timeless -
r27702:39122c24 default
parent child Browse files
Show More
@@ -1,476 +1,479
1 from __future__ import absolute_import
1 from __future__ import absolute_import
2
2
3 import errno
3 import errno
4 import os
4 import os
5 import re
5 import re
6 import socket
6 import socket
7 import stat
7 import stat
8 import subprocess
8 import subprocess
9 import sys
9 import sys
10 import tempfile
10 import tempfile
11
11
12 tempprefix = 'hg-hghave-'
12 tempprefix = 'hg-hghave-'
13
13
14 checks = {
14 checks = {
15 "true": (lambda: True, "yak shaving"),
15 "true": (lambda: True, "yak shaving"),
16 "false": (lambda: False, "nail clipper"),
16 "false": (lambda: False, "nail clipper"),
17 }
17 }
18
18
19 def check(name, desc):
19 def check(name, desc):
20 def decorator(func):
20 def decorator(func):
21 checks[name] = (func, desc)
21 checks[name] = (func, desc)
22 return func
22 return func
23 return decorator
23 return decorator
24
24
25 def checkfeatures(features):
25 def checkfeatures(features):
26 result = {
26 result = {
27 'error': [],
27 'error': [],
28 'missing': [],
28 'missing': [],
29 'skipped': [],
29 'skipped': [],
30 }
30 }
31
31
32 for feature in features:
32 for feature in features:
33 negate = feature.startswith('no-')
33 negate = feature.startswith('no-')
34 if negate:
34 if negate:
35 feature = feature[3:]
35 feature = feature[3:]
36
36
37 if feature not in checks:
37 if feature not in checks:
38 result['missing'].append(feature)
38 result['missing'].append(feature)
39 continue
39 continue
40
40
41 check, desc = checks[feature]
41 check, desc = checks[feature]
42 try:
42 try:
43 available = check()
43 available = check()
44 except Exception:
44 except Exception:
45 result['error'].append('hghave check failed: %s' % feature)
45 result['error'].append('hghave check failed: %s' % feature)
46 continue
46 continue
47
47
48 if not negate and not available:
48 if not negate and not available:
49 result['skipped'].append('missing feature: %s' % desc)
49 result['skipped'].append('missing feature: %s' % desc)
50 elif negate and available:
50 elif negate and available:
51 result['skipped'].append('system supports %s' % desc)
51 result['skipped'].append('system supports %s' % desc)
52
52
53 return result
53 return result
54
54
55 def require(features):
55 def require(features):
56 """Require that features are available, exiting if not."""
56 """Require that features are available, exiting if not."""
57 result = checkfeatures(features)
57 result = checkfeatures(features)
58
58
59 for missing in result['missing']:
59 for missing in result['missing']:
60 sys.stderr.write('skipped: unknown feature: %s\n' % missing)
60 sys.stderr.write('skipped: unknown feature: %s\n' % missing)
61 for msg in result['skipped']:
61 for msg in result['skipped']:
62 sys.stderr.write('skipped: %s\n' % msg)
62 sys.stderr.write('skipped: %s\n' % msg)
63 for msg in result['error']:
63 for msg in result['error']:
64 sys.stderr.write('%s\n' % msg)
64 sys.stderr.write('%s\n' % msg)
65
65
66 if result['missing']:
66 if result['missing']:
67 sys.exit(2)
67 sys.exit(2)
68
68
69 if result['skipped'] or result['error']:
69 if result['skipped'] or result['error']:
70 sys.exit(1)
70 sys.exit(1)
71
71
72 def matchoutput(cmd, regexp, ignorestatus=False):
72 def matchoutput(cmd, regexp, ignorestatus=False):
73 """Return the match object if cmd executes successfully and its output
73 """Return the match object if cmd executes successfully and its output
74 is matched by the supplied regular expression.
74 is matched by the supplied regular expression.
75 """
75 """
76 r = re.compile(regexp)
76 r = re.compile(regexp)
77 try:
77 try:
78 p = subprocess.Popen(
78 p = subprocess.Popen(
79 cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
79 cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
80 except OSError as e:
80 except OSError as e:
81 if e.errno != errno.ENOENT:
81 if e.errno != errno.ENOENT:
82 raise
82 raise
83 ret = -1
83 ret = -1
84 ret = p.wait()
84 ret = p.wait()
85 s = p.stdout.read()
85 s = p.stdout.read()
86 return (ignorestatus or not ret) and r.search(s)
86 return (ignorestatus or not ret) and r.search(s)
87
87
88 @check("baz", "GNU Arch baz client")
88 @check("baz", "GNU Arch baz client")
89 def has_baz():
89 def has_baz():
90 return matchoutput('baz --version 2>&1', r'baz Bazaar version')
90 return matchoutput('baz --version 2>&1', r'baz Bazaar version')
91
91
92 @check("bzr", "Canonical's Bazaar client")
92 @check("bzr", "Canonical's Bazaar client")
93 def has_bzr():
93 def has_bzr():
94 try:
94 try:
95 import bzrlib
95 import bzrlib
96 return bzrlib.__doc__ is not None
96 return bzrlib.__doc__ is not None
97 except ImportError:
97 except ImportError:
98 return False
98 return False
99
99
100 @check("bzr114", "Canonical's Bazaar client >= 1.14")
100 @check("bzr114", "Canonical's Bazaar client >= 1.14")
101 def has_bzr114():
101 def has_bzr114():
102 try:
102 try:
103 import bzrlib
103 import bzrlib
104 return (bzrlib.__doc__ is not None
104 return (bzrlib.__doc__ is not None
105 and bzrlib.version_info[:2] >= (1, 14))
105 and bzrlib.version_info[:2] >= (1, 14))
106 except ImportError:
106 except ImportError:
107 return False
107 return False
108
108
109 @check("cvs", "cvs client/server")
109 @check("cvs", "cvs client/server")
110 def has_cvs():
110 def has_cvs():
111 re = r'Concurrent Versions System.*?server'
111 re = r'Concurrent Versions System.*?server'
112 return matchoutput('cvs --version 2>&1', re) and not has_msys()
112 return matchoutput('cvs --version 2>&1', re) and not has_msys()
113
113
114 @check("cvs112", "cvs client/server >= 1.12")
114 @check("cvs112", "cvs client/server >= 1.12")
115 def has_cvs112():
115 def has_cvs112():
116 re = r'Concurrent Versions System \(CVS\) 1.12.*?server'
116 re = r'Concurrent Versions System \(CVS\) 1.12.*?server'
117 return matchoutput('cvs --version 2>&1', re) and not has_msys()
117 return matchoutput('cvs --version 2>&1', re) and not has_msys()
118
118
119 @check("darcs", "darcs client")
119 @check("darcs", "darcs client")
120 def has_darcs():
120 def has_darcs():
121 return matchoutput('darcs --version', r'2\.[2-9]', True)
121 return matchoutput('darcs --version', r'2\.[2-9]', True)
122
122
123 @check("mtn", "monotone client (>= 1.0)")
123 @check("mtn", "monotone client (>= 1.0)")
124 def has_mtn():
124 def has_mtn():
125 return matchoutput('mtn --version', r'monotone', True) and not matchoutput(
125 return matchoutput('mtn --version', r'monotone', True) and not matchoutput(
126 'mtn --version', r'monotone 0\.', True)
126 'mtn --version', r'monotone 0\.', True)
127
127
128 @check("eol-in-paths", "end-of-lines in paths")
128 @check("eol-in-paths", "end-of-lines in paths")
129 def has_eol_in_paths():
129 def has_eol_in_paths():
130 try:
130 try:
131 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix, suffix='\n\r')
131 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix, suffix='\n\r')
132 os.close(fd)
132 os.close(fd)
133 os.remove(path)
133 os.remove(path)
134 return True
134 return True
135 except (IOError, OSError):
135 except (IOError, OSError):
136 return False
136 return False
137
137
138 @check("execbit", "executable bit")
138 @check("execbit", "executable bit")
139 def has_executablebit():
139 def has_executablebit():
140 try:
140 try:
141 EXECFLAGS = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
141 EXECFLAGS = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
142 fh, fn = tempfile.mkstemp(dir='.', prefix=tempprefix)
142 fh, fn = tempfile.mkstemp(dir='.', prefix=tempprefix)
143 try:
143 try:
144 os.close(fh)
144 os.close(fh)
145 m = os.stat(fn).st_mode & 0o777
145 m = os.stat(fn).st_mode & 0o777
146 new_file_has_exec = m & EXECFLAGS
146 new_file_has_exec = m & EXECFLAGS
147 os.chmod(fn, m ^ EXECFLAGS)
147 os.chmod(fn, m ^ EXECFLAGS)
148 exec_flags_cannot_flip = ((os.stat(fn).st_mode & 0o777) == m)
148 exec_flags_cannot_flip = ((os.stat(fn).st_mode & 0o777) == m)
149 finally:
149 finally:
150 os.unlink(fn)
150 os.unlink(fn)
151 except (IOError, OSError):
151 except (IOError, OSError):
152 # we don't care, the user probably won't be able to commit anyway
152 # we don't care, the user probably won't be able to commit anyway
153 return False
153 return False
154 return not (new_file_has_exec or exec_flags_cannot_flip)
154 return not (new_file_has_exec or exec_flags_cannot_flip)
155
155
156 @check("icasefs", "case insensitive file system")
156 @check("icasefs", "case insensitive file system")
157 def has_icasefs():
157 def has_icasefs():
158 # Stolen from mercurial.util
158 # Stolen from mercurial.util
159 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix)
159 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix)
160 os.close(fd)
160 os.close(fd)
161 try:
161 try:
162 s1 = os.stat(path)
162 s1 = os.stat(path)
163 d, b = os.path.split(path)
163 d, b = os.path.split(path)
164 p2 = os.path.join(d, b.upper())
164 p2 = os.path.join(d, b.upper())
165 if path == p2:
165 if path == p2:
166 p2 = os.path.join(d, b.lower())
166 p2 = os.path.join(d, b.lower())
167 try:
167 try:
168 s2 = os.stat(p2)
168 s2 = os.stat(p2)
169 return s2 == s1
169 return s2 == s1
170 except OSError:
170 except OSError:
171 return False
171 return False
172 finally:
172 finally:
173 os.remove(path)
173 os.remove(path)
174
174
175 @check("fifo", "named pipes")
175 @check("fifo", "named pipes")
176 def has_fifo():
176 def has_fifo():
177 if getattr(os, "mkfifo", None) is None:
177 if getattr(os, "mkfifo", None) is None:
178 return False
178 return False
179 name = tempfile.mktemp(dir='.', prefix=tempprefix)
179 name = tempfile.mktemp(dir='.', prefix=tempprefix)
180 try:
180 try:
181 os.mkfifo(name)
181 os.mkfifo(name)
182 os.unlink(name)
182 os.unlink(name)
183 return True
183 return True
184 except OSError:
184 except OSError:
185 return False
185 return False
186
186
187 @check("killdaemons", 'killdaemons.py support')
187 @check("killdaemons", 'killdaemons.py support')
188 def has_killdaemons():
188 def has_killdaemons():
189 return True
189 return True
190
190
191 @check("cacheable", "cacheable filesystem")
191 @check("cacheable", "cacheable filesystem")
192 def has_cacheable_fs():
192 def has_cacheable_fs():
193 from mercurial import util
193 from mercurial import util
194
194
195 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix)
195 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix)
196 os.close(fd)
196 os.close(fd)
197 try:
197 try:
198 return util.cachestat(path).cacheable()
198 return util.cachestat(path).cacheable()
199 finally:
199 finally:
200 os.remove(path)
200 os.remove(path)
201
201
202 @check("lsprof", "python lsprof module")
202 @check("lsprof", "python lsprof module")
203 def has_lsprof():
203 def has_lsprof():
204 try:
204 try:
205 import _lsprof
205 import _lsprof
206 _lsprof.Profiler # silence unused import warning
206 _lsprof.Profiler # silence unused import warning
207 return True
207 return True
208 except ImportError:
208 except ImportError:
209 return False
209 return False
210
210
211 @check("gettext", "GNU Gettext (msgfmt)")
211 @check("gettext", "GNU Gettext (msgfmt)")
212 def has_gettext():
212 def has_gettext():
213 return matchoutput('msgfmt --version', 'GNU gettext-tools')
213 return matchoutput('msgfmt --version', 'GNU gettext-tools')
214
214
215 @check("git", "git command line client")
215 @check("git", "git command line client")
216 def has_git():
216 def has_git():
217 return matchoutput('git --version 2>&1', r'^git version')
217 return matchoutput('git --version 2>&1', r'^git version')
218
218
219 @check("docutils", "Docutils text processing library")
219 @check("docutils", "Docutils text processing library")
220 def has_docutils():
220 def has_docutils():
221 try:
221 try:
222 from docutils.core import publish_cmdline
222 from docutils.core import publish_cmdline
223 publish_cmdline # silence unused import
223 publish_cmdline # silence unused import
224 return True
224 return True
225 except ImportError:
225 except ImportError:
226 return False
226 return False
227
227
228 def getsvnversion():
228 def getsvnversion():
229 m = matchoutput('svn --version --quiet 2>&1', r'^(\d+)\.(\d+)')
229 m = matchoutput('svn --version --quiet 2>&1', r'^(\d+)\.(\d+)')
230 if not m:
230 if not m:
231 return (0, 0)
231 return (0, 0)
232 return (int(m.group(1)), int(m.group(2)))
232 return (int(m.group(1)), int(m.group(2)))
233
233
234 @check("svn15", "subversion client and admin tools >= 1.5")
234 @check("svn15", "subversion client and admin tools >= 1.5")
235 def has_svn15():
235 def has_svn15():
236 return getsvnversion() >= (1, 5)
236 return getsvnversion() >= (1, 5)
237
237
238 @check("svn13", "subversion client and admin tools >= 1.3")
238 @check("svn13", "subversion client and admin tools >= 1.3")
239 def has_svn13():
239 def has_svn13():
240 return getsvnversion() >= (1, 3)
240 return getsvnversion() >= (1, 3)
241
241
242 @check("svn", "subversion client and admin tools")
242 @check("svn", "subversion client and admin tools")
243 def has_svn():
243 def has_svn():
244 return matchoutput('svn --version 2>&1', r'^svn, version') and \
244 return matchoutput('svn --version 2>&1', r'^svn, version') and \
245 matchoutput('svnadmin --version 2>&1', r'^svnadmin, version')
245 matchoutput('svnadmin --version 2>&1', r'^svnadmin, version')
246
246
247 @check("svn-bindings", "subversion python bindings")
247 @check("svn-bindings", "subversion python bindings")
248 def has_svn_bindings():
248 def has_svn_bindings():
249 try:
249 try:
250 import svn.core
250 import svn.core
251 version = svn.core.SVN_VER_MAJOR, svn.core.SVN_VER_MINOR
251 version = svn.core.SVN_VER_MAJOR, svn.core.SVN_VER_MINOR
252 if version < (1, 4):
252 if version < (1, 4):
253 return False
253 return False
254 return True
254 return True
255 except ImportError:
255 except ImportError:
256 return False
256 return False
257
257
258 @check("p4", "Perforce server and client")
258 @check("p4", "Perforce server and client")
259 def has_p4():
259 def has_p4():
260 return (matchoutput('p4 -V', r'Rev\. P4/') and
260 return (matchoutput('p4 -V', r'Rev\. P4/') and
261 matchoutput('p4d -V', r'Rev\. P4D/'))
261 matchoutput('p4d -V', r'Rev\. P4D/'))
262
262
263 @check("symlink", "symbolic links")
263 @check("symlink", "symbolic links")
264 def has_symlink():
264 def has_symlink():
265 if getattr(os, "symlink", None) is None:
265 if getattr(os, "symlink", None) is None:
266 return False
266 return False
267 name = tempfile.mktemp(dir='.', prefix=tempprefix)
267 name = tempfile.mktemp(dir='.', prefix=tempprefix)
268 try:
268 try:
269 os.symlink(".", name)
269 os.symlink(".", name)
270 os.unlink(name)
270 os.unlink(name)
271 return True
271 return True
272 except (OSError, AttributeError):
272 except (OSError, AttributeError):
273 return False
273 return False
274
274
275 @check("hardlink", "hardlinks")
275 @check("hardlink", "hardlinks")
276 def has_hardlink():
276 def has_hardlink():
277 from mercurial import util
277 from mercurial import util
278 fh, fn = tempfile.mkstemp(dir='.', prefix=tempprefix)
278 fh, fn = tempfile.mkstemp(dir='.', prefix=tempprefix)
279 os.close(fh)
279 os.close(fh)
280 name = tempfile.mktemp(dir='.', prefix=tempprefix)
280 name = tempfile.mktemp(dir='.', prefix=tempprefix)
281 try:
281 try:
282 util.oslink(fn, name)
282 util.oslink(fn, name)
283 os.unlink(name)
283 os.unlink(name)
284 return True
284 return True
285 except OSError:
285 except OSError:
286 return False
286 return False
287 finally:
287 finally:
288 os.unlink(fn)
288 os.unlink(fn)
289
289
290 @check("tla", "GNU Arch tla client")
290 @check("tla", "GNU Arch tla client")
291 def has_tla():
291 def has_tla():
292 return matchoutput('tla --version 2>&1', r'The GNU Arch Revision')
292 return matchoutput('tla --version 2>&1', r'The GNU Arch Revision')
293
293
294 @check("gpg", "gpg client")
294 @check("gpg", "gpg client")
295 def has_gpg():
295 def has_gpg():
296 return matchoutput('gpg --version 2>&1', r'GnuPG')
296 return matchoutput('gpg --version 2>&1', r'GnuPG')
297
297
298 @check("unix-permissions", "unix-style permissions")
298 @check("unix-permissions", "unix-style permissions")
299 def has_unix_permissions():
299 def has_unix_permissions():
300 d = tempfile.mkdtemp(dir='.', prefix=tempprefix)
300 d = tempfile.mkdtemp(dir='.', prefix=tempprefix)
301 try:
301 try:
302 fname = os.path.join(d, 'foo')
302 fname = os.path.join(d, 'foo')
303 for umask in (0o77, 0o07, 0o22):
303 for umask in (0o77, 0o07, 0o22):
304 os.umask(umask)
304 os.umask(umask)
305 f = open(fname, 'w')
305 f = open(fname, 'w')
306 f.close()
306 f.close()
307 mode = os.stat(fname).st_mode
307 mode = os.stat(fname).st_mode
308 os.unlink(fname)
308 os.unlink(fname)
309 if mode & 0o777 != ~umask & 0o666:
309 if mode & 0o777 != ~umask & 0o666:
310 return False
310 return False
311 return True
311 return True
312 finally:
312 finally:
313 os.rmdir(d)
313 os.rmdir(d)
314
314
315 @check("unix-socket", "AF_UNIX socket family")
315 @check("unix-socket", "AF_UNIX socket family")
316 def has_unix_socket():
316 def has_unix_socket():
317 return getattr(socket, 'AF_UNIX', None) is not None
317 return getattr(socket, 'AF_UNIX', None) is not None
318
318
319 @check("root", "root permissions")
319 @check("root", "root permissions")
320 def has_root():
320 def has_root():
321 return getattr(os, 'geteuid', None) and os.geteuid() == 0
321 return getattr(os, 'geteuid', None) and os.geteuid() == 0
322
322
323 @check("pyflakes", "Pyflakes python linter")
323 @check("pyflakes", "Pyflakes python linter")
324 def has_pyflakes():
324 def has_pyflakes():
325 return matchoutput("sh -c \"echo 'import re' 2>&1 | pyflakes\"",
325 return matchoutput("sh -c \"echo 'import re' 2>&1 | pyflakes\"",
326 r"<stdin>:1: 're' imported but unused",
326 r"<stdin>:1: 're' imported but unused",
327 True)
327 True)
328
328
329 @check("pygments", "Pygments source highlighting library")
329 @check("pygments", "Pygments source highlighting library")
330 def has_pygments():
330 def has_pygments():
331 try:
331 try:
332 import pygments
332 import pygments
333 pygments.highlight # silence unused import warning
333 pygments.highlight # silence unused import warning
334 return True
334 return True
335 except ImportError:
335 except ImportError:
336 return False
336 return False
337
337
338 @check("json", "some json module available")
338 @check("json", "some json module available")
339 def has_json():
339 def has_json():
340 try:
340 try:
341 import json
341 import json
342 json.dumps
342 json.dumps
343 return True
343 return True
344 except ImportError:
344 except ImportError:
345 try:
345 try:
346 import simplejson as json
346 import simplejson as json
347 json.dumps
347 json.dumps
348 return True
348 return True
349 except ImportError:
349 except ImportError:
350 pass
350 pass
351 return False
351 return False
352
352
353 @check("outer-repo", "outer repo")
353 @check("outer-repo", "outer repo")
354 def has_outer_repo():
354 def has_outer_repo():
355 # failing for other reasons than 'no repo' imply that there is a repo
355 # failing for other reasons than 'no repo' imply that there is a repo
356 return not matchoutput('hg root 2>&1',
356 return not matchoutput('hg root 2>&1',
357 r'abort: no repository found', True)
357 r'abort: no repository found', True)
358
358
359 @check("ssl", ("(python >= 2.6 ssl module and python OpenSSL) "
359 @check("ssl", ("(python >= 2.6 ssl module and python OpenSSL) "
360 "OR python >= 2.7.9 ssl"))
360 "OR python >= 2.7.9 ssl"))
361 def has_ssl():
361 def has_ssl():
362 try:
362 try:
363 import ssl
363 import ssl
364 if getattr(ssl, 'create_default_context', False):
364 if getattr(ssl, 'create_default_context', False):
365 return True
365 return True
366 import OpenSSL
366 import OpenSSL
367 OpenSSL.SSL.Context
367 OpenSSL.SSL.Context
368 return True
368 return True
369 except ImportError:
369 except ImportError:
370 return False
370 return False
371
371
372 @check("sslcontext", "python >= 2.7.9 ssl")
372 @check("sslcontext", "python >= 2.7.9 ssl")
373 def has_sslcontext():
373 def has_sslcontext():
374 try:
374 try:
375 import ssl
375 import ssl
376 ssl.SSLContext
376 ssl.SSLContext
377 return True
377 return True
378 except (ImportError, AttributeError):
378 except (ImportError, AttributeError):
379 return False
379 return False
380
380
381 @check("defaultcacerts", "can verify SSL certs by system's CA certs store")
381 @check("defaultcacerts", "can verify SSL certs by system's CA certs store")
382 def has_defaultcacerts():
382 def has_defaultcacerts():
383 from mercurial import sslutil
383 from mercurial import sslutil
384 return sslutil._defaultcacerts() != '!'
384 return sslutil._defaultcacerts() != '!'
385
385
386 @check("windows", "Windows")
386 @check("windows", "Windows")
387 def has_windows():
387 def has_windows():
388 return os.name == 'nt'
388 return os.name == 'nt'
389
389
390 @check("system-sh", "system() uses sh")
390 @check("system-sh", "system() uses sh")
391 def has_system_sh():
391 def has_system_sh():
392 return os.name != 'nt'
392 return os.name != 'nt'
393
393
394 @check("serve", "platform and python can manage 'hg serve -d'")
394 @check("serve", "platform and python can manage 'hg serve -d'")
395 def has_serve():
395 def has_serve():
396 return os.name != 'nt' # gross approximation
396 return os.name != 'nt' # gross approximation
397
397
398 @check("test-repo", "running tests from repository")
398 @check("test-repo", "running tests from repository")
399 def has_test_repo():
399 def has_test_repo():
400 t = os.environ["TESTDIR"]
400 t = os.environ["TESTDIR"]
401 return os.path.isdir(os.path.join(t, "..", ".hg"))
401 return os.path.isdir(os.path.join(t, "..", ".hg"))
402
402
403 @check("tic", "terminfo compiler and curses module")
403 @check("tic", "terminfo compiler and curses module")
404 def has_tic():
404 def has_tic():
405 try:
405 try:
406 import curses
406 import curses
407 curses.COLOR_BLUE
407 curses.COLOR_BLUE
408 return matchoutput('test -x "`which tic`"', '')
408 return matchoutput('test -x "`which tic`"', '')
409 except ImportError:
409 except ImportError:
410 return False
410 return False
411
411
412 @check("msys", "Windows with MSYS")
412 @check("msys", "Windows with MSYS")
413 def has_msys():
413 def has_msys():
414 return os.getenv('MSYSTEM')
414 return os.getenv('MSYSTEM')
415
415
416 @check("aix", "AIX")
416 @check("aix", "AIX")
417 def has_aix():
417 def has_aix():
418 return sys.platform.startswith("aix")
418 return sys.platform.startswith("aix")
419
419
420 @check("osx", "OS X")
420 @check("osx", "OS X")
421 def has_osx():
421 def has_osx():
422 return sys.platform == 'darwin'
422 return sys.platform == 'darwin'
423
423
424 @check("docker", "docker support")
424 @check("docker", "docker support")
425 def has_docker():
425 def has_docker():
426 pat = r'A self-sufficient runtime for linux containers\.'
426 pat = r'A self-sufficient runtime for linux containers\.'
427 if matchoutput('docker --help', pat):
427 if matchoutput('docker --help', pat):
428 if 'linux' not in sys.platform:
428 if 'linux' not in sys.platform:
429 # TODO: in theory we should be able to test docker-based
429 # TODO: in theory we should be able to test docker-based
430 # package creation on non-linux using boot2docker, but in
430 # package creation on non-linux using boot2docker, but in
431 # practice that requires extra coordination to make sure
431 # practice that requires extra coordination to make sure
432 # $TESTTEMP is going to be visible at the same path to the
432 # $TESTTEMP is going to be visible at the same path to the
433 # boot2docker VM. If we figure out how to verify that, we
433 # boot2docker VM. If we figure out how to verify that, we
434 # can use the following instead of just saying False:
434 # can use the following instead of just saying False:
435 # return 'DOCKER_HOST' in os.environ
435 # return 'DOCKER_HOST' in os.environ
436 return False
436 return False
437
437
438 return True
438 return True
439 return False
439 return False
440
440
441 @check("debhelper", "debian packaging tools")
441 @check("debhelper", "debian packaging tools")
442 def has_debhelper():
442 def has_debhelper():
443 dpkg = matchoutput('dpkg --version',
443 dpkg = matchoutput('dpkg --version',
444 "Debian `dpkg' package management program")
444 "Debian `dpkg' package management program")
445 dh = matchoutput('dh --help',
445 dh = matchoutput('dh --help',
446 'dh is a part of debhelper.', ignorestatus=True)
446 'dh is a part of debhelper.', ignorestatus=True)
447 dh_py2 = matchoutput('dh_python2 --help',
447 dh_py2 = matchoutput('dh_python2 --help',
448 'other supported Python versions')
448 'other supported Python versions')
449 return dpkg and dh and dh_py2
449 return dpkg and dh and dh_py2
450
450
451 @check("absimport", "absolute_import in __future__")
451 @check("absimport", "absolute_import in __future__")
452 def has_absimport():
452 def has_absimport():
453 import __future__
453 import __future__
454 from mercurial import util
454 from mercurial import util
455 return util.safehasattr(__future__, "absolute_import")
455 return util.safehasattr(__future__, "absolute_import")
456
456
457 @check("py3k", "running with Python 3.x")
457 @check("py3k", "running with Python 3.x")
458 def has_py3k():
458 def has_py3k():
459 return 3 == sys.version_info[0]
459 return 3 == sys.version_info[0]
460
460
461 @check("pure", "running with pure Python code")
461 @check("pure", "running with pure Python code")
462 def has_pure():
462 def has_pure():
463 return os.environ.get("HGTEST_RUN_TESTS_PURE") == "--pure"
463 return any([
464 os.environ.get("HGMODULEPOLICY") == "py",
465 os.environ.get("HGTEST_RUN_TESTS_PURE") == "--pure",
466 ])
464
467
465 @check("slow", "allow slow tests")
468 @check("slow", "allow slow tests")
466 def has_slow():
469 def has_slow():
467 return os.environ.get('HGTEST_SLOW') == 'slow'
470 return os.environ.get('HGTEST_SLOW') == 'slow'
468
471
469 @check("hypothesis", "is Hypothesis installed")
472 @check("hypothesis", "is Hypothesis installed")
470 def has_hypothesis():
473 def has_hypothesis():
471 try:
474 try:
472 import hypothesis
475 import hypothesis
473 hypothesis.given
476 hypothesis.given
474 return True
477 return True
475 except ImportError:
478 except ImportError:
476 return False
479 return False
General Comments 0
You need to be logged in to leave comments. Login now