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