Compare commits

...

23 Commits

Author SHA1 Message Date
f01f35238d Release 2.13.5 2024-04-04 13:33:03 +03:00
d30d512eb6 fix: update Repo.init to the latest pacman release 2024-04-04 13:16:05 +03:00
0437f90e5a build: install base-devel package 2024-04-04 13:16:03 +03:00
3cab65855a fix: lazy web component initialization
In some cases (probably slow internet) in place initialization can cause
exception, because elements are not available yet. This commit moves
events initialization to $()
2024-04-04 13:14:17 +03:00
ecfb615f97 feat: add ability to disable debug packages distribution
The feature is implemented as supplying !debug option to makepkg when
generating package list. In this case debug packages still will be
built, however, they will not be added to the repository
2024-04-04 13:14:17 +03:00
243983ee64 docs: update docs 2024-02-10 03:12:09 +02:00
812c03d1eb Release 2.13.4 2024-02-09 17:47:01 +02:00
01597c531b fix: return only built packages from task
Since the last updates makepkg --packagelist also adds debug packages
which causes errors
2024-02-09 17:37:50 +02:00
4fec42eac8 refactor: rename packages http methods to own package
docs: update docs import
2024-01-22 02:20:11 +02:00
7574b8e5ce Release 2.13.3 2024-01-13 01:24:30 +02:00
0f2e7f45da fix: replace logo and name in title to just icon 2024-01-12 01:25:46 +02:00
5956a8720b Release 2.13.2 2024-01-08 22:48:55 +02:00
8dd4ced5e9 fix: report only unique result entries
since builder intro the triggers are called with merged result, thus it
would lead to duplicated callouts
2024-01-08 22:46:42 +02:00
6361c41f76 Release 2.13.1 2024-01-08 21:17:35 +02:00
270084bb39 fix: do not raise 404 in case of unknown package on patches endpoints
Previous improvements raise 404 error in case if no packages were found
for patches endpoints. However, in case of multirepo setup this feature
doesn't work properly because package can be located in any other
repository different from default
2024-01-08 14:32:40 +02:00
f89a5252de build: pass ssh agent to tox release env 2024-01-08 14:22:53 +02:00
8cafdb52e5 Release 2.13.0 2024-01-05 22:48:03 +02:00
203ebad817 ci: explicit isolated build for old ubuntu tox 2024-01-05 22:47:28 +02:00
9f471d11a7 docs: add comments to configuration 2024-01-05 22:24:37 +02:00
2ea8a4a07f test: add pytlint imports plugin and fix errors 2024-01-05 19:52:51 +02:00
856bbc30d4 refactor: fix pylint warnings in tests 2024-01-05 16:40:38 +02:00
c88f97c36e refactor: simplify lock processing in worker trigger 2024-01-05 16:11:32 +02:00
174d7578a0 refactor: split Path elements to / and first directory 2024-01-05 15:22:46 +02:00
136 changed files with 10968 additions and 9054 deletions

View File

@ -12,7 +12,7 @@ pacman -Syu --noconfirm
# main dependencies # main dependencies
pacman -Sy --noconfirm devtools git pyalpm python-cerberus python-inflection python-passlib python-requests python-srcinfo python-systemd sudo pacman -Sy --noconfirm devtools git pyalpm python-cerberus python-inflection python-passlib python-requests python-srcinfo python-systemd sudo
# make dependencies # make dependencies
pacman -Sy --noconfirm python-build python-flit python-installer python-tox python-wheel pacman -Sy --noconfirm --asdeps base-devel python-build python-flit python-installer python-tox python-wheel
# optional dependencies # optional dependencies
if [[ -z $MINIMAL_INSTALL ]]; then if [[ -z $MINIMAL_INSTALL ]]; then
# VCS support # VCS support
@ -32,10 +32,13 @@ mv dist/ahriman-*.tar.gz package/archlinux
chmod +777 package/archlinux # because fuck you that's why chmod +777 package/archlinux # because fuck you that's why
cd package/archlinux cd package/archlinux
sudo -u nobody -- makepkg -cf --skipchecksums --noconfirm sudo -u nobody -- makepkg -cf --skipchecksums --noconfirm
sudo -u nobody -- makepkg --packagelist | pacman -U --noconfirm - sudo -u nobody -- makepkg --packagelist | grep -v -- -debug- | pacman -U --noconfirm -
# create machine-id which is required by build tools # create machine-id which is required by build tools
systemd-machine-id-setup systemd-machine-id-setup
# remove unused dependencies
pacman -Qdtq | pacman -Rscn --noconfirm -
# initial setup command as root # initial setup command as root
[[ -z $MINIMAL_INSTALL ]] && WEB_ARGS=("--web-port" "8080") [[ -z $MINIMAL_INSTALL ]] && WEB_ARGS=("--web-port" "8080")
ahriman -a x86_64 -r "github" service-setup --packager "ahriman bot <ahriman@example.com>" "${WEB_ARGS[@]}" ahriman -a x86_64 -r "github" service-setup --packager "ahriman bot <ahriman@example.com>" "${WEB_ARGS[@]}"
@ -50,7 +53,7 @@ if [[ -z $MINIMAL_INSTALL ]]; then
WEB_PID=$! WEB_PID=$!
fi fi
# add the first package # add the first package
sudo -u ahriman -- ahriman package-add --now ahriman sudo -u ahriman -- ahriman --log-handler console package-add --now ahriman
# check if package was actually installed # check if package was actually installed
test -n "$(find "/var/lib/ahriman/repository/github/x86_64" -name "ahriman*pkg*")" test -n "$(find "/var/lib/ahriman/repository/github/x86_64" -name "ahriman*pkg*")"
# run package check # run package check

View File

@ -83,6 +83,7 @@ limit-inference-results=100
# usually to register additional checkers. # usually to register additional checkers.
load-plugins=pylint.extensions.docparams, load-plugins=pylint.extensions.docparams,
definition_order, definition_order,
import_order,
# Pickle collected data for later comparisons. # Pickle collected data for later comparisons.
persistent=yes persistent=yes

View File

@ -33,9 +33,9 @@ COPY "docker/install-aur-package.sh" "/usr/local/bin/install-aur-package"
## install package dependencies ## install package dependencies
## darcs is not installed by reasons, because it requires a lot haskell packages which dramatically increase image size ## darcs is not installed by reasons, because it requires a lot haskell packages which dramatically increase image size
RUN pacman -Sy --noconfirm --asdeps devtools git pyalpm python-cerberus python-inflection python-passlib python-requests python-srcinfo && \ RUN pacman -Sy --noconfirm --asdeps devtools git pyalpm python-cerberus python-inflection python-passlib python-requests python-srcinfo && \
pacman -Sy --noconfirm --asdeps python-build python-flit python-installer python-wheel && \ pacman -Sy --noconfirm --asdeps base-devel python-build python-flit python-installer python-wheel && \
pacman -Sy --noconfirm --asdeps breezy git mercurial python-aiohttp python-boto3 python-cryptography python-jinja python-requests-unixsocket python-systemd rsync subversion && \ pacman -Sy --noconfirm --asdeps breezy git mercurial python-aiohttp python-boto3 python-cryptography python-jinja python-requests-unixsocket python-systemd rsync subversion && \
runuser -u build -- install-aur-package python-aioauth-client python-aiohttp-apispec-git python-aiohttp-cors \ runuser -u build -- install-aur-package python-aioauth-client python-webargs python-aiohttp-apispec-git python-aiohttp-cors \
python-aiohttp-jinja2 python-aiohttp-session python-aiohttp-security python-aiohttp-jinja2 python-aiohttp-session python-aiohttp-security
## FIXME since 1.0.4 devtools requires dbus to be run, which doesn't work now in container ## FIXME since 1.0.4 devtools requires dbus to be run, which doesn't work now in container

View File

@ -6,7 +6,7 @@ for PACKAGE in "$@"; do
BUILD_DIR="$(mktemp -d)" BUILD_DIR="$(mktemp -d)"
git clone https://aur.archlinux.org/"$PACKAGE".git "$BUILD_DIR" git clone https://aur.archlinux.org/"$PACKAGE".git "$BUILD_DIR"
cd "$BUILD_DIR" cd "$BUILD_DIR"
makepkg --noconfirm --install --rmdeps --syncdeps makepkg --nocheck --noconfirm --install --rmdeps --syncdeps
cd / cd /
rm -r "$BUILD_DIR" rm -r "$BUILD_DIR"
done done

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 993 KiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

@ -0,0 +1,61 @@
ahriman.web.views.v1.packages package
=====================================
Submodules
----------
ahriman.web.views.v1.packages.changes module
--------------------------------------------
.. automodule:: ahriman.web.views.v1.packages.changes
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.v1.packages.logs module
-----------------------------------------
.. automodule:: ahriman.web.views.v1.packages.logs
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.v1.packages.package module
--------------------------------------------
.. automodule:: ahriman.web.views.v1.packages.package
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.v1.packages.packages module
---------------------------------------------
.. automodule:: ahriman.web.views.v1.packages.packages
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.v1.packages.patch module
------------------------------------------
.. automodule:: ahriman.web.views.v1.packages.patch
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.v1.packages.patches module
--------------------------------------------
.. automodule:: ahriman.web.views.v1.packages.patches
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.web.views.v1.packages
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -8,6 +8,7 @@ Subpackages
:maxdepth: 4 :maxdepth: 4
ahriman.web.views.v1.distributed ahriman.web.views.v1.distributed
ahriman.web.views.v1.packages
ahriman.web.views.v1.service ahriman.web.views.v1.service
ahriman.web.views.v1.status ahriman.web.views.v1.status
ahriman.web.views.v1.user ahriman.web.views.v1.user

View File

@ -4,14 +4,6 @@ ahriman.web.views.v1.status package
Submodules Submodules
---------- ----------
ahriman.web.views.v1.status.changes module
------------------------------------------
.. automodule:: ahriman.web.views.v1.status.changes
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.v1.status.info module ahriman.web.views.v1.status.info module
--------------------------------------- ---------------------------------------
@ -20,46 +12,6 @@ ahriman.web.views.v1.status.info module
:no-undoc-members: :no-undoc-members:
:show-inheritance: :show-inheritance:
ahriman.web.views.v1.status.logs module
---------------------------------------
.. automodule:: ahriman.web.views.v1.status.logs
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.v1.status.package module
------------------------------------------
.. automodule:: ahriman.web.views.v1.status.package
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.v1.status.packages module
-------------------------------------------
.. automodule:: ahriman.web.views.v1.status.packages
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.v1.status.patch module
----------------------------------------
.. automodule:: ahriman.web.views.v1.status.patch
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.v1.status.patches module
------------------------------------------
.. automodule:: ahriman.web.views.v1.status.patches
:members:
:no-undoc-members:
:show-inheritance:
ahriman.web.views.v1.status.repositories module ahriman.web.views.v1.status.repositories module
----------------------------------------------- -----------------------------------------------

View File

@ -0,0 +1,21 @@
ahriman.web.views.v2.packages package
=====================================
Submodules
----------
ahriman.web.views.v2.packages.logs module
-----------------------------------------
.. automodule:: ahriman.web.views.v2.packages.logs
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.web.views.v2.packages
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -7,7 +7,7 @@ Subpackages
.. toctree:: .. toctree::
:maxdepth: 4 :maxdepth: 4
ahriman.web.views.v2.status ahriman.web.views.v2.packages
Module contents Module contents
--------------- ---------------

View File

@ -1,21 +0,0 @@
ahriman.web.views.v2.status package
===================================
Submodules
----------
ahriman.web.views.v2.status.logs module
---------------------------------------
.. automodule:: ahriman.web.views.v2.status.logs
:members:
:no-undoc-members:
:show-inheritance:
Module contents
---------------
.. automodule:: ahriman.web.views.v2.status
:members:
:no-undoc-members:
:show-inheritance:

View File

