Compare commits

..

2 Commits

Author SHA1 Message Date
1a8d3efaf1 update tests 2023-08-29 04:52:18 +03:00
6612510d12 allow to use one application for multiple repositories 2023-08-29 03:49:33 +03:00
79 changed files with 933 additions and 414 deletions

View File

@ -40,12 +40,12 @@ fi
if [ -n "$AHRIMAN_PACMAN_MIRROR" ]; then if [ -n "$AHRIMAN_PACMAN_MIRROR" ]; then
AHRIMAN_SETUP_ARGS+=("--mirror" "$AHRIMAN_PACMAN_MIRROR") AHRIMAN_SETUP_ARGS+=("--mirror" "$AHRIMAN_PACMAN_MIRROR")
fi fi
if [ -n "$AHRIMAN_PORT" ]; then
AHRIMAN_SETUP_ARGS+=("--web-port" "$AHRIMAN_PORT")
fi
if [ -n "$AHRIMAN_REPOSITORY_SERVER" ]; then if [ -n "$AHRIMAN_REPOSITORY_SERVER" ]; then
AHRIMAN_SETUP_ARGS+=("--server" "$AHRIMAN_REPOSITORY_SERVER") AHRIMAN_SETUP_ARGS+=("--server" "$AHRIMAN_REPOSITORY_SERVER")
fi fi
if [ -n "$AHRIMAN_PORT" ]; then
AHRIMAN_SETUP_ARGS+=("--web-port" "$AHRIMAN_PORT")
fi
if [ -n "$AHRIMAN_UNIX_SOCKET" ]; then if [ -n "$AHRIMAN_UNIX_SOCKET" ]; then
AHRIMAN_SETUP_ARGS+=("--web-unix-socket" "$AHRIMAN_UNIX_SOCKET") AHRIMAN_SETUP_ARGS+=("--web-unix-socket" "$AHRIMAN_UNIX_SOCKET")
fi fi

View File

@ -1,7 +1,12 @@
Configuration Configuration
============= =============
Some groups can be specified for each architecture separately. E.g. if there are ``build`` and ``build:x86_64`` groups it will use an option from ``build:x86_64`` for the ``x86_64`` architecture and ``build`` for any other (architecture specific group has higher priority). In case if both groups are presented, architecture specific options will be merged into global ones overriding them. Some groups can be specified for each architecture and/or repository separately. E.g. if there are ``build`` and ``build:x86_64`` groups it will use an option from ``build:x86_64`` for the ``x86_64`` architecture and ``build`` for any other (architecture specific group has higher priority). In case if both groups are presented, architecture specific options will be merged into global ones overriding them. The order which will be used for option resolution is the following:
1. Repository and architecture specific, e.g. ``build:aur-clone:x86_64``.
2. Repository specific, e.g. ``build:aur-clone``.
2. Architecture specific, e.g. ``build:x86_64``.
2. Default section, e.g. ``build``.
There are two variable types which have been added to default ones, they are paths and lists. List values will be read in the same way as shell does: There are two variable types which have been added to default ones, they are paths and lists. List values will be read in the same way as shell does:
@ -86,7 +91,6 @@ Build related configuration. Group name can refer to architecture, e.g. ``build:
Base repository settings. Base repository settings.
* ``name`` - repository name, string, required.
* ``root`` - root path for application, string, required. * ``root`` - root path for application, string, required.
``sign:*`` groups ``sign:*`` groups
@ -291,20 +295,21 @@ Type will be read from several sources:
``github`` type ``github`` type
^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
This feature requires Github key creation (see below). Section name must be either ``github`` (plus optional architecture name, e.g. ``github:x86_64``) or random name with ``type`` set. This feature requires GitHub key creation (see below). Section name must be either ``github`` (plus optional architecture name, e.g. ``github:x86_64``) or random name with ``type`` set.
* ``type`` - type of the upload, string, optional, must be set to ``github`` if exists. * ``type`` - type of the upload, string, optional, must be set to ``github`` if exists.
* ``owner`` - Github repository owner, string, required. * ``owner`` - GitHub repository owner, string, required.
* ``password`` - created Github API key. In order to create it do the following: * ``password`` - created GitHub API key. In order to create it do the following:
#. Go to `settings page <https://github.com/settings/profile>`_. #. Go to `settings page <https://github.com/settings/profile>`_.
#. Switch to `developers settings <https://github.com/settings/apps>`_. #. Switch to `developers settings <https://github.com/settings/apps>`_.
#. Switch to `personal access tokens <https://github.com/settings/tokens>`_. #. Switch to `personal access tokens <https://github.com/settings/tokens>`_.
#. Generate new token. Required scope is ``public_repo`` (or ``repo`` for private repository support). #. Generate new token. Required scope is ``public_repo`` (or ``repo`` for private repository support).
* ``repository`` - Github repository name, string, required. Repository must be created before any action and must have active branch (e.g. with readme). * ``repository`` - GitHub repository name, string, required. Repository must be created before any action and must have active branch (e.g. with readme).
* ``timeout`` - HTTP request timeout in seconds, int, optional, default is ``30``. * ``timeout`` - HTTP request timeout in seconds, int, optional, default is ``30``.
* ``username`` - Github authorization user, string, required. Basically the same as ``owner``. * ``use_full_release_name`` - if set to ``yes``, the release will contain both repository name and architecture, and only architecture otherwise, boolean, optional, default ``no``.
* ``username`` - GitHub authorization user, string, required. Basically the same as ``owner``.
``remote-service`` type ``remote-service`` type
^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^
@ -328,7 +333,7 @@ Requires ``rsync`` package to be installed. Do not forget to configure ssh for u
Requires ``boto3`` library to be installed. Section name must be either ``s3`` (plus optional architecture name, e.g. ``s3:x86_64``) or random name with ``type`` set. Requires ``boto3`` library to be installed. Section name must be either ``s3`` (plus optional architecture name, e.g. ``s3:x86_64``) or random name with ``type`` set.
* ``type`` - type of the upload, string, optional, must be set to ``github`` if exists. * ``type`` - type of the upload, string, optional, must be set to ``s3`` if exists.
* ``access_key`` - AWS access key ID, string, required. * ``access_key`` - AWS access key ID, string, required.
* ``bucket`` - bucket name (e.g. ``bucket``), string, required. * ``bucket`` - bucket name (e.g. ``bucket``), string, required.
* ``chunk_size`` - chunk size for calculating entity tags, int, optional, default 8 * 1024 * 1024. * ``chunk_size`` - chunk size for calculating entity tags, int, optional, default 8 * 1024 * 1024.

View File

@ -17,7 +17,7 @@ TL;DR
.. code-block:: shell .. code-block:: shell
yay -S ahriman yay -S ahriman
ahriman -a x86_64 service-setup --packager "ahriman bot <ahriman@example.com>" --repository "repository" ahriman -a x86_64 -r aur-clone service-setup --packager "ahriman bot <ahriman@example.com>"
systemctl enable --now ahriman@x86_64.timer systemctl enable --now ahriman@x86_64.timer
Long answer Long answer
@ -32,7 +32,7 @@ There is special command which can be used in order to validate current configur
.. code-block:: shell .. code-block:: shell
ahriman -a x86_64 service-config-validate --exit-code ahriman -a x86_64 -r aur-clone service-config-validate --exit-code
This command will print found errors, based on `cerberus <https://docs.python-cerberus.org/>`_, e.g.: This command will print found errors, based on `cerberus <https://docs.python-cerberus.org/>`_, e.g.:
@ -317,7 +317,7 @@ Add the following lines to your ``pacman.conf``:
.. code-block:: ini .. code-block:: ini
[repository] [repository]
Server = file:///var/lib/ahriman/repository/x86_64 Server = file:///var/lib/ahriman/repository/$repo/$arch
(You might need to add ``SigLevel`` option according to the pacman documentation.) (You might need to add ``SigLevel`` option according to the pacman documentation.)
@ -554,8 +554,8 @@ There are several choices:
.. code-block:: .. code-block::
server { server {
location /x86_64 { location /aur-clone/x86_64 {
root /var/lib/ahriman/repository/x86_64; root /var/lib/ahriman/repository/aur-clone/x86_64;
autoindex on; autoindex on;
} }
} }
@ -571,7 +571,7 @@ There are several choices:
[rsync] [rsync]
remote = 192.168.0.1:/srv/repo remote = 192.168.0.1:/srv/repo
After that just add ``/srv/repo`` to the ``pacman.conf`` as usual. You can also upload to S3 (e.g. ``Server = https://s3.eu-central-1.amazonaws.com/repository/x86_64``) or to Github (e.g. ``Server = https://github.com/ahriman/repository/releases/download/x86_64``). After that just add ``/srv/repo`` to the ``pacman.conf`` as usual. You can also upload to S3 (e.g. ``Server = https://s3.eu-central-1.amazonaws.com/repository/aur-clone/x86_64``) or to Github (e.g. ``Server = https://github.com/ahriman/repository/releases/download/aur-clone-x86_64``).
How to sync to S3 How to sync to S3
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
@ -676,7 +676,7 @@ How to report by email
[email] [email]
host = smtp.example.com host = smtp.example.com
link_path = http://example.com/x86_64 link_path = http://example.com/aur-clone/x86_64
password = ... password = ...
port = 465 port = 465
receivers = me@example.com receivers = me@example.com
@ -702,8 +702,8 @@ How to generate index page for S3
target = html target = html
[html] [html]
path = /var/lib/ahriman/repository/x86_64/index.html path = /var/lib/ahriman/repository/aur-clone/x86_64/index.html
link_path = http://example.com/x86_64 link_path = http://example.com/aur-clone/x86_64
After these steps ``index.html`` file will be automatically synced to S3 After these steps ``index.html`` file will be automatically synced to S3
@ -741,7 +741,7 @@ How to post build report to telegram
[telegram] [telegram]
api_key = aaAAbbBBccCC api_key = aaAAbbBBccCC
chat_id = @ahriman chat_id = @ahriman
link_path = http://example.com/x86_64 link_path = http://example.com/aur-clone/x86_64
``api_key`` is the one sent by `@BotFather <https://t.me/botfather>`_, ``chat_id`` is the value retrieved from previous step. ``api_key`` is the one sent by `@BotFather <https://t.me/botfather>`_, ``chat_id`` is the value retrieved from previous step.

View File

@ -10,7 +10,7 @@ Initial setup
.. code-block:: shell .. code-block:: shell
sudo ahriman -a x86_64 service-setup ... sudo ahriman -a x86_64 -r aur-clone service-setup ...
``service-setup`` literally does the following steps: ``service-setup`` literally does the following steps:
@ -29,26 +29,26 @@ Initial setup
.. code-block:: shell .. code-block:: shell
ln -s /usr/bin/archbuild /usr/local/bin/ahriman-x86_64-build ln -s /usr/bin/archbuild /usr/local/bin/aur-clone-x86_64-build
#. #.
Create configuration file (same as previous ``{name}.conf``): Create configuration file (same as previous ``{name}.conf``):
.. code-block:: shell .. code-block:: shell
cp /usr/share/devtools/pacman.conf.d/{extra,ahriman}.conf cp /usr/share/devtools/pacman.conf.d/{extra,aur-clone}.conf
#. #.
Change configuration file, add your own repository, add multilib repository etc: Change configuration file, add your own repository, add multilib repository etc:
.. code-block:: shell .. code-block:: shell
echo '[multilib]' | tee -a /usr/share/devtools/pacman-ahriman.conf echo '[multilib]' | tee -a /usr/share/devtools/pacman.conf.d/aur-clone-x86_64.conf
echo 'Include = /etc/pacman.d/mirrorlist' | tee -a /usr/share/devtools/pacman.conf.d/ahriman.conf echo 'Include = /etc/pacman.d/mirrorlist' | tee -a /usr/share/devtools/pacman.conf.d/aur-clone-x86_64.conf
echo '[aur-clone]' | tee -a /usr/share/devtools/pacman-ahriman.conf echo '[aur-clone]' | tee -a /usr/share/devtools/pacman.conf.d/aur-clone-x86_64.conf
echo 'SigLevel = Optional TrustAll' | tee -a /usr/share/devtools/pacman.conf.d/ahriman.conf echo 'SigLevel = Optional TrustAll' | tee -a /usr/share/devtools/pacman.conf.d/aur-clone-x86_64.conf
echo 'Server = file:///var/lib/ahriman/repository/$arch' | tee -a /usr/share/devtools/pacman.conf.d/ahriman.conf echo 'Server = file:///var/lib/ahriman/repository/$repo/$arch' | tee -a /usr/share/devtools/pacman.conf.d/aur-clone-x86_64.conf
#. #.
Set ``build_command`` option to point to your command: Set ``build_command`` option to point to your command:
@ -56,14 +56,14 @@ Initial setup
.. code-block:: shell .. code-block:: shell
echo '[build]' | tee -a /etc/ahriman.ini.d/build.ini echo '[build]' | tee -a /etc/ahriman.ini.d/build.ini
echo 'build_command = ahriman-x86_64-build' | tee -a /etc/ahriman.ini.d/build.ini echo 'build_command = aur-clone-x86_64-build' | tee -a /etc/ahriman.ini.d/build.ini
#. #.
Configure ``/etc/sudoers.d/ahriman`` to allow running command without a password: Configure ``/etc/sudoers.d/ahriman`` to allow running command without a password:
.. code-block:: shell .. code-block:: shell
echo 'Cmnd_Alias CARCHBUILD_CMD = /usr/local/bin/ahriman-x86_64-build *' | tee -a /etc/sudoers.d/ahriman echo 'Cmnd_Alias CARCHBUILD_CMD = /usr/local/bin/aur-clone-x86_64-build *' | tee -a /etc/sudoers.d/ahriman
echo 'ahriman ALL=(ALL) NOPASSWD:SETENV: CARCHBUILD_CMD' | tee -a /etc/sudoers.d/ahriman echo 'ahriman ALL=(ALL) NOPASSWD:SETENV: CARCHBUILD_CMD' | tee -a /etc/sudoers.d/ahriman
chmod 400 /etc/sudoers.d/ahriman chmod 400 /etc/sudoers.d/ahriman
@ -88,6 +88,6 @@ Initial setup
.. code-block:: shell .. code-block:: shell
sudo -u ahriman ahriman -a x86_64 package-add ahriman --now --refresh sudo -u ahriman ahriman package-add ahriman --now --refresh
The ``--refresh`` flag is required in order to handle local database update. The ``--refresh`` flag is required in order to handle local database update.

View File

@ -20,7 +20,6 @@ allow_read_only = yes
[build] [build]
archbuild_flags = archbuild_flags =
build_command = extra-x86_64-build
ignore_packages = ignore_packages =
makechrootpkg_flags = makechrootpkg_flags =
makepkg_flags = --nocolor --ignorearch makepkg_flags = --nocolor --ignorearch
@ -29,7 +28,6 @@ triggers_known = ahriman.core.gitremote.RemotePullTrigger ahriman.core.gitremote
vcs_allowed_age = 604800 vcs_allowed_age = 604800
[repository] [repository]
name = aur-clone
root = /var/lib/ahriman root = /var/lib/ahriman
[sign] [sign]

View File

@ -81,7 +81,7 @@ def _parser() -> argparse.ArgumentParser:
type=LogHandler, choices=enum_values(LogHandler)) type=LogHandler, choices=enum_values(LogHandler))
parser.add_argument("--report", help="force enable or disable reporting to web service", parser.add_argument("--report", help="force enable or disable reporting to web service",
action=argparse.BooleanOptionalAction, default=True) action=argparse.BooleanOptionalAction, default=True)
parser.add_argument("-R", "--repository", help="target repository. For several subcommands it can be used " parser.add_argument("-r", "--repository", help="target repository. For several subcommands it can be used "
"multiple times", action="append") "multiple times", action="append")
parser.add_argument("-q", "--quiet", help="force disable any logging", action="store_true") parser.add_argument("-q", "--quiet", help="force disable any logging", action="store_true")
parser.add_argument("--unsafe", help="allow to run ahriman as non-ahriman user. Some actions might be unavailable", parser.add_argument("--unsafe", help="allow to run ahriman as non-ahriman user. Some actions might be unavailable",
@ -943,7 +943,7 @@ def _set_user_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
"`Name Surname <mail@example.com>`") "`Name Surname <mail@example.com>`")
parser.add_argument("-p", "--password", help="user password. Blank password will be treated as empty password, " parser.add_argument("-p", "--password", help="user password. Blank password will be treated as empty password, "
"which is in particular must be used for OAuth2 authorization type.") "which is in particular must be used for OAuth2 authorization type.")
parser.add_argument("-r", "--role", help="user access level", parser.add_argument("-R", "--role", help="user access level",
type=UserAccess, choices=enum_values(UserAccess), default=UserAccess.Read) type=UserAccess, choices=enum_values(UserAccess), default=UserAccess.Read)
parser.set_defaults(handler=handlers.Users, action=Action.Update, architecture=[""], lock=None, report=False, parser.set_defaults(handler=handlers.Users, action=Action.Update, architecture=[""], lock=None, report=False,
quiet=True) quiet=True)
@ -965,7 +965,7 @@ def _set_user_list_parser(root: SubParserAction) -> argparse.ArgumentParser:
formatter_class=_formatter) formatter_class=_formatter)
parser.add_argument("username", help="filter users by username", nargs="?") parser.add_argument("username", help="filter users by username", nargs="?")
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty", action="store_true") parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty", action="store_true")
parser.add_argument("-r", "--role", help="filter users by role", type=UserAccess, choices=enum_values(UserAccess)) parser.add_argument("-R", "--role", help="filter users by role", type=UserAccess, choices=enum_values(UserAccess))
parser.set_defaults(handler=handlers.Users, action=Action.List, architecture=[""], lock=None, report=False, parser.set_defaults(handler=handlers.Users, action=Action.List, architecture=[""], lock=None, report=False,
quiet=True, unsafe=True) quiet=True, unsafe=True)
return parser return parser

View File

@ -40,7 +40,7 @@ class Application(ApplicationPackages, ApplicationRepository):
>>> from ahriman.models.repository_id import RepositoryId >>> from ahriman.models.repository_id import RepositoryId
>>> >>>
>>> configuration = Configuration() >>> configuration = Configuration()
>>> application = Application(RepositoryId("x86_64", None), configuration, report=True) >>> application = Application(RepositoryId("x86_64", "x86_64"), configuration, report=True)
>>> # add packages to build queue >>> # add packages to build queue
>>> application.add(["ahriman"], PackageSource.AUR) >>> application.add(["ahriman"], PackageSource.AUR)
>>> >>>

View File

