upload: search local projects in parallel

Search for project branches to upload in parallel.  This can cut the
lookup time in half for large projects.  We still run the actual hooks
in serial once we have the list of projects to process, but we would
need to rethink things quite a bit before we could handle running them
in parallel too.

Change-Id: I8da0cbc5010566aa860e1a158f3dc07f0709dcff
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/304842
Reviewed-by: Raman Tenneti <rtenneti@google.com>
Tested-by: Mike Frysinger <vapier@google.com>
This commit is contained in:
Mike Frysinger 2021-05-01 12:02:01 -04:00
parent 29626b4f46
commit d1f3e149df

View File

@ -13,10 +13,11 @@
# limitations under the License. # limitations under the License.
import copy import copy
import functools
import re import re
import sys import sys
from command import InteractiveCommand from command import DEFAULT_LOCAL_JOBS, InteractiveCommand
from editor import Editor from editor import Editor
from error import UploadError from error import UploadError
from git_command import GitCommand from git_command import GitCommand
@ -145,6 +146,7 @@ https://gerrit-review.googlesource.com/Documentation/user-upload.html#notify
Gerrit Code Review: https://www.gerritcodereview.com/ Gerrit Code Review: https://www.gerritcodereview.com/
""" """
PARALLEL_JOBS = DEFAULT_LOCAL_JOBS
def _Options(self, p): def _Options(self, p):
p.add_option('-t', p.add_option('-t',
@ -165,9 +167,9 @@ Gerrit Code Review: https://www.gerritcodereview.com/
p.add_option('--cc', p.add_option('--cc',
type='string', action='append', dest='cc', type='string', action='append', dest='cc',
help='Also send email to these email addresses.') help='Also send email to these email addresses.')
p.add_option('--br', p.add_option('--br', '--branch',
type='string', action='store', dest='branch', type='string', action='store', dest='branch',
help='Branch to upload.') help='(Local) branch to upload.')
p.add_option('--cbr', '--current-branch', p.add_option('--cbr', '--current-branch',
dest='current_branch', action='store_true', dest='current_branch', action='store_true',
help='Upload current git branch.') help='Upload current git branch.')
@ -502,40 +504,46 @@ Gerrit Code Review: https://www.gerritcodereview.com/
merge_branch = p.stdout.strip() merge_branch = p.stdout.strip()
return merge_branch return merge_branch
@staticmethod
def _GatherOne(opt, project):
"""Figure out the upload status for |project|."""
if opt.current_branch:
cbr = project.CurrentBranch
up_branch = project.GetUploadableBranch(cbr)
avail = [up_branch] if up_branch else None
else:
avail = project.GetUploadableBranches(opt.branch)
return (project, avail)
def Execute(self, opt, args): def Execute(self, opt, args):
project_list = self.GetProjects(args) projects = self.GetProjects(args)
pending = []
reviewers = []
cc = []
branch = None
if opt.branch: def _ProcessResults(_pool, _out, results):
branch = opt.branch pending = []
for result in results:
for project in project_list: project, avail = result
if opt.current_branch: if avail is None:
cbr = project.CurrentBranch
up_branch = project.GetUploadableBranch(cbr)
if up_branch:
avail = [up_branch]
else:
avail = None
print('repo: error: %s: Unable to upload branch "%s". ' print('repo: error: %s: Unable to upload branch "%s". '
'You might be able to fix the branch by running:\n' 'You might be able to fix the branch by running:\n'
' git branch --set-upstream-to m/%s' % ' git branch --set-upstream-to m/%s' %
(project.relpath, str(cbr), self.manifest.branch), (project.relpath, project.CurrentBranch, self.manifest.branch),
file=sys.stderr) file=sys.stderr)
else: elif avail:
avail = project.GetUploadableBranches(branch) pending.append(result)
if avail: return pending
pending.append((project, avail))
pending = self.ExecuteInParallel(
opt.jobs,
functools.partial(self._GatherOne, opt),
projects,
callback=_ProcessResults)
if not pending: if not pending:
if branch is None: if opt.branch is None:
print('repo: error: no branches ready for upload', file=sys.stderr) print('repo: error: no branches ready for upload', file=sys.stderr)
else: else:
print('repo: error: no branches named "%s" ready for upload' % print('repo: error: no branches named "%s" ready for upload' %
(branch,), file=sys.stderr) (opt.branch,), file=sys.stderr)
return 1 return 1
pending_proj_names = [project.name for (project, available) in pending] pending_proj_names = [project.name for (project, available) in pending]
@ -548,10 +556,8 @@ Gerrit Code Review: https://www.gerritcodereview.com/
worktree_list=pending_worktrees): worktree_list=pending_worktrees):
return 1 return 1
if opt.reviewers: reviewers = _SplitEmails(opt.reviewers) if opt.reviewers else []
reviewers = _SplitEmails(opt.reviewers) cc = _SplitEmails(opt.cc) if opt.cc else []
if opt.cc:
cc = _SplitEmails(opt.cc)
people = (reviewers, cc) people = (reviewers, cc)
if len(pending) == 1 and len(pending[0][1]) == 1: if len(pending) == 1 and len(pending[0][1]) == 1: