mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-19 15:16:33 +00:00
Addon repositories (#2071)
* stash * Add test * Use executor * Make remove a coroutine * Change logging and return
This commit is contained in:
parent
9274a0fa17
commit
1af90721cc
@ -142,6 +142,10 @@ class APISupervisor(CoreSysAttributes):
|
||||
if ATTR_ADDONS_REPOSITORIES in body:
|
||||
new = set(body[ATTR_ADDONS_REPOSITORIES])
|
||||
await asyncio.shield(self.sys_store.update_repositories(new))
|
||||
if sorted(body[ATTR_ADDONS_REPOSITORIES]) != sorted(
|
||||
self.sys_config.addons_repositories
|
||||
):
|
||||
raise APIError("Not a valid add-on repository")
|
||||
|
||||
self.sys_updater.save_data()
|
||||
self.sys_config.save_data()
|
||||
|
@ -1,10 +1,17 @@
|
||||
"""Add-on Store handler."""
|
||||
import asyncio
|
||||
import logging
|
||||
from pathlib import Path
|
||||
from typing import Dict, List
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from supervisor.store.validate import SCHEMA_REPOSITORY_CONFIG
|
||||
from supervisor.utils.json import read_json_file
|
||||
|
||||
from ..const import REPOSITORY_CORE, REPOSITORY_LOCAL
|
||||
from ..coresys import CoreSys, CoreSysAttributes
|
||||
from ..exceptions import JsonFileError
|
||||
from .addon import AddonStore
|
||||
from .data import StoreData
|
||||
from .repository import Repository
|
||||
@ -60,19 +67,31 @@ class StoreManager(CoreSysAttributes):
|
||||
if not await repository.load():
|
||||
_LOGGER.error("Can't load from repository %s", url)
|
||||
return
|
||||
self.repositories[url] = repository
|
||||
|
||||
# don't add built-in repository to config
|
||||
if url not in BUILTIN_REPOSITORIES:
|
||||
# Verify that it is a add-on repository
|
||||
repository_file = Path(repository.git.path, "repository.json")
|
||||
try:
|
||||
await self.sys_run_in_executor(
|
||||
SCHEMA_REPOSITORY_CONFIG, read_json_file(repository_file)
|
||||
)
|
||||
except (JsonFileError, vol.Invalid) as err:
|
||||
_LOGGER.error("%s is not a valid add-on repository. %s", url, err)
|
||||
await repository.remove()
|
||||
return
|
||||
|
||||
self.sys_config.add_addon_repository(url)
|
||||
|
||||
self.repositories[url] = repository
|
||||
|
||||
tasks = [_add_repository(url) for url in new_rep - old_rep]
|
||||
if tasks:
|
||||
await asyncio.wait(tasks)
|
||||
|
||||
# del new repository
|
||||
for url in old_rep - new_rep - BUILTIN_REPOSITORIES:
|
||||
self.repositories.pop(url).remove()
|
||||
await self.repositories.pop(url).remove()
|
||||
self.sys_config.drop_addon_repository(url)
|
||||
|
||||
# update data
|
||||
|
@ -94,7 +94,7 @@ class GitRepo(CoreSysAttributes):
|
||||
async def pull(self):
|
||||
"""Pull Git add-on repo."""
|
||||
if self.lock.locked():
|
||||
_LOGGER.warning("It is already a task in progress")
|
||||
_LOGGER.warning("There is already a task in progress")
|
||||
return False
|
||||
|
||||
async with self.lock:
|
||||
@ -128,8 +128,12 @@ class GitRepo(CoreSysAttributes):
|
||||
|
||||
return True
|
||||
|
||||
def _remove(self):
|
||||
async def _remove(self):
|
||||
"""Remove a repository."""
|
||||
if self.lock.locked():
|
||||
_LOGGER.warning("There is already a task in progress")
|
||||
return
|
||||
|
||||
if not self.path.is_dir():
|
||||
return
|
||||
|
||||
@ -137,7 +141,9 @@ class GitRepo(CoreSysAttributes):
|
||||
"""Log error."""
|
||||
_LOGGER.warning("Can't remove %s", path)
|
||||
|
||||
shutil.rmtree(self.path, onerror=log_err)
|
||||
await self.sys_run_in_executor(
|
||||
ft.partial(shutil.rmtree, self.path, onerror=log_err)
|
||||
)
|
||||
|
||||
|
||||
class GitRepoHassIO(GitRepo):
|
||||
@ -157,7 +163,7 @@ class GitRepoCustom(GitRepo):
|
||||
|
||||
super().__init__(coresys, path, url)
|
||||
|
||||
def remove(self):
|
||||
async def remove(self):
|
||||
"""Remove a custom repository."""
|
||||
_LOGGER.info("Remove custom add-on repository %s", self.url)
|
||||
self._remove()
|
||||
await self._remove()
|
||||
|
@ -67,9 +67,9 @@ class Repository(CoreSysAttributes):
|
||||
return await self.git.pull()
|
||||
return True
|
||||
|
||||
def remove(self):
|
||||
async def remove(self):
|
||||
"""Remove add-on repository."""
|
||||
if self.slug in (REPOSITORY_CORE, REPOSITORY_LOCAL):
|
||||
raise APIError("Can't remove built-in repositories!")
|
||||
|
||||
self.git.remove()
|
||||
await self.git.remove()
|
||||
|
@ -141,3 +141,12 @@ async def network_interface(dbus):
|
||||
await interface.connect(dbus, "/org/freedesktop/NetworkManager/ActiveConnection/1")
|
||||
await interface.connection.update_information()
|
||||
yield interface
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def store_manager(coresys: CoreSys):
|
||||
"""Fixture for the store manager."""
|
||||
sm_obj = coresys.store
|
||||
sm_obj.repositories = set(coresys.config.addons_repositories)
|
||||
with patch("supervisor.store.data.StoreData.update", return_value=MagicMock()):
|
||||
yield sm_obj
|
||||
|
29
tests/store/test_custom_repository.py
Normal file
29
tests/store/test_custom_repository.py
Normal file
@ -0,0 +1,29 @@
|
||||
"""Test add custom repository."""
|
||||
import json
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_add_valid_repository(coresys, store_manager):
|
||||
"""Test add custom repository."""
|
||||
current = coresys.config.addons_repositories
|
||||
with patch("supervisor.store.repository.Repository.load", return_value=True), patch(
|
||||
"pathlib.Path.read_text",
|
||||
return_value=json.dumps({"name": "Awesome repository"}),
|
||||
):
|
||||
await store_manager.update_repositories(current + ["http://example.com"])
|
||||
assert "http://example.com" in coresys.config.addons_repositories
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_add_invalid_repository(coresys, store_manager):
|
||||
"""Test add custom repository."""
|
||||
current = coresys.config.addons_repositories
|
||||
with patch("supervisor.store.repository.Repository.load", return_value=True), patch(
|
||||
"pathlib.Path.read_text",
|
||||
return_value="",
|
||||
):
|
||||
await store_manager.update_repositories(current + ["http://example.com"])
|
||||
assert "http://example.com" not in coresys.config.addons_repositories
|
Loading…
x
Reference in New Issue
Block a user