async def get(self, request, requested_file): # pylint: disable=unused-argument """DEPRECATED.""" hacs = get_hacs() if hacs.system.ha_version.split(".")[1] >= "107": logger = Logger("hacs.deprecated") logger.warning( "The '/community_plugin/*' is deprecated and will be removed in an upcoming version of HACS, it has been replaced by '/hacsfiles/*', if you use the UI to manage your lovelace configuration, you can update this by going to the settings tab in HACS, if you use YAML to manage your lovelace configuration, you manually need to replace the URL in your resources." ) return await get_file_response(requested_file)
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 def write(self): """Write content to the store files.""" if self.system.status.background_task: return self.logger.debug("Saving data") # Hacs path = f"{self.system.config_path}/.storage/{STORES['hacs']}" hacs = {"view": self.configuration.frontend_mode} save(self.logger, path, hacs) # Installed path = f"{self.system.config_path}/.storage/{STORES['installed']}" installed = {} for repository_name in self.common.installed: repository = self.get_by_name(repository_name) if repository is None: self.logger.warning( f"Did not save information about {repository_name}") continue installed[repository.information.full_name] = { "version_type": repository.display_version_or_commit, "version_installed": repository.display_installed_version, "version_available": repository.display_available_version, } save(self.logger, path, installed) # Repositories path = f"{self.system.config_path}/.storage/{STORES['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, } # Validate installed repositories count_installed = len(installed) + 1 # For HACS it self count_installed_restore = 0 for repository in self.repositories: if repository.status.installed: count_installed_restore += 1 if count_installed < count_installed_restore: self.logger.debug("Save failed!") self.logger.debug( f"Number of installed repositories does not match the number of stored repositories [{count_installed} vs {count_installed_restore}]" ) return save(self.logger, path, content) async def restore(self): """Restore saved data.""" try: hacs = self.read("hacs") installed = self.read("installed") repositrories = self.read("repositories") 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 installed is None and repositrories is None: # Assume new install return True self.logger.info("Restore started") # Hacs hacs = hacs["data"] self.configuration.frontend_mode = hacs["view"] # Installed installed = installed["data"] for repository in installed: self.common.installed.append(repository) # Repositories repositrories = repositrories["data"] for entry in repositrories: repo = repositrories[entry] 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( 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"] == "custom-components/hacs": 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"] if repo["full_name"] in self.common.installed: repository.status.installed = True repository.status.new = False frominstalled = installed[repo["full_name"]] if frominstalled["version_type"] == "commit": repository.versions.installed_commit = frominstalled[ "version_installed"] repository.versions.available_commit = frominstalled[ "version_available"] else: repository.versions.installed = frominstalled[ "version_installed"] repository.versions.available = frominstalled[ "version_available"] # Check the restore. count_installed = len(installed) + 1 # For HACS it self count_installed_restore = 0 installed_restore = [] for repository in self.repositories: if repository.status.installed: installed_restore.append(repository.information.full_name) if (repository.information.full_name not in self.common.installed and repository.information.full_name != "custom-components/hacs"): self.logger.warning( f"{repository.information.full_name} is not in common.installed" ) count_installed_restore += 1 if count_installed < count_installed_restore: for repo in installed: installed_restore.remove(repo) self.logger.warning(f"Check {repo}") self.logger.critical("Restore failed!") self.logger.critical( f"Number of installed repositories does not match the number of restored repositories [{count_installed} vs {count_installed_restore}]" ) return False self.logger.info("Restore done") except Exception as exception: self.logger.critical(f"[{exception}] Restore Failed!") return False return True