Files
supervisor/hassio/addons/git.py
Pascal Vizeli 28f295a1e2 Cleanup
2018-04-21 22:33:06 +02:00

133 lines
3.9 KiB
Python

"""Init file for HassIO addons 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.getLogger(__name__)
class GitRepo(CoreSysAttributes):
"""Manage addons git repo."""
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 addon repo."""
if not self.path.is_dir():
return await self.clone()
async with self.lock:
try:
_LOGGER.info("Load addon %s repository", self.path)
self.repo = await self.sys_loop.run_in_executor(
None, 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)
return False
return True
async def clone(self):
"""Clone git addon repo."""
async with self.lock:
git_args = {
attribute: value
for attribute, value in (
('recursive', True),
('branch', self.branch)
) if value is not None
}
try:
_LOGGER.info("Clone addon %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 repo: %s.", self.url, err)
return False
return True
async def pull(self):
"""Pull git addon repo."""
if self.lock.locked():
_LOGGER.warning("It is already a task in progress.")
return False
async with self.lock:
try:
_LOGGER.info("Pull addon %s repository", self.url)
await self.sys_loop.run_in_executor(
None, self.repo.remotes.origin.pull)
except (git.InvalidGitRepositoryError, git.NoSuchPathError,
git.GitCommandError) as err:
_LOGGER.error("Can't pull %s repo: %s.", self.url, err)
return False
return True
class GitRepoHassIO(GitRepo):
"""HassIO addons repository."""
def __init__(self, coresys):
"""Initialize git hassio addon repository."""
super().__init__(
coresys, coresys.config.path_addons_core, URL_HASSIO_ADDONS)
class GitRepoCustom(GitRepo):
"""Custom addons repository."""
def __init__(self, coresys, url):
"""Initialize git hassio addon repository."""
path = Path(
coresys.config.path_addons_git,
get_hash_from_repository(url))
super().__init__(coresys, path, url)
def remove(self):
"""Remove a custom addon."""
if self.path.is_dir():
_LOGGER.info("Remove custom addon repository %s", self.url)
def log_err(funct, path, _):
"""Log error."""
_LOGGER.warning("Can't remove %s", path)
shutil.rmtree(str(self.path), onerror=log_err)