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