summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/manifest-format.txt13
-rw-r--r--manifest_xml.py39
2 files changed, 44 insertions, 8 deletions
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:
63 <!ELEMENT repo-hooks (EMPTY)> 63 <!ELEMENT repo-hooks (EMPTY)>
64 <!ATTLIST repo-hooks in-project CDATA #REQUIRED> 64 <!ATTLIST repo-hooks in-project CDATA #REQUIRED>
65 <!ATTLIST repo-hooks enabled-list CDATA #REQUIRED> 65 <!ATTLIST repo-hooks enabled-list CDATA #REQUIRED>
66
67 <!ELEMENT include (EMPTY)>
68 <!ATTLIST include name CDATA #REQUIRED>
66 ]> 69 ]>
67 70
68A description of the elements and their attributes follows. 71A description of the elements and their attributes follows.
@@ -192,6 +195,16 @@ This element is mostly useful in the local_manifest.xml, where
192the user can remove a project, and possibly replace it with their 195the user can remove a project, and possibly replace it with their
193own definition. 196own definition.
194 197
198Element include
199---------------
200
201This element provides the capability of including another manifest
202file into the originating manifest. Normal rules apply for the
203target manifest to include- it must be a usable manifest on it's own.
204
205Attribute `name`; the manifest to include, specified relative to
206the manifest repositories root.
207
195 208
196Local Manifest 209Local Manifest
197============== 210==============
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):
298 298
299 self._loaded = True 299 self._loaded = True
300 300
301 def _ParseManifest(self, is_root_file): 301 def _ParseManifestObject(self, path):
302 root = xml.dom.minidom.parse(self.manifestFile) 302 root = xml.dom.minidom.parse(path)
303 if not root or not root.childNodes: 303 if not root or not root.childNodes:
304 raise ManifestParseError( 304 raise ManifestParseError("no root node in %s" % (path,))
305 "no root node in %s" %
306 self.manifestFile)
307 305
308 config = root.childNodes[0] 306 config = root.childNodes[0]
309 if config.nodeName != 'manifest': 307 if config.nodeName != 'manifest':
310 raise ManifestParseError( 308 raise ManifestParseError("no <manifest> in %s" % (path,))
311 "no <manifest> in %s" % 309
312 self.manifestFile) 310 return config
311
312 def _ParseManifest(self, is_root_file):
313 config = self._ParseManifestObject(self.manifestFile)
314
315 for node in config.childNodes:
316 if node.nodeName == 'include':
317 name = self._reqatt(node, 'name')
318 fp = os.path.join(self.manifestProject.worktree, name)
319 if not os.path.isfile(fp):
320 raise ManifestParseError, \
321 "include %s doesn't exist or isn't a file" % \
322 (name,)
323 try:
324 subconfig = self._ParseManifestObject(fp)
325 # should isolate this to the exact exception, but that's
326 # tricky. actual parsing implementation may vary.
327 except (KeyboardInterrupt, RuntimeError, SystemExit):
328 raise
329 except Exception, e:
330 raise ManifestParseError(
331 "failed parsing included manifest %s: %s", (name, e))
332
333 for sub_node in subconfig.childNodes:
334 config.appendChild(sub_node.cloneNode(True))
335
313 336
314 for node in config.childNodes: 337 for node in config.childNodes:
315 if node.nodeName == 'remove-project': 338 if node.nodeName == 'remove-project':