@ -25,7 +25,7 @@ from multiprocessing import Pool
from ahriman.application.lock import Lock from ahriman.application.lock import Lock
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.exceptions import ExitCode, MissingArchitectureError, MultipleArchitecturesError from ahriman.core.exceptions import ExitCode, MissingArchitectureError, MultipleArchitecturesError
from ahriman.core.log import Log from ahriman.core.log.log_loader import LogLoader
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId
from ahriman.models.repository_paths import RepositoryPaths from ahriman.models.repository_paths import RepositoryPaths
@ -65,8 +65,8 @@ class Handler:
try: try:
configuration = Configuration.from_path(args.configuration, repository_id) configuration = Configuration.from_path(args.configuration, repository_id)
log_handler = Log.handler(args.log_handler) log_handler = LogLoader.handler(args.log_handler)
Log.load(configuration, log_handler, quiet=args.quiet, report=args.report) LogLoader.load(configuration, log_handler, quiet=args.quiet, report=args.report)
with Lock(args, repository_id, configuration): with Lock(args, repository_id, configuration):
cls.run(args, repository_id, configuration, report=args.report) cls.run(args, repository_id, configuration, report=args.report)
@ -116,7 +116,7 @@ class Handler:
args(argparse.Namespace): command line args args(argparse.Namespace): command line args
Returns: Returns:
tuple[str | None, str]: list of repository names and architectures for which tree is created list[RepositoryId]: list of repository names and architectures for which tree is created
Raises: Raises:
MissingArchitectureError: if no architecture set and automatic detection is not allowed or failed MissingArchitectureError: if no architecture set and automatic detection is not allowed or failed
@ -125,8 +125,13 @@ class Handler:
# for some parsers (e.g. config) we need to run with specific architecture # for some parsers (e.g. config) we need to run with specific architecture
# for those cases architecture must be set explicitly # for those cases architecture must be set explicitly
raise MissingArchitectureError(args.command) raise MissingArchitectureError(args.command)
configuration = Configuration()
configuration.load(args.configuration)
name = configuration.get("repository", "name", fallback="") # will only be used for legacy mode
if args.architecture: # architecture is specified explicitly if args.architecture: # architecture is specified explicitly
repositories = args.repository or [None] # fallback for legacy mode repositories = args.repository or [name] # fallback for legacy mode
return sorted( return sorted(
set( set(
RepositoryId(architecture, repository) RepositoryId(architecture, repository)
@ -135,11 +140,8 @@ class Handler:
) )
) )
configuration = Configuration()
configuration.load(args.configuration)
# wtf??? # wtf???
root = configuration.getpath("repository", "root") # pylint: disable=assignment-from-no-return root = configuration.getpath("repository", "root") # pylint: disable=assignment-from-no-return
name = configuration.get("repository", "name", fallback="") # will only be used for legacy mode
architectures = RepositoryPaths.known_architectures(root, name) architectures = RepositoryPaths.known_architectures(root, name)
if not architectures: # well we did not find anything if not architectures: # well we did not find anything

View File

@ -66,8 +66,8 @@ class Setup(Handler):
Setup.configuration_create_makepkg(args.packager, args.makeflags_jobs, application.repository.paths) Setup.configuration_create_makepkg(args.packager, args.makeflags_jobs, application.repository.paths)
Setup.executable_create(application.repository.paths, repository_id) Setup.executable_create(application.repository.paths, repository_id)
repository_server = f"file://{application.repository.paths.repository}" if args.server is None else args.server repository_server = f"file://{application.repository.paths.repository}" if args.server is None else args.server
Setup.configuration_create_devtools(repository_id, args.from_configuration, args.mirror, args.multilib, Setup.configuration_create_devtools(
repository_server) repository_id, args.from_configuration, args.mirror, args.multilib, repository_server)
Setup.configuration_create_sudo(application.repository.paths, repository_id) Setup.configuration_create_sudo(application.repository.paths, repository_id)
application.repository.repo.init() application.repository.repo.init()
@ -89,10 +89,8 @@ class Setup(Handler):
return root / f"{repository_id.name}-{repository_id.architecture}-build" return root / f"{repository_id.name}-{repository_id.architecture}-build"
@staticmethod @staticmethod
def configuration_create_ahriman( def configuration_create_ahriman(args: argparse.Namespace, repository_id: RepositoryId,
args: argparse.Namespace, root: Configuration) -> None:
repository_id: RepositoryId,
root: Configuration) -> None:
""" """
create service specific configuration create service specific configuration
@ -106,7 +104,7 @@ class Setup(Handler):
section = Configuration.section_name("build", repository_id.name, repository_id.architecture) section = Configuration.section_name("build", repository_id.name, repository_id.architecture)
build_command = Setup.build_command(root.repository_paths.root, repository_id) build_command = Setup.build_command(root.repository_paths.root, repository_id)
configuration.set_option(section, "build_command", str(build_command)) configuration.set_option(section, "build_command", str(build_command))
configuration.set_option("repository", "name", repository_id.name) configuration.set_option("repository", "name", repository_id.name) # backward compatibility for docker
if args.build_as_user is not None: if args.build_as_user is not None:
configuration.set_option(section, "makechrootpkg_flags", f"-U {args.build_as_user}") configuration.set_option(section, "makechrootpkg_flags", f"-U {args.build_as_user}")

View File

@ -77,8 +77,7 @@ class Web(Handler):
""" """
# read architecture from the same argument list # read architecture from the same argument list
yield from ["--architecture", repository_id.architecture] yield from ["--architecture", repository_id.architecture]
if repository_id.name is not None: yield from ["--repository", repository_id.name]
yield from ["--repository", repository_id.name]
# read configuration path from current settings # read configuration path from current settings
if (configuration_path := configuration.path) is not None: if (configuration_path := configuration.path) is not None:
yield from ["--configuration", str(configuration_path)] yield from ["--configuration", str(configuration_path)]

View File

@ -55,7 +55,7 @@ class Lock(LazyLogging):
>>> >>>
>>> configuration = Configuration() >>> configuration = Configuration()
>>> try: >>> try:
>>> with Lock(args, RepositoryId("x86_64", None), configuration): >>> with Lock(args, RepositoryId("x86_64", "aur-clone"), configuration):
>>> perform_actions() >>> perform_actions()
>>> except Exception as exception: >>> except Exception as exception:
>>> handle_exceptions(exception) >>> handle_exceptions(exception)

View File

@ -50,7 +50,7 @@ class Configuration(configparser.RawConfigParser):
>>> from pathlib import Path >>> from pathlib import Path
>>> >>>
>>> configuration = Configuration.from_path(Path("/etc/ahriman.ini"), RepositoryId("x86_64", None)) >>> configuration = Configuration.from_path(Path("/etc/ahriman.ini"), RepositoryId("x86_64", "aur-clone"))
>>> repository_name = configuration.get("repository", "name") >>> repository_name = configuration.get("repository", "name")
>>> makepkg_flags = configuration.getlist("build", "makepkg_flags") >>> makepkg_flags = configuration.getlist("build", "makepkg_flags")
@ -109,6 +109,17 @@ class Configuration(configparser.RawConfigParser):
""" """
return self.getpath("settings", "logging") return self.getpath("settings", "logging")
@property
def repository_name(self) -> str:
"""
repository name for backward compatibility
Returns:
str: repository name
"""
_, repository_id = self.check_loaded()
return repository_id.name
@property @property
def repository_paths(self) -> RepositoryPaths: def repository_paths(self) -> RepositoryPaths:
""" """

View File

@ -183,7 +183,6 @@ CONFIGURATION_SCHEMA: ConfigurationSchema = {
"schema": { "schema": {
"name": { "name": {
"type": "string", "type": "string",
"required": True,
}, },
"root": { "root": {
"type": "string", "type": "string",

View File

@ -71,7 +71,18 @@ def migrate_package_remotes(connection: Connection, paths: RepositoryPaths) -> N
paths(RepositoryPaths): repository paths instance paths(RepositoryPaths): repository paths instance
""" """
from ahriman.core.alpm.remote import AUR from ahriman.core.alpm.remote import AUR
from ahriman.core.database.operations import PackageOperations from ahriman.models.package import Package
def get_packages() -> dict[str, Package]:
return {
row["package_base"]: Package(
base=row["package_base"],
version=row["version"],
remote=RemoteSource.from_json(row),
packages={},
packager=row["packager"] or None,
) for row in connection.execute("""select * from package_bases""")
}
def insert_remote(base: str, remote: RemoteSource) -> None: def insert_remote(base: str, remote: RemoteSource) -> None:
connection.execute( connection.execute(
@ -88,8 +99,7 @@ def migrate_package_remotes(connection: Connection, paths: RepositoryPaths) -> N
} }
) )
packages = PackageOperations._packages_get_select_package_bases(connection) for package_base, package in get_packages().items():
for package_base, package in packages.items():
local_cache = paths.cache_for(package_base) local_cache = paths.cache_for(package_base)
if local_cache.exists() and not package.is_vcs: if local_cache.exists() and not package.is_vcs:
continue # skip packages which are not VCS and with local cache continue # skip packages which are not VCS and with local cache

View File

@ -45,9 +45,9 @@ steps = [
) )
""", """,
""" """
insert into packages select * from packages_ where architecture is not null; insert into packages select * from packages_ where architecture is not null
""", """,
""" """
drop table packages_; drop table packages_
""", """,
] ]

View File

@ -0,0 +1,245 @@
#
# Copyright (c) 2021-2023 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/>.
#
from sqlite3 import Connection
from ahriman.core.configuration import Configuration
__all__ = ["migrate_data", "steps"]
steps = [
# set correct types for schema
"""
alter table users rename to users_
""",
"""
create table users (
username text not null unique,
access text not null,
password text,
packager_id text,
key_id text
)
""",
"""
insert into users select * from users_
""",
"""
drop table users_
""",
# update base tables
# build_queue
"""
alter table build_queue add column repository text not null default ''
""",
"""
alter table build_queue rename to build_queue_
""",
"""
create table build_queue (
package_base text not null,
properties json not null,
repository text not null,
primary key (package_base, repository)
)
""",
"""
insert into build_queue select * from build_queue_
""",
"""
drop table build_queue_
""",
# package_bases
"""
alter table package_bases add column repository text not null default ''
""",
"""
alter table package_bases rename to package_bases_
""",
"""
create table package_bases (
package_base text not null,
version text not null,
branch text,
git_url text,
path text,
web_url text,
source text,
packager text,
repository text not null,
primary key (package_base, repository)
)
""",
"""
insert into package_bases select * from package_bases_
""",
"""
drop table package_bases_
""",
# package_statuses
"""
alter table package_statuses add column repository text not null default ''
""",
"""
alter table package_statuses rename to package_statuses_
""",
"""
create table package_statuses (
package_base text not null,
status text not null,
last_updated integer,
repository text not null,
primary key (package_base, repository)
)
""",
"""
insert into package_statuses select * from package_statuses_
""",
"""
drop table package_statuses_
""",
# packages
"""
alter table packages add column repository text not null default ''
""",
"""
alter table packages rename to packages_
""",
"""
create table packages (
package text not null,
package_base text not null,
architecture text not null,
archive_size integer,
build_date integer,
depends json,
description text,
filename text,
"groups" json,
installed_size integer,
licenses json,
provides json,
url text,
make_depends json,
opt_depends json,
check_depends json,
repository text not null,
primary key (package, architecture, repository)
)
""",
"""
insert into packages select * from packages_
""",
"""
drop table packages_
""",
# patches
"""
alter table patches add column repository text not null default ''
""",
"""
drop index patches_package_base_variable
""",
"""
alter table patches rename to patches_
""",
"""
create table patches (
package_base text not null,
variable text,
patch blob not null,
repository text not null
)
""",
"""
create unique index patches_package_base_variable_repository
on patches (package_base, coalesce(variable, ''), repository)
""",
"""
insert into patches select * from patches_
""",
"""
drop table patches_
""",
# logs
"""
alter table logs add column repository text not null default ''
""",
"""
drop index logs_package_base_version
""",
"""
alter table logs rename to logs_
""",
"""
create table logs (
package_base text not null,
created real not null,
record text,
version text not null,
repository text not null
)
""",
"""
insert into logs select * from logs_
""",
"""
create index logs_package_base_version on logs (package_base, version)
""",
"""
drop table logs_
""",
]
def migrate_data(connection: Connection, configuration: Configuration) -> None:
"""
perform data migration
Args:
connection(Connection): database connection
configuration(Configuration): configuration instance
"""
migrate_package_repository(connection, configuration)
def migrate_package_repository(connection: Connection, configuration: Configuration) -> None:
"""
update repository name from current settings
Args:
connection(Connection): database connection
configuration(Configuration): configuration instance
"""
_, repository_id = configuration.check_loaded()
connection.execute("""update build_queue set repository = :repository""",
{"repository": repository_id.name, })
connection.execute("""update package_bases set repository = :repository""",
{"repository": repository_id.name, })
connection.execute("""update package_statuses set repository = :repository""",
{"repository": repository_id.name, })
connection.execute("""update packages set repository = :repository""",
{"repository": repository_id.name, })
connection.execute("""update patches set repository = :repository""",
{"repository": repository_id.name, })
connection.execute("""update logs set repository = :repository""",
{"repository": repository_id.name, })

View File

@ -39,9 +39,9 @@ class BuildOperations(Operations):
connection.execute( connection.execute(
""" """
delete from build_queue delete from build_queue
where :package_base is null or package_base = :package_base where (:package_base is null or package_base = :package_base) and repository = :repository
""", """,
{"package_base": package_base}) {"package_base": package_base, "repository": self.repository_id.name})
return self.with_connection(run, commit=True) return self.with_connection(run, commit=True)
@ -55,7 +55,10 @@ class BuildOperations(Operations):
def run(connection: Connection) -> list[Package]: def run(connection: Connection) -> list[Package]:
return [ return [
Package.from_json(row["properties"]) Package.from_json(row["properties"])
for row in connection.execute("""select * from build_queue""") for row in connection.execute(
"""select properties from build_queue where repository = :repository""",
{"repository": self.repository_id.name}
)
] ]
return self.with_connection(run) return self.with_connection(run)
@ -71,12 +74,12 @@ class BuildOperations(Operations):
connection.execute( connection.execute(
""" """
insert into build_queue insert into build_queue
(package_base, properties) (package_base, properties, repository)
values values
(:package_base, :properties) (:package_base, :properties, :repository)
on conflict (package_base) do update set on conflict (package_base, repository) do update set
properties = :properties properties = :properties
""", """,
{"package_base": package.base, "properties": package.view()}) {"package_base": package.base, "properties": package.view(), "repository": self.repository_id.name})
return self.with_connection(run, commit=True) return self.with_connection(run, commit=True)

View File

@ -44,10 +44,11 @@ class LogsOperations(Operations):
f"""[{pretty_datetime(row["created"])}] {row["record"]}""" f"""[{pretty_datetime(row["created"])}] {row["record"]}"""
for row in connection.execute( for row in connection.execute(
""" """
select created, record from logs where package_base = :package_base select created, record from logs
where package_base = :package_base and repository = :repository
order by created order by created
""", """,
{"package_base": package_base}) {"package_base": package_base, "repository": self.repository_id.name})
] ]
records = self.with_connection(run) records = self.with_connection(run)
@ -66,15 +67,16 @@ class LogsOperations(Operations):
connection.execute( connection.execute(
""" """
insert into logs insert into logs
(package_base, version, created, record) (package_base, version, created, record, repository)
values values
(:package_base, :version, :created, :record) (:package_base, :version, :created, :record, :repository)
""", """,
{ {
"package_base": log_record_id.package_base, "package_base": log_record_id.package_base,
"version": log_record_id.version, "version": log_record_id.version,
"created": created, "created": created,
"record": record, "record": record,
"repository": self.repository_id.name,
} }
) )
@ -93,9 +95,10 @@ class LogsOperations(Operations):
connection.execute( connection.execute(
""" """
delete from logs delete from logs
where package_base = :package_base and (:version is null or version <> :version) where package_base = :package_base and repository = :repository
and (:version is null or version <> :version)
""", """,
{"package_base": package_base, "version": version} {"package_base": package_base, "version": version, "repository": self.repository_id.name}
) )
return self.with_connection(run, commit=True) return self.with_connection(run, commit=True)

View File

@ -24,6 +24,7 @@ from pathlib import Path
from typing import Any, TypeVar from typing import Any, TypeVar
from ahriman.core.log import LazyLogging from ahriman.core.log import LazyLogging
from ahriman.models.repository_id import RepositoryId
T = TypeVar("T") T = TypeVar("T")
@ -35,16 +36,19 @@ class Operations(LazyLogging):
Attributes: Attributes:
path(Path): path to the database file path(Path): path to the database file
repository_id(RepositoryId): repository unique identifier to perform implicit filtering
""" """
def __init__(self, path: Path) -> None: def __init__(self, path: Path, repository_id: RepositoryId) -> None:
""" """
default constructor default constructor
Args: Args:
path(Path): path to the database file path(Path): path to the database file
repository_id(RepositoryId): repository unique identifier
""" """
self.path = path self.path = path
self.repository_id = repository_id
@staticmethod @staticmethod
def factory(cursor: sqlite3.Cursor, row: tuple[Any, ...]) -> dict[str, Any]: def factory(cursor: sqlite3.Cursor, row: tuple[Any, ...]) -> dict[str, Any]:

View File

