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