26 |
26 |
27 osenvironb = getattr(os, 'environb', os.environ) |
27 osenvironb = getattr(os, 'environb', os.environ) |
28 |
28 |
29 if sys.version_info > (3, 5, 0): |
29 if sys.version_info > (3, 5, 0): |
30 PYTHON3 = True |
30 PYTHON3 = True |
31 xrange = range # we use xrange in one place, and we'd rather not use range |
31 xrange = range # we use xrange in one place, and we'd rather not use range |
|
32 |
32 def _bytespath(p): |
33 def _bytespath(p): |
33 return p.encode('utf-8') |
34 return p.encode('utf-8') |
34 |
35 |
|
36 |
35 elif sys.version_info >= (3, 0, 0): |
37 elif sys.version_info >= (3, 0, 0): |
36 print('%s is only supported on Python 3.5+ and 2.7, not %s' % |
38 print( |
37 (sys.argv[0], '.'.join(str(v) for v in sys.version_info[:3]))) |
39 '%s is only supported on Python 3.5+ and 2.7, not %s' |
38 sys.exit(70) # EX_SOFTWARE from `man 3 sysexit` |
40 % (sys.argv[0], '.'.join(str(v) for v in sys.version_info[:3])) |
|
41 ) |
|
42 sys.exit(70) # EX_SOFTWARE from `man 3 sysexit` |
39 else: |
43 else: |
40 PYTHON3 = False |
44 PYTHON3 = False |
41 |
45 |
42 # In python 2.x, path operations are generally done using |
46 # In python 2.x, path operations are generally done using |
43 # bytestrings by default, so we don't have to do any extra |
47 # bytestrings by default, so we don't have to do any extra |
44 # fiddling there. We define the wrapper functions anyway just to |
48 # fiddling there. We define the wrapper functions anyway just to |
45 # help keep code consistent between platforms. |
49 # help keep code consistent between platforms. |
46 def _bytespath(p): |
50 def _bytespath(p): |
47 return p |
51 return p |
48 |
52 |
|
53 |
49 def getparser(): |
54 def getparser(): |
50 """Obtain the argument parser used by the CLI.""" |
55 """Obtain the argument parser used by the CLI.""" |
51 parser = argparse.ArgumentParser( |
56 parser = argparse.ArgumentParser( |
52 description='Run tests with fsmonitor enabled.', |
57 description='Run tests with fsmonitor enabled.', |
53 epilog='Unrecognized options are passed to run-tests.py.') |
58 epilog='Unrecognized options are passed to run-tests.py.', |
|
59 ) |
54 # - keep these sorted |
60 # - keep these sorted |
55 # - none of these options should conflict with any in run-tests.py |
61 # - none of these options should conflict with any in run-tests.py |
56 parser.add_argument('--keep-fsmonitor-tmpdir', action='store_true', |
62 parser.add_argument( |
57 help='keep temporary directory with fsmonitor state') |
63 '--keep-fsmonitor-tmpdir', |
58 parser.add_argument('--watchman', |
64 action='store_true', |
|
65 help='keep temporary directory with fsmonitor state', |
|
66 ) |
|
67 parser.add_argument( |
|
68 '--watchman', |
59 help='location of watchman binary (default: watchman in PATH)', |
69 help='location of watchman binary (default: watchman in PATH)', |
60 default='watchman') |
70 default='watchman', |
|
71 ) |
61 |
72 |
62 return parser |
73 return parser |
|
74 |
63 |
75 |
64 @contextlib.contextmanager |
76 @contextlib.contextmanager |
65 def watchman(args): |
77 def watchman(args): |
66 basedir = tempfile.mkdtemp(prefix='hg-fsmonitor') |
78 basedir = tempfile.mkdtemp(prefix='hg-fsmonitor') |
67 try: |
79 try: |
80 pidfile = os.path.join(basedir, 'pid') |
92 pidfile = os.path.join(basedir, 'pid') |
81 statefile = os.path.join(basedir, 'state') |
93 statefile = os.path.join(basedir, 'state') |
82 |
94 |
83 argv = [ |
95 argv = [ |
84 args.watchman, |
96 args.watchman, |
85 '--sockname', sockfile, |
97 '--sockname', |
86 '--logfile', logfile, |
98 sockfile, |
87 '--pidfile', pidfile, |
99 '--logfile', |
88 '--statefile', statefile, |
100 logfile, |
|
101 '--pidfile', |
|
102 pidfile, |
|
103 '--statefile', |
|
104 statefile, |
89 '--foreground', |
105 '--foreground', |
90 '--log-level=2', # debug logging for watchman |
106 '--log-level=2', # debug logging for watchman |
91 ] |
107 ] |
92 |
108 |
93 envb = osenvironb.copy() |
109 envb = osenvironb.copy() |
94 envb[b'WATCHMAN_CONFIG_FILE'] = _bytespath(cfgfile) |
110 envb[b'WATCHMAN_CONFIG_FILE'] = _bytespath(cfgfile) |
95 with open(clilogfile, 'wb') as f: |
111 with open(clilogfile, 'wb') as f: |
96 proc = subprocess.Popen( |
112 proc = subprocess.Popen( |
97 argv, env=envb, stdin=None, stdout=f, stderr=f) |
113 argv, env=envb, stdin=None, stdout=f, stderr=f |
|
114 ) |
98 try: |
115 try: |
99 yield sockfile |
116 yield sockfile |
100 finally: |
117 finally: |
101 proc.terminate() |
118 proc.terminate() |
102 proc.kill() |
119 proc.kill() |
103 finally: |
120 finally: |
104 if args.keep_fsmonitor_tmpdir: |
121 if args.keep_fsmonitor_tmpdir: |
105 print('fsmonitor dir available at %s' % basedir) |
122 print('fsmonitor dir available at %s' % basedir) |
106 else: |
123 else: |
107 shutil.rmtree(basedir, ignore_errors=True) |
124 shutil.rmtree(basedir, ignore_errors=True) |
|
125 |
108 |
126 |
109 def run(): |
127 def run(): |
110 parser = getparser() |
128 parser = getparser() |
111 args, runtestsargv = parser.parse_known_args() |
129 args, runtestsargv = parser.parse_known_args() |
112 |
130 |
118 runtestdir = os.path.dirname(__file__) |
136 runtestdir = os.path.dirname(__file__) |
119 runtests = os.path.join(runtestdir, 'run-tests.py') |
137 runtests = os.path.join(runtestdir, 'run-tests.py') |
120 blacklist = os.path.join(runtestdir, 'blacklists', 'fsmonitor') |
138 blacklist = os.path.join(runtestdir, 'blacklists', 'fsmonitor') |
121 |
139 |
122 runtestsargv.insert(0, runtests) |
140 runtestsargv.insert(0, runtests) |
123 runtestsargv.extend([ |
141 runtestsargv.extend( |
124 '--extra-config', |
142 [ |
125 'extensions.fsmonitor=', |
143 '--extra-config', |
126 # specify fsmonitor.mode=paranoid always in order to force |
144 'extensions.fsmonitor=', |
127 # fsmonitor extension execute "paranoid" code path |
145 # specify fsmonitor.mode=paranoid always in order to force |
128 # |
146 # fsmonitor extension execute "paranoid" code path |
129 # TODO: make fsmonitor-run-tests.py accept specific options |
147 # |
130 '--extra-config', |
148 # TODO: make fsmonitor-run-tests.py accept specific options |
131 'fsmonitor.mode=paranoid', |
149 '--extra-config', |
132 '--blacklist', |
150 'fsmonitor.mode=paranoid', |
133 blacklist, |
151 '--blacklist', |
134 ]) |
152 blacklist, |
|
153 ] |
|
154 ) |
135 |
155 |
136 return subprocess.call(runtestsargv) |
156 return subprocess.call(runtestsargv) |
137 |
157 |
|
158 |
138 if __name__ == '__main__': |
159 if __name__ == '__main__': |
139 sys.exit(run()) |
160 sys.exit(run()) |