diff options
-rw-r--r-- | docs/manifest-format.txt | 22 | ||||
-rw-r--r-- | manifest_xml.py | 24 |
2 files changed, 44 insertions, 2 deletions
diff --git a/docs/manifest-format.txt b/docs/manifest-format.txt index f187bfaf..65cd70bc 100644 --- a/docs/manifest-format.txt +++ b/docs/manifest-format.txt | |||
@@ -26,6 +26,7 @@ following DTD: | |||
26 | manifest-server?, | 26 | manifest-server?, |
27 | remove-project*, | 27 | remove-project*, |
28 | project*, | 28 | project*, |
29 | extend-project*, | ||
29 | repo-hooks?)> | 30 | repo-hooks?)> |
30 | 31 | ||
31 | <!ELEMENT notice (#PCDATA)> | 32 | <!ELEMENT notice (#PCDATA)> |
@@ -67,6 +68,11 @@ following DTD: | |||
67 | <!ATTLIST annotation value CDATA #REQUIRED> | 68 | <!ATTLIST annotation value CDATA #REQUIRED> |
68 | <!ATTLIST annotation keep CDATA "true"> | 69 | <!ATTLIST annotation keep CDATA "true"> |
69 | 70 | ||
71 | <!ELEMENT extend-project> | ||
72 | <!ATTLIST extend-project name CDATA #REQUIRED> | ||
73 | <!ATTLIST extend-project path CDATA #IMPLIED> | ||
74 | <!ATTLIST extend-project groups CDATA #IMPLIED> | ||
75 | |||
70 | <!ELEMENT remove-project (EMPTY)> | 76 | <!ELEMENT remove-project (EMPTY)> |
71 | <!ATTLIST remove-project name CDATA #REQUIRED> | 77 | <!ATTLIST remove-project name CDATA #REQUIRED> |
72 | 78 | ||
@@ -252,6 +258,22 @@ rather than the `name` attribute. This attribute only applies to the | |||
252 | local mirrors syncing, it will be ignored when syncing the projects in a | 258 | local mirrors syncing, it will be ignored when syncing the projects in a |
253 | client working directory. | 259 | client working directory. |
254 | 260 | ||
261 | Element extend-project | ||
262 | ---------------------- | ||
263 | |||
264 | Modify the attributes of the named project. | ||
265 | |||
266 | This element is mostly useful in a local manifest file, to modify the | ||
267 | attributes of an existing project without completely replacing the | ||
268 | existing project definition. This makes the local manifest more robust | ||
269 | against changes to the original manifest. | ||
270 | |||
271 | Attribute `path`: If specified, limit the change to projects checked out | ||
272 | at the specified path, rather than all projects with the given name. | ||
273 | |||
274 | Attribute `groups`: List of additional groups to which this project | ||
275 | belongs. Same syntax as the corresponding element of `project`. | ||
276 | |||
255 | Element annotation | 277 | Element annotation |
256 | ------------------ | 278 | ------------------ |
257 | 279 | ||
diff --git a/manifest_xml.py b/manifest_xml.py index fdc31778..bd1ab69b 100644 --- a/manifest_xml.py +++ b/manifest_xml.py | |||
@@ -164,6 +164,9 @@ class XmlManifest(object): | |||
164 | if r.revision is not None: | 164 | if r.revision is not None: |
165 | e.setAttribute('revision', r.revision) | 165 | e.setAttribute('revision', r.revision) |
166 | 166 | ||
167 | def _ParseGroups(self, groups): | ||
168 | return [x for x in re.split(r'[,\s]+', groups) if x] | ||
169 | |||
167 | def Save(self, fd, peg_rev=False, peg_rev_upstream=True): | 170 | def Save(self, fd, peg_rev=False, peg_rev_upstream=True): |
168 | """Write the current manifest out to the given file descriptor. | 171 | """Write the current manifest out to the given file descriptor. |
169 | """ | 172 | """ |
@@ -171,7 +174,7 @@ class XmlManifest(object): | |||
171 | 174 | ||
172 | groups = mp.config.GetString('manifest.groups') | 175 | groups = mp.config.GetString('manifest.groups') |
173 | if groups: | 176 | if groups: |
174 | groups = [x for x in re.split(r'[,\s]+', groups) if x] | 177 | groups = self._ParseGroups(groups) |
175 | 178 | ||
176 | doc = xml.dom.minidom.Document() | 179 | doc = xml.dom.minidom.Document() |
177 | root = doc.createElement('manifest') | 180 | root = doc.createElement('manifest') |
@@ -505,6 +508,23 @@ class XmlManifest(object): | |||
505 | if node.nodeName == 'project': | 508 | if node.nodeName == 'project': |
506 | project = self._ParseProject(node) | 509 | project = self._ParseProject(node) |
507 | recursively_add_projects(project) | 510 | recursively_add_projects(project) |
511 | if node.nodeName == 'extend-project': | ||
512 | name = self._reqatt(node, 'name') | ||
513 | |||
514 | if name not in self._projects: | ||
515 | raise ManifestParseError('extend-project element specifies non-existent ' | ||
516 | 'project: %s' % name) | ||
517 | |||
518 | path = node.getAttribute('path') | ||
519 | groups = node.getAttribute('groups') | ||
520 | if groups: | ||
521 | groups = self._ParseGroups(groups) | ||
522 | |||
523 | for p in self._projects[name]: | ||
524 | if path and p.relpath != path: | ||
525 | continue | ||
526 | if groups: | ||
527 | p.groups.extend(groups) | ||
508 | if node.nodeName == 'repo-hooks': | 528 | if node.nodeName == 'repo-hooks': |
509 | # Get the name of the project and the (space-separated) list of enabled. | 529 | # Get the name of the project and the (space-separated) list of enabled. |
510 | repo_hooks_project = self._reqatt(node, 'in-project') | 530 | repo_hooks_project = self._reqatt(node, 'in-project') |
@@ -745,7 +765,7 @@ class XmlManifest(object): | |||
745 | groups = '' | 765 | groups = '' |
746 | if node.hasAttribute('groups'): | 766 | if node.hasAttribute('groups'): |
747 | groups = node.getAttribute('groups') | 767 | groups = node.getAttribute('groups') |
748 | groups = [x for x in re.split(r'[,\s]+', groups) if x] | 768 | groups = self._ParseGroups(groups) |
749 | 769 | ||
750 | if parent is None: | 770 | if parent is None: |
751 | relpath, worktree, gitdir, objdir = self.GetProjectPaths(name, path) | 771 | relpath, worktree, gitdir, objdir = self.GetProjectPaths(name, path) |