Update HACS
This commit is contained in:
@@ -5,7 +5,7 @@ from typing import TYPE_CHECKING
|
||||
|
||||
from aiogithubapi import AIOGitHubAPIException
|
||||
|
||||
from ..enums import HacsCategory
|
||||
from ..enums import HacsCategory, HacsDispatchEvent
|
||||
from ..exceptions import HacsException
|
||||
from ..utils.decorator import concurrent
|
||||
from .base import HacsRepository
|
||||
@@ -66,7 +66,7 @@ class HacsAppdaemonRepository(HacsRepository):
|
||||
|
||||
# Get appdaemon objects.
|
||||
if self.repository_manifest:
|
||||
if self.data.content_in_root:
|
||||
if self.repository_manifest.content_in_root:
|
||||
self.content.path.remote = ""
|
||||
|
||||
if self.content.path.remote == "apps":
|
||||
@@ -81,8 +81,8 @@ class HacsAppdaemonRepository(HacsRepository):
|
||||
|
||||
# Signal entities to refresh
|
||||
if self.data.installed:
|
||||
self.hacs.hass.bus.async_fire(
|
||||
"hacs/repository",
|
||||
self.hacs.async_dispatch(
|
||||
HacsDispatchEvent.REPOSITORY,
|
||||
{
|
||||
"id": 1337,
|
||||
"action": "update",
|
||||
|
||||
@@ -8,7 +8,7 @@ import os
|
||||
import pathlib
|
||||
import shutil
|
||||
import tempfile
|
||||
from typing import TYPE_CHECKING, Any, List, Optional
|
||||
from typing import TYPE_CHECKING, Any, List
|
||||
import zipfile
|
||||
|
||||
from aiogithubapi import (
|
||||
@@ -20,10 +20,9 @@ from aiogithubapi.const import BASE_API_URL
|
||||
from aiogithubapi.objects.repository import AIOGitHubAPIRepository
|
||||
import attr
|
||||
from homeassistant.helpers import device_registry as dr
|
||||
from homeassistant.helpers.json import JSONEncoder
|
||||
|
||||
from ..const import DOMAIN
|
||||
from ..enums import ConfigurationType, HacsCategory, RepositoryFile
|
||||
from ..enums import ConfigurationType, HacsDispatchEvent, RepositoryFile
|
||||
from ..exceptions import (
|
||||
HacsException,
|
||||
HacsNotModifiedException,
|
||||
@@ -43,7 +42,6 @@ from ..utils.validate import Validate
|
||||
from ..utils.version import (
|
||||
version_left_higher_or_equal_then_right,
|
||||
version_left_higher_then_right,
|
||||
version_to_download,
|
||||
)
|
||||
from ..utils.workarounds import DOMAIN_OVERRIDES
|
||||
|
||||
@@ -51,6 +49,38 @@ if TYPE_CHECKING:
|
||||
from ..base import HacsBase
|
||||
|
||||
|
||||
TOPIC_FILTER = (
|
||||
"custom-card",
|
||||
"custom-component",
|
||||
"custom-components",
|
||||
"customcomponents",
|
||||
"hacktoberfest",
|
||||
"hacs-default",
|
||||
"hacs-integration",
|
||||
"hacs",
|
||||
"hass",
|
||||
"hassio",
|
||||
"home-assistant",
|
||||
"home-automation",
|
||||
"homeassistant-components",
|
||||
"homeassistant-integration",
|
||||
"homeassistant-sensor",
|
||||
"homeassistant",
|
||||
"homeautomation",
|
||||
"integration",
|
||||
"lovelace",
|
||||
"python",
|
||||
"sensor",
|
||||
"theme",
|
||||
"themes",
|
||||
"custom-cards",
|
||||
"home-assistant-frontend",
|
||||
"home-assistant-hacs",
|
||||
"home-assistant-custom",
|
||||
"lovelace-ui",
|
||||
)
|
||||
|
||||
|
||||
class FileInformation:
|
||||
"""FileInformation."""
|
||||
|
||||
@@ -67,52 +97,34 @@ class RepositoryData:
|
||||
archived: bool = False
|
||||
authors: List[str] = []
|
||||
category: str = ""
|
||||
content_in_root: bool = False
|
||||
country: List[str] = []
|
||||
config_flow: bool = False
|
||||
default_branch: str = None
|
||||
description: str = ""
|
||||
domain: str = ""
|
||||
domains: List[str] = []
|
||||
domain: str = None
|
||||
downloads: int = 0
|
||||
etag_repository: str = None
|
||||
file_name: str = ""
|
||||
filename: str = ""
|
||||
first_install: bool = False
|
||||
fork: bool = False
|
||||
full_name: str = ""
|
||||
hacs: str = None # Minimum HACS version
|
||||
hide: bool = False
|
||||
hide_default_branch: bool = False
|
||||
homeassistant: str = None # Minimum Home Assistant version
|
||||
id: int = 0
|
||||
iot_class: str = None
|
||||
installed: bool = False
|
||||
installed_commit: str = None
|
||||
installed_version: str = None
|
||||
open_issues: int = 0
|
||||
installed: bool = False
|
||||
last_commit: str = None
|
||||
last_version: str = None
|
||||
last_fetched: datetime = None
|
||||
last_updated: str = 0
|
||||
last_version: str = None
|
||||
manifest_name: str = None
|
||||
new: bool = True
|
||||
last_fetched: datetime = None
|
||||
persistent_directory: str = None
|
||||
open_issues: int = 0
|
||||
published_tags: List[str] = []
|
||||
pushed_at: str = ""
|
||||
releases: bool = False
|
||||
render_readme: bool = False
|
||||
published_tags: List[str] = []
|
||||
selected_tag: str = None
|
||||
show_beta: bool = False
|
||||
stargazers_count: int = 0
|
||||
topics: List[str] = []
|
||||
zip_release: bool = False
|
||||
_storage_data: Optional[dict] = None
|
||||
|
||||
@property
|
||||
def stars(self):
|
||||
"""Return the stargazers count."""
|
||||
return self.stargazers_count or 0
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
@@ -123,57 +135,13 @@ class RepositoryData:
|
||||
|
||||
def to_json(self):
|
||||
"""Export to json."""
|
||||
return attr.asdict(
|
||||
self,
|
||||
filter=lambda attr, _: attr.name != "_storage_data" and attr.name != "last_fetched",
|
||||
)
|
||||
|
||||
def memorize_storage(self, data) -> None:
|
||||
"""Memorize the storage data."""
|
||||
self._storage_data = data
|
||||
|
||||
def export_data(self) -> Optional[dict]:
|
||||
"""Export to json if the data has changed.
|
||||
|
||||
Returns the data to export if the data needs
|
||||
to be written.
|
||||
|
||||
Returns None if the data has not changed.
|
||||
"""
|
||||
export = json.loads(json.dumps(self.to_json(), cls=JSONEncoder))
|
||||
return None if self._storage_data == export else export
|
||||
return attr.asdict(self, filter=lambda attr, value: attr.name != "last_fetched")
|
||||
|
||||
@staticmethod
|
||||
def create_from_dict(source: dict):
|
||||
"""Set attributes from dicts."""
|
||||
data = RepositoryData()
|
||||
for key in source:
|
||||
if key not in data.__dict__:
|
||||
continue
|
||||
if key == "pushed_at":
|
||||
if source[key] == "":
|
||||
continue
|
||||
if "Z" in source[key]:
|
||||
setattr(
|
||||
data,
|
||||
key,
|
||||
datetime.strptime(source[key], "%Y-%m-%dT%H:%M:%SZ"),
|
||||
)
|
||||
else:
|
||||
setattr(
|
||||
data,
|
||||
key,
|
||||
datetime.strptime(source[key], "%Y-%m-%dT%H:%M:%S"),
|
||||
)
|
||||
elif key == "id":
|
||||
setattr(data, key, str(source[key]))
|
||||
elif key == "country":
|
||||
if isinstance(source[key], str):
|
||||
setattr(data, key, [source[key]])
|
||||
else:
|
||||
setattr(data, key, source[key])
|
||||
else:
|
||||
setattr(data, key, source[key])
|
||||
data.update_data(source)
|
||||
return data
|
||||
|
||||
def update_data(self, data: dict):
|
||||
@@ -199,6 +167,9 @@ class RepositoryData:
|
||||
setattr(self, key, [data[key]])
|
||||
else:
|
||||
setattr(self, key, data[key])
|
||||
elif key == "topics":
|
||||
setattr(self, key, [topic for topic in data[key] if topic not in TOPIC_FILTER])
|
||||
|
||||
else:
|
||||
setattr(self, key, data[key])
|
||||
|
||||
@@ -207,19 +178,17 @@ class RepositoryData:
|
||||
class HacsManifest:
|
||||
"""HacsManifest class."""
|
||||
|
||||
name: str = None
|
||||
content_in_root: bool = False
|
||||
zip_release: bool = False
|
||||
filename: str = None
|
||||
manifest: dict = {}
|
||||
hacs: str = None
|
||||
hide_default_branch: bool = False
|
||||
domains: List[str] = []
|
||||
country: List[str] = []
|
||||
homeassistant: str = None
|
||||
filename: str = None
|
||||
hacs: str = None # Minimum HACS version
|
||||
hide_default_branch: bool = False
|
||||
homeassistant: str = None # Minimum Home Assistant version
|
||||
manifest: dict = {}
|
||||
name: str = None
|
||||
persistent_directory: str = None
|
||||
iot_class: str = None
|
||||
render_readme: bool = False
|
||||
zip_release: bool = False
|
||||
|
||||
def to_dict(self):
|
||||
"""Export to json."""
|
||||
@@ -232,38 +201,25 @@ class HacsManifest:
|
||||
raise HacsException("Missing manifest data")
|
||||
|
||||
manifest_data = HacsManifest()
|
||||
manifest_data.manifest = {
|
||||
k: v
|
||||
for k, v in manifest.items()
|
||||
if k in manifest_data.__dict__ and v != manifest_data.__getattribute__(k)
|
||||
}
|
||||
|
||||
manifest_data.manifest = manifest
|
||||
|
||||
if country := manifest.get("country"):
|
||||
if isinstance(country, str):
|
||||
manifest["country"] = [country]
|
||||
|
||||
for key in manifest:
|
||||
setattr(manifest_data, key, manifest[key])
|
||||
for key, value in manifest_data.manifest.items():
|
||||
if key == "country" and isinstance(value, str):
|
||||
setattr(manifest_data, key, [value])
|
||||
elif key in manifest_data.__dict__:
|
||||
setattr(manifest_data, key, value)
|
||||
return manifest_data
|
||||
|
||||
|
||||
class RepositoryStatus:
|
||||
"""Repository status."""
|
||||
|
||||
hide = False
|
||||
installed = False
|
||||
last_updated = None
|
||||
new = True
|
||||
selected_tag = None
|
||||
show_beta = False
|
||||
track = True
|
||||
updated_info = False
|
||||
first_install = True
|
||||
|
||||
|
||||
class RepositoryReleases:
|
||||
"""RepositoyReleases."""
|
||||
|
||||
last_release = None
|
||||
last_release_object = None
|
||||
last_release_object_downloads = None
|
||||
published_tags = []
|
||||
objects: list[GitHubReleaseModel] = []
|
||||
releases = False
|
||||
@@ -273,8 +229,8 @@ class RepositoryReleases:
|
||||
class RepositoryPath:
|
||||
"""RepositoryPath."""
|
||||
|
||||
local = None
|
||||
remote = None
|
||||
local: str | None = None
|
||||
remote: str | None = None
|
||||
|
||||
|
||||
class RepositoryContent:
|
||||
@@ -297,7 +253,7 @@ class HacsRepository:
|
||||
self.content = RepositoryContent()
|
||||
self.content.path = RepositoryPath()
|
||||
self.repository_object: AIOGitHubAPIRepository | None = None
|
||||
self.status = RepositoryStatus()
|
||||
self.updated_info = False
|
||||
self.state = None
|
||||
self.force_branch = False
|
||||
self.integration_manifest = {}
|
||||
@@ -326,9 +282,10 @@ class HacsRepository:
|
||||
return self.repository_manifest.name
|
||||
|
||||
if self.data.category == "integration":
|
||||
if self.integration_manifest:
|
||||
if "name" in self.integration_manifest:
|
||||
return self.integration_manifest["name"]
|
||||
if self.data.manifest_name is not None:
|
||||
return self.data.manifest_name
|
||||
if "name" in self.integration_manifest:
|
||||
return self.integration_manifest["name"]
|
||||
|
||||
return self.data.full_name.split("/")[-1].replace("-", " ").replace("_", " ").title()
|
||||
|
||||
@@ -338,9 +295,10 @@ class HacsRepository:
|
||||
if self.data.installed:
|
||||
return False
|
||||
configuration = self.hacs.configuration.country.lower()
|
||||
manifest = [entry.lower() for entry in self.repository_manifest.country or []]
|
||||
if configuration == "all":
|
||||
return False
|
||||
|
||||
manifest = [entry.lower() for entry in self.repository_manifest.country or []]
|
||||
if not manifest:
|
||||
return False
|
||||
return configuration not in manifest
|
||||
@@ -444,11 +402,11 @@ class HacsRepository:
|
||||
@property
|
||||
def can_download(self) -> bool:
|
||||
"""Return True if we can download."""
|
||||
if self.data.homeassistant is not None:
|
||||
if self.repository_manifest.homeassistant is not None:
|
||||
if self.data.releases:
|
||||
if not version_left_higher_or_equal_then_right(
|
||||
self.hacs.core.ha_version.string,
|
||||
self.data.homeassistant,
|
||||
self.repository_manifest.homeassistant,
|
||||
):
|
||||
return False
|
||||
return True
|
||||
@@ -461,8 +419,8 @@ class HacsRepository:
|
||||
@property
|
||||
def should_try_releases(self) -> bool:
|
||||
"""Return a boolean indicating whether to download releases or not."""
|
||||
if self.data.zip_release:
|
||||
if self.data.filename.endswith(".zip"):
|
||||
if self.repository_manifest.zip_release:
|
||||
if self.repository_manifest.filename.endswith(".zip"):
|
||||
if self.ref != self.data.default_branch:
|
||||
return True
|
||||
if self.ref == self.data.default_branch:
|
||||
@@ -511,9 +469,6 @@ class HacsRepository:
|
||||
# Set topics
|
||||
self.data.topics = self.data.topics
|
||||
|
||||
# Set stargazers_count
|
||||
self.data.stargazers_count = self.data.stargazers_count
|
||||
|
||||
# Set description
|
||||
self.data.description = self.data.description
|
||||
|
||||
@@ -597,7 +552,7 @@ class HacsRepository:
|
||||
return
|
||||
|
||||
temp_dir = await self.hacs.hass.async_add_executor_job(tempfile.mkdtemp)
|
||||
temp_file = f"{temp_dir}/{self.data.filename}"
|
||||
temp_file = f"{temp_dir}/{self.repository_manifest.filename}"
|
||||
|
||||
result = await self.hacs.async_save_file(temp_file, filecontent)
|
||||
with zipfile.ZipFile(temp_file, "r") as zip_file:
|
||||
@@ -622,10 +577,9 @@ class HacsRepository:
|
||||
"""Download the content of a directory."""
|
||||
if self.hacs.configuration.experimental:
|
||||
if (
|
||||
not self.data.zip_release
|
||||
not self.repository_manifest.zip_release
|
||||
and not self.data.file_name
|
||||
and self.data.category == HacsCategory.INTEGRATION
|
||||
and self.content.path.remote
|
||||
and self.content.path.remote is not None
|
||||
):
|
||||
self.logger.info("%s Trying experimental download", self.string)
|
||||
try:
|
||||
@@ -635,16 +589,16 @@ class HacsRepository:
|
||||
self.logger.exception(exception)
|
||||
|
||||
contents = self.gather_files_to_download()
|
||||
if self.data.filename:
|
||||
self.logger.debug("%s %s", self.string, self.data.filename)
|
||||
if self.repository_manifest.filename:
|
||||
self.logger.debug("%s %s", self.string, self.repository_manifest.filename)
|
||||
if not contents:
|
||||
raise HacsException("No content to download")
|
||||
|
||||
download_queue = QueueManager(hass=self.hacs.hass)
|
||||
|
||||
for content in contents:
|
||||
if self.data.content_in_root and self.data.filename:
|
||||
if content.name != self.data.filename:
|
||||
if self.repository_manifest.content_in_root and self.repository_manifest.filename:
|
||||
if content.name != self.repository_manifest.filename:
|
||||
continue
|
||||
download_queue.add(self.dowload_repository_content(content))
|
||||
|
||||
@@ -670,7 +624,7 @@ class HacsRepository:
|
||||
raise HacsException(f"[{self}] Failed to download zipball")
|
||||
|
||||
temp_dir = await self.hacs.hass.async_add_executor_job(tempfile.mkdtemp)
|
||||
temp_file = f"{temp_dir}/{self.data.filename}"
|
||||
temp_file = f"{temp_dir}/{self.repository_manifest.filename}"
|
||||
result = await self.hacs.async_save_file(temp_file, filecontent)
|
||||
if not result:
|
||||
raise HacsException("Could not save ZIP file")
|
||||
@@ -702,7 +656,7 @@ class HacsRepository:
|
||||
raise_exception=False,
|
||||
repository=self.data.full_name,
|
||||
path=RepositoryFile.HACS_JSON,
|
||||
**{"params": {"ref": ref or version_to_download(self)}},
|
||||
**{"params": {"ref": ref or self.version_to_download()}},
|
||||
)
|
||||
if response:
|
||||
return json.loads(decode_content(response.data.content))
|
||||
@@ -715,7 +669,7 @@ class HacsRepository:
|
||||
def _info_file_variants() -> tuple[str, ...]:
|
||||
name: str = (
|
||||
"readme"
|
||||
if self.data.render_readme or self.hacs.configuration.experimental
|
||||
if self.repository_manifest.render_readme or self.hacs.configuration.experimental
|
||||
else "info"
|
||||
)
|
||||
return (
|
||||
@@ -779,8 +733,8 @@ class HacsRepository:
|
||||
|
||||
self.data.installed_version = None
|
||||
self.data.installed_commit = None
|
||||
self.hacs.hass.bus.async_fire(
|
||||
"hacs/repository",
|
||||
self.hacs.async_dispatch(
|
||||
HacsDispatchEvent.REPOSITORY,
|
||||
{
|
||||
"id": 1337,
|
||||
"action": "uninstall",
|
||||
@@ -844,6 +798,7 @@ class HacsRepository:
|
||||
async def async_pre_registration(self) -> None:
|
||||
"""Run pre registration steps."""
|
||||
|
||||
@concurrent(concurrenttasks=10)
|
||||
async def async_registration(self, ref=None) -> None:
|
||||
"""Run registration steps."""
|
||||
await self.async_pre_registration()
|
||||
@@ -867,6 +822,8 @@ class HacsRepository:
|
||||
|
||||
async def async_post_registration(self) -> None:
|
||||
"""Run post registration steps."""
|
||||
if not self.hacs.system.action:
|
||||
return
|
||||
await self.hacs.validation.async_run_repository_checks(self)
|
||||
|
||||
async def async_pre_install(self) -> None:
|
||||
@@ -881,10 +838,22 @@ class HacsRepository:
|
||||
async def async_install(self) -> None:
|
||||
"""Run install steps."""
|
||||
await self._async_pre_install()
|
||||
self.hacs.async_dispatch(
|
||||
HacsDispatchEvent.REPOSITORY_DOWNLOAD_PROGRESS,
|
||||
{"repository": self.data.full_name, "progress": 30},
|
||||
)
|
||||
self.logger.info("%s Running installation steps", self.string)
|
||||
await self.async_install_repository()
|
||||
self.hacs.async_dispatch(
|
||||
HacsDispatchEvent.REPOSITORY_DOWNLOAD_PROGRESS,
|
||||
{"repository": self.data.full_name, "progress": 90},
|
||||
)
|
||||
self.logger.info("%s Installation steps completed", self.string)
|
||||
await self._async_post_install()
|
||||
self.hacs.async_dispatch(
|
||||
HacsDispatchEvent.REPOSITORY_DOWNLOAD_PROGRESS,
|
||||
{"repository": self.data.full_name, "progress": False},
|
||||
)
|
||||
|
||||
async def async_post_installation(self) -> None:
|
||||
"""Run post install steps."""
|
||||
@@ -894,8 +863,8 @@ class HacsRepository:
|
||||
self.logger.info("%s Running post installation steps", self.string)
|
||||
await self.async_post_installation()
|
||||
self.data.new = False
|
||||
self.hacs.hass.bus.async_fire(
|
||||
"hacs/repository",
|
||||
self.hacs.async_dispatch(
|
||||
HacsDispatchEvent.REPOSITORY,
|
||||
{
|
||||
"id": 1337,
|
||||
"action": "install",
|
||||
@@ -916,21 +885,28 @@ class HacsRepository:
|
||||
if not self.can_download:
|
||||
raise HacsException("The version of Home Assistant is not compatible with this version")
|
||||
|
||||
version = version_to_download(self)
|
||||
version = self.version_to_download()
|
||||
if version == self.data.default_branch:
|
||||
self.ref = version
|
||||
else:
|
||||
self.ref = f"tags/{version}"
|
||||
|
||||
self.hacs.async_dispatch(
|
||||
HacsDispatchEvent.REPOSITORY_DOWNLOAD_PROGRESS,
|
||||
{"repository": self.data.full_name, "progress": 40},
|
||||
)
|
||||
|
||||
if self.data.installed and self.data.category == "netdaemon":
|
||||
persistent_directory = BackupNetDaemon(hacs=self.hacs, repository=self)
|
||||
await self.hacs.hass.async_add_executor_job(persistent_directory.create)
|
||||
|
||||
elif self.data.persistent_directory:
|
||||
if os.path.exists(f"{self.content.path.local}/{self.data.persistent_directory}"):
|
||||
elif self.repository_manifest.persistent_directory:
|
||||
if os.path.exists(
|
||||
f"{self.content.path.local}/{self.repository_manifest.persistent_directory}"
|
||||
):
|
||||
persistent_directory = Backup(
|
||||
hacs=self.hacs,
|
||||
local_path=f"{self.content.path.local}/{self.data.persistent_directory}",
|
||||
local_path=f"{self.content.path.local}/{self.repository_manifest.persistent_directory}",
|
||||
backup_path=tempfile.gettempdir() + "/hacs_persistent_directory/",
|
||||
)
|
||||
await self.hacs.hass.async_add_executor_job(persistent_directory.create)
|
||||
@@ -942,11 +918,21 @@ class HacsRepository:
|
||||
self.hacs.log.debug("%s Local path is set to %s", self.string, self.content.path.local)
|
||||
self.hacs.log.debug("%s Remote path is set to %s", self.string, self.content.path.remote)
|
||||
|
||||
if self.data.zip_release and version != self.data.default_branch:
|
||||
self.hacs.async_dispatch(
|
||||
HacsDispatchEvent.REPOSITORY_DOWNLOAD_PROGRESS,
|
||||
{"repository": self.data.full_name, "progress": 50},
|
||||
)
|
||||
|
||||
if self.repository_manifest.zip_release and version != self.data.default_branch:
|
||||
await self.download_zip_files(self.validate)
|
||||
else:
|
||||
await self.download_content()
|
||||
|
||||
self.hacs.async_dispatch(
|
||||
HacsDispatchEvent.REPOSITORY_DOWNLOAD_PROGRESS,
|
||||
{"repository": self.data.full_name, "progress": 70},
|
||||
)
|
||||
|
||||
if self.validate.errors:
|
||||
for error in self.validate.errors:
|
||||
self.logger.error("%s %s", self.string, error)
|
||||
@@ -955,6 +941,11 @@ class HacsRepository:
|
||||
await self.hacs.hass.async_add_executor_job(backup.cleanup)
|
||||
raise HacsException("Could not download, see log for details")
|
||||
|
||||
self.hacs.async_dispatch(
|
||||
HacsDispatchEvent.REPOSITORY_DOWNLOAD_PROGRESS,
|
||||
{"repository": self.data.full_name, "progress": 80},
|
||||
)
|
||||
|
||||
if self.data.installed and not self.content.single:
|
||||
await self.hacs.hass.async_add_executor_job(backup.cleanup)
|
||||
|
||||
@@ -1068,7 +1059,7 @@ class HacsRepository:
|
||||
self.data.releases = False
|
||||
|
||||
if not self.force_branch:
|
||||
self.ref = version_to_download(self)
|
||||
self.ref = self.version_to_download()
|
||||
if self.data.releases:
|
||||
for release in self.releases.objects or []:
|
||||
if release.tag_name == self.ref:
|
||||
@@ -1141,8 +1132,8 @@ class HacsRepository:
|
||||
if files:
|
||||
return files
|
||||
|
||||
if self.data.content_in_root:
|
||||
if not self.data.filename:
|
||||
if self.repository_manifest.content_in_root:
|
||||
if not self.repository_manifest.filename:
|
||||
if category == "theme":
|
||||
tree = filter_content_return_one_of_type(self.tree, "", "yaml", "full_path")
|
||||
|
||||
@@ -1171,7 +1162,7 @@ class HacsRepository:
|
||||
|
||||
else:
|
||||
_content_path = content.path
|
||||
if not self.data.content_in_root:
|
||||
if not self.repository_manifest.content_in_root:
|
||||
_content_path = _content_path.replace(f"{self.content.path.remote}", "")
|
||||
|
||||
local_directory = f"{self.content.path.local}/{_content_path}"
|
||||
@@ -1197,7 +1188,6 @@ class HacsRepository:
|
||||
"""Remove the entity device."""
|
||||
if (
|
||||
self.hacs.configuration == ConfigurationType.YAML
|
||||
or not self.hacs.core.ha_version >= "2022.4.0.dev0"
|
||||
or not self.hacs.configuration.experimental
|
||||
):
|
||||
return
|
||||
@@ -1209,3 +1199,21 @@ class HacsRepository:
|
||||
return
|
||||
|
||||
device_registry.async_remove_device(device_id=device.id)
|
||||
|
||||
def version_to_download(self) -> str:
|
||||
"""Determine which version to download."""
|
||||
if self.data.last_version is not None:
|
||||
if self.data.selected_tag is not None:
|
||||
if self.data.selected_tag == self.data.last_version:
|
||||
self.data.selected_tag = None
|
||||
return self.data.last_version
|
||||
return self.data.selected_tag
|
||||
return self.data.last_version
|
||||
|
||||
if self.data.selected_tag is not None:
|
||||
if self.data.selected_tag == self.data.default_branch:
|
||||
return self.data.default_branch
|
||||
if self.data.selected_tag in self.data.published_tags:
|
||||
return self.data.selected_tag
|
||||
|
||||
return self.data.default_branch or "main"
|
||||
|
||||
@@ -6,12 +6,11 @@ from typing import TYPE_CHECKING, Any
|
||||
|
||||
from homeassistant.loader import async_get_custom_components
|
||||
|
||||
from ..enums import HacsCategory, HacsGitHubRepo, RepositoryFile
|
||||
from ..enums import HacsCategory, HacsDispatchEvent, HacsGitHubRepo, RepositoryFile
|
||||
from ..exceptions import AddonRepositoryException, HacsException
|
||||
from ..utils.decode import decode_content
|
||||
from ..utils.decorator import concurrent
|
||||
from ..utils.filters import get_first_directory_in_directory
|
||||
from ..utils.version import version_to_download
|
||||
from .base import HacsRepository
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -50,7 +49,7 @@ class HacsIntegrationRepository(HacsRepository):
|
||||
await self.common_validate()
|
||||
|
||||
# Custom step 1: Validate content.
|
||||
if self.data.content_in_root:
|
||||
if self.repository_manifest.content_in_root:
|
||||
self.content.path.remote = ""
|
||||
|
||||
if self.content.path.remote == "custom_components":
|
||||
@@ -100,7 +99,7 @@ class HacsIntegrationRepository(HacsRepository):
|
||||
if not await self.common_update(ignore_issues, force) and not force:
|
||||
return
|
||||
|
||||
if self.data.content_in_root:
|
||||
if self.repository_manifest.content_in_root:
|
||||
self.content.path.remote = ""
|
||||
|
||||
if self.content.path.remote == "custom_components":
|
||||
@@ -129,8 +128,8 @@ class HacsIntegrationRepository(HacsRepository):
|
||||
|
||||
# Signal entities to refresh
|
||||
if self.data.installed:
|
||||
self.hacs.hass.bus.async_fire(
|
||||
"hacs/repository",
|
||||
self.hacs.async_dispatch(
|
||||
HacsDispatchEvent.REPOSITORY,
|
||||
{
|
||||
"id": 1337,
|
||||
"action": "update",
|
||||
@@ -150,7 +149,7 @@ class HacsIntegrationRepository(HacsRepository):
|
||||
"""Get the content of the manifest.json file."""
|
||||
manifest_path = (
|
||||
"manifest.json"
|
||||
if self.data.content_in_root
|
||||
if self.repository_manifest.content_in_root
|
||||
else f"{self.content.path.remote}/{RepositoryFile.MAINIFEST_JSON}"
|
||||
)
|
||||
|
||||
@@ -161,7 +160,7 @@ class HacsIntegrationRepository(HacsRepository):
|
||||
method=self.hacs.githubapi.repos.contents.get,
|
||||
repository=self.data.full_name,
|
||||
path=manifest_path,
|
||||
**{"params": {"ref": ref or version_to_download(self)}},
|
||||
**{"params": {"ref": ref or self.version_to_download()}},
|
||||
)
|
||||
if response:
|
||||
return json.loads(decode_content(response.data.content))
|
||||
|
||||
@@ -3,7 +3,7 @@ from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from ..enums import HacsCategory
|
||||
from ..enums import HacsCategory, HacsDispatchEvent
|
||||
from ..exceptions import HacsException
|
||||
from ..utils import filters
|
||||
from ..utils.decorator import concurrent
|
||||
@@ -36,7 +36,7 @@ class HacsNetdaemonRepository(HacsRepository):
|
||||
|
||||
# Custom step 1: Validate content.
|
||||
if self.repository_manifest:
|
||||
if self.data.content_in_root:
|
||||
if self.repository_manifest.content_in_root:
|
||||
self.content.path.remote = ""
|
||||
|
||||
if self.content.path.remote == "apps":
|
||||
@@ -70,7 +70,7 @@ class HacsNetdaemonRepository(HacsRepository):
|
||||
|
||||
# Get appdaemon objects.
|
||||
if self.repository_manifest:
|
||||
if self.data.content_in_root:
|
||||
if self.repository_manifest.content_in_root:
|
||||
self.content.path.remote = ""
|
||||
|
||||
if self.content.path.remote == "apps":
|
||||
@@ -84,8 +84,8 @@ class HacsNetdaemonRepository(HacsRepository):
|
||||
|
||||
# Signal entities to refresh
|
||||
if self.data.installed:
|
||||
self.hacs.hass.bus.async_fire(
|
||||
"hacs/repository",
|
||||
self.hacs.async_dispatch(
|
||||
HacsDispatchEvent.REPOSITORY,
|
||||
{
|
||||
"id": 1337,
|
||||
"action": "update",
|
||||
|
||||
@@ -4,6 +4,7 @@ from __future__ import annotations
|
||||
import json
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from ..enums import HacsCategory, HacsDispatchEvent
|
||||
from ..exceptions import HacsException
|
||||
from ..utils.decorator import concurrent
|
||||
from .base import HacsRepository
|
||||
@@ -21,7 +22,7 @@ class HacsPluginRepository(HacsRepository):
|
||||
self.data.full_name = full_name
|
||||
self.data.full_name_lower = full_name.lower()
|
||||
self.data.file_name = None
|
||||
self.data.category = "plugin"
|
||||
self.data.category = HacsCategory.PLUGIN
|
||||
self.content.path.local = self.localpath
|
||||
|
||||
@property
|
||||
@@ -71,8 +72,8 @@ class HacsPluginRepository(HacsRepository):
|
||||
|
||||
# Signal entities to refresh
|
||||
if self.data.installed:
|
||||
self.hacs.hass.bus.async_fire(
|
||||
"hacs/repository",
|
||||
self.hacs.async_dispatch(
|
||||
HacsDispatchEvent.REPOSITORY,
|
||||
{
|
||||
"id": 1337,
|
||||
"action": "update",
|
||||
@@ -94,11 +95,13 @@ class HacsPluginRepository(HacsRepository):
|
||||
|
||||
def update_filenames(self) -> None:
|
||||
"""Get the filename to target."""
|
||||
possible_locations = ("",) if self.data.content_in_root else ("release", "dist", "")
|
||||
possible_locations = (
|
||||
("",) if self.repository_manifest.content_in_root else ("release", "dist", "")
|
||||
)
|
||||
|
||||
# Handler for plug requirement 3
|
||||
if self.data.filename:
|
||||
valid_filenames = (self.data.filename,)
|
||||
if self.repository_manifest.filename:
|
||||
valid_filenames = (self.repository_manifest.filename,)
|
||||
else:
|
||||
valid_filenames = (
|
||||
f"{self.data.name.replace('lovelace-', '')}.js",
|
||||
|
||||
@@ -3,7 +3,7 @@ from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from ..enums import HacsCategory
|
||||
from ..enums import HacsCategory, HacsDispatchEvent
|
||||
from ..exceptions import HacsException
|
||||
from ..utils.decorator import concurrent
|
||||
from .base import HacsRepository
|
||||
@@ -38,7 +38,7 @@ class HacsPythonScriptRepository(HacsRepository):
|
||||
await self.common_validate()
|
||||
|
||||
# Custom step 1: Validate content.
|
||||
if self.data.content_in_root:
|
||||
if self.repository_manifest.content_in_root:
|
||||
self.content.path.remote = ""
|
||||
|
||||
compliant = False
|
||||
@@ -70,7 +70,7 @@ class HacsPythonScriptRepository(HacsRepository):
|
||||
return
|
||||
|
||||
# Get python_script objects.
|
||||
if self.data.content_in_root:
|
||||
if self.repository_manifest.content_in_root:
|
||||
self.content.path.remote = ""
|
||||
|
||||
compliant = False
|
||||
@@ -88,8 +88,8 @@ class HacsPythonScriptRepository(HacsRepository):
|
||||
|
||||
# Signal entities to refresh
|
||||
if self.data.installed:
|
||||
self.hacs.hass.bus.async_fire(
|
||||
"hacs/repository",
|
||||
self.hacs.async_dispatch(
|
||||
HacsDispatchEvent.REPOSITORY,
|
||||
{
|
||||
"id": 1337,
|
||||
"action": "update",
|
||||
|
||||
@@ -3,7 +3,7 @@ from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from ..enums import HacsCategory
|
||||
from ..enums import HacsCategory, HacsDispatchEvent
|
||||
from ..exceptions import HacsException
|
||||
from ..utils.decorator import concurrent
|
||||
from .base import HacsRepository
|
||||
@@ -53,7 +53,7 @@ class HacsThemeRepository(HacsRepository):
|
||||
f"Repository structure for {self.ref.replace('tags/','')} is not compliant"
|
||||
)
|
||||
|
||||
if self.data.content_in_root:
|
||||
if self.repository_manifest.content_in_root:
|
||||
self.content.path.remote = ""
|
||||
|
||||
# Handle potential errors
|
||||
@@ -76,7 +76,7 @@ class HacsThemeRepository(HacsRepository):
|
||||
return
|
||||
|
||||
# Get theme objects.
|
||||
if self.data.content_in_root:
|
||||
if self.repository_manifest.content_in_root:
|
||||
self.content.path.remote = ""
|
||||
|
||||
# Update name
|
||||
@@ -85,8 +85,8 @@ class HacsThemeRepository(HacsRepository):
|
||||
|
||||
# Signal entities to refresh
|
||||
if self.data.installed:
|
||||
self.hacs.hass.bus.async_fire(
|
||||
"hacs/repository",
|
||||
self.hacs.async_dispatch(
|
||||
HacsDispatchEvent.REPOSITORY,
|
||||
{
|
||||
"id": 1337,
|
||||
"action": "update",
|
||||
|
||||
Reference in New Issue
Block a user