diff options
| -rw-r--r-- | docs/manifest-format.md | 8 | ||||
| -rw-r--r-- | manifest_xml.py | 21 | ||||
| -rw-r--r-- | 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: | |||
| 125 | <!ATTLIST contactinfo bugurl CDATA #REQUIRED> | 125 | <!ATTLIST contactinfo bugurl CDATA #REQUIRED> |
| 126 | 126 | ||
| 127 | <!ELEMENT include EMPTY> | 127 | <!ELEMENT include EMPTY> |
| 128 | <!ATTLIST include name CDATA #REQUIRED> | 128 | <!ATTLIST include name CDATA #REQUIRED> |
| 129 | <!ATTLIST include groups CDATA #IMPLIED> | 129 | <!ATTLIST include groups CDATA #IMPLIED> |
| 130 | <!ATTLIST include revision CDATA #IMPLIED> | ||
| 130 | ]> | 131 | ]> |
| 131 | ``` | 132 | ``` |
| 132 | 133 | ||
| @@ -553,6 +554,9 @@ in the included manifest belong. This appends and recurses, meaning | |||
| 553 | all projects in included manifests carry all parent include groups. | 554 | all projects in included manifests carry all parent include groups. |
| 554 | Same syntax as the corresponding element of `project`. | 555 | Same syntax as the corresponding element of `project`. |
| 555 | 556 | ||
| 557 | Attribute `revision`: Name of a Git branch (e.g. `main` or `refs/heads/main`) | ||
| 558 | default to which all projects in the included manifest belong. | ||
| 559 | |||
| 556 | ## Local Manifests {#local-manifests} | 560 | ## Local Manifests {#local-manifests} |
| 557 | 561 | ||
| 558 | Additional remotes and projects may be added through local manifest | 562 | 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 | |||
| 1233 | ) | 1233 | ) |
| 1234 | 1234 | ||
| 1235 | def _ParseManifestXml( | 1235 | def _ParseManifestXml( |
| 1236 | self, path, include_root, parent_groups="", restrict_includes=True | 1236 | self, |
| 1237 | path, | ||
| 1238 | include_root, | ||
| 1239 | parent_groups="", | ||
| 1240 | restrict_includes=True, | ||
| 1241 | parent_node=None, | ||
| 1237 | ): | 1242 | ): |
| 1238 | """Parse a manifest XML and return the computed nodes. | 1243 | """Parse a manifest XML and return the computed nodes. |
| 1239 | 1244 | ||
| @@ -1243,6 +1248,8 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md | |||
| 1243 | parent_groups: The groups to apply to this projects. | 1248 | parent_groups: The groups to apply to this projects. |
| 1244 | restrict_includes: Whether to constrain the "name" attribute of | 1249 | restrict_includes: Whether to constrain the "name" attribute of |
| 1245 | includes. | 1250 | includes. |
| 1251 | parent_node: The parent include node, to apply attribute to this | ||
| 1252 | projects. | ||
| 1246 | 1253 | ||
| 1247 | Returns: | 1254 | Returns: |
| 1248 | List of XML nodes. | 1255 | List of XML nodes. |
| @@ -1288,7 +1295,9 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md | |||
| 1288 | ) | 1295 | ) |
| 1289 | try: | 1296 | try: |
| 1290 | nodes.extend( | 1297 | nodes.extend( |
| 1291 | self._ParseManifestXml(fp, include_root, include_groups) | 1298 | self._ParseManifestXml( |
| 1299 | fp, include_root, include_groups, parent_node=node | ||
| 1300 | ) | ||
| 1292 | ) | 1301 | ) |
| 1293 | # should isolate this to the exact exception, but that's | 1302 | # should isolate this to the exact exception, but that's |
| 1294 | # tricky. actual parsing implementation may vary. | 1303 | # tricky. actual parsing implementation may vary. |
| @@ -1311,6 +1320,14 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md | |||
| 1311 | node.getAttribute("groups") + "," + nodeGroups | 1320 | node.getAttribute("groups") + "," + nodeGroups |
| 1312 | ) | 1321 | ) |
| 1313 | node.setAttribute("groups", nodeGroups) | 1322 | node.setAttribute("groups", nodeGroups) |
| 1323 | if ( | ||
| 1324 | parent_node | ||
| 1325 | and node.nodeName == "project" | ||
| 1326 | and not node.hasAttribute("revision") | ||
| 1327 | ): | ||
| 1328 | node.setAttribute( | ||
| 1329 | "revision", parent_node.getAttribute("revision") | ||
| 1330 | ) | ||
| 1314 | nodes.append(node) | 1331 | nodes.append(node) |
| 1315 | return nodes | 1332 | return nodes |
| 1316 | 1333 | ||
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): | |||
| 389 | class IncludeElementTests(ManifestParseTestCase): | 389 | class IncludeElementTests(ManifestParseTestCase): |
| 390 | """Tests for <include>.""" | 390 | """Tests for <include>.""" |
| 391 | 391 | ||
| 392 | def test_revision_default(self): | ||
| 393 | """Check handling of revision attribute.""" | ||
| 394 | root_m = os.path.join(self.manifest_dir, "root.xml") | ||
| 395 | with open(root_m, "w") as fp: | ||
| 396 | fp.write( | ||
| 397 | """ | ||
| 398 | <manifest> | ||
| 399 | <remote name="test-remote" fetch="http://localhost" /> | ||
| 400 | <default remote="test-remote" revision="refs/heads/main" /> | ||
| 401 | <include name="stable.xml" revision="stable-branch" /> | ||
| 402 | <project name="root-name1" path="root-path1" /> | ||
| 403 | <project name="root-name2" path="root-path2" /> | ||
| 404 | </manifest> | ||
| 405 | """ | ||
| 406 | ) | ||
| 407 | with open(os.path.join(self.manifest_dir, "stable.xml"), "w") as fp: | ||
| 408 | fp.write( | ||
| 409 | """ | ||
| 410 | <manifest> | ||
| 411 | <project name="stable-name1" path="stable-path1" /> | ||
| 412 | <project name="stable-name2" path="stable-path2" revision="stable-branch2" /> | ||
| 413 | </manifest> | ||
| 414 | """ | ||
| 415 | ) | ||
| 416 | include_m = manifest_xml.XmlManifest(self.repodir, root_m) | ||
| 417 | for proj in include_m.projects: | ||
| 418 | if proj.name == "root-name1": | ||
| 419 | # Check include revision not set on root level proj. | ||
| 420 | self.assertNotEqual("stable-branch", proj.revisionExpr) | ||
| 421 | if proj.name == "root-name2": | ||
| 422 | # Check root proj revision not removed. | ||
| 423 | self.assertEqual("refs/heads/main", proj.revisionExpr) | ||
| 424 | if proj.name == "stable-name1": | ||
| 425 | # Check stable proj has inherited revision include node. | ||
| 426 | self.assertEqual("stable-branch", proj.revisionExpr) | ||
| 427 | if proj.name == "stable-name2": | ||
| 428 | # Check stable proj revision can override include node. | ||
| 429 | self.assertEqual("stable-branch2", proj.revisionExpr) | ||
| 430 | |||
| 392 | def test_group_levels(self): | 431 | def test_group_levels(self): |
| 393 | root_m = os.path.join(self.manifest_dir, "root.xml") | 432 | root_m = os.path.join(self.manifest_dir, "root.xml") |
| 394 | with open(root_m, "w") as fp: | 433 | with open(root_m, "w") as fp: |
