mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-10 02:36:29 +00:00
Refactor addon git repo (#5987)
* Refactor Repository into setup with inheritance * Remove subclasses of GitRepo
This commit is contained in:
parent
3e20a0937d
commit
abc44946bb
@ -42,13 +42,8 @@ class FixupStoreExecuteReset(FixupBase):
|
||||
_LOGGER.warning("Can't find store %s for fixup", reference)
|
||||
return
|
||||
|
||||
# Local add-ons are not a git repo, can't remove and re-pull
|
||||
try:
|
||||
if repository.git:
|
||||
await repository.git.reset()
|
||||
|
||||
# Load data again
|
||||
await repository.load()
|
||||
await repository.reset()
|
||||
except StoreError:
|
||||
raise ResolutionFixupError() from None
|
||||
|
||||
|
@ -135,7 +135,7 @@ class StoreManager(CoreSysAttributes, FileConfiguration):
|
||||
if url == URL_HASSIO_ADDONS:
|
||||
url = StoreType.CORE
|
||||
|
||||
repository = Repository(self.coresys, url)
|
||||
repository = Repository.create(self.coresys, url)
|
||||
|
||||
if repository.slug in self.repositories:
|
||||
raise StoreError(f"Can't add {url}, already in the store", _LOGGER.error)
|
||||
@ -183,7 +183,7 @@ class StoreManager(CoreSysAttributes, FileConfiguration):
|
||||
raise err
|
||||
|
||||
else:
|
||||
if not await self.sys_run_in_executor(repository.validate):
|
||||
if not await repository.validate():
|
||||
if add_with_errors:
|
||||
_LOGGER.error("%s is not a valid add-on repository", url)
|
||||
self.sys_resolution.create_issue(
|
||||
|
@ -1,6 +1,5 @@
|
||||
"""Init file for Supervisor add-on Git."""
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
import asyncio
|
||||
import errno
|
||||
import functools as ft
|
||||
@ -16,17 +15,14 @@ from ..exceptions import StoreGitCloneError, StoreGitError, StoreJobError
|
||||
from ..jobs.decorator import Job, JobCondition
|
||||
from ..resolution.const import ContextType, IssueType, SuggestionType, UnhealthyReason
|
||||
from ..utils import remove_folder
|
||||
from .utils import get_hash_from_repository
|
||||
from .validate import RE_REPOSITORY, BuiltinRepository
|
||||
from .validate import RE_REPOSITORY
|
||||
|
||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class GitRepo(CoreSysAttributes, ABC):
|
||||
class GitRepo(CoreSysAttributes):
|
||||
"""Manage Add-on Git repository."""
|
||||
|
||||
builtin: bool
|
||||
|
||||
def __init__(self, coresys: CoreSys, path: Path, url: str):
|
||||
"""Initialize Git base wrapper."""
|
||||
self.coresys: CoreSys = coresys
|
||||
@ -239,38 +235,8 @@ class GitRepo(CoreSysAttributes, ABC):
|
||||
)
|
||||
raise StoreGitError() from err
|
||||
|
||||
@abstractmethod
|
||||
async def remove(self) -> None:
|
||||
"""Remove a repository."""
|
||||
|
||||
|
||||
class GitRepoBuiltin(GitRepo):
|
||||
"""Built-in add-ons repository."""
|
||||
|
||||
builtin: bool = True
|
||||
|
||||
def __init__(self, coresys: CoreSys, repository: BuiltinRepository):
|
||||
"""Initialize Git Supervisor add-on repository."""
|
||||
super().__init__(coresys, repository.get_path(coresys), repository.url)
|
||||
|
||||
async def remove(self) -> None:
|
||||
"""Raise. Cannot remove built-in repositories."""
|
||||
raise RuntimeError("Cannot remove built-in repositories!")
|
||||
|
||||
|
||||
class GitRepoCustom(GitRepo):
|
||||
"""Custom add-ons repository."""
|
||||
|
||||
builtin: bool = False
|
||||
|
||||
def __init__(self, coresys, url):
|
||||
"""Initialize custom Git Supervisor addo-n repository."""
|
||||
path = Path(coresys.config.path_addons_git, get_hash_from_repository(url))
|
||||
|
||||
super().__init__(coresys, path, url)
|
||||
|
||||
async def remove(self) -> None:
|
||||
"""Remove a custom repository."""
|
||||
if self.lock.locked():
|
||||
_LOGGER.warning(
|
||||
"Cannot remove add-on repository %s, there is already a task in progress",
|
||||
|
@ -1,5 +1,8 @@
|
||||
"""Represent a Supervisor repository."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
@ -12,7 +15,7 @@ from ..coresys import CoreSys, CoreSysAttributes
|
||||
from ..exceptions import ConfigurationFileError, StoreError
|
||||
from ..utils.common import read_json_or_yaml_file
|
||||
from .const import StoreType
|
||||
from .git import GitRepo, GitRepoBuiltin, GitRepoCustom
|
||||
from .git import GitRepo
|
||||
from .utils import get_hash_from_repository
|
||||
from .validate import SCHEMA_REPOSITORY_CONFIG, BuiltinRepository
|
||||
|
||||
@ -20,28 +23,24 @@ _LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||
UNKNOWN = "unknown"
|
||||
|
||||
|
||||
class Repository(CoreSysAttributes):
|
||||
class Repository(CoreSysAttributes, ABC):
|
||||
"""Add-on store repository in Supervisor."""
|
||||
|
||||
def __init__(self, coresys: CoreSys, repository: str):
|
||||
"""Initialize add-on store repository object."""
|
||||
self._slug: str
|
||||
self._type: StoreType
|
||||
self.coresys: CoreSys = coresys
|
||||
self.git: GitRepo | None = None
|
||||
|
||||
self.source: str = repository
|
||||
|
||||
@staticmethod
|
||||
def create(coresys: CoreSys, repository: str) -> Repository:
|
||||
"""Create a repository instance."""
|
||||
if repository == StoreType.LOCAL:
|
||||
self._slug = repository
|
||||
self._type = StoreType.LOCAL
|
||||
self._latest_mtime: float | None = None
|
||||
elif repository in BuiltinRepository:
|
||||
builtin = BuiltinRepository(repository)
|
||||
self.git = GitRepoBuiltin(coresys, builtin)
|
||||
self._slug = builtin.id
|
||||
self._type = builtin.type
|
||||
else:
|
||||
self.git = GitRepoCustom(coresys, repository)
|
||||
self._slug = get_hash_from_repository(repository)
|
||||
self._type = StoreType.GIT
|
||||
return RepositoryLocal(coresys)
|
||||
if repository in BuiltinRepository:
|
||||
return RepositoryGitBuiltin(coresys, BuiltinRepository(repository))
|
||||
return RepositoryCustom(coresys, repository)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""Return internal representation."""
|
||||
@ -77,52 +76,117 @@ class Repository(CoreSysAttributes):
|
||||
"""Return url of repository."""
|
||||
return self.data.get(ATTR_MAINTAINER, UNKNOWN)
|
||||
|
||||
def validate(self) -> bool:
|
||||
"""Check if store is valid.
|
||||
@abstractmethod
|
||||
async def validate(self) -> bool:
|
||||
"""Check if store is valid."""
|
||||
|
||||
Must be run in executor.
|
||||
@abstractmethod
|
||||
async def load(self) -> None:
|
||||
"""Load addon repository."""
|
||||
|
||||
@abstractmethod
|
||||
async def update(self) -> bool:
|
||||
"""Update add-on repository.
|
||||
|
||||
Returns True if the repository was updated.
|
||||
"""
|
||||
if not self.git or self.type == StoreType.CORE:
|
||||
return True
|
||||
|
||||
# If exists?
|
||||
for filetype in FILE_SUFFIX_CONFIGURATION:
|
||||
repository_file = Path(self.git.path / f"repository{filetype}")
|
||||
if repository_file.exists():
|
||||
break
|
||||
@abstractmethod
|
||||
async def remove(self) -> None:
|
||||
"""Remove add-on repository."""
|
||||
|
||||
if not repository_file.exists():
|
||||
return False
|
||||
@abstractmethod
|
||||
async def reset(self) -> None:
|
||||
"""Reset add-on repository to fix corruption issue with files."""
|
||||
|
||||
# If valid?
|
||||
try:
|
||||
SCHEMA_REPOSITORY_CONFIG(read_json_or_yaml_file(repository_file))
|
||||
except (ConfigurationFileError, vol.Invalid) as err:
|
||||
_LOGGER.warning("Could not validate repository configuration %s", err)
|
||||
return False
|
||||
|
||||
class RepositoryBuiltin(Repository, ABC):
|
||||
"""A built-in add-on repository."""
|
||||
|
||||
def __init__(self, coresys: CoreSys, builtin: BuiltinRepository) -> None:
|
||||
"""Initialize object."""
|
||||
super().__init__(coresys, builtin.value)
|
||||
self._builtin = builtin
|
||||
self._slug = builtin.id
|
||||
self._type = builtin.type
|
||||
|
||||
async def validate(self) -> bool:
|
||||
"""Assume built-in repositories are always valid."""
|
||||
return True
|
||||
|
||||
async def remove(self) -> None:
|
||||
"""Raise. Not supported for built-in repositories."""
|
||||
raise StoreError("Can't remove built-in repositories!", _LOGGER.error)
|
||||
|
||||
|
||||
class RepositoryGit(Repository, ABC):
|
||||
"""A git based add-on repository."""
|
||||
|
||||
_git: GitRepo
|
||||
|
||||
async def load(self) -> None:
|
||||
"""Load addon repository."""
|
||||
if not self.git:
|
||||
self._latest_mtime, _ = await self.sys_run_in_executor(
|
||||
get_latest_mtime, self.sys_config.path_addons_local
|
||||
)
|
||||
return
|
||||
await self.git.load()
|
||||
await self._git.load()
|
||||
|
||||
async def update(self) -> bool:
|
||||
"""Update add-on repository.
|
||||
|
||||
Returns True if the repository was updated.
|
||||
"""
|
||||
if not await self.sys_run_in_executor(self.validate):
|
||||
if not await self.validate():
|
||||
return False
|
||||
|
||||
if self.git:
|
||||
return await self.git.pull()
|
||||
return await self._git.pull()
|
||||
|
||||
async def validate(self) -> bool:
|
||||
"""Check if store is valid."""
|
||||
|
||||
def validate_file() -> bool:
|
||||
# If exists?
|
||||
for filetype in FILE_SUFFIX_CONFIGURATION:
|
||||
repository_file = Path(self._git.path / f"repository{filetype}")
|
||||
if repository_file.exists():
|
||||
break
|
||||
|
||||
if not repository_file.exists():
|
||||
return False
|
||||
|
||||
# If valid?
|
||||
try:
|
||||
SCHEMA_REPOSITORY_CONFIG(read_json_or_yaml_file(repository_file))
|
||||
except (ConfigurationFileError, vol.Invalid) as err:
|
||||
_LOGGER.warning("Could not validate repository configuration %s", err)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
return await self.sys_run_in_executor(validate_file)
|
||||
|
||||
async def reset(self) -> None:
|
||||
"""Reset add-on repository to fix corruption issue with files."""
|
||||
await self._git.reset()
|
||||
await self.load()
|
||||
|
||||
|
||||
class RepositoryLocal(RepositoryBuiltin):
|
||||
"""A local add-on repository."""
|
||||
|
||||
def __init__(self, coresys: CoreSys) -> None:
|
||||
"""Initialize object."""
|
||||
super().__init__(coresys, BuiltinRepository.LOCAL)
|
||||
self._latest_mtime: float | None = None
|
||||
|
||||
async def load(self) -> None:
|
||||
"""Load addon repository."""
|
||||
self._latest_mtime, _ = await self.sys_run_in_executor(
|
||||
get_latest_mtime, self.sys_config.path_addons_local
|
||||
)
|
||||
|
||||
async def update(self) -> bool:
|
||||
"""Update add-on repository.
|
||||
|
||||
Returns True if the repository was updated.
|
||||
"""
|
||||
# Check local modifications
|
||||
latest_mtime, modified_path = await self.sys_run_in_executor(
|
||||
get_latest_mtime, self.sys_config.path_addons_local
|
||||
@ -138,9 +202,32 @@ class Repository(CoreSysAttributes):
|
||||
|
||||
return False
|
||||
|
||||
async def reset(self) -> None:
|
||||
"""Raise. Not supported for local repository."""
|
||||
raise StoreError(
|
||||
"Can't reset local repository as it is not git based!", _LOGGER.error
|
||||
)
|
||||
|
||||
|
||||
class RepositoryGitBuiltin(RepositoryBuiltin, RepositoryGit):
|
||||
"""A built-in add-on repository based on git."""
|
||||
|
||||
def __init__(self, coresys: CoreSys, builtin: BuiltinRepository) -> None:
|
||||
"""Initialize object."""
|
||||
super().__init__(coresys, builtin)
|
||||
self._git = GitRepo(coresys, builtin.get_path(coresys), builtin.url)
|
||||
|
||||
|
||||
class RepositoryCustom(RepositoryGit):
|
||||
"""A custom add-on repository."""
|
||||
|
||||
def __init__(self, coresys: CoreSys, url: str) -> None:
|
||||
"""Initialize object."""
|
||||
super().__init__(coresys, url)
|
||||
self._slug = get_hash_from_repository(url)
|
||||
self._type = StoreType.GIT
|
||||
self._git = GitRepo(coresys, coresys.config.path_addons_git / self._slug, url)
|
||||
|
||||
async def remove(self) -> None:
|
||||
"""Remove add-on repository."""
|
||||
if not self.git or self.git.builtin:
|
||||
raise StoreError("Can't remove built-in repositories!", _LOGGER.error)
|
||||
|
||||
await self.git.remove()
|
||||
await self._git.remove()
|
||||
|
@ -820,7 +820,7 @@ async def test_paths_cache(coresys: CoreSys, install_addon_ssh: Addon):
|
||||
|
||||
with (
|
||||
patch("supervisor.addons.addon.Path.exists", return_value=True),
|
||||
patch("supervisor.store.repository.Repository.update", return_value=True),
|
||||
patch("supervisor.store.repository.RepositoryLocal.update", return_value=True),
|
||||
):
|
||||
await coresys.store.reload(coresys.store.get("local"))
|
||||
|
||||
|
@ -29,7 +29,7 @@ from supervisor.plugins.dns import PluginDns
|
||||
from supervisor.resolution.const import ContextType, IssueType, SuggestionType
|
||||
from supervisor.resolution.data import Issue, Suggestion
|
||||
from supervisor.store.addon import AddonStore
|
||||
from supervisor.store.repository import Repository
|
||||
from supervisor.store.repository import RepositoryLocal
|
||||
from supervisor.utils import check_exception_chain
|
||||
from supervisor.utils.common import write_json_file
|
||||
|
||||
@ -442,7 +442,7 @@ async def test_store_data_changes_during_update(
|
||||
update_task = coresys.create_task(simulate_update())
|
||||
await asyncio.sleep(0)
|
||||
|
||||
with patch.object(Repository, "update", return_value=True):
|
||||
with patch.object(RepositoryLocal, "update", return_value=True):
|
||||
await coresys.store.reload()
|
||||
|
||||
assert "image" not in coresys.store.data.addons["local_ssh"]
|
||||
|
@ -97,8 +97,8 @@ async def test_api_store_add_repository(
|
||||
) -> None:
|
||||
"""Test POST /store/repositories REST API."""
|
||||
with (
|
||||
patch("supervisor.store.repository.Repository.load", return_value=None),
|
||||
patch("supervisor.store.repository.Repository.validate", return_value=True),
|
||||
patch("supervisor.store.repository.RepositoryGit.load", return_value=None),
|
||||
patch("supervisor.store.repository.RepositoryGit.validate", return_value=True),
|
||||
):
|
||||
response = await api_client.post(
|
||||
"/store/repositories", json={"repository": REPO_URL}
|
||||
|
@ -42,8 +42,8 @@ async def test_api_supervisor_options_add_repository(
|
||||
coresys.store.get_from_url(REPO_URL)
|
||||
|
||||
with (
|
||||
patch("supervisor.store.repository.Repository.load", return_value=None),
|
||||
patch("supervisor.store.repository.Repository.validate", return_value=True),
|
||||
patch("supervisor.store.repository.RepositoryGit.load", return_value=None),
|
||||
patch("supervisor.store.repository.RepositoryGit.validate", return_value=True),
|
||||
):
|
||||
response = await api_client.post(
|
||||
"/supervisor/options", json={"addons_repositories": [REPO_URL]}
|
||||
@ -76,9 +76,9 @@ async def test_api_supervisor_options_repositories_skipped_on_error(
|
||||
):
|
||||
"""Test repositories skipped on error via POST /supervisor/options REST API."""
|
||||
with (
|
||||
patch("supervisor.store.repository.Repository.load", side_effect=git_error),
|
||||
patch("supervisor.store.repository.Repository.validate", return_value=False),
|
||||
patch("supervisor.store.repository.Repository.remove"),
|
||||
patch("supervisor.store.repository.RepositoryGit.load", side_effect=git_error),
|
||||
patch("supervisor.store.repository.RepositoryGit.validate", return_value=False),
|
||||
patch("supervisor.store.repository.RepositoryCustom.remove"),
|
||||
):
|
||||
response = await api_client.post(
|
||||
"/supervisor/options", json={"addons_repositories": [REPO_URL]}
|
||||
@ -98,7 +98,7 @@ async def test_api_supervisor_options_repo_error_with_config_change(
|
||||
assert not coresys.config.debug
|
||||
|
||||
with patch(
|
||||
"supervisor.store.repository.Repository.load", side_effect=StoreGitError()
|
||||
"supervisor.store.repository.RepositoryGit.load", side_effect=StoreGitError()
|
||||
):
|
||||
response = await api_client.post(
|
||||
"/supervisor/options",
|
||||
|
@ -409,7 +409,7 @@ async def coresys(
|
||||
coresys_obj.init_websession = AsyncMock()
|
||||
|
||||
# Don't remove files/folders related to addons and stores
|
||||
with patch("supervisor.store.git.GitRepoCustom.remove"):
|
||||
with patch("supervisor.store.git.GitRepo.remove"):
|
||||
yield coresys_obj
|
||||
|
||||
await coresys_obj.dbus.unload()
|
||||
@ -611,7 +611,7 @@ async def repository(coresys: CoreSys):
|
||||
):
|
||||
await coresys.store.load()
|
||||
|
||||
repository_obj = Repository(
|
||||
repository_obj = Repository.create(
|
||||
coresys, "https://github.com/awesome-developer/awesome-repo"
|
||||
)
|
||||
|
||||
|
@ -67,7 +67,7 @@ async def test_fixup(coresys: CoreSys):
|
||||
path = path or obj.path
|
||||
await coresys.run_in_executor((path / ".git").mkdir)
|
||||
|
||||
coresys.store.repositories["94cfad5a"] = Repository(
|
||||
coresys.store.repositories["94cfad5a"] = Repository.create(
|
||||
coresys, "https://github.com/home-assistant/addons-example"
|
||||
)
|
||||
with (
|
||||
@ -97,7 +97,7 @@ async def test_fixup_clone_fail(coresys: CoreSys):
|
||||
assert test_repo.exists()
|
||||
assert corrupt_marker.exists()
|
||||
|
||||
coresys.store.repositories["94cfad5a"] = Repository(
|
||||
coresys.store.repositories["94cfad5a"] = Repository.create(
|
||||
coresys, "https://github.com/home-assistant/addons-example"
|
||||
)
|
||||
with (
|
||||
@ -129,7 +129,7 @@ async def test_fixup_move_fail(coresys: CoreSys, error_num: int, unhealthy: bool
|
||||
|
||||
add_store_reset_suggestion(coresys)
|
||||
test_repo.mkdir(parents=True)
|
||||
coresys.store.repositories["94cfad5a"] = Repository(
|
||||
coresys.store.repositories["94cfad5a"] = Repository.create(
|
||||
coresys, "https://github.com/home-assistant/addons-example"
|
||||
)
|
||||
with (
|
||||
|
@ -33,7 +33,7 @@ async def test_add_valid_repository(
|
||||
"""Test add custom repository."""
|
||||
current = coresys.store.repository_urls
|
||||
with (
|
||||
patch("supervisor.store.repository.Repository.load", return_value=None),
|
||||
patch("supervisor.store.repository.RepositoryGit.load", return_value=None),
|
||||
patch(
|
||||
"supervisor.utils.common.read_yaml_file",
|
||||
return_value={"name": "Awesome repository"},
|
||||
@ -54,7 +54,7 @@ async def test_add_invalid_repository(coresys: CoreSys, store_manager: StoreMana
|
||||
"""Test add invalid custom repository."""
|
||||
current = coresys.store.repository_urls
|
||||
with (
|
||||
patch("supervisor.store.repository.Repository.load", return_value=None),
|
||||
patch("supervisor.store.repository.RepositoryGit.load", return_value=None),
|
||||
patch(
|
||||
"pathlib.Path.read_text",
|
||||
return_value="",
|
||||
@ -64,9 +64,7 @@ async def test_add_invalid_repository(coresys: CoreSys, store_manager: StoreMana
|
||||
current + ["http://example.com"], add_with_errors=True
|
||||
)
|
||||
|
||||
assert not await coresys.run_in_executor(
|
||||
store_manager.get_from_url("http://example.com").validate
|
||||
)
|
||||
assert not await store_manager.get_from_url("http://example.com").validate()
|
||||
|
||||
assert "http://example.com" in coresys.store.repository_urls
|
||||
assert coresys.resolution.suggestions[-1].type == SuggestionType.EXECUTE_REMOVE
|
||||
@ -79,7 +77,7 @@ async def test_error_on_invalid_repository(
|
||||
"""Test invalid repository not added."""
|
||||
current = coresys.store.repository_urls
|
||||
with (
|
||||
patch("supervisor.store.repository.Repository.load", return_value=None),
|
||||
patch("supervisor.store.repository.RepositoryGit.load", return_value=None),
|
||||
patch(
|
||||
"pathlib.Path.read_text",
|
||||
return_value="",
|
||||
@ -103,7 +101,7 @@ async def test_add_invalid_repository_file(
|
||||
"""Test add invalid custom repository file."""
|
||||
current = coresys.store.repository_urls
|
||||
with (
|
||||
patch("supervisor.store.repository.Repository.load", return_value=None),
|
||||
patch("supervisor.store.repository.RepositoryGit.load", return_value=None),
|
||||
patch(
|
||||
"pathlib.Path.read_text",
|
||||
return_value=json.dumps({"name": "Awesome repository"}),
|
||||
@ -114,7 +112,7 @@ async def test_add_invalid_repository_file(
|
||||
current + ["http://example.com"], add_with_errors=True
|
||||
)
|
||||
|
||||
assert not store_manager.get_from_url("http://example.com").validate()
|
||||
assert not await store_manager.get_from_url("http://example.com").validate()
|
||||
|
||||
assert "http://example.com" in coresys.store.repository_urls
|
||||
assert coresys.resolution.suggestions[-1].type == SuggestionType.EXECUTE_REMOVE
|
||||
@ -135,7 +133,7 @@ async def test_add_repository_with_git_error(
|
||||
):
|
||||
"""Test repo added with issue on git error."""
|
||||
current = coresys.store.repository_urls
|
||||
with patch("supervisor.store.repository.Repository.load", side_effect=git_error):
|
||||
with patch("supervisor.store.repository.RepositoryGit.load", side_effect=git_error):
|
||||
await store_manager.update_repositories(
|
||||
current + ["http://example.com"], add_with_errors=True
|
||||
)
|
||||
@ -163,7 +161,7 @@ async def test_error_on_repository_with_git_error(
|
||||
"""Test repo not added on git error."""
|
||||
current = coresys.store.repository_urls
|
||||
with (
|
||||
patch("supervisor.store.repository.Repository.load", side_effect=git_error),
|
||||
patch("supervisor.store.repository.RepositoryGit.load", side_effect=git_error),
|
||||
pytest.raises(StoreError),
|
||||
):
|
||||
if use_update:
|
||||
@ -182,7 +180,7 @@ async def test_preinstall_valid_repository(
|
||||
coresys: CoreSys, store_manager: StoreManager
|
||||
):
|
||||
"""Test add core repository valid."""
|
||||
with patch("supervisor.store.repository.Repository.load", return_value=None):
|
||||
with patch("supervisor.store.repository.RepositoryGit.load", return_value=None):
|
||||
await store_manager.update_repositories(BUILTIN_REPOSITORIES)
|
||||
|
||||
def validate():
|
||||
@ -244,8 +242,8 @@ async def test_remove_used_repository(
|
||||
|
||||
async def test_update_partial_error(coresys: CoreSys, store_manager: StoreManager):
|
||||
"""Test partial error on update does partial save and errors."""
|
||||
with patch("supervisor.store.repository.Repository.validate", return_value=True):
|
||||
with patch("supervisor.store.repository.Repository.load", return_value=None):
|
||||
with patch("supervisor.store.repository.RepositoryGit.validate", return_value=True):
|
||||
with patch("supervisor.store.repository.RepositoryGit.load", return_value=None):
|
||||
await store_manager.update_repositories([])
|
||||
|
||||
store_manager.data.update.assert_called_once()
|
||||
@ -256,7 +254,7 @@ async def test_update_partial_error(coresys: CoreSys, store_manager: StoreManage
|
||||
|
||||
with (
|
||||
patch(
|
||||
"supervisor.store.repository.Repository.load",
|
||||
"supervisor.store.repository.RepositoryGit.load",
|
||||
side_effect=[None, StoreGitError()],
|
||||
),
|
||||
pytest.raises(StoreError),
|
||||
@ -275,8 +273,8 @@ async def test_error_adding_duplicate(
|
||||
"""Test adding a duplicate repository causes an error."""
|
||||
assert repository.source in coresys.store.repository_urls
|
||||
with (
|
||||
patch("supervisor.store.repository.Repository.validate", return_value=True),
|
||||
patch("supervisor.store.repository.Repository.load", return_value=None),
|
||||
patch("supervisor.store.repository.RepositoryGit.validate", return_value=True),
|
||||
patch("supervisor.store.repository.RepositoryGit.load", return_value=None),
|
||||
pytest.raises(StoreError),
|
||||
):
|
||||
await store_manager.add_repository(repository.source)
|
||||
@ -290,7 +288,7 @@ async def test_add_with_update_repositories(
|
||||
assert "http://example.com" not in coresys.store.repository_urls
|
||||
|
||||
with (
|
||||
patch("supervisor.store.repository.Repository.load", return_value=None),
|
||||
patch("supervisor.store.repository.RepositoryGit.load", return_value=None),
|
||||
patch(
|
||||
"supervisor.utils.common.read_yaml_file",
|
||||
return_value={"name": "Awesome repository"},
|
||||
@ -328,7 +326,7 @@ async def test_repositories_loaded_ignore_updates(
|
||||
):
|
||||
"""Test repositories loaded whether or not supervisor needs an update."""
|
||||
with (
|
||||
patch("supervisor.store.repository.Repository.load", return_value=None),
|
||||
patch("supervisor.store.repository.RepositoryGit.load", return_value=None),
|
||||
patch.object(
|
||||
type(coresys.supervisor),
|
||||
"need_update",
|
||||
|
@ -15,13 +15,6 @@ from supervisor.store.git import GitRepo
|
||||
REPO_URL = "https://github.com/awesome-developer/awesome-repo"
|
||||
|
||||
|
||||
class GitRepoTest(GitRepo):
|
||||
"""Implementation of GitRepo for tests that allows direct setting of path."""
|
||||
|
||||
async def remove(self) -> None:
|
||||
"""Not implemented."""
|
||||
|
||||
|
||||
@pytest.fixture(name="clone_from")
|
||||
async def fixture_clone_from():
|
||||
"""Mock git clone_from."""
|
||||
@ -35,7 +28,7 @@ async def test_git_clone(
|
||||
):
|
||||
"""Test git clone."""
|
||||
fragment = f"#{branch}" if branch else ""
|
||||
repo = GitRepoTest(coresys, tmp_path, f"{REPO_URL}{fragment}")
|
||||
repo = GitRepo(coresys, tmp_path, f"{REPO_URL}{fragment}")
|
||||
|
||||
await repo.clone.__wrapped__(repo)
|
||||
|
||||
@ -63,7 +56,7 @@ async def test_git_clone_error(
|
||||
coresys: CoreSys, tmp_path: Path, clone_from: AsyncMock, git_error: Exception
|
||||
):
|
||||
"""Test git clone error."""
|
||||
repo = GitRepoTest(coresys, tmp_path, REPO_URL)
|
||||
repo = GitRepo(coresys, tmp_path, REPO_URL)
|
||||
|
||||
clone_from.side_effect = git_error
|
||||
with pytest.raises(StoreGitCloneError):
|
||||
@ -75,7 +68,7 @@ async def test_git_clone_error(
|
||||
async def test_git_load(coresys: CoreSys, tmp_path: Path):
|
||||
"""Test git load."""
|
||||
repo_dir = tmp_path / "repo"
|
||||
repo = GitRepoTest(coresys, repo_dir, REPO_URL)
|
||||
repo = GitRepo(coresys, repo_dir, REPO_URL)
|
||||
repo.clone = AsyncMock()
|
||||
|
||||
# Test with non-existing git repo root directory
|
||||
@ -113,7 +106,7 @@ async def test_git_load(coresys: CoreSys, tmp_path: Path):
|
||||
async def test_git_load_error(coresys: CoreSys, tmp_path: Path, git_errors: Exception):
|
||||
"""Test git load error."""
|
||||
coresys.hardware.disk.get_disk_free_space = lambda x: 5000
|
||||
repo = GitRepoTest(coresys, tmp_path, REPO_URL)
|
||||
repo = GitRepo(coresys, tmp_path, REPO_URL)
|
||||
|
||||
# Pretend we have a repo
|
||||
(tmp_path / ".git").mkdir()
|
||||
|
@ -32,7 +32,8 @@ async def test_default_load(coresys: CoreSys):
|
||||
refresh_cache_calls.add(obj.slug)
|
||||
|
||||
with (
|
||||
patch("supervisor.store.repository.Repository.load", return_value=None),
|
||||
patch("supervisor.store.repository.RepositoryGit.load", return_value=None),
|
||||
patch("supervisor.store.repository.RepositoryLocal.load", return_value=None),
|
||||
patch.object(type(coresys.config), "addons_repositories", return_value=[]),
|
||||
patch("pathlib.Path.exists", return_value=True),
|
||||
patch.object(AddonStore, "refresh_path_cache", new=mock_refresh_cache),
|
||||
@ -80,9 +81,13 @@ async def test_load_with_custom_repository(coresys: CoreSys):
|
||||
store_manager = await StoreManager(coresys).load_config()
|
||||
|
||||
with (
|
||||
patch("supervisor.store.repository.Repository.load", return_value=None),
|
||||
patch("supervisor.store.repository.RepositoryGit.load", return_value=None),
|
||||
patch("supervisor.store.repository.RepositoryLocal.load", return_value=None),
|
||||
patch.object(type(coresys.config), "addons_repositories", return_value=[]),
|
||||
patch("supervisor.store.repository.Repository.validate", return_value=True),
|
||||
patch("supervisor.store.repository.RepositoryGit.validate", return_value=True),
|
||||
patch(
|
||||
"supervisor.store.repository.RepositoryLocal.validate", return_value=True
|
||||
),
|
||||
patch("pathlib.Path.exists", return_value=True),
|
||||
patch.object(AddonStore, "refresh_path_cache", new=mock_refresh_cache),
|
||||
):
|
||||
|
Loading…
x
Reference in New Issue
Block a user