@ -39,9 +39,9 @@ It will check current settings on common errors and compare configuration with k
Base configuration settings. Base configuration settings.
* ``apply_migrations`` - perform migrations on application start, boolean, optional, default ``yes``. Useful if you are using git version. Note, however, that this option must be changed only if you know what to do and going to handle migrations manually. * ``apply_migrations`` - perform database migrations on the application start, boolean, optional, default ``yes``. Useful if you are using git version. Note, however, that this option must be changed only if you know what to do and going to handle migrations manually.
* ``database`` - path to SQLite database, string, required. * ``database`` - path to the application SQLite database, string, required.
* ``include`` - path to directory with configuration files overrides, string, optional. * ``include`` - path to directory with configuration files overrides, string, optional. Files will be read in alphabetical order.
* ``logging`` - path to logging configuration, string, required. Check ``logging.ini`` for reference. * ``logging`` - path to logging configuration, string, required. Check ``logging.ini`` for reference.
``alpm:*`` groups ``alpm:*`` groups
@ -51,9 +51,9 @@ libalpm and AUR related configuration. Group name can refer to architecture, e.g
* ``database`` - path to pacman system database cache, string, required. * ``database`` - path to pacman system database cache, string, required.
* ``mirror`` - package database mirror used by pacman for synchronization, string, required. This option supports standard pacman substitutions with ``$arch`` and ``$repo``. Note that the mentioned mirror should contain all repositories which are set by ``alpm.repositories`` option. * ``mirror`` - package database mirror used by pacman for synchronization, string, required. This option supports standard pacman substitutions with ``$arch`` and ``$repo``. Note that the mentioned mirror should contain all repositories which are set by ``alpm.repositories`` option.
* ``repositories`` - list of pacman repositories, space separated list of strings, required. * ``repositories`` - list of pacman repositories, used for package search, space separated list of strings, required.
* ``root`` - root for alpm library, string, required. * ``root`` - root for alpm library, string, required. In the most cases it must point to the system root.
* ``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). * ``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.
``auth`` group ``auth`` group
-------------- --------------
@ -64,7 +64,7 @@ Base authorization settings. ``OAuth`` provider requires ``aioauth-client`` libr
* ``allow_read_only`` - allow requesting status APIs without authorization, boolean, required. * ``allow_read_only`` - allow requesting status APIs without authorization, boolean, required.
* ``client_id`` - OAuth2 application client ID, string, required in case if ``oauth`` is used. * ``client_id`` - OAuth2 application client ID, string, required in case if ``oauth`` is used.
* ``client_secret`` - OAuth2 application client secret key, string, required in case if ``oauth`` is used. * ``client_secret`` - OAuth2 application client secret key, string, required in case if ``oauth`` is used.
* ``cookie_secret_key`` - secret key which will be used for cookies encryption, string, optional. It must be 32 URL-safe base64-encoded bytes and can be generated as following ``base64.urlsafe_b64encode(os.urandom(32)).decode("utf8")``. If not set, it will be generated automatically; note, however, that in this case, all sessions will be automatically invalidated during the service restart. * ``cookie_secret_key`` - secret key which will be used for cookies encryption, string, optional. It must be 32 bytes URL-safe base64-encoded and can be generated as following ``base64.urlsafe_b64encode(os.urandom(32)).decode("utf8")``. If not set, it will be generated automatically; note, however, that in this case, all sessions will be automatically invalidated during the service restart.
* ``max_age`` - parameter which controls both cookie expiration and token expiration inside the service in seconds, integer, optional, default is 7 days. * ``max_age`` - parameter which controls both cookie expiration and token expiration inside the service in seconds, integer, optional, default is 7 days.
* ``oauth_icon`` - OAuth2 login button icon, string, optional, default is ``google``. Must be valid `Bootstrap icon <https://icons.getbootstrap.com/>`__ name. * ``oauth_icon`` - OAuth2 login button icon, string, optional, default is ``google``. Must be valid `Bootstrap icon <https://icons.getbootstrap.com/>`__ name.
* ``oauth_provider`` - OAuth2 provider class name as is in ``aioauth-client`` (e.g. ``GoogleClient``, ``GithubClient`` etc), string, required in case if ``oauth`` is used. * ``oauth_provider`` - OAuth2 provider class name as is in ``aioauth-client`` (e.g. ``GoogleClient``, ``GithubClient`` etc), string, required in case if ``oauth`` is used.
@ -81,6 +81,7 @@ Build related configuration. Group name can refer to architecture, e.g. ``build:
* ``archbuild_flags`` - additional flags passed to ``archbuild`` command, space separated list of strings, optional. * ``archbuild_flags`` - additional flags passed to ``archbuild`` command, space separated list of strings, optional.
* ``build_command`` - default build command, string, required. * ``build_command`` - default build command, string, required.
* ``ignore_packages`` - list packages to ignore during a regular update (manual update will still work), space separated list of strings, optional. * ``ignore_packages`` - list packages to ignore during a regular update (manual update will still work), space separated list of strings, optional.
* ``include_debug_packages`` - distribute debug packages, boolean, optional, default ``yes``.
* ``makepkg_flags`` - additional flags passed to ``makepkg`` command, space separated list of strings, optional. * ``makepkg_flags`` - additional flags passed to ``makepkg`` command, space separated list of strings, optional.
* ``makechrootpkg_flags`` - additional flags passed to ``makechrootpkg`` command, space separated list of strings, optional. * ``makechrootpkg_flags`` - additional flags passed to ``makechrootpkg`` command, space separated list of strings, optional.
* ``triggers`` - list of ``ahriman.core.triggers.Trigger`` class implementation (e.g. ``ahriman.core.report.ReportTrigger ahriman.core.upload.UploadTrigger``) which will be loaded and run at the end of processing, space separated list of strings, optional. You can also specify triggers by their paths, e.g. ``/usr/lib/python3.10/site-packages/ahriman/core/report/report.py.ReportTrigger``. Triggers are run in the order of definition. * ``triggers`` - list of ``ahriman.core.triggers.Trigger`` class implementation (e.g. ``ahriman.core.report.ReportTrigger ahriman.core.upload.UploadTrigger``) which will be loaded and run at the end of processing, space separated list of strings, optional. You can also specify triggers by their paths, e.g. ``/usr/lib/python3.10/site-packages/ahriman/core/report/report.py.ReportTrigger``. Triggers are run in the order of definition.
@ -148,7 +149,7 @@ Keyring generator plugin
* ``homepage`` - URL to homepage location if any, string, optional. * ``homepage`` - URL to homepage location if any, string, optional.
* ``license`` - list of licenses which are applied to this package, space separated list of strings, optional, default is ``Unlicense``. * ``license`` - list of licenses which are applied to this package, space separated list of strings, optional, default is ``Unlicense``.
* ``package`` - keyring package name, string, optional, default is ``repo-keyring``, where ``repo`` is the repository name. * ``package`` - keyring package name, string, optional, default is ``repo-keyring``, where ``repo`` is the repository name.
* ``packagers`` - list of packagers keys, space separated list of strings, optional, if not set, the ``key_*`` options from ``sign`` group will be used. * ``packagers`` - list of packagers keys, space separated list of strings, optional, if not set, the user keys from database will be used.
* ``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.

View File

@ -1,7 +1,7 @@
# Maintainer: Evgeniy Alekseev # Maintainer: Evgeniy Alekseev
pkgname='ahriman' pkgname='ahriman'
pkgver=2.12.2 pkgver=2.13.5
pkgrel=1 pkgrel=1
pkgdesc="ArcH linux ReposItory MANager" pkgdesc="ArcH linux ReposItory MANager"
arch=('any') arch=('any')

View File

