Add multi-manifest support with <submanifest> element

To be addressed in another change:
 - a partial `repo sync` (with a list of projects/paths to sync)
   requires `--this-tree-only`.

Change-Id: I6c7400bf001540e9d7694fa70934f8f204cb5f57
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/322657
Tested-by: LaMont Jones <lamontjones@google.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
This commit is contained in:
LaMont Jones
2021-11-18 22:40:18 +00:00
parent 87cce68b28
commit cc879a97c3
28 changed files with 794 additions and 162 deletions

View File

@@ -69,7 +69,8 @@ It is equivalent to "git branch -D <branchname>".
nb = args[0]
err = defaultdict(list)
success = defaultdict(list)
all_projects = self.GetProjects(args[1:])
all_projects = self.GetProjects(args[1:], all_manifests=not opt.this_manifest_only)
_RelPath = lambda p: p.RelPath(local=opt.this_manifest_only)
def _ProcessResults(_pool, pm, states):
for (results, project) in states:
@@ -94,7 +95,7 @@ It is equivalent to "git branch -D <branchname>".
err_msg = "error: cannot abandon %s" % br
print(err_msg, file=sys.stderr)
for proj in err[br]:
print(' ' * len(err_msg) + " | %s" % proj.relpath, file=sys.stderr)
print(' ' * len(err_msg) + " | %s" % _RelPath(proj), file=sys.stderr)
sys.exit(1)
elif not success:
print('error: no project has local branch(es) : %s' % nb,
@@ -110,5 +111,5 @@ It is equivalent to "git branch -D <branchname>".
result = "all project"
else:
result = "%s" % (
('\n' + ' ' * width + '| ').join(p.relpath for p in success[br]))
('\n' + ' ' * width + '| ').join(_RelPath(p) for p in success[br]))
print("%s%s| %s\n" % (br, ' ' * (width - len(br)), result))

View File

@@ -98,7 +98,7 @@ is shown, then the branch appears in all projects.
PARALLEL_JOBS = DEFAULT_LOCAL_JOBS
def Execute(self, opt, args):
projects = self.GetProjects(args)
projects = self.GetProjects(args, all_manifests=not opt.this_manifest_only)
out = BranchColoring(self.manifest.manifestProject.config)
all_branches = {}
project_cnt = len(projects)
@@ -147,6 +147,7 @@ is shown, then the branch appears in all projects.
hdr('%c%c %-*s' % (current, published, width, name))
out.write(' |')
_RelPath = lambda p: p.RelPath(local=opt.this_manifest_only)
if in_cnt < project_cnt:
fmt = out.write
paths = []
@@ -154,19 +155,20 @@ is shown, then the branch appears in all projects.
if i.IsSplitCurrent or (in_cnt <= project_cnt - in_cnt):
in_type = 'in'
for b in i.projects:
relpath = b.project.relpath
if not i.IsSplitCurrent or b.current:
paths.append(b.project.relpath)
paths.append(_RelPath(b.project))
else:
non_cur_paths.append(b.project.relpath)
non_cur_paths.append(_RelPath(b.project))
else:
fmt = out.notinproject
in_type = 'not in'
have = set()
for b in i.projects:
have.add(b.project.relpath)
have.add(_RelPath(b.project))
for p in projects:
if p.relpath not in have:
paths.append(p.relpath)
if _RelPath(p) not in have:
paths.append(_RelPath(p))
s = ' %s %s' % (in_type, ', '.join(paths))
if not i.IsSplitCurrent and (width + 7 + len(s) < 80):

View File

@@ -47,7 +47,7 @@ The command is equivalent to:
nb = args[0]
err = []
success = []
all_projects = self.GetProjects(args[1:])
all_projects = self.GetProjects(args[1:], all_manifests=not opt.this_manifest_only)
def _ProcessResults(_pool, pm, results):
for status, project in results:

View File

@@ -50,7 +50,7 @@ to the Unix 'patch' command.
return (ret, buf.getvalue())
def Execute(self, opt, args):
all_projects = self.GetProjects(args)
all_projects = self.GetProjects(args, all_manifests=not opt.this_manifest_only)
def _ProcessResults(_pool, _output, results):
ret = 0

