Override the manifest for the entire command

When a manifest file is overridden, remember that and keep using the
override for the remainder of the process.  If we need to revert it,
make the override name evaluate False.

Change-Id: I1eee05fec6988c1ee4a3c751c4b540d5b5d11797
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/335136
Tested-by: LaMont Jones <lamontjones@google.com>
Reviewed-by: Mike Frysinger <vapier@google.com>
This commit is contained in:
LaMont Jones 2022-04-14 15:00:09 +00:00
parent a46047a822
commit b90a422ab6
3 changed files with 72 additions and 56 deletions

View File

@ -310,7 +310,7 @@ class _Repo(object):
# (sub)manifest, and then any child submanifests. # (sub)manifest, and then any child submanifests.
result = cmd.Execute(copts, cargs) result = cmd.Execute(copts, cargs)
for submanifest in repo_client.manifest.submanifests.values(): for submanifest in repo_client.manifest.submanifests.values():
spec = submanifest.ToSubmanifestSpec(root=repo_client.outer_client) spec = submanifest.ToSubmanifestSpec()
gopts.submanifest_path = submanifest.repo_client.path_prefix gopts.submanifest_path = submanifest.repo_client.path_prefix
child_argv = argv[:] child_argv = argv[:]
child_argv.append('--no-outer-manifest') child_argv.append('--no-outer-manifest')

View File

