mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-06-27 14:22:10 +00:00
Compare commits
61 Commits
2.5.1
...
feature/pk
Author | SHA1 | Date | |
---|---|---|---|
aac3ccfc30 | |||
8c55438140 | |||
277d40d231 | |||
2ff56965d9 | |||
9dc6d56a8d | |||
d59a0629c5 | |||
31f47b8069 | |||
e42ca95789 | |||
ff917281a2 | |||
f7e260e1f4 | |||
abf29083c4 | |||
54d36ccf36 | |||
2cd61b0a20 | |||
9503a9f2ae | |||
39fde7cd5f | |||
58379e7bf3 | |||
3c068edf4f | |||
1106ff6482 | |||
e08ab2db10 | |||
8f4a2547e8 | |||
7f5e541120 | |||
ec0550a275 | |||
df23be9269 | |||
a8c40a6b87 | |||
a274f91677 | |||
13faf66bdb | |||
4fb9335df9 | |||
d517d8bfbb | |||
37e57c13c8 | |||
19bb19e9f5 | |||
3a4e8f4d97 | |||
4db8ad8e8d | |||
117f096d41 | |||
917ec48be5 | |||
0a2ba4ae07 | |||
9d7f63e549 | |||
25eee9ca5e | |||
5af84955ac | |||
d3ad4c3c08 | |||
5bbb9d269b | |||
17466d8d37 | |||
9e4e3b701b | |||
c6555cf2c7 | |||
85baad6a41 | |||
616a1950ae | |||
30b9bcb45a | |||
d7356926c4 | |||
43a7d09cab | |||
77954b988b | |||
0239fb50b6 | |||
d942a70272 | |||
1f07a89316 | |||
014007ade3 | |||
730f3ca0c9 | |||
42c13b5d4b | |||
04e5a263b7 | |||
caca1576c8 | |||
98f2f19d5b | |||
5c4d3eeffd | |||
84d4523e85 | |||
2c2eae2334 |
@ -1 +1 @@
|
||||
skips: ['B101', 'B105', 'B106', 'B404']
|
||||
skips: ['B101', 'B104', 'B105', 'B106', 'B404']
|
||||
|
12
.github/workflows/setup.sh
vendored
12
.github/workflows/setup.sh
vendored
@ -10,7 +10,7 @@ echo -e '[arcanisrepo]\nServer = http://repo.arcanis.me/$arch\nSigLevel = Never'
|
||||
# refresh the image
|
||||
pacman --noconfirm -Syu
|
||||
# main dependencies
|
||||
pacman --noconfirm -Sy base-devel devtools git pyalpm python-aur python-passlib python-setuptools python-srcinfo sudo
|
||||
pacman --noconfirm -Sy base-devel devtools-git-poc git pyalpm python-cerberus python-inflection python-passlib python-requests python-srcinfo sudo
|
||||
# make dependencies
|
||||
pacman --noconfirm -Sy python-build python-installer python-wheel
|
||||
# optional dependencies
|
||||
@ -18,7 +18,7 @@ if [[ -z $MINIMAL_INSTALL ]]; then
|
||||
# VCS support
|
||||
pacman --noconfirm -Sy breezy darcs mercurial subversion
|
||||
# web server
|
||||
pacman --noconfirm -Sy python-aioauth-client python-aiohttp python-aiohttp-debugtoolbar python-aiohttp-jinja2 python-aiohttp-security python-aiohttp-session python-cryptography python-jinja
|
||||
pacman --noconfirm -Sy python-aioauth-client python-aiohttp python-aiohttp-apispec-git python-aiohttp-cors python-aiohttp-debugtoolbar python-aiohttp-jinja2 python-aiohttp-security python-aiohttp-session python-cryptography python-jinja
|
||||
# additional features
|
||||
pacman --noconfirm -Sy gnupg python-boto3 rsync
|
||||
fi
|
||||
@ -38,7 +38,9 @@ systemd-machine-id-setup
|
||||
sed -i "s/handlers = syslog_handler/handlers = console_handler/g" /etc/ahriman.ini.d/logging.ini
|
||||
# initial setup command as root
|
||||
[[ -z $MINIMAL_INSTALL ]] && WEB_ARGS=("--web-port" "8080")
|
||||
ahriman -a x86_64 repo-setup --packager "ahriman bot <ahriman@example.com>" --repository "github" "${WEB_ARGS[@]}"
|
||||
ahriman -a x86_64 service-setup --packager "ahriman bot <ahriman@example.com>" --repository "github" "${WEB_ARGS[@]}"
|
||||
# validate configuration
|
||||
ahriman -a x86_64 service-config-validate --exit-code
|
||||
# enable services
|
||||
systemctl enable ahriman-web@x86_64
|
||||
systemctl enable ahriman@x86_64.timer
|
||||
@ -50,9 +52,9 @@ if [[ -z $MINIMAL_INSTALL ]]; then
|
||||
fi
|
||||
# add the first package
|
||||
# the build itself does not really work in the container
|
||||
sudo -u ahriman -- ahriman package-add --now yay
|
||||
sudo -u ahriman -- ahriman package-add --now ahriman
|
||||
# check if package was actually installed
|
||||
test -n "$(find "/var/lib/ahriman/repository/x86_64" -name "yay*pkg*")"
|
||||
test -n "$(find "/var/lib/ahriman/repository/x86_64" -name "ahriman*pkg*")"
|
||||
# run package check
|
||||
sudo -u ahriman -- ahriman repo-update
|
||||
# stop web service lol
|
||||
|
2
.github/workflows/tests.sh
vendored
2
.github/workflows/tests.sh
vendored
@ -4,7 +4,7 @@
|
||||
set -ex
|
||||
|
||||
# install dependencies
|
||||
pacman --noconfirm -Syu base-devel python-pip python-setuptools python-tox
|
||||
pacman --noconfirm -Syu base-devel python-setuptools python-tox
|
||||
|
||||
# run test and check targets
|
||||
make check tests
|
||||
|
@ -533,5 +533,5 @@ valid-metaclass-classmethod-first-arg=cls
|
||||
|
||||
# Exceptions that will emit a warning when being caught. Defaults to
|
||||
# "BaseException, Exception".
|
||||
overgeneral-exceptions=BaseException,
|
||||
Exception
|
||||
overgeneral-exceptions=builtins.BaseException,
|
||||
builtins.Exception
|
||||
|
146
CONTRIBUTING.md
146
CONTRIBUTING.md
@ -26,7 +26,103 @@ In order to resolve all difficult cases the `autopep8` is used. You can perform
|
||||
Again, the most checks can be performed by `make check` command, though some additional guidelines must be applied:
|
||||
|
||||
* Every class, every function (including private and protected), every attribute must be documented. The project follows [Google style documentation](https://google.github.io/styleguide/pyguide.html). The only exception is local functions.
|
||||
* Type annotations are the must, even for local functions.
|
||||
* Correct way to document function, if section is empty, e.g. no notes or there are no args, it should be omitted:
|
||||
|
||||
```python
|
||||
def foo(argument: str, *, flag: bool = False) -> int:
|
||||
"""
|
||||
do foo. With very very very long
|
||||
docstring
|
||||
|
||||
Note:
|
||||
Very important note about this function
|
||||
|
||||
Args:
|
||||
argument(str): an argument. This argument has
|
||||
long description also
|
||||
flag(bool, optional): a flag (Default value = False)
|
||||
|
||||
Returns:
|
||||
int: result
|
||||
|
||||
Raises:
|
||||
RuntimeException: a local function error occurs
|
||||
|
||||
Examples:
|
||||
Very informative example how to use this function, e.g.::
|
||||
|
||||
>>> foo("argument", flag=False)
|
||||
|
||||
Note that function documentation is in rST.
|
||||
"""
|
||||
```
|
||||
|
||||
`Returns` should be replaced with `Yields` for generators.
|
||||
|
||||
Class attributes should be documented in the following way:
|
||||
|
||||
```python
|
||||
class Clazz(BaseClazz):
|
||||
"""
|
||||
brand-new implementation of ``BaseClazz``
|
||||
|
||||
Attributes:
|
||||
CLAZZ_ATTRIBUTE(int): (class attribute) a brand-new class attribute
|
||||
instance_attribute(str): an instance attribute
|
||||
|
||||
Examples:
|
||||
Very informative class usage example, e.g.::
|
||||
|
||||
>>> from module import Clazz
|
||||
>>> clazz = Clazz()
|
||||
"""
|
||||
|
||||
CLAZZ_ATTRIBUTE = 42
|
||||
|
||||
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
||||
"""
|
||||
default constructor
|
||||
|
||||
Args:
|
||||
*args(Any): positional arguments
|
||||
**kwargs(Any): keyword arguments
|
||||
"""
|
||||
self.instance_attribute = ""
|
||||
```
|
||||
|
||||
* Type annotations are the must, even for local functions. For the function argument `self` (for instance methods) and `cls` (for class methods) should not be annotated.
|
||||
* For collection types built-in classes must be used if possible (e.g. `dict` instead of `typing.Dict`, `tuple` instead of `typing.Tuple`). In case if built-in type is not available, but `collections.abc` provides interface, it must be used (e.g. `collections.abc.Awaitable` instead of `typing.Awaitable`, `collections.abc.Iterable` instead of `typing.Iterable`). For union classes, the bar operator (`|`) must be used (e.g. `float | int` instead of `typing.Union[float, int]`), which also includes `typinng.Optional` (e.g. `str | None` instead of `Optional[str]`).
|
||||
* `classmethod` should always return `Self`. In case of mypy warning (e.g. if there is a branch in which function doesn't return the instance of `cls`) consider using `staticmethod` instead.
|
||||
* Recommended order of function definitions in class:
|
||||
|
||||
```python
|
||||
class Clazz:
|
||||
|
||||
def __init__(self) -> None: ... # replace with `__post_init__` for dataclasses
|
||||
|
||||
@property
|
||||
def property(self) -> Any: ...
|
||||
|
||||
@classmethod
|
||||
def class_method(cls) -> Self: ...
|
||||
|
||||
@staticmethod
|
||||
def static_method() -> Any: ...
|
||||
|
||||
def __private_method(self) -> Any: ...
|
||||
|
||||
def _protected_method(self) -> Any: ...
|
||||
|
||||
def usual_method(self) -> Any: ...
|
||||
|
||||
def __hash__(self) -> int: ... # basically any magic (or look-alike) method
|
||||
```
|
||||
|
||||
Methods inside one group should be ordered alphabetically, the only exception is `__init__` method (`__post__init__` for dataclasses) which should be defined first. For test methods it is recommended to follow the order in which functions are defined.
|
||||
|
||||
Though, we would like to highlight abstract methods (i.e. ones which raise `NotImplementedError`), we still keep in global order at the moment.
|
||||
|
||||
* Abstract methods must raise `NotImplementedError` instead of using `abc.abstractmethod`. The reason behind this restriction is the fact that we have class/static abstract methods for those we need to define their attribute first making the code harder to read.
|
||||
* For any path interactions `pathlib.Path` must be used.
|
||||
* Configuration interactions must go through `ahriman.core.configuration.Configuration` class instance.
|
||||
* In case if class load requires some actions, it is recommended to create class method which can be used for class instantiating.
|
||||
@ -59,9 +155,55 @@ Again, the most checks can be performed by `make check` command, though some add
|
||||
* One file should define only one class, exception is class satellites in case if file length remains less than 400 lines.
|
||||
* It is possible to create file which contains some functions (e.g. `ahriman.core.util`), but in this case you would need to define `__all__` attribute.
|
||||
* The file size mentioned above must be applicable in general. In case of big classes consider splitting them into traits. Note, however, that `pylint` includes comments and docstrings into counter, thus you need to check file size by other tools.
|
||||
* No global variable is allowed outside of `ahriman.version` module.
|
||||
* No global variable is allowed outside of `ahriman.version` module. `ahriman.core.context` is also special case.
|
||||
* Single quotes are not allowed. The reason behind this restriction is the fact that docstrings must be written by using double quotes only, and we would like to make style consistent.
|
||||
* If your class writes anything to log, the `ahriman.core.log.LazyLogging` trait must be used.
|
||||
* Web API methods must be documented by using `aiohttp_apispec` library. Schema testing mostly should be implemented in related view class tests. Recommended example for documentation (excluding comments):
|
||||
|
||||
```python
|
||||
import aiohttp_apispec
|
||||
|
||||
from marshmallow import Schema, fields
|
||||
|
||||
from ahriman.web.schemas.auth_schema import AuthSchema
|
||||
from ahriman.web.schemas.error_schema import ErrorSchema
|
||||
from ahriman.web.schemas.package_name_schema import PackageNameSchema
|
||||
from ahriman.web.views.base import BaseView
|
||||
|
||||
|
||||
class RequestSchema(Schema):
|
||||
|
||||
field = fields.String(metadata={"description": "Field description", "example": "foo"})
|
||||
|
||||
|
||||
class ResponseSchema(Schema):
|
||||
|
||||
field = fields.String(required=True, metadata={"description": "Field description"})
|
||||
|
||||
|
||||
class Foo(BaseView):
|
||||
|
||||
POST_PERMISSION = ...
|
||||
|
||||
@aiohttp_apispec.docs(
|
||||
tags=["Tag"],
|
||||
summary="Do foo",
|
||||
description="Extended description of the method which does foo",
|
||||
responses={
|
||||
200: {"description": "Success response", "schema": ResponseSchema},
|
||||
204: {"description": "Success response"}, # example without json schema response
|
||||
400: {"description": "Bad data is supplied", "schema": ErrorSchema}, # exception raised by this method
|
||||
401: {"description": "Authorization required", "schema": ErrorSchema}, # should be always presented
|
||||
403: {"description": "Access is forbidden", "schema": ErrorSchema}, # should be always presented
|
||||
500: {"description": "Internal server error", "schema": ErrorSchema}, # should be always presented
|
||||
},
|
||||
security=[{"token": [POST_PERMISSION]}],
|
||||
)
|
||||
@aiohttp_apispec.cookies_schema(AuthSchema) # should be always presented
|
||||
@aiohttp_apispec.match_info_schema(PackageNameSchema)
|
||||
@aiohttp_apispec.json_schema(RequestSchema(many=True))
|
||||
async def post(self) -> None: ...
|
||||
```
|
||||
|
||||
### Other checks
|
||||
|
||||
|
11
Dockerfile
11
Dockerfile
@ -5,13 +5,16 @@ ENV AHRIMAN_ARCHITECTURE="x86_64"
|
||||
ENV AHRIMAN_DEBUG=""
|
||||
ENV AHRIMAN_FORCE_ROOT=""
|
||||
ENV AHRIMAN_HOST="0.0.0.0"
|
||||
ENV AHRIMAN_MULTILIB="yes"
|
||||
ENV AHRIMAN_OUTPUT="syslog"
|
||||
ENV AHRIMAN_PACKAGER="ahriman bot <ahriman@example.com>"
|
||||
ENV AHRIMAN_PACMAN_MIRROR=""
|
||||
ENV AHRIMAN_PORT=""
|
||||
ENV AHRIMAN_REPOSITORY="aur-clone"
|
||||
ENV AHRIMAN_REPOSITORY_ROOT="/var/lib/ahriman/ahriman"
|
||||
ENV AHRIMAN_UNIX_SOCKET=""
|
||||
ENV AHRIMAN_USER="ahriman"
|
||||
ENV AHRIMAN_VALIDATE_CONFIGURATION="yes"
|
||||
|
||||
# install environment
|
||||
## update pacman.conf with multilib
|
||||
@ -25,11 +28,11 @@ RUN useradd -m -d "/home/build" -s "/usr/bin/nologin" build && \
|
||||
COPY "docker/install-aur-package.sh" "/usr/local/bin/install-aur-package"
|
||||
## install package dependencies
|
||||
## darcs is not installed by reasons, because it requires a lot haskell packages which dramatically increase image size
|
||||
RUN pacman --noconfirm -Sy devtools git pyalpm python-inflection python-passlib python-requests python-setuptools python-srcinfo && \
|
||||
RUN pacman --noconfirm -Sy devtools-git-poc git pyalpm python-cerberus python-inflection python-passlib python-requests python-srcinfo && \
|
||||
pacman --noconfirm -Sy python-build python-installer python-wheel && \
|
||||
pacman --noconfirm -Sy breezy mercurial python-aiohttp python-boto3 python-cryptography python-jinja python-requests-unixsocket rsync subversion && \
|
||||
runuser -u build -- install-aur-package python-aioauth-client python-aiohttp-jinja2 python-aiohttp-debugtoolbar \
|
||||
python-aiohttp-session python-aiohttp-security
|
||||
pacman --noconfirm -Sy breezy mercurial python-aiohttp python-aiohttp-cors python-boto3 python-cryptography python-jinja python-requests-unixsocket rsync subversion && \
|
||||
runuser -u build -- install-aur-package python-aioauth-client python-aiohttp-apispec-git python-aiohttp-jinja2 \
|
||||
python-aiohttp-debugtoolbar python-aiohttp-session python-aiohttp-security
|
||||
|
||||
# cleanup unused
|
||||
RUN find "/var/cache/pacman/pkg" -type f -delete
|
||||
|
@ -36,6 +36,6 @@ The application provides reasonable defaults which allow to use it out-of-box; h
|
||||
|
||||
## Live demos
|
||||
|
||||
* [Build status page](https://ahriman-demo.arcanis.me). You can log in as `demo` user by using `demo` password. However, you will not be able to run tasks.
|
||||
* [Build status page](https://ahriman-demo.arcanis.me). You can log in as `demo` user by using `demo` password. However, you will not be able to run tasks. [HTTP API documentation](https://ahriman-demo.arcanis.me/api-docs) is also available.
|
||||
* [Repository index](http://repo.arcanis.me/x86_64/index.html).
|
||||
* [Telegram feed](https://t.me/arcanisrepo).
|
||||
|
@ -36,16 +36,24 @@ AHRIMAN_GNUPG_HOME="$(getent passwd "$AHRIMAN_USER" | cut -d : -f 6)/.gnupg"
|
||||
chown "$AHRIMAN_USER":"$AHRIMAN_USER" "$AHRIMAN_GNUPG_HOME"
|
||||
|
||||
# run built-in setup command
|
||||
AHRIMAN_SETUP_ARGS=("--build-as-user" "$AHRIMAN_USER")
|
||||
AHRIMAN_SETUP_ARGS+=("--packager" "$AHRIMAN_PACKAGER")
|
||||
AHRIMAN_SETUP_ARGS+=("--repository" "$AHRIMAN_REPOSITORY")
|
||||
if [ -z "$AHRIMAN_MULTILIB" ]; then
|
||||
AHRIMAN_SETUP_ARGS+=("--no-multilib")
|
||||
fi
|
||||
if [ -n "$AHRIMAN_PACMAN_MIRROR" ]; then
|
||||
AHRIMAN_SETUP_ARGS+=("--mirror" "$AHRIMAN_PACMAN_MIRROR")
|
||||
fi
|
||||
if [ -n "$AHRIMAN_PORT" ]; then
|
||||
AHRIMAN_SETUP_ARGS+=("--web-port" "$AHRIMAN_PORT")
|
||||
fi
|
||||
if [ -n "$AHRIMAN_UNIX_SOCKET" ]; then
|
||||
AHRIMAN_SETUP_ARGS+=("--web-unix-socket" "$AHRIMAN_UNIX_SOCKET")
|
||||
fi
|
||||
ahriman "${AHRIMAN_DEFAULT_ARGS[@]}" repo-setup "${AHRIMAN_SETUP_ARGS[@]}"
|
||||
ahriman "${AHRIMAN_DEFAULT_ARGS[@]}" service-setup "${AHRIMAN_SETUP_ARGS[@]}"
|
||||
|
||||
# validate configuration if set
|
||||
[ -n "$AHRIMAN_VALIDATE_CONFIGURATION" ] && ahriman "${AHRIMAN_DEFAULT_ARGS[@]}" service-config-validate --exit-code
|
||||
|
||||
# create machine-id which is required by build tools
|
||||
systemd-machine-id-setup &> /dev/null
|
||||
|
File diff suppressed because it is too large
Load Diff
Before Width: | Height: | Size: 641 KiB After Width: | Height: | Size: 750 KiB |
353
docs/ahriman.1
353
docs/ahriman.1
@ -1,9 +1,9 @@
|
||||
.TH AHRIMAN "1" "2022\-12\-31" "ahriman" "Generated Python Manual"
|
||||
.TH AHRIMAN "1" "2023\-04\-09" "ahriman" "Generated Python Manual"
|
||||
.SH NAME
|
||||
ahriman
|
||||
.SH SYNOPSIS
|
||||
.B ahriman
|
||||
[-h] [-a ARCHITECTURE] [-c CONFIGURATION] [--force] [-l LOCK] [--report | --no-report] [-q] [--unsafe] [-V] {aur-search,search,daemon,help,help-commands-unsafe,key-import,package-add,add,package-update,package-remove,remove,package-status,status,package-status-remove,package-status-update,status-update,patch-add,patch-list,patch-remove,patch-set-add,repo-backup,repo-check,check,repo-clean,clean,repo-config,config,repo-rebuild,rebuild,repo-remove-unknown,remove-unknown,repo-report,report,repo-restore,repo-setup,init,repo-init,setup,repo-sign,sign,repo-status-update,repo-sync,sync,repo-tree,repo-triggers,repo-update,update,shell,user-add,user-list,user-remove,version,web} ...
|
||||
[-h] [-a ARCHITECTURE] [-c CONFIGURATION] [--force] [-l LOCK] [--report | --no-report] [-q] [--unsafe] [-V] {aur-search,search,help,help-commands-unsafe,help-updates,help-version,version,package-add,add,package-update,package-remove,remove,package-status,status,package-status-remove,package-status-update,status-update,patch-add,patch-list,patch-remove,patch-set-add,repo-backup,repo-check,check,repo-daemon,daemon,repo-rebuild,rebuild,repo-remove-unknown,remove-unknown,repo-report,report,repo-restore,repo-sign,sign,repo-status-update,repo-sync,sync,repo-tree,repo-triggers,repo-update,update,service-clean,clean,repo-clean,service-config,config,repo-config,service-config-validate,config-validate,repo-config-validate,service-key-import,key-import,service-setup,init,repo-init,repo-setup,setup,service-shell,shell,user-add,user-list,user-remove,web} ...
|
||||
.SH DESCRIPTION
|
||||
ArcH linux ReposItory MANager
|
||||
|
||||
@ -46,17 +46,17 @@ COMMAND
|
||||
\fBahriman\fR \fI\,aur\-search\/\fR
|
||||
search for package
|
||||
.TP
|
||||
\fBahriman\fR \fI\,daemon\/\fR
|
||||
run application as daemon
|
||||
.TP
|
||||
\fBahriman\fR \fI\,help\/\fR
|
||||
show help message
|
||||
.TP
|
||||
\fBahriman\fR \fI\,help\-commands\-unsafe\/\fR
|
||||
list unsafe commands
|
||||
.TP
|
||||
\fBahriman\fR \fI\,key\-import\/\fR
|
||||
import PGP key
|
||||
\fBahriman\fR \fI\,help\-updates\/\fR
|
||||
check for service updates
|
||||
.TP
|
||||
\fBahriman\fR \fI\,help\-version\/\fR
|
||||
application version
|
||||
.TP
|
||||
\fBahriman\fR \fI\,package\-add\/\fR
|
||||
add package
|
||||
@ -91,11 +91,8 @@ backup repository data
|
||||
\fBahriman\fR \fI\,repo\-check\/\fR
|
||||
check for updates
|
||||
.TP
|
||||
\fBahriman\fR \fI\,repo\-clean\/\fR
|
||||
clean local caches
|
||||
.TP
|
||||
\fBahriman\fR \fI\,repo\-config\/\fR
|
||||
dump configuration
|
||||
\fBahriman\fR \fI\,repo\-daemon\/\fR
|
||||
run application as daemon
|
||||
.TP
|
||||
\fBahriman\fR \fI\,repo\-rebuild\/\fR
|
||||
rebuild repository
|
||||
@ -109,9 +106,6 @@ generate report
|
||||
\fBahriman\fR \fI\,repo\-restore\/\fR
|
||||
restore repository data
|
||||
.TP
|
||||
\fBahriman\fR \fI\,repo\-setup\/\fR
|
||||
initial service configuration
|
||||
.TP
|
||||
\fBahriman\fR \fI\,repo\-sign\/\fR
|
||||
sign packages
|
||||
.TP
|
||||
@ -130,7 +124,22 @@ run triggers
|
||||
\fBahriman\fR \fI\,repo\-update\/\fR
|
||||
update packages
|
||||
.TP
|
||||
\fBahriman\fR \fI\,shell\/\fR
|
||||
\fBahriman\fR \fI\,service\-clean\/\fR
|
||||
clean local caches
|
||||
.TP
|
||||
\fBahriman\fR \fI\,service\-config\/\fR
|
||||
dump configuration
|
||||
.TP
|
||||
\fBahriman\fR \fI\,service\-config\-validate\/\fR
|
||||
validate system configuration
|
||||
.TP
|
||||
\fBahriman\fR \fI\,service\-key\-import\/\fR
|
||||
import PGP key
|
||||
.TP
|
||||
\fBahriman\fR \fI\,service\-setup\/\fR
|
||||
initial service configuration
|
||||
.TP
|
||||
\fBahriman\fR \fI\,service\-shell\/\fR
|
||||
invoke python shell
|
||||
.TP
|
||||
\fBahriman\fR \fI\,user\-add\/\fR
|
||||
@ -142,15 +151,12 @@ user known users and their access
|
||||
\fBahriman\fR \fI\,user\-remove\/\fR
|
||||
remove user
|
||||
.TP
|
||||
\fBahriman\fR \fI\,version\/\fR
|
||||
application version
|
||||
.TP
|
||||
\fBahriman\fR \fI\,web\/\fR
|
||||
web server
|
||||
|
||||
.SH COMMAND \fI\,'ahriman aur\-search'\/\fR
|
||||
usage: ahriman aur\-search [\-h] [\-e] [\-\-info | \-\-no\-info]
|
||||
[\-\-sort\-by {description,first_submitted,id,last_modified,maintainer,name,num_votes,out_of_date,package_base,package_base_id,popularity,repository,url,url_path,version}]
|
||||
[\-\-sort\-by {description,first_submitted,id,last_modified,maintainer,name,num_votes,out_of_date,package_base,package_base_id,popularity,repository,submitter,url,url_path,version}]
|
||||
search [search ...]
|
||||
|
||||
search for package in AUR using API
|
||||
@ -169,41 +175,10 @@ return non\-zero exit status if result is empty
|
||||
show additional package information (default: False)
|
||||
|
||||
.TP
|
||||
\fB\-\-sort\-by\fR \fI\,{description,first_submitted,id,last_modified,maintainer,name,num_votes,out_of_date,package_base,package_base_id,popularity,repository,url,url_path,version}\/\fR
|
||||
\fB\-\-sort\-by\fR \fI\,{description,first_submitted,id,last_modified,maintainer,name,num_votes,out_of_date,package_base,package_base_id,popularity,repository,submitter,url,url_path,version}\/\fR
|
||||
sort field by this field. In case if two packages have the same value of the specified field, they will be always sorted
|
||||
by name
|
||||
|
||||
.SH COMMAND \fI\,'ahriman daemon'\/\fR
|
||||
usage: ahriman daemon [\-h] [\-i INTERVAL] [\-\-aur | \-\-no\-aur] [\-\-local | \-\-no\-local] [\-\-manual | \-\-no\-manual]
|
||||
[\-\-vcs | \-\-no\-vcs] [\-y]
|
||||
|
||||
start process which periodically will run update process
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman daemon'\/\fR
|
||||
.TP
|
||||
\fB\-i\fR \fI\,INTERVAL\/\fR, \fB\-\-interval\fR \fI\,INTERVAL\/\fR
|
||||
interval between runs in seconds
|
||||
|
||||
.TP
|
||||
\fB\-\-aur\fR, \fB\-\-no\-aur\fR
|
||||
enable or disable checking for AUR updates. Implies \-\-no\-vcs (default: True)
|
||||
|
||||
.TP
|
||||
\fB\-\-local\fR, \fB\-\-no\-local\fR
|
||||
enable or disable checking of local packages for updates (default: True)
|
||||
|
||||
.TP
|
||||
\fB\-\-manual\fR, \fB\-\-no\-manual\fR
|
||||
include or exclude manual updates (default: True)
|
||||
|
||||
.TP
|
||||
\fB\-\-vcs\fR, \fB\-\-no\-vcs\fR
|
||||
enable or disable checking of VCS packages (default: True)
|
||||
|
||||
.TP
|
||||
\fB\-y\fR, \fB\-\-refresh\fR
|
||||
download fresh package databases from the mirror before actions, \-yy to force refresh even if up to date
|
||||
|
||||
.SH COMMAND \fI\,'ahriman help'\/\fR
|
||||
usage: ahriman help [\-h] [command]
|
||||
|
||||
@ -224,23 +199,24 @@ list unsafe commands as defined in default args
|
||||
instead of showing commands, just test command line for unsafe subcommand and return 0 in case if command is safe and 1
|
||||
otherwise
|
||||
|
||||
.SH COMMAND \fI\,'ahriman key\-import'\/\fR
|
||||
usage: ahriman key\-import [\-h] [\-\-key\-server KEY_SERVER] key
|
||||
.SH COMMAND \fI\,'ahriman help\-updates'\/\fR
|
||||
usage: ahriman help\-updates [\-h] [\-e]
|
||||
|
||||
import PGP key from public sources to the repository user
|
||||
request AUR for current version and compare with current service version
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman help\-updates'\/\fR
|
||||
.TP
|
||||
\fBkey\fR
|
||||
PGP key to import from public server
|
||||
\fB\-e\fR, \fB\-\-exit\-code\fR
|
||||
return non\-zero exit code if updates available
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman key\-import'\/\fR
|
||||
.TP
|
||||
\fB\-\-key\-server\fR \fI\,KEY_SERVER\/\fR
|
||||
key server for key import
|
||||
.SH COMMAND \fI\,'ahriman help\-version'\/\fR
|
||||
usage: ahriman help\-version [\-h]
|
||||
|
||||
print application and its dependencies versions
|
||||
|
||||
.SH COMMAND \fI\,'ahriman package\-add'\/\fR
|
||||
usage: ahriman package\-add [\-h] [\-e] [\-n] [\-y] [\-s {auto,archive,aur,directory,local,remote,repository}]
|
||||
[\-\-without\-dependencies]
|
||||
usage: ahriman package\-add [\-h] [\-\-dependencies | \-\-no\-dependencies] [\-e] [\-n] [\-y]
|
||||
[\-s {auto,archive,aur,directory,local,remote,repository}]
|
||||
package [package ...]
|
||||
|
||||
add existing or new package to the build queue
|
||||
@ -250,6 +226,10 @@ add existing or new package to the build queue
|
||||
package source (base name, path to local files, remote URL)
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman package\-add'\/\fR
|
||||
.TP
|
||||
\fB\-\-dependencies\fR, \fB\-\-no\-dependencies\fR
|
||||
process missing package dependencies (default: True)
|
||||
|
||||
.TP
|
||||
\fB\-e\fR, \fB\-\-exit\-code\fR
|
||||
return non\-zero exit status if result is empty
|
||||
@ -266,10 +246,6 @@ download fresh package databases from the mirror before actions, \-yy to force r
|
||||
\fB\-s\fR \fI\,{auto,archive,aur,directory,local,remote,repository}\/\fR, \fB\-\-source\fR \fI\,{auto,archive,aur,directory,local,remote,repository}\/\fR
|
||||
explicitly specify the package source for this command
|
||||
|
||||
.TP
|
||||
\fB\-\-without\-dependencies\fR
|
||||
do not add dependencies
|
||||
|
||||
.SH COMMAND \fI\,'ahriman package\-remove'\/\fR
|
||||
usage: ahriman package\-remove [\-h] package [package ...]
|
||||
|
||||
@ -418,43 +394,46 @@ return non\-zero exit status if result is empty
|
||||
|
||||
.TP
|
||||
\fB\-\-vcs\fR, \fB\-\-no\-vcs\fR
|
||||
enable or disable checking of VCS packages (default: True)
|
||||
fetch actual version of VCS packages (default: True)
|
||||
|
||||
.TP
|
||||
\fB\-y\fR, \fB\-\-refresh\fR
|
||||
download fresh package databases from the mirror before actions, \-yy to force refresh even if up to date
|
||||
|
||||
.SH COMMAND \fI\,'ahriman repo\-clean'\/\fR
|
||||
usage: ahriman repo\-clean [\-h] [\-\-cache | \-\-no\-cache] [\-\-chroot | \-\-no\-chroot] [\-\-manual | \-\-no\-manual]
|
||||
[\-\-packages | \-\-no\-packages] [\-\-pacman | \-\-no\-pacman]
|
||||
.SH COMMAND \fI\,'ahriman repo\-daemon'\/\fR
|
||||
usage: ahriman repo\-daemon [\-h] [\-i INTERVAL] [\-\-aur | \-\-no\-aur] [\-\-dependencies | \-\-no\-dependencies]
|
||||
[\-\-local | \-\-no\-local] [\-\-manual | \-\-no\-manual] [\-\-vcs | \-\-no\-vcs] [\-y]
|
||||
|
||||
remove local caches
|
||||
start process which periodically will run update process
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman repo\-clean'\/\fR
|
||||
.SH OPTIONS \fI\,'ahriman repo\-daemon'\/\fR
|
||||
.TP
|
||||
\fB\-\-cache\fR, \fB\-\-no\-cache\fR
|
||||
clear directory with package caches (default: False)
|
||||
\fB\-i\fR \fI\,INTERVAL\/\fR, \fB\-\-interval\fR \fI\,INTERVAL\/\fR
|
||||
interval between runs in seconds
|
||||
|
||||
.TP
|
||||
\fB\-\-chroot\fR, \fB\-\-no\-chroot\fR
|
||||
clear build chroot (default: False)
|
||||
\fB\-\-aur\fR, \fB\-\-no\-aur\fR
|
||||
enable or disable checking for AUR updates (default: True)
|
||||
|
||||
.TP
|
||||
\fB\-\-dependencies\fR, \fB\-\-no\-dependencies\fR
|
||||
process missing package dependencies (default: True)
|
||||
|
||||
.TP
|
||||
\fB\-\-local\fR, \fB\-\-no\-local\fR
|
||||
enable or disable checking of local packages for updates (default: True)
|
||||
|
||||
.TP
|
||||
\fB\-\-manual\fR, \fB\-\-no\-manual\fR
|
||||
clear manually added packages queue (default: False)
|
||||
include or exclude manual updates (default: True)
|
||||
|
||||
.TP
|
||||
\fB\-\-packages\fR, \fB\-\-no\-packages\fR
|
||||
clear directory with built packages (default: False)
|
||||
\fB\-\-vcs\fR, \fB\-\-no\-vcs\fR
|
||||
fetch actual version of VCS packages (default: True)
|
||||
|
||||
.TP
|
||||
\fB\-\-pacman\fR, \fB\-\-no\-pacman\fR
|
||||
clear directory with pacman local database cache (default: False)
|
||||
|
||||
.SH COMMAND \fI\,'ahriman repo\-config'\/\fR
|
||||
usage: ahriman repo\-config [\-h]
|
||||
|
||||
dump configuration for the specified architecture
|
||||
\fB\-y\fR, \fB\-\-refresh\fR
|
||||
download fresh package databases from the mirror before actions, \-yy to force refresh even if up to date
|
||||
|
||||
.SH COMMAND \fI\,'ahriman repo\-rebuild'\/\fR
|
||||
usage: ahriman repo\-rebuild [\-h] [\-\-depends\-on DEPENDS_ON] [\-\-dry\-run] [\-\-from\-database] [\-e]
|
||||
@ -509,60 +488,6 @@ path of the input archive
|
||||
\fB\-o\fR \fI\,OUTPUT\/\fR, \fB\-\-output\fR \fI\,OUTPUT\/\fR
|
||||
root path of the extracted files
|
||||
|
||||
.SH COMMAND \fI\,'ahriman repo\-setup'\/\fR
|
||||
usage: ahriman repo\-setup [\-h] [\-\-build\-as\-user BUILD_AS_USER] [\-\-build\-command BUILD_COMMAND]
|
||||
[\-\-from\-configuration FROM_CONFIGURATION] [\-\-makeflags\-jobs | \-\-no\-makeflags\-jobs]
|
||||
[\-\-multilib | \-\-no\-multilib] \-\-packager PACKAGER \-\-repository REPOSITORY [\-\-sign\-key SIGN_KEY]
|
||||
[\-\-sign\-target {disabled,packages,repository}] [\-\-web\-port WEB_PORT]
|
||||
[\-\-web\-unix\-socket WEB_UNIX_SOCKET]
|
||||
|
||||
create initial service configuration, requires root
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman repo\-setup'\/\fR
|
||||
.TP
|
||||
\fB\-\-build\-as\-user\fR \fI\,BUILD_AS_USER\/\fR
|
||||
force makepkg user to the specific one
|
||||
|
||||
.TP
|
||||
\fB\-\-build\-command\fR \fI\,BUILD_COMMAND\/\fR
|
||||
build command prefix
|
||||
|
||||
.TP
|
||||
\fB\-\-from\-configuration\fR \fI\,FROM_CONFIGURATION\/\fR
|
||||
path to default devtools pacman configuration
|
||||
|
||||
.TP
|
||||
\fB\-\-makeflags\-jobs\fR, \fB\-\-no\-makeflags\-jobs\fR
|
||||
append MAKEFLAGS variable with parallelism set to number of cores (default: True)
|
||||
|
||||
.TP
|
||||
\fB\-\-multilib\fR, \fB\-\-no\-multilib\fR
|
||||
add or do not multilib repository (default: True)
|
||||
|
||||
.TP
|
||||
\fB\-\-packager\fR \fI\,PACKAGER\/\fR
|
||||
packager name and email
|
||||
|
||||
.TP
|
||||
\fB\-\-repository\fR \fI\,REPOSITORY\/\fR
|
||||
repository name
|
||||
|
||||
.TP
|
||||
\fB\-\-sign\-key\fR \fI\,SIGN_KEY\/\fR
|
||||
sign key id
|
||||
|
||||
.TP
|
||||
\fB\-\-sign\-target\fR \fI\,{disabled,packages,repository}\/\fR
|
||||
sign options
|
||||
|
||||
.TP
|
||||
\fB\-\-web\-port\fR \fI\,WEB_PORT\/\fR
|
||||
port of the web service
|
||||
|
||||
.TP
|
||||
\fB\-\-web\-unix\-socket\fR \fI\,WEB_UNIX_SOCKET\/\fR
|
||||
path to unix socket used for interprocess communications
|
||||
|
||||
.SH COMMAND \fI\,'ahriman repo\-sign'\/\fR
|
||||
usage: ahriman repo\-sign [\-h] [package ...]
|
||||
|
||||
@ -602,8 +527,8 @@ run triggers on empty build result as configured by settings
|
||||
instead of running all triggers as set by configuration, just process specified ones in order of mention
|
||||
|
||||
.SH COMMAND \fI\,'ahriman repo\-update'\/\fR
|
||||
usage: ahriman repo\-update [\-h] [\-\-dry\-run] [\-e] [\-\-aur | \-\-no\-aur] [\-\-local | \-\-no\-local] [\-\-manual | \-\-no\-manual]
|
||||
[\-\-vcs | \-\-no\-vcs] [\-y]
|
||||
usage: ahriman repo\-update [\-h] [\-\-aur | \-\-no\-aur] [\-\-dependencies | \-\-no\-dependencies] [\-\-dry\-run] [\-e]
|
||||
[\-\-local | \-\-no\-local] [\-\-manual | \-\-no\-manual] [\-\-vcs | \-\-no\-vcs] [\-y]
|
||||
[package ...]
|
||||
|
||||
check for packages updates and run build process if requested
|
||||
@ -613,6 +538,14 @@ check for packages updates and run build process if requested
|
||||
filter check by package base
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman repo\-update'\/\fR
|
||||
.TP
|
||||
\fB\-\-aur\fR, \fB\-\-no\-aur\fR
|
||||
enable or disable checking for AUR updates (default: True)
|
||||
|
||||
.TP
|
||||
\fB\-\-dependencies\fR, \fB\-\-no\-dependencies\fR
|
||||
process missing package dependencies (default: True)
|
||||
|
||||
.TP
|
||||
\fB\-\-dry\-run\fR
|
||||
just perform check for updates, same as check command
|
||||
@ -621,10 +554,6 @@ just perform check for updates, same as check command
|
||||
\fB\-e\fR, \fB\-\-exit\-code\fR
|
||||
return non\-zero exit status if result is empty
|
||||
|
||||
.TP
|
||||
\fB\-\-aur\fR, \fB\-\-no\-aur\fR
|
||||
enable or disable checking for AUR updates. Implies \-\-no\-vcs (default: True)
|
||||
|
||||
.TP
|
||||
\fB\-\-local\fR, \fB\-\-no\-local\fR
|
||||
enable or disable checking of local packages for updates (default: True)
|
||||
@ -635,14 +564,133 @@ include or exclude manual updates (default: True)
|
||||
|
||||
.TP
|
||||
\fB\-\-vcs\fR, \fB\-\-no\-vcs\fR
|
||||
enable or disable checking of VCS packages (default: True)
|
||||
fetch actual version of VCS packages (default: True)
|
||||
|
||||
.TP
|
||||
\fB\-y\fR, \fB\-\-refresh\fR
|
||||
download fresh package databases from the mirror before actions, \-yy to force refresh even if up to date
|
||||
|
||||
.SH COMMAND \fI\,'ahriman shell'\/\fR
|
||||
usage: ahriman shell [\-h] [code]
|
||||
.SH COMMAND \fI\,'ahriman service\-clean'\/\fR
|
||||
usage: ahriman service\-clean [\-h] [\-\-cache | \-\-no\-cache] [\-\-chroot | \-\-no\-chroot] [\-\-manual | \-\-no\-manual]
|
||||
[\-\-packages | \-\-no\-packages] [\-\-pacman | \-\-no\-pacman]
|
||||
|
||||
remove local caches
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman service\-clean'\/\fR
|
||||
.TP
|
||||
\fB\-\-cache\fR, \fB\-\-no\-cache\fR
|
||||
clear directory with package caches (default: False)
|
||||
|
||||
.TP
|
||||
\fB\-\-chroot\fR, \fB\-\-no\-chroot\fR
|
||||
clear build chroot (default: False)
|
||||
|
||||
.TP
|
||||
\fB\-\-manual\fR, \fB\-\-no\-manual\fR
|
||||
clear manually added packages queue (default: False)
|
||||
|
||||
.TP
|
||||
\fB\-\-packages\fR, \fB\-\-no\-packages\fR
|
||||
clear directory with built packages (default: False)
|
||||
|
||||
.TP
|
||||
\fB\-\-pacman\fR, \fB\-\-no\-pacman\fR
|
||||
clear directory with pacman local database cache (default: False)
|
||||
|
||||
.SH COMMAND \fI\,'ahriman service\-config'\/\fR
|
||||
usage: ahriman service\-config [\-h] [\-\-secure | \-\-no\-secure]
|
||||
|
||||
dump configuration for the specified architecture
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman service\-config'\/\fR
|
||||
.TP
|
||||
\fB\-\-secure\fR, \fB\-\-no\-secure\fR
|
||||
hide passwords and secrets from output (default: True)
|
||||
|
||||
.SH COMMAND \fI\,'ahriman service\-config\-validate'\/\fR
|
||||
usage: ahriman service\-config\-validate [\-h] [\-e]
|
||||
|
||||
validate configuration and print found errors
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman service\-config\-validate'\/\fR
|
||||
.TP
|
||||
\fB\-e\fR, \fB\-\-exit\-code\fR
|
||||
return non\-zero exit status if configuration is invalid
|
||||
|
||||
.SH COMMAND \fI\,'ahriman service\-key\-import'\/\fR
|
||||
usage: ahriman service\-key\-import [\-h] [\-\-key\-server KEY_SERVER] key
|
||||
|
||||
import PGP key from public sources to the repository user
|
||||
|
||||
.TP
|
||||
\fBkey\fR
|
||||
PGP key to import from public server
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman service\-key\-import'\/\fR
|
||||
.TP
|
||||
\fB\-\-key\-server\fR \fI\,KEY_SERVER\/\fR
|
||||
key server for key import
|
||||
|
||||
.SH COMMAND \fI\,'ahriman service\-setup'\/\fR
|
||||
usage: ahriman service\-setup [\-h] [\-\-build\-as\-user BUILD_AS_USER] [\-\-build\-command BUILD_COMMAND]
|
||||
[\-\-from\-configuration FROM_CONFIGURATION] [\-\-makeflags\-jobs | \-\-no\-makeflags\-jobs]
|
||||
[\-\-mirror MIRROR] [\-\-multilib | \-\-no\-multilib] \-\-packager PACKAGER \-\-repository REPOSITORY
|
||||
[\-\-sign\-key SIGN_KEY] [\-\-sign\-target {disabled,packages,repository}] [\-\-web\-port WEB_PORT]
|
||||
[\-\-web\-unix\-socket WEB_UNIX_SOCKET]
|
||||
|
||||
create initial service configuration, requires root
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman service\-setup'\/\fR
|
||||
.TP
|
||||
\fB\-\-build\-as\-user\fR \fI\,BUILD_AS_USER\/\fR
|
||||
force makepkg user to the specific one
|
||||
|
||||
.TP
|
||||
\fB\-\-build\-command\fR \fI\,BUILD_COMMAND\/\fR
|
||||
build command prefix
|
||||
|
||||
.TP
|
||||
\fB\-\-from\-configuration\fR \fI\,FROM_CONFIGURATION\/\fR
|
||||
path to default devtools pacman configuration
|
||||
|
||||
.TP
|
||||
\fB\-\-makeflags\-jobs\fR, \fB\-\-no\-makeflags\-jobs\fR
|
||||
append MAKEFLAGS variable with parallelism set to number of cores (default: True)
|
||||
|
||||
.TP
|
||||
\fB\-\-mirror\fR \fI\,MIRROR\/\fR
|
||||
use the specified explicitly mirror instead of including mirrorlist
|
||||
|
||||
.TP
|
||||
\fB\-\-multilib\fR, \fB\-\-no\-multilib\fR
|
||||
add or do not multilib repository (default: True)
|
||||
|
||||
.TP
|
||||
\fB\-\-packager\fR \fI\,PACKAGER\/\fR
|
||||
packager name and email
|
||||
|
||||
.TP
|
||||
\fB\-\-repository\fR \fI\,REPOSITORY\/\fR
|
||||
repository name
|
||||
|
||||
.TP
|
||||
\fB\-\-sign\-key\fR \fI\,SIGN_KEY\/\fR
|
||||
sign key id
|
||||
|
||||
.TP
|
||||
\fB\-\-sign\-target\fR \fI\,{disabled,packages,repository}\/\fR
|
||||
sign options
|
||||
|
||||
.TP
|
||||
\fB\-\-web\-port\fR \fI\,WEB_PORT\/\fR
|
||||
port of the web service
|
||||
|
||||
.TP
|
||||
\fB\-\-web\-unix\-socket\fR \fI\,WEB_UNIX_SOCKET\/\fR
|
||||
path to unix socket used for interprocess communications
|
||||
|
||||
.SH COMMAND \fI\,'ahriman service\-shell'\/\fR
|
||||
usage: ahriman service\-shell [\-h] [code]
|
||||
|
||||
drop into python shell while having created application
|
||||
|
||||
@ -700,11 +748,6 @@ remove user from the user mapping and update the configuration
|
||||
\fBusername\fR
|
||||
username for web service
|
||||
|
||||
.SH COMMAND \fI\,'ahriman version'\/\fR
|
||||
usage: ahriman version [\-h]
|
||||
|
||||
print application and its dependencies versions
|
||||
|
||||
.SH COMMAND \fI\,'ahriman web'\/\fR
|
||||
usage: ahriman web [\-h]
|
||||
|
||||
|
@ -116,6 +116,14 @@ ahriman.application.handlers.search module
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.application.handlers.service\_updates module
|
||||
----------------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.application.handlers.service_updates
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.application.handlers.setup module
|
||||
-----------------------------------------
|
||||
|
||||
@ -196,6 +204,14 @@ ahriman.application.handlers.users module
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.application.handlers.validate module
|
||||
--------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.application.handlers.validate
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.application.handlers.versions module
|
||||
--------------------------------------------
|
||||
|
||||
|
37
docs/ahriman.core.configuration.rst
Normal file
37
docs/ahriman.core.configuration.rst
Normal file
@ -0,0 +1,37 @@
|
||||
ahriman.core.configuration package
|
||||
==================================
|
||||
|
||||
Submodules
|
||||
----------
|
||||
|
||||
ahriman.core.configuration.configuration module
|
||||
-----------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.core.configuration.configuration
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.core.configuration.schema module
|
||||
----------------------------------------
|
||||
|
||||
.. automodule:: ahriman.core.configuration.schema
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.core.configuration.validator module
|
||||
-------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.core.configuration.validator
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
Module contents
|
||||
---------------
|
||||
|
||||
.. automodule:: ahriman.core.configuration
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
@ -1,45 +0,0 @@
|
||||
ahriman.core.database.data package
|
||||
==================================
|
||||
|
||||
Submodules
|
||||
----------
|
||||
|
||||
ahriman.core.database.data.package\_remotes module
|
||||
--------------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.core.database.data.package_remotes
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.core.database.data.package\_statuses module
|
||||
---------------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.core.database.data.package_statuses
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.core.database.data.patches module
|
||||
-----------------------------------------
|
||||
|
||||
.. automodule:: ahriman.core.database.data.patches
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.core.database.data.users module
|
||||
---------------------------------------
|
||||
|
||||
.. automodule:: ahriman.core.database.data.users
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
Module contents
|
||||
---------------
|
||||
|
||||
.. automodule:: ahriman.core.database.data
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
@ -44,6 +44,22 @@ ahriman.core.database.migrations.m004\_logs module
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.core.database.migrations.m005\_make\_opt\_depends module
|
||||
----------------------------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.core.database.migrations.m005_make_opt_depends
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.core.database.migrations.m006\_packages\_architecture\_required module
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.core.database.migrations.m006_packages_architecture_required
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
Module contents
|
||||
---------------
|
||||
|
||||
|
@ -7,7 +7,6 @@ Subpackages
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
|
||||
ahriman.core.database.data
|
||||
ahriman.core.database.migrations
|
||||
ahriman.core.database.operations
|
||||
|
||||
|
@ -92,6 +92,14 @@ ahriman.core.formatters.user\_printer module
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.core.formatters.validation\_printer module
|
||||
--------------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.core.formatters.validation_printer
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.core.formatters.version\_printer module
|
||||
-----------------------------------------------
|
||||
|
||||
|
@ -10,6 +10,7 @@ Subpackages
|
||||
ahriman.core.alpm
|
||||
ahriman.core.auth
|
||||
ahriman.core.build_tools
|
||||
ahriman.core.configuration
|
||||
ahriman.core.database
|
||||
ahriman.core.formatters
|
||||
ahriman.core.gitremote
|
||||
@ -24,14 +25,6 @@ Subpackages
|
||||
Submodules
|
||||
----------
|
||||
|
||||
ahriman.core.configuration module
|
||||
---------------------------------
|
||||
|
||||
.. automodule:: ahriman.core.configuration
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.core.exceptions module
|
||||
------------------------------
|
||||
|
||||
|
@ -196,14 +196,6 @@ ahriman.models.user\_access module
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.models.user\_identity module
|
||||
------------------------------------
|
||||
|
||||
.. automodule:: ahriman.models.user_identity
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
Module contents
|
||||
---------------
|
||||
|
||||
|
@ -8,11 +8,28 @@ Subpackages
|
||||
:maxdepth: 4
|
||||
|
||||
ahriman.web.middlewares
|
||||
ahriman.web.schemas
|
||||
ahriman.web.views
|
||||
|
||||
Submodules
|
||||
----------
|
||||
|
||||
ahriman.web.apispec module
|
||||
--------------------------
|
||||
|
||||
.. automodule:: ahriman.web.apispec
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.cors module
|
||||
-----------------------
|
||||
|
||||
.. automodule:: ahriman.web.cors
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.routes module
|
||||
-------------------------
|
||||
|
||||
|
165
docs/ahriman.web.schemas.rst
Normal file
165
docs/ahriman.web.schemas.rst
Normal file
@ -0,0 +1,165 @@
|
||||
ahriman.web.schemas package
|
||||
===========================
|
||||
|
||||
Submodules
|
||||
----------
|
||||
|
||||
ahriman.web.schemas.aur\_package\_schema module
|
||||
-----------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.schemas.aur_package_schema
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.schemas.auth\_schema module
|
||||
---------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.schemas.auth_schema
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.schemas.counters\_schema module
|
||||
-------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.schemas.counters_schema
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.schemas.error\_schema module
|
||||
----------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.schemas.error_schema
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.schemas.internal\_status\_schema module
|
||||
---------------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.schemas.internal_status_schema
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.schemas.log\_schema module
|
||||
--------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.schemas.log_schema
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.schemas.login\_schema module
|
||||
----------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.schemas.login_schema
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.schemas.logs\_schema module
|
||||
---------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.schemas.logs_schema
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.schemas.oauth2\_schema module
|
||||
-----------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.schemas.oauth2_schema
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.schemas.package\_name\_schema module
|
||||
------------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.schemas.package_name_schema
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.schemas.package\_names\_schema module
|
||||
-------------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.schemas.package_names_schema
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.schemas.package\_properties\_schema module
|
||||
------------------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.schemas.package_properties_schema
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.schemas.package\_schema module
|
||||
------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.schemas.package_schema
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.schemas.package\_status\_schema module
|
||||
--------------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.schemas.package_status_schema
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.schemas.pgp\_key\_id\_schema module
|
||||
-----------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.schemas.pgp_key_id_schema
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.schemas.pgp\_key\_schema module
|
||||
-------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.schemas.pgp_key_schema
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.schemas.remote\_schema module
|
||||
-----------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.schemas.remote_schema
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.schemas.search\_schema module
|
||||
-----------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.schemas.search_schema
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.schemas.status\_schema module
|
||||
-----------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.schemas.status_schema
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
Module contents
|
||||
---------------
|
||||
|
||||
.. automodule:: ahriman.web.schemas
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
29
docs/ahriman.web.views.api.rst
Normal file
29
docs/ahriman.web.views.api.rst
Normal file
@ -0,0 +1,29 @@
|
||||
ahriman.web.views.api package
|
||||
=============================
|
||||
|
||||
Submodules
|
||||
----------
|
||||
|
||||
ahriman.web.views.api.docs module
|
||||
---------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.api.docs
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.views.api.swagger module
|
||||
------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.api.swagger
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
Module contents
|
||||
---------------
|
||||
|
||||
.. automodule:: ahriman.web.views.api
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
@ -7,6 +7,7 @@ Subpackages
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
|
||||
ahriman.web.views.api
|
||||
ahriman.web.views.service
|
||||
ahriman.web.views.status
|
||||
ahriman.web.views.user
|
||||
|
@ -81,6 +81,22 @@ In the most cases handlers spawn god class ``ahriman.application.application.App
|
||||
|
||||
Application is designed to run from ``systemd`` services and provides parametrized by architecture timer and service file for that.
|
||||
|
||||
Subcommand design
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
All subcommands are divided into several groups depending on the role they are doing:
|
||||
|
||||
* ``aur`` (``aur-search``) group is for AUR operations.
|
||||
* ``help`` (e.g. ``help``) are system commands.
|
||||
* ``package`` subcommands (e.g. ``package-add``) allow to perform single package actions.
|
||||
* ``patch`` subcommands (e.g. ``pacth-list``) are the special case of ``package`` subcommands introduced in order to control patches for packages.
|
||||
* ``repo`` subcommands (e.g. ``repo-check``) usually perform actions on whole repository.
|
||||
* ``service`` subcommands (e.g. ``service-setup``) perform actions which are related to whole service managing: create repository, show configuration.
|
||||
* ``user`` subcommands (``user-add``) are intended for user management.
|
||||
* ``web`` subcommands are related to web service management.
|
||||
|
||||
For historical reasons and in order to keep backward compatibility some subcommands have aliases to their shorter forms or even other groups, but the service doesn't guarantee that they will remain unchanged.
|
||||
|
||||
Database
|
||||
--------
|
||||
|
||||
@ -98,14 +114,14 @@ Schema and data migrations
|
||||
|
||||
The schema migration are applied according to current ``pragma user_info`` values, located at ``ahriman.core.database.migrations`` package and named as ``m000_migration_name.py`` (the preceding ``m`` is required in order to import migration content for tests). Additional class ``ahriman.core.database.migrations.Migrations`` reads all migrations automatically and applies them in alphabetical order.
|
||||
|
||||
There are also data migrations which are located at ``ahriman.core.database.data`` package and move data from old-style (e.g. json files in filesystem, directory trees, etc) to the database. They are also part of migration and (unlike schema migrations) are applied only at specific version breakpoints (e.g. if ``user_version`` is more than 0 no initial migration will be applied).
|
||||
These migrations also contain data migrations. Though the recommended way is to migrate data directly from SQL requests, sometimes it is required to have external data (like packages list) in order to set correct data. To do so, special method `migrate_data` is used.
|
||||
|
||||
Type conversions
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
By default, it parses rows into python dictionary. In addition, the following pseudo-types are supported:
|
||||
|
||||
* ``Dict[str, Any]``, ``List[Any]`` - for storing JSON data structures in database (technically there is no restriction on types for dictionary keys and values, but it is recommended to use only string keys). The type is stored as ``json`` data type and ``json.loads`` and ``json.dumps`` methods are used in order to read and write from/to database respectively.
|
||||
* ``dict[str, Any]``, ``list[Any]`` - for storing JSON data structures in database (technically there is no restriction on types for dictionary keys and values, but it is recommended to use only string keys). The type is stored as ``json`` data type and ``json.loads`` and ``json.dumps`` methods are used in order to read and write from/to database respectively.
|
||||
|
||||
Basic flows
|
||||
-----------
|
||||
@ -219,7 +235,7 @@ Triggers are extensions which can be used in order to perform any actions on app
|
||||
|
||||
The main idea is to load classes by their full path (e.g. ``ahriman.core.upload.UploadTrigger``) by using ``importlib``: get the last part of the import and treat it as class name, join remain part by ``.`` and interpret as module path, import module and extract attribute from it.
|
||||
|
||||
The loaded triggers will be called with ``ahriman.models.result.Result`` and ``List[Packages]`` arguments, which describes the process result and current repository packages respectively. Any exception raised will be suppressed and will generate an exception message in logs.
|
||||
The loaded triggers will be called with ``ahriman.models.result.Result`` and ``list[Packages]`` arguments, which describes the process result and current repository packages respectively. Any exception raised will be suppressed and will generate an exception message in logs.
|
||||
|
||||
In addition triggers can implement ``on_start`` and ``on_stop`` actions which will be called on the application start and right before the application exit. The ``on_start`` action is usually being called from handlers directly in order to make sure that no trigger will be run when it is not required (e.g. on user management). As soon as ``on_start`` action is called, the additional flag will be set; ``ahriman.core.triggers.TriggerLoader`` class implements ``__del__`` method in which, if the flag is set, the ``on_stop`` actions will be called.
|
||||
|
||||
@ -253,6 +269,7 @@ Web application
|
||||
Web application requires the following python packages to be installed:
|
||||
|
||||
* Core part requires ``aiohttp`` (application itself), ``aiohttp_jinja2`` and ``Jinja2`` (HTML generation from templates).
|
||||
* Additional web features also require ``aiohttp-apispec`` (autogenerated documentation), ``aiohttp_cors`` (CORS support, required by documentation)
|
||||
* In addition, ``aiohttp_debugtoolbar`` is required for debug panel. Please note that this option does not work together with authorization and basically must not be used in production.
|
||||
* In addition, authorization feature requires ``aiohttp_security``, ``aiohttp_session`` and ``cryptography``.
|
||||
* In addition to base authorization dependencies, OAuth2 also requires ``aioauth-client`` library.
|
||||
@ -263,6 +280,13 @@ Middlewares
|
||||
|
||||
Service provides some custom middlewares, e.g. logging every exception (except for user ones) and user authorization.
|
||||
|
||||
HEAD and OPTIONS requests
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
``HEAD`` request is automatically generated by ``ahriman.web.views.base.BaseView`` class. It just calls ``GET`` method, removes any data from body and returns the result. In case if no ``GET`` method available for this view, the ``aiohttp.web.HTTPMethodNotAllowed`` exception will be raised.
|
||||
|
||||
On the other side, ``OPTIONS`` method is implemented in the ``ahriman.web.middlewares.exception_handler.exception_handler`` middleware. In case if ``aiohttp.web.HTTPMethodNotAllowed`` exception is raised and original method was ``OPTIONS``, the middleware handles it, converts to valid request and returns response to user.
|
||||
|
||||
Web views
|
||||
^^^^^^^^^
|
||||
|
||||
@ -272,6 +296,7 @@ REST API supports both form and JSON data, but the last one is recommended.
|
||||
|
||||
Different APIs are separated into different packages:
|
||||
|
||||
* ``ahriman.web.views.api`` not a real API, but some views which provide OpenAPI support.
|
||||
* ``ahriman.web.views.service`` provides views for application controls.
|
||||
* ``ahriman.web.views.status`` package provides REST API for application reporting.
|
||||
* ``ahriman.web.views.user`` package provides login and logout methods which can be called without authorization.
|
||||
|
@ -1,17 +1,18 @@
|
||||
# AUTOMATICALLY GENERATED by `shtab`
|
||||
|
||||
_shtab_ahriman_subparsers=('aur-search' 'search' 'daemon' 'help' 'help-commands-unsafe' 'key-import' 'package-add' 'add' 'package-update' 'package-remove' 'remove' 'package-status' 'status' 'package-status-remove' 'package-status-update' 'status-update' 'patch-add' 'patch-list' 'patch-remove' 'patch-set-add' 'repo-backup' 'repo-check' 'check' 'repo-clean' 'clean' 'repo-config' 'config' 'repo-rebuild' 'rebuild' 'repo-remove-unknown' 'remove-unknown' 'repo-report' 'report' 'repo-restore' 'repo-setup' 'init' 'repo-init' 'setup' 'repo-sign' 'sign' 'repo-status-update' 'repo-sync' 'sync' 'repo-tree' 'repo-triggers' 'repo-update' 'update' 'shell' 'user-add' 'user-list' 'user-remove' 'version' 'web')
|
||||
_shtab_ahriman_subparsers=('aur-search' 'search' 'help' 'help-commands-unsafe' 'help-updates' 'help-version' 'version' 'package-add' 'add' 'package-update' 'package-remove' 'remove' 'package-status' 'status' 'package-status-remove' 'package-status-update' 'status-update' 'patch-add' 'patch-list' 'patch-remove' 'patch-set-add' 'repo-backup' 'repo-check' 'check' 'repo-daemon' 'daemon' 'repo-rebuild' 'rebuild' 'repo-remove-unknown' 'remove-unknown' 'repo-report' 'report' 'repo-restore' 'repo-sign' 'sign' 'repo-status-update' 'repo-sync' 'sync' 'repo-tree' 'repo-triggers' 'repo-update' 'update' 'service-clean' 'clean' 'repo-clean' 'service-config' 'config' 'repo-config' 'service-config-validate' 'config-validate' 'repo-config-validate' 'service-key-import' 'key-import' 'service-setup' 'init' 'repo-init' 'repo-setup' 'setup' 'service-shell' 'shell' 'user-add' 'user-list' 'user-remove' 'web')
|
||||
|
||||
_shtab_ahriman_option_strings=('-h' '--help' '-a' '--architecture' '-c' '--configuration' '--force' '-l' '--lock' '--report' '--no-report' '-q' '--quiet' '--unsafe' '-V' '--version')
|
||||
_shtab_ahriman_aur_search_option_strings=('-h' '--help' '-e' '--exit-code' '--info' '--no-info' '--sort-by')
|
||||
_shtab_ahriman_search_option_strings=('-h' '--help' '-e' '--exit-code' '--info' '--no-info' '--sort-by')
|
||||
_shtab_ahriman_daemon_option_strings=('-h' '--help' '-i' '--interval' '--aur' '--no-aur' '--local' '--no-local' '--manual' '--no-manual' '--vcs' '--no-vcs' '-y' '--refresh')
|
||||
_shtab_ahriman_help_option_strings=('-h' '--help')
|
||||
_shtab_ahriman_help_commands_unsafe_option_strings=('-h' '--help' '--command')
|
||||
_shtab_ahriman_key_import_option_strings=('-h' '--help' '--key-server')
|
||||
_shtab_ahriman_package_add_option_strings=('-h' '--help' '-e' '--exit-code' '-n' '--now' '-y' '--refresh' '-s' '--source' '--without-dependencies')
|
||||
_shtab_ahriman_add_option_strings=('-h' '--help' '-e' '--exit-code' '-n' '--now' '-y' '--refresh' '-s' '--source' '--without-dependencies')
|
||||
_shtab_ahriman_package_update_option_strings=('-h' '--help' '-e' '--exit-code' '-n' '--now' '-y' '--refresh' '-s' '--source' '--without-dependencies')
|
||||
_shtab_ahriman_help_updates_option_strings=('-h' '--help' '-e' '--exit-code')
|
||||
_shtab_ahriman_help_version_option_strings=('-h' '--help')
|
||||
_shtab_ahriman_version_option_strings=('-h' '--help')
|
||||
_shtab_ahriman_package_add_option_strings=('-h' '--help' '--dependencies' '--no-dependencies' '-e' '--exit-code' '-n' '--now' '-y' '--refresh' '-s' '--source')
|
||||
_shtab_ahriman_add_option_strings=('-h' '--help' '--dependencies' '--no-dependencies' '-e' '--exit-code' '-n' '--now' '-y' '--refresh' '-s' '--source')
|
||||
_shtab_ahriman_package_update_option_strings=('-h' '--help' '--dependencies' '--no-dependencies' '-e' '--exit-code' '-n' '--now' '-y' '--refresh' '-s' '--source')
|
||||
_shtab_ahriman_package_remove_option_strings=('-h' '--help')
|
||||
_shtab_ahriman_remove_option_strings=('-h' '--help')
|
||||
_shtab_ahriman_package_status_option_strings=('-h' '--help' '--ahriman' '-e' '--exit-code' '--info' '--no-info' '-s' '--status')
|
||||
@ -26,10 +27,8 @@ _shtab_ahriman_patch_set_add_option_strings=('-h' '--help' '-t' '--track')
|
||||
_shtab_ahriman_repo_backup_option_strings=('-h' '--help')
|
||||
_shtab_ahriman_repo_check_option_strings=('-h' '--help' '-e' '--exit-code' '--vcs' '--no-vcs' '-y' '--refresh')
|
||||
_shtab_ahriman_check_option_strings=('-h' '--help' '-e' '--exit-code' '--vcs' '--no-vcs' '-y' '--refresh')
|
||||
_shtab_ahriman_repo_clean_option_strings=('-h' '--help' '--cache' '--no-cache' '--chroot' '--no-chroot' '--manual' '--no-manual' '--packages' '--no-packages' '--pacman' '--no-pacman')
|
||||
_shtab_ahriman_clean_option_strings=('-h' '--help' '--cache' '--no-cache' '--chroot' '--no-chroot' '--manual' '--no-manual' '--packages' '--no-packages' '--pacman' '--no-pacman')
|
||||
_shtab_ahriman_repo_config_option_strings=('-h' '--help')
|
||||
_shtab_ahriman_config_option_strings=('-h' '--help')
|
||||
_shtab_ahriman_repo_daemon_option_strings=('-h' '--help' '-i' '--interval' '--aur' '--no-aur' '--dependencies' '--no-dependencies' '--local' '--no-local' '--manual' '--no-manual' '--vcs' '--no-vcs' '-y' '--refresh')
|
||||
_shtab_ahriman_daemon_option_strings=('-h' '--help' '-i' '--interval' '--aur' '--no-aur' '--dependencies' '--no-dependencies' '--local' '--no-local' '--manual' '--no-manual' '--vcs' '--no-vcs' '-y' '--refresh')
|
||||
_shtab_ahriman_repo_rebuild_option_strings=('-h' '--help' '--depends-on' '--dry-run' '--from-database' '-e' '--exit-code')
|
||||
_shtab_ahriman_rebuild_option_strings=('-h' '--help' '--depends-on' '--dry-run' '--from-database' '-e' '--exit-code')
|
||||
_shtab_ahriman_repo_remove_unknown_option_strings=('-h' '--help' '--dry-run')
|
||||
@ -37,10 +36,6 @@ _shtab_ahriman_remove_unknown_option_strings=('-h' '--help' '--dry-run')
|
||||
_shtab_ahriman_repo_report_option_strings=('-h' '--help')
|
||||
_shtab_ahriman_report_option_strings=('-h' '--help')
|
||||
_shtab_ahriman_repo_restore_option_strings=('-h' '--help' '-o' '--output')
|
||||
_shtab_ahriman_repo_setup_option_strings=('-h' '--help' '--build-as-user' '--build-command' '--from-configuration' '--makeflags-jobs' '--no-makeflags-jobs' '--multilib' '--no-multilib' '--packager' '--repository' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket')
|
||||
_shtab_ahriman_init_option_strings=('-h' '--help' '--build-as-user' '--build-command' '--from-configuration' '--makeflags-jobs' '--no-makeflags-jobs' '--multilib' '--no-multilib' '--packager' '--repository' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket')
|
||||
_shtab_ahriman_repo_init_option_strings=('-h' '--help' '--build-as-user' '--build-command' '--from-configuration' '--makeflags-jobs' '--no-makeflags-jobs' '--multilib' '--no-multilib' '--packager' '--repository' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket')
|
||||
_shtab_ahriman_setup_option_strings=('-h' '--help' '--build-as-user' '--build-command' '--from-configuration' '--makeflags-jobs' '--no-makeflags-jobs' '--multilib' '--no-multilib' '--packager' '--repository' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket')
|
||||
_shtab_ahriman_repo_sign_option_strings=('-h' '--help')
|
||||
_shtab_ahriman_sign_option_strings=('-h' '--help')
|
||||
_shtab_ahriman_repo_status_update_option_strings=('-h' '--help' '-s' '--status')
|
||||
@ -48,20 +43,36 @@ _shtab_ahriman_repo_sync_option_strings=('-h' '--help')
|
||||
_shtab_ahriman_sync_option_strings=('-h' '--help')
|
||||
_shtab_ahriman_repo_tree_option_strings=('-h' '--help')
|
||||
_shtab_ahriman_repo_triggers_option_strings=('-h' '--help')
|
||||
_shtab_ahriman_repo_update_option_strings=('-h' '--help' '--dry-run' '-e' '--exit-code' '--aur' '--no-aur' '--local' '--no-local' '--manual' '--no-manual' '--vcs' '--no-vcs' '-y' '--refresh')
|
||||
_shtab_ahriman_update_option_strings=('-h' '--help' '--dry-run' '-e' '--exit-code' '--aur' '--no-aur' '--local' '--no-local' '--manual' '--no-manual' '--vcs' '--no-vcs' '-y' '--refresh')
|
||||
_shtab_ahriman_repo_update_option_strings=('-h' '--help' '--aur' '--no-aur' '--dependencies' '--no-dependencies' '--dry-run' '-e' '--exit-code' '--local' '--no-local' '--manual' '--no-manual' '--vcs' '--no-vcs' '-y' '--refresh')
|
||||
_shtab_ahriman_update_option_strings=('-h' '--help' '--aur' '--no-aur' '--dependencies' '--no-dependencies' '--dry-run' '-e' '--exit-code' '--local' '--no-local' '--manual' '--no-manual' '--vcs' '--no-vcs' '-y' '--refresh')
|
||||
_shtab_ahriman_service_clean_option_strings=('-h' '--help' '--cache' '--no-cache' '--chroot' '--no-chroot' '--manual' '--no-manual' '--packages' '--no-packages' '--pacman' '--no-pacman')
|
||||
_shtab_ahriman_clean_option_strings=('-h' '--help' '--cache' '--no-cache' '--chroot' '--no-chroot' '--manual' '--no-manual' '--packages' '--no-packages' '--pacman' '--no-pacman')
|
||||
_shtab_ahriman_repo_clean_option_strings=('-h' '--help' '--cache' '--no-cache' '--chroot' '--no-chroot' '--manual' '--no-manual' '--packages' '--no-packages' '--pacman' '--no-pacman')
|
||||
_shtab_ahriman_service_config_option_strings=('-h' '--help' '--secure' '--no-secure')
|
||||
_shtab_ahriman_config_option_strings=('-h' '--help' '--secure' '--no-secure')
|
||||
_shtab_ahriman_repo_config_option_strings=('-h' '--help' '--secure' '--no-secure')
|
||||
_shtab_ahriman_service_config_validate_option_strings=('-h' '--help' '-e' '--exit-code')
|
||||
_shtab_ahriman_config_validate_option_strings=('-h' '--help' '-e' '--exit-code')
|
||||
_shtab_ahriman_repo_config_validate_option_strings=('-h' '--help' '-e' '--exit-code')
|
||||
_shtab_ahriman_service_key_import_option_strings=('-h' '--help' '--key-server')
|
||||
_shtab_ahriman_key_import_option_strings=('-h' '--help' '--key-server')
|
||||
_shtab_ahriman_service_setup_option_strings=('-h' '--help' '--build-as-user' '--build-command' '--from-configuration' '--makeflags-jobs' '--no-makeflags-jobs' '--mirror' '--multilib' '--no-multilib' '--packager' '--repository' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket')
|
||||
_shtab_ahriman_init_option_strings=('-h' '--help' '--build-as-user' '--build-command' '--from-configuration' '--makeflags-jobs' '--no-makeflags-jobs' '--mirror' '--multilib' '--no-multilib' '--packager' '--repository' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket')
|
||||
_shtab_ahriman_repo_init_option_strings=('-h' '--help' '--build-as-user' '--build-command' '--from-configuration' '--makeflags-jobs' '--no-makeflags-jobs' '--mirror' '--multilib' '--no-multilib' '--packager' '--repository' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket')
|
||||
_shtab_ahriman_repo_setup_option_strings=('-h' '--help' '--build-as-user' '--build-command' '--from-configuration' '--makeflags-jobs' '--no-makeflags-jobs' '--mirror' '--multilib' '--no-multilib' '--packager' '--repository' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket')
|
||||
_shtab_ahriman_setup_option_strings=('-h' '--help' '--build-as-user' '--build-command' '--from-configuration' '--makeflags-jobs' '--no-makeflags-jobs' '--mirror' '--multilib' '--no-multilib' '--packager' '--repository' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket')
|
||||
_shtab_ahriman_service_shell_option_strings=('-h' '--help')
|
||||
_shtab_ahriman_shell_option_strings=('-h' '--help')
|
||||
_shtab_ahriman_user_add_option_strings=('-h' '--help' '-p' '--password' '-r' '--role' '-s' '--secure')
|
||||
_shtab_ahriman_user_list_option_strings=('-h' '--help' '-e' '--exit-code' '-r' '--role')
|
||||
_shtab_ahriman_user_remove_option_strings=('-h' '--help')
|
||||
_shtab_ahriman_version_option_strings=('-h' '--help')
|
||||
_shtab_ahriman_web_option_strings=('-h' '--help')
|
||||
|
||||
|
||||
|
||||
_shtab_ahriman_pos_0_choices=('aur-search' 'search' 'daemon' 'help' 'help-commands-unsafe' 'key-import' 'package-add' 'add' 'package-update' 'package-remove' 'remove' 'package-status' 'status' 'package-status-remove' 'package-status-update' 'status-update' 'patch-add' 'patch-list' 'patch-remove' 'patch-set-add' 'repo-backup' 'repo-check' 'check' 'repo-clean' 'clean' 'repo-config' 'config' 'repo-rebuild' 'rebuild' 'repo-remove-unknown' 'remove-unknown' 'repo-report' 'report' 'repo-restore' 'repo-setup' 'init' 'repo-init' 'setup' 'repo-sign' 'sign' 'repo-status-update' 'repo-sync' 'sync' 'repo-tree' 'repo-triggers' 'repo-update' 'update' 'shell' 'user-add' 'user-list' 'user-remove' 'version' 'web')
|
||||
_shtab_ahriman_aur_search___sort_by_choices=('description' 'first_submitted' 'id' 'last_modified' 'maintainer' 'name' 'num_votes' 'out_of_date' 'package_base' 'package_base_id' 'popularity' 'repository' 'url' 'url_path' 'version')
|
||||
_shtab_ahriman_search___sort_by_choices=('description' 'first_submitted' 'id' 'last_modified' 'maintainer' 'name' 'num_votes' 'out_of_date' 'package_base' 'package_base_id' 'popularity' 'repository' 'url' 'url_path' 'version')
|
||||
_shtab_ahriman_pos_0_choices=('aur-search' 'search' 'help' 'help-commands-unsafe' 'help-updates' 'help-version' 'version' 'package-add' 'add' 'package-update' 'package-remove' 'remove' 'package-status' 'status' 'package-status-remove' 'package-status-update' 'status-update' 'patch-add' 'patch-list' 'patch-remove' 'patch-set-add' 'repo-backup' 'repo-check' 'check' 'repo-daemon' 'daemon' 'repo-rebuild' 'rebuild' 'repo-remove-unknown' 'remove-unknown' 'repo-report' 'report' 'repo-restore' 'repo-sign' 'sign' 'repo-status-update' 'repo-sync' 'sync' 'repo-tree' 'repo-triggers' 'repo-update' 'update' 'service-clean' 'clean' 'repo-clean' 'service-config' 'config' 'repo-config' 'service-config-validate' 'config-validate' 'repo-config-validate' 'service-key-import' 'key-import' 'service-setup' 'init' 'repo-init' 'repo-setup' 'setup' 'service-shell' 'shell' 'user-add' 'user-list' 'user-remove' 'web')
|
||||
_shtab_ahriman_aur_search___sort_by_choices=('description' 'first_submitted' 'id' 'last_modified' 'maintainer' 'name' 'num_votes' 'out_of_date' 'package_base' 'package_base_id' 'popularity' 'repository' 'submitter' 'url' 'url_path' 'version')
|
||||
_shtab_ahriman_search___sort_by_choices=('description' 'first_submitted' 'id' 'last_modified' 'maintainer' 'name' 'num_votes' 'out_of_date' 'package_base' 'package_base_id' 'popularity' 'repository' 'submitter' 'url' 'url_path' 'version')
|
||||
_shtab_ahriman_package_add__s_choices=('auto' 'archive' 'aur' 'directory' 'local' 'remote' 'repository')
|
||||
_shtab_ahriman_package_add___source_choices=('auto' 'archive' 'aur' 'directory' 'local' 'remote' 'repository')
|
||||
_shtab_ahriman_add__s_choices=('auto' 'archive' 'aur' 'directory' 'local' 'remote' 'repository')
|
||||
@ -76,12 +87,13 @@ _shtab_ahriman_package_status_update__s_choices=('unknown' 'pending' 'building'
|
||||
_shtab_ahriman_package_status_update___status_choices=('unknown' 'pending' 'building' 'failed' 'success')
|
||||
_shtab_ahriman_status_update__s_choices=('unknown' 'pending' 'building' 'failed' 'success')
|
||||
_shtab_ahriman_status_update___status_choices=('unknown' 'pending' 'building' 'failed' 'success')
|
||||
_shtab_ahriman_repo_setup___sign_target_choices=('disabled' 'packages' 'repository')
|
||||
_shtab_ahriman_init___sign_target_choices=('disabled' 'packages' 'repository')
|
||||
_shtab_ahriman_repo_init___sign_target_choices=('disabled' 'packages' 'repository')
|
||||
_shtab_ahriman_setup___sign_target_choices=('disabled' 'packages' 'repository')
|
||||
_shtab_ahriman_repo_status_update__s_choices=('unknown' 'pending' 'building' 'failed' 'success')
|
||||
_shtab_ahriman_repo_status_update___status_choices=('unknown' 'pending' 'building' 'failed' 'success')
|
||||
_shtab_ahriman_service_setup___sign_target_choices=('disabled' 'packages' 'repository')
|
||||
_shtab_ahriman_init___sign_target_choices=('disabled' 'packages' 'repository')
|
||||
_shtab_ahriman_repo_init___sign_target_choices=('disabled' 'packages' 'repository')
|
||||
_shtab_ahriman_repo_setup___sign_target_choices=('disabled' 'packages' 'repository')
|
||||
_shtab_ahriman_setup___sign_target_choices=('disabled' 'packages' 'repository')
|
||||
_shtab_ahriman_user_add__r_choices=('unauthorized' 'read' 'reporter' 'full')
|
||||
_shtab_ahriman_user_add___role_choices=('unauthorized' 'read' 'reporter' 'full')
|
||||
_shtab_ahriman_user_list__r_choices=('unauthorized' 'read' 'reporter' 'full')
|
||||
@ -112,54 +124,51 @@ _shtab_ahriman_search__e_nargs=0
|
||||
_shtab_ahriman_search___exit_code_nargs=0
|
||||
_shtab_ahriman_search___info_nargs=0
|
||||
_shtab_ahriman_search___no_info_nargs=0
|
||||
_shtab_ahriman_daemon__h_nargs=0
|
||||
_shtab_ahriman_daemon___help_nargs=0
|
||||
_shtab_ahriman_daemon___aur_nargs=0
|
||||
_shtab_ahriman_daemon___no_aur_nargs=0
|
||||
_shtab_ahriman_daemon___local_nargs=0
|
||||
_shtab_ahriman_daemon___no_local_nargs=0
|
||||
_shtab_ahriman_daemon___manual_nargs=0
|
||||
_shtab_ahriman_daemon___no_manual_nargs=0
|
||||
_shtab_ahriman_daemon___vcs_nargs=0
|
||||
_shtab_ahriman_daemon___no_vcs_nargs=0
|
||||
_shtab_ahriman_daemon__y_nargs=0
|
||||
_shtab_ahriman_daemon___refresh_nargs=0
|
||||
_shtab_ahriman_help__h_nargs=0
|
||||
_shtab_ahriman_help___help_nargs=0
|
||||
_shtab_ahriman_help_commands_unsafe__h_nargs=0
|
||||
_shtab_ahriman_help_commands_unsafe___help_nargs=0
|
||||
_shtab_ahriman_key_import__h_nargs=0
|
||||
_shtab_ahriman_key_import___help_nargs=0
|
||||
_shtab_ahriman_help_updates__h_nargs=0
|
||||
_shtab_ahriman_help_updates___help_nargs=0
|
||||
_shtab_ahriman_help_updates__e_nargs=0
|
||||
_shtab_ahriman_help_updates___exit_code_nargs=0
|
||||
_shtab_ahriman_help_version__h_nargs=0
|
||||
_shtab_ahriman_help_version___help_nargs=0
|
||||
_shtab_ahriman_version__h_nargs=0
|
||||
_shtab_ahriman_version___help_nargs=0
|
||||
_shtab_ahriman_package_add_pos_0_nargs=+
|
||||
_shtab_ahriman_package_add__h_nargs=0
|
||||
_shtab_ahriman_package_add___help_nargs=0
|
||||
_shtab_ahriman_package_add___dependencies_nargs=0
|
||||
_shtab_ahriman_package_add___no_dependencies_nargs=0
|
||||
_shtab_ahriman_package_add__e_nargs=0
|
||||
_shtab_ahriman_package_add___exit_code_nargs=0
|
||||
_shtab_ahriman_package_add__n_nargs=0
|
||||
_shtab_ahriman_package_add___now_nargs=0
|
||||
_shtab_ahriman_package_add__y_nargs=0
|
||||
_shtab_ahriman_package_add___refresh_nargs=0
|
||||
_shtab_ahriman_package_add___without_dependencies_nargs=0
|
||||
_shtab_ahriman_add_pos_0_nargs=+
|
||||
_shtab_ahriman_add__h_nargs=0
|
||||
_shtab_ahriman_add___help_nargs=0
|
||||
_shtab_ahriman_add___dependencies_nargs=0
|
||||
_shtab_ahriman_add___no_dependencies_nargs=0
|
||||
_shtab_ahriman_add__e_nargs=0
|
||||
_shtab_ahriman_add___exit_code_nargs=0
|
||||
_shtab_ahriman_add__n_nargs=0
|
||||
_shtab_ahriman_add___now_nargs=0
|
||||
_shtab_ahriman_add__y_nargs=0
|
||||
_shtab_ahriman_add___refresh_nargs=0
|
||||
_shtab_ahriman_add___without_dependencies_nargs=0
|
||||
_shtab_ahriman_package_update_pos_0_nargs=+
|
||||
_shtab_ahriman_package_update__h_nargs=0
|
||||
_shtab_ahriman_package_update___help_nargs=0
|
||||
_shtab_ahriman_package_update___dependencies_nargs=0
|
||||
_shtab_ahriman_package_update___no_dependencies_nargs=0
|
||||
_shtab_ahriman_package_update__e_nargs=0
|
||||
_shtab_ahriman_package_update___exit_code_nargs=0
|
||||
_shtab_ahriman_package_update__n_nargs=0
|
||||
_shtab_ahriman_package_update___now_nargs=0
|
||||
_shtab_ahriman_package_update__y_nargs=0
|
||||
_shtab_ahriman_package_update___refresh_nargs=0
|
||||
_shtab_ahriman_package_update___without_dependencies_nargs=0
|
||||
_shtab_ahriman_package_remove_pos_0_nargs=+
|
||||
_shtab_ahriman_package_remove__h_nargs=0
|
||||
_shtab_ahriman_package_remove___help_nargs=0
|
||||
@ -221,34 +230,34 @@ _shtab_ahriman_check___vcs_nargs=0
|
||||
_shtab_ahriman_check___no_vcs_nargs=0
|
||||
_shtab_ahriman_check__y_nargs=0
|
||||
_shtab_ahriman_check___refresh_nargs=0
|
||||
_shtab_ahriman_repo_clean__h_nargs=0
|
||||
_shtab_ahriman_repo_clean___help_nargs=0
|
||||
_shtab_ahriman_repo_clean___cache_nargs=0
|
||||
_shtab_ahriman_repo_clean___no_cache_nargs=0
|
||||
_shtab_ahriman_repo_clean___chroot_nargs=0
|
||||
_shtab_ahriman_repo_clean___no_chroot_nargs=0
|
||||
_shtab_ahriman_repo_clean___manual_nargs=0
|
||||
_shtab_ahriman_repo_clean___no_manual_nargs=0
|
||||
_shtab_ahriman_repo_clean___packages_nargs=0
|
||||
_shtab_ahriman_repo_clean___no_packages_nargs=0
|
||||
_shtab_ahriman_repo_clean___pacman_nargs=0
|
||||
_shtab_ahriman_repo_clean___no_pacman_nargs=0
|
||||
_shtab_ahriman_clean__h_nargs=0
|
||||
_shtab_ahriman_clean___help_nargs=0
|
||||
_shtab_ahriman_clean___cache_nargs=0
|
||||
_shtab_ahriman_clean___no_cache_nargs=0
|
||||
_shtab_ahriman_clean___chroot_nargs=0
|
||||
_shtab_ahriman_clean___no_chroot_nargs=0
|
||||
_shtab_ahriman_clean___manual_nargs=0
|
||||
_shtab_ahriman_clean___no_manual_nargs=0
|
||||
_shtab_ahriman_clean___packages_nargs=0
|
||||
_shtab_ahriman_clean___no_packages_nargs=0
|
||||
_shtab_ahriman_clean___pacman_nargs=0
|
||||
_shtab_ahriman_clean___no_pacman_nargs=0
|
||||
_shtab_ahriman_repo_config__h_nargs=0
|
||||
_shtab_ahriman_repo_config___help_nargs=0
|
||||
_shtab_ahriman_config__h_nargs=0
|
||||
_shtab_ahriman_config___help_nargs=0
|
||||
_shtab_ahriman_repo_daemon__h_nargs=0
|
||||
_shtab_ahriman_repo_daemon___help_nargs=0
|
||||
_shtab_ahriman_repo_daemon___aur_nargs=0
|
||||
_shtab_ahriman_repo_daemon___no_aur_nargs=0
|
||||
_shtab_ahriman_repo_daemon___dependencies_nargs=0
|
||||
_shtab_ahriman_repo_daemon___no_dependencies_nargs=0
|
||||
_shtab_ahriman_repo_daemon___local_nargs=0
|
||||
_shtab_ahriman_repo_daemon___no_local_nargs=0
|
||||
_shtab_ahriman_repo_daemon___manual_nargs=0
|
||||
_shtab_ahriman_repo_daemon___no_manual_nargs=0
|
||||
_shtab_ahriman_repo_daemon___vcs_nargs=0
|
||||
_shtab_ahriman_repo_daemon___no_vcs_nargs=0
|
||||
_shtab_ahriman_repo_daemon__y_nargs=0
|
||||
_shtab_ahriman_repo_daemon___refresh_nargs=0
|
||||
_shtab_ahriman_daemon__h_nargs=0
|
||||
_shtab_ahriman_daemon___help_nargs=0
|
||||
_shtab_ahriman_daemon___aur_nargs=0
|
||||
_shtab_ahriman_daemon___no_aur_nargs=0
|
||||
_shtab_ahriman_daemon___dependencies_nargs=0
|
||||
_shtab_ahriman_daemon___no_dependencies_nargs=0
|
||||
_shtab_ahriman_daemon___local_nargs=0
|
||||
_shtab_ahriman_daemon___no_local_nargs=0
|
||||
_shtab_ahriman_daemon___manual_nargs=0
|
||||
_shtab_ahriman_daemon___no_manual_nargs=0
|
||||
_shtab_ahriman_daemon___vcs_nargs=0
|
||||
_shtab_ahriman_daemon___no_vcs_nargs=0
|
||||
_shtab_ahriman_daemon__y_nargs=0
|
||||
_shtab_ahriman_daemon___refresh_nargs=0
|
||||
_shtab_ahriman_repo_rebuild__h_nargs=0
|
||||
_shtab_ahriman_repo_rebuild___help_nargs=0
|
||||
_shtab_ahriman_repo_rebuild___dry_run_nargs=0
|
||||
@ -273,30 +282,6 @@ _shtab_ahriman_report__h_nargs=0
|
||||
_shtab_ahriman_report___help_nargs=0
|
||||
_shtab_ahriman_repo_restore__h_nargs=0
|
||||
_shtab_ahriman_repo_restore___help_nargs=0
|
||||
_shtab_ahriman_repo_setup__h_nargs=0
|
||||
_shtab_ahriman_repo_setup___help_nargs=0
|
||||
_shtab_ahriman_repo_setup___makeflags_jobs_nargs=0
|
||||
_shtab_ahriman_repo_setup___no_makeflags_jobs_nargs=0
|
||||
_shtab_ahriman_repo_setup___multilib_nargs=0
|
||||
_shtab_ahriman_repo_setup___no_multilib_nargs=0
|
||||
_shtab_ahriman_init__h_nargs=0
|
||||
_shtab_ahriman_init___help_nargs=0
|
||||
_shtab_ahriman_init___makeflags_jobs_nargs=0
|
||||
_shtab_ahriman_init___no_makeflags_jobs_nargs=0
|
||||
_shtab_ahriman_init___multilib_nargs=0
|
||||
_shtab_ahriman_init___no_multilib_nargs=0
|
||||
_shtab_ahriman_repo_init__h_nargs=0
|
||||
_shtab_ahriman_repo_init___help_nargs=0
|
||||
_shtab_ahriman_repo_init___makeflags_jobs_nargs=0
|
||||
_shtab_ahriman_repo_init___no_makeflags_jobs_nargs=0
|
||||
_shtab_ahriman_repo_init___multilib_nargs=0
|
||||
_shtab_ahriman_repo_init___no_multilib_nargs=0
|
||||
_shtab_ahriman_setup__h_nargs=0
|
||||
_shtab_ahriman_setup___help_nargs=0
|
||||
_shtab_ahriman_setup___makeflags_jobs_nargs=0
|
||||
_shtab_ahriman_setup___no_makeflags_jobs_nargs=0
|
||||
_shtab_ahriman_setup___multilib_nargs=0
|
||||
_shtab_ahriman_setup___no_multilib_nargs=0
|
||||
_shtab_ahriman_repo_sign_pos_0_nargs=*
|
||||
_shtab_ahriman_repo_sign__h_nargs=0
|
||||
_shtab_ahriman_repo_sign___help_nargs=0
|
||||
@ -317,11 +302,13 @@ _shtab_ahriman_repo_triggers___help_nargs=0
|
||||
_shtab_ahriman_repo_update_pos_0_nargs=*
|
||||
_shtab_ahriman_repo_update__h_nargs=0
|
||||
_shtab_ahriman_repo_update___help_nargs=0
|
||||
_shtab_ahriman_repo_update___aur_nargs=0
|
||||
_shtab_ahriman_repo_update___no_aur_nargs=0
|
||||
_shtab_ahriman_repo_update___dependencies_nargs=0
|
||||
_shtab_ahriman_repo_update___no_dependencies_nargs=0
|
||||
_shtab_ahriman_repo_update___dry_run_nargs=0
|
||||
_shtab_ahriman_repo_update__e_nargs=0
|
||||
_shtab_ahriman_repo_update___exit_code_nargs=0
|
||||
_shtab_ahriman_repo_update___aur_nargs=0
|
||||
_shtab_ahriman_repo_update___no_aur_nargs=0
|
||||
_shtab_ahriman_repo_update___local_nargs=0
|
||||
_shtab_ahriman_repo_update___no_local_nargs=0
|
||||
_shtab_ahriman_repo_update___manual_nargs=0
|
||||
@ -333,11 +320,13 @@ _shtab_ahriman_repo_update___refresh_nargs=0
|
||||
_shtab_ahriman_update_pos_0_nargs=*
|
||||
_shtab_ahriman_update__h_nargs=0
|
||||
_shtab_ahriman_update___help_nargs=0
|
||||
_shtab_ahriman_update___aur_nargs=0
|
||||
_shtab_ahriman_update___no_aur_nargs=0
|
||||
_shtab_ahriman_update___dependencies_nargs=0
|
||||
_shtab_ahriman_update___no_dependencies_nargs=0
|
||||
_shtab_ahriman_update___dry_run_nargs=0
|
||||
_shtab_ahriman_update__e_nargs=0
|
||||
_shtab_ahriman_update___exit_code_nargs=0
|
||||
_shtab_ahriman_update___aur_nargs=0
|
||||
_shtab_ahriman_update___no_aur_nargs=0
|
||||
_shtab_ahriman_update___local_nargs=0
|
||||
_shtab_ahriman_update___no_local_nargs=0
|
||||
_shtab_ahriman_update___manual_nargs=0
|
||||
@ -346,6 +335,104 @@ _shtab_ahriman_update___vcs_nargs=0
|
||||
_shtab_ahriman_update___no_vcs_nargs=0
|
||||
_shtab_ahriman_update__y_nargs=0
|
||||
_shtab_ahriman_update___refresh_nargs=0
|
||||
_shtab_ahriman_service_clean__h_nargs=0
|
||||
_shtab_ahriman_service_clean___help_nargs=0
|
||||
_shtab_ahriman_service_clean___cache_nargs=0
|
||||
_shtab_ahriman_service_clean___no_cache_nargs=0
|
||||
_shtab_ahriman_service_clean___chroot_nargs=0
|
||||
_shtab_ahriman_service_clean___no_chroot_nargs=0
|
||||
_shtab_ahriman_service_clean___manual_nargs=0
|
||||
_shtab_ahriman_service_clean___no_manual_nargs=0
|
||||
_shtab_ahriman_service_clean___packages_nargs=0
|
||||
_shtab_ahriman_service_clean___no_packages_nargs=0
|
||||
_shtab_ahriman_service_clean___pacman_nargs=0
|
||||
_shtab_ahriman_service_clean___no_pacman_nargs=0
|
||||
_shtab_ahriman_clean__h_nargs=0
|
||||
_shtab_ahriman_clean___help_nargs=0
|
||||
_shtab_ahriman_clean___cache_nargs=0
|
||||
_shtab_ahriman_clean___no_cache_nargs=0
|
||||
_shtab_ahriman_clean___chroot_nargs=0
|
||||
_shtab_ahriman_clean___no_chroot_nargs=0
|
||||
_shtab_ahriman_clean___manual_nargs=0
|
||||
_shtab_ahriman_clean___no_manual_nargs=0
|
||||
_shtab_ahriman_clean___packages_nargs=0
|
||||
_shtab_ahriman_clean___no_packages_nargs=0
|
||||
_shtab_ahriman_clean___pacman_nargs=0
|
||||
_shtab_ahriman_clean___no_pacman_nargs=0
|
||||
_shtab_ahriman_repo_clean__h_nargs=0
|
||||
_shtab_ahriman_repo_clean___help_nargs=0
|
||||
_shtab_ahriman_repo_clean___cache_nargs=0
|
||||
_shtab_ahriman_repo_clean___no_cache_nargs=0
|
||||
_shtab_ahriman_repo_clean___chroot_nargs=0
|
||||
_shtab_ahriman_repo_clean___no_chroot_nargs=0
|
||||
_shtab_ahriman_repo_clean___manual_nargs=0
|
||||
_shtab_ahriman_repo_clean___no_manual_nargs=0
|
||||
_shtab_ahriman_repo_clean___packages_nargs=0
|
||||
_shtab_ahriman_repo_clean___no_packages_nargs=0
|
||||
_shtab_ahriman_repo_clean___pacman_nargs=0
|
||||
_shtab_ahriman_repo_clean___no_pacman_nargs=0
|
||||
_shtab_ahriman_service_config__h_nargs=0
|
||||
_shtab_ahriman_service_config___help_nargs=0
|
||||
_shtab_ahriman_service_config___secure_nargs=0
|
||||
_shtab_ahriman_service_config___no_secure_nargs=0
|
||||
_shtab_ahriman_config__h_nargs=0
|
||||
_shtab_ahriman_config___help_nargs=0
|
||||
_shtab_ahriman_config___secure_nargs=0
|
||||
_shtab_ahriman_config___no_secure_nargs=0
|
||||
_shtab_ahriman_repo_config__h_nargs=0
|
||||
_shtab_ahriman_repo_config___help_nargs=0
|
||||
_shtab_ahriman_repo_config___secure_nargs=0
|
||||
_shtab_ahriman_repo_config___no_secure_nargs=0
|
||||
_shtab_ahriman_service_config_validate__h_nargs=0
|
||||
_shtab_ahriman_service_config_validate___help_nargs=0
|
||||
_shtab_ahriman_service_config_validate__e_nargs=0
|
||||
_shtab_ahriman_service_config_validate___exit_code_nargs=0
|
||||
_shtab_ahriman_config_validate__h_nargs=0
|
||||
_shtab_ahriman_config_validate___help_nargs=0
|
||||
_shtab_ahriman_config_validate__e_nargs=0
|
||||
_shtab_ahriman_config_validate___exit_code_nargs=0
|
||||
_shtab_ahriman_repo_config_validate__h_nargs=0
|
||||
_shtab_ahriman_repo_config_validate___help_nargs=0
|
||||
_shtab_ahriman_repo_config_validate__e_nargs=0
|
||||
_shtab_ahriman_repo_config_validate___exit_code_nargs=0
|
||||
_shtab_ahriman_service_key_import__h_nargs=0
|
||||
_shtab_ahriman_service_key_import___help_nargs=0
|
||||
_shtab_ahriman_key_import__h_nargs=0
|
||||
_shtab_ahriman_key_import___help_nargs=0
|
||||
_shtab_ahriman_service_setup__h_nargs=0
|
||||
_shtab_ahriman_service_setup___help_nargs=0
|
||||
_shtab_ahriman_service_setup___makeflags_jobs_nargs=0
|
||||
_shtab_ahriman_service_setup___no_makeflags_jobs_nargs=0
|
||||
_shtab_ahriman_service_setup___multilib_nargs=0
|
||||
_shtab_ahriman_service_setup___no_multilib_nargs=0
|
||||
_shtab_ahriman_init__h_nargs=0
|
||||
_shtab_ahriman_init___help_nargs=0
|
||||
_shtab_ahriman_init___makeflags_jobs_nargs=0
|
||||
_shtab_ahriman_init___no_makeflags_jobs_nargs=0
|
||||
_shtab_ahriman_init___multilib_nargs=0
|
||||
_shtab_ahriman_init___no_multilib_nargs=0
|
||||
_shtab_ahriman_repo_init__h_nargs=0
|
||||
_shtab_ahriman_repo_init___help_nargs=0
|
||||
_shtab_ahriman_repo_init___makeflags_jobs_nargs=0
|
||||
_shtab_ahriman_repo_init___no_makeflags_jobs_nargs=0
|
||||
_shtab_ahriman_repo_init___multilib_nargs=0
|
||||
_shtab_ahriman_repo_init___no_multilib_nargs=0
|
||||
_shtab_ahriman_repo_setup__h_nargs=0
|
||||
_shtab_ahriman_repo_setup___help_nargs=0
|
||||
_shtab_ahriman_repo_setup___makeflags_jobs_nargs=0
|
||||
_shtab_ahriman_repo_setup___no_makeflags_jobs_nargs=0
|
||||
_shtab_ahriman_repo_setup___multilib_nargs=0
|
||||
_shtab_ahriman_repo_setup___no_multilib_nargs=0
|
||||
_shtab_ahriman_setup__h_nargs=0
|
||||
_shtab_ahriman_setup___help_nargs=0
|
||||
_shtab_ahriman_setup___makeflags_jobs_nargs=0
|
||||
_shtab_ahriman_setup___no_makeflags_jobs_nargs=0
|
||||
_shtab_ahriman_setup___multilib_nargs=0
|
||||
_shtab_ahriman_setup___no_multilib_nargs=0
|
||||
_shtab_ahriman_service_shell__h_nargs=0
|
||||
_shtab_ahriman_service_shell___help_nargs=0
|
||||
_shtab_ahriman_service_shell__v_nargs=0
|
||||
_shtab_ahriman_service_shell___verbose_nargs=0
|
||||
_shtab_ahriman_shell__h_nargs=0
|
||||
_shtab_ahriman_shell___help_nargs=0
|
||||
_shtab_ahriman_shell__v_nargs=0
|
||||
@ -360,8 +447,6 @@ _shtab_ahriman_user_list__e_nargs=0
|
||||
_shtab_ahriman_user_list___exit_code_nargs=0
|
||||
_shtab_ahriman_user_remove__h_nargs=0
|
||||
_shtab_ahriman_user_remove___help_nargs=0
|
||||
_shtab_ahriman_version__h_nargs=0
|
||||
_shtab_ahriman_version___help_nargs=0
|
||||
_shtab_ahriman_web__h_nargs=0
|
||||
_shtab_ahriman_web___help_nargs=0
|
||||
|
||||
|
@ -10,9 +10,12 @@ _shtab_ahriman_commands() {
|
||||
"check:check for packages updates. Same as repo-update --dry-run --no-manual"
|
||||
"clean:remove local caches"
|
||||
"config:dump configuration for the specified architecture"
|
||||
"config-validate:validate configuration and print found errors"
|
||||
"daemon:start process which periodically will run update process"
|
||||
"help:show help message for application or command and exit"
|
||||
"help-commands-unsafe:list unsafe commands as defined in default args"
|
||||
"help-updates:request AUR for current version and compare with current service version"
|
||||
"help-version:print application and its dependencies versions"
|
||||
"init:create initial service configuration, requires root"
|
||||
"key-import:import PGP key from public sources to the repository user"
|
||||
"package-add:add existing or new package to the build queue"
|
||||
@ -32,6 +35,8 @@ _shtab_ahriman_commands() {
|
||||
"repo-check:check for packages updates. Same as repo-update --dry-run --no-manual"
|
||||
"repo-clean:remove local caches"
|
||||
"repo-config:dump configuration for the specified architecture"
|
||||
"repo-config-validate:validate configuration and print found errors"
|
||||
"repo-daemon:start process which periodically will run update process"
|
||||
"repo-init:create initial service configuration, requires root"
|
||||
"repo-rebuild:force rebuild whole repository"
|
||||
"repo-remove-unknown:remove packages which are missing in AUR and do not have local PKGBUILDs"
|
||||
@ -46,6 +51,12 @@ _shtab_ahriman_commands() {
|
||||
"repo-update:check for packages updates and run build process if requested"
|
||||
"report:generate repository report according to current settings"
|
||||
"search:search for package in AUR using API"
|
||||
"service-clean:remove local caches"
|
||||
"service-config:dump configuration for the specified architecture"
|
||||
"service-config-validate:validate configuration and print found errors"
|
||||
"service-key-import:import PGP key from public sources to the repository user"
|
||||
"service-setup:create initial service configuration, requires root"
|
||||
"service-shell:drop into python shell while having created application"
|
||||
"setup:create initial service configuration, requires root"
|
||||
"shell:drop into python shell while having created application"
|
||||
"sign:(re-)sign packages and repository database according to current settings"
|
||||
@ -76,11 +87,11 @@ _shtab_ahriman_options=(
|
||||
|
||||
_shtab_ahriman_add_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{--dependencies,--no-dependencies}"[process missing package dependencies (default\: \%(default)s)]:dependencies:"
|
||||
{-e,--exit-code}"[return non-zero exit status if result is empty]"
|
||||
{-n,--now}"[run update function after]"
|
||||
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date]"
|
||||
{-s,--source}"[explicitly specify the package source for this command]:source:(auto archive aur directory local remote repository)"
|
||||
"--without-dependencies[do not add dependencies]"
|
||||
"(*):package source (base name, path to local files, remote URL):"
|
||||
)
|
||||
|
||||
@ -88,14 +99,14 @@ _shtab_ahriman_aur_search_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{-e,--exit-code}"[return non-zero exit status if result is empty]"
|
||||
{--info,--no-info}"[show additional package information (default\: \%(default)s)]:info:"
|
||||
"--sort-by[sort field by this field. In case if two packages have the same value of the specified field, they will be always sorted by name]:sort_by:(description first_submitted id last_modified maintainer name num_votes out_of_date package_base package_base_id popularity repository url url_path version)"
|
||||
"--sort-by[sort field by this field. In case if two packages have the same value of the specified field, they will be always sorted by name]:sort_by:(description first_submitted id last_modified maintainer name num_votes out_of_date package_base package_base_id popularity repository submitter url url_path version)"
|
||||
"(*):search terms, can be specified multiple times, the result will match all terms:"
|
||||
)
|
||||
|
||||
_shtab_ahriman_check_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{-e,--exit-code}"[return non-zero exit status if result is empty]"
|
||||
{--vcs,--no-vcs}"[enable or disable checking of VCS packages (default\: \%(default)s)]:vcs:"
|
||||
{--vcs,--no-vcs}"[fetch actual version of VCS packages (default\: \%(default)s)]:vcs:"
|
||||
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date]"
|
||||
"(*)::filter check by package base:"
|
||||
)
|
||||
@ -111,15 +122,22 @@ _shtab_ahriman_clean_options=(
|
||||
|
||||
_shtab_ahriman_config_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{--secure,--no-secure}"[hide passwords and secrets from output (default\: \%(default)s)]:secure:"
|
||||
)
|
||||
|
||||
_shtab_ahriman_config_validate_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{-e,--exit-code}"[return non-zero exit status if configuration is invalid]"
|
||||
)
|
||||
|
||||
_shtab_ahriman_daemon_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{-i,--interval}"[interval between runs in seconds]:interval:"
|
||||
{--aur,--no-aur}"[enable or disable checking for AUR updates. Implies --no-vcs (default\: \%(default)s)]:aur:"
|
||||
{--aur,--no-aur}"[enable or disable checking for AUR updates (default\: \%(default)s)]:aur:"
|
||||
{--dependencies,--no-dependencies}"[process missing package dependencies (default\: \%(default)s)]:dependencies:"
|
||||
{--local,--no-local}"[enable or disable checking of local packages for updates (default\: \%(default)s)]:local:"
|
||||
{--manual,--no-manual}"[include or exclude manual updates (default\: \%(default)s)]:manual:"
|
||||
{--vcs,--no-vcs}"[enable or disable checking of VCS packages (default\: \%(default)s)]:vcs:"
|
||||
{--vcs,--no-vcs}"[fetch actual version of VCS packages (default\: \%(default)s)]:vcs:"
|
||||
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date]"
|
||||
)
|
||||
|
||||
@ -133,12 +151,22 @@ _shtab_ahriman_help_commands_unsafe_options=(
|
||||
"--command[instead of showing commands, just test command line for unsafe subcommand and return 0 in case if command is safe and 1 otherwise]:command:"
|
||||
)
|
||||
|
||||
_shtab_ahriman_help_updates_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{-e,--exit-code}"[return non-zero exit code if updates available]"
|
||||
)
|
||||
|
||||
_shtab_ahriman_help_version_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
)
|
||||
|
||||
_shtab_ahriman_init_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"--build-as-user[force makepkg user to the specific one]:build_as_user:"
|
||||
"--build-command[build command prefix]:build_command:"
|
||||
"--from-configuration[path to default devtools pacman configuration]:from_configuration:"
|
||||
{--makeflags-jobs,--no-makeflags-jobs}"[append MAKEFLAGS variable with parallelism set to number of cores (default\: \%(default)s)]:makeflags_jobs:"
|
||||
"--mirror[use the specified explicitly mirror instead of including mirrorlist]:mirror:"
|
||||
{--multilib,--no-multilib}"[add or do not multilib repository (default\: \%(default)s)]:multilib:"
|
||||
"--packager[packager name and email]:packager:"
|
||||
"--repository[repository name]:repository:"
|
||||
@ -156,11 +184,11 @@ _shtab_ahriman_key_import_options=(
|
||||
|
||||
_shtab_ahriman_package_add_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{--dependencies,--no-dependencies}"[process missing package dependencies (default\: \%(default)s)]:dependencies:"
|
||||
{-e,--exit-code}"[return non-zero exit status if result is empty]"
|
||||
{-n,--now}"[run update function after]"
|
||||
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date]"
|
||||
{-s,--source}"[explicitly specify the package source for this command]:source:(auto archive aur directory local remote repository)"
|
||||
"--without-dependencies[do not add dependencies]"
|
||||
"(*):package source (base name, path to local files, remote URL):"
|
||||
)
|
||||
|
||||
@ -191,11 +219,11 @@ _shtab_ahriman_package_status_update_options=(
|
||||
|
||||
_shtab_ahriman_package_update_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{--dependencies,--no-dependencies}"[process missing package dependencies (default\: \%(default)s)]:dependencies:"
|
||||
{-e,--exit-code}"[return non-zero exit status if result is empty]"
|
||||
{-n,--now}"[run update function after]"
|
||||
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date]"
|
||||
{-s,--source}"[explicitly specify the package source for this command]:source:(auto archive aur directory local remote repository)"
|
||||
"--without-dependencies[do not add dependencies]"
|
||||
"(*):package source (base name, path to local files, remote URL):"
|
||||
)
|
||||
|
||||
@ -251,7 +279,7 @@ _shtab_ahriman_repo_backup_options=(
|
||||
_shtab_ahriman_repo_check_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{-e,--exit-code}"[return non-zero exit status if result is empty]"
|
||||
{--vcs,--no-vcs}"[enable or disable checking of VCS packages (default\: \%(default)s)]:vcs:"
|
||||
{--vcs,--no-vcs}"[fetch actual version of VCS packages (default\: \%(default)s)]:vcs:"
|
||||
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date]"
|
||||
"(*)::filter check by package base:"
|
||||
)
|
||||
@ -267,6 +295,23 @@ _shtab_ahriman_repo_clean_options=(
|
||||
|
||||
_shtab_ahriman_repo_config_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{--secure,--no-secure}"[hide passwords and secrets from output (default\: \%(default)s)]:secure:"
|
||||
)
|
||||
|
||||
_shtab_ahriman_repo_config_validate_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{-e,--exit-code}"[return non-zero exit status if configuration is invalid]"
|
||||
)
|
||||
|
||||
_shtab_ahriman_repo_daemon_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{-i,--interval}"[interval between runs in seconds]:interval:"
|
||||
{--aur,--no-aur}"[enable or disable checking for AUR updates (default\: \%(default)s)]:aur:"
|
||||
{--dependencies,--no-dependencies}"[process missing package dependencies (default\: \%(default)s)]:dependencies:"
|
||||
{--local,--no-local}"[enable or disable checking of local packages for updates (default\: \%(default)s)]:local:"
|
||||
{--manual,--no-manual}"[include or exclude manual updates (default\: \%(default)s)]:manual:"
|
||||
{--vcs,--no-vcs}"[fetch actual version of VCS packages (default\: \%(default)s)]:vcs:"
|
||||
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date]"
|
||||
)
|
||||
|
||||
_shtab_ahriman_repo_init_options=(
|
||||
@ -275,6 +320,7 @@ _shtab_ahriman_repo_init_options=(
|
||||
"--build-command[build command prefix]:build_command:"
|
||||
"--from-configuration[path to default devtools pacman configuration]:from_configuration:"
|
||||
{--makeflags-jobs,--no-makeflags-jobs}"[append MAKEFLAGS variable with parallelism set to number of cores (default\: \%(default)s)]:makeflags_jobs:"
|
||||
"--mirror[use the specified explicitly mirror instead of including mirrorlist]:mirror:"
|
||||
{--multilib,--no-multilib}"[add or do not multilib repository (default\: \%(default)s)]:multilib:"
|
||||
"--packager[packager name and email]:packager:"
|
||||
"--repository[repository name]:repository:"
|
||||
@ -313,6 +359,7 @@ _shtab_ahriman_repo_setup_options=(
|
||||
"--build-command[build command prefix]:build_command:"
|
||||
"--from-configuration[path to default devtools pacman configuration]:from_configuration:"
|
||||
{--makeflags-jobs,--no-makeflags-jobs}"[append MAKEFLAGS variable with parallelism set to number of cores (default\: \%(default)s)]:makeflags_jobs:"
|
||||
"--mirror[use the specified explicitly mirror instead of including mirrorlist]:mirror:"
|
||||
{--multilib,--no-multilib}"[add or do not multilib repository (default\: \%(default)s)]:multilib:"
|
||||
"--packager[packager name and email]:packager:"
|
||||
"--repository[repository name]:repository:"
|
||||
@ -347,12 +394,13 @@ _shtab_ahriman_repo_triggers_options=(
|
||||
|
||||
_shtab_ahriman_repo_update_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{--aur,--no-aur}"[enable or disable checking for AUR updates (default\: \%(default)s)]:aur:"
|
||||
{--dependencies,--no-dependencies}"[process missing package dependencies (default\: \%(default)s)]:dependencies:"
|
||||
"--dry-run[just perform check for updates, same as check command]"
|
||||
{-e,--exit-code}"[return non-zero exit status if result is empty]"
|
||||
{--aur,--no-aur}"[enable or disable checking for AUR updates. Implies --no-vcs (default\: \%(default)s)]:aur:"
|
||||
{--local,--no-local}"[enable or disable checking of local packages for updates (default\: \%(default)s)]:local:"
|
||||
{--manual,--no-manual}"[include or exclude manual updates (default\: \%(default)s)]:manual:"
|
||||
{--vcs,--no-vcs}"[enable or disable checking of VCS packages (default\: \%(default)s)]:vcs:"
|
||||
{--vcs,--no-vcs}"[fetch actual version of VCS packages (default\: \%(default)s)]:vcs:"
|
||||
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date]"
|
||||
"(*)::filter check by package base:"
|
||||
)
|
||||
@ -365,16 +413,63 @@ _shtab_ahriman_search_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{-e,--exit-code}"[return non-zero exit status if result is empty]"
|
||||
{--info,--no-info}"[show additional package information (default\: \%(default)s)]:info:"
|
||||
"--sort-by[sort field by this field. In case if two packages have the same value of the specified field, they will be always sorted by name]:sort_by:(description first_submitted id last_modified maintainer name num_votes out_of_date package_base package_base_id popularity repository url url_path version)"
|
||||
"--sort-by[sort field by this field. In case if two packages have the same value of the specified field, they will be always sorted by name]:sort_by:(description first_submitted id last_modified maintainer name num_votes out_of_date package_base package_base_id popularity repository submitter url url_path version)"
|
||||
"(*):search terms, can be specified multiple times, the result will match all terms:"
|
||||
)
|
||||
|
||||
_shtab_ahriman_service_clean_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{--cache,--no-cache}"[clear directory with package caches (default\: \%(default)s)]:cache:"
|
||||
{--chroot,--no-chroot}"[clear build chroot (default\: \%(default)s)]:chroot:"
|
||||
{--manual,--no-manual}"[clear manually added packages queue (default\: \%(default)s)]:manual:"
|
||||
{--packages,--no-packages}"[clear directory with built packages (default\: \%(default)s)]:packages:"
|
||||
{--pacman,--no-pacman}"[clear directory with pacman local database cache (default\: \%(default)s)]:pacman:"
|
||||
)
|
||||
|
||||
_shtab_ahriman_service_config_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{--secure,--no-secure}"[hide passwords and secrets from output (default\: \%(default)s)]:secure:"
|
||||
)
|
||||
|
||||
_shtab_ahriman_service_config_validate_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{-e,--exit-code}"[return non-zero exit status if configuration is invalid]"
|
||||
)
|
||||
|
||||
_shtab_ahriman_service_key_import_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"--key-server[key server for key import]:key_server:"
|
||||
":PGP key to import from public server:"
|
||||
)
|
||||
|
||||
_shtab_ahriman_service_setup_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"--build-as-user[force makepkg user to the specific one]:build_as_user:"
|
||||
"--build-command[build command prefix]:build_command:"
|
||||
"--from-configuration[path to default devtools pacman configuration]:from_configuration:"
|
||||
{--makeflags-jobs,--no-makeflags-jobs}"[append MAKEFLAGS variable with parallelism set to number of cores (default\: \%(default)s)]:makeflags_jobs:"
|
||||
"--mirror[use the specified explicitly mirror instead of including mirrorlist]:mirror:"
|
||||
{--multilib,--no-multilib}"[add or do not multilib repository (default\: \%(default)s)]:multilib:"
|
||||
"--packager[packager name and email]:packager:"
|
||||
"--repository[repository name]:repository:"
|
||||
"--sign-key[sign key id]:sign_key:"
|
||||
"*--sign-target[sign options]:sign_target:(disabled packages repository)"
|
||||
"--web-port[port of the web service]:web_port:"
|
||||
"--web-unix-socket[path to unix socket used for interprocess communications]:web_unix_socket:"
|
||||
)
|
||||
|
||||
_shtab_ahriman_service_shell_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
":instead of dropping into shell, just execute the specified code:"
|
||||
)
|
||||
|
||||
_shtab_ahriman_setup_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"--build-as-user[force makepkg user to the specific one]:build_as_user:"
|
||||
"--build-command[build command prefix]:build_command:"
|
||||
"--from-configuration[path to default devtools pacman configuration]:from_configuration:"
|
||||
{--makeflags-jobs,--no-makeflags-jobs}"[append MAKEFLAGS variable with parallelism set to number of cores (default\: \%(default)s)]:makeflags_jobs:"
|
||||
"--mirror[use the specified explicitly mirror instead of including mirrorlist]:mirror:"
|
||||
{--multilib,--no-multilib}"[add or do not multilib repository (default\: \%(default)s)]:multilib:"
|
||||
"--packager[packager name and email]:packager:"
|
||||
"--repository[repository name]:repository:"
|
||||
@ -415,12 +510,13 @@ _shtab_ahriman_sync_options=(
|
||||
|
||||
_shtab_ahriman_update_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{--aur,--no-aur}"[enable or disable checking for AUR updates (default\: \%(default)s)]:aur:"
|
||||
{--dependencies,--no-dependencies}"[process missing package dependencies (default\: \%(default)s)]:dependencies:"
|
||||
"--dry-run[just perform check for updates, same as check command]"
|
||||
{-e,--exit-code}"[return non-zero exit status if result is empty]"
|
||||
{--aur,--no-aur}"[enable or disable checking for AUR updates. Implies --no-vcs (default\: \%(default)s)]:aur:"
|
||||
{--local,--no-local}"[enable or disable checking of local packages for updates (default\: \%(default)s)]:local:"
|
||||
{--manual,--no-manual}"[include or exclude manual updates (default\: \%(default)s)]:manual:"
|
||||
{--vcs,--no-vcs}"[enable or disable checking of VCS packages (default\: \%(default)s)]:vcs:"
|
||||
{--vcs,--no-vcs}"[fetch actual version of VCS packages (default\: \%(default)s)]:vcs:"
|
||||
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date]"
|
||||
"(*)::filter check by package base:"
|
||||
)
|
||||
@ -473,9 +569,12 @@ _shtab_ahriman() {
|
||||
check) _arguments -C $_shtab_ahriman_check_options ;;
|
||||
clean) _arguments -C $_shtab_ahriman_clean_options ;;
|
||||
config) _arguments -C $_shtab_ahriman_config_options ;;
|
||||
config-validate) _arguments -C $_shtab_ahriman_config_validate_options ;;
|
||||
daemon) _arguments -C $_shtab_ahriman_daemon_options ;;
|
||||
help) _arguments -C $_shtab_ahriman_help_options ;;
|
||||
help-commands-unsafe) _arguments -C $_shtab_ahriman_help_commands_unsafe_options ;;
|
||||
help-updates) _arguments -C $_shtab_ahriman_help_updates_options ;;
|
||||
help-version) _arguments -C $_shtab_ahriman_help_version_options ;;
|
||||
init) _arguments -C $_shtab_ahriman_init_options ;;
|
||||
key-import) _arguments -C $_shtab_ahriman_key_import_options ;;
|
||||
package-add) _arguments -C $_shtab_ahriman_package_add_options ;;
|
||||
@ -495,6 +594,8 @@ _shtab_ahriman() {
|
||||
repo-check) _arguments -C $_shtab_ahriman_repo_check_options ;;
|
||||
repo-clean) _arguments -C $_shtab_ahriman_repo_clean_options ;;
|
||||
repo-config) _arguments -C $_shtab_ahriman_repo_config_options ;;
|
||||
repo-config-validate) _arguments -C $_shtab_ahriman_repo_config_validate_options ;;
|
||||
repo-daemon) _arguments -C $_shtab_ahriman_repo_daemon_options ;;
|
||||
repo-init) _arguments -C $_shtab_ahriman_repo_init_options ;;
|
||||
repo-rebuild) _arguments -C $_shtab_ahriman_repo_rebuild_options ;;
|
||||
repo-remove-unknown) _arguments -C $_shtab_ahriman_repo_remove_unknown_options ;;
|
||||
@ -509,6 +610,12 @@ _shtab_ahriman() {
|
||||
repo-update) _arguments -C $_shtab_ahriman_repo_update_options ;;
|
||||
report) _arguments -C $_shtab_ahriman_report_options ;;
|
||||
search) _arguments -C $_shtab_ahriman_search_options ;;
|
||||
service-clean) _arguments -C $_shtab_ahriman_service_clean_options ;;
|
||||
service-config) _arguments -C $_shtab_ahriman_service_config_options ;;
|
||||
service-config-validate) _arguments -C $_shtab_ahriman_service_config_validate_options ;;
|
||||
service-key-import) _arguments -C $_shtab_ahriman_service_key_import_options ;;
|
||||
service-setup) _arguments -C $_shtab_ahriman_service_setup_options ;;
|
||||
service-shell) _arguments -C $_shtab_ahriman_service_shell_options ;;
|
||||
setup) _arguments -C $_shtab_ahriman_setup_options ;;
|
||||
shell) _arguments -C $_shtab_ahriman_shell_options ;;
|
||||
sign) _arguments -C $_shtab_ahriman_sign_options ;;
|
||||
|
@ -35,7 +35,7 @@ for module in (
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = "ahriman"
|
||||
copyright = "2021-2022, ahriman team"
|
||||
copyright = "2021-2023, ahriman team"
|
||||
author = "ahriman team"
|
||||
|
||||
# The full version, including alpha/beta/rc tags
|
||||
|
@ -12,6 +12,14 @@ There are two variable types which have been added to default ones, they are pat
|
||||
|
||||
Path values, except for casting to ``pathlib.Path`` type, will be also expanded to absolute paths relative to the configuration path. E.g. if path is set to ``ahriman.ini.d/logging.ini`` and root configuration path is ``/etc/ahriman.ini``, the value will be expanded to ``/etc/ahriman.ini.d/logging.ini``. In order to disable path expand, use the full path, e.g. ``/etc/ahriman.ini.d/logging.ini``.
|
||||
|
||||
There is also additional subcommand which will allow to validate configuration and print found errors. In order to do so, run ``service-config-validate`` subcommand, e.g.:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
ahriman -a x86_64 service-config-validate
|
||||
|
||||
It will check current settings on common errors and compare configuration with known schema.
|
||||
|
||||
``settings`` group
|
||||
------------------
|
||||
|
||||
@ -20,11 +28,12 @@ Base configuration settings.
|
||||
* ``include`` - path to directory with configuration files overrides, string, required.
|
||||
* ``database`` - path to SQLite database, string, required.
|
||||
* ``logging`` - path to logging configuration, string, required. Check ``logging.ini`` for reference.
|
||||
* ``suppress_http_log_errors`` - suppress http log errors, boolean, optional, default ``no``. If set to ``yes``, any http log errors (e.g. if web server is not available, but http logging is enabled) will be suppressed.
|
||||
|
||||
``alpm`` group
|
||||
--------------
|
||||
|
||||
libalpm and AUR related configuration.
|
||||
libalpm and AUR related configuration. Group name can refer to architecture, e.g. ``alpm:x86_64`` can be used for x86_64 architecture specific settings.
|
||||
|
||||
* ``database`` - path to pacman system database cache, string, required.
|
||||
* ``mirror`` - package database mirror used by pacman for syncronization, 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.
|
||||
@ -41,6 +50,7 @@ Base authorization settings. ``OAuth`` provider requires ``aioauth-client`` libr
|
||||
* ``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_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 expired during restart.
|
||||
* ``max_age`` - parameter which controls both cookie expiration and token expiration inside the service, integer, optional, default is 7 days.
|
||||
* ``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_scopes`` - scopes list for OAuth2 provider, which will allow retrieving user email (which is used for checking user permissions), e.g. ``https://www.googleapis.com/auth/userinfo.email`` for ``GoogleClient`` or ``user:email`` for ``GithubClient``, space separated list of strings, required in case if ``oauth`` is used.
|
||||
@ -53,13 +63,11 @@ Authorized users are stored inside internal database, if any of external provide
|
||||
|
||||
Build related configuration. Group name can refer to architecture, e.g. ``build:x86_64`` can be used for x86_64 architecture specific settings.
|
||||
|
||||
* ``archbuild_flags`` - additional flags passed to ``archbuild`` command, space separated list of strings, optional.
|
||||
* ``build_command`` - default build command, string, required.
|
||||
* ``build_flags`` - additional ``pkgctl`` flags, 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.
|
||||
* ``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.
|
||||
* ``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 mention.
|
||||
* ``vcs_allowed_age`` - maximal age in seconds of the VCS packages before their version will be updated with its remote source, int, optional, default ``0``.
|
||||
* ``vcs_allowed_age`` - maximal age in seconds of the VCS packages before their version will be updated with its remote source, int, optional, default ``604800``.
|
||||
|
||||
``repository`` group
|
||||
--------------------
|
||||
@ -78,12 +86,36 @@ Settings for signing packages or repository. Group name can refer to architectur
|
||||
* ``key`` - default PGP key, string, required. This key will also be used for database signing if enabled.
|
||||
* ``key_*`` settings - PGP key which will be used for specific packages, string, optional. For example, if there is ``key_yay`` option the specified key will be used for yay package and default key for others.
|
||||
|
||||
``web:*`` groups
|
||||
----------------
|
||||
|
||||
Web server settings. If any of ``host``/``port`` is not set, web integration will be disabled. Group name can refer to architecture, e.g. ``web:x86_64`` can be used for x86_64 architecture specific settings. This feature requires ``aiohttp`` libraries to be installed.
|
||||
|
||||
* ``address`` - optional address in form ``proto://host:port`` (``port`` can be omitted in case of default ``proto`` ports), will be used instead of ``http://{host}:{port}`` in case if set, string, optional. This option is required in case if ``OAuth`` provider is used.
|
||||
* ``debug`` - enable debug toolbar, boolean, optional, default ``no``.
|
||||
* ``debug_check_host`` - check hosts to access debug toolbar, boolean, optional, default ``no``.
|
||||
* ``debug_allowed_hosts`` - allowed hosts to get access to debug toolbar, space separated list of string, optional.
|
||||
* ``host`` - host to bind, string, optional.
|
||||
* ``index_url`` - full url of the repository index page, string, optional.
|
||||
* ``password`` - password to authorize in web service in order to update service status, string, required in case if authorization enabled.
|
||||
* ``port`` - port to bind, int, optional.
|
||||
* ``static_path`` - path to directory with static files, string, required.
|
||||
* ``templates`` - path to templates directory, string, required.
|
||||
* ``unix_socket`` - path to the listening unix socket, string, optional. If set, server will create the socket on the specified address which can (and will) be used by application. Note, that unlike usual host/port configuration, unix socket allows to perform requests without authorization.
|
||||
* ``unix_socket_unsafe`` - set unsafe (o+w) permissions to unix socket, boolean, optional, default ``yes``. This option is enabled by default, because it is supposed that unix socket is created in safe environment (only web service is supposed to be used in unsafe), but it can be disabled by configuration.
|
||||
* ``username`` - username to authorize in web service in order to update service status, string, required in case if authorization enabled.
|
||||
|
||||
``remote-pull`` group
|
||||
---------------------
|
||||
|
||||
Remote git source synchronization settings. Unlike ``Upload`` triggers those triggers are used for PKGBUILD synchronization - fetch from remote repository PKGBUILDs before updating process.
|
||||
|
||||
It supports authorization; to do so you'd need to prefix the url with authorization part, e.g. ``https://key:token@github.com/arcan1s/ahriman.git``. It is highly recommended to use application tokens instead of your user authorization details.
|
||||
It supports authorization; to do so you'd need to prefix the url with authorization part, e.g. ``https://key:token@github.com/arcan1s/ahriman.git``. It is highly recommended to use application tokens instead of your user authorization details. Alternatively, you can use any other option supported by git, e.g.:
|
||||
|
||||
* by SSH key: generate SSH key as ``ahriman`` user and put public part of it to the repository keys.
|
||||
* by git credentials helper: consult with the `related man page <https://git-scm.com/docs/gitcredentials>`_.
|
||||
|
||||
Available options are:
|
||||
|
||||
* ``target`` - list of remote pull triggers to be used, space separated list of strings, optional, defaults to ``gitremote``. It must point to valid section (or to section with architecture), e.g. ``gitremote`` must point to either ``gitremote`` or ``gitremote:x86_64`` (the one with architecture has higher priority).
|
||||
|
||||
@ -98,7 +130,12 @@ Remote pull trigger
|
||||
|
||||
Remote git source synchronization settings. Same as remote pull triggers those triggers are used for PKGBUILD synchronization - push updated PKGBUILDs to the remote repository after build process.
|
||||
|
||||
It supports authorization; to do so you'd need to prefix the url with authorization part, e.g. ``https://key:token@github.com/arcan1s/ahriman.git``. It is highly recommended to use application tokens instead of your user authorization details.
|
||||
It supports authorization; to do so you'd need to prefix the url with authorization part, e.g. ``https://key:token@github.com/arcan1s/ahriman.git``. It is highly recommended to use application tokens instead of your user authorization details. Alternatively, you can use any other option supported by git, e.g.:
|
||||
|
||||
* by SSH key: generate SSH key as ``ahriman`` user and put public part of it to the repository keys.
|
||||
* by git credentials helper: consult with the `related man page <https://git-scm.com/docs/gitcredentials>`_.
|
||||
|
||||
Available options are:
|
||||
|
||||
* ``target`` - list of remote push triggers to be used, space separated list of strings, optional, defaults to ``gitremote``. It must point to valid section (or to section with architecture), e.g. ``gitremote`` must point to either ``gitremote`` or ``gitremote:x86_64`` (the one with architecture has higher priority).
|
||||
|
||||
@ -224,22 +261,4 @@ Requires ``boto3`` library to be installed. Section name must be either ``s3`` (
|
||||
* ``bucket`` - bucket name (e.g. ``bucket``), string, required.
|
||||
* ``chunk_size`` - chunk size for calculating entity tags, int, optional, default 8 * 1024 * 1024.
|
||||
* ``region`` - bucket region (e.g. ``eu-central-1``), string, required.
|
||||
* ``secret_key`` - AWS secret access key, string, required.
|
||||
|
||||
``web:*`` groups
|
||||
----------------
|
||||
|
||||
Web server settings. If any of ``host``/``port`` is not set, web integration will be disabled. Group name can refer to architecture, e.g. ``web:x86_64`` can be used for x86_64 architecture specific settings. This feature requires ``aiohttp`` libraries to be installed.
|
||||
|
||||
* ``address`` - optional address in form ``proto://host:port`` (``port`` can be omitted in case of default ``proto`` ports), will be used instead of ``http://{host}:{port}`` in case if set, string, optional. This option is required in case if ``OAuth`` provider is used.
|
||||
* ``debug`` - enable debug toolbar, boolean, optional, default ``no``.
|
||||
* ``debug_check_host`` - check hosts to access debug toolbar, boolean, optional, default ``no``.
|
||||
* ``debug_allowed_hosts`` - allowed hosts to get access to debug toolbar, space separated list of string, optional.
|
||||
* ``host`` - host to bind, string, optional.
|
||||
* ``index_url`` - full url of the repository index page, string, optional.
|
||||
* ``password`` - password to authorize in web service in order to update service status, string, required in case if authorization enabled.
|
||||
* ``port`` - port to bind, int, optional.
|
||||
* ``static_path`` - path to directory with static files, string, required.
|
||||
* ``templates`` - path to templates directory, string, required.
|
||||
* ``unix_socket`` - path to the listening unix socket, string, optional. If set, server will create the socket on the specified address which can (and will) be used by application. Note, that unlike usual host/port configuration, unix socket allows to perform requests without authorization.
|
||||
* ``username`` - username to authorize in web service in order to update service status, string, required in case if authorization enabled.
|
||||
* ``secret_key`` - AWS secret access key, string, required.
|
191
docs/faq.rst
191
docs/faq.rst
@ -18,7 +18,7 @@ TL;DR
|
||||
.. code-block:: shell
|
||||
|
||||
yay -S ahriman
|
||||
sudo ahriman -a x86_64 repo-setup --packager "ahriman bot <ahriman@example.com>" --repository "repository"
|
||||
ahriman -a x86_64 service-setup --packager "ahriman bot <ahriman@example.com>" --repository "repository"
|
||||
systemctl enable --now ahriman@x86_64.timer
|
||||
|
||||
Long answer
|
||||
@ -26,6 +26,33 @@ Long answer
|
||||
|
||||
The idea is to install the package as usual, create working directory tree, create configuration for ``sudo`` and ``devtools``. Detailed description of the setup instruction can be found :doc:`here <setup>`.
|
||||
|
||||
How to validate settings
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
There is special command which can be used in order to validate current configuration:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
ahriman -a x86_64 service-config-validate --exit-code
|
||||
|
||||
This command will print found errors, based on `cerberus <https://docs.python-cerberus.org/>`_, e.g.:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
auth
|
||||
ssalt: unknown field
|
||||
target: none or more than one rule validate
|
||||
oneof definition 0: unallowed value mapping
|
||||
oneof definition 1: field 'salt' is required
|
||||
oneof definition 2: unallowed value mapping
|
||||
oneof definition 2: field 'salt' is required
|
||||
oneof definition 2: field 'client_id' is required
|
||||
oneof definition 2: field 'client_secret' is required
|
||||
gitremote
|
||||
pull_url: unknown field
|
||||
|
||||
If an additional flag ``--exit-code`` is supplied, the application will return non-zero exit code, which can be used partially in scripts.
|
||||
|
||||
What does "architecture specific" mean / How to configure for different architectures
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@ -117,52 +144,30 @@ Before using this command you will need to create local directory, put ``PKGBUIL
|
||||
How to fetch PKGBUILDs from remote repository
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
For that purpose you could use ``RemotePullTrigger`` trigger. To do so you will need:
|
||||
For that purpose you could use ``RemotePullTrigger`` trigger. To do so you will need to configure trigger as following:
|
||||
|
||||
#.
|
||||
Append ``triggers`` option in ``build`` section with the following line:
|
||||
.. code-block:: ini
|
||||
|
||||
.. code-block:: ini
|
||||
[remote-pull]
|
||||
target = gitremote
|
||||
|
||||
[build]
|
||||
triggers = ahriman.core.gitremote.RemotePullTrigger
|
||||
|
||||
#.
|
||||
Configure trigger as following:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[remote-pull]
|
||||
target = gitremote
|
||||
|
||||
[gitremote]
|
||||
pull_url = https://github.com/username/repository
|
||||
[gitremote]
|
||||
pull_url = https://github.com/username/repository
|
||||
|
||||
During the next application run it will fetch repository from the specified url and will try to find packages there which can be used as local sources.
|
||||
|
||||
How to push updated PKGBUILDs to remote repository
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
For that purpose you'd need to use another trigger called ``RemotePushTrigger``. Configure it as following:
|
||||
For that purpose you'd need to use another trigger called ``RemotePushTrigger``. Configure trigger as following:
|
||||
|
||||
#.
|
||||
Append ``triggers`` option in ``build`` section with the trigger name:
|
||||
.. code-block:: ini
|
||||
|
||||
.. code-block:: ini
|
||||
[remote-push]
|
||||
target = gitremote
|
||||
|
||||
[build]
|
||||
triggers = ahriman.core.gitremote.RemotePushTrigger
|
||||
|
||||
#.
|
||||
Configure trigger as following:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[remote-push]
|
||||
target = gitremote
|
||||
|
||||
[gitremote]
|
||||
push_url = https://github.com/username/repository
|
||||
[gitremote]
|
||||
push_url = https://github.com/username/repository
|
||||
|
||||
Unlike ``RemotePullTrigger`` trigger, the ``RemotePushTrigger`` more likely will require authorization. It is highly recommended to use application tokens for that instead of using your password (e.g. for Github you can generate tokens `here <https://github.com/settings/tokens>`_ with scope ``public_repo``). Authorization can be supplied by using authorization part of the url, e.g. ``https://key:token@github.com/username/repository``.
|
||||
|
||||
@ -214,7 +219,7 @@ TL;DR
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
sudo -u ahriman ahriman key-import ...
|
||||
sudo -u ahriman ahriman service-key-import ...
|
||||
|
||||
How to update VCS packages
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -386,13 +391,16 @@ The following environment variables are supported:
|
||||
* ``AHRIMAN_DEBUG`` - if set all commands will be logged to console.
|
||||
* ``AHRIMAN_FORCE_ROOT`` - force run ahriman as root instead of guessing by subcommand.
|
||||
* ``AHRIMAN_HOST`` - host for the web interface, default is ``0.0.0.0``.
|
||||
* ``AHRIMAN_MULTILIB`` - if set (default) multilib repository will be used, disabled otherwise.
|
||||
* ``AHRIMAN_OUTPUT`` - controls logging handler, e.g. ``syslog``, ``console``. The name must be found in logging configuration. Note that if ``syslog`` (the default) handler is used you will need to mount ``/dev/log`` inside container because it is not available there.
|
||||
* ``AHRIMAN_PACKAGER`` - packager name from which packages will be built, default is ``ahriman bot <ahriman@example.com>``.
|
||||
* ``AHRIMAN_PACMAN_MIRROR`` - override pacman mirror server if set.
|
||||
* ``AHRIMAN_PORT`` - HTTP server port if any, default is empty.
|
||||
* ``AHRIMAN_REPOSITORY`` - repository name, default is ``aur-clone``.
|
||||
* ``AHRIMAN_REPOSITORY_ROOT`` - repository root. Because of filesystem rights it is required to override default repository root. By default, it uses ``ahriman`` directory inside ahriman's home, which can be passed as mount volume.
|
||||
* ``AHRIMAN_UNIX_SOCKET`` - full path to unix socket which is used by web server, default is empty. Note that more likely you would like to put it inside ``AHRIMAN_REPOSITORY_ROOT`` directory (e.g. ``/var/lib/ahriman/ahriman/ahriman-web.sock``) or to ``/tmp``.
|
||||
* ``AHRIMAN_USER`` - ahriman user, usually must not be overwritten, default is ``ahriman``.
|
||||
* ``AHRIMAN_USER`` - ahriman user, usually must not be overwritten, default is ``ahriman``.
|
||||
* ``AHRIMAN_VALIDATE_CONFIGURATION`` - if set validate service configuration
|
||||
|
||||
You can pass any of these variables by using ``-e`` argument, e.g.:
|
||||
|
||||
@ -403,11 +411,11 @@ You can pass any of these variables by using ``-e`` argument, e.g.:
|
||||
Daemon service
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
There is special ``daemon`` subcommand which emulates systemd timer and will perform repository update periodically:
|
||||
There is special ``repo-daemon`` subcommand which emulates systemd timer and will perform repository update periodically:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
docker run --privileged -v /path/to/local/repo:/var/lib/ahriman arcan1s/ahriman:latest daemon
|
||||
docker run --privileged -v /path/to/local/repo:/var/lib/ahriman arcan1s/ahriman:latest repo-daemon
|
||||
|
||||
This command uses same rules as ``repo-update``, thus, e.g. requires ``--privileged`` flag.
|
||||
|
||||
@ -436,6 +444,102 @@ Otherwise, you would need to pass ``AHRIMAN_PORT`` and mount container network t
|
||||
|
||||
docker run --privileged --net=host -e AHRIMAN_PORT=8080 -v /path/to/local/repo:/var/lib/ahriman arcan1s/ahriman:latest
|
||||
|
||||
|
||||
Non-x86_64 architecture setup
|
||||
-----------------------------
|
||||
|
||||
The following section describes how to setup ahriman with architecture different from x86_64, as example i686. For most cases you have base repository available, e.g. archlinux32 repositories for i686 architecture; in case if base repository is not available, steps are a bit different, however, idea remains the same.
|
||||
|
||||
Physical server setup
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
In this example we are going to use files and packages which are provided by official repositories of the used architecture. Note, that versions might be different, thus you need to find correct versions on the distribution web site, e.g. `archlinux32 packages <https://www.archlinux32.org/packages/>`_.
|
||||
|
||||
#.
|
||||
First, considering having base Arch Linux system, we need to install keyring for the specified repositories:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
wget http://pool.mirror.archlinux32.org/i686/core/archlinux32-keyring-20220927-1.0-any.pkg.tar.zst
|
||||
pacman -U archlinux32-keyring-20220927-1.0-any.pkg.tar.zst
|
||||
|
||||
#.
|
||||
In order to run ``devtools`` scripts for custom architecture they also need specific ``makepkg`` configuration, it can be retrieved by installing the ``devtools`` package of the distribution:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
wget http://pool.mirror.archlinux32.org/i686/extra/devtools-20221208-1.0-any.pkg.tar.zst
|
||||
pacman -U devtools-20221208-1.0-any.pkg.tar.zst
|
||||
|
||||
Alternatively, you can create your own ``makepkg`` configuration and save it as ``/usr/share/devtools/makepkg-i686.conf``.
|
||||
|
||||
#.
|
||||
Setup repository as usual:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
ahriman -a i686 service-setup --mirror 'http://de.mirror.archlinux32.org/$arch/$repo'--no-multilib ...
|
||||
|
||||
In addition to usual options, you need to specify the following options:
|
||||
|
||||
* ``--mirror`` - link to the mirrors which will be used instead of official repositories.
|
||||
* ``--no-multilib`` - in the example we are using i686 architecture for which multilib repository doesn't exist.
|
||||
|
||||
Docker container setup
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
There are two possible ways to achieve same setup, by using docker container. The first one is just mount required files inside container and run it as usual (with specific environment variables). Another one is to create own container based on official one:
|
||||
|
||||
#.
|
||||
Clone official container as base:
|
||||
|
||||
.. code-block:: dockerfile
|
||||
|
||||
FROM arcan1s/ahriman:latest
|
||||
|
||||
#.
|
||||
Init pacman keys. This command is required in order to populate distribution keys:
|
||||
|
||||
.. code-block:: dockerfile
|
||||
|
||||
RUN pacman-key --init
|
||||
|
||||
#.
|
||||
Install packages as it was described above:
|
||||
|
||||
.. code-block:: dockerfile
|
||||
|
||||
RUN pacman --noconfirm -Sy wget
|
||||
RUN wget http://pool.mirror.archlinux32.org/i686/extra/devtools-20221208-1.0-any.pkg.tar.zst && pacman --noconfirm -U devtools-20221208-1.0-any.pkg.tar.zst
|
||||
RUN wget http://pool.mirror.archlinux32.org/i686/core/archlinux32-keyring-20220927-1.0-any.pkg.tar.zst && pacman --noconfirm -U archlinux32-keyring-20220927-1.0-any.pkg.tar.zst
|
||||
|
||||
#.
|
||||
At that point you should have full ``Dockerfile`` like:
|
||||
|
||||
.. code-block:: dockerfile
|
||||
|
||||
FROM arcan1s/ahriman:latest
|
||||
|
||||
RUN pacman-key --init
|
||||
|
||||
RUN pacman --noconfirm -Sy wget
|
||||
RUN wget http://pool.mirror.archlinux32.org/i686/extra/devtools-20221208-1.0-any.pkg.tar.zst && pacman --noconfirm -U devtools-20221208-1.0-any.pkg.tar.zst
|
||||
RUN wget http://pool.mirror.archlinux32.org/i686/core/archlinux32-keyring-20220927-1.0-any.pkg.tar.zst && pacman --noconfirm -U archlinux32-keyring-20220927-1.0-any.pkg.tar.zst
|
||||
|
||||
#.
|
||||
After that you can build you own container, e.g.:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
docker build --tag ahriman-i686:latest
|
||||
|
||||
#.
|
||||
Now you can run locally built container as usual with passing environment variables for setup command:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
docker run --privileged -p 8080:8080 -e AHRIMAN_ARCHITECTURE=i686 -e AHRIMAN_PACMAN_MIRROR='http://de.mirror.archlinux32.org/$arch/$repo' -e AHRIMAN_MULTILIB= ahriman-i686:latest
|
||||
|
||||
Remote synchronization
|
||||
----------------------
|
||||
|
||||
@ -774,6 +878,11 @@ How to enable OAuth authorization
|
||||
#.
|
||||
Restart web service ``systemctl restart ahriman-web@x86_64``.
|
||||
|
||||
How to implement own interface
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
You can write your own interface by using API which is provided by the web service. Full autogenerated API documentation is available at ``http://localhost:8080/api-docs``.
|
||||
|
||||
Backup and restore
|
||||
------------------
|
||||
|
||||
@ -784,7 +893,7 @@ The service provides several commands aim to do easy repository backup and resto
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
sudo ahriman repo-backup /tmp/repo.tar.gz
|
||||
ahriman repo-backup /tmp/repo.tar.gz
|
||||
|
||||
This command will pack all configuration files together with database file into the archive specified as command line argument (i.e. ``/tmp/repo.tar.gz``). In addition it will also archive ``cache`` directory (the one which contains local clones used by e.g. local packages) and ``.gnupg`` of the ``ahriman`` user.
|
||||
|
||||
@ -799,7 +908,7 @@ The service provides several commands aim to do easy repository backup and resto
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
sudo ahriman repo-restore /tmp/repo.tar.gz
|
||||
ahriman repo-restore /tmp/repo.tar.gz
|
||||
|
||||
An additional argument ``-o``/``--output`` can be used to specify extraction root (``/`` by default).
|
||||
|
||||
|
@ -19,7 +19,7 @@ Features
|
||||
Live demos
|
||||
----------
|
||||
|
||||
* `Build status page <https://ahriman-demo.arcanis.me>`_. You can login as ``demo`` user by using ``demo`` password. Note, however, you will not be able to run tasks.
|
||||
* `Build status page <https://ahriman-demo.arcanis.me>`_. You can login as ``demo`` user by using ``demo`` password. Note, however, you will not be able to run tasks. `HTTP API documentation <https://ahriman-demo.arcanis.me/api-docs>`_ is also available.
|
||||
* `Repository index <http://repo.arcanis.me/x86_64/index.html>`_.
|
||||
* `Telegram feed <https://t.me/arcanisrepo>`_.
|
||||
|
||||
|
@ -10,9 +10,9 @@ Initial setup
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
sudo ahriman -a x86_64 repo-setup ...
|
||||
sudo ahriman -a x86_64 service-setup ...
|
||||
|
||||
``repo-setup`` literally does the following steps:
|
||||
``service-setup`` literally does the following steps:
|
||||
|
||||
#.
|
||||
Create ``/var/lib/ahriman/.makepkg.conf`` with ``makepkg.conf`` overrides if required (at least you might want to set ``PACKAGER``):
|
||||
@ -24,46 +24,31 @@ Initial setup
|
||||
#.
|
||||
Configure build tools (it is required for correct dependency management system):
|
||||
|
||||
#.
|
||||
Create build command (you can choose any name for command, basically it should be ``{name}-{arch}-build``):
|
||||
#.
|
||||
Create configuration file ``{repository}.conf``:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
ln -s /usr/bin/archbuild /usr/local/bin/ahriman-x86_64-build
|
||||
|
||||
#.
|
||||
Create configuration file (same as previous ``pacman-{name}.conf``):
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
cp /usr/share/devtools/pacman-{extra,ahriman}.conf
|
||||
cp /usr/local/share/devtools-git-poc/pacman.conf.d/{extra,aur-clone}.conf
|
||||
|
||||
#.
|
||||
Change configuration file, add your own repository, add multilib repository etc:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
echo '[multilib]' | tee -a /usr/share/devtools/pacman-ahriman.conf
|
||||
echo 'Include = /etc/pacman.d/mirrorlist' | tee -a /usr/share/devtools/pacman-ahriman.conf
|
||||
echo '[multilib]' | tee -a /usr/local/share/devtools-git-poc/pacman.conf.d/aur-clone.conf
|
||||
echo 'Include = /etc/pacman.d/mirrorlist' | tee -a /usr/local/share/devtools-git-poc/pacman.conf.d/aur-clone.conf
|
||||
|
||||
echo '[aur-clone]' | tee -a /usr/share/devtools/pacman-ahriman.conf
|
||||
echo 'SigLevel = Optional TrustAll' | tee -a /usr/share/devtools/pacman-ahriman.conf
|
||||
echo 'Server = file:///var/lib/ahriman/repository/$arch' | tee -a /usr/share/devtools/pacman-ahriman.conf
|
||||
|
||||
#.
|
||||
Set ``build_command`` option to point to your command:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
echo '[build]' | tee -a /etc/ahriman.ini.d/build.ini
|
||||
echo 'build_command = ahriman-x86_64-build' | tee -a /etc/ahriman.ini.d/build.ini
|
||||
echo '[aur-clone]' | tee -a /usr/local/share/devtools-git-poc/pacman.conf.d/aur-clone.conf
|
||||
echo 'SigLevel = Optional TrustAll' | tee -a /usr/local/share/devtools-git-poc/pacman.conf.d/aur-clone.conf
|
||||
echo 'Server = file:///var/lib/ahriman/repository/$arch' | tee -a /usr/local/share/devtools-git-poc/pacman.conf.d/aur-clone.conf
|
||||
|
||||
#.
|
||||
Configure ``/etc/sudoers.d/ahriman`` to allow running command without a password:
|
||||
Configure ``/etc/sudoers.d/ahriman`` to allow running devtools command without a password:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
echo 'Cmnd_Alias CARCHBUILD_CMD = /usr/local/bin/ahriman-x86_64-build *' | tee -a /etc/sudoers.d/ahriman
|
||||
echo 'Cmnd_Alias CARCHBUILD_CMD = /usr/bin/pkgctl build *' | tee -a /etc/sudoers.d/ahriman
|
||||
echo 'ahriman ALL=(ALL) NOPASSWD: CARCHBUILD_CMD' | tee -a /etc/sudoers.d/ahriman
|
||||
chmod 400 /etc/sudoers.d/ahriman
|
||||
|
||||
@ -88,4 +73,6 @@ Initial setup
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
sudo -u ahriman ahriman -a x86_64 package-add ahriman --now
|
||||
sudo -u ahriman ahriman -a x86_64 package-add ahriman --now --refresh
|
||||
|
||||
The ``--refresh`` flag is required in order to handle local database update.
|
||||
|
@ -125,3 +125,8 @@ Setup the trigger
|
||||
First, put the trigger in any path it can be exported, e.g. by packing the resource into python package (which will lead to import path as ``package.slack_reporter.SlackReporter``) or just put file somewhere it can be accessed by application (e.g. ``/usr/local/lib/slack_reporter.py.SlackReporter``).
|
||||
|
||||
After that run application as usual and receive notification in your slack channel.
|
||||
|
||||
Trigger configuration schema
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Triggers can expose their configuration schema. It can be achieved by implementing ``CONFIGURATION_SCHEMA`` class variable according to `cerberus <https://docs.python-cerberus.org/>`_ documentation. For more details and examples, please refer to built-in triggers implementations.
|
||||
|
@ -1,19 +1,21 @@
|
||||
# Maintainer: Evgeniy Alekseev
|
||||
|
||||
pkgname='ahriman'
|
||||
pkgver=2.5.1
|
||||
pkgver=2.8.0
|
||||
pkgrel=1
|
||||
pkgdesc="ArcH linux ReposItory MANager"
|
||||
arch=('any')
|
||||
url="https://github.com/arcan1s/ahriman"
|
||||
license=('GPL3')
|
||||
depends=('devtools' 'git' 'pyalpm' 'python-inflection' 'python-passlib' 'python-requests' 'python-setuptools' 'python-srcinfo')
|
||||
depends=('devtools-git-poc' 'git' 'pyalpm' 'python-cerberus' 'python-inflection' 'python-passlib' 'python-requests' 'python-srcinfo')
|
||||
makedepends=('python-build' 'python-installer' 'python-wheel')
|
||||
optdepends=('breezy: -bzr packages support'
|
||||
'darcs: -darcs packages support'
|
||||
'mercurial: -hg packages support'
|
||||
'python-aioauth-client: web server with OAuth2 authorization'
|
||||
'python-aiohttp: web server'
|
||||
'python-aiohttp-apispec>=3.0.0: web server'
|
||||
'python-aiohttp-cors: web server'
|
||||
'python-aiohttp-debugtoolbar: web server with enabled debug panel'
|
||||
'python-aiohttp-jinja2: web server'
|
||||
'python-aiohttp-security: web server with authorization'
|
||||
|
@ -9,4 +9,4 @@ User=ahriman
|
||||
Group=ahriman
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
WantedBy=multi-user.target
|
||||
|
@ -2,6 +2,7 @@
|
||||
include = ahriman.ini.d
|
||||
logging = ahriman.ini.d/logging.ini
|
||||
database = /var/lib/ahriman/ahriman.db
|
||||
suppress_http_log_errors = yes
|
||||
|
||||
[alpm]
|
||||
database = /var/lib/pacman
|
||||
@ -18,12 +19,10 @@ oauth_scopes = https://www.googleapis.com/auth/userinfo.email
|
||||
allow_read_only = yes
|
||||
|
||||
[build]
|
||||
archbuild_flags =
|
||||
build_command = extra-x86_64-build
|
||||
build_command = pkgctl
|
||||
ignore_packages =
|
||||
makechrootpkg_flags =
|
||||
makepkg_flags = --nocolor --ignorearch
|
||||
triggers = ahriman.core.report.ReportTrigger ahriman.core.upload.UploadTrigger
|
||||
pkgctl_flags =
|
||||
triggers = ahriman.core.gitremote.RemotePullTrigger ahriman.core.report.ReportTrigger ahriman.core.upload.UploadTrigger ahriman.core.gitremote.RemotePushTrigger
|
||||
vcs_allowed_age = 604800
|
||||
|
||||
[repository]
|
||||
@ -33,6 +32,12 @@ root = /var/lib/ahriman
|
||||
[sign]
|
||||
target =
|
||||
|
||||
[remote-pull]
|
||||
target =
|
||||
|
||||
[remote-push]
|
||||
target =
|
||||
|
||||
[report]
|
||||
target = console
|
||||
|
||||
@ -65,4 +70,5 @@ debug_check_host = no
|
||||
debug_allowed_hosts =
|
||||
host = 127.0.0.1
|
||||
static_path = /usr/share/ahriman/templates/static
|
||||
templates = /usr/share/ahriman/templates
|
||||
templates = /usr/share/ahriman/templates
|
||||
unix_socket_unsafe = yes
|
23
package/share/ahriman/templates/api.jinja2
Normal file
23
package/share/ahriman/templates/api.jinja2
Normal file
@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>ahriman API</title>
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<!-- Embed elements Elements via Web Component -->
|
||||
<script src="https://unpkg.com/@stoplight/elements/web-components.min.js"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/@stoplight/elements/styles.min.css" type="text/css">
|
||||
|
||||
<link rel="shortcut icon" href="/static/favicon.ico">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<elements-api
|
||||
apiDescriptionUrl="/api-docs/swagger.json"
|
||||
router="hash"
|
||||
layout="sidebar"
|
||||
/>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -100,6 +100,7 @@
|
||||
<li><a id="badge-version" class="nav-link" href="https://github.com/arcan1s/ahriman" title="sources"><i class="bi bi-github"></i> ahriman</a></li>
|
||||
<li><a class="nav-link" href="https://github.com/arcan1s/ahriman/releases" title="releases list">releases</a></li>
|
||||
<li><a class="nav-link" href="https://github.com/arcan1s/ahriman/issues" title="issues tracker">report a bug</a></li>
|
||||
<li><a class="nav-link" href="/api-docs" title="API documentation">api</a></li>
|
||||
</ul>
|
||||
|
||||
{% if index_url is not none %}
|
||||
|
14
setup.py
14
setup.py
@ -1,10 +1,10 @@
|
||||
from pathlib import Path
|
||||
from setuptools import find_packages, setup
|
||||
from typing import Any, Dict
|
||||
from typing import Any
|
||||
|
||||
|
||||
metadata_path = Path(__file__).resolve().parent / "src/ahriman/version.py"
|
||||
metadata: Dict[str, Any] = {}
|
||||
metadata: dict[str, Any] = {}
|
||||
with metadata_path.open() as metadata_file:
|
||||
exec(metadata_file.read(), metadata) # pylint: disable=exec-used
|
||||
|
||||
@ -25,14 +25,15 @@ setup(
|
||||
|
||||
packages=find_packages("src"),
|
||||
package_dir={"": "src"},
|
||||
package_data={"": ["py.typed"]},
|
||||
|
||||
dependency_links=[
|
||||
],
|
||||
install_requires=[
|
||||
"cerberus",
|
||||
"inflection",
|
||||
"passlib",
|
||||
"requests",
|
||||
"setuptools",
|
||||
"srcinfo",
|
||||
],
|
||||
setup_requires=[
|
||||
@ -67,6 +68,7 @@ setup(
|
||||
]),
|
||||
# templates
|
||||
("share/ahriman/templates", [
|
||||
"package/share/ahriman/templates/api.jinja2",
|
||||
"package/share/ahriman/templates/build-status.jinja2",
|
||||
"package/share/ahriman/templates/email-index.jinja2",
|
||||
"package/share/ahriman/templates/error.jinja2",
|
||||
@ -139,9 +141,11 @@ setup(
|
||||
],
|
||||
"web": [
|
||||
"Jinja2",
|
||||
"aiohttp",
|
||||
"aiohttp_jinja2",
|
||||
"aioauth-client",
|
||||
"aiohttp",
|
||||
"aiohttp-apispec",
|
||||
"aiohttp_cors",
|
||||
"aiohttp_jinja2",
|
||||
"aiohttp_debugtoolbar",
|
||||
"aiohttp_session",
|
||||
"aiohttp_security",
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -23,7 +23,7 @@ import sys
|
||||
import tempfile
|
||||
|
||||
from pathlib import Path
|
||||
from typing import List, TypeVar
|
||||
from typing import TypeVar
|
||||
|
||||
from ahriman import version
|
||||
from ahriman.application import handlers
|
||||
@ -35,7 +35,7 @@ from ahriman.models.sign_settings import SignSettings
|
||||
from ahriman.models.user_access import UserAccess
|
||||
|
||||
|
||||
__all__: List[str] = []
|
||||
__all__: list[str] = []
|
||||
|
||||
|
||||
# this workaround is for several things
|
||||
@ -70,7 +70,8 @@ def _parser() -> argparse.ArgumentParser:
|
||||
fromfile_prefix_chars="@", formatter_class=_formatter)
|
||||
parser.add_argument("-a", "--architecture", help="target architectures. For several subcommands it can be used "
|
||||
"multiple times", action="append")
|
||||
parser.add_argument("-c", "--configuration", help="configuration path", type=Path, default=Path("/etc/ahriman.ini"))
|
||||
parser.add_argument("-c", "--configuration", help="configuration path", type=Path,
|
||||
default=Path("/etc") / "ahriman.ini")
|
||||
parser.add_argument("--force", help="force run, remove file lock", action="store_true")
|
||||
parser.add_argument("-l", "--lock", help="lock file", type=Path,
|
||||
default=Path(tempfile.gettempdir()) / "ahriman.lock")
|
||||
@ -84,10 +85,10 @@ def _parser() -> argparse.ArgumentParser:
|
||||
subparsers = parser.add_subparsers(title="command", help="command to run", dest="command", required=True)
|
||||
|
||||
_set_aur_search_parser(subparsers)
|
||||
_set_daemon_parser(subparsers)
|
||||
_set_help_parser(subparsers)
|
||||
_set_help_commands_unsafe_parser(subparsers)
|
||||
_set_key_import_parser(subparsers)
|
||||
_set_help_updates_parser(subparsers)
|
||||
_set_help_version_parser(subparsers)
|
||||
_set_package_add_parser(subparsers)
|
||||
_set_package_remove_parser(subparsers)
|
||||
_set_package_status_parser(subparsers)
|
||||
@ -99,24 +100,26 @@ def _parser() -> argparse.ArgumentParser:
|
||||
_set_patch_set_add_parser(subparsers)
|
||||
_set_repo_backup_parser(subparsers)
|
||||
_set_repo_check_parser(subparsers)
|
||||
_set_repo_clean_parser(subparsers)
|
||||
_set_repo_config_parser(subparsers)
|
||||
_set_repo_daemon_parser(subparsers)
|
||||
_set_repo_rebuild_parser(subparsers)
|
||||
_set_repo_remove_unknown_parser(subparsers)
|
||||
_set_repo_report_parser(subparsers)
|
||||
_set_repo_restore_parser(subparsers)
|
||||
_set_repo_setup_parser(subparsers)
|
||||
_set_repo_sign_parser(subparsers)
|
||||
_set_repo_status_update_parser(subparsers)
|
||||
_set_repo_sync_parser(subparsers)
|
||||
_set_repo_tree_parser(subparsers)
|
||||
_set_repo_triggers_parser(subparsers)
|
||||
_set_repo_update_parser(subparsers)
|
||||
_set_shell_parser(subparsers)
|
||||
_set_service_clean_parser(subparsers)
|
||||
_set_service_config_parser(subparsers)
|
||||
_set_service_config_validate_parser(subparsers)
|
||||
_set_service_key_import_parser(subparsers)
|
||||
_set_service_setup_parser(subparsers)
|
||||
_set_service_shell_parser(subparsers)
|
||||
_set_user_add_parser(subparsers)
|
||||
_set_user_list_parser(subparsers)
|
||||
_set_user_remove_parser(subparsers)
|
||||
_set_version_parser(subparsers)
|
||||
_set_web_parser(subparsers)
|
||||
|
||||
return parser
|
||||
@ -146,35 +149,6 @@ def _set_aur_search_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
return parser
|
||||
|
||||
|
||||
def _set_daemon_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for daemon subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("daemon", help="run application as daemon",
|
||||
description="start process which periodically will run update process",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("-i", "--interval", help="interval between runs in seconds", type=int, default=60 * 60 * 12)
|
||||
parser.add_argument("--aur", help="enable or disable checking for AUR updates. Implies --no-vcs",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--local", help="enable or disable checking of local packages for updates",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--manual", help="include or exclude manual updates",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--vcs", help="enable or disable checking of VCS packages",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("-y", "--refresh", help="download fresh package databases from the mirror before actions, "
|
||||
"-yy to force refresh even if up to date",
|
||||
action="count", default=False)
|
||||
parser.set_defaults(handler=handlers.Daemon, dry_run=False, exit_code=False, package=[])
|
||||
return parser
|
||||
|
||||
|
||||
def _set_help_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for listing help subcommand
|
||||
@ -189,8 +163,8 @@ def _set_help_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
description="show help message for application or command and exit",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("command", help="show help message for specific command", nargs="?")
|
||||
parser.set_defaults(handler=handlers.Help, architecture=[""], lock=None, report=False, quiet=True,
|
||||
unsafe=True, parser=_parser)
|
||||
parser.set_defaults(handler=handlers.Help, architecture=[""], lock=None, report=False, quiet=True, unsafe=True,
|
||||
parser=_parser)
|
||||
return parser
|
||||
|
||||
|
||||
@ -213,9 +187,9 @@ def _set_help_commands_unsafe_parser(root: SubParserAction) -> argparse.Argument
|
||||
return parser
|
||||
|
||||
|
||||
def _set_key_import_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
def _set_help_updates_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for key import subcommand
|
||||
add parser for service update check subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
@ -223,16 +197,28 @@ def _set_key_import_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("key-import", help="import PGP key",
|
||||
description="import PGP key from public sources to the repository user",
|
||||
epilog="By default ahriman runs build process with package sources validation "
|
||||
"(in case if signature and keys are available in PKGBUILD). This process will "
|
||||
"fail in case if key is not known for build user. This subcommand can be used "
|
||||
"in order to import the PGP key to user keychain.",
|
||||
parser = root.add_parser("help-updates", help="check for service updates",
|
||||
description="request AUR for current version and compare with current service version",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("--key-server", help="key server for key import", default="keyserver.ubuntu.com")
|
||||
parser.add_argument("key", help="PGP key to import from public server")
|
||||
parser.set_defaults(handler=handlers.KeyImport, architecture=[""], lock=None, report=False)
|
||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit code if updates available", action="store_true")
|
||||
parser.set_defaults(handler=handlers.ServiceUpdates, architecture=[""], lock=None, report=False, quiet=True,
|
||||
unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_help_version_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for version subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("help-version", aliases=["version"], help="application version",
|
||||
description="print application and its dependencies versions", formatter_class=_formatter)
|
||||
parser.set_defaults(handler=handlers.Versions, architecture=[""], lock=None, report=False, quiet=True, unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
@ -260,6 +246,8 @@ def _set_package_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"5) and finally you can add package from AUR.",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("package", help="package source (base name, path to local files, remote URL)", nargs="+")
|
||||
parser.add_argument("--dependencies", help="process missing package dependencies",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty", action="store_true")
|
||||
parser.add_argument("-n", "--now", help="run update function after", action="store_true")
|
||||
parser.add_argument("-y", "--refresh", help="download fresh package databases from the mirror before actions, "
|
||||
@ -267,7 +255,6 @@ def _set_package_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
action="count", default=False)
|
||||
parser.add_argument("-s", "--source", help="explicitly specify the package source for this command",
|
||||
type=PackageSource, choices=enum_values(PackageSource), default=PackageSource.Auto)
|
||||
parser.add_argument("--without-dependencies", help="do not add dependencies", action="store_true")
|
||||
parser.set_defaults(handler=handlers.Add)
|
||||
return parser
|
||||
|
||||
@ -399,7 +386,8 @@ def _set_patch_list_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty", action="store_true")
|
||||
parser.add_argument("-v", "--variable", help="if set, show only patches for specified PKGBUILD variables",
|
||||
action="append")
|
||||
parser.set_defaults(handler=handlers.Patch, action=Action.List, architecture=[""], lock=None, report=False)
|
||||
parser.set_defaults(handler=handlers.Patch, action=Action.List, architecture=[""], lock=None, report=False,
|
||||
unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
@ -481,18 +469,18 @@ def _set_repo_check_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("package", help="filter check by package base", nargs="*")
|
||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty", action="store_true")
|
||||
parser.add_argument("--vcs", help="enable or disable checking of VCS packages",
|
||||
parser.add_argument("--vcs", help="fetch actual version of VCS packages",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("-y", "--refresh", help="download fresh package databases from the mirror before actions, "
|
||||
"-yy to force refresh even if up to date",
|
||||
action="count", default=False)
|
||||
parser.set_defaults(handler=handlers.Update, dry_run=True, aur=True, local=True, manual=False)
|
||||
parser.set_defaults(handler=handlers.Update, dependencies=False, dry_run=True, aur=True, local=True, manual=False)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_repo_clean_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
def _set_repo_daemon_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for repository clean subcommand
|
||||
add parser for daemon subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
@ -500,39 +488,24 @@ def _set_repo_clean_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("repo-clean", aliases=["clean"], help="clean local caches",
|
||||
description="remove local caches",
|
||||
epilog="The subcommand clears every temporary directories (builds, caches etc). Normally "
|
||||
"you should not run this command manually. Also in case if you are going to clear "
|
||||
"the chroot directories you will need root privileges.",
|
||||
parser = root.add_parser("repo-daemon", aliases=["daemon"], help="run application as daemon",
|
||||
description="start process which periodically will run update process",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("--cache", help="clear directory with package caches",
|
||||
action=argparse.BooleanOptionalAction, default=False)
|
||||
parser.add_argument("--chroot", help="clear build chroot", action=argparse.BooleanOptionalAction, default=False)
|
||||
parser.add_argument("--manual", help="clear manually added packages queue",
|
||||
action=argparse.BooleanOptionalAction, default=False)
|
||||
parser.add_argument("--packages", help="clear directory with built packages",
|
||||
action=argparse.BooleanOptionalAction, default=False)
|
||||
parser.add_argument("--pacman", help="clear directory with pacman local database cache",
|
||||
action=argparse.BooleanOptionalAction, default=False)
|
||||
parser.set_defaults(handler=handlers.Clean, quiet=True, unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_repo_config_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for config subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("repo-config", aliases=["config"], help="dump configuration",
|
||||
description="dump configuration for the specified architecture",
|
||||
formatter_class=_formatter)
|
||||
parser.set_defaults(handler=handlers.Dump, lock=None, report=False, quiet=True, unsafe=True)
|
||||
parser.add_argument("-i", "--interval", help="interval between runs in seconds", type=int, default=60 * 60 * 12)
|
||||
parser.add_argument("--aur", help="enable or disable checking for AUR updates",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--dependencies", help="process missing package dependencies",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--local", help="enable or disable checking of local packages for updates",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--manual", help="include or exclude manual updates",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--vcs", help="fetch actual version of VCS packages",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("-y", "--refresh", help="download fresh package databases from the mirror before actions, "
|
||||
"-yy to force refresh even if up to date",
|
||||
action="count", default=False)
|
||||
parser.set_defaults(handler=handlers.Daemon, dry_run=False, exit_code=False, package=[])
|
||||
return parser
|
||||
|
||||
|
||||
@ -616,39 +589,6 @@ def _set_repo_restore_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
return parser
|
||||
|
||||
|
||||
def _set_repo_setup_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for setup subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("repo-setup", aliases=["init", "repo-init", "setup"], help="initial service configuration",
|
||||
description="create initial service configuration, requires root",
|
||||
epilog="Create _minimal_ configuration for the service according to provided options.",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("--build-as-user", help="force makepkg user to the specific one")
|
||||
parser.add_argument("--build-command", help="build command prefix", default="ahriman")
|
||||
parser.add_argument("--from-configuration", help="path to default devtools pacman configuration",
|
||||
type=Path, default=Path("/usr/share/devtools/pacman-extra.conf"))
|
||||
parser.add_argument("--makeflags-jobs", help="append MAKEFLAGS variable with parallelism set to number of cores",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--multilib", help="add or do not multilib repository",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--packager", help="packager name and email", required=True)
|
||||
parser.add_argument("--repository", help="repository name", required=True)
|
||||
parser.add_argument("--sign-key", help="sign key id")
|
||||
parser.add_argument("--sign-target", help="sign options", action="append",
|
||||
type=SignSettings.from_option, choices=enum_values(SignSettings))
|
||||
parser.add_argument("--web-port", help="port of the web service", type=int)
|
||||
parser.add_argument("--web-unix-socket", help="path to unix socket used for interprocess communications", type=Path)
|
||||
parser.set_defaults(handler=handlers.Setup, lock=None, report=False, quiet=True, unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_repo_sign_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for sign subcommand
|
||||
@ -718,7 +658,7 @@ def _set_repo_tree_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
parser = root.add_parser("repo-tree", help="dump repository tree",
|
||||
description="dump repository tree based on packages dependencies",
|
||||
formatter_class=_formatter)
|
||||
parser.set_defaults(handler=handlers.Structure, lock=None, report=False, quiet=True)
|
||||
parser.set_defaults(handler=handlers.Structure, lock=None, report=False, quiet=True, unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
@ -755,15 +695,17 @@ def _set_repo_update_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
description="check for packages updates and run build process if requested",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("package", help="filter check by package base", nargs="*")
|
||||
parser.add_argument("--aur", help="enable or disable checking for AUR updates",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--dependencies", help="process missing package dependencies",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--dry-run", help="just perform check for updates, same as check command", action="store_true")
|
||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty", action="store_true")
|
||||
parser.add_argument("--aur", help="enable or disable checking for AUR updates. Implies --no-vcs",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--local", help="enable or disable checking of local packages for updates",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--manual", help="include or exclude manual updates",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--vcs", help="enable or disable checking of VCS packages",
|
||||
parser.add_argument("--vcs", help="fetch actual version of VCS packages",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("-y", "--refresh", help="download fresh package databases from the mirror before actions, "
|
||||
"-yy to force refresh even if up to date",
|
||||
@ -772,7 +714,132 @@ def _set_repo_update_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
return parser
|
||||
|
||||
|
||||
def _set_shell_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
def _set_service_clean_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for repository clean subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("service-clean", aliases=["clean", "repo-clean"], help="clean local caches",
|
||||
description="remove local caches",
|
||||
epilog="The subcommand clears every temporary directories (builds, caches etc). Normally "
|
||||
"you should not run this command manually. Also in case if you are going to clear "
|
||||
"the chroot directories you will need root privileges.",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("--cache", help="clear directory with package caches",
|
||||
action=argparse.BooleanOptionalAction, default=False)
|
||||
parser.add_argument("--chroot", help="clear build chroot", action=argparse.BooleanOptionalAction, default=False)
|
||||
parser.add_argument("--manual", help="clear manually added packages queue",
|
||||
action=argparse.BooleanOptionalAction, default=False)
|
||||
parser.add_argument("--packages", help="clear directory with built packages",
|
||||
action=argparse.BooleanOptionalAction, default=False)
|
||||
parser.add_argument("--pacman", help="clear directory with pacman local database cache",
|
||||
action=argparse.BooleanOptionalAction, default=False)
|
||||
parser.set_defaults(handler=handlers.Clean, quiet=True, unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_service_config_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for config subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("service-config", aliases=["config", "repo-config"], help="dump configuration",
|
||||
description="dump configuration for the specified architecture",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("--secure", help="hide passwords and secrets from output",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.set_defaults(handler=handlers.Dump, lock=None, report=False, quiet=True, unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_service_config_validate_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for config validation subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("service-config-validate", aliases=["config-validate", "repo-config-validate"],
|
||||
help="validate system configuration",
|
||||
description="validate configuration and print found errors",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if configuration is invalid",
|
||||
action="store_true")
|
||||
parser.set_defaults(handler=handlers.Validate, lock=None, report=False, quiet=True, unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_service_key_import_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for key import subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("service-key-import", aliases=["key-import"], help="import PGP key",
|
||||
description="import PGP key from public sources to the repository user",
|
||||
epilog="By default ahriman runs build process with package sources validation "
|
||||
"(in case if signature and keys are available in PKGBUILD). This process will "
|
||||
"fail in case if key is not known for build user. This subcommand can be used "
|
||||
"in order to import the PGP key to user keychain.",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("--key-server", help="key server for key import", default="keyserver.ubuntu.com")
|
||||
parser.add_argument("key", help="PGP key to import from public server")
|
||||
parser.set_defaults(handler=handlers.KeyImport, architecture=[""], lock=None, report=False)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_service_setup_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for setup subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("service-setup", aliases=["init", "repo-init", "repo-setup", "setup"],
|
||||
help="initial service configuration",
|
||||
description="create initial service configuration, requires root",
|
||||
epilog="Create _minimal_ configuration for the service according to provided options.",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("--build-command", help="path to build command", default=Path("/usr") / "bin" / "pkgctl")
|
||||
parser.add_argument("--from-configuration", help="path to default devtools pacman configuration", type=Path,
|
||||
default=Path("/usr") / "local" / "share" / "devtools-git-poc" / "pacman.conf.d" / "extra.conf")
|
||||
parser.add_argument("--makeflags-jobs", help="append MAKEFLAGS variable with parallelism set to number of cores",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--mirror", help="use the specified explicitly mirror instead of including mirrorlist")
|
||||
parser.add_argument("--multilib", help="add or do not multilib repository",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("--packager", help="packager name and email", required=True)
|
||||
parser.add_argument("--repository", help="repository name", required=True)
|
||||
parser.add_argument("--sign-key", help="sign key id")
|
||||
parser.add_argument("--sign-target", help="sign options", action="append",
|
||||
type=SignSettings.from_option, choices=enum_values(SignSettings))
|
||||
parser.add_argument("--web-port", help="port of the web service", type=int)
|
||||
parser.add_argument("--web-unix-socket", help="path to unix socket used for interprocess communications", type=Path)
|
||||
parser.set_defaults(handler=handlers.Setup, lock=None, report=False, quiet=True, unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_service_shell_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for shell subcommand
|
||||
|
||||
@ -782,7 +849,7 @@ def _set_shell_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("shell", help="invoke python shell",
|
||||
parser = root.add_parser("service-shell", aliases=["shell"], help="invoke python shell",
|
||||
description="drop into python shell while having created application",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("code", help="instead of dropping into shell, just execute the specified code", nargs="?")
|
||||
@ -814,7 +881,7 @@ def _set_user_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
type=UserAccess, choices=enum_values(UserAccess), default=UserAccess.Read)
|
||||
parser.add_argument("-s", "--secure", help="set file permissions to user-only", action="store_true")
|
||||
parser.set_defaults(handler=handlers.Users, action=Action.Update, architecture=[""], lock=None, report=False,
|
||||
quiet=True, unsafe=True)
|
||||
quiet=True)
|
||||
return parser
|
||||
|
||||
|
||||
@ -854,24 +921,7 @@ def _set_user_remove_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("username", help="username for web service")
|
||||
parser.set_defaults(handler=handlers.Users, action=Action.Remove, architecture=[""], lock=None, report=False, # nosec
|
||||
password="", quiet=True, unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_version_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for version subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("version", help="application version",
|
||||
description="print application and its dependencies versions", formatter_class=_formatter)
|
||||
parser.set_defaults(handler=handlers.Versions, architecture=[""], lock=None, report=False, quiet=True,
|
||||
unsafe=True)
|
||||
password="", quiet=True)
|
||||
return parser
|
||||
|
||||
|
||||
@ -886,7 +936,8 @@ def _set_web_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("web", help="web server", description="start web server", formatter_class=_formatter)
|
||||
parser.set_defaults(handler=handlers.Web, lock=None, report=False, parser=_parser)
|
||||
parser.set_defaults(handler=handlers.Web, lock=Path(tempfile.gettempdir()) / "ahriman-web.lock", report=False,
|
||||
parser=_parser)
|
||||
return parser
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -17,10 +17,11 @@
|
||||
# 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 typing import Set
|
||||
from collections.abc import Iterable
|
||||
|
||||
from ahriman.application.application.application_packages import ApplicationPackages
|
||||
from ahriman.application.application.application_repository import ApplicationRepository
|
||||
from ahriman.models.package import Package
|
||||
from ahriman.models.result import Result
|
||||
|
||||
|
||||
@ -49,14 +50,14 @@ class Application(ApplicationPackages, ApplicationRepository):
|
||||
be used instead.
|
||||
"""
|
||||
|
||||
def _known_packages(self) -> Set[str]:
|
||||
def _known_packages(self) -> set[str]:
|
||||
"""
|
||||
load packages from repository and pacman repositories
|
||||
|
||||
Returns:
|
||||
Set[str]: list of known packages
|
||||
set[str]: list of known packages
|
||||
"""
|
||||
known_packages: Set[str] = set()
|
||||
known_packages: set[str] = set()
|
||||
# local set
|
||||
for base in self.repository.packages():
|
||||
for package, properties in base.packages.items():
|
||||
@ -87,3 +88,39 @@ class Application(ApplicationPackages, ApplicationRepository):
|
||||
directly as it will be called after on_start action
|
||||
"""
|
||||
self.repository.triggers.on_stop()
|
||||
|
||||
def with_dependencies(self, packages: list[Package], *, process_dependencies: bool) -> list[Package]:
|
||||
"""
|
||||
add missing dependencies to list of packages
|
||||
|
||||
Args:
|
||||
packages(list[Package]): list of source packages of which dependencies have to be processed
|
||||
process_dependencies(bool): if no set, dependencies will not be processed
|
||||
"""
|
||||
def missing_dependencies(source: Iterable[Package]) -> set[str]:
|
||||
# build initial list of dependencies
|
||||
result = set()
|
||||
for package in source:
|
||||
result.update(package.depends_build)
|
||||
|
||||
# remove ones which are already well-known
|
||||
result = result.difference(known_packages)
|
||||
|
||||
# remove ones which are in this list already
|
||||
for package in source:
|
||||
result = result.difference(package.packages_full)
|
||||
|
||||
return result
|
||||
|
||||
if not process_dependencies or not packages:
|
||||
return packages
|
||||
|
||||
known_packages = self._known_packages()
|
||||
with_dependencies = {package.base: package for package in packages}
|
||||
|
||||
while missing := missing_dependencies(with_dependencies.values()):
|
||||
for package_name in missing:
|
||||
package = Package.from_aur(package_name, self.repository.pacman)
|
||||
with_dependencies[package.base] = package
|
||||
|
||||
return list(with_dependencies.values())
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -20,9 +20,9 @@
|
||||
import requests
|
||||
import shutil
|
||||
|
||||
from collections.abc import Iterable
|
||||
from pathlib import Path
|
||||
from tempfile import TemporaryDirectory
|
||||
from typing import Any, Iterable, Set
|
||||
from typing import Any
|
||||
|
||||
from ahriman.application.application.application_properties import ApplicationProperties
|
||||
from ahriman.core.build_tools.sources import Sources
|
||||
@ -37,30 +37,6 @@ class ApplicationPackages(ApplicationProperties):
|
||||
package control class
|
||||
"""
|
||||
|
||||
def _known_packages(self) -> Set[str]:
|
||||
"""
|
||||
load packages from repository and pacman repositories
|
||||
|
||||
Returns:
|
||||
Set[str]: list of known packages
|
||||
|
||||
Raises:
|
||||
NotImplementedError: not implemented method
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def on_result(self, result: Result) -> None:
|
||||
"""
|
||||
generate report and sync to remote server
|
||||
|
||||
Args:
|
||||
result(Result): build result
|
||||
|
||||
Raises:
|
||||
NotImplementedError: not implemented method
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def _add_archive(self, source: str, *_: Any) -> None:
|
||||
"""
|
||||
add package from archive
|
||||
@ -72,24 +48,18 @@ class ApplicationPackages(ApplicationProperties):
|
||||
dst = self.repository.paths.packages / local_path.name
|
||||
shutil.copy(local_path, dst)
|
||||
|
||||
def _add_aur(self, source: str, known_packages: Set[str], without_dependencies: bool) -> None:
|
||||
def _add_aur(self, source: str) -> None:
|
||||
"""
|
||||
add package from AUR
|
||||
|
||||
Args:
|
||||
source(str): package base name
|
||||
known_packages(Set[str]): list of packages which are known by the service
|
||||
without_dependencies(bool): if set, dependency check will be disabled
|
||||
"""
|
||||
package = Package.from_aur(source, self.repository.pacman)
|
||||
|
||||
self.database.build_queue_insert(package)
|
||||
self.database.remote_update(package)
|
||||
|
||||
with TemporaryDirectory(ignore_cleanup_errors=True) as dir_name, (local_dir := Path(dir_name)):
|
||||
Sources.load(local_dir, package, self.database.patches_get(package.base), self.repository.paths)
|
||||
self._process_dependencies(local_dir, known_packages, without_dependencies)
|
||||
|
||||
def _add_directory(self, source: str, *_: Any) -> None:
|
||||
"""
|
||||
add packages from directory
|
||||
@ -101,25 +71,21 @@ class ApplicationPackages(ApplicationProperties):
|
||||
for full_path in filter(package_like, local_dir.iterdir()):
|
||||
self._add_archive(str(full_path))
|
||||
|
||||
def _add_local(self, source: str, known_packages: Set[str], without_dependencies: bool) -> None:
|
||||
def _add_local(self, source: str) -> None:
|
||||
"""
|
||||
add package from local PKGBUILDs
|
||||
|
||||
Args:
|
||||
source(str): path to directory with local source files
|
||||
known_packages(Set[str]): list of packages which are known by the service
|
||||
without_dependencies(bool): if set, dependency check will be disabled
|
||||
"""
|
||||
source_dir = Path(source)
|
||||
package = Package.from_build(source_dir)
|
||||
package = Package.from_build(source_dir, self.architecture)
|
||||
cache_dir = self.repository.paths.cache_for(package.base)
|
||||
shutil.copytree(source_dir, cache_dir) # copy package to store in caches
|
||||
Sources.init(cache_dir) # we need to run init command in directory where we do have permissions
|
||||
|
||||
self.database.build_queue_insert(package)
|
||||
|
||||
self._process_dependencies(cache_dir, known_packages, without_dependencies)
|
||||
|
||||
def _add_remote(self, source: str, *_: Any) -> None:
|
||||
"""
|
||||
add package from remote sources (e.g. HTTP)
|
||||
@ -128,7 +94,8 @@ class ApplicationPackages(ApplicationProperties):
|
||||
source(str): remote URL of the package archive
|
||||
"""
|
||||
dst = self.repository.paths.packages / Path(source).name # URL is path, is not it?
|
||||
response = requests.get(source, stream=True, timeout=None) # timeout=None to suppress pylint warns
|
||||
# timeout=None to suppress pylint warns. Also suppress bandit warnings
|
||||
response = requests.get(source, stream=True, timeout=None) # nosec
|
||||
response.raise_for_status()
|
||||
|
||||
with dst.open("wb") as local_file:
|
||||
@ -145,38 +112,31 @@ class ApplicationPackages(ApplicationProperties):
|
||||
package = Package.from_official(source, self.repository.pacman)
|
||||
self.database.build_queue_insert(package)
|
||||
self.database.remote_update(package)
|
||||
# repository packages must not depend on unknown packages, thus we are not going to process dependencies
|
||||
|
||||
def _process_dependencies(self, local_dir: Path, known_packages: Set[str], without_dependencies: bool) -> None:
|
||||
"""
|
||||
process package dependencies
|
||||
|
||||
Args:
|
||||
local_dir(Path): path to local package sources (i.e. cloned AUR repository)
|
||||
known_packages(Set[str]): list of packages which are known by the service
|
||||
without_dependencies(bool): if set, dependency check will be disabled
|
||||
"""
|
||||
if without_dependencies:
|
||||
return
|
||||
|
||||
dependencies = Package.dependencies(local_dir)
|
||||
self.add(dependencies.difference(known_packages), PackageSource.AUR, without_dependencies)
|
||||
|
||||
def add(self, names: Iterable[str], source: PackageSource, without_dependencies: bool) -> None:
|
||||
def add(self, names: Iterable[str], source: PackageSource) -> None:
|
||||
"""
|
||||
add packages for the next build
|
||||
|
||||
Args:
|
||||
names(Iterable[str]): list of package bases to add
|
||||
source(PackageSource): package source to add
|
||||
without_dependencies(bool): if set, dependency check will be disabled
|
||||
"""
|
||||
known_packages = self._known_packages() # speedup dependencies processing
|
||||
|
||||
for name in names:
|
||||
resolved_source = source.resolve(name)
|
||||
fn = getattr(self, f"_add_{resolved_source.value}")
|
||||
fn(name, known_packages, without_dependencies)
|
||||
fn(name)
|
||||
|
||||
def on_result(self, result: Result) -> None:
|
||||
"""
|
||||
generate report and sync to remote server
|
||||
|
||||
Args:
|
||||
result(Result): build result
|
||||
|
||||
Raises:
|
||||
NotImplementedError: not implemented method
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def remove(self, names: Iterable[str]) -> None:
|
||||
"""
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -21,6 +21,7 @@ from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.database import SQLite
|
||||
from ahriman.core.log import LazyLogging
|
||||
from ahriman.core.repository import Repository
|
||||
from ahriman.models.pacman_synchronization import PacmanSynchronization
|
||||
|
||||
|
||||
class ApplicationProperties(LazyLogging):
|
||||
@ -34,8 +35,8 @@ class ApplicationProperties(LazyLogging):
|
||||
repository(Repository): repository instance
|
||||
"""
|
||||
|
||||
def __init__(self, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool, refresh_pacman_database: int = 0) -> None:
|
||||
def __init__(self, architecture: str, configuration: Configuration, *, report: bool, unsafe: bool,
|
||||
refresh_pacman_database: PacmanSynchronization = PacmanSynchronization.Disabled) -> None:
|
||||
"""
|
||||
default constructor
|
||||
|
||||
@ -44,8 +45,8 @@ class ApplicationProperties(LazyLogging):
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
unsafe(bool): if set no user check will be performed before path creation
|
||||
refresh_pacman_database(int, optional): pacman database syncronization level, ``0`` is disabled
|
||||
(Default value = 0)
|
||||
refresh_pacman_database(PacmanSynchronization, optional): pacman database synchronization level
|
||||
(Default value = PacmanSynchronization.Disabled)
|
||||
"""
|
||||
self.configuration = configuration
|
||||
self.architecture = architecture
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -17,8 +17,8 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
from collections.abc import Callable, Iterable
|
||||
from pathlib import Path
|
||||
from typing import Callable, Iterable, List
|
||||
|
||||
from ahriman.application.application.application_properties import ApplicationProperties
|
||||
from ahriman.core.build_tools.sources import Sources
|
||||
@ -33,18 +33,6 @@ class ApplicationRepository(ApplicationProperties):
|
||||
repository control class
|
||||
"""
|
||||
|
||||
def on_result(self, result: Result) -> None:
|
||||
"""
|
||||
generate report and sync to remote server
|
||||
|
||||
Args:
|
||||
result(Result): build result
|
||||
|
||||
Raises:
|
||||
NotImplementedError: not implemented method
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def clean(self, *, cache: bool, chroot: bool, manual: bool, packages: bool, pacman: bool) -> None:
|
||||
"""
|
||||
run all clean methods. Warning: some functions might not be available under non-root
|
||||
@ -67,6 +55,18 @@ class ApplicationRepository(ApplicationProperties):
|
||||
if pacman:
|
||||
self.repository.clear_pacman()
|
||||
|
||||
def on_result(self, result: Result) -> None:
|
||||
"""
|
||||
generate report and sync to remote server
|
||||
|
||||
Args:
|
||||
result(Result): build result
|
||||
|
||||
Raises:
|
||||
NotImplementedError: not implemented method
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def sign(self, packages: Iterable[str]) -> None:
|
||||
"""
|
||||
sign packages and repository
|
||||
@ -89,19 +89,19 @@ class ApplicationRepository(ApplicationProperties):
|
||||
# process triggers
|
||||
self.on_result(Result())
|
||||
|
||||
def unknown(self) -> List[str]:
|
||||
def unknown(self) -> list[str]:
|
||||
"""
|
||||
get packages which were not found in AUR
|
||||
|
||||
Returns:
|
||||
List[str]: unknown package archive list
|
||||
list[str]: unknown package archive list
|
||||
"""
|
||||
def has_local(probe: Package) -> bool:
|
||||
cache_dir = self.repository.paths.cache_for(probe.base)
|
||||
return cache_dir.is_dir() and not Sources.has_remotes(cache_dir)
|
||||
|
||||
def unknown_aur(probe: Package) -> List[str]:
|
||||
packages: List[str] = []
|
||||
def unknown_aur(probe: Package) -> list[str]:
|
||||
packages: list[str] = []
|
||||
for single in probe.packages:
|
||||
try:
|
||||
_ = Package.from_aur(single, self.repository.pacman)
|
||||
@ -109,9 +109,9 @@ class ApplicationRepository(ApplicationProperties):
|
||||
packages.append(single)
|
||||
return packages
|
||||
|
||||
def unknown_local(probe: Package) -> List[str]:
|
||||
def unknown_local(probe: Package) -> list[str]:
|
||||
cache_dir = self.repository.paths.cache_for(probe.base)
|
||||
local = Package.from_build(cache_dir)
|
||||
local = Package.from_build(cache_dir, self.architecture)
|
||||
packages = set(probe.packages.keys()).difference(local.packages.keys())
|
||||
return list(packages)
|
||||
|
||||
@ -145,7 +145,7 @@ class ApplicationRepository(ApplicationProperties):
|
||||
process_update(packages, build_result)
|
||||
|
||||
# process manual packages
|
||||
tree = Tree.resolve(updates, self.repository.paths, self.database)
|
||||
tree = Tree.resolve(updates)
|
||||
for num, level in enumerate(tree):
|
||||
self.logger.info("processing level #%i %s", num, [package.base for package in level])
|
||||
build_result = self.repository.process_build(level)
|
||||
@ -155,7 +155,7 @@ class ApplicationRepository(ApplicationProperties):
|
||||
return build_result
|
||||
|
||||
def updates(self, filter_packages: Iterable[str], *,
|
||||
aur: bool, local: bool, manual: bool, vcs: bool, log_fn: Callable[[str], None]) -> List[Package]:
|
||||
aur: bool, local: bool, manual: bool, vcs: bool, log_fn: Callable[[str], None]) -> list[Package]:
|
||||
"""
|
||||
get list of packages to run update process
|
||||
|
||||
@ -168,14 +168,14 @@ class ApplicationRepository(ApplicationProperties):
|
||||
log_fn(Callable[[str], None]): logger function to log updates
|
||||
|
||||
Returns:
|
||||
List[Package]: list of out-of-dated packages
|
||||
list[Package]: list of out-of-dated packages
|
||||
"""
|
||||
updates = {}
|
||||
|
||||
if aur:
|
||||
updates.update({package.base: package for package in self.repository.updates_aur(filter_packages, vcs=vcs)})
|
||||
if local:
|
||||
updates.update({package.base: package for package in self.repository.updates_local()})
|
||||
updates.update({package.base: package for package in self.repository.updates_local(vcs=vcs)})
|
||||
if manual:
|
||||
updates.update({package.base: package for package in self.repository.updates_manual()})
|
||||
|
||||
@ -183,7 +183,7 @@ class ApplicationRepository(ApplicationProperties):
|
||||
updated_packages = [package for _, package in sorted(updates.items())]
|
||||
|
||||
# reorder updates according to the dependency tree
|
||||
tree = Tree.resolve(updated_packages, self.repository.paths, self.database)
|
||||
tree = Tree.resolve(updated_packages)
|
||||
for level in tree:
|
||||
for package in level:
|
||||
UpdatePrinter(package, local_versions.get(package.base)).print(
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -32,6 +32,7 @@ from ahriman.application.handlers.remove import Remove
|
||||
from ahriman.application.handlers.remove_unknown import RemoveUnknown
|
||||
from ahriman.application.handlers.restore import Restore
|
||||
from ahriman.application.handlers.search import Search
|
||||
from ahriman.application.handlers.service_updates import ServiceUpdates
|
||||
from ahriman.application.handlers.setup import Setup
|
||||
from ahriman.application.handlers.shell import Shell
|
||||
from ahriman.application.handlers.sign import Sign
|
||||
@ -42,5 +43,6 @@ from ahriman.application.handlers.triggers import Triggers
|
||||
from ahriman.application.handlers.unsafe_commands import UnsafeCommands
|
||||
from ahriman.application.handlers.update import Update
|
||||
from ahriman.application.handlers.users import Users
|
||||
from ahriman.application.handlers.validate import Validate
|
||||
from ahriman.application.handlers.versions import Versions
|
||||
from ahriman.application.handlers.web import Web
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -19,8 +19,6 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import Type
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -32,7 +30,7 @@ class Add(Handler):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
@ -47,11 +45,12 @@ class Add(Handler):
|
||||
application = Application(architecture, configuration,
|
||||
report=report, unsafe=unsafe, refresh_pacman_database=args.refresh)
|
||||
application.on_start()
|
||||
application.add(args.package, args.source, args.without_dependencies)
|
||||
application.add(args.package, args.source)
|
||||
if not args.now:
|
||||
return
|
||||
|
||||
packages = application.updates(args.package, aur=False, local=False, manual=True, vcs=False,
|
||||
log_fn=application.logger.info)
|
||||
packages = application.with_dependencies(packages, process_dependencies=args.dependencies)
|
||||
result = application.update(packages)
|
||||
Add.check_if_empty(args.exit_code, result.is_empty)
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -22,7 +22,6 @@ import pwd
|
||||
|
||||
from pathlib import Path
|
||||
from tarfile import TarFile
|
||||
from typing import Set, Type
|
||||
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -37,7 +36,7 @@ class Backup(Handler):
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
@ -55,7 +54,7 @@ class Backup(Handler):
|
||||
archive.add(backup_path)
|
||||
|
||||
@staticmethod
|
||||
def get_paths(configuration: Configuration) -> Set[Path]:
|
||||
def get_paths(configuration: Configuration) -> set[Path]:
|
||||
"""
|
||||
extract paths to back up
|
||||
|
||||
@ -63,7 +62,7 @@ class Backup(Handler):
|
||||
configuration(Configuration): configuration instance
|
||||
|
||||
Returns:
|
||||
Set[Path]: map of the filesystem paths
|
||||
set[Path]: map of the filesystem paths
|
||||
"""
|
||||
paths = set(configuration.include.glob("*.ini"))
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -19,8 +19,6 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import Type
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -32,7 +30,7 @@ class Clean(Handler):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -20,8 +20,6 @@
|
||||
import argparse
|
||||
import threading
|
||||
|
||||
from typing import Type
|
||||
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
|
||||
@ -32,7 +30,7 @@ class Daemon(Handler):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -19,8 +19,6 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import Type
|
||||
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.formatters import ConfigurationPrinter
|
||||
@ -34,7 +32,7 @@ class Dump(Handler):
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
@ -48,4 +46,4 @@ class Dump(Handler):
|
||||
"""
|
||||
dump = configuration.dump()
|
||||
for section, values in sorted(dump.items()):
|
||||
ConfigurationPrinter(section, values).print(verbose=False, separator=" = ")
|
||||
ConfigurationPrinter(section, values).print(verbose=not args.secure, separator=" = ")
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -17,13 +17,10 @@
|
||||
# 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 __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from multiprocessing import Pool
|
||||
from typing import List, Type
|
||||
|
||||
from ahriman.application.lock import Lock
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -53,7 +50,7 @@ class Handler:
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN = True
|
||||
|
||||
@classmethod
|
||||
def architectures_extract(cls: Type[Handler], args: argparse.Namespace) -> List[str]:
|
||||
def architectures_extract(cls, args: argparse.Namespace) -> list[str]:
|
||||
"""
|
||||
get known architectures
|
||||
|
||||
@ -61,7 +58,7 @@ class Handler:
|
||||
args(argparse.Namespace): command line args
|
||||
|
||||
Returns:
|
||||
List[str]: list of architectures for which tree is created
|
||||
list[str]: list of architectures for which tree is created
|
||||
|
||||
Raises:
|
||||
MissingArchitecture: if no architecture set and automatic detection is not allowed or failed
|
||||
@ -84,7 +81,7 @@ class Handler:
|
||||
return sorted(architectures)
|
||||
|
||||
@classmethod
|
||||
def call(cls: Type[Handler], args: argparse.Namespace, architecture: str) -> bool:
|
||||
def call(cls, args: argparse.Namespace, architecture: str) -> bool:
|
||||
"""
|
||||
additional function to wrap all calls for multiprocessing library
|
||||
|
||||
@ -109,7 +106,7 @@ class Handler:
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def execute(cls: Type[Handler], args: argparse.Namespace) -> int:
|
||||
def execute(cls, args: argparse.Namespace) -> int:
|
||||
"""
|
||||
execute function for all aru
|
||||
|
||||
@ -138,7 +135,7 @@ class Handler:
|
||||
return 0 if all(result) else 1
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -19,8 +19,6 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import Type
|
||||
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
|
||||
@ -33,7 +31,7 @@ class Help(Handler):
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -19,8 +19,6 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import Type
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -34,7 +32,7 @@ class KeyImport(Handler):
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -21,7 +21,6 @@ import argparse
|
||||
import sys
|
||||
|
||||
from pathlib import Path
|
||||
from typing import List, Optional, Tuple, Type
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
@ -39,7 +38,7 @@ class Patch(Handler):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
@ -58,7 +57,7 @@ class Patch(Handler):
|
||||
patch = Patch.patch_create_from_function(args.variable, args.patch)
|
||||
Patch.patch_set_create(application, args.package, patch)
|
||||
elif args.action == Action.Update and args.variable is None:
|
||||
package_base, patch = Patch.patch_create_from_diff(args.package, args.track)
|
||||
package_base, patch = Patch.patch_create_from_diff(args.package, architecture, args.track)
|
||||
Patch.patch_set_create(application, package_base, patch)
|
||||
elif args.action == Action.List:
|
||||
Patch.patch_set_list(application, args.package, args.variable, args.exit_code)
|
||||
@ -66,30 +65,31 @@ class Patch(Handler):
|
||||
Patch.patch_set_remove(application, args.package, args.variable)
|
||||
|
||||
@staticmethod
|
||||
def patch_create_from_diff(sources_dir: Path, track: List[str]) -> Tuple[str, PkgbuildPatch]:
|
||||
def patch_create_from_diff(sources_dir: Path, architecture: str, track: list[str]) -> tuple[str, PkgbuildPatch]:
|
||||
"""
|
||||
create PKGBUILD plain diff patches from sources directory
|
||||
|
||||
Args:
|
||||
sources_dir(Path): path to directory with the package sources
|
||||
track(List[str]): track files which match the glob before creating the patch
|
||||
architecture(str): repository architecture
|
||||
track(list[str]): track files which match the glob before creating the patch
|
||||
|
||||
Returns:
|
||||
Tuple[str, PkgbuildPatch]: package base and created PKGBUILD patch based on the diff from master HEAD
|
||||
tuple[str, PkgbuildPatch]: package base and created PKGBUILD patch based on the diff from master HEAD
|
||||
to current files
|
||||
"""
|
||||
package = Package.from_build(sources_dir)
|
||||
package = Package.from_build(sources_dir, architecture)
|
||||
patch = Sources.patch_create(sources_dir, *track)
|
||||
return package.base, PkgbuildPatch(None, patch)
|
||||
|
||||
@staticmethod
|
||||
def patch_create_from_function(variable: str, patch_path: Optional[Path]) -> PkgbuildPatch:
|
||||
def patch_create_from_function(variable: str, patch_path: Path | None) -> PkgbuildPatch:
|
||||
"""
|
||||
create single-function patch set for the package base
|
||||
|
||||
Args:
|
||||
variable(str): function or variable name inside PKGBUILD
|
||||
patch_path(Path): optional path to patch content. If not set, it will be read from stdin
|
||||
patch_path(Path | None): optional path to patch content. If not set, it will be read from stdin
|
||||
|
||||
Returns:
|
||||
PkgbuildPatch: created patch for the PKGBUILD function
|
||||
@ -115,15 +115,15 @@ class Patch(Handler):
|
||||
application.database.patches_insert(package_base, patch)
|
||||
|
||||
@staticmethod
|
||||
def patch_set_list(application: Application, package_base: Optional[str], variables: List[str],
|
||||
def patch_set_list(application: Application, package_base: str | None, variables: list[str],
|
||||
exit_code: bool) -> None:
|
||||
"""
|
||||
list patches available for the package base
|
||||
|
||||
Args:
|
||||
application(Application): application instance
|
||||
package_base(Optional[str]): package base
|
||||
variables(List[str]): extract patches only for specified PKGBUILD variables
|
||||
package_base(str | None): package base
|
||||
variables(list[str]): extract patches only for specified PKGBUILD variables
|
||||
exit_code(bool): exit with error on empty search result
|
||||
"""
|
||||
patches = application.database.patches_list(package_base, variables)
|
||||
@ -133,13 +133,13 @@ class Patch(Handler):
|
||||
PatchPrinter(base, patch).print(verbose=True, separator=" = ")
|
||||
|
||||
@staticmethod
|
||||
def patch_set_remove(application: Application, package_base: str, variables: List[str]) -> None:
|
||||
def patch_set_remove(application: Application, package_base: str, variables: list[str]) -> None:
|
||||
"""
|
||||
remove patch set for the package base
|
||||
|
||||
Args:
|
||||
application(Application): application instance
|
||||
package_base(str): package base
|
||||
variables(List[str]): remove patches only for specified PKGBUILD variables
|
||||
variables(list[str]): remove patches only for specified PKGBUILD variables
|
||||
"""
|
||||
application.database.patches_remove(package_base, variables)
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -19,8 +19,6 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import List, Type
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -34,7 +32,7 @@ class Rebuild(Handler):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
@ -46,13 +44,11 @@ class Rebuild(Handler):
|
||||
report(bool): force enable or disable reporting
|
||||
unsafe(bool): if set no user check will be performed before path creation
|
||||
"""
|
||||
depends_on = set(args.depends_on) if args.depends_on else None
|
||||
|
||||
application = Application(architecture, configuration, report=report, unsafe=unsafe)
|
||||
application.on_start()
|
||||
|
||||
packages = Rebuild.extract_packages(application, from_database=args.from_database)
|
||||
updates = application.repository.packages_depend_on(packages, depends_on)
|
||||
updates = application.repository.packages_depend_on(packages, args.depends_on or None)
|
||||
|
||||
Rebuild.check_if_empty(args.exit_code, not updates)
|
||||
if args.dry_run:
|
||||
@ -64,7 +60,7 @@ class Rebuild(Handler):
|
||||
Rebuild.check_if_empty(args.exit_code, result.is_empty)
|
||||
|
||||
@staticmethod
|
||||
def extract_packages(application: Application, *, from_database: bool) -> List[Package]:
|
||||
def extract_packages(application: Application, *, from_database: bool) -> list[Package]:
|
||||
"""
|
||||
extract packages from database file
|
||||
|
||||
@ -73,7 +69,7 @@ class Rebuild(Handler):
|
||||
from_database(bool): extract packages from database instead of repository filesystem
|
||||
|
||||
Returns:
|
||||
List[Package]: list of packages which were stored in database
|
||||
list[Package]: list of packages which were stored in database
|
||||
"""
|
||||
if from_database:
|
||||
return [package for (package, _) in application.database.packages_get()]
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -19,8 +19,6 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import Type
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -32,7 +30,7 @@ class Remove(Handler):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -19,8 +19,6 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import Type
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -33,7 +31,7 @@ class RemoveUnknown(Handler):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
@ -51,7 +49,7 @@ class RemoveUnknown(Handler):
|
||||
|
||||
if args.dry_run:
|
||||
for package in sorted(unknown_packages):
|
||||
StringPrinter(package).print(False)
|
||||
StringPrinter(package).print(verbose=False)
|
||||
return
|
||||
|
||||
application.remove(unknown_packages)
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -19,7 +19,6 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import Type
|
||||
from tarfile import TarFile
|
||||
|
||||
from ahriman.application.handlers import Handler
|
||||
@ -34,7 +33,7 @@ class Restore(Handler):
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -20,7 +20,7 @@
|
||||
import argparse
|
||||
|
||||
from dataclasses import fields
|
||||
from typing import Callable, Iterable, List, Tuple, Type
|
||||
from collections.abc import Callable, Iterable
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
@ -36,14 +36,18 @@ class Search(Handler):
|
||||
packages search handler
|
||||
|
||||
Attributes:
|
||||
SORT_FIELDS(Set[str]): (class attribute) allowed fields to sort the package list
|
||||
SORT_FIELDS(set[str]): (class attribute) allowed fields to sort the package list
|
||||
"""
|
||||
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
||||
SORT_FIELDS = {field.name for field in fields(AURPackage) if field.default_factory is not list}
|
||||
SORT_FIELDS = {
|
||||
field.name
|
||||
for field in fields(AURPackage)
|
||||
if field.default_factory is not list # type: ignore[comparison-overlap]
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
@ -64,10 +68,10 @@ class Search(Handler):
|
||||
for packages_list in (official_packages_list, aur_packages_list):
|
||||
# keep sorting by packages source
|
||||
for package in Search.sort(packages_list, args.sort_by):
|
||||
AurPrinter(package).print(args.info)
|
||||
AurPrinter(package).print(verbose=args.info)
|
||||
|
||||
@staticmethod
|
||||
def sort(packages: Iterable[AURPackage], sort_by: str) -> List[AURPackage]:
|
||||
def sort(packages: Iterable[AURPackage], sort_by: str) -> list[AURPackage]:
|
||||
"""
|
||||
sort package list by specified field
|
||||
|
||||
@ -76,7 +80,7 @@ class Search(Handler):
|
||||
sort_by(str): AUR package field name to sort by
|
||||
|
||||
Returns:
|
||||
List[AURPackage]: sorted list for packages
|
||||
list[AURPackage]: sorted list for packages
|
||||
|
||||
Raises:
|
||||
InvalidOption: if search fields is not in list of allowed ones
|
||||
@ -85,6 +89,6 @@ class Search(Handler):
|
||||
raise OptionError(sort_by)
|
||||
# always sort by package name at the last
|
||||
# well technically it is not a string, but we can deal with it
|
||||
comparator: Callable[[AURPackage], Tuple[str, str]] =\
|
||||
comparator: Callable[[AURPackage], tuple[str, str]] =\
|
||||
lambda package: (getattr(package, sort_by), package.name)
|
||||
return sorted(packages, key=comparator)
|
||||
|
63
src/ahriman/application/handlers/service_updates.py
Normal file
63
src/ahriman/application/handlers/service_updates.py
Normal file
@ -0,0 +1,63 @@
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
import argparse
|
||||
|
||||
from ahriman import version
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.formatters import UpdatePrinter
|
||||
from ahriman.models.package import Package
|
||||
|
||||
|
||||
class ServiceUpdates(Handler):
|
||||
"""
|
||||
service updates handler
|
||||
"""
|
||||
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
unsafe(bool): if set no user check will be performed before path creation
|
||||
"""
|
||||
application = Application(architecture, configuration, report=report, unsafe=unsafe)
|
||||
|
||||
remote = Package.from_aur("ahriman", application.repository.pacman)
|
||||
release = remote.version.rsplit("-", 1)[-1] # we don't store pkgrel locally, so we just append it
|
||||
local_version = f"{version.__version__}-{release}"
|
||||
|
||||
# technically we would like to compare versions, but it is fine to raise an exception in case if locally
|
||||
# installed package is newer than in AUR
|
||||
same_version = remote.version == local_version
|
||||
if same_version:
|
||||
return
|
||||
|
||||
UpdatePrinter(remote, local_version).print(verbose=True, separator=" -> ")
|
||||
ServiceUpdates.check_if_empty(args.exit_code, not same_version)
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -21,7 +21,6 @@ import argparse
|
||||
|
||||
from pathlib import Path
|
||||
from pwd import getpwuid
|
||||
from typing import Type
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
@ -34,19 +33,17 @@ class Setup(Handler):
|
||||
setup handler
|
||||
|
||||
Attributes:
|
||||
ARCHBUILD_COMMAND_PATH(Path): (class attribute) default devtools command
|
||||
MIRRORLIST_PATH(Path): (class attribute) path to pacman default mirrorlist (used by multilib repository)
|
||||
SUDOERS_DIR_PATH(Path): (class attribute) path to sudoers.d includes directory
|
||||
"""
|
||||
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False
|
||||
|
||||
ARCHBUILD_COMMAND_PATH = Path("/usr/bin/archbuild")
|
||||
MIRRORLIST_PATH = Path("/etc/pacman.d/mirrorlist")
|
||||
SUDOERS_DIR_PATH = Path("/etc/sudoers.d")
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
@ -58,40 +55,23 @@ class Setup(Handler):
|
||||
report(bool): force enable or disable reporting
|
||||
unsafe(bool): if set no user check will be performed before path creation
|
||||
"""
|
||||
Setup.configuration_create_ahriman(args, architecture, args.repository, configuration.include,
|
||||
configuration.repository_paths)
|
||||
Setup.configuration_create_ahriman(args, architecture, args.repository, configuration)
|
||||
configuration.reload()
|
||||
|
||||
application = Application(architecture, configuration, report=report, unsafe=unsafe)
|
||||
|
||||
Setup.configuration_create_makepkg(args.packager, args.makeflags_jobs, application.repository.paths)
|
||||
Setup.executable_create(application.repository.paths, args.build_command, architecture)
|
||||
Setup.configuration_create_devtools(args.build_command, architecture, args.from_configuration,
|
||||
Setup.configuration_create_devtools(architecture, args.from_configuration, args.mirror,
|
||||
args.multilib, args.repository, application.repository.paths)
|
||||
Setup.configuration_create_sudo(application.repository.paths, args.build_command, architecture)
|
||||
Setup.configuration_create_sudo(args.build_command)
|
||||
|
||||
application.repository.repo.init()
|
||||
# lazy database sync
|
||||
application.repository.pacman.handle # pylint: disable=pointless-statement
|
||||
|
||||
@staticmethod
|
||||
def build_command(root: Path, prefix: str, architecture: str) -> Path:
|
||||
"""
|
||||
generate build command name
|
||||
|
||||
Args:
|
||||
root(Path): root directory for the build command (must be root of the repository)
|
||||
prefix(str): command prefix in {prefix}-{architecture}-build
|
||||
architecture(str): repository architecture
|
||||
|
||||
Returns:
|
||||
Path: valid devtools command name
|
||||
"""
|
||||
return root / f"{prefix}-{architecture}-build"
|
||||
|
||||
@staticmethod
|
||||
def configuration_create_ahriman(args: argparse.Namespace, architecture: str, repository: str,
|
||||
include_path: Path, paths: RepositoryPaths) -> None:
|
||||
root: Configuration) -> None:
|
||||
"""
|
||||
create service specific configuration
|
||||
|
||||
@ -99,37 +79,39 @@ class Setup(Handler):
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
repository(str): repository name
|
||||
include_path(Path): path to directory with configuration includes
|
||||
paths(RepositoryPaths): repository paths instance
|
||||
root(Configuration): root configuration instance
|
||||
"""
|
||||
configuration = Configuration()
|
||||
|
||||
section = Configuration.section_name("build", architecture)
|
||||
build_command = Setup.build_command(paths.root, args.build_command, architecture)
|
||||
configuration.set_option(section, "build_command", str(build_command))
|
||||
configuration.set_option("repository", "name", repository)
|
||||
if args.build_as_user is not None:
|
||||
configuration.set_option(section, "makechrootpkg_flags", f"-U {args.build_as_user}")
|
||||
|
||||
section = Configuration.section_name("build", architecture)
|
||||
configuration.set_option(section, "build_command", str(args.build_command))
|
||||
|
||||
section = Configuration.section_name("alpm", architecture)
|
||||
if args.mirror is not None:
|
||||
configuration.set_option(section, "mirror", args.mirror)
|
||||
if not args.multilib:
|
||||
repositories = filter(lambda r: r != "multilib", root.getlist("alpm", "repositories"))
|
||||
configuration.set_option(section, "repositories", " ".join(repositories))
|
||||
|
||||
section = Configuration.section_name("sign", architecture)
|
||||
if args.sign_key is not None:
|
||||
section = Configuration.section_name("sign", architecture)
|
||||
configuration.set_option(section, "target", " ".join([target.name.lower() for target in args.sign_target]))
|
||||
configuration.set_option(section, "key", args.sign_key)
|
||||
|
||||
section = Configuration.section_name("web", architecture)
|
||||
if args.web_port is not None:
|
||||
section = Configuration.section_name("web", architecture)
|
||||
configuration.set_option(section, "port", str(args.web_port))
|
||||
|
||||
if args.web_unix_socket is not None:
|
||||
section = Configuration.section_name("web", architecture)
|
||||
configuration.set_option(section, "unix_socket", str(args.web_unix_socket))
|
||||
|
||||
target = include_path / "00-setup-overrides.ini"
|
||||
target = root.include / "00-setup-overrides.ini"
|
||||
with target.open("w") as ahriman_configuration:
|
||||
configuration.write(ahriman_configuration)
|
||||
|
||||
@staticmethod
|
||||
def configuration_create_devtools(prefix: str, architecture: str, source: Path,
|
||||
def configuration_create_devtools(architecture: str, source: Path, mirror: str | None,
|
||||
multilib: bool, repository: str, paths: RepositoryPaths) -> None:
|
||||
"""
|
||||
create configuration for devtools based on ``source`` configuration
|
||||
@ -138,9 +120,9 @@ class Setup(Handler):
|
||||
devtools does not allow to specify the pacman configuration, thus we still have to use configuration in /usr
|
||||
|
||||
Args:
|
||||
prefix(str): command prefix in {prefix}-{architecture}-build
|
||||
architecture(str): repository architecture
|
||||
source(Path): path to source configuration file
|
||||
mirror(str | None): link to package server mirror
|
||||
multilib(bool): add or do not multilib repository to the configuration
|
||||
repository(str): repository name
|
||||
paths(RepositoryPaths): repository paths instance
|
||||
@ -150,7 +132,7 @@ class Setup(Handler):
|
||||
configuration = Configuration(allow_no_value=True)
|
||||
# preserve case
|
||||
# stupid mypy thinks that it is impossible
|
||||
configuration.optionxform = lambda key: key # type: ignore
|
||||
configuration.optionxform = lambda key: key # type: ignore[method-assign]
|
||||
|
||||
# load default configuration first
|
||||
# we cannot use Include here because it will be copied to new chroot, thus no includes there
|
||||
@ -163,11 +145,19 @@ class Setup(Handler):
|
||||
if multilib:
|
||||
configuration.set_option("multilib", "Include", str(Setup.MIRRORLIST_PATH))
|
||||
|
||||
# override Include option to Server in case if mirror option set
|
||||
if mirror is not None:
|
||||
for section in filter(lambda s: s != "options", configuration.sections()):
|
||||
if configuration.get(section, "Include", fallback=None) != str(Setup.MIRRORLIST_PATH):
|
||||
continue
|
||||
configuration.remove_option(section, "Include")
|
||||
configuration.set_option(section, "Server", mirror)
|
||||
|
||||
# add repository itself
|
||||
configuration.set_option(repository, "SigLevel", "Optional TrustAll") # we don't care
|
||||
configuration.set_option(repository, "Server", f"file://{paths.repository}")
|
||||
|
||||
target = source.parent / f"pacman-{prefix}-{architecture}.conf"
|
||||
target = source.parent / f"{repository}.conf"
|
||||
with target.open("w") as devtools_configuration:
|
||||
configuration.write(devtools_configuration)
|
||||
|
||||
@ -191,31 +181,13 @@ class Setup(Handler):
|
||||
(home_dir / ".makepkg.conf").write_text(content, encoding="utf8")
|
||||
|
||||
@staticmethod
|
||||
def configuration_create_sudo(paths: RepositoryPaths, prefix: str, architecture: str) -> None:
|
||||
def configuration_create_sudo(build_command: Path) -> None:
|
||||
"""
|
||||
create configuration to run build command with sudo without password
|
||||
|
||||
Args:
|
||||
paths(RepositoryPaths): repository paths instance
|
||||
prefix(str): command prefix in {prefix}-{architecture}-build
|
||||
architecture(str): repository architecture
|
||||
build_command(Path): path to build command
|
||||
"""
|
||||
command = Setup.build_command(paths.root, prefix, architecture)
|
||||
sudoers_file = Setup.build_command(Setup.SUDOERS_DIR_PATH, prefix, architecture)
|
||||
sudoers_file.write_text(f"ahriman ALL=(ALL) NOPASSWD: {command} *\n", encoding="utf8")
|
||||
sudoers_file = Setup.SUDOERS_DIR_PATH / f"ahriman-{build_command.name}"
|
||||
sudoers_file.write_text(f"ahriman ALL=(ALL) NOPASSWD: {build_command} build *\n", encoding="utf8")
|
||||
sudoers_file.chmod(0o400) # security!
|
||||
|
||||
@staticmethod
|
||||
def executable_create(paths: RepositoryPaths, prefix: str, architecture: str) -> None:
|
||||
"""
|
||||
create executable for the service
|
||||
|
||||
Args:
|
||||
paths(RepositoryPaths): repository paths instance
|
||||
prefix(str): command prefix in {prefix}-{architecture}-build
|
||||
architecture(str): repository architecture
|
||||
"""
|
||||
command = Setup.build_command(paths.root, prefix, architecture)
|
||||
command.unlink(missing_ok=True)
|
||||
command.symlink_to(Setup.ARCHBUILD_COMMAND_PATH)
|
||||
paths.chown(command) # we would like to keep owner inside ahriman's home
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -22,7 +22,6 @@ import code
|
||||
import sys
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Type
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
@ -38,7 +37,7 @@ class Shell(Handler):
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN = False
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
@ -56,7 +55,7 @@ class Shell(Handler):
|
||||
# licensed by https://creativecommons.org/licenses/by-sa/3.0
|
||||
path = Path(sys.prefix) / "share" / "ahriman" / "templates" / "shell"
|
||||
StringPrinter(path.read_text(encoding="utf8")).print(verbose=False)
|
||||
# we only want to pass application isntance inside
|
||||
# we only want to pass application instance inside
|
||||
if args.code is None:
|
||||
code.interact(local={"application": application})
|
||||
else:
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -19,8 +19,6 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import Type
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -32,7 +30,7 @@ class Sign(Handler):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -19,7 +19,7 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import Callable, Iterable, Tuple, Type
|
||||
from collections.abc import Callable
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
@ -37,7 +37,7 @@ class Status(Handler):
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
@ -53,9 +53,9 @@ class Status(Handler):
|
||||
client = Application(architecture, configuration, report=True, unsafe=unsafe).repository.reporter
|
||||
if args.ahriman:
|
||||
service_status = client.get_internal()
|
||||
StatusPrinter(service_status.status).print(args.info)
|
||||
StatusPrinter(service_status.status).print(verbose=args.info)
|
||||
if args.package:
|
||||
packages: Iterable[Tuple[Package, BuildStatus]] = sum(
|
||||
packages: list[tuple[Package, BuildStatus]] = sum(
|
||||
(client.get(base) for base in args.package),
|
||||
start=[])
|
||||
else:
|
||||
@ -63,8 +63,8 @@ class Status(Handler):
|
||||
|
||||
Status.check_if_empty(args.exit_code, not packages)
|
||||
|
||||
comparator: Callable[[Tuple[Package, BuildStatus]], str] = lambda item: item[0].base
|
||||
filter_fn: Callable[[Tuple[Package, BuildStatus]], bool] =\
|
||||
comparator: Callable[[tuple[Package, BuildStatus]], str] = lambda item: item[0].base
|
||||
filter_fn: Callable[[tuple[Package, BuildStatus]], bool] =\
|
||||
lambda item: args.status is None or item[1].status == args.status
|
||||
for package, package_status in sorted(filter(filter_fn, packages), key=comparator):
|
||||
PackagePrinter(package, package_status).print(args.info)
|
||||
PackagePrinter(package, package_status).print(verbose=args.info)
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -19,8 +19,6 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import Type
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -35,7 +33,7 @@ class StatusUpdate(Handler):
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -19,8 +19,6 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import Type
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -36,7 +34,7 @@ class Structure(Handler):
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
@ -51,6 +49,6 @@ class Structure(Handler):
|
||||
application = Application(architecture, configuration, report=report, unsafe=unsafe)
|
||||
packages = application.repository.packages()
|
||||
|
||||
tree = Tree.resolve(packages, application.repository.paths, application.database)
|
||||
tree = Tree.resolve(packages)
|
||||
for num, level in enumerate(tree):
|
||||
TreePrinter(num, level).print(verbose=True, separator=" ")
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -19,8 +19,6 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import Type
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -33,7 +31,7 @@ class Triggers(Handler):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
@ -48,6 +46,6 @@ class Triggers(Handler):
|
||||
application = Application(architecture, configuration, report=report, unsafe=unsafe)
|
||||
if args.trigger:
|
||||
loader = application.repository.triggers
|
||||
loader.triggers = [loader.load_trigger(trigger) for trigger in args.trigger]
|
||||
loader.triggers = [loader.load_trigger(trigger, architecture, configuration) for trigger in args.trigger]
|
||||
application.on_start()
|
||||
application.on_result(Result())
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -20,8 +20,6 @@
|
||||
import argparse
|
||||
import shlex
|
||||
|
||||
from typing import List, Type
|
||||
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.formatters import StringPrinter
|
||||
@ -35,7 +33,7 @@ class UnsafeCommands(Handler):
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
@ -56,20 +54,20 @@ class UnsafeCommands(Handler):
|
||||
UnsafeCommands.check_unsafe(args.command, unsafe_commands, parser)
|
||||
|
||||
@staticmethod
|
||||
def check_unsafe(command: str, unsafe_commands: List[str], parser: argparse.ArgumentParser) -> None:
|
||||
def check_unsafe(command: str, unsafe_commands: list[str], parser: argparse.ArgumentParser) -> None:
|
||||
"""
|
||||
check if command is unsafe
|
||||
|
||||
Args:
|
||||
command(str): command to check
|
||||
unsafe_commands(List[str]): list of unsafe commands
|
||||
unsafe_commands(list[str]): list of unsafe commands
|
||||
parser(argparse.ArgumentParser): generated argument parser
|
||||
"""
|
||||
args = parser.parse_args(shlex.split(command))
|
||||
UnsafeCommands.check_if_empty(True, args.command in unsafe_commands)
|
||||
|
||||
@staticmethod
|
||||
def get_unsafe_commands(parser: argparse.ArgumentParser) -> List[str]:
|
||||
def get_unsafe_commands(parser: argparse.ArgumentParser) -> list[str]:
|
||||
"""
|
||||
extract unsafe commands from argument parser
|
||||
|
||||
@ -77,9 +75,9 @@ class UnsafeCommands(Handler):
|
||||
parser(argparse.ArgumentParser): generated argument parser
|
||||
|
||||
Returns:
|
||||
List[str]: list of commands with default unsafe flag
|
||||
list[str]: list of commands with default unsafe flag
|
||||
"""
|
||||
# should never fail
|
||||
# pylint: disable=protected-access
|
||||
subparser = next(action for action in parser._actions if isinstance(action, argparse._SubParsersAction))
|
||||
return [action_name for action_name, action in subparser.choices.items() if action.get_default("unsafe")]
|
||||
return sorted(action_name for action_name, action in subparser.choices.items() if action.get_default("unsafe"))
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -19,7 +19,7 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import Callable, Type
|
||||
from collections.abc import Callable
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
@ -32,7 +32,7 @@ class Update(Handler):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
@ -53,6 +53,7 @@ class Update(Handler):
|
||||
if args.dry_run:
|
||||
return
|
||||
|
||||
packages = application.with_dependencies(packages, process_dependencies=args.dependencies)
|
||||
result = application.update(packages)
|
||||
Update.check_if_empty(args.exit_code, result.is_empty)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -21,7 +21,6 @@ import argparse
|
||||
import getpass
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Optional, Tuple, Type
|
||||
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -40,7 +39,7 @@ class Users(Handler):
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
@ -119,7 +118,7 @@ class Users(Handler):
|
||||
path.chmod(0o600)
|
||||
|
||||
@staticmethod
|
||||
def get_salt(configuration: Configuration, salt_length: int = 20) -> Tuple[Optional[str], str]:
|
||||
def get_salt(configuration: Configuration, salt_length: int = 20) -> tuple[str | None, str]:
|
||||
"""
|
||||
get salt from configuration or create new string
|
||||
|
||||
@ -128,7 +127,7 @@ class Users(Handler):
|
||||
salt_length(int, optional): salt length (Default value = 20)
|
||||
|
||||
Returns:
|
||||
Tuple[Optional[str], str]: tuple containing salt from configuration if any and actual salt which must be
|
||||
tuple[str | None, str]: tuple containing salt from configuration if any and actual salt which must be
|
||||
used for password hash
|
||||
"""
|
||||
if salt := configuration.get("auth", "salt", fallback=None):
|
||||
|
135
src/ahriman/application/handlers/validate.py
Normal file
135
src/ahriman/application/handlers/validate.py
Normal file
@ -0,0 +1,135 @@
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
import argparse
|
||||
import copy
|
||||
|
||||
from typing import Any
|
||||
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.configuration.schema import CONFIGURATION_SCHEMA, ConfigurationSchema
|
||||
from ahriman.core.configuration.validator import Validator
|
||||
from ahriman.core.exceptions import ExtensionError
|
||||
from ahriman.core.formatters import ValidationPrinter
|
||||
from ahriman.core.triggers import TriggerLoader
|
||||
|
||||
|
||||
class Validate(Handler):
|
||||
"""
|
||||
configuration validator handler
|
||||
"""
|
||||
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
unsafe(bool): if set no user check will be performed before path creation
|
||||
"""
|
||||
schema = Validate.schema(architecture, configuration)
|
||||
validator = Validator(configuration=configuration, schema=schema)
|
||||
|
||||
if validator.validate(configuration.dump()):
|
||||
return # no errors found
|
||||
for node, errors in validator.errors.items():
|
||||
ValidationPrinter(node, errors).print(verbose=True)
|
||||
|
||||
# as we reach this part it means that we always have errors
|
||||
Validate.check_if_empty(args.exit_code, True)
|
||||
|
||||
@staticmethod
|
||||
def schema(architecture: str, configuration: Configuration) -> ConfigurationSchema:
|
||||
"""
|
||||
get schema with triggers
|
||||
|
||||
Args:
|
||||
architecture(str): repository architecture
|
||||
configuration(Configuration): configuration instance
|
||||
|
||||
Returns:
|
||||
ConfigurationSchema: configuration validation schema
|
||||
"""
|
||||
root = copy.deepcopy(CONFIGURATION_SCHEMA)
|
||||
|
||||
# create trigger loader instance
|
||||
loader = TriggerLoader()
|
||||
for trigger in loader.selected_triggers(configuration):
|
||||
try:
|
||||
trigger_class = loader.load_trigger_class(trigger)
|
||||
except ExtensionError:
|
||||
continue
|
||||
|
||||
# default settings if any
|
||||
for schema_name, schema in trigger_class.configuration_schema(architecture, None).items():
|
||||
erased = Validate.schema_erase_required(copy.deepcopy(schema))
|
||||
root[schema_name] = Validate.schema_merge(root.get(schema_name, {}), erased)
|
||||
|
||||
# settings according to enabled triggers
|
||||
for schema_name, schema in trigger_class.configuration_schema(architecture, configuration).items():
|
||||
root[schema_name] = Validate.schema_merge(root.get(schema_name, {}), copy.deepcopy(schema))
|
||||
|
||||
return root
|
||||
|
||||
@staticmethod
|
||||
def schema_erase_required(schema: ConfigurationSchema) -> ConfigurationSchema:
|
||||
"""
|
||||
recursively remove required field from supplied cerberus schema
|
||||
|
||||
Args:
|
||||
schema(ConfigurationSchema): source schema from which required field must be removed
|
||||
|
||||
Returns:
|
||||
ConfigurationSchema: schema without required fields. Note, that source schema will be modified in-place
|
||||
"""
|
||||
schema.pop("required", None)
|
||||
for value in filter(lambda v: isinstance(v, dict), schema.values()):
|
||||
Validate.schema_erase_required(value)
|
||||
return schema
|
||||
|
||||
@staticmethod
|
||||
def schema_merge(source: dict[str, Any], schema: dict[str, Any]) -> dict[str, Any]:
|
||||
"""
|
||||
merge child schema into source. In case if source already contains values, new keys will be added
|
||||
(possibly with overrides - in case if such key already set also)
|
||||
|
||||
Args:
|
||||
source(dict[str, Any]): source (current) schema into which will be merged
|
||||
schema(dict[str, Any]): new schema to be merged
|
||||
|
||||
Returns:
|
||||
dict[str, Any]: schema with added elements from source schema if they were set before and not presented
|
||||
in the new one. Note, that schema will be modified in-place
|
||||
"""
|
||||
for key, value in source.items():
|
||||
if key not in schema:
|
||||
schema[key] = value # new key found, just add it as is
|
||||
elif isinstance(value, dict):
|
||||
# value is dictionary, so we need to go deeper
|
||||
Validate.schema_merge(value, schema[key])
|
||||
|
||||
return schema
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -18,10 +18,11 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
import argparse
|
||||
import pkg_resources
|
||||
import re
|
||||
import sys
|
||||
|
||||
from typing import Dict, List, Tuple, Type
|
||||
from collections.abc import Generator
|
||||
from importlib import metadata
|
||||
|
||||
from ahriman import version
|
||||
from ahriman.application.handlers import Handler
|
||||
@ -32,12 +33,16 @@ from ahriman.core.formatters import VersionPrinter
|
||||
class Versions(Handler):
|
||||
"""
|
||||
version handler
|
||||
|
||||
Attributes:
|
||||
PEP423_PACKAGE_NAME(str): (class attribute) special regex for valid PEP423 package name
|
||||
"""
|
||||
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
||||
PEP423_PACKAGE_NAME = re.compile(r"^[A-Za-z0-9._-]+")
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
@ -51,37 +56,43 @@ class Versions(Handler):
|
||||
"""
|
||||
VersionPrinter(f"Module version {version.__version__}",
|
||||
{"Python": sys.version}).print(verbose=False, separator=" ")
|
||||
packages = Versions.package_dependencies("ahriman", ("pacman", "s3", "web"))
|
||||
VersionPrinter("Installed packages", packages).print(verbose=False, separator=" ")
|
||||
packages = Versions.package_dependencies("ahriman")
|
||||
VersionPrinter("Installed packages", dict(packages)).print(verbose=False, separator=" ")
|
||||
|
||||
@staticmethod
|
||||
def package_dependencies(root: str, root_extras: Tuple[str, ...] = ()) -> Dict[str, str]:
|
||||
def package_dependencies(root: str) -> Generator[tuple[str, str], None, None]:
|
||||
"""
|
||||
extract list of ahriman package dependencies installed into system with their versions
|
||||
|
||||
Args:
|
||||
root(str): root package name
|
||||
root_extras(Tuple[str, ...]): extras for the root package (Default value = ())
|
||||
|
||||
Returns:
|
||||
Dict[str, str]: map of installed dependency to its version
|
||||
Generator[tuple[str, str], None, None]: map of installed dependency to its version
|
||||
"""
|
||||
resources: Dict[str, pkg_resources.Distribution] = pkg_resources.working_set.by_key # type: ignore
|
||||
def dependencies_by_key(key: str) -> Generator[str, None, None]:
|
||||
# in importlib it returns requires in the following format
|
||||
# ["pytest (>=3.0.0) ; extra == 'test'", "pytest-cov ; extra == 'test'"]
|
||||
try:
|
||||
requires = metadata.requires(key)
|
||||
except metadata.PackageNotFoundError:
|
||||
return
|
||||
for entry in requires or []:
|
||||
yield from Versions.PEP423_PACKAGE_NAME.findall(entry)
|
||||
|
||||
def dependencies_by_key(key: str, extras: Tuple[str, ...] = ()) -> List[str]:
|
||||
return [entry.key for entry in resources[key].requires(extras)]
|
||||
|
||||
keys: List[str] = []
|
||||
portion = {key for key in dependencies_by_key(root, root_extras) if key in resources}
|
||||
keys: list[str] = []
|
||||
portion = set(dependencies_by_key(root))
|
||||
while portion:
|
||||
keys.extend(portion)
|
||||
portion = {
|
||||
key
|
||||
for key in sum((dependencies_by_key(key) for key in portion), start=[])
|
||||
if key not in keys and key in resources
|
||||
for key in sum((list(dependencies_by_key(key)) for key in portion), start=[])
|
||||
if key not in keys
|
||||
}
|
||||
|
||||
return {
|
||||
resource.project_name: resource.version
|
||||
for resource in map(lambda key: resources[key], keys)
|
||||
}
|
||||
for key in keys:
|
||||
try:
|
||||
distribution = metadata.distribution(key)
|
||||
yield distribution.name, distribution.version
|
||||
except metadata.PackageNotFoundError:
|
||||
continue
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -19,8 +19,6 @@
|
||||
#
|
||||
import argparse
|
||||
|
||||
from typing import Type
|
||||
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.spawn import Spawn
|
||||
@ -35,7 +33,7 @@ class Web(Handler):
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # required to be able to spawn external processes
|
||||
|
||||
@classmethod
|
||||
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *,
|
||||
report: bool, unsafe: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
@ -55,3 +53,7 @@ class Web(Handler):
|
||||
|
||||
application = setup_service(architecture, configuration, spawner)
|
||||
run_server(application)
|
||||
|
||||
# terminate spawn process at the last
|
||||
spawner.stop()
|
||||
spawner.join()
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -17,13 +17,10 @@
|
||||
# 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 __future__ import annotations
|
||||
|
||||
import argparse
|
||||
|
||||
from pathlib import Path
|
||||
from types import TracebackType
|
||||
from typing import Literal, Optional, Type
|
||||
from typing import Literal, Self
|
||||
|
||||
from ahriman import version
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -68,47 +65,13 @@ class Lock(LazyLogging):
|
||||
architecture(str): repository architecture
|
||||
configuration(Configuration): configuration instance
|
||||
"""
|
||||
self.path = Path(f"{args.lock}_{architecture}") if args.lock is not None else None
|
||||
self.path = args.lock.with_stem(f"{args.lock.stem}_{architecture}") if args.lock is not None else None
|
||||
self.force = args.force
|
||||
self.unsafe = args.unsafe
|
||||
|
||||
self.paths = configuration.repository_paths
|
||||
self.reporter = Client.load(configuration, report=args.report)
|
||||
|
||||
def __enter__(self) -> Lock:
|
||||
"""
|
||||
default workflow is the following:
|
||||
|
||||
1. Check user UID
|
||||
2. Check if there is lock file
|
||||
3. Check web status watcher status
|
||||
4. Create lock file
|
||||
5. Report to status page if enabled
|
||||
"""
|
||||
self.check_user()
|
||||
self.check_version()
|
||||
self.create()
|
||||
self.reporter.update_self(BuildStatusEnum.Building)
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type: Optional[Type[Exception]], exc_val: Optional[Exception],
|
||||
exc_tb: TracebackType) -> Literal[False]:
|
||||
"""
|
||||
remove lock file when done
|
||||
|
||||
Args:
|
||||
exc_type(Optional[Type[Exception]]): exception type name if any
|
||||
exc_val(Optional[Exception]): exception raised if any
|
||||
exc_tb(TracebackType): exception traceback if any
|
||||
|
||||
Returns:
|
||||
Literal[False]: always False (do not suppress any exception)
|
||||
"""
|
||||
self.clear()
|
||||
status = BuildStatusEnum.Success if exc_val is None else BuildStatusEnum.Failed
|
||||
self.reporter.update_self(status)
|
||||
return False
|
||||
|
||||
def check_version(self) -> None:
|
||||
"""
|
||||
check web server version
|
||||
@ -145,3 +108,40 @@ class Lock(LazyLogging):
|
||||
self.path.touch(exist_ok=self.force)
|
||||
except FileExistsError:
|
||||
raise DuplicateRunError()
|
||||
|
||||
def __enter__(self) -> Self:
|
||||
"""
|
||||
default workflow is the following:
|
||||
|
||||
1. Check user UID
|
||||
2. Check if there is lock file
|
||||
3. Check web status watcher status
|
||||
4. Create lock file
|
||||
5. Report to status page if enabled
|
||||
|
||||
Returns:
|
||||
Self: always instance of self
|
||||
"""
|
||||
self.check_user()
|
||||
self.check_version()
|
||||
self.create()
|
||||
self.reporter.update_self(BuildStatusEnum.Building)
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type: type[Exception] | None, exc_val: Exception | None,
|
||||
exc_tb: TracebackType) -> Literal[False]:
|
||||
"""
|
||||
remove lock file when done
|
||||
|
||||
Args:
|
||||
exc_type(type[Exception] | None): exception type name if any
|
||||
exc_val(Exception | None): exception raised if any
|
||||
exc_tb(TracebackType): exception traceback if any
|
||||
|
||||
Returns:
|
||||
Literal[False]: always False (do not suppress any exception)
|
||||
"""
|
||||
self.clear()
|
||||
status = BuildStatusEnum.Success if exc_val is None else BuildStatusEnum.Failed
|
||||
self.reporter.update_self(status)
|
||||
return False
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -17,8 +17,9 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
from collections.abc import Iterator
|
||||
from contextvars import ContextVar
|
||||
from typing import Any, Dict, Iterator, TypeVar
|
||||
from typing import Any, TypeVar
|
||||
|
||||
from ahriman.models.context_key import ContextKey
|
||||
|
||||
@ -35,7 +36,7 @@ class _Context:
|
||||
"""
|
||||
default constructor. Must not be used directly
|
||||
"""
|
||||
self._content: Dict[str, Any] = {}
|
||||
self._content: dict[str, Any] = {}
|
||||
|
||||
def get(self, key: ContextKey[T]) -> T:
|
||||
"""
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -19,12 +19,15 @@
|
||||
#
|
||||
import shutil
|
||||
|
||||
from collections.abc import Callable, Generator
|
||||
from pathlib import Path
|
||||
from pyalpm import DB, Handle, Package, SIG_PACKAGE, error as PyalpmError # type: ignore
|
||||
from typing import Any, Callable, Generator, Set
|
||||
from pyalpm import DB, Handle, Package, SIG_PACKAGE, error as PyalpmError # type: ignore[import]
|
||||
from typing import Any
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.log import LazyLogging
|
||||
from ahriman.core.util import trim_package
|
||||
from ahriman.models.pacman_synchronization import PacmanSynchronization
|
||||
from ahriman.models.repository_paths import RepositoryPaths
|
||||
|
||||
|
||||
@ -38,28 +41,28 @@ class Pacman(LazyLogging):
|
||||
|
||||
handle: Handle
|
||||
|
||||
def __init__(self, architecture: str, configuration: Configuration, *, refresh_database: int) -> None:
|
||||
def __init__(self, architecture: str, configuration: Configuration, *,
|
||||
refresh_database: PacmanSynchronization) -> None:
|
||||
"""
|
||||
default constructor
|
||||
|
||||
Args:
|
||||
architecture(str): repository architecture
|
||||
configuration(Configuration): configuration instance
|
||||
refresh_database(int): synchronize local cache to remote. If set to ``0``, no syncronization will be
|
||||
enabled, if set to ``1`` - normal syncronization, if set to ``2`` - force syncronization
|
||||
refresh_database(PacmanSynchronization): synchronize local cache to remote
|
||||
"""
|
||||
self.__create_handle_fn: Callable[[], Handle] = lambda: self.__create_handle(
|
||||
architecture, configuration, refresh_database=refresh_database)
|
||||
|
||||
def __create_handle(self, architecture: str, configuration: Configuration, *, refresh_database: int) -> Handle:
|
||||
def __create_handle(self, architecture: str, configuration: Configuration, *,
|
||||
refresh_database: PacmanSynchronization) -> Handle:
|
||||
"""
|
||||
create lazy handle function
|
||||
|
||||
Args:
|
||||
architecture(str): repository architecture
|
||||
configuration(Configuration): configuration instance
|
||||
refresh_database(int): synchronize local cache to remote. If set to ``0``, no syncronization will be
|
||||
enabled, if set to ``1`` - normal syncronization, if set to ``2`` - force syncronization
|
||||
refresh_database(PacmanSynchronization): synchronize local cache to remote
|
||||
|
||||
Returns:
|
||||
Handle: fully initialized pacman handle
|
||||
@ -77,29 +80,10 @@ class Pacman(LazyLogging):
|
||||
self.database_copy(handle, database, pacman_root, paths, use_ahriman_cache=use_ahriman_cache)
|
||||
|
||||
if use_ahriman_cache and refresh_database:
|
||||
self.database_sync(handle, force=refresh_database > 1)
|
||||
self.database_sync(handle, force=refresh_database == PacmanSynchronization.Force)
|
||||
|
||||
return handle
|
||||
|
||||
def __getattr__(self, item: str) -> Any:
|
||||
"""
|
||||
pacman handle extractor
|
||||
|
||||
Args:
|
||||
item(str): property name
|
||||
|
||||
Returns:
|
||||
Any: attribute by its name
|
||||
|
||||
Raises:
|
||||
AttributeError: in case if no such attribute found
|
||||
"""
|
||||
if item == "handle":
|
||||
handle = self.__create_handle_fn()
|
||||
setattr(self, item, handle)
|
||||
return handle
|
||||
return super().__getattr__(item) # required for logging attribute
|
||||
|
||||
def database_copy(self, handle: Handle, database: DB, pacman_root: Path, paths: RepositoryPaths, *,
|
||||
use_ahriman_cache: bool) -> None:
|
||||
"""
|
||||
@ -145,7 +129,7 @@ class Pacman(LazyLogging):
|
||||
Returns:
|
||||
DB: loaded pacman database instance
|
||||
"""
|
||||
self.logger.info("loading pacman databases")
|
||||
self.logger.info("loading pacman database %s", repository)
|
||||
database: DB = handle.register_syncdb(repository, SIG_PACKAGE)
|
||||
# replace variables in mirror address
|
||||
database.servers = [mirror.replace("$repo", repository).replace("$arch", architecture)]
|
||||
@ -157,7 +141,7 @@ class Pacman(LazyLogging):
|
||||
|
||||
Args:
|
||||
handle(Handle): pacman handle which will be used for database sync
|
||||
force(bool): force database syncronization (same as ``pacman -Syy``)
|
||||
force(bool): force database synchronization (same as ``pacman -Syy``)
|
||||
"""
|
||||
self.logger.info("refresh ahriman's home pacman database (force refresh %s)", force)
|
||||
transaction = handle.init_transaction()
|
||||
@ -184,17 +168,38 @@ class Pacman(LazyLogging):
|
||||
continue
|
||||
yield package
|
||||
|
||||
def packages(self) -> Set[str]:
|
||||
def packages(self) -> set[str]:
|
||||
"""
|
||||
get list of packages known for alpm
|
||||
|
||||
Returns:
|
||||
Set[str]: list of package names
|
||||
set[str]: list of package names
|
||||
"""
|
||||
result: Set[str] = set()
|
||||
result: set[str] = set()
|
||||
for database in self.handle.get_syncdbs():
|
||||
for package in database.pkgcache:
|
||||
result.add(package.name) # package itself
|
||||
result.update(package.provides) # provides list for meta-packages
|
||||
# package itself
|
||||
result.add(package.name)
|
||||
# provides list for meta-packages
|
||||
result.update(trim_package(provides) for provides in package.provides)
|
||||
|
||||
return result
|
||||
|
||||
def __getattr__(self, item: str) -> Any:
|
||||
"""
|
||||
pacman handle extractor
|
||||
|
||||
Args:
|
||||
item(str): property name
|
||||
|
||||
Returns:
|
||||
Any: attribute by its name
|
||||
|
||||
Raises:
|
||||
AttributeError: in case if no such attribute found
|
||||
"""
|
||||
if item == "handle":
|
||||
handle = self.__create_handle_fn()
|
||||
setattr(self, item, handle)
|
||||
return handle
|
||||
return super().__getattr__(item) # required for logging attribute
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -19,7 +19,7 @@
|
||||
#
|
||||
import requests
|
||||
|
||||
from typing import Any, Dict, List, Type
|
||||
from typing import Any
|
||||
|
||||
from ahriman.core.alpm.pacman import Pacman
|
||||
from ahriman.core.alpm.remote import Remote
|
||||
@ -44,28 +44,8 @@ class AUR(Remote):
|
||||
DEFAULT_RPC_VERSION = "5"
|
||||
DEFAULT_TIMEOUT = 30
|
||||
|
||||
@staticmethod
|
||||
def parse_response(response: Dict[str, Any]) -> List[AURPackage]:
|
||||
"""
|
||||
parse RPC response to package list
|
||||
|
||||
Args:
|
||||
response(Dict[str, Any]): RPC response json
|
||||
|
||||
Returns:
|
||||
List[AURPackage]: list of parsed packages
|
||||
|
||||
Raises:
|
||||
InvalidPackageInfo: for error API response
|
||||
"""
|
||||
response_type = response["type"]
|
||||
if response_type == "error":
|
||||
error_details = response.get("error", "Unknown API error")
|
||||
raise PackageInfoError(error_details)
|
||||
return [AURPackage.from_json(package) for package in response["results"]]
|
||||
|
||||
@classmethod
|
||||
def remote_git_url(cls: Type[Remote], package_base: str, repository: str) -> str:
|
||||
def remote_git_url(cls, package_base: str, repository: str) -> str:
|
||||
"""
|
||||
generate remote git url from the package base
|
||||
|
||||
@ -79,7 +59,7 @@ class AUR(Remote):
|
||||
return f"{AUR.DEFAULT_AUR_URL}/{package_base}.git"
|
||||
|
||||
@classmethod
|
||||
def remote_web_url(cls: Type[Remote], package_base: str) -> str:
|
||||
def remote_web_url(cls, package_base: str) -> str:
|
||||
"""
|
||||
generate remote web url from the package base
|
||||
|
||||
@ -91,7 +71,27 @@ class AUR(Remote):
|
||||
"""
|
||||
return f"{AUR.DEFAULT_AUR_URL}/packages/{package_base}"
|
||||
|
||||
def make_request(self, request_type: str, *args: str, **kwargs: str) -> List[AURPackage]:
|
||||
@staticmethod
|
||||
def parse_response(response: dict[str, Any]) -> list[AURPackage]:
|
||||
"""
|
||||
parse RPC response to package list
|
||||
|
||||
Args:
|
||||
response(dict[str, Any]): RPC response json
|
||||
|
||||
Returns:
|
||||
list[AURPackage]: list of parsed packages
|
||||
|
||||
Raises:
|
||||
InvalidPackageInfo: for error API response
|
||||
"""
|
||||
response_type = response["type"]
|
||||
if response_type == "error":
|
||||
error_details = response.get("error", "Unknown API error")
|
||||
raise PackageInfoError(error_details)
|
||||
return [AURPackage.from_json(package) for package in response["results"]]
|
||||
|
||||
def make_request(self, request_type: str, *args: str, **kwargs: str) -> list[AURPackage]:
|
||||
"""
|
||||
perform request to AUR RPC
|
||||
|
||||
@ -101,9 +101,9 @@ class AUR(Remote):
|
||||
**kwargs(str): list of additional named parameters like by
|
||||
|
||||
Returns:
|
||||
List[AURPackage]: response parsed to package list
|
||||
list[AURPackage]: response parsed to package list
|
||||
"""
|
||||
query: Dict[str, Any] = {
|
||||
query: dict[str, Any] = {
|
||||
"type": request_type,
|
||||
"v": self.DEFAULT_RPC_VERSION
|
||||
}
|
||||
@ -145,7 +145,7 @@ class AUR(Remote):
|
||||
except StopIteration:
|
||||
raise UnknownPackageError(package_name)
|
||||
|
||||
def package_search(self, *keywords: str, pacman: Pacman) -> List[AURPackage]:
|
||||
def package_search(self, *keywords: str, pacman: Pacman) -> list[AURPackage]:
|
||||
"""
|
||||
search package in AUR web
|
||||
|
||||
@ -154,6 +154,6 @@ class AUR(Remote):
|
||||
pacman(Pacman): alpm wrapper instance
|
||||
|
||||
Returns:
|
||||
List[AURPackage]: list of packages which match the criteria
|
||||
list[AURPackage]: list of packages which match the criteria
|
||||
"""
|
||||
return self.make_request("search", *keywords, by="name-desc")
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -19,7 +19,7 @@
|
||||
#
|
||||
import requests
|
||||
|
||||
from typing import Any, Dict, List, Type
|
||||
from typing import Any
|
||||
|
||||
from ahriman.core.alpm.pacman import Pacman
|
||||
from ahriman.core.alpm.remote import Remote
|
||||
@ -34,7 +34,7 @@ class Official(Remote):
|
||||
|
||||
Attributes:
|
||||
DEFAULT_ARCHLINUX_URL(str): (class attribute) default archlinux url
|
||||
DEFAULT_SEARCH_REPOSITORIES(List[str]): (class attribute) default list of repositories to search
|
||||
DEFAULT_SEARCH_REPOSITORIES(list[str]): (class attribute) default list of repositories to search
|
||||
DEFAULT_RPC_URL(str): (class attribute) default archlinux repositories RPC url
|
||||
DEFAULT_TIMEOUT(int): (class attribute) HTTP request timeout in seconds
|
||||
"""
|
||||
@ -44,26 +44,8 @@ class Official(Remote):
|
||||
DEFAULT_RPC_URL = "https://archlinux.org/packages/search/json"
|
||||
DEFAULT_TIMEOUT = 30
|
||||
|
||||
@staticmethod
|
||||
def parse_response(response: Dict[str, Any]) -> List[AURPackage]:
|
||||
"""
|
||||
parse RPC response to package list
|
||||
|
||||
Args:
|
||||
response(Dict[str, Any]): RPC response json
|
||||
|
||||
Returns:
|
||||
List[AURPackage]: list of parsed packages
|
||||
|
||||
Raises:
|
||||
InvalidPackageInfo: for error API response
|
||||
"""
|
||||
if not response["valid"]:
|
||||
raise PackageInfoError("API validation error")
|
||||
return [AURPackage.from_repo(package) for package in response["results"]]
|
||||
|
||||
@classmethod
|
||||
def remote_git_url(cls: Type[Remote], package_base: str, repository: str) -> str:
|
||||
def remote_git_url(cls, package_base: str, repository: str) -> str:
|
||||
"""
|
||||
generate remote git url from the package base
|
||||
|
||||
@ -79,7 +61,7 @@ class Official(Remote):
|
||||
return "https://github.com/archlinux/svntogit-community.git"
|
||||
|
||||
@classmethod
|
||||
def remote_web_url(cls: Type[Remote], package_base: str) -> str:
|
||||
def remote_web_url(cls, package_base: str) -> str:
|
||||
"""
|
||||
generate remote web url from the package base
|
||||
|
||||
@ -91,7 +73,25 @@ class Official(Remote):
|
||||
"""
|
||||
return f"{Official.DEFAULT_ARCHLINUX_URL}/packages/{package_base}"
|
||||
|
||||
def make_request(self, *args: str, by: str) -> List[AURPackage]:
|
||||
@staticmethod
|
||||
def parse_response(response: dict[str, Any]) -> list[AURPackage]:
|
||||
"""
|
||||
parse RPC response to package list
|
||||
|
||||
Args:
|
||||
response(dict[str, Any]): RPC response json
|
||||
|
||||
Returns:
|
||||
list[AURPackage]: list of parsed packages
|
||||
|
||||
Raises:
|
||||
InvalidPackageInfo: for error API response
|
||||
"""
|
||||
if not response["valid"]:
|
||||
raise PackageInfoError("API validation error")
|
||||
return [AURPackage.from_repo(package) for package in response["results"]]
|
||||
|
||||
def make_request(self, *args: str, by: str) -> list[AURPackage]:
|
||||
"""
|
||||
perform request to official repositories RPC
|
||||
|
||||
@ -100,7 +100,7 @@ class Official(Remote):
|
||||
by(str): search by the field
|
||||
|
||||
Returns:
|
||||
List[AURPackage]: response parsed to package list
|
||||
list[AURPackage]: response parsed to package list
|
||||
"""
|
||||
try:
|
||||
response = requests.get(
|
||||
@ -133,7 +133,7 @@ class Official(Remote):
|
||||
except StopIteration:
|
||||
raise UnknownPackageError(package_name)
|
||||
|
||||
def package_search(self, *keywords: str, pacman: Pacman) -> List[AURPackage]:
|
||||
def package_search(self, *keywords: str, pacman: Pacman) -> list[AURPackage]:
|
||||
"""
|
||||
search package in AUR web
|
||||
|
||||
@ -142,6 +142,6 @@ class Official(Remote):
|
||||
pacman(Pacman): alpm wrapper instance
|
||||
|
||||
Returns:
|
||||
List[AURPackage]: list of packages which match the criteria
|
||||
list[AURPackage]: list of packages which match the criteria
|
||||
"""
|
||||
return self.make_request(*keywords, by="q")
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -17,10 +17,6 @@
|
||||
# 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 __future__ import annotations
|
||||
|
||||
from typing import Dict, List, Type
|
||||
|
||||
from ahriman.core.alpm.pacman import Pacman
|
||||
from ahriman.core.log import LazyLogging
|
||||
from ahriman.models.aur_package import AURPackage
|
||||
@ -44,7 +40,7 @@ class Remote(LazyLogging):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def info(cls: Type[Remote], package_name: str, *, pacman: Pacman) -> AURPackage:
|
||||
def info(cls, package_name: str, *, pacman: Pacman) -> AURPackage:
|
||||
"""
|
||||
get package info by its name
|
||||
|
||||
@ -58,7 +54,7 @@ class Remote(LazyLogging):
|
||||
return cls().package_info(package_name, pacman=pacman)
|
||||
|
||||
@classmethod
|
||||
def multisearch(cls: Type[Remote], *keywords: str, pacman: Pacman) -> List[AURPackage]:
|
||||
def multisearch(cls, *keywords: str, pacman: Pacman) -> list[AURPackage]:
|
||||
"""
|
||||
search in remote repository by using API with multiple words. This method is required in order to handle
|
||||
https://bugs.archlinux.org/task/49133. In addition, short words will be dropped
|
||||
@ -68,10 +64,10 @@ class Remote(LazyLogging):
|
||||
pacman(Pacman): alpm wrapper instance
|
||||
|
||||
Returns:
|
||||
List[AURPackage]: list of packages each of them matches all search terms
|
||||
list[AURPackage]: list of packages each of them matches all search terms
|
||||
"""
|
||||
instance = cls()
|
||||
packages: Dict[str, AURPackage] = {}
|
||||
packages: dict[str, AURPackage] = {}
|
||||
for term in filter(lambda word: len(word) >= 3, keywords):
|
||||
portion = instance.search(term, pacman=pacman)
|
||||
packages = {
|
||||
@ -82,7 +78,7 @@ class Remote(LazyLogging):
|
||||
return list(packages.values())
|
||||
|
||||
@classmethod
|
||||
def remote_git_url(cls: Type[Remote], package_base: str, repository: str) -> str:
|
||||
def remote_git_url(cls, package_base: str, repository: str) -> str:
|
||||
"""
|
||||
generate remote git url from the package base
|
||||
|
||||
@ -99,7 +95,7 @@ class Remote(LazyLogging):
|
||||
raise NotImplementedError
|
||||
|
||||
@classmethod
|
||||
def remote_web_url(cls: Type[Remote], package_base: str) -> str:
|
||||
def remote_web_url(cls, package_base: str) -> str:
|
||||
"""
|
||||
generate remote web url from the package base
|
||||
|
||||
@ -115,7 +111,7 @@ class Remote(LazyLogging):
|
||||
raise NotImplementedError
|
||||
|
||||
@classmethod
|
||||
def search(cls: Type[Remote], *keywords: str, pacman: Pacman) -> List[AURPackage]:
|
||||
def search(cls, *keywords: str, pacman: Pacman) -> list[AURPackage]:
|
||||
"""
|
||||
search package in AUR web
|
||||
|
||||
@ -124,7 +120,7 @@ class Remote(LazyLogging):
|
||||
pacman(Pacman): alpm wrapper instance
|
||||
|
||||
Returns:
|
||||
List[AURPackage]: list of packages which match the criteria
|
||||
list[AURPackage]: list of packages which match the criteria
|
||||
"""
|
||||
return cls().package_search(*keywords, pacman=pacman)
|
||||
|
||||
@ -144,7 +140,7 @@ class Remote(LazyLogging):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def package_search(self, *keywords: str, pacman: Pacman) -> List[AURPackage]:
|
||||
def package_search(self, *keywords: str, pacman: Pacman) -> list[AURPackage]:
|
||||
"""
|
||||
search package in AUR web
|
||||
|
||||
@ -153,7 +149,7 @@ class Remote(LazyLogging):
|
||||
pacman(Pacman): alpm wrapper instance
|
||||
|
||||
Returns:
|
||||
List[AURPackage]: list of packages which match the criteria
|
||||
list[AURPackage]: list of packages which match the criteria
|
||||
|
||||
Raises:
|
||||
NotImplementedError: not implemented method
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -18,7 +18,6 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
from ahriman.core.exceptions import BuildError
|
||||
from ahriman.core.log import LazyLogging
|
||||
@ -33,20 +32,20 @@ class Repo(LazyLogging):
|
||||
Attributes:
|
||||
name(str): repository name
|
||||
paths(RepositoryPaths): repository paths instance
|
||||
sign_args(List[str]): additional args which have to be used to sign repository archive
|
||||
sign_args(list[str]): additional args which have to be used to sign repository archive
|
||||
uid(int): uid of the repository owner user
|
||||
"""
|
||||
|
||||
_check_output = check_output
|
||||
|
||||
def __init__(self, name: str, paths: RepositoryPaths, sign_args: List[str]) -> None:
|
||||
def __init__(self, name: str, paths: RepositoryPaths, sign_args: list[str]) -> None:
|
||||
"""
|
||||
default constructor
|
||||
|
||||
Args:
|
||||
name(str): repository name
|
||||
paths(RepositoryPaths): repository paths instance
|
||||
sign_args(List[str]): additional args which have to be used to sign repository archive
|
||||
sign_args(list[str]): additional args which have to be used to sign repository archive
|
||||
"""
|
||||
self.name = name
|
||||
self.paths = paths
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -18,6 +18,3 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
from ahriman.core.auth.auth import Auth
|
||||
|
||||
from ahriman.core.auth.mapping import Mapping
|
||||
from ahriman.core.auth.oauth import OAuth
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -19,8 +19,6 @@
|
||||
#
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Optional, Type
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.database import SQLite
|
||||
from ahriman.core.log import LazyLogging
|
||||
@ -64,8 +62,8 @@ class Auth(LazyLogging):
|
||||
"""
|
||||
return """<button type="button" class="btn btn-link" data-bs-toggle="modal" data-bs-target="#login-modal" style="text-decoration: none"><i class="bi bi-box-arrow-in-right"></i> login</button>"""
|
||||
|
||||
@classmethod
|
||||
def load(cls: Type[Auth], configuration: Configuration, database: SQLite) -> Auth:
|
||||
@staticmethod
|
||||
def load(configuration: Configuration, database: SQLite) -> Auth:
|
||||
"""
|
||||
load authorization module from settings
|
||||
|
||||
@ -78,20 +76,20 @@ class Auth(LazyLogging):
|
||||
"""
|
||||
provider = AuthSettings.from_option(configuration.get("auth", "target", fallback="disabled"))
|
||||
if provider == AuthSettings.Configuration:
|
||||
from ahriman.core.auth import Mapping
|
||||
from ahriman.core.auth.mapping import Mapping
|
||||
return Mapping(configuration, database)
|
||||
if provider == AuthSettings.OAuth:
|
||||
from ahriman.core.auth import OAuth
|
||||
from ahriman.core.auth.oauth import OAuth
|
||||
return OAuth(configuration, database)
|
||||
return cls(configuration)
|
||||
return Auth(configuration)
|
||||
|
||||
async def check_credentials(self, username: Optional[str], password: Optional[str]) -> bool:
|
||||
async def check_credentials(self, username: str | None, password: str | None) -> bool:
|
||||
"""
|
||||
validate user password
|
||||
|
||||
Args:
|
||||
username(Optional[str]): username
|
||||
password(Optional[str]): entered password
|
||||
username(str | None): username
|
||||
password(str | None): entered password
|
||||
|
||||
Returns:
|
||||
bool: True in case if password matches, False otherwise
|
||||
@ -99,12 +97,12 @@ class Auth(LazyLogging):
|
||||
del username, password
|
||||
return True
|
||||
|
||||
async def known_username(self, username: Optional[str]) -> bool:
|
||||
async def known_username(self, username: str | None) -> bool:
|
||||
"""
|
||||
check if user is known
|
||||
|
||||
Args:
|
||||
username(Optional[str]): username
|
||||
username(str | None): username
|
||||
|
||||
Returns:
|
||||
bool: True in case if user is known and can be authorized and False otherwise
|
||||
@ -112,14 +110,14 @@ class Auth(LazyLogging):
|
||||
del username
|
||||
return True
|
||||
|
||||
async def verify_access(self, username: str, required: UserAccess, context: Optional[str]) -> bool:
|
||||
async def verify_access(self, username: str, required: UserAccess, context: str | None) -> bool:
|
||||
"""
|
||||
validate if user has access to requested resource
|
||||
|
||||
Args:
|
||||
username(str): username
|
||||
required(UserAccess): required access level
|
||||
context(Optional[str]): URI request path
|
||||
context(str | None): URI request path
|
||||
|
||||
Returns:
|
||||
bool: True in case if user is allowed to do this request and False otherwise
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -20,7 +20,7 @@
|
||||
from typing import Any
|
||||
|
||||
try:
|
||||
import aiohttp_security # type: ignore
|
||||
import aiohttp_security # type: ignore[import]
|
||||
_has_aiohttp_security = True
|
||||
except ImportError:
|
||||
_has_aiohttp_security = False
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -17,8 +17,6 @@
|
||||
# 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 typing import Optional
|
||||
|
||||
from ahriman.core.auth import Auth
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.database import SQLite
|
||||
@ -50,13 +48,13 @@ class Mapping(Auth):
|
||||
self.database = database
|
||||
self.salt = configuration.get("auth", "salt")
|
||||
|
||||
async def check_credentials(self, username: Optional[str], password: Optional[str]) -> bool:
|
||||
async def check_credentials(self, username: str | None, password: str | None) -> bool:
|
||||
"""
|
||||
validate user password
|
||||
|
||||
Args:
|
||||
username(Optional[str]): username
|
||||
password(Optional[str]): entered password
|
||||
username(str | None): username
|
||||
password(str | None): entered password
|
||||
|
||||
Returns:
|
||||
bool: True in case if password matches, False otherwise
|
||||
@ -66,7 +64,7 @@ class Mapping(Auth):
|
||||
user = self.get_user(username)
|
||||
return user is not None and user.check_credentials(password, self.salt)
|
||||
|
||||
def get_user(self, username: str) -> Optional[User]:
|
||||
def get_user(self, username: str) -> User | None:
|
||||
"""
|
||||
retrieve user from in-memory mapping
|
||||
|
||||
@ -74,30 +72,30 @@ class Mapping(Auth):
|
||||
username(str): username
|
||||
|
||||
Returns:
|
||||
Optional[User]: user descriptor if username is known and None otherwise
|
||||
User | None: user descriptor if username is known and None otherwise
|
||||
"""
|
||||
return self.database.user_get(username)
|
||||
|
||||
async def known_username(self, username: Optional[str]) -> bool:
|
||||
async def known_username(self, username: str | None) -> bool:
|
||||
"""
|
||||
check if user is known
|
||||
|
||||
Args:
|
||||
username(Optional[str]): username
|
||||
username(str | None): username
|
||||
|
||||
Returns:
|
||||
bool: True in case if user is known and can be authorized and False otherwise
|
||||
"""
|
||||
return username is not None and self.get_user(username) is not None
|
||||
|
||||
async def verify_access(self, username: str, required: UserAccess, context: Optional[str]) -> bool:
|
||||
async def verify_access(self, username: str, required: UserAccess, context: str | None) -> bool:
|
||||
"""
|
||||
validate if user has access to requested resource
|
||||
|
||||
Args:
|
||||
username(str): username
|
||||
required(UserAccess): required access level
|
||||
context(Optional[str]): URI request path
|
||||
context(str | None): URI request path
|
||||
|
||||
Returns:
|
||||
bool: True in case if user is allowed to do this request and False otherwise
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -19,9 +19,7 @@
|
||||
#
|
||||
import aioauth_client
|
||||
|
||||
from typing import Optional, Type
|
||||
|
||||
from ahriman.core.auth import Mapping
|
||||
from ahriman.core.auth.mapping import Mapping
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.database import SQLite
|
||||
from ahriman.core.exceptions import OptionError
|
||||
@ -72,7 +70,7 @@ class OAuth(Mapping):
|
||||
return """<a class="nav-link" href="/api/v1/login" title="login via OAuth2"><i class="bi bi-google"></i> login</a>"""
|
||||
|
||||
@staticmethod
|
||||
def get_provider(name: str) -> Type[aioauth_client.OAuth2Client]:
|
||||
def get_provider(name: str) -> type[aioauth_client.OAuth2Client]:
|
||||
"""
|
||||
load OAuth2 provider by name
|
||||
|
||||
@ -80,12 +78,12 @@ class OAuth(Mapping):
|
||||
name(str): name of the provider. Must be valid class defined in aioauth-client library
|
||||
|
||||
Returns:
|
||||
Type[aioauth_client.OAuth2Client]: loaded provider type
|
||||
type[aioauth_client.OAuth2Client]: loaded provider type
|
||||
|
||||
Raises:
|
||||
InvalidOption: in case if invalid OAuth provider name supplied
|
||||
"""
|
||||
provider: Type[aioauth_client.OAuth2Client] = getattr(aioauth_client, name)
|
||||
provider: type[aioauth_client.OAuth2Client] = getattr(aioauth_client, name)
|
||||
try:
|
||||
is_oauth2_client = issubclass(provider, aioauth_client.OAuth2Client)
|
||||
except TypeError: # what if it is random string?
|
||||
@ -114,7 +112,7 @@ class OAuth(Mapping):
|
||||
uri: str = client.get_authorize_url(scope=self.scopes, redirect_uri=self.redirect_uri)
|
||||
return uri
|
||||
|
||||
async def get_oauth_username(self, code: str) -> Optional[str]:
|
||||
async def get_oauth_username(self, code: str) -> str | None:
|
||||
"""
|
||||
extract OAuth username from remote
|
||||
|
||||
@ -122,7 +120,7 @@ class OAuth(Mapping):
|
||||
code(str): authorization code provided by external service
|
||||
|
||||
Returns:
|
||||
Optional[str]: username as is in OAuth provider
|
||||
str | None: username as is in OAuth provider
|
||||
"""
|
||||
try:
|
||||
client = self.get_client()
|
||||
@ -130,7 +128,7 @@ class OAuth(Mapping):
|
||||
client.access_token = access_token
|
||||
|
||||
user, _ = await client.user_info()
|
||||
username: str = user.email # type: ignore
|
||||
username: str = user.email # type: ignore[attr-defined]
|
||||
return username
|
||||
except Exception:
|
||||
self.logger.exception("got exception while performing request")
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -20,7 +20,6 @@
|
||||
import shutil
|
||||
|
||||
from pathlib import Path
|
||||
from typing import List, Optional
|
||||
|
||||
from ahriman.core.log import LazyLogging
|
||||
from ahriman.core.util import check_output, utcnow, walk
|
||||
@ -44,7 +43,7 @@ class Sources(LazyLogging):
|
||||
_check_output = check_output
|
||||
|
||||
@staticmethod
|
||||
def extend_architectures(sources_dir: Path, architecture: str) -> List[PkgbuildPatch]:
|
||||
def extend_architectures(sources_dir: Path, architecture: str) -> list[PkgbuildPatch]:
|
||||
"""
|
||||
extend existing PKGBUILD with repository architecture
|
||||
|
||||
@ -53,7 +52,7 @@ class Sources(LazyLogging):
|
||||
architecture(str): repository architecture
|
||||
|
||||
Returns:
|
||||
List[PkgbuildPatch]: generated patch for PKGBUILD architectures if required
|
||||
list[PkgbuildPatch]: generated patch for PKGBUILD architectures if required
|
||||
"""
|
||||
architectures = Package.supported_architectures(sources_dir)
|
||||
if "any" in architectures: # makepkg does not like when there is any other arch except for any
|
||||
@ -62,13 +61,13 @@ class Sources(LazyLogging):
|
||||
return [PkgbuildPatch("arch", list(architectures))]
|
||||
|
||||
@staticmethod
|
||||
def fetch(sources_dir: Path, remote: Optional[RemoteSource]) -> None:
|
||||
def fetch(sources_dir: Path, remote: RemoteSource | None) -> None:
|
||||
"""
|
||||
either clone repository or update it to origin/``remote.branch``
|
||||
|
||||
Args:
|
||||
sources_dir(Path): local path to fetch
|
||||
remote(Optional[RemoteSource]): remote target (from where to fetch)
|
||||
remote(RemoteSource | None): remote target (from where to fetch)
|
||||
"""
|
||||
instance = Sources()
|
||||
# local directory exists and there is .git directory
|
||||
@ -127,14 +126,14 @@ class Sources(LazyLogging):
|
||||
cwd=sources_dir, logger=instance.logger)
|
||||
|
||||
@staticmethod
|
||||
def load(sources_dir: Path, package: Package, patches: List[PkgbuildPatch], paths: RepositoryPaths) -> None:
|
||||
def load(sources_dir: Path, package: Package, patches: list[PkgbuildPatch], paths: RepositoryPaths) -> None:
|
||||
"""
|
||||
fetch sources from remote and apply patches
|
||||
|
||||
Args:
|
||||
sources_dir(Path): local path to fetch
|
||||
package(Package): package definitions
|
||||
patches(List[PkgbuildPatch]): optional patch to be applied
|
||||
patches(list[PkgbuildPatch]): optional patch to be applied
|
||||
paths(RepositoryPaths): repository paths instance
|
||||
"""
|
||||
instance = Sources()
|
||||
@ -165,7 +164,7 @@ class Sources(LazyLogging):
|
||||
return f"{diff}\n" # otherwise, patch will be broken
|
||||
|
||||
@staticmethod
|
||||
def push(sources_dir: Path, remote: RemoteSource, *pattern: str, commit_author: Optional[str] = None) -> None:
|
||||
def push(sources_dir: Path, remote: RemoteSource, *pattern: str, commit_author: str | None = None) -> None:
|
||||
"""
|
||||
commit selected changes and push files to the remote repository
|
||||
|
||||
@ -173,7 +172,7 @@ class Sources(LazyLogging):
|
||||
sources_dir(Path): local path to git repository
|
||||
remote(RemoteSource): remote target, branch and url
|
||||
*pattern(str): glob patterns
|
||||
commit_author(Optional[str], optional): commit author in form of git config (i.e. ``user <user@host>``)
|
||||
commit_author(str | None, optional): commit author in form of git config (i.e. ``user <user@host>``)
|
||||
(Default value = None)
|
||||
"""
|
||||
instance = Sources()
|
||||
@ -192,7 +191,7 @@ class Sources(LazyLogging):
|
||||
--intent-to-add git flag (Default value = False)
|
||||
"""
|
||||
# glob directory to find files which match the specified patterns
|
||||
found_files: List[Path] = []
|
||||
found_files: list[Path] = []
|
||||
for glob in pattern:
|
||||
found_files.extend(sources_dir.glob(glob))
|
||||
if not found_files:
|
||||
@ -203,15 +202,15 @@ class Sources(LazyLogging):
|
||||
Sources._check_output("git", "add", *args, *[str(fn.relative_to(sources_dir)) for fn in found_files],
|
||||
cwd=sources_dir, logger=self.logger)
|
||||
|
||||
def commit(self, sources_dir: Path, message: Optional[str] = None, author: Optional[str] = None) -> None:
|
||||
def commit(self, sources_dir: Path, message: str | None = None, author: str | None = None) -> None:
|
||||
"""
|
||||
commit changes
|
||||
|
||||
Args:
|
||||
sources_dir(Path): local path to git repository
|
||||
message(Optional[str], optional): optional commit message if any. If none set, message will be generated
|
||||
message(str | None, optional): optional commit message if any. If none set, message will be generated
|
||||
according to the current timestamp (Default value = None)
|
||||
author(Optional[str], optional): optional commit author if any (Default value = None)
|
||||
author(str | None, optional): optional commit author if any (Default value = None)
|
||||
"""
|
||||
if message is None:
|
||||
message = f"Autogenerated commit at {utcnow()}"
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -18,7 +18,6 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
from ahriman.core.build_tools.sources import Sources
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -35,6 +34,10 @@ class Task(LazyLogging):
|
||||
base package build task
|
||||
|
||||
Attributes:
|
||||
architecture(str): repository architecture
|
||||
build_command(str): build command
|
||||
build_flags(list[str]): list of additional flags to pkgctl
|
||||
name(str): repository name
|
||||
package(Package): package definitions
|
||||
paths(RepositoryPaths): repository paths instance
|
||||
uid(int): uid of the repository owner user
|
||||
@ -53,14 +56,15 @@ class Task(LazyLogging):
|
||||
"""
|
||||
self.package = package
|
||||
self.paths = paths
|
||||
|
||||
_, self.architecture = configuration.check_loaded()
|
||||
self.uid, _ = paths.root_owner
|
||||
self.name = configuration.get("repository", "name")
|
||||
|
||||
self.archbuild_flags = configuration.getlist("build", "archbuild_flags", fallback=[])
|
||||
self.build_command = configuration.get("build", "build_command")
|
||||
self.makepkg_flags = configuration.getlist("build", "makepkg_flags", fallback=[])
|
||||
self.makechrootpkg_flags = configuration.getlist("build", "makechrootpkg_flags", fallback=[])
|
||||
self.build_flags = configuration.getlist("build", "pkgctl_flags", fallback=[])
|
||||
|
||||
def build(self, sources_dir: Path) -> List[Path]:
|
||||
def build(self, sources_dir: Path) -> list[Path]:
|
||||
"""
|
||||
run package build
|
||||
|
||||
@ -68,12 +72,11 @@ class Task(LazyLogging):
|
||||
sources_dir(Path): path to where sources are
|
||||
|
||||
Returns:
|
||||
List[Path]: paths of produced packages
|
||||
list[Path]: paths of produced packages
|
||||
"""
|
||||
command = [self.build_command, "-r", str(self.paths.chroot)]
|
||||
command.extend(self.archbuild_flags)
|
||||
command.extend(["--"] + self.makechrootpkg_flags)
|
||||
command.extend(["--"] + self.makepkg_flags)
|
||||
command = [self.build_command, "build"] + self.build_flags
|
||||
command.extend(["--arch", self.architecture])
|
||||
command.extend(["--repo", self.name])
|
||||
self.logger.info("using %s for %s", command, self.package.base)
|
||||
|
||||
Task._check_output(
|
||||
|
20
src/ahriman/core/configuration/__init__.py
Normal file
20
src/ahriman/core/configuration/__init__.py
Normal file
@ -0,0 +1,20 @@
|
||||
#
|
||||
# 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 ahriman.core.configuration.configuration import Configuration
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
@ -17,14 +17,13 @@
|
||||
# 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 __future__ import annotations
|
||||
|
||||
import configparser
|
||||
import shlex
|
||||
import sys
|
||||
|
||||
from collections.abc import Callable
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List, Optional, Tuple, Type
|
||||
from typing import Any, Self
|
||||
|
||||
from ahriman.core.exceptions import InitializeError
|
||||
from ahriman.models.repository_paths import RepositoryPaths
|
||||
@ -35,11 +34,11 @@ class Configuration(configparser.RawConfigParser):
|
||||
extension for built-in configuration parser
|
||||
|
||||
Attributes:
|
||||
ARCHITECTURE_SPECIFIC_SECTIONS(List[str]): (class attribute) known sections which can be architecture specific.
|
||||
ARCHITECTURE_SPECIFIC_SECTIONS(list[str]): (class attribute) known sections which can be architecture specific.
|
||||
Required by dump and merging functions
|
||||
SYSTEM_CONFIGURATION_PATH(Path): (class attribute) default system configuration path distributed by package
|
||||
architecture(Optional[str]): repository architecture
|
||||
path(Optional[Path]): path to root configuration file
|
||||
architecture(str | None): repository architecture
|
||||
path(Path | None): path to root configuration file
|
||||
|
||||
Examples:
|
||||
Configuration class provides additional method in order to handle application configuration. Since this class is
|
||||
@ -56,13 +55,14 @@ class Configuration(configparser.RawConfigParser):
|
||||
architecture according to the merge rules. Moreover, the architecture names will be removed from section names.
|
||||
|
||||
In order to get current settings, the ``check_loaded`` method can be used. This method will raise an
|
||||
``InitializeException`` in case if configuration was not yet loaded::
|
||||
``InitializeError`` in case if configuration was not yet loaded::
|
||||
|
||||
>>> path, architecture = configuration.check_loaded()
|
||||
"""
|
||||
|
||||
ARCHITECTURE_SPECIFIC_SECTIONS = ["build", "sign", "web"]
|
||||
ARCHITECTURE_SPECIFIC_SECTIONS = ["alpm", "build", "sign", "web"]
|
||||
SYSTEM_CONFIGURATION_PATH = Path(sys.prefix) / "share" / "ahriman" / "settings" / "ahriman.ini"
|
||||
converters: dict[str, Callable[[str], Any]] # typing guard
|
||||
|
||||
def __init__(self, allow_no_value: bool = False) -> None:
|
||||
"""
|
||||
@ -74,10 +74,10 @@ class Configuration(configparser.RawConfigParser):
|
||||
"""
|
||||
configparser.RawConfigParser.__init__(self, allow_no_value=allow_no_value, converters={
|
||||
"list": shlex.split,
|
||||
"path": self.__convert_path,
|
||||
"path": self._convert_path,
|
||||
})
|
||||
self.architecture: Optional[str] = None
|
||||
self.path: Optional[Path] = None
|
||||
self.architecture: str | None = None
|
||||
self.path: Path | None = None
|
||||
|
||||
@property
|
||||
def include(self) -> Path:
|
||||
@ -111,7 +111,7 @@ class Configuration(configparser.RawConfigParser):
|
||||
return RepositoryPaths(self.getpath("repository", "root"), architecture)
|
||||
|
||||
@classmethod
|
||||
def from_path(cls: Type[Configuration], path: Path, architecture: str) -> Configuration:
|
||||
def from_path(cls, path: Path, architecture: str) -> Self:
|
||||
"""
|
||||
constructor with full object initialization
|
||||
|
||||
@ -120,7 +120,7 @@ class Configuration(configparser.RawConfigParser):
|
||||
architecture(str): repository architecture
|
||||
|
||||
Returns:
|
||||
Configuration: configuration instance
|
||||
Self: configuration instance
|
||||
"""
|
||||
configuration = cls()
|
||||
configuration.load(path)
|
||||
@ -141,7 +141,7 @@ class Configuration(configparser.RawConfigParser):
|
||||
"""
|
||||
return f"{section}:{suffix}"
|
||||
|
||||
def __convert_path(self, value: str) -> Path:
|
||||
def _convert_path(self, value: str) -> Path:
|
||||
"""
|
||||
convert string value to path object
|
||||
|
||||
@ -156,26 +156,26 @@ class Configuration(configparser.RawConfigParser):
|
||||
return path
|
||||
return self.path.parent / path
|
||||
|
||||
def check_loaded(self) -> Tuple[Path, str]:
|
||||
def check_loaded(self) -> tuple[Path, str]:
|
||||
"""
|
||||
check if service was actually loaded
|
||||
|
||||
Returns:
|
||||
Tuple[Path, str]: configuration root path and architecture if loaded
|
||||
tuple[Path, str]: configuration root path and architecture if loaded
|
||||
|
||||
Raises:
|
||||
InitializeException: in case if architecture and/or path are not set
|
||||
InitializeError: in case if architecture and/or path are not set
|
||||
"""
|
||||
if self.path is None or self.architecture is None:
|
||||
raise InitializeError("Configuration path and/or architecture are not set")
|
||||
return self.path, self.architecture
|
||||
|
||||
def dump(self) -> Dict[str, Dict[str, str]]:
|
||||
def dump(self) -> dict[str, dict[str, str]]:
|
||||
"""
|
||||
dump configuration to dictionary
|
||||
|
||||
Returns:
|
||||
Dict[str, Dict[str, str]]: configuration dump for specific architecture
|
||||
dict[str, dict[str, str]]: configuration dump for specific architecture
|
||||
"""
|
||||
return {
|
||||
section: dict(self[section])
|
||||
@ -184,11 +184,11 @@ class Configuration(configparser.RawConfigParser):
|
||||
|
||||
# pylint and mypy are too stupid to find these methods
|
||||
# pylint: disable=missing-function-docstring,multiple-statements,unused-argument
|
||||
def getlist(self, *args: Any, **kwargs: Any) -> List[str]: ... # type: ignore
|
||||
def getlist(self, *args: Any, **kwargs: Any) -> list[str]: ... # type: ignore[empty-body]
|
||||
|
||||
def getpath(self, *args: Any, **kwargs: Any) -> Path: ... # type: ignore
|
||||
def getpath(self, *args: Any, **kwargs: Any) -> Path: ... # type: ignore[empty-body]
|
||||
|
||||
def gettype(self, section: str, architecture: str) -> Tuple[str, str]:
|
||||
def gettype(self, section: str, architecture: str, *, fallback: str | None = None) -> tuple[str, str]:
|
||||
"""
|
||||
get type variable with fallback to old logic. Despite the fact that it has same semantics as other get* methods,
|
||||
but it has different argument list
|
||||
@ -196,24 +196,25 @@ class Configuration(configparser.RawConfigParser):
|
||||
Args:
|
||||
section(str): section name
|
||||
architecture(str): repository architecture
|
||||
fallback(str | None, optional): optional fallback type if any. If set, second element of the tuple will
|
||||
be always set to this value (Default value = None)
|
||||
|
||||
Returns:
|
||||
Tuple[str, str]: section name and found type name
|
||||
tuple[str, str]: section name and found type name
|
||||
|
||||
Raises:
|
||||
configparser.NoSectionError: in case if no section found
|
||||
"""
|
||||
group_type = self.get(section, "type", fallback=None) # new-style logic
|
||||
if group_type is not None:
|
||||
return section, group_type
|
||||
if (group_type := self.get(section, "type", fallback=fallback)) is not None:
|
||||
return section, group_type # new-style logic
|
||||
# okay lets check for the section with architecture name
|
||||
full_section = self.section_name(section, architecture)
|
||||
if self.has_section(full_section):
|
||||
return full_section, section
|
||||
# okay lets just use section as type
|
||||
if not self.has_section(section):
|
||||
raise configparser.NoSectionError(section)
|
||||
return section, section
|
||||
if self.has_section(section):
|
||||
return section, section
|
||||
raise configparser.NoSectionError(section)
|
||||
|
||||
def load(self, path: Path) -> None:
|
||||
"""
|
||||
@ -273,14 +274,14 @@ class Configuration(configparser.RawConfigParser):
|
||||
self.load(path)
|
||||
self.merge_sections(architecture)
|
||||
|
||||
def set_option(self, section: str, option: str, value: Optional[str]) -> None:
|
||||
def set_option(self, section: str, option: str, value: str) -> None:
|
||||
"""
|
||||
set option. Unlike default ``configparser.RawConfigParser.set`` it also creates section if it does not exist
|
||||
|
||||
Args:
|
||||
section(str): section name
|
||||
option(str): option name
|
||||
value(Optional[str]): option value as string in parsable format
|
||||
value(str): option value as string in parsable format
|
||||
"""
|
||||
if not self.has_section(section):
|
||||
self.add_section(section)
|
259
src/ahriman/core/configuration/schema.py
Normal file
259
src/ahriman/core/configuration/schema.py
Normal file
@ -0,0 +1,259 @@
|
||||
#
|
||||
# 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 typing import Any
|
||||
|
||||
|
||||
__all__ = ["CONFIGURATION_SCHEMA", "ConfigurationSchema"]
|
||||
|
||||
|
||||
ConfigurationSchema = dict[str, dict[str, Any]]
|
||||
|
||||
|
||||
CONFIGURATION_SCHEMA: ConfigurationSchema = {
|
||||
"settings": {
|
||||
"type": "dict",
|
||||
"schema": {
|
||||
"include": {
|
||||
"type": "path",
|
||||
"coerce": "absolute_path",
|
||||
"required": True,
|
||||
"path_exists": True,
|
||||
},
|
||||
"database": {
|
||||
"type": "path",
|
||||
"coerce": "absolute_path",
|
||||
"required": True,
|
||||
},
|
||||
"logging": {
|
||||
"type": "path",
|
||||
"coerce": "absolute_path",
|
||||
"required": True,
|
||||
"path_exists": True,
|
||||
},
|
||||
"suppress_http_log_errors": {
|
||||
"type": "boolean",
|
||||
"coerce": "boolean",
|
||||
}
|
||||
},
|
||||
},
|
||||
"alpm": {
|
||||
"type": "dict",
|
||||
"schema": {
|
||||
"database": {
|
||||
"type": "path",
|
||||
"coerce": "absolute_path",
|
||||
"required": True,
|
||||
},
|
||||
"mirror": {
|
||||
"type": "string",
|
||||
"required": True,
|
||||
"is_url": [],
|
||||
},
|
||||
"repositories": {
|
||||
"type": "list",
|
||||
"coerce": "list",
|
||||
"schema": {"type": "string"},
|
||||
"required": True,
|
||||
"empty": False,
|
||||
},
|
||||
"root": {
|
||||
"type": "path",
|
||||
"coerce": "absolute_path",
|
||||
"required": True,
|
||||
"path_exists": True,
|
||||
},
|
||||
"use_ahriman_cache": {
|
||||
"type": "boolean",
|
||||
"coerce": "boolean",
|
||||
"required": True,
|
||||
},
|
||||
},
|
||||
},
|
||||
"auth": {
|
||||
"type": "dict",
|
||||
"schema": {
|
||||
"target": {
|
||||
"type": "string",
|
||||
"oneof": [
|
||||
{"allowed": ["disabled"]},
|
||||
{"allowed": ["configuration", "mapping"], "dependencies": ["salt"]},
|
||||
{"allowed": ["oauth"], "dependencies": [
|
||||
"client_id", "client_secret", "oauth_provider", "oauth_scopes", "salt"
|
||||
]},
|
||||
],
|
||||
},
|
||||
"allow_read_only": {
|
||||
"type": "boolean",
|
||||
"coerce": "boolean",
|
||||
"required": True,
|
||||
},
|
||||
"client_id": {
|
||||
"type": "string",
|
||||
},
|
||||
"client_secret": {
|
||||
"type": "string",
|
||||
},
|
||||
"cookie_secret_key": {
|
||||
"type": "string",
|
||||
"minlength": 32,
|
||||
"maxlength": 64, # we cannot verify maxlength, because base64 representation might be longer than bytes
|
||||
},
|
||||
"max_age": {
|
||||
"type": "integer",
|
||||
"coerce": "integer",
|
||||
"min": 0,
|
||||
},
|
||||
"oauth_provider": {
|
||||
"type": "string",
|
||||
},
|
||||
"oauth_scopes": {
|
||||
"type": "string",
|
||||
},
|
||||
"salt": {
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
},
|
||||
"build": {
|
||||
"type": "dict",
|
||||
"schema": {
|
||||
"build_command": {
|
||||
"type": "string",
|
||||
"required": True,
|
||||
},
|
||||
"ignore_packages": {
|
||||
"type": "list",
|
||||
"coerce": "list",
|
||||
"schema": {"type": "string"},
|
||||
},
|
||||
"pkgctl_flags": {
|
||||
"type": "list",
|
||||
"coerce": "list",
|
||||
"schema": {"type": "string"},
|
||||
},
|
||||
"triggers": {
|
||||
"type": "list",
|
||||
"coerce": "list",
|
||||
"schema": {"type": "string"},
|
||||
},
|
||||
"vcs_allowed_age": {
|
||||
"type": "integer",
|
||||
"coerce": "integer",
|
||||
"min": 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
"repository": {
|
||||
"type": "dict",
|
||||
"schema": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"required": True,
|
||||
},
|
||||
"root": {
|
||||
"type": "string",
|
||||
"required": True,
|
||||
},
|
||||
},
|
||||
},
|
||||
"sign": {
|
||||
"type": "dict",
|
||||
"allow_unknown": True,
|
||||
"keysrules": {
|
||||
"type": "string",
|
||||
"anyof_regex": ["^target$", "^key$", "^key_.*"],
|
||||
},
|
||||
"schema": {
|
||||
"target": {
|
||||
"type": "list",
|
||||
"coerce": "list",
|
||||
"oneof": [
|
||||
{"allowed": []},
|
||||
{"allowed": ["package", "repository"], "dependencies": ["key"]},
|
||||
],
|
||||
},
|
||||
"key": {
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
},
|
||||
"web": {
|
||||
"type": "dict",
|
||||
"schema": {
|
||||
"address": {
|
||||
"type": "string",
|
||||
"is_url": ["http", "https"],
|
||||
},
|
||||
"debug": {
|
||||
"type": "boolean",
|
||||
"coerce": "boolean",
|
||||
},
|
||||
"debug_check_host": {
|
||||
"type": "boolean",
|
||||
"coerce": "boolean",
|
||||
},
|
||||
"debug_allowed_hosts": {
|
||||
"type": "list",
|
||||
"coerce": "list",
|
||||
"schema": {"type": "string"},
|
||||
},
|
||||
"host": {
|
||||
"type": "string",
|
||||
"is_ip_address": ["localhost"],
|
||||
},
|
||||
"index_url": {
|
||||
"type": "string",
|
||||
"is_url": ["http", "https"],
|
||||
},
|
||||
"password": {
|
||||
"type": "string",
|
||||
},
|
||||
"port": {
|
||||
"type": "integer",
|
||||
"coerce": "integer",
|
||||
"min": 0,
|
||||
"max": 65535,
|
||||
},
|
||||
"static_path": {
|
||||
"type": "path",
|
||||
"coerce": "absolute_path",
|
||||
"required": True,
|
||||
"path_exists": True,
|
||||
},
|
||||
"templates": {
|
||||
"type": "path",
|
||||
"coerce": "absolute_path",
|
||||
"required": True,
|
||||
"path_exists": True,
|
||||
},
|
||||
"unix_socket": {
|
||||
"type": "path",
|
||||
"coerce": "absolute_path",
|
||||
},
|
||||
"unix_socket_unsafe": {
|
||||
"type": "boolean",
|
||||
"coerce": "boolean",
|
||||
},
|
||||
"username": {
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
161
src/ahriman/core/configuration/validator.py
Normal file
161
src/ahriman/core/configuration/validator.py
Normal file
@ -0,0 +1,161 @@
|
||||
#
|
||||
# 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/>.
|
||||
#
|
||||
import ipaddress
|
||||
|
||||
from cerberus import TypeDefinition, Validator as RootValidator # type: ignore[import]
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
|
||||
|
||||
class Validator(RootValidator):
|
||||
"""
|
||||
class which defines custom validation methods for the service configuration
|
||||
|
||||
Attributes:
|
||||
configuration(Configuration): configuration instance
|
||||
"""
|
||||
|
||||
types_mapping = RootValidator.types_mapping.copy()
|
||||
types_mapping["path"] = TypeDefinition("path", (Path,), ())
|
||||
|
||||
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
||||
"""
|
||||
default constructor
|
||||
|
||||
Args:
|
||||
configuration(Configuration): configuration instance used for extraction
|
||||
*args(Any): positional arguments to be passed to base validator
|
||||
**kwargs(): keyword arguments to be passed to base validator
|
||||
"""
|
||||
RootValidator.__init__(self, *args, **kwargs)
|
||||
self.configuration: Configuration = kwargs["configuration"]
|
||||
|
||||
def _normalize_coerce_absolute_path(self, value: str) -> Path:
|
||||
"""
|
||||
extract path from string value
|
||||
|
||||
Args:
|
||||
value(str): converting value
|
||||
|
||||
Returns:
|
||||
Path: value converted to path instance according to configuration rules
|
||||
"""
|
||||
converted: Path = self.configuration.converters["path"](value)
|
||||
return converted
|
||||
|
||||
def _normalize_coerce_boolean(self, value: str) -> bool:
|
||||
"""
|
||||
extract boolean from string value
|
||||
|
||||
Args:
|
||||
value(str): converting value
|
||||
|
||||
Returns:
|
||||
bool: value converted to boolean according to configuration rules
|
||||
"""
|
||||
# pylint: disable=protected-access
|
||||
converted: bool = self.configuration._convert_to_boolean(value) # type: ignore[attr-defined]
|
||||
return converted
|
||||
|
||||
def _normalize_coerce_integer(self, value: str) -> int:
|
||||
"""
|
||||
extract integer from string value
|
||||
|
||||
Args:
|
||||
value(str): converting value
|
||||
|
||||
Returns:
|
||||
int: value converted to int according to configuration rules
|
||||
"""
|
||||
del self
|
||||
return int(value)
|
||||
|
||||
def _normalize_coerce_list(self, value: str) -> list[str]:
|
||||
"""
|
||||
extract string list from string value
|
||||
|
||||
Args:
|
||||
value(str): converting value
|
||||
|
||||
Returns:
|
||||
list[str]: value converted to string list instance according to configuration rules
|
||||
"""
|
||||
converted: list[str] = self.configuration.converters["list"](value)
|
||||
return converted
|
||||
|
||||
def _validate_is_ip_address(self, constraint: list[str], field: str, value: str) -> None:
|
||||
"""
|
||||
check if the specified value is valid ip address
|
||||
|
||||
Args:
|
||||
constraint(list[str]): optional list of allowed special words (e.g. ``localhost``)
|
||||
field(str): field name to be checked
|
||||
value(Path): value to be checked
|
||||
|
||||
Examples:
|
||||
The rule's arguments are validated against this schema:
|
||||
{"type": "list", "schema": {"type": "string"}}
|
||||
"""
|
||||
if value in constraint:
|
||||
return
|
||||
try:
|
||||
ipaddress.ip_address(value)
|
||||
except ValueError:
|
||||
self._error(field, f"Value {value} must be valid IP address")
|
||||
|
||||
def _validate_is_url(self, constraint: list[str], field: str, value: str) -> None:
|
||||
"""
|
||||
check if the specified value is a valid url
|
||||
|
||||
Args:
|
||||
constraint(list[str]): optional list of supported schemas. If empty, no schema validation will be performed
|
||||
field(str): field name to be checked
|
||||
value(str): value to be checked
|
||||
|
||||
Examples:
|
||||
The rule's arguments are validated against this schema:
|
||||
{"type": "list", "schema": {"type": "string"}}
|
||||
"""
|
||||
url = urlparse(value) # it probably will never rise exceptions on parse
|
||||
if not url.scheme:
|
||||
self._error(field, f"Url scheme is not set for {value}")
|
||||
if not url.netloc and url.scheme not in ("file",):
|
||||
self._error(field, f"Location must be set for url {value} of scheme {url.scheme}")
|
||||
if constraint and url.scheme not in constraint:
|
||||
self._error(field, f"Url {value} scheme must be one of {constraint}")
|
||||
|
||||
def _validate_path_exists(self, constraint: bool, field: str, value: Path) -> None:
|
||||
"""
|
||||
check if paths exists
|
||||
|
||||
Args:
|
||||
constraint(bool): True in case if path must exist and False otherwise
|
||||
field(str): field name to be checked
|
||||
value(Path): value to be checked
|
||||
|
||||
Examples:
|
||||
The rule's arguments are validated against this schema:
|
||||
{"type": "boolean"}
|
||||
"""
|
||||
if constraint and not value.exists():
|
||||
self._error(field, f"Path {value} must exist")
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
# Copyright (c) 2021-2023 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
|
@ -1,47 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
from sqlite3 import Connection
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.database.data.package_remotes import migrate_package_remotes
|
||||
from ahriman.core.database.data.package_statuses import migrate_package_statuses
|
||||
from ahriman.core.database.data.patches import migrate_patches
|
||||
from ahriman.core.database.data.users import migrate_users_data
|
||||
from ahriman.models.migration_result import MigrationResult
|
||||
|
||||
|
||||
def migrate_data(result: MigrationResult, connection: Connection, configuration: Configuration) -> None:
|
||||
"""
|
||||
perform data migration
|
||||
|
||||
Args:
|
||||
result(MigrationResult): result of the schema migration
|
||||
connection(Connection): database connection
|
||||
configuration(Configuration): configuration instance
|
||||
"""
|
||||
# initial data migration
|
||||
repository_paths = configuration.repository_paths
|
||||
|
||||
if result.old_version <= 0:
|
||||
migrate_package_statuses(connection, repository_paths)
|
||||
migrate_patches(connection, repository_paths)
|
||||
migrate_users_data(connection, configuration)
|
||||
if result.old_version <= 1:
|
||||
migrate_package_remotes(connection, repository_paths)
|
@ -1,64 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
from sqlite3 import Connection
|
||||
|
||||
from ahriman.models.package_source import PackageSource
|
||||
from ahriman.models.remote_source import RemoteSource
|
||||
from ahriman.models.repository_paths import RepositoryPaths
|
||||
|
||||
|
||||
__all__ = ["migrate_package_remotes"]
|
||||
|
||||
|
||||
# pylint: disable=protected-access
|
||||
def migrate_package_remotes(connection: Connection, paths: RepositoryPaths) -> None:
|
||||
"""
|
||||
perform migration for package remote sources
|
||||
|
||||
Args:
|
||||
connection(Connection): database connection
|
||||
paths(RepositoryPaths): repository paths instance
|
||||
"""
|
||||
from ahriman.core.database.operations import PackageOperations
|
||||
|
||||
def insert_remote(base: str, remote: RemoteSource) -> None:
|
||||
connection.execute(
|
||||
"""
|
||||
update package_bases set
|
||||
branch = :branch, git_url = :git_url, path = :path,
|
||||
web_url = :web_url, source = :source
|
||||
where package_base = :package_base
|
||||
""",
|
||||
dict(
|
||||
package_base=base,
|
||||
branch=remote.branch, git_url=remote.git_url, path=remote.path,
|
||||
web_url=remote.web_url, source=remote.source
|
||||
)
|
||||
)
|
||||
|
||||
packages = PackageOperations._packages_get_select_package_bases(connection)
|
||||
for package_base, package in packages.items():
|
||||
local_cache = paths.cache_for(package_base)
|
||||
if local_cache.exists() and not package.is_vcs:
|
||||
continue # skip packages which are not VCS and with local cache
|
||||
remote_source = RemoteSource.from_source(PackageSource.AUR, package_base, "aur")
|
||||
if remote_source is None:
|
||||
continue # should never happen
|
||||
insert_remote(package_base, remote_source)
|
@ -1,82 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2021-2022 ahriman team.
|
||||
#
|
||||
# This file is part of ahriman
|
||||
# (see https://github.com/arcan1s/ahriman).
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
import json
|
||||
|
||||
from sqlite3 import Connection
|
||||
|
||||
from ahriman.models.build_status import BuildStatus
|
||||
from ahriman.models.package import Package
|
||||
from ahriman.models.repository_paths import RepositoryPaths
|
||||
|
||||
|
||||
__all__ = ["migrate_package_statuses"]
|
||||
|
||||
|
||||
def migrate_package_statuses(connection: Connection, paths: RepositoryPaths) -> None:
|
||||
"""
|
||||
perform migration for package statuses
|
||||
|
||||
Args:
|
||||
connection(Connection): database connection
|
||||
paths(RepositoryPaths): repository paths instance
|
||||
"""
|
||||
def insert_base(metadata: Package, last_status: BuildStatus) -> None:
|
||||
connection.execute(
|
||||
"""
|
||||
insert into package_bases
|
||||
(package_base, version, aur_url)
|
||||
values
|
||||
(:package_base, :version, :aur_url)
|
||||
""",
|
||||
dict(package_base=metadata.base, version=metadata.version, aur_url=""))
|
||||
connection.execute(
|
||||
"""
|
||||
insert into package_statuses
|
||||
(package_base, status, last_updated)
|
||||
values
|
||||
(:package_base, :status, :last_updated)""",
|
||||
dict(package_base=metadata.base, status=last_status.status.value, last_updated=last_status.timestamp))
|
||||
|
||||
def insert_packages(metadata: Package) -> None:
|
||||
package_list = []
|
||||
for name, description in metadata.packages.items():
|
||||
package_list.append(dict(package=name, package_base=metadata.base, **description.view()))
|
||||
connection.executemany(
|
||||
"""
|
||||
insert into packages
|
||||
(package, package_base, architecture, archive_size, build_date, depends, description,
|
||||
filename, "groups", installed_size, licenses, provides, url)
|
||||
values
|
||||
(:package, :package_base, :architecture, :archive_size, :build_date, :depends, :description,
|
||||
:filename, :groups, :installed_size, :licenses, :provides, :url)
|
||||
""",
|
||||
package_list)
|
||||
|
||||
cache_path = paths.root / "status_cache.json"
|
||||
if not cache_path.is_file():
|
||||
return # no file found
|
||||
with cache_path.open() as cache:
|
||||
dump = json.load(cache)
|
||||
|
||||
for item in dump.get("packages", []):
|
||||
package = Package.from_json(item["package"])
|
||||
status = BuildStatus.from_json(item["status"])
|
||||
insert_base(package, status)
|
||||
insert_packages(package)
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user