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