@ -32,8 +32,7 @@ class PackageOperations(Operations):
package operations package operations
""" """
@staticmethod def _package_remove_package_base(self, connection: Connection, package_base: str) -> None:
def _package_remove_package_base(connection: Connection, package_base: str) -> None:
""" """
remove package base information remove package base information
@ -41,13 +40,20 @@ class PackageOperations(Operations):
connection(Connection): database connection connection(Connection): database connection
package_base(str): package base name package_base(str): package base name
""" """
connection.execute("""delete from package_statuses where package_base = :package_base""", connection.execute(
{"package_base": package_base}) """
connection.execute("""delete from package_bases where package_base = :package_base""", delete from package_statuses
{"package_base": package_base}) where package_base = :package_base and repository = :repository
""",
{"package_base": package_base, "repository": self.repository_id.name})
connection.execute(
"""
delete from package_bases
where package_base = :package_base and repository = :repository""",
{"package_base": package_base, "repository": self.repository_id.name})
@staticmethod def _package_remove_packages(self, connection: Connection, package_base: str,
def _package_remove_packages(connection: Connection, package_base: str, current_packages: Iterable[str]) -> None: current_packages: Iterable[str]) -> None:
""" """
remove packages belong to the package base remove packages belong to the package base
@ -59,13 +65,20 @@ class PackageOperations(Operations):
packages = [ packages = [
package package
for package in connection.execute( for package in connection.execute(
"""select package from packages where package_base = :package_base""", {"package_base": package_base}) """
select package, repository from packages
where package_base = :package_base and repository = :repository""",
{"package_base": package_base, "repository": self.repository_id.name})
if package["package"] not in current_packages if package["package"] not in current_packages
] ]
connection.executemany("""delete from packages where package = :package""", packages) connection.executemany(
"""
delete from packages
where package = :package and repository = :repository
""",
packages)
@staticmethod def _package_update_insert_base(self, connection: Connection, package: Package) -> None:
def _package_update_insert_base(connection: Connection, package: Package) -> None:
""" """
insert base package into table insert base package into table
@ -76,10 +89,10 @@ class PackageOperations(Operations):
connection.execute( connection.execute(
""" """
insert into package_bases insert into package_bases
(package_base, version, source, branch, git_url, path, web_url, packager) (package_base, version, source, branch, git_url, path, web_url, packager, repository)
values values
(:package_base, :version, :source, :branch, :git_url, :path, :web_url, :packager) (:package_base, :version, :source, :branch, :git_url, :path, :web_url, :packager, :repository)
on conflict (package_base) do update set on conflict (package_base, repository) do update set
version = :version, branch = :branch, git_url = :git_url, path = :path, web_url = :web_url, version = :version, branch = :branch, git_url = :git_url, path = :path, web_url = :web_url,
source = :source, packager = :packager source = :source, packager = :packager
""", """,
@ -92,11 +105,11 @@ class PackageOperations(Operations):
"web_url": package.remote.web_url, "web_url": package.remote.web_url,
"source": package.remote.source.value, "source": package.remote.source.value,
"packager": package.packager, "packager": package.packager,
"repository": self.repository_id.name,
} }
) )
@staticmethod def _package_update_insert_packages(self, connection: Connection, package: Package) -> None:
def _package_update_insert_packages(connection: Connection, package: Package) -> None:
""" """
insert packages into table insert packages into table
@ -108,20 +121,27 @@ class PackageOperations(Operations):
for name, description in package.packages.items(): for name, description in package.packages.items():
if description.architecture is None: if description.architecture is None:
continue # architecture is required continue # architecture is required
package_list.append({"package": name, "package_base": package.base, **description.view()}) package_list.append({
"package": name,
"package_base": package.base,
"repository": self.repository_id.name,
**description.view(),
})
connection.executemany( connection.executemany(
""" """
insert into packages insert into packages
(package, package_base, architecture, archive_size, (package, package_base, architecture, archive_size,
build_date, depends, description, filename, build_date, depends, description, filename,
"groups", installed_size, licenses, provides, "groups", installed_size, licenses, provides,
url, make_depends, opt_depends, check_depends) url, make_depends, opt_depends, check_depends,
repository)
values values
(:package, :package_base, :architecture, :archive_size, (:package, :package_base, :architecture, :archive_size,
:build_date, :depends, :description, :filename, :build_date, :depends, :description, :filename,
:groups, :installed_size, :licenses, :provides, :groups, :installed_size, :licenses, :provides,
:url, :make_depends, :opt_depends, :check_depends) :url, :make_depends, :opt_depends, :check_depends,
on conflict (package, architecture) do update set :repository)
on conflict (package, architecture, repository) do update set
package_base = :package_base, archive_size = :archive_size, package_base = :package_base, archive_size = :archive_size,
build_date = :build_date, depends = :depends, description = :description, filename = :filename, build_date = :build_date, depends = :depends, description = :description, filename = :filename,
"groups" = :groups, installed_size = :installed_size, licenses = :licenses, provides = :provides, "groups" = :groups, installed_size = :installed_size, licenses = :licenses, provides = :provides,
@ -129,8 +149,7 @@ class PackageOperations(Operations):
""", """,
package_list) package_list)
@staticmethod def _package_update_insert_status(self, connection: Connection, package_base: str, status: BuildStatus) -> None:
def _package_update_insert_status(connection: Connection, package_base: str, status: BuildStatus) -> None:
""" """
insert base package status into table insert base package status into table
@ -141,16 +160,21 @@ class PackageOperations(Operations):
""" """
connection.execute( connection.execute(
""" """
insert into package_statuses (package_base, status, last_updated) insert into package_statuses
(package_base, status, last_updated, repository)
values values
(:package_base, :status, :last_updated) (:package_base, :status, :last_updated, :repository)
on conflict (package_base) do update set on conflict (package_base, repository) do update set
status = :status, last_updated = :last_updated status = :status, last_updated = :last_updated
""", """,
{"package_base": package_base, "status": status.status.value, "last_updated": status.timestamp}) {
"package_base": package_base,
"status": status.status.value,
"last_updated": status.timestamp,
"repository": self.repository_id.name,
})
@staticmethod def _packages_get_select_package_bases(self, connection: Connection) -> dict[str, Package]:
def _packages_get_select_package_bases(connection: Connection) -> dict[str, Package]:
""" """
select package bases from the table select package bases from the table
@ -167,11 +191,13 @@ class PackageOperations(Operations):
remote=RemoteSource.from_json(row), remote=RemoteSource.from_json(row),
packages={}, packages={},
packager=row["packager"] or None, packager=row["packager"] or None,
) for row in connection.execute("""select * from package_bases""") ) for row in connection.execute(
"""select * from package_bases where repository = :repository""",
{"repository": self.repository_id.name}
)
} }
@staticmethod def _packages_get_select_packages(self, connection: Connection, packages: dict[str, Package]) -> dict[str, Package]:
def _packages_get_select_packages(connection: Connection, packages: dict[str, Package]) -> dict[str, Package]:
""" """
select packages from the table select packages from the table
@ -182,14 +208,15 @@ class PackageOperations(Operations):
Returns: Returns:
dict[str, Package]: map of the package base to its descriptor including individual packages dict[str, Package]: map of the package base to its descriptor including individual packages
""" """
for row in connection.execute("""select * from packages"""): for row in connection.execute(
"""select * from packages where repository = :repository""",
{"repository": self.repository_id.name}):
if row["package_base"] not in packages: if row["package_base"] not in packages:
continue # normally must never happen though continue # normally must never happen though
packages[row["package_base"]].packages[row["package"]] = PackageDescription.from_json(row) packages[row["package_base"]].packages[row["package"]] = PackageDescription.from_json(row)
return packages return packages
@staticmethod def _packages_get_select_statuses(self, connection: Connection) -> dict[str, BuildStatus]:
def _packages_get_select_statuses(connection: Connection) -> dict[str, BuildStatus]:
""" """
select package build statuses from the table select package build statuses from the table
@ -201,7 +228,10 @@ class PackageOperations(Operations):
""" """
return { return {
row["package_base"]: BuildStatus.from_json({"status": row["status"], "timestamp": row["last_updated"]}) row["package_base"]: BuildStatus.from_json({"status": row["status"], "timestamp": row["last_updated"]})
for row in connection.execute("""select * from package_statuses""") for row in connection.execute(
"""select * from package_statuses where repository = :repository""",
{"repository": self.repository_id.name}
)
} }
def package_remove(self, package_base: str) -> None: def package_remove(self, package_base: str) -> None:

View File

