diff --git a/hassio/addons/__init__.py b/hassio/addons/__init__.py index f432ac96c..a2891d21f 100644 --- a/hassio/addons/__init__.py +++ b/hassio/addons/__init__.py @@ -40,10 +40,10 @@ class AddonManager(AddonsData): tasks = [addon.load() for addon in self.repositories] if tasks: await asyncio.wait(tasks, loop=self.loop) - self.read_addons_repo() - # Update config - self.merge_local_config() + # read data from repositories + self.read_data_from_repositories() + self.merge_update_config() # load installed addons for addon in self.list_installed: @@ -53,7 +53,7 @@ class AddonManager(AddonsData): async def add_custom_repository(self, url): """Add a new custom repository.""" - if url in self.config.addons_repositories.keys(): + if url in self.config.addons_repositories: _LOGGER.warning("Repository already exists %s", url) return False @@ -63,6 +63,7 @@ class AddonManager(AddonsData): _LOGGER.error("Can't load from repository %s", url) return False + self.config.addons_repositories = repo self.repositories.append(repo) return True @@ -71,6 +72,7 @@ class AddonManager(AddonsData): for repo in self.repositories: if repo.url == url: repo = self.repositories.pop(repo, repo) + self.config.drop_addon_repository(url) repo.remove() return True @@ -84,9 +86,9 @@ class AddonManager(AddonsData): await asyncio.wait(tasks, loop=self.loop) - # Update config - self.read_addons_repo() - self.merge_local_config() + # read data from repositories + self.read_data_from_repositories() + self.merge_update_config() # remove stalled addons for addon in self.list_removed: diff --git a/hassio/addons/data.py b/hassio/addons/data.py index d43131f88..e42d6f630 100644 --- a/hassio/addons/data.py +++ b/hassio/addons/data.py @@ -42,7 +42,7 @@ class AddonsData(Config): } super().save() - def read_addons_repo(self): + def read_data_from_repositories(self): """Read data from addons repository.""" self._current_data = {} @@ -67,7 +67,7 @@ class AddonsData(Config): _LOGGER.warning("Can't read %s -> %s", addon, humanize_error(addon_config, ex)) - def merge_local_config(self): + def merge_update_config(self): """Update local config if they have update. It need to be the same version as the local version is. diff --git a/hassio/addons/git.py b/hassio/addons/git.py index 16ace9e08..02f015a97 100644 --- a/hassio/addons/git.py +++ b/hassio/addons/git.py @@ -3,10 +3,10 @@ import asyncio import logging import os import shutil -import tempfile import git +from .util import get_hash_from_repository from ..const import URL_HASSIO_ADDONS _LOGGER = logging.getLogger(__name__) @@ -86,17 +86,11 @@ class AddonsRepoHassIO(AddonsRepo): class AddonsRepoCustom(AddonsRepo): """Custom addons repository.""" - def __init__(self, config, loop, url, slug=None): + def __init__(self, config, loop, url): """Initialize git hassio addon repository.""" - if slug is None: - _LOGGER("Init new custom addon repository %s", url) - with tempfile.TemporaryDirectory(dir=config.path_addons_custom) \ - as temp_dir: - slug = temp_dir.name + path = os.path.join( + config.path_addons_custom, get_hash_from_repository(url)) - config.add_addons_repository(url, slug) - - path = os.path.join(config.path_addons_custom, slug) super().__init__(config, loop, path, url) def remove(self): @@ -109,5 +103,3 @@ class AddonsRepoCustom(AddonsRepo): _LOGGER.warning("Can't remove %s", path) shutil.rmtree(self.path, onerror=log_err) - - self.config.drop_addons_repository(self.url) diff --git a/hassio/addons/util.py b/hassio/addons/util.py new file mode 100644 index 000000000..688291246 --- /dev/null +++ b/hassio/addons/util.py @@ -0,0 +1,8 @@ +"""Util addons functions.""" +import hashlib + + +def get_hash_from_repository(repo): + """Generate a hash from repository.""" + key = repo.lower().encode() + return hashlib.sha1(key).hexdigest() diff --git a/hassio/api/supervisor.py b/hassio/api/supervisor.py index 28e3e03d0..938b7f685 100644 --- a/hassio/api/supervisor.py +++ b/hassio/api/supervisor.py @@ -46,8 +46,7 @@ class APISupervisor(object): ATTR_LAST_VERSION: self.config.last_hassio, ATTR_BETA_CHANNEL: self.config.upstream_beta, ATTR_ADDONS: self.addons.list_api, - ATTR_ADDONS_REPOSITORIES: - list(self.config.addons_repositories.keys()), + ATTR_ADDONS_REPOSITORIES: list(self.config.addons_repositories), } @api_process @@ -70,7 +69,7 @@ class APISupervisor(object): for url in set(old - new): self.addons.drop_custom_repository(url) - return self.config.save() + return True @api_process async def update(self, request): diff --git a/hassio/config.py b/hassio/config.py index 86b8d61c9..f8bba1749 100644 --- a/hassio/config.py +++ b/hassio/config.py @@ -44,9 +44,7 @@ SCHEMA_CONFIG = vol.Schema({ vol.Optional(HOMEASSISTANT_LAST): vol.Coerce(str), vol.Optional(HASSIO_LAST): vol.Coerce(str), vol.Optional(HASSIO_CLEANUP): vol.Coerce(str), - vol.Optional(ADDONS_CUSTOM_LIST, default={}): { - vol.Url(): vol.Coerce(str), - } + vol.Optional(ADDONS_CUSTOM_LIST, default=[]): [vol.Url()], }, extra=vol.REMOVE_EXTRA) @@ -214,17 +212,21 @@ class CoreConfig(Config): """Return root backup data folder extern for docker.""" return BACKUP_DATA.format(self.path_hassio_docker) - def add_addons_repository(self, repo, slug): + @addons_repositories.setter + def addons_repositories(self, repo): """Add a custom repository to list.""" - self._data[ADDONS_CUSTOM_LIST][repo] = slug - self.save() + if repo in self._data[ADDONS_CUSTOM_LIST]: + return - def drop_addons_repository(self, repo): - """Remove a custom repository from list.""" - if self._data[ADDONS_CUSTOM_LIST].pop(repo, None): - self.save() + self._data[ADDONS_CUSTOM_LIST].append(repo) + self.save() @property def addons_repositories(self): """Return list of addons custom repositories.""" return self._data[ADDONS_CUSTOM_LIST] + + def drop_addon_repository(self, repo): + """Remove a custom repository from list.""" + if self._data[ADDONS_CUSTOM_LIST].pop(repo, False): + self.save()