From 3e3340d94f8a680156ceaa81faca1c3b8863c6ac Mon Sep 17 00:00:00 2001 From: Shuchuan Zeng Date: Tue, 18 Apr 2023 10:36:50 +0800 Subject: [PATCH] manifest: add support for revision in include Attribute groups can now be added to manifest include, thus all projects in an included manifest file can easily modify default branch without modifying all projects in that manifest file. For example, the main manifest.xml has an include node contain revision attribute, ``` ``` and the include.xml has some projects, ``` ``` With this change, the final manifest will have revision="r1" for project2. ``` ``` Test: added unit tests to cover the inheritance Change-Id: I4b8547a7198610ec3a3c6aeb2136e0c0f3557df0 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/369714 Reviewed-by: Mike Frysinger Commit-Queue: Shuchuan Zeng Tested-by: Shuchuan Zeng --- docs/manifest-format.md | 8 ++++++-- manifest_xml.py | 21 ++++++++++++++++++-- tests/test_manifest_xml.py | 39 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 4 deletions(-) diff --git a/docs/manifest-format.md b/docs/manifest-format.md index bcdf5a8e..edcb28cb 100644 --- a/docs/manifest-format.md +++ b/docs/manifest-format.md @@ -125,8 +125,9 @@ following DTD: - - + + + ]> ``` @@ -553,6 +554,9 @@ in the included manifest belong. This appends and recurses, meaning all projects in included manifests carry all parent include groups. Same syntax as the corresponding element of `project`. +Attribute `revision`: Name of a Git branch (e.g. `main` or `refs/heads/main`) +default to which all projects in the included manifest belong. + ## Local Manifests {#local-manifests} Additional remotes and projects may be added through local manifest diff --git a/manifest_xml.py b/manifest_xml.py index 9603906f..14b03a30 100644 --- a/manifest_xml.py +++ b/manifest_xml.py @@ -1233,7 +1233,12 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md ) def _ParseManifestXml( - self, path, include_root, parent_groups="", restrict_includes=True + self, + path, + include_root, + parent_groups="", + restrict_includes=True, + parent_node=None, ): """Parse a manifest XML and return the computed nodes. @@ -1243,6 +1248,8 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md parent_groups: The groups to apply to this projects. restrict_includes: Whether to constrain the "name" attribute of includes. + parent_node: The parent include node, to apply attribute to this + projects. Returns: List of XML nodes. @@ -1288,7 +1295,9 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md ) try: nodes.extend( - self._ParseManifestXml(fp, include_root, include_groups) + self._ParseManifestXml( + fp, include_root, include_groups, parent_node=node + ) ) # should isolate this to the exact exception, but that's # tricky. actual parsing implementation may vary. @@ -1311,6 +1320,14 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md node.getAttribute("groups") + "," + nodeGroups ) node.setAttribute("groups", nodeGroups) + if ( + parent_node + and node.nodeName == "project" + and not node.hasAttribute("revision") + ): + node.setAttribute( + "revision", parent_node.getAttribute("revision") + ) nodes.append(node) return nodes diff --git a/tests/test_manifest_xml.py b/tests/test_manifest_xml.py index 648acde8..ef511055 100644 --- a/tests/test_manifest_xml.py +++ b/tests/test_manifest_xml.py @@ -389,6 +389,45 @@ class XmlManifestTests(ManifestParseTestCase): class IncludeElementTests(ManifestParseTestCase): """Tests for .""" + def test_revision_default(self): + """Check handling of revision attribute.""" + root_m = os.path.join(self.manifest_dir, "root.xml") + with open(root_m, "w") as fp: + fp.write( + """ + + + + + + + +""" + ) + with open(os.path.join(self.manifest_dir, "stable.xml"), "w") as fp: + fp.write( + """ + + + + +""" + ) + include_m = manifest_xml.XmlManifest(self.repodir, root_m) + for proj in include_m.projects: + if proj.name == "root-name1": + # Check include revision not set on root level proj. + self.assertNotEqual("stable-branch", proj.revisionExpr) + if proj.name == "root-name2": + # Check root proj revision not removed. + self.assertEqual("refs/heads/main", proj.revisionExpr) + if proj.name == "stable-name1": + # Check stable proj has inherited revision include node. + self.assertEqual("stable-branch", proj.revisionExpr) + if proj.name == "stable-name2": + # Check stable proj revision can override include node. + self.assertEqual("stable-branch2", proj.revisionExpr) + def test_group_levels(self): root_m = os.path.join(self.manifest_dir, "root.xml") with open(root_m, "w") as fp: