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