summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--subcmds/forall.py106
1 files changed, 40 insertions, 66 deletions
diff --git a/subcmds/forall.py b/subcmds/forall.py
index b874b6d2..4ea7db66 100644
--- a/subcmds/forall.py
+++ b/subcmds/forall.py
@@ -13,6 +13,7 @@
13# limitations under the License. 13# limitations under the License.
14 14
15import errno 15import errno
16import io
16import multiprocessing 17import multiprocessing
17import re 18import re
18import os 19import os
@@ -22,7 +23,6 @@ import subprocess
22 23
23from color import Coloring 24from color import Coloring
24from command import DEFAULT_LOCAL_JOBS, Command, MirrorSafeCommand, WORKER_BATCH_SIZE 25from command import DEFAULT_LOCAL_JOBS, Command, MirrorSafeCommand, WORKER_BATCH_SIZE
25import platform_utils
26 26
27_CAN_COLOR = [ 27_CAN_COLOR = [
28 'branch', 28 'branch',
@@ -241,7 +241,18 @@ without iterating through the remaining projects.
241 DoWorkWrapper, 241 DoWorkWrapper,
242 self.ProjectArgs(projects, mirror, opt, cmd, shell, config), 242 self.ProjectArgs(projects, mirror, opt, cmd, shell, config),
243 chunksize=WORKER_BATCH_SIZE) 243 chunksize=WORKER_BATCH_SIZE)
244 for r in results_it: 244 first = True
245 for (r, output) in results_it:
246 if output:
247 if first:
248 first = False
249 elif opt.project_header:
250 print()
251 # To simplify the DoWorkWrapper, take care of automatic newlines.
252 end = '\n'
253 if output[-1] == '\n':
254 end = ''
255 print(output, end=end)
245 rc = rc or r 256 rc = rc or r
246 if r != 0 and opt.abort_on_errors: 257 if r != 0 and opt.abort_on_errors:
247 raise Exception('Aborting due to previous error') 258 raise Exception('Aborting due to previous error')
@@ -326,73 +337,36 @@ def DoWork(project, mirror, opt, cmd, shell, cnt, config):
326 # Allow the user to silently ignore missing checkouts so they can run on 337 # Allow the user to silently ignore missing checkouts so they can run on
327 # partial checkouts (good for infra recovery tools). 338 # partial checkouts (good for infra recovery tools).
328 if opt.ignore_missing: 339 if opt.ignore_missing:
329 return 0 340 return (0, '')
341
342 output = ''
330 if ((opt.project_header and opt.verbose) 343 if ((opt.project_header and opt.verbose)
331 or not opt.project_header): 344 or not opt.project_header):
332 print('skipping %s/' % project['relpath'], file=sys.stderr) 345 output = 'skipping %s/' % project['relpath']
333 return 1 346 return (1, output)
334 347
335 if opt.project_header: 348 if opt.verbose:
336 stdin = subprocess.PIPE 349 stderr = subprocess.STDOUT
337 stdout = subprocess.PIPE
338 stderr = subprocess.PIPE
339 else: 350 else:
340 stdin = None 351 stderr = subprocess.DEVNULL
341 stdout = None
342 stderr = None
343
344 p = subprocess.Popen(cmd,
345 cwd=cwd,
346 shell=shell,
347 env=env,
348 stdin=stdin,
349 stdout=stdout,
350 stderr=stderr)
351 352
353 result = subprocess.run(
354 cmd, cwd=cwd, shell=shell, env=env, check=False,
355 encoding='utf-8', errors='replace',
356 stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=stderr)
357
358 output = result.stdout
352 if opt.project_header: 359 if opt.project_header:
353 out = ForallColoring(config) 360 if output:
354 out.redirect(sys.stdout) 361 buf = io.StringIO()
355 empty = True 362 out = ForallColoring(config)
356 errbuf = '' 363 out.redirect(buf)
357 364 if mirror:
358 p.stdin.close() 365 project_header_path = project['name']
359 s_in = platform_utils.FileDescriptorStreams.create() 366 else:
360 s_in.add(p.stdout, sys.stdout, 'stdout') 367 project_header_path = project['relpath']
361 s_in.add(p.stderr, sys.stderr, 'stderr') 368 out.project('project %s/' % project_header_path)
362 369 out.nl()
363 while not s_in.is_done: 370 buf.write(output)
364 in_ready = s_in.select() 371 output = buf.getvalue()
365 for s in in_ready: 372 return (result.returncode, output)
366 buf = s.read().decode()
367 if not buf:
368 s_in.remove(s)
369 s.close()
370 continue
371
372 if not opt.verbose:
373 if s.std_name == 'stderr':
374 errbuf += buf
375 continue
376
377 if empty and out:
378 if not cnt == 0:
379 out.nl()
380
381 if mirror:
382 project_header_path = project['name']
383 else:
384 project_header_path = project['relpath']
385 out.project('project %s/', project_header_path)
386 out.nl()
387 out.flush()
388 if errbuf:
389 sys.stderr.write(errbuf)
390 sys.stderr.flush()
391 errbuf = ''
392 empty = False
393
394 s.dest.write(buf)
395 s.dest.flush()
396
397 r = p.wait()
398 return r