@ -1,85 +1,356 @@
[settings] [settings]
; Relative path to directory with configuration files overrides. Overrides will be applied in alphabetic order.
include = ahriman.ini.d include = ahriman.ini.d
; Relative path to configuration used by logging package.
logging = ahriman.ini.d/logging.ini logging = ahriman.ini.d/logging.ini
apply_migrations = yes ; Perform database migrations on the application start. Do not touch this option unless you know what are you doing.
;apply_migrations = yes
; Path to the application SQLite database.
database = /var/lib/ahriman/ahriman.db database = /var/lib/ahriman/ahriman.db
[alpm] [alpm]
; Path to pacman system database cache.
database = /var/lib/pacman database = /var/lib/pacman
; Arch linux mirror used by local pacman for synchronization.
mirror = https://geo.mirror.pkgbuild.com/$repo/os/$arch mirror = https://geo.mirror.pkgbuild.com/$repo/os/$arch
; Space separated list of pacman repositories to search for packages.
repositories = core extra multilib repositories = core extra multilib
; Pacman's root directory. In the most cases it must point to the system root.
root = / root = /
; Use local packages cache. If this option is enabled, the service will be able to synchronize databases (available
; as additional option for some subcommands). If set to no, databases must be synchronized manually.
use_ahriman_cache = yes use_ahriman_cache = yes
[auth] [auth]
; Authentication provider, must be one of disabled, configuration, oauth.
target = disabled target = disabled
max_age = 604800 ; Allow read-only endpoint to be called without authentication.
oauth_provider = GoogleClient
oauth_scopes = https://www.googleapis.com/auth/userinfo.email
allow_read_only = yes allow_read_only = yes
; OAuth2 application client ID and secret. Required if oauth is used.
;client_id =
;client_secret =
; Cookie secret key to be used for cookies encryption. Must be valid 32 bytes URL-safe base64-encoded string.
; If not set, it will be generated automatically.
;cookie_secret_key =
; Authentication cookie expiration in seconds.
;max_age = 604800
; OAuth2 provider icon for the web interface.
;oauth_icon = google
; OAuth2 provider class name, one of provided by aioauth-client. Required if oauth is used.
;oauth_provider = GoogleClient
; Scopes list for OAuth2 provider. Required if oauth is used.
;oauth_scopes = https://www.googleapis.com/auth/userinfo.email
; Optional password salt.
;salt =
[build] [build]
archbuild_flags = ; List of additional flags passed to archbuild command.
ignore_packages = ;archbuild_flags =
makechrootpkg_flags = ; Path to build command
;build_command =
; List of packages to be ignored during automatic updates.
;ignore_packages =
; Include debug packages
;include_debug_packages = yes
; List of additional flags passed to makechrootpkg command.
;makechrootpkg_flags =
; List of additional flags passed to makepkg command.
makepkg_flags = --nocolor --ignorearch makepkg_flags = --nocolor --ignorearch
; List of enabled triggers in the order of calls.
triggers = ahriman.core.gitremote.RemotePullTrigger ahriman.core.report.ReportTrigger ahriman.core.upload.UploadTrigger ahriman.core.gitremote.RemotePushTrigger triggers = ahriman.core.gitremote.RemotePullTrigger ahriman.core.report.ReportTrigger ahriman.core.upload.UploadTrigger ahriman.core.gitremote.RemotePushTrigger
; List of well-known triggers. Used only for configuration purposes.
triggers_known = ahriman.core.distributed.WorkerLoaderTrigger ahriman.core.distributed.WorkerRegisterTrigger ahriman.core.distributed.WorkerTrigger ahriman.core.distributed.WorkerUnregisterTrigger ahriman.core.gitremote.RemotePullTrigger ahriman.core.gitremote.RemotePushTrigger ahriman.core.report.ReportTrigger ahriman.core.upload.UploadTrigger ahriman.core.support.KeyringTrigger ahriman.core.support.MirrorlistTrigger triggers_known = ahriman.core.distributed.WorkerLoaderTrigger ahriman.core.distributed.WorkerRegisterTrigger ahriman.core.distributed.WorkerTrigger ahriman.core.distributed.WorkerUnregisterTrigger ahriman.core.gitremote.RemotePullTrigger ahriman.core.gitremote.RemotePushTrigger ahriman.core.report.ReportTrigger ahriman.core.upload.UploadTrigger ahriman.core.support.KeyringTrigger ahriman.core.support.MirrorlistTrigger
vcs_allowed_age = 604800 ; Maximal age in seconds of the VCS packages before their version will be updated with its remote source.
;vcs_allowed_age = 604800
; List of worker nodes addresses used for build process, e.g.:
; workers = http://10.0.0.1:8080 http://10.0.0.3:8080
; Empty list means run on the local instance.
;workers =
[repository] [repository]
; Application root.
root = /var/lib/ahriman root = /var/lib/ahriman
[sign] [sign]
; Enable repository or package signing. Must be one of repository, package.
target = target =
; PGP key used for signing as default.
[keyring] ;key =
target =
[mirrorlist]
target =
[remote-pull]
target =
[remote-push]
target =
[report]
target = console
[console]
use_utf = yes
[email]
no_empty_report = yes
template = email-index.jinja2
templates = /usr/share/ahriman/templates
ssl = disabled
[html]
template = repo-index.jinja2
templates = /usr/share/ahriman/templates
[status] [status]
; Global switch to enable or disable status reporting.
enabled = yes enabled = yes
; Address of the remote service, e.g.:
; address = http://1.0.0.1:8080
; 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 =
; Optional password for authentication (if enabled).
;password =
; Do not log HTTP errors if occurs.
suppress_http_log_errors = yes suppress_http_log_errors = yes
; HTTP request timeout in seconds.
[telegram] ;timeout = 30
template = telegram-index.jinja2 ; Optional username for authentication (if enabled).
templates = /usr/share/ahriman/templates ;username =
[upload]
target =
[rsync]
command = rsync --archive --compress --partial --delete
[s3]
chunk_size = 8388608
[web] [web]
; External address of the web service. Will be used for some features like OAuth. If none set will be generated as
; address = http://web.host:web.port
;address =
; Enable file upload endpoint used by some triggers.
;enable_archive_upload = no
; Address to bind the server.
host = 127.0.0.1 host = 127.0.0.1
; Full URL to the repository index page used by templates.
;index_url =
; Max file size in bytes which can be uploaded to the server.
;max_body_size =
; Port to listen. Must be set, if the web service is enabled.
;port =
; Disable status (e.g. package status, logs, etc) endpoints. Useful for build only modes.
;service_only = no
; Path to directory with static files.
static_path = /usr/share/ahriman/templates/static static_path = /usr/share/ahriman/templates/static
; List of directories with templates.
templates = /usr/share/ahriman/templates templates = /usr/share/ahriman/templates
unix_socket_unsafe = yes ; Path to unix socket. If none set, unix socket will be disabled.
;unix_socket =
; Allow unix socket to be world readable.
;unix_socket_unsafe = yes
; Maximum amount of time in seconds to be waited before lock will be free, used by spawned processes (0 is infinite).
;wait_timeout =
[keyring]
; List of configuration section names for keyring generator plugin, e.g.:
; target = keyring-trigger
target =
; Keyring generator trigger sample.
;[keyring-trigger]
; Generator type name.
;type = keyring-generator
; Optional keyring package description.
;description=
; Optional URL to the repository homepage.
;homepage=
; Keyring package licenses list.
;license = Unlicense
; Optional keyring package name.
;package =
; Optional packager PGP keys list. If none set, it will read from database.
;packagers =
; List of revoked PGP keys.
;revoked =
; List of master PGP keys. If none set, the sign.key value will be used.
;trusted =
[mirrorlist]
; List of configuration section names for mirrorlist generator plugin, e.g.:
; target = mirrorlist-trigger
target =
; Mirror list generator trigger sample.
;[mirrorlist-trigger]
; Generator type name.
;type = mirrorlist-generator
; Optional mirrorlist package description.
;description=
; Optional URL to the repository homepage.
;homepage=
; Mirrorlist package licenses list.
;license = Unlicense
; Optional mirrorlist package name.
;package =
; Absolute path to generated mirrorlist file, usually path inside /etc/pacman.d directory.
;path =
; List of repository mirrors.
;servers =
[remote-pull]
; List of configuration section names for git remote pull plugin, e.g.:
; target = remote-pull-trigger
target =
; git remote pull trigger sample.
;[remote-pull-trigger]
; Valid URL to pull repository, e.g.:
; pull_url = https://github.com/arcan1s/arcanisrepo.git
;pull_url =
; Remote branch to pull.
;pull_branch = master
[remote-push]
; List of configuration section names for git remote push plugin, e.g.:
; target = remote-push-trigger
target =
; git remote push trigger sample.
;[remote-push-trigger]
; Author commit email.
;commit_email = ahriman@localhost
; Author commit user.
;commit_user = ahriman
; Valid URL to push repository, e.g.:
; push_url = https://key:token@github.com/arcan1s/arcanisrepo.git
; Note, that more likely authentication must be enabled.
;push_url =
; Remote branch to push.
;push_branch = master
[report]
; List of configuration section names for reporting plugin.
target = console
; Console reporting trigger configuration sample.
[console]
; Trigger type name
;type = console
; Use utf8 symbols in output.
use_utf = yes
; Email reporting trigger configuration sample.
[email]
; Trigger type name
;type = email
; Optional URL to the repository homepage.
;homepage=
; SMTP server address.
;host =
; Prefix for packages links. Link to a package will be formed as link_path / filename.
;link_path =
; Skip report generation if no packages were updated.
;no_empty_report = yes
; SMTP password.
;password =
; SMTP server port.
;port =
; List of emails to receive the reports.
;receivers =
; Sender email.
;sender =
; SMTP server SSL mode, one of ssl, starttls, disabled.
;ssl = disabled
; Template name to be used.
template = email-index.jinja2
; Template name to be used for full packages list generation (same as HTML report).
;template_full =
; List of directories with templates.
templates = /usr/share/ahriman/templates
; SMTP user.
;user =
; HTML reporting trigger configuration sample.
[html]
; Trigger type name
;type = html
; Optional URL to the repository homepage.
;homepage=
; Prefix for packages links. Link to a package will be formed as link_path / filename.
;link_path =
; Output path for the HTML report.
;path =
; Template name to be used.
template = repo-index.jinja2
; List of directories with templates.
templates = /usr/share/ahriman/templates
; Remote service callback trigger configuration sample.
[remote-call]
; Trigger type name
;type = remote-call
; Call for AUR packages update.
;aur = no
; Call for local packages update.
;local = no
; Call for manual packages update.
;manual = no
; Wait until remote process will be terminated in seconds.
;wait_timeout = -1
; Telegram reporting trigger configuration sample.
[telegram]
; Trigger type name
;type = telegram
; Telegram bot API key.
;api_key =
; Telegram chat ID.
;chat_id =
; Optional URL to the repository homepage.
;homepage=
; Prefix for packages links. Link to a package will be formed as link_path / filename.
;link_path =
; Template name to be used.
template = telegram-index.jinja2
; Telegram specific template mode, one of MarkdownV2, HTML or Markdown.
;template_type = HTML
; List of directories with templates.
templates = /usr/share/ahriman/templates
; HTTP request timeout in seconds.
;timeout = 30
[upload]
; List of configuration section names for remote upload plugin, e.g.:
; target = rsync s3
target =
; GitHub upload trigger configuration sample.
[github]
; Trigger type name
;type = github
; GitHub repository owner username.
;owner =
; GitHub API key. public_repo (repo) scope is required.
;password =
; GitHub repository name.
;repository =
; HTTP request timeout in seconds.
;timeout = 30
; Include repository name to release name (recommended).
;use_full_release_name = no
; GitHub authentication username.
;username =
; Remote instance upload trigger configuration sample.
[remote-service]
; Trigger type name
;type = remote-service
; HTTP request timeout in seconds.
;timeout = 30
; rsync upload trigger configuration sample.
[rsync]
; Trigger type name
;type = rsync
; rsync command to run.
command = rsync --archive --compress --partial --delete
; Remote address and directory to sync, e.g.:
; remote = ahriman@10.0.0.1:/srv/repo
;remote =
; S3 upload trigger configuration sample.
[s3]
; Trigger type name
;type = s3
; AWS services access key.
;access_key =
; AWS S3 bucket name.
;bucket =
; Chunk size tp calculate ETags. Do not edit this value.
;chunk_size = 8388608
; Optional path prefix for stored objects.
;object_path =
; AWS S3 bucket region.
;region =
; AWS services secret key.
;secret_key =
; Remote worker configuration sample.
;[worker]
; Remotely reachable address of this instance, e.g.:
; address = http://10.0.0.1:8080
;address =
; Unique identifier of this instance if any.
;identifier =
; Maximum amount of time in seconds after which worker will be considered offline in case of no reports.
;time_to_live = 60

View File

@ -15,7 +15,7 @@
<div class="container"> <div class="container">
<nav class="navbar navbar-expand-lg"> <nav class="navbar navbar-expand-lg">
<div class="navbar-brand"><img src="/static/logo.svg" width="30" height="30" alt=""> ahriman</div> <div class="navbar-brand"><img src="/static/logo.svg" width="30" height="30" alt=""></div>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#repositories-navbar-supported-content" aria-controls="repositories-navbar-supported-content" aria-expanded="false" aria-label="Toggle navigation"> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#repositories-navbar-supported-content" aria-controls="repositories-navbar-supported-content" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span> <span class="navbar-toggler-icon"></span>
</button> </button>

View File

@ -38,10 +38,6 @@
<script> <script>
const keyImportModal = $("#key-import-modal"); const keyImportModal = $("#key-import-modal");
const keyImportForm = $("#key-import-form"); const keyImportForm = $("#key-import-form");
keyImportModal.on("hidden.bs.modal", () => {
keyImportBodyInput.text("");
keyImportForm.trigger("reset");
});
const keyImportBodyInput = $("#key-import-body-input"); const keyImportBodyInput = $("#key-import-body-input");
const keyImportCopyButton = $("#key-import-copy-button"); const keyImportCopyButton = $("#key-import-copy-button");
@ -90,4 +86,11 @@
}); });
} }
} }
$(() => {
keyImportModal.on("hidden.bs.modal", () => {
keyImportBodyInput.text("");
keyImportForm.trigger("reset");
});
});
</script> </script>

View File

@ -36,9 +36,6 @@
<script> <script>
const loginModal = $("#login-modal"); const loginModal = $("#login-modal");
const loginForm = $("#login-form"); const loginForm = $("#login-form");
loginModal.on("hidden.bs.modal", () => {
loginForm.trigger("reset");
});
const loginPasswordInput = $("#login-password"); const loginPasswordInput = $("#login-password");
const loginUsernameInput = $("#login-username"); const loginUsernameInput = $("#login-username");
@ -77,4 +74,10 @@
showHidePasswordButton.addClass("bi-eye"); showHidePasswordButton.addClass("bi-eye");
} }
} }
$(() => {
loginModal.on("hidden.bs.modal", () => {
loginForm.trigger("reset");
});
});
</script> </script>

View File

@ -43,41 +43,10 @@
<script> <script>
const packageAddModal = $("#package-add-modal"); const packageAddModal = $("#package-add-modal");
const packageAddForm = $("#package-add-form"); const packageAddForm = $("#package-add-form");
packageAddModal.on("shown.bs.modal", () => {
$(`#package-add-repository-input option[value="${repository.architecture}-${repository.repository}"]`).prop("selected", true);
});
packageAddModal.on("hidden.bs.modal", () => {
packageAddVariablesDiv.empty();
packageAddForm.trigger("reset");
});
const packageAddInput = $("#package-add-input"); const packageAddInput = $("#package-add-input");
const packageAddRepositoryInput = $("#package-add-repository-input"); const packageAddRepositoryInput = $("#package-add-repository-input");
const packageAddKnownPackagesList = $("#package-add-known-packages-dlist"); const packageAddKnownPackagesList = $("#package-add-known-packages-dlist");
packageAddInput.keyup(() => {
clearTimeout(packageAddInput.data("timeout"));
packageAddInput.data("timeout", setTimeout($.proxy(() => {
const value = packageAddInput.val();
if (value.length >= 3) {
$.ajax({
url: "/api/v1/service/search",
data: {"for": value},
type: "GET",
dataType: "json",
success: response => {
const options = response.map(pkg => {
const option = document.createElement("option");
option.value = pkg.package;
option.innerText = `${pkg.package} (${pkg.description})`;
return option;
});
packageAddKnownPackagesList.empty().append(options);
},
});
}
}, this), 500));
});
const packageAddVariablesDiv = $("#package-add-variables-div"); const packageAddVariablesDiv = $("#package-add-variables-div");
@ -156,4 +125,39 @@
doPackageAction("/api/v1/service/request", [packages], repository, onSuccess, onFailure, patches); doPackageAction("/api/v1/service/request", [packages], repository, onSuccess, onFailure, patches);
} }
} }
$(() => {
packageAddModal.on("shown.bs.modal", () => {
$(`#package-add-repository-input option[value="${repository.architecture}-${repository.repository}"]`).prop("selected", true);
});
packageAddModal.on("hidden.bs.modal", () => {
packageAddVariablesDiv.empty();
packageAddForm.trigger("reset");
});
packageAddInput.keyup(() => {
clearTimeout(packageAddInput.data("timeout"));
packageAddInput.data("timeout", setTimeout($.proxy(() => {
const value = packageAddInput.val();
if (value.length >= 3) {
$.ajax({
url: "/api/v1/service/search",
data: {"for": value},
type: "GET",
dataType: "json",
success: response => {
const options = response.map(pkg => {
const option = document.createElement("option");
option.value = pkg.package;
option.innerText = `${pkg.package} (${pkg.description})`;
return option;
});
packageAddKnownPackagesList.empty().append(options);
},
});
}
}, this), 500));
});
});
</script> </script>

