Skip to content

Commit

Permalink
Check hacs.json before downloading (#3350)
Browse files Browse the repository at this point in the history
  • Loading branch information
ludeeus authored Nov 17, 2023
1 parent 09ec684 commit a746614
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 68 deletions.
72 changes: 10 additions & 62 deletions custom_components/hacs/repositories/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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)
Expand Down Expand Up @@ -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:
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
29 changes: 23 additions & 6 deletions custom_components/hacs/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down

0 comments on commit a746614

Please sign in to comment.