@ -54,13 +54,19 @@ class PatchOperations(Operations):
connection.execute( connection.execute(
""" """
insert into patches insert into patches
(package_base, variable, patch) (package_base, variable, patch, repository)
values values
(:package_base, :variable, :patch) (:package_base, :variable, :patch, :repository)
on conflict (package_base, coalesce(variable, '')) do update set on conflict (package_base, coalesce(variable, ''), repository) do update set
patch = :patch patch = :patch
""", """,
{"package_base": package_base, "variable": patch.key, "patch": patch.value}) {
"package_base": package_base,
"variable": patch.key,
"patch": patch.value,
"repository": self.repository_id.name,
}
)
return self.with_connection(run, commit=True) return self.with_connection(run, commit=True)
@ -79,8 +85,10 @@ class PatchOperations(Operations):
return [ return [
(row["package_base"], PkgbuildPatch(row["variable"], row["patch"])) (row["package_base"], PkgbuildPatch(row["variable"], row["patch"]))
for row in connection.execute( for row in connection.execute(
"""select * from patches where :package_base is null or package_base = :package_base""", """
{"package_base": package_base}) select * from patches
where (:package_base is null or package_base = :package_base) and repository = :repository""",
{"package_base": package_base, "repository": self.repository_id.name})
] ]
# we could use itertools & operator but why? # we could use itertools & operator but why?
@ -101,13 +109,23 @@ class PatchOperations(Operations):
""" """
def run_many(connection: Connection) -> None: def run_many(connection: Connection) -> None:
connection.executemany( connection.executemany(
"""delete from patches where package_base = :package_base and variable = :variable""", """
[{"package_base": package_base, "variable": variable} for variable in variables]) delete from patches
where package_base = :package_base and variable = :variable and repository = :repository
""",
[
{
"package_base": package_base,
"variable": variable,
"repository": self.repository_id.name,
} for variable in variables
]
)
def run(connection: Connection) -> None: def run(connection: Connection) -> None:
connection.execute( connection.execute(
"""delete from patches where package_base = :package_base""", """delete from patches where package_base = :package_base and repository = :repository""",
{"package_base": package_base}) {"package_base": package_base, "repository": self.repository_id.name})
if variables: if variables:
return self.with_connection(run_many, commit=True) return self.with_connection(run_many, commit=True)

View File

@ -56,8 +56,11 @@ class SQLite(AuthOperations, BuildOperations, LogsOperations, PackageOperations,
Self: fully initialized instance of the database Self: fully initialized instance of the database
""" """
path = cls.database_path(configuration) path = cls.database_path(configuration)
database = cls(path) _, repository_id = configuration.check_loaded()
database = cls(path, repository_id)
database.init(configuration) database.init(configuration)
return database return database
@staticmethod @staticmethod

View File

@ -41,14 +41,14 @@ class SyncHttpClient(LazyLogging):
timeout(int): HTTP request timeout in seconds timeout(int): HTTP request timeout in seconds
""" """
def __init__(self, section: str | None = None, configuration: Configuration | None = None, *, def __init__(self, configuration: Configuration | None = None, section: str | None = None, *,
suppress_errors: bool = False) -> None: suppress_errors: bool = False) -> None:
""" """
default constructor default constructor
Args: Args:
section(str, optional): settings section name (Default value = None)
configuration(Configuration | None): configuration instance (Default value = None) configuration(Configuration | None): configuration instance (Default value = None)
section(str, optional): settings section name (Default value = None)
suppress_errors(bool, optional): suppress logging of request errors (Default value = False) suppress_errors(bool, optional): suppress logging of request errors (Default value = False)
""" """
if configuration is None: if configuration is None:

View File

@ -18,4 +18,3 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
from ahriman.core.log.lazy_logging import LazyLogging from ahriman.core.log.lazy_logging import LazyLogging
from ahriman.core.log.log import Log

View File

@ -27,7 +27,7 @@ from ahriman.core.log.http_log_handler import HttpLogHandler
from ahriman.models.log_handler import LogHandler from ahriman.models.log_handler import LogHandler
class Log: class LogLoader:
""" """
simple static method class which setups application loggers simple static method class which setups application loggers
@ -63,7 +63,7 @@ class Log:
del JournalHandler del JournalHandler
return LogHandler.Journald # journald import was found return LogHandler.Journald # journald import was found
except ImportError: except ImportError:
if Log.DEFAULT_SYSLOG_DEVICE.exists(): if LogLoader.DEFAULT_SYSLOG_DEVICE.exists():
return LogHandler.Syslog return LogHandler.Syslog
return LogHandler.Console return LogHandler.Console
@ -94,8 +94,7 @@ class Log:
fileConfig(log_configuration, disable_existing_loggers=True) fileConfig(log_configuration, disable_existing_loggers=True)
logging.debug("using %s logger", default_handler) logging.debug("using %s logger", default_handler)
except Exception: except Exception:
logging.basicConfig(filename=None, format=Log.DEFAULT_LOG_FORMAT, logging.basicConfig(filename=None, format=LogLoader.DEFAULT_LOG_FORMAT, level=LogLoader.DEFAULT_LOG_LEVEL)
level=Log.DEFAULT_LOG_LEVEL)
logging.exception("could not load logging from configuration, fallback to stderr") logging.exception("could not load logging from configuration, fallback to stderr")
HttpLogHandler.load(configuration, report=report) HttpLogHandler.load(configuration, report=report)

View File

@ -41,7 +41,7 @@ class Report(LazyLogging):
method ``load`` which can be used in order to determine right report instance:: method ``load`` which can be used in order to determine right report instance::
>>> configuration = Configuration() >>> configuration = Configuration()
>>> report = Report.load(RepositoryId("x86_64", None), configuration, "email") >>> report = Report.load(RepositoryId("x86_64", "aur-clone"), configuration, "email")
The ``generate`` method can be used in order to perform the report itself, whereas ``run`` method handles The ``generate`` method can be used in order to perform the report itself, whereas ``run`` method handles
exception and raises ``ReportFailed`` instead:: exception and raises ``ReportFailed`` instead::

View File

@ -53,7 +53,7 @@ class Telegram(Report, JinjaTemplate, SyncHttpClient):
""" """
Report.__init__(self, repository_id, configuration) Report.__init__(self, repository_id, configuration)
JinjaTemplate.__init__(self, repository_id, configuration, section) JinjaTemplate.__init__(self, repository_id, configuration, section)
SyncHttpClient.__init__(self, section, configuration) SyncHttpClient.__init__(self, configuration, section)
self.api_key = configuration.get(section, "api_key") self.api_key = configuration.get(section, "api_key")
self.chat_id = configuration.get(section, "chat_id") self.chat_id = configuration.get(section, "chat_id")

View File

@ -48,7 +48,7 @@ class Repository(Executor, UpdateHandler):
>>> >>>
>>> configuration = Configuration() >>> configuration = Configuration()
>>> database = SQLite.load(configuration) >>> database = SQLite.load(configuration)
>>> repository = Repository.load(RepositoryId("x86_64", None), configuration, database, report=True) >>> repository = Repository.load(RepositoryId("x86_64", "x86_64"), configuration, database, report=True)
>>> known_packages = repository.packages() >>> known_packages = repository.packages()
>>> >>>
>>> build_result = repository.process_build(known_packages) >>> build_result = repository.process_build(known_packages)

View File

@ -51,7 +51,7 @@ class WebClient(Client, SyncHttpClient):
configuration(Configuration): configuration instance configuration(Configuration): configuration instance
""" """
suppress_errors = configuration.getboolean("settings", "suppress_http_log_errors", fallback=False) suppress_errors = configuration.getboolean("settings", "suppress_http_log_errors", fallback=False)
SyncHttpClient.__init__(self, "web", configuration, suppress_errors=suppress_errors) SyncHttpClient.__init__(self, configuration, "web", suppress_errors=suppress_errors)
self.address, self.use_unix_socket = self.parse_address(configuration) self.address, self.use_unix_socket = self.parse_address(configuration)

View File

@ -106,7 +106,7 @@ class Tree:
>>> >>>
>>> configuration = Configuration() >>> configuration = Configuration()
>>> database = SQLite.load(configuration) >>> database = SQLite.load(configuration)
>>> repository = Repository.load(RepositoryId("x86_64", None), configuration, database, report=True) >>> repository = Repository.load(RepositoryId("x86_64", "aur-clone"), configuration, database, report=True)
>>> packages = repository.packages() >>> packages = repository.packages()
>>> >>>
>>> tree = Tree.resolve(packages) >>> tree = Tree.resolve(packages)

View File

@ -52,7 +52,7 @@ class Trigger(LazyLogging):
>>> configuration = Configuration() >>> configuration = Configuration()
>>> configuration.set_option("build", "triggers", "my.awesome.package.CustomTrigger") >>> configuration.set_option("build", "triggers", "my.awesome.package.CustomTrigger")
>>> >>>
>>> loader = TriggerLoader.load(RepositoryId("x86_64", None), configuration) >>> loader = TriggerLoader.load(RepositoryId("x86_64", "aur-clone"), configuration)
>>> loader.on_result(Result(), []) >>> loader.on_result(Result(), [])
""" """
@ -70,6 +70,16 @@ class Trigger(LazyLogging):
self.repository_id = repository_id self.repository_id = repository_id
self.configuration = configuration self.configuration = configuration
@property
def architecture(self) -> str:
"""
repository architecture for backward compatibility
Returns:
str: repository architecture
"""
return self.repository_id.architecture
@classmethod @classmethod
def configuration_schema(cls, repository_id: RepositoryId, def configuration_schema(cls, repository_id: RepositoryId,
configuration: Configuration | None) -> ConfigurationSchema: configuration: Configuration | None) -> ConfigurationSchema:

View File

@ -50,7 +50,7 @@ class TriggerLoader(LazyLogging):
Having such configuration you can create instance of the loader:: Having such configuration you can create instance of the loader::
>>> loader = TriggerLoader.load(RepositoryId("x86_64", None), configuration) >>> loader = TriggerLoader.load(RepositoryId("x86_64", "aur-clone"), configuration)
>>> print(loader.triggers) >>> print(loader.triggers)
After that you are free to run triggers:: After that you are free to run triggers::

View File

@ -31,7 +31,7 @@ from ahriman.models.package import Package
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId
class Github(Upload, HttpUpload): class GitHub(Upload, HttpUpload):
""" """
upload files to GitHub releases upload files to GitHub releases
@ -52,12 +52,12 @@ class Github(Upload, HttpUpload):
section(str): settings section name section(str): settings section name
""" """
Upload.__init__(self, repository_id, configuration) Upload.__init__(self, repository_id, configuration)
HttpUpload.__init__(self, section, configuration) HttpUpload.__init__(self, configuration, section)
self.github_owner = configuration.get(section, "owner") self.github_owner = configuration.get(section, "owner")
self.github_repository = configuration.get(section, "repository") self.github_repository = configuration.get(section, "repository")
if repository_id.name is not None: if configuration.getboolean(section, "use_full_release_name", fallback=False):
self.github_release_tag = f"{repository_id.name}-{repository_id.architecture}" self.github_release_tag = f"{repository_id.name}-{repository_id.architecture}"
self.github_release_tag_name = f"{repository_id.name} {repository_id.architecture}" self.github_release_tag_name = f"{repository_id.name} {repository_id.architecture}"
else: else:

View File

@ -50,7 +50,7 @@ class RemoteService(Upload, HttpUpload):
section(str): settings section name section(str): settings section name
""" """
Upload.__init__(self, repository_id, configuration) Upload.__init__(self, repository_id, configuration)
HttpUpload.__init__(self, section, configuration) HttpUpload.__init__(self, configuration, section)
self.client = WebClient(configuration) self.client = WebClient(configuration)
@cached_property @cached_property

View File

@ -43,7 +43,7 @@ class Upload(LazyLogging):
wraps any internal exceptions into the ``SyncFailed`` exception:: wraps any internal exceptions into the ``SyncFailed`` exception::
>>> configuration = Configuration() >>> configuration = Configuration()
>>> upload = Upload.load(RepositoryId("x86_64", None), configuration, "s3") >>> upload = Upload.load(RepositoryId("x86_64", "aur-clone"), configuration, "s3")
>>> upload.run(configuration.repository_paths.repository, []) >>> upload.run(configuration.repository_paths.repository, [])
Or in case if direct access to exception is required, the ``sync`` method can be used:: Or in case if direct access to exception is required, the ``sync`` method can be used::
@ -87,8 +87,8 @@ class Upload(LazyLogging):
from ahriman.core.upload.s3 import S3 from ahriman.core.upload.s3 import S3
return S3(repository_id, configuration, section) return S3(repository_id, configuration, section)
case UploadSettings.GitHub: case UploadSettings.GitHub:
from ahriman.core.upload.github import Github from ahriman.core.upload.github import GitHub
return Github(repository_id, configuration, section) return GitHub(repository_id, configuration, section)
case UploadSettings.RemoteService: case UploadSettings.RemoteService:
from ahriman.core.upload.remote_service import RemoteService from ahriman.core.upload.remote_service import RemoteService
return RemoteService(repository_id, configuration, section) return RemoteService(repository_id, configuration, section)

View File

@ -68,6 +68,10 @@ class UploadTrigger(Trigger):
"coerce": "integer", "coerce": "integer",
"min": 0, "min": 0,
}, },
"use_full_release_name": {
"type": "boolean",
"coerce": "boolean",
},
"username": { "username": {
"type": "string", "type": "string",
}, },

View File

@ -71,7 +71,7 @@ class AURPackage:
>>> from ahriman.models.repository_id import RepositoryId >>> from ahriman.models.repository_id import RepositoryId
>>> >>>
>>> configuration = Configuration() >>> configuration = Configuration()
>>> pacman = Pacman(RepositoryId("x86_64", None), configuration) >>> pacman = Pacman(RepositoryId("x86_64", "aur-clone"), configuration)
>>> metadata = pacman.package_get("pacman") >>> metadata = pacman.package_get("pacman")
>>> package = AURPackage.from_pacman(next(metadata)) # load package from pyalpm wrapper >>> package = AURPackage.from_pacman(next(metadata)) # load package from pyalpm wrapper
""" """

View File

@ -59,7 +59,7 @@ class PackageDescription:
>>> from ahriman.models.repository_id import RepositoryId >>> from ahriman.models.repository_id import RepositoryId
>>> >>>
>>> configuration = Configuration() >>> configuration = Configuration()
>>> pacman = Pacman(RepositoryId("x86_64", None), configuration) >>> pacman = Pacman(RepositoryId("x86_64", "aur-clone"), configuration)
>>> pyalpm_description = next(package for package in pacman.package_get("pacman")) >>> pyalpm_description = next(package for package in pacman.package_get("pacman"))
>>> description = PackageDescription.from_package( >>> description = PackageDescription.from_package(
>>> pyalpm_description, Path("/var/cache/pacman/pkg/pacman-6.0.1-4-x86_64.pkg.tar.zst")) >>> pyalpm_description, Path("/var/cache/pacman/pkg/pacman-6.0.1-4-x86_64.pkg.tar.zst"))

View File

@ -21,15 +21,17 @@ import os
import shutil import shutil
from collections.abc import Generator from collections.abc import Generator
from dataclasses import dataclass, field from dataclasses import dataclass
from functools import cached_property
from pathlib import Path from pathlib import Path
from ahriman.core.exceptions import PathError from ahriman.core.exceptions import PathError
from ahriman.core.log import LazyLogging
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId
@dataclass(frozen=True) @dataclass(frozen=True)
class RepositoryPaths: class RepositoryPaths(LazyLogging):
""" """
repository paths holder. For the most operations with paths you want to use this object repository paths holder. For the most operations with paths you want to use this object
@ -40,7 +42,7 @@ class RepositoryPaths:
Examples: Examples:
This class can be used in order to access the repository tree structure:: This class can be used in order to access the repository tree structure::
>>> paths = RepositoryPaths(Path("/var/lib/ahriman"), RepositoryId("x86_64", None)) >>> paths = RepositoryPaths(Path("/var/lib/ahriman"), RepositoryId("x86_64", "aur-clone"))
Additional methods can be used in order to ensure that tree is created:: Additional methods can be used in order to ensure that tree is created::
@ -54,18 +56,20 @@ class RepositoryPaths:
root: Path root: Path
repository_id: RepositoryId repository_id: RepositoryId
_suffix: Path = field(init=False)
def __post_init__(self) -> None: @cached_property
def _suffix(self) -> Path:
""" """
load suffix for different modes (legacy or not suffix of the paths as defined by repository structure
Returns:
Path: relative path which contains only architecture segment in case if legacy tree is used and repository
name and architecture otherwise
""" """
if self.repository.parent.with_name(self.repository_id.architecture).exists(): if (self.root / "repository" / self.repository_id.architecture).is_dir():
# there is created legacy tree self.logger.warning("legacy single repository tree has been found")
_suffix = Path(self.repository_id.architecture) return Path(self.repository_id.architecture)
else: return Path(self.repository_id.name) / self.repository_id.architecture
_suffix = Path(self.repository_id.name) / self.repository_id.architecture
object.__setattr__(self, "_suffix", _suffix)
@property @property
def cache(self) -> Path: def cache(self) -> Path:

View File

@ -27,7 +27,8 @@ def application_packages(configuration: Configuration, database: SQLite, reposit
""" """
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository) mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.core.database.SQLite.load", return_value=database) mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
return ApplicationPackages("x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
return ApplicationPackages(repository_id, configuration, report=False)
@pytest.fixture @pytest.fixture
@ -47,7 +48,8 @@ def application_properties(configuration: Configuration, database: SQLite, repos
""" """
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository) mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.core.database.SQLite.load", return_value=database) mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
return ApplicationProperties("x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
return ApplicationProperties(repository_id, configuration, report=False)
@pytest.fixture @pytest.fixture
@ -67,4 +69,5 @@ def application_repository(configuration: Configuration, database: SQLite, repos
""" """
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository) mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.core.database.SQLite.load", return_value=database) mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
return ApplicationRepository("x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
return ApplicationRepository(repository_id, configuration, report=False)

View File

@ -6,3 +6,10 @@ def test_create_tree(application_properties: ApplicationProperties) -> None:
must have repository attribute must have repository attribute
""" """
assert application_properties.repository assert application_properties.repository
def test_architecture(application_properties: ApplicationProperties) -> None:
"""
must return repository architecture
"""
assert application_properties.architecture == application_properties.repository_id.architecture

View File

@ -28,7 +28,8 @@ def application(configuration: Configuration, repository: Repository, database:
""" """
mocker.patch("ahriman.core.database.SQLite.load", return_value=database) mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository) mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
return Application("x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
return Application(repository_id, configuration, report=False)
@pytest.fixture @pytest.fixture
@ -54,7 +55,8 @@ def lock(args: argparse.Namespace, configuration: Configuration) -> Lock:
Returns: Returns:
Lock: file lock test instance Lock: file lock test instance
""" """
return Lock(args, "x86_64", configuration) _, repository_id = configuration.check_loaded()
return Lock(args, repository_id, configuration)
@pytest.fixture @pytest.fixture

View File

@ -8,48 +8,7 @@ from ahriman.application.handlers import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.exceptions import ExitCode, MissingArchitectureError, MultipleArchitecturesError from ahriman.core.exceptions import ExitCode, MissingArchitectureError, MultipleArchitecturesError
from ahriman.models.log_handler import LogHandler from ahriman.models.log_handler import LogHandler
from ahriman.models.repository_id import RepositoryId
def test_architectures_extract(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must generate list of available architectures
"""
args.configuration = configuration.path
known_architectures_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_architectures")
Handler.architectures_extract(args)
known_architectures_mock.assert_called_once_with(configuration.getpath("repository", "root"))
def test_architectures_extract_empty(args: argparse.Namespace, configuration: Configuration,
mocker: MockerFixture) -> None:
"""
must raise exception if no available architectures found
"""
args.command = "config"
args.configuration = configuration.path
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_architectures", return_value=set())
with pytest.raises(MissingArchitectureError):
Handler.architectures_extract(args)
def test_architectures_extract_exception(args: argparse.Namespace, mocker: MockerFixture) -> None:
"""
must raise exception on missing architectures
"""
args.command = "config"
mocker.patch.object(Handler, "ALLOW_AUTO_ARCHITECTURE_RUN", False)
with pytest.raises(MissingArchitectureError):
Handler.architectures_extract(args)
def test_architectures_extract_specified(args: argparse.Namespace) -> None:
"""
must return architecture list if it has been specified
"""
architectures = args.architecture = ["i686", "x86_64"]
assert Handler.architectures_extract(args) == sorted(set(architectures))
def test_call(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None: def test_call(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
@ -62,20 +21,21 @@ def test_call(args: argparse.Namespace, configuration: Configuration, mocker: Mo
args.report = False args.report = False
mocker.patch("ahriman.application.handlers.Handler.run") mocker.patch("ahriman.application.handlers.Handler.run")
configuration_mock = mocker.patch("ahriman.core.configuration.Configuration.from_path", return_value=configuration) configuration_mock = mocker.patch("ahriman.core.configuration.Configuration.from_path", return_value=configuration)
log_handler_mock = mocker.patch("ahriman.core.log.Log.handler", return_value=args.log_handler) log_handler_mock = mocker.patch("ahriman.core.log.log_loader.LogLoader.handler", return_value=args.log_handler)
log_load_mock = mocker.patch("ahriman.core.log.Log.load") log_load_mock = mocker.patch("ahriman.core.log.log_loader.LogLoader.load")
enter_mock = mocker.patch("ahriman.application.lock.Lock.__enter__") enter_mock = mocker.patch("ahriman.application.lock.Lock.__enter__")
exit_mock = mocker.patch("ahriman.application.lock.Lock.__exit__") exit_mock = mocker.patch("ahriman.application.lock.Lock.__exit__")
assert Handler.call(args, "x86_64") _, repository_id = configuration.check_loaded()
configuration_mock.assert_called_once_with(args.configuration, "x86_64") assert Handler.call(args, repository_id)
configuration_mock.assert_called_once_with(args.configuration, repository_id)
log_handler_mock.assert_called_once_with(args.log_handler) log_handler_mock.assert_called_once_with(args.log_handler)
log_load_mock.assert_called_once_with(configuration, args.log_handler, quiet=args.quiet, report=args.report) log_load_mock.assert_called_once_with(configuration, args.log_handler, quiet=args.quiet, report=args.report)
enter_mock.assert_called_once_with() enter_mock.assert_called_once_with()
exit_mock.assert_called_once_with(None, None, None) exit_mock.assert_called_once_with(None, None, None)
def test_call_exception(args: argparse.Namespace, mocker: MockerFixture) -> None: def test_call_exception(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
""" """
must process exception must process exception
""" """
@ -84,11 +44,12 @@ def test_call_exception(args: argparse.Namespace, mocker: MockerFixture) -> None
mocker.patch("ahriman.core.configuration.Configuration.from_path", side_effect=Exception()) mocker.patch("ahriman.core.configuration.Configuration.from_path", side_effect=Exception())
logging_mock = mocker.patch("logging.Logger.exception") logging_mock = mocker.patch("logging.Logger.exception")
assert not Handler.call(args, "x86_64") _, repository_id = configuration.check_loaded()
assert not Handler.call(args, repository_id)
logging_mock.assert_called_once_with(pytest.helpers.anyvar(str, strict=True)) logging_mock.assert_called_once_with(pytest.helpers.anyvar(str, strict=True))
def test_call_exit_code(args: argparse.Namespace, mocker: MockerFixture) -> None: def test_call_exit_code(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
""" """
must process exitcode exception must process exitcode exception
""" """
@ -97,7 +58,8 @@ def test_call_exit_code(args: argparse.Namespace, mocker: MockerFixture) -> None
mocker.patch("ahriman.core.configuration.Configuration.from_path", side_effect=ExitCode()) mocker.patch("ahriman.core.configuration.Configuration.from_path", side_effect=ExitCode())
logging_mock = mocker.patch("logging.Logger.exception") logging_mock = mocker.patch("logging.Logger.exception")
assert not Handler.call(args, "x86_64") _, repository_id = configuration.check_loaded()
assert not Handler.call(args, repository_id)
logging_mock.assert_not_called() logging_mock.assert_not_called()
@ -105,33 +67,39 @@ def test_execute(args: argparse.Namespace, mocker: MockerFixture) -> None:
""" """
must run execution in multiple processes must run execution in multiple processes
""" """
args.architecture = ["i686", "x86_64"] ids = [
RepositoryId("i686", "aur-clone"),
RepositoryId("x86_64", "aur-clone"),
]
mocker.patch("ahriman.application.handlers.Handler.repositories_extract", return_value=ids)
starmap_mock = mocker.patch("multiprocessing.pool.Pool.starmap") starmap_mock = mocker.patch("multiprocessing.pool.Pool.starmap")
Handler.execute(args) Handler.execute(args)
starmap_mock.assert_called_once_with(Handler.call, [(args, architecture) for architecture in args.architecture]) starmap_mock.assert_called_once_with(Handler.call, [(args, repository_id) for repository_id in ids])
def test_execute_multiple_not_supported(args: argparse.Namespace, mocker: MockerFixture) -> None: def test_execute_multiple_not_supported(args: argparse.Namespace, mocker: MockerFixture) -> None:
""" """
must raise an exception if multiple architectures are not supported by the handler must raise an exception if multiple architectures are not supported by the handler
""" """
args.architecture = ["i686", "x86_64"]
args.command = "web" args.command = "web"
mocker.patch("ahriman.application.handlers.Handler.repositories_extract", return_value=[
RepositoryId("i686", "aur-clone"),
RepositoryId("x86_64", "aur-clone"),
])
mocker.patch.object(Handler, "ALLOW_MULTI_ARCHITECTURE_RUN", False) mocker.patch.object(Handler, "ALLOW_MULTI_ARCHITECTURE_RUN", False)
with pytest.raises(MultipleArchitecturesError): with pytest.raises(MultipleArchitecturesError):
Handler.execute(args) Handler.execute(args)
def test_execute_single(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None: def test_execute_single(args: argparse.Namespace, mocker: MockerFixture) -> None:
""" """
must run execution in current process if only one architecture supplied must run execution in current process if only one architecture supplied
""" """
args.architecture = ["x86_64"] mocker.patch("ahriman.application.handlers.Handler.repositories_extract", return_value=[
args.configuration = Path("") RepositoryId("x86_64", "aur-clone"),
args.quiet = False ])
mocker.patch("ahriman.core.configuration.Configuration.from_path", return_value=configuration)
starmap_mock = mocker.patch("multiprocessing.pool.Pool.starmap") starmap_mock = mocker.patch("multiprocessing.pool.Pool.starmap")
Handler.execute(args) Handler.execute(args)
@ -142,8 +110,73 @@ def test_run(args: argparse.Namespace, configuration: Configuration) -> None:
""" """
must raise NotImplemented for missing method must raise NotImplemented for missing method
""" """
_, repository_id = configuration.check_loaded()
with pytest.raises(NotImplementedError): with pytest.raises(NotImplementedError):
Handler.run(args, "x86_64", configuration, report=True) Handler.run(args, repository_id, configuration, report=True)
def test_repositories_extract(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
"""
must generate list of available architectures
"""
args.configuration = configuration.path
_, repository_id = configuration.check_loaded()
known_architectures_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_architectures")
Handler.repositories_extract(args)
known_architectures_mock.assert_called_once_with(configuration.getpath("repository", "root"), repository_id.name)
def test_repositories_extract_empty(args: argparse.Namespace, configuration: Configuration,
mocker: MockerFixture) -> None:
"""
must raise exception if no available architectures found
"""
args.command = "config"
args.configuration = configuration.path
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_architectures", return_value=set())
with pytest.raises(MissingArchitectureError):
Handler.repositories_extract(args)
def test_repositories_extract_exception(args: argparse.Namespace, mocker: MockerFixture) -> None:
"""
must raise exception on missing architectures
"""
args.command = "config"
mocker.patch.object(Handler, "ALLOW_AUTO_ARCHITECTURE_RUN", False)
with pytest.raises(MissingArchitectureError):
Handler.repositories_extract(args)
def test_repositories_extract_specified(args: argparse.Namespace, configuration: Configuration) -> None:
"""
must return architecture list if it has been specified
"""
args.configuration = configuration.path
args.architecture = ["i686", "x86_64"]
args.repository = []
_, repository_id = configuration.check_loaded()
ids = [RepositoryId(architecture, repository_id.name) for architecture in args.architecture]
assert Handler.repositories_extract(args) == sorted(set(ids))
def test_repositories_extract_specified_with_repository(args: argparse.Namespace, configuration: Configuration) -> None:
"""
must return architecture list if it has been specified together with repositories
"""
args.configuration = configuration.path
args.architecture = ["i686", "x86_64"]
args.repository = ["repo1", "repo2"]
ids = [
RepositoryId(architecture, name)
for architecture in args.architecture
for name in args.repository
]
assert Handler.repositories_extract(args) == sorted(set(ids))
def test_check_if_empty() -> None: def test_check_if_empty() -> None:

View File

@ -44,7 +44,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
dependencies_mock = mocker.patch("ahriman.application.application.Application.with_dependencies") dependencies_mock = mocker.patch("ahriman.application.application.Application.with_dependencies")
on_start_mock = mocker.patch("ahriman.application.application.Application.on_start") on_start_mock = mocker.patch("ahriman.application.application.Application.on_start")
Add.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Add.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with(args.package, args.source, args.username) application_mock.assert_called_once_with(args.package, args.source, args.username)
dependencies_mock.assert_not_called() dependencies_mock.assert_not_called()
on_start_mock.assert_called_once_with() on_start_mock.assert_called_once_with()
@ -68,7 +69,8 @@ def test_run_with_updates(args: argparse.Namespace, configuration: Configuration
return_value=[package_ahriman]) return_value=[package_ahriman])
print_mock = mocker.patch("ahriman.application.application.Application.print_updates") print_mock = mocker.patch("ahriman.application.application.Application.print_updates")
Add.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Add.run(args, repository_id, configuration, report=False)
updates_mock.assert_called_once_with(args.package, aur=False, local=False, manual=True, vcs=False) updates_mock.assert_called_once_with(args.package, aur=False, local=False, manual=True, vcs=False)
application_mock.assert_called_once_with([package_ahriman], application_mock.assert_called_once_with([package_ahriman],
Packagers(args.username, {package_ahriman.base: "packager"}), Packagers(args.username, {package_ahriman.base: "packager"}),
@ -94,5 +96,6 @@ def test_run_empty_exception(args: argparse.Namespace, configuration: Configurat
mocker.patch("ahriman.application.application.Application.print_updates") mocker.patch("ahriman.application.application.Application.print_updates")
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty") check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
Add.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Add.run(args, repository_id, configuration, report=False)
check_mock.assert_called_once_with(True, True) check_mock.assert_called_once_with(True, True)

View File

@ -33,7 +33,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
add_mock = tarfile.__enter__.return_value = MagicMock() add_mock = tarfile.__enter__.return_value = MagicMock()
mocker.patch("tarfile.TarFile.__new__", return_value=tarfile) mocker.patch("tarfile.TarFile.__new__", return_value=tarfile)
Backup.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Backup.run(args, repository_id, configuration, report=False)
add_mock.add.assert_called_once_with(Path("path")) add_mock.add.assert_called_once_with(Path("path"))

View File

@ -35,6 +35,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
application_mock = mocker.patch("ahriman.application.application.Application.clean") application_mock = mocker.patch("ahriman.application.application.Application.clean")
on_start_mock = mocker.patch("ahriman.application.application.Application.on_start") on_start_mock = mocker.patch("ahriman.application.application.Application.on_start")
Clean.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Clean.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with(cache=False, chroot=False, manual=False, packages=False, pacman=False) application_mock.assert_called_once_with(cache=False, chroot=False, manual=False, packages=False, pacman=False)
on_start_mock.assert_called_once_with() on_start_mock.assert_called_once_with()

View File

@ -33,7 +33,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
start_mock = mocker.patch("threading.Timer.start") start_mock = mocker.patch("threading.Timer.start")
join_mock = mocker.patch("threading.Timer.join") join_mock = mocker.patch("threading.Timer.join")
Daemon.run(args, "x86_64", configuration, report=True) _, repository_id = configuration.check_loaded()
run_mock.assert_called_once_with(args, "x86_64", configuration, report=True) Daemon.run(args, repository_id, configuration, report=True)
run_mock.assert_called_once_with(args, repository_id, configuration, report=True)
start_mock.assert_called_once_with() start_mock.assert_called_once_with()
join_mock.assert_called_once_with() join_mock.assert_called_once_with()

View File

@ -29,7 +29,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
application_mock = mocker.patch("ahriman.core.configuration.Configuration.dump", application_mock = mocker.patch("ahriman.core.configuration.Configuration.dump",
return_value=configuration.dump()) return_value=configuration.dump())
Dump.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Dump.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with() application_mock.assert_called_once_with()
print_mock.assert_called() print_mock.assert_called()

View File

@ -29,7 +29,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
args = _default_args(args) args = _default_args(args)
parse_mock = mocker.patch("argparse.ArgumentParser.parse_args") parse_mock = mocker.patch("argparse.ArgumentParser.parse_args")
Help.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Help.run(args, repository_id, configuration, report=False)
parse_mock.assert_called_once_with(["--help"]) parse_mock.assert_called_once_with(["--help"])
@ -41,7 +42,8 @@ def test_run_command(args: argparse.Namespace, configuration: Configuration, moc
args.command = "aur-search" args.command = "aur-search"
parse_mock = mocker.patch("argparse.ArgumentParser.parse_args") parse_mock = mocker.patch("argparse.ArgumentParser.parse_args")
Help.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Help.run(args, repository_id, configuration, report=False)
parse_mock.assert_called_once_with(["aur-search", "--help"]) parse_mock.assert_called_once_with(["aur-search", "--help"])

View File

@ -31,7 +31,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository) mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
application_mock = mocker.patch("ahriman.core.sign.gpg.GPG.key_import") application_mock = mocker.patch("ahriman.core.sign.gpg.GPG.key_import")
KeyImport.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
KeyImport.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with(args.key_server, args.key) application_mock.assert_called_once_with(args.key_server, args.key)

View File

@ -44,8 +44,9 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
return_value=(args.package, PkgbuildPatch(None, "patch"))) return_value=(args.package, PkgbuildPatch(None, "patch")))
application_mock = mocker.patch("ahriman.application.handlers.Patch.patch_set_create") application_mock = mocker.patch("ahriman.application.handlers.Patch.patch_set_create")
Patch.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
patch_mock.assert_called_once_with(args.package, "x86_64", args.track) Patch.run(args, repository_id, configuration, report=False)
patch_mock.assert_called_once_with(args.package, repository_id.architecture, args.track)
application_mock.assert_called_once_with(pytest.helpers.anyvar(int), args.package, PkgbuildPatch(None, "patch")) application_mock.assert_called_once_with(pytest.helpers.anyvar(int), args.package, PkgbuildPatch(None, "patch"))
@ -63,7 +64,8 @@ def test_run_function(args: argparse.Namespace, configuration: Configuration, re
patch_mock = mocker.patch("ahriman.application.handlers.Patch.patch_create_from_function", return_value=patch) patch_mock = mocker.patch("ahriman.application.handlers.Patch.patch_create_from_function", return_value=patch)
application_mock = mocker.patch("ahriman.application.handlers.Patch.patch_set_create") application_mock = mocker.patch("ahriman.application.handlers.Patch.patch_set_create")
Patch.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Patch.run(args, repository_id, configuration, report=False)
patch_mock.assert_called_once_with(args.variable, args.patch) patch_mock.assert_called_once_with(args.variable, args.patch)
application_mock.assert_called_once_with(pytest.helpers.anyvar(int), args.package, patch) application_mock.assert_called_once_with(pytest.helpers.anyvar(int), args.package, patch)
@ -79,7 +81,8 @@ def test_run_list(args: argparse.Namespace, configuration: Configuration, reposi
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository) mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
application_mock = mocker.patch("ahriman.application.handlers.Patch.patch_set_list") application_mock = mocker.patch("ahriman.application.handlers.Patch.patch_set_list")
Patch.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Patch.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with(pytest.helpers.anyvar(int), args.package, ["version"], False) application_mock.assert_called_once_with(pytest.helpers.anyvar(int), args.package, ["version"], False)
@ -94,11 +97,12 @@ def test_run_remove(args: argparse.Namespace, configuration: Configuration, repo
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository) mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
application_mock = mocker.patch("ahriman.application.handlers.Patch.patch_set_remove") application_mock = mocker.patch("ahriman.application.handlers.Patch.patch_set_remove")
Patch.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Patch.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with(pytest.helpers.anyvar(int), args.package, ["version"]) application_mock.assert_called_once_with(pytest.helpers.anyvar(int), args.package, ["version"])
def test_patch_create_from_diff(package_ahriman: Package, mocker: MockerFixture) -> None: def test_patch_create_from_diff(package_ahriman: Package, configuration: Configuration, mocker: MockerFixture) -> None:
""" """
must create patch from directory tree diff must create patch from directory tree diff
""" """
@ -108,8 +112,9 @@ def test_patch_create_from_diff(package_ahriman: Package, mocker: MockerFixture)
package_mock = mocker.patch("ahriman.models.package.Package.from_build", return_value=package_ahriman) package_mock = mocker.patch("ahriman.models.package.Package.from_build", return_value=package_ahriman)
sources_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.patch_create", return_value=patch.value) sources_mock = mocker.patch("ahriman.core.build_tools.sources.Sources.patch_create", return_value=patch.value)
assert Patch.patch_create_from_diff(path, "x86_64", ["*.diff"]) == (package_ahriman.base, patch) _, repository_id = configuration.check_loaded()
package_mock.assert_called_once_with(path, "x86_64", None) assert Patch.patch_create_from_diff(path, repository_id.architecture, ["*.diff"]) == (package_ahriman.base, patch)
package_mock.assert_called_once_with(path, repository_id.architecture, None)
sources_mock.assert_called_once_with(path, "*.diff") sources_mock.assert_called_once_with(path, "*.diff")

View File

@ -49,7 +49,8 @@ def test_run(args: argparse.Namespace, package_ahriman: Package, configuration:
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty") check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
on_start_mock = mocker.patch("ahriman.application.application.Application.on_start") on_start_mock = mocker.patch("ahriman.application.application.Application.on_start")
Rebuild.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Rebuild.run(args, repository_id, configuration, report=False)
extract_mock.assert_called_once_with(pytest.helpers.anyvar(int), args.status, from_database=args.from_database) extract_mock.assert_called_once_with(pytest.helpers.anyvar(int), args.status, from_database=args.from_database)
application_packages_mock.assert_called_once_with([package_ahriman], None) application_packages_mock.assert_called_once_with([package_ahriman], None)
application_mock.assert_called_once_with([package_ahriman], args.username, bump_pkgrel=args.increment) application_mock.assert_called_once_with([package_ahriman], args.username, bump_pkgrel=args.increment)
@ -70,7 +71,8 @@ def test_run_extract_packages(args: argparse.Namespace, configuration: Configura
mocker.patch("ahriman.application.application.Application.print_updates") mocker.patch("ahriman.application.application.Application.print_updates")
extract_mock = mocker.patch("ahriman.application.handlers.Rebuild.extract_packages", return_value=[]) extract_mock = mocker.patch("ahriman.application.handlers.Rebuild.extract_packages", return_value=[])
Rebuild.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Rebuild.run(args, repository_id, configuration, report=False)
extract_mock.assert_called_once_with(pytest.helpers.anyvar(int), args.status, from_database=args.from_database) extract_mock.assert_called_once_with(pytest.helpers.anyvar(int), args.status, from_database=args.from_database)
@ -87,7 +89,8 @@ def test_run_dry_run(args: argparse.Namespace, configuration: Configuration, rep
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty") check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
print_mock = mocker.patch("ahriman.application.application.Application.print_updates") print_mock = mocker.patch("ahriman.application.application.Application.print_updates")
Rebuild.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Rebuild.run(args, repository_id, configuration, report=False)
application_mock.assert_not_called() application_mock.assert_not_called()
check_mock.assert_called_once_with(False, False) check_mock.assert_called_once_with(False, False)
print_mock.assert_called_once_with([package_ahriman], log_fn=pytest.helpers.anyvar(int)) print_mock.assert_called_once_with([package_ahriman], log_fn=pytest.helpers.anyvar(int))
@ -105,7 +108,8 @@ def test_run_filter(args: argparse.Namespace, configuration: Configuration, repo
mocker.patch("ahriman.application.handlers.Rebuild.extract_packages", return_value=[]) mocker.patch("ahriman.application.handlers.Rebuild.extract_packages", return_value=[])
application_packages_mock = mocker.patch("ahriman.core.repository.repository.Repository.packages_depend_on") application_packages_mock = mocker.patch("ahriman.core.repository.repository.Repository.packages_depend_on")
Rebuild.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Rebuild.run(args, repository_id, configuration, report=False)
application_packages_mock.assert_called_once_with([], ["python-aur"]) application_packages_mock.assert_called_once_with([], ["python-aur"])
@ -120,7 +124,8 @@ def test_run_without_filter(args: argparse.Namespace, configuration: Configurati
mocker.patch("ahriman.application.handlers.Rebuild.extract_packages", return_value=[]) mocker.patch("ahriman.application.handlers.Rebuild.extract_packages", return_value=[])
application_packages_mock = mocker.patch("ahriman.core.repository.repository.Repository.packages_depend_on") application_packages_mock = mocker.patch("ahriman.core.repository.repository.Repository.packages_depend_on")
Rebuild.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Rebuild.run(args, repository_id, configuration, report=False)
application_packages_mock.assert_called_once_with([], None) application_packages_mock.assert_called_once_with([], None)
@ -138,7 +143,8 @@ def test_run_update_empty_exception(args: argparse.Namespace, configuration: Con
mocker.patch("ahriman.application.application.Application.print_updates") mocker.patch("ahriman.application.application.Application.print_updates")
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty") check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
Rebuild.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Rebuild.run(args, repository_id, configuration, report=False)
check_mock.assert_called_once_with(True, True) check_mock.assert_called_once_with(True, True)
@ -155,7 +161,8 @@ def test_run_build_empty_exception(args: argparse.Namespace, configuration: Conf
mocker.patch("ahriman.application.application.Application.update", return_value=Result()) mocker.patch("ahriman.application.application.Application.update", return_value=Result())
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty") check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
Rebuild.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Rebuild.run(args, repository_id, configuration, report=False)
check_mock.assert_has_calls([MockCall(True, False), MockCall(True, True)]) check_mock.assert_has_calls([MockCall(True, False), MockCall(True, True)])

View File

@ -31,6 +31,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
application_mock = mocker.patch("ahriman.application.application.Application.remove") application_mock = mocker.patch("ahriman.application.application.Application.remove")
on_start_mock = mocker.patch("ahriman.application.application.Application.on_start") on_start_mock = mocker.patch("ahriman.application.application.Application.on_start")
Remove.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Remove.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with([]) application_mock.assert_called_once_with([])
on_start_mock.assert_called_once_with() on_start_mock.assert_called_once_with()

View File

@ -34,7 +34,8 @@ def test_run(args: argparse.Namespace, package_ahriman: Package, configuration:
remove_mock = mocker.patch("ahriman.application.application.Application.remove") remove_mock = mocker.patch("ahriman.application.application.Application.remove")
on_start_mock = mocker.patch("ahriman.application.application.Application.on_start") on_start_mock = mocker.patch("ahriman.application.application.Application.on_start")
RemoveUnknown.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
RemoveUnknown.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with() application_mock.assert_called_once_with()
remove_mock.assert_called_once_with([package_ahriman]) remove_mock.assert_called_once_with([package_ahriman])
on_start_mock.assert_called_once_with() on_start_mock.assert_called_once_with()
@ -53,7 +54,8 @@ def test_run_dry_run(args: argparse.Namespace, configuration: Configuration, rep
remove_mock = mocker.patch("ahriman.application.application.Application.remove") remove_mock = mocker.patch("ahriman.application.application.Application.remove")
print_mock = mocker.patch("ahriman.core.formatters.Printer.print") print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
RemoveUnknown.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
RemoveUnknown.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with() application_mock.assert_called_once_with()
remove_mock.assert_not_called() remove_mock.assert_not_called()
print_mock.assert_called_once_with(verbose=False) print_mock.assert_called_once_with(verbose=False)

View File

@ -32,7 +32,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
extract_mock = tarfile.__enter__.return_value = MagicMock() extract_mock = tarfile.__enter__.return_value = MagicMock()
mocker.patch("tarfile.TarFile.__new__", return_value=tarfile) mocker.patch("tarfile.TarFile.__new__", return_value=tarfile)
Restore.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Restore.run(args, repository_id, configuration, report=False)
extract_mock.extractall.assert_called_once_with(path=args.output) extract_mock.extractall.assert_called_once_with(path=args.output)

View File

@ -42,7 +42,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty") check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
print_mock = mocker.patch("ahriman.core.formatters.Printer.print") print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
Search.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Search.run(args, repository_id, configuration, report=False)
aur_search_mock.assert_called_once_with("ahriman", pacman=pytest.helpers.anyvar(int)) aur_search_mock.assert_called_once_with("ahriman", pacman=pytest.helpers.anyvar(int))
official_search_mock.assert_called_once_with("ahriman", pacman=pytest.helpers.anyvar(int)) official_search_mock.assert_called_once_with("ahriman", pacman=pytest.helpers.anyvar(int))
check_mock.assert_called_once_with(False, False) check_mock.assert_called_once_with(False, False)
@ -62,7 +63,8 @@ def test_run_empty_exception(args: argparse.Namespace, configuration: Configurat
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository) mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty") check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
Search.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Search.run(args, repository_id, configuration, report=False)
check_mock.assert_called_once_with(True, True) check_mock.assert_called_once_with(True, True)
@ -77,7 +79,8 @@ def test_run_sort(args: argparse.Namespace, configuration: Configuration, reposi
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository) mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
sort_mock = mocker.patch("ahriman.application.handlers.Search.sort") sort_mock = mocker.patch("ahriman.application.handlers.Search.sort")
Search.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Search.run(args, repository_id, configuration, report=False)
sort_mock.assert_has_calls([ sort_mock.assert_has_calls([
MockCall([], "name"), MockCall().__iter__(), MockCall([], "name"), MockCall().__iter__(),
MockCall([aur_package_ahriman], "name"), MockCall().__iter__() MockCall([aur_package_ahriman], "name"), MockCall().__iter__()
@ -96,7 +99,8 @@ def test_run_sort_by(args: argparse.Namespace, configuration: Configuration, rep
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository) mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
sort_mock = mocker.patch("ahriman.application.handlers.Search.sort") sort_mock = mocker.patch("ahriman.application.handlers.Search.sort")
Search.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Search.run(args, repository_id, configuration, report=False)
sort_mock.assert_has_calls([ sort_mock.assert_has_calls([
MockCall([], "field"), MockCall().__iter__(), MockCall([], "field"), MockCall().__iter__(),
MockCall([aur_package_ahriman], "field"), MockCall().__iter__() MockCall([aur_package_ahriman], "field"), MockCall().__iter__()

View File

@ -35,7 +35,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
application_mock = mocker.patch("ahriman.core.formatters.Printer.print") application_mock = mocker.patch("ahriman.core.formatters.Printer.print")
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty") check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
ServiceUpdates.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
ServiceUpdates.run(args, repository_id, configuration, report=False)
package_mock.assert_called_once_with(package_ahriman.base, repository.pacman, None) package_mock.assert_called_once_with(package_ahriman.base, repository.pacman, None)
application_mock.assert_called_once_with(verbose=True, separator=" -> ") application_mock.assert_called_once_with(verbose=True, separator=" -> ")
check_mock.assert_called_once_with(args.exit_code, True) check_mock.assert_called_once_with(args.exit_code, True)
@ -53,6 +54,7 @@ def test_run_skip(args: argparse.Namespace, configuration: Configuration, reposi
application_mock = mocker.patch("ahriman.core.formatters.Printer.print") application_mock = mocker.patch("ahriman.core.formatters.Printer.print")
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty") check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
ServiceUpdates.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
ServiceUpdates.run(args, repository_id, configuration, report=False)
application_mock.assert_not_called() application_mock.assert_not_called()
check_mock.assert_not_called() check_mock.assert_not_called()

View File

@ -9,6 +9,7 @@ from unittest.mock import call as MockCall
from ahriman.application.handlers import Setup from ahriman.application.handlers import Setup
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.repository import Repository from ahriman.core.repository import Repository
from ahriman.models.repository_id import RepositoryId
from ahriman.models.repository_paths import RepositoryPaths from ahriman.models.repository_paths import RepositoryPaths
from ahriman.models.sign_settings import SignSettings from ahriman.models.sign_settings import SignSettings
@ -24,14 +25,12 @@ def _default_args(args: argparse.Namespace) -> argparse.Namespace:
argparse.Namespace: generated arguments for these test cases argparse.Namespace: generated arguments for these test cases
""" """
args.build_as_user = "ahriman" args.build_as_user = "ahriman"
args.build_command = "ahriman"
args.from_configuration = Path("/usr/share/devtools/pacman.conf.d/extra.conf") args.from_configuration = Path("/usr/share/devtools/pacman.conf.d/extra.conf")
args.generate_salt = True args.generate_salt = True
args.makeflags_jobs = True args.makeflags_jobs = True
args.mirror = "mirror" args.mirror = "mirror"
args.multilib = True args.multilib = True
args.packager = "John Doe <john@doe.com>" args.packager = "John Doe <john@doe.com>"
args.repository = "aur-clone"
args.server = None args.server = None
args.sign_key = "key" args.sign_key = "key"
args.sign_target = [SignSettings.Packages] args.sign_target = [SignSettings.Packages]
@ -54,14 +53,14 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
executable_mock = mocker.patch("ahriman.application.handlers.Setup.executable_create") executable_mock = mocker.patch("ahriman.application.handlers.Setup.executable_create")
init_mock = mocker.patch("ahriman.core.alpm.repo.Repo.init") init_mock = mocker.patch("ahriman.core.alpm.repo.Repo.init")
Setup.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
ahriman_configuration_mock.assert_called_once_with(args, "x86_64", args.repository, configuration) Setup.run(args, repository_id, configuration, report=False)
ahriman_configuration_mock.assert_called_once_with(args, repository_id, configuration)
devtools_configuration_mock.assert_called_once_with( devtools_configuration_mock.assert_called_once_with(
args.build_command, "x86_64", args.from_configuration, args.mirror, args.multilib, args.repository, repository_id, args.from_configuration, args.mirror, args.multilib, f"file://{repository_paths.repository}")
f"file://{repository_paths.repository}")
makepkg_configuration_mock.assert_called_once_with(args.packager, args.makeflags_jobs, repository_paths) makepkg_configuration_mock.assert_called_once_with(args.packager, args.makeflags_jobs, repository_paths)
sudo_configuration_mock.assert_called_once_with(repository_paths, args.build_command, "x86_64") sudo_configuration_mock.assert_called_once_with(repository_paths, repository_id)
executable_mock.assert_called_once_with(repository_paths, args.build_command, "x86_64") executable_mock.assert_called_once_with(repository_paths, repository_id)
init_mock.assert_called_once_with() init_mock.assert_called_once_with()
@ -80,21 +79,20 @@ def test_run_with_server(args: argparse.Namespace, configuration: Configuration,
mocker.patch("ahriman.core.alpm.repo.Repo.init") mocker.patch("ahriman.core.alpm.repo.Repo.init")
devtools_configuration_mock = mocker.patch("ahriman.application.handlers.Setup.configuration_create_devtools") devtools_configuration_mock = mocker.patch("ahriman.application.handlers.Setup.configuration_create_devtools")
Setup.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Setup.run(args, repository_id, configuration, report=False)
devtools_configuration_mock.assert_called_once_with( devtools_configuration_mock.assert_called_once_with(
args.build_command, "x86_64", args.from_configuration, args.mirror, args.multilib, args.repository, repository_id, args.from_configuration, args.mirror, args.multilib, "server")
"server")
def test_build_command(args: argparse.Namespace) -> None: def test_build_command(repository_id: RepositoryId) -> None:
""" """
must generate correct build command name must generate correct build command name
""" """
args = _default_args(args)
path = Path("local") path = Path("local")
build_command = Setup.build_command(path, args.build_command, "x86_64") build_command = Setup.build_command(path, repository_id)
assert build_command.name == f"{args.build_command}-x86_64-build" assert build_command.name == f"{repository_id.name}-{repository_id.architecture}-build"
assert build_command.parent == path assert build_command.parent == path
@ -107,19 +105,26 @@ def test_configuration_create_ahriman(args: argparse.Namespace, configuration: C
mocker.patch("pathlib.Path.open") mocker.patch("pathlib.Path.open")
set_option_mock = mocker.patch("ahriman.core.configuration.Configuration.set_option") set_option_mock = mocker.patch("ahriman.core.configuration.Configuration.set_option")
write_mock = mocker.patch("ahriman.core.configuration.Configuration.write") write_mock = mocker.patch("ahriman.core.configuration.Configuration.write")
command = Setup.build_command(repository_paths.root, args.build_command, "x86_64") _, repository_id = configuration.check_loaded()
command = Setup.build_command(repository_paths.root, repository_id)
Setup.configuration_create_ahriman(args, "x86_64", args.repository, configuration) Setup.configuration_create_ahriman(args, repository_id, configuration)
set_option_mock.assert_has_calls([ set_option_mock.assert_has_calls([
MockCall(Configuration.section_name("build", "x86_64"), "build_command", str(command)), MockCall(Configuration.section_name("build", repository_id.name, repository_id.architecture), "build_command",
MockCall("repository", "name", args.repository), str(command)),
MockCall(Configuration.section_name("build", "x86_64"), "makechrootpkg_flags", f"-U {args.build_as_user}"), MockCall("repository", "name", repository_id.name),
MockCall(Configuration.section_name("alpm", "x86_64"), "mirror", args.mirror), MockCall(Configuration.section_name("build", repository_id.name, repository_id.architecture),
MockCall(Configuration.section_name("sign", "x86_64"), "target", "makechrootpkg_flags", f"-U {args.build_as_user}"),
MockCall(Configuration.section_name(
"alpm", repository_id.name, repository_id.architecture), "mirror", args.mirror),
MockCall(Configuration.section_name("sign", repository_id.name, repository_id.architecture), "target",
" ".join([target.name.lower() for target in args.sign_target])), " ".join([target.name.lower() for target in args.sign_target])),
MockCall(Configuration.section_name("sign", "x86_64"), "key", args.sign_key), MockCall(Configuration.section_name("sign", repository_id.name, repository_id.architecture), "key",
MockCall(Configuration.section_name("web", "x86_64"), "port", str(args.web_port)), args.sign_key),
MockCall(Configuration.section_name("web", "x86_64"), "unix_socket", str(args.web_unix_socket)), MockCall(Configuration.section_name("web", repository_id.name, repository_id.architecture), "port",
str(args.web_port)),
MockCall(Configuration.section_name("web", repository_id.name, repository_id.architecture), "unix_socket",
str(args.web_unix_socket)),
MockCall("auth", "salt", pytest.helpers.anyvar(str, strict=True)), MockCall("auth", "salt", pytest.helpers.anyvar(str, strict=True)),
]) ])
write_mock.assert_called_once_with(pytest.helpers.anyvar(int)) write_mock.assert_called_once_with(pytest.helpers.anyvar(int))
@ -136,13 +141,16 @@ def test_configuration_create_ahriman_no_multilib(args: argparse.Namespace, conf
mocker.patch("ahriman.core.configuration.Configuration.write") mocker.patch("ahriman.core.configuration.Configuration.write")
set_option_mock = mocker.patch("ahriman.core.configuration.Configuration.set_option") set_option_mock = mocker.patch("ahriman.core.configuration.Configuration.set_option")
Setup.configuration_create_ahriman(args, "x86_64", args.repository, configuration) _, repository_id = configuration.check_loaded()
Setup.configuration_create_ahriman(args, repository_id, configuration)
set_option_mock.assert_has_calls([ set_option_mock.assert_has_calls([
MockCall(Configuration.section_name("alpm", "x86_64"), "mirror", args.mirror), MockCall(Configuration.section_name("alpm", repository_id.name, repository_id.architecture), "mirror",
args.mirror),
]) # non-strict check called intentionally ]) # non-strict check called intentionally
def test_configuration_create_devtools(args: argparse.Namespace, mocker: MockerFixture) -> None: def test_configuration_create_devtools(args: argparse.Namespace, configuration: Configuration,
mocker: MockerFixture) -> None:
""" """
must create configuration for the devtools must create configuration for the devtools
""" """
@ -152,13 +160,14 @@ def test_configuration_create_devtools(args: argparse.Namespace, mocker: MockerF
add_section_mock = mocker.patch("ahriman.core.configuration.Configuration.add_section") add_section_mock = mocker.patch("ahriman.core.configuration.Configuration.add_section")
write_mock = mocker.patch("ahriman.core.configuration.Configuration.write") write_mock = mocker.patch("ahriman.core.configuration.Configuration.write")
Setup.configuration_create_devtools(args.build_command, "x86_64", args.from_configuration, _, repository_id = configuration.check_loaded()
None, args.multilib, args.repository, "server") Setup.configuration_create_devtools(repository_id, args.from_configuration, None, args.multilib, "server")
add_section_mock.assert_has_calls([MockCall("multilib"), MockCall(args.repository)]) add_section_mock.assert_has_calls([MockCall("multilib"), MockCall(repository_id.name)])
write_mock.assert_called_once_with(pytest.helpers.anyvar(int)) write_mock.assert_called_once_with(pytest.helpers.anyvar(int))
def test_configuration_create_devtools_mirror(args: argparse.Namespace, mocker: MockerFixture) -> None: def test_configuration_create_devtools_mirror(args: argparse.Namespace, configuration: Configuration,
mocker: MockerFixture) -> None:
""" """
must create configuration for the devtools with mirror set explicitly must create configuration for the devtools with mirror set explicitly
""" """
@ -176,14 +185,15 @@ def test_configuration_create_devtools_mirror(args: argparse.Namespace, mocker:
remove_option_mock = mocker.patch("ahriman.core.configuration.Configuration.remove_option") remove_option_mock = mocker.patch("ahriman.core.configuration.Configuration.remove_option")
set_option_mock = mocker.patch("ahriman.core.configuration.Configuration.set_option") set_option_mock = mocker.patch("ahriman.core.configuration.Configuration.set_option")
Setup.configuration_create_devtools(args.build_command, "x86_64", args.from_configuration, _, repository_id = configuration.check_loaded()
args.mirror, False, args.repository, "server") Setup.configuration_create_devtools(repository_id, args.from_configuration, args.mirror, args.multilib, "server")
get_mock.assert_has_calls([MockCall("core", "Include", fallback=None), MockCall("extra", "Include", fallback=None)]) get_mock.assert_has_calls([MockCall("core", "Include", fallback=None), MockCall("extra", "Include", fallback=None)])
remove_option_mock.assert_called_once_with("core", "Include") remove_option_mock.assert_called_once_with("core", "Include")
set_option_mock.assert_has_calls([MockCall("core", "Server", args.mirror)]) # non-strict check called intentionally set_option_mock.assert_has_calls([MockCall("core", "Server", args.mirror)]) # non-strict check called intentionally
def test_configuration_create_devtools_no_multilib(args: argparse.Namespace, mocker: MockerFixture) -> None: def test_configuration_create_devtools_no_multilib(args: argparse.Namespace, configuration: Configuration,
mocker: MockerFixture) -> None:
""" """
must create configuration for the devtools without multilib must create configuration for the devtools without multilib
""" """
@ -192,8 +202,8 @@ def test_configuration_create_devtools_no_multilib(args: argparse.Namespace, moc
mocker.patch("ahriman.core.configuration.Configuration.set") mocker.patch("ahriman.core.configuration.Configuration.set")
write_mock = mocker.patch("ahriman.core.configuration.Configuration.write") write_mock = mocker.patch("ahriman.core.configuration.Configuration.write")
Setup.configuration_create_devtools(args.build_command, "x86_64", args.from_configuration, _, repository_id = configuration.check_loaded()
None, False, args.repository, "server") Setup.configuration_create_devtools(repository_id, args.from_configuration, args.mirror, False, "server")
write_mock.assert_called_once_with(pytest.helpers.anyvar(int)) write_mock.assert_called_once_with(pytest.helpers.anyvar(int))
@ -211,31 +221,32 @@ def test_configuration_create_makepkg(args: argparse.Namespace, repository_paths
Path("home") / ".makepkg.conf", pytest.helpers.anyvar(str, True), encoding="utf8") Path("home") / ".makepkg.conf", pytest.helpers.anyvar(str, True), encoding="utf8")
def test_configuration_create_sudo(args: argparse.Namespace, repository_paths: RepositoryPaths, def test_configuration_create_sudo(configuration: Configuration, repository_paths: RepositoryPaths,
mocker: MockerFixture) -> None: mocker: MockerFixture) -> None:
""" """
must create sudo configuration must create sudo configuration
""" """
args = _default_args(args)
chmod_text_mock = mocker.patch("pathlib.Path.chmod") chmod_text_mock = mocker.patch("pathlib.Path.chmod")
write_text_mock = mocker.patch("pathlib.Path.write_text") write_text_mock = mocker.patch("pathlib.Path.write_text")
Setup.configuration_create_sudo(repository_paths, args.build_command, "x86_64") _, repository_id = configuration.check_loaded()
Setup.configuration_create_sudo(repository_paths, repository_id)
chmod_text_mock.assert_called_once_with(0o400) chmod_text_mock.assert_called_once_with(0o400)
write_text_mock.assert_called_once_with(pytest.helpers.anyvar(str, True), encoding="utf8") write_text_mock.assert_called_once_with(pytest.helpers.anyvar(str, True), encoding="utf8")
def test_executable_create(args: argparse.Namespace, repository_paths: RepositoryPaths, mocker: MockerFixture) -> None: def test_executable_create(configuration: Configuration, repository_paths: RepositoryPaths,
mocker: MockerFixture) -> None:
""" """
must create executable must create executable
""" """
args = _default_args(args)
chown_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.chown") chown_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.chown")
symlink_mock = mocker.patch("pathlib.Path.symlink_to") symlink_mock = mocker.patch("pathlib.Path.symlink_to")
unlink_mock = mocker.patch("pathlib.Path.unlink") unlink_mock = mocker.patch("pathlib.Path.unlink")
Setup.executable_create(repository_paths, args.build_command, "x86_64") _, repository_id = configuration.check_loaded()
chown_mock.assert_called_once_with(Setup.build_command(repository_paths.root, args.build_command, "x86_64")) Setup.executable_create(repository_paths, repository_id)
chown_mock.assert_called_once_with(Setup.build_command(repository_paths.root, repository_id))
symlink_mock.assert_called_once_with(Setup.ARCHBUILD_COMMAND_PATH) symlink_mock.assert_called_once_with(Setup.ARCHBUILD_COMMAND_PATH)
unlink_mock.assert_called_once_with(missing_ok=True) unlink_mock.assert_called_once_with(missing_ok=True)

View File

@ -32,7 +32,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository) mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
application_mock = mocker.patch("code.interact") application_mock = mocker.patch("code.interact")
Shell.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Shell.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with(local=pytest.helpers.anyvar(int)) application_mock.assert_called_once_with(local=pytest.helpers.anyvar(int))
@ -46,7 +47,8 @@ def test_run_eval(args: argparse.Namespace, configuration: Configuration, reposi
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository) mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
application_mock = mocker.patch("code.InteractiveConsole.runcode") application_mock = mocker.patch("code.InteractiveConsole.runcode")
Shell.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Shell.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with(args.code) application_mock.assert_called_once_with(args.code)
@ -62,7 +64,8 @@ def test_run_verbose(args: argparse.Namespace, configuration: Configuration, rep
print_mock = mocker.patch("ahriman.core.formatters.Printer.print") print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
application_mock = mocker.patch("code.interact") application_mock = mocker.patch("code.interact")
Shell.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Shell.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with(local=pytest.helpers.anyvar(int)) application_mock.assert_called_once_with(local=pytest.helpers.anyvar(int))
read_mock.assert_called_once_with(encoding="utf8") read_mock.assert_called_once_with(encoding="utf8")
print_mock.assert_called_once_with(verbose=False) print_mock.assert_called_once_with(verbose=False)

View File

@ -30,5 +30,6 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository) mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
application_mock = mocker.patch("ahriman.application.application.Application.sign") application_mock = mocker.patch("ahriman.application.application.Application.sign")
Sign.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Sign.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with([]) application_mock.assert_called_once_with([])

View File

@ -43,7 +43,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty") check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
print_mock = mocker.patch("ahriman.core.formatters.Printer.print") print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
Status.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Status.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with() application_mock.assert_called_once_with()
packages_mock.assert_called_once_with(None) packages_mock.assert_called_once_with(None)
check_mock.assert_called_once_with(False, False) check_mock.assert_called_once_with(False, False)
@ -62,7 +63,8 @@ def test_run_empty_exception(args: argparse.Namespace, configuration: Configurat
mocker.patch("ahriman.core.status.client.Client.package_get", return_value=[]) mocker.patch("ahriman.core.status.client.Client.package_get", return_value=[])
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty") check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
Status.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Status.run(args, repository_id, configuration, report=False)
check_mock.assert_called_once_with(True, True) check_mock.assert_called_once_with(True, True)
@ -78,7 +80,8 @@ def test_run_verbose(args: argparse.Namespace, configuration: Configuration, rep
return_value=[(package_ahriman, BuildStatus(BuildStatusEnum.Success))]) return_value=[(package_ahriman, BuildStatus(BuildStatusEnum.Success))])
print_mock = mocker.patch("ahriman.core.formatters.Printer.print") print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
Status.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Status.run(args, repository_id, configuration, report=False)
print_mock.assert_has_calls([MockCall(verbose=True) for _ in range(2)]) print_mock.assert_has_calls([MockCall(verbose=True) for _ in range(2)])
@ -93,7 +96,8 @@ def test_run_with_package_filter(args: argparse.Namespace, configuration: Config
packages_mock = mocker.patch("ahriman.core.status.client.Client.package_get", packages_mock = mocker.patch("ahriman.core.status.client.Client.package_get",
return_value=[(package_ahriman, BuildStatus(BuildStatusEnum.Success))]) return_value=[(package_ahriman, BuildStatus(BuildStatusEnum.Success))])
Status.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Status.run(args, repository_id, configuration, report=False)
packages_mock.assert_called_once_with(package_ahriman.base) packages_mock.assert_called_once_with(package_ahriman.base)
@ -110,7 +114,8 @@ def test_run_by_status(args: argparse.Namespace, configuration: Configuration, r
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository) mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
print_mock = mocker.patch("ahriman.core.formatters.Printer.print") print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
Status.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Status.run(args, repository_id, configuration, report=False)
print_mock.assert_has_calls([MockCall(verbose=False) for _ in range(2)]) print_mock.assert_has_calls([MockCall(verbose=False) for _ in range(2)])
@ -123,8 +128,9 @@ def test_imply_with_report(args: argparse.Namespace, configuration: Configuratio
mocker.patch("ahriman.core.database.SQLite.load", return_value=database) mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
load_mock = mocker.patch("ahriman.core.repository.Repository.load") load_mock = mocker.patch("ahriman.core.repository.Repository.load")
Status.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
load_mock.assert_called_once_with("x86_64", configuration, database, report=True, refresh_pacman_database=0) Status.run(args, repository_id, configuration, report=False)
load_mock.assert_called_once_with(repository_id, configuration, database, report=True, refresh_pacman_database=0)
def test_disallow_auto_architecture_run() -> None: def test_disallow_auto_architecture_run() -> None:

View File

@ -36,7 +36,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository) mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
update_self_mock = mocker.patch("ahriman.core.status.client.Client.status_update") update_self_mock = mocker.patch("ahriman.core.status.client.Client.status_update")
StatusUpdate.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
StatusUpdate.run(args, repository_id, configuration, report=False)
update_self_mock.assert_called_once_with(args.status) update_self_mock.assert_called_once_with(args.status)
@ -50,7 +51,8 @@ def test_run_packages(args: argparse.Namespace, configuration: Configuration, re
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository) mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
update_mock = mocker.patch("ahriman.core.status.client.Client.package_update") update_mock = mocker.patch("ahriman.core.status.client.Client.package_update")
StatusUpdate.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
StatusUpdate.run(args, repository_id, configuration, report=False)
update_mock.assert_called_once_with(package_ahriman.base, args.status) update_mock.assert_called_once_with(package_ahriman.base, args.status)
@ -65,7 +67,8 @@ def test_run_remove(args: argparse.Namespace, configuration: Configuration, repo
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository) mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
update_mock = mocker.patch("ahriman.core.status.client.Client.package_remove") update_mock = mocker.patch("ahriman.core.status.client.Client.package_remove")
StatusUpdate.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
StatusUpdate.run(args, repository_id, configuration, report=False)
update_mock.assert_called_once_with(package_ahriman.base) update_mock.assert_called_once_with(package_ahriman.base)
@ -78,8 +81,9 @@ def test_imply_with_report(args: argparse.Namespace, configuration: Configuratio
mocker.patch("ahriman.core.database.SQLite.load", return_value=database) mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
load_mock = mocker.patch("ahriman.core.repository.Repository.load") load_mock = mocker.patch("ahriman.core.repository.Repository.load")
StatusUpdate.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
load_mock.assert_called_once_with("x86_64", configuration, database, report=True, refresh_pacman_database=0) StatusUpdate.run(args, repository_id, configuration, report=False)
load_mock.assert_called_once_with(repository_id, configuration, database, report=True, refresh_pacman_database=0)
def test_disallow_auto_architecture_run() -> None: def test_disallow_auto_architecture_run() -> None:

View File

@ -35,7 +35,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
application_mock = mocker.patch("ahriman.core.tree.Tree.resolve", return_value=[[package_ahriman]]) application_mock = mocker.patch("ahriman.core.tree.Tree.resolve", return_value=[[package_ahriman]])
print_mock = mocker.patch("ahriman.core.formatters.Printer.print") print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
Structure.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Structure.run(args, repository_id, configuration, report=False)
packages_mock.assert_called_once_with([package_ahriman], count=args.partitions) packages_mock.assert_called_once_with([package_ahriman], count=args.partitions)
application_mock.assert_called_once_with([package_ahriman]) application_mock.assert_called_once_with([package_ahriman])
print_mock.assert_has_calls([ print_mock.assert_has_calls([

View File

@ -33,7 +33,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
application_mock = mocker.patch("ahriman.application.application.Application.on_result") application_mock = mocker.patch("ahriman.application.application.Application.on_result")
on_start_mock = mocker.patch("ahriman.application.application.Application.on_start") on_start_mock = mocker.patch("ahriman.application.application.Application.on_start")
Triggers.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Triggers.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with(Result()) application_mock.assert_called_once_with(Result())
on_start_mock.assert_called_once_with() on_start_mock.assert_called_once_with()
@ -50,6 +51,7 @@ def test_run_trigger(args: argparse.Namespace, configuration: Configuration, rep
report_mock = mocker.patch("ahriman.core.report.ReportTrigger.on_result") report_mock = mocker.patch("ahriman.core.report.ReportTrigger.on_result")
upload_mock = mocker.patch("ahriman.core.upload.UploadTrigger.on_result") upload_mock = mocker.patch("ahriman.core.upload.UploadTrigger.on_result")
Triggers.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Triggers.run(args, repository_id, configuration, report=False)
report_mock.assert_called_once_with(Result(), [package_ahriman]) report_mock.assert_called_once_with(Result(), [package_ahriman])
upload_mock.assert_not_called() upload_mock.assert_not_called()

View File

@ -32,7 +32,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
return_value=["command"]) return_value=["command"])
print_mock = mocker.patch("ahriman.core.formatters.Printer.print") print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
UnsafeCommands.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
UnsafeCommands.run(args, repository_id, configuration, report=False)
commands_mock.assert_called_once_with(pytest.helpers.anyvar(int)) commands_mock.assert_called_once_with(pytest.helpers.anyvar(int))
print_mock.assert_called_once_with(verbose=True) print_mock.assert_called_once_with(verbose=True)
@ -47,7 +48,8 @@ def test_run_check(args: argparse.Namespace, configuration: Configuration, mocke
return_value=["command"]) return_value=["command"])
check_mock = mocker.patch("ahriman.application.handlers.UnsafeCommands.check_unsafe") check_mock = mocker.patch("ahriman.application.handlers.UnsafeCommands.check_unsafe")
UnsafeCommands.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
UnsafeCommands.run(args, repository_id, configuration, report=False)
commands_mock.assert_called_once_with(pytest.helpers.anyvar(int)) commands_mock.assert_called_once_with(pytest.helpers.anyvar(int))
check_mock.assert_called_once_with(["clean"], ["command"], pytest.helpers.anyvar(int)) check_mock.assert_called_once_with(["clean"], ["command"], pytest.helpers.anyvar(int))

View File

@ -54,7 +54,8 @@ def test_run(args: argparse.Namespace, package_ahriman: Package, configuration:
on_start_mock = mocker.patch("ahriman.application.application.Application.on_start") on_start_mock = mocker.patch("ahriman.application.application.Application.on_start")
print_mock = mocker.patch("ahriman.application.application.Application.print_updates") print_mock = mocker.patch("ahriman.application.application.Application.print_updates")
Update.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Update.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with([package_ahriman], application_mock.assert_called_once_with([package_ahriman],
Packagers(args.username, {package_ahriman.base: "packager"}), Packagers(args.username, {package_ahriman.base: "packager"}),
bump_pkgrel=args.increment) bump_pkgrel=args.increment)
@ -77,7 +78,8 @@ def test_run_empty_exception(args: argparse.Namespace, configuration: Configurat
mocker.patch("ahriman.application.application.Application.updates", return_value=[]) mocker.patch("ahriman.application.application.Application.updates", return_value=[])
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty") check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
Update.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Update.run(args, repository_id, configuration, report=False)
check_mock.assert_called_once_with(True, True) check_mock.assert_called_once_with(True, True)
@ -95,7 +97,8 @@ def test_run_update_empty_exception(args: argparse.Namespace, package_ahriman: P
mocker.patch("ahriman.application.application.Application.print_updates") mocker.patch("ahriman.application.application.Application.print_updates")
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty") check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
Update.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Update.run(args, repository_id, configuration, report=False)
check_mock.assert_has_calls([MockCall(True, False), MockCall(True, True)]) check_mock.assert_has_calls([MockCall(True, False), MockCall(True, True)])
@ -111,7 +114,8 @@ def test_run_dry_run(args: argparse.Namespace, configuration: Configuration, rep
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty") check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
updates_mock = mocker.patch("ahriman.application.application.Application.updates") updates_mock = mocker.patch("ahriman.application.application.Application.updates")
Update.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Update.run(args, repository_id, configuration, report=False)
updates_mock.assert_called_once_with(args.package, aur=args.aur, local=args.local, manual=args.manual, vcs=args.vcs) updates_mock.assert_called_once_with(args.package, aur=args.aur, local=args.local, manual=args.manual, vcs=args.vcs)
application_mock.assert_not_called() application_mock.assert_not_called()
check_mock.assert_called_once_with(False, pytest.helpers.anyvar(int)) check_mock.assert_called_once_with(False, pytest.helpers.anyvar(int))

View File

@ -47,7 +47,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, database: S
create_user_mock = mocker.patch("ahriman.application.handlers.Users.user_create", return_value=user) create_user_mock = mocker.patch("ahriman.application.handlers.Users.user_create", return_value=user)
update_mock = mocker.patch("ahriman.core.database.SQLite.user_update") update_mock = mocker.patch("ahriman.core.database.SQLite.user_update")
Users.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Users.run(args, repository_id, configuration, report=False)
create_user_mock.assert_called_once_with(args) create_user_mock.assert_called_once_with(args)
update_mock.assert_called_once_with(user) update_mock.assert_called_once_with(user)
@ -64,7 +65,8 @@ def test_run_empty_salt(args: argparse.Namespace, configuration: Configuration,
create_user_mock = mocker.patch("ahriman.application.handlers.Users.user_create", return_value=user) create_user_mock = mocker.patch("ahriman.application.handlers.Users.user_create", return_value=user)
update_mock = mocker.patch("ahriman.core.database.SQLite.user_update") update_mock = mocker.patch("ahriman.core.database.SQLite.user_update")
Users.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Users.run(args, repository_id, configuration, report=False)
create_user_mock.assert_called_once_with(args) create_user_mock.assert_called_once_with(args)
update_mock.assert_called_once_with(user) update_mock.assert_called_once_with(user)
@ -83,7 +85,8 @@ def test_run_empty_salt_without_password(args: argparse.Namespace, configuration
create_user_mock = mocker.patch("ahriman.application.handlers.Users.user_create", return_value=user) create_user_mock = mocker.patch("ahriman.application.handlers.Users.user_create", return_value=user)
update_mock = mocker.patch("ahriman.core.database.SQLite.user_update") update_mock = mocker.patch("ahriman.core.database.SQLite.user_update")
Users.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Users.run(args, repository_id, configuration, report=False)
create_user_mock.assert_called_once_with(args) create_user_mock.assert_called_once_with(args)
update_mock.assert_called_once_with(user) update_mock.assert_called_once_with(user)
@ -99,7 +102,8 @@ def test_run_list(args: argparse.Namespace, configuration: Configuration, databa
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty") check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
list_mock = mocker.patch("ahriman.core.database.SQLite.user_list", return_value=[user]) list_mock = mocker.patch("ahriman.core.database.SQLite.user_list", return_value=[user])
Users.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Users.run(args, repository_id, configuration, report=False)
list_mock.assert_called_once_with("user", args.role) list_mock.assert_called_once_with("user", args.role)
check_mock.assert_called_once_with(False, False) check_mock.assert_called_once_with(False, False)
@ -116,7 +120,8 @@ def test_run_empty_exception(args: argparse.Namespace, configuration: Configurat
mocker.patch("ahriman.core.database.SQLite.user_list", return_value=[]) mocker.patch("ahriman.core.database.SQLite.user_list", return_value=[])
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty") check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
Users.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Users.run(args, repository_id, configuration, report=False)
check_mock.assert_called_once_with(True, True) check_mock.assert_called_once_with(True, True)
@ -130,7 +135,8 @@ def test_run_remove(args: argparse.Namespace, configuration: Configuration, data
mocker.patch("ahriman.core.database.SQLite.load", return_value=database) mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
remove_mock = mocker.patch("ahriman.core.database.SQLite.user_remove") remove_mock = mocker.patch("ahriman.core.database.SQLite.user_remove")
Users.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Users.run(args, repository_id, configuration, report=False)
remove_mock.assert_called_once_with(args.username) remove_mock.assert_called_once_with(args.username)

View File

@ -33,8 +33,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
print_mock = mocker.patch("ahriman.core.formatters.Printer.print") print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
application_mock = mocker.patch("ahriman.core.configuration.validator.Validator.validate", return_value=False) application_mock = mocker.patch("ahriman.core.configuration.validator.Validator.validate", return_value=False)
Validate.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Validate.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with(configuration.dump()) application_mock.assert_called_once_with(configuration.dump())
print_mock.assert_called_once_with(verbose=True) print_mock.assert_called_once_with(verbose=True)
@ -47,7 +47,8 @@ def test_run_skip(args: argparse.Namespace, configuration: Configuration, mocker
mocker.patch("ahriman.core.configuration.validator.Validator.validate", return_value=True) mocker.patch("ahriman.core.configuration.validator.Validator.validate", return_value=True)
print_mock = mocker.patch("ahriman.core.formatters.Printer.print") print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
Validate.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Validate.run(args, repository_id, configuration, report=False)
print_mock.assert_not_called() print_mock.assert_not_called()
@ -55,7 +56,8 @@ def test_schema(configuration: Configuration) -> None:
""" """
must generate full schema correctly must generate full schema correctly
""" """
schema = Validate.schema("x86_64", configuration) _, repository_id = configuration.check_loaded()
schema = Validate.schema(repository_id, configuration)
# defaults # defaults
assert schema.pop("console") assert schema.pop("console")
@ -86,7 +88,9 @@ def test_schema_invalid_trigger(configuration: Configuration) -> None:
""" """
configuration.set_option("build", "triggers", "some.invalid.trigger.path.Trigger") configuration.set_option("build", "triggers", "some.invalid.trigger.path.Trigger")
configuration.remove_option("build", "triggers_known") configuration.remove_option("build", "triggers_known")
assert Validate.schema("x86_64", configuration) == CONFIGURATION_SCHEMA _, repository_id = configuration.check_loaded()
assert Validate.schema(repository_id, configuration) == CONFIGURATION_SCHEMA
def test_schema_erase_required() -> None: def test_schema_erase_required() -> None:

View File

@ -14,7 +14,8 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
application_mock = mocker.patch("ahriman.application.handlers.Versions.package_dependencies") application_mock = mocker.patch("ahriman.application.handlers.Versions.package_dependencies")
print_mock = mocker.patch("ahriman.core.formatters.Printer.print") print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
Versions.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
Versions.run(args, repository_id, configuration, report=False)
application_mock.assert_called_once_with("ahriman") application_mock.assert_called_once_with("ahriman")
print_mock.assert_has_calls([MockCall(verbose=False, separator=" "), MockCall(verbose=False, separator=" ")]) print_mock.assert_has_calls([MockCall(verbose=False, separator=" "), MockCall(verbose=False, separator=" ")])

View File

@ -41,8 +41,9 @@ def test_run(args: argparse.Namespace, configuration: Configuration, repository:
stop_mock = mocker.patch("ahriman.core.spawn.Spawn.stop") stop_mock = mocker.patch("ahriman.core.spawn.Spawn.stop")
join_mock = mocker.patch("ahriman.core.spawn.Spawn.join") join_mock = mocker.patch("ahriman.core.spawn.Spawn.join")
Web.run(args, "x86_64", configuration, report=False) _, repository_id = configuration.check_loaded()
setup_mock.assert_called_once_with("x86_64", configuration, pytest.helpers.anyvar(int)) Web.run(args, repository_id, configuration, report=False)
setup_mock.assert_called_once_with(repository_id, configuration, pytest.helpers.anyvar(int))
run_mock.assert_called_once_with(pytest.helpers.anyvar(int)) run_mock.assert_called_once_with(pytest.helpers.anyvar(int))
start_mock.assert_called_once_with() start_mock.assert_called_once_with()
stop_mock.assert_called_once_with() stop_mock.assert_called_once_with()
@ -53,33 +54,35 @@ def test_extract_arguments(args: argparse.Namespace, configuration: Configuratio
""" """
must extract correct args must extract correct args
""" """
_, repository_id = configuration.check_loaded()
expected = [ expected = [
"--architecture", "x86_64", "--architecture", repository_id.architecture,
"--repository", repository_id.name,
"--configuration", str(configuration.path), "--configuration", str(configuration.path),
] ]
probe = _default_args(args) probe = _default_args(args)
assert list(Web.extract_arguments(probe, "x86_64", configuration)) == expected assert list(Web.extract_arguments(probe, repository_id, configuration)) == expected
probe.force = True probe.force = True
expected.extend(["--force"]) expected.extend(["--force"])
assert list(Web.extract_arguments(probe, "x86_64", configuration)) == expected assert list(Web.extract_arguments(probe, repository_id, configuration)) == expected
probe.log_handler = LogHandler.Console probe.log_handler = LogHandler.Console
expected.extend(["--log-handler", probe.log_handler.value]) expected.extend(["--log-handler", probe.log_handler.value])
assert list(Web.extract_arguments(probe, "x86_64", configuration)) == expected assert list(Web.extract_arguments(probe, repository_id, configuration)) == expected
probe.quiet = True probe.quiet = True
expected.extend(["--quiet"]) expected.extend(["--quiet"])
assert list(Web.extract_arguments(probe, "x86_64", configuration)) == expected assert list(Web.extract_arguments(probe, repository_id, configuration)) == expected
probe.unsafe = True probe.unsafe = True
expected.extend(["--unsafe"]) expected.extend(["--unsafe"])
assert list(Web.extract_arguments(probe, "x86_64", configuration)) == expected assert list(Web.extract_arguments(probe, repository_id, configuration)) == expected
configuration.set_option("web", "wait_timeout", "60") configuration.set_option("web", "wait_timeout", "60")
expected.extend(["--wait-timeout", "60"]) expected.extend(["--wait-timeout", "60"])
assert list(Web.extract_arguments(probe, "x86_64", configuration)) == expected assert list(Web.extract_arguments(probe, repository_id, configuration)) == expected
def test_extract_arguments_full(parser: argparse.ArgumentParser, configuration: Configuration): def test_extract_arguments_full(parser: argparse.ArgumentParser, configuration: Configuration):
@ -101,8 +104,10 @@ def test_extract_arguments_full(parser: argparse.ArgumentParser, configuration:
value = action.type(value) value = action.type(value)
setattr(args, action.dest, value) setattr(args, action.dest, value)
assert list(Web.extract_arguments(args, "x86_64", configuration)) == [ _, repository_id = configuration.check_loaded()
"--architecture", "x86_64", assert list(Web.extract_arguments(args, repository_id, configuration)) == [
"--architecture", repository_id.architecture,
"--repository", repository_id.name,
"--configuration", str(configuration.path), "--configuration", str(configuration.path),
"--force", "--force",
"--log-handler", "console", "--log-handler", "console",

View File

@ -5,6 +5,7 @@ from pytest_mock import MockerFixture
from ahriman.application import ahriman from ahriman.application import ahriman
from ahriman.application.handlers import Handler from ahriman.application.handlers import Handler
from ahriman.core.configuration import Configuration
from ahriman.models.action import Action from ahriman.models.action import Action
from ahriman.models.build_status import BuildStatusEnum from ahriman.models.build_status import BuildStatusEnum
from ahriman.models.log_handler import LogHandler from ahriman.models.log_handler import LogHandler
@ -65,6 +66,14 @@ def test_multiple_architectures(parser: argparse.ArgumentParser) -> None:
assert args.architecture == ["x86_64", "i686"] assert args.architecture == ["x86_64", "i686"]
def test_multiple_repositories(parser: argparse.ArgumentParser) -> None:
"""
must accept multiple architectures
"""
args = parser.parse_args(["-r", "repo1", "-r", "repo2", "service-config"])
assert args.repository == ["repo1", "repo2"]
def test_subparsers_aur_search(parser: argparse.ArgumentParser) -> None: def test_subparsers_aur_search(parser: argparse.ArgumentParser) -> None:
""" """
aur-search command must imply architecture list, lock, report, quiet and unsafe aur-search command must imply architecture list, lock, report, quiet and unsafe
@ -707,8 +716,7 @@ def test_subparsers_service_setup(parser: argparse.ArgumentParser) -> None:
""" """
service-setup command must imply lock, report, quiet and unsafe service-setup command must imply lock, report, quiet and unsafe
""" """
args = parser.parse_args(["-a", "x86_64", "service-setup", "--packager", "John Doe <john@doe.com>", args = parser.parse_args(["-a", "x86_64", "service-setup", "--packager", "John Doe <john@doe.com>"])
"--repository", "aur-clone"])
assert args.architecture == ["x86_64"] assert args.architecture == ["x86_64"]
assert args.lock is None assert args.lock is None
assert not args.report assert not args.report
@ -720,11 +728,10 @@ def test_subparsers_service_setup_option_from_configuration(parser: argparse.Arg
""" """
service-setup command must convert from-configuration option to path instance service-setup command must convert from-configuration option to path instance
""" """
args = parser.parse_args(["-a", "x86_64", "service-setup", "--packager", "John Doe <john@doe.com>", args = parser.parse_args(["-a", "x86_64", "service-setup", "--packager", "John Doe <john@doe.com>"])
"--repository", "aur-clone"])
assert isinstance(args.from_configuration, Path) assert isinstance(args.from_configuration, Path)
args = parser.parse_args(["-a", "x86_64", "service-setup", "--packager", "John Doe <john@doe.com>", args = parser.parse_args(["-a", "x86_64", "service-setup", "--packager", "John Doe <john@doe.com>",
"--repository", "aur-clone", "--from-configuration", "path"]) "--from-configuration", "path"])
assert isinstance(args.from_configuration, Path) assert isinstance(args.from_configuration, Path)
@ -733,7 +740,7 @@ def test_subparsers_service_setup_option_sign_target(parser: argparse.ArgumentPa
service-setup command must convert sign-target option to SignSettings instance service-setup command must convert sign-target option to SignSettings instance
""" """
args = parser.parse_args(["-a", "x86_64", "service-setup", "--packager", "John Doe <john@doe.com>", args = parser.parse_args(["-a", "x86_64", "service-setup", "--packager", "John Doe <john@doe.com>",
"--repository", "aur-clone", "--sign-target", "packages"]) "--sign-target", "packages"])
assert args.sign_target assert args.sign_target
assert all(isinstance(target, SignSettings) for target in args.sign_target) assert all(isinstance(target, SignSettings) for target in args.sign_target)
@ -836,13 +843,17 @@ def test_subparsers_web(parser: argparse.ArgumentParser) -> None:
assert args.parser is not None and args.parser() assert args.parser is not None and args.parser()
def test_run(args: argparse.Namespace, mocker: MockerFixture) -> None: def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
""" """
application must be run application must be run
""" """
args.architecture = "x86_64" path, repository_id = configuration.check_loaded()
args.architecture = repository_id.architecture
args.repository = repository_id.name
args.configuration = path
args.handler = Handler args.handler = Handler
mocker.patch("argparse.ArgumentParser.parse_args", return_value=args) mocker.patch("argparse.ArgumentParser.parse_args", return_value=args)
assert ahriman.run() == 1 assert ahriman.run() == 1 # not implemented

View File

@ -19,7 +19,9 @@ from ahriman.models.build_status import BuildStatus, BuildStatusEnum
from ahriman.models.package import Package from ahriman.models.package import Package
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
from ahriman.models.pacman_synchronization import PacmanSynchronization
from ahriman.models.remote_source import RemoteSource from ahriman.models.remote_source import RemoteSource
from ahriman.models.repository_id import RepositoryId
from ahriman.models.repository_paths import RepositoryPaths from ahriman.models.repository_paths import RepositoryPaths
from ahriman.models.result import Result from ahriman.models.result import Result
from ahriman.models.user import User from ahriman.models.user import User
@ -243,18 +245,19 @@ def auth(configuration: Configuration) -> Auth:
@pytest.fixture @pytest.fixture
def configuration(resource_path_root: Path) -> Configuration: def configuration(repository_id: RepositoryId, resource_path_root: Path) -> Configuration:
""" """
configuration fixture configuration fixture
Args: Args:
repository_id(RepositoryId): repository identifier fixture
resource_path_root(Path): resource path root directory resource_path_root(Path): resource path root directory
Returns: Returns:
Configuration: configuration test instance Configuration: configuration test instance
""" """
path = resource_path_root / "core" / "ahriman.ini" path = resource_path_root / "core" / "ahriman.ini"
return Configuration.from_path(path=path, architecture="x86_64") return Configuration.from_path(path, repository_id)
@pytest.fixture @pytest.fixture
@ -434,7 +437,8 @@ def pacman(configuration: Configuration) -> Pacman:
Returns: Returns:
Pacman: pacman wrapper test instance Pacman: pacman wrapper test instance
""" """
return Pacman("x86_64", configuration, refresh_database=0) _, repository_id = configuration.check_loaded()
return Pacman(repository_id, configuration, refresh_database=PacmanSynchronization.Disabled)
@pytest.fixture @pytest.fixture
@ -481,7 +485,19 @@ def repository(configuration: Configuration, database: SQLite, mocker: MockerFix
Repository: repository test instance Repository: repository test instance
""" """
mocker.patch("ahriman.core.repository.Repository._set_context") mocker.patch("ahriman.core.repository.Repository._set_context")
return Repository.load("x86_64", configuration, database, report=False) _, repository_id = configuration.check_loaded()
return Repository.load(repository_id, configuration, database, report=False)
@pytest.fixture
def repository_id() -> RepositoryId:
"""
fixture for repository identifier
Returns:
RepositoryId: repository identifier test instance
"""
return RepositoryId("x86_64", "aur-clone")
@pytest.fixture @pytest.fixture
@ -525,7 +541,12 @@ def spawner(configuration: Configuration) -> Spawn:
Returns: Returns:
Spawn: spawner fixture Spawn: spawner fixture
""" """
return Spawn(MagicMock(), "x86_64", ["--architecture", "x86_64", "--configuration", str(configuration.path)]) _, repository_id = configuration.check_loaded()
return Spawn(MagicMock(), repository_id, [
"--architecture", "x86_64",
"--repository", repository_id.name,
"--configuration", str(configuration.path),
])
@pytest.fixture @pytest.fixture
@ -554,4 +575,5 @@ def watcher(configuration: Configuration, database: SQLite, repository: Reposito
Watcher: package status watcher test instance Watcher: package status watcher test instance
""" """
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository) mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
return Watcher("x86_64", configuration, database) _, repository_id = configuration.check_loaded()
return Watcher(repository_id, configuration, database)

View File

@ -7,7 +7,7 @@ from pytest_mock import MockerFixture
from systemd.journal import JournalHandler from systemd.journal import JournalHandler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.log import Log from ahriman.core.log.log_loader import LogLoader
from ahriman.models.log_handler import LogHandler from ahriman.models.log_handler import LogHandler
@ -15,14 +15,14 @@ def test_handler() -> None:
""" """
must extract journald handler if available must extract journald handler if available
""" """
assert Log.handler(None) == LogHandler.Journald assert LogLoader.handler(None) == LogHandler.Journald
def test_handler_selected() -> None: def test_handler_selected() -> None:
""" """
must return selected log handler must return selected log handler
""" """
assert Log.handler(LogHandler.Console) == LogHandler.Console assert LogLoader.handler(LogHandler.Console) == LogHandler.Console
def test_handler_syslog(mocker: MockerFixture) -> None: def test_handler_syslog(mocker: MockerFixture) -> None:
@ -31,7 +31,7 @@ def test_handler_syslog(mocker: MockerFixture) -> None:
""" """
mocker.patch("pathlib.Path.exists", return_value=True) mocker.patch("pathlib.Path.exists", return_value=True)
mocker.patch.dict(sys.modules, {"systemd.journal": None}) mocker.patch.dict(sys.modules, {"systemd.journal": None})
assert Log.handler(None) == LogHandler.Syslog assert LogLoader.handler(None) == LogHandler.Syslog
def test_handler_console(mocker: MockerFixture) -> None: def test_handler_console(mocker: MockerFixture) -> None:
@ -40,17 +40,17 @@ def test_handler_console(mocker: MockerFixture) -> None:
""" """
mocker.patch("pathlib.Path.exists", return_value=False) mocker.patch("pathlib.Path.exists", return_value=False)
mocker.patch.dict(sys.modules, {"systemd.journal": None}) mocker.patch.dict(sys.modules, {"systemd.journal": None})
assert Log.handler(None) == LogHandler.Console assert LogLoader.handler(None) == LogHandler.Console
def test_load(configuration: Configuration, mocker: MockerFixture) -> None: def test_load(configuration: Configuration, mocker: MockerFixture) -> None:
""" """
must load logging must load logging
""" """
logging_mock = mocker.patch("ahriman.core.log.log.fileConfig", side_effect=fileConfig) logging_mock = mocker.patch("ahriman.core.log.log_loader.fileConfig", side_effect=fileConfig)
http_log_mock = mocker.patch("ahriman.core.log.http_log_handler.HttpLogHandler.load") http_log_mock = mocker.patch("ahriman.core.log.http_log_handler.HttpLogHandler.load")
Log.load(configuration, LogHandler.Journald, quiet=False, report=False) LogLoader.load(configuration, LogHandler.Journald, quiet=False, report=False)
logging_mock.assert_called_once_with(pytest.helpers.anyvar(int), disable_existing_loggers=True) logging_mock.assert_called_once_with(pytest.helpers.anyvar(int), disable_existing_loggers=True)
http_log_mock.assert_called_once_with(configuration, report=False) http_log_mock.assert_called_once_with(configuration, report=False)
assert all(isinstance(handler, JournalHandler) for handler in logging.getLogger().handlers) assert all(isinstance(handler, JournalHandler) for handler in logging.getLogger().handlers)
@ -60,8 +60,8 @@ def test_load_fallback(configuration: Configuration, mocker: MockerFixture) -> N
""" """
must fall back to stderr without errors must fall back to stderr without errors
""" """
mocker.patch("ahriman.core.log.log.fileConfig", side_effect=PermissionError()) mocker.patch("ahriman.core.log.log_loader.fileConfig", side_effect=PermissionError())
Log.load(configuration, LogHandler.Journald, quiet=False, report=False) LogLoader.load(configuration, LogHandler.Journald, quiet=False, report=False)
def test_load_quiet(configuration: Configuration, mocker: MockerFixture) -> None: def test_load_quiet(configuration: Configuration, mocker: MockerFixture) -> None:
@ -69,5 +69,5 @@ def test_load_quiet(configuration: Configuration, mocker: MockerFixture) -> None
must disable logging in case if quiet flag set must disable logging in case if quiet flag set
""" """
disable_mock = mocker.patch("logging.disable") disable_mock = mocker.patch("logging.disable")
Log.load(configuration, LogHandler.Journald, quiet=True, report=False) LogLoader.load(configuration, LogHandler.Journald, quiet=True, report=False)
disable_mock.assert_called_once_with(logging.WARNING) disable_mock.assert_called_once_with(logging.WARNING)

View File

@ -17,4 +17,5 @@ def remote_call(configuration: Configuration) -> RemoteCall:
""" """
configuration.set_option("web", "host", "localhost") configuration.set_option("web", "host", "localhost")
configuration.set_option("web", "port", "8080") configuration.set_option("web", "port", "8080")
return RemoteCall("x86_64", configuration, "remote-call") _, repository_id = configuration.check_loaded()
return RemoteCall(repository_id, configuration, "remote-call")

View File

@ -22,7 +22,8 @@ def cleaner(configuration: Configuration, database: SQLite) -> Cleaner:
Returns: Returns:
Cleaner: cleaner test instance Cleaner: cleaner test instance
""" """
return Cleaner("x86_64", configuration, database, report=False, _, repository_id = configuration.check_loaded()
return Cleaner(repository_id, configuration, database, report=False,
refresh_pacman_database=PacmanSynchronization.Disabled) refresh_pacman_database=PacmanSynchronization.Disabled)
@ -43,7 +44,8 @@ def executor(configuration: Configuration, database: SQLite, mocker: MockerFixtu
mocker.patch("ahriman.core.repository.cleaner.Cleaner.clear_chroot") mocker.patch("ahriman.core.repository.cleaner.Cleaner.clear_chroot")
mocker.patch("ahriman.core.repository.cleaner.Cleaner.clear_packages") mocker.patch("ahriman.core.repository.cleaner.Cleaner.clear_packages")
mocker.patch("ahriman.core.repository.cleaner.Cleaner.clear_queue") mocker.patch("ahriman.core.repository.cleaner.Cleaner.clear_queue")
return Executor("x86_64", configuration, database, report=False, _, repository_id = configuration.check_loaded()
return Executor(repository_id, configuration, database, report=False,
refresh_pacman_database=PacmanSynchronization.Disabled) refresh_pacman_database=PacmanSynchronization.Disabled)
@ -64,5 +66,6 @@ def update_handler(configuration: Configuration, database: SQLite, mocker: Mocke
mocker.patch("ahriman.core.repository.cleaner.Cleaner.clear_chroot") mocker.patch("ahriman.core.repository.cleaner.Cleaner.clear_chroot")
mocker.patch("ahriman.core.repository.cleaner.Cleaner.clear_packages") mocker.patch("ahriman.core.repository.cleaner.Cleaner.clear_packages")
mocker.patch("ahriman.core.repository.cleaner.Cleaner.clear_queue") mocker.patch("ahriman.core.repository.cleaner.Cleaner.clear_queue")
return UpdateHandler("x86_64", configuration, database, report=False, _, repository_id = configuration.check_loaded()
return UpdateHandler(repository_id, configuration, database, report=False,
refresh_pacman_database=PacmanSynchronization.Disabled) refresh_pacman_database=PacmanSynchronization.Disabled)

View File

@ -15,7 +15,8 @@ def trigger(configuration: Configuration) -> Trigger:
Returns: Returns:
Trigger: trigger test instance Trigger: trigger test instance
""" """
return Trigger("x86_64", configuration) _, repository_id = configuration.check_loaded()
return Trigger(repository_id, configuration)
@pytest.fixture @pytest.fixture
@ -28,4 +29,5 @@ def trigger_loader(configuration: Configuration) -> TriggerLoader:
Returns: Returns:
TriggerLoader: trigger loader test instance TriggerLoader: trigger loader test instance
""" """
return TriggerLoader.load("x86_64", configuration) _, repository_id = configuration.check_loaded()
return TriggerLoader.load(repository_id, configuration)

View File

@ -4,33 +4,34 @@ from typing import Any
from unittest.mock import MagicMock from unittest.mock import MagicMock
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.upload.github import Github from ahriman.core.upload.github import GitHub
from ahriman.core.upload.remote_service import RemoteService from ahriman.core.upload.remote_service import RemoteService
from ahriman.core.upload.rsync import Rsync from ahriman.core.upload.rsync import Rsync
from ahriman.core.upload.s3 import S3 from ahriman.core.upload.s3 import S3
@pytest.fixture @pytest.fixture
def github(configuration: Configuration) -> Github: def github(configuration: Configuration) -> GitHub:
""" """
fixture for github synchronization fixture for GitHub synchronization
Args: Args:
configuration(Configuration): configuration fixture configuration(Configuration): configuration fixture
Returns: Returns:
Github: github test instance GitHub: GitHub test instance
""" """
return Github("x86_64", configuration, "github:x86_64") _, repository_id = configuration.check_loaded()
return GitHub(repository_id, configuration, "github:x86_64")
@pytest.fixture @pytest.fixture
def github_release() -> dict[str, Any]: def github_release() -> dict[str, Any]:
""" """
fixture for the github release object fixture for the GitHub release object
Returns: Returns:
dict[str, Any]: github test release object dict[str, Any]: GitHub test release object
""" """
return { return {
"url": "release_url", "url": "release_url",
@ -59,7 +60,8 @@ def remote_service(configuration: Configuration) -> RemoteService:
""" """
configuration.set_option("web", "host", "localhost") configuration.set_option("web", "host", "localhost")
configuration.set_option("web", "port", "8080") configuration.set_option("web", "port", "8080")
return RemoteService("x86_64", configuration, "remote-service") _, repository_id = configuration.check_loaded()
return RemoteService(repository_id, configuration, "remote-service")
@pytest.fixture @pytest.fixture
@ -73,7 +75,8 @@ def rsync(configuration: Configuration) -> Rsync:
Returns: Returns:
Rsync: rsync test instance Rsync: rsync test instance
""" """
return Rsync("x86_64", configuration, "rsync") _, repository_id = configuration.check_loaded()
return Rsync(repository_id, configuration, "rsync")
@pytest.fixture @pytest.fixture
@ -87,7 +90,8 @@ def s3(configuration: Configuration) -> S3:
Returns: Returns:
S3: S3 test instance S3: S3 test instance
""" """
return S3("x86_64", configuration, "customs3") _, repository_id = configuration.check_loaded()
return S3(repository_id, configuration, "customs3")
@pytest.fixture @pytest.fixture

View File

@ -6,10 +6,10 @@ from pytest_mock import MockerFixture
from typing import Any from typing import Any
from unittest.mock import call as MockCall from unittest.mock import call as MockCall
from ahriman.core.upload.github import Github from ahriman.core.upload.github import GitHub
def test_asset_remove(github: Github, github_release: dict[str, Any], mocker: MockerFixture) -> None: def test_asset_remove(github: GitHub, github_release: dict[str, Any], mocker: MockerFixture) -> None:
""" """
must remove asset from the release must remove asset from the release
""" """
@ -18,7 +18,7 @@ def test_asset_remove(github: Github, github_release: dict[str, Any], mocker: Mo
request_mock.assert_called_once_with("DELETE", "asset_url") request_mock.assert_called_once_with("DELETE", "asset_url")
def test_asset_remove_unknown(github: Github, github_release: dict[str, Any], mocker: MockerFixture) -> None: def test_asset_remove_unknown(github: GitHub, github_release: dict[str, Any], mocker: MockerFixture) -> None:
""" """
must not fail if no asset found must not fail if no asset found
""" """
@ -27,7 +27,7 @@ def test_asset_remove_unknown(github: Github, github_release: dict[str, Any], mo
request_mock.assert_not_called() request_mock.assert_not_called()
def test_asset_upload(github: Github, github_release: dict[str, Any], mocker: MockerFixture) -> None: def test_asset_upload(github: GitHub, github_release: dict[str, Any], mocker: MockerFixture) -> None:
""" """
must upload asset to the repository must upload asset to the repository
""" """
@ -42,7 +42,7 @@ def test_asset_upload(github: Github, github_release: dict[str, Any], mocker: Mo
remove_mock.assert_not_called() remove_mock.assert_not_called()
def test_asset_upload_with_removal(github: Github, github_release: dict[str, Any], mocker: MockerFixture) -> None: def test_asset_upload_with_removal(github: GitHub, github_release: dict[str, Any], mocker: MockerFixture) -> None:
""" """
must remove existing file before upload must remove existing file before upload
""" """
@ -58,7 +58,7 @@ def test_asset_upload_with_removal(github: Github, github_release: dict[str, Any
]) ])
def test_asset_upload_empty_mimetype(github: Github, github_release: dict[str, Any], mocker: MockerFixture) -> None: def test_asset_upload_empty_mimetype(github: GitHub, github_release: dict[str, Any], mocker: MockerFixture) -> None:
""" """
must upload asset to the repository with empty mime type if the library cannot guess it must upload asset to the repository with empty mime type if the library cannot guess it
""" """
@ -73,7 +73,7 @@ def test_asset_upload_empty_mimetype(github: Github, github_release: dict[str, A
headers={"Content-Type": "application/octet-stream"}) headers={"Content-Type": "application/octet-stream"})
def test_get_local_files(github: Github, resource_path_root: Path, mocker: MockerFixture) -> None: def test_get_local_files(github: GitHub, resource_path_root: Path, mocker: MockerFixture) -> None:
""" """
must get all local files recursively must get all local files recursively
""" """
@ -82,7 +82,7 @@ def test_get_local_files(github: Github, resource_path_root: Path, mocker: Mocke
walk_mock.assert_called() walk_mock.assert_called()
def test_files_remove(github: Github, github_release: dict[str, Any], mocker: MockerFixture) -> None: def test_files_remove(github: GitHub, github_release: dict[str, Any], mocker: MockerFixture) -> None:
""" """
must remove files from the remote must remove files from the remote
""" """
@ -91,7 +91,7 @@ def test_files_remove(github: Github, github_release: dict[str, Any], mocker: Mo
remove_mock.assert_called_once_with(github_release, "b") remove_mock.assert_called_once_with(github_release, "b")
def test_files_remove_empty(github: Github, github_release: dict[str, Any], mocker: MockerFixture) -> None: def test_files_remove_empty(github: GitHub, github_release: dict[str, Any], mocker: MockerFixture) -> None:
""" """
must remove nothing if nothing changed must remove nothing if nothing changed
""" """
@ -100,7 +100,7 @@ def test_files_remove_empty(github: Github, github_release: dict[str, Any], mock
remove_mock.assert_not_called() remove_mock.assert_not_called()
def test_files_upload(github: Github, github_release: dict[str, Any], mocker: MockerFixture) -> None: def test_files_upload(github: GitHub, github_release: dict[str, Any], mocker: MockerFixture) -> None:
""" """
must upload files to the remote must upload files to the remote
""" """
@ -112,7 +112,7 @@ def test_files_upload(github: Github, github_release: dict[str, Any], mocker: Mo
]) ])
def test_files_upload_empty(github: Github, github_release: dict[str, Any], mocker: MockerFixture) -> None: def test_files_upload_empty(github: GitHub, github_release: dict[str, Any], mocker: MockerFixture) -> None:
""" """
must upload nothing if nothing changed must upload nothing if nothing changed
""" """
@ -121,7 +121,7 @@ def test_files_upload_empty(github: Github, github_release: dict[str, Any], mock
upload_mock.assert_not_called() upload_mock.assert_not_called()
def test_release_create(github: Github, mocker: MockerFixture) -> None: def test_release_create(github: GitHub, mocker: MockerFixture) -> None:
""" """
must create release must create release
""" """
@ -131,7 +131,7 @@ def test_release_create(github: Github, mocker: MockerFixture) -> None:
json={"tag_name": github.architecture, "name": github.architecture}) json={"tag_name": github.architecture, "name": github.architecture})
def test_release_get(github: Github, mocker: MockerFixture) -> None: def test_release_get(github: GitHub, mocker: MockerFixture) -> None:
""" """
must get release must get release
""" """
@ -140,7 +140,7 @@ def test_release_get(github: Github, mocker: MockerFixture) -> None:
request_mock.assert_called_once_with("GET", pytest.helpers.anyvar(str, True)) request_mock.assert_called_once_with("GET", pytest.helpers.anyvar(str, True))
def test_release_get_empty(github: Github, mocker: MockerFixture) -> None: def test_release_get_empty(github: GitHub, mocker: MockerFixture) -> None:
""" """
must return nothing in case of 404 status code must return nothing in case of 404 status code
""" """
@ -151,7 +151,7 @@ def test_release_get_empty(github: Github, mocker: MockerFixture) -> None:
assert github.release_get() is None assert github.release_get() is None
def test_release_get_exception(github: Github, mocker: MockerFixture) -> None: def test_release_get_exception(github: GitHub, mocker: MockerFixture) -> None:
""" """
must re-raise non HTTPError exception must re-raise non HTTPError exception
""" """
@ -160,7 +160,7 @@ def test_release_get_exception(github: Github, mocker: MockerFixture) -> None:
github.release_get() github.release_get()
def test_release_get_exception_http_error(github: Github, mocker: MockerFixture) -> None: def test_release_get_exception_http_error(github: GitHub, mocker: MockerFixture) -> None:
""" """
must re-raise HTTPError exception with code differs from 404 must re-raise HTTPError exception with code differs from 404
""" """
@ -170,7 +170,7 @@ def test_release_get_exception_http_error(github: Github, mocker: MockerFixture)
github.release_get() github.release_get()
def test_release_update(github: Github, github_release: dict[str, Any], mocker: MockerFixture) -> None: def test_release_update(github: GitHub, github_release: dict[str, Any], mocker: MockerFixture) -> None:
""" """
must update release must update release
""" """
@ -179,7 +179,7 @@ def test_release_update(github: Github, github_release: dict[str, Any], mocker:
request_mock.assert_called_once_with("POST", "release_url", json={"body": "body"}) request_mock.assert_called_once_with("POST", "release_url", json={"body": "body"})
def test_release_sync(github: Github, mocker: MockerFixture) -> None: def test_release_sync(github: GitHub, mocker: MockerFixture) -> None:
""" """
must run sync command must run sync command
""" """
@ -199,7 +199,7 @@ def test_release_sync(github: Github, mocker: MockerFixture) -> None:
release_update_mock.assert_called_once_with({}, pytest.helpers.anyvar(int)) release_update_mock.assert_called_once_with({}, pytest.helpers.anyvar(int))
def test_release_sync_create_release(github: Github, mocker: MockerFixture) -> None: def test_release_sync_create_release(github: GitHub, mocker: MockerFixture) -> None:
""" """
must create release in case if it does not exist must create release in case if it does not exist
""" """

View File

@ -112,7 +112,9 @@ def application(configuration: Configuration, spawner: Spawn, database: SQLite,
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository) mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("aiohttp_apispec.setup_aiohttp_apispec") mocker.patch("aiohttp_apispec.setup_aiohttp_apispec")
mocker.patch.object(ahriman.core.auth.helpers, "_has_aiohttp_security", False) mocker.patch.object(ahriman.core.auth.helpers, "_has_aiohttp_security", False)
return setup_service("x86_64", configuration, spawner) _, repository_id = configuration.check_loaded()
return setup_service(repository_id, configuration, spawner)
@pytest.fixture @pytest.fixture
@ -138,7 +140,8 @@ def application_with_auth(configuration: Configuration, user: User, spawner: Spa
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository) mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("aiohttp_apispec.setup_aiohttp_apispec") mocker.patch("aiohttp_apispec.setup_aiohttp_apispec")
mocker.patch.object(ahriman.core.auth.helpers, "_has_aiohttp_security", True) mocker.patch.object(ahriman.core.auth.helpers, "_has_aiohttp_security", True)
application = setup_service("x86_64", configuration, spawner) _, repository_id = configuration.check_loaded()
application = setup_service(repository_id, configuration, spawner)
generated = user.hash_password(application["validator"].salt) generated = user.hash_password(application["validator"].salt)
mocker.patch("ahriman.core.database.SQLite.user_get", return_value=generated) mocker.patch("ahriman.core.database.SQLite.user_get", return_value=generated)
@ -169,7 +172,9 @@ def application_with_debug(configuration: Configuration, user: User, spawner: Sp
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository) mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("aiohttp_apispec.setup_aiohttp_apispec") mocker.patch("aiohttp_apispec.setup_aiohttp_apispec")
mocker.patch.object(ahriman.core.auth.helpers, "_has_aiohttp_security", False) mocker.patch.object(ahriman.core.auth.helpers, "_has_aiohttp_security", False)
return setup_service("x86_64", configuration, spawner) _, repository_id = configuration.check_loaded()
return setup_service(repository_id, configuration, spawner)
@pytest.fixture @pytest.fixture