forall: allow interactive commands with -j1

Historically forall has been interactive since it ran in serial.
Recent rework in here dropped that to enable parallel processing.
Restore support for interactive commands when running -j1 or with
an explicit --interactive option.

Bug: https://crbug.com/gerrit/14256
Change-Id: I502007186f771914cfd7830846a4e1938b5e1f38
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/300722
Reviewed-by: Michael Mortensen <mmortensen@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
This commit is contained in:
Mike Frysinger 2021-03-18 13:54:34 -04:00
parent a5b40a2845
commit d34af28ac2

View File

@ -52,6 +52,11 @@ Executes the same shell command in each project.
The -r option allows running the command only on projects matching The -r option allows running the command only on projects matching
regex or wildcard expression. regex or wildcard expression.
By default, projects are processed non-interactively in parallel. If you want
to run interactive commands, make sure to pass --interactive to force --jobs 1.
While the processing order of projects is not guaranteed, the order of project
output is stable.
# Output Formatting # Output Formatting
The -p option causes '%prog' to bind pipes to the command's stdin, The -p option causes '%prog' to bind pipes to the command's stdin,
@ -154,6 +159,9 @@ without iterating through the remaining projects.
g.add_option('-v', '--verbose', g.add_option('-v', '--verbose',
dest='verbose', action='store_true', dest='verbose', action='store_true',
help='Show command error messages') help='Show command error messages')
p.add_option('--interactive',
action='store_true',
help='force interactive usage')
def WantPager(self, opt): def WantPager(self, opt):
return opt.project_header and opt.jobs == 1 return opt.project_header and opt.jobs == 1
@ -173,6 +181,11 @@ without iterating through the remaining projects.
cmd.append(cmd[0]) cmd.append(cmd[0])
cmd.extend(opt.command[1:]) cmd.extend(opt.command[1:])
# Historically, forall operated interactively, and in serial. If the user
# has selected 1 job, then default to interacive mode.
if opt.jobs == 1:
opt.interactive = True
if opt.project_header \ if opt.project_header \
and not shell \ and not shell \
and cmd[0] == 'git': and cmd[0] == 'git':
@ -313,10 +326,12 @@ def DoWork(project, mirror, opt, cmd, shell, cnt, config):
else: else:
stderr = subprocess.DEVNULL stderr = subprocess.DEVNULL
stdin = None if opt.interactive else subprocess.DEVNULL
result = subprocess.run( result = subprocess.run(
cmd, cwd=cwd, shell=shell, env=env, check=False, cmd, cwd=cwd, shell=shell, env=env, check=False,
encoding='utf-8', errors='replace', encoding='utf-8', errors='replace',
stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=stderr) stdin=stdin, stdout=subprocess.PIPE, stderr=stderr)
output = result.stdout output = result.stdout
if opt.project_header: if opt.project_header: