diff --git a/docs/manifest-format.md b/docs/manifest-format.md index 06d370a3e..d1a11cc99 100644 --- a/docs/manifest-format.md +++ b/docs/manifest-format.md @@ -566,6 +566,7 @@ These restrictions are not enforced for [Local Manifests]. Attribute `groups`: List of additional groups to which all projects in the included manifest belong. This appends and recurses, meaning all projects in included manifests carry all parent include groups. +This also applies to all extend-project elements in the included manifests. Same syntax as the corresponding element of `project`. Attribute `revision`: Name of a Git branch (e.g. `main` or `refs/heads/main`) diff --git a/man/repo-manifest.1 b/man/repo-manifest.1 index 4658b1e92..df3943ceb 100644 --- a/man/repo-manifest.1 +++ b/man/repo-manifest.1 @@ -627,7 +627,8 @@ restrictions are not enforced for [Local Manifests]. .PP Attribute `groups`: List of additional groups to which all projects in the included manifest belong. This appends and recurses, meaning all projects in -included manifests carry all parent include groups. Same syntax as the +included manifests carry all parent include groups. This also applies to all +extend\-project elements in the included manifests. Same syntax as the corresponding element of `project`. .PP Attribute `revision`: Name of a Git branch (e.g. `main` or `refs/heads/main`) diff --git a/manifest_xml.py b/manifest_xml.py index 5e0b53b99..33a552827 100644 --- a/manifest_xml.py +++ b/manifest_xml.py @@ -1335,7 +1335,10 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md f"failed parsing included manifest {name}: {e}" ) else: - if parent_groups and node.nodeName == "project": + if parent_groups and node.nodeName in ( + "project", + "extend-project", + ): nodeGroups = parent_groups if node.hasAttribute("groups"): nodeGroups = ( diff --git a/tests/test_manifest_xml.py b/tests/test_manifest_xml.py index c1fed2bf9..d4bf76a91 100644 --- a/tests/test_manifest_xml.py +++ b/tests/test_manifest_xml.py @@ -488,6 +488,41 @@ class IncludeElementTests(ManifestParseTestCase): # Check level2 proj group not removed. self.assertIn("l2g1", proj.groups) + def test_group_levels_with_extend_project(self): + root_m = self.manifest_dir / "root.xml" + root_m.write_text( + """ + + + + + + +""" + ) + (self.manifest_dir / "man1.xml").write_text( + """ + + + +""" + ) + (self.manifest_dir / "man2.xml").write_text( + """ + + + +""" + ) + include_m = manifest_xml.XmlManifest(str(self.repodir), str(root_m)) + proj = include_m.projects[0] + # Check project has inherited group via project element. + self.assertIn("top-group1", proj.groups) + # Check project has inherited group via extend-project element. + self.assertIn("top-group2", proj.groups) + # Check project has set group via extend-project element. + self.assertIn("eg1", proj.groups) + def test_allow_bad_name_from_user(self): """Check handling of bad name attribute from the user's input."""