diff --git a/docs/manifest-format.txt b/docs/manifest-format.txt index 53789651..9f4585b8 100644 --- a/docs/manifest-format.txt +++ b/docs/manifest-format.txt @@ -63,6 +63,9 @@ following DTD: + + + ]> A description of the elements and their attributes follows. @@ -192,6 +195,16 @@ This element is mostly useful in the local_manifest.xml, where the user can remove a project, and possibly replace it with their own definition. +Element include +--------------- + +This element provides the capability of including another manifest +file into the originating manifest. Normal rules apply for the +target manifest to include- it must be a usable manifest on it's own. + +Attribute `name`; the manifest to include, specified relative to +the manifest repositories root. + Local Manifest ============== diff --git a/manifest_xml.py b/manifest_xml.py index ca65e33f..2927fd1c 100644 --- a/manifest_xml.py +++ b/manifest_xml.py @@ -298,18 +298,41 @@ class XmlManifest(object): self._loaded = True - def _ParseManifest(self, is_root_file): - root = xml.dom.minidom.parse(self.manifestFile) + def _ParseManifestObject(self, path): + root = xml.dom.minidom.parse(path) if not root or not root.childNodes: - raise ManifestParseError( - "no root node in %s" % - self.manifestFile) + raise ManifestParseError("no root node in %s" % (path,)) config = root.childNodes[0] if config.nodeName != 'manifest': - raise ManifestParseError( - "no in %s" % - self.manifestFile) + raise ManifestParseError("no in %s" % (path,)) + + return config + + def _ParseManifest(self, is_root_file): + config = self._ParseManifestObject(self.manifestFile) + + for node in config.childNodes: + if node.nodeName == 'include': + name = self._reqatt(node, 'name') + fp = os.path.join(self.manifestProject.worktree, 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) + # should isolate this to the exact exception, but that's + # tricky. actual parsing implementation may vary. + except (KeyboardInterrupt, RuntimeError, SystemExit): + raise + except Exception, e: + raise ManifestParseError( + "failed parsing included manifest %s: %s", (name, e)) + + for sub_node in subconfig.childNodes: + config.appendChild(sub_node.cloneNode(True)) + for node in config.childNodes: if node.nodeName == 'remove-project':