mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-04-24 07:17:17 +00:00
review loggers once more
This commit makes loggers like java.util.logging with fully qualified logger name which is created by LazyLogging trait
This commit is contained in:
parent
eb5ac5a52b
commit
fac228d6c6
@ -60,6 +60,7 @@ Again, the most checks can be performed by `make check` command, though some add
|
|||||||
* The file size mentioned above must be applicable in general. In case of big classes consider splitting them into traits.
|
* The file size mentioned above must be applicable in general. In case of big classes consider splitting them into traits.
|
||||||
* No global variable allowed outside of `ahriman.version` module.
|
* No global variable allowed outside of `ahriman.version` module.
|
||||||
* Single quotes are not allowed. The reason behind this restriction is the fact that docstrings must be written by using double quotes only, and we would like to make style consistent.
|
* Single quotes are not allowed. The reason behind this restriction is the fact that docstrings must be written by using double quotes only, and we would like to make style consistent.
|
||||||
|
* If your class writes anything to log, the `ahriman.core.lazy_logging.LazyLogging` trait must be used.
|
||||||
|
|
||||||
### Other checks
|
### Other checks
|
||||||
|
|
||||||
|
@ -692,7 +692,7 @@ You can also edit configuration and forward logs to ``stderr``, just change ``ha
|
|||||||
|
|
||||||
sed -i 's/handlers = syslog_handler/handlers = console_handler/g' /etc/ahriman.ini.d/logging.ini
|
sed -i 's/handlers = syslog_handler/handlers = console_handler/g' /etc/ahriman.ini.d/logging.ini
|
||||||
|
|
||||||
You can even configure logging as you wish, but kindly refer to python ``logging`` module `configuration <https://docs.python.org/3/library/logging.config.html>`_.
|
You can even configure logging as you wish, but kindly refer to python ``logging`` module `configuration <https://docs.python.org/3/library/logging.config.html>`_. The application uses java concept to log messages, e.g. class ``Application`` imported from ``ahriman.application.application`` package will have logger called ``ahriman.application.application.Application``. In order to e.g. change logger name for whole application package it is possible to change values for ``ahriman.application`` package; thus editing ``ahriman`` logger configuration will change logging for whole application (unless there are overrides for another logger).
|
||||||
|
|
||||||
Html customization
|
Html customization
|
||||||
^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
[loggers]
|
[loggers]
|
||||||
keys = root,build,http,stderr,boto3,botocore,nose,s3transfer
|
keys = root,http,stderr,boto3,botocore,nose,s3transfer
|
||||||
|
|
||||||
[handlers]
|
[handlers]
|
||||||
keys = console_handler,syslog_handler
|
keys = console_handler,syslog_handler
|
||||||
@ -20,11 +20,11 @@ formatter = syslog_format
|
|||||||
args = ("/dev/log",)
|
args = ("/dev/log",)
|
||||||
|
|
||||||
[formatter_generic_format]
|
[formatter_generic_format]
|
||||||
format = [%(levelname)s %(asctime)s] [%(filename)s:%(lineno)d %(funcName)s]: %(message)s
|
format = [%(levelname)s %(asctime)s] [%(threadName)s] [%(name)s]: %(message)s
|
||||||
datefmt =
|
datefmt =
|
||||||
|
|
||||||
[formatter_syslog_format]
|
[formatter_syslog_format]
|
||||||
format = [%(levelname)s] [%(name)s] [%(filename)s:%(lineno)d] [%(funcName)s]: %(message)s
|
format = [%(levelname)s] [%(threadName)s] [%(name)s]: %(message)s
|
||||||
datefmt =
|
datefmt =
|
||||||
|
|
||||||
[logger_root]
|
[logger_root]
|
||||||
@ -32,12 +32,6 @@ level = DEBUG
|
|||||||
handlers = syslog_handler
|
handlers = syslog_handler
|
||||||
qualname = root
|
qualname = root
|
||||||
|
|
||||||
[logger_build]
|
|
||||||
level = DEBUG
|
|
||||||
handlers = syslog_handler
|
|
||||||
qualname = build
|
|
||||||
propagate = 0
|
|
||||||
|
|
||||||
[logger_http]
|
[logger_http]
|
||||||
level = DEBUG
|
level = DEBUG
|
||||||
handlers = syslog_handler
|
handlers = syslog_handler
|
||||||
|
@ -17,14 +17,13 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
import logging
|
|
||||||
|
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.database import SQLite
|
from ahriman.core.database import SQLite
|
||||||
|
from ahriman.core.lazy_logging import LazyLogging
|
||||||
from ahriman.core.repository import Repository
|
from ahriman.core.repository import Repository
|
||||||
|
|
||||||
|
|
||||||
class ApplicationProperties:
|
class ApplicationProperties(LazyLogging):
|
||||||
"""
|
"""
|
||||||
application base properties class
|
application base properties class
|
||||||
|
|
||||||
@ -32,7 +31,6 @@ class ApplicationProperties:
|
|||||||
architecture(str): repository architecture
|
architecture(str): repository architecture
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
database(SQLite): database instance
|
database(SQLite): database instance
|
||||||
logger(logging.Logger): application logger
|
|
||||||
repository(Repository): repository instance
|
repository(Repository): repository instance
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -44,9 +42,8 @@ class ApplicationProperties:
|
|||||||
architecture(str): repository architecture
|
architecture(str): repository architecture
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
no_report(bool): force disable reporting
|
no_report(bool): force disable reporting
|
||||||
unsafe(bool): if set no user check will be performed before path creation
|
unsafe(bool): if set no user check will be performed before path creation
|
||||||
"""
|
"""
|
||||||
self.logger = logging.getLogger("root")
|
|
||||||
self.configuration = configuration
|
self.configuration = configuration
|
||||||
self.architecture = architecture
|
self.architecture = architecture
|
||||||
self.database = SQLite.load(configuration)
|
self.database = SQLite.load(configuration)
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import logging
|
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from types import TracebackType
|
from types import TracebackType
|
||||||
@ -29,12 +28,13 @@ from typing import Literal, Optional, Type
|
|||||||
from ahriman import version
|
from ahriman import version
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.exceptions import DuplicateRun
|
from ahriman.core.exceptions import DuplicateRun
|
||||||
|
from ahriman.core.lazy_logging import LazyLogging
|
||||||
from ahriman.core.status.client import Client
|
from ahriman.core.status.client import Client
|
||||||
from ahriman.core.util import check_user
|
from ahriman.core.util import check_user
|
||||||
from ahriman.models.build_status import BuildStatusEnum
|
from ahriman.models.build_status import BuildStatusEnum
|
||||||
|
|
||||||
|
|
||||||
class Lock:
|
class Lock(LazyLogging):
|
||||||
"""
|
"""
|
||||||
wrapper for application lock file
|
wrapper for application lock file
|
||||||
|
|
||||||
@ -115,10 +115,8 @@ class Lock:
|
|||||||
"""
|
"""
|
||||||
status = self.reporter.get_internal()
|
status = self.reporter.get_internal()
|
||||||
if status.version is not None and status.version != version.__version__:
|
if status.version is not None and status.version != version.__version__:
|
||||||
logging.getLogger("root").warning(
|
self.logger.warning("status watcher version mismatch, our %s, their %s",
|
||||||
"status watcher version mismatch, our %s, their %s",
|
version.__version__, status.version)
|
||||||
version.__version__,
|
|
||||||
status.version)
|
|
||||||
|
|
||||||
def check_user(self) -> None:
|
def check_user(self) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -19,21 +19,17 @@
|
|||||||
#
|
#
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
|
||||||
|
|
||||||
from typing import Dict, List, Type
|
from typing import Dict, List, Type
|
||||||
|
|
||||||
from ahriman.core.alpm.pacman import Pacman
|
from ahriman.core.alpm.pacman import Pacman
|
||||||
|
from ahriman.core.lazy_logging import LazyLogging
|
||||||
from ahriman.models.aur_package import AURPackage
|
from ahriman.models.aur_package import AURPackage
|
||||||
|
|
||||||
|
|
||||||
class Remote:
|
class Remote(LazyLogging):
|
||||||
"""
|
"""
|
||||||
base class for remote package search
|
base class for remote package search
|
||||||
|
|
||||||
Attributes:
|
|
||||||
logger(logging.Logger): class logger
|
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
These classes are designed to be used without instancing. In order to achieve it several class methods are
|
These classes are designed to be used without instancing. In order to achieve it several class methods are
|
||||||
provided: ``info``, ``multisearch`` and ``search``. Thus, the basic flow is the following::
|
provided: ``info``, ``multisearch`` and ``search``. Thus, the basic flow is the following::
|
||||||
@ -47,12 +43,6 @@ class Remote:
|
|||||||
directly, whereas ``multisearch`` splits search one by one and finds intersection between search results.
|
directly, whereas ``multisearch`` splits search one by one and finds intersection between search results.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self) -> None:
|
|
||||||
"""
|
|
||||||
default constructor
|
|
||||||
"""
|
|
||||||
self.logger = logging.getLogger("build")
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def info(cls: Type[Remote], package_name: str, *, pacman: Pacman) -> AURPackage:
|
def info(cls: Type[Remote], package_name: str, *, pacman: Pacman) -> AURPackage:
|
||||||
"""
|
"""
|
||||||
|
@ -17,22 +17,20 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
import logging
|
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from ahriman.core.exceptions import BuildFailed
|
from ahriman.core.exceptions import BuildFailed
|
||||||
|
from ahriman.core.lazy_logging import LazyLogging
|
||||||
from ahriman.core.util import check_output
|
from ahriman.core.util import check_output
|
||||||
from ahriman.models.repository_paths import RepositoryPaths
|
from ahriman.models.repository_paths import RepositoryPaths
|
||||||
|
|
||||||
|
|
||||||
class Repo:
|
class Repo(LazyLogging):
|
||||||
"""
|
"""
|
||||||
repo-add and repo-remove wrapper
|
repo-add and repo-remove wrapper
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
logger(logging.Logger): class logger
|
|
||||||
name(str): repository name
|
name(str): repository name
|
||||||
paths(RepositoryPaths): repository paths instance
|
paths(RepositoryPaths): repository paths instance
|
||||||
sign_args(List[str]): additional args which have to be used to sign repository archive
|
sign_args(List[str]): additional args which have to be used to sign repository archive
|
||||||
@ -50,7 +48,6 @@ class Repo:
|
|||||||
paths(RepositoryPaths): repository paths instance
|
paths(RepositoryPaths): repository paths instance
|
||||||
sign_args(List[str]): additional args which have to be used to sign repository archive
|
sign_args(List[str]): additional args which have to be used to sign repository archive
|
||||||
"""
|
"""
|
||||||
self.logger = logging.getLogger("build")
|
|
||||||
self.name = name
|
self.name = name
|
||||||
self.paths = paths
|
self.paths = paths
|
||||||
self.uid, _ = paths.root_owner
|
self.uid, _ = paths.root_owner
|
||||||
|
@ -19,23 +19,21 @@
|
|||||||
#
|
#
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
|
||||||
|
|
||||||
from typing import Optional, Type
|
from typing import Optional, Type
|
||||||
|
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.database import SQLite
|
from ahriman.core.database import SQLite
|
||||||
|
from ahriman.core.lazy_logging import LazyLogging
|
||||||
from ahriman.models.auth_settings import AuthSettings
|
from ahriman.models.auth_settings import AuthSettings
|
||||||
from ahriman.models.user_access import UserAccess
|
from ahriman.models.user_access import UserAccess
|
||||||
|
|
||||||
|
|
||||||
class Auth:
|
class Auth(LazyLogging):
|
||||||
"""
|
"""
|
||||||
helper to deal with user authorization
|
helper to deal with user authorization
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
enabled(bool): indicates if authorization is enabled
|
enabled(bool): indicates if authorization is enabled
|
||||||
logger(logging.Logger): class logger
|
|
||||||
max_age(int): session age in seconds. It will be used for both client side and server side checks
|
max_age(int): session age in seconds. It will be used for both client side and server side checks
|
||||||
allow_read_only(bool): allow read only access to APIs
|
allow_read_only(bool): allow read only access to APIs
|
||||||
"""
|
"""
|
||||||
@ -48,8 +46,6 @@ class Auth:
|
|||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
provider(AuthSettings, optional): authorization type definition (Default value = AuthSettings.Disabled)
|
provider(AuthSettings, optional): authorization type definition (Default value = AuthSettings.Disabled)
|
||||||
"""
|
"""
|
||||||
self.logger = logging.getLogger("http")
|
|
||||||
|
|
||||||
self.allow_read_only = configuration.getboolean("auth", "allow_read_only")
|
self.allow_read_only = configuration.getboolean("auth", "allow_read_only")
|
||||||
|
|
||||||
self.enabled = provider.is_enabled
|
self.enabled = provider.is_enabled
|
||||||
|
@ -17,82 +17,31 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
import logging
|
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
|
from ahriman.core.lazy_logging import LazyLogging
|
||||||
from ahriman.core.util import check_output, walk
|
from ahriman.core.util import check_output, walk
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
from ahriman.models.remote_source import RemoteSource
|
from ahriman.models.remote_source import RemoteSource
|
||||||
from ahriman.models.repository_paths import RepositoryPaths
|
from ahriman.models.repository_paths import RepositoryPaths
|
||||||
|
|
||||||
|
|
||||||
class Sources:
|
class Sources(LazyLogging):
|
||||||
"""
|
"""
|
||||||
helper to download package sources (PKGBUILD etc)
|
helper to download package sources (PKGBUILD etc)
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
DEFAULT_BRANCH(str): (class attribute) default branch to process git repositories.
|
DEFAULT_BRANCH(str): (class attribute) default branch to process git repositories.
|
||||||
Must be used only for local stored repositories, use RemoteSource descriptor instead for real packages
|
Must be used only for local stored repositories, use RemoteSource descriptor instead for real packages
|
||||||
logger(logging.Logger): (class attribute) class logger
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
DEFAULT_BRANCH = "master" # default fallback branch
|
DEFAULT_BRANCH = "master" # default fallback branch
|
||||||
logger = logging.getLogger("build")
|
|
||||||
|
|
||||||
_check_output = check_output
|
_check_output = check_output
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _add(sources_dir: Path, *pattern: str) -> None:
|
|
||||||
"""
|
|
||||||
track found files via git
|
|
||||||
|
|
||||||
Args:
|
|
||||||
sources_dir(Path): local path to git repository
|
|
||||||
*pattern(str): glob patterns
|
|
||||||
"""
|
|
||||||
# glob directory to find files which match the specified patterns
|
|
||||||
found_files: List[Path] = []
|
|
||||||
for glob in pattern:
|
|
||||||
found_files.extend(sources_dir.glob(glob))
|
|
||||||
if not found_files:
|
|
||||||
return # no additional files found
|
|
||||||
Sources.logger.info("found matching files %s", found_files)
|
|
||||||
# add them to index
|
|
||||||
Sources._check_output("git", "add", "--intent-to-add",
|
|
||||||
*[str(fn.relative_to(sources_dir)) for fn in found_files],
|
|
||||||
exception=None, cwd=sources_dir, logger=Sources.logger)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _diff(sources_dir: Path) -> str:
|
|
||||||
"""
|
|
||||||
generate diff from the current version and write it to the output file
|
|
||||||
|
|
||||||
Args:
|
|
||||||
sources_dir(Path): local path to git repository
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
str: patch as plain string
|
|
||||||
"""
|
|
||||||
return Sources._check_output("git", "diff", exception=None, cwd=sources_dir, logger=Sources.logger)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _move(pkgbuild_dir: Path, sources_dir: Path) -> None:
|
|
||||||
"""
|
|
||||||
move content from pkgbuild_dir to sources_dir
|
|
||||||
|
|
||||||
Args:
|
|
||||||
pkgbuild_dir(Path): path to directory with pkgbuild from which need to move
|
|
||||||
sources_dir(Path): path to target directory
|
|
||||||
"""
|
|
||||||
if pkgbuild_dir == sources_dir:
|
|
||||||
return # directories are the same, no need to move
|
|
||||||
for src in walk(pkgbuild_dir):
|
|
||||||
dst = sources_dir / src.relative_to(pkgbuild_dir)
|
|
||||||
shutil.move(src, dst)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def fetch(sources_dir: Path, remote: Optional[RemoteSource]) -> None:
|
def fetch(sources_dir: Path, remote: Optional[RemoteSource]) -> None:
|
||||||
"""
|
"""
|
||||||
@ -102,37 +51,38 @@ class Sources:
|
|||||||
sources_dir(Path): local path to fetch
|
sources_dir(Path): local path to fetch
|
||||||
remote(Optional[RemoteSource]): remote target (from where to fetch)
|
remote(Optional[RemoteSource]): remote target (from where to fetch)
|
||||||
"""
|
"""
|
||||||
|
instance = Sources()
|
||||||
# local directory exists and there is .git directory
|
# local directory exists and there is .git directory
|
||||||
is_initialized_git = (sources_dir / ".git").is_dir()
|
is_initialized_git = (sources_dir / ".git").is_dir()
|
||||||
if is_initialized_git and not Sources.has_remotes(sources_dir):
|
if is_initialized_git and not instance.has_remotes(sources_dir):
|
||||||
# there is git repository, but no remote configured so far
|
# there is git repository, but no remote configured so far
|
||||||
Sources.logger.info("skip update at %s because there are no branches configured", sources_dir)
|
instance.logger.info("skip update at %s because there are no branches configured", sources_dir)
|
||||||
return
|
return
|
||||||
|
|
||||||
branch = remote.branch if remote is not None else Sources.DEFAULT_BRANCH
|
branch = remote.branch if remote is not None else instance.DEFAULT_BRANCH
|
||||||
if is_initialized_git:
|
if is_initialized_git:
|
||||||
Sources.logger.info("update HEAD to remote at %s using branch %s", sources_dir, branch)
|
instance.logger.info("update HEAD to remote at %s using branch %s", sources_dir, branch)
|
||||||
Sources._check_output("git", "fetch", "origin", branch,
|
Sources._check_output("git", "fetch", "origin", branch,
|
||||||
exception=None, cwd=sources_dir, logger=Sources.logger)
|
exception=None, cwd=sources_dir, logger=instance.logger)
|
||||||
elif remote is not None:
|
elif remote is not None:
|
||||||
Sources.logger.info("clone remote %s to %s using branch %s", remote.git_url, sources_dir, branch)
|
instance.logger.info("clone remote %s to %s using branch %s", remote.git_url, sources_dir, branch)
|
||||||
Sources._check_output("git", "clone", "--branch", branch, "--single-branch",
|
Sources._check_output("git", "clone", "--branch", branch, "--single-branch",
|
||||||
remote.git_url, str(sources_dir),
|
remote.git_url, str(sources_dir),
|
||||||
exception=None, cwd=sources_dir, logger=Sources.logger)
|
exception=None, cwd=sources_dir, logger=instance.logger)
|
||||||
else:
|
else:
|
||||||
# it will cause an exception later
|
# it will cause an exception later
|
||||||
Sources.logger.error("%s is not initialized, but no remote provided", sources_dir)
|
instance.logger.error("%s is not initialized, but no remote provided", sources_dir)
|
||||||
|
|
||||||
# and now force reset to our branch
|
# and now force reset to our branch
|
||||||
Sources._check_output("git", "checkout", "--force", branch,
|
Sources._check_output("git", "checkout", "--force", branch,
|
||||||
exception=None, cwd=sources_dir, logger=Sources.logger)
|
exception=None, cwd=sources_dir, logger=instance.logger)
|
||||||
Sources._check_output("git", "reset", "--hard", f"origin/{branch}",
|
Sources._check_output("git", "reset", "--hard", f"origin/{branch}",
|
||||||
exception=None, cwd=sources_dir, logger=Sources.logger)
|
exception=None, cwd=sources_dir, logger=instance.logger)
|
||||||
|
|
||||||
# move content if required
|
# move content if required
|
||||||
# we are using full path to source directory in order to make append possible
|
# we are using full path to source directory in order to make append possible
|
||||||
pkgbuild_dir = remote.pkgbuild_dir if remote is not None else sources_dir.resolve()
|
pkgbuild_dir = remote.pkgbuild_dir if remote is not None else sources_dir.resolve()
|
||||||
Sources._move((sources_dir / pkgbuild_dir).resolve(), sources_dir)
|
instance.move((sources_dir / pkgbuild_dir).resolve(), sources_dir)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def has_remotes(sources_dir: Path) -> bool:
|
def has_remotes(sources_dir: Path) -> bool:
|
||||||
@ -145,7 +95,8 @@ class Sources:
|
|||||||
Returns:
|
Returns:
|
||||||
bool: True in case if there is any remote and false otherwise
|
bool: True in case if there is any remote and false otherwise
|
||||||
"""
|
"""
|
||||||
remotes = Sources._check_output("git", "remote", exception=None, cwd=sources_dir, logger=Sources.logger)
|
instance = Sources()
|
||||||
|
remotes = Sources._check_output("git", "remote", exception=None, cwd=sources_dir, logger=instance.logger)
|
||||||
return bool(remotes)
|
return bool(remotes)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -156,8 +107,9 @@ class Sources:
|
|||||||
Args:
|
Args:
|
||||||
sources_dir(Path): local path to sources
|
sources_dir(Path): local path to sources
|
||||||
"""
|
"""
|
||||||
|
instance = Sources()
|
||||||
Sources._check_output("git", "init", "--initial-branch", Sources.DEFAULT_BRANCH,
|
Sources._check_output("git", "init", "--initial-branch", Sources.DEFAULT_BRANCH,
|
||||||
exception=None, cwd=sources_dir, logger=Sources.logger)
|
exception=None, cwd=sources_dir, logger=instance.logger)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def load(sources_dir: Path, package: Package, patch: Optional[str], paths: RepositoryPaths) -> None:
|
def load(sources_dir: Path, package: Package, patch: Optional[str], paths: RepositoryPaths) -> None:
|
||||||
@ -170,29 +122,16 @@ class Sources:
|
|||||||
patch(Optional[str]): optional patch to be applied
|
patch(Optional[str]): optional patch to be applied
|
||||||
paths(RepositoryPaths): repository paths instance
|
paths(RepositoryPaths): repository paths instance
|
||||||
"""
|
"""
|
||||||
|
instance = Sources()
|
||||||
if (cache_dir := paths.cache_for(package.base)).is_dir() and cache_dir != sources_dir:
|
if (cache_dir := paths.cache_for(package.base)).is_dir() and cache_dir != sources_dir:
|
||||||
# no need to clone whole repository, just copy from cache first
|
# no need to clone whole repository, just copy from cache first
|
||||||
shutil.copytree(cache_dir, sources_dir, dirs_exist_ok=True)
|
shutil.copytree(cache_dir, sources_dir, dirs_exist_ok=True)
|
||||||
Sources.fetch(sources_dir, package.remote)
|
Sources.fetch(sources_dir, package.remote)
|
||||||
|
|
||||||
if patch is None:
|
if patch is None:
|
||||||
Sources.logger.info("no patches found")
|
instance.logger.info("no patches found")
|
||||||
return
|
return
|
||||||
Sources.patch_apply(sources_dir, patch)
|
instance.patch_apply(sources_dir, patch)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def patch_apply(sources_dir: Path, patch: str) -> None:
|
|
||||||
"""
|
|
||||||
apply patches if any
|
|
||||||
|
|
||||||
Args:
|
|
||||||
sources_dir(Path): local path to directory with git sources
|
|
||||||
patch(str): patch to be applied
|
|
||||||
"""
|
|
||||||
# create patch
|
|
||||||
Sources.logger.info("apply patch from database")
|
|
||||||
Sources._check_output("git", "apply", "--ignore-space-change", "--ignore-whitespace",
|
|
||||||
exception=None, cwd=sources_dir, input_data=patch, logger=Sources.logger)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def patch_create(sources_dir: Path, *pattern: str) -> str:
|
def patch_create(sources_dir: Path, *pattern: str) -> str:
|
||||||
@ -206,6 +145,67 @@ class Sources:
|
|||||||
Returns:
|
Returns:
|
||||||
str: patch as plain text
|
str: patch as plain text
|
||||||
"""
|
"""
|
||||||
Sources._add(sources_dir, *pattern)
|
instance = Sources()
|
||||||
diff = Sources._diff(sources_dir)
|
instance.add(sources_dir, *pattern)
|
||||||
|
diff = instance.diff(sources_dir)
|
||||||
return f"{diff}\n" # otherwise, patch will be broken
|
return f"{diff}\n" # otherwise, patch will be broken
|
||||||
|
|
||||||
|
def add(self, sources_dir: Path, *pattern: str) -> None:
|
||||||
|
"""
|
||||||
|
track found files via git
|
||||||
|
|
||||||
|
Args:
|
||||||
|
sources_dir(Path): local path to git repository
|
||||||
|
*pattern(str): glob patterns
|
||||||
|
"""
|
||||||
|
# glob directory to find files which match the specified patterns
|
||||||
|
found_files: List[Path] = []
|
||||||
|
for glob in pattern:
|
||||||
|
found_files.extend(sources_dir.glob(glob))
|
||||||
|
if not found_files:
|
||||||
|
return # no additional files found
|
||||||
|
self.logger.info("found matching files %s", found_files)
|
||||||
|
# add them to index
|
||||||
|
Sources._check_output("git", "add", "--intent-to-add",
|
||||||
|
*[str(fn.relative_to(sources_dir)) for fn in found_files],
|
||||||
|
exception=None, cwd=sources_dir, logger=self.logger)
|
||||||
|
|
||||||
|
def diff(self, sources_dir: Path) -> str:
|
||||||
|
"""
|
||||||
|
generate diff from the current version and write it to the output file
|
||||||
|
|
||||||
|
Args:
|
||||||
|
sources_dir(Path): local path to git repository
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: patch as plain string
|
||||||
|
"""
|
||||||
|
return Sources._check_output("git", "diff", exception=None, cwd=sources_dir, logger=self.logger)
|
||||||
|
|
||||||
|
def move(self, pkgbuild_dir: Path, sources_dir: Path) -> None:
|
||||||
|
"""
|
||||||
|
move content from pkgbuild_dir to sources_dir
|
||||||
|
|
||||||
|
Args:
|
||||||
|
pkgbuild_dir(Path): path to directory with pkgbuild from which need to move
|
||||||
|
sources_dir(Path): path to target directory
|
||||||
|
"""
|
||||||
|
del self
|
||||||
|
if pkgbuild_dir == sources_dir:
|
||||||
|
return # directories are the same, no need to move
|
||||||
|
for src in walk(pkgbuild_dir):
|
||||||
|
dst = sources_dir / src.relative_to(pkgbuild_dir)
|
||||||
|
shutil.move(src, dst)
|
||||||
|
|
||||||
|
def patch_apply(self, sources_dir: Path, patch: str) -> None:
|
||||||
|
"""
|
||||||
|
apply patches if any
|
||||||
|
|
||||||
|
Args:
|
||||||
|
sources_dir(Path): local path to directory with git sources
|
||||||
|
patch(str): patch to be applied
|
||||||
|
"""
|
||||||
|
# create patch
|
||||||
|
self.logger.info("apply patch from database")
|
||||||
|
Sources._check_output("git", "apply", "--ignore-space-change", "--ignore-whitespace",
|
||||||
|
exception=None, cwd=sources_dir, input_data=patch, logger=self.logger)
|
||||||
|
@ -17,8 +17,6 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
import logging
|
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
@ -26,17 +24,17 @@ from ahriman.core.build_tools.sources import Sources
|
|||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.database import SQLite
|
from ahriman.core.database import SQLite
|
||||||
from ahriman.core.exceptions import BuildFailed
|
from ahriman.core.exceptions import BuildFailed
|
||||||
|
from ahriman.core.lazy_logging import LazyLogging
|
||||||
from ahriman.core.util import check_output
|
from ahriman.core.util import check_output
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
from ahriman.models.repository_paths import RepositoryPaths
|
from ahriman.models.repository_paths import RepositoryPaths
|
||||||
|
|
||||||
|
|
||||||
class Task:
|
class Task(LazyLogging):
|
||||||
"""
|
"""
|
||||||
base package build task
|
base package build task
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
logger(logging.Logger): class logger
|
|
||||||
package(Package): package definitions
|
package(Package): package definitions
|
||||||
paths(RepositoryPaths): repository paths instance
|
paths(RepositoryPaths): repository paths instance
|
||||||
uid(int): uid of the repository owner user
|
uid(int): uid of the repository owner user
|
||||||
@ -53,7 +51,6 @@ class Task:
|
|||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
paths(RepositoryPaths): repository paths instance
|
paths(RepositoryPaths): repository paths instance
|
||||||
"""
|
"""
|
||||||
self.logger = logging.getLogger("build")
|
|
||||||
self.package = package
|
self.package = package
|
||||||
self.paths = paths
|
self.paths = paths
|
||||||
self.uid, _ = paths.root_owner
|
self.uid, _ = paths.root_owner
|
||||||
|
@ -19,8 +19,6 @@
|
|||||||
#
|
#
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
|
||||||
|
|
||||||
from importlib import import_module
|
from importlib import import_module
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from pkgutil import iter_modules
|
from pkgutil import iter_modules
|
||||||
@ -29,11 +27,12 @@ from typing import List, Type
|
|||||||
|
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.database.data import migrate_data
|
from ahriman.core.database.data import migrate_data
|
||||||
|
from ahriman.core.lazy_logging import LazyLogging
|
||||||
from ahriman.models.migration import Migration
|
from ahriman.models.migration import Migration
|
||||||
from ahriman.models.migration_result import MigrationResult
|
from ahriman.models.migration_result import MigrationResult
|
||||||
|
|
||||||
|
|
||||||
class Migrations:
|
class Migrations(LazyLogging):
|
||||||
"""
|
"""
|
||||||
simple migration wrapper for the sqlite
|
simple migration wrapper for the sqlite
|
||||||
idea comes from https://www.ash.dev/blog/simple-migration-system-in-sqlite/
|
idea comes from https://www.ash.dev/blog/simple-migration-system-in-sqlite/
|
||||||
@ -41,7 +40,6 @@ class Migrations:
|
|||||||
Attributes:
|
Attributes:
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
connection(Connection): database connection
|
connection(Connection): database connection
|
||||||
logger(logging.Logger): class logger
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, connection: Connection, configuration: Configuration) -> None:
|
def __init__(self, connection: Connection, configuration: Configuration) -> None:
|
||||||
@ -54,7 +52,6 @@ class Migrations:
|
|||||||
"""
|
"""
|
||||||
self.connection = connection
|
self.connection = connection
|
||||||
self.configuration = configuration
|
self.configuration = configuration
|
||||||
self.logger = logging.getLogger("root")
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def migrate(cls: Type[Migrations], connection: Connection, configuration: Configuration) -> MigrationResult:
|
def migrate(cls: Type[Migrations], connection: Connection, configuration: Configuration) -> MigrationResult:
|
||||||
|
@ -17,23 +17,22 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
import logging
|
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from sqlite3 import Connection, Cursor
|
from sqlite3 import Connection, Cursor
|
||||||
from typing import Any, Dict, Tuple, TypeVar, Callable
|
from typing import Any, Dict, Tuple, TypeVar, Callable
|
||||||
|
|
||||||
|
from ahriman.core.lazy_logging import LazyLogging
|
||||||
|
|
||||||
T = TypeVar("T")
|
T = TypeVar("T")
|
||||||
|
|
||||||
|
|
||||||
class Operations:
|
class Operations(LazyLogging):
|
||||||
"""
|
"""
|
||||||
base operation class
|
base operation class
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
logger(logging.Logger): class logger
|
|
||||||
path(Path): path to the database file
|
path(Path): path to the database file
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -45,7 +44,6 @@ class Operations:
|
|||||||
path(Path): path to the database file
|
path(Path): path to the database file
|
||||||
"""
|
"""
|
||||||
self.path = path
|
self.path = path
|
||||||
self.logger = logging.getLogger("root")
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def factory(cursor: Cursor, row: Tuple[Any, ...]) -> Dict[str, Any]:
|
def factory(cursor: Cursor, row: Tuple[Any, ...]) -> Dict[str, Any]:
|
||||||
|
64
src/ahriman/core/lazy_logging.py
Normal file
64
src/ahriman/core/lazy_logging.py
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2021-2022 ahriman team.
|
||||||
|
#
|
||||||
|
# This file is part of ahriman
|
||||||
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
|
class LazyLogging:
|
||||||
|
"""
|
||||||
|
wrapper for the logger library inspired by scala lazy logging module
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
logger(logging.Logger): class logger instance
|
||||||
|
"""
|
||||||
|
|
||||||
|
logger: logging.Logger
|
||||||
|
|
||||||
|
def __getattr__(self, item: str) -> Any:
|
||||||
|
"""
|
||||||
|
logger extractor
|
||||||
|
|
||||||
|
Args:
|
||||||
|
item(str) property name:
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Any: attribute by its name
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
AttributeError: in case if no such attribute found
|
||||||
|
"""
|
||||||
|
if item == "logger":
|
||||||
|
logger = logging.getLogger(self.logger_name)
|
||||||
|
setattr(self, item, logger)
|
||||||
|
return logger
|
||||||
|
raise AttributeError(f"'{self.__class__.__qualname__}' object has no attribute '{item}'")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def logger_name(self) -> str:
|
||||||
|
"""
|
||||||
|
extract logger name for the class
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: logger name as combination of module name and class name
|
||||||
|
"""
|
||||||
|
clazz = self.__class__
|
||||||
|
prefix = "" if clazz.__module__ is None else f"{clazz.__module__}."
|
||||||
|
return f"{prefix}{self.__class__.__qualname__}"
|
@ -19,25 +19,23 @@
|
|||||||
#
|
#
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
|
||||||
|
|
||||||
from typing import Iterable, Type
|
from typing import Iterable, Type
|
||||||
|
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.exceptions import ReportFailed
|
from ahriman.core.exceptions import ReportFailed
|
||||||
|
from ahriman.core.lazy_logging import LazyLogging
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
from ahriman.models.report_settings import ReportSettings
|
from ahriman.models.report_settings import ReportSettings
|
||||||
from ahriman.models.result import Result
|
from ahriman.models.result import Result
|
||||||
|
|
||||||
|
|
||||||
class Report:
|
class Report(LazyLogging):
|
||||||
"""
|
"""
|
||||||
base report generator
|
base report generator
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
architecture(str): repository architecture
|
architecture(str): repository architecture
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
logger(logging.Logger): class logger
|
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
``Report`` classes provide several method in order to operate with the report generation and additional class
|
``Report`` classes provide several method in order to operate with the report generation and additional class
|
||||||
@ -67,7 +65,6 @@ class Report:
|
|||||||
architecture(str): repository architecture
|
architecture(str): repository architecture
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
"""
|
"""
|
||||||
self.logger = logging.getLogger("root")
|
|
||||||
self.architecture = architecture
|
self.architecture = architecture
|
||||||
self.configuration = configuration
|
self.configuration = configuration
|
||||||
|
|
||||||
|
@ -17,20 +17,19 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
import logging
|
|
||||||
|
|
||||||
from ahriman.core.alpm.pacman import Pacman
|
from ahriman.core.alpm.pacman import Pacman
|
||||||
from ahriman.core.alpm.repo import Repo
|
from ahriman.core.alpm.repo import Repo
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.database import SQLite
|
from ahriman.core.database import SQLite
|
||||||
from ahriman.core.exceptions import UnsafeRun
|
from ahriman.core.exceptions import UnsafeRun
|
||||||
|
from ahriman.core.lazy_logging import LazyLogging
|
||||||
from ahriman.core.sign.gpg import GPG
|
from ahriman.core.sign.gpg import GPG
|
||||||
from ahriman.core.status.client import Client
|
from ahriman.core.status.client import Client
|
||||||
from ahriman.core.triggers import TriggerLoader
|
from ahriman.core.triggers import TriggerLoader
|
||||||
from ahriman.core.util import check_user
|
from ahriman.core.util import check_user
|
||||||
|
|
||||||
|
|
||||||
class RepositoryProperties:
|
class RepositoryProperties(LazyLogging):
|
||||||
"""
|
"""
|
||||||
repository internal objects holder
|
repository internal objects holder
|
||||||
|
|
||||||
@ -39,7 +38,6 @@ class RepositoryProperties:
|
|||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
database(SQLite): database instance
|
database(SQLite): database instance
|
||||||
ignore_list(List[str]): package bases which will be ignored during auto updates
|
ignore_list(List[str]): package bases which will be ignored during auto updates
|
||||||
logger(logging.Logger): class logger
|
|
||||||
name(str): repository name
|
name(str): repository name
|
||||||
pacman(Pacman): alpm wrapper instance
|
pacman(Pacman): alpm wrapper instance
|
||||||
paths(RepositoryPaths): repository paths instance
|
paths(RepositoryPaths): repository paths instance
|
||||||
@ -61,7 +59,6 @@ class RepositoryProperties:
|
|||||||
no_report(bool): force disable reporting
|
no_report(bool): force disable reporting
|
||||||
unsafe(bool): if set no user check will be performed before path creation
|
unsafe(bool): if set no user check will be performed before path creation
|
||||||
"""
|
"""
|
||||||
self.logger = logging.getLogger("root")
|
|
||||||
self.architecture = architecture
|
self.architecture = architecture
|
||||||
self.configuration = configuration
|
self.configuration = configuration
|
||||||
self.database = database
|
self.database = database
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
import logging
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@ -25,11 +24,12 @@ from typing import List, Optional, Set, Tuple
|
|||||||
|
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.exceptions import BuildFailed
|
from ahriman.core.exceptions import BuildFailed
|
||||||
|
from ahriman.core.lazy_logging import LazyLogging
|
||||||
from ahriman.core.util import check_output, exception_response_text
|
from ahriman.core.util import check_output, exception_response_text
|
||||||
from ahriman.models.sign_settings import SignSettings
|
from ahriman.models.sign_settings import SignSettings
|
||||||
|
|
||||||
|
|
||||||
class GPG:
|
class GPG(LazyLogging):
|
||||||
"""
|
"""
|
||||||
gnupg wrapper
|
gnupg wrapper
|
||||||
|
|
||||||
@ -37,7 +37,6 @@ class GPG:
|
|||||||
architecture(str): repository architecture
|
architecture(str): repository architecture
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
default_key(Optional[str]): default PGP key ID to use
|
default_key(Optional[str]): default PGP key ID to use
|
||||||
logger(logging.Logger): class logger
|
|
||||||
targets(Set[SignSettings]): list of targets to sign (repository, package etc)
|
targets(Set[SignSettings]): list of targets to sign (repository, package etc)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -51,7 +50,6 @@ class GPG:
|
|||||||
architecture(str): repository architecture
|
architecture(str): repository architecture
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
"""
|
"""
|
||||||
self.logger = logging.getLogger("build")
|
|
||||||
self.architecture = architecture
|
self.architecture = architecture
|
||||||
self.configuration = configuration
|
self.configuration = configuration
|
||||||
self.targets, self.default_key = self.sign_options(configuration)
|
self.targets, self.default_key = self.sign_options(configuration)
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import logging
|
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from multiprocessing import Process, Queue
|
from multiprocessing import Process, Queue
|
||||||
@ -28,10 +27,11 @@ from threading import Lock, Thread
|
|||||||
from typing import Callable, Dict, Iterable, Tuple
|
from typing import Callable, Dict, Iterable, Tuple
|
||||||
|
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
|
from ahriman.core.lazy_logging import LazyLogging
|
||||||
from ahriman.models.package_source import PackageSource
|
from ahriman.models.package_source import PackageSource
|
||||||
|
|
||||||
|
|
||||||
class Spawn(Thread):
|
class Spawn(Thread, LazyLogging):
|
||||||
"""
|
"""
|
||||||
helper to spawn external ahriman process
|
helper to spawn external ahriman process
|
||||||
MUST NOT be used directly, the only one usage allowed is to spawn process from web services
|
MUST NOT be used directly, the only one usage allowed is to spawn process from web services
|
||||||
@ -40,7 +40,6 @@ class Spawn(Thread):
|
|||||||
active(Dict[str, Process]): map of active child processes required to avoid zombies
|
active(Dict[str, Process]): map of active child processes required to avoid zombies
|
||||||
architecture(str): repository architecture
|
architecture(str): repository architecture
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
logger(logging.Logger): spawner logger
|
|
||||||
queue(Queue[Tuple[str, bool]]): multiprocessing queue to read updates from processes
|
queue(Queue[Tuple[str, bool]]): multiprocessing queue to read updates from processes
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -57,7 +56,6 @@ class Spawn(Thread):
|
|||||||
self.architecture = architecture
|
self.architecture = architecture
|
||||||
self.args_parser = args_parser
|
self.args_parser = args_parser
|
||||||
self.configuration = configuration
|
self.configuration = configuration
|
||||||
self.logger = logging.getLogger("http")
|
|
||||||
|
|
||||||
self.lock = Lock()
|
self.lock = Lock()
|
||||||
self.active: Dict[str, Process] = {}
|
self.active: Dict[str, Process] = {}
|
||||||
|
@ -17,19 +17,18 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
import logging
|
|
||||||
|
|
||||||
from typing import Dict, List, Optional, Tuple
|
from typing import Dict, List, Optional, Tuple
|
||||||
|
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.database import SQLite
|
from ahriman.core.database import SQLite
|
||||||
from ahriman.core.exceptions import UnknownPackage
|
from ahriman.core.exceptions import UnknownPackage
|
||||||
|
from ahriman.core.lazy_logging import LazyLogging
|
||||||
from ahriman.core.repository import Repository
|
from ahriman.core.repository import Repository
|
||||||
from ahriman.models.build_status import BuildStatus, BuildStatusEnum
|
from ahriman.models.build_status import BuildStatus, BuildStatusEnum
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
|
|
||||||
|
|
||||||
class Watcher:
|
class Watcher(LazyLogging):
|
||||||
"""
|
"""
|
||||||
package status watcher
|
package status watcher
|
||||||
|
|
||||||
@ -38,7 +37,6 @@ class Watcher:
|
|||||||
database(SQLite): database instance
|
database(SQLite): database instance
|
||||||
known(Dict[str, Tuple[Package, BuildStatus]]): list of known packages. For the most cases ``packages`` should
|
known(Dict[str, Tuple[Package, BuildStatus]]): list of known packages. For the most cases ``packages`` should
|
||||||
be used instead
|
be used instead
|
||||||
logger(logging.Logger): class logger
|
|
||||||
repository(Repository): repository object
|
repository(Repository): repository object
|
||||||
status(BuildStatus): daemon status
|
status(BuildStatus): daemon status
|
||||||
"""
|
"""
|
||||||
@ -52,8 +50,6 @@ class Watcher:
|
|||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
database(SQLite): database instance
|
database(SQLite): database instance
|
||||||
"""
|
"""
|
||||||
self.logger = logging.getLogger("http")
|
|
||||||
|
|
||||||
self.architecture = architecture
|
self.architecture = architecture
|
||||||
self.database = database
|
self.database = database
|
||||||
self.repository = Repository(architecture, configuration, database, no_report=True, unsafe=False)
|
self.repository = Repository(architecture, configuration, database, no_report=True, unsafe=False)
|
||||||
|
@ -17,12 +17,12 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
import logging
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from typing import List, Optional, Tuple
|
from typing import List, Optional, Tuple
|
||||||
|
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
|
from ahriman.core.lazy_logging import LazyLogging
|
||||||
from ahriman.core.status.client import Client
|
from ahriman.core.status.client import Client
|
||||||
from ahriman.core.util import exception_response_text
|
from ahriman.core.util import exception_response_text
|
||||||
from ahriman.models.build_status import BuildStatusEnum, BuildStatus
|
from ahriman.models.build_status import BuildStatusEnum, BuildStatus
|
||||||
@ -31,13 +31,12 @@ from ahriman.models.package import Package
|
|||||||
from ahriman.models.user import User
|
from ahriman.models.user import User
|
||||||
|
|
||||||
|
|
||||||
class WebClient(Client):
|
class WebClient(Client, LazyLogging):
|
||||||
"""
|
"""
|
||||||
build status reporter web client
|
build status reporter web client
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
address(str): address of the web service
|
address(str): address of the web service
|
||||||
logger(logging.Logger): class logger
|
|
||||||
user(Optional[User]): web service user descriptor
|
user(Optional[User]): web service user descriptor
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -48,7 +47,6 @@ class WebClient(Client):
|
|||||||
Args:
|
Args:
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
"""
|
"""
|
||||||
self.logger = logging.getLogger("http")
|
|
||||||
self.address = self.parse_address(configuration)
|
self.address = self.parse_address(configuration)
|
||||||
self.user = User.from_option(
|
self.user = User.from_option(
|
||||||
configuration.get("web", "username", fallback=None),
|
configuration.get("web", "username", fallback=None),
|
||||||
|
@ -17,23 +17,21 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
import logging
|
|
||||||
|
|
||||||
from typing import Iterable
|
from typing import Iterable
|
||||||
|
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
|
from ahriman.core.lazy_logging import LazyLogging
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
from ahriman.models.result import Result
|
from ahriman.models.result import Result
|
||||||
|
|
||||||
|
|
||||||
class Trigger:
|
class Trigger(LazyLogging):
|
||||||
"""
|
"""
|
||||||
trigger base class
|
trigger base class
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
architecture(str): repository architecture
|
architecture(str): repository architecture
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
logger(logging.Logger): application logger
|
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
This class must be used in order to create own extension. Basically idea is the following::
|
This class must be used in order to create own extension. Basically idea is the following::
|
||||||
@ -61,7 +59,6 @@ class Trigger:
|
|||||||
architecture(str): repository architecture
|
architecture(str): repository architecture
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
"""
|
"""
|
||||||
self.logger = logging.getLogger("root")
|
|
||||||
self.architecture = architecture
|
self.architecture = architecture
|
||||||
self.configuration = configuration
|
self.configuration = configuration
|
||||||
|
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
import importlib
|
import importlib
|
||||||
import logging
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@ -27,19 +26,19 @@ from typing import Iterable
|
|||||||
|
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.exceptions import InvalidExtension
|
from ahriman.core.exceptions import InvalidExtension
|
||||||
|
from ahriman.core.lazy_logging import LazyLogging
|
||||||
from ahriman.core.triggers import Trigger
|
from ahriman.core.triggers import Trigger
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
from ahriman.models.result import Result
|
from ahriman.models.result import Result
|
||||||
|
|
||||||
|
|
||||||
class TriggerLoader:
|
class TriggerLoader(LazyLogging):
|
||||||
"""
|
"""
|
||||||
trigger loader class
|
trigger loader class
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
architecture(str): repository architecture
|
architecture(str): repository architecture
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
logger(logging.Logger): application logger
|
|
||||||
triggers(List[Trigger]): list of loaded triggers according to the configuration
|
triggers(List[Trigger]): list of loaded triggers according to the configuration
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
@ -66,7 +65,6 @@ class TriggerLoader:
|
|||||||
architecture(str): repository architecture
|
architecture(str): repository architecture
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
"""
|
"""
|
||||||
self.logger = logging.getLogger("root")
|
|
||||||
self.architecture = architecture
|
self.architecture = architecture
|
||||||
self.configuration = configuration
|
self.configuration = configuration
|
||||||
|
|
||||||
|
@ -19,25 +19,23 @@
|
|||||||
#
|
#
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Iterable, Type
|
from typing import Iterable, Type
|
||||||
|
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.exceptions import SyncFailed
|
from ahriman.core.exceptions import SyncFailed
|
||||||
|
from ahriman.core.lazy_logging import LazyLogging
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
from ahriman.models.upload_settings import UploadSettings
|
from ahriman.models.upload_settings import UploadSettings
|
||||||
|
|
||||||
|
|
||||||
class Upload:
|
class Upload(LazyLogging):
|
||||||
"""
|
"""
|
||||||
base remote sync class
|
base remote sync class
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
architecture(str): repository architecture
|
architecture(str): repository architecture
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
logger(logging.Logger): application logger
|
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
These classes provide the way to upload packages to remote sources as it is described in their implementations.
|
These classes provide the way to upload packages to remote sources as it is described in their implementations.
|
||||||
@ -66,7 +64,6 @@ class Upload:
|
|||||||
architecture(str): repository architecture
|
architecture(str): repository architecture
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
"""
|
"""
|
||||||
self.logger = logging.getLogger("root")
|
|
||||||
self.architecture = architecture
|
self.architecture = architecture
|
||||||
self.configuration = configuration
|
self.configuration = configuration
|
||||||
|
|
||||||
|
@ -20,14 +20,13 @@
|
|||||||
import datetime
|
import datetime
|
||||||
import io
|
import io
|
||||||
import os
|
import os
|
||||||
from enum import Enum
|
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
from enum import Enum
|
||||||
from logging import Logger
|
from logging import Logger
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Dict, Generator, IO, Iterable, List, Optional, Type, Union
|
from typing import Any, Dict, Generator, IO, Iterable, List, Optional, Type, Union
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
import logging
|
|
||||||
|
|
||||||
from dataclasses import asdict, dataclass
|
from dataclasses import asdict, dataclass
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@ -31,6 +30,7 @@ from typing import Any, Dict, Iterable, List, Optional, Set, Type
|
|||||||
from ahriman.core.alpm.pacman import Pacman
|
from ahriman.core.alpm.pacman import Pacman
|
||||||
from ahriman.core.alpm.remote import AUR, Official, OfficialSyncdb
|
from ahriman.core.alpm.remote import AUR, Official, OfficialSyncdb
|
||||||
from ahriman.core.exceptions import InvalidPackageInfo
|
from ahriman.core.exceptions import InvalidPackageInfo
|
||||||
|
from ahriman.core.lazy_logging import LazyLogging
|
||||||
from ahriman.core.util import check_output, full_version
|
from ahriman.core.util import check_output, full_version
|
||||||
from ahriman.models.package_description import PackageDescription
|
from ahriman.models.package_description import PackageDescription
|
||||||
from ahriman.models.package_source import PackageSource
|
from ahriman.models.package_source import PackageSource
|
||||||
@ -39,7 +39,7 @@ from ahriman.models.repository_paths import RepositoryPaths
|
|||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Package:
|
class Package(LazyLogging):
|
||||||
"""
|
"""
|
||||||
package properties representation
|
package properties representation
|
||||||
|
|
||||||
@ -281,23 +281,22 @@ class Package:
|
|||||||
|
|
||||||
from ahriman.core.build_tools.sources import Sources
|
from ahriman.core.build_tools.sources import Sources
|
||||||
|
|
||||||
logger = logging.getLogger("build")
|
|
||||||
Sources.load(paths.cache_for(self.base), self, None, paths)
|
Sources.load(paths.cache_for(self.base), self, None, paths)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# update pkgver first
|
# update pkgver first
|
||||||
Package._check_output("makepkg", "--nodeps", "--nobuild",
|
Package._check_output("makepkg", "--nodeps", "--nobuild",
|
||||||
exception=None, cwd=paths.cache_for(self.base), logger=logger)
|
exception=None, cwd=paths.cache_for(self.base), logger=self.logger)
|
||||||
# generate new .SRCINFO and put it to parser
|
# generate new .SRCINFO and put it to parser
|
||||||
srcinfo_source = Package._check_output("makepkg", "--printsrcinfo",
|
srcinfo_source = Package._check_output("makepkg", "--printsrcinfo",
|
||||||
exception=None, cwd=paths.cache_for(self.base), logger=logger)
|
exception=None, cwd=paths.cache_for(self.base), logger=self.logger)
|
||||||
srcinfo, errors = parse_srcinfo(srcinfo_source)
|
srcinfo, errors = parse_srcinfo(srcinfo_source)
|
||||||
if errors:
|
if errors:
|
||||||
raise InvalidPackageInfo(errors)
|
raise InvalidPackageInfo(errors)
|
||||||
|
|
||||||
return full_version(srcinfo.get("epoch"), srcinfo["pkgver"], srcinfo["pkgrel"])
|
return full_version(srcinfo.get("epoch"), srcinfo["pkgver"], srcinfo["pkgrel"])
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.exception("cannot determine version of VCS package, make sure that you have VCS tools installed")
|
self.logger.exception("cannot determine version of VCS package, make sure that VCS tools are installed")
|
||||||
|
|
||||||
return self.version
|
return self.version
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ def setup_service(architecture: str, configuration: Configuration, spawner: Spaw
|
|||||||
Returns:
|
Returns:
|
||||||
web.Application: web application instance
|
web.Application: web application instance
|
||||||
"""
|
"""
|
||||||
application = web.Application(logger=logging.getLogger("http"))
|
application = web.Application(logger=logging.getLogger(__name__))
|
||||||
application.on_shutdown.append(on_shutdown)
|
application.on_shutdown.append(on_shutdown)
|
||||||
application.on_startup.append(on_startup)
|
application.on_startup.append(on_startup)
|
||||||
|
|
||||||
|
14
tests/ahriman/core/build_tools/conftest.py
Normal file
14
tests/ahriman/core/build_tools/conftest.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
from ahriman.core.build_tools.sources import Sources
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def sources() -> Sources:
|
||||||
|
"""
|
||||||
|
sources fixture
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Sources: sources instance
|
||||||
|
"""
|
||||||
|
return Sources()
|
@ -10,64 +10,6 @@ from ahriman.models.remote_source import RemoteSource
|
|||||||
from ahriman.models.repository_paths import RepositoryPaths
|
from ahriman.models.repository_paths import RepositoryPaths
|
||||||
|
|
||||||
|
|
||||||
def test_add(mocker: MockerFixture) -> None:
|
|
||||||
"""
|
|
||||||
must add files to git
|
|
||||||
"""
|
|
||||||
glob_mock = mocker.patch("pathlib.Path.glob", return_value=[Path("local/1"), Path("local/2")])
|
|
||||||
check_output_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._check_output")
|
|
||||||
|
|
||||||
local = Path("local")
|
|
||||||
Sources._add(local, "pattern1", "pattern2")
|
|
||||||
glob_mock.assert_has_calls([mock.call("pattern1"), mock.call("pattern2")])
|
|
||||||
check_output_mock.assert_called_once_with(
|
|
||||||
"git", "add", "--intent-to-add", "1", "2", "1", "2",
|
|
||||||
exception=None, cwd=local, logger=pytest.helpers.anyvar(int))
|
|
||||||
|
|
||||||
|
|
||||||
def test_add_skip(mocker: MockerFixture) -> None:
|
|
||||||
"""
|
|
||||||
must skip addition of files to index if no fiels found
|
|
||||||
"""
|
|
||||||
mocker.patch("pathlib.Path.glob", return_value=[])
|
|
||||||
check_output_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._check_output")
|
|
||||||
|
|
||||||
Sources._add(Path("local"), "pattern1")
|
|
||||||
check_output_mock.assert_not_called()
|
|
||||||
|
|
||||||
|
|
||||||
def test_diff(mocker: MockerFixture) -> None:
|
|
||||||
"""
|
|
||||||
must calculate diff
|
|
||||||
"""
|
|
||||||
check_output_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._check_output")
|
|
||||||
|
|
||||||
local = Path("local")
|
|
||||||
assert Sources._diff(local)
|
|
||||||
check_output_mock.assert_called_once_with(
|
|
||||||
"git", "diff", exception=None, cwd=local, logger=pytest.helpers.anyvar(int))
|
|
||||||
|
|
||||||
|
|
||||||
def test_move(mocker: MockerFixture) -> None:
|
|
||||||
"""
|
|
||||||
must move content between directories
|
|
||||||
"""
|
|
||||||
mocker.patch("ahriman.core.build_tools.sources.walk", return_value=[Path("/source/path")])
|
|
||||||
move_mock = mocker.patch("shutil.move")
|
|
||||||
|
|
||||||
Sources._move(Path("/source"), Path("/destination"))
|
|
||||||
move_mock.assert_called_once_with(Path("/source/path"), Path("/destination/path"))
|
|
||||||
|
|
||||||
|
|
||||||
def test_move_same(mocker: MockerFixture) -> None:
|
|
||||||
"""
|
|
||||||
must not do anything in case if directories are the same
|
|
||||||
"""
|
|
||||||
walk_mock = mocker.patch("ahriman.core.build_tools.sources.walk")
|
|
||||||
Sources._move(Path("/same"), Path("/same"))
|
|
||||||
walk_mock.assert_not_called()
|
|
||||||
|
|
||||||
|
|
||||||
def test_fetch_empty(remote_source: RemoteSource, mocker: MockerFixture) -> None:
|
def test_fetch_empty(remote_source: RemoteSource, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must do nothing in case if no branches available
|
must do nothing in case if no branches available
|
||||||
@ -87,7 +29,7 @@ def test_fetch_existing(remote_source: RemoteSource, mocker: MockerFixture) -> N
|
|||||||
mocker.patch("pathlib.Path.is_dir", return_value=True)
|
mocker.patch("pathlib.Path.is_dir", return_value=True)
|
||||||
mocker.patch("ahriman.core.build_tools.sources.Sources.has_remotes", return_value=True)
|
mocker.patch("ahriman.core.build_tools.sources.Sources.has_remotes", return_value=True)
|
||||||
check_output_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._check_output")
|
check_output_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._check_output")
|
||||||
move_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._move")
|
move_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.move")
|
||||||
|
|
||||||
local = Path("local")
|
local = Path("local")
|
||||||
Sources.fetch(local, remote_source)
|
Sources.fetch(local, remote_source)
|
||||||
@ -108,7 +50,7 @@ def test_fetch_new(remote_source: RemoteSource, mocker: MockerFixture) -> None:
|
|||||||
"""
|
"""
|
||||||
mocker.patch("pathlib.Path.is_dir", return_value=False)
|
mocker.patch("pathlib.Path.is_dir", return_value=False)
|
||||||
check_output_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._check_output")
|
check_output_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._check_output")
|
||||||
move_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._move")
|
move_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.move")
|
||||||
|
|
||||||
local = Path("local")
|
local = Path("local")
|
||||||
Sources.fetch(local, remote_source)
|
Sources.fetch(local, remote_source)
|
||||||
@ -129,7 +71,7 @@ def test_fetch_new_without_remote(mocker: MockerFixture) -> None:
|
|||||||
"""
|
"""
|
||||||
mocker.patch("pathlib.Path.is_dir", return_value=False)
|
mocker.patch("pathlib.Path.is_dir", return_value=False)
|
||||||
check_output_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._check_output")
|
check_output_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._check_output")
|
||||||
move_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._move")
|
move_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.move")
|
||||||
|
|
||||||
local = Path("local")
|
local = Path("local")
|
||||||
Sources.fetch(local, None)
|
Sources.fetch(local, None)
|
||||||
@ -147,7 +89,7 @@ def test_fetch_relative(remote_source: RemoteSource, mocker: MockerFixture) -> N
|
|||||||
must process move correctly on relative directory
|
must process move correctly on relative directory
|
||||||
"""
|
"""
|
||||||
mocker.patch("ahriman.core.build_tools.sources.Sources._check_output")
|
mocker.patch("ahriman.core.build_tools.sources.Sources._check_output")
|
||||||
move_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._move")
|
move_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.move")
|
||||||
|
|
||||||
Sources.fetch(Path("path"), remote_source)
|
Sources.fetch(Path("path"), remote_source)
|
||||||
move_mock.assert_called_once_with(Path("path").resolve(), Path("path"))
|
move_mock.assert_called_once_with(Path("path").resolve(), Path("path"))
|
||||||
@ -222,26 +164,12 @@ def test_load_with_cache(package_ahriman: Package, repository_paths: RepositoryP
|
|||||||
copytree_mock.assert_called_once() # we do not check full command here, sorry
|
copytree_mock.assert_called_once() # we do not check full command here, sorry
|
||||||
|
|
||||||
|
|
||||||
def test_patch_apply(mocker: MockerFixture) -> None:
|
|
||||||
"""
|
|
||||||
must apply patches if any
|
|
||||||
"""
|
|
||||||
check_output_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._check_output")
|
|
||||||
|
|
||||||
local = Path("local")
|
|
||||||
Sources.patch_apply(local, "patches")
|
|
||||||
check_output_mock.assert_called_once_with(
|
|
||||||
"git", "apply", "--ignore-space-change", "--ignore-whitespace",
|
|
||||||
exception=None, cwd=local, input_data="patches", logger=pytest.helpers.anyvar(int)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_patch_create(mocker: MockerFixture) -> None:
|
def test_patch_create(mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must create patch set for the package
|
must create patch set for the package
|
||||||
"""
|
"""
|
||||||
add_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._add")
|
add_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.add")
|
||||||
diff_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._diff")
|
diff_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.diff")
|
||||||
|
|
||||||
Sources.patch_create(Path("local"), "glob")
|
Sources.patch_create(Path("local"), "glob")
|
||||||
add_mock.assert_called_once_with(Path("local"), "glob")
|
add_mock.assert_called_once_with(Path("local"), "glob")
|
||||||
@ -252,6 +180,78 @@ def test_patch_create_with_newline(mocker: MockerFixture) -> None:
|
|||||||
"""
|
"""
|
||||||
created patch must have new line at the end
|
created patch must have new line at the end
|
||||||
"""
|
"""
|
||||||
mocker.patch("ahriman.core.build_tools.sources.Sources._add")
|
mocker.patch("ahriman.core.build_tools.sources.Sources.add")
|
||||||
mocker.patch("ahriman.core.build_tools.sources.Sources._diff", return_value="diff")
|
mocker.patch("ahriman.core.build_tools.sources.Sources.diff", return_value="diff")
|
||||||
assert Sources.patch_create(Path("local"), "glob").endswith("\n")
|
assert Sources.patch_create(Path("local"), "glob").endswith("\n")
|
||||||
|
|
||||||
|
|
||||||
|
def test_add(sources: Sources, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must add files to git
|
||||||
|
"""
|
||||||
|
glob_mock = mocker.patch("pathlib.Path.glob", return_value=[Path("local/1"), Path("local/2")])
|
||||||
|
check_output_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._check_output")
|
||||||
|
|
||||||
|
local = Path("local")
|
||||||
|
sources.add(local, "pattern1", "pattern2")
|
||||||
|
glob_mock.assert_has_calls([mock.call("pattern1"), mock.call("pattern2")])
|
||||||
|
check_output_mock.assert_called_once_with(
|
||||||
|
"git", "add", "--intent-to-add", "1", "2", "1", "2",
|
||||||
|
exception=None, cwd=local, logger=pytest.helpers.anyvar(int))
|
||||||
|
|
||||||
|
|
||||||
|
def test_add_skip(sources: Sources, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must skip addition of files to index if no fiels found
|
||||||
|
"""
|
||||||
|
mocker.patch("pathlib.Path.glob", return_value=[])
|
||||||
|
check_output_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._check_output")
|
||||||
|
|
||||||
|
sources.add(Path("local"), "pattern1")
|
||||||
|
check_output_mock.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
|
def test_diff(sources: Sources, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must calculate diff
|
||||||
|
"""
|
||||||
|
check_output_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._check_output")
|
||||||
|
|
||||||
|
local = Path("local")
|
||||||
|
assert sources.diff(local)
|
||||||
|
check_output_mock.assert_called_once_with(
|
||||||
|
"git", "diff", exception=None, cwd=local, logger=pytest.helpers.anyvar(int))
|
||||||
|
|
||||||
|
|
||||||
|
def test_move(sources: Sources, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must move content between directories
|
||||||
|
"""
|
||||||
|
mocker.patch("ahriman.core.build_tools.sources.walk", return_value=[Path("/source/path")])
|
||||||
|
move_mock = mocker.patch("shutil.move")
|
||||||
|
|
||||||
|
sources.move(Path("/source"), Path("/destination"))
|
||||||
|
move_mock.assert_called_once_with(Path("/source/path"), Path("/destination/path"))
|
||||||
|
|
||||||
|
|
||||||
|
def test_move_same(sources: Sources, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must not do anything in case if directories are the same
|
||||||
|
"""
|
||||||
|
walk_mock = mocker.patch("ahriman.core.build_tools.sources.walk")
|
||||||
|
sources.move(Path("/same"), Path("/same"))
|
||||||
|
walk_mock.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
|
def test_patch_apply(sources: Sources, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must apply patches if any
|
||||||
|
"""
|
||||||
|
check_output_mock = mocker.patch("ahriman.core.build_tools.sources.Sources._check_output")
|
||||||
|
|
||||||
|
local = Path("local")
|
||||||
|
sources.patch_apply(local, "patches")
|
||||||
|
check_output_mock.assert_called_once_with(
|
||||||
|
"git", "apply", "--ignore-space-change", "--ignore-whitespace",
|
||||||
|
exception=None, cwd=local, input_data="patches", logger=pytest.helpers.anyvar(int)
|
||||||
|
)
|
||||||
|
28
tests/ahriman/core/test_lazy_logging.py
Normal file
28
tests/ahriman/core/test_lazy_logging.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
from ahriman.core.alpm.repo import Repo
|
||||||
|
from ahriman.core.database import SQLite
|
||||||
|
|
||||||
|
|
||||||
|
def test_logger(database: SQLite) -> None:
|
||||||
|
"""
|
||||||
|
must set logger attribute
|
||||||
|
"""
|
||||||
|
assert database.logger
|
||||||
|
assert database.logger.name == "ahriman.core.database.sqlite.SQLite"
|
||||||
|
|
||||||
|
|
||||||
|
def test_logger_attribute_error(database: SQLite) -> None:
|
||||||
|
"""
|
||||||
|
must raise AttributeError in case if no attribute found
|
||||||
|
"""
|
||||||
|
with pytest.raises(AttributeError):
|
||||||
|
database.loggerrrr
|
||||||
|
|
||||||
|
|
||||||
|
def test_logger_name(database: SQLite, repo: Repo) -> None:
|
||||||
|
"""
|
||||||
|
must correctly generate logger name
|
||||||
|
"""
|
||||||
|
assert database.logger_name == "ahriman.core.database.sqlite.SQLite"
|
||||||
|
assert repo.logger_name == "ahriman.core.alpm.repo.Repo"
|
Loading…
Reference in New Issue
Block a user