Add extend-project tag to support adding groups to an existing project
Currently, if a local manifest wants to add groups to an existing
project, it must use remove-project and then re-add the project with
the new groups. This makes the local manifest more fragile, requiring
updates to the local manifest if the original manifest changes.
Add a new extend-project tag, which supports adding groups to an
existing project.
Change-Id: Ib4d1352efd722a65dd263d02644b9ea5ab6ed400
diff --git a/docs/manifest-format.txt b/docs/manifest-format.txt
index f187bfa..65cd70b 100644
--- a/docs/manifest-format.txt
+++ b/docs/manifest-format.txt
@@ -26,6 +26,7 @@
manifest-server?,
remove-project*,
project*,
+ extend-project*,
repo-hooks?)>
<!ELEMENT notice (#PCDATA)>
@@ -67,6 +68,11 @@
<!ATTLIST annotation value CDATA #REQUIRED>
<!ATTLIST annotation keep CDATA "true">
+ <!ELEMENT extend-project>
+ <!ATTLIST extend-project name CDATA #REQUIRED>
+ <!ATTLIST extend-project path CDATA #IMPLIED>
+ <!ATTLIST extend-project groups CDATA #IMPLIED>
+
<!ELEMENT remove-project (EMPTY)>
<!ATTLIST remove-project name CDATA #REQUIRED>
@@ -252,6 +258,22 @@
local mirrors syncing, it will be ignored when syncing the projects in a
client working directory.
+Element extend-project
+----------------------
+
+Modify the attributes of the named project.
+
+This element is mostly useful in a local manifest file, to modify the
+attributes of an existing project without completely replacing the
+existing project definition. This makes the local manifest more robust
+against changes to the original manifest.
+
+Attribute `path`: If specified, limit the change to projects checked out
+at the specified path, rather than all projects with the given name.
+
+Attribute `groups`: List of additional groups to which this project
+belongs. Same syntax as the corresponding element of `project`.
+
Element annotation
------------------
diff --git a/manifest_xml.py b/manifest_xml.py
index fdc3177..bd1ab69 100644
--- a/manifest_xml.py
+++ b/manifest_xml.py
@@ -164,6 +164,9 @@
if r.revision is not None:
e.setAttribute('revision', r.revision)
+ def _ParseGroups(self, groups):
+ return [x for x in re.split(r'[,\s]+', groups) if x]
+
def Save(self, fd, peg_rev=False, peg_rev_upstream=True):
"""Write the current manifest out to the given file descriptor.
"""
@@ -171,7 +174,7 @@
groups = mp.config.GetString('manifest.groups')
if groups:
- groups = [x for x in re.split(r'[,\s]+', groups) if x]
+ groups = self._ParseGroups(groups)
doc = xml.dom.minidom.Document()
root = doc.createElement('manifest')
@@ -505,6 +508,23 @@
if node.nodeName == 'project':
project = self._ParseProject(node)
recursively_add_projects(project)
+ if node.nodeName == 'extend-project':
+ name = self._reqatt(node, 'name')
+
+ if name not in self._projects:
+ raise ManifestParseError('extend-project element specifies non-existent '
+ 'project: %s' % name)
+
+ path = node.getAttribute('path')
+ groups = node.getAttribute('groups')
+ if groups:
+ groups = self._ParseGroups(groups)
+
+ for p in self._projects[name]:
+ if path and p.relpath != path:
+ continue
+ if groups:
+ p.groups.extend(groups)
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')
@@ -745,7 +765,7 @@
groups = ''
if node.hasAttribute('groups'):
groups = node.getAttribute('groups')
- groups = [x for x in re.split(r'[,\s]+', groups) if x]
+ groups = self._ParseGroups(groups)
if parent is None:
relpath, worktree, gitdir, objdir = self.GetProjectPaths(name, path)