@ -215,8 +215,9 @@ class _XmlSubmanifest:
manifestName: a string, the submanifest file name. manifestName: a string, the submanifest file name.
groups: a list of strings, the groups to add to all projects in the submanifest. groups: a list of strings, the groups to add to all projects in the submanifest.
path: a string, the relative path for the submanifest checkout. path: a string, the relative path for the submanifest checkout.
parent: an XmlManifest, the parent manifest.
annotations: (derived) a list of annotations. annotations: (derived) a list of annotations.
present: (derived) a boolean, whether the submanifest's manifest file is present. present: (derived) a boolean, whether the sub manifest file is present.
""" """
def __init__(self, def __init__(self,
name, name,
@ -234,6 +235,7 @@ class _XmlSubmanifest:
self.manifestName = manifestName self.manifestName = manifestName
self.groups = groups self.groups = groups
self.path = path self.path = path
self.parent = parent
self.annotations = [] self.annotations = []
outer_client = parent._outer_client or parent outer_client = parent._outer_client or parent
if self.remote and not self.project: if self.remote and not self.project:
@ -268,10 +270,10 @@ class _XmlSubmanifest:
def __ne__(self, other): def __ne__(self, other):
return not self.__eq__(other) return not self.__eq__(other)
def ToSubmanifestSpec(self, root): def ToSubmanifestSpec(self):
"""Return a SubmanifestSpec object, populating attributes""" """Return a SubmanifestSpec object, populating attributes"""
mp = root.manifestProject mp = self.parent.manifestProject
remote = root.remotes[self.remote or root.default.remote.name] remote = self.parent.remotes[self.remote or self.parent.default.remote.name]
# If a project was given, generate the url from the remote and project. # If a project was given, generate the url from the remote and project.
# If not, use this manifestProject's url. # If not, use this manifestProject's url.
if self.project: if self.project:
@ -348,6 +350,11 @@ class XmlManifest(object):
if manifest_file != os.path.abspath(manifest_file): if manifest_file != os.path.abspath(manifest_file):
raise ManifestParseError('manifest_file must be abspath') raise ManifestParseError('manifest_file must be abspath')
self.manifestFile = manifest_file self.manifestFile = manifest_file
if not outer_client or outer_client == self:
# manifestFileOverrides only exists in the outer_client's manifest, since
# that is the only instance left when Unload() is called on the outer
# manifest.
self.manifestFileOverrides = {}
self.local_manifests = local_manifests self.local_manifests = local_manifests
self._load_local_manifests = True self._load_local_manifests = True
self.parent_groups = parent_groups self.parent_groups = parent_groups
@ -396,14 +403,10 @@ class XmlManifest(object):
if not os.path.isfile(path): if not os.path.isfile(path):
raise ManifestParseError('manifest %s not found' % name) raise ManifestParseError('manifest %s not found' % name)
old = self.manifestFile self._load_local_manifests = load_local_manifests
try: self._outer_client.manifestFileOverrides[self.path_prefix] = path
self._load_local_manifests = load_local_manifests self.Unload()
self.manifestFile = path self._Load()
self.Unload()
self._Load()
finally:
self.manifestFile = old
def Link(self, name): def Link(self, name):
"""Update the repo metadata to use a different manifest. """Update the repo metadata to use a different manifest.
@ -880,6 +883,10 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
exclude = self.manifest.manifestProject.partial_clone_exclude or '' exclude = self.manifest.manifestProject.partial_clone_exclude or ''
return set(x.strip() for x in exclude.split(',')) return set(x.strip() for x in exclude.split(','))
def SetManifestOverride(self, path):
"""Override manifestFile. The caller must call Unload()"""
self._outer_client.manifest.manifestFileOverrides[self.path_prefix] = path
@property @property
def UseLocalManifests(self): def UseLocalManifests(self):
return self._load_local_manifests return self._load_local_manifests
@ -1005,57 +1012,66 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md
# This will load all clients. # This will load all clients.
self._outer_client._Load(initial_client=self) self._outer_client._Load(initial_client=self)
m = self.manifestProject savedManifestFile = self.manifestFile
b = m.GetBranch(m.CurrentBranch).merge override = self._outer_client.manifestFileOverrides.get(self.path_prefix)
if b is not None and b.startswith(R_HEADS): if override:
b = b[len(R_HEADS):] self.manifestFile = override
self.branch = b
parent_groups = self.parent_groups
if self.path_prefix:
parent_groups = f'{SUBMANIFEST_GROUP_PREFIX}:path:{self.path_prefix},{parent_groups}'
# The manifestFile was specified by the user which is why we allow include
# paths to point anywhere.
nodes = []
nodes.append(self._ParseManifestXml(
self.manifestFile, self.manifestProject.worktree,
parent_groups=parent_groups, restrict_includes=False))
if self._load_local_manifests and self.local_manifests:
try:
for local_file in sorted(platform_utils.listdir(self.local_manifests)):
if local_file.endswith('.xml'):
local = os.path.join(self.local_manifests, local_file)
# Since local manifests are entirely managed by the user, allow
# them to point anywhere the user wants.
local_group = f'{LOCAL_MANIFEST_GROUP_PREFIX}:{local_file[:-4]}'
nodes.append(self._ParseManifestXml(
local, self.subdir,
parent_groups=f'{local_group},{parent_groups}',
restrict_includes=False))
except OSError:
pass
try: try:
self._ParseManifest(nodes) m = self.manifestProject
except ManifestParseError as e: b = m.GetBranch(m.CurrentBranch).merge
# There was a problem parsing, unload ourselves in case they catch if b is not None and b.startswith(R_HEADS):
# this error and try again later, we will show the correct error b = b[len(R_HEADS):]
self.Unload() self.branch = b
raise e
if self.IsMirror: parent_groups = self.parent_groups
self._AddMetaProjectMirror(self.repoProject) if self.path_prefix:
self._AddMetaProjectMirror(self.manifestProject) parent_groups = f'{SUBMANIFEST_GROUP_PREFIX}:path:{self.path_prefix},{parent_groups}'
self._loaded = True # The manifestFile was specified by the user which is why we allow include
# paths to point anywhere.
nodes = []
nodes.append(self._ParseManifestXml(
self.manifestFile, self.manifestProject.worktree,
parent_groups=parent_groups, restrict_includes=False))
if self._load_local_manifests and self.local_manifests:
try:
for local_file in sorted(platform_utils.listdir(self.local_manifests)):
if local_file.endswith('.xml'):
local = os.path.join(self.local_manifests, local_file)
# Since local manifests are entirely managed by the user, allow
# them to point anywhere the user wants.
local_group = f'{LOCAL_MANIFEST_GROUP_PREFIX}:{local_file[:-4]}'
nodes.append(self._ParseManifestXml(
local, self.subdir,
parent_groups=f'{local_group},{parent_groups}',
restrict_includes=False))
except OSError:
pass
try:
self._ParseManifest(nodes)
except ManifestParseError as e:
# There was a problem parsing, unload ourselves in case they catch
# this error and try again later, we will show the correct error
self.Unload()
raise e
if self.IsMirror:
self._AddMetaProjectMirror(self.repoProject)
self._AddMetaProjectMirror(self.manifestProject)
self._loaded = True
finally:
if override:
self.manifestFile = savedManifestFile
# Now that we have loaded this manifest, load any submanifest manifests # Now that we have loaded this manifest, load any submanifest manifests
# as well. We need to do this after self._loaded is set to avoid looping. # as well. We need to do this after self._loaded is set to avoid looping.
for name in self._submanifests: for name in self._submanifests:
tree = self._submanifests[name] tree = self._submanifests[name]
spec = tree.ToSubmanifestSpec(self) spec = tree.ToSubmanifestSpec()
present = os.path.exists(os.path.join(self.subdir, MANIFEST_FILE_NAME)) present = os.path.exists(os.path.join(self.subdir, MANIFEST_FILE_NAME))
if present and tree.present and not tree.repo_client: if present and tree.present and not tree.repo_client:
if initial_client and initial_client.topdir == self.topdir: if initial_client and initial_client.topdir == self.topdir:

View File

@ -3760,7 +3760,7 @@ class ManifestProject(MetaProject):
if not this_manifest_only: if not this_manifest_only:
for submanifest in self.manifest.submanifests.values(): for submanifest in self.manifest.submanifests.values():
spec = submanifest.ToSubmanifestSpec(root=self.manifest.outer_client) spec = submanifest.ToSubmanifestSpec()
submanifest.repo_client.manifestProject.Sync( submanifest.repo_client.manifestProject.Sync(
manifest_url=spec.manifestUrl, manifest_url=spec.manifestUrl,
manifest_branch=spec.revision, manifest_branch=spec.revision,