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>
diff --git a/main.py b/main.py
index 6fb688c..34dfb77 100755
--- a/main.py
+++ b/main.py
@@ -310,7 +310,7 @@
# (sub)manifest, and then any child submanifests.
result = cmd.Execute(copts, cargs)
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
child_argv = argv[:]
child_argv.append('--no-outer-manifest')
diff --git a/manifest_xml.py b/manifest_xml.py
index 7d19d63..dbab974 100644
--- a/manifest_xml.py
+++ b/manifest_xml.py
@@ -215,8 +215,9 @@
manifestName: a string, the submanifest file name.
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.
+ parent: an XmlManifest, the parent manifest.
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,
name,
@@ -234,6 +235,7 @@
self.manifestName = manifestName
self.groups = groups
self.path = path
+ self.parent = parent
self.annotations = []
outer_client = parent._outer_client or parent
if self.remote and not self.project:
@@ -268,10 +270,10 @@
def __ne__(self, other):
return not self.__eq__(other)
- def ToSubmanifestSpec(self, root):
+ def ToSubmanifestSpec(self):
"""Return a SubmanifestSpec object, populating attributes"""
- mp = root.manifestProject
- remote = root.remotes[self.remote or root.default.remote.name]
+ mp = self.parent.manifestProject
+ 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 not, use this manifestProject's url.
if self.project:
@@ -348,6 +350,11 @@
if manifest_file != os.path.abspath(manifest_file):
raise ManifestParseError('manifest_file must be abspath')
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._load_local_manifests = True
self.parent_groups = parent_groups
@@ -396,14 +403,10 @@
if not os.path.isfile(path):
raise ManifestParseError('manifest %s not found' % name)
- old = self.manifestFile
- try:
- self._load_local_manifests = load_local_manifests
- self.manifestFile = path
- self.Unload()
- self._Load()
- finally:
- self.manifestFile = old
+ self._load_local_manifests = load_local_manifests
+ self._outer_client.manifestFileOverrides[self.path_prefix] = path
+ self.Unload()
+ self._Load()
def Link(self, name):
"""Update the repo metadata to use a different manifest.
@@ -880,6 +883,10 @@
exclude = self.manifest.manifestProject.partial_clone_exclude or ''
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
def UseLocalManifests(self):
return self._load_local_manifests
@@ -1005,57 +1012,66 @@
# This will load all clients.
self._outer_client._Load(initial_client=self)
- m = self.manifestProject
- b = m.GetBranch(m.CurrentBranch).merge
- if b is not None and b.startswith(R_HEADS):
- b = b[len(R_HEADS):]
- 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
+ savedManifestFile = self.manifestFile
+ override = self._outer_client.manifestFileOverrides.get(self.path_prefix)
+ if override:
+ self.manifestFile = override
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
+ m = self.manifestProject
+ b = m.GetBranch(m.CurrentBranch).merge
+ if b is not None and b.startswith(R_HEADS):
+ b = b[len(R_HEADS):]
+ self.branch = b
- if self.IsMirror:
- self._AddMetaProjectMirror(self.repoProject)
- self._AddMetaProjectMirror(self.manifestProject)
+ parent_groups = self.parent_groups
+ if self.path_prefix:
+ 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
# as well. We need to do this after self._loaded is set to avoid looping.
for name in self._submanifests:
tree = self._submanifests[name]
- spec = tree.ToSubmanifestSpec(self)
+ spec = tree.ToSubmanifestSpec()
present = os.path.exists(os.path.join(self.subdir, MANIFEST_FILE_NAME))
if present and tree.present and not tree.repo_client:
if initial_client and initial_client.topdir == self.topdir:
diff --git a/project.py b/project.py
index 7da7b1d..aeb092c 100644
--- a/project.py
+++ b/project.py
@@ -3760,7 +3760,7 @@
if not this_manifest_only:
for submanifest in self.manifest.submanifests.values():
- spec = submanifest.ToSubmanifestSpec(root=self.manifest.outer_client)
+ spec = submanifest.ToSubmanifestSpec()
submanifest.repo_client.manifestProject.Sync(
manifest_url=spec.manifestUrl,
manifest_branch=spec.revision,