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