Snap for 11926388 from b81c243083f0b2961e4a7c92e4856e33cd2572ca to 24Q3-release Change-Id: I3d78f659584248d2c1421ae376c4a9da9d5b68bc
diff --git a/manifest.py b/manifest.py index de60413..3fd68c1 100644 --- a/manifest.py +++ b/manifest.py
@@ -51,10 +51,11 @@ ) -> Project: """Parses a Project from the given XML node.""" try: - path = node.attrib["path"] + # Path is optional, defaults to project name per manifest spec + path = x if (x := node.attrib.get("path")) is not None else node.attrib["name"] except KeyError as ex: raise RuntimeError( - f"<project /> element missing required path attribute: {node}" + f"<project /> element missing required name attribute: {node}" ) from ex return Project(
diff --git a/test_manifest.py b/test_manifest.py index ca6088a..2e9c8b9 100644 --- a/test_manifest.py +++ b/test_manifest.py
@@ -58,6 +58,25 @@ with pytest.raises(RuntimeError): ManifestParser(manifest_path).parse() + def test_name_missing(self, tmp_path: Path) -> None: + """Tests that an error is raised when neither name nor path is defined for a project.""" + manifest_path = tmp_path / "manifest.xml" + manifest_path.write_text( + textwrap.dedent( + """\ + <?xml version="1.0" encoding="UTF-8"?> + <manifest> + <default revision="main" remote="aosp" /> + + <project /> + </manifest> + """ + ) + ) + with pytest.raises(RuntimeError): + ManifestParser(manifest_path).parse() + + def test_multiple_default(self, tmp_path: Path) -> None: """Tests that an error is raised when there is more than one default node.""" manifest = tmp_path / "manifest.xml" @@ -114,6 +133,24 @@ manifest = ManifestParser(manifest_path).parse() assert manifest.project_with_path("external/project").revision == "main" + def test_path_default(self, tmp_path: Path) -> None: + """Tests that the default path is used when not defined by the project.""" + manifest_path = tmp_path / "manifest.xml" + manifest_path.write_text( + textwrap.dedent( + """\ + <?xml version="1.0" encoding="UTF-8"?> + <manifest> + <default revision="main" remote="aosp" /> + + <project name="external/project" /> + </manifest> + """ + ) + ) + manifest = ManifestParser(manifest_path).parse() + assert manifest.project_with_path("external/project") is not None + def test_remote_explicit(self, tmp_path: Path) -> None: """Tests that the project remote is used when defined.""" manifest_path = tmp_path / "manifest.xml" @@ -150,6 +187,23 @@ manifest = ManifestParser(manifest_path).parse() assert manifest.project_with_path("external/project").revision == "master" + def test_path_explicit(self, tmp_path: Path) -> None: + """Tests that the project path is used when defined.""" + manifest_path = tmp_path / "manifest.xml" + manifest_path.write_text( + textwrap.dedent( + """\ + <?xml version="1.0" encoding="UTF-8"?> + <manifest> + <default revision="main" remote="aosp" /> + + <project name="external/project" path="other/path" /> + </manifest> + """ + ) + ) + manifest = ManifestParser(manifest_path).parse() + assert manifest.project_with_path("other/path") is not None class TestManifest: """Tests for Manifest."""