View File

@@ -179,6 +179,9 @@ synced and their revisions won't be found.
def ValidateOptions(self, opt, args):
if not args or len(args) > 2:
self.OptionParser.error('missing manifests to diff')
if opt.this_manifest_only is False:
raise self.OptionParser.error(
'`diffmanifest` only supports the current tree')
def Execute(self, opt, args):
self.out = _Coloring(self.client.globalConfig)

View File

@@ -48,7 +48,7 @@ If no project is specified try to use current directory as a project.
dest='ffonly', action='store_true',
help="force fast-forward merge")
def _ParseChangeIds(self, args):
def _ParseChangeIds(self, opt, args):
if not args:
self.Usage()
@@ -77,7 +77,7 @@ If no project is specified try to use current directory as a project.
ps_id = max(int(match.group(1)), ps_id)
to_get.append((project, chg_id, ps_id))
else:
projects = self.GetProjects([a])
projects = self.GetProjects([a], all_manifests=not opt.this_manifest_only)
if len(projects) > 1:
# If the cwd is one of the projects, assume they want that.
try:
@@ -88,8 +88,8 @@ If no project is specified try to use current directory as a project.
print('error: %s matches too many projects; please re-run inside '
'the project checkout.' % (a,), file=sys.stderr)
for project in projects:
print(' %s/ @ %s' % (project.relpath, project.revisionExpr),
file=sys.stderr)
print(' %s/ @ %s' % (project.RelPath(local=opt.this_manifest_only),
project.revisionExpr), file=sys.stderr)
sys.exit(1)
else:
project = projects[0]
@@ -105,7 +105,7 @@ If no project is specified try to use current directory as a project.
self.OptionParser.error('-x and --ff are mutually exclusive options')
def Execute(self, opt, args):
for project, change_id, ps_id in self._ParseChangeIds(args):
for project, change_id, ps_id in self._ParseChangeIds(opt, args):
dl = project.DownloadPatchSet(change_id, ps_id)
if not dl:
print('[%s] change %d/%d not found'

View File

@@ -168,6 +168,7 @@ without iterating through the remaining projects.
def Execute(self, opt, args):
cmd = [opt.command[0]]
all_trees = not opt.this_manifest_only
shell = True
if re.compile(r'^[a-z0-9A-Z_/\.-]+$').match(cmd[0]):
@@ -213,11 +214,11 @@ without iterating through the remaining projects.
self.manifest.Override(smart_sync_manifest_path)
if opt.regex:
projects = self.FindProjects(args)
projects = self.FindProjects(args, all_manifests=all_trees)
elif opt.inverse_regex:
projects = self.FindProjects(args, inverse=True)
projects = self.FindProjects(args, inverse=True, all_manifests=all_trees)
else:
projects = self.GetProjects(args, groups=opt.groups)
projects = self.GetProjects(args, groups=opt.groups, all_manifests=all_trees)
os.environ['REPO_COUNT'] = str(len(projects))
@@ -290,6 +291,7 @@ def DoWork(project, mirror, opt, cmd, shell, cnt, config):
setenv('REPO_PROJECT', project.name)
setenv('REPO_PATH', project.relpath)
setenv('REPO_OUTERPATH', project.RelPath(local=opt.this_manifest_only))
setenv('REPO_REMOTE', project.remote.name)
try:
# If we aren't in a fully synced state and we don't have the ref the manifest
@@ -320,7 +322,7 @@ def DoWork(project, mirror, opt, cmd, shell, cnt, config):
output = ''
if ((opt.project_header and opt.verbose)
or not opt.project_header):
output = 'skipping %s/' % project.relpath
output = 'skipping %s/' % project.RelPath(local=opt.this_manifest_only)
return (1, output)
if opt.verbose:
@@ -344,7 +346,7 @@ def DoWork(project, mirror, opt, cmd, shell, cnt, config):
if mirror:
project_header_path = project.name
else:
project_header_path = project.relpath
project_header_path = project.RelPath(local=opt.this_manifest_only)
out.project('project %s/' % project_header_path)
out.nl()
buf.write(output)

View File

@@ -24,6 +24,7 @@ import wrapper
class GitcInit(init.Init, GitcAvailableCommand):
COMMON = True
MULTI_MANIFEST_SUPPORT = False
helpSummary = "Initialize a GITC Client."
helpUsage = """
%prog [options] [client name]

View File

@@ -172,15 +172,16 @@ contain a line that matches both expressions:
return (project, p.Wait(), p.stdout, p.stderr)
@staticmethod
def _ProcessResults(full_name, have_rev, _pool, out, results):
def _ProcessResults(full_name, have_rev, opt, _pool, out, results):
git_failed = False
bad_rev = False
have_match = False
_RelPath = lambda p: p.RelPath(local=opt.this_manifest_only)
for project, rc, stdout, stderr in results:
if rc < 0:
git_failed = True
out.project('--- project %s ---' % project.relpath)
out.project('--- project %s ---' % _RelPath(project))
out.nl()
out.fail('%s', stderr)
out.nl()
@@ -192,7 +193,7 @@ contain a line that matches both expressions:
if have_rev and 'fatal: ambiguous argument' in stderr:
bad_rev = True
else:
out.project('--- project %s ---' % project.relpath)
out.project('--- project %s ---' % _RelPath(project))
out.nl()
out.fail('%s', stderr.strip())
out.nl()
@@ -208,13 +209,13 @@ contain a line that matches both expressions:
rev, line = line.split(':', 1)
out.write("%s", rev)
out.write(':')
out.project(project.relpath)
out.project(_RelPath(project))
out.write('/')
out.write("%s", line)
out.nl()
elif full_name:
for line in r:
out.project(project.relpath)
out.project(_RelPath(project))
out.write('/')
out.write("%s", line)
out.nl()
@@ -239,7 +240,7 @@ contain a line that matches both expressions:
cmd_argv.append(args[0])
args = args[1:]
projects = self.GetProjects(args)
projects = self.GetProjects(args, all_manifests=not opt.this_manifest_only)
full_name = False
if len(projects) > 1:
@@ -259,7 +260,7 @@ contain a line that matches both expressions:
opt.jobs,
functools.partial(self._ExecuteOne, cmd_argv),
projects,
callback=functools.partial(self._ProcessResults, full_name, have_rev),
callback=functools.partial(self._ProcessResults, full_name, have_rev, opt),
output=out,
ordered=True)

View File

@@ -61,6 +61,8 @@ class Info(PagedCommand):
self.opt = opt
if not opt.this_manifest_only:
self.manifest = self.manifest.outer_client
manifestConfig = self.manifest.manifestProject.config
mergeBranch = manifestConfig.GetBranch("default").merge
manifestGroups = (manifestConfig.GetString('manifest.groups')
@@ -80,17 +82,17 @@ class Info(PagedCommand):
self.printSeparator()
if not opt.overview:
self.printDiffInfo(args)
self._printDiffInfo(opt, args)
else:
self.printCommitOverview(args)
self._printCommitOverview(opt, args)
def printSeparator(self):
self.text("----------------------------")
self.out.nl()
def printDiffInfo(self, args):
def _printDiffInfo(self, opt, args):
# We let exceptions bubble up to main as they'll be well structured.
projs = self.GetProjects(args)
projs = self.GetProjects(args, all_manifests=not opt.this_manifest_only)
for p in projs:
self.heading("Project: ")
@@ -179,9 +181,9 @@ class Info(PagedCommand):
self.text(" ".join(split[1:]))
self.out.nl()
def printCommitOverview(self, args):
def _printCommitOverview(self, opt, args):
all_branches = []
for project in self.GetProjects(args):
for project in self.GetProjects(args, all_manifests=not opt.this_manifest_only):
br = [project.GetUploadableBranch(x)
for x in project.GetBranches()]
br = [x for x in br if x]
@@ -200,7 +202,7 @@ class Info(PagedCommand):
if project != branch.project:
project = branch.project
self.out.nl()
self.headtext(project.relpath)
self.headtext(project.RelPath(local=opt.this_manifest_only))
self.out.nl()
commits = branch.commits

View File

@@ -32,6 +32,7 @@ from wrapper import Wrapper
class Init(InteractiveCommand, MirrorSafeCommand):
COMMON = True
MULTI_MANIFEST_SUPPORT = False
helpSummary = "Initialize a repo client checkout in the current directory"
helpUsage = """
%prog [options] [manifest url]
@@ -90,6 +91,17 @@ to update the working directory files.
def _Options(self, p, gitc_init=False):
Wrapper().InitParser(p, gitc_init=gitc_init)
m = p.add_option_group('Multi-manifest')
m.add_option('--outer-manifest', action='store_true',
help='operate starting at the outermost manifest')
m.add_option('--no-outer-manifest', dest='outer_manifest',
action='store_false', default=None,
help='do not operate on outer manifests')
m.add_option('--this-manifest-only', action='store_true', default=None,
help='only operate on this (sub)manifest')
m.add_option('--no-this-manifest-only', '--all-manifests',
dest='this_manifest_only', action='store_false',
help='operate on this manifest and its submanifests')
def _RegisteredEnvironmentOptions(self):
return {'REPO_MANIFEST_URL': 'manifest_url',

View File

@@ -77,16 +77,17 @@ This is similar to running: repo forall -c 'echo "$REPO_PATH : $REPO_PROJECT"'.
args: Positional args. Can be a list of projects to list, or empty.
"""
if not opt.regex:
projects = self.GetProjects(args, groups=opt.groups, missing_ok=opt.all)
projects = self.GetProjects(args, groups=opt.groups, missing_ok=opt.all,
all_manifests=not opt.this_manifest_only)
else:
projects = self.FindProjects(args)
projects = self.FindProjects(args, all_manifests=not opt.this_manifest_only)
def _getpath(x):
if opt.fullpath:
return x.worktree
if opt.relative_to:
return os.path.relpath(x.worktree, opt.relative_to)
return x.relpath
return x.RelPath(local=opt.this_manifest_only)
lines = []
for project in projects:

View File

@@ -15,6 +15,7 @@
import json
import os
import sys
import optparse
from command import PagedCommand
@@ -75,7 +76,7 @@ to indicate the remote ref to push changes to via 'repo upload'.
p.add_option('-o', '--output-file',
dest='output_file',
default='-',
help='file to save the manifest to',
help='file to save the manifest to. (Filename prefix for multi-tree.)',
metavar='-|NAME.xml')
def _Output(self, opt):
@@ -83,36 +84,45 @@ to indicate the remote ref to push changes to via 'repo upload'.
if opt.manifest_name:
self.manifest.Override(opt.manifest_name, False)
if opt.output_file == '-':
fd = sys.stdout
else:
fd = open(opt.output_file, 'w')
for manifest in self.ManifestList(opt):
output_file = opt.output_file
if output_file == '-':
fd = sys.stdout
else:
if manifest.path_prefix:
output_file = f'{opt.output_file}:{manifest.path_prefix.replace("/", "%2f")}'
fd = open(output_file, 'w')
self.manifest.SetUseLocalManifests(not opt.ignore_local_manifests)
manifest.SetUseLocalManifests(not opt.ignore_local_manifests)
if opt.json:
print('warning: --json is experimental!', file=sys.stderr)
doc = self.manifest.ToDict(peg_rev=opt.peg_rev,
peg_rev_upstream=opt.peg_rev_upstream,
peg_rev_dest_branch=opt.peg_rev_dest_branch)
if opt.json:
print('warning: --json is experimental!', file=sys.stderr)
doc = manifest.ToDict(peg_rev=opt.peg_rev,
peg_rev_upstream=opt.peg_rev_upstream,
peg_rev_dest_branch=opt.peg_rev_dest_branch)
json_settings = {
# JSON style guide says Uunicode characters are fully allowed.
'ensure_ascii': False,
# We use 2 space indent to match JSON style guide.
'indent': 2 if opt.pretty else None,
'separators': (',', ': ') if opt.pretty else (',', ':'),
'sort_keys': True,
}
fd.write(json.dumps(doc, **json_settings))
else:
manifest.Save(fd,
peg_rev=opt.peg_rev,
peg_rev_upstream=opt.peg_rev_upstream,
peg_rev_dest_branch=opt.peg_rev_dest_branch)
if output_file != '-':
fd.close()
if manifest.path_prefix:
print(f'Saved {manifest.path_prefix} submanifest to {output_file}',
file=sys.stderr)
else:
print(f'Saved manifest to {output_file}', file=sys.stderr)
json_settings = {
# JSON style guide says Uunicode characters are fully allowed.
'ensure_ascii': False,
# We use 2 space indent to match JSON style guide.
'indent': 2 if opt.pretty else None,
'separators': (',', ': ') if opt.pretty else (',', ':'),
'sort_keys': True,
}
fd.write(json.dumps(doc, **json_settings))
else:
self.manifest.Save(fd,
peg_rev=opt.peg_rev,
peg_rev_upstream=opt.peg_rev_upstream,
peg_rev_dest_branch=opt.peg_rev_dest_branch)
fd.close()
if opt.output_file != '-':
print('Saved manifest to %s' % opt.output_file, file=sys.stderr)
def ValidateOptions(self, opt, args):
if args:

View File

@@ -47,7 +47,7 @@ are displayed.
def Execute(self, opt, args):
all_branches = []
for project in self.GetProjects(args):
for project in self.GetProjects(args, all_manifests=not opt.this_manifest_only):
br = [project.GetUploadableBranch(x)
for x in project.GetBranches()]
br = [x for x in br if x]
@@ -76,7 +76,7 @@ are displayed.
if project != branch.project:
project = branch.project
out.nl()
out.project('project %s/' % project.relpath)
out.project('project %s/' % project.RelPath(local=opt.this_manifest_only))
out.nl()
commits = branch.commits

View File

@@ -31,7 +31,7 @@ class Prune(PagedCommand):
return project.PruneHeads()
def Execute(self, opt, args):
projects = self.GetProjects(args)
projects = self.GetProjects(args, all_manifests=not opt.this_manifest_only)
# NB: Should be able to refactor this module to display summary as results
# come back from children.
@@ -63,7 +63,7 @@ class Prune(PagedCommand):
if project != branch.project:
project = branch.project
out.nl()
out.project('project %s/' % project.relpath)
out.project('project %s/' % project.RelPath(local=opt.this_manifest_only))
out.nl()
print('%s %-33s ' % (

View File

@@ -69,7 +69,7 @@ branch but need to incorporate new upstream changes "underneath" them.
'consistent if you previously synced to a manifest)')
def Execute(self, opt, args):
all_projects = self.GetProjects(args)
all_projects = self.GetProjects(args, all_manifests=not opt.this_manifest_only)
one_project = len(all_projects) == 1
if opt.interactive and not one_project:
@@ -98,6 +98,7 @@ branch but need to incorporate new upstream changes "underneath" them.
config = self.manifest.manifestProject.config
out = RebaseColoring(config)
out.redirect(sys.stdout)
_RelPath = lambda p: p.RelPath(local=opt.this_manifest_only)
ret = 0
for project in all_projects:
@@ -107,7 +108,7 @@ branch but need to incorporate new upstream changes "underneath" them.
cb = project.CurrentBranch
if not cb:
if one_project:
print("error: project %s has a detached HEAD" % project.relpath,
print("error: project %s has a detached HEAD" % _RelPath(project),
file=sys.stderr)
return 1
# ignore branches with detatched HEADs
@@ -117,7 +118,7 @@ branch but need to incorporate new upstream changes "underneath" them.
if not upbranch.LocalMerge:
if one_project:
print("error: project %s does not track any remote branches"
% project.relpath, file=sys.stderr)
% _RelPath(project), file=sys.stderr)
return 1
# ignore branches without remotes
continue
@@ -130,7 +131,7 @@ branch but need to incorporate new upstream changes "underneath" them.
args.append(upbranch.LocalMerge)
out.project('project %s: rebasing %s -> %s',
project.relpath, cb, upbranch.LocalMerge)
_RelPath(project), cb, upbranch.LocalMerge)
out.nl()
out.flush()

View File

@@ -50,7 +50,9 @@ The '%prog' command stages files to prepare the next commit.
self.Usage()
def _Interactive(self, opt, args):
all_projects = [p for p in self.GetProjects(args) if p.IsDirty()]
all_projects = [
p for p in self.GetProjects(args, all_manifests=not opt.this_manifest_only)
if p.IsDirty()]
if not all_projects:
print('no projects have uncommitted modifications', file=sys.stderr)
return
@@ -62,7 +64,8 @@ The '%prog' command stages files to prepare the next commit.
for i in range(len(all_projects)):
project = all_projects[i]
out.write('%3d: %s', i + 1, project.relpath + '/')
out.write('%3d: %s', i + 1,
project.RelPath(local=opt.this_manifest_only) + '/')
out.nl()
out.nl()
@@ -99,7 +102,9 @@ The '%prog' command stages files to prepare the next commit.
_AddI(all_projects[a_index - 1])
continue
projects = [p for p in all_projects if a in [p.name, p.relpath]]
projects = [
p for p in all_projects
if a in [p.name, p.RelPath(local=opt.this_manifest_only)]]
if len(projects) == 1:
_AddI(projects[0])
continue

View File

@@ -84,7 +84,8 @@ revision specified in the manifest.
projects = ['.'] # start it in the local project by default
all_projects = self.GetProjects(projects,
missing_ok=bool(self.gitc_manifest))
missing_ok=bool(self.gitc_manifest),
all_manifests=not opt.this_manifest_only)
# This must happen after we find all_projects, since GetProjects may need
# the local directory, which will disappear once we save the GITC manifest.
@@ -137,6 +138,6 @@ revision specified in the manifest.
if err:
for p in err:
print("error: %s/: cannot start %s" % (p.relpath, nb),
print("error: %s/: cannot start %s" % (p.RelPath(local=opt.this_manifest_only), nb),
file=sys.stderr)
sys.exit(1)

View File

@@ -117,7 +117,7 @@ the following meanings:
outstring.append(''.join([status_header, item, '/']))
def Execute(self, opt, args):
all_projects = self.GetProjects(args)
all_projects = self.GetProjects(args, all_manifests=not opt.this_manifest_only)
def _ProcessResults(_pool, _output, results):
ret = 0
@@ -141,9 +141,10 @@ the following meanings:
if opt.orphans:
proj_dirs = set()
proj_dirs_parents = set()
for project in self.GetProjects(None, missing_ok=True):
proj_dirs.add(project.relpath)
(head, _tail) = os.path.split(project.relpath)
for project in self.GetProjects(None, missing_ok=True, all_manifests=not opt.this_manifest_only):
relpath = project.RelPath(local=opt.this_manifest_only)
proj_dirs.add(relpath)
(head, _tail) = os.path.split(relpath)
while head != "":
proj_dirs_parents.add(head)
(head, _tail) = os.path.split(head)

View File

@@ -66,6 +66,7 @@ _ONE_DAY_S = 24 * 60 * 60
class Sync(Command, MirrorSafeCommand):
jobs = 1
COMMON = True
MULTI_MANIFEST_SUPPORT = False
helpSummary = "Update working tree to the latest revision"
helpUsage = """
%prog [<project>...]
@@ -704,7 +705,7 @@ later is required to fix a server side protocol bug.
if project.relpath:
new_project_paths.append(project.relpath)
file_name = 'project.list'
file_path = os.path.join(self.repodir, file_name)
file_path = os.path.join(self.manifest.subdir, file_name)
old_project_paths = []
if os.path.exists(file_path):
@@ -760,7 +761,7 @@ later is required to fix a server side protocol bug.
}
copylinkfile_name = 'copy-link-files.json'
copylinkfile_path = os.path.join(self.manifest.repodir, copylinkfile_name)
copylinkfile_path = os.path.join(self.manifest.subdir, copylinkfile_name)
old_copylinkfile_paths = {}
if os.path.exists(copylinkfile_path):
@@ -932,6 +933,9 @@ later is required to fix a server side protocol bug.
if opt.prune is None:
opt.prune = True
if self.manifest.is_multimanifest and not opt.this_manifest_only and args:
self.OptionParser.error('partial syncs must use --this-manifest-only')
def Execute(self, opt, args):
if opt.jobs:
self.jobs = opt.jobs

View File

@@ -226,7 +226,8 @@ Gerrit Code Review: https://www.gerritcodereview.com/
destination = opt.dest_branch or project.dest_branch or project.revisionExpr
print('Upload project %s/ to remote branch %s%s:' %
(project.relpath, destination, ' (private)' if opt.private else ''))
(project.RelPath(local=opt.this_manifest_only), destination,
' (private)' if opt.private else ''))
print(' branch %s (%2d commit%s, %s):' % (
name,
len(commit_list),
@@ -262,7 +263,7 @@ Gerrit Code Review: https://www.gerritcodereview.com/
script.append('# Uncomment the branches to upload:')
for project, avail in pending:
script.append('#')
script.append('# project %s/:' % project.relpath)
script.append('# project %s/:' % project.RelPath(local=opt.this_manifest_only))
b = {}
for branch in avail:
@@ -285,7 +286,7 @@ Gerrit Code Review: https://www.gerritcodereview.com/
script.append('# %s' % commit)
b[name] = branch
projects[project.relpath] = project
projects[project.RelPath(local=opt.this_manifest_only)] = project
branches[project.name] = b
script.append('')
@@ -313,7 +314,7 @@ Gerrit Code Review: https://www.gerritcodereview.com/
_die('project for branch %s not in script', name)
branch = branches[project.name].get(name)
if not branch:
_die('branch %s not in %s', name, project.relpath)
_die('branch %s not in %s', name, project.RelPath(local=opt.this_manifest_only))
todo.append(branch)
if not todo:
_die("nothing uncommented for upload")
@@ -481,7 +482,7 @@ Gerrit Code Review: https://www.gerritcodereview.com/
else:
fmt = '\n (%s)'
print(('[FAILED] %-15s %-15s' + fmt) % (
branch.project.relpath + '/',
branch.project.RelPath(local=opt.this_manifest_only) + '/',
branch.name,
str(branch.error)),
file=sys.stderr)
@@ -490,7 +491,7 @@ Gerrit Code Review: https://www.gerritcodereview.com/
for branch in todo:
if branch.uploaded:
print('[OK ] %-15s %s' % (
branch.project.relpath + '/',
branch.project.RelPath(local=opt.this_manifest_only) + '/',
branch.name),
file=sys.stderr)
@@ -524,7 +525,7 @@ Gerrit Code Review: https://www.gerritcodereview.com/
return (project, avail)
def Execute(self, opt, args):
projects = self.GetProjects(args)
projects = self.GetProjects(args, all_manifests=not opt.this_manifest_only)
def _ProcessResults(_pool, _out, results):
pending = []
@@ -534,7 +535,8 @@ Gerrit Code Review: https://www.gerritcodereview.com/
print('repo: error: %s: Unable to upload branch "%s". '
'You might be able to fix the branch by running:\n'
' git branch --set-upstream-to m/%s' %
(project.relpath, project.CurrentBranch, self.manifest.branch),
(project.RelPath(local=opt.this_manifest_only), project.CurrentBranch,
project.manifest.branch),
file=sys.stderr)
elif avail:
pending.append(result)
@@ -554,15 +556,23 @@ Gerrit Code Review: https://www.gerritcodereview.com/
(opt.branch,), file=sys.stderr)
return 1
pending_proj_names = [project.name for (project, available) in pending]
pending_worktrees = [project.worktree for (project, available) in pending]
hook = RepoHook.FromSubcmd(
hook_type='pre-upload', manifest=self.manifest,
opt=opt, abort_if_user_denies=True)
if not hook.Run(
project_list=pending_proj_names,
worktree_list=pending_worktrees):
return 1
manifests = {project.manifest.topdir: project.manifest
for (project, available) in pending}
ret = 0
for manifest in manifests.values():
pending_proj_names = [project.name for (project, available) in pending
if project.manifest.topdir == manifest.topdir]
pending_worktrees = [project.worktree for (project, available) in pending
if project.manifest.topdir == manifest.topdir]
hook = RepoHook.FromSubcmd(
hook_type='pre-upload', manifest=manifest,
opt=opt, abort_if_user_denies=True)
if not hook.Run(
project_list=pending_proj_names,
worktree_list=pending_worktrees):
ret = 1
if ret:
return ret
reviewers = _SplitEmails(opt.reviewers) if opt.reviewers else []
cc = _SplitEmails(opt.cc) if opt.cc else []