diff --git a/custom_components/hacs/repositories/base.py b/custom_components/hacs/repositories/base.py index 2f611f70375..1fdb7a677b5 100644 --- a/custom_components/hacs/repositories/base.py +++ b/custom_components/hacs/repositories/base.py @@ -560,56 +560,23 @@ async def common_update(self, ignore_issues=False, force=False, skip_releases=Fa async def download_zip_files(self, validate: Validate) -> None: """Download ZIP archive from repository release.""" - contents: list[DownloadableContent] = [] - target_ref = self.ref.split("/")[1] - if self.repository_manifest.zip_release: - contents.append( + try: + await self.async_download_zip_file( DownloadableContent( name=self.repository_manifest.filename, url=asset_download( repository=self.data.full_name, - version=target_ref, + version=self.ref, filenme=self.repository_manifest.filename, ), - ) + ), + validate, ) - else: - for release in self.releases.objects: - self.logger.debug( - "%s ref: %s --- tag: %s", self.string, target_ref, release.tag_name - ) - if release.tag_name == target_ref and release.assets: - contents = [ - DownloadableContent( - name=asset.name, - url=asset.browser_download_url, - ) - for asset in release.assets - ] - break - - if len(contents) == 0: - validate.errors.append(f"No assets found for release '{self.ref}'") - return - - download_queue = QueueManager(hass=self.hacs.hass) - try: - for content in contents: - if ( - self.repository_manifest.zip_release - and content["name"] != self.repository_manifest.filename - ): - continue - download_queue.add(self.async_download_zip_file(content, validate)) - - if download_queue.pending_tasks == 0: - validate.errors.append("Nothing to download") - return - - await download_queue.execute() except BaseException: # lgtm [py/catch-base-exception] pylint: disable=broad-except - validate.errors.append("Download was not completed") + validate.errors.append( + f"Download of {self.repository_manifest.filename} was not completed" + ) async def async_download_zip_file( self, @@ -621,7 +588,7 @@ async def async_download_zip_file( filecontent = await self.hacs.async_download_file(content["url"]) if filecontent is None: - validate.errors.append(f"[{content['name']}] was not downloaded") + validate.errors.append(f"Failed to download {content['url']}") return temp_dir = await self.hacs.hass.async_add_executor_job(tempfile.mkdtemp) @@ -706,7 +673,6 @@ async def download_repository_zip(self): raise HacsException(f"[{self}] Failed to download zipball") temp_dir = await self.hacs.hass.async_add_executor_job(tempfile.mkdtemp) - tmp_extract = f"{temp_dir}/extracted" temp_file = f"{temp_dir}/{self.repository_manifest.filename}" result = await self.hacs.async_save_file(temp_file, filecontent) if not result: @@ -723,24 +689,6 @@ async def download_repository_zip(self): path.filename = filename.replace(self.content.path.remote, "") extractable.append(path) - if filename == "hacs.json": - path.filename = "hacs.json" - zip_file.extract(path, tmp_extract) - with open(f"{tmp_extract}/hacs.json", encoding="utf-8") as hacsfile: - hacs_manifest = json_loads(hacsfile.read()) - if ( - hacs_version := hacs_manifest.get("hacs") - ) and hacs_version > self.hacs.version: - raise HacsException( - f"This repository requires HACS version {hacs_manifest['hacs']}, you have {self.hacs.version}" - ) - if ( - homeassistant_version := hacs_manifest["homeassistant"] - ) and homeassistant_version > self.hacs.core.ha_version: - raise HacsException( - f"This repository requires Home Assistant version {hacs_manifest['homeassistant']}, you have {self.hacs.core.ha_version}" - ) - if len(extractable) == 0: raise HacsException("No content to extract") zip_file.extractall(self.content.path.local, extractable) @@ -1019,7 +967,7 @@ async def async_install_repository(self, *, version: str | None = None, **_) -> {"repository": self.data.full_name, "progress": 50}, ) - if self.repository_manifest.zip_release and version_to_install != self.data.default_branch: + if self.repository_manifest.zip_release and self.repository_manifest.filename: await self.download_zip_files(self.validate) else: await self.download_content(version_to_install) diff --git a/custom_components/hacs/update.py b/custom_components/hacs/update.py index 50e69bab26b..851d77df7b2 100644 --- a/custom_components/hacs/update.py +++ b/custom_components/hacs/update.py @@ -12,6 +12,7 @@ from .entity import HacsRepositoryEntity from .enums import HacsCategory, HacsDispatchEvent from .exceptions import HacsException +from .repositories.base import HacsManifest async def async_setup_entry(hass, _config_entry, async_add_devices): @@ -70,25 +71,41 @@ def entity_picture(self) -> str | None: return f"https://brands.home-assistant.io/_/{self.repository.data.domain}/icon.png" - def _ensure_capabilities(self, version: str | None, **kwargs: Any) -> None: + async def _ensure_capabilities(self, version: str | None, **kwargs: Any) -> None: """Ensure that the entity has capabilities.""" + target_manifest: HacsManifest | None = None if version is None: if not self.repository.can_download: raise HomeAssistantError( f"This {self.repository.data.category.value} is not available for download." ) return + + if version == self.repository.data.last_version: + target_manifest = self.repository.repository_manifest + else: + target_manifest = await self.repository.get_hacs_json(version=version) + + if target_manifest is None: + raise HomeAssistantError( + f"The version {version} for this {self.repository.data.category.value} can not be used with HACS." + ) + + self.repository.logger.warning("target_manifest: %s", target_manifest.to_dict()) + if ( - self.repository.display_version_or_commit != "version" - or self.repository.repository_manifest.hide_default_branch + target_manifest.homeassistant is not None + and self.hacs.core.ha_version < target_manifest.homeassistant ): raise HomeAssistantError( - f"This {self.repository.data.category.value} does not support version selection." + f"This version requires Home Assistant {target_manifest.homeassistant} or newer." ) + if target_manifest.hacs is not None and self.hacs.core.ha_version < target_manifest.hacs: + raise HomeAssistantError(f"This version requires HACS {target_manifest.hacs} or newer.") async def async_install(self, version: str | None, backup: bool, **kwargs: Any) -> None: """Install an update.""" - self._ensure_capabilities(version) + await self._ensure_capabilities(version) self.repository.logger.info("Starting update, %s", version) if self.repository.display_version_or_commit == "version": self._update_in_progress(progress=10) @@ -104,7 +121,7 @@ async def async_install(self, version: str | None, backup: bool, **kwargs: Any) await self.repository.async_install(version=version) except HacsException as exception: raise HomeAssistantError( - f"{exception} for {version}" if version else exception + f"Downloading {self.repository.data.full_name} with version {version or self.repository.data.last_version or self.repository.data.last_commit} failed with ({exception})" ) from exception finally: self._update_in_progress(progress=False)