mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-07-27 19:16:29 +00:00
Fix issue on store git clone (#2331)
This commit is contained in:
parent
f8fd7b5933
commit
0c55bf20fc
@ -44,7 +44,7 @@ from .misc.hwmon import HwMonitor
|
|||||||
from .misc.scheduler import Scheduler
|
from .misc.scheduler import Scheduler
|
||||||
from .misc.tasks import Tasks
|
from .misc.tasks import Tasks
|
||||||
from .plugins import PluginManager
|
from .plugins import PluginManager
|
||||||
from .resolution import ResolutionManager
|
from .resolution.module import ResolutionManager
|
||||||
from .services import ServiceManager
|
from .services import ServiceManager
|
||||||
from .snapshots import SnapshotManager
|
from .snapshots import SnapshotManager
|
||||||
from .store import StoreManager
|
from .store import StoreManager
|
||||||
|
@ -83,6 +83,7 @@ class Core(CoreSysAttributes):
|
|||||||
"""Start setting up supervisor orchestration."""
|
"""Start setting up supervisor orchestration."""
|
||||||
self.state = CoreState.SETUP
|
self.state = CoreState.SETUP
|
||||||
|
|
||||||
|
# Order can be important!
|
||||||
setup_loads: List[Awaitable[None]] = [
|
setup_loads: List[Awaitable[None]] = [
|
||||||
# rest api views
|
# rest api views
|
||||||
self.sys_api.load(),
|
self.sys_api.load(),
|
||||||
|
@ -30,7 +30,7 @@ if TYPE_CHECKING:
|
|||||||
from .misc.scheduler import Scheduler
|
from .misc.scheduler import Scheduler
|
||||||
from .misc.tasks import Tasks
|
from .misc.tasks import Tasks
|
||||||
from .plugins import PluginManager
|
from .plugins import PluginManager
|
||||||
from .resolution import ResolutionManager
|
from .resolution.module import ResolutionManager
|
||||||
from .services import ServiceManager
|
from .services import ServiceManager
|
||||||
from .snapshots import SnapshotManager
|
from .snapshots import SnapshotManager
|
||||||
from .store import StoreManager
|
from .store import StoreManager
|
||||||
|
@ -322,6 +322,10 @@ class ResolutionFixupError(HassioError):
|
|||||||
"""Rasie if a fixup fails."""
|
"""Rasie if a fixup fails."""
|
||||||
|
|
||||||
|
|
||||||
|
class ResolutionFixupJobError(ResolutionFixupError, JobException):
|
||||||
|
"""Raise on job error."""
|
||||||
|
|
||||||
|
|
||||||
# Store
|
# Store
|
||||||
|
|
||||||
|
|
||||||
@ -335,3 +339,7 @@ class StoreGitError(StoreError):
|
|||||||
|
|
||||||
class StoreNotFound(StoreError):
|
class StoreNotFound(StoreError):
|
||||||
"""Raise if slug is not known."""
|
"""Raise if slug is not known."""
|
||||||
|
|
||||||
|
|
||||||
|
class StoreJobError(StoreError, JobException):
|
||||||
|
"""Raise on job error with git."""
|
||||||
|
@ -1,181 +1 @@
|
|||||||
"""Supervisor resolution center."""
|
"""Resolution Supervisor module."""
|
||||||
from datetime import time
|
|
||||||
import logging
|
|
||||||
from typing import List, Optional
|
|
||||||
|
|
||||||
from ..coresys import CoreSys, CoreSysAttributes
|
|
||||||
from ..exceptions import ResolutionError, ResolutionNotFound
|
|
||||||
from .check import ResolutionCheck
|
|
||||||
from .const import (
|
|
||||||
SCHEDULED_HEALTHCHECK,
|
|
||||||
ContextType,
|
|
||||||
IssueType,
|
|
||||||
SuggestionType,
|
|
||||||
UnhealthyReason,
|
|
||||||
UnsupportedReason,
|
|
||||||
)
|
|
||||||
from .data import Issue, Suggestion
|
|
||||||
from .evaluate import ResolutionEvaluation
|
|
||||||
from .fixup import ResolutionFixup
|
|
||||||
from .notify import ResolutionNotify
|
|
||||||
|
|
||||||
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class ResolutionManager(CoreSysAttributes):
|
|
||||||
"""Resolution manager for supervisor."""
|
|
||||||
|
|
||||||
def __init__(self, coresys: CoreSys):
|
|
||||||
"""Initialize Resolution manager."""
|
|
||||||
self.coresys: CoreSys = coresys
|
|
||||||
self._evaluate = ResolutionEvaluation(coresys)
|
|
||||||
self._check = ResolutionCheck(coresys)
|
|
||||||
self._fixup = ResolutionFixup(coresys)
|
|
||||||
self._notify = ResolutionNotify(coresys)
|
|
||||||
|
|
||||||
self._suggestions: List[Suggestion] = []
|
|
||||||
self._issues: List[Issue] = []
|
|
||||||
self._unsupported: List[UnsupportedReason] = []
|
|
||||||
self._unhealthy: List[UnhealthyReason] = []
|
|
||||||
|
|
||||||
@property
|
|
||||||
def evaluate(self) -> ResolutionEvaluation:
|
|
||||||
"""Return the ResolutionEvaluation class."""
|
|
||||||
return self._evaluate
|
|
||||||
|
|
||||||
@property
|
|
||||||
def check(self) -> ResolutionCheck:
|
|
||||||
"""Return the ResolutionCheck class."""
|
|
||||||
return self._check
|
|
||||||
|
|
||||||
@property
|
|
||||||
def fixup(self) -> ResolutionFixup:
|
|
||||||
"""Return the ResolutionFixup class."""
|
|
||||||
return self._fixup
|
|
||||||
|
|
||||||
@property
|
|
||||||
def notify(self) -> ResolutionNotify:
|
|
||||||
"""Return the ResolutionNotify class."""
|
|
||||||
return self._notify
|
|
||||||
|
|
||||||
@property
|
|
||||||
def issues(self) -> List[Issue]:
|
|
||||||
"""Return a list of issues."""
|
|
||||||
return self._issues
|
|
||||||
|
|
||||||
@issues.setter
|
|
||||||
def issues(self, issue: Issue) -> None:
|
|
||||||
"""Add issues."""
|
|
||||||
if issue not in self._issues:
|
|
||||||
self._issues.append(issue)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def suggestions(self) -> List[Suggestion]:
|
|
||||||
"""Return a list of suggestions that can handled."""
|
|
||||||
return self._suggestions
|
|
||||||
|
|
||||||
@suggestions.setter
|
|
||||||
def suggestions(self, suggestion: Suggestion) -> None:
|
|
||||||
"""Add suggestion."""
|
|
||||||
if suggestion not in self._suggestions:
|
|
||||||
self._suggestions.append(suggestion)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def unsupported(self) -> List[UnsupportedReason]:
|
|
||||||
"""Return a list of unsupported reasons."""
|
|
||||||
return self._unsupported
|
|
||||||
|
|
||||||
@unsupported.setter
|
|
||||||
def unsupported(self, reason: UnsupportedReason) -> None:
|
|
||||||
"""Add a reason for unsupported."""
|
|
||||||
if reason not in self._unsupported:
|
|
||||||
self._unsupported.append(reason)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def unhealthy(self) -> List[UnhealthyReason]:
|
|
||||||
"""Return a list of unsupported reasons."""
|
|
||||||
return self._unhealthy
|
|
||||||
|
|
||||||
@unhealthy.setter
|
|
||||||
def unhealthy(self, reason: UnhealthyReason) -> None:
|
|
||||||
"""Add a reason for unsupported."""
|
|
||||||
if reason not in self._unhealthy:
|
|
||||||
self._unhealthy.append(reason)
|
|
||||||
|
|
||||||
def get_suggestion(self, uuid: str) -> Suggestion:
|
|
||||||
"""Return suggestion with uuid."""
|
|
||||||
for suggestion in self._suggestions:
|
|
||||||
if suggestion.uuid != uuid:
|
|
||||||
continue
|
|
||||||
return suggestion
|
|
||||||
raise ResolutionNotFound()
|
|
||||||
|
|
||||||
def get_issue(self, uuid: str) -> Issue:
|
|
||||||
"""Return issue with uuid."""
|
|
||||||
for issue in self._issues:
|
|
||||||
if issue.uuid != uuid:
|
|
||||||
continue
|
|
||||||
return issue
|
|
||||||
raise ResolutionNotFound()
|
|
||||||
|
|
||||||
def create_issue(
|
|
||||||
self,
|
|
||||||
issue: IssueType,
|
|
||||||
context: ContextType,
|
|
||||||
reference: Optional[str] = None,
|
|
||||||
suggestions: Optional[List[SuggestionType]] = None,
|
|
||||||
) -> None:
|
|
||||||
"""Create issues and suggestion."""
|
|
||||||
self.issues = Issue(issue, context, reference)
|
|
||||||
if not suggestions:
|
|
||||||
return
|
|
||||||
|
|
||||||
# Add suggestions
|
|
||||||
for suggestion in suggestions:
|
|
||||||
self.suggestions = Suggestion(suggestion, context, reference)
|
|
||||||
|
|
||||||
async def load(self):
|
|
||||||
"""Load the resoulution manager."""
|
|
||||||
# Initial healthcheck when the manager is loaded
|
|
||||||
await self.healthcheck()
|
|
||||||
|
|
||||||
# Schedule the healthcheck
|
|
||||||
self.sys_scheduler.register_task(self.healthcheck, SCHEDULED_HEALTHCHECK)
|
|
||||||
self.sys_scheduler.register_task(self.fixup.run_autofix, time(hour=2))
|
|
||||||
|
|
||||||
async def healthcheck(self):
|
|
||||||
"""Scheduled task to check for known issues."""
|
|
||||||
await self.check.check_system()
|
|
||||||
|
|
||||||
# Create notification for any known issues
|
|
||||||
await self.notify.issue_notifications()
|
|
||||||
|
|
||||||
async def apply_suggestion(self, suggestion: Suggestion) -> None:
|
|
||||||
"""Apply suggested action."""
|
|
||||||
if suggestion not in self._suggestions:
|
|
||||||
_LOGGER.warning("Suggestion %s is not valid", suggestion.uuid)
|
|
||||||
raise ResolutionError()
|
|
||||||
|
|
||||||
await self.fixup.apply_fixup(suggestion)
|
|
||||||
await self.healthcheck()
|
|
||||||
|
|
||||||
def dismiss_suggestion(self, suggestion: Suggestion) -> None:
|
|
||||||
"""Dismiss suggested action."""
|
|
||||||
if suggestion not in self._suggestions:
|
|
||||||
_LOGGER.warning("The UUID %s is not valid suggestion", suggestion.uuid)
|
|
||||||
raise ResolutionError()
|
|
||||||
self._suggestions.remove(suggestion)
|
|
||||||
|
|
||||||
def dismiss_issue(self, issue: Issue) -> None:
|
|
||||||
"""Dismiss suggested action."""
|
|
||||||
if issue not in self._issues:
|
|
||||||
_LOGGER.warning("The UUID %s is not a valid issue", issue.uuid)
|
|
||||||
raise ResolutionError()
|
|
||||||
self._issues.remove(issue)
|
|
||||||
|
|
||||||
def dismiss_unsupported(self, reason: Issue) -> None:
|
|
||||||
"""Dismiss a reason for unsupported."""
|
|
||||||
if reason not in self._unsupported:
|
|
||||||
_LOGGER.warning("The reason %s is not active", reason)
|
|
||||||
raise ResolutionError()
|
|
||||||
self._unsupported.remove(reason)
|
|
||||||
|
@ -29,7 +29,10 @@ class ResolutionFixup(CoreSysAttributes):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def all_fixes(self) -> List[FixupBase]:
|
def all_fixes(self) -> List[FixupBase]:
|
||||||
"""Return a list of all fixups."""
|
"""Return a list of all fixups.
|
||||||
|
|
||||||
|
Order can be important!
|
||||||
|
"""
|
||||||
return [
|
return [
|
||||||
self._create_full_snapshot,
|
self._create_full_snapshot,
|
||||||
self._clear_full_snapshot,
|
self._clear_full_snapshot,
|
||||||
|
@ -2,8 +2,14 @@
|
|||||||
import logging
|
import logging
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
from supervisor.exceptions import ResolutionFixupError, StoreError, StoreNotFound
|
from ...exceptions import (
|
||||||
|
ResolutionFixupError,
|
||||||
|
ResolutionFixupJobError,
|
||||||
|
StoreError,
|
||||||
|
StoreNotFound,
|
||||||
|
)
|
||||||
|
from ...jobs.const import JobCondition
|
||||||
|
from ...jobs.decorator import Job
|
||||||
from ...utils import remove_folder
|
from ...utils import remove_folder
|
||||||
from ..const import ContextType, IssueType, SuggestionType
|
from ..const import ContextType, IssueType, SuggestionType
|
||||||
from .base import FixupBase
|
from .base import FixupBase
|
||||||
@ -14,6 +20,9 @@ _LOGGER: logging.Logger = logging.getLogger(__name__)
|
|||||||
class FixupStoreExecuteReset(FixupBase):
|
class FixupStoreExecuteReset(FixupBase):
|
||||||
"""Storage class for fixup."""
|
"""Storage class for fixup."""
|
||||||
|
|
||||||
|
@Job(
|
||||||
|
conditions=[JobCondition.INTERNET_SYSTEM], on_condition=ResolutionFixupJobError
|
||||||
|
)
|
||||||
async def process_fixup(self, reference: Optional[str] = None) -> None:
|
async def process_fixup(self, reference: Optional[str] = None) -> None:
|
||||||
"""Initialize the fixup class."""
|
"""Initialize the fixup class."""
|
||||||
_LOGGER.info("Reset corrupt Store: %s", reference)
|
_LOGGER.info("Reset corrupt Store: %s", reference)
|
||||||
|
181
supervisor/resolution/module.py
Normal file
181
supervisor/resolution/module.py
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
"""Supervisor resolution center."""
|
||||||
|
from datetime import time
|
||||||
|
import logging
|
||||||
|
from typing import List, Optional
|
||||||
|
|
||||||
|
from ..coresys import CoreSys, CoreSysAttributes
|
||||||
|
from ..exceptions import ResolutionError, ResolutionNotFound
|
||||||
|
from .check import ResolutionCheck
|
||||||
|
from .const import (
|
||||||
|
SCHEDULED_HEALTHCHECK,
|
||||||
|
ContextType,
|
||||||
|
IssueType,
|
||||||
|
SuggestionType,
|
||||||
|
UnhealthyReason,
|
||||||
|
UnsupportedReason,
|
||||||
|
)
|
||||||
|
from .data import Issue, Suggestion
|
||||||
|
from .evaluate import ResolutionEvaluation
|
||||||
|
from .fixup import ResolutionFixup
|
||||||
|
from .notify import ResolutionNotify
|
||||||
|
|
||||||
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class ResolutionManager(CoreSysAttributes):
|
||||||
|
"""Resolution manager for supervisor."""
|
||||||
|
|
||||||
|
def __init__(self, coresys: CoreSys):
|
||||||
|
"""Initialize Resolution manager."""
|
||||||
|
self.coresys: CoreSys = coresys
|
||||||
|
self._evaluate = ResolutionEvaluation(coresys)
|
||||||
|
self._check = ResolutionCheck(coresys)
|
||||||
|
self._fixup = ResolutionFixup(coresys)
|
||||||
|
self._notify = ResolutionNotify(coresys)
|
||||||
|
|
||||||
|
self._suggestions: List[Suggestion] = []
|
||||||
|
self._issues: List[Issue] = []
|
||||||
|
self._unsupported: List[UnsupportedReason] = []
|
||||||
|
self._unhealthy: List[UnhealthyReason] = []
|
||||||
|
|
||||||
|
@property
|
||||||
|
def evaluate(self) -> ResolutionEvaluation:
|
||||||
|
"""Return the ResolutionEvaluation class."""
|
||||||
|
return self._evaluate
|
||||||
|
|
||||||
|
@property
|
||||||
|
def check(self) -> ResolutionCheck:
|
||||||
|
"""Return the ResolutionCheck class."""
|
||||||
|
return self._check
|
||||||
|
|
||||||
|
@property
|
||||||
|
def fixup(self) -> ResolutionFixup:
|
||||||
|
"""Return the ResolutionFixup class."""
|
||||||
|
return self._fixup
|
||||||
|
|
||||||
|
@property
|
||||||
|
def notify(self) -> ResolutionNotify:
|
||||||
|
"""Return the ResolutionNotify class."""
|
||||||
|
return self._notify
|
||||||
|
|
||||||
|
@property
|
||||||
|
def issues(self) -> List[Issue]:
|
||||||
|
"""Return a list of issues."""
|
||||||
|
return self._issues
|
||||||
|
|
||||||
|
@issues.setter
|
||||||
|
def issues(self, issue: Issue) -> None:
|
||||||
|
"""Add issues."""
|
||||||
|
if issue not in self._issues:
|
||||||
|
self._issues.append(issue)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def suggestions(self) -> List[Suggestion]:
|
||||||
|
"""Return a list of suggestions that can handled."""
|
||||||
|
return self._suggestions
|
||||||
|
|
||||||
|
@suggestions.setter
|
||||||
|
def suggestions(self, suggestion: Suggestion) -> None:
|
||||||
|
"""Add suggestion."""
|
||||||
|
if suggestion not in self._suggestions:
|
||||||
|
self._suggestions.append(suggestion)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def unsupported(self) -> List[UnsupportedReason]:
|
||||||
|
"""Return a list of unsupported reasons."""
|
||||||
|
return self._unsupported
|
||||||
|
|
||||||
|
@unsupported.setter
|
||||||
|
def unsupported(self, reason: UnsupportedReason) -> None:
|
||||||
|
"""Add a reason for unsupported."""
|
||||||
|
if reason not in self._unsupported:
|
||||||
|
self._unsupported.append(reason)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def unhealthy(self) -> List[UnhealthyReason]:
|
||||||
|
"""Return a list of unsupported reasons."""
|
||||||
|
return self._unhealthy
|
||||||
|
|
||||||
|
@unhealthy.setter
|
||||||
|
def unhealthy(self, reason: UnhealthyReason) -> None:
|
||||||
|
"""Add a reason for unsupported."""
|
||||||
|
if reason not in self._unhealthy:
|
||||||
|
self._unhealthy.append(reason)
|
||||||
|
|
||||||
|
def get_suggestion(self, uuid: str) -> Suggestion:
|
||||||
|
"""Return suggestion with uuid."""
|
||||||
|
for suggestion in self._suggestions:
|
||||||
|
if suggestion.uuid != uuid:
|
||||||
|
continue
|
||||||
|
return suggestion
|
||||||
|
raise ResolutionNotFound()
|
||||||
|
|
||||||
|
def get_issue(self, uuid: str) -> Issue:
|
||||||
|
"""Return issue with uuid."""
|
||||||
|
for issue in self._issues:
|
||||||
|
if issue.uuid != uuid:
|
||||||
|
continue
|
||||||
|
return issue
|
||||||
|
raise ResolutionNotFound()
|
||||||
|
|
||||||
|
def create_issue(
|
||||||
|
self,
|
||||||
|
issue: IssueType,
|
||||||
|
context: ContextType,
|
||||||
|
reference: Optional[str] = None,
|
||||||
|
suggestions: Optional[List[SuggestionType]] = None,
|
||||||
|
) -> None:
|
||||||
|
"""Create issues and suggestion."""
|
||||||
|
self.issues = Issue(issue, context, reference)
|
||||||
|
if not suggestions:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Add suggestions
|
||||||
|
for suggestion in suggestions:
|
||||||
|
self.suggestions = Suggestion(suggestion, context, reference)
|
||||||
|
|
||||||
|
async def load(self):
|
||||||
|
"""Load the resoulution manager."""
|
||||||
|
# Initial healthcheck when the manager is loaded
|
||||||
|
await self.healthcheck()
|
||||||
|
|
||||||
|
# Schedule the healthcheck
|
||||||
|
self.sys_scheduler.register_task(self.healthcheck, SCHEDULED_HEALTHCHECK)
|
||||||
|
self.sys_scheduler.register_task(self.fixup.run_autofix, time(hour=2))
|
||||||
|
|
||||||
|
async def healthcheck(self):
|
||||||
|
"""Scheduled task to check for known issues."""
|
||||||
|
await self.check.check_system()
|
||||||
|
|
||||||
|
# Create notification for any known issues
|
||||||
|
await self.notify.issue_notifications()
|
||||||
|
|
||||||
|
async def apply_suggestion(self, suggestion: Suggestion) -> None:
|
||||||
|
"""Apply suggested action."""
|
||||||
|
if suggestion not in self._suggestions:
|
||||||
|
_LOGGER.warning("Suggestion %s is not valid", suggestion.uuid)
|
||||||
|
raise ResolutionError()
|
||||||
|
|
||||||
|
await self.fixup.apply_fixup(suggestion)
|
||||||
|
await self.healthcheck()
|
||||||
|
|
||||||
|
def dismiss_suggestion(self, suggestion: Suggestion) -> None:
|
||||||
|
"""Dismiss suggested action."""
|
||||||
|
if suggestion not in self._suggestions:
|
||||||
|
_LOGGER.warning("The UUID %s is not valid suggestion", suggestion.uuid)
|
||||||
|
raise ResolutionError()
|
||||||
|
self._suggestions.remove(suggestion)
|
||||||
|
|
||||||
|
def dismiss_issue(self, issue: Issue) -> None:
|
||||||
|
"""Dismiss suggested action."""
|
||||||
|
if issue not in self._issues:
|
||||||
|
_LOGGER.warning("The UUID %s is not a valid issue", issue.uuid)
|
||||||
|
raise ResolutionError()
|
||||||
|
self._issues.remove(issue)
|
||||||
|
|
||||||
|
def dismiss_unsupported(self, reason: Issue) -> None:
|
||||||
|
"""Dismiss a reason for unsupported."""
|
||||||
|
if reason not in self._unsupported:
|
||||||
|
_LOGGER.warning("The reason %s is not active", reason)
|
||||||
|
raise ResolutionError()
|
||||||
|
self._unsupported.remove(reason)
|
@ -4,7 +4,7 @@ import logging
|
|||||||
from typing import Dict, List
|
from typing import Dict, List
|
||||||
|
|
||||||
from ..coresys import CoreSys, CoreSysAttributes
|
from ..coresys import CoreSys, CoreSysAttributes
|
||||||
from ..exceptions import StoreGitError, StoreNotFound
|
from ..exceptions import StoreGitError, StoreJobError, StoreNotFound
|
||||||
from ..jobs.decorator import Job, JobCondition
|
from ..jobs.decorator import Job, JobCondition
|
||||||
from ..resolution.const import ContextType, IssueType, SuggestionType
|
from ..resolution.const import ContextType, IssueType, SuggestionType
|
||||||
from .addon import AddonStore
|
from .addon import AddonStore
|
||||||
@ -83,6 +83,14 @@ class StoreManager(CoreSysAttributes):
|
|||||||
await repository.load()
|
await repository.load()
|
||||||
except StoreGitError:
|
except StoreGitError:
|
||||||
_LOGGER.error("Can't load data from repository %s", url)
|
_LOGGER.error("Can't load data from repository %s", url)
|
||||||
|
except StoreJobError:
|
||||||
|
_LOGGER.warning("Skip update to later for %s", repository.slug)
|
||||||
|
self.sys_resolution.create_issue(
|
||||||
|
IssueType.FATAL_ERROR,
|
||||||
|
ContextType.STORE,
|
||||||
|
refrence=repository.slug,
|
||||||
|
suggestions=[SuggestionType.EXECUTE_RELOAD],
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
if not repository.validate():
|
if not repository.validate():
|
||||||
_LOGGER.error("%s is not a valid add-on repository", url)
|
_LOGGER.error("%s is not a valid add-on repository", url)
|
||||||
|
@ -9,7 +9,7 @@ import git
|
|||||||
|
|
||||||
from ..const import ATTR_BRANCH, ATTR_URL, URL_HASSIO_ADDONS
|
from ..const import ATTR_BRANCH, ATTR_URL, URL_HASSIO_ADDONS
|
||||||
from ..coresys import CoreSys, CoreSysAttributes
|
from ..coresys import CoreSys, CoreSysAttributes
|
||||||
from ..exceptions import StoreGitError
|
from ..exceptions import StoreGitError, StoreJobError
|
||||||
from ..jobs.decorator import Job, JobCondition
|
from ..jobs.decorator import Job, JobCondition
|
||||||
from ..resolution.const import ContextType, IssueType, SuggestionType
|
from ..resolution.const import ContextType, IssueType, SuggestionType
|
||||||
from ..utils import remove_folder
|
from ..utils import remove_folder
|
||||||
@ -22,6 +22,8 @@ _LOGGER: logging.Logger = logging.getLogger(__name__)
|
|||||||
class GitRepo(CoreSysAttributes):
|
class GitRepo(CoreSysAttributes):
|
||||||
"""Manage Add-on Git repository."""
|
"""Manage Add-on Git repository."""
|
||||||
|
|
||||||
|
builtin: bool
|
||||||
|
|
||||||
def __init__(self, coresys: CoreSys, path: Path, url: str):
|
def __init__(self, coresys: CoreSys, path: Path, url: str):
|
||||||
"""Initialize Git base wrapper."""
|
"""Initialize Git base wrapper."""
|
||||||
self.coresys: CoreSys = coresys
|
self.coresys: CoreSys = coresys
|
||||||
@ -82,7 +84,10 @@ class GitRepo(CoreSysAttributes):
|
|||||||
)
|
)
|
||||||
raise StoreGitError() from err
|
raise StoreGitError() from err
|
||||||
|
|
||||||
@Job(conditions=[JobCondition.FREE_SPACE, JobCondition.INTERNET_SYSTEM])
|
@Job(
|
||||||
|
conditions=[JobCondition.FREE_SPACE, JobCondition.INTERNET_SYSTEM],
|
||||||
|
on_condition=StoreJobError,
|
||||||
|
)
|
||||||
async def clone(self) -> None:
|
async def clone(self) -> None:
|
||||||
"""Clone git add-on repository."""
|
"""Clone git add-on repository."""
|
||||||
async with self.lock:
|
async with self.lock:
|
||||||
@ -115,11 +120,18 @@ class GitRepo(CoreSysAttributes):
|
|||||||
IssueType.FATAL_ERROR,
|
IssueType.FATAL_ERROR,
|
||||||
ContextType.STORE,
|
ContextType.STORE,
|
||||||
reference=self.path.stem,
|
reference=self.path.stem,
|
||||||
suggestions=[SuggestionType.EXECUTE_RELOAD],
|
suggestions=[
|
||||||
|
SuggestionType.EXECUTE_RELOAD
|
||||||
|
if self.builtin
|
||||||
|
else SuggestionType.EXECUTE_REMOVE
|
||||||
|
],
|
||||||
)
|
)
|
||||||
raise StoreGitError() from err
|
raise StoreGitError() from err
|
||||||
|
|
||||||
@Job(conditions=[JobCondition.FREE_SPACE, JobCondition.INTERNET_SYSTEM])
|
@Job(
|
||||||
|
conditions=[JobCondition.FREE_SPACE, JobCondition.INTERNET_SYSTEM],
|
||||||
|
on_condition=StoreJobError,
|
||||||
|
)
|
||||||
async def pull(self):
|
async def pull(self):
|
||||||
"""Pull Git add-on repo."""
|
"""Pull Git add-on repo."""
|
||||||
if self.lock.locked():
|
if self.lock.locked():
|
||||||
@ -175,6 +187,8 @@ class GitRepo(CoreSysAttributes):
|
|||||||
class GitRepoHassIO(GitRepo):
|
class GitRepoHassIO(GitRepo):
|
||||||
"""Supervisor add-ons repository."""
|
"""Supervisor add-ons repository."""
|
||||||
|
|
||||||
|
builtin: bool = False
|
||||||
|
|
||||||
def __init__(self, coresys):
|
def __init__(self, coresys):
|
||||||
"""Initialize Git Supervisor add-on repository."""
|
"""Initialize Git Supervisor add-on repository."""
|
||||||
super().__init__(coresys, coresys.config.path_addons_core, URL_HASSIO_ADDONS)
|
super().__init__(coresys, coresys.config.path_addons_core, URL_HASSIO_ADDONS)
|
||||||
@ -183,6 +197,8 @@ class GitRepoHassIO(GitRepo):
|
|||||||
class GitRepoCustom(GitRepo):
|
class GitRepoCustom(GitRepo):
|
||||||
"""Custom add-ons repository."""
|
"""Custom add-ons repository."""
|
||||||
|
|
||||||
|
builtin: bool = False
|
||||||
|
|
||||||
def __init__(self, coresys, url):
|
def __init__(self, coresys, url):
|
||||||
"""Initialize custom Git Supervisor addo-n repository."""
|
"""Initialize custom Git Supervisor addo-n repository."""
|
||||||
path = Path(coresys.config.path_addons_git, get_hash_from_repository(url))
|
path = Path(coresys.config.path_addons_git, get_hash_from_repository(url))
|
||||||
|
@ -100,7 +100,7 @@ class Repository(CoreSysAttributes):
|
|||||||
|
|
||||||
async def update(self) -> None:
|
async def update(self) -> None:
|
||||||
"""Update add-on repository."""
|
"""Update add-on repository."""
|
||||||
if self.type == StoreType.LOCAL:
|
if self.type == StoreType.LOCAL or not self.validate():
|
||||||
return
|
return
|
||||||
await self.git.pull()
|
await self.git.pull()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user