diff options
Diffstat (limited to 'subcmds')
| -rw-r--r-- | subcmds/forall.py | 106 |
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 | ||
| 15 | import errno | 15 | import errno |
| 16 | import io | ||
| 16 | import multiprocessing | 17 | import multiprocessing |
| 17 | import re | 18 | import re |
| 18 | import os | 19 | import os |
| @@ -22,7 +23,6 @@ import subprocess | |||
| 22 | 23 | ||
| 23 | from color import Coloring | 24 | from color import Coloring |
| 24 | from command import DEFAULT_LOCAL_JOBS, Command, MirrorSafeCommand, WORKER_BATCH_SIZE | 25 | from command import DEFAULT_LOCAL_JOBS, Command, MirrorSafeCommand, WORKER_BATCH_SIZE |
| 25 | import 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 | ||
