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