mirror of
https://github.com/home-assistant/supervisor.git
synced 2025-06-22 01:46:29 +00:00

* Improve gdbus error handling * Fix logging type * Detect no dbus * Fix issue with complex * Update hassio/dbus/__init__.py Co-Authored-By: Franck Nijhof <frenck@frenck.nl> * Update hassio/dbus/hostname.py Co-Authored-By: Franck Nijhof <frenck@frenck.nl> * Update hassio/dbus/rauc.py Co-Authored-By: Franck Nijhof <frenck@frenck.nl> * Update hassio/dbus/systemd.py Co-Authored-By: Franck Nijhof <frenck@frenck.nl> * Fix black
164 lines
4.8 KiB
Python
164 lines
4.8 KiB
Python
"""Init file for Hass.io add-on Git."""
|
|
import asyncio
|
|
import logging
|
|
import functools as ft
|
|
from pathlib import Path
|
|
import shutil
|
|
|
|
import git
|
|
|
|
from .utils import get_hash_from_repository
|
|
from ..const import URL_HASSIO_ADDONS, ATTR_URL, ATTR_BRANCH
|
|
from ..coresys import CoreSysAttributes
|
|
from ..validate import RE_REPOSITORY
|
|
|
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
|
|
|
|
|
class GitRepo(CoreSysAttributes):
|
|
"""Manage Add-on Git repository."""
|
|
|
|
def __init__(self, coresys, path, url):
|
|
"""Initialize Git base wrapper."""
|
|
self.coresys = coresys
|
|
self.repo = None
|
|
self.path = path
|
|
self.lock = asyncio.Lock(loop=coresys.loop)
|
|
|
|
self.data = RE_REPOSITORY.match(url).groupdict()
|
|
|
|
@property
|
|
def url(self):
|
|
"""Return repository URL."""
|
|
return self.data[ATTR_URL]
|
|
|
|
@property
|
|
def branch(self):
|
|
"""Return repository branch."""
|
|
return self.data[ATTR_BRANCH]
|
|
|
|
async def load(self):
|
|
"""Init Git add-on repository."""
|
|
if not self.path.is_dir():
|
|
return await self.clone()
|
|
|
|
async with self.lock:
|
|
try:
|
|
_LOGGER.info("Load add-on %s repository", self.path)
|
|
self.repo = await self.sys_run_in_executor(git.Repo, str(self.path))
|
|
|
|
except (
|
|
git.InvalidGitRepositoryError,
|
|
git.NoSuchPathError,
|
|
git.GitCommandError,
|
|
) as err:
|
|
_LOGGER.error("Can't load %s repo: %s.", self.path, err)
|
|
self._remove()
|
|
return False
|
|
|
|
return True
|
|
|
|
async def clone(self):
|
|
"""Clone git add-on repository."""
|
|
async with self.lock:
|
|
git_args = {
|
|
attribute: value
|
|
for attribute, value in (
|
|
("recursive", True),
|
|
("branch", self.branch),
|
|
("depth", 1),
|
|
("shallow-submodules", True),
|
|
)
|
|
if value is not None
|
|
}
|
|
|
|
try:
|
|
_LOGGER.info("Clone add-on %s repository", self.url)
|
|
self.repo = await self.sys_run_in_executor(
|
|
ft.partial(
|
|
git.Repo.clone_from, self.url, str(self.path), **git_args
|
|
)
|
|
)
|
|
|
|
except (
|
|
git.InvalidGitRepositoryError,
|
|
git.NoSuchPathError,
|
|
git.GitCommandError,
|
|
) as err:
|
|
_LOGGER.error("Can't clone %s repository: %s.", self.url, err)
|
|
self._remove()
|
|
return False
|
|
|
|
return True
|
|
|
|
async def pull(self):
|
|
"""Pull Git add-on repo."""
|
|
if self.lock.locked():
|
|
_LOGGER.warning("It is already a task in progress")
|
|
return False
|
|
|
|
async with self.lock:
|
|
_LOGGER.info("Update add-on %s repository", self.url)
|
|
branch = self.repo.active_branch.name
|
|
|
|
try:
|
|
# Download data
|
|
await self.sys_run_in_executor(
|
|
ft.partial(
|
|
self.repo.remotes.origin.fetch,
|
|
**{"update-shallow": True, "depth": 1},
|
|
)
|
|
)
|
|
|
|
# Jump on top of that
|
|
await self.sys_run_in_executor(
|
|
ft.partial(self.repo.git.reset, f"origin/{branch}", hard=True)
|
|
)
|
|
|
|
# Cleanup old data
|
|
await self.sys_run_in_executor(ft.partial(self.repo.git.clean, "-xdf"))
|
|
|
|
except (
|
|
git.InvalidGitRepositoryError,
|
|
git.NoSuchPathError,
|
|
git.GitCommandError,
|
|
) as err:
|
|
_LOGGER.error("Can't update %s repo: %s.", self.url, err)
|
|
return False
|
|
|
|
return True
|
|
|
|
def _remove(self):
|
|
"""Remove a repository."""
|
|
if not self.path.is_dir():
|
|
return
|
|
|
|
def log_err(funct, path, _):
|
|
"""Log error."""
|
|
_LOGGER.warning("Can't remove %s", path)
|
|
|
|
shutil.rmtree(str(self.path), onerror=log_err)
|
|
|
|
|
|
class GitRepoHassIO(GitRepo):
|
|
"""Hass.io add-ons repository."""
|
|
|
|
def __init__(self, coresys):
|
|
"""Initialize Git Hass.io add-on repository."""
|
|
super().__init__(coresys, coresys.config.path_addons_core, URL_HASSIO_ADDONS)
|
|
|
|
|
|
class GitRepoCustom(GitRepo):
|
|
"""Custom add-ons repository."""
|
|
|
|
def __init__(self, coresys, url):
|
|
"""Initialize custom Git Hass.io addo-n repository."""
|
|
path = Path(coresys.config.path_addons_git, get_hash_from_repository(url))
|
|
|
|
super().__init__(coresys, path, url)
|
|
|
|
def remove(self):
|
|
"""Remove a custom repository."""
|
|
_LOGGER.info("Remove custom add-on repository %s", self.url)
|
|
self._remove()
|