From 23acdd3f1460bc1c040b319940c5e0e8a78f1040 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Sat, 21 Apr 2012 00:33:54 -0700 Subject: [PATCH] Parse manifest and local_manifest together Combine manifest and local_manifest into a single list of elements before parsing. This will allow elements in the local_manifest to affect elements in the main manifest. Change-Id: I4d34c9260b299a76be2960b07c0c3fe1af35f33c --- manifest_xml.py | 74 ++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 41 deletions(-) diff --git a/manifest_xml.py b/manifest_xml.py index 2927fd1c..daf5740b 100644 --- a/manifest_xml.py +++ b/manifest_xml.py @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import itertools import os import re import sys @@ -281,16 +282,14 @@ class XmlManifest(object): b = b[len(R_HEADS):] self.branch = b - self._ParseManifest(True) + nodes = [] + nodes.append(self._ParseManifestXml(self.manifestFile)) local = os.path.join(self.repodir, LOCAL_MANIFEST_NAME) if os.path.exists(local): - try: - real = self.manifestFile - self.manifestFile = local - self._ParseManifest(False) - finally: - self.manifestFile = real + nodes.append(self._ParseManifestXml(local)) + + self._ParseManifest(nodes) if self.IsMirror: self._AddMetaProjectMirror(self.repoProject) @@ -298,7 +297,7 @@ class XmlManifest(object): self._loaded = True - def _ParseManifestObject(self, path): + def _ParseManifestXml(self, path): root = xml.dom.minidom.parse(path) if not root or not root.childNodes: raise ManifestParseError("no root node in %s" % (path,)) @@ -307,21 +306,17 @@ class XmlManifest(object): if config.nodeName != 'manifest': raise ManifestParseError("no in %s" % (path,)) - return config - - def _ParseManifest(self, is_root_file): - config = self._ParseManifestObject(self.manifestFile) - + nodes = [] for node in config.childNodes: if node.nodeName == 'include': name = self._reqatt(node, 'name') - fp = os.path.join(self.manifestProject.worktree, name) + fp = os.path.join(os.path.dirname(path), name) if not os.path.isfile(fp): raise ManifestParseError, \ "include %s doesn't exist or isn't a file" % \ (name,) try: - subconfig = self._ParseManifestObject(fp) + nodes.extend(self._ParseManifestXml(fp)) # should isolate this to the exact exception, but that's # tricky. actual parsing implementation may vary. except (KeyboardInterrupt, RuntimeError, SystemExit): @@ -329,27 +324,12 @@ class XmlManifest(object): except Exception, e: raise ManifestParseError( "failed parsing included manifest %s: %s", (name, e)) + else: + nodes.append(node) + return nodes - for sub_node in subconfig.childNodes: - config.appendChild(sub_node.cloneNode(True)) - - - for node in config.childNodes: - if node.nodeName == 'remove-project': - name = self._reqatt(node, 'name') - try: - del self._projects[name] - except KeyError: - raise ManifestParseError( - 'project %s not found' % - (name)) - - # If the manifest removes the hooks project, treat it as if it deleted - # the repo-hooks element too. - if self._repo_hooks_project and (self._repo_hooks_project.name == name): - self._repo_hooks_project = None - - for node in config.childNodes: + def _ParseManifest(self, node_list): + for node in itertools.chain(*node_list): if node.nodeName == 'remote': remote = self._ParseRemote(node) if self._remotes.get(remote.name): @@ -358,7 +338,7 @@ class XmlManifest(object): (remote.name, self.manifestFile)) self._remotes[remote.name] = remote - for node in config.childNodes: + for node in itertools.chain(*node_list): if node.nodeName == 'default': if self._default is not None: raise ManifestParseError( @@ -368,7 +348,7 @@ class XmlManifest(object): if self._default is None: self._default = _Default() - for node in config.childNodes: + for node in itertools.chain(*node_list): if node.nodeName == 'notice': if self._notice is not None: raise ManifestParseError( @@ -376,7 +356,7 @@ class XmlManifest(object): (self.manifestFile)) self._notice = self._ParseNotice(node) - for node in config.childNodes: + for node in itertools.chain(*node_list): if node.nodeName == 'manifest-server': url = self._reqatt(node, 'url') if self._manifest_server is not None: @@ -385,7 +365,7 @@ class XmlManifest(object): (self.manifestFile)) self._manifest_server = url - for node in config.childNodes: + for node in itertools.chain(*node_list): if node.nodeName == 'project': project = self._ParseProject(node) if self._projects.get(project.name): @@ -393,8 +373,6 @@ class XmlManifest(object): 'duplicate project %s in %s' % (project.name, self.manifestFile)) self._projects[project.name] = project - - for node in config.childNodes: if node.nodeName == 'repo-hooks': # Get the name of the project and the (space-separated) list of enabled. repo_hooks_project = self._reqatt(node, 'in-project') @@ -416,6 +394,20 @@ class XmlManifest(object): # Store the enabled hooks in the Project object. self._repo_hooks_project.enabled_repo_hooks = enabled_repo_hooks + if node.nodeName == 'remove-project': + name = self._reqatt(node, 'name') + try: + del self._projects[name] + except KeyError: + raise ManifestParseError( + 'project %s not found' % + (name)) + + # If the manifest removes the hooks project, treat it as if it deleted + # the repo-hooks element too. + if self._repo_hooks_project and (self._repo_hooks_project.name == name): + self._repo_hooks_project = None + def _AddMetaProjectMirror(self, m): name = None