From 2e815170f775fa86c50046046263e332efbe0a1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20S=C3=B8rensen?= Date: Mon, 19 Aug 2024 13:19:43 +0200 Subject: [PATCH] Raise an error when update service target the downloaded version (#3984) --- custom_components/hacs/update.py | 4 + tests/repositories/test_update_repository.py | 75 ++++++++++++++++++- ...st-update-repository-entity-no-update.json | 17 +++++ ...pository-entity-same-provided-version.json | 17 +++++ 4 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 tests/snapshots/api-usage/tests/repositories/test_update_repositorytest-update-repository-entity-no-update.json create mode 100644 tests/snapshots/api-usage/tests/repositories/test_update_repositorytest-update-repository-entity-same-provided-version.json diff --git a/custom_components/hacs/update.py b/custom_components/hacs/update.py index e6d613a0ae1..ce8a0b2b7b7 100644 --- a/custom_components/hacs/update.py +++ b/custom_components/hacs/update.py @@ -80,6 +80,10 @@ def entity_picture(self) -> str | None: async def async_install(self, version: str | None, backup: bool, **kwargs: Any) -> None: """Install an update.""" + to_download = version or self.latest_version + if to_download == self.installed_version: + raise HomeAssistantError(f"Version {self.installed_version} of { + self.repository.data.full_name} is already downloaded") try: await self.repository.async_download_repository(ref=version or self.latest_version) except HacsException as exception: diff --git a/tests/repositories/test_update_repository.py b/tests/repositories/test_update_repository.py index ad14ed4cbca..ad7d35cb285 100644 --- a/tests/repositories/test_update_repository.py +++ b/tests/repositories/test_update_repository.py @@ -57,7 +57,7 @@ async def test_update_repository_entity( await snapshots.assert_hacs_data( hacs, f"{category_test_data['repository'] - }/test_update_repository_entity.json", + }/test_update_repository_entity.json", ) @@ -87,7 +87,7 @@ async def test_update_repository_websocket( await snapshots.assert_hacs_data( hacs, f"{category_test_data['repository'] - }/test_update_repository_websocket.json", + }/test_update_repository_websocket.json", ) @@ -256,3 +256,74 @@ async def test_update_repository_entity_download_failure( service_data={"entity_id": entity_id, "version": "2.0.0"}, blocking=True, ) + + +async def test_update_repository_entity_same_provided_version( + hass: HomeAssistant, setup_integration: Generator +): + hacs = get_hacs(hass) + repo = hacs.repositories.get_by_full_name("hacs-test-org/integration-basic") + + assert repo is not None + + repo.data.installed = True + repo.data.installed_version = "2.0.0" + + await hass.config_entries.async_reload(hacs.configuration.config_entry.entry_id) + await hass.async_block_till_done() + + # Get a new HACS instance after reload + hacs = get_hacs(hass) + + er = async_get_entity_registry(hacs.hass) + + entity_id = er.async_get_entity_id("update", DOMAIN, repo.data.id) + + with pytest.raises( + HomeAssistantError, + match=re.escape( + "Version 2.0.0 of hacs-test-org/integration-basic is already downloaded", + ), + ): + await hass.services.async_call( + "update", + "install", + service_data={"entity_id": entity_id, "version": "2.0.0"}, + blocking=True, + ) + + +async def test_update_repository_entity_no_update( + hass: HomeAssistant, + setup_integration: Generator, +): + hacs = get_hacs(hass) + repo = hacs.repositories.get_by_full_name("hacs-test-org/integration-basic") + + assert repo is not None + + repo.data.installed = True + repo.data.installed_version = "1.0.0" + + await hass.config_entries.async_reload(hacs.configuration.config_entry.entry_id) + await hass.async_block_till_done() + + # Get a new HACS instance after reload + hacs = get_hacs(hass) + + er = async_get_entity_registry(hacs.hass) + + entity_id = er.async_get_entity_id("update", DOMAIN, repo.data.id) + + with pytest.raises( + HomeAssistantError, + match=re.escape( + "No update available for update.basic_integration_update", + ), + ): + await hass.services.async_call( + "update", + "install", + service_data={"entity_id": entity_id}, + blocking=True, + ) diff --git a/tests/snapshots/api-usage/tests/repositories/test_update_repositorytest-update-repository-entity-no-update.json b/tests/snapshots/api-usage/tests/repositories/test_update_repositorytest-update-repository-entity-no-update.json new file mode 100644 index 00000000000..be152d07800 --- /dev/null +++ b/tests/snapshots/api-usage/tests/repositories/test_update_repositorytest-update-repository-entity-no-update.json @@ -0,0 +1,17 @@ +{ + "tests/repositories/test_update_repository.py::test_update_repository_entity_no_update": { + "https://api.github.com/repos/hacs/integration": 1, + "https://api.github.com/repos/hacs/integration/contents/custom_components/hacs/manifest.json": 1, + "https://api.github.com/repos/hacs/integration/contents/hacs.json": 1, + "https://api.github.com/repos/hacs/integration/git/trees/main": 1, + "https://api.github.com/repos/hacs/integration/releases": 1, + "https://data-v2.hacs.xyz/appdaemon/data.json": 1, + "https://data-v2.hacs.xyz/critical/data.json": 1, + "https://data-v2.hacs.xyz/integration/data.json": 1, + "https://data-v2.hacs.xyz/plugin/data.json": 1, + "https://data-v2.hacs.xyz/python_script/data.json": 1, + "https://data-v2.hacs.xyz/removed/data.json": 1, + "https://data-v2.hacs.xyz/template/data.json": 1, + "https://data-v2.hacs.xyz/theme/data.json": 1 + } +} \ No newline at end of file diff --git a/tests/snapshots/api-usage/tests/repositories/test_update_repositorytest-update-repository-entity-same-provided-version.json b/tests/snapshots/api-usage/tests/repositories/test_update_repositorytest-update-repository-entity-same-provided-version.json new file mode 100644 index 00000000000..6c9c90a4860 --- /dev/null +++ b/tests/snapshots/api-usage/tests/repositories/test_update_repositorytest-update-repository-entity-same-provided-version.json @@ -0,0 +1,17 @@ +{ + "tests/repositories/test_update_repository.py::test_update_repository_entity_same_provided_version": { + "https://api.github.com/repos/hacs/integration": 1, + "https://api.github.com/repos/hacs/integration/contents/custom_components/hacs/manifest.json": 1, + "https://api.github.com/repos/hacs/integration/contents/hacs.json": 1, + "https://api.github.com/repos/hacs/integration/git/trees/main": 1, + "https://api.github.com/repos/hacs/integration/releases": 1, + "https://data-v2.hacs.xyz/appdaemon/data.json": 1, + "https://data-v2.hacs.xyz/critical/data.json": 1, + "https://data-v2.hacs.xyz/integration/data.json": 1, + "https://data-v2.hacs.xyz/plugin/data.json": 1, + "https://data-v2.hacs.xyz/python_script/data.json": 1, + "https://data-v2.hacs.xyz/removed/data.json": 1, + "https://data-v2.hacs.xyz/template/data.json": 1, + "https://data-v2.hacs.xyz/theme/data.json": 1 + } +} \ No newline at end of file