some new automations
This commit is contained in:
@@ -0,0 +1,215 @@
|
||||
"""Data handler for HACS."""
|
||||
import os
|
||||
import json
|
||||
from integrationhelper import Logger
|
||||
from . import Hacs
|
||||
from .const import STORAGE_VERSION
|
||||
from ..const import VERSION
|
||||
from ..repositories.manifest import HacsManifest
|
||||
from ..store import async_save_to_store, async_load_from_store
|
||||
|
||||
|
||||
STORES = {
|
||||
"old": "hacs",
|
||||
"hacs": "hacs.hacs",
|
||||
"installed": "hacs.installed",
|
||||
"repositories": "hacs.repositories",
|
||||
}
|
||||
|
||||
|
||||
class HacsData(Hacs):
|
||||
"""HacsData class."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize."""
|
||||
self.logger = Logger("hacs.data")
|
||||
|
||||
def check_corrupted_files(self):
|
||||
"""Return True if one (or more) of the files are corrupted."""
|
||||
for store in STORES:
|
||||
path = f"{self.system.config_path}/.storage/{STORES[store]}"
|
||||
if os.path.exists(path):
|
||||
if os.stat(path).st_size == 0:
|
||||
# File is empty (corrupted)
|
||||
return True
|
||||
return False
|
||||
|
||||
def read(self, store):
|
||||
"""Return data from a store."""
|
||||
path = f"{self.system.config_path}/.storage/{STORES[store]}"
|
||||
content = None
|
||||
if os.path.exists(path):
|
||||
with open(path, "r", encoding="utf-8") as storefile:
|
||||
content = storefile.read()
|
||||
content = json.loads(content)
|
||||
return content
|
||||
|
||||
async def async_write(self):
|
||||
"""Write content to the store files."""
|
||||
if self.system.status.background_task:
|
||||
return
|
||||
|
||||
self.logger.debug("Saving data")
|
||||
|
||||
# Hacs
|
||||
await async_save_to_store(
|
||||
self.hass, "hacs", {"view": self.configuration.frontend_mode}
|
||||
)
|
||||
|
||||
# Repositories
|
||||
content = {}
|
||||
for repository in self.repositories:
|
||||
if repository.repository_manifest is not None:
|
||||
repository_manifest = repository.repository_manifest.manifest
|
||||
else:
|
||||
repository_manifest = None
|
||||
content[repository.information.uid] = {
|
||||
"authors": repository.information.authors,
|
||||
"topics": repository.information.topics,
|
||||
"category": repository.information.category,
|
||||
"description": repository.information.description,
|
||||
"full_name": repository.information.full_name,
|
||||
"hide": repository.status.hide,
|
||||
"installed_commit": repository.versions.installed_commit,
|
||||
"installed": repository.status.installed,
|
||||
"last_commit": repository.versions.available_commit,
|
||||
"last_release_tag": repository.versions.available,
|
||||
"repository_manifest": repository_manifest,
|
||||
"name": repository.information.name,
|
||||
"new": repository.status.new,
|
||||
"selected_tag": repository.status.selected_tag,
|
||||
"show_beta": repository.status.show_beta,
|
||||
"version_installed": repository.versions.installed,
|
||||
}
|
||||
|
||||
await async_save_to_store(self.hass, "repositories", content)
|
||||
self.hass.bus.async_fire("hacs/repository", {})
|
||||
self.hass.bus.fire("hacs/config", {})
|
||||
|
||||
async def restore(self):
|
||||
"""Restore saved data."""
|
||||
hacs = {}
|
||||
repositories = {}
|
||||
|
||||
try:
|
||||
hacs = await async_load_from_store(self.hass, "hacs")
|
||||
except KeyError:
|
||||
await async_save_to_store(self.hass, "hacs", self.data.read("hacs")["data"])
|
||||
hacs = await async_load_from_store(self.hass, "hacs")
|
||||
|
||||
try:
|
||||
repositories = await async_load_from_store(self.hass, "repositories")
|
||||
except KeyError:
|
||||
await async_save_to_store(
|
||||
self.hass, "repositories", self.data.read("repositories")["data"]
|
||||
)
|
||||
repositories = await async_load_from_store(self.hass, "repositories")
|
||||
|
||||
try:
|
||||
if self.check_corrupted_files():
|
||||
# Coruptted installation
|
||||
self.logger.critical("Restore failed one or more files are corrupted!")
|
||||
return False
|
||||
if hacs is None and repositories is None:
|
||||
# Assume new install
|
||||
return True
|
||||
|
||||
self.logger.info("Restore started")
|
||||
|
||||
# Hacs
|
||||
self.configuration.frontend_mode = hacs.get("view", "Grid")
|
||||
|
||||
# Repositories
|
||||
repositories = repositories
|
||||
for entry in repositories:
|
||||
repo = repositories[entry]
|
||||
if repo["full_name"] == "custom-components/hacs":
|
||||
# Skip the old repo location
|
||||
continue
|
||||
if not self.is_known(repo["full_name"]):
|
||||
await self.register_repository(
|
||||
repo["full_name"], repo["category"], False
|
||||
)
|
||||
repository = self.get_by_name(repo["full_name"])
|
||||
if repository is None:
|
||||
self.logger.error(f"Did not find {repo['full_name']}")
|
||||
continue
|
||||
|
||||
# Restore repository attributes
|
||||
if repo.get("authors") is not None:
|
||||
repository.information.authors = repo["authors"]
|
||||
|
||||
if repo.get("topics", []):
|
||||
repository.information.topics = repo["topics"]
|
||||
|
||||
if repo.get("description") is not None:
|
||||
repository.information.description = repo["description"]
|
||||
|
||||
if repo.get("name") is not None:
|
||||
repository.information.name = repo["name"]
|
||||
|
||||
if repo.get("hide") is not None:
|
||||
repository.status.hide = repo["hide"]
|
||||
|
||||
if repo.get("installed") is not None:
|
||||
repository.status.installed = repo["installed"]
|
||||
if repository.status.installed:
|
||||
repository.status.first_install = False
|
||||
|
||||
if repo.get("selected_tag") is not None:
|
||||
repository.status.selected_tag = repo["selected_tag"]
|
||||
|
||||
if repo.get("repository_manifest") is not None:
|
||||
repository.repository_manifest = HacsManifest.from_dict(
|
||||
repo["repository_manifest"]
|
||||
)
|
||||
|
||||
if repo.get("show_beta") is not None:
|
||||
repository.status.show_beta = repo["show_beta"]
|
||||
|
||||
if repo.get("last_commit") is not None:
|
||||
repository.versions.available_commit = repo["last_commit"]
|
||||
|
||||
repository.information.uid = entry
|
||||
|
||||
if repo.get("last_release_tag") is not None:
|
||||
repository.releases.last_release = repo["last_release_tag"]
|
||||
repository.versions.available = repo["last_release_tag"]
|
||||
|
||||
if repo.get("new") is not None:
|
||||
repository.status.new = repo["new"]
|
||||
|
||||
if repo["full_name"] == "hacs/integration":
|
||||
repository.versions.installed = VERSION
|
||||
repository.status.installed = True
|
||||
if "b" in VERSION:
|
||||
repository.status.show_beta = True
|
||||
elif repo.get("version_installed") is not None:
|
||||
repository.versions.installed = repo["version_installed"]
|
||||
|
||||
if repo.get("installed_commit") is not None:
|
||||
repository.versions.installed_commit = repo["installed_commit"]
|
||||
|
||||
self.logger.info("Restore done")
|
||||
except Exception as exception:
|
||||
self.logger.critical(
|
||||
f"[{exception}] Restore Failed! see https://github.com/hacs/integration/issues/639 for more details."
|
||||
)
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def save(logger, path, content):
|
||||
"""Save file."""
|
||||
from .backup import Backup
|
||||
|
||||
backup = Backup(path)
|
||||
backup.create()
|
||||
try:
|
||||
content = {"data": content, "schema": STORAGE_VERSION}
|
||||
with open(path, "w", encoding="utf-8") as storefile:
|
||||
json.dump(content, storefile, indent=4)
|
||||
except Exception as exception: # pylint: disable=broad-except
|
||||
logger.warning(f"Saving {path} failed - {exception}")
|
||||
backup.restore()
|
||||
backup.cleanup()
|
||||
Reference in New Issue
Block a user