diff --git a/docs/manifest-format.md b/docs/manifest-format.md index 45fd615e..c3bfcff0 100644 --- a/docs/manifest-format.md +++ b/docs/manifest-format.md @@ -96,6 +96,7 @@ following DTD: + @@ -393,6 +394,9 @@ This element is mostly useful in a local manifest file, where the user can remove a project, and possibly replace it with their own definition. +Attribute `optional`: Set to true to ignore remove-project elements with no +matching `project` element. + ### Element repo-hooks NB: See the [practical documentation](./repo-hooks.md) for using repo hooks. diff --git a/manifest_xml.py b/manifest_xml.py index ab4be2f5..be74bf49 100644 --- a/manifest_xml.py +++ b/manifest_xml.py @@ -918,19 +918,19 @@ https://gerrit.googlesource.com/git-repo/+/HEAD/docs/manifest-format.md if node.nodeName == 'remove-project': name = self._reqatt(node, 'name') - if name not in self._projects: + if name in self._projects: + for p in self._projects[name]: + del self._paths[p.relpath] + del self._projects[name] + + # If the manifest removes the hooks project, treat it as if it deleted + # the repo-hooks element too. + if self._repo_hooks_project and (self._repo_hooks_project.name == name): + self._repo_hooks_project = None + elif not XmlBool(node, 'optional', False): raise ManifestParseError('remove-project element specifies non-existent ' 'project: %s' % name) - for p in self._projects[name]: - del self._paths[p.relpath] - del self._projects[name] - - # If the manifest removes the hooks project, treat it as if it deleted - # the repo-hooks element too. - if self._repo_hooks_project and (self._repo_hooks_project.name == name): - self._repo_hooks_project = None - def _AddMetaProjectMirror(self, m): name = None m_url = m.GetRemote(m.remote.name).url diff --git a/tests/test_manifest_xml.py b/tests/test_manifest_xml.py index 55468b51..96ee4c4a 100644 --- a/tests/test_manifest_xml.py +++ b/tests/test_manifest_xml.py @@ -638,3 +638,53 @@ class RemoteElementTests(ManifestParseTestCase): self.assertNotEqual(a, manifest_xml._Default()) self.assertNotEqual(a, 123) self.assertNotEqual(a, None) + + +class RemoveProjectElementTests(ManifestParseTestCase): + """Tests for .""" + + def test_remove_one_project(self): + manifest = self.getXmlManifest(""" + + + + + + +""") + self.assertEqual(manifest.projects, []) + + def test_remove_one_project_one_remains(self): + manifest = self.getXmlManifest(""" + + + + + + + +""") + + self.assertEqual(len(manifest.projects), 1) + self.assertEqual(manifest.projects[0].name, 'yourproject') + + def test_remove_one_project_doesnt_exist(self): + with self.assertRaises(manifest_xml.ManifestParseError): + manifest = self.getXmlManifest(""" + + + + + +""") + manifest.projects + + def test_remove_one_optional_project_doesnt_exist(self): + manifest = self.getXmlManifest(""" + + + + + +""") + self.assertEqual(manifest.projects, [])