Merge "Add extend-project tag to support adding groups to an existing project"
diff --git a/docs/manifest-format.txt b/docs/manifest-format.txt
index 28a21bb..d5c6a02 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 6d70c86..890c954 100644
--- a/manifest_xml.py
+++ b/manifest_xml.py
@@ -168,6 +168,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.
"""
@@ -175,7 +178,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')
@@ -511,6 +514,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')
@@ -751,7 +771,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)