View File

@ -72,26 +72,6 @@
const packageInfoModal = $("#package-info-modal"); const packageInfoModal = $("#package-info-modal");
const packageInfoModalHeader = $("#package-info-modal-header"); const packageInfoModalHeader = $("#package-info-modal-header");
const packageInfo = $("#package-info"); const packageInfo = $("#package-info");
packageInfoModal.on("hidden.bs.modal", () => {
packageInfoAurUrl.empty();
packageInfoDepends.empty();
packageInfoGroups.empty();
packageInfoLicenses.empty();
packageInfoPackager.empty();
packageInfoPackages.empty();
packageInfoUpstreamUrl.empty();
packageInfoVersion.empty();
packageInfoVariablesBlock.attr("hidden", true);
packageInfoVariablesDiv.empty();
packageInfoLogsInput.empty();
packageInfoChangesInput.empty();
packageInfoModal.trigger("reset");
hideInfoControls(true);
});
const packageInfoLogsInput = $("#package-info-logs-input"); const packageInfoLogsInput = $("#package-info-logs-input");
const packageInfoLogsCopyButton = $("#package-info-logs-copy-button"); const packageInfoLogsCopyButton = $("#package-info-logs-copy-button");
@ -309,4 +289,27 @@
if (isPackageBaseSet) packageInfoModal.modal("show"); if (isPackageBaseSet) packageInfoModal.modal("show");
} }
$(() => {
packageInfoModal.on("hidden.bs.modal", () => {
packageInfoAurUrl.empty();
packageInfoDepends.empty();
packageInfoGroups.empty();
packageInfoLicenses.empty();
packageInfoPackager.empty();
packageInfoPackages.empty();
packageInfoUpstreamUrl.empty();
packageInfoVersion.empty();
packageInfoVariablesBlock.attr("hidden", true);
packageInfoVariablesDiv.empty();
packageInfoLogsInput.empty();
packageInfoChangesInput.empty();
packageInfoModal.trigger("reset");
hideInfoControls(true);
});
});
</script> </script>

View File

@ -35,11 +35,6 @@
<script> <script>
const packageRebuildModal = $("#package-rebuild-modal"); const packageRebuildModal = $("#package-rebuild-modal");
const packageRebuildForm = $("#package-rebuild-form"); const packageRebuildForm = $("#package-rebuild-form");
packageRebuildModal.on("shown.bs.modal", () => {
$(`#package-rebuild-repository-input option[value="${repository.architecture}-${repository.repository}"]`).prop("selected", true);
});
packageRebuildModal.on("hidden.bs.modal", () => { packageRebuildForm.trigger("reset"); });
const packageRebuildDependencyInput = $("#package-rebuild-dependency-input"); const packageRebuildDependencyInput = $("#package-rebuild-dependency-input");
const packageRebuildRepositoryInput = $("#package-rebuild-repository-input"); const packageRebuildRepositoryInput = $("#package-rebuild-repository-input");
@ -54,4 +49,12 @@
doPackageAction("/api/v1/service/rebuild", [packages], repository, onSuccess, onFailure); doPackageAction("/api/v1/service/rebuild", [packages], repository, onSuccess, onFailure);
} }
} }
$(() => {
packageRebuildModal.on("shown.bs.modal", () => {
$(`#package-rebuild-repository-input option[value="${repository.architecture}-${repository.repository}"]`).prop("selected", true);
});
packageRebuildModal.on("hidden.bs.modal", () => { packageRebuildForm.trigger("reset"); });
});
</script> </script>

View File

