53 import tempfile |
53 import tempfile |
54 import time |
54 import time |
55 import re |
55 import re |
56 import threading |
56 import threading |
57 |
57 |
|
58 processlock = threading.Lock() |
|
59 |
58 closefds = os.name == 'posix' |
60 closefds = os.name == 'posix' |
59 def Popen4(cmd, timeout): |
61 def Popen4(cmd, wd, timeout): |
|
62 processlock.acquire() |
|
63 orig = os.getcwd() |
|
64 os.chdir(wd) |
60 p = subprocess.Popen(cmd, shell=True, bufsize=-1, |
65 p = subprocess.Popen(cmd, shell=True, bufsize=-1, |
61 close_fds=closefds, |
66 close_fds=closefds, |
62 stdin=subprocess.PIPE, stdout=subprocess.PIPE, |
67 stdin=subprocess.PIPE, stdout=subprocess.PIPE, |
63 stderr=subprocess.STDOUT) |
68 stderr=subprocess.STDOUT) |
|
69 os.chdir(orig) |
|
70 processlock.release() |
|
71 |
64 p.fromchild = p.stdout |
72 p.fromchild = p.stdout |
65 p.tochild = p.stdin |
73 p.tochild = p.stdin |
66 p.childerr = p.stderr |
74 p.childerr = p.stderr |
67 |
75 |
68 if timeout: |
76 if timeout: |
453 adir = os.path.join(TESTDIR, 'annotated') |
463 adir = os.path.join(TESTDIR, 'annotated') |
454 if not os.path.isdir(adir): |
464 if not os.path.isdir(adir): |
455 os.mkdir(adir) |
465 os.mkdir(adir) |
456 covrun('-i', '-a', '"--directory=%s"' % adir, '"--omit=%s"' % omit) |
466 covrun('-i', '-a', '"--directory=%s"' % adir, '"--omit=%s"' % omit) |
457 |
467 |
458 def pytest(test, options, replacements): |
468 def pytest(test, wd, options, replacements): |
459 py3kswitch = options.py3k_warnings and ' -3' or '' |
469 py3kswitch = options.py3k_warnings and ' -3' or '' |
460 cmd = '%s%s "%s"' % (PYTHON, py3kswitch, test) |
470 cmd = '%s%s "%s"' % (PYTHON, py3kswitch, test) |
461 vlog("# Running", cmd) |
471 vlog("# Running", cmd) |
462 return run(cmd, options, replacements) |
472 return run(cmd, wd, options, replacements) |
463 |
473 |
464 def shtest(test, options, replacements): |
474 def shtest(test, wd, options, replacements): |
465 cmd = '"%s"' % test |
475 cmd = '"%s"' % test |
466 vlog("# Running", cmd) |
476 vlog("# Running", cmd) |
467 return run(cmd, options, replacements) |
477 return run(cmd, wd, options, replacements) |
468 |
478 |
469 needescape = re.compile(r'[\x00-\x08\x0b-\x1f\x7f-\xff]').search |
479 needescape = re.compile(r'[\x00-\x08\x0b-\x1f\x7f-\xff]').search |
470 escapesub = re.compile(r'[\x00-\x08\x0b-\x1f\\\x7f-\xff]').sub |
480 escapesub = re.compile(r'[\x00-\x08\x0b-\x1f\\\x7f-\xff]').sub |
471 escapemap = dict((chr(i), r'\x%02x' % i) for i in range(256)) |
481 escapemap = dict((chr(i), r'\x%02x' % i) for i in range(256)) |
472 escapemap.update({'\\': '\\\\', '\r': r'\r'}) |
482 escapemap.update({'\\': '\\\\', '\r': r'\r'}) |
473 def escapef(m): |
483 def escapef(m): |
474 return escapemap[m.group(0)] |
484 return escapemap[m.group(0)] |
475 def stringescape(s): |
485 def stringescape(s): |
476 return escapesub(escapef, s) |
486 return escapesub(escapef, s) |
477 |
487 |
478 def tsttest(test, options, replacements): |
488 def tsttest(test, wd, options, replacements): |
479 t = open(test) |
489 t = open(test) |
480 out = [] |
490 out = [] |
481 script = [] |
491 script = [] |
482 salt = "SALT" + str(time.time()) |
492 salt = "SALT" + str(time.time()) |
483 |
493 |
514 os.write(fd, l) |
524 os.write(fd, l) |
515 os.close(fd) |
525 os.close(fd) |
516 |
526 |
517 cmd = '/bin/sh "%s"' % name |
527 cmd = '/bin/sh "%s"' % name |
518 vlog("# Running", cmd) |
528 vlog("# Running", cmd) |
519 exitcode, output = run(cmd, options, replacements) |
529 exitcode, output = run(cmd, wd, options, replacements) |
520 # do not merge output if skipped, return hghave message instead |
530 # do not merge output if skipped, return hghave message instead |
521 # similarly, with --debug, output is None |
531 # similarly, with --debug, output is None |
522 if exitcode == SKIPPED_STATUS or output is None: |
532 if exitcode == SKIPPED_STATUS or output is None: |
523 return exitcode, output |
533 return exitcode, output |
524 finally: |
534 finally: |
593 postout += after.pop(pos) |
603 postout += after.pop(pos) |
594 |
604 |
595 return exitcode, postout |
605 return exitcode, postout |
596 |
606 |
597 wifexited = getattr(os, "WIFEXITED", lambda x: False) |
607 wifexited = getattr(os, "WIFEXITED", lambda x: False) |
598 def run(cmd, options, replacements): |
608 def run(cmd, wd, options, replacements): |
599 """Run command in a sub-process, capturing the output (stdout and stderr). |
609 """Run command in a sub-process, capturing the output (stdout and stderr). |
600 Return a tuple (exitcode, output). output is None in debug mode.""" |
610 Return a tuple (exitcode, output). output is None in debug mode.""" |
601 # TODO: Use subprocess.Popen if we're running on Python 2.4 |
611 # TODO: Use subprocess.Popen if we're running on Python 2.4 |
602 if options.debug: |
612 if options.debug: |
603 proc = subprocess.Popen(cmd, shell=True) |
613 proc = subprocess.Popen(cmd, shell=True) |
771 # Make a tmp subdirectory to work in |
781 # Make a tmp subdirectory to work in |
772 testtmp = os.environ["TESTTMP"] = os.environ["HOME"] = \ |
782 testtmp = os.environ["TESTTMP"] = os.environ["HOME"] = \ |
773 os.path.join(HGTMP, test) |
783 os.path.join(HGTMP, test) |
774 |
784 |
775 os.mkdir(testtmp) |
785 os.mkdir(testtmp) |
776 os.chdir(testtmp) |
786 ret, out = runner(testpath, testtmp, options, [ |
777 |
|
778 ret, out = runner(testpath, options, [ |
|
779 (re.escape(testtmp), '$TESTTMP'), |
787 (re.escape(testtmp), '$TESTTMP'), |
780 (r':%s\b' % options.port, ':$HGPORT'), |
788 (r':%s\b' % options.port, ':$HGPORT'), |
781 (r':%s\b' % (options.port + 1), ':$HGPORT1'), |
789 (r':%s\b' % (options.port + 1), ':$HGPORT1'), |
782 (r':%s\b' % (options.port + 2), ':$HGPORT2'), |
790 (r':%s\b' % (options.port + 2), ':$HGPORT2'), |
783 ]) |
791 ]) |