##// END OF EJS Templates
hghave: update the check for virtualenv...
Matt Harbison -
r46713:1b5e0d0b default
parent child Browse files
Show More
@@ -1,1083 +1,1082 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 _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("py2virtualenv", "Python2 virtualenv support")
890 def has_py2virtualenv():
891 if sys.version_info[0] != 2:
892 return False
893
889 @check("virtualenv", "virtualenv support")
890 def has_virtualenv():
894 891 try:
895 892 import virtualenv
896 893
897 virtualenv.ACTIVATE_SH
898 return True
899 except ImportError:
894 # --no-site-package became the default in 1.7 (Nov 2011), and the
895 # argument was removed in 20.0 (Feb 2020). Rather than make the
896 # script complicated, just ignore ancient versions.
897 return int(virtualenv.__version__.split('.')[0]) > 1
898 except (AttributeError, ImportError, IndexError):
900 899 return False
901 900
902 901
903 902 @check("fsmonitor", "running tests with fsmonitor")
904 903 def has_fsmonitor():
905 904 return 'HGFSMONITOR_TESTS' in os.environ
906 905
907 906
908 907 @check("fuzzywuzzy", "Fuzzy string matching library")
909 908 def has_fuzzywuzzy():
910 909 try:
911 910 import fuzzywuzzy
912 911
913 912 fuzzywuzzy.__version__
914 913 return True
915 914 except ImportError:
916 915 return False
917 916
918 917
919 918 @check("clang-libfuzzer", "clang new enough to include libfuzzer")
920 919 def has_clang_libfuzzer():
921 920 mat = matchoutput('clang --version', br'clang version (\d)')
922 921 if mat:
923 922 # libfuzzer is new in clang 6
924 923 return int(mat.group(1)) > 5
925 924 return False
926 925
927 926
928 927 @check("clang-6.0", "clang 6.0 with version suffix (libfuzzer included)")
929 928 def has_clang60():
930 929 return matchoutput('clang-6.0 --version', br'clang version 6\.')
931 930
932 931
933 932 @check("xdiff", "xdiff algorithm")
934 933 def has_xdiff():
935 934 try:
936 935 from mercurial import policy
937 936
938 937 bdiff = policy.importmod('bdiff')
939 938 return bdiff.xdiffblocks(b'', b'') == [(0, 0, 0, 0)]
940 939 except (ImportError, AttributeError):
941 940 return False
942 941
943 942
944 943 @check('extraextensions', 'whether tests are running with extra extensions')
945 944 def has_extraextensions():
946 945 return 'HGTESTEXTRAEXTENSIONS' in os.environ
947 946
948 947
949 948 def getrepofeatures():
950 949 """Obtain set of repository features in use.
951 950
952 951 HGREPOFEATURES can be used to define or remove features. It contains
953 952 a space-delimited list of feature strings. Strings beginning with ``-``
954 953 mean to remove.
955 954 """
956 955 # Default list provided by core.
957 956 features = {
958 957 'bundlerepo',
959 958 'revlogstore',
960 959 'fncache',
961 960 }
962 961
963 962 # Features that imply other features.
964 963 implies = {
965 964 'simplestore': ['-revlogstore', '-bundlerepo', '-fncache'],
966 965 }
967 966
968 967 for override in os.environ.get('HGREPOFEATURES', '').split(' '):
969 968 if not override:
970 969 continue
971 970
972 971 if override.startswith('-'):
973 972 if override[1:] in features:
974 973 features.remove(override[1:])
975 974 else:
976 975 features.add(override)
977 976
978 977 for imply in implies.get(override, []):
979 978 if imply.startswith('-'):
980 979 if imply[1:] in features:
981 980 features.remove(imply[1:])
982 981 else:
983 982 features.add(imply)
984 983
985 984 return features
986 985
987 986
988 987 @check('reporevlogstore', 'repository using the default revlog store')
989 988 def has_reporevlogstore():
990 989 return 'revlogstore' in getrepofeatures()
991 990
992 991
993 992 @check('reposimplestore', 'repository using simple storage extension')
994 993 def has_reposimplestore():
995 994 return 'simplestore' in getrepofeatures()
996 995
997 996
998 997 @check('repobundlerepo', 'whether we can open bundle files as repos')
999 998 def has_repobundlerepo():
1000 999 return 'bundlerepo' in getrepofeatures()
1001 1000
1002 1001
1003 1002 @check('repofncache', 'repository has an fncache')
1004 1003 def has_repofncache():
1005 1004 return 'fncache' in getrepofeatures()
1006 1005
1007 1006
1008 1007 @check('sqlite', 'sqlite3 module is available')
1009 1008 def has_sqlite():
1010 1009 try:
1011 1010 import sqlite3
1012 1011
1013 1012 version = sqlite3.sqlite_version_info
1014 1013 except ImportError:
1015 1014 return False
1016 1015
1017 1016 if version < (3, 8, 3):
1018 1017 # WITH clause not supported
1019 1018 return False
1020 1019
1021 1020 return matchoutput('sqlite3 -version', br'^3\.\d+')
1022 1021
1023 1022
1024 1023 @check('vcr', 'vcr http mocking library')
1025 1024 def has_vcr():
1026 1025 try:
1027 1026 import vcr
1028 1027
1029 1028 vcr.VCR
1030 1029 return True
1031 1030 except (ImportError, AttributeError):
1032 1031 pass
1033 1032 return False
1034 1033
1035 1034
1036 1035 @check('emacs', 'GNU Emacs')
1037 1036 def has_emacs():
1038 1037 # Our emacs lisp uses `with-eval-after-load` which is new in emacs
1039 1038 # 24.4, so we allow emacs 24.4, 24.5, and 25+ (24.5 was the last
1040 1039 # 24 release)
1041 1040 return matchoutput('emacs --version', b'GNU Emacs 2(4.4|4.5|5|6|7|8|9)')
1042 1041
1043 1042
1044 1043 @check('black', 'the black formatter for python')
1045 1044 def has_black():
1046 1045 blackcmd = 'black --version'
1047 1046 version_regex = b'black, version ([0-9a-b.]+)'
1048 1047 version = matchoutput(blackcmd, version_regex)
1049 1048 sv = distutils.version.StrictVersion
1050 1049 return version and sv(_bytes2sys(version.group(1))) >= sv('20.8b1')
1051 1050
1052 1051
1053 1052 @check('pytype', 'the pytype type checker')
1054 1053 def has_pytype():
1055 1054 pytypecmd = 'pytype --version'
1056 1055 version = matchoutput(pytypecmd, b'[0-9a-b.]+')
1057 1056 sv = distutils.version.StrictVersion
1058 1057 return version and sv(_bytes2sys(version.group(0))) >= sv('2019.10.17')
1059 1058
1060 1059
1061 1060 @check("rustfmt", "rustfmt tool at version nightly-2020-10-04")
1062 1061 def has_rustfmt():
1063 1062 # We use Nightly's rustfmt due to current unstable config options.
1064 1063 return matchoutput(
1065 1064 '`rustup which --toolchain nightly-2020-10-04 rustfmt` --version',
1066 1065 b'rustfmt',
1067 1066 )
1068 1067
1069 1068
1070 1069 @check("cargo", "cargo tool")
1071 1070 def has_cargo():
1072 1071 return matchoutput('`rustup which cargo` --version', b'cargo')
1073 1072
1074 1073
1075 1074 @check("lzma", "python lzma module")
1076 1075 def has_lzma():
1077 1076 try:
1078 1077 import _lzma
1079 1078
1080 1079 _lzma.FORMAT_XZ
1081 1080 return True
1082 1081 except ImportError:
1083 1082 return False
@@ -1,263 +1,262 b''
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 Hack: Debian does something a bit different in ensurepip.bootstrap. This makes
191 191 it so that pip thinks the 'wheel' wheel is installed so it can build wheels;
192 192 when it goes to try, however, it shells out to run `python3 -u <setup.py>`,
193 193 that *doesn't* get the 'wheel' wheel, and it fails with an invalid command
194 194 'bdist_wheel'. To fix this, we just delete the wheel from where Debian put it in
195 195 our virtual env. Then pip doesn't think it's installed and doesn't try to build.
196 196 $ rm installenv/share/python-wheels/wheel-*.whl >/dev/null 2>&1 || true
197 197
198 198 Note: we use this weird path to run pip and hg to avoid platform differences,
199 199 since it's bin on most platforms but Scripts on Windows.
200 200 $ ./installenv/*/pip install --no-index $TESTDIR/.. >> pip.log
201 201 Failed building wheel for mercurial (?)
202 202 $ ./installenv/*/hg debuginstall || cat pip.log
203 203 checking encoding (ascii)...
204 204 checking Python executable (*) (glob)
205 205 checking Python implementation (*) (glob)
206 206 checking Python version (3.*) (glob)
207 207 checking Python lib (*)... (glob)
208 208 checking Python security support (*) (glob)
209 209 checking Rust extensions \((installed|missing)\) (re)
210 210 checking Mercurial version (*) (glob)
211 211 checking Mercurial custom build (*) (glob)
212 212 checking module policy (*) (glob)
213 213 checking installed modules (*/mercurial)... (glob)
214 214 checking registered compression engines (*) (glob)
215 215 checking available compression engines (*) (glob)
216 216 checking available compression engines for wire protocol (*) (glob)
217 217 checking "re2" regexp engine \((available|missing)\) (re)
218 218 checking templates ($TESTTMP/installenv/*/site-packages/mercurial/templates)... (glob)
219 219 checking default template ($TESTTMP/installenv/*/site-packages/mercurial/templates/map-cmdline.default) (glob)
220 220 checking commit editor... (*) (glob)
221 221 checking username (test)
222 222 no problems detected
223 223 #endif
224 224
225 #if py2virtualenv
225 #if virtualenv no-py3
226 226
227 Note: --no-site-packages is deprecated, but some places have an
228 ancient virtualenv from their linux distro or similar and it's not yet
229 the default for them.
227 Note: --no-site-packages is the default for all versions enabled by hghave
230 228
231 $ "$PYTHON" -m virtualenv --no-site-packages --never-download installenv >> pip.log
229 $ "$PYTHON" -m virtualenv --never-download installenv >> pip.log
232 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. (?)
233 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 (?)
234 232
235 233 Note: we use this weird path to run pip and hg to avoid platform differences,
236 234 since it's bin on most platforms but Scripts on Windows.
237 235 $ ./installenv/*/pip install --no-index $TESTDIR/.. >> pip.log
238 236 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. (?)
239 237 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 (?)
238 DEPRECATION: Python 2.7 reached the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 is no longer maintained. pip 21.0 will drop support for Python 2.7 in January 2021. More details about Python 2 support in pip can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support pip 21.0 will remove support for this functionality. (?)
240 239 $ ./installenv/*/hg debuginstall || cat pip.log
241 240 checking encoding (ascii)...
242 241 checking Python executable (*) (glob)
243 242 checking Python implementation (*) (glob)
244 243 checking Python version (2.*) (glob)
245 244 checking Python lib (*)... (glob)
246 245 checking Python security support (*) (glob)
247 246 TLS 1.2 not supported by Python install; network connections lack modern security (?)
248 247 SNI not supported by Python install; may have connectivity issues with some servers (?)
249 248 checking Rust extensions \((installed|missing)\) (re)
250 249 checking Mercurial version (*) (glob)
251 250 checking Mercurial custom build (*) (glob)
252 251 checking module policy (*) (glob)
253 252 checking installed modules (*/mercurial)... (glob)
254 253 checking registered compression engines (*) (glob)
255 254 checking available compression engines (*) (glob)
256 255 checking available compression engines for wire protocol (*) (glob)
257 256 checking "re2" regexp engine \((available|missing)\) (re)
258 257 checking templates ($TESTTMP/installenv/*/site-packages/mercurial/templates)... (glob)
259 258 checking default template ($TESTTMP/installenv/*/site-packages/mercurial/templates/map-cmdline.default) (glob)
260 259 checking commit editor... (*) (glob)
261 260 checking username (test)
262 261 no problems detected
263 262 #endif
General Comments 0
You need to be logged in to leave comments. Login now