@ -9,46 +9,8 @@
const packageInfoUpdateButton = $("#package-info-update-button"); const packageInfoUpdateButton = $("#package-info-update-button");
let repository = null; let repository = null;
$("#repositories a").on("click", (event) => {
const element = event.target;
repository = {
architecture: element.dataset.architecture,
repository: element.dataset.repository,
};
packageUpdateButton.html(`<i class="bi bi-play"></i> update<span class="d-none d-sm-inline"> ${safe(repository.repository)} (${safe(repository.architecture)})</span>`);
$(`#${element.id}`).tab("show");
reload();
});
const table = $("#packages"); const table = $("#packages");
table.on("check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table", () => {
packageRemoveButton.prop("disabled", !table.bootstrapTable("getSelections").length);
});
table.on("click-row.bs.table", (self, data, row, cell) => {
if (0 === cell || "base" === cell) {
const method = data[0] === true ? "uncheckBy" : "checkBy"; // fck javascript
table.bootstrapTable(method, {field: "id", values: [data.id]});
} else showPackageInfo(data.id);
});
table.on("created-controls.bs.table", () => {
const pickerInput = $(".bootstrap-table-filter-control-timestamp");
pickerInput.daterangepicker({
autoUpdateInput: false,
locale: {
cancelLabel: "Clear",
},
});
pickerInput.on("apply.daterangepicker", (event, picker) => {
pickerInput.val(`${picker.startDate.format("YYYY-MM-DD")} - ${picker.endDate.format("YYYY-MM-DD")}`);
table.bootstrapTable("triggerSearch");
});
pickerInput.on("cancel.daterangepicker", () => {
pickerInput.val("");
table.bootstrapTable("triggerSearch");
});
});
const statusBadge = $("#badge-status"); const statusBadge = $("#badge-status");
const versionBadge = $("#badge-version"); const versionBadge = $("#badge-version");
@ -221,6 +183,46 @@
} }
$(() => { $(() => {
$("#repositories a").on("click", event => {
const element = event.target;
repository = {
architecture: element.dataset.architecture,
repository: element.dataset.repository,
};
packageUpdateButton.html(`<i class="bi bi-play"></i> update<span class="d-none d-sm-inline"> ${safe(repository.repository)} (${safe(repository.architecture)})</span>`);
$(`#${element.id}`).tab("show");
reload();
});
table.on("check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table", () => {
packageRemoveButton.prop("disabled", !table.bootstrapTable("getSelections").length);
});
table.on("click-row.bs.table", (self, data, row, cell) => {
if (0 === cell || "base" === cell) {
const method = data[0] === true ? "uncheckBy" : "checkBy"; // fck javascript
table.bootstrapTable(method, {field: "id", values: [data.id]});
} else showPackageInfo(data.id);
});
table.on("created-controls.bs.table", () => {
const pickerInput = $(".bootstrap-table-filter-control-timestamp");
pickerInput.daterangepicker({
autoUpdateInput: false,
locale: {
cancelLabel: "Clear",
},
});
pickerInput.on("apply.daterangepicker", (event, picker) => {
pickerInput.val(`${picker.startDate.format("YYYY-MM-DD")} - ${picker.endDate.format("YYYY-MM-DD")}`);
table.bootstrapTable("triggerSearch");
});
pickerInput.on("cancel.daterangepicker", () => {
pickerInput.val("");
table.bootstrapTable("triggerSearch");
});
});
table.bootstrapTable({}); table.bootstrapTable({});
statusBadge.popover(); statusBadge.popover();
selectRepository(); selectRepository();

View File

@ -102,25 +102,6 @@ SigLevel = Database{% if has_repo_signed %}Required{% else %}Never{% endif %} Pa
<script> <script>
const table = $("#packages"); const table = $("#packages");
table.on("created-controls.bs.table", () => {
const pickerInput = $(".bootstrap-table-filter-control-timestamp");
pickerInput.daterangepicker({
autoUpdateInput: false,
locale: {
cancelLabel: "Clear",
},
});
pickerInput.on("apply.daterangepicker", (event, picker) => {
pickerInput.val(`${picker.startDate.format("YYYY-MM-DD")} - ${picker.endDate.format("YYYY-MM-DD")}`);
table.bootstrapTable("triggerSearch");
});
pickerInput.on("cancel.daterangepicker", () => {
pickerInput.val("");
table.bootstrapTable("triggerSearch");
});
});
const pacmanConf = $("#pacman-conf"); const pacmanConf = $("#pacman-conf");
const pacmanConfCopyButton = $("#copy-btn"); const pacmanConfCopyButton = $("#copy-btn");
@ -141,6 +122,28 @@ SigLevel = Database{% if has_repo_signed %}Required{% else %}Never{% endif %} Pa
function filterListLicenses() { function filterListLicenses() {
return extractDataList(table.bootstrapTable("getData"), "licenses"); return extractDataList(table.bootstrapTable("getData"), "licenses");
} }
$(() => {
table.on("created-controls.bs.table", () => {
const pickerInput = $(".bootstrap-table-filter-control-timestamp");
pickerInput.daterangepicker({
autoUpdateInput: false,
locale: {
cancelLabel: "Clear",
},
});
pickerInput.on("apply.daterangepicker", (event, picker) => {
pickerInput.val(`${picker.startDate.format("YYYY-MM-DD")} - ${picker.endDate.format("YYYY-MM-DD")}`);
table.bootstrapTable("triggerSearch");
});
pickerInput.on("cancel.daterangepicker", () => {
pickerInput.val("");
table.bootstrapTable("triggerSearch");
});
});
});
</script> </script>
</body> </body>

View File

@ -584,7 +584,7 @@ _set_new_action() {
current_action_nargs=1 current_action_nargs=1
fi fi
current_action_args_start_index=$(( $word_index + 1 )) current_action_args_start_index=$(( $word_index + 1 - $pos_only ))
current_action_is_positional=$2 current_action_is_positional=$2
} }
@ -611,6 +611,7 @@ _shtab_ahriman() {
local prefix=_shtab_ahriman local prefix=_shtab_ahriman
local word_index=0 local word_index=0
local pos_only=0 # "--" delimeter not encountered yet
_set_parser_defaults _set_parser_defaults
word_index=1 word_index=1
@ -619,6 +620,7 @@ _shtab_ahriman() {
while [ $word_index -ne $COMP_CWORD ]; do while [ $word_index -ne $COMP_CWORD ]; do
local this_word="${COMP_WORDS[$word_index]}" local this_word="${COMP_WORDS[$word_index]}"
if [[ $pos_only = 1 || " $this_word " != " -- " ]]; then
if [[ -n $sub_parsers && " ${sub_parsers[@]} " == *" ${this_word} "* ]]; then if [[ -n $sub_parsers && " ${sub_parsers[@]} " == *" ${this_word} "* ]]; then
# valid subcommand: add it to the prefix & reset the current action # valid subcommand: add it to the prefix & reset the current action
prefix="${prefix}_$(_shtab_replace_nonword $this_word)" prefix="${prefix}_$(_shtab_replace_nonword $this_word)"
@ -635,18 +637,21 @@ _shtab_ahriman() {
if [[ "$current_action_nargs" != "*" ]] && \ if [[ "$current_action_nargs" != "*" ]] && \
[[ "$current_action_nargs" != "+" ]] && \ [[ "$current_action_nargs" != "+" ]] && \
[[ "$current_action_nargs" != *"..." ]] && \ [[ "$current_action_nargs" != *"..." ]] && \
(( $word_index + 1 - $current_action_args_start_index >= \ (( $word_index + 1 - $current_action_args_start_index - $pos_only >= \
$current_action_nargs )); then $current_action_nargs )); then
$current_action_is_positional && let "completed_positional_actions += 1" $current_action_is_positional && let "completed_positional_actions += 1"
_set_new_action "pos_${completed_positional_actions}" true _set_new_action "pos_${completed_positional_actions}" true
fi fi
else
pos_only=1 # "--" delimeter encountered
fi
let "word_index+=1" let "word_index+=1"
done done
# Generate the completions # Generate the completions
if [[ "${completing_word}" == -* ]]; then if [[ $pos_only = 0 && "${completing_word}" == -* ]]; then
# optional argument started: use option strings # optional argument started: use option strings
COMPREPLY=( $(compgen -W "${current_option_strings[*]}" -- "${completing_word}") ) COMPREPLY=( $(compgen -W "${current_option_strings[*]}" -- "${completing_word}") )
else else

View File

@ -1,4 +1,4 @@
.TH AHRIMAN "1" "2024\-01\-02" "ahriman" "Generated Python Manual" .TH AHRIMAN "1" "2024\-04\-04" "ahriman" "Generated Python Manual"
.SH NAME .SH NAME
ahriman ahriman
.SH SYNOPSIS .SH SYNOPSIS

View File

@ -736,4 +736,12 @@ _shtab_ahriman() {
typeset -A opt_args typeset -A opt_args
if [[ $zsh_eval_context[-1] == eval ]]; then
# eval/source/. command, register function for later
compdef _shtab_ahriman -N ahriman
else
# autoload from fpath, call function directly
_shtab_ahriman "$@" _shtab_ahriman "$@"
fi

View File

@ -25,19 +25,19 @@ from pylint.lint import PyLinter
from typing import Any from typing import Any
class MethodTypeOrder(StrEnum): class MethodType(StrEnum):
""" """
method type enumeration method type enumeration
Attributes: Attributes:
Class(MethodTypeOrder): (class attribute) class method Class(MethodType): (class attribute) class method
Delete(MethodTypeOrder): (class attribute) destructor-like methods Delete(MethodType): (class attribute) destructor-like methods
Init(MethodTypeOrder): (class attribute) initialization method Init(MethodType): (class attribute) initialization method
Magic(MethodTypeOrder): (class attribute) other magical methods Magic(MethodType): (class attribute) other magical methods
New(MethodTypeOrder): (class attribute) constructor method New(MethodType): (class attribute) constructor method
Normal(MethodTypeOrder): (class attribute) usual method Normal(MethodType): (class attribute) usual method
Property(MethodTypeOrder): (class attribute) property method Property(MethodType): (class attribute) property method
Static(MethodTypeOrder): (class attribute) static method Static(MethodType): (class attribute) static method
""" """
Class = "classmethod" Class = "classmethod"
@ -59,20 +59,20 @@ class DefinitionOrder(BaseRawFileChecker):
""" """
DECORATED_METHODS_ORDER = { DECORATED_METHODS_ORDER = {
"cached_property": MethodTypeOrder.Property, "cached_property": MethodType.Property,
"classmethod": MethodTypeOrder.Class, "classmethod": MethodType.Class,
"property": MethodTypeOrder.Property, "property": MethodType.Property,
"staticmethod": MethodTypeOrder.Static, "staticmethod": MethodType.Static,
} }
name = "method-ordering"
msgs = { msgs = {
"W6001": ( "W6001": (
"Invalid method order %s, expected %s", "Invalid method order %s, expected %s",
"methods-out-of-order", "methods-out-of-order",
"Methods are defined out of recommended order.", "Methods are defined out of recommended order.",
) ),
} }
name = "method-ordering"
options = ( options = (
( (
"method-type-order", "method-type-order",
@ -114,7 +114,7 @@ class DefinitionOrder(BaseRawFileChecker):
return list(filter(is_defined_function, source)) return list(filter(is_defined_function, source))
@staticmethod @staticmethod
def resolve_type(function: nodes.FunctionDef) -> MethodTypeOrder: def resolve_type(function: nodes.FunctionDef) -> MethodType:
""" """
resolve type of the function resolve type of the function
@ -122,15 +122,15 @@ class DefinitionOrder(BaseRawFileChecker):
function(nodes.FunctionDef): function definition function(nodes.FunctionDef): function definition
Returns: Returns:
MethodTypeOrder: resolved function type MethodType: resolved function type
""" """
# init methods # init methods
if function.name in ("__init__", "__post_init__"): if function.name in ("__init__", "__post_init__"):
return MethodTypeOrder.Init return MethodType.Init
if function.name in ("__new__",): if function.name in ("__new__",):
return MethodTypeOrder.New return MethodType.New
if function.name in ("__del__",): if function.name in ("__del__",):
return MethodTypeOrder.Delete return MethodType.Delete
# decorated methods # decorated methods
decorators = [] decorators = []
@ -142,10 +142,10 @@ class DefinitionOrder(BaseRawFileChecker):
# magic methods # magic methods
if function.name.startswith("__") and function.name.endswith("__"): if function.name.startswith("__") and function.name.endswith("__"):
return MethodTypeOrder.Magic return MethodType.Magic
# normal method # normal method
return MethodTypeOrder.Normal return MethodType.Normal
def check_class(self, clazz: nodes.ClassDef) -> None: def check_class(self, clazz: nodes.ClassDef) -> None:
""" """
@ -184,7 +184,7 @@ class DefinitionOrder(BaseRawFileChecker):
try: try:
function_type_index = self.linter.config.method_type_order.index(function_type) function_type_index = self.linter.config.method_type_order.index(function_type)
except ValueError: except ValueError:
function_type_index = 10 # not in the list function_type_index = len(self.linter.config.method_type_order) # not in the list
return function_type_index, function.name return function_type_index, function.name

View File

@ -0,0 +1,196 @@
#
# Copyright (c) 2021-2023 ahriman team.
#
# This file is part of ahriman
# (see https://github.com/arcan1s/ahriman).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
from astroid import nodes
from collections.abc import Iterable
from enum import StrEnum
from pylint.checkers import BaseRawFileChecker
from pylint.lint import PyLinter
from typing import Any
class ImportType(StrEnum):
"""
import type enumeration
Attributes:
Package(MethodTypeOrder): (class attribute) package import
PackageFrom(MethodTypeOrder): (class attribute) package import, from clause
System(ImportType): (class attribute) system installed packages
SystemFrom(MethodTypeOrder): (class attribute) system installed packages, from clause
"""
Package = "package"
PackageFrom = "package-from"
System = "system"
SystemFrom = "system-from"
class ImportOrder(BaseRawFileChecker):
"""
check if imports are defined in recommended order
"""
msgs = {
"W6002": (
"Invalid import order %s, expected before %s",
"imports-out-of-order",
"Imports are defined out of recommended order.",
),
"W6003": (
"Import contains more than one package: %s",
"multiple-package-imports",
"Multiple package imports are not allowed.",
),
"W6004": (
"Invalid from import order %s, expected %s",
"from-imports-out-of-order",
"From imports are defined out of recommended order.",
),
}
name = "import-ordering"
options = (
(
"import-type-order",
{
"default": [
"system",
"system-from",
"package",
"package-from",
],
"type": "csv",
"metavar": "<comma-separated types>",
"help": "Import types order to check.",
},
),
(
"root-module",
{
"default": "ahriman",
"type": "string",
"help": "Root module name",
}
)
)
@staticmethod
def imports(source: Iterable[Any], start_lineno: int = 0) -> list[nodes.Import | nodes.ImportFrom]:
"""
extract import nodes from list of raw nodes
Args:
source(Iterable[Any]): all available nodes
start_lineno(int, optional): minimal allowed line number (Default value = 0)
Returns:
list[nodes.Import | nodes.ImportFrom]: list of import nodes
"""
def is_defined_import(imports: Any) -> bool:
return isinstance(imports, (nodes.Import, nodes.ImportFrom)) \
and imports.lineno is not None \
and imports.lineno >= start_lineno
return list(filter(is_defined_import, source))
def check_from_imports(self, imports: nodes.ImportFrom) -> None:
"""
check import from statement
Args:
imports(nodes.ImportFrom): import from node
"""
imported = [names for names, _ in imports.names]
for real, expected in zip(imported, sorted(imported)):
if real == expected:
continue
self.add_message("from-imports-out-of-order", line=imports.lineno, args=(real, expected))
break
def check_imports(self, imports: list[nodes.Import | nodes.ImportFrom], root_package: str) -> None:
"""
check imports
Args:
imports(list[nodes.Import | nodes.ImportFrom]): list of imports in their defined order
root_package(str): root package name
"""
last_statement: tuple[int, str] | None = None
for statement in imports:
# define types and perform specific checks
if isinstance(statement, nodes.ImportFrom):
import_name = statement.modname
root, *_ = import_name.split(".", maxsplit=1)
import_type = ImportType.PackageFrom if root_package == root else ImportType.SystemFrom
# check from import itself
self.check_from_imports(statement)
else:
import_name = next(name for name, _ in statement.names)
root, *_ = import_name.split(".", maxsplit=1)[0]
import_type = ImportType.Package if root_package == root else ImportType.System
# check import itself
self.check_package_imports(statement)
# extract index
try:
import_type_index = self.linter.config.import_type_order.index(import_type)
except ValueError:
import_type_index = len(self.linter.config.import_type_order)
# check ordering if possible
if last_statement is not None:
_, last_statement_name = last_statement
if last_statement > (import_type_index, import_name):
self.add_message("imports-out-of-order", line=statement.lineno,
args=(import_name, last_statement_name))
# update the last value
last_statement = import_type_index, import_name
def check_package_imports(self, imports: nodes.Import) -> None:
"""
check package import
Args:
imports(nodes.Import): package import node
"""
if len(imports.names) != 1:
self.add_message("multiple-package-imports", line=imports.lineno, args=(imports.names,))
def process_module(self, node: nodes.Module) -> None:
"""
process module
Args:
node(nodes.Module): module node to check
"""
root_module, *_ = node.qname().split(".")
self.check_imports(self.imports(node.values()), root_module)
def register(linter: PyLinter) -> None:
"""
register custom checker
Args:
linter(PyLinter): linter in which checker should be registered
"""
linter.register_checker(ImportOrder(linter))

View File

@ -8,7 +8,8 @@ name = "ahriman"
description = "ArcH linux ReposItory MANager" description = "ArcH linux ReposItory MANager"
readme = "README.md" readme = "README.md"
requires-python = ">=3.11" # Actually we are using features from the latest python, however, ubuntu, which is used for CI doesn't have it
requires-python = ">=3"
license = {file = "COPYING"} license = {file = "COPYING"}
authors = [ authors = [

View File

@ -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.12.2" __version__ = "2.13.5"

View File

@ -71,7 +71,7 @@ def _parser() -> argparse.ArgumentParser:
fromfile_prefix_chars="@", formatter_class=_formatter) fromfile_prefix_chars="@", formatter_class=_formatter)
parser.add_argument("-a", "--architecture", help="filter by target architecture") parser.add_argument("-a", "--architecture", help="filter by target architecture")
parser.add_argument("-c", "--configuration", help="configuration path", type=Path, parser.add_argument("-c", "--configuration", help="configuration path", type=Path,
default=Path("/etc") / "ahriman.ini") default=Path("/") / "etc" / "ahriman.ini")
parser.add_argument("--force", help="force run, remove file lock", action="store_true") parser.add_argument("--force", help="force run, remove file lock", action="store_true")
parser.add_argument("-l", "--lock", help="lock file", type=Path, parser.add_argument("-l", "--lock", help="lock file", type=Path,
default=Path(tempfile.gettempdir()) / "ahriman.lock") default=Path(tempfile.gettempdir()) / "ahriman.lock")
@ -999,7 +999,7 @@ def _set_service_setup_parser(root: SubParserAction) -> argparse.ArgumentParser:
formatter_class=_formatter) formatter_class=_formatter)
parser.add_argument("--build-as-user", help="force makepkg user to the specific one") parser.add_argument("--build-as-user", help="force makepkg user to the specific one")
parser.add_argument("--from-configuration", help="path to default devtools pacman configuration", parser.add_argument("--from-configuration", help="path to default devtools pacman configuration",
type=Path, default=Path("/usr") / "share" / "devtools" / "pacman.conf.d" / "extra.conf") type=Path, default=Path("/") / "usr" / "share" / "devtools" / "pacman.conf.d" / "extra.conf")
parser.add_argument("--generate-salt", help="generate salt for user passwords", parser.add_argument("--generate-salt", help="generate salt for user passwords",
action=argparse.BooleanOptionalAction, default=False) action=argparse.BooleanOptionalAction, default=False)
parser.add_argument("--makeflags-jobs", help="append MAKEFLAGS variable with parallelism set to number of cores", parser.add_argument("--makeflags-jobs", help="append MAKEFLAGS variable with parallelism set to number of cores",

View File

@ -163,8 +163,8 @@ class ApplicationRepository(ApplicationProperties):
built_packages = self.repository.packages_built() built_packages = self.repository.packages_built()
if built_packages: # speedup a bit if built_packages: # speedup a bit
build_result = self.repository.process_update(built_packages, packagers) build_result = self.repository.process_update(built_packages, packagers)
self.on_result(build_result)
result.merge(build_result) result.merge(build_result)
self.on_result(result.merge(build_result))
builder = Updater.load(self.repository_id, self.configuration, self.repository) builder = Updater.load(self.repository_id, self.configuration, self.repository)
@ -173,7 +173,8 @@ class ApplicationRepository(ApplicationProperties):
for num, partition in enumerate(partitions): for num, partition in enumerate(partitions):
self.logger.info("processing chunk #%i %s", num, [package.base for package in partition]) self.logger.info("processing chunk #%i %s", num, [package.base for package in partition])
build_result = builder.update(partition, packagers, bump_pkgrel=bump_pkgrel) build_result = builder.update(partition, packagers, bump_pkgrel=bump_pkgrel)
self.on_result(result.merge(build_result)) self.on_result(build_result)
result.merge(build_result)
return result return result

View File

@ -17,14 +17,13 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
from ahriman.application.handlers.handler import Handler
from ahriman.application.handlers.add import Add from ahriman.application.handlers.add import Add
from ahriman.application.handlers.backup import Backup from ahriman.application.handlers.backup import Backup
from ahriman.application.handlers.change import Change from ahriman.application.handlers.change import Change
from ahriman.application.handlers.clean import Clean from ahriman.application.handlers.clean import Clean
from ahriman.application.handlers.daemon import Daemon from ahriman.application.handlers.daemon import Daemon
from ahriman.application.handlers.dump import Dump from ahriman.application.handlers.dump import Dump
from ahriman.application.handlers.handler import Handler
from ahriman.application.handlers.help import Help from ahriman.application.handlers.help import Help
from ahriman.application.handlers.key_import import KeyImport from ahriman.application.handlers.key_import import KeyImport
from ahriman.application.handlers.patch import Patch from ahriman.application.handlers.patch import Patch

View File

@ -20,7 +20,7 @@
import argparse import argparse
from ahriman.application.application import Application from ahriman.application.application import Application
from ahriman.application.handlers import Handler from ahriman.application.handlers.handler import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.models.packagers import Packagers from ahriman.models.packagers import Packagers
from ahriman.models.pkgbuild_patch import PkgbuildPatch from ahriman.models.pkgbuild_patch import PkgbuildPatch

View File

@ -23,7 +23,7 @@ import pwd
from pathlib import Path from pathlib import Path
from tarfile import TarFile from tarfile import TarFile
from ahriman.application.handlers import Handler from ahriman.application.handlers.handler import Handler
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.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId

View File

@ -20,7 +20,7 @@
import argparse import argparse
from ahriman.application.application import Application from ahriman.application.application import Application
from ahriman.application.handlers import Handler from ahriman.application.handlers.handler import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.formatters import ChangesPrinter from ahriman.core.formatters import ChangesPrinter
from ahriman.models.action import Action from ahriman.models.action import Action

View File

@ -20,7 +20,7 @@
import argparse import argparse
from ahriman.application.application import Application from ahriman.application.application import Application
from ahriman.application.handlers import Handler from ahriman.application.handlers.handler import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId

View File

@ -21,7 +21,7 @@ import argparse
from ahriman.application.application import Application from ahriman.application.application import Application
from ahriman.application.application.updates_iterator import FixedUpdatesIterator, UpdatesIterator from ahriman.application.application.updates_iterator import FixedUpdatesIterator, UpdatesIterator
from ahriman.application.handlers import Handler from ahriman.application.handlers.handler import Handler
from ahriman.application.handlers.update import Update from ahriman.application.handlers.update import Update
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId

View File

@ -19,7 +19,7 @@
# #
import argparse import argparse
from ahriman.application.handlers import Handler from ahriman.application.handlers.handler import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.formatters import ConfigurationPathsPrinter, ConfigurationPrinter, StringPrinter from ahriman.core.formatters import ConfigurationPathsPrinter, ConfigurationPrinter, StringPrinter
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId

View File

@ -19,7 +19,7 @@
# #
import argparse import argparse
from ahriman.application.handlers import Handler from ahriman.application.handlers.handler import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId

View File

@ -20,7 +20,7 @@
import argparse import argparse
from ahriman.application.application import Application from ahriman.application.application import Application
from ahriman.application.handlers import Handler from ahriman.application.handlers.handler import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId

View File

@ -23,7 +23,7 @@ import sys
from pathlib import Path from pathlib import Path
from ahriman.application.application import Application from ahriman.application.application import Application
from ahriman.application.handlers import Handler from ahriman.application.handlers.handler import Handler
from ahriman.core.build_tools.sources import Sources from ahriman.core.build_tools.sources import Sources
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.formatters import PatchPrinter from ahriman.core.formatters import PatchPrinter

View File

@ -20,7 +20,7 @@
import argparse import argparse
from ahriman.application.application import Application from ahriman.application.application import Application
from ahriman.application.handlers import Handler from ahriman.application.handlers.handler import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.models.build_status import BuildStatusEnum from ahriman.models.build_status import BuildStatusEnum
from ahriman.models.package import Package from ahriman.models.package import Package

View File

@ -20,7 +20,7 @@
import argparse import argparse
from ahriman.application.application import Application from ahriman.application.application import Application
from ahriman.application.handlers import Handler from ahriman.application.handlers.handler import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId

View File

@ -20,7 +20,7 @@
import argparse import argparse
from ahriman.application.application import Application from ahriman.application.application import Application
from ahriman.application.handlers import Handler from ahriman.application.handlers.handler import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.formatters import StringPrinter from ahriman.core.formatters import StringPrinter
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId

View File

@ -19,7 +19,7 @@
# #
import argparse import argparse
from ahriman.application.handlers import Handler from ahriman.application.handlers.handler import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.formatters import RepositoryPrinter from ahriman.core.formatters import RepositoryPrinter
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId

View File

@ -21,7 +21,7 @@ import argparse
from tarfile import TarFile from tarfile import TarFile
from ahriman.application.handlers import Handler from ahriman.application.handlers.handler import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId

View File

@ -20,7 +20,7 @@
import argparse import argparse
import shlex import shlex
from ahriman.application.handlers import Handler from ahriman.application.handlers.handler import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId

View File

@ -19,10 +19,10 @@
# #
import argparse import argparse
from dataclasses import fields
from collections.abc import Callable, Iterable from collections.abc import Callable, Iterable
from dataclasses import fields
from ahriman.application.handlers import Handler from ahriman.application.handlers.handler import Handler
from ahriman.core.alpm.remote import AUR, Official from ahriman.core.alpm.remote import AUR, Official
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.exceptions import OptionError from ahriman.core.exceptions import OptionError

View File

@ -20,7 +20,7 @@
import argparse import argparse
from ahriman import __version__ from ahriman import __version__
from ahriman.application.handlers import Handler from ahriman.application.handlers.handler import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.formatters import UpdatePrinter from ahriman.core.formatters import UpdatePrinter
from ahriman.models.package import Package from ahriman.models.package import Package

View File

@ -24,7 +24,7 @@ from pwd import getpwuid
from urllib.parse import quote_plus as urlencode from urllib.parse import quote_plus as urlencode
from ahriman.application.application import Application from ahriman.application.application import Application
from ahriman.application.handlers import Handler from ahriman.application.handlers.handler import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.exceptions import MissingArchitectureError from ahriman.core.exceptions import MissingArchitectureError
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId
@ -44,9 +44,9 @@ class Setup(Handler):
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io
ARCHBUILD_COMMAND_PATH = Path("/usr") / "bin" / "archbuild" ARCHBUILD_COMMAND_PATH = Path("/") / "usr" / "bin" / "archbuild"
MIRRORLIST_PATH = Path("/etc") / "pacman.d" / "mirrorlist" MIRRORLIST_PATH = Path("/") / "etc" / "pacman.d" / "mirrorlist"
SUDOERS_DIR_PATH = Path("/etc") / "sudoers.d" SUDOERS_DIR_PATH = Path("/") / "etc" / "sudoers.d"
@classmethod @classmethod
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *, def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,

View File

@ -23,7 +23,7 @@ import sys
from pathlib import Path from pathlib import Path
from ahriman.application.handlers import Handler from ahriman.application.handlers.handler import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.formatters import StringPrinter from ahriman.core.formatters import StringPrinter
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId

View File

@ -20,7 +20,7 @@
import argparse import argparse
from ahriman.application.application import Application from ahriman.application.application import Application
from ahriman.application.handlers import Handler from ahriman.application.handlers.handler import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId

View File

@ -22,7 +22,7 @@ import argparse
from collections.abc import Callable from collections.abc import Callable
from ahriman.application.application import Application from ahriman.application.application import Application
from ahriman.application.handlers import Handler from ahriman.application.handlers.handler import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.formatters import PackagePrinter, StatusPrinter from ahriman.core.formatters import PackagePrinter, StatusPrinter
from ahriman.models.build_status import BuildStatus from ahriman.models.build_status import BuildStatus

View File

@ -20,7 +20,7 @@
import argparse import argparse
from ahriman.application.application import Application from ahriman.application.application import Application
from ahriman.application.handlers import Handler from ahriman.application.handlers.handler import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.models.action import Action from ahriman.models.action import Action
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId

View File

@ -20,7 +20,7 @@
import argparse import argparse
from ahriman.application.application import Application from ahriman.application.application import Application
from ahriman.application.handlers import Handler from ahriman.application.handlers.handler import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.formatters import StringPrinter, TreePrinter from ahriman.core.formatters import StringPrinter, TreePrinter
from ahriman.core.tree import Tree from ahriman.core.tree import Tree

View File

@ -19,7 +19,7 @@
# #
import argparse import argparse
from ahriman.application.handlers import Handler from ahriman.application.handlers.handler import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId
from ahriman.models.repository_paths import RepositoryPaths from ahriman.models.repository_paths import RepositoryPaths

View File

@ -20,7 +20,7 @@
import argparse import argparse
from ahriman.application.application import Application from ahriman.application.application import Application
from ahriman.application.handlers import Handler from ahriman.application.handlers.handler import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId
from ahriman.models.result import Result from ahriman.models.result import Result

View File

@ -19,7 +19,7 @@
# #
import argparse import argparse
from ahriman.application.handlers import Handler from ahriman.application.handlers.handler import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.formatters import StringPrinter from ahriman.core.formatters import StringPrinter
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId

View File

@ -22,7 +22,7 @@ import argparse
from collections.abc import Callable from collections.abc import Callable
from ahriman.application.application import Application from ahriman.application.application import Application
from ahriman.application.handlers import Handler from ahriman.application.handlers.handler import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.models.packagers import Packagers from ahriman.models.packagers import Packagers
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId

View File

@ -20,7 +20,7 @@
import argparse import argparse
import getpass import getpass
from ahriman.application.handlers import Handler from ahriman.application.handlers.handler import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.database import SQLite from ahriman.core.database import SQLite
from ahriman.core.exceptions import PasswordError from ahriman.core.exceptions import PasswordError

View File

@ -22,7 +22,7 @@ import copy
from typing import Any from typing import Any
from ahriman.application.handlers import Handler from ahriman.application.handlers.handler import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.configuration.schema import CONFIGURATION_SCHEMA, ConfigurationSchema from ahriman.core.configuration.schema import CONFIGURATION_SCHEMA, ConfigurationSchema
from ahriman.core.configuration.validator import Validator from ahriman.core.configuration.validator import Validator

View File

@ -25,7 +25,7 @@ from collections.abc import Generator
from importlib import metadata from importlib import metadata
from ahriman import __version__ from ahriman import __version__
from ahriman.application.handlers import Handler from ahriman.application.handlers.handler import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.formatters import VersionPrinter from ahriman.core.formatters import VersionPrinter
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId

View File

@ -21,7 +21,7 @@ import argparse
from collections.abc import Generator from collections.abc import Generator
from ahriman.application.handlers import Handler from ahriman.application.handlers.handler import Handler
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.spawn import Spawn from ahriman.core.spawn import Spawn
from ahriman.core.triggers import TriggerLoader from ahriman.core.triggers import TriggerLoader

View File

@ -17,8 +17,7 @@
# 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.alpm.remote.remote import Remote
from ahriman.core.alpm.remote.aur import AUR from ahriman.core.alpm.remote.aur import AUR
from ahriman.core.alpm.remote.official import Official from ahriman.core.alpm.remote.official import Official
from ahriman.core.alpm.remote.official_syncdb import OfficialSyncdb from ahriman.core.alpm.remote.official_syncdb import OfficialSyncdb
from ahriman.core.alpm.remote.remote import Remote

View File

@ -20,7 +20,7 @@
from typing import Any from typing import Any
from ahriman.core.alpm.pacman import Pacman from ahriman.core.alpm.pacman import Pacman
from ahriman.core.alpm.remote import Remote from ahriman.core.alpm.remote.remote import Remote
from ahriman.core.exceptions import PackageInfoError, UnknownPackageError from ahriman.core.exceptions import PackageInfoError, UnknownPackageError
from ahriman.models.aur_package import AURPackage from ahriman.models.aur_package import AURPackage

View File

@ -20,7 +20,7 @@
from typing import Any from typing import Any
from ahriman.core.alpm.pacman import Pacman from ahriman.core.alpm.pacman import Pacman
from ahriman.core.alpm.remote import Remote from ahriman.core.alpm.remote.remote import Remote
from ahriman.core.exceptions import PackageInfoError, UnknownPackageError from ahriman.core.exceptions import PackageInfoError, UnknownPackageError
from ahriman.models.aur_package import AURPackage from ahriman.models.aur_package import AURPackage

View File

@ -18,7 +18,7 @@
# 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.alpm.pacman import Pacman from ahriman.core.alpm.pacman import Pacman
from ahriman.core.alpm.remote import Official from ahriman.core.alpm.remote.official import Official
from ahriman.core.exceptions import UnknownPackageError from ahriman.core.exceptions import UnknownPackageError
from ahriman.models.aur_package import AURPackage from ahriman.models.aur_package import AURPackage

View File

@ -68,7 +68,7 @@ class Repo(LazyLogging):
path(Path): path to archive to add path(Path): path to archive to add
""" """
check_output( check_output(
"repo-add", *self.sign_args, "-R", str(self.repo_path), str(path), "repo-add", *self.sign_args, "--remove", str(self.repo_path), str(path),
exception=BuildError.from_process(path.name), exception=BuildError.from_process(path.name),
cwd=self.paths.repository, cwd=self.paths.repository,
logger=self.logger, logger=self.logger,
@ -78,8 +78,13 @@ class Repo(LazyLogging):
""" """
create empty repository database. It just calls add with empty arguments create empty repository database. It just calls add with empty arguments
""" """
check_output("repo-add", *self.sign_args, str(self.repo_path), # since pacman-6.1.0 repo-add doesn't create empty database in case if no packages supplied
cwd=self.paths.repository, logger=self.logger, user=self.uid) # this code creates empty files instead
if self.repo_path.exists():
return # database is already created, skip this part
self.repo_path.touch(exist_ok=True)
(self.paths.repository / f"{self.name}.db").symlink_to(self.repo_path)
def remove(self, package: str, filename: Path) -> None: def remove(self, package: str, filename: Path) -> None:
""" """

View File

@ -38,6 +38,7 @@ class Task(LazyLogging):
archbuild_flags(list[str]): command flags for archbuild command archbuild_flags(list[str]): command flags for archbuild command
architecture(str): repository architecture architecture(str): repository architecture
build_command(str): build command build_command(str): build command
include_debug_packages(bool): whether to include debug packages or not
makechrootpkg_flags(list[str]): command flags for makechrootpkg command makechrootpkg_flags(list[str]): command flags for makechrootpkg command
makepkg_flags(list[str]): command flags for makepkg command makepkg_flags(list[str]): command flags for makepkg command
package(Package): package definitions package(Package): package definitions
@ -63,6 +64,7 @@ class Task(LazyLogging):
self.archbuild_flags = configuration.getlist("build", "archbuild_flags", fallback=[]) self.archbuild_flags = configuration.getlist("build", "archbuild_flags", fallback=[])
self.build_command = configuration.get("build", "build_command") self.build_command = configuration.get("build", "build_command")
self.include_debug_packages = configuration.getboolean("build", "include_debug_packages", fallback=True)
self.makepkg_flags = configuration.getlist("build", "makepkg_flags", fallback=[]) self.makepkg_flags = configuration.getlist("build", "makepkg_flags", fallback=[])
self.makechrootpkg_flags = configuration.getlist("build", "makechrootpkg_flags", fallback=[]) self.makechrootpkg_flags = configuration.getlist("build", "makechrootpkg_flags", fallback=[])
@ -99,15 +101,20 @@ class Task(LazyLogging):
environment=environment, environment=environment,
) )
# well it is not actually correct, but we can deal with it package_list_command = ["makepkg", "--packagelist"]
if not self.include_debug_packages:
package_list_command.append("OPTIONS=(!debug)") # disable debug flag manually
packages = check_output( packages = check_output(
"makepkg", "--packagelist", *package_list_command,
exception=BuildError.from_process(self.package.base), exception=BuildError.from_process(self.package.base),
cwd=sources_dir, cwd=sources_dir,
logger=self.logger, logger=self.logger,
environment=environment, environment=environment,
).splitlines() ).splitlines()
return [Path(package) for package in packages] # some dirty magic here
# the filter is applied in order to make sure that result will only contain packages which were actually built
# e.g. in some cases packagelist command produces debug packages which were not actually built
return list(filter(lambda path: path.is_file(), map(Path, packages)))
def init(self, sources_dir: Path, database: SQLite, local_version: str | None) -> str | None: def init(self, sources_dir: Path, database: SQLite, local_version: str | None) -> str | None:
""" """

View File

@ -176,6 +176,10 @@ CONFIGURATION_SCHEMA: ConfigurationSchema = {
"empty": False, "empty": False,
}, },
}, },
"include_debug_packages": {
"type": "boolean",
"coerce": "boolean",
},
"makepkg_flags": { "makepkg_flags": {
"type": "list", "type": "list",
"coerce": "list", "coerce": "list",

View File

@ -17,8 +17,6 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
from ahriman.core.database.operations.operations import Operations
from ahriman.core.database.operations.auth_operations import AuthOperations from ahriman.core.database.operations.auth_operations import AuthOperations
from ahriman.core.database.operations.build_operations import BuildOperations from ahriman.core.database.operations.build_operations import BuildOperations
from ahriman.core.database.operations.changes_operations import ChangesOperations from ahriman.core.database.operations.changes_operations import ChangesOperations

View File

@ -19,7 +19,7 @@
# #
from sqlite3 import Connection from sqlite3 import Connection
from ahriman.core.database.operations import Operations from ahriman.core.database.operations.operations import Operations
from ahriman.models.user import User from ahriman.models.user import User
from ahriman.models.user_access import UserAccess from ahriman.models.user_access import UserAccess

View File

@ -19,7 +19,7 @@
# #
from sqlite3 import Connection from sqlite3 import Connection
from ahriman.core.database.operations import Operations from ahriman.core.database.operations.operations import Operations
from ahriman.models.package import Package from ahriman.models.package import Package
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId

View File

@ -19,7 +19,7 @@
# #
from sqlite3 import Connection from sqlite3 import Connection
from ahriman.core.database.operations import Operations from ahriman.core.database.operations.operations import Operations
from ahriman.models.changes import Changes from ahriman.models.changes import Changes
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId

View File

@ -19,7 +19,7 @@
# #
from sqlite3 import Connection from sqlite3 import Connection
from ahriman.core.database.operations import Operations from ahriman.core.database.operations.operations import Operations
from ahriman.models.log_record_id import LogRecordId from ahriman.models.log_record_id import LogRecordId
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId

View File

@ -20,7 +20,7 @@
from collections.abc import Generator, Iterable from collections.abc import Generator, Iterable
from sqlite3 import Connection from sqlite3 import Connection
from ahriman.core.database.operations import Operations from ahriman.core.database.operations.operations import Operations
from ahriman.models.build_status import BuildStatus from ahriman.models.build_status import BuildStatus
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

View File

@ -20,7 +20,7 @@
from collections import defaultdict from collections import defaultdict
from sqlite3 import Connection from sqlite3 import Connection
from ahriman.core.database.operations import Operations from ahriman.core.database.operations.operations import Operations
from ahriman.models.pkgbuild_patch import PkgbuildPatch from ahriman.models.pkgbuild_patch import PkgbuildPatch

View File

@ -17,7 +17,6 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
from collections import deque
from threading import Lock, Timer from threading import Lock, Timer
from ahriman.core.configuration import Configuration from ahriman.core.configuration import Configuration
@ -47,15 +46,14 @@ class WorkerTrigger(DistributedSystem):
self.ping_interval = configuration.getint(section, "time_to_live", fallback=60) / 4.0 self.ping_interval = configuration.getint(section, "time_to_live", fallback=60) / 4.0
self._lock = Lock() self._lock = Lock()
self._timers: deque[Timer] = deque() # because python doesn't have atomics self._timer: Timer | None = None
def create_timer(self) -> None: def create_timer(self) -> None:
""" """
create timer object and put it to queue create timer object and put it to queue
""" """
timer = Timer(self.ping_interval, self.ping) self._timer = Timer(self.ping_interval, self.ping)
timer.start() self._timer.start()
self._timers.append(timer)
def on_start(self) -> None: def on_start(self) -> None:
""" """
@ -71,21 +69,19 @@ class WorkerTrigger(DistributedSystem):
""" """
self.logger.info("removing instance %s in %s", self.worker, self.address) self.logger.info("removing instance %s in %s", self.worker, self.address)
with self._lock: with self._lock:
current_timers = self._timers.copy() # will be used later if self._timer is None:
self._timers.clear() # clear timer list return
for timer in current_timers: self._timer.cancel() # cancel remaining timers
timer.cancel() # cancel remaining timers self._timer = None # reset state
def ping(self) -> None: def ping(self) -> None:
""" """
register itself as alive worker and update the timer register itself as alive worker and update the timer
""" """
with self._lock: with self._lock:
if not self._timers: # make sure that there is related specific timer if self._timer is None: # no active timer set, exit loop
return return
self._timers.popleft() # pop first timer
self.register() self.register()
self.create_timer() self.create_timer()

View File

@ -17,8 +17,6 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
from ahriman.core.formatters.printer import Printer
from ahriman.core.formatters.aur_printer import AurPrinter from ahriman.core.formatters.aur_printer import AurPrinter
from ahriman.core.formatters.build_printer import BuildPrinter from ahriman.core.formatters.build_printer import BuildPrinter
from ahriman.core.formatters.changes_printer import ChangesPrinter from ahriman.core.formatters.changes_printer import ChangesPrinter
@ -26,6 +24,7 @@ from ahriman.core.formatters.configuration_paths_printer import ConfigurationPat
from ahriman.core.formatters.configuration_printer import ConfigurationPrinter from ahriman.core.formatters.configuration_printer import ConfigurationPrinter
from ahriman.core.formatters.package_printer import PackagePrinter from ahriman.core.formatters.package_printer import PackagePrinter
from ahriman.core.formatters.patch_printer import PatchPrinter from ahriman.core.formatters.patch_printer import PatchPrinter
from ahriman.core.formatters.printer import Printer
from ahriman.core.formatters.repository_printer import RepositoryPrinter from ahriman.core.formatters.repository_printer import RepositoryPrinter
from ahriman.core.formatters.status_printer import StatusPrinter from ahriman.core.formatters.status_printer import StatusPrinter
from ahriman.core.formatters.string_printer import StringPrinter from ahriman.core.formatters.string_printer import StringPrinter

View File

@ -17,7 +17,7 @@
# 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.formatters import Printer from ahriman.core.formatters.printer import Printer
from ahriman.models.changes import Changes from ahriman.models.changes import Changes
from ahriman.models.property import Property from ahriman.models.property import Property

View File

@ -17,7 +17,7 @@
# 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.formatters import Printer from ahriman.core.formatters.printer import Printer
class StringPrinter(Printer): class StringPrinter(Printer):

View File

@ -17,7 +17,7 @@
# 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 logging import NullHandler from logging import NullHandler # pylint: disable=imports-out-of-order
from typing import Any from typing import Any

View File

@ -40,7 +40,7 @@ class LogLoader:
DEFAULT_LOG_FORMAT = "[%(levelname)s %(asctime)s] [%(filename)s:%(lineno)d %(funcName)s]: %(message)s" DEFAULT_LOG_FORMAT = "[%(levelname)s %(asctime)s] [%(filename)s:%(lineno)d %(funcName)s]: %(message)s"
DEFAULT_LOG_LEVEL = logging.DEBUG DEFAULT_LOG_LEVEL = logging.DEBUG
DEFAULT_SYSLOG_DEVICE = Path("/dev") / "log" DEFAULT_SYSLOG_DEVICE = Path("/") / "dev" / "log"
@staticmethod @staticmethod
def handler(selected: LogHandler | None) -> LogHandler: def handler(selected: LogHandler | None) -> LogHandler:

View File

@ -18,8 +18,8 @@
# 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.configuration import Configuration from ahriman.core.configuration import Configuration
from ahriman.core.triggers import Trigger
from ahriman.core.report.report import Report from ahriman.core.report.report import Report
from ahriman.core.triggers import Trigger
from ahriman.models.package import Package from ahriman.models.package import Package
from ahriman.models.repository_id import RepositoryId from ahriman.models.repository_id import RepositoryId
from ahriman.models.result import Result from ahriman.models.result import Result

View File

@ -190,7 +190,8 @@ class Watcher(LazyLogging):
Returns: Returns:
list[PkgbuildPatch]: list of patches which are stored for the package list[PkgbuildPatch]: list of patches which are stored for the package
""" """
self.package_get(package_base) # patches are package base based, we don't know (and don't differentiate) to which package does them belong
# so here we skip checking if package exists or not
variables = [variable] if variable is not None else None variables = [variable] if variable is not None else None
return self.database.patches_list(package_base, variables).get(package_base, []) return self.database.patches_list(package_base, variables).get(package_base, [])

View File

@ -51,7 +51,7 @@ class MirrorlistGenerator(PkgbuildGenerator):
# configuration fields # configuration fields
self.servers = configuration.getlist(section, "servers") self.servers = configuration.getlist(section, "servers")
self.path = configuration.getpath( self.path = configuration.getpath(
section, "path", fallback=Path("/etc") / "pacman.d" / f"{repository_id.name}-mirrorlist") section, "path", fallback=Path("/") / "etc" / "pacman.d" / f"{repository_id.name}-mirrorlist")
self.path = self.path.relative_to("/") # in pkgbuild we are always operating with relative to / path self.path = self.path.relative_to("/") # in pkgbuild we are always operating with relative to / path
# pkgbuild description fields # pkgbuild description fields
self.pkgbuild_pkgname = configuration.get(section, "package", fallback=f"{repository_id.name}-mirrorlist") self.pkgbuild_pkgname = configuration.get(section, "package", fallback=f"{repository_id.name}-mirrorlist")

View File

@ -19,7 +19,7 @@
# #
from __future__ import annotations from __future__ import annotations
from collections.abc import Iterable, Callable from collections.abc import Callable, Iterable
from typing import Any, Self from typing import Any, Self
from ahriman.models.package import Package from ahriman.models.package import Package

View File

@ -17,9 +17,9 @@
# 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 secrets import token_urlsafe as generate_password
from dataclasses import dataclass, replace from dataclasses import dataclass, replace
from passlib.hash import sha512_crypt from passlib.hash import sha512_crypt
from secrets import token_urlsafe as generate_password
from typing import Self from typing import Self
from ahriman.models.user_access import UserAccess from ahriman.models.user_access import UserAccess

View File

@ -35,7 +35,7 @@ from ahriman.web.schemas.package_names_schema import PackageNamesSchema
from ahriman.web.schemas.package_patch_schema import PackagePatchSchema from ahriman.web.schemas.package_patch_schema import PackagePatchSchema
from ahriman.web.schemas.package_properties_schema import PackagePropertiesSchema from ahriman.web.schemas.package_properties_schema import PackagePropertiesSchema
from ahriman.web.schemas.package_schema import PackageSchema from ahriman.web.schemas.package_schema import PackageSchema
from ahriman.web.schemas.package_status_schema import PackageStatusSimplifiedSchema, PackageStatusSchema from ahriman.web.schemas.package_status_schema import PackageStatusSchema, PackageStatusSimplifiedSchema
from ahriman.web.schemas.pagination_schema import PaginationSchema from ahriman.web.schemas.pagination_schema import PaginationSchema
from ahriman.web.schemas.patch_name_schema import PatchNameSchema from ahriman.web.schemas.patch_name_schema import PatchNameSchema
from ahriman.web.schemas.patch_schema import PatchSchema from ahriman.web.schemas.patch_schema import PatchSchema

View File

@ -25,22 +25,6 @@ from ahriman.web.schemas.repository_id_schema import RepositoryIdSchema
from ahriman.web.schemas.status_schema import StatusSchema from ahriman.web.schemas.status_schema import StatusSchema
class PackageStatusSimplifiedSchema(Schema):
"""
special request package status schema
"""
package = fields.Nested(PackageSchema(), metadata={
"description": "Package description",
})
status = fields.Enum(BuildStatusEnum, by_value=True, required=True, metadata={
"description": "Current status",
})
repository = fields.Nested(RepositoryIdSchema(), required=True, metadata={
"description": "Repository identifier",
})
class PackageStatusSchema(Schema): class PackageStatusSchema(Schema):
""" """
response package status schema response package status schema
@ -55,3 +39,19 @@ class PackageStatusSchema(Schema):
repository = fields.Nested(RepositoryIdSchema(), required=True, metadata={ repository = fields.Nested(RepositoryIdSchema(), required=True, metadata={
"description": "Repository identifier", "description": "Repository identifier",
}) })
class PackageStatusSimplifiedSchema(Schema):
"""
special request package status schema
"""
package = fields.Nested(PackageSchema(), metadata={
"description": "Package description",
})
status = fields.Enum(BuildStatusEnum, by_value=True, required=True, metadata={
"description": "Current status",
})
repository = fields.Nested(RepositoryIdSchema(), required=True, metadata={
"description": "Repository identifier",
})

View File

@ -17,8 +17,8 @@
# 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 aiohttp_cors import CorsViewMixin # type: ignore[import-untyped]
from aiohttp.web import HTTPBadRequest, HTTPNotFound, Request, StreamResponse, View from aiohttp.web import HTTPBadRequest, HTTPNotFound, Request, StreamResponse, View
from aiohttp_cors import CorsViewMixin # type: ignore[import-untyped]
from collections.abc import Awaitable, Callable from collections.abc import Awaitable, Callable
from typing import TypeVar from typing import TypeVar

View File

@ -19,8 +19,8 @@
# #
import aiohttp_apispec # type: ignore[import-untyped] import aiohttp_apispec # type: ignore[import-untyped]
from collections.abc import Callable
from aiohttp.web import HTTPBadRequest, HTTPNoContent, Response, json_response from aiohttp.web import HTTPBadRequest, HTTPNoContent, Response, json_response
from collections.abc import Callable
from ahriman.models.user_access import UserAccess from ahriman.models.user_access import UserAccess
from ahriman.models.worker import Worker from ahriman.models.worker import Worker

View File

@ -20,8 +20,8 @@
import aiohttp_apispec # type: ignore[import-untyped] import aiohttp_apispec # type: ignore[import-untyped]
import itertools import itertools
from collections.abc import Callable
from aiohttp.web import HTTPNoContent, Response, json_response from aiohttp.web import HTTPNoContent, Response, json_response
from collections.abc import Callable
from ahriman.models.build_status import BuildStatus from ahriman.models.build_status import BuildStatus
from ahriman.models.package import Package from ahriman.models.package import Package

View File

@ -21,7 +21,6 @@ import aiohttp_apispec # type: ignore[import-untyped]
from aiohttp.web import HTTPNoContent, HTTPNotFound, Response, json_response from aiohttp.web import HTTPNoContent, HTTPNotFound, Response, json_response
from ahriman.core.exceptions import UnknownPackageError
from ahriman.models.user_access import UserAccess from ahriman.models.user_access import UserAccess
from ahriman.web.schemas import AuthSchema, ErrorSchema, PatchNameSchema, PatchSchema from ahriman.web.schemas import AuthSchema, ErrorSchema, PatchNameSchema, PatchSchema
from ahriman.web.views.base import BaseView from ahriman.web.views.base import BaseView
@ -76,7 +75,7 @@ class PatchView(StatusViewGuard, BaseView):
200: {"description": "Success response", "schema": PatchSchema}, 200: {"description": "Success response", "schema": PatchSchema},
401: {"description": "Authorization required", "schema": ErrorSchema}, 401: {"description": "Authorization required", "schema": ErrorSchema},
403: {"description": "Access is forbidden", "schema": ErrorSchema}, 403: {"description": "Access is forbidden", "schema": ErrorSchema},
404: {"description": "Package base and/or patch name are unknown", "schema": ErrorSchema}, 404: {"description": "Patch name is unknown", "schema": ErrorSchema},
500: {"description": "Internal server error", "schema": ErrorSchema}, 500: {"description": "Internal server error", "schema": ErrorSchema},
}, },
security=[{"token": [GET_PERMISSION]}], security=[{"token": [GET_PERMISSION]}],
@ -91,15 +90,12 @@ class PatchView(StatusViewGuard, BaseView):
Response: 200 with package patch on success Response: 200 with package patch on success
Raises: Raises:
HTTPNotFound: if package base is unknown HTTPNotFound: if package patch is unknown
""" """
package_base = self.request.match_info["package"] package_base = self.request.match_info["package"]
variable = self.request.match_info["patch"] variable = self.request.match_info["patch"]
try:
patches = self.service().patches_get(package_base, variable) patches = self.service().patches_get(package_base, variable)
except UnknownPackageError:
raise HTTPNotFound(reason=f"Package {package_base} is unknown")
selected = next((patch for patch in patches if patch.key == variable), None) selected = next((patch for patch in patches if patch.key == variable), None)
if selected is None: if selected is None:

View File

@ -19,9 +19,8 @@
# #
import aiohttp_apispec # type: ignore[import-untyped] import aiohttp_apispec # type: ignore[import-untyped]
from aiohttp.web import HTTPBadRequest, HTTPNoContent, HTTPNotFound, Response, json_response from aiohttp.web import HTTPBadRequest, HTTPNoContent, Response, json_response
from ahriman.core.exceptions import UnknownPackageError
from ahriman.models.pkgbuild_patch import PkgbuildPatch from ahriman.models.pkgbuild_patch import PkgbuildPatch
from ahriman.models.user_access import UserAccess from ahriman.models.user_access import UserAccess
from ahriman.web.schemas import AuthSchema, ErrorSchema, PackageNameSchema, PatchSchema from ahriman.web.schemas import AuthSchema, ErrorSchema, PackageNameSchema, PatchSchema
@ -50,7 +49,6 @@ class PatchesView(StatusViewGuard, BaseView):
200: {"description": "Success response", "schema": PatchSchema(many=True)}, 200: {"description": "Success response", "schema": PatchSchema(many=True)},
401: {"description": "Authorization required", "schema": ErrorSchema}, 401: {"description": "Authorization required", "schema": ErrorSchema},
403: {"description": "Access is forbidden", "schema": ErrorSchema}, 403: {"description": "Access is forbidden", "schema": ErrorSchema},
404: {"description": "Package base is unknown", "schema": ErrorSchema},
500: {"description": "Internal server error", "schema": ErrorSchema}, 500: {"description": "Internal server error", "schema": ErrorSchema},
}, },
security=[{"token": [GET_PERMISSION]}], security=[{"token": [GET_PERMISSION]}],
@ -63,15 +61,9 @@ class PatchesView(StatusViewGuard, BaseView):
Returns: Returns:
Response: 200 with package patches on success Response: 200 with package patches on success
Raises:
HTTPNotFound: if package base is unknown
""" """
package_base = self.request.match_info["package"] package_base = self.request.match_info["package"]
try:
patches = self.service().patches_get(package_base, None) patches = self.service().patches_get(package_base, None)
except UnknownPackageError:
raise HTTPNotFound(reason=f"Package {package_base} is unknown")
response = [patch.view() for patch in patches] response = [patch.view() for patch in patches]
return json_response(response) return json_response(response)

View File

@ -22,7 +22,7 @@ import aiohttp_apispec # type: ignore[import-untyped]
from aiohttp.web import HTTPBadRequest, Response, json_response from aiohttp.web import HTTPBadRequest, Response, json_response
from ahriman.models.user_access import UserAccess from ahriman.models.user_access import UserAccess
from ahriman.web.schemas import AuthSchema, ErrorSchema, ProcessIdSchema, UpdateFlagsSchema, RepositoryIdSchema from ahriman.web.schemas import AuthSchema, ErrorSchema, ProcessIdSchema, RepositoryIdSchema, UpdateFlagsSchema
from ahriman.web.views.base import BaseView from ahriman.web.views.base import BaseView

Some files were not shown because too many files have changed in this diff Show More