mirror of
https://github.com/arcan1s/ahriman.git
synced 2026-04-07 19:03:38 +00:00
Compare commits
23 Commits
2.20.0rc2
...
bb31919858
| Author | SHA1 | Date | |
|---|---|---|---|
| bb31919858 | |||
| d0ebd6559c | |||
| f92105a132 | |||
| 666c3750ac | |||
| 49d433ab37 | |||
| 8c01c1c6bc | |||
| af4d013c3b | |||
| 35019741ac | |||
| 61c6dc03d6 | |||
| 9eaed20b8a | |||
| efac4c1663 | |||
| 94a164d32d | |||
| bb77a9413f | |||
| d1fb969ca7 | |||
| 144fcbcef2 | |||
| 1a30d90bdc | |||
| 449c508fdf | |||
| 208b12b50b | |||
| 5d5e0064c3 | |||
| cea706c4b6 | |||
| 81494059dd | |||
| c3982859e3 | |||
| a5c4f735db |
2
.github/workflows/setup.sh
vendored
2
.github/workflows/setup.sh
vendored
@@ -10,7 +10,7 @@ echo -e '[arcanisrepo]\nServer = https://repo.arcanis.me/$arch\nSigLevel = Never
|
|||||||
# refresh the image
|
# refresh the image
|
||||||
pacman -Syyu --noconfirm
|
pacman -Syyu --noconfirm
|
||||||
# main dependencies
|
# main dependencies
|
||||||
pacman -S --noconfirm devtools git pyalpm python-bcrypt python-filelock python-inflection python-pyelftools python-requests python-systemd sudo
|
pacman -S --noconfirm devtools git pyalpm python-bcrypt python-inflection python-pyelftools python-requests python-systemd sudo
|
||||||
# make dependencies
|
# make dependencies
|
||||||
pacman -S --noconfirm --asdeps base-devel python-build python-flit python-installer python-tox python-wheel
|
pacman -S --noconfirm --asdeps base-devel python-build python-flit python-installer python-tox python-wheel
|
||||||
# optional dependencies
|
# optional dependencies
|
||||||
|
|||||||
@@ -24,8 +24,7 @@ RUN pacman -S --noconfirm --asdeps \
|
|||||||
devtools \
|
devtools \
|
||||||
git \
|
git \
|
||||||
pyalpm \
|
pyalpm \
|
||||||
python-bcrypt \
|
python-bcrypt \
|
||||||
python-filelock \
|
|
||||||
python-inflection \
|
python-inflection \
|
||||||
python-pyelftools \
|
python-pyelftools \
|
||||||
python-requests \
|
python-requests \
|
||||||
|
|||||||
2942
docs/_static/architecture.dot
vendored
2942
docs/_static/architecture.dot
vendored
File diff suppressed because it is too large
Load Diff
@@ -28,14 +28,6 @@ ahriman.core.repository.executor module
|
|||||||
:no-undoc-members:
|
:no-undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
ahriman.core.repository.explorer module
|
|
||||||
---------------------------------------
|
|
||||||
|
|
||||||
.. automodule:: ahriman.core.repository.explorer
|
|
||||||
:members:
|
|
||||||
:no-undoc-members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
ahriman.core.repository.package\_info module
|
ahriman.core.repository.package\_info module
|
||||||
--------------------------------------------
|
--------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -120,20 +120,6 @@ Having default root as ``/var/lib/ahriman`` (differs from container though), the
|
|||||||
|
|
||||||
/var/lib/ahriman/
|
/var/lib/ahriman/
|
||||||
├── ahriman.db
|
├── ahriman.db
|
||||||
├── archive
|
|
||||||
│ ├── packages
|
|
||||||
│ │ └── a
|
|
||||||
│ │ └── ahriman
|
|
||||||
│ │ └── ahriman-2.0.0-1-any.pkg.tar.zst
|
|
||||||
│ └── repos
|
|
||||||
│ └── 2026
|
|
||||||
│ └── 01
|
|
||||||
│ └── 01
|
|
||||||
│ └── aur
|
|
||||||
│ └── x86_64
|
|
||||||
│ ├── ahriman-2.0.0-1-any.pkg.tar.zst -> ../../../../../../packages/a/ahriman/ahriman-2.0.0-1-any.pkg.tar.zst
|
|
||||||
│ ├── aur.db -> aur.db.tar.gz
|
|
||||||
│ └── aur.db.tar.gz
|
|
||||||
├── cache
|
├── cache
|
||||||
├── chroot
|
├── chroot
|
||||||
│ └── aur
|
│ └── aur
|
||||||
@@ -153,7 +139,6 @@ Having default root as ``/var/lib/ahriman`` (differs from container though), the
|
|||||||
└── repository
|
└── repository
|
||||||
└── aur
|
└── aur
|
||||||
└── x86_64
|
└── x86_64
|
||||||
├── ahriman-2.0.0-1-any.pkg.tar.zst -> ../../../archive/packages/a/ahriman/ahriman-2.0.0-1-any.pkg.tar.zst
|
|
||||||
├── aur.db -> aur.db.tar.gz
|
├── aur.db -> aur.db.tar.gz
|
||||||
├── aur.db.tar.gz
|
├── aur.db.tar.gz
|
||||||
├── aur.files -> aur.files.tar.gz
|
├── aur.files -> aur.files.tar.gz
|
||||||
@@ -161,18 +146,11 @@ Having default root as ``/var/lib/ahriman`` (differs from container though), the
|
|||||||
|
|
||||||
There are multiple subdirectories, some of them are commons for any repository, but some of them are not.
|
There are multiple subdirectories, some of them are commons for any repository, but some of them are not.
|
||||||
|
|
||||||
* ``archive`` is the package archive directory. It is common for all repositories and architectures and contains two subdirectories:
|
|
||||||
|
|
||||||
* ``archive/packages/{first_letter}/{package_base}`` stores the actual built package files and their signatures.
|
|
||||||
* ``archive/repos/{YYYY}/{MM}/{DD}/{repository}/{architecture}`` contains daily repository snapshots. Each snapshot is a repository database with symlinks pointing to the corresponding packages in the ``archive/packages`` tree.
|
|
||||||
|
|
||||||
The archive also allows the build process to skip rebuilding a package if a matching version already exists.
|
|
||||||
|
|
||||||
* ``cache`` is a directory with locally stored PKGBUILD's and VCS packages. It is common for all repositories and architectures.
|
* ``cache`` is a directory with locally stored PKGBUILD's and VCS packages. It is common for all repositories and architectures.
|
||||||
* ``chroot/{repository}`` is a chroot directory for ``devtools``. It is specific for each repository, but shared for different architectures inside (the ``devtools`` handles architectures automatically).
|
* ``chroot/{repository}`` is a chroot directory for ``devtools``. It is specific for each repository, but shared for different architectures inside (the ``devtools`` handles architectures automatically).
|
||||||
* ``packages/{repository}/{architecture}`` is a directory with prebuilt packages. When a package is built, first it will be uploaded to this directory and later will be handled by update process. It is architecture and repository specific.
|
* ``packages/{repository}/{architecture}`` is a directory with prebuilt packages. When a package is built, first it will be uploaded to this directory and later will be handled by update process. It is architecture and repository specific.
|
||||||
* ``pacman/{repository}/{architecture}`` is the repository and architecture specific caches for pacman's databases.
|
* ``pacman/{repository}/{architecture}`` is the repository and architecture specific caches for pacman's databases.
|
||||||
* ``repository/{repository}/{architecture}`` is a repository packages directory. Package files in this directory are symlinks to the archive.
|
* ``repository/{repository}/{architecture}`` is a repository packages directory.
|
||||||
|
|
||||||
Normally you should avoid direct interaction with the application tree. For tree migration process refer to the :doc:`migration notes <migrations/index>`.
|
Normally you should avoid direct interaction with the application tree. For tree migration process refer to the :doc:`migration notes <migrations/index>`.
|
||||||
|
|
||||||
|
|||||||
@@ -97,14 +97,12 @@ libalpm and AUR related configuration. Group name can refer to architecture, e.g
|
|||||||
* ``sync_files_database`` - download files database from mirror, boolean, required.
|
* ``sync_files_database`` - download files database from mirror, boolean, required.
|
||||||
* ``use_ahriman_cache`` - use local pacman package cache instead of system one, boolean, required. With this option enabled you might want to refresh database periodically (available as additional flag for some subcommands). If set to ``no``, databases must be synchronized manually.
|
* ``use_ahriman_cache`` - use local pacman package cache instead of system one, boolean, required. With this option enabled you might want to refresh database periodically (available as additional flag for some subcommands). If set to ``no``, databases must be synchronized manually.
|
||||||
|
|
||||||
``aur`` group
|
``archive`` group
|
||||||
-------------
|
-----------------
|
||||||
|
|
||||||
Archlinux User Repository related configuration.
|
Describes settings for packages archives management extensions.
|
||||||
|
|
||||||
* ``max_retries`` - maximum amount of retries of HTTP requests, integer, optional, default ``0``.
|
* ``keep_built_packages`` - keep this amount of built packages with different versions, integer, required. ``0`` (or negative number) will effectively disable archives removal.
|
||||||
* ``retry_backoff`` - retry exponential backoff, float, optional, default ``0.0``.
|
|
||||||
* ``timeout`` - HTTP request timeout in seconds, integer, optional, default is ``30``.
|
|
||||||
|
|
||||||
``auth`` group
|
``auth`` group
|
||||||
--------------
|
--------------
|
||||||
@@ -167,9 +165,7 @@ Reporting to web service related settings. In most cases there is fallback to we
|
|||||||
|
|
||||||
* ``enabled`` - enable reporting to web service, boolean, optional, default ``yes`` for backward compatibility.
|
* ``enabled`` - enable reporting to web service, boolean, optional, default ``yes`` for backward compatibility.
|
||||||
* ``address`` - remote web service address with protocol, string, optional. In case of websocket, the ``http+unix`` scheme and URL encoded address (e.g. ``%2Fvar%2Flib%2Fahriman`` for ``/var/lib/ahriman``) must be used, e.g. ``http+unix://%2Fvar%2Flib%2Fahriman%2Fsocket``. In case if none set, it will be guessed from ``web`` section.
|
* ``address`` - remote web service address with protocol, string, optional. In case of websocket, the ``http+unix`` scheme and URL encoded address (e.g. ``%2Fvar%2Flib%2Fahriman`` for ``/var/lib/ahriman``) must be used, e.g. ``http+unix://%2Fvar%2Flib%2Fahriman%2Fsocket``. In case if none set, it will be guessed from ``web`` section.
|
||||||
* ``max_retries`` - maximum amount of retries of HTTP requests, integer, optional, default ``0``.
|
|
||||||
* ``password`` - password to authorize in web service in order to update service status, string, required in case if authorization enabled.
|
* ``password`` - password to authorize in web service in order to update service status, string, required in case if authorization enabled.
|
||||||
* ``retry_backoff`` - retry exponential backoff, float, optional, default ``0.0``.
|
|
||||||
* ``suppress_http_log_errors`` - suppress HTTP log errors, boolean, optional, default ``no``. If set to ``yes``, any HTTP log errors (e.g. if web server is not available, but HTTP logging is enabled) will be suppressed.
|
* ``suppress_http_log_errors`` - suppress HTTP log errors, boolean, optional, default ``no``. If set to ``yes``, any HTTP log errors (e.g. if web server is not available, but HTTP logging is enabled) will be suppressed.
|
||||||
* ``timeout`` - HTTP request timeout in seconds, integer, optional, default is ``30``.
|
* ``timeout`` - HTTP request timeout in seconds, integer, optional, default is ``30``.
|
||||||
* ``username`` - username to authorize in web service in order to update service status, string, required in case if authorization enabled.
|
* ``username`` - username to authorize in web service in order to update service status, string, required in case if authorization enabled.
|
||||||
@@ -193,13 +189,6 @@ Web server settings. This feature requires ``aiohttp`` libraries to be installed
|
|||||||
* ``unix_socket_unsafe`` - set unsafe (o+w) permissions to unix socket, boolean, optional, default ``yes``. This option is enabled by default, because it is supposed that unix socket is created in safe environment (only web service is supposed to be used in unsafe), but it can be disabled by configuration.
|
* ``unix_socket_unsafe`` - set unsafe (o+w) permissions to unix socket, boolean, optional, default ``yes``. This option is enabled by default, because it is supposed that unix socket is created in safe environment (only web service is supposed to be used in unsafe), but it can be disabled by configuration.
|
||||||
* ``wait_timeout`` - wait timeout in seconds, maximum amount of time to be waited before lock will be free, integer, optional.
|
* ``wait_timeout`` - wait timeout in seconds, maximum amount of time to be waited before lock will be free, integer, optional.
|
||||||
|
|
||||||
``archive`` group
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
Describes settings for packages archives management extensions.
|
|
||||||
|
|
||||||
* ``keep_built_packages`` - keep this amount of built packages with different versions, integer, required. ``0`` will effectively disable archives removal.
|
|
||||||
|
|
||||||
``keyring`` group
|
``keyring`` group
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
@@ -219,12 +208,12 @@ Keyring generator plugin
|
|||||||
* ``revoked`` - list of revoked packagers keys, space separated list of strings, optional.
|
* ``revoked`` - list of revoked packagers keys, space separated list of strings, optional.
|
||||||
* ``trusted`` - list of master keys, space separated list of strings, optional, if not set, the ``key`` option from ``sign`` group will be used.
|
* ``trusted`` - list of master keys, space separated list of strings, optional, if not set, the ``key`` option from ``sign`` group will be used.
|
||||||
|
|
||||||
``logs-rotation`` group
|
``housekeeping`` group
|
||||||
-----------------------
|
----------------------
|
||||||
|
|
||||||
This section describes settings for the ``ahriman.core.housekeeping.LogsRotationTrigger`` plugin.
|
This section describes settings for the ``ahriman.core.housekeeping.LogsRotationTrigger`` plugin.
|
||||||
|
|
||||||
* ``keep_last_logs`` - amount of build logs to be kept for each package, integer, required. Logs will be cleared at the end of each process.
|
* ``keep_last_logs`` - amount of build logs to be kept for each package, integer, optional ,default ``0``. Logs will be cleared at the end of each process.
|
||||||
|
|
||||||
``mirrorlist`` group
|
``mirrorlist`` group
|
||||||
--------------------
|
--------------------
|
||||||
@@ -261,7 +250,6 @@ Available options are:
|
|||||||
Remote pull trigger
|
Remote pull trigger
|
||||||
^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
* ``type`` - type of the pull, string, optional, must be set to ``gitremote`` if exists.
|
|
||||||
* ``pull_url`` - URL of the remote repository from which PKGBUILDs can be pulled before build process, string, required.
|
* ``pull_url`` - URL of the remote repository from which PKGBUILDs can be pulled before build process, string, required.
|
||||||
* ``pull_branch`` - branch of the remote repository from which PKGBUILDs can be pulled before build process, string, optional, default is ``master``.
|
* ``pull_branch`` - branch of the remote repository from which PKGBUILDs can be pulled before build process, string, optional, default is ``master``.
|
||||||
|
|
||||||
@@ -282,7 +270,6 @@ Available options are:
|
|||||||
Remote push trigger
|
Remote push trigger
|
||||||
^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
* ``type`` - type of the push, string, optional, must be set to ``gitremote`` if exists.
|
|
||||||
* ``commit_email`` - git commit email, string, optional, default is ``ahriman@localhost``.
|
* ``commit_email`` - git commit email, string, optional, default is ``ahriman@localhost``.
|
||||||
* ``commit_user`` - git commit user, string, optional, default is ``ahriman``.
|
* ``commit_user`` - git commit user, string, optional, default is ``ahriman``.
|
||||||
* ``push_url`` - URL of the remote repository to which PKGBUILDs should be pushed after build process, string, required.
|
* ``push_url`` - URL of the remote repository to which PKGBUILDs should be pushed after build process, string, required.
|
||||||
@@ -378,8 +365,6 @@ Section name must be either ``telegram`` (plus optional architecture name, e.g.
|
|||||||
* ``chat_id`` - telegram chat id, either string with ``@`` or integer value, required.
|
* ``chat_id`` - telegram chat id, either string with ``@`` or integer value, required.
|
||||||
* ``homepage`` - link to homepage, string, optional.
|
* ``homepage`` - link to homepage, string, optional.
|
||||||
* ``link_path`` - prefix for HTML links, string, required.
|
* ``link_path`` - prefix for HTML links, string, required.
|
||||||
* ``max_retries`` - maximum amount of retries of HTTP requests, integer, optional, default ``0``.
|
|
||||||
* ``retry_backoff`` - retry exponential backoff, float, optional, default ``0.0``.
|
|
||||||
* ``rss_url`` - link to RSS feed, string, optional.
|
* ``rss_url`` - link to RSS feed, string, optional.
|
||||||
* ``template`` - Jinja2 template name, string, required.
|
* ``template`` - Jinja2 template name, string, required.
|
||||||
* ``template_type`` - ``parse_mode`` to be passed to telegram API, one of ``MarkdownV2``, ``HTML``, ``Markdown``, string, optional, default ``HTML``.
|
* ``template_type`` - ``parse_mode`` to be passed to telegram API, one of ``MarkdownV2``, ``HTML``, ``Markdown``, string, optional, default ``HTML``.
|
||||||
@@ -405,7 +390,6 @@ Type will be read from several sources:
|
|||||||
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.
|
||||||
* ``max_retries`` - maximum amount of retries of HTTP requests, integer, optional, default ``0``.
|
|
||||||
* ``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:
|
||||||
|
|
||||||
@@ -415,7 +399,6 @@ This feature requires GitHub key creation (see below). Section name must be eith
|
|||||||
#. 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).
|
||||||
* ``retry_backoff`` - retry exponential backoff, float, optional, default ``0.0``.
|
|
||||||
* ``timeout`` - HTTP request timeout in seconds, integer, optional, default is ``30``.
|
* ``timeout`` - HTTP request timeout in seconds, integer, optional, default is ``30``.
|
||||||
* ``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`` (legacy behavior).
|
* ``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`` (legacy behavior).
|
||||||
* ``username`` - GitHub authorization user, string, required. Basically the same as ``owner``.
|
* ``username`` - GitHub authorization user, string, required. Basically the same as ``owner``.
|
||||||
@@ -426,8 +409,6 @@ This feature requires GitHub key creation (see below). Section name must be eith
|
|||||||
Section name must be either ``remote-service`` (plus optional architecture name, e.g. ``remote-service:x86_64``) or random name with ``type`` set.
|
Section name must be either ``remote-service`` (plus optional architecture name, e.g. ``remote-service:x86_64``) or random name with ``type`` set.
|
||||||
|
|
||||||
* ``type`` - type of the report, string, optional, must be set to ``remote-service`` if exists.
|
* ``type`` - type of the report, string, optional, must be set to ``remote-service`` if exists.
|
||||||
* ``max_retries`` - maximum amount of retries of HTTP requests, integer, optional, default ``0``.
|
|
||||||
* ``retry_backoff`` - retry exponential backoff, float, optional, default ``0.0``.
|
|
||||||
* ``timeout`` - HTTP request timeout in seconds, integer, optional, default is ``30``.
|
* ``timeout`` - HTTP request timeout in seconds, integer, optional, default is ``30``.
|
||||||
|
|
||||||
``rsync`` type
|
``rsync`` type
|
||||||
|
|||||||
@@ -40,8 +40,6 @@ docutils==0.21.2
|
|||||||
# sphinx
|
# sphinx
|
||||||
# sphinx-argparse
|
# sphinx-argparse
|
||||||
# sphinx-rtd-theme
|
# sphinx-rtd-theme
|
||||||
filelock==3.24.0
|
|
||||||
# via ahriman (pyproject.toml)
|
|
||||||
frozenlist==1.6.0
|
frozenlist==1.6.0
|
||||||
# via
|
# via
|
||||||
# aiohttp
|
# aiohttp
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
Triggers
|
Triggers
|
||||||
========
|
========
|
||||||
|
|
||||||
The package provides ability to write custom extensions which will be run on (the most) actions, e.g. after updates. By default ahriman provides several types of extensions - reporting, files uploading, PKGBUILD synchronization, repository archiving, housekeeping and distributed builds support. Each extension must derive from the ``ahriman.core.triggers.Trigger`` class and should implement at least one of the abstract methods:
|
The package provides ability to write custom extensions which will be run on (the most) actions, e.g. after updates. By default ahriman provides three types of extensions - reporting, files uploading and PKGBUILD synchronization. Each extension must derive from the ``ahriman.core.triggers.Trigger`` class and should implement at least one of the abstract methods:
|
||||||
|
|
||||||
* ``on_result`` - trigger action which will be called after build process, the build result and the list of repository packages will be supplied as arguments.
|
* ``on_result`` - trigger action which will be called after build process, the build result and the list of repository packages will be supplied as arguments.
|
||||||
* ``on_start`` - trigger action which will be called right before the start of the application process.
|
* ``on_start`` - trigger action which will be called right before the start of the application process.
|
||||||
@@ -14,11 +14,6 @@ Built-in triggers
|
|||||||
|
|
||||||
For the configuration details and settings explanation kindly refer to the :doc:`documentation <configuration>`.
|
For the configuration details and settings explanation kindly refer to the :doc:`documentation <configuration>`.
|
||||||
|
|
||||||
``ahriman.core.archive.ArchiveTrigger``
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
This trigger provides date-based snapshots of the repository. It organizes packages into a daily directory tree (``repos/YYYY/MM/DD``) with its own pacman database. On each run it creates symlinks from the daily snapshot to the actual package archives and maintains the database accordingly. It also takes care of cleaning up broken symlinks and empty directories for packages which have been removed.
|
|
||||||
|
|
||||||
``ahriman.core.distributed.WorkerLoaderTrigger``
|
``ahriman.core.distributed.WorkerLoaderTrigger``
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
@@ -41,16 +36,6 @@ In order to update those packages you would need to clone your repository separa
|
|||||||
|
|
||||||
This trigger will be called right after build process (``on_result``). It will pick PKGBUILDs for the updated packages, pull them (together with any other files) and commit and push changes to remote repository. No real use cases, but the most of user repositories do it.
|
This trigger will be called right after build process (``on_result``). It will pick PKGBUILDs for the updated packages, pull them (together with any other files) and commit and push changes to remote repository. No real use cases, but the most of user repositories do it.
|
||||||
|
|
||||||
``ahriman.core.housekeeping.ArchiveRotationTrigger``
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
This trigger removes old package versions from the archive directory. It implements ``on_result`` and, after each build, compares available versions for updated packages and removes the older ones, keeping only the last N versions as configured by ``keep_built_packages`` option.
|
|
||||||
|
|
||||||
``ahriman.core.housekeeping.LogsRotationTrigger``
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
||||||
Simple trigger to rotate build logs. It implements ``on_result`` and removes old log records after each build process, keeping only the last N records as configured by ``keep_last_logs`` option.
|
|
||||||
|
|
||||||
``ahriman.core.report.ReportTrigger``
|
``ahriman.core.report.ReportTrigger``
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
|||||||
@@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
pkgbase='ahriman'
|
pkgbase='ahriman'
|
||||||
pkgname=('ahriman' 'ahriman-core' 'ahriman-triggers' 'ahriman-web')
|
pkgname=('ahriman' 'ahriman-core' 'ahriman-triggers' 'ahriman-web')
|
||||||
pkgver=2.20.0rc2
|
pkgver=2.19.0
|
||||||
pkgrel=1
|
pkgrel=1
|
||||||
pkgdesc="ArcH linux ReposItory MANager"
|
pkgdesc="ArcH linux ReposItory MANager"
|
||||||
arch=('any')
|
arch=('any')
|
||||||
url="https://ahriman.readthedocs.io/"
|
url="https://ahriman.readthedocs.io/"
|
||||||
license=('GPL-3.0-or-later')
|
license=('GPL-3.0-or-later')
|
||||||
depends=('devtools>=1:1.0.0' 'git' 'pyalpm' 'python-bcrypt' 'python-filelock' 'python-inflection' 'python-pyelftools' 'python-requests')
|
depends=('devtools>=1:1.0.0' 'git' 'pyalpm' 'python-bcrypt' 'python-inflection' 'python-pyelftools' 'python-requests')
|
||||||
makedepends=('python-build' 'python-flit' 'python-installer' 'python-wheel')
|
makedepends=('python-build' 'python-flit' 'python-installer' 'python-wheel')
|
||||||
source=("https://github.com/arcan1s/ahriman/releases/download/$pkgver/$pkgbase-$pkgver.tar.gz"
|
source=("https://github.com/arcan1s/ahriman/releases/download/$pkgver/$pkgbase-$pkgver.tar.gz"
|
||||||
"$pkgbase.sysusers"
|
"$pkgbase.sysusers"
|
||||||
|
|||||||
@@ -23,14 +23,6 @@ sync_files_database = yes
|
|||||||
; as additional option for some subcommands). If set to no, databases must be synchronized manually.
|
; as additional option for some subcommands). If set to no, databases must be synchronized manually.
|
||||||
use_ahriman_cache = yes
|
use_ahriman_cache = yes
|
||||||
|
|
||||||
[aur]
|
|
||||||
; Maximum amount of retries of HTTP requests.
|
|
||||||
max_retries = 3
|
|
||||||
; Retry exponential backoff.
|
|
||||||
retry_backoff = 1.0
|
|
||||||
; HTTP request timeout in seconds.
|
|
||||||
;timeout = 30
|
|
||||||
|
|
||||||
[build]
|
[build]
|
||||||
; List of additional flags passed to archbuild command.
|
; List of additional flags passed to archbuild command.
|
||||||
;archbuild_flags =
|
;archbuild_flags =
|
||||||
@@ -81,12 +73,8 @@ enabled = yes
|
|||||||
; In case if unix sockets are used, it might point to the valid socket with encoded path, e.g.:
|
; In case if unix sockets are used, it might point to the valid socket with encoded path, e.g.:
|
||||||
; address = http+unix://%2Fvar%2Flib%2Fahriman%2Fsocket
|
; address = http+unix://%2Fvar%2Flib%2Fahriman%2Fsocket
|
||||||
;address = http://${web:host}:${web:port}
|
;address = http://${web:host}:${web:port}
|
||||||
; Maximum amount of retries of HTTP requests.
|
|
||||||
;max_retries = 0
|
|
||||||
; Optional password for authentication (if enabled).
|
; Optional password for authentication (if enabled).
|
||||||
;password =
|
;password =
|
||||||
; Retry exponential backoff.
|
|
||||||
;retry_backoff = 0.0
|
|
||||||
; Do not log HTTP errors if occurs.
|
; Do not log HTTP errors if occurs.
|
||||||
suppress_http_log_errors = yes
|
suppress_http_log_errors = yes
|
||||||
; HTTP request timeout in seconds.
|
; HTTP request timeout in seconds.
|
||||||
@@ -228,10 +216,6 @@ templates[] = ${prefix}/share/ahriman/templates
|
|||||||
;homepage=
|
;homepage=
|
||||||
; Prefix for packages links. Link to a package will be formed as link_path / filename.
|
; Prefix for packages links. Link to a package will be formed as link_path / filename.
|
||||||
;link_path =
|
;link_path =
|
||||||
; Maximum amount of retries of HTTP requests.
|
|
||||||
;max_retries = 0
|
|
||||||
; Retry exponential backoff.
|
|
||||||
;retry_backoff = 0.0
|
|
||||||
; Optional link to the RSS feed.
|
; Optional link to the RSS feed.
|
||||||
;rss_url =
|
;rss_url =
|
||||||
; Template name to be used.
|
; Template name to be used.
|
||||||
@@ -252,16 +236,12 @@ target =
|
|||||||
[github]
|
[github]
|
||||||
; Trigger type name.
|
; Trigger type name.
|
||||||
;type = github
|
;type = github
|
||||||
; Maximum amount of retries of HTTP requests.
|
|
||||||
;max_retries = 0
|
|
||||||
; GitHub repository owner username.
|
; GitHub repository owner username.
|
||||||
;owner =
|
;owner =
|
||||||
; GitHub API key. public_repo (repo) scope is required.
|
; GitHub API key. public_repo (repo) scope is required.
|
||||||
;password =
|
;password =
|
||||||
; GitHub repository name.
|
; GitHub repository name.
|
||||||
;repository =
|
;repository =
|
||||||
; Retry exponential backoff.
|
|
||||||
;retry_backoff = 0.0
|
|
||||||
; HTTP request timeout in seconds.
|
; HTTP request timeout in seconds.
|
||||||
;timeout = 30
|
;timeout = 30
|
||||||
; Include repository name to release name (recommended).
|
; Include repository name to release name (recommended).
|
||||||
@@ -273,10 +253,6 @@ target =
|
|||||||
[remote-service]
|
[remote-service]
|
||||||
; Trigger type name.
|
; Trigger type name.
|
||||||
;type = remote-service
|
;type = remote-service
|
||||||
; Maximum amount of retries of HTTP requests.
|
|
||||||
;max_retries = 0
|
|
||||||
; Retry exponential backoff.
|
|
||||||
;retry_backoff = 0.0
|
|
||||||
; HTTP request timeout in seconds.
|
; HTTP request timeout in seconds.
|
||||||
;timeout = 30
|
;timeout = 30
|
||||||
|
|
||||||
|
|||||||
@@ -87,7 +87,7 @@
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
updateTable(table, payload, row => row.timestamp);
|
updateTable(table, payload);
|
||||||
table.bootstrapTable("hideLoading");
|
table.bootstrapTable("hideLoading");
|
||||||
},
|
},
|
||||||
onFailure,
|
onFailure,
|
||||||
|
|||||||
@@ -195,19 +195,16 @@
|
|||||||
return intervalId;
|
return intervalId;
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateTable(table, rows, rowChangedKey) {
|
function updateTable(table, rows) {
|
||||||
// instead of using load method here, we just update rows manually to avoid table reinitialization
|
// instead of using load method here, we just update rows manually to avoid table reinitialization
|
||||||
const currentData = table.bootstrapTable("getData").reduce((accumulator, row) => {
|
const currentData = table.bootstrapTable("getData").reduce((accumulator, row) => {
|
||||||
accumulator[row.id] = {state: row["0"], key: rowChangedKey(row)};
|
accumulator[row.id] = row["0"];
|
||||||
return accumulator;
|
return accumulator;
|
||||||
}, {});
|
}, {});
|
||||||
// insert or update rows, skipping ones whose status hasn't changed
|
// insert or update rows
|
||||||
rows.forEach(row => {
|
rows.forEach(row => {
|
||||||
if (Object.hasOwn(currentData, row.id)) {
|
if (Object.hasOwn(currentData, row.id)) {
|
||||||
if (rowChangedKey(row) === currentData[row.id].key) {
|
row["0"] = currentData[row.id]; // copy checkbox state
|
||||||
return;
|
|
||||||
}
|
|
||||||
row["0"] = currentData[row.id].state; // copy checkbox state
|
|
||||||
table.bootstrapTable("updateByUniqueId", {
|
table.bootstrapTable("updateByUniqueId", {
|
||||||
id: row.id,
|
id: row.id,
|
||||||
row: row,
|
row: row,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# AUTOMATICALLY GENERATED by `shtab`
|
# AUTOMATICALLY GENERATED by `shtab`
|
||||||
|
|
||||||
_shtab_ahriman_subparsers=('add' 'aur-search' 'check' 'clean' 'config' 'config-validate' 'copy' 'daemon' 'help' 'help-commands-unsafe' 'help-updates' 'help-version' 'init' 'key-import' 'package-add' 'package-changes' 'package-changes-remove' 'package-copy' 'package-remove' 'package-status' 'package-status-remove' 'package-status-update' 'package-update' 'patch-add' 'patch-list' 'patch-remove' 'patch-set-add' 'rebuild' 'remove' 'remove-unknown' 'repo-backup' 'repo-check' 'repo-clean' 'repo-config' 'repo-config-validate' 'repo-create-keyring' 'repo-create-mirrorlist' 'repo-daemon' 'repo-init' 'repo-rebuild' 'repo-remove-unknown' 'repo-report' 'repo-restore' 'repo-setup' 'repo-sign' 'repo-statistics' 'repo-status-update' 'repo-sync' 'repo-tree' 'repo-triggers' 'repo-update' 'report' 'run' 'search' 'service-clean' 'service-config' 'service-config-validate' 'service-key-import' 'service-repositories' 'service-run' 'service-setup' 'service-shell' 'service-tree-migrate' 'setup' 'shell' 'sign' 'status' 'status-update' 'sync' 'update' 'user-add' 'user-list' 'user-remove' 'version' 'web' 'web-reload')
|
_shtab_ahriman_subparsers=('add' 'aur-search' 'check' 'clean' 'config' 'config-validate' 'copy' 'daemon' 'help' 'help-commands-unsafe' 'help-updates' 'help-version' 'init' 'key-import' 'package-add' 'package-changes' 'package-changes-remove' 'package-copy' 'package-remove' 'package-status' 'package-status-remove' 'package-status-update' 'package-update' 'patch-add' 'patch-list' 'patch-remove' 'patch-set-add' 'rebuild' 'remove' 'remove-unknown' 'repo-backup' 'repo-check' 'repo-clean' 'repo-config' 'repo-config-validate' 'repo-create-keyring' 'repo-create-mirrorlist' 'repo-daemon' 'repo-init' 'repo-rebuild' 'repo-remove-unknown' 'repo-report' 'repo-restore' 'repo-setup' 'repo-sign' 'repo-statistics' 'repo-status-update' 'repo-sync' 'repo-tree' 'repo-triggers' 'repo-update' 'report' 'run' 'search' 'service-clean' 'service-config' 'service-config-validate' 'service-key-import' 'service-repositories' 'service-run' 'service-setup' 'service-shell' 'service-tree-migrate' 'setup' 'shell' 'sign' 'status' 'status-update' 'sync' 'update' 'user-add' 'user-list' 'user-remove' 'version' 'web')
|
||||||
|
|
||||||
_shtab_ahriman_option_strings=('-h' '--help' '-a' '--architecture' '-c' '--configuration' '--force' '-l' '--lock' '--log-handler' '-q' '--quiet' '--report' '--no-report' '-r' '--repository' '--unsafe' '-V' '--version' '--wait-timeout')
|
_shtab_ahriman_option_strings=('-h' '--help' '-a' '--architecture' '-c' '--configuration' '--force' '-l' '--lock' '--log-handler' '-q' '--quiet' '--report' '--no-report' '-r' '--repository' '--unsafe' '-V' '--version' '--wait-timeout')
|
||||||
_shtab_ahriman_add_option_strings=('-h' '--help' '--changes' '--no-changes' '--dependencies' '--no-dependencies' '-e' '--exit-code' '--increment' '--no-increment' '-n' '--now' '-y' '--refresh' '-s' '--source' '-u' '--username' '-v' '--variable')
|
_shtab_ahriman_add_option_strings=('-h' '--help' '--changes' '--no-changes' '--dependencies' '--no-dependencies' '-e' '--exit-code' '--increment' '--no-increment' '-n' '--now' '-y' '--refresh' '-s' '--source' '-u' '--username' '-v' '--variable')
|
||||||
@@ -78,11 +78,10 @@ _shtab_ahriman_user_list_option_strings=('-h' '--help' '-e' '--exit-code' '-R' '
|
|||||||
_shtab_ahriman_user_remove_option_strings=('-h' '--help')
|
_shtab_ahriman_user_remove_option_strings=('-h' '--help')
|
||||||
_shtab_ahriman_version_option_strings=('-h' '--help')
|
_shtab_ahriman_version_option_strings=('-h' '--help')
|
||||||
_shtab_ahriman_web_option_strings=('-h' '--help')
|
_shtab_ahriman_web_option_strings=('-h' '--help')
|
||||||
_shtab_ahriman_web_reload_option_strings=('-h' '--help')
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
_shtab_ahriman_pos_0_choices=('add' 'aur-search' 'check' 'clean' 'config' 'config-validate' 'copy' 'daemon' 'help' 'help-commands-unsafe' 'help-updates' 'help-version' 'init' 'key-import' 'package-add' 'package-changes' 'package-changes-remove' 'package-copy' 'package-remove' 'package-status' 'package-status-remove' 'package-status-update' 'package-update' 'patch-add' 'patch-list' 'patch-remove' 'patch-set-add' 'rebuild' 'remove' 'remove-unknown' 'repo-backup' 'repo-check' 'repo-clean' 'repo-config' 'repo-config-validate' 'repo-create-keyring' 'repo-create-mirrorlist' 'repo-daemon' 'repo-init' 'repo-rebuild' 'repo-remove-unknown' 'repo-report' 'repo-restore' 'repo-setup' 'repo-sign' 'repo-statistics' 'repo-status-update' 'repo-sync' 'repo-tree' 'repo-triggers' 'repo-update' 'report' 'run' 'search' 'service-clean' 'service-config' 'service-config-validate' 'service-key-import' 'service-repositories' 'service-run' 'service-setup' 'service-shell' 'service-tree-migrate' 'setup' 'shell' 'sign' 'status' 'status-update' 'sync' 'update' 'user-add' 'user-list' 'user-remove' 'version' 'web' 'web-reload')
|
_shtab_ahriman_pos_0_choices=('add' 'aur-search' 'check' 'clean' 'config' 'config-validate' 'copy' 'daemon' 'help' 'help-commands-unsafe' 'help-updates' 'help-version' 'init' 'key-import' 'package-add' 'package-changes' 'package-changes-remove' 'package-copy' 'package-remove' 'package-status' 'package-status-remove' 'package-status-update' 'package-update' 'patch-add' 'patch-list' 'patch-remove' 'patch-set-add' 'rebuild' 'remove' 'remove-unknown' 'repo-backup' 'repo-check' 'repo-clean' 'repo-config' 'repo-config-validate' 'repo-create-keyring' 'repo-create-mirrorlist' 'repo-daemon' 'repo-init' 'repo-rebuild' 'repo-remove-unknown' 'repo-report' 'repo-restore' 'repo-setup' 'repo-sign' 'repo-statistics' 'repo-status-update' 'repo-sync' 'repo-tree' 'repo-triggers' 'repo-update' 'report' 'run' 'search' 'service-clean' 'service-config' 'service-config-validate' 'service-key-import' 'service-repositories' 'service-run' 'service-setup' 'service-shell' 'service-tree-migrate' 'setup' 'shell' 'sign' 'status' 'status-update' 'sync' 'update' 'user-add' 'user-list' 'user-remove' 'version' 'web')
|
||||||
_shtab_ahriman___log_handler_choices=('console' 'syslog' 'journald')
|
_shtab_ahriman___log_handler_choices=('console' 'syslog' 'journald')
|
||||||
_shtab_ahriman_add__s_choices=('auto' 'archive' 'aur' 'directory' 'local' 'remote' 'repository')
|
_shtab_ahriman_add__s_choices=('auto' 'archive' 'aur' 'directory' 'local' 'remote' 'repository')
|
||||||
_shtab_ahriman_add___source_choices=('auto' 'archive' 'aur' 'directory' 'local' 'remote' 'repository')
|
_shtab_ahriman_add___source_choices=('auto' 'archive' 'aur' 'directory' 'local' 'remote' 'repository')
|
||||||
@@ -573,8 +572,6 @@ _shtab_ahriman_version__h_nargs=0
|
|||||||
_shtab_ahriman_version___help_nargs=0
|
_shtab_ahriman_version___help_nargs=0
|
||||||
_shtab_ahriman_web__h_nargs=0
|
_shtab_ahriman_web__h_nargs=0
|
||||||
_shtab_ahriman_web___help_nargs=0
|
_shtab_ahriman_web___help_nargs=0
|
||||||
_shtab_ahriman_web_reload__h_nargs=0
|
|
||||||
_shtab_ahriman_web_reload___help_nargs=0
|
|
||||||
|
|
||||||
|
|
||||||
# $1=COMP_WORDS[1]
|
# $1=COMP_WORDS[1]
|
||||||
@@ -677,7 +674,6 @@ _shtab_ahriman() {
|
|||||||
|
|
||||||
if [[ "$current_action_nargs" != "*" ]] && \
|
if [[ "$current_action_nargs" != "*" ]] && \
|
||||||
[[ "$current_action_nargs" != "+" ]] && \
|
[[ "$current_action_nargs" != "+" ]] && \
|
||||||
[[ "$current_action_nargs" != "?" ]] && \
|
|
||||||
[[ "$current_action_nargs" != *"..." ]] && \
|
[[ "$current_action_nargs" != *"..." ]] && \
|
||||||
(( $word_index + 1 - $current_action_args_start_index - $pos_only >= \
|
(( $word_index + 1 - $current_action_args_start_index - $pos_only >= \
|
||||||
$current_action_nargs )); then
|
$current_action_nargs )); then
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
.TH AHRIMAN "1" "2026\-02\-20" "ahriman 2.20.0rc2" "ArcH linux ReposItory MANager"
|
.TH AHRIMAN "1" "2025\-06\-29" "ahriman 2.19.0" "ArcH linux ReposItory MANager"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
ahriman \- ArcH linux ReposItory MANager
|
ahriman \- ArcH linux ReposItory MANager
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B [0m[1;35mahriman[0m
|
.B ahriman
|
||||||
[[32m-h[0m] [[32m-a [33mARCHITECTURE[0m] [[32m-c [33mCONFIGURATION[0m] [[36m--force[0m] [[32m-l [33mLOCK[0m] [[36m--log-handler [33m{console,syslog,journald}[0m] [[32m-q[0m] [[36m--report | --no-report[0m] [[32m-r [33mREPOSITORY[0m] [[36m--unsafe[0m] [[32m-V[0m] [[36m--wait-timeout [33mWAIT_TIMEOUT[0m] [32m{add,aur-search,check,clean,config,config-validate,copy,daemon,help,help-commands-unsafe,help-updates,help-version,init,key-import,package-add,package-changes,package-changes-remove,package-copy,package-remove,package-status,package-status-remove,package-status-update,package-update,patch-add,patch-list,patch-remove,patch-set-add,rebuild,remove,remove-unknown,repo-backup,repo-check,repo-clean,repo-config,repo-config-validate,repo-create-keyring,repo-create-mirrorlist,repo-daemon,repo-init,repo-rebuild,repo-remove-unknown,repo-report,repo-restore,repo-setup,repo-sign,repo-statistics,repo-status-update,repo-sync,repo-tree,repo-triggers,repo-update,report,run,search,service-clean,service-config,service-config-validate,service-key-import,service-repositories,service-run,service-setup,service-shell,service-tree-migrate,setup,shell,sign,status,status-update,sync,update,user-add,user-list,user-remove,version,web,web-reload} ...[0m
|
[-h] [-a ARCHITECTURE] [-c CONFIGURATION] [--force] [-l LOCK] [--log-handler {console,syslog,journald}] [-q] [--report | --no-report] [-r REPOSITORY] [--unsafe] [-V] [--wait-timeout WAIT_TIMEOUT] {add,aur-search,check,clean,config,config-validate,copy,daemon,help,help-commands-unsafe,help-updates,help-version,init,key-import,package-add,package-changes,package-changes-remove,package-copy,package-remove,package-status,package-status-remove,package-status-update,package-update,patch-add,patch-list,patch-remove,patch-set-add,rebuild,remove,remove-unknown,repo-backup,repo-check,repo-clean,repo-config,repo-config-validate,repo-create-keyring,repo-create-mirrorlist,repo-daemon,repo-init,repo-rebuild,repo-remove-unknown,repo-report,repo-restore,repo-setup,repo-sign,repo-statistics,repo-status-update,repo-sync,repo-tree,repo-triggers,repo-update,report,run,search,service-clean,service-config,service-config-validate,service-key-import,service-repositories,service-run,service-setup,service-shell,service-tree-migrate,setup,shell,sign,status,status-update,sync,update,user-add,user-list,user-remove,version,web} ...
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
ArcH linux ReposItory MANager
|
ArcH linux ReposItory MANager
|
||||||
|
|
||||||
@@ -193,14 +193,11 @@ remove user
|
|||||||
.TP
|
.TP
|
||||||
\fBahriman\fR \fI\,web\/\fR
|
\fBahriman\fR \fI\,web\/\fR
|
||||||
web server
|
web server
|
||||||
.TP
|
|
||||||
\fBahriman\fR \fI\,web\-reload\/\fR
|
|
||||||
reload configuration
|
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman aur\-search'\/\fR
|
.SH COMMAND \fI\,'ahriman aur\-search'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman aur\-search[0m [[32m\-h[0m] [[32m\-e[0m] [[36m\-\-info | \-\-no\-info[0m]
|
usage: ahriman aur\-search [\-h] [\-e] [\-\-info | \-\-no\-info]
|
||||||
[[36m\-\-sort\-by [33m{description,first_submitted,id,last_modified,maintainer,name,num_votes,out_of_date,package_base,package_base_id,popularity,repository,submitter,url,url_path,version}[0m]
|
[\-\-sort\-by {description,first_submitted,id,last_modified,maintainer,name,num_votes,out_of_date,package_base,package_base_id,popularity,repository,submitter,url,url_path,version}]
|
||||||
[32msearch [search ...][0m
|
search [search ...]
|
||||||
|
|
||||||
search for package in AUR using API
|
search for package in AUR using API
|
||||||
|
|
||||||
@@ -223,7 +220,7 @@ sort field by this field. In case if two packages have the same value of the spe
|
|||||||
by name
|
by name
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman help'\/\fR
|
.SH COMMAND \fI\,'ahriman help'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman help[0m [[32m\-h[0m] [32m[subcommand][0m
|
usage: ahriman help [\-h] [subcommand]
|
||||||
|
|
||||||
show help message for application or command and exit
|
show help message for application or command and exit
|
||||||
|
|
||||||
@@ -232,7 +229,7 @@ show help message for application or command and exit
|
|||||||
show help message for specific command
|
show help message for specific command
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman help\-commands\-unsafe'\/\fR
|
.SH COMMAND \fI\,'ahriman help\-commands\-unsafe'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman help\-commands\-unsafe[0m [[32m\-h[0m] [32m[subcommand ...][0m
|
usage: ahriman help\-commands\-unsafe [\-h] [subcommand ...]
|
||||||
|
|
||||||
list unsafe commands as defined in default args
|
list unsafe commands as defined in default args
|
||||||
|
|
||||||
@@ -242,7 +239,7 @@ instead of showing commands, just test command line for unsafe subcommand and re
|
|||||||
otherwise
|
otherwise
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman help\-updates'\/\fR
|
.SH COMMAND \fI\,'ahriman help\-updates'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman help\-updates[0m [[32m\-h[0m] [[32m\-e[0m]
|
usage: ahriman help\-updates [\-h] [\-e]
|
||||||
|
|
||||||
request AUR for current version and compare with current service version
|
request AUR for current version and compare with current service version
|
||||||
|
|
||||||
@@ -252,15 +249,15 @@ request AUR for current version and compare with current service version
|
|||||||
return non\-zero exit code if updates available
|
return non\-zero exit code if updates available
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman help\-version'\/\fR
|
.SH COMMAND \fI\,'ahriman help\-version'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman help\-version[0m [[32m\-h[0m]
|
usage: ahriman help\-version [\-h]
|
||||||
|
|
||||||
print application and its dependencies versions
|
print application and its dependencies versions
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman package\-add'\/\fR
|
.SH COMMAND \fI\,'ahriman package\-add'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman package\-add[0m [[32m\-h[0m] [[36m\-\-changes | \-\-no\-changes[0m] [[36m\-\-dependencies | \-\-no\-dependencies[0m] [[32m\-e[0m]
|
usage: ahriman package\-add [\-h] [\-\-changes | \-\-no\-changes] [\-\-dependencies | \-\-no\-dependencies] [\-e]
|
||||||
[[36m\-\-increment | \-\-no\-increment[0m] [[32m\-n[0m] [[32m\-y[0m]
|
[\-\-increment | \-\-no\-increment] [\-n] [\-y]
|
||||||
[[32m\-s [33m{auto,archive,aur,directory,local,remote,repository}[0m] [[32m\-u [33mUSERNAME[0m] [[32m\-v [33mVARIABLE[0m]
|
[\-s {auto,archive,aur,directory,local,remote,repository}] [\-u USERNAME] [\-v VARIABLE]
|
||||||
[32mpackage [package ...][0m
|
package [package ...]
|
||||||
|
|
||||||
add existing or new package to the build queue
|
add existing or new package to the build queue
|
||||||
|
|
||||||
@@ -306,7 +303,7 @@ build as user
|
|||||||
apply specified makepkg variables to the next build
|
apply specified makepkg variables to the next build
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman package\-changes'\/\fR
|
.SH COMMAND \fI\,'ahriman package\-changes'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman package\-changes[0m [[32m\-h[0m] [[32m\-e[0m] [32mpackage[0m
|
usage: ahriman package\-changes [\-h] [\-e] package
|
||||||
|
|
||||||
retrieve package changes stored in database
|
retrieve package changes stored in database
|
||||||
|
|
||||||
@@ -320,7 +317,7 @@ package base
|
|||||||
return non\-zero exit status if result is empty
|
return non\-zero exit status if result is empty
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman package\-changes\-remove'\/\fR
|
.SH COMMAND \fI\,'ahriman package\-changes\-remove'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman package\-changes\-remove[0m [[32m\-h[0m] [32mpackage[0m
|
usage: ahriman package\-changes\-remove [\-h] package
|
||||||
|
|
||||||
remove the package changes stored remotely
|
remove the package changes stored remotely
|
||||||
|
|
||||||
@@ -329,7 +326,7 @@ remove the package changes stored remotely
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman package\-copy'\/\fR
|
.SH COMMAND \fI\,'ahriman package\-copy'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman package\-copy[0m [[32m\-h[0m] [[32m\-e[0m] [[36m\-\-remove[0m] [32msource[0m [32mpackage [package ...][0m
|
usage: ahriman package\-copy [\-h] [\-e] [\-\-remove] source package [package ...]
|
||||||
|
|
||||||
copy package and its metadata from another repository
|
copy package and its metadata from another repository
|
||||||
|
|
||||||
@@ -351,7 +348,7 @@ return non\-zero exit status if result is empty
|
|||||||
remove package from the source repository after
|
remove package from the source repository after
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman package\-remove'\/\fR
|
.SH COMMAND \fI\,'ahriman package\-remove'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman package\-remove[0m [[32m\-h[0m] [32mpackage [package ...][0m
|
usage: ahriman package\-remove [\-h] package [package ...]
|
||||||
|
|
||||||
remove package from the repository
|
remove package from the repository
|
||||||
|
|
||||||
@@ -360,8 +357,8 @@ remove package from the repository
|
|||||||
package name or base
|
package name or base
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman package\-status'\/\fR
|
.SH COMMAND \fI\,'ahriman package\-status'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman package\-status[0m [[32m\-h[0m] [[36m\-\-ahriman[0m] [[32m\-e[0m] [[36m\-\-info | \-\-no\-info[0m] [[32m\-s [33m{unknown,pending,building,failed,success}[0m]
|
usage: ahriman package\-status [\-h] [\-\-ahriman] [\-e] [\-\-info | \-\-no\-info] [\-s {unknown,pending,building,failed,success}]
|
||||||
[32m[package ...][0m
|
[package ...]
|
||||||
|
|
||||||
request status of the package
|
request status of the package
|
||||||
|
|
||||||
@@ -387,7 +384,7 @@ show additional package information
|
|||||||
filter packages by status
|
filter packages by status
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman package\-status\-remove'\/\fR
|
.SH COMMAND \fI\,'ahriman package\-status\-remove'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman package\-status\-remove[0m [[32m\-h[0m] [32mpackage [package ...][0m
|
usage: ahriman package\-status\-remove [\-h] package [package ...]
|
||||||
|
|
||||||
remove the package from the status page
|
remove the package from the status page
|
||||||
|
|
||||||
@@ -396,7 +393,7 @@ remove the package from the status page
|
|||||||
remove specified packages from status page
|
remove specified packages from status page
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman package\-status\-update'\/\fR
|
.SH COMMAND \fI\,'ahriman package\-status\-update'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman package\-status\-update[0m [[32m\-h[0m] [[32m\-s [33m{unknown,pending,building,failed,success}[0m] [32m[package ...][0m
|
usage: ahriman package\-status\-update [\-h] [\-s {unknown,pending,building,failed,success}] [package ...]
|
||||||
|
|
||||||
update package status on the status page
|
update package status on the status page
|
||||||
|
|
||||||
@@ -410,7 +407,7 @@ set status for specified packages. If no packages supplied, service status will
|
|||||||
new package build status
|
new package build status
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman patch\-add'\/\fR
|
.SH COMMAND \fI\,'ahriman patch\-add'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman patch\-add[0m [[32m\-h[0m] [32mpackage[0m [32mvariable[0m [32m[patch][0m
|
usage: ahriman patch\-add [\-h] package variable [patch]
|
||||||
|
|
||||||
create or update patched PKGBUILD function or variable
|
create or update patched PKGBUILD function or variable
|
||||||
|
|
||||||
@@ -427,7 +424,7 @@ PKGBUILD variable or function name. If variable is a function, it must end with
|
|||||||
path to file which contains function or variable value. If not set, the value will be read from stdin
|
path to file which contains function or variable value. If not set, the value will be read from stdin
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman patch\-list'\/\fR
|
.SH COMMAND \fI\,'ahriman patch\-list'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman patch\-list[0m [[32m\-h[0m] [[32m\-e[0m] [[32m\-v [33mVARIABLE[0m] [32mpackage[0m
|
usage: ahriman patch\-list [\-h] [\-e] [\-v VARIABLE] package
|
||||||
|
|
||||||
list available patches for the package
|
list available patches for the package
|
||||||
|
|
||||||
@@ -445,7 +442,7 @@ return non\-zero exit status if result is empty
|
|||||||
if set, show only patches for specified PKGBUILD variables
|
if set, show only patches for specified PKGBUILD variables
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman patch\-remove'\/\fR
|
.SH COMMAND \fI\,'ahriman patch\-remove'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman patch\-remove[0m [[32m\-h[0m] [[32m\-v [33mVARIABLE[0m] [32mpackage[0m
|
usage: ahriman patch\-remove [\-h] [\-v VARIABLE] package
|
||||||
|
|
||||||
remove patches for the package
|
remove patches for the package
|
||||||
|
|
||||||
@@ -460,7 +457,7 @@ should be used for single\-function patches in case if you wold like to remove o
|
|||||||
if not set, it will remove all patches related to the package
|
if not set, it will remove all patches related to the package
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman patch\-set\-add'\/\fR
|
.SH COMMAND \fI\,'ahriman patch\-set\-add'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman patch\-set\-add[0m [[32m\-h[0m] [[32m\-t [33mTRACK[0m] [32mpackage[0m
|
usage: ahriman patch\-set\-add [\-h] [\-t TRACK] package
|
||||||
|
|
||||||
create or update source patches
|
create or update source patches
|
||||||
|
|
||||||
@@ -474,7 +471,7 @@ path to directory with changed files for patch addition/update
|
|||||||
files which has to be tracked
|
files which has to be tracked
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman repo\-backup'\/\fR
|
.SH COMMAND \fI\,'ahriman repo\-backup'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman repo\-backup[0m [[32m\-h[0m] [32mpath[0m
|
usage: ahriman repo\-backup [\-h] path
|
||||||
|
|
||||||
backup repository settings and database
|
backup repository settings and database
|
||||||
|
|
||||||
@@ -483,9 +480,9 @@ backup repository settings and database
|
|||||||
path of the output archive
|
path of the output archive
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman repo\-check'\/\fR
|
.SH COMMAND \fI\,'ahriman repo\-check'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman repo\-check[0m [[32m\-h[0m] [[36m\-\-changes | \-\-no\-changes[0m] [[36m\-\-check\-files | \-\-no\-check\-files[0m] [[32m\-e[0m] [[36m\-\-vcs | \-\-no\-vcs[0m]
|
usage: ahriman repo\-check [\-h] [\-\-changes | \-\-no\-changes] [\-\-check\-files | \-\-no\-check\-files] [\-e] [\-\-vcs | \-\-no\-vcs]
|
||||||
[[32m\-y[0m]
|
[\-y]
|
||||||
[32m[package ...][0m
|
[package ...]
|
||||||
|
|
||||||
check for packages updates. Same as repo\-update \-\-dry\-run \-\-no\-manual
|
check for packages updates. Same as repo\-update \-\-dry\-run \-\-no\-manual
|
||||||
|
|
||||||
@@ -515,20 +512,20 @@ fetch actual version of VCS packages
|
|||||||
download fresh package databases from the mirror before actions, \-yy to force refresh even if up to date
|
download fresh package databases from the mirror before actions, \-yy to force refresh even if up to date
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman repo\-create\-keyring'\/\fR
|
.SH COMMAND \fI\,'ahriman repo\-create\-keyring'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman repo\-create\-keyring[0m [[32m\-h[0m]
|
usage: ahriman repo\-create\-keyring [\-h]
|
||||||
|
|
||||||
create package which contains list of trusted keys as set by configuration. Note, that this action will only create package, the package itself has to be built manually
|
create package which contains list of trusted keys as set by configuration. Note, that this action will only create package, the package itself has to be built manually
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman repo\-create\-mirrorlist'\/\fR
|
.SH COMMAND \fI\,'ahriman repo\-create\-mirrorlist'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman repo\-create\-mirrorlist[0m [[32m\-h[0m]
|
usage: ahriman repo\-create\-mirrorlist [\-h]
|
||||||
|
|
||||||
create package which contains list of available mirrors as set by configuration. Note, that this action will only create package, the package itself has to be built manually
|
create package which contains list of available mirrors as set by configuration. Note, that this action will only create package, the package itself has to be built manually
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman repo\-daemon'\/\fR
|
.SH COMMAND \fI\,'ahriman repo\-daemon'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman repo\-daemon[0m [[32m\-h[0m] [[32m\-i [33mINTERVAL[0m] [[36m\-\-aur | \-\-no\-aur[0m] [[36m\-\-changes | \-\-no\-changes[0m]
|
usage: ahriman repo\-daemon [\-h] [\-i INTERVAL] [\-\-aur | \-\-no\-aur] [\-\-changes | \-\-no\-changes]
|
||||||
[[36m\-\-check\-files | \-\-no\-check\-files[0m] [[36m\-\-dependencies | \-\-no\-dependencies[0m] [[36m\-\-dry\-run[0m]
|
[\-\-check\-files | \-\-no\-check\-files] [\-\-dependencies | \-\-no\-dependencies] [\-\-dry\-run]
|
||||||
[[36m\-\-increment | \-\-no\-increment[0m] [[36m\-\-local | \-\-no\-local[0m] [[36m\-\-manual | \-\-no\-manual[0m]
|
[\-\-increment | \-\-no\-increment] [\-\-local | \-\-no\-local] [\-\-manual | \-\-no\-manual]
|
||||||
[[36m\-\-partitions | \-\-no\-partitions[0m] [[32m\-u [33mUSERNAME[0m] [[36m\-\-vcs | \-\-no\-vcs[0m] [[32m\-y[0m]
|
[\-\-partitions | \-\-no\-partitions] [\-u USERNAME] [\-\-vcs | \-\-no\-vcs] [\-y]
|
||||||
|
|
||||||
start process which periodically will run update process
|
start process which periodically will run update process
|
||||||
|
|
||||||
@@ -586,8 +583,8 @@ fetch actual version of VCS packages
|
|||||||
download fresh package databases from the mirror before actions, \-yy to force refresh even if up to date
|
download fresh package databases from the mirror before actions, \-yy to force refresh even if up to date
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman repo\-rebuild'\/\fR
|
.SH COMMAND \fI\,'ahriman repo\-rebuild'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman repo\-rebuild[0m [[32m\-h[0m] [[36m\-\-depends\-on [33mDEPENDS_ON[0m] [[36m\-\-dry\-run[0m] [[36m\-\-from\-database[0m] [[36m\-\-increment | \-\-no\-increment[0m]
|
usage: ahriman repo\-rebuild [\-h] [\-\-depends\-on DEPENDS_ON] [\-\-dry\-run] [\-\-from\-database] [\-\-increment | \-\-no\-increment]
|
||||||
[[32m\-e[0m] [[32m\-s [33m{unknown,pending,building,failed,success}[0m] [[32m\-u [33mUSERNAME[0m]
|
[\-e] [\-s {unknown,pending,building,failed,success}] [\-u USERNAME]
|
||||||
|
|
||||||
force rebuild whole repository
|
force rebuild whole repository
|
||||||
|
|
||||||
@@ -623,7 +620,7 @@ filter packages by status. Requires \-\-from\-database to be set
|
|||||||
build as user
|
build as user
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman repo\-remove\-unknown'\/\fR
|
.SH COMMAND \fI\,'ahriman repo\-remove\-unknown'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman repo\-remove\-unknown[0m [[32m\-h[0m] [[36m\-\-dry\-run[0m]
|
usage: ahriman repo\-remove\-unknown [\-h] [\-\-dry\-run]
|
||||||
|
|
||||||
remove packages which are missing in AUR and do not have local PKGBUILDs
|
remove packages which are missing in AUR and do not have local PKGBUILDs
|
||||||
|
|
||||||
@@ -633,12 +630,12 @@ remove packages which are missing in AUR and do not have local PKGBUILDs
|
|||||||
just perform check for packages without removal
|
just perform check for packages without removal
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman repo\-report'\/\fR
|
.SH COMMAND \fI\,'ahriman repo\-report'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman repo\-report[0m [[32m\-h[0m]
|
usage: ahriman repo\-report [\-h]
|
||||||
|
|
||||||
generate repository report according to current settings
|
generate repository report according to current settings
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman repo\-restore'\/\fR
|
.SH COMMAND \fI\,'ahriman repo\-restore'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman repo\-restore[0m [[32m\-h[0m] [[32m\-o [33mOUTPUT[0m] [32mpath[0m
|
usage: ahriman repo\-restore [\-h] [\-o OUTPUT] path
|
||||||
|
|
||||||
restore settings and database
|
restore settings and database
|
||||||
|
|
||||||
@@ -652,7 +649,7 @@ path of the input archive
|
|||||||
root path of the extracted files
|
root path of the extracted files
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman repo\-sign'\/\fR
|
.SH COMMAND \fI\,'ahriman repo\-sign'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman repo\-sign[0m [[32m\-h[0m] [32m[package ...][0m
|
usage: ahriman repo\-sign [\-h] [package ...]
|
||||||
|
|
||||||
(re\-)sign packages and repository database according to current settings
|
(re\-)sign packages and repository database according to current settings
|
||||||
|
|
||||||
@@ -661,10 +658,10 @@ root path of the extracted files
|
|||||||
sign only specified packages
|
sign only specified packages
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman repo\-statistics'\/\fR
|
.SH COMMAND \fI\,'ahriman repo\-statistics'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman repo\-statistics[0m [[32m\-h[0m] [[36m\-\-chart [33mCHART[0m]
|
usage: ahriman repo\-statistics [\-h] [\-\-chart CHART]
|
||||||
[[32m\-e [33m{package\-outdated,package\-removed,package\-update\-failed,package\-updated}[0m]
|
[\-e {package\-outdated,package\-removed,package\-update\-failed,package\-updated}]
|
||||||
[[36m\-\-from\-date [33mFROM_DATE[0m] [[36m\-\-limit [33mLIMIT[0m] [[36m\-\-offset [33mOFFSET[0m] [[36m\-\-to\-date [33mTO_DATE[0m]
|
[\-\-from\-date FROM_DATE] [\-\-limit LIMIT] [\-\-offset OFFSET] [\-\-to\-date TO_DATE]
|
||||||
[32m[package][0m
|
[package]
|
||||||
|
|
||||||
fetch repository statistics
|
fetch repository statistics
|
||||||
|
|
||||||
@@ -698,7 +695,7 @@ skip specified amount of events
|
|||||||
only fetch events which are older than the date
|
only fetch events which are older than the date
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman repo\-status\-update'\/\fR
|
.SH COMMAND \fI\,'ahriman repo\-status\-update'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman repo\-status\-update[0m [[32m\-h[0m] [[32m\-s [33m{unknown,pending,building,failed,success}[0m]
|
usage: ahriman repo\-status\-update [\-h] [\-s {unknown,pending,building,failed,success}]
|
||||||
|
|
||||||
update repository status on the status page
|
update repository status on the status page
|
||||||
|
|
||||||
@@ -708,12 +705,12 @@ update repository status on the status page
|
|||||||
new status
|
new status
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman repo\-sync'\/\fR
|
.SH COMMAND \fI\,'ahriman repo\-sync'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman repo\-sync[0m [[32m\-h[0m]
|
usage: ahriman repo\-sync [\-h]
|
||||||
|
|
||||||
sync repository files to remote server according to current settings
|
sync repository files to remote server according to current settings
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman repo\-tree'\/\fR
|
.SH COMMAND \fI\,'ahriman repo\-tree'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman repo\-tree[0m [[32m\-h[0m] [[32m\-p [33mPARTITIONS[0m]
|
usage: ahriman repo\-tree [\-h] [\-p PARTITIONS]
|
||||||
|
|
||||||
dump repository tree based on packages dependencies
|
dump repository tree based on packages dependencies
|
||||||
|
|
||||||
@@ -723,7 +720,7 @@ dump repository tree based on packages dependencies
|
|||||||
also divide packages by independent partitions
|
also divide packages by independent partitions
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman repo\-triggers'\/\fR
|
.SH COMMAND \fI\,'ahriman repo\-triggers'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman repo\-triggers[0m [[32m\-h[0m] [32m[trigger ...][0m
|
usage: ahriman repo\-triggers [\-h] [trigger ...]
|
||||||
|
|
||||||
run triggers on empty build result as configured by settings
|
run triggers on empty build result as configured by settings
|
||||||
|
|
||||||
@@ -732,10 +729,10 @@ run triggers on empty build result as configured by settings
|
|||||||
instead of running all triggers as set by configuration, just process specified ones in order of mention
|
instead of running all triggers as set by configuration, just process specified ones in order of mention
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman repo\-update'\/\fR
|
.SH COMMAND \fI\,'ahriman repo\-update'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman repo\-update[0m [[32m\-h[0m] [[36m\-\-aur | \-\-no\-aur[0m] [[36m\-\-changes | \-\-no\-changes[0m] [[36m\-\-check\-files | \-\-no\-check\-files[0m]
|
usage: ahriman repo\-update [\-h] [\-\-aur | \-\-no\-aur] [\-\-changes | \-\-no\-changes] [\-\-check\-files | \-\-no\-check\-files]
|
||||||
[[36m\-\-dependencies | \-\-no\-dependencies[0m] [[36m\-\-dry\-run[0m] [[32m\-e[0m] [[36m\-\-increment | \-\-no\-increment[0m]
|
[\-\-dependencies | \-\-no\-dependencies] [\-\-dry\-run] [\-e] [\-\-increment | \-\-no\-increment]
|
||||||
[[36m\-\-local | \-\-no\-local[0m] [[36m\-\-manual | \-\-no\-manual[0m] [[32m\-u [33mUSERNAME[0m] [[36m\-\-vcs | \-\-no\-vcs[0m] [[32m\-y[0m]
|
[\-\-local | \-\-no\-local] [\-\-manual | \-\-no\-manual] [\-u USERNAME] [\-\-vcs | \-\-no\-vcs] [\-y]
|
||||||
[32m[package ...][0m
|
[package ...]
|
||||||
|
|
||||||
check for packages updates and run build process if requested
|
check for packages updates and run build process if requested
|
||||||
|
|
||||||
@@ -793,8 +790,8 @@ fetch actual version of VCS packages
|
|||||||
download fresh package databases from the mirror before actions, \-yy to force refresh even if up to date
|
download fresh package databases from the mirror before actions, \-yy to force refresh even if up to date
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman service\-clean'\/\fR
|
.SH COMMAND \fI\,'ahriman service\-clean'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman service\-clean[0m [[32m\-h[0m] [[36m\-\-cache | \-\-no\-cache[0m] [[36m\-\-chroot | \-\-no\-chroot[0m] [[36m\-\-manual | \-\-no\-manual[0m]
|
usage: ahriman service\-clean [\-h] [\-\-cache | \-\-no\-cache] [\-\-chroot | \-\-no\-chroot] [\-\-manual | \-\-no\-manual]
|
||||||
[[36m\-\-packages | \-\-no\-packages[0m] [[36m\-\-pacman | \-\-no\-pacman[0m]
|
[\-\-packages | \-\-no\-packages] [\-\-pacman | \-\-no\-pacman]
|
||||||
|
|
||||||
remove local caches
|
remove local caches
|
||||||
|
|
||||||
@@ -820,7 +817,7 @@ clear directory with built packages
|
|||||||
clear directory with pacman local database cache
|
clear directory with pacman local database cache
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman service\-config'\/\fR
|
.SH COMMAND \fI\,'ahriman service\-config'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman service\-config[0m [[32m\-h[0m] [[36m\-\-info | \-\-no\-info[0m] [[36m\-\-secure | \-\-no\-secure[0m] [32m[section][0m [32m[key][0m
|
usage: ahriman service\-config [\-h] [\-\-info | \-\-no\-info] [\-\-secure | \-\-no\-secure] [section] [key]
|
||||||
|
|
||||||
dump configuration for the specified architecture
|
dump configuration for the specified architecture
|
||||||
|
|
||||||
@@ -842,7 +839,7 @@ show additional information, e.g. configuration files
|
|||||||
hide passwords and secrets from output
|
hide passwords and secrets from output
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman service\-config\-validate'\/\fR
|
.SH COMMAND \fI\,'ahriman service\-config\-validate'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman service\-config\-validate[0m [[32m\-h[0m] [[32m\-e[0m]
|
usage: ahriman service\-config\-validate [\-h] [\-e]
|
||||||
|
|
||||||
validate configuration and print found errors
|
validate configuration and print found errors
|
||||||
|
|
||||||
@@ -852,7 +849,7 @@ validate configuration and print found errors
|
|||||||
return non\-zero exit status if configuration is invalid
|
return non\-zero exit status if configuration is invalid
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman service\-key\-import'\/\fR
|
.SH COMMAND \fI\,'ahriman service\-key\-import'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman service\-key\-import[0m [[32m\-h[0m] [[36m\-\-key\-server [33mKEY_SERVER[0m] [32mkey[0m
|
usage: ahriman service\-key\-import [\-h] [\-\-key\-server KEY_SERVER] key
|
||||||
|
|
||||||
import PGP key from public sources to the repository user
|
import PGP key from public sources to the repository user
|
||||||
|
|
||||||
@@ -866,7 +863,7 @@ PGP key to import from public server
|
|||||||
key server for key import
|
key server for key import
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman service\-repositories'\/\fR
|
.SH COMMAND \fI\,'ahriman service\-repositories'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman service\-repositories[0m [[32m\-h[0m] [[36m\-\-id\-only | \-\-no\-id\-only[0m]
|
usage: ahriman service\-repositories [\-h] [\-\-id\-only | \-\-no\-id\-only]
|
||||||
|
|
||||||
list all available repositories
|
list all available repositories
|
||||||
|
|
||||||
@@ -876,7 +873,7 @@ list all available repositories
|
|||||||
show machine readable identifier instead
|
show machine readable identifier instead
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman service\-run'\/\fR
|
.SH COMMAND \fI\,'ahriman service\-run'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman service\-run[0m [[32m\-h[0m] [32mcommand [command ...][0m
|
usage: ahriman service\-run [\-h] command [command ...]
|
||||||
|
|
||||||
run multiple commands on success run of the previous command
|
run multiple commands on success run of the previous command
|
||||||
|
|
||||||
@@ -885,11 +882,11 @@ run multiple commands on success run of the previous command
|
|||||||
command to be run (quoted) without ``ahriman``
|
command to be run (quoted) without ``ahriman``
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman service\-setup'\/\fR
|
.SH COMMAND \fI\,'ahriman service\-setup'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman service\-setup[0m [[32m\-h[0m] [[36m\-\-build\-as\-user [33mBUILD_AS_USER[0m] [[36m\-\-from\-configuration [33mFROM_CONFIGURATION[0m]
|
usage: ahriman service\-setup [\-h] [\-\-build\-as\-user BUILD_AS_USER] [\-\-from\-configuration FROM_CONFIGURATION]
|
||||||
[[36m\-\-generate\-salt | \-\-no\-generate\-salt[0m] [[36m\-\-makeflags\-jobs | \-\-no\-makeflags\-jobs[0m]
|
[\-\-generate\-salt | \-\-no\-generate\-salt] [\-\-makeflags\-jobs | \-\-no\-makeflags\-jobs]
|
||||||
[[36m\-\-mirror [33mMIRROR[0m] [[36m\-\-multilib | \-\-no\-multilib[0m] [36m\-\-packager [33mPACKAGER[0m [[36m\-\-server [33mSERVER[0m]
|
[\-\-mirror MIRROR] [\-\-multilib | \-\-no\-multilib] \-\-packager PACKAGER [\-\-server SERVER]
|
||||||
[[36m\-\-sign\-key [33mSIGN_KEY[0m] [[36m\-\-sign\-target [33m{disabled,packages,repository}[0m] [[36m\-\-web\-port [33mWEB_PORT[0m]
|
[\-\-sign\-key SIGN_KEY] [\-\-sign\-target {disabled,packages,repository}] [\-\-web\-port WEB_PORT]
|
||||||
[[36m\-\-web\-unix\-socket [33mWEB_UNIX_SOCKET[0m]
|
[\-\-web\-unix\-socket WEB_UNIX_SOCKET]
|
||||||
|
|
||||||
create initial service configuration, requires root
|
create initial service configuration, requires root
|
||||||
|
|
||||||
@@ -943,7 +940,7 @@ port of the web service
|
|||||||
path to unix socket used for interprocess communications
|
path to unix socket used for interprocess communications
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman service\-shell'\/\fR
|
.SH COMMAND \fI\,'ahriman service\-shell'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman service\-shell[0m [[32m\-h[0m] [[32m\-o [33mOUTPUT[0m] [32m[code][0m
|
usage: ahriman service\-shell [\-h] [\-o OUTPUT] [code]
|
||||||
|
|
||||||
drop into python shell
|
drop into python shell
|
||||||
|
|
||||||
@@ -957,13 +954,13 @@ instead of dropping into shell, just execute the specified code
|
|||||||
output commands and result to the file
|
output commands and result to the file
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman service\-tree\-migrate'\/\fR
|
.SH COMMAND \fI\,'ahriman service\-tree\-migrate'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman service\-tree\-migrate[0m [[32m\-h[0m]
|
usage: ahriman service\-tree\-migrate [\-h]
|
||||||
|
|
||||||
migrate repository tree between versions
|
migrate repository tree between versions
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman user\-add'\/\fR
|
.SH COMMAND \fI\,'ahriman user\-add'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman user\-add[0m [[32m\-h[0m] [[36m\-\-key [33mKEY[0m] [[36m\-\-packager [33mPACKAGER[0m] [[32m\-p [33mPASSWORD[0m] [[32m\-R [33m{unauthorized,read,reporter,full}[0m]
|
usage: ahriman user\-add [\-h] [\-\-key KEY] [\-\-packager PACKAGER] [\-p PASSWORD] [\-R {unauthorized,read,reporter,full}]
|
||||||
[32musername[0m
|
username
|
||||||
|
|
||||||
update user for web services with the given password and role. In case if password was not entered it will be asked interactively
|
update user for web services with the given password and role. In case if password was not entered it will be asked interactively
|
||||||
|
|
||||||
@@ -990,7 +987,7 @@ authorization type.
|
|||||||
user access level
|
user access level
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman user\-list'\/\fR
|
.SH COMMAND \fI\,'ahriman user\-list'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman user\-list[0m [[32m\-h[0m] [[32m\-e[0m] [[32m\-R [33m{unauthorized,read,reporter,full}[0m] [32m[username][0m
|
usage: ahriman user\-list [\-h] [\-e] [\-R {unauthorized,read,reporter,full}] [username]
|
||||||
|
|
||||||
list users from the user mapping and their roles
|
list users from the user mapping and their roles
|
||||||
|
|
||||||
@@ -1008,7 +1005,7 @@ return non\-zero exit status if result is empty
|
|||||||
filter users by role
|
filter users by role
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman user\-remove'\/\fR
|
.SH COMMAND \fI\,'ahriman user\-remove'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman user\-remove[0m [[32m\-h[0m] [32musername[0m
|
usage: ahriman user\-remove [\-h] username
|
||||||
|
|
||||||
remove user from the user mapping and update the configuration
|
remove user from the user mapping and update the configuration
|
||||||
|
|
||||||
@@ -1017,15 +1014,10 @@ remove user from the user mapping and update the configuration
|
|||||||
username for web service
|
username for web service
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman web'\/\fR
|
.SH COMMAND \fI\,'ahriman web'\/\fR
|
||||||
[1;34musage: [0m[1;35mahriman web[0m [[32m\-h[0m]
|
usage: ahriman web [\-h]
|
||||||
|
|
||||||
start web server
|
start web server
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman web\-reload'\/\fR
|
|
||||||
[1;34musage: [0m[1;35mahriman web\-reload[0m [[32m\-h[0m]
|
|
||||||
|
|
||||||
reload web server configuration
|
|
||||||
|
|
||||||
.SH COMMENTS
|
.SH COMMENTS
|
||||||
Quick setup command (replace repository name, architecture and packager as needed):
|
Quick setup command (replace repository name, architecture and packager as needed):
|
||||||
|
|
||||||
|
|||||||
@@ -80,7 +80,6 @@ _shtab_ahriman_commands() {
|
|||||||
"user-remove:remove user from the user mapping and update the configuration"
|
"user-remove:remove user from the user mapping and update the configuration"
|
||||||
"version:print application and its dependencies versions"
|
"version:print application and its dependencies versions"
|
||||||
"web:start web server"
|
"web:start web server"
|
||||||
"web-reload:reload web server configuration"
|
|
||||||
)
|
)
|
||||||
_describe 'ahriman commands' _commands
|
_describe 'ahriman commands' _commands
|
||||||
}
|
}
|
||||||
@@ -100,9 +99,6 @@ _shtab_ahriman_options=(
|
|||||||
"--wait-timeout[wait for lock to be free. Negative value will lead to immediate application run even if there is lock file. In case of zero value, the application will wait infinitely (default\: -1)]:wait_timeout:"
|
"--wait-timeout[wait for lock to be free. Negative value will lead to immediate application run even if there is lock file. In case of zero value, the application will wait infinitely (default\: -1)]:wait_timeout:"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_add_options=(
|
_shtab_ahriman_add_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{--changes,--no-changes}"[calculate changes from the latest known commit if available (default\: True)]:changes:"
|
{--changes,--no-changes}"[calculate changes from the latest known commit if available (default\: True)]:changes:"
|
||||||
@@ -117,9 +113,6 @@ _shtab_ahriman_add_options=(
|
|||||||
"(*):package source (base name, path to local files, remote URL):"
|
"(*):package source (base name, path to local files, remote URL):"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_add_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_aur_search_options=(
|
_shtab_ahriman_aur_search_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{-e,--exit-code}"[return non-zero exit status if result is empty (default\: False)]"
|
{-e,--exit-code}"[return non-zero exit status if result is empty (default\: False)]"
|
||||||
@@ -128,9 +121,6 @@ _shtab_ahriman_aur_search_options=(
|
|||||||
"(*):search terms, can be specified multiple times, the result will match all terms:"
|
"(*):search terms, can be specified multiple times, the result will match all terms:"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_aur_search_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_check_options=(
|
_shtab_ahriman_check_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{--changes,--no-changes}"[calculate changes from the latest known commit if available (default\: True)]:changes:"
|
{--changes,--no-changes}"[calculate changes from the latest known commit if available (default\: True)]:changes:"
|
||||||
@@ -141,9 +131,6 @@ _shtab_ahriman_check_options=(
|
|||||||
"(*)::filter check by package base (default\: None):"
|
"(*)::filter check by package base (default\: None):"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_check_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_clean_options=(
|
_shtab_ahriman_clean_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{--cache,--no-cache}"[clear directory with package caches (default\: False)]:cache:"
|
{--cache,--no-cache}"[clear directory with package caches (default\: False)]:cache:"
|
||||||
@@ -153,9 +140,6 @@ _shtab_ahriman_clean_options=(
|
|||||||
{--pacman,--no-pacman}"[clear directory with pacman local database cache (default\: False)]:pacman:"
|
{--pacman,--no-pacman}"[clear directory with pacman local database cache (default\: False)]:pacman:"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_clean_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_config_options=(
|
_shtab_ahriman_config_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{--info,--no-info}"[show additional information, e.g. configuration files (default\: True)]:info:"
|
{--info,--no-info}"[show additional information, e.g. configuration files (default\: True)]:info:"
|
||||||
@@ -164,17 +148,11 @@ _shtab_ahriman_config_options=(
|
|||||||
":filter settings by key (default\: None):"
|
":filter settings by key (default\: None):"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_config_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_config_validate_options=(
|
_shtab_ahriman_config_validate_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{-e,--exit-code}"[return non-zero exit status if configuration is invalid (default\: False)]"
|
{-e,--exit-code}"[return non-zero exit status if configuration is invalid (default\: False)]"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_config_validate_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_copy_options=(
|
_shtab_ahriman_copy_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{-e,--exit-code}"[return non-zero exit status if result is empty (default\: False)]"
|
{-e,--exit-code}"[return non-zero exit status if result is empty (default\: False)]"
|
||||||
@@ -183,9 +161,6 @@ _shtab_ahriman_copy_options=(
|
|||||||
"(*):package base:"
|
"(*):package base:"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_copy_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_daemon_options=(
|
_shtab_ahriman_daemon_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{-i,--interval}"[interval between runs in seconds (default\: 43200)]:interval:"
|
{-i,--interval}"[interval between runs in seconds (default\: 43200)]:interval:"
|
||||||
@@ -203,40 +178,25 @@ _shtab_ahriman_daemon_options=(
|
|||||||
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date (default\: False)]"
|
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date (default\: False)]"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_daemon_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_help_options=(
|
_shtab_ahriman_help_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
":show help message for specific command (default\: None):"
|
":show help message for specific command (default\: None):"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_help_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_help_commands_unsafe_options=(
|
_shtab_ahriman_help_commands_unsafe_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
"(*)::instead of showing commands, just test command line for unsafe subcommand and return 0 in case if command is safe and 1 otherwise (default\: None):"
|
"(*)::instead of showing commands, just test command line for unsafe subcommand and return 0 in case if command is safe and 1 otherwise (default\: None):"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_help_commands_unsafe_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_help_updates_options=(
|
_shtab_ahriman_help_updates_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{-e,--exit-code}"[return non-zero exit code if updates available (default\: False)]"
|
{-e,--exit-code}"[return non-zero exit code if updates available (default\: False)]"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_help_updates_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_help_version_options=(
|
_shtab_ahriman_help_version_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_help_version_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_init_options=(
|
_shtab_ahriman_init_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
"--build-as-user[force makepkg user to the specific one (default\: None)]:build_as_user:"
|
"--build-as-user[force makepkg user to the specific one (default\: None)]:build_as_user:"
|
||||||
@@ -245,7 +205,7 @@ _shtab_ahriman_init_options=(
|
|||||||
{--makeflags-jobs,--no-makeflags-jobs}"[append MAKEFLAGS variable with parallelism set to number of cores (default\: True)]:makeflags_jobs:"
|
{--makeflags-jobs,--no-makeflags-jobs}"[append MAKEFLAGS variable with parallelism set to number of cores (default\: True)]:makeflags_jobs:"
|
||||||
"--mirror[use the specified explicitly mirror instead of including mirrorlist (default\: None)]:mirror:"
|
"--mirror[use the specified explicitly mirror instead of including mirrorlist (default\: None)]:mirror:"
|
||||||
{--multilib,--no-multilib}"[add or do not multilib repository (default\: True)]:multilib:"
|
{--multilib,--no-multilib}"[add or do not multilib repository (default\: True)]:multilib:"
|
||||||
"--packager[packager name and email]:packager:"
|
"--packager[packager name and email (default\: None)]:packager:"
|
||||||
"--server[server to be used for devtools. If none set, local files will be used (default\: None)]:server:"
|
"--server[server to be used for devtools. If none set, local files will be used (default\: None)]:server:"
|
||||||
"--sign-key[sign key id (default\: None)]:sign_key:"
|
"--sign-key[sign key id (default\: None)]:sign_key:"
|
||||||
"*--sign-target[sign options (default\: None)]:sign_target:(disabled packages repository)"
|
"*--sign-target[sign options (default\: None)]:sign_target:(disabled packages repository)"
|
||||||
@@ -253,18 +213,12 @@ _shtab_ahriman_init_options=(
|
|||||||
"--web-unix-socket[path to unix socket used for interprocess communications (default\: None)]:web_unix_socket:"
|
"--web-unix-socket[path to unix socket used for interprocess communications (default\: None)]:web_unix_socket:"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_init_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_key_import_options=(
|
_shtab_ahriman_key_import_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
"--key-server[key server for key import (default\: keyserver.ubuntu.com)]:key_server:"
|
"--key-server[key server for key import (default\: keyserver.ubuntu.com)]:key_server:"
|
||||||
":PGP key to import from public server:"
|
":PGP key to import from public server:"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_key_import_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_package_add_options=(
|
_shtab_ahriman_package_add_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{--changes,--no-changes}"[calculate changes from the latest known commit if available (default\: True)]:changes:"
|
{--changes,--no-changes}"[calculate changes from the latest known commit if available (default\: True)]:changes:"
|
||||||
@@ -279,26 +233,17 @@ _shtab_ahriman_package_add_options=(
|
|||||||
"(*):package source (base name, path to local files, remote URL):"
|
"(*):package source (base name, path to local files, remote URL):"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_package_add_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_package_changes_options=(
|
_shtab_ahriman_package_changes_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{-e,--exit-code}"[return non-zero exit status if result is empty (default\: False)]"
|
{-e,--exit-code}"[return non-zero exit status if result is empty (default\: False)]"
|
||||||
":package base:"
|
":package base:"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_package_changes_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_package_changes_remove_options=(
|
_shtab_ahriman_package_changes_remove_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
":package base:"
|
":package base:"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_package_changes_remove_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_package_copy_options=(
|
_shtab_ahriman_package_copy_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{-e,--exit-code}"[return non-zero exit status if result is empty (default\: False)]"
|
{-e,--exit-code}"[return non-zero exit status if result is empty (default\: False)]"
|
||||||
@@ -307,17 +252,11 @@ _shtab_ahriman_package_copy_options=(
|
|||||||
"(*):package base:"
|
"(*):package base:"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_package_copy_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_package_remove_options=(
|
_shtab_ahriman_package_remove_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
"(*):package name or base:"
|
"(*):package name or base:"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_package_remove_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_package_status_options=(
|
_shtab_ahriman_package_status_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
"--ahriman[get service status itself (default\: False)]"
|
"--ahriman[get service status itself (default\: False)]"
|
||||||
@@ -327,26 +266,17 @@ _shtab_ahriman_package_status_options=(
|
|||||||
"(*)::filter status by package base (default\: None):"
|
"(*)::filter status by package base (default\: None):"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_package_status_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_package_status_remove_options=(
|
_shtab_ahriman_package_status_remove_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
"(*):remove specified packages from status page:"
|
"(*):remove specified packages from status page:"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_package_status_remove_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_package_status_update_options=(
|
_shtab_ahriman_package_status_update_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{-s,--status}"[new package build status (default\: success)]:status:(unknown pending building failed success)"
|
{-s,--status}"[new package build status (default\: success)]:status:(unknown pending building failed success)"
|
||||||
"(*)::set status for specified packages. If no packages supplied, service status will be updated (default\: None):"
|
"(*)::set status for specified packages. If no packages supplied, service status will be updated (default\: None):"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_package_status_update_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_package_update_options=(
|
_shtab_ahriman_package_update_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{--changes,--no-changes}"[calculate changes from the latest known commit if available (default\: True)]:changes:"
|
{--changes,--no-changes}"[calculate changes from the latest known commit if available (default\: True)]:changes:"
|
||||||
@@ -361,9 +291,6 @@ _shtab_ahriman_package_update_options=(
|
|||||||
"(*):package source (base name, path to local files, remote URL):"
|
"(*):package source (base name, path to local files, remote URL):"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_package_update_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_patch_add_options=(
|
_shtab_ahriman_patch_add_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
":package base:"
|
":package base:"
|
||||||
@@ -371,9 +298,6 @@ _shtab_ahriman_patch_add_options=(
|
|||||||
":path to file which contains function or variable value. If not set, the value will be read from stdin (default\: None):"
|
":path to file which contains function or variable value. If not set, the value will be read from stdin (default\: None):"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_patch_add_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_patch_list_options=(
|
_shtab_ahriman_patch_list_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{-e,--exit-code}"[return non-zero exit status if result is empty (default\: False)]"
|
{-e,--exit-code}"[return non-zero exit status if result is empty (default\: False)]"
|
||||||
@@ -381,27 +305,18 @@ _shtab_ahriman_patch_list_options=(
|
|||||||
":package base:"
|
":package base:"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_patch_list_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_patch_remove_options=(
|
_shtab_ahriman_patch_remove_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
"*"{-v,--variable}"[should be used for single-function patches in case if you wold like to remove only specified PKGBUILD variables. In case if not set, it will remove all patches related to the package (default\: None)]:variable:"
|
"*"{-v,--variable}"[should be used for single-function patches in case if you wold like to remove only specified PKGBUILD variables. In case if not set, it will remove all patches related to the package (default\: None)]:variable:"
|
||||||
":package base:"
|
":package base:"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_patch_remove_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_patch_set_add_options=(
|
_shtab_ahriman_patch_set_add_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
"*"{-t,--track}"[files which has to be tracked (default\: \[\'\*.diff\', \'\*.patch\'\])]:track:"
|
"*"{-t,--track}"[files which has to be tracked (default\: \[\'\*.diff\', \'\*.patch\'\])]:track:"
|
||||||
":path to directory with changed files for patch addition\/update:"
|
":path to directory with changed files for patch addition\/update:"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_patch_set_add_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_rebuild_options=(
|
_shtab_ahriman_rebuild_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
"*--depends-on[only rebuild packages that depend on specified packages (default\: None)]:depends_on:"
|
"*--depends-on[only rebuild packages that depend on specified packages (default\: None)]:depends_on:"
|
||||||
@@ -413,33 +328,21 @@ _shtab_ahriman_rebuild_options=(
|
|||||||
{-u,--username}"[build as user (default\: None)]:username:"
|
{-u,--username}"[build as user (default\: None)]:username:"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_rebuild_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_remove_options=(
|
_shtab_ahriman_remove_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
"(*):package name or base:"
|
"(*):package name or base:"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_remove_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_remove_unknown_options=(
|
_shtab_ahriman_remove_unknown_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
"--dry-run[just perform check for packages without removal (default\: False)]"
|
"--dry-run[just perform check for packages without removal (default\: False)]"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_remove_unknown_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_repo_backup_options=(
|
_shtab_ahriman_repo_backup_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
":path of the output archive:"
|
":path of the output archive:"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_repo_backup_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_repo_check_options=(
|
_shtab_ahriman_repo_check_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{--changes,--no-changes}"[calculate changes from the latest known commit if available (default\: True)]:changes:"
|
{--changes,--no-changes}"[calculate changes from the latest known commit if available (default\: True)]:changes:"
|
||||||
@@ -450,9 +353,6 @@ _shtab_ahriman_repo_check_options=(
|
|||||||
"(*)::filter check by package base (default\: None):"
|
"(*)::filter check by package base (default\: None):"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_repo_check_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_repo_clean_options=(
|
_shtab_ahriman_repo_clean_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{--cache,--no-cache}"[clear directory with package caches (default\: False)]:cache:"
|
{--cache,--no-cache}"[clear directory with package caches (default\: False)]:cache:"
|
||||||
@@ -462,9 +362,6 @@ _shtab_ahriman_repo_clean_options=(
|
|||||||
{--pacman,--no-pacman}"[clear directory with pacman local database cache (default\: False)]:pacman:"
|
{--pacman,--no-pacman}"[clear directory with pacman local database cache (default\: False)]:pacman:"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_repo_clean_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_repo_config_options=(
|
_shtab_ahriman_repo_config_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{--info,--no-info}"[show additional information, e.g. configuration files (default\: True)]:info:"
|
{--info,--no-info}"[show additional information, e.g. configuration files (default\: True)]:info:"
|
||||||
@@ -473,31 +370,19 @@ _shtab_ahriman_repo_config_options=(
|
|||||||
":filter settings by key (default\: None):"
|
":filter settings by key (default\: None):"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_repo_config_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_repo_config_validate_options=(
|
_shtab_ahriman_repo_config_validate_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{-e,--exit-code}"[return non-zero exit status if configuration is invalid (default\: False)]"
|
{-e,--exit-code}"[return non-zero exit status if configuration is invalid (default\: False)]"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_repo_config_validate_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_repo_create_keyring_options=(
|
_shtab_ahriman_repo_create_keyring_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_repo_create_keyring_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_repo_create_mirrorlist_options=(
|
_shtab_ahriman_repo_create_mirrorlist_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_repo_create_mirrorlist_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_repo_daemon_options=(
|
_shtab_ahriman_repo_daemon_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{-i,--interval}"[interval between runs in seconds (default\: 43200)]:interval:"
|
{-i,--interval}"[interval between runs in seconds (default\: 43200)]:interval:"
|
||||||
@@ -515,9 +400,6 @@ _shtab_ahriman_repo_daemon_options=(
|
|||||||
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date (default\: False)]"
|
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date (default\: False)]"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_repo_daemon_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_repo_init_options=(
|
_shtab_ahriman_repo_init_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
"--build-as-user[force makepkg user to the specific one (default\: None)]:build_as_user:"
|
"--build-as-user[force makepkg user to the specific one (default\: None)]:build_as_user:"
|
||||||
@@ -526,7 +408,7 @@ _shtab_ahriman_repo_init_options=(
|
|||||||
{--makeflags-jobs,--no-makeflags-jobs}"[append MAKEFLAGS variable with parallelism set to number of cores (default\: True)]:makeflags_jobs:"
|
{--makeflags-jobs,--no-makeflags-jobs}"[append MAKEFLAGS variable with parallelism set to number of cores (default\: True)]:makeflags_jobs:"
|
||||||
"--mirror[use the specified explicitly mirror instead of including mirrorlist (default\: None)]:mirror:"
|
"--mirror[use the specified explicitly mirror instead of including mirrorlist (default\: None)]:mirror:"
|
||||||
{--multilib,--no-multilib}"[add or do not multilib repository (default\: True)]:multilib:"
|
{--multilib,--no-multilib}"[add or do not multilib repository (default\: True)]:multilib:"
|
||||||
"--packager[packager name and email]:packager:"
|
"--packager[packager name and email (default\: None)]:packager:"
|
||||||
"--server[server to be used for devtools. If none set, local files will be used (default\: None)]:server:"
|
"--server[server to be used for devtools. If none set, local files will be used (default\: None)]:server:"
|
||||||
"--sign-key[sign key id (default\: None)]:sign_key:"
|
"--sign-key[sign key id (default\: None)]:sign_key:"
|
||||||
"*--sign-target[sign options (default\: None)]:sign_target:(disabled packages repository)"
|
"*--sign-target[sign options (default\: None)]:sign_target:(disabled packages repository)"
|
||||||
@@ -534,9 +416,6 @@ _shtab_ahriman_repo_init_options=(
|
|||||||
"--web-unix-socket[path to unix socket used for interprocess communications (default\: None)]:web_unix_socket:"
|
"--web-unix-socket[path to unix socket used for interprocess communications (default\: None)]:web_unix_socket:"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_repo_init_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_repo_rebuild_options=(
|
_shtab_ahriman_repo_rebuild_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
"*--depends-on[only rebuild packages that depend on specified packages (default\: None)]:depends_on:"
|
"*--depends-on[only rebuild packages that depend on specified packages (default\: None)]:depends_on:"
|
||||||
@@ -548,33 +427,21 @@ _shtab_ahriman_repo_rebuild_options=(
|
|||||||
{-u,--username}"[build as user (default\: None)]:username:"
|
{-u,--username}"[build as user (default\: None)]:username:"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_repo_rebuild_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_repo_remove_unknown_options=(
|
_shtab_ahriman_repo_remove_unknown_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
"--dry-run[just perform check for packages without removal (default\: False)]"
|
"--dry-run[just perform check for packages without removal (default\: False)]"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_repo_remove_unknown_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_repo_report_options=(
|
_shtab_ahriman_repo_report_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_repo_report_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_repo_restore_options=(
|
_shtab_ahriman_repo_restore_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{-o,--output}"[root path of the extracted files (default\: \/)]:output:"
|
{-o,--output}"[root path of the extracted files (default\: \/)]:output:"
|
||||||
":path of the input archive:"
|
":path of the input archive:"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_repo_restore_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_repo_setup_options=(
|
_shtab_ahriman_repo_setup_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
"--build-as-user[force makepkg user to the specific one (default\: None)]:build_as_user:"
|
"--build-as-user[force makepkg user to the specific one (default\: None)]:build_as_user:"
|
||||||
@@ -583,7 +450,7 @@ _shtab_ahriman_repo_setup_options=(
|
|||||||
{--makeflags-jobs,--no-makeflags-jobs}"[append MAKEFLAGS variable with parallelism set to number of cores (default\: True)]:makeflags_jobs:"
|
{--makeflags-jobs,--no-makeflags-jobs}"[append MAKEFLAGS variable with parallelism set to number of cores (default\: True)]:makeflags_jobs:"
|
||||||
"--mirror[use the specified explicitly mirror instead of including mirrorlist (default\: None)]:mirror:"
|
"--mirror[use the specified explicitly mirror instead of including mirrorlist (default\: None)]:mirror:"
|
||||||
{--multilib,--no-multilib}"[add or do not multilib repository (default\: True)]:multilib:"
|
{--multilib,--no-multilib}"[add or do not multilib repository (default\: True)]:multilib:"
|
||||||
"--packager[packager name and email]:packager:"
|
"--packager[packager name and email (default\: None)]:packager:"
|
||||||
"--server[server to be used for devtools. If none set, local files will be used (default\: None)]:server:"
|
"--server[server to be used for devtools. If none set, local files will be used (default\: None)]:server:"
|
||||||
"--sign-key[sign key id (default\: None)]:sign_key:"
|
"--sign-key[sign key id (default\: None)]:sign_key:"
|
||||||
"*--sign-target[sign options (default\: None)]:sign_target:(disabled packages repository)"
|
"*--sign-target[sign options (default\: None)]:sign_target:(disabled packages repository)"
|
||||||
@@ -591,17 +458,11 @@ _shtab_ahriman_repo_setup_options=(
|
|||||||
"--web-unix-socket[path to unix socket used for interprocess communications (default\: None)]:web_unix_socket:"
|
"--web-unix-socket[path to unix socket used for interprocess communications (default\: None)]:web_unix_socket:"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_repo_setup_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_repo_sign_options=(
|
_shtab_ahriman_repo_sign_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
"(*)::sign only specified packages (default\: None):"
|
"(*)::sign only specified packages (default\: None):"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_repo_sign_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_repo_statistics_options=(
|
_shtab_ahriman_repo_statistics_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
"--chart[create updates chart and save it to the specified path (default\: None)]:chart:"
|
"--chart[create updates chart and save it to the specified path (default\: None)]:chart:"
|
||||||
@@ -613,40 +474,25 @@ _shtab_ahriman_repo_statistics_options=(
|
|||||||
":fetch only events for the specified package (default\: None):"
|
":fetch only events for the specified package (default\: None):"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_repo_statistics_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_repo_status_update_options=(
|
_shtab_ahriman_repo_status_update_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{-s,--status}"[new status (default\: success)]:status:(unknown pending building failed success)"
|
{-s,--status}"[new status (default\: success)]:status:(unknown pending building failed success)"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_repo_status_update_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_repo_sync_options=(
|
_shtab_ahriman_repo_sync_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_repo_sync_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_repo_tree_options=(
|
_shtab_ahriman_repo_tree_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{-p,--partitions}"[also divide packages by independent partitions (default\: 1)]:partitions:"
|
{-p,--partitions}"[also divide packages by independent partitions (default\: 1)]:partitions:"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_repo_tree_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_repo_triggers_options=(
|
_shtab_ahriman_repo_triggers_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
"(*)::instead of running all triggers as set by configuration, just process specified ones in order of mention (default\: None):"
|
"(*)::instead of running all triggers as set by configuration, just process specified ones in order of mention (default\: None):"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_repo_triggers_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_repo_update_options=(
|
_shtab_ahriman_repo_update_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{--aur,--no-aur}"[enable or disable checking for AUR updates (default\: True)]:aur:"
|
{--aur,--no-aur}"[enable or disable checking for AUR updates (default\: True)]:aur:"
|
||||||
@@ -664,24 +510,15 @@ _shtab_ahriman_repo_update_options=(
|
|||||||
"(*)::filter check by package base (default\: None):"
|
"(*)::filter check by package base (default\: None):"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_repo_update_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_report_options=(
|
_shtab_ahriman_report_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_report_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_run_options=(
|
_shtab_ahriman_run_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
"(*):command to be run (quoted) without \`\`ahriman\`\`:"
|
"(*):command to be run (quoted) without \`\`ahriman\`\`:"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_run_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_search_options=(
|
_shtab_ahriman_search_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{-e,--exit-code}"[return non-zero exit status if result is empty (default\: False)]"
|
{-e,--exit-code}"[return non-zero exit status if result is empty (default\: False)]"
|
||||||
@@ -690,9 +527,6 @@ _shtab_ahriman_search_options=(
|
|||||||
"(*):search terms, can be specified multiple times, the result will match all terms:"
|
"(*):search terms, can be specified multiple times, the result will match all terms:"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_search_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_service_clean_options=(
|
_shtab_ahriman_service_clean_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{--cache,--no-cache}"[clear directory with package caches (default\: False)]:cache:"
|
{--cache,--no-cache}"[clear directory with package caches (default\: False)]:cache:"
|
||||||
@@ -702,9 +536,6 @@ _shtab_ahriman_service_clean_options=(
|
|||||||
{--pacman,--no-pacman}"[clear directory with pacman local database cache (default\: False)]:pacman:"
|
{--pacman,--no-pacman}"[clear directory with pacman local database cache (default\: False)]:pacman:"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_service_clean_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_service_config_options=(
|
_shtab_ahriman_service_config_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{--info,--no-info}"[show additional information, e.g. configuration files (default\: True)]:info:"
|
{--info,--no-info}"[show additional information, e.g. configuration files (default\: True)]:info:"
|
||||||
@@ -713,42 +544,27 @@ _shtab_ahriman_service_config_options=(
|
|||||||
":filter settings by key (default\: None):"
|
":filter settings by key (default\: None):"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_service_config_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_service_config_validate_options=(
|
_shtab_ahriman_service_config_validate_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{-e,--exit-code}"[return non-zero exit status if configuration is invalid (default\: False)]"
|
{-e,--exit-code}"[return non-zero exit status if configuration is invalid (default\: False)]"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_service_config_validate_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_service_key_import_options=(
|
_shtab_ahriman_service_key_import_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
"--key-server[key server for key import (default\: keyserver.ubuntu.com)]:key_server:"
|
"--key-server[key server for key import (default\: keyserver.ubuntu.com)]:key_server:"
|
||||||
":PGP key to import from public server:"
|
":PGP key to import from public server:"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_service_key_import_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_service_repositories_options=(
|
_shtab_ahriman_service_repositories_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{--id-only,--no-id-only}"[show machine readable identifier instead (default\: False)]:id_only:"
|
{--id-only,--no-id-only}"[show machine readable identifier instead (default\: False)]:id_only:"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_service_repositories_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_service_run_options=(
|
_shtab_ahriman_service_run_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
"(*):command to be run (quoted) without \`\`ahriman\`\`:"
|
"(*):command to be run (quoted) without \`\`ahriman\`\`:"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_service_run_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_service_setup_options=(
|
_shtab_ahriman_service_setup_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
"--build-as-user[force makepkg user to the specific one (default\: None)]:build_as_user:"
|
"--build-as-user[force makepkg user to the specific one (default\: None)]:build_as_user:"
|
||||||
@@ -757,7 +573,7 @@ _shtab_ahriman_service_setup_options=(
|
|||||||
{--makeflags-jobs,--no-makeflags-jobs}"[append MAKEFLAGS variable with parallelism set to number of cores (default\: True)]:makeflags_jobs:"
|
{--makeflags-jobs,--no-makeflags-jobs}"[append MAKEFLAGS variable with parallelism set to number of cores (default\: True)]:makeflags_jobs:"
|
||||||
"--mirror[use the specified explicitly mirror instead of including mirrorlist (default\: None)]:mirror:"
|
"--mirror[use the specified explicitly mirror instead of including mirrorlist (default\: None)]:mirror:"
|
||||||
{--multilib,--no-multilib}"[add or do not multilib repository (default\: True)]:multilib:"
|
{--multilib,--no-multilib}"[add or do not multilib repository (default\: True)]:multilib:"
|
||||||
"--packager[packager name and email]:packager:"
|
"--packager[packager name and email (default\: None)]:packager:"
|
||||||
"--server[server to be used for devtools. If none set, local files will be used (default\: None)]:server:"
|
"--server[server to be used for devtools. If none set, local files will be used (default\: None)]:server:"
|
||||||
"--sign-key[sign key id (default\: None)]:sign_key:"
|
"--sign-key[sign key id (default\: None)]:sign_key:"
|
||||||
"*--sign-target[sign options (default\: None)]:sign_target:(disabled packages repository)"
|
"*--sign-target[sign options (default\: None)]:sign_target:(disabled packages repository)"
|
||||||
@@ -765,25 +581,16 @@ _shtab_ahriman_service_setup_options=(
|
|||||||
"--web-unix-socket[path to unix socket used for interprocess communications (default\: None)]:web_unix_socket:"
|
"--web-unix-socket[path to unix socket used for interprocess communications (default\: None)]:web_unix_socket:"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_service_setup_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_service_shell_options=(
|
_shtab_ahriman_service_shell_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{-o,--output}"[output commands and result to the file (default\: None)]:output:"
|
{-o,--output}"[output commands and result to the file (default\: None)]:output:"
|
||||||
":instead of dropping into shell, just execute the specified code (default\: None):"
|
":instead of dropping into shell, just execute the specified code (default\: None):"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_service_shell_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_service_tree_migrate_options=(
|
_shtab_ahriman_service_tree_migrate_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_service_tree_migrate_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_setup_options=(
|
_shtab_ahriman_setup_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
"--build-as-user[force makepkg user to the specific one (default\: None)]:build_as_user:"
|
"--build-as-user[force makepkg user to the specific one (default\: None)]:build_as_user:"
|
||||||
@@ -792,7 +599,7 @@ _shtab_ahriman_setup_options=(
|
|||||||
{--makeflags-jobs,--no-makeflags-jobs}"[append MAKEFLAGS variable with parallelism set to number of cores (default\: True)]:makeflags_jobs:"
|
{--makeflags-jobs,--no-makeflags-jobs}"[append MAKEFLAGS variable with parallelism set to number of cores (default\: True)]:makeflags_jobs:"
|
||||||
"--mirror[use the specified explicitly mirror instead of including mirrorlist (default\: None)]:mirror:"
|
"--mirror[use the specified explicitly mirror instead of including mirrorlist (default\: None)]:mirror:"
|
||||||
{--multilib,--no-multilib}"[add or do not multilib repository (default\: True)]:multilib:"
|
{--multilib,--no-multilib}"[add or do not multilib repository (default\: True)]:multilib:"
|
||||||
"--packager[packager name and email]:packager:"
|
"--packager[packager name and email (default\: None)]:packager:"
|
||||||
"--server[server to be used for devtools. If none set, local files will be used (default\: None)]:server:"
|
"--server[server to be used for devtools. If none set, local files will be used (default\: None)]:server:"
|
||||||
"--sign-key[sign key id (default\: None)]:sign_key:"
|
"--sign-key[sign key id (default\: None)]:sign_key:"
|
||||||
"*--sign-target[sign options (default\: None)]:sign_target:(disabled packages repository)"
|
"*--sign-target[sign options (default\: None)]:sign_target:(disabled packages repository)"
|
||||||
@@ -800,26 +607,17 @@ _shtab_ahriman_setup_options=(
|
|||||||
"--web-unix-socket[path to unix socket used for interprocess communications (default\: None)]:web_unix_socket:"
|
"--web-unix-socket[path to unix socket used for interprocess communications (default\: None)]:web_unix_socket:"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_setup_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_shell_options=(
|
_shtab_ahriman_shell_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{-o,--output}"[output commands and result to the file (default\: None)]:output:"
|
{-o,--output}"[output commands and result to the file (default\: None)]:output:"
|
||||||
":instead of dropping into shell, just execute the specified code (default\: None):"
|
":instead of dropping into shell, just execute the specified code (default\: None):"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_shell_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_sign_options=(
|
_shtab_ahriman_sign_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
"(*)::sign only specified packages (default\: None):"
|
"(*)::sign only specified packages (default\: None):"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_sign_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_status_options=(
|
_shtab_ahriman_status_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
"--ahriman[get service status itself (default\: False)]"
|
"--ahriman[get service status itself (default\: False)]"
|
||||||
@@ -829,25 +627,16 @@ _shtab_ahriman_status_options=(
|
|||||||
"(*)::filter status by package base (default\: None):"
|
"(*)::filter status by package base (default\: None):"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_status_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_status_update_options=(
|
_shtab_ahriman_status_update_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{-s,--status}"[new package build status (default\: success)]:status:(unknown pending building failed success)"
|
{-s,--status}"[new package build status (default\: success)]:status:(unknown pending building failed success)"
|
||||||
"(*)::set status for specified packages. If no packages supplied, service status will be updated (default\: None):"
|
"(*)::set status for specified packages. If no packages supplied, service status will be updated (default\: None):"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_status_update_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_sync_options=(
|
_shtab_ahriman_sync_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_sync_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_update_options=(
|
_shtab_ahriman_update_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{--aur,--no-aur}"[enable or disable checking for AUR updates (default\: True)]:aur:"
|
{--aur,--no-aur}"[enable or disable checking for AUR updates (default\: True)]:aur:"
|
||||||
@@ -865,9 +654,6 @@ _shtab_ahriman_update_options=(
|
|||||||
"(*)::filter check by package base (default\: None):"
|
"(*)::filter check by package base (default\: None):"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_update_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_user_add_options=(
|
_shtab_ahriman_user_add_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
"--key[optional PGP key used by this user. The private key must be imported (default\: None)]:key:"
|
"--key[optional PGP key used by this user. The private key must be imported (default\: None)]:key:"
|
||||||
@@ -877,9 +663,6 @@ _shtab_ahriman_user_add_options=(
|
|||||||
":username for web service:"
|
":username for web service:"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_user_add_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_user_list_options=(
|
_shtab_ahriman_user_list_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{-e,--exit-code}"[return non-zero exit status if result is empty (default\: False)]"
|
{-e,--exit-code}"[return non-zero exit status if result is empty (default\: False)]"
|
||||||
@@ -887,48 +670,25 @@ _shtab_ahriman_user_list_options=(
|
|||||||
":filter users by username (default\: None):"
|
":filter users by username (default\: None):"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_user_list_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_user_remove_options=(
|
_shtab_ahriman_user_remove_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
":username for web service:"
|
":username for web service:"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_user_remove_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_version_options=(
|
_shtab_ahriman_version_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_version_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_web_options=(
|
_shtab_ahriman_web_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
)
|
)
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_web_defaults_added=0
|
|
||||||
|
|
||||||
_shtab_ahriman_web_reload_options=(
|
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
|
||||||
)
|
|
||||||
|
|
||||||
# guard to ensure default positional specs are added only once per session
|
|
||||||
_shtab_ahriman_web_reload_defaults_added=0
|
|
||||||
|
|
||||||
|
|
||||||
_shtab_ahriman() {
|
_shtab_ahriman() {
|
||||||
local context state line curcontext="$curcontext" one_or_more='(*)' remainder='(-)*' default='*::: :->ahriman'
|
local context state line curcontext="$curcontext" one_or_more='(-)*' remainder='(*)'
|
||||||
|
|
||||||
# Add default positional/remainder specs only if none exist, and only once per session
|
if ((${_shtab_ahriman_options[(I)${(q)one_or_more}*]} + ${_shtab_ahriman_options[(I)${(q)remainder}*]} == 0)); then # noqa: E501
|
||||||
if (( ! _shtab_ahriman_defaults_added )); then
|
_shtab_ahriman_options+=(': :_shtab_ahriman_commands' '*::: :->ahriman')
|
||||||
if (( ${_shtab_ahriman_options[(I)${(q)one_or_more}*]} + ${_shtab_ahriman_options[(I)${(q)remainder}*]} + ${_shtab_ahriman_options[(I)${(q)default}]} == 0 )); then
|
|
||||||
_shtab_ahriman_options+=(': :_shtab_ahriman_commands' '*::: :->ahriman')
|
|
||||||
fi
|
|
||||||
_shtab_ahriman_defaults_added=1
|
|
||||||
fi
|
fi
|
||||||
_arguments -C -s $_shtab_ahriman_options
|
_arguments -C -s $_shtab_ahriman_options
|
||||||
|
|
||||||
@@ -1013,7 +773,6 @@ _shtab_ahriman() {
|
|||||||
user-remove) _arguments -C -s $_shtab_ahriman_user_remove_options ;;
|
user-remove) _arguments -C -s $_shtab_ahriman_user_remove_options ;;
|
||||||
version) _arguments -C -s $_shtab_ahriman_version_options ;;
|
version) _arguments -C -s $_shtab_ahriman_version_options ;;
|
||||||
web) _arguments -C -s $_shtab_ahriman_web_options ;;
|
web) _arguments -C -s $_shtab_ahriman_web_options ;;
|
||||||
web-reload) _arguments -C -s $_shtab_ahriman_web_reload_options ;;
|
|
||||||
esac
|
esac
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ authors = [
|
|||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bcrypt",
|
"bcrypt",
|
||||||
"filelock",
|
|
||||||
"inflection",
|
"inflection",
|
||||||
"pyelftools",
|
"pyelftools",
|
||||||
"requests",
|
"requests",
|
||||||
|
|||||||
@@ -17,4 +17,4 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
__version__ = "2.20.0rc2"
|
__version__ = "2.19.0"
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ from collections.abc import Iterable
|
|||||||
from ahriman.application.application.application_properties import ApplicationProperties
|
from ahriman.application.application.application_properties import ApplicationProperties
|
||||||
from ahriman.application.application.workers import Updater
|
from ahriman.application.application.workers import Updater
|
||||||
from ahriman.core.build_tools.sources import Sources
|
from ahriman.core.build_tools.sources import Sources
|
||||||
from ahriman.core.exceptions import UnknownPackageError
|
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
from ahriman.models.packagers import Packagers
|
from ahriman.models.packagers import Packagers
|
||||||
from ahriman.models.result import Result
|
from ahriman.models.result import Result
|
||||||
@@ -117,7 +116,7 @@ class ApplicationRepository(ApplicationProperties):
|
|||||||
for single in probe.packages:
|
for single in probe.packages:
|
||||||
try:
|
try:
|
||||||
_ = Package.from_aur(single, None)
|
_ = Package.from_aur(single, None)
|
||||||
except UnknownPackageError:
|
except Exception:
|
||||||
packages.append(single)
|
packages.append(single)
|
||||||
return packages
|
return packages
|
||||||
|
|
||||||
|
|||||||
@@ -81,13 +81,11 @@ class Backup(Handler):
|
|||||||
Returns:
|
Returns:
|
||||||
set[Path]: map of the filesystem paths
|
set[Path]: map of the filesystem paths
|
||||||
"""
|
"""
|
||||||
# configuration files
|
paths = set(configuration.include.glob("*.ini"))
|
||||||
root, _ = configuration.check_loaded()
|
|
||||||
paths = set(configuration.includes)
|
|
||||||
paths.add(root)
|
|
||||||
|
|
||||||
# database
|
root, _ = configuration.check_loaded()
|
||||||
paths.add(SQLite.database_path(configuration))
|
paths.add(root) # the configuration itself
|
||||||
|
paths.add(SQLite.database_path(configuration)) # database
|
||||||
|
|
||||||
# local caches
|
# local caches
|
||||||
repository_paths = configuration.repository_paths
|
repository_paths = configuration.repository_paths
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
import argparse
|
import argparse
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from collections.abc import Callable
|
from collections.abc import Callable, Iterable
|
||||||
from multiprocessing import Pool
|
from multiprocessing import Pool
|
||||||
from typing import ClassVar, TypeVar
|
from typing import ClassVar, TypeVar
|
||||||
|
|
||||||
@@ -28,9 +28,9 @@ 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.log_loader import LogLoader
|
from ahriman.core.log.log_loader import LogLoader
|
||||||
from ahriman.core.repository import Explorer
|
|
||||||
from ahriman.core.types import ExplicitBool
|
from ahriman.core.types import ExplicitBool
|
||||||
from ahriman.models.repository_id import RepositoryId
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
from ahriman.models.repository_paths import RepositoryPaths
|
||||||
|
|
||||||
|
|
||||||
# this workaround is for several things
|
# this workaround is for several things
|
||||||
@@ -169,6 +169,11 @@ class Handler:
|
|||||||
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
|
||||||
"""
|
"""
|
||||||
|
configuration = Configuration()
|
||||||
|
configuration.load(args.configuration)
|
||||||
|
# pylint, wtf???
|
||||||
|
root = configuration.getpath("repository", "root") # pylint: disable=assignment-from-no-return
|
||||||
|
|
||||||
# preparse systemd repository-id argument
|
# preparse systemd repository-id argument
|
||||||
# we are using unescaped values, so / is not allowed here, because it is impossible to separate if from dashes
|
# we are using unescaped values, so / is not allowed here, because it is impossible to separate if from dashes
|
||||||
if args.repository_id is not None:
|
if args.repository_id is not None:
|
||||||
@@ -179,10 +184,27 @@ class Handler:
|
|||||||
if repository_parts:
|
if repository_parts:
|
||||||
args.repository = "-".join(repository_parts) # replace slash with dash
|
args.repository = "-".join(repository_parts) # replace slash with dash
|
||||||
|
|
||||||
configuration = Configuration()
|
# extract repository names first
|
||||||
configuration.load(args.configuration)
|
if (from_args := args.repository) is not None:
|
||||||
repositories = Explorer.repositories_extract(configuration, args.repository, args.architecture)
|
repositories: Iterable[str] = [from_args]
|
||||||
|
elif from_filesystem := RepositoryPaths.known_repositories(root):
|
||||||
|
repositories = from_filesystem
|
||||||
|
else: # try to read configuration now
|
||||||
|
repositories = [configuration.get("repository", "name")]
|
||||||
|
|
||||||
if not repositories:
|
# extract architecture names
|
||||||
|
if (architecture := args.architecture) is not None:
|
||||||
|
parsed = set(
|
||||||
|
RepositoryId(architecture, repository)
|
||||||
|
for repository in repositories
|
||||||
|
)
|
||||||
|
else: # try to read from file system
|
||||||
|
parsed = set(
|
||||||
|
RepositoryId(architecture, repository)
|
||||||
|
for repository in repositories
|
||||||
|
for architecture in RepositoryPaths.known_architectures(root, repository)
|
||||||
|
)
|
||||||
|
|
||||||
|
if not parsed:
|
||||||
raise MissingArchitectureError(args.command)
|
raise MissingArchitectureError(args.command)
|
||||||
return sorted(repositories)
|
return sorted(parsed)
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ class Restore(Handler):
|
|||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
"""
|
"""
|
||||||
with tarfile.open(args.path) as archive:
|
with tarfile.open(args.path) as archive:
|
||||||
archive.extractall(path=args.output, filter="data")
|
archive.extractall(path=args.output) # nosec
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _set_repo_restore_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
def _set_repo_restore_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ class TreeMigrate(Handler):
|
|||||||
target_tree.tree_create()
|
target_tree.tree_create()
|
||||||
# perform migration
|
# perform migration
|
||||||
TreeMigrate.tree_move(current_tree, target_tree)
|
TreeMigrate.tree_move(current_tree, target_tree)
|
||||||
TreeMigrate.symlinks_fix(target_tree)
|
TreeMigrate.fix_symlinks(target_tree)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _set_service_tree_migrate_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
def _set_service_tree_migrate_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
@@ -69,7 +69,7 @@ class TreeMigrate(Handler):
|
|||||||
return parser
|
return parser
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def symlinks_fix(paths: RepositoryPaths) -> None:
|
def fix_symlinks(paths: RepositoryPaths) -> None:
|
||||||
"""
|
"""
|
||||||
fix package archive symlinks
|
fix package archive symlinks
|
||||||
|
|
||||||
|
|||||||
@@ -59,15 +59,22 @@ class Repo(LazyLogging):
|
|||||||
"""
|
"""
|
||||||
return self.root / f"{self.name}.db.tar.gz"
|
return self.root / f"{self.name}.db.tar.gz"
|
||||||
|
|
||||||
def add(self, path: Path) -> None:
|
def add(self, path: Path, *, remove: bool = True) -> None:
|
||||||
"""
|
"""
|
||||||
add new package to repository
|
add new package to repository
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
path(Path): path to archive to add
|
path(Path): path to archive to add
|
||||||
|
remove(bool, optional): whether to remove old packages or not (Default value = True)
|
||||||
"""
|
"""
|
||||||
|
command = ["repo-add", *self.sign_args]
|
||||||
|
if remove:
|
||||||
|
command.extend(["--remove"])
|
||||||
|
command.extend([str(self.repo_path), str(path)])
|
||||||
|
|
||||||
|
# add to repository
|
||||||
check_output(
|
check_output(
|
||||||
"repo-add", *self.sign_args, "--remove", str(self.repo_path), str(path),
|
*command,
|
||||||
exception=BuildError.from_process(path.name),
|
exception=BuildError.from_process(path.name),
|
||||||
cwd=self.root,
|
cwd=self.root,
|
||||||
logger=self.logger,
|
logger=self.logger,
|
||||||
@@ -90,7 +97,7 @@ class Repo(LazyLogging):
|
|||||||
filename(Path): package filename to remove
|
filename(Path): package filename to remove
|
||||||
"""
|
"""
|
||||||
# remove package and signature (if any) from filesystem
|
# remove package and signature (if any) from filesystem
|
||||||
for full_path in self.root.glob(f"{filename.name}*"):
|
for full_path in self.root.glob(f"**/{filename.name}*"):
|
||||||
full_path.unlink()
|
full_path.unlink()
|
||||||
|
|
||||||
# remove package from registry
|
# remove package from registry
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ from pathlib import Path
|
|||||||
|
|
||||||
from ahriman.core.alpm.repo import Repo
|
from ahriman.core.alpm.repo import Repo
|
||||||
from ahriman.core.log import LazyLogging
|
from ahriman.core.log import LazyLogging
|
||||||
from ahriman.core.utils import package_like, symlink_relative, utcnow, walk
|
from ahriman.core.utils import symlink_relative, utcnow, walk
|
||||||
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.repository_paths import RepositoryPaths
|
from ahriman.models.repository_paths import RepositoryPaths
|
||||||
@@ -50,8 +50,7 @@ class ArchiveTree(LazyLogging):
|
|||||||
self.repository_id = repository_path.repository_id
|
self.repository_id = repository_path.repository_id
|
||||||
self.sign_args = sign_args
|
self.sign_args = sign_args
|
||||||
|
|
||||||
@staticmethod
|
def _package_symlinks_create(self, package_description: PackageDescription, root: Path, archive: Path) -> bool:
|
||||||
def _package_symlinks_create(package_description: PackageDescription, root: Path, archive: Path) -> bool:
|
|
||||||
"""
|
"""
|
||||||
process symlinks creation for single package
|
process symlinks creation for single package
|
||||||
|
|
||||||
@@ -98,9 +97,8 @@ class ArchiveTree(LazyLogging):
|
|||||||
parents = [repository] + list(repository.parents[:-1])
|
parents = [repository] + list(repository.parents[:-1])
|
||||||
for parent in parents:
|
for parent in parents:
|
||||||
path = root / parent
|
path = root / parent
|
||||||
if list(path.iterdir()):
|
if not list(path.iterdir()):
|
||||||
continue # directory is not empty
|
path.rmdir()
|
||||||
path.rmdir()
|
|
||||||
|
|
||||||
def repository_for(self, date: datetime.date | None = None) -> Path:
|
def repository_for(self, date: datetime.date | None = None) -> Path:
|
||||||
"""
|
"""
|
||||||
@@ -158,8 +156,6 @@ class ArchiveTree(LazyLogging):
|
|||||||
if self.repository_id.name != name or self.repository_id.architecture != architecture:
|
if self.repository_id.name != name or self.repository_id.architecture != architecture:
|
||||||
continue # we only process same name repositories
|
continue # we only process same name repositories
|
||||||
|
|
||||||
if not package_like(path):
|
|
||||||
continue
|
|
||||||
if not path.is_symlink():
|
if not path.is_symlink():
|
||||||
continue # find symlinks only
|
continue # find symlinks only
|
||||||
if path.exists():
|
if path.exists():
|
||||||
|
|||||||
@@ -22,11 +22,6 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
aiohttp_security = None # type: ignore[assignment]
|
aiohttp_security = None # type: ignore[assignment]
|
||||||
|
|
||||||
try:
|
|
||||||
import aiohttp_session
|
|
||||||
except ImportError:
|
|
||||||
aiohttp_session = None # type: ignore[assignment]
|
|
||||||
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
@@ -55,7 +50,7 @@ async def check_authorized(*args: Any, **kwargs: Any) -> Any:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
*args(Any): argument list as provided by check_authorized function
|
*args(Any): argument list as provided by check_authorized function
|
||||||
**kwargs(Any): named argument list as provided by check_authorized function
|
**kwargs(Any): named argument list as provided by authorized_userid function
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Any: ``None`` in case if no aiohttp_security module found and function call otherwise
|
Any: ``None`` in case if no aiohttp_security module found and function call otherwise
|
||||||
@@ -71,7 +66,7 @@ async def forget(*args: Any, **kwargs: Any) -> Any:
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
*args(Any): argument list as provided by forget function
|
*args(Any): argument list as provided by forget function
|
||||||
**kwargs(Any): named argument list as provided by forget function
|
**kwargs(Any): named argument list as provided by authorized_userid function
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Any: ``None`` in case if no aiohttp_security module found and function call otherwise
|
Any: ``None`` in case if no aiohttp_security module found and function call otherwise
|
||||||
@@ -81,29 +76,13 @@ async def forget(*args: Any, **kwargs: Any) -> Any:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
async def get_session(*args: Any, **kwargs: Any) -> Any:
|
|
||||||
"""
|
|
||||||
handle aiohttp session methods
|
|
||||||
|
|
||||||
Args:
|
|
||||||
*args(Any): argument list as provided by get_session function
|
|
||||||
**kwargs(Any): named argument list as provided by get_session function
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Any: empty dictionary in case if no aiohttp_session module found and function call otherwise
|
|
||||||
"""
|
|
||||||
if aiohttp_session is not None:
|
|
||||||
return await aiohttp_session.get_session(*args, **kwargs)
|
|
||||||
return {}
|
|
||||||
|
|
||||||
|
|
||||||
async def remember(*args: Any, **kwargs: Any) -> Any:
|
async def remember(*args: Any, **kwargs: Any) -> Any:
|
||||||
"""
|
"""
|
||||||
handle disabled auth
|
handle disabled auth
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
*args(Any): argument list as provided by remember function
|
*args(Any): argument list as provided by remember function
|
||||||
**kwargs(Any): named argument list as provided by remember function
|
**kwargs(Any): named argument list as provided by authorized_userid function
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Any: ``None`` in case if no aiohttp_security module found and function call otherwise
|
Any: ``None`` in case if no aiohttp_security module found and function call otherwise
|
||||||
|
|||||||
@@ -19,8 +19,6 @@
|
|||||||
#
|
#
|
||||||
import aioauth_client
|
import aioauth_client
|
||||||
|
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
from ahriman.core.auth.mapping import Mapping
|
from ahriman.core.auth.mapping import Mapping
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.database import SQLite
|
from ahriman.core.database import SQLite
|
||||||
@@ -55,7 +53,7 @@ class OAuth(Mapping):
|
|||||||
self.client_secret = configuration.get("auth", "client_secret")
|
self.client_secret = configuration.get("auth", "client_secret")
|
||||||
# in order to use OAuth feature the service must be publicity available
|
# in order to use OAuth feature the service must be publicity available
|
||||||
# thus we expect that address is set
|
# thus we expect that address is set
|
||||||
self.redirect_uri = f"{configuration.get("web", "address")}/api/v1/login"
|
self.redirect_uri = f"""{configuration.get("web", "address")}/api/v1/login"""
|
||||||
self.provider = self.get_provider(configuration.get("auth", "oauth_provider"))
|
self.provider = self.get_provider(configuration.get("auth", "oauth_provider"))
|
||||||
# it is list, but we will have to convert to string it anyway
|
# it is list, but we will have to convert to string it anyway
|
||||||
self.scopes = configuration.get("auth", "oauth_scopes")
|
self.scopes = configuration.get("auth", "oauth_scopes")
|
||||||
@@ -86,7 +84,7 @@ class OAuth(Mapping):
|
|||||||
Raises:
|
Raises:
|
||||||
OptionError: in case if invalid OAuth provider name supplied
|
OptionError: in case if invalid OAuth provider name supplied
|
||||||
"""
|
"""
|
||||||
provider: type = getattr(aioauth_client, name, type(None))
|
provider: type[aioauth_client.OAuth2Client] = getattr(aioauth_client, name)
|
||||||
try:
|
try:
|
||||||
is_oauth2_client = issubclass(provider, aioauth_client.OAuth2Client)
|
is_oauth2_client = issubclass(provider, aioauth_client.OAuth2Client)
|
||||||
except TypeError: # what if it is random string?
|
except TypeError: # what if it is random string?
|
||||||
@@ -104,35 +102,27 @@ class OAuth(Mapping):
|
|||||||
"""
|
"""
|
||||||
return self.provider(client_id=self.client_id, client_secret=self.client_secret)
|
return self.provider(client_id=self.client_id, client_secret=self.client_secret)
|
||||||
|
|
||||||
def get_oauth_url(self, state: str) -> str:
|
def get_oauth_url(self) -> str:
|
||||||
"""
|
"""
|
||||||
get authorization URI for the specified settings
|
get authorization URI for the specified settings
|
||||||
|
|
||||||
Args:
|
|
||||||
state(str): CSRF token to pass to OAuth2 provider
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
str: authorization URI as a string
|
str: authorization URI as a string
|
||||||
"""
|
"""
|
||||||
client = self.get_client()
|
client = self.get_client()
|
||||||
uri: str = client.get_authorize_url(scope=self.scopes, redirect_uri=self.redirect_uri, state=state)
|
uri: str = client.get_authorize_url(scope=self.scopes, redirect_uri=self.redirect_uri)
|
||||||
return uri
|
return uri
|
||||||
|
|
||||||
async def get_oauth_username(self, code: str, state: str | None, session: dict[str, Any]) -> str | None:
|
async def get_oauth_username(self, code: str) -> str | None:
|
||||||
"""
|
"""
|
||||||
extract OAuth username from remote
|
extract OAuth username from remote
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
code(str): authorization code provided by external service
|
code(str): authorization code provided by external service
|
||||||
state(str | None): CSRF token returned by external service
|
|
||||||
session(dict[str, Any]): current session instance
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
str | None: username as is in OAuth provider
|
str | None: username as is in OAuth provider
|
||||||
"""
|
"""
|
||||||
if state is None or state != session.get("state"):
|
|
||||||
return None
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
client = self.get_client()
|
client = self.get_client()
|
||||||
access_token, _ = await client.get_access_token(code, redirect_uri=self.redirect_uri)
|
access_token, _ = await client.get_access_token(code, redirect_uri=self.redirect_uri)
|
||||||
|
|||||||
@@ -97,26 +97,6 @@ CONFIGURATION_SCHEMA: ConfigurationSchema = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"aur": {
|
|
||||||
"type": "dict",
|
|
||||||
"schema": {
|
|
||||||
"max_retries": {
|
|
||||||
"type": "integer",
|
|
||||||
"coerce": "integer",
|
|
||||||
"min": 0,
|
|
||||||
},
|
|
||||||
"retry_backoff": {
|
|
||||||
"type": "float",
|
|
||||||
"coerce": "float",
|
|
||||||
"min": 0,
|
|
||||||
},
|
|
||||||
"timeout": {
|
|
||||||
"type": "integer",
|
|
||||||
"coerce": "integer",
|
|
||||||
"min": 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"auth": {
|
"auth": {
|
||||||
"type": "dict",
|
"type": "dict",
|
||||||
"schema": {
|
"schema": {
|
||||||
@@ -316,20 +296,10 @@ CONFIGURATION_SCHEMA: ConfigurationSchema = {
|
|||||||
"empty": False,
|
"empty": False,
|
||||||
"is_url": [],
|
"is_url": [],
|
||||||
},
|
},
|
||||||
"max_retries": {
|
|
||||||
"type": "integer",
|
|
||||||
"coerce": "integer",
|
|
||||||
"min": 0,
|
|
||||||
},
|
|
||||||
"password": {
|
"password": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"empty": False,
|
"empty": False,
|
||||||
},
|
},
|
||||||
"retry_backoff": {
|
|
||||||
"type": "float",
|
|
||||||
"coerce": "float",
|
|
||||||
"min": 0,
|
|
||||||
},
|
|
||||||
"suppress_http_log_errors": {
|
"suppress_http_log_errors": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"coerce": "boolean",
|
"coerce": "boolean",
|
||||||
|
|||||||
@@ -76,19 +76,6 @@ class Validator(RootValidator):
|
|||||||
converted: bool = self.configuration._convert_to_boolean(value) # type: ignore[attr-defined]
|
converted: bool = self.configuration._convert_to_boolean(value) # type: ignore[attr-defined]
|
||||||
return converted
|
return converted
|
||||||
|
|
||||||
def _normalize_coerce_float(self, value: str) -> float:
|
|
||||||
"""
|
|
||||||
extract float from string value
|
|
||||||
|
|
||||||
Args:
|
|
||||||
value(str): converting value
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
float: value converted to float according to configuration rules
|
|
||||||
"""
|
|
||||||
del self
|
|
||||||
return float(value)
|
|
||||||
|
|
||||||
def _normalize_coerce_integer(self, value: str) -> int:
|
def _normalize_coerce_integer(self, value: str) -> int:
|
||||||
"""
|
"""
|
||||||
extract integer from string value
|
extract integer from string value
|
||||||
|
|||||||
@@ -17,12 +17,14 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
import argparse
|
||||||
|
|
||||||
from dataclasses import replace
|
from dataclasses import replace
|
||||||
from sqlite3 import Connection
|
from sqlite3 import Connection
|
||||||
|
|
||||||
|
from ahriman.application.handlers.handler import Handler
|
||||||
from ahriman.core.alpm.pacman import Pacman
|
from ahriman.core.alpm.pacman import Pacman
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.repository import Explorer
|
|
||||||
from ahriman.core.sign.gpg import GPG
|
from ahriman.core.sign.gpg import GPG
|
||||||
from ahriman.core.utils import atomic_move, package_like, symlink_relative
|
from ahriman.core.utils import atomic_move, package_like, symlink_relative
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
@@ -43,7 +45,10 @@ def migrate_data(connection: Connection, configuration: Configuration) -> None:
|
|||||||
"""
|
"""
|
||||||
del connection
|
del connection
|
||||||
|
|
||||||
for repository_id in Explorer.repositories_extract(configuration):
|
config_path, _ = configuration.check_loaded()
|
||||||
|
args = argparse.Namespace(configuration=config_path, architecture=None, repository=None, repository_id=None)
|
||||||
|
|
||||||
|
for repository_id in Handler.repositories_extract(args):
|
||||||
paths = replace(configuration.repository_paths, repository_id=repository_id)
|
paths = replace(configuration.repository_paths, repository_id=repository_id)
|
||||||
pacman = Pacman(repository_id, configuration, refresh_database=PacmanSynchronization.Disabled)
|
pacman = Pacman(repository_id, configuration, refresh_database=PacmanSynchronization.Disabled)
|
||||||
|
|
||||||
@@ -74,8 +79,8 @@ def move_packages(repository_paths: RepositoryPaths, pacman: Pacman) -> None:
|
|||||||
artifacts.append(signature)
|
artifacts.append(signature)
|
||||||
|
|
||||||
for source in artifacts:
|
for source in artifacts:
|
||||||
target = repository_paths.ensure_exists(repository_paths.archive_for(package.base)) / source.name
|
|
||||||
# move package to the archive directory
|
# move package to the archive directory
|
||||||
|
target = repository_paths.archive_for(package.base) / source.name
|
||||||
atomic_move(source, target)
|
atomic_move(source, target)
|
||||||
# create symlink to the archive
|
# create symlink to the archive
|
||||||
symlink_relative(source, target)
|
symlink_relative(source, target)
|
||||||
|
|||||||
@@ -141,15 +141,14 @@ class LogsOperations(Operations):
|
|||||||
connection.execute(
|
connection.execute(
|
||||||
"""
|
"""
|
||||||
delete from logs
|
delete from logs
|
||||||
where repository = :repository
|
where (package_base, version, repository, process_id) not in (
|
||||||
and (package_base, version, repository, process_id) not in (
|
select package_base, version, repository, process_id from logs
|
||||||
select package_base, version, repository, process_id from logs
|
where (package_base, version, repository, created) in (
|
||||||
where (package_base, version, repository, created) in (
|
select package_base, version, repository, max(created) from logs
|
||||||
select package_base, version, repository, max(created) from logs
|
where repository = :repository
|
||||||
where repository = :repository
|
group by package_base, version, repository
|
||||||
group by package_base, version, repository
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
)
|
||||||
""",
|
""",
|
||||||
{
|
{
|
||||||
"repository": repository_id.id,
|
"repository": repository_id.id,
|
||||||
|
|||||||
@@ -48,10 +48,6 @@ class RemotePullTrigger(Trigger):
|
|||||||
"gitremote": {
|
"gitremote": {
|
||||||
"type": "dict",
|
"type": "dict",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"allowed": ["gitremote"],
|
|
||||||
},
|
|
||||||
"pull_url": {
|
"pull_url": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"required": True,
|
"required": True,
|
||||||
@@ -64,6 +60,7 @@ class RemotePullTrigger(Trigger):
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
CONFIGURATION_SCHEMA_FALLBACK = "gitremote"
|
||||||
|
|
||||||
def __init__(self, repository_id: RepositoryId, configuration: Configuration) -> None:
|
def __init__(self, repository_id: RepositoryId, configuration: Configuration) -> None:
|
||||||
"""
|
"""
|
||||||
@@ -92,6 +89,7 @@ class RemotePullTrigger(Trigger):
|
|||||||
trigger action which will be called at the start of the application
|
trigger action which will be called at the start of the application
|
||||||
"""
|
"""
|
||||||
for target in self.targets:
|
for target in self.targets:
|
||||||
section, _ = self.configuration.gettype(target, self.repository_id, fallback="gitremote")
|
section, _ = self.configuration.gettype(
|
||||||
|
target, self.repository_id, fallback=self.CONFIGURATION_SCHEMA_FALLBACK)
|
||||||
runner = RemotePull(self.repository_id, self.configuration, section)
|
runner = RemotePull(self.repository_id, self.configuration, section)
|
||||||
runner.run()
|
runner.run()
|
||||||
|
|||||||
@@ -52,10 +52,6 @@ class RemotePushTrigger(Trigger):
|
|||||||
"gitremote": {
|
"gitremote": {
|
||||||
"type": "dict",
|
"type": "dict",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": {
|
|
||||||
"type": "string",
|
|
||||||
"allowed": ["gitremote"],
|
|
||||||
},
|
|
||||||
"commit_email": {
|
"commit_email": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"empty": False,
|
"empty": False,
|
||||||
@@ -76,6 +72,7 @@ class RemotePushTrigger(Trigger):
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
CONFIGURATION_SCHEMA_FALLBACK = "gitremote"
|
||||||
|
|
||||||
def __init__(self, repository_id: RepositoryId, configuration: Configuration) -> None:
|
def __init__(self, repository_id: RepositoryId, configuration: Configuration) -> None:
|
||||||
"""
|
"""
|
||||||
@@ -114,6 +111,7 @@ class RemotePushTrigger(Trigger):
|
|||||||
reporter = ctx.get(Client)
|
reporter = ctx.get(Client)
|
||||||
|
|
||||||
for target in self.targets:
|
for target in self.targets:
|
||||||
section, _ = self.configuration.gettype(target, self.repository_id, fallback="gitremote")
|
section, _ = self.configuration.gettype(
|
||||||
|
target, self.repository_id, fallback=self.CONFIGURATION_SCHEMA_FALLBACK)
|
||||||
runner = RemotePush(reporter, self.configuration, section)
|
runner = RemotePush(reporter, self.configuration, section)
|
||||||
runner.run(result)
|
runner.run(result)
|
||||||
|
|||||||
@@ -20,9 +20,10 @@
|
|||||||
import contextlib
|
import contextlib
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from requests.adapters import BaseAdapter
|
from functools import cached_property
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
|
from ahriman import __version__
|
||||||
from ahriman.core.http.sync_http_client import SyncHttpClient
|
from ahriman.core.http.sync_http_client import SyncHttpClient
|
||||||
|
|
||||||
|
|
||||||
@@ -36,36 +37,32 @@ class SyncAhrimanClient(SyncHttpClient):
|
|||||||
|
|
||||||
address: str
|
address: str
|
||||||
|
|
||||||
def _login_url(self) -> str:
|
@cached_property
|
||||||
|
def session(self) -> requests.Session:
|
||||||
"""
|
"""
|
||||||
get url for the login api
|
get or create session
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
str: full url for web service to log in
|
request.Session: created session object
|
||||||
"""
|
"""
|
||||||
return f"{self.address}/api/v1/login"
|
if urlparse(self.address).scheme == "http+unix":
|
||||||
|
import requests_unixsocket
|
||||||
|
session: requests.Session = requests_unixsocket.Session() # type: ignore[no-untyped-call]
|
||||||
|
session.headers["User-Agent"] = f"ahriman/{__version__}"
|
||||||
|
return session
|
||||||
|
|
||||||
def adapters(self) -> dict[str, BaseAdapter]:
|
session = requests.Session()
|
||||||
|
session.headers["User-Agent"] = f"ahriman/{__version__}"
|
||||||
|
self._login(session)
|
||||||
|
|
||||||
|
return session
|
||||||
|
|
||||||
|
def _login(self, session: requests.Session) -> None:
|
||||||
"""
|
"""
|
||||||
get registered adapters
|
process login to the service
|
||||||
|
|
||||||
Returns:
|
|
||||||
dict[str, BaseAdapter]: map of protocol and adapter used for this protocol
|
|
||||||
"""
|
|
||||||
adapters = SyncHttpClient.adapters(self)
|
|
||||||
|
|
||||||
if (scheme := urlparse(self.address).scheme) == "http+unix":
|
|
||||||
from requests_unixsocket.adapters import UnixAdapter
|
|
||||||
adapters[f"{scheme}://"] = UnixAdapter() # type: ignore[no-untyped-call]
|
|
||||||
|
|
||||||
return adapters
|
|
||||||
|
|
||||||
def on_session_creation(self, session: requests.Session) -> None:
|
|
||||||
"""
|
|
||||||
method which will be called on session creation
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
session(requests.Session): created requests session
|
session(requests.Session): request session to login
|
||||||
"""
|
"""
|
||||||
if self.auth is None:
|
if self.auth is None:
|
||||||
return # no auth configured
|
return # no auth configured
|
||||||
@@ -77,3 +74,12 @@ class SyncAhrimanClient(SyncHttpClient):
|
|||||||
}
|
}
|
||||||
with contextlib.suppress(Exception):
|
with contextlib.suppress(Exception):
|
||||||
self.make_request("POST", self._login_url(), json=payload, session=session)
|
self.make_request("POST", self._login_url(), json=payload, session=session)
|
||||||
|
|
||||||
|
def _login_url(self) -> str:
|
||||||
|
"""
|
||||||
|
get url for the login api
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: full url for web service to log in
|
||||||
|
"""
|
||||||
|
return f"{self.address}/api/v1/login"
|
||||||
|
|||||||
@@ -21,9 +21,7 @@ import requests
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
from functools import cached_property
|
from functools import cached_property
|
||||||
from requests.adapters import BaseAdapter, HTTPAdapter
|
|
||||||
from typing import Any, IO, Literal
|
from typing import Any, IO, Literal
|
||||||
from urllib3.util.retry import Retry
|
|
||||||
|
|
||||||
from ahriman import __version__
|
from ahriman import __version__
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
@@ -40,14 +38,10 @@ class SyncHttpClient(LazyLogging):
|
|||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
auth(tuple[str, str] | None): HTTP basic auth object if set
|
auth(tuple[str, str] | None): HTTP basic auth object if set
|
||||||
retry(Retry): retry policy of the HTTP client. Disabled by default
|
|
||||||
suppress_errors(bool): suppress logging of request errors
|
suppress_errors(bool): suppress logging of request errors
|
||||||
timeout(int | None): HTTP request timeout in seconds
|
timeout(int | None): HTTP request timeout in seconds
|
||||||
"""
|
"""
|
||||||
|
|
||||||
retry: Retry = Retry()
|
|
||||||
timeout: int | None = None
|
|
||||||
|
|
||||||
def __init__(self, configuration: Configuration | None = None, section: str | None = None, *,
|
def __init__(self, configuration: Configuration | None = None, section: str | None = None, *,
|
||||||
suppress_errors: bool = False) -> None:
|
suppress_errors: bool = False) -> None:
|
||||||
"""
|
"""
|
||||||
@@ -56,21 +50,18 @@ class SyncHttpClient(LazyLogging):
|
|||||||
section(str | None, optional): settings section name (Default value = None)
|
section(str | None, 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)
|
||||||
"""
|
"""
|
||||||
configuration = configuration or Configuration() # dummy configuration
|
if configuration is None:
|
||||||
section = section or configuration.default_section
|
configuration = Configuration() # dummy configuration
|
||||||
|
if section is None:
|
||||||
|
section = configuration.default_section
|
||||||
|
|
||||||
username = configuration.get(section, "username", fallback=None)
|
username = configuration.get(section, "username", fallback=None)
|
||||||
password = configuration.get(section, "password", fallback=None)
|
password = configuration.get(section, "password", fallback=None)
|
||||||
self.auth = (username, password) if username and password else None
|
self.auth = (username, password) if username and password else None
|
||||||
|
|
||||||
|
self.timeout: int | None = configuration.getint(section, "timeout", fallback=30)
|
||||||
self.suppress_errors = suppress_errors
|
self.suppress_errors = suppress_errors
|
||||||
|
|
||||||
self.timeout = configuration.getint(section, "timeout", fallback=30)
|
|
||||||
self.retry = SyncHttpClient.retry_policy(
|
|
||||||
max_retries=configuration.getint(section, "max_retries", fallback=0),
|
|
||||||
retry_backoff=configuration.getfloat(section, "retry_backoff", fallback=0.0),
|
|
||||||
)
|
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def session(self) -> requests.Session:
|
def session(self) -> requests.Session:
|
||||||
"""
|
"""
|
||||||
@@ -80,17 +71,11 @@ class SyncHttpClient(LazyLogging):
|
|||||||
request.Session: created session object
|
request.Session: created session object
|
||||||
"""
|
"""
|
||||||
session = requests.Session()
|
session = requests.Session()
|
||||||
|
|
||||||
for protocol, adapter in self.adapters().items():
|
|
||||||
session.mount(protocol, adapter)
|
|
||||||
|
|
||||||
python_version = ".".join(map(str, sys.version_info[:3])) # just major.minor.patch
|
python_version = ".".join(map(str, sys.version_info[:3])) # just major.minor.patch
|
||||||
session.headers["User-Agent"] = f"ahriman/{__version__} " \
|
session.headers["User-Agent"] = f"ahriman/{__version__} " \
|
||||||
f"{requests.utils.default_user_agent()} " \
|
f"{requests.utils.default_user_agent()} " \
|
||||||
f"python/{python_version}"
|
f"python/{python_version}"
|
||||||
|
|
||||||
self.on_session_creation(session)
|
|
||||||
|
|
||||||
return session
|
return session
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -107,39 +92,6 @@ class SyncHttpClient(LazyLogging):
|
|||||||
result: str = exception.response.text if exception.response is not None else ""
|
result: str = exception.response.text if exception.response is not None else ""
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def retry_policy(max_retries: int = 0, retry_backoff: float = 0.0) -> Retry:
|
|
||||||
"""
|
|
||||||
build retry policy for class
|
|
||||||
|
|
||||||
Args:
|
|
||||||
max_retries(int, optional): maximum amount of retries allowed (Default value = 0)
|
|
||||||
retry_backoff(float, optional): retry exponential backoff (Default value = 0.0)
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Retry: built retry policy
|
|
||||||
"""
|
|
||||||
return Retry(
|
|
||||||
total=max_retries,
|
|
||||||
connect=max_retries,
|
|
||||||
read=max_retries,
|
|
||||||
status=max_retries,
|
|
||||||
status_forcelist=[429, 500, 502, 503, 504],
|
|
||||||
backoff_factor=retry_backoff,
|
|
||||||
)
|
|
||||||
|
|
||||||
def adapters(self) -> dict[str, BaseAdapter]:
|
|
||||||
"""
|
|
||||||
get registered adapters
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
dict[str, BaseAdapter]: map of protocol and adapter used for this protocol
|
|
||||||
"""
|
|
||||||
return {
|
|
||||||
"http://": HTTPAdapter(max_retries=self.retry),
|
|
||||||
"https://": HTTPAdapter(max_retries=self.retry),
|
|
||||||
}
|
|
||||||
|
|
||||||
def make_request(self, method: Literal["DELETE", "GET", "HEAD", "POST", "PUT"], url: str, *,
|
def make_request(self, method: Literal["DELETE", "GET", "HEAD", "POST", "PUT"], url: str, *,
|
||||||
headers: dict[str, str] | None = None,
|
headers: dict[str, str] | None = None,
|
||||||
params: list[tuple[str, str]] | None = None,
|
params: list[tuple[str, str]] | None = None,
|
||||||
@@ -187,11 +139,3 @@ class SyncHttpClient(LazyLogging):
|
|||||||
if not suppress_errors:
|
if not suppress_errors:
|
||||||
self.logger.exception("could not perform http request")
|
self.logger.exception("could not perform http request")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def on_session_creation(self, session: requests.Session) -> None:
|
|
||||||
"""
|
|
||||||
method which will be called on session creation
|
|
||||||
|
|
||||||
Args:
|
|
||||||
session(requests.Session): created requests session
|
|
||||||
"""
|
|
||||||
|
|||||||
@@ -74,18 +74,6 @@ class Email(Report, JinjaTemplate):
|
|||||||
self.ssl = SmtpSSLSettings.from_option(configuration.get(section, "ssl", fallback="disabled"))
|
self.ssl = SmtpSSLSettings.from_option(configuration.get(section, "ssl", fallback="disabled"))
|
||||||
self.user = configuration.get(section, "user", fallback=None)
|
self.user = configuration.get(section, "user", fallback=None)
|
||||||
|
|
||||||
@property
|
|
||||||
def _smtp_session(self) -> type[smtplib.SMTP]:
|
|
||||||
"""
|
|
||||||
build SMTP session based on configuration settings
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
type[smtplib.SMTP]: SMTP or SMTP_SSL session depending on whether SSL is enabled or not
|
|
||||||
"""
|
|
||||||
if self.ssl == SmtpSSLSettings.SSL:
|
|
||||||
return smtplib.SMTP_SSL
|
|
||||||
return smtplib.SMTP
|
|
||||||
|
|
||||||
def _send(self, text: str, attachment: dict[str, str]) -> None:
|
def _send(self, text: str, attachment: dict[str, str]) -> None:
|
||||||
"""
|
"""
|
||||||
send email callback
|
send email callback
|
||||||
@@ -105,13 +93,16 @@ class Email(Report, JinjaTemplate):
|
|||||||
attach.add_header("Content-Disposition", "attachment", filename=filename)
|
attach.add_header("Content-Disposition", "attachment", filename=filename)
|
||||||
message.attach(attach)
|
message.attach(attach)
|
||||||
|
|
||||||
with self._smtp_session(self.host, self.port) as session:
|
if self.ssl != SmtpSSLSettings.SSL:
|
||||||
|
session = smtplib.SMTP(self.host, self.port)
|
||||||
if self.ssl == SmtpSSLSettings.STARTTLS:
|
if self.ssl == SmtpSSLSettings.STARTTLS:
|
||||||
session.starttls()
|
session.starttls()
|
||||||
|
else:
|
||||||
if self.user is not None and self.password is not None:
|
session = smtplib.SMTP_SSL(self.host, self.port)
|
||||||
session.login(self.user, self.password)
|
if self.user is not None and self.password is not None:
|
||||||
session.sendmail(self.sender, self.receivers, message.as_string())
|
session.login(self.user, self.password)
|
||||||
|
session.sendmail(self.sender, self.receivers, message.as_string())
|
||||||
|
session.quit()
|
||||||
|
|
||||||
def generate(self, packages: list[Package], result: Result) -> None:
|
def generate(self, packages: list[Package], result: Result) -> None:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -302,16 +302,6 @@ class ReportTrigger(Trigger):
|
|||||||
"empty": False,
|
"empty": False,
|
||||||
"is_url": [],
|
"is_url": [],
|
||||||
},
|
},
|
||||||
"max_retries": {
|
|
||||||
"type": "integer",
|
|
||||||
"coerce": "integer",
|
|
||||||
"min": 0,
|
|
||||||
},
|
|
||||||
"retry_backoff": {
|
|
||||||
"type": "float",
|
|
||||||
"coerce": "float",
|
|
||||||
"min": 0,
|
|
||||||
},
|
|
||||||
"rss_url": {
|
"rss_url": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"empty": False,
|
"empty": False,
|
||||||
|
|||||||
@@ -17,5 +17,4 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
from ahriman.core.repository.explorer import Explorer
|
|
||||||
from ahriman.core.repository.repository import Repository
|
from ahriman.core.repository.repository import Repository
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
#
|
#
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
from collections.abc import Iterable
|
from collections.abc import Iterable, Iterator
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from tempfile import TemporaryDirectory
|
from tempfile import TemporaryDirectory
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ from ahriman.core.build_tools.package_archive import PackageArchive
|
|||||||
from ahriman.core.build_tools.task import Task
|
from ahriman.core.build_tools.task import Task
|
||||||
from ahriman.core.repository.cleaner import Cleaner
|
from ahriman.core.repository.cleaner import Cleaner
|
||||||
from ahriman.core.repository.package_info import PackageInfo
|
from ahriman.core.repository.package_info import PackageInfo
|
||||||
from ahriman.core.utils import atomic_move, filelock, list_flatmap, package_like, safe_filename, symlink_relative
|
from ahriman.core.utils import atomic_move, filelock, package_like, safe_filename, symlink_relative
|
||||||
from ahriman.models.changes import Changes
|
from ahriman.models.changes import Changes
|
||||||
from ahriman.models.event import EventType
|
from ahriman.models.event import EventType
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
@@ -41,34 +41,35 @@ class Executor(PackageInfo, Cleaner):
|
|||||||
trait for common repository update processes
|
trait for common repository update processes
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _archive_lookup(self, package: Package) -> list[Path]:
|
def _archive_lookup(self, package: Package) -> Iterator[Path]:
|
||||||
"""
|
"""
|
||||||
check if there is a rebuilt package already
|
check if there is a rebuilt package already
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
package(Package): package to check
|
package(Package): package to check
|
||||||
|
|
||||||
Returns:
|
Yields:
|
||||||
list[Path]: list of built packages and signatures if available, empty list otherwise
|
Path: list of built packages and signatures if available, empty list otherwise
|
||||||
"""
|
"""
|
||||||
archive = self.paths.archive_for(package.base)
|
archive = self.paths.archive_for(package.base)
|
||||||
if not archive.is_dir():
|
|
||||||
return []
|
|
||||||
|
|
||||||
for path in filter(package_like, archive.iterdir()):
|
# find all packages which have same version
|
||||||
# check if package version is the same
|
same_version = [
|
||||||
built = Package.from_archive(path, self.pacman)
|
built
|
||||||
if built.version != package.version:
|
for path in filter(package_like, archive.iterdir())
|
||||||
continue
|
if (built := Package.from_archive(path, self.pacman)).version == package.version
|
||||||
|
]
|
||||||
|
# no packages of the same version found
|
||||||
|
if not same_version:
|
||||||
|
return
|
||||||
|
|
||||||
packages = built.packages.values()
|
packages = [single for built in same_version for single in built.packages.values()]
|
||||||
# all packages must be either any or same architecture
|
# all packages must be either any or same architecture
|
||||||
if not all(single.architecture in ("any", self.architecture) for single in packages):
|
if not all(single.architecture in ("any", self.architecture) for single in packages):
|
||||||
continue
|
return
|
||||||
|
|
||||||
return list_flatmap(packages, lambda single: archive.glob(f"{single.filename}*"))
|
for single in packages:
|
||||||
|
yield from archive.glob(f"{single.filename}*")
|
||||||
return []
|
|
||||||
|
|
||||||
def _archive_rename(self, description: PackageDescription, package_base: str) -> None:
|
def _archive_rename(self, description: PackageDescription, package_base: str) -> None:
|
||||||
"""
|
"""
|
||||||
@@ -168,7 +169,7 @@ class Executor(PackageInfo, Cleaner):
|
|||||||
files = self.sign.process_sign_package(full_path, packager_key)
|
files = self.sign.process_sign_package(full_path, packager_key)
|
||||||
|
|
||||||
for src in files:
|
for src in files:
|
||||||
dst = self.paths.ensure_exists(self.paths.archive_for(package_base)) / src.name
|
dst = self.paths.archive_for(package_base) / src.name
|
||||||
atomic_move(src, dst) # move package to archive directory
|
atomic_move(src, dst) # move package to archive directory
|
||||||
if not (symlink := self.paths.repository / dst.name).exists():
|
if not (symlink := self.paths.repository / dst.name).exists():
|
||||||
symlink_relative(symlink, dst) # create link to archive
|
symlink_relative(symlink, dst) # create link to archive
|
||||||
|
|||||||
@@ -1,70 +0,0 @@
|
|||||||
#
|
|
||||||
# Copyright (c) 2021-2026 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 collections.abc import Iterable
|
|
||||||
|
|
||||||
from ahriman.core.configuration import Configuration
|
|
||||||
from ahriman.models.repository_id import RepositoryId
|
|
||||||
from ahriman.models.repository_paths import RepositoryPaths
|
|
||||||
|
|
||||||
|
|
||||||
class Explorer:
|
|
||||||
"""
|
|
||||||
helper to read filesystem and find created repositories
|
|
||||||
"""
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def repositories_extract(configuration: Configuration, repository: str | None = None,
|
|
||||||
architecture: str | None = None) -> list[RepositoryId]:
|
|
||||||
"""
|
|
||||||
get known architectures
|
|
||||||
|
|
||||||
Args:
|
|
||||||
configuration(Configuration): configuration instance
|
|
||||||
repository(str | None, optional): predefined repository name if available (Default value = None)
|
|
||||||
architecture(str | None, optional): predefined repository architecture if available (Default value = None)
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[RepositoryId]: list of repository names and architectures for which tree is created
|
|
||||||
"""
|
|
||||||
# pylint, wtf???
|
|
||||||
root = configuration.getpath("repository", "root") # pylint: disable=assignment-from-no-return
|
|
||||||
|
|
||||||
# extract repository names first
|
|
||||||
if repository is not None:
|
|
||||||
repositories: Iterable[str] = [repository]
|
|
||||||
elif from_filesystem := RepositoryPaths.known_repositories(root):
|
|
||||||
repositories = from_filesystem
|
|
||||||
else: # try to read configuration now
|
|
||||||
repositories = [configuration.get("repository", "name")]
|
|
||||||
|
|
||||||
# extract architecture names
|
|
||||||
if architecture is not None:
|
|
||||||
parsed = set(
|
|
||||||
RepositoryId(architecture, repository)
|
|
||||||
for repository in repositories
|
|
||||||
)
|
|
||||||
else: # try to read from file system
|
|
||||||
parsed = set(
|
|
||||||
RepositoryId(architecture, repository)
|
|
||||||
for repository in repositories
|
|
||||||
for architecture in RepositoryPaths.known_architectures(root, repository)
|
|
||||||
)
|
|
||||||
|
|
||||||
return sorted(parsed)
|
|
||||||
@@ -21,7 +21,6 @@ from typing import Self
|
|||||||
|
|
||||||
from ahriman.core import _Context, context
|
from ahriman.core import _Context, context
|
||||||
from ahriman.core.alpm.pacman import Pacman
|
from ahriman.core.alpm.pacman import Pacman
|
||||||
from ahriman.core.alpm.remote import AUR
|
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.database import SQLite
|
from ahriman.core.database import SQLite
|
||||||
from ahriman.core.repository.executor import Executor
|
from ahriman.core.repository.executor import Executor
|
||||||
@@ -74,26 +73,9 @@ class Repository(Executor, UpdateHandler):
|
|||||||
"""
|
"""
|
||||||
instance = cls(repository_id, configuration, database,
|
instance = cls(repository_id, configuration, database,
|
||||||
report=report, refresh_pacman_database=refresh_pacman_database)
|
report=report, refresh_pacman_database=refresh_pacman_database)
|
||||||
|
|
||||||
instance._set_globals(configuration)
|
|
||||||
instance._set_context()
|
instance._set_context()
|
||||||
|
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _set_globals(configuration: Configuration) -> None:
|
|
||||||
"""
|
|
||||||
set global settings based on configuration via class attributes
|
|
||||||
|
|
||||||
Args:
|
|
||||||
configuration(Configuration): configuration instance
|
|
||||||
"""
|
|
||||||
AUR.timeout = configuration.getint("aur", "timeout", fallback=30)
|
|
||||||
AUR.retry = AUR.retry_policy(
|
|
||||||
max_retries=configuration.getint("aur", "max_retries", fallback=0),
|
|
||||||
retry_backoff=configuration.getfloat("aur", "retry_backoff", fallback=0.0),
|
|
||||||
)
|
|
||||||
|
|
||||||
def _set_context(self) -> None:
|
def _set_context(self) -> None:
|
||||||
"""
|
"""
|
||||||
create context variables and set their values
|
create context variables and set their values
|
||||||
|
|||||||
@@ -185,9 +185,8 @@ class UpdateHandler(PackageInfo, Cleaner):
|
|||||||
else:
|
else:
|
||||||
self.reporter.set_pending(local.base)
|
self.reporter.set_pending(local.base)
|
||||||
self.event(local.base, EventType.PackageOutdated, "Manual update is requested")
|
self.event(local.base, EventType.PackageOutdated, "Manual update is requested")
|
||||||
|
|
||||||
self.clear_queue()
|
|
||||||
except Exception:
|
except Exception:
|
||||||
self.logger.exception("could not load packages from database")
|
self.logger.exception("could not load packages from database")
|
||||||
|
self.clear_queue()
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ class Trigger(LazyLogging):
|
|||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
CONFIGURATION_SCHEMA(ConfigurationSchema): (class attribute) configuration schema template
|
CONFIGURATION_SCHEMA(ConfigurationSchema): (class attribute) configuration schema template
|
||||||
|
CONFIGURATION_SCHEMA_FALLBACK(str | None): (class attribute) optional fallback option for defining
|
||||||
|
configuration schema type used
|
||||||
REQUIRES_REPOSITORY(bool): (class attribute) either trigger requires loaded repository or not
|
REQUIRES_REPOSITORY(bool): (class attribute) either trigger requires loaded repository or not
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
repository_id(RepositoryId): repository unique identifier
|
repository_id(RepositoryId): repository unique identifier
|
||||||
@@ -57,6 +59,7 @@ class Trigger(LazyLogging):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
CONFIGURATION_SCHEMA: ClassVar[ConfigurationSchema] = {}
|
CONFIGURATION_SCHEMA: ClassVar[ConfigurationSchema] = {}
|
||||||
|
CONFIGURATION_SCHEMA_FALLBACK: ClassVar[str | None] = None
|
||||||
REQUIRES_REPOSITORY: ClassVar[bool] = True
|
REQUIRES_REPOSITORY: ClassVar[bool] = True
|
||||||
|
|
||||||
def __init__(self, repository_id: RepositoryId, configuration: Configuration) -> None:
|
def __init__(self, repository_id: RepositoryId, configuration: Configuration) -> None:
|
||||||
|
|||||||
@@ -54,11 +54,6 @@ class UploadTrigger(Trigger):
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"allowed": ["github"],
|
"allowed": ["github"],
|
||||||
},
|
},
|
||||||
"max_retries": {
|
|
||||||
"type": "integer",
|
|
||||||
"coerce": "integer",
|
|
||||||
"min": 0,
|
|
||||||
},
|
|
||||||
"owner": {
|
"owner": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"required": True,
|
"required": True,
|
||||||
@@ -73,11 +68,6 @@ class UploadTrigger(Trigger):
|
|||||||
"required": True,
|
"required": True,
|
||||||
"empty": False,
|
"empty": False,
|
||||||
},
|
},
|
||||||
"retry_backoff": {
|
|
||||||
"type": "float",
|
|
||||||
"coerce": "float",
|
|
||||||
"min": 0,
|
|
||||||
},
|
|
||||||
"timeout": {
|
"timeout": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"coerce": "integer",
|
"coerce": "integer",
|
||||||
@@ -100,16 +90,6 @@ class UploadTrigger(Trigger):
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"allowed": ["ahriman", "remote-service"],
|
"allowed": ["ahriman", "remote-service"],
|
||||||
},
|
},
|
||||||
"max_retries": {
|
|
||||||
"type": "integer",
|
|
||||||
"coerce": "integer",
|
|
||||||
"min": 0,
|
|
||||||
},
|
|
||||||
"retry_backoff": {
|
|
||||||
"type": "float",
|
|
||||||
"coerce": "float",
|
|
||||||
"min": 0,
|
|
||||||
},
|
|
||||||
"timeout": {
|
"timeout": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"coerce": "integer",
|
"coerce": "integer",
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
# pylint: disable=too-many-lines
|
# pylint: disable=too-many-lines
|
||||||
import contextlib
|
import contextlib
|
||||||
import datetime
|
import datetime
|
||||||
|
import fcntl
|
||||||
import io
|
import io
|
||||||
import itertools
|
import itertools
|
||||||
import logging
|
import logging
|
||||||
@@ -32,7 +33,6 @@ import subprocess
|
|||||||
from collections.abc import Callable, Iterable, Iterator, Mapping
|
from collections.abc import Callable, Iterable, Iterator, Mapping
|
||||||
from dataclasses import asdict
|
from dataclasses import asdict
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from filelock import FileLock
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from pwd import getpwuid
|
from pwd import getpwuid
|
||||||
from typing import Any, IO, TypeVar
|
from typing import Any, IO, TypeVar
|
||||||
@@ -164,11 +164,6 @@ def check_output(*args: str, exception: Exception | Callable[[int, list[str], st
|
|||||||
if key in ("PATH",) # whitelisted variables only
|
if key in ("PATH",) # whitelisted variables only
|
||||||
} | environment
|
} | environment
|
||||||
|
|
||||||
result: dict[str, list[str]] = {
|
|
||||||
"stdout": [],
|
|
||||||
"stderr": [],
|
|
||||||
}
|
|
||||||
|
|
||||||
with subprocess.Popen(args, cwd=cwd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
with subprocess.Popen(args, cwd=cwd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||||
user=user, env=full_environment, text=True, encoding="utf8", errors="backslashreplace",
|
user=user, env=full_environment, text=True, encoding="utf8", errors="backslashreplace",
|
||||||
bufsize=1) as process:
|
bufsize=1) as process:
|
||||||
@@ -177,27 +172,30 @@ def check_output(*args: str, exception: Exception | Callable[[int, list[str], st
|
|||||||
input_channel.write(input_data)
|
input_channel.write(input_data)
|
||||||
input_channel.close()
|
input_channel.close()
|
||||||
|
|
||||||
with selectors.DefaultSelector() as selector:
|
selector = selectors.DefaultSelector()
|
||||||
selector.register(get_io(process, "stdout"), selectors.EVENT_READ, data="stdout")
|
selector.register(get_io(process, "stdout"), selectors.EVENT_READ, data="stdout")
|
||||||
selector.register(get_io(process, "stderr"), selectors.EVENT_READ, data="stderr")
|
selector.register(get_io(process, "stderr"), selectors.EVENT_READ, data="stderr")
|
||||||
|
|
||||||
while selector.get_map(): # while there are unread selectors, keep reading
|
result: dict[str, list[str]] = {
|
||||||
for key_data, output in poll(selector):
|
"stdout": [],
|
||||||
result[key_data].append(output)
|
"stderr": [],
|
||||||
|
}
|
||||||
|
while selector.get_map(): # while there are unread selectors, keep reading
|
||||||
|
for key_data, output in poll(selector):
|
||||||
|
result[key_data].append(output)
|
||||||
|
|
||||||
|
stdout = "\n".join(result["stdout"]).rstrip("\n") # remove newline at the end of any
|
||||||
|
stderr = "\n".join(result["stderr"]).rstrip("\n")
|
||||||
|
|
||||||
status_code = process.wait()
|
status_code = process.wait()
|
||||||
|
if status_code != 0:
|
||||||
|
if isinstance(exception, Exception):
|
||||||
|
raise exception
|
||||||
|
if callable(exception):
|
||||||
|
raise exception(status_code, list(args), stdout, stderr)
|
||||||
|
raise CalledProcessError(status_code, list(args), stderr)
|
||||||
|
|
||||||
stdout = "\n".join(result["stdout"]).rstrip("\n") # remove newline at the end of any
|
return stdout
|
||||||
stderr = "\n".join(result["stderr"]).rstrip("\n")
|
|
||||||
|
|
||||||
if status_code != 0:
|
|
||||||
if isinstance(exception, Exception):
|
|
||||||
raise exception
|
|
||||||
if callable(exception):
|
|
||||||
raise exception(status_code, list(args), stdout, stderr)
|
|
||||||
raise CalledProcessError(status_code, list(args), stderr)
|
|
||||||
|
|
||||||
return stdout
|
|
||||||
|
|
||||||
|
|
||||||
def check_user(root: Path, *, unsafe: bool) -> None:
|
def check_user(root: Path, *, unsafe: bool) -> None:
|
||||||
@@ -267,21 +265,25 @@ def extract_user() -> str | None:
|
|||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
def filelock(path: Path) -> Iterator[FileLock]:
|
def filelock(path: Path) -> Iterator[None]:
|
||||||
"""
|
"""
|
||||||
wrapper around :class:`filelock.FileLock`, which also removes locks afterward
|
lock on file passed as argument
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
path(Path): path to lock on. The lock file will be created as ``.{path.name}.lock``
|
path(Path): path object on which lock must be performed
|
||||||
|
|
||||||
Yields:
|
|
||||||
FileLock: acquired file lock instance
|
|
||||||
"""
|
"""
|
||||||
lock_path = path.with_name(f".{path.name}.lock")
|
lock_path = path.with_name(f".{path.name}")
|
||||||
try:
|
try:
|
||||||
with FileLock(lock_path) as lock:
|
with lock_path.open("ab") as lock_file:
|
||||||
yield lock
|
fd = lock_file.fileno()
|
||||||
|
try:
|
||||||
|
fcntl.flock(fd, fcntl.LOCK_EX) # lock file and wait lock is until available
|
||||||
|
yield
|
||||||
|
finally:
|
||||||
|
fcntl.flock(fd, fcntl.LOCK_UN) # unlock file first
|
||||||
finally:
|
finally:
|
||||||
|
# remove lock file at the end
|
||||||
|
# there might be a race condition here, but we don't care about this case
|
||||||
lock_path.unlink(missing_ok=True)
|
lock_path.unlink(missing_ok=True)
|
||||||
|
|
||||||
|
|
||||||
@@ -325,16 +327,16 @@ def full_version(epoch: str | int | None, pkgver: str, pkgrel: str) -> str:
|
|||||||
return f"{prefix}{pkgver}-{pkgrel}"
|
return f"{prefix}{pkgver}-{pkgrel}"
|
||||||
|
|
||||||
|
|
||||||
def list_flatmap(source: Iterable[T], extractor: Callable[[T], Iterable[R]]) -> list[R]:
|
def list_flatmap(source: Iterable[T], extractor: Callable[[T], list[R]]) -> list[R]:
|
||||||
"""
|
"""
|
||||||
extract elements from list of lists, flatten them and apply ``extractor``
|
extract elements from list of lists, flatten them and apply ``extractor``
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
source(Iterable[T]): source list
|
source(Iterable[T]): source list
|
||||||
extractor(Callable[[T], Iterable[R]]): property extractor
|
extractor(Callable[[T], list[R]): property extractor
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
list[R]: combined list of unique entries in properties list
|
list[T]: combined list of unique entries in properties list
|
||||||
"""
|
"""
|
||||||
def generator() -> Iterator[R]:
|
def generator() -> Iterator[R]:
|
||||||
for inner in source:
|
for inner in source:
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ class Package(LazyLogging):
|
|||||||
bool: ``True`` in case if package base looks like VCS package and ``False`` otherwise
|
bool: ``True`` in case if package base looks like VCS package and ``False`` otherwise
|
||||||
"""
|
"""
|
||||||
return self.base.endswith("-bzr") \
|
return self.base.endswith("-bzr") \
|
||||||
or self.base.endswith("-cvs") \
|
or self.base.endswith("-csv") \
|
||||||
or self.base.endswith("-darcs") \
|
or self.base.endswith("-darcs") \
|
||||||
or self.base.endswith("-git") \
|
or self.base.endswith("-git") \
|
||||||
or self.base.endswith("-hg") \
|
or self.base.endswith("-hg") \
|
||||||
|
|||||||
@@ -228,7 +228,12 @@ class RepositoryPaths(LazyLogging):
|
|||||||
Returns:
|
Returns:
|
||||||
Path: path to archive directory for package base
|
Path: path to archive directory for package base
|
||||||
"""
|
"""
|
||||||
return self.archive / "packages" / package_base[0] / package_base
|
directory = self.archive / "packages" / package_base[0] / package_base
|
||||||
|
if not directory.is_dir(): # create if not exists
|
||||||
|
with self.preserve_owner():
|
||||||
|
directory.mkdir(mode=0o755, parents=True)
|
||||||
|
|
||||||
|
return directory
|
||||||
|
|
||||||
def cache_for(self, package_base: str) -> Path:
|
def cache_for(self, package_base: str) -> Path:
|
||||||
"""
|
"""
|
||||||
@@ -242,27 +247,6 @@ class RepositoryPaths(LazyLogging):
|
|||||||
"""
|
"""
|
||||||
return self.cache / package_base
|
return self.cache / package_base
|
||||||
|
|
||||||
def ensure_exists(self, directory: Path) -> Path:
|
|
||||||
"""
|
|
||||||
get path based on ``directory`` callable provided and ensure it exists
|
|
||||||
|
|
||||||
Args:
|
|
||||||
directory(Path): path to directory to check
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Path: original path based on extractor provided. Directory will always exist
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
This method calls directory accessor and then checks if there is a directory and - otherwise - creates it::
|
|
||||||
|
|
||||||
>>> paths.ensure_exists(paths.archive_for(package_base))
|
|
||||||
"""
|
|
||||||
if not directory.is_dir():
|
|
||||||
with self.preserve_owner():
|
|
||||||
directory.mkdir(mode=0o755, parents=True)
|
|
||||||
|
|
||||||
return directory
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
def preserve_owner(self) -> Iterator[None]:
|
def preserve_owner(self) -> Iterator[None]:
|
||||||
"""
|
"""
|
||||||
@@ -319,12 +303,13 @@ class RepositoryPaths(LazyLogging):
|
|||||||
if self.repository_id.is_empty:
|
if self.repository_id.is_empty:
|
||||||
return # do not even try to create tree in case if no repository id set
|
return # do not even try to create tree in case if no repository id set
|
||||||
|
|
||||||
for directory in (
|
with self.preserve_owner():
|
||||||
self.archive,
|
for directory in (
|
||||||
self.cache,
|
self.archive,
|
||||||
self.chroot,
|
self.cache,
|
||||||
self.packages,
|
self.chroot,
|
||||||
self.pacman,
|
self.packages,
|
||||||
self.repository,
|
self.pacman,
|
||||||
):
|
self.repository,
|
||||||
self.ensure_exists(directory)
|
):
|
||||||
|
directory.mkdir(mode=0o755, parents=True, exist_ok=True)
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ def _security() -> list[dict[str, Any]]:
|
|||||||
return [{
|
return [{
|
||||||
"token": {
|
"token": {
|
||||||
"type": "apiKey", # as per specification we are using api key
|
"type": "apiKey", # as per specification we are using api key
|
||||||
"name": "AHRIMAN",
|
"name": "API_SESSION",
|
||||||
"in": "cookie",
|
"in": "cookie",
|
||||||
}
|
}
|
||||||
}]
|
}]
|
||||||
|
|||||||
@@ -149,17 +149,11 @@ def setup_auth(application: Application, configuration: Configuration, validator
|
|||||||
Application: configured web application
|
Application: configured web application
|
||||||
"""
|
"""
|
||||||
secret_key = _cookie_secret_key(configuration)
|
secret_key = _cookie_secret_key(configuration)
|
||||||
storage = EncryptedCookieStorage(
|
storage = EncryptedCookieStorage(secret_key, cookie_name="API_SESSION", max_age=validator.max_age)
|
||||||
secret_key,
|
|
||||||
cookie_name="AHRIMAN",
|
|
||||||
max_age=validator.max_age,
|
|
||||||
httponly=True,
|
|
||||||
samesite="Strict",
|
|
||||||
)
|
|
||||||
setup_session(application, storage)
|
setup_session(application, storage)
|
||||||
|
|
||||||
authorization_policy = _AuthorizationPolicy(validator)
|
authorization_policy = _AuthorizationPolicy(validator)
|
||||||
identity_policy = aiohttp_security.SessionIdentityPolicy("SESSION")
|
identity_policy = aiohttp_security.SessionIdentityPolicy()
|
||||||
|
|
||||||
aiohttp_security.setup(application, identity_policy, authorization_policy)
|
aiohttp_security.setup(application, identity_policy, authorization_policy)
|
||||||
application.middlewares.append(_auth_handler(validator.allow_read_only))
|
application.middlewares.append(_auth_handler(validator.allow_read_only))
|
||||||
|
|||||||
@@ -25,6 +25,6 @@ class AuthSchema(Schema):
|
|||||||
request cookie authorization schema
|
request cookie authorization schema
|
||||||
"""
|
"""
|
||||||
|
|
||||||
AHRIMAN = fields.String(required=True, metadata={
|
API_SESSION = fields.String(required=True, metadata={
|
||||||
"description": "API session key as returned from authorization",
|
"description": "API session key as returned from authorization",
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -28,6 +28,3 @@ class OAuth2Schema(Schema):
|
|||||||
code = fields.String(metadata={
|
code = fields.String(metadata={
|
||||||
"description": "OAuth2 authorization code. In case if not set, the redirect to provider will be initiated",
|
"description": "OAuth2 authorization code. In case if not set, the redirect to provider will be initiated",
|
||||||
})
|
})
|
||||||
state = fields.String(metadata={
|
|
||||||
"description": "CSRF token returned by OAuth2 provider",
|
|
||||||
})
|
|
||||||
|
|||||||
@@ -18,10 +18,9 @@
|
|||||||
# 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 aiohttp.web import HTTPBadRequest, HTTPFound, HTTPMethodNotAllowed, HTTPUnauthorized
|
from aiohttp.web import HTTPBadRequest, HTTPFound, HTTPMethodNotAllowed, HTTPUnauthorized
|
||||||
from secrets import token_urlsafe
|
|
||||||
from typing import ClassVar
|
from typing import ClassVar
|
||||||
|
|
||||||
from ahriman.core.auth.helpers import get_session, remember
|
from ahriman.core.auth.helpers import remember
|
||||||
from ahriman.models.user_access import UserAccess
|
from ahriman.models.user_access import UserAccess
|
||||||
from ahriman.web.apispec.decorators import apidocs
|
from ahriman.web.apispec.decorators import apidocs
|
||||||
from ahriman.web.schemas import LoginSchema, OAuth2Schema
|
from ahriman.web.schemas import LoginSchema, OAuth2Schema
|
||||||
@@ -69,18 +68,15 @@ class LoginView(BaseView):
|
|||||||
raise HTTPMethodNotAllowed(self.request.method, ["POST"])
|
raise HTTPMethodNotAllowed(self.request.method, ["POST"])
|
||||||
|
|
||||||
oauth_provider = self.validator
|
oauth_provider = self.validator
|
||||||
if not isinstance(oauth_provider, OAuth):
|
if not isinstance(oauth_provider, OAuth): # there is actually property, but mypy does not like it anyway
|
||||||
raise HTTPMethodNotAllowed(self.request.method, ["POST"])
|
raise HTTPMethodNotAllowed(self.request.method, ["POST"])
|
||||||
|
|
||||||
session = await get_session(self.request)
|
|
||||||
|
|
||||||
code = self.request.query.get("code")
|
code = self.request.query.get("code")
|
||||||
if not code:
|
if not code:
|
||||||
state = session["state"] = token_urlsafe()
|
raise HTTPFound(oauth_provider.get_oauth_url())
|
||||||
raise HTTPFound(oauth_provider.get_oauth_url(state))
|
|
||||||
|
|
||||||
response = HTTPFound("/")
|
response = HTTPFound("/")
|
||||||
identity = await oauth_provider.get_oauth_username(code, self.request.query.get("state"), session)
|
identity = await oauth_provider.get_oauth_username(code)
|
||||||
if identity is not None and await self.validator.known_username(identity):
|
if identity is not None and await self.validator.known_username(identity):
|
||||||
await remember(self.request, response, identity)
|
await remember(self.request, response, identity)
|
||||||
raise response
|
raise response
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ from pytest_mock import MockerFixture
|
|||||||
from unittest.mock import call as MockCall
|
from unittest.mock import call as MockCall
|
||||||
|
|
||||||
from ahriman.application.application.application_repository import ApplicationRepository
|
from ahriman.application.application.application_repository import ApplicationRepository
|
||||||
from ahriman.core.exceptions import UnknownPackageError
|
|
||||||
from ahriman.core.tree import Leaf, Tree
|
from ahriman.core.tree import Leaf, Tree
|
||||||
from ahriman.models.changes import Changes
|
from ahriman.models.changes import Changes
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
@@ -136,7 +135,7 @@ def test_unknown_no_aur(application_repository: ApplicationRepository, package_a
|
|||||||
must return empty list in case if there is locally stored PKGBUILD
|
must return empty list in case if there is locally stored PKGBUILD
|
||||||
"""
|
"""
|
||||||
mocker.patch("ahriman.core.repository.repository.Repository.packages", return_value=[package_ahriman])
|
mocker.patch("ahriman.core.repository.repository.Repository.packages", return_value=[package_ahriman])
|
||||||
mocker.patch("ahriman.models.package.Package.from_aur", side_effect=UnknownPackageError(package_ahriman.base))
|
mocker.patch("ahriman.models.package.Package.from_aur", side_effect=Exception)
|
||||||
mocker.patch("ahriman.models.package.Package.from_build", return_value=package_ahriman)
|
mocker.patch("ahriman.models.package.Package.from_build", return_value=package_ahriman)
|
||||||
mocker.patch("pathlib.Path.is_dir", return_value=True)
|
mocker.patch("pathlib.Path.is_dir", return_value=True)
|
||||||
mocker.patch("ahriman.core.build_tools.sources.Sources.has_remotes", return_value=False)
|
mocker.patch("ahriman.core.build_tools.sources.Sources.has_remotes", return_value=False)
|
||||||
@@ -150,7 +149,7 @@ def test_unknown_no_aur_no_local(application_repository: ApplicationRepository,
|
|||||||
must return list of packages missing in aur and in local storage
|
must return list of packages missing in aur and in local storage
|
||||||
"""
|
"""
|
||||||
mocker.patch("ahriman.core.repository.repository.Repository.packages", return_value=[package_ahriman])
|
mocker.patch("ahriman.core.repository.repository.Repository.packages", return_value=[package_ahriman])
|
||||||
mocker.patch("ahriman.models.package.Package.from_aur", side_effect=UnknownPackageError(package_ahriman.base))
|
mocker.patch("ahriman.models.package.Package.from_aur", side_effect=Exception)
|
||||||
mocker.patch("pathlib.Path.is_dir", return_value=False)
|
mocker.patch("pathlib.Path.is_dir", return_value=False)
|
||||||
|
|
||||||
packages = application_repository.unknown()
|
packages = application_repository.unknown()
|
||||||
|
|||||||
@@ -145,11 +145,63 @@ def test_repositories_extract(args: argparse.Namespace, configuration: Configura
|
|||||||
args.configuration = configuration.path
|
args.configuration = configuration.path
|
||||||
args.repository = "repo"
|
args.repository = "repo"
|
||||||
mocker.patch("ahriman.core.configuration.Configuration.load", new=lambda self, _: self.copy_from(configuration))
|
mocker.patch("ahriman.core.configuration.Configuration.load", new=lambda self, _: self.copy_from(configuration))
|
||||||
extract_mock = mocker.patch("ahriman.core.repository.Explorer.repositories_extract",
|
known_architectures_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_architectures")
|
||||||
return_value=[RepositoryId("arch", "repo")])
|
known_repositories_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_repositories")
|
||||||
|
|
||||||
assert Handler.repositories_extract(args) == [RepositoryId("arch", "repo")]
|
assert Handler.repositories_extract(args) == [RepositoryId("arch", "repo")]
|
||||||
extract_mock.assert_called_once_with(pytest.helpers.anyvar(Configuration, True), args.repository, args.architecture)
|
known_architectures_mock.assert_not_called()
|
||||||
|
known_repositories_mock.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
|
def test_repositories_extract_repository(args: argparse.Namespace, configuration: Configuration,
|
||||||
|
mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must generate list of available repositories based on flags and tree
|
||||||
|
"""
|
||||||
|
args.architecture = "arch"
|
||||||
|
args.configuration = configuration.path
|
||||||
|
mocker.patch("ahriman.core.configuration.Configuration.load", new=lambda self, _: self.copy_from(configuration))
|
||||||
|
known_architectures_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_architectures")
|
||||||
|
known_repositories_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_repositories",
|
||||||
|
return_value={"repo"})
|
||||||
|
|
||||||
|
assert Handler.repositories_extract(args) == [RepositoryId("arch", "repo")]
|
||||||
|
known_architectures_mock.assert_not_called()
|
||||||
|
known_repositories_mock.assert_called_once_with(configuration.repository_paths.root)
|
||||||
|
|
||||||
|
|
||||||
|
def test_repositories_extract_repository_legacy(args: argparse.Namespace, configuration: Configuration,
|
||||||
|
mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must generate list of available repositories based on flags and tree (legacy mode)
|
||||||
|
"""
|
||||||
|
args.architecture = "arch"
|
||||||
|
args.configuration = configuration.path
|
||||||
|
mocker.patch("ahriman.core.configuration.Configuration.load", new=lambda self, _: self.copy_from(configuration))
|
||||||
|
known_architectures_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_architectures")
|
||||||
|
known_repositories_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_repositories",
|
||||||
|
return_value=set())
|
||||||
|
|
||||||
|
assert Handler.repositories_extract(args) == [RepositoryId("arch", "aur")]
|
||||||
|
known_architectures_mock.assert_not_called()
|
||||||
|
known_repositories_mock.assert_called_once_with(configuration.repository_paths.root)
|
||||||
|
|
||||||
|
|
||||||
|
def test_repositories_extract_architecture(args: argparse.Namespace, configuration: Configuration,
|
||||||
|
mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must read repository name from config
|
||||||
|
"""
|
||||||
|
args.configuration = configuration.path
|
||||||
|
args.repository = "repo"
|
||||||
|
mocker.patch("ahriman.core.configuration.Configuration.load", new=lambda self, _: self.copy_from(configuration))
|
||||||
|
known_architectures_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_architectures",
|
||||||
|
return_value={"arch"})
|
||||||
|
known_repositories_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_repositories")
|
||||||
|
|
||||||
|
assert Handler.repositories_extract(args) == [RepositoryId("arch", "repo")]
|
||||||
|
known_architectures_mock.assert_called_once_with(configuration.repository_paths.root, "repo")
|
||||||
|
known_repositories_mock.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
def test_repositories_extract_empty(args: argparse.Namespace, configuration: Configuration,
|
def test_repositories_extract_empty(args: argparse.Namespace, configuration: Configuration,
|
||||||
@@ -160,7 +212,8 @@ def test_repositories_extract_empty(args: argparse.Namespace, configuration: Con
|
|||||||
args.command = "config"
|
args.command = "config"
|
||||||
args.configuration = configuration.path
|
args.configuration = configuration.path
|
||||||
mocker.patch("ahriman.core.configuration.Configuration.load", new=lambda self, _: self.copy_from(configuration))
|
mocker.patch("ahriman.core.configuration.Configuration.load", new=lambda self, _: self.copy_from(configuration))
|
||||||
mocker.patch("ahriman.core.repository.Explorer.repositories_extract", return_value=[])
|
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_architectures", return_value=set())
|
||||||
|
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_repositories", return_value=set())
|
||||||
|
|
||||||
with pytest.raises(MissingArchitectureError):
|
with pytest.raises(MissingArchitectureError):
|
||||||
Handler.repositories_extract(args)
|
Handler.repositories_extract(args)
|
||||||
@@ -174,11 +227,12 @@ def test_repositories_extract_systemd(args: argparse.Namespace, configuration: C
|
|||||||
args.configuration = configuration.path
|
args.configuration = configuration.path
|
||||||
args.repository_id = "i686/some/repo/name"
|
args.repository_id = "i686/some/repo/name"
|
||||||
mocker.patch("ahriman.core.configuration.Configuration.load", new=lambda self, _: self.copy_from(configuration))
|
mocker.patch("ahriman.core.configuration.Configuration.load", new=lambda self, _: self.copy_from(configuration))
|
||||||
extract_mock = mocker.patch("ahriman.core.repository.Explorer.repositories_extract",
|
known_architectures_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_architectures")
|
||||||
return_value=[RepositoryId("i686", "some-repo-name")])
|
known_repositories_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_repositories")
|
||||||
|
|
||||||
assert Handler.repositories_extract(args) == [RepositoryId("i686", "some-repo-name")]
|
assert Handler.repositories_extract(args) == [RepositoryId("i686", "some-repo-name")]
|
||||||
extract_mock.assert_called_once_with(pytest.helpers.anyvar(Configuration, True), "some-repo-name", "i686")
|
known_architectures_mock.assert_not_called()
|
||||||
|
known_repositories_mock.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
def test_repositories_extract_systemd_with_dash(args: argparse.Namespace, configuration: Configuration,
|
def test_repositories_extract_systemd_with_dash(args: argparse.Namespace, configuration: Configuration,
|
||||||
@@ -189,11 +243,12 @@ def test_repositories_extract_systemd_with_dash(args: argparse.Namespace, config
|
|||||||
args.configuration = configuration.path
|
args.configuration = configuration.path
|
||||||
args.repository_id = "i686-some-repo-name"
|
args.repository_id = "i686-some-repo-name"
|
||||||
mocker.patch("ahriman.core.configuration.Configuration.load", new=lambda self, _: self.copy_from(configuration))
|
mocker.patch("ahriman.core.configuration.Configuration.load", new=lambda self, _: self.copy_from(configuration))
|
||||||
extract_mock = mocker.patch("ahriman.core.repository.Explorer.repositories_extract",
|
known_architectures_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_architectures")
|
||||||
return_value=[RepositoryId("i686", "some-repo-name")])
|
known_repositories_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_repositories")
|
||||||
|
|
||||||
assert Handler.repositories_extract(args) == [RepositoryId("i686", "some-repo-name")]
|
assert Handler.repositories_extract(args) == [RepositoryId("i686", "some-repo-name")]
|
||||||
extract_mock.assert_called_once_with(pytest.helpers.anyvar(Configuration, True), "some-repo-name", "i686")
|
known_architectures_mock.assert_not_called()
|
||||||
|
known_repositories_mock.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
def test_repositories_extract_systemd_legacy(args: argparse.Namespace, configuration: Configuration,
|
def test_repositories_extract_systemd_legacy(args: argparse.Namespace, configuration: Configuration,
|
||||||
@@ -204,8 +259,10 @@ def test_repositories_extract_systemd_legacy(args: argparse.Namespace, configura
|
|||||||
args.configuration = configuration.path
|
args.configuration = configuration.path
|
||||||
args.repository_id = "i686"
|
args.repository_id = "i686"
|
||||||
mocker.patch("ahriman.core.configuration.Configuration.load", new=lambda self, _: self.copy_from(configuration))
|
mocker.patch("ahriman.core.configuration.Configuration.load", new=lambda self, _: self.copy_from(configuration))
|
||||||
extract_mock = mocker.patch("ahriman.core.repository.Explorer.repositories_extract",
|
known_architectures_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_architectures")
|
||||||
return_value=[RepositoryId("i686", "aur")])
|
known_repositories_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_repositories",
|
||||||
|
return_value=set())
|
||||||
|
|
||||||
assert Handler.repositories_extract(args) == [RepositoryId("i686", "aur")]
|
assert Handler.repositories_extract(args) == [RepositoryId("i686", "aur")]
|
||||||
extract_mock.assert_called_once_with(pytest.helpers.anyvar(Configuration, True), None, "i686")
|
known_architectures_mock.assert_not_called()
|
||||||
|
known_repositories_mock.assert_called_once_with(configuration.repository_paths.root)
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
|
|||||||
|
|
||||||
_, repository_id = configuration.check_loaded()
|
_, repository_id = configuration.check_loaded()
|
||||||
Restore.run(args, repository_id, configuration, report=False)
|
Restore.run(args, repository_id, configuration, report=False)
|
||||||
extract_mock.extractall.assert_called_once_with(path=args.output, filter="data")
|
extract_mock.extractall.assert_called_once_with(path=args.output)
|
||||||
|
|
||||||
|
|
||||||
def test_disallow_multi_architecture_run() -> None:
|
def test_disallow_multi_architecture_run() -> None:
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
|
|||||||
"""
|
"""
|
||||||
tree_create_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
tree_create_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||||
application_mock = mocker.patch("ahriman.application.handlers.tree_migrate.TreeMigrate.tree_move")
|
application_mock = mocker.patch("ahriman.application.handlers.tree_migrate.TreeMigrate.tree_move")
|
||||||
symlinks_mock = mocker.patch("ahriman.application.handlers.tree_migrate.TreeMigrate.symlinks_fix")
|
symlinks_mock = mocker.patch("ahriman.application.handlers.tree_migrate.TreeMigrate.fix_symlinks")
|
||||||
_, repository_id = configuration.check_loaded()
|
_, repository_id = configuration.check_loaded()
|
||||||
old_paths = configuration.repository_paths
|
old_paths = configuration.repository_paths
|
||||||
new_paths = RepositoryPaths(old_paths.root, old_paths.repository_id, _force_current_tree=True)
|
new_paths = RepositoryPaths(old_paths.root, old_paths.repository_id, _force_current_tree=True)
|
||||||
@@ -28,10 +28,11 @@ def test_run(args: argparse.Namespace, configuration: Configuration, mocker: Moc
|
|||||||
symlinks_mock.assert_called_once_with(new_paths)
|
symlinks_mock.assert_called_once_with(new_paths)
|
||||||
|
|
||||||
|
|
||||||
def test_symlinks_fix(repository_paths: RepositoryPaths, package_ahriman: Package, mocker: MockerFixture) -> None:
|
def test_fix_symlinks(repository_paths: RepositoryPaths, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must replace symlinks during migration
|
must replace symlinks during migration
|
||||||
"""
|
"""
|
||||||
|
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.preserve_owner")
|
||||||
mocker.patch("ahriman.application.handlers.tree_migrate.walk", side_effect=[
|
mocker.patch("ahriman.application.handlers.tree_migrate.walk", side_effect=[
|
||||||
[
|
[
|
||||||
repository_paths.archive_for(package_ahriman.base) / "file",
|
repository_paths.archive_for(package_ahriman.base) / "file",
|
||||||
@@ -46,7 +47,7 @@ def test_symlinks_fix(repository_paths: RepositoryPaths, package_ahriman: Packag
|
|||||||
unlink_mock = mocker.patch("pathlib.Path.unlink")
|
unlink_mock = mocker.patch("pathlib.Path.unlink")
|
||||||
symlink_mock = mocker.patch("pathlib.Path.symlink_to")
|
symlink_mock = mocker.patch("pathlib.Path.symlink_to")
|
||||||
|
|
||||||
TreeMigrate.symlinks_fix(repository_paths)
|
TreeMigrate.fix_symlinks(repository_paths)
|
||||||
unlink_mock.assert_called_once_with()
|
unlink_mock.assert_called_once_with()
|
||||||
symlink_mock.assert_called_once_with(
|
symlink_mock.assert_called_once_with(
|
||||||
Path("..") /
|
Path("..") /
|
||||||
|
|||||||
@@ -35,6 +35,17 @@ def test_repo_add(repo: Repo, mocker: MockerFixture) -> None:
|
|||||||
assert "--remove" in check_output_mock.call_args[0]
|
assert "--remove" in check_output_mock.call_args[0]
|
||||||
|
|
||||||
|
|
||||||
|
def test_repo_add_no_remove(repo: Repo, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must call repo-add without remove flag
|
||||||
|
"""
|
||||||
|
check_output_mock = mocker.patch("ahriman.core.alpm.repo.check_output")
|
||||||
|
|
||||||
|
repo.add(Path("path"), remove=False)
|
||||||
|
check_output_mock.assert_called_once() # it will be checked later
|
||||||
|
assert "--remove" not in check_output_mock.call_args[0]
|
||||||
|
|
||||||
|
|
||||||
def test_repo_init(repo: Repo, mocker: MockerFixture) -> None:
|
def test_repo_init(repo: Repo, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must call repo-add with empty package list on repo initializing
|
must call repo-add with empty package list on repo initializing
|
||||||
|
|||||||
@@ -109,7 +109,6 @@ def test_symlinks_fix(archive_tree: ArchiveTree, mocker: MockerFixture) -> None:
|
|||||||
archive_tree.repository_for() / filename
|
archive_tree.repository_for() / filename
|
||||||
for filename in (
|
for filename in (
|
||||||
"symlink-1.0.0-1-x86_64.pkg.tar.zst",
|
"symlink-1.0.0-1-x86_64.pkg.tar.zst",
|
||||||
"symlink-1.0.0-1-x86_64.pkg.tar.zst.sig",
|
|
||||||
"broken_symlink-1.0.0-1-x86_64.pkg.tar.zst",
|
"broken_symlink-1.0.0-1-x86_64.pkg.tar.zst",
|
||||||
"file-1.0.0-1-x86_64.pkg.tar.zst",
|
"file-1.0.0-1-x86_64.pkg.tar.zst",
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -13,13 +13,6 @@ def test_import_aiohttp_security() -> None:
|
|||||||
assert helpers.aiohttp_security
|
assert helpers.aiohttp_security
|
||||||
|
|
||||||
|
|
||||||
def test_import_aiohttp_session() -> None:
|
|
||||||
"""
|
|
||||||
must import aiohttp_session correctly
|
|
||||||
"""
|
|
||||||
assert helpers.aiohttp_session
|
|
||||||
|
|
||||||
|
|
||||||
async def test_authorized_userid_dummy(mocker: MockerFixture) -> None:
|
async def test_authorized_userid_dummy(mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must not call authorized_userid from library if not enabled
|
must not call authorized_userid from library if not enabled
|
||||||
@@ -62,23 +55,6 @@ async def test_forget_dummy(mocker: MockerFixture) -> None:
|
|||||||
await helpers.forget()
|
await helpers.forget()
|
||||||
|
|
||||||
|
|
||||||
async def test_get_session_dummy(mocker: MockerFixture) -> None:
|
|
||||||
"""
|
|
||||||
must return empty dict if no aiohttp_session module found
|
|
||||||
"""
|
|
||||||
mocker.patch.object(helpers, "aiohttp_session", None)
|
|
||||||
assert await helpers.get_session() == {}
|
|
||||||
|
|
||||||
|
|
||||||
async def test_get_session_library(mocker: MockerFixture) -> None:
|
|
||||||
"""
|
|
||||||
must call get_session from library if enabled
|
|
||||||
"""
|
|
||||||
get_session_mock = mocker.patch("aiohttp_session.get_session")
|
|
||||||
await helpers.get_session()
|
|
||||||
get_session_mock.assert_called_once_with()
|
|
||||||
|
|
||||||
|
|
||||||
async def test_forget_library(mocker: MockerFixture) -> None:
|
async def test_forget_library(mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must call forget from library if enabled
|
must call forget from library if enabled
|
||||||
@@ -112,12 +88,3 @@ def test_import_aiohttp_security_missing(mocker: MockerFixture) -> None:
|
|||||||
mocker.patch.dict(sys.modules, {"aiohttp_security": None})
|
mocker.patch.dict(sys.modules, {"aiohttp_security": None})
|
||||||
importlib.reload(helpers)
|
importlib.reload(helpers)
|
||||||
assert helpers.aiohttp_security is None
|
assert helpers.aiohttp_security is None
|
||||||
|
|
||||||
|
|
||||||
def test_import_aiohttp_session_missing(mocker: MockerFixture) -> None:
|
|
||||||
"""
|
|
||||||
must set missing flag if no aiohttp_session module found
|
|
||||||
"""
|
|
||||||
mocker.patch.dict(sys.modules, {"aiohttp_session": None})
|
|
||||||
importlib.reload(helpers)
|
|
||||||
assert helpers.aiohttp_session is None
|
|
||||||
|
|||||||
@@ -57,8 +57,8 @@ def test_get_oauth_url(oauth: OAuth, mocker: MockerFixture) -> None:
|
|||||||
must generate valid OAuth authorization URL
|
must generate valid OAuth authorization URL
|
||||||
"""
|
"""
|
||||||
authorize_url_mock = mocker.patch("aioauth_client.GoogleClient.get_authorize_url")
|
authorize_url_mock = mocker.patch("aioauth_client.GoogleClient.get_authorize_url")
|
||||||
oauth.get_oauth_url(state="state")
|
oauth.get_oauth_url()
|
||||||
authorize_url_mock.assert_called_once_with(scope=oauth.scopes, redirect_uri=oauth.redirect_uri, state="state")
|
authorize_url_mock.assert_called_once_with(scope=oauth.scopes, redirect_uri=oauth.redirect_uri)
|
||||||
|
|
||||||
|
|
||||||
async def test_get_oauth_username(oauth: OAuth, mocker: MockerFixture) -> None:
|
async def test_get_oauth_username(oauth: OAuth, mocker: MockerFixture) -> None:
|
||||||
@@ -69,9 +69,10 @@ async def test_get_oauth_username(oauth: OAuth, mocker: MockerFixture) -> None:
|
|||||||
user_info_mock = mocker.patch("aioauth_client.GoogleClient.user_info",
|
user_info_mock = mocker.patch("aioauth_client.GoogleClient.user_info",
|
||||||
return_value=(aioauth_client.User(email="email"), ""))
|
return_value=(aioauth_client.User(email="email"), ""))
|
||||||
|
|
||||||
assert await oauth.get_oauth_username("code", state="state", session={"state": "state"}) == "email"
|
email = await oauth.get_oauth_username("code")
|
||||||
access_token_mock.assert_called_once_with("code", redirect_uri=oauth.redirect_uri)
|
access_token_mock.assert_called_once_with("code", redirect_uri=oauth.redirect_uri)
|
||||||
user_info_mock.assert_called_once_with()
|
user_info_mock.assert_called_once_with()
|
||||||
|
assert email == "email"
|
||||||
|
|
||||||
|
|
||||||
async def test_get_oauth_username_empty_email(oauth: OAuth, mocker: MockerFixture) -> None:
|
async def test_get_oauth_username_empty_email(oauth: OAuth, mocker: MockerFixture) -> None:
|
||||||
@@ -81,7 +82,8 @@ async def test_get_oauth_username_empty_email(oauth: OAuth, mocker: MockerFixtur
|
|||||||
mocker.patch("aioauth_client.GoogleClient.get_access_token", return_value=("token", ""))
|
mocker.patch("aioauth_client.GoogleClient.get_access_token", return_value=("token", ""))
|
||||||
mocker.patch("aioauth_client.GoogleClient.user_info", return_value=(aioauth_client.User(username="username"), ""))
|
mocker.patch("aioauth_client.GoogleClient.user_info", return_value=(aioauth_client.User(username="username"), ""))
|
||||||
|
|
||||||
assert await oauth.get_oauth_username("code", state="state", session={"state": "state"}) == "username"
|
username = await oauth.get_oauth_username("code")
|
||||||
|
assert username == "username"
|
||||||
|
|
||||||
|
|
||||||
async def test_get_oauth_username_exception_1(oauth: OAuth, mocker: MockerFixture) -> None:
|
async def test_get_oauth_username_exception_1(oauth: OAuth, mocker: MockerFixture) -> None:
|
||||||
@@ -91,7 +93,8 @@ async def test_get_oauth_username_exception_1(oauth: OAuth, mocker: MockerFixtur
|
|||||||
mocker.patch("aioauth_client.GoogleClient.get_access_token", side_effect=Exception)
|
mocker.patch("aioauth_client.GoogleClient.get_access_token", side_effect=Exception)
|
||||||
user_info_mock = mocker.patch("aioauth_client.GoogleClient.user_info")
|
user_info_mock = mocker.patch("aioauth_client.GoogleClient.user_info")
|
||||||
|
|
||||||
assert await oauth.get_oauth_username("code", state="state", session={"state": "state"}) is None
|
email = await oauth.get_oauth_username("code")
|
||||||
|
assert email is None
|
||||||
user_info_mock.assert_not_called()
|
user_info_mock.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
@@ -102,19 +105,5 @@ async def test_get_oauth_username_exception_2(oauth: OAuth, mocker: MockerFixtur
|
|||||||
mocker.patch("aioauth_client.GoogleClient.get_access_token", return_value=("token", ""))
|
mocker.patch("aioauth_client.GoogleClient.get_access_token", return_value=("token", ""))
|
||||||
mocker.patch("aioauth_client.GoogleClient.user_info", side_effect=Exception)
|
mocker.patch("aioauth_client.GoogleClient.user_info", side_effect=Exception)
|
||||||
|
|
||||||
username = await oauth.get_oauth_username("code", state="state", session={"state": "state"})
|
email = await oauth.get_oauth_username("code")
|
||||||
assert username is None
|
assert email is None
|
||||||
|
|
||||||
|
|
||||||
async def test_get_oauth_username_csrf_missing(oauth: OAuth) -> None:
|
|
||||||
"""
|
|
||||||
must return None if CSRF state is missing
|
|
||||||
"""
|
|
||||||
assert await oauth.get_oauth_username("code", state=None, session={"state": "state"}) is None
|
|
||||||
|
|
||||||
|
|
||||||
async def test_get_oauth_username_csrf_mismatch(oauth: OAuth) -> None:
|
|
||||||
"""
|
|
||||||
must return None if CSRF state does not match session
|
|
||||||
"""
|
|
||||||
assert await oauth.get_oauth_username("code", state="wrong", session={"state": "state"}) is None
|
|
||||||
|
|||||||
@@ -33,14 +33,6 @@ def test_normalize_coerce_boolean(validator: Validator, mocker: MockerFixture) -
|
|||||||
convert_mock.assert_called_once_with("1")
|
convert_mock.assert_called_once_with("1")
|
||||||
|
|
||||||
|
|
||||||
def test_normalize_coerce_float(validator: Validator) -> None:
|
|
||||||
"""
|
|
||||||
must convert string value to float by using configuration converters
|
|
||||||
"""
|
|
||||||
assert validator._normalize_coerce_float("1.5") == 1.5
|
|
||||||
assert validator._normalize_coerce_float("0.0") == 0.0
|
|
||||||
|
|
||||||
|
|
||||||
def test_normalize_coerce_integer(validator: Validator) -> None:
|
def test_normalize_coerce_integer(validator: Validator) -> None:
|
||||||
"""
|
"""
|
||||||
must convert string value to integer by using configuration converters
|
must convert string value to integer by using configuration converters
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ def test_migrate_data(connection: Connection, configuration: Configuration, mock
|
|||||||
repository_id,
|
repository_id,
|
||||||
replace(repository_id, architecture="i686"),
|
replace(repository_id, architecture="i686"),
|
||||||
]
|
]
|
||||||
mocker.patch("ahriman.core.repository.Explorer.repositories_extract", return_value=repositories)
|
mocker.patch("ahriman.application.handlers.handler.Handler.repositories_extract", return_value=repositories)
|
||||||
migration_mock = mocker.patch("ahriman.core.database.migrations.m016_archive.move_packages")
|
migration_mock = mocker.patch("ahriman.core.database.migrations.m016_archive.move_packages")
|
||||||
|
|
||||||
migrate_data(connection, configuration)
|
migrate_data(connection, configuration)
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ def test_load(configuration: Configuration, mocker: MockerFixture) -> None:
|
|||||||
init_mock.assert_called_once_with()
|
init_mock.assert_called_once_with()
|
||||||
|
|
||||||
|
|
||||||
def test_init(database: SQLite, mocker: MockerFixture) -> None:
|
def test_init(database: SQLite, configuration: Configuration, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must run migrations on init
|
must run migrations on init
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import pytest
|
import pytest
|
||||||
import requests
|
import requests
|
||||||
|
import requests_unixsocket
|
||||||
|
|
||||||
from pytest_mock import MockerFixture
|
from pytest_mock import MockerFixture
|
||||||
|
|
||||||
@@ -7,32 +8,31 @@ from ahriman.core.http import SyncAhrimanClient
|
|||||||
from ahriman.models.user import User
|
from ahriman.models.user import User
|
||||||
|
|
||||||
|
|
||||||
def test_adapters(ahriman_client: SyncAhrimanClient) -> None:
|
def test_session(ahriman_client: SyncAhrimanClient, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must return native adapters
|
must create normal requests session
|
||||||
"""
|
"""
|
||||||
assert "http+unix://" not in ahriman_client.adapters()
|
login_mock = mocker.patch("ahriman.core.http.SyncAhrimanClient._login")
|
||||||
|
|
||||||
|
assert isinstance(ahriman_client.session, requests.Session)
|
||||||
|
assert not isinstance(ahriman_client.session, requests_unixsocket.Session)
|
||||||
|
login_mock.assert_called_once_with(pytest.helpers.anyvar(int))
|
||||||
|
|
||||||
|
|
||||||
def test_adapters_unix_socket(ahriman_client: SyncAhrimanClient) -> None:
|
def test_session_unix_socket(ahriman_client: SyncAhrimanClient, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must register unix socket adapter
|
must create unix socket session
|
||||||
"""
|
"""
|
||||||
|
login_mock = mocker.patch("ahriman.core.http.SyncAhrimanClient._login")
|
||||||
ahriman_client.address = "http+unix://path"
|
ahriman_client.address = "http+unix://path"
|
||||||
assert "http+unix://" in ahriman_client.adapters()
|
|
||||||
|
assert isinstance(ahriman_client.session, requests_unixsocket.Session)
|
||||||
|
login_mock.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
def test_login_url(ahriman_client: SyncAhrimanClient) -> None:
|
def test_login(ahriman_client: SyncAhrimanClient, user: User, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must generate login url correctly
|
must login user
|
||||||
"""
|
|
||||||
assert ahriman_client._login_url().startswith(ahriman_client.address)
|
|
||||||
assert ahriman_client._login_url().endswith("/api/v1/login")
|
|
||||||
|
|
||||||
|
|
||||||
def test_on_session_creation(ahriman_client: SyncAhrimanClient, user: User, mocker: MockerFixture) -> None:
|
|
||||||
"""
|
|
||||||
must log in user on start
|
|
||||||
"""
|
"""
|
||||||
ahriman_client.auth = (user.username, user.password)
|
ahriman_client.auth = (user.username, user.password)
|
||||||
requests_mock = mocker.patch("ahriman.core.http.SyncAhrimanClient.make_request")
|
requests_mock = mocker.patch("ahriman.core.http.SyncAhrimanClient.make_request")
|
||||||
@@ -42,32 +42,40 @@ def test_on_session_creation(ahriman_client: SyncAhrimanClient, user: User, mock
|
|||||||
}
|
}
|
||||||
session = requests.Session()
|
session = requests.Session()
|
||||||
|
|
||||||
ahriman_client.on_session_creation(session)
|
ahriman_client._login(session)
|
||||||
requests_mock.assert_called_once_with("POST", pytest.helpers.anyvar(str, True), json=payload, session=session)
|
requests_mock.assert_called_once_with("POST", pytest.helpers.anyvar(str, True), json=payload, session=session)
|
||||||
|
|
||||||
|
|
||||||
def test_on_session_creation_failed(ahriman_client: SyncAhrimanClient, user: User, mocker: MockerFixture) -> None:
|
def test_login_failed(ahriman_client: SyncAhrimanClient, user: User, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must suppress any exception happened during session start
|
must suppress any exception happened during login
|
||||||
"""
|
"""
|
||||||
ahriman_client.user = user
|
ahriman_client.user = user
|
||||||
mocker.patch("requests.Session.request", side_effect=Exception)
|
mocker.patch("requests.Session.request", side_effect=Exception)
|
||||||
ahriman_client.on_session_creation(requests.Session())
|
ahriman_client._login(requests.Session())
|
||||||
|
|
||||||
|
|
||||||
def test_start_failed_http_error(ahriman_client: SyncAhrimanClient, user: User, mocker: MockerFixture) -> None:
|
def test_login_failed_http_error(ahriman_client: SyncAhrimanClient, user: User, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must suppress HTTP exception happened during session start
|
must suppress HTTP exception happened during login
|
||||||
"""
|
"""
|
||||||
ahriman_client.user = user
|
ahriman_client.user = user
|
||||||
mocker.patch("requests.Session.request", side_effect=requests.HTTPError)
|
mocker.patch("requests.Session.request", side_effect=requests.HTTPError)
|
||||||
ahriman_client.on_session_creation(requests.Session())
|
ahriman_client._login(requests.Session())
|
||||||
|
|
||||||
|
|
||||||
def test_start_skip(ahriman_client: SyncAhrimanClient, mocker: MockerFixture) -> None:
|
def test_login_skip(ahriman_client: SyncAhrimanClient, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must skip login if no user set
|
must skip login if no user set
|
||||||
"""
|
"""
|
||||||
requests_mock = mocker.patch("requests.Session.request")
|
requests_mock = mocker.patch("requests.Session.request")
|
||||||
ahriman_client.on_session_creation(requests.Session())
|
ahriman_client._login(requests.Session())
|
||||||
requests_mock.assert_not_called()
|
requests_mock.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
|
def test_login_url(ahriman_client: SyncAhrimanClient) -> None:
|
||||||
|
"""
|
||||||
|
must generate login url correctly
|
||||||
|
"""
|
||||||
|
assert ahriman_client._login_url().startswith(ahriman_client.address)
|
||||||
|
assert ahriman_client._login_url().endswith("/api/v1/login")
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import requests
|
|||||||
from pytest_mock import MockerFixture
|
from pytest_mock import MockerFixture
|
||||||
from unittest.mock import MagicMock, call as MockCall
|
from unittest.mock import MagicMock, call as MockCall
|
||||||
|
|
||||||
from ahriman.core.alpm.remote import AUR
|
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.http import SyncHttpClient
|
from ahriman.core.http import SyncHttpClient
|
||||||
|
|
||||||
@@ -34,29 +33,12 @@ def test_init_auth_empty() -> None:
|
|||||||
assert SyncHttpClient().auth is None
|
assert SyncHttpClient().auth is None
|
||||||
|
|
||||||
|
|
||||||
def test_session(mocker: MockerFixture) -> None:
|
def test_session() -> None:
|
||||||
"""
|
"""
|
||||||
must generate valid session
|
must generate valid session
|
||||||
"""
|
"""
|
||||||
on_session_creation_mock = mocker.patch("ahriman.core.http.sync_http_client.SyncHttpClient.on_session_creation")
|
|
||||||
|
|
||||||
session = SyncHttpClient().session
|
session = SyncHttpClient().session
|
||||||
assert "User-Agent" in session.headers
|
assert "User-Agent" in session.headers
|
||||||
on_session_creation_mock.assert_called_once_with(pytest.helpers.anyvar(int))
|
|
||||||
|
|
||||||
|
|
||||||
def test_retry_policy() -> None:
|
|
||||||
"""
|
|
||||||
must set retry policy
|
|
||||||
"""
|
|
||||||
SyncHttpClient.retry = SyncHttpClient.retry_policy(1, 2.0)
|
|
||||||
AUR.retry = AUR.retry_policy(3, 4.0)
|
|
||||||
|
|
||||||
assert SyncHttpClient.retry.connect == 1
|
|
||||||
assert SyncHttpClient.retry.backoff_factor == 2.0
|
|
||||||
|
|
||||||
assert AUR.retry.connect == 3
|
|
||||||
assert AUR.retry.backoff_factor == 4.0
|
|
||||||
|
|
||||||
|
|
||||||
def test_exception_response_text() -> None:
|
def test_exception_response_text() -> None:
|
||||||
@@ -78,18 +60,6 @@ def test_exception_response_text_empty() -> None:
|
|||||||
assert SyncHttpClient.exception_response_text(exception) == ""
|
assert SyncHttpClient.exception_response_text(exception) == ""
|
||||||
|
|
||||||
|
|
||||||
def test_adapters() -> None:
|
|
||||||
"""
|
|
||||||
must create adapters with retry policy
|
|
||||||
"""
|
|
||||||
client = SyncHttpClient()
|
|
||||||
adapters = client.adapters()
|
|
||||||
|
|
||||||
assert "http://" in adapters
|
|
||||||
assert "https://" in adapters
|
|
||||||
assert all(adapter.max_retries == client.retry for adapter in adapters.values())
|
|
||||||
|
|
||||||
|
|
||||||
def test_make_request(mocker: MockerFixture) -> None:
|
def test_make_request(mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must make HTTP request
|
must make HTTP request
|
||||||
@@ -188,11 +158,3 @@ def test_make_request_session() -> None:
|
|||||||
session_mock.request.assert_called_once_with(
|
session_mock.request.assert_called_once_with(
|
||||||
"GET", "url", params=None, data=None, headers=None, files=None, json=None,
|
"GET", "url", params=None, data=None, headers=None, files=None, json=None,
|
||||||
stream=None, auth=None, timeout=client.timeout)
|
stream=None, auth=None, timeout=client.timeout)
|
||||||
|
|
||||||
|
|
||||||
def test_on_session_creation() -> None:
|
|
||||||
"""
|
|
||||||
must do nothing on start
|
|
||||||
"""
|
|
||||||
client = SyncHttpClient()
|
|
||||||
client.on_session_creation(client.session)
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import logging
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from pytest_mock import MockerFixture
|
from pytest_mock import MockerFixture
|
||||||
|
from unittest.mock import call as MockCall
|
||||||
|
|
||||||
from ahriman.core.alpm.repo import Repo
|
from ahriman.core.alpm.repo import Repo
|
||||||
from ahriman.core.build_tools.task import Task
|
from ahriman.core.build_tools.task import Task
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
import smtplib
|
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from pytest_mock import MockerFixture
|
from pytest_mock import MockerFixture
|
||||||
@@ -8,7 +6,6 @@ from ahriman.core.configuration import Configuration
|
|||||||
from ahriman.core.report.email import Email
|
from ahriman.core.report.email import Email
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
from ahriman.models.result import Result
|
from ahriman.models.result import Result
|
||||||
from ahriman.models.smtp_ssl_settings import SmtpSSLSettings
|
|
||||||
|
|
||||||
|
|
||||||
def test_template(configuration: Configuration) -> None:
|
def test_template(configuration: Configuration) -> None:
|
||||||
@@ -40,36 +37,17 @@ def test_template_full(configuration: Configuration) -> None:
|
|||||||
assert Email(repository_id, configuration, "email").template_full == root.parent / template
|
assert Email(repository_id, configuration, "email").template_full == root.parent / template
|
||||||
|
|
||||||
|
|
||||||
def test_smtp_session(email: Email) -> None:
|
|
||||||
"""
|
|
||||||
must build normal SMTP session if SSL is disabled
|
|
||||||
"""
|
|
||||||
email.ssl = SmtpSSLSettings.Disabled
|
|
||||||
assert email._smtp_session == smtplib.SMTP
|
|
||||||
|
|
||||||
email.ssl = SmtpSSLSettings.STARTTLS
|
|
||||||
assert email._smtp_session == smtplib.SMTP
|
|
||||||
|
|
||||||
|
|
||||||
def test_smtp_session_ssl(email: Email) -> None:
|
|
||||||
"""
|
|
||||||
must build SMTP_SSL session if SSL is enabled
|
|
||||||
"""
|
|
||||||
email.ssl = SmtpSSLSettings.SSL
|
|
||||||
assert email._smtp_session == smtplib.SMTP_SSL
|
|
||||||
|
|
||||||
|
|
||||||
def test_send(email: Email, mocker: MockerFixture) -> None:
|
def test_send(email: Email, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must send an email with attachment
|
must send an email with attachment
|
||||||
"""
|
"""
|
||||||
smtp_mock = mocker.patch("smtplib.SMTP")
|
smtp_mock = mocker.patch("smtplib.SMTP")
|
||||||
smtp_mock.return_value.__enter__.return_value = smtp_mock.return_value
|
|
||||||
|
|
||||||
email._send("a text", {"attachment.html": "an attachment"})
|
email._send("a text", {"attachment.html": "an attachment"})
|
||||||
smtp_mock.return_value.starttls.assert_not_called()
|
smtp_mock.return_value.starttls.assert_not_called()
|
||||||
smtp_mock.return_value.login.assert_not_called()
|
smtp_mock.return_value.login.assert_not_called()
|
||||||
smtp_mock.return_value.sendmail.assert_called_once_with(email.sender, email.receivers, pytest.helpers.anyvar(int))
|
smtp_mock.return_value.sendmail.assert_called_once_with(email.sender, email.receivers, pytest.helpers.anyvar(int))
|
||||||
|
smtp_mock.return_value.quit.assert_called_once_with()
|
||||||
|
|
||||||
|
|
||||||
def test_send_auth(configuration: Configuration, mocker: MockerFixture) -> None:
|
def test_send_auth(configuration: Configuration, mocker: MockerFixture) -> None:
|
||||||
@@ -79,7 +57,6 @@ def test_send_auth(configuration: Configuration, mocker: MockerFixture) -> None:
|
|||||||
configuration.set_option("email", "user", "username")
|
configuration.set_option("email", "user", "username")
|
||||||
configuration.set_option("email", "password", "password")
|
configuration.set_option("email", "password", "password")
|
||||||
smtp_mock = mocker.patch("smtplib.SMTP")
|
smtp_mock = mocker.patch("smtplib.SMTP")
|
||||||
smtp_mock.return_value.__enter__.return_value = smtp_mock.return_value
|
|
||||||
_, repository_id = configuration.check_loaded()
|
_, repository_id = configuration.check_loaded()
|
||||||
|
|
||||||
email = Email(repository_id, configuration, "email")
|
email = Email(repository_id, configuration, "email")
|
||||||
@@ -93,7 +70,6 @@ def test_send_auth_no_password(configuration: Configuration, mocker: MockerFixtu
|
|||||||
"""
|
"""
|
||||||
configuration.set_option("email", "user", "username")
|
configuration.set_option("email", "user", "username")
|
||||||
smtp_mock = mocker.patch("smtplib.SMTP")
|
smtp_mock = mocker.patch("smtplib.SMTP")
|
||||||
smtp_mock.return_value.__enter__.return_value = smtp_mock.return_value
|
|
||||||
_, repository_id = configuration.check_loaded()
|
_, repository_id = configuration.check_loaded()
|
||||||
|
|
||||||
email = Email(repository_id, configuration, "email")
|
email = Email(repository_id, configuration, "email")
|
||||||
@@ -107,7 +83,6 @@ def test_send_auth_no_user(configuration: Configuration, mocker: MockerFixture)
|
|||||||
"""
|
"""
|
||||||
configuration.set_option("email", "password", "password")
|
configuration.set_option("email", "password", "password")
|
||||||
smtp_mock = mocker.patch("smtplib.SMTP")
|
smtp_mock = mocker.patch("smtplib.SMTP")
|
||||||
smtp_mock.return_value.__enter__.return_value = smtp_mock.return_value
|
|
||||||
_, repository_id = configuration.check_loaded()
|
_, repository_id = configuration.check_loaded()
|
||||||
|
|
||||||
email = Email(repository_id, configuration, "email")
|
email = Email(repository_id, configuration, "email")
|
||||||
@@ -121,7 +96,6 @@ def test_send_ssl_tls(configuration: Configuration, mocker: MockerFixture) -> No
|
|||||||
"""
|
"""
|
||||||
configuration.set_option("email", "ssl", "ssl")
|
configuration.set_option("email", "ssl", "ssl")
|
||||||
smtp_mock = mocker.patch("smtplib.SMTP_SSL")
|
smtp_mock = mocker.patch("smtplib.SMTP_SSL")
|
||||||
smtp_mock.return_value.__enter__.return_value = smtp_mock.return_value
|
|
||||||
_, repository_id = configuration.check_loaded()
|
_, repository_id = configuration.check_loaded()
|
||||||
|
|
||||||
email = Email(repository_id, configuration, "email")
|
email = Email(repository_id, configuration, "email")
|
||||||
@@ -129,6 +103,7 @@ def test_send_ssl_tls(configuration: Configuration, mocker: MockerFixture) -> No
|
|||||||
smtp_mock.return_value.starttls.assert_not_called()
|
smtp_mock.return_value.starttls.assert_not_called()
|
||||||
smtp_mock.return_value.login.assert_not_called()
|
smtp_mock.return_value.login.assert_not_called()
|
||||||
smtp_mock.return_value.sendmail.assert_called_once_with(email.sender, email.receivers, pytest.helpers.anyvar(int))
|
smtp_mock.return_value.sendmail.assert_called_once_with(email.sender, email.receivers, pytest.helpers.anyvar(int))
|
||||||
|
smtp_mock.return_value.quit.assert_called_once_with()
|
||||||
|
|
||||||
|
|
||||||
def test_send_starttls(configuration: Configuration, mocker: MockerFixture) -> None:
|
def test_send_starttls(configuration: Configuration, mocker: MockerFixture) -> None:
|
||||||
@@ -137,7 +112,6 @@ def test_send_starttls(configuration: Configuration, mocker: MockerFixture) -> N
|
|||||||
"""
|
"""
|
||||||
configuration.set_option("email", "ssl", "starttls")
|
configuration.set_option("email", "ssl", "starttls")
|
||||||
smtp_mock = mocker.patch("smtplib.SMTP")
|
smtp_mock = mocker.patch("smtplib.SMTP")
|
||||||
smtp_mock.return_value.__enter__.return_value = smtp_mock.return_value
|
|
||||||
_, repository_id = configuration.check_loaded()
|
_, repository_id = configuration.check_loaded()
|
||||||
|
|
||||||
email = Email(repository_id, configuration, "email")
|
email = Email(repository_id, configuration, "email")
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ def test_archive_lookup(executor: Executor, package_ahriman: Package, package_py
|
|||||||
"""
|
"""
|
||||||
must existing packages which match the version
|
must existing packages which match the version
|
||||||
"""
|
"""
|
||||||
mocker.patch("pathlib.Path.is_dir", return_value=True)
|
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.preserve_owner")
|
||||||
mocker.patch("pathlib.Path.iterdir", return_value=[
|
mocker.patch("pathlib.Path.iterdir", return_value=[
|
||||||
Path("1.pkg.tar.zst"),
|
Path("1.pkg.tar.zst"),
|
||||||
Path("2.pkg.tar.zst"),
|
Path("2.pkg.tar.zst"),
|
||||||
@@ -40,7 +40,7 @@ def test_archive_lookup_version_mismatch(executor: Executor, package_ahriman: Pa
|
|||||||
"""
|
"""
|
||||||
must return nothing if no packages found with the same version
|
must return nothing if no packages found with the same version
|
||||||
"""
|
"""
|
||||||
mocker.patch("pathlib.Path.is_dir", return_value=True)
|
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.preserve_owner")
|
||||||
mocker.patch("pathlib.Path.iterdir", return_value=[
|
mocker.patch("pathlib.Path.iterdir", return_value=[
|
||||||
Path("1.pkg.tar.zst"),
|
Path("1.pkg.tar.zst"),
|
||||||
])
|
])
|
||||||
@@ -55,8 +55,8 @@ def test_archive_lookup_architecture_mismatch(executor: Executor, package_ahrima
|
|||||||
must return nothing if architecture doesn't match
|
must return nothing if architecture doesn't match
|
||||||
"""
|
"""
|
||||||
package_ahriman.packages[package_ahriman.base].architecture = "x86_64"
|
package_ahriman.packages[package_ahriman.base].architecture = "x86_64"
|
||||||
mocker.patch("pathlib.Path.is_dir", return_value=True)
|
|
||||||
mocker.patch("ahriman.core.repository.executor.Executor.architecture", return_value="i686")
|
mocker.patch("ahriman.core.repository.executor.Executor.architecture", return_value="i686")
|
||||||
|
mocker.patch("ahriman.models.repository_paths.RepositoryPaths.preserve_owner")
|
||||||
mocker.patch("pathlib.Path.iterdir", return_value=[
|
mocker.patch("pathlib.Path.iterdir", return_value=[
|
||||||
Path("1.pkg.tar.zst"),
|
Path("1.pkg.tar.zst"),
|
||||||
])
|
])
|
||||||
@@ -65,17 +65,6 @@ def test_archive_lookup_architecture_mismatch(executor: Executor, package_ahrima
|
|||||||
assert list(executor._archive_lookup(package_ahriman)) == []
|
assert list(executor._archive_lookup(package_ahriman)) == []
|
||||||
|
|
||||||
|
|
||||||
def test_archive_lookup_no_archive_directory(
|
|
||||||
executor: Executor,
|
|
||||||
package_ahriman: Package,
|
|
||||||
mocker: MockerFixture) -> None:
|
|
||||||
"""
|
|
||||||
must return nothing if no archive directory found
|
|
||||||
"""
|
|
||||||
mocker.patch("pathlib.Path.is_dir", return_value=False)
|
|
||||||
assert list(executor._archive_lookup(package_ahriman)) == []
|
|
||||||
|
|
||||||
|
|
||||||
def test_archive_rename(executor: Executor, package_ahriman: Package, mocker: MockerFixture) -> None:
|
def test_archive_rename(executor: Executor, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must correctly remove package archive
|
must correctly remove package archive
|
||||||
|
|||||||
@@ -1,56 +0,0 @@
|
|||||||
from pytest_mock import MockerFixture
|
|
||||||
|
|
||||||
from ahriman.core.configuration import Configuration
|
|
||||||
from ahriman.core.repository import Explorer
|
|
||||||
from ahriman.models.repository_id import RepositoryId
|
|
||||||
|
|
||||||
|
|
||||||
def test_repositories_extract(configuration: Configuration, mocker: MockerFixture) -> None:
|
|
||||||
"""
|
|
||||||
must generate list of available repositories based on arguments
|
|
||||||
"""
|
|
||||||
known_architectures_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_architectures")
|
|
||||||
known_repositories_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_repositories")
|
|
||||||
|
|
||||||
assert Explorer.repositories_extract(configuration, "repo", "arch") == [RepositoryId("arch", "repo")]
|
|
||||||
known_architectures_mock.assert_not_called()
|
|
||||||
known_repositories_mock.assert_not_called()
|
|
||||||
|
|
||||||
|
|
||||||
def test_repositories_extract_repository(configuration: Configuration, mocker: MockerFixture) -> None:
|
|
||||||
"""
|
|
||||||
must generate list of available repositories based on arguments and tree
|
|
||||||
"""
|
|
||||||
known_architectures_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_architectures")
|
|
||||||
known_repositories_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_repositories",
|
|
||||||
return_value={"repo"})
|
|
||||||
|
|
||||||
assert Explorer.repositories_extract(configuration, architecture="arch") == [RepositoryId("arch", "repo")]
|
|
||||||
known_architectures_mock.assert_not_called()
|
|
||||||
known_repositories_mock.assert_called_once_with(configuration.repository_paths.root)
|
|
||||||
|
|
||||||
|
|
||||||
def test_repositories_extract_repository_legacy(configuration: Configuration, mocker: MockerFixture) -> None:
|
|
||||||
"""
|
|
||||||
must generate list of available repositories based on arguments and tree (legacy mode)
|
|
||||||
"""
|
|
||||||
known_architectures_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_architectures")
|
|
||||||
known_repositories_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_repositories",
|
|
||||||
return_value=set())
|
|
||||||
|
|
||||||
assert Explorer.repositories_extract(configuration, architecture="arch") == [RepositoryId("arch", "aur")]
|
|
||||||
known_architectures_mock.assert_not_called()
|
|
||||||
known_repositories_mock.assert_called_once_with(configuration.repository_paths.root)
|
|
||||||
|
|
||||||
|
|
||||||
def test_repositories_extract_architecture(configuration: Configuration, mocker: MockerFixture) -> None:
|
|
||||||
"""
|
|
||||||
must read repository name from config
|
|
||||||
"""
|
|
||||||
known_architectures_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_architectures",
|
|
||||||
return_value={"arch"})
|
|
||||||
known_repositories_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.known_repositories")
|
|
||||||
|
|
||||||
assert Explorer.repositories_extract(configuration, repository="repo") == [RepositoryId("arch", "repo")]
|
|
||||||
known_architectures_mock.assert_called_once_with(configuration.repository_paths.root, "repo")
|
|
||||||
known_repositories_mock.assert_not_called()
|
|
||||||
@@ -2,7 +2,6 @@ from pytest_mock import MockerFixture
|
|||||||
from unittest.mock import call as MockCall
|
from unittest.mock import call as MockCall
|
||||||
|
|
||||||
from ahriman.core.alpm.pacman import Pacman
|
from ahriman.core.alpm.pacman import Pacman
|
||||||
from ahriman.core.alpm.remote import AUR
|
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.database import SQLite
|
from ahriman.core.database import SQLite
|
||||||
from ahriman.core.repository import Repository
|
from ahriman.core.repository import Repository
|
||||||
@@ -14,27 +13,13 @@ def test_load(configuration: Configuration, database: SQLite, mocker: MockerFixt
|
|||||||
"""
|
"""
|
||||||
must correctly load instance
|
must correctly load instance
|
||||||
"""
|
"""
|
||||||
globals_mock = mocker.patch("ahriman.core.repository.Repository._set_globals")
|
|
||||||
context_mock = mocker.patch("ahriman.core.repository.Repository._set_context")
|
context_mock = mocker.patch("ahriman.core.repository.Repository._set_context")
|
||||||
_, repository_id = configuration.check_loaded()
|
_, repository_id = configuration.check_loaded()
|
||||||
|
|
||||||
Repository.load(repository_id, configuration, database, report=False)
|
Repository.load(repository_id, configuration, database, report=False)
|
||||||
globals_mock.assert_called_once_with(configuration)
|
|
||||||
context_mock.assert_called_once_with()
|
context_mock.assert_called_once_with()
|
||||||
|
|
||||||
|
|
||||||
def test_set_globals(configuration: Configuration) -> None:
|
|
||||||
"""
|
|
||||||
must correctly set globals
|
|
||||||
"""
|
|
||||||
configuration.set_option("aur", "timeout", "42")
|
|
||||||
configuration.set_option("aur", "max_retries", "10")
|
|
||||||
|
|
||||||
Repository._set_globals(configuration)
|
|
||||||
assert AUR.timeout == 42
|
|
||||||
assert AUR.retry.connect == 10
|
|
||||||
|
|
||||||
|
|
||||||
def test_set_context(configuration: Configuration, database: SQLite, mocker: MockerFixture) -> None:
|
def test_set_context(configuration: Configuration, database: SQLite, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must set context variables
|
must set context variables
|
||||||
|
|||||||
@@ -357,8 +357,4 @@ def test_updates_manual_with_failures(update_handler: UpdateHandler, package_ahr
|
|||||||
"""
|
"""
|
||||||
mocker.patch("ahriman.core.database.SQLite.build_queue_get", side_effect=Exception)
|
mocker.patch("ahriman.core.database.SQLite.build_queue_get", side_effect=Exception)
|
||||||
mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.packages", return_value=[package_ahriman])
|
mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.packages", return_value=[package_ahriman])
|
||||||
|
|
||||||
assert update_handler.updates_manual() == []
|
assert update_handler.updates_manual() == []
|
||||||
|
|
||||||
from ahriman.core.repository.cleaner import Cleaner
|
|
||||||
Cleaner.clear_queue.assert_not_called()
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ def test_event_get(local_client: LocalClient, package_ahriman: Package, mocker:
|
|||||||
local_client.repository_id)
|
local_client.repository_id)
|
||||||
|
|
||||||
|
|
||||||
def test_logs_rotate(local_client: LocalClient, mocker: MockerFixture) -> None:
|
def test_logs_rotate(local_client: LocalClient, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must rotate logs
|
must rotate logs
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import datetime
|
import datetime
|
||||||
|
import fcntl
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import pytest
|
import pytest
|
||||||
@@ -247,28 +248,51 @@ def test_extract_user() -> None:
|
|||||||
assert extract_user() == "doas"
|
assert extract_user() == "doas"
|
||||||
|
|
||||||
|
|
||||||
def test_filelock(tmp_path: Path) -> None:
|
def test_filelock(mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must acquire lock and remove lock file after
|
must perform file locking
|
||||||
"""
|
"""
|
||||||
local = tmp_path / "local"
|
lock_mock = mocker.patch("fcntl.flock")
|
||||||
lock = local.with_name(f".{local.name}.lock")
|
open_mock = mocker.patch("pathlib.Path.open", autospec=True)
|
||||||
|
unlink_mock = mocker.patch("pathlib.Path.unlink")
|
||||||
|
|
||||||
with filelock(local):
|
with filelock(Path("local")):
|
||||||
assert lock.exists()
|
pass
|
||||||
assert not lock.exists()
|
open_mock.assert_called_once_with(Path(".local"), "ab")
|
||||||
|
lock_mock.assert_has_calls([
|
||||||
|
MockCall(pytest.helpers.anyvar(int), fcntl.LOCK_EX),
|
||||||
|
MockCall(pytest.helpers.anyvar(int), fcntl.LOCK_UN),
|
||||||
|
])
|
||||||
|
unlink_mock.assert_called_once_with(missing_ok=True)
|
||||||
|
|
||||||
|
|
||||||
def test_filelock_cleanup_on_missing(tmp_path: Path) -> None:
|
def test_filelock_remove_lock(mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must not fail if lock file is already removed
|
must remove lock file in case of exception
|
||||||
"""
|
"""
|
||||||
local = tmp_path / "local"
|
mocker.patch("pathlib.Path.open", side_effect=Exception)
|
||||||
lock = local.with_name(f".{local.name}.lock")
|
unlink_mock = mocker.patch("pathlib.Path.unlink")
|
||||||
|
|
||||||
with filelock(local):
|
with pytest.raises(Exception):
|
||||||
lock.unlink(missing_ok=True)
|
with filelock(Path("local")):
|
||||||
assert not lock.exists()
|
pass
|
||||||
|
unlink_mock.assert_called_once_with(missing_ok=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_filelock_unlock(mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must unlock file in case of exception
|
||||||
|
"""
|
||||||
|
mocker.patch("pathlib.Path.open")
|
||||||
|
lock_mock = mocker.patch("fcntl.flock")
|
||||||
|
|
||||||
|
with pytest.raises(Exception):
|
||||||
|
with filelock(Path("local")):
|
||||||
|
raise Exception
|
||||||
|
lock_mock.assert_has_calls([
|
||||||
|
MockCall(pytest.helpers.anyvar(int), fcntl.LOCK_EX),
|
||||||
|
MockCall(pytest.helpers.anyvar(int), fcntl.LOCK_UN),
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
def test_filter_json(package_ahriman: Package) -> None:
|
def test_filter_json(package_ahriman: Package) -> None:
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ def test_configuration_schema_no_schema(configuration: Configuration) -> None:
|
|||||||
assert ReportTrigger.configuration_schema(configuration) == {}
|
assert ReportTrigger.configuration_schema(configuration) == {}
|
||||||
|
|
||||||
|
|
||||||
def test_configuration_schema_empty() -> None:
|
def test_configuration_schema_empty(configuration: Configuration) -> None:
|
||||||
"""
|
"""
|
||||||
must return default schema if no configuration set
|
must return default schema if no configuration set
|
||||||
"""
|
"""
|
||||||
@@ -70,6 +70,7 @@ def test_configuration_schema_variables() -> None:
|
|||||||
must return empty schema
|
must return empty schema
|
||||||
"""
|
"""
|
||||||
assert Trigger.CONFIGURATION_SCHEMA == {}
|
assert Trigger.CONFIGURATION_SCHEMA == {}
|
||||||
|
assert Trigger.CONFIGURATION_SCHEMA_FALLBACK is None
|
||||||
|
|
||||||
|
|
||||||
def test_configuration_sections(configuration: Configuration) -> None:
|
def test_configuration_sections(configuration: Configuration) -> None:
|
||||||
|
|||||||
@@ -4,12 +4,16 @@ from pathlib import Path
|
|||||||
from unittest.mock import MagicMock, PropertyMock
|
from unittest.mock import MagicMock, PropertyMock
|
||||||
|
|
||||||
from ahriman import __version__
|
from ahriman import __version__
|
||||||
|
from ahriman.core.alpm.remote import AUR
|
||||||
from ahriman.models.build_status import BuildStatus, BuildStatusEnum
|
from ahriman.models.build_status import BuildStatus, BuildStatusEnum
|
||||||
from ahriman.models.counters import Counters
|
from ahriman.models.counters import Counters
|
||||||
from ahriman.models.filesystem_package import FilesystemPackage
|
from ahriman.models.filesystem_package import FilesystemPackage
|
||||||
from ahriman.models.internal_status import InternalStatus
|
from ahriman.models.internal_status import InternalStatus
|
||||||
|
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.pkgbuild import Pkgbuild
|
from ahriman.models.pkgbuild import Pkgbuild
|
||||||
|
from ahriman.models.remote_source import RemoteSource
|
||||||
from ahriman.models.repository_stats import RepositoryStats
|
from ahriman.models.repository_stats import RepositoryStats
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -185,14 +185,28 @@ def test_known_repositories_empty(repository_paths: RepositoryPaths, mocker: Moc
|
|||||||
iterdir_mock.assert_not_called()
|
iterdir_mock.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
def test_archive_for(repository_paths: RepositoryPaths, package_ahriman: Package) -> None:
|
def test_archive_for(repository_paths: RepositoryPaths, package_ahriman: Package, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must correctly define archive path
|
must correctly define archive path
|
||||||
"""
|
"""
|
||||||
|
mocker.patch("pathlib.Path.is_dir", return_value=True)
|
||||||
path = repository_paths.archive_for(package_ahriman.base)
|
path = repository_paths.archive_for(package_ahriman.base)
|
||||||
assert path == repository_paths.archive / "packages" / "a" / package_ahriman.base
|
assert path == repository_paths.archive / "packages" / "a" / package_ahriman.base
|
||||||
|
|
||||||
|
|
||||||
|
def test_archive_for_create_tree(repository_paths: RepositoryPaths, package_ahriman: Package,
|
||||||
|
mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must create archive directory if it doesn't exist
|
||||||
|
"""
|
||||||
|
owner_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.preserve_owner")
|
||||||
|
mkdir_mock = mocker.patch("pathlib.Path.mkdir")
|
||||||
|
|
||||||
|
repository_paths.archive_for(package_ahriman.base)
|
||||||
|
owner_mock.assert_called_once_with()
|
||||||
|
mkdir_mock.assert_called_once_with(mode=0o755, parents=True)
|
||||||
|
|
||||||
|
|
||||||
def test_cache_for(repository_paths: RepositoryPaths, package_ahriman: Package) -> None:
|
def test_cache_for(repository_paths: RepositoryPaths, package_ahriman: Package) -> None:
|
||||||
"""
|
"""
|
||||||
must return correct path for cache directory
|
must return correct path for cache directory
|
||||||
@@ -202,29 +216,6 @@ def test_cache_for(repository_paths: RepositoryPaths, package_ahriman: Package)
|
|||||||
assert path.parent == repository_paths.cache
|
assert path.parent == repository_paths.cache
|
||||||
|
|
||||||
|
|
||||||
def test_ensure_exists(repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
|
|
||||||
"""
|
|
||||||
must create directory if it doesn't exist
|
|
||||||
"""
|
|
||||||
owner_guard_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.preserve_owner")
|
|
||||||
mkdir_mock = mocker.patch("pathlib.Path.mkdir")
|
|
||||||
|
|
||||||
repository_paths.ensure_exists(repository_paths.archive)
|
|
||||||
owner_guard_mock.assert_called_once_with()
|
|
||||||
mkdir_mock.assert_called_once_with(mode=0o755, parents=True)
|
|
||||||
|
|
||||||
|
|
||||||
def test_ensure_exists_skip(repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
|
|
||||||
"""
|
|
||||||
must do not create directory if it already exists
|
|
||||||
"""
|
|
||||||
mocker.patch("pathlib.Path.is_dir", return_value=True)
|
|
||||||
mkdir_mock = mocker.patch("pathlib.Path.mkdir")
|
|
||||||
|
|
||||||
repository_paths.ensure_exists(repository_paths.archive)
|
|
||||||
mkdir_mock.assert_not_called()
|
|
||||||
|
|
||||||
|
|
||||||
def test_preserve_owner(tmp_path: Path, repository_id: RepositoryId, mocker: MockerFixture) -> None:
|
def test_preserve_owner(tmp_path: Path, repository_id: RepositoryId, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must preserve file owner during operations
|
must preserve file owner during operations
|
||||||
@@ -314,12 +305,8 @@ def test_tree_create(repository_paths: RepositoryPaths, mocker: MockerFixture) -
|
|||||||
owner_guard_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.preserve_owner")
|
owner_guard_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.preserve_owner")
|
||||||
|
|
||||||
repository_paths.tree_create()
|
repository_paths.tree_create()
|
||||||
mkdir_mock.assert_has_calls([MockCall(mode=0o755, parents=True) for _ in paths], any_order=True)
|
mkdir_mock.assert_has_calls([MockCall(mode=0o755, parents=True, exist_ok=True) for _ in paths], any_order=True)
|
||||||
owner_guard_mock.assert_has_calls([
|
owner_guard_mock.assert_called_once_with()
|
||||||
MockCall(),
|
|
||||||
MockCall().__enter__(),
|
|
||||||
MockCall().__exit__(None, None, None)
|
|
||||||
] * len(paths))
|
|
||||||
|
|
||||||
|
|
||||||
def test_tree_create_skip(mocker: MockerFixture) -> None:
|
def test_tree_create_skip(mocker: MockerFixture) -> None:
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ def test_security() -> None:
|
|||||||
must generate security definitions for swagger
|
must generate security definitions for swagger
|
||||||
"""
|
"""
|
||||||
token = next(iter(_security()))["token"]
|
token = next(iter(_security()))["token"]
|
||||||
assert token == {"type": "apiKey", "name": "AHRIMAN", "in": "cookie"}
|
assert token == {"type": "apiKey", "name": "API_SESSION", "in": "cookie"}
|
||||||
|
|
||||||
|
|
||||||
def test_servers(application: Application) -> None:
|
def test_servers(application: Application) -> None:
|
||||||
|
|||||||
@@ -6,4 +6,4 @@ def test_schema() -> None:
|
|||||||
must return valid schema
|
must return valid schema
|
||||||
"""
|
"""
|
||||||
schema = AuthSchema()
|
schema = AuthSchema()
|
||||||
assert not schema.validate({"AHRIMAN": "key"})
|
assert not schema.validate({"API_SESSION": "key"})
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ def _client(client: TestClient, mocker: MockerFixture) -> TestClient:
|
|||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"in": "cookie",
|
"in": "cookie",
|
||||||
"name": "AHRIMAN",
|
"name": "API_SESSION",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
},
|
},
|
||||||
@@ -39,7 +39,7 @@ def _client(client: TestClient, mocker: MockerFixture) -> TestClient:
|
|||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"in": "cookie",
|
"in": "cookie",
|
||||||
"name": "AHRIMAN",
|
"name": "API_SESSION",
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
},
|
},
|
||||||
@@ -60,7 +60,7 @@ def _client(client: TestClient, mocker: MockerFixture) -> TestClient:
|
|||||||
{
|
{
|
||||||
"token": {
|
"token": {
|
||||||
"type": "apiKey",
|
"type": "apiKey",
|
||||||
"name": "AHRIMAN",
|
"name": "API_SESSION",
|
||||||
"in": "cookie",
|
"in": "cookie",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ async def test_delete_partially(client: TestClient, package_ahriman: Package) ->
|
|||||||
assert json
|
assert json
|
||||||
|
|
||||||
|
|
||||||
async def test_delete_exception(client: TestClient) -> None:
|
async def test_delete_exception(client: TestClient, package_ahriman: Package) -> None:
|
||||||
"""
|
"""
|
||||||
must raise exception on invalid payload
|
must raise exception on invalid payload
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ async def test_get_redirect_to_oauth(client_with_oauth_auth: TestClient) -> None
|
|||||||
assert not request_schema.validate(payload)
|
assert not request_schema.validate(payload)
|
||||||
response = await client_with_oauth_auth.get("/api/v1/login", params=payload, allow_redirects=False)
|
response = await client_with_oauth_auth.get("/api/v1/login", params=payload, allow_redirects=False)
|
||||||
assert response.ok
|
assert response.ok
|
||||||
oauth.get_oauth_url.assert_called_once_with(pytest.helpers.anyvar(str))
|
oauth.get_oauth_url.assert_called_once_with()
|
||||||
|
|
||||||
|
|
||||||
async def test_get_redirect_to_oauth_empty_code(client_with_oauth_auth: TestClient) -> None:
|
async def test_get_redirect_to_oauth_empty_code(client_with_oauth_auth: TestClient) -> None:
|
||||||
@@ -69,15 +69,13 @@ async def test_get_redirect_to_oauth_empty_code(client_with_oauth_auth: TestClie
|
|||||||
assert not request_schema.validate(payload)
|
assert not request_schema.validate(payload)
|
||||||
response = await client_with_oauth_auth.get("/api/v1/login", params=payload, allow_redirects=False)
|
response = await client_with_oauth_auth.get("/api/v1/login", params=payload, allow_redirects=False)
|
||||||
assert response.ok
|
assert response.ok
|
||||||
oauth.get_oauth_url.assert_called_once_with(pytest.helpers.anyvar(str))
|
oauth.get_oauth_url.assert_called_once_with()
|
||||||
|
|
||||||
|
|
||||||
async def test_get(client_with_oauth_auth: TestClient, mocker: MockerFixture) -> None:
|
async def test_get(client_with_oauth_auth: TestClient, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must log in user correctly from OAuth
|
must log in user correctly from OAuth
|
||||||
"""
|
"""
|
||||||
session = {"state": "state"}
|
|
||||||
mocker.patch("ahriman.web.views.v1.user.login.get_session", return_value=session)
|
|
||||||
oauth = client_with_oauth_auth.app[AuthKey]
|
oauth = client_with_oauth_auth.app[AuthKey]
|
||||||
oauth.get_oauth_username.return_value = "user"
|
oauth.get_oauth_username.return_value = "user"
|
||||||
oauth.known_username.return_value = True
|
oauth.known_username.return_value = True
|
||||||
@@ -86,12 +84,12 @@ async def test_get(client_with_oauth_auth: TestClient, mocker: MockerFixture) ->
|
|||||||
remember_mock = mocker.patch("ahriman.web.views.v1.user.login.remember")
|
remember_mock = mocker.patch("ahriman.web.views.v1.user.login.remember")
|
||||||
request_schema = pytest.helpers.schema_request(LoginView.get, location="querystring")
|
request_schema = pytest.helpers.schema_request(LoginView.get, location="querystring")
|
||||||
|
|
||||||
payload = {"code": "code", "state": "state"}
|
payload = {"code": "code"}
|
||||||
assert not request_schema.validate(payload)
|
assert not request_schema.validate(payload)
|
||||||
response = await client_with_oauth_auth.get("/api/v1/login", params=payload)
|
response = await client_with_oauth_auth.get("/api/v1/login", params=payload)
|
||||||
|
|
||||||
assert response.ok
|
assert response.ok
|
||||||
oauth.get_oauth_username.assert_called_once_with("code", "state", session)
|
oauth.get_oauth_username.assert_called_once_with("code")
|
||||||
oauth.known_username.assert_called_once_with("user")
|
oauth.known_username.assert_called_once_with("user")
|
||||||
remember_mock.assert_called_once_with(
|
remember_mock.assert_called_once_with(
|
||||||
pytest.helpers.anyvar(int), pytest.helpers.anyvar(int), pytest.helpers.anyvar(int))
|
pytest.helpers.anyvar(int), pytest.helpers.anyvar(int), pytest.helpers.anyvar(int))
|
||||||
|
|||||||
Reference in New Issue
Block a user