##// END OF EJS Templates
tests: virtualenv is only used on py2, rename and conditionalize...
Kyle Lippincott -
r45775:357d8415 default
parent child Browse files
Show More
@@ -1,1074 +1,1077
1 1 from __future__ import absolute_import, print_function
2 2
3 3 import distutils.version
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 try:
20 20 import msvcrt
21 21
22 22 msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
23 23 msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY)
24 24 except ImportError:
25 25 pass
26 26
27 27 stdout = getattr(sys.stdout, 'buffer', sys.stdout)
28 28 stderr = getattr(sys.stderr, 'buffer', sys.stderr)
29 29
30 30 if sys.version_info[0] >= 3:
31 31
32 32 def _sys2bytes(p):
33 33 if p is None:
34 34 return p
35 35 return p.encode('utf-8')
36 36
37 37 def _bytes2sys(p):
38 38 if p is None:
39 39 return p
40 40 return p.decode('utf-8')
41 41
42 42
43 43 else:
44 44
45 45 def _sys2bytes(p):
46 46 return p
47 47
48 48 _bytes2sys = _sys2bytes
49 49
50 50
51 51 def check(name, desc):
52 52 """Registers a check function for a feature."""
53 53
54 54 def decorator(func):
55 55 checks[name] = (func, desc)
56 56 return func
57 57
58 58 return decorator
59 59
60 60
61 61 def checkvers(name, desc, vers):
62 62 """Registers a check function for each of a series of versions.
63 63
64 64 vers can be a list or an iterator.
65 65
66 66 Produces a series of feature checks that have the form <name><vers> without
67 67 any punctuation (even if there's punctuation in 'vers'; i.e. this produces
68 68 'py38', not 'py3.8' or 'py-38')."""
69 69
70 70 def decorator(func):
71 71 def funcv(v):
72 72 def f():
73 73 return func(v)
74 74
75 75 return f
76 76
77 77 for v in vers:
78 78 v = str(v)
79 79 f = funcv(v)
80 80 checks['%s%s' % (name, v.replace('.', ''))] = (f, desc % v)
81 81 return func
82 82
83 83 return decorator
84 84
85 85
86 86 def checkfeatures(features):
87 87 result = {
88 88 'error': [],
89 89 'missing': [],
90 90 'skipped': [],
91 91 }
92 92
93 93 for feature in features:
94 94 negate = feature.startswith('no-')
95 95 if negate:
96 96 feature = feature[3:]
97 97
98 98 if feature not in checks:
99 99 result['missing'].append(feature)
100 100 continue
101 101
102 102 check, desc = checks[feature]
103 103 try:
104 104 available = check()
105 105 except Exception:
106 106 result['error'].append('hghave check failed: %s' % feature)
107 107 continue
108 108
109 109 if not negate and not available:
110 110 result['skipped'].append('missing feature: %s' % desc)
111 111 elif negate and available:
112 112 result['skipped'].append('system supports %s' % desc)
113 113
114 114 return result
115 115
116 116
117 117 def require(features):
118 118 """Require that features are available, exiting if not."""
119 119 result = checkfeatures(features)
120 120
121 121 for missing in result['missing']:
122 122 stderr.write(
123 123 ('skipped: unknown feature: %s\n' % missing).encode('utf-8')
124 124 )
125 125 for msg in result['skipped']:
126 126 stderr.write(('skipped: %s\n' % msg).encode('utf-8'))
127 127 for msg in result['error']:
128 128 stderr.write(('%s\n' % msg).encode('utf-8'))
129 129
130 130 if result['missing']:
131 131 sys.exit(2)
132 132
133 133 if result['skipped'] or result['error']:
134 134 sys.exit(1)
135 135
136 136
137 137 def matchoutput(cmd, regexp, ignorestatus=False):
138 138 """Return the match object if cmd executes successfully and its output
139 139 is matched by the supplied regular expression.
140 140 """
141 141 r = re.compile(regexp)
142 142 p = subprocess.Popen(
143 143 cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
144 144 )
145 145 s = p.communicate()[0]
146 146 ret = p.returncode
147 147 return (ignorestatus or not ret) and r.search(s)
148 148
149 149
150 150 @check("baz", "GNU Arch baz client")
151 151 def has_baz():
152 152 return matchoutput('baz --version 2>&1', br'baz Bazaar version')
153 153
154 154
155 155 @check("bzr", "Canonical's Bazaar client")
156 156 def has_bzr():
157 157 try:
158 158 import bzrlib
159 159 import bzrlib.bzrdir
160 160 import bzrlib.errors
161 161 import bzrlib.revision
162 162 import bzrlib.revisionspec
163 163
164 164 bzrlib.revisionspec.RevisionSpec
165 165 return bzrlib.__doc__ is not None
166 166 except (AttributeError, ImportError):
167 167 return False
168 168
169 169
170 170 @checkvers("bzr", "Canonical's Bazaar client >= %s", (1.14,))
171 171 def has_bzr_range(v):
172 172 major, minor = v.split('rc')[0].split('.')[0:2]
173 173 try:
174 174 import bzrlib
175 175
176 176 return bzrlib.__doc__ is not None and bzrlib.version_info[:2] >= (
177 177 int(major),
178 178 int(minor),
179 179 )
180 180 except ImportError:
181 181 return False
182 182
183 183
184 184 @check("chg", "running with chg")
185 185 def has_chg():
186 186 return 'CHGHG' in os.environ
187 187
188 188
189 189 @check("cvs", "cvs client/server")
190 190 def has_cvs():
191 191 re = br'Concurrent Versions System.*?server'
192 192 return matchoutput('cvs --version 2>&1', re) and not has_msys()
193 193
194 194
195 195 @check("cvs112", "cvs client/server 1.12.* (not cvsnt)")
196 196 def has_cvs112():
197 197 re = br'Concurrent Versions System \(CVS\) 1.12.*?server'
198 198 return matchoutput('cvs --version 2>&1', re) and not has_msys()
199 199
200 200
201 201 @check("cvsnt", "cvsnt client/server")
202 202 def has_cvsnt():
203 203 re = br'Concurrent Versions System \(CVSNT\) (\d+).(\d+).*\(client/server\)'
204 204 return matchoutput('cvsnt --version 2>&1', re)
205 205
206 206
207 207 @check("darcs", "darcs client")
208 208 def has_darcs():
209 209 return matchoutput('darcs --version', br'\b2\.([2-9]|\d{2})', True)
210 210
211 211
212 212 @check("mtn", "monotone client (>= 1.0)")
213 213 def has_mtn():
214 214 return matchoutput('mtn --version', br'monotone', True) and not matchoutput(
215 215 'mtn --version', br'monotone 0\.', True
216 216 )
217 217
218 218
219 219 @check("eol-in-paths", "end-of-lines in paths")
220 220 def has_eol_in_paths():
221 221 try:
222 222 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix, suffix='\n\r')
223 223 os.close(fd)
224 224 os.remove(path)
225 225 return True
226 226 except (IOError, OSError):
227 227 return False
228 228
229 229
230 230 @check("execbit", "executable bit")
231 231 def has_executablebit():
232 232 try:
233 233 EXECFLAGS = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
234 234 fh, fn = tempfile.mkstemp(dir='.', prefix=tempprefix)
235 235 try:
236 236 os.close(fh)
237 237 m = os.stat(fn).st_mode & 0o777
238 238 new_file_has_exec = m & EXECFLAGS
239 239 os.chmod(fn, m ^ EXECFLAGS)
240 240 exec_flags_cannot_flip = (os.stat(fn).st_mode & 0o777) == m
241 241 finally:
242 242 os.unlink(fn)
243 243 except (IOError, OSError):
244 244 # we don't care, the user probably won't be able to commit anyway
245 245 return False
246 246 return not (new_file_has_exec or exec_flags_cannot_flip)
247 247
248 248
249 249 @check("icasefs", "case insensitive file system")
250 250 def has_icasefs():
251 251 # Stolen from mercurial.util
252 252 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix)
253 253 os.close(fd)
254 254 try:
255 255 s1 = os.stat(path)
256 256 d, b = os.path.split(path)
257 257 p2 = os.path.join(d, b.upper())
258 258 if path == p2:
259 259 p2 = os.path.join(d, b.lower())
260 260 try:
261 261 s2 = os.stat(p2)
262 262 return s2 == s1
263 263 except OSError:
264 264 return False
265 265 finally:
266 266 os.remove(path)
267 267
268 268
269 269 @check("fifo", "named pipes")
270 270 def has_fifo():
271 271 if getattr(os, "mkfifo", None) is None:
272 272 return False
273 273 name = tempfile.mktemp(dir='.', prefix=tempprefix)
274 274 try:
275 275 os.mkfifo(name)
276 276 os.unlink(name)
277 277 return True
278 278 except OSError:
279 279 return False
280 280
281 281
282 282 @check("killdaemons", 'killdaemons.py support')
283 283 def has_killdaemons():
284 284 return True
285 285
286 286
287 287 @check("cacheable", "cacheable filesystem")
288 288 def has_cacheable_fs():
289 289 from mercurial import util
290 290
291 291 fd, path = tempfile.mkstemp(dir='.', prefix=tempprefix)
292 292 os.close(fd)
293 293 try:
294 294 return util.cachestat(path).cacheable()
295 295 finally:
296 296 os.remove(path)
297 297
298 298
299 299 @check("lsprof", "python lsprof module")
300 300 def has_lsprof():
301 301 try:
302 302 import _lsprof
303 303
304 304 _lsprof.Profiler # silence unused import warning
305 305 return True
306 306 except ImportError:
307 307 return False
308 308
309 309
310 310 def _gethgversion():
311 311 m = matchoutput('hg --version --quiet 2>&1', br'(\d+)\.(\d+)')
312 312 if not m:
313 313 return (0, 0)
314 314 return (int(m.group(1)), int(m.group(2)))
315 315
316 316
317 317 _hgversion = None
318 318
319 319
320 320 def gethgversion():
321 321 global _hgversion
322 322 if _hgversion is None:
323 323 _hgversion = _gethgversion()
324 324 return _hgversion
325 325
326 326
327 327 @checkvers(
328 328 "hg", "Mercurial >= %s", list([(1.0 * x) / 10 for x in range(9, 99)])
329 329 )
330 330 def has_hg_range(v):
331 331 major, minor = v.split('.')[0:2]
332 332 return gethgversion() >= (int(major), int(minor))
333 333
334 334
335 335 @check("rust", "Using the Rust extensions")
336 336 def has_rust():
337 337 """Check is the mercurial currently running is using some rust code"""
338 338 cmd = 'hg debuginstall --quiet 2>&1'
339 339 match = br'checking module policy \(([^)]+)\)'
340 340 policy = matchoutput(cmd, match)
341 341 if not policy:
342 342 return False
343 343 return b'rust' in policy.group(1)
344 344
345 345
346 346 @check("hg08", "Mercurial >= 0.8")
347 347 def has_hg08():
348 348 if checks["hg09"][0]():
349 349 return True
350 350 return matchoutput('hg help annotate 2>&1', '--date')
351 351
352 352
353 353 @check("hg07", "Mercurial >= 0.7")
354 354 def has_hg07():
355 355 if checks["hg08"][0]():
356 356 return True
357 357 return matchoutput('hg --version --quiet 2>&1', 'Mercurial Distributed SCM')
358 358
359 359
360 360 @check("hg06", "Mercurial >= 0.6")
361 361 def has_hg06():
362 362 if checks["hg07"][0]():
363 363 return True
364 364 return matchoutput('hg --version --quiet 2>&1', 'Mercurial version')
365 365
366 366
367 367 @check("gettext", "GNU Gettext (msgfmt)")
368 368 def has_gettext():
369 369 return matchoutput('msgfmt --version', br'GNU gettext-tools')
370 370
371 371
372 372 @check("git", "git command line client")
373 373 def has_git():
374 374 return matchoutput('git --version 2>&1', br'^git version')
375 375
376 376
377 377 def getgitversion():
378 378 m = matchoutput('git --version 2>&1', br'git version (\d+)\.(\d+)')
379 379 if not m:
380 380 return (0, 0)
381 381 return (int(m.group(1)), int(m.group(2)))
382 382
383 383
384 384 @check("pygit2", "pygit2 Python library")
385 385 def has_git():
386 386 try:
387 387 import pygit2
388 388
389 389 pygit2.Oid # silence unused import
390 390 return True
391 391 except ImportError:
392 392 return False
393 393
394 394
395 395 # https://github.com/git-lfs/lfs-test-server
396 396 @check("lfs-test-server", "git-lfs test server")
397 397 def has_lfsserver():
398 398 exe = 'lfs-test-server'
399 399 if has_windows():
400 400 exe = 'lfs-test-server.exe'
401 401 return any(
402 402 os.access(os.path.join(path, exe), os.X_OK)
403 403 for path in os.environ["PATH"].split(os.pathsep)
404 404 )
405 405
406 406
407 407 @checkvers("git", "git client (with ext::sh support) version >= %s", (1.9,))
408 408 def has_git_range(v):
409 409 major, minor = v.split('.')[0:2]
410 410 return getgitversion() >= (int(major), int(minor))
411 411
412 412
413 413 @check("docutils", "Docutils text processing library")
414 414 def has_docutils():
415 415 try:
416 416 import docutils.core
417 417
418 418 docutils.core.publish_cmdline # silence unused import
419 419 return True
420 420 except ImportError:
421 421 return False
422 422
423 423
424 424 def getsvnversion():
425 425 m = matchoutput('svn --version --quiet 2>&1', br'^(\d+)\.(\d+)')
426 426 if not m:
427 427 return (0, 0)
428 428 return (int(m.group(1)), int(m.group(2)))
429 429
430 430
431 431 @checkvers("svn", "subversion client and admin tools >= %s", (1.3, 1.5))
432 432 def has_svn_range(v):
433 433 major, minor = v.split('.')[0:2]
434 434 return getsvnversion() >= (int(major), int(minor))
435 435
436 436
437 437 @check("svn", "subversion client and admin tools")
438 438 def has_svn():
439 439 return matchoutput('svn --version 2>&1', br'^svn, version') and matchoutput(
440 440 'svnadmin --version 2>&1', br'^svnadmin, version'
441 441 )
442 442
443 443
444 444 @check("svn-bindings", "subversion python bindings")
445 445 def has_svn_bindings():
446 446 try:
447 447 import svn.core
448 448
449 449 version = svn.core.SVN_VER_MAJOR, svn.core.SVN_VER_MINOR
450 450 if version < (1, 4):
451 451 return False
452 452 return True
453 453 except ImportError:
454 454 return False
455 455
456 456
457 457 @check("p4", "Perforce server and client")
458 458 def has_p4():
459 459 return matchoutput('p4 -V', br'Rev\. P4/') and matchoutput(
460 460 'p4d -V', br'Rev\. P4D/'
461 461 )
462 462
463 463
464 464 @check("symlink", "symbolic links")
465 465 def has_symlink():
466 466 # mercurial.windows.checklink() is a hard 'no' at the moment
467 467 if os.name == 'nt' or getattr(os, "symlink", None) is None:
468 468 return False
469 469 name = tempfile.mktemp(dir='.', prefix=tempprefix)
470 470 try:
471 471 os.symlink(".", name)
472 472 os.unlink(name)
473 473 return True
474 474 except (OSError, AttributeError):
475 475 return False
476 476
477 477
478 478 @check("hardlink", "hardlinks")
479 479 def has_hardlink():
480 480 from mercurial import util
481 481
482 482 fh, fn = tempfile.mkstemp(dir='.', prefix=tempprefix)
483 483 os.close(fh)
484 484 name = tempfile.mktemp(dir='.', prefix=tempprefix)
485 485 try:
486 486 util.oslink(_sys2bytes(fn), _sys2bytes(name))
487 487 os.unlink(name)
488 488 return True
489 489 except OSError:
490 490 return False
491 491 finally:
492 492 os.unlink(fn)
493 493
494 494
495 495 @check("hardlink-whitelisted", "hardlinks on whitelisted filesystems")
496 496 def has_hardlink_whitelisted():
497 497 from mercurial import util
498 498
499 499 try:
500 500 fstype = util.getfstype(b'.')
501 501 except OSError:
502 502 return False
503 503 return fstype in util._hardlinkfswhitelist
504 504
505 505
506 506 @check("rmcwd", "can remove current working directory")
507 507 def has_rmcwd():
508 508 ocwd = os.getcwd()
509 509 temp = tempfile.mkdtemp(dir='.', prefix=tempprefix)
510 510 try:
511 511 os.chdir(temp)
512 512 # On Linux, 'rmdir .' isn't allowed, but the other names are okay.
513 513 # On Solaris and Windows, the cwd can't be removed by any names.
514 514 os.rmdir(os.getcwd())
515 515 return True
516 516 except OSError:
517 517 return False
518 518 finally:
519 519 os.chdir(ocwd)
520 520 # clean up temp dir on platforms where cwd can't be removed
521 521 try:
522 522 os.rmdir(temp)
523 523 except OSError:
524 524 pass
525 525
526 526
527 527 @check("tla", "GNU Arch tla client")
528 528 def has_tla():
529 529 return matchoutput('tla --version 2>&1', br'The GNU Arch Revision')
530 530
531 531
532 532 @check("gpg", "gpg client")
533 533 def has_gpg():
534 534 return matchoutput('gpg --version 2>&1', br'GnuPG')
535 535
536 536
537 537 @check("gpg2", "gpg client v2")
538 538 def has_gpg2():
539 539 return matchoutput('gpg --version 2>&1', br'GnuPG[^0-9]+2\.')
540 540
541 541
542 542 @check("gpg21", "gpg client v2.1+")
543 543 def has_gpg21():
544 544 return matchoutput('gpg --version 2>&1', br'GnuPG[^0-9]+2\.(?!0)')
545 545
546 546
547 547 @check("unix-permissions", "unix-style permissions")
548 548 def has_unix_permissions():
549 549 d = tempfile.mkdtemp(dir='.', prefix=tempprefix)
550 550 try:
551 551 fname = os.path.join(d, 'foo')
552 552 for umask in (0o77, 0o07, 0o22):
553 553 os.umask(umask)
554 554 f = open(fname, 'w')
555 555 f.close()
556 556 mode = os.stat(fname).st_mode
557 557 os.unlink(fname)
558 558 if mode & 0o777 != ~umask & 0o666:
559 559 return False
560 560 return True
561 561 finally:
562 562 os.rmdir(d)
563 563
564 564
565 565 @check("unix-socket", "AF_UNIX socket family")
566 566 def has_unix_socket():
567 567 return getattr(socket, 'AF_UNIX', None) is not None
568 568
569 569
570 570 @check("root", "root permissions")
571 571 def has_root():
572 572 return getattr(os, 'geteuid', None) and os.geteuid() == 0
573 573
574 574
575 575 @check("pyflakes", "Pyflakes python linter")
576 576 def has_pyflakes():
577 577 try:
578 578 import pyflakes
579 579
580 580 pyflakes.__version__
581 581 except ImportError:
582 582 return False
583 583 else:
584 584 return True
585 585
586 586
587 587 @check("pylint", "Pylint python linter")
588 588 def has_pylint():
589 589 return matchoutput("pylint --help", br"Usage: pylint", True)
590 590
591 591
592 592 @check("clang-format", "clang-format C code formatter")
593 593 def has_clang_format():
594 594 m = matchoutput('clang-format --version', br'clang-format version (\d+)')
595 595 # style changed somewhere between 4.x and 6.x
596 596 return m and int(m.group(1)) >= 6
597 597
598 598
599 599 @check("jshint", "JSHint static code analysis tool")
600 600 def has_jshint():
601 601 return matchoutput("jshint --version 2>&1", br"jshint v")
602 602
603 603
604 604 @check("pygments", "Pygments source highlighting library")
605 605 def has_pygments():
606 606 try:
607 607 import pygments
608 608
609 609 pygments.highlight # silence unused import warning
610 610 return True
611 611 except ImportError:
612 612 return False
613 613
614 614
615 615 @check("pygments25", "Pygments version >= 2.5")
616 616 def pygments25():
617 617 try:
618 618 import pygments
619 619
620 620 v = pygments.__version__
621 621 except ImportError:
622 622 return False
623 623
624 624 parts = v.split(".")
625 625 major = int(parts[0])
626 626 minor = int(parts[1])
627 627
628 628 return (major, minor) >= (2, 5)
629 629
630 630
631 631 @check("outer-repo", "outer repo")
632 632 def has_outer_repo():
633 633 # failing for other reasons than 'no repo' imply that there is a repo
634 634 return not matchoutput('hg root 2>&1', br'abort: no repository found', True)
635 635
636 636
637 637 @check("ssl", "ssl module available")
638 638 def has_ssl():
639 639 try:
640 640 import ssl
641 641
642 642 ssl.CERT_NONE
643 643 return True
644 644 except ImportError:
645 645 return False
646 646
647 647
648 648 @check("defaultcacertsloaded", "detected presence of loaded system CA certs")
649 649 def has_defaultcacertsloaded():
650 650 import ssl
651 651 from mercurial import sslutil, ui as uimod
652 652
653 653 ui = uimod.ui.load()
654 654 cafile = sslutil._defaultcacerts(ui)
655 655 ctx = ssl.create_default_context()
656 656 if cafile:
657 657 ctx.load_verify_locations(cafile=cafile)
658 658 else:
659 659 ctx.load_default_certs()
660 660
661 661 return len(ctx.get_ca_certs()) > 0
662 662
663 663
664 664 @check("tls1.2", "TLS 1.2 protocol support")
665 665 def has_tls1_2():
666 666 from mercurial import sslutil
667 667
668 668 return b'tls1.2' in sslutil.supportedprotocols
669 669
670 670
671 671 @check("windows", "Windows")
672 672 def has_windows():
673 673 return os.name == 'nt'
674 674
675 675
676 676 @check("system-sh", "system() uses sh")
677 677 def has_system_sh():
678 678 return os.name != 'nt'
679 679
680 680
681 681 @check("serve", "platform and python can manage 'hg serve -d'")
682 682 def has_serve():
683 683 return True
684 684
685 685
686 686 @check("setprocname", "whether osutil.setprocname is available or not")
687 687 def has_setprocname():
688 688 try:
689 689 from mercurial.utils import procutil
690 690
691 691 procutil.setprocname
692 692 return True
693 693 except AttributeError:
694 694 return False
695 695
696 696
697 697 @check("test-repo", "running tests from repository")
698 698 def has_test_repo():
699 699 t = os.environ["TESTDIR"]
700 700 return os.path.isdir(os.path.join(t, "..", ".hg"))
701 701
702 702
703 703 @check("tic", "terminfo compiler and curses module")
704 704 def has_tic():
705 705 try:
706 706 import curses
707 707
708 708 curses.COLOR_BLUE
709 709 return matchoutput('test -x "`which tic`"', br'')
710 710 except (ImportError, AttributeError):
711 711 return False
712 712
713 713
714 714 @check("xz", "xz compression utility")
715 715 def has_xz():
716 716 # When Windows invokes a subprocess in shell mode, it uses `cmd.exe`, which
717 717 # only knows `where`, not `which`. So invoke MSYS shell explicitly.
718 718 return matchoutput("sh -c 'test -x \"`which xz`\"'", b'')
719 719
720 720
721 721 @check("msys", "Windows with MSYS")
722 722 def has_msys():
723 723 return os.getenv('MSYSTEM')
724 724
725 725
726 726 @check("aix", "AIX")
727 727 def has_aix():
728 728 return sys.platform.startswith("aix")
729 729
730 730
731 731 @check("osx", "OS X")
732 732 def has_osx():
733 733 return sys.platform == 'darwin'
734 734
735 735
736 736 @check("osxpackaging", "OS X packaging tools")
737 737 def has_osxpackaging():
738 738 try:
739 739 return (
740 740 matchoutput('pkgbuild', br'Usage: pkgbuild ', ignorestatus=1)
741 741 and matchoutput(
742 742 'productbuild', br'Usage: productbuild ', ignorestatus=1
743 743 )
744 744 and matchoutput('lsbom', br'Usage: lsbom', ignorestatus=1)
745 745 and matchoutput('xar --help', br'Usage: xar', ignorestatus=1)
746 746 )
747 747 except ImportError:
748 748 return False
749 749
750 750
751 751 @check('linuxormacos', 'Linux or MacOS')
752 752 def has_linuxormacos():
753 753 # This isn't a perfect test for MacOS. But it is sufficient for our needs.
754 754 return sys.platform.startswith(('linux', 'darwin'))
755 755
756 756
757 757 @check("docker", "docker support")
758 758 def has_docker():
759 759 pat = br'A self-sufficient runtime for'
760 760 if matchoutput('docker --help', pat):
761 761 if 'linux' not in sys.platform:
762 762 # TODO: in theory we should be able to test docker-based
763 763 # package creation on non-linux using boot2docker, but in
764 764 # practice that requires extra coordination to make sure
765 765 # $TESTTEMP is going to be visible at the same path to the
766 766 # boot2docker VM. If we figure out how to verify that, we
767 767 # can use the following instead of just saying False:
768 768 # return 'DOCKER_HOST' in os.environ
769 769 return False
770 770
771 771 return True
772 772 return False
773 773
774 774
775 775 @check("debhelper", "debian packaging tools")
776 776 def has_debhelper():
777 777 # Some versions of dpkg say `dpkg', some say 'dpkg' (` vs ' on the first
778 778 # quote), so just accept anything in that spot.
779 779 dpkg = matchoutput(
780 780 'dpkg --version', br"Debian .dpkg' package management program"
781 781 )
782 782 dh = matchoutput(
783 783 'dh --help', br'dh is a part of debhelper.', ignorestatus=True
784 784 )
785 785 dh_py2 = matchoutput(
786 786 'dh_python2 --help', br'other supported Python versions'
787 787 )
788 788 # debuild comes from the 'devscripts' package, though you might want
789 789 # the 'build-debs' package instead, which has a dependency on devscripts.
790 790 debuild = matchoutput(
791 791 'debuild --help', br'to run debian/rules with given parameter'
792 792 )
793 793 return dpkg and dh and dh_py2 and debuild
794 794
795 795
796 796 @check(
797 797 "debdeps", "debian build dependencies (run dpkg-checkbuilddeps in contrib/)"
798 798 )
799 799 def has_debdeps():
800 800 # just check exit status (ignoring output)
801 801 path = '%s/../contrib/packaging/debian/control' % os.environ['TESTDIR']
802 802 return matchoutput('dpkg-checkbuilddeps %s' % path, br'')
803 803
804 804
805 805 @check("demandimport", "demandimport enabled")
806 806 def has_demandimport():
807 807 # chg disables demandimport intentionally for performance wins.
808 808 return (not has_chg()) and os.environ.get('HGDEMANDIMPORT') != 'disable'
809 809
810 810
811 811 # Add "py27", "py35", ... as possible feature checks. Note that there's no
812 812 # punctuation here.
813 813 @checkvers("py", "Python >= %s", (2.7, 3.5, 3.6, 3.7, 3.8, 3.9))
814 814 def has_python_range(v):
815 815 major, minor = v.split('.')[0:2]
816 816 py_major, py_minor = sys.version_info.major, sys.version_info.minor
817 817
818 818 return (py_major, py_minor) >= (int(major), int(minor))
819 819
820 820
821 821 @check("py3", "running with Python 3.x")
822 822 def has_py3():
823 823 return 3 == sys.version_info[0]
824 824
825 825
826 826 @check("py3exe", "a Python 3.x interpreter is available")
827 827 def has_python3exe():
828 828 return matchoutput('python3 -V', br'^Python 3.(5|6|7|8|9)')
829 829
830 830
831 831 @check("pure", "running with pure Python code")
832 832 def has_pure():
833 833 return any(
834 834 [
835 835 os.environ.get("HGMODULEPOLICY") == "py",
836 836 os.environ.get("HGTEST_RUN_TESTS_PURE") == "--pure",
837 837 ]
838 838 )
839 839
840 840
841 841 @check("slow", "allow slow tests (use --allow-slow-tests)")
842 842 def has_slow():
843 843 return os.environ.get('HGTEST_SLOW') == 'slow'
844 844
845 845
846 846 @check("hypothesis", "Hypothesis automated test generation")
847 847 def has_hypothesis():
848 848 try:
849 849 import hypothesis
850 850
851 851 hypothesis.given
852 852 return True
853 853 except ImportError:
854 854 return False
855 855
856 856
857 857 @check("unziplinks", "unzip(1) understands and extracts symlinks")
858 858 def unzip_understands_symlinks():
859 859 return matchoutput('unzip --help', br'Info-ZIP')
860 860
861 861
862 862 @check("zstd", "zstd Python module available")
863 863 def has_zstd():
864 864 try:
865 865 import mercurial.zstd
866 866
867 867 mercurial.zstd.__version__
868 868 return True
869 869 except ImportError:
870 870 return False
871 871
872 872
873 873 @check("devfull", "/dev/full special file")
874 874 def has_dev_full():
875 875 return os.path.exists('/dev/full')
876 876
877 877
878 878 @check("ensurepip", "ensurepip module")
879 879 def has_ensurepip():
880 880 try:
881 881 import ensurepip
882 882
883 883 ensurepip.bootstrap
884 884 return True
885 885 except ImportError:
886 886 return False
887 887
888 888
889 @check("virtualenv", "Python virtualenv support")
890 def has_virtualenv():
889 @check("py2virtualenv", "Python2 virtualenv support")
890 def has_py2virtualenv():
891 if sys.version_info[0] != 2:
892 return False
893
891 894 try:
892 895 import virtualenv
893 896
894 897 virtualenv.ACTIVATE_SH
895 898 return True
896 899 except ImportError:
897 900 return False
898 901
899 902
900 903 @check("fsmonitor", "running tests with fsmonitor")
901 904 def has_fsmonitor():
902 905 return 'HGFSMONITOR_TESTS' in os.environ
903 906
904 907
905 908 @check("fuzzywuzzy", "Fuzzy string matching library")
906 909 def has_fuzzywuzzy():
907 910 try:
908 911 import fuzzywuzzy
909 912
910 913 fuzzywuzzy.__version__
911 914 return True
912 915 except ImportError:
913 916 return False
914 917
915 918
916 919 @check("clang-libfuzzer", "clang new enough to include libfuzzer")
917 920 def has_clang_libfuzzer():
918 921 mat = matchoutput('clang --version', br'clang version (\d)')
919 922 if mat:
920 923 # libfuzzer is new in clang 6
921 924 return int(mat.group(1)) > 5
922 925 return False
923 926
924 927
925 928 @check("clang-6.0", "clang 6.0 with version suffix (libfuzzer included)")
926 929 def has_clang60():
927 930 return matchoutput('clang-6.0 --version', br'clang version 6\.')
928 931
929 932
930 933 @check("xdiff", "xdiff algorithm")
931 934 def has_xdiff():
932 935 try:
933 936 from mercurial import policy
934 937
935 938 bdiff = policy.importmod('bdiff')
936 939 return bdiff.xdiffblocks(b'', b'') == [(0, 0, 0, 0)]
937 940 except (ImportError, AttributeError):
938 941 return False
939 942
940 943
941 944 @check('extraextensions', 'whether tests are running with extra extensions')
942 945 def has_extraextensions():
943 946 return 'HGTESTEXTRAEXTENSIONS' in os.environ
944 947
945 948
946 949 def getrepofeatures():
947 950 """Obtain set of repository features in use.
948 951
949 952 HGREPOFEATURES can be used to define or remove features. It contains
950 953 a space-delimited list of feature strings. Strings beginning with ``-``
951 954 mean to remove.
952 955 """
953 956 # Default list provided by core.
954 957 features = {
955 958 'bundlerepo',
956 959 'revlogstore',
957 960 'fncache',
958 961 }
959 962
960 963 # Features that imply other features.
961 964 implies = {
962 965 'simplestore': ['-revlogstore', '-bundlerepo', '-fncache'],
963 966 }
964 967
965 968 for override in os.environ.get('HGREPOFEATURES', '').split(' '):
966 969 if not override:
967 970 continue
968 971
969 972 if override.startswith('-'):
970 973 if override[1:] in features:
971 974 features.remove(override[1:])
972 975 else:
973 976 features.add(override)
974 977
975 978 for imply in implies.get(override, []):
976 979 if imply.startswith('-'):
977 980 if imply[1:] in features:
978 981 features.remove(imply[1:])
979 982 else:
980 983 features.add(imply)
981 984
982 985 return features
983 986
984 987
985 988 @check('reporevlogstore', 'repository using the default revlog store')
986 989 def has_reporevlogstore():
987 990 return 'revlogstore' in getrepofeatures()
988 991
989 992
990 993 @check('reposimplestore', 'repository using simple storage extension')
991 994 def has_reposimplestore():
992 995 return 'simplestore' in getrepofeatures()
993 996
994 997
995 998 @check('repobundlerepo', 'whether we can open bundle files as repos')
996 999 def has_repobundlerepo():
997 1000 return 'bundlerepo' in getrepofeatures()
998 1001
999 1002
1000 1003 @check('repofncache', 'repository has an fncache')
1001 1004 def has_repofncache():
1002 1005 return 'fncache' in getrepofeatures()
1003 1006
1004 1007
1005 1008 @check('sqlite', 'sqlite3 module is available')
1006 1009 def has_sqlite():
1007 1010 try:
1008 1011 import sqlite3
1009 1012
1010 1013 version = sqlite3.sqlite_version_info
1011 1014 except ImportError:
1012 1015 return False
1013 1016
1014 1017 if version < (3, 8, 3):
1015 1018 # WITH clause not supported
1016 1019 return False
1017 1020
1018 1021 return matchoutput('sqlite3 -version', br'^3\.\d+')
1019 1022
1020 1023
1021 1024 @check('vcr', 'vcr http mocking library')
1022 1025 def has_vcr():
1023 1026 try:
1024 1027 import vcr
1025 1028
1026 1029 vcr.VCR
1027 1030 return True
1028 1031 except (ImportError, AttributeError):
1029 1032 pass
1030 1033 return False
1031 1034
1032 1035
1033 1036 @check('emacs', 'GNU Emacs')
1034 1037 def has_emacs():
1035 1038 # Our emacs lisp uses `with-eval-after-load` which is new in emacs
1036 1039 # 24.4, so we allow emacs 24.4, 24.5, and 25+ (24.5 was the last
1037 1040 # 24 release)
1038 1041 return matchoutput('emacs --version', b'GNU Emacs 2(4.4|4.5|5|6|7|8|9)')
1039 1042
1040 1043
1041 1044 @check('black', 'the black formatter for python')
1042 1045 def has_black():
1043 1046 blackcmd = 'black --version'
1044 1047 version_regex = b'black, version ([0-9a-b.]+)'
1045 1048 version = matchoutput(blackcmd, version_regex)
1046 1049 sv = distutils.version.StrictVersion
1047 1050 return version and sv(_bytes2sys(version.group(1))) >= sv('19.10b0')
1048 1051
1049 1052
1050 1053 @check('pytype', 'the pytype type checker')
1051 1054 def has_pytype():
1052 1055 pytypecmd = 'pytype --version'
1053 1056 version = matchoutput(pytypecmd, b'[0-9a-b.]+')
1054 1057 sv = distutils.version.StrictVersion
1055 1058 return version and sv(_bytes2sys(version.group(0))) >= sv('2019.10.17')
1056 1059
1057 1060
1058 1061 @check("rustfmt", "rustfmt tool")
1059 1062 def has_rustfmt():
1060 1063 # We use Nightly's rustfmt due to current unstable config options.
1061 1064 return matchoutput(
1062 1065 '`rustup which --toolchain nightly rustfmt` --version', b'rustfmt'
1063 1066 )
1064 1067
1065 1068
1066 1069 @check("lzma", "python lzma module")
1067 1070 def has_lzma():
1068 1071 try:
1069 1072 import _lzma
1070 1073
1071 1074 _lzma.FORMAT_XZ
1072 1075 return True
1073 1076 except ImportError:
1074 1077 return False
@@ -1,255 +1,255
1 1 hg debuginstall
2 2 $ hg debuginstall
3 3 checking encoding (ascii)...
4 4 checking Python executable (*) (glob)
5 5 checking Python implementation (*) (glob)
6 6 checking Python version (2.*) (glob) (no-py3 !)
7 7 checking Python version (3.*) (glob) (py3 !)
8 8 checking Python lib (.*[Ll]ib.*)... (re)
9 9 checking Python security support (*) (glob)
10 10 TLS 1.2 not supported by Python install; network connections lack modern security (?)
11 11 SNI not supported by Python install; may have connectivity issues with some servers (?)
12 12 checking Rust extensions \((installed|missing)\) (re)
13 13 checking Mercurial version (*) (glob)
14 14 checking Mercurial custom build (*) (glob)
15 15 checking module policy (*) (glob)
16 16 checking installed modules (*mercurial)... (glob)
17 17 checking registered compression engines (*zlib*) (glob)
18 18 checking available compression engines (*zlib*) (glob)
19 19 checking available compression engines for wire protocol (*zlib*) (glob)
20 20 checking "re2" regexp engine \((available|missing)\) (re)
21 21 checking templates (*mercurial?templates)... (glob)
22 22 checking default template (*mercurial?templates?map-cmdline.default) (glob)
23 23 checking commit editor... (*) (glob)
24 24 checking username (test)
25 25 no problems detected
26 26
27 27 hg debuginstall JSON
28 28 $ hg debuginstall -Tjson | sed 's|\\\\|\\|g'
29 29 [
30 30 {
31 31 "compengines": ["bz2", "bz2truncated", "none", "zlib"*], (glob)
32 32 "compenginesavail": ["bz2", "bz2truncated", "none", "zlib"*], (glob)
33 33 "compenginesserver": [*"zlib"*], (glob)
34 34 "defaulttemplate": "*mercurial?templates?map-cmdline.default", (glob)
35 35 "defaulttemplateerror": null,
36 36 "defaulttemplatenotfound": "default",
37 37 "editor": "*", (glob)
38 38 "editornotfound": false,
39 39 "encoding": "ascii",
40 40 "encodingerror": null,
41 41 "extensionserror": null, (no-pure !)
42 42 "hgmodulepolicy": "*", (glob)
43 43 "hgmodules": "*mercurial", (glob)
44 44 "hgver": "*", (glob)
45 45 "hgverextra": "*", (glob)
46 46 "problems": 0,
47 47 "pythonexe": "*", (glob)
48 48 "pythonimplementation": "*", (glob)
49 49 "pythonlib": "*", (glob)
50 50 "pythonsecurity": [*], (glob)
51 51 "pythonver": "*.*.*", (glob)
52 52 "re2": (true|false), (re)
53 53 "templatedirs": "*mercurial?templates", (glob)
54 54 "username": "test",
55 55 "usernameerror": null,
56 56 "vinotfound": false
57 57 }
58 58 ]
59 59
60 60 hg debuginstall with no username
61 61 $ HGUSER= hg debuginstall
62 62 checking encoding (ascii)...
63 63 checking Python executable (*) (glob)
64 64 checking Python implementation (*) (glob)
65 65 checking Python version (2.*) (glob) (no-py3 !)
66 66 checking Python version (3.*) (glob) (py3 !)
67 67 checking Python lib (.*[Ll]ib.*)... (re)
68 68 checking Python security support (*) (glob)
69 69 TLS 1.2 not supported by Python install; network connections lack modern security (?)
70 70 SNI not supported by Python install; may have connectivity issues with some servers (?)
71 71 checking Rust extensions \((installed|missing)\) (re)
72 72 checking Mercurial version (*) (glob)
73 73 checking Mercurial custom build (*) (glob)
74 74 checking module policy (*) (glob)
75 75 checking installed modules (*mercurial)... (glob)
76 76 checking registered compression engines (*zlib*) (glob)
77 77 checking available compression engines (*zlib*) (glob)
78 78 checking available compression engines for wire protocol (*zlib*) (glob)
79 79 checking "re2" regexp engine \((available|missing)\) (re)
80 80 checking templates (*mercurial?templates)... (glob)
81 81 checking default template (*mercurial?templates?map-cmdline.default) (glob)
82 82 checking commit editor... (*) (glob)
83 83 checking username...
84 84 no username supplied
85 85 (specify a username in your configuration file)
86 86 1 problems detected, please check your install!
87 87 [1]
88 88
89 89 hg debuginstall with invalid encoding
90 90 $ HGENCODING=invalidenc hg debuginstall | grep encoding
91 91 checking encoding (invalidenc)...
92 92 unknown encoding: invalidenc
93 93
94 94 exception message in JSON
95 95
96 96 $ HGENCODING=invalidenc HGUSER= hg debuginstall -Tjson | grep error
97 97 "defaulttemplateerror": null,
98 98 "encodingerror": "unknown encoding: invalidenc",
99 99 "extensionserror": null, (no-pure !)
100 100 "usernameerror": "no username supplied",
101 101
102 102 path variables are expanded (~ is the same as $TESTTMP)
103 103 $ mkdir tools
104 104 $ touch tools/testeditor.exe
105 105 #if execbit
106 106 $ chmod 755 tools/testeditor.exe
107 107 #endif
108 108 $ HGEDITOR="~/tools/testeditor.exe" hg debuginstall
109 109 checking encoding (ascii)...
110 110 checking Python executable (*) (glob)
111 111 checking Python implementation (*) (glob)
112 112 checking Python version (2.*) (glob) (no-py3 !)
113 113 checking Python version (3.*) (glob) (py3 !)
114 114 checking Python lib (.*[Ll]ib.*)... (re)
115 115 checking Python security support (*) (glob)
116 116 TLS 1.2 not supported by Python install; network connections lack modern security (?)
117 117 SNI not supported by Python install; may have connectivity issues with some servers (?)
118 118 checking Rust extensions \((installed|missing)\) (re)
119 119 checking Mercurial version (*) (glob)
120 120 checking Mercurial custom build (*) (glob)
121 121 checking module policy (*) (glob)
122 122 checking installed modules (*mercurial)... (glob)
123 123 checking registered compression engines (*zlib*) (glob)
124 124 checking available compression engines (*zlib*) (glob)
125 125 checking available compression engines for wire protocol (*zlib*) (glob)
126 126 checking "re2" regexp engine \((available|missing)\) (re)
127 127 checking templates (*mercurial?templates)... (glob)
128 128 checking default template (*mercurial?templates?map-cmdline.default) (glob)
129 129 checking commit editor... ($TESTTMP/tools/testeditor.exe)
130 130 checking username (test)
131 131 no problems detected
132 132
133 133 print out the binary post-shlexsplit in the error message when commit editor is
134 134 not found (this is intentionally using backslashes to mimic a windows usecase).
135 135 $ HGEDITOR="c:\foo\bar\baz.exe -y -z" hg debuginstall
136 136 checking encoding (ascii)...
137 137 checking Python executable (*) (glob)
138 138 checking Python implementation (*) (glob)
139 139 checking Python version (2.*) (glob) (no-py3 !)
140 140 checking Python version (3.*) (glob) (py3 !)
141 141 checking Python lib (.*[Ll]ib.*)... (re)
142 142 checking Python security support (*) (glob)
143 143 TLS 1.2 not supported by Python install; network connections lack modern security (?)
144 144 SNI not supported by Python install; may have connectivity issues with some servers (?)
145 145 checking Rust extensions \((installed|missing)\) (re)
146 146 checking Mercurial version (*) (glob)
147 147 checking Mercurial custom build (*) (glob)
148 148 checking module policy (*) (glob)
149 149 checking installed modules (*mercurial)... (glob)
150 150 checking registered compression engines (*zlib*) (glob)
151 151 checking available compression engines (*zlib*) (glob)
152 152 checking available compression engines for wire protocol (*zlib*) (glob)
153 153 checking "re2" regexp engine \((available|missing)\) (re)
154 154 checking templates (*mercurial?templates)... (glob)
155 155 checking default template (*mercurial?templates?map-cmdline.default) (glob)
156 156 checking commit editor... (c:\foo\bar\baz.exe) (windows !)
157 157 Can't find editor 'c:\foo\bar\baz.exe' in PATH (windows !)
158 158 checking commit editor... (c:foobarbaz.exe) (no-windows !)
159 159 Can't find editor 'c:foobarbaz.exe' in PATH (no-windows !)
160 160 (specify a commit editor in your configuration file)
161 161 checking username (test)
162 162 1 problems detected, please check your install!
163 163 [1]
164 164
165 165 debuginstall extension support
166 166 $ hg debuginstall --config extensions.fsmonitor= --config fsmonitor.watchman_exe=false | grep atchman
167 167 fsmonitor checking for watchman binary... (false)
168 168 watchman binary missing or broken: warning: Watchman unavailable: watchman exited with code 1
169 169 Verify the json works too:
170 170 $ hg debuginstall --config extensions.fsmonitor= --config fsmonitor.watchman_exe=false -Tjson | grep atchman
171 171 "fsmonitor-watchman": "false",
172 172 "fsmonitor-watchman-error": "warning: Watchman unavailable: watchman exited with code 1",
173 173
174 174 Verify that Mercurial is installable with pip. Note that this MUST be
175 175 the last test in this file, because we do some nasty things to the
176 176 shell environment in order to make the virtualenv work reliably.
177 177
178 178 On Python 3, we use the venv module, which is part of the standard library.
179 179 But some Linux distros strip out this module's functionality involving pip,
180 180 so we have to look for the ensurepip module, which these distros strip out
181 181 completely.
182 182 On Python 2, we use the 3rd party virtualenv module, if available.
183 183
184 184 $ cd $TESTTMP
185 185 $ unset PYTHONPATH
186 186
187 187 #if py3 ensurepip
188 188 $ "$PYTHON" -m venv installenv >> pip.log
189 189
190 190 Note: we use this weird path to run pip and hg to avoid platform differences,
191 191 since it's bin on most platforms but Scripts on Windows.
192 192 $ ./installenv/*/pip install --no-index $TESTDIR/.. >> pip.log
193 193 Failed building wheel for mercurial (?)
194 194 $ ./installenv/*/hg debuginstall || cat pip.log
195 195 checking encoding (ascii)...
196 196 checking Python executable (*) (glob)
197 197 checking Python implementation (*) (glob)
198 198 checking Python version (3.*) (glob)
199 199 checking Python lib (*)... (glob)
200 200 checking Python security support (*) (glob)
201 201 checking Rust extensions \((installed|missing)\) (re)
202 202 checking Mercurial version (*) (glob)
203 203 checking Mercurial custom build (*) (glob)
204 204 checking module policy (*) (glob)
205 205 checking installed modules (*/mercurial)... (glob)
206 206 checking registered compression engines (*) (glob)
207 207 checking available compression engines (*) (glob)
208 208 checking available compression engines for wire protocol (*) (glob)
209 209 checking "re2" regexp engine \((available|missing)\) (re)
210 210 checking templates ($TESTTMP/installenv/*/site-packages/mercurial/templates)... (glob)
211 211 checking default template ($TESTTMP/installenv/*/site-packages/mercurial/templates/map-cmdline.default) (glob)
212 212 checking commit editor... (*) (glob)
213 213 checking username (test)
214 214 no problems detected
215 215 #endif
216 216
217 #if no-py3 virtualenv
217 #if py2virtualenv
218 218
219 219 Note: --no-site-packages is deprecated, but some places have an
220 220 ancient virtualenv from their linux distro or similar and it's not yet
221 221 the default for them.
222 222
223 223 $ "$PYTHON" -m virtualenv --no-site-packages --never-download installenv >> pip.log
224 224 DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7. (?)
225 225 DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support (?)
226 226
227 227 Note: we use this weird path to run pip and hg to avoid platform differences,
228 228 since it's bin on most platforms but Scripts on Windows.
229 229 $ ./installenv/*/pip install --no-index $TESTDIR/.. >> pip.log
230 230 DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7. (?)
231 231 DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support (?)
232 232 $ ./installenv/*/hg debuginstall || cat pip.log
233 233 checking encoding (ascii)...
234 234 checking Python executable (*) (glob)
235 235 checking Python implementation (*) (glob)
236 236 checking Python version (2.*) (glob)
237 237 checking Python lib (*)... (glob)
238 238 checking Python security support (*) (glob)
239 239 TLS 1.2 not supported by Python install; network connections lack modern security (?)
240 240 SNI not supported by Python install; may have connectivity issues with some servers (?)
241 241 checking Rust extensions \((installed|missing)\) (re)
242 242 checking Mercurial version (*) (glob)
243 243 checking Mercurial custom build (*) (glob)
244 244 checking module policy (*) (glob)
245 245 checking installed modules (*/mercurial)... (glob)
246 246 checking registered compression engines (*) (glob)
247 247 checking available compression engines (*) (glob)
248 248 checking available compression engines for wire protocol (*) (glob)
249 249 checking "re2" regexp engine \((available|missing)\) (re)
250 250 checking templates ($TESTTMP/installenv/*/site-packages/mercurial/templates)... (glob)
251 251 checking default template ($TESTTMP/installenv/*/site-packages/mercurial/templates/map-cmdline.default) (glob)
252 252 checking commit editor... (*) (glob)
253 253 checking username (test)
254 254 no problems detected
255 255 #endif
General Comments 0
You need to be logged in to leave comments. Login now