mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-06-27 06:11:51 +00:00
Compare commits
24 Commits
2.11.0
...
2b207e1a89
Author | SHA1 | Date | |
---|---|---|---|
2b207e1a89 | |||
c5bd862ae9 | |||
5a4b6c69a5 | |||
17e6573e7f | |||
4eb187aead | |||
f2ac27ccb7 | |||
b198778810 | |||
57c8ed3557 | |||
1859d14f78 | |||
d5f4fc9b86 | |||
462096ee8a | |||
98e594df90 | |||
657bcdcc0b | |||
edcc464658 | |||
018d9589e1 | |||
a56fe28003 | |||
03c183d66c | |||
efde0b2e86 | |||
c915d68c97 | |||
853185c659 | |||
28afcde3fa | |||
62ae3ada4a | |||
6fcb5449c3 | |||
74209acc21 |
42
.github/workflows/docker-image.yml
vendored
42
.github/workflows/docker-image.yml
vendored
@ -1,42 +0,0 @@
|
||||
name: docker image
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
tags:
|
||||
- '*'
|
||||
- '!*rc*'
|
||||
|
||||
jobs:
|
||||
docker-image:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: extract docker metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v3
|
||||
with:
|
||||
images: |
|
||||
arcan1s/ahriman
|
||||
tags: |
|
||||
type=ref,event=tag
|
||||
type=edge
|
||||
|
||||
- name: setup QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
|
||||
- name: setup docker buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
|
||||
- name: login to docker hub
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: build an image and push
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
51
.github/workflows/docker.yml
vendored
Normal file
51
.github/workflows/docker.yml
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
name: Docker image
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
tags:
|
||||
- '*'
|
||||
- '!*rc*'
|
||||
|
||||
jobs:
|
||||
docker-image:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- uses: docker/setup-qemu-action@v2
|
||||
|
||||
- uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Login to docker hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Login to github container registry
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract docker metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v3
|
||||
with:
|
||||
images: |
|
||||
arcan1s/ahriman
|
||||
ghcr.io/arcan1s/ahriman
|
||||
tags: |
|
||||
type=semver,pattern={{raw}}
|
||||
type=edge
|
||||
|
||||
- name: Build an image and push
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
12
.github/workflows/release.yml
vendored
12
.github/workflows/release.yml
vendored
@ -1,4 +1,4 @@
|
||||
name: release
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
@ -11,25 +11,25 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: extract version
|
||||
- name: Extract version
|
||||
id: version
|
||||
run: echo ::set-output name=VERSION::${GITHUB_REF#refs/tags/}
|
||||
|
||||
- name: create changelog
|
||||
- name: Create changelog
|
||||
id: changelog
|
||||
uses: jaywcjlove/changelog-generator@main
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
filter: 'Release \d+\.\d+\.\d+'
|
||||
|
||||
- name: create archive
|
||||
- name: Create archive
|
||||
run: make archive
|
||||
env:
|
||||
VERSION: ${{ steps.version.outputs.VERSION }}
|
||||
|
||||
- name: release
|
||||
- name: Publish release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
body: |
|
||||
|
16
.github/workflows/setup.sh
vendored
16
.github/workflows/setup.sh
vendored
@ -22,6 +22,8 @@ if [[ -z $MINIMAL_INSTALL ]]; then
|
||||
# additional features
|
||||
pacman --noconfirm -Sy gnupg python-boto3 rsync
|
||||
fi
|
||||
# FIXME since 1.0.4 devtools requires dbus to be run, which doesn't work now in container
|
||||
cp "docker/systemd-nspawn.sh" "/usr/local/bin/systemd-nspawn"
|
||||
|
||||
# create fresh tarball
|
||||
make VERSION=1.0.0 archlinux # well, it does not really matter which version we will put here
|
||||
@ -36,21 +38,21 @@ systemd-machine-id-setup
|
||||
|
||||
# initial setup command as root
|
||||
[[ -z $MINIMAL_INSTALL ]] && WEB_ARGS=("--web-port" "8080")
|
||||
ahriman -a x86_64 service-setup --packager "ahriman bot <ahriman@example.com>" --repository "github" "${WEB_ARGS[@]}"
|
||||
ahriman -a x86_64 -r "github" service-setup --packager "ahriman bot <ahriman@example.com>" "${WEB_ARGS[@]}"
|
||||
# validate configuration
|
||||
ahriman -a x86_64 service-config-validate --exit-code
|
||||
ahriman service-config-validate --exit-code
|
||||
# enable services
|
||||
systemctl enable ahriman-web@x86_64
|
||||
systemctl enable ahriman@x86_64.timer
|
||||
systemctl enable ahriman-web
|
||||
systemctl enable ahriman@x86_64-github.timer
|
||||
if [[ -z $MINIMAL_INSTALL ]]; then
|
||||
# run web service (detached)
|
||||
sudo -u ahriman -- ahriman -a x86_64 web &
|
||||
sudo -u ahriman -- ahriman web &
|
||||
WEB_PID=$!
|
||||
fi
|
||||
# add the first package
|
||||
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/github/x86_64" -name "ahriman*pkg*")"
|
||||
# run package check
|
||||
sudo -u ahriman -- ahriman repo-update
|
||||
# stop web service lol
|
||||
|
@ -1,4 +1,4 @@
|
||||
name: setup
|
||||
name: Setup
|
||||
|
||||
on:
|
||||
push:
|
||||
@ -12,15 +12,15 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
container:
|
||||
image: archlinux:latest
|
||||
image: archlinux:base
|
||||
volumes:
|
||||
- ${{ github.workspace }}:/build
|
||||
options: --privileged -w /build
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: setup the minimal service in arch linux container
|
||||
- name: Setup the minimal service in arch linux container
|
||||
run: .github/workflows/setup.sh minimal
|
||||
|
||||
run-setup:
|
||||
@ -28,13 +28,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
container:
|
||||
image: archlinux:latest
|
||||
image: archlinux:base
|
||||
volumes:
|
||||
- ${{ github.workspace }}:/build
|
||||
options: --privileged -w /build
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: setup the service in arch linux container
|
||||
- name: Setup the service in arch linux container
|
||||
run: .github/workflows/setup.sh
|
@ -1,4 +1,4 @@
|
||||
name: tests
|
||||
name: Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
@ -12,13 +12,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
container:
|
||||
image: archlinux:latest
|
||||
image: archlinux:base
|
||||
volumes:
|
||||
- ${{ github.workspace }}:/build
|
||||
options: -w /build
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: run check and tests in arch linux container
|
||||
- name: Run check and tests in arch linux container
|
||||
run: .github/workflows/tests.sh
|
@ -174,9 +174,7 @@ Again, the most checks can be performed by `make check` command, though some add
|
||||
|
||||
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.schemas import AuthSchema, ErrorSchema, PackageNameSchema, PaginationSchema
|
||||
from ahriman.web.views.base import BaseView
|
||||
|
||||
|
||||
@ -204,16 +202,21 @@ Again, the most checks can be performed by `make check` command, though some add
|
||||
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
|
||||
404: {"description": "Repository is unknown", "schema": ErrorSchema}, # include if BaseView.service() method is called
|
||||
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.querystring_schema(PaginationSchema)
|
||||
@aiohttp_apispec.json_schema(RequestSchema(many=True))
|
||||
async def post(self) -> None: ...
|
||||
```
|
||||
|
||||
* It is allowed to change web API to add new fields or remove optional ones. However, in case of model changes, new API version must be introduced.
|
||||
* On the other hand, it is allowed to change method signatures, however, it is recommended to add new parameters as optional if possible. Deprecated API can be dropped during major release.
|
||||
|
||||
### Other checks
|
||||
|
||||
The projects also uses typing checks (provided by `mypy`) and some linter checks provided by `pylint` and `bandit`. Those checks must be passed successfully for any open pull requests.
|
||||
|
@ -10,6 +10,8 @@ ENV AHRIMAN_OUTPUT=""
|
||||
ENV AHRIMAN_PACKAGER="ahriman bot <ahriman@example.com>"
|
||||
ENV AHRIMAN_PACMAN_MIRROR=""
|
||||
ENV AHRIMAN_PORT=""
|
||||
ENV AHRIMAN_POSTSETUP_COMMAND=""
|
||||
ENV AHRIMAN_PRESETUP_COMMAND=""
|
||||
ENV AHRIMAN_REPOSITORY="aur-clone"
|
||||
ENV AHRIMAN_REPOSITORY_SERVER=""
|
||||
ENV AHRIMAN_REPOSITORY_ROOT="/var/lib/ahriman/ahriman"
|
||||
@ -35,6 +37,9 @@ RUN pacman -Sy --noconfirm --asdeps devtools git pyalpm python-cerberus python-i
|
||||
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
|
||||
|
||||
## FIXME since 1.0.4 devtools requires dbus to be run, which doesn't work now in container
|
||||
COPY "docker/systemd-nspawn.sh" "/usr/local/bin/systemd-nspawn"
|
||||
|
||||
# install ahriman
|
||||
## copy tree
|
||||
COPY --chown=build . "/home/build/ahriman"
|
||||
|
@ -1,8 +1,8 @@
|
||||
# ArcH linux ReposItory MANager
|
||||
|
||||
[](https://github.com/arcan1s/ahriman/actions/workflows/run-tests.yml)
|
||||
[](https://github.com/arcan1s/ahriman/actions/workflows/run-setup.yml)
|
||||
[](https://hub.docker.com/r/arcan1s/ahriman)
|
||||
[](https://github.com/arcan1s/ahriman/actions/workflows/tests.yml)
|
||||
[](https://github.com/arcan1s/ahriman/actions/workflows/setup.yml)
|
||||
[](https://hub.docker.com/r/arcan1s/ahriman)
|
||||
[](https://www.codefactor.io/repository/github/arcan1s/ahriman)
|
||||
[](https://ahriman.readthedocs.io/?badge=latest)
|
||||
|
||||
@ -38,5 +38,5 @@ 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. [HTTP API documentation](https://ahriman-demo.arcanis.me/api-docs) is also available.
|
||||
* [Repository index](http://repo.arcanis.me/x86_64/index.html).
|
||||
* [Repository index](http://repo.arcanis.me/arcanisrepo/x86_64/).
|
||||
* [Telegram feed](https://t.me/arcanisrepo).
|
||||
|
@ -17,6 +17,7 @@ host = $AHRIMAN_HOST
|
||||
EOF
|
||||
|
||||
AHRIMAN_DEFAULT_ARGS=("--architecture" "$AHRIMAN_ARCHITECTURE")
|
||||
AHRIMAN_DEFAULT_ARGS+=("--repository" "$AHRIMAN_REPOSITORY")
|
||||
if [ -n "$AHRIMAN_OUTPUT" ]; then
|
||||
AHRIMAN_DEFAULT_ARGS+=("--log-handler" "$AHRIMAN_OUTPUT")
|
||||
fi
|
||||
@ -33,23 +34,25 @@ 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_REPOSITORY_SERVER" ]; then
|
||||
AHRIMAN_SETUP_ARGS+=("--server" "$AHRIMAN_REPOSITORY_SERVER")
|
||||
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
|
||||
|
||||
[ -n "$AHRIMAN_PRESETUP_COMMAND" ] && eval "$AHRIMAN_PRESETUP_COMMAND"
|
||||
ahriman "${AHRIMAN_DEFAULT_ARGS[@]}" service-setup "${AHRIMAN_SETUP_ARGS[@]}"
|
||||
[ -n "$AHRIMAN_POSTSETUP_COMMAND" ] && eval "$AHRIMAN_POSTSETUP_COMMAND"
|
||||
|
||||
# validate configuration if set
|
||||
[ -n "$AHRIMAN_VALIDATE_CONFIGURATION" ] && ahriman "${AHRIMAN_DEFAULT_ARGS[@]}" service-config-validate --exit-code
|
||||
|
15
docker/systemd-nspawn.sh
Executable file
15
docker/systemd-nspawn.sh
Executable file
@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
# Since https://gitlab.archlinux.org/archlinux/devtools/-/commit/5f4fd52e3836ddddb25a0f9e15d0acfed06f693d
|
||||
# it is impossible to start devtools inside docker container, because it requires slice registering
|
||||
# which is impossible because there is no init in container
|
||||
|
||||
is_slice() {
|
||||
[[ $1 =~ ^--slice* ]]
|
||||
}
|
||||
|
||||
allowed=()
|
||||
for arg in "$@"; do
|
||||
is_slice "$arg" && allowed+=("--keep-unit") || allowed+=("$arg")
|
||||
done
|
||||
|
||||
exec /usr/bin/systemd-nspawn "${allowed[@]}"
|
@ -9,8 +9,9 @@ Depending on the goal the package can be used in different ways. Nevertheless, i
|
||||
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.database import SQLite
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
architecture = "x86_64"
|
||||
repository_id = RepositoryId("x86_64", "aur-clone")
|
||||
configuration = Configuration.from_path(Path("/etc/ahriman.ini"), architecture)
|
||||
database = SQLite.load(configuration)
|
||||
|
||||
@ -26,8 +27,10 @@ Almost all actions are wrapped by ``ahriman.core.repository.Repository`` class
|
||||
.. code-block:: python
|
||||
|
||||
from ahriman.core.repository import Repository
|
||||
from ahriman.models.pacman_synchronization import PacmanSynchronization
|
||||
|
||||
repository = Repository(architecture, configuration, database, report=True, unsafe=False)
|
||||
repository = Repository(repository_id, configuration, database,
|
||||
report=True, refresh_pacman_database=PacmanSynchronization.Disabled)
|
||||
|
||||
And the ``repository`` instance can be used to perform repository maintenance
|
||||
|
||||
|
@ -100,6 +100,14 @@ ahriman.application.handlers.remove\_unknown module
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.application.handlers.repositories module
|
||||
------------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.application.handlers.repositories
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.application.handlers.restore module
|
||||
-------------------------------------------
|
||||
|
||||
@ -172,6 +180,14 @@ ahriman.application.handlers.structure module
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.application.handlers.tree\_migrate module
|
||||
-------------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.application.handlers.tree_migrate
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.application.handlers.triggers module
|
||||
--------------------------------------------
|
||||
|
||||
|
@ -92,6 +92,14 @@ ahriman.core.database.migrations.m010\_version\_based\_logs\_removal module
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.core.database.migrations.m011\_repository\_name module
|
||||
--------------------------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.core.database.migrations.m011_repository_name
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
Module contents
|
||||
---------------
|
||||
|
||||
|
@ -60,6 +60,14 @@ ahriman.core.formatters.printer module
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.core.formatters.repository\_printer module
|
||||
--------------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.core.formatters.repository_printer
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.core.formatters.status\_printer module
|
||||
----------------------------------------------
|
||||
|
||||
|
@ -36,10 +36,10 @@ ahriman.core.log.lazy\_logging module
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.core.log.log module
|
||||
---------------------------
|
||||
ahriman.core.log.log\_loader module
|
||||
-----------------------------------
|
||||
|
||||
.. automodule:: ahriman.core.log.log
|
||||
.. automodule:: ahriman.core.log.log_loader
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
@ -140,6 +140,14 @@ ahriman.models.pkgbuild\_patch module
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.models.process\_status module
|
||||
-------------------------------------
|
||||
|
||||
.. automodule:: ahriman.models.process_status
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.models.property module
|
||||
------------------------------
|
||||
|
||||
@ -164,6 +172,14 @@ ahriman.models.report\_settings module
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.models.repository\_id module
|
||||
------------------------------------
|
||||
|
||||
.. automodule:: ahriman.models.repository_id
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.models.repository\_paths module
|
||||
---------------------------------------
|
||||
|
||||
|
@ -124,6 +124,14 @@ ahriman.web.schemas.package\_status\_schema module
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.schemas.pagination\_schema module
|
||||
---------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.schemas.pagination_schema
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.schemas.pgp\_key\_id\_schema module
|
||||
-----------------------------------------------
|
||||
|
||||
@ -164,6 +172,14 @@ ahriman.web.schemas.remote\_schema module
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.schemas.repository\_id\_schema module
|
||||
-------------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.schemas.repository_id_schema
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.schemas.search\_schema module
|
||||
-----------------------------------------
|
||||
|
||||
|
@ -8,9 +8,8 @@ Subpackages
|
||||
:maxdepth: 4
|
||||
|
||||
ahriman.web.views.api
|
||||
ahriman.web.views.service
|
||||
ahriman.web.views.status
|
||||
ahriman.web.views.user
|
||||
ahriman.web.views.v1
|
||||
ahriman.web.views.v2
|
||||
|
||||
Submodules
|
||||
----------
|
||||
|
@ -1,85 +0,0 @@
|
||||
ahriman.web.views.service package
|
||||
=================================
|
||||
|
||||
Submodules
|
||||
----------
|
||||
|
||||
ahriman.web.views.service.add module
|
||||
------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.service.add
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.views.service.pgp module
|
||||
------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.service.pgp
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.views.service.process module
|
||||
----------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.service.process
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.views.service.rebuild module
|
||||
----------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.service.rebuild
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.views.service.remove module
|
||||
---------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.service.remove
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.views.service.request module
|
||||
----------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.service.request
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.views.service.search module
|
||||
---------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.service.search
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.views.service.update module
|
||||
---------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.service.update
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.views.service.upload module
|
||||
---------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.service.upload
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
Module contents
|
||||
---------------
|
||||
|
||||
.. automodule:: ahriman.web.views.service
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
@ -1,45 +0,0 @@
|
||||
ahriman.web.views.status package
|
||||
================================
|
||||
|
||||
Submodules
|
||||
----------
|
||||
|
||||
ahriman.web.views.status.logs module
|
||||
------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.status.logs
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.views.status.package module
|
||||
---------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.status.package
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.views.status.packages module
|
||||
----------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.status.packages
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.views.status.status module
|
||||
--------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.status.status
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
Module contents
|
||||
---------------
|
||||
|
||||
.. automodule:: ahriman.web.views.status
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
@ -1,29 +0,0 @@
|
||||
ahriman.web.views.user package
|
||||
==============================
|
||||
|
||||
Submodules
|
||||
----------
|
||||
|
||||
ahriman.web.views.user.login module
|
||||
-----------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.user.login
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.views.user.logout module
|
||||
------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.user.logout
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
Module contents
|
||||
---------------
|
||||
|
||||
.. automodule:: ahriman.web.views.user
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
20
docs/ahriman.web.views.v1.rst
Normal file
20
docs/ahriman.web.views.v1.rst
Normal file
@ -0,0 +1,20 @@
|
||||
ahriman.web.views.v1 package
|
||||
============================
|
||||
|
||||
Subpackages
|
||||
-----------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
|
||||
ahriman.web.views.v1.service
|
||||
ahriman.web.views.v1.status
|
||||
ahriman.web.views.v1.user
|
||||
|
||||
Module contents
|
||||
---------------
|
||||
|
||||
.. automodule:: ahriman.web.views.v1
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
85
docs/ahriman.web.views.v1.service.rst
Normal file
85
docs/ahriman.web.views.v1.service.rst
Normal file
@ -0,0 +1,85 @@
|
||||
ahriman.web.views.v1.service package
|
||||
====================================
|
||||
|
||||
Submodules
|
||||
----------
|
||||
|
||||
ahriman.web.views.v1.service.add module
|
||||
---------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.v1.service.add
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.views.v1.service.pgp module
|
||||
---------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.v1.service.pgp
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.views.v1.service.process module
|
||||
-------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.v1.service.process
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.views.v1.service.rebuild module
|
||||
-------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.v1.service.rebuild
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.views.v1.service.remove module
|
||||
------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.v1.service.remove
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.views.v1.service.request module
|
||||
-------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.v1.service.request
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.views.v1.service.search module
|
||||
------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.v1.service.search
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.views.v1.service.update module
|
||||
------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.v1.service.update
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.views.v1.service.upload module
|
||||
------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.v1.service.upload
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
Module contents
|
||||
---------------
|
||||
|
||||
.. automodule:: ahriman.web.views.v1.service
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
53
docs/ahriman.web.views.v1.status.rst
Normal file
53
docs/ahriman.web.views.v1.status.rst
Normal file
@ -0,0 +1,53 @@
|
||||
ahriman.web.views.v1.status package
|
||||
===================================
|
||||
|
||||
Submodules
|
||||
----------
|
||||
|
||||
ahriman.web.views.v1.status.logs module
|
||||
---------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.v1.status.logs
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.views.v1.status.package module
|
||||
------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.v1.status.package
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.views.v1.status.packages module
|
||||
-------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.v1.status.packages
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.views.v1.status.repositories module
|
||||
-----------------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.v1.status.repositories
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.views.v1.status.status module
|
||||
-----------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.v1.status.status
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
Module contents
|
||||
---------------
|
||||
|
||||
.. automodule:: ahriman.web.views.v1.status
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
29
docs/ahriman.web.views.v1.user.rst
Normal file
29
docs/ahriman.web.views.v1.user.rst
Normal file
@ -0,0 +1,29 @@
|
||||
ahriman.web.views.v1.user package
|
||||
=================================
|
||||
|
||||
Submodules
|
||||
----------
|
||||
|
||||
ahriman.web.views.v1.user.login module
|
||||
--------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.v1.user.login
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
ahriman.web.views.v1.user.logout module
|
||||
---------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.v1.user.logout
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
Module contents
|
||||
---------------
|
||||
|
||||
.. automodule:: ahriman.web.views.v1.user
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
18
docs/ahriman.web.views.v2.rst
Normal file
18
docs/ahriman.web.views.v2.rst
Normal file
@ -0,0 +1,18 @@
|
||||
ahriman.web.views.v2 package
|
||||
============================
|
||||
|
||||
Subpackages
|
||||
-----------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 4
|
||||
|
||||
ahriman.web.views.v2.status
|
||||
|
||||
Module contents
|
||||
---------------
|
||||
|
||||
.. automodule:: ahriman.web.views.v2
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
21
docs/ahriman.web.views.v2.status.rst
Normal file
21
docs/ahriman.web.views.v2.status.rst
Normal file
@ -0,0 +1,21 @@
|
||||
ahriman.web.views.v2.status package
|
||||
===================================
|
||||
|
||||
Submodules
|
||||
----------
|
||||
|
||||
ahriman.web.views.v2.status.logs module
|
||||
---------------------------------------
|
||||
|
||||
.. automodule:: ahriman.web.views.v2.status.logs
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
||||
|
||||
Module contents
|
||||
---------------
|
||||
|
||||
.. automodule:: ahriman.web.views.v2.status
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
:show-inheritance:
|
@ -19,7 +19,7 @@ Full dependency diagram:
|
||||
``ahriman.application`` package
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This package contains application (aka executable) related classes and everything for that. It also contains package called ``ahriman.application.handlers`` in which all available subcommands are described as separated classes derived from base ``ahriman.application.handlers.Handler`` class.
|
||||
This package contains application (aka executable) related classes and everything for it. It also contains package called ``ahriman.application.handlers`` in which all available subcommands are described as separated classes derived from base ``ahriman.application.handlers.Handler`` class.
|
||||
|
||||
``ahriman.application.application.Application`` (god class) is used for any interaction from parsers with repository. It is divided into multiple traits by functions (package related and repository related) in the same package.
|
||||
|
||||
@ -44,7 +44,7 @@ This package contains everything required for the most of application actions an
|
||||
* ``ahriman.core.sign`` package provides sign feature (only gpg calls are available).
|
||||
* ``ahriman.core.status`` contains helpers and watcher class which are required for web application. Reporter must be initialized by using ``ahriman.core.status.client.Client.load`` method.
|
||||
* ``ahriman.core.support`` provides plugins for support packages (mirrorlist and keyring) generation.
|
||||
* ``ahriman.core.triggers`` package contains base trigger classes. Classes from this package must be imported in order to implement user extensions. In fact, ``ahriman.core.report`` and ``ahriman.core.upload`` use this package.
|
||||
* ``ahriman.core.triggers`` package contains base trigger classes. Classes from this package must be imported in order to implement user extensions. In fact, ``ahriman.core.report``, ``ahriman.core.upload`` and other built-in triggers use this package.
|
||||
* ``ahriman.core.upload`` package provides sync feature, should not be called directly.
|
||||
|
||||
This package also provides some generic functions and classes which may be used by other packages:
|
||||
@ -56,7 +56,7 @@ This package also provides some generic functions and classes which may be used
|
||||
``ahriman.models`` package
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
It provides models for any other part of application. Unlike ``ahriman.core`` package classes from here provide only conversion methods (e.g. create class from another or convert to). Mostly case classes and enumerations.
|
||||
It provides models for any other part of application. Unlike ``ahriman.core`` package classes from here provide only conversion methods (e.g. create class from another or convert to). It is mostly presented by case classes and enumerations.
|
||||
|
||||
``ahriman.web`` package
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -74,9 +74,9 @@ Web application. It is important that this package is isolated from any other to
|
||||
Application run
|
||||
---------------
|
||||
|
||||
#. Parse command line arguments, find command and related handler which is set by parser.
|
||||
#. Parse command line arguments, find subcommand and related handler which is set by the parser.
|
||||
#. Call ``Handler.execute`` method.
|
||||
#. Define list of architectures to run. In case if there is more than one architecture specified run several subprocesses or process in current process otherwise. Class attribute ``ALLOW_MULTI_ARCHITECTURE_RUN`` controls whether application can be run in multiple processes or not - this feature is required for some handlers (e.g. ``Web``) which should be able to spawn child process in daemon mode (it is impossible to do from daemonic processes).
|
||||
#. Define list of architectures to run. In case if there is more than one architecture specified run several subprocesses or continue in current process otherwise. Class attribute ``ALLOW_MULTI_ARCHITECTURE_RUN`` controls whether the application can be run in multiple processes or not - this feature is required for some handlers (e.g. ``Web``, which should be able to spawn child process in daemon mode; it is impossible to do from daemonic processes).
|
||||
#. In each child process call lock functions.
|
||||
#. After success checks pass control to ``Handler.run`` method defined by specific handler class.
|
||||
#. Return result (success or failure) of each subprocess and exit from application.
|
||||
@ -84,7 +84,7 @@ Application run
|
||||
|
||||
In the most cases handlers spawn god class ``ahriman.application.application.Application`` class and call required methods.
|
||||
|
||||
Application is designed to run from ``systemd`` services and provides parametrized by architecture timer and service file for that.
|
||||
The application is designed to run from ``systemd`` services and provides parametrized by repository identifier timer and service file for that.
|
||||
|
||||
Subcommand design
|
||||
^^^^^^^^^^^^^^^^^
|
||||
@ -100,7 +100,52 @@ All subcommands are divided into several groups depending on the role they are d
|
||||
* ``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.
|
||||
For historical reasons and in order to keep backward compatibility some subcommands have aliases to their shorter forms or even other groups, but the application doesn't guarantee that they will remain unchanged.
|
||||
|
||||
Filesystem tree
|
||||
---------------
|
||||
|
||||
The application supports two types of trees, one is for the legacy configuration (when there were no repository name explicit configuration available) and another one is the new-style tree. This document describes only new-style tree in order to avoid deprecated structures.
|
||||
|
||||
Having default root as ``/var/lib/ahriman`` (differs from container though), the directory structure is the following:
|
||||
|
||||
.. code-block::
|
||||
|
||||
/var/lib/ahriman/
|
||||
├── ahriman.db
|
||||
├── cache
|
||||
├── chroot
|
||||
│ └── aur-clone
|
||||
├── packages
|
||||
│ └── aur-clone
|
||||
│ └── x86_64
|
||||
├── pacman
|
||||
│ └── aur-clone
|
||||
│ └── x86_64
|
||||
│ ├── local
|
||||
│ │ └── ALPM_DB_VERSION
|
||||
│ └── sync
|
||||
│ ├── core.db
|
||||
│ ├── extra.db
|
||||
│ └── multilib.db
|
||||
│
|
||||
└── repository
|
||||
└── aur-clone
|
||||
└── x86_64
|
||||
├── aur-clone.db -> aur-clone.db.tar.gz
|
||||
├── aur-clone.db.tar.gz
|
||||
├── aur-clone.files -> aur-clone.files.tar.gz
|
||||
└── aur-clone.files.tar.gz
|
||||
|
||||
There are multiple subdirectories, some of them are commons for any repository, but some of them are not.
|
||||
|
||||
* ``cache`` is a directory with locally stored PKGBUILD's and VCS packages. It is common for all repositories and architectures.
|
||||
* ``chroot/{repository}`` is a chroot directory for ``devtools``. It is specific for each repository, but shared for different architectures inside (the ``devtools`` handles architectures automatically).
|
||||
* ``packages/{repository}/{architecture}`` is a directory with prebuilt packages. When package is built, first it will be uploaded to this directory and later will be handled by update process. It is architecture and repository specific.
|
||||
* ``pacman/{repository}/{architecture}`` is the repository and architecture specific caches for pacman's databases.
|
||||
* ``repository/{repository}/{architecture}`` is a repository packages directory.
|
||||
|
||||
Normally you should avoid direct interaction with the application tree. For tree migration process refer to the :doc:`migration notes <migration>`.
|
||||
|
||||
Database
|
||||
--------
|
||||
@ -119,7 +164,7 @@ 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.
|
||||
|
||||
These migrations can 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.
|
||||
These migrations can 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
|
||||
^^^^^^^^^^^^^^^^
|
||||
@ -146,7 +191,7 @@ Idea is to copy package to the directory from which it will be handled at the ne
|
||||
* If supplied argument is directory and there is ``PKGBUILD`` file there it will be treated as local package. In this case it will queue this package to build and copy source files (``PKGBUILD`` and ``.SRCINFO``) to caches.
|
||||
* If supplied argument is not file then application tries to lookup for the specified name in AUR and clones it into the directory with manual updates. This scenario can also handle package dependencies which are missing in repositories.
|
||||
|
||||
This logic can be overwritten by specifying the ``source`` parameter, which is partially useful if you would like to add package from AUR, but there is local directory cloned from AUR.
|
||||
This logic can be overwritten by specifying the ``source`` parameter, which is partially useful if you would like to add package from AUR, but there is local directory cloned from AUR. Also official repositories calls are hidden behind explicit source definition.
|
||||
|
||||
Rebuild packages
|
||||
^^^^^^^^^^^^^^^^
|
||||
@ -197,12 +242,12 @@ Core functions reference
|
||||
Configuration
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
``ahriman.core.configuration.Configuration`` class provides some additional methods (e.g. ``getpath`` and ``getlist``) and also combines multiple files into single configuration dictionary using architecture overrides. It is the recommended way to deal with settings.
|
||||
``ahriman.core.configuration.Configuration`` class provides some additional methods (e.g. ``getpath`` and ``getlist``) and also combines multiple files into single configuration dictionary using repository identifier overrides. It is the recommended way to deal with settings.
|
||||
|
||||
Enumerations
|
||||
^^^^^^^^^^^^
|
||||
|
||||
All enumerations are derived from ``str`` and ``enum.Enum``. Integer enumerations are not allowed, because most of operations require conversions from string variable. Derivation from string class is required to make json conversions implicitly (e.g. during calling ``json.dumps`` methods).
|
||||
All enumerations are derived from ``str`` and ``enum.Enum``. Integer enumerations in general are not allowed, because most of operations require conversions from string variable. Derivation from string class is required to make json conversions implicitly (e.g. during calling ``json.dumps`` methods).
|
||||
|
||||
In addition, some enumerations provide ``from_option`` class methods in order to allow some flexibility while reading configuration options.
|
||||
|
||||
@ -216,7 +261,7 @@ Context variables
|
||||
|
||||
Package provides implicit global variables which can be accessed from ``ahriman.core`` package as ``context`` variable, wrapped by ``contextvars.ContextVar`` class. The value of the variable is defaulting to private ``_Context`` class which is defined in the same module. The default values - such as ``database`` and ``sign`` - are being set on the service initialization.
|
||||
|
||||
The ``_Context`` class itself mimics default collection interface (as is Mapping) and can be modified by ``_Context.set`` method. The stored variables can be achieved by ``_Context.get`` method, which is unlike default ``Mapping`` interface also performs type and presence checks.
|
||||
The ``_Context`` class itself mimics default collection interface (as is ``Mapping``) and can be modified by ``_Context.set`` method. The stored variables can be achieved by ``_Context.get`` method, which is unlike default ``Mapping`` interface also performs type and presence checks.
|
||||
|
||||
In order to provide statically typed interface, the ``ahriman.models.context_key.ContextKey`` class is used for both ``_Content.get`` and ``_Content.set`` methods; the context instance itself, however, does not store information about types.
|
||||
|
||||
@ -252,7 +297,7 @@ OAuth's implementation also allows authenticating users via username + password
|
||||
|
||||
In addition, web service checks the source socket used. In case if it belongs to ``socket.AF_UNIX`` family, it will skip any further checks considering the request to be performed in safe environment (e.g. on the same physical machine). This feature, in particular is being used by the reporter instances in case if socket address is set in configuration.
|
||||
|
||||
In order to configure users there are special commands.
|
||||
In order to configure users there are special subcommands.
|
||||
|
||||
Triggers
|
||||
^^^^^^^^
|
||||
@ -263,7 +308,7 @@ The main idea is to load classes by their full path (e.g. ``ahriman.core.upload.
|
||||
|
||||
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.
|
||||
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 respectively. 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.
|
||||
|
||||
For more details how to deal with the triggers, refer to :doc:`documentation <triggers>` and modules descriptions.
|
||||
|
||||
@ -274,7 +319,7 @@ There are several supported synchronization providers, currently they are ``rsyn
|
||||
|
||||
``rsync`` provider does not have any specific logic except for running external rsync application with configured arguments. The service does not handle SSH configuration, thus it has to be configured before running application manually.
|
||||
|
||||
``s3`` provider uses ``boto3`` package and implements sync feature. The files are stored in architecture directory (e.g. if bucket is ``repository``, packages will be stored in ``repository/x86_64`` for the ``x86_64`` architecture), bucket must be created before any action and API key must have permissions to write to the bucket. No external configuration required. In order to upload only changed files the service compares calculated hashes with the Amazon ETags, used realization is described `here <https://teppen.io/2018/10/23/aws_s3_verify_etags/>`_.
|
||||
``s3`` provider uses ``boto3`` package and implements sync feature. The files are stored in architecture directory (e.g. if bucket is ``repository``, packages will be stored in ``repository/aur-clone/x86_64`` for the ``aur-clone`` repository ``x86_64`` architecture), bucket must be created before any action and API key must have permissions to write to the bucket. No external configuration required. In order to upload only changed files the service compares calculated hashes with the Amazon ETags, used realization is described `here <https://teppen.io/2018/10/23/aws_s3_verify_etags/>`_.
|
||||
|
||||
``github`` provider authenticates through basic auth, API key with repository write permissions is required. There will be created a release with the name of the architecture in case if it does not exist; files will be uploaded to the release assets. It also stores array of files and their MD5 checksums in release body in order to upload only changed ones. According to the Github API in case if there is already uploaded asset with the same name (e.g. database files), asset will be removed first.
|
||||
|
||||
@ -323,9 +368,11 @@ 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.
|
||||
* ``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.
|
||||
|
||||
The views are also divided by supporting API versions (e.g. ``v1``, ``v2``).
|
||||
|
||||
Templating
|
||||
^^^^^^^^^^
|
||||
|
@ -85,7 +85,7 @@ autoclass_content = "both"
|
||||
|
||||
autodoc_member_order = "groupwise"
|
||||
|
||||
autodoc_mock_imports = ["pyalpm"]
|
||||
autodoc_mock_imports = ["cryptography", "pyalpm"]
|
||||
|
||||
autodoc_default_options = {
|
||||
"no-undoc-members": True,
|
||||
|
@ -1,7 +1,12 @@
|
||||
Configuration
|
||||
=============
|
||||
|
||||
Some groups can be specified for each architecture separately. E.g. if there are ``build`` and ``build:x86_64`` groups it will use an option from ``build:x86_64`` for the ``x86_64`` architecture and ``build`` for any other (architecture specific group has higher priority). In case if both groups are presented, architecture specific options will be merged into global ones overriding them.
|
||||
Some groups can be specified for each architecture and/or repository separately. E.g. if there are ``build`` and ``build:x86_64`` groups it will use an option from ``build:x86_64`` for the ``x86_64`` architecture and ``build`` for any other (architecture specific group has higher priority). In case if both groups are presented, architecture specific options will be merged into global ones overriding them. The order which will be used for option resolution is the following:
|
||||
|
||||
#. Repository and architecture specific, e.g. ``build:aur-clone:x86_64``.
|
||||
#. Repository specific, e.g. ``build:aur-clone``.
|
||||
#. Architecture specific, e.g. ``build:x86_64``.
|
||||
#. Default section, e.g. ``build``.
|
||||
|
||||
There are two variable types which have been added to default ones, they are paths and lists. List values will be read in the same way as shell does:
|
||||
|
||||
@ -25,7 +30,7 @@ There is also additional subcommand which will allow to validate configuration a
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
ahriman -a x86_64 service-config-validate
|
||||
ahriman service-config-validate
|
||||
|
||||
It will check current settings on common errors and compare configuration with known schema.
|
||||
|
||||
@ -34,8 +39,9 @@ It will check current settings on common errors and compare configuration with k
|
||||
|
||||
Base configuration settings.
|
||||
|
||||
* ``include`` - path to directory with configuration files overrides, string, required.
|
||||
* ``apply_migrations`` - perform migrations on application start, boolean, optional, default ``yes``. Useful if you are using git version. Note, however, that this option must be changed only if you know what to do and going to handle migrations automatically.
|
||||
* ``database`` - path to SQLite database, string, required.
|
||||
* ``include`` - path to directory with configuration files overrides, string, optional.
|
||||
* ``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.
|
||||
|
||||
@ -61,6 +67,7 @@ Base authorization settings. ``OAuth`` provider requires ``aioauth-client`` libr
|
||||
* ``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_icon`` - OAuth2 login button icon, string, optional, default is ``google``. Must be valid `Bootstrap icon <https://icons.getbootstrap.com/>`_ name.
|
||||
* ``oauth_provider`` - OAuth2 provider class name as is in ``aioauth-client`` (e.g. ``GoogleClient``, ``GithubClient`` etc), string, required in case if ``oauth`` is used.
|
||||
* ``oauth_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.
|
||||
* ``salt`` - additional password hash salt, string, optional.
|
||||
@ -86,7 +93,6 @@ Build related configuration. Group name can refer to architecture, e.g. ``build:
|
||||
|
||||
Base repository settings.
|
||||
|
||||
* ``name`` - repository name, string, required.
|
||||
* ``root`` - root path for application, string, required.
|
||||
|
||||
``sign:*`` groups
|
||||
@ -97,10 +103,10 @@ Settings for signing packages or repository. Group name can refer to architectur
|
||||
* ``target`` - configuration flag to enable signing, space separated list of strings, required. Allowed values are ``package`` (sign each package separately), ``repository`` (sign repository database file).
|
||||
* ``key`` - default PGP key, string, required. This key will also be used for database signing if enabled.
|
||||
|
||||
``web:*`` groups
|
||||
----------------
|
||||
``web`` group
|
||||
-------------
|
||||
|
||||
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.
|
||||
Web server settings. If any of ``host``/``port`` is not set, web integration will be disabled. 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``.
|
||||
@ -113,7 +119,7 @@ Web server settings. If any of ``host``/``port`` is not set, web integration wil
|
||||
* ``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.
|
||||
* ``templates`` - path to templates directories, space separated list of strings, required.
|
||||
* ``timeout`` - HTTP request timeout in seconds, int, optional, default is ``30``.
|
||||
* ``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.
|
||||
@ -226,7 +232,6 @@ Section name must be either ``console`` (plus optional architecture name, e.g. `
|
||||
Section name must be either ``email`` (plus optional architecture name, e.g. ``email:x86_64``) or random name with ``type`` set.
|
||||
|
||||
* ``type`` - type of the report, string, optional, must be set to ``email`` if exists.
|
||||
* ``full_template_path`` - path to Jinja2 template for full package description index, string, optional.
|
||||
* ``homepage`` - link to homepage, string, optional.
|
||||
* ``host`` - SMTP host for sending emails, string, required.
|
||||
* ``link_path`` - prefix for HTML links, string, required.
|
||||
@ -236,7 +241,9 @@ Section name must be either ``email`` (plus optional architecture name, e.g. ``e
|
||||
* ``receivers`` - SMTP receiver addresses, space separated list of strings, required.
|
||||
* ``sender`` - SMTP sender address, string, required.
|
||||
* ``ssl`` - SSL mode for SMTP connection, one of ``ssl``, ``starttls``, ``disabled``, optional, default ``disabled``.
|
||||
* ``template_path`` - path to Jinja2 template, string, required.
|
||||
* ``template`` - Jinja2 template name, string, required.
|
||||
* ``template_full`` - Jinja2 template name for full package description index, string, optional.
|
||||
* ``templates`` - path to templates directories, space separated list of strings, required.
|
||||
* ``user`` - SMTP user to authenticate, string, optional.
|
||||
|
||||
``html`` type
|
||||
@ -248,7 +255,8 @@ Section name must be either ``html`` (plus optional architecture name, e.g. ``ht
|
||||
* ``homepage`` - link to homepage, string, optional.
|
||||
* ``link_path`` - prefix for HTML links, string, required.
|
||||
* ``path`` - path to html report file, string, required.
|
||||
* ``template_path`` - path to Jinja2 template, string, required.
|
||||
* ``template`` - Jinja2 template name, string, required.
|
||||
* ``templates`` - path to templates directories, space separated list of strings, required.
|
||||
|
||||
``remote-call`` type
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
@ -271,8 +279,9 @@ Section name must be either ``telegram`` (plus optional architecture name, e.g.
|
||||
* ``chat_id`` - telegram chat id, either string with ``@`` or integer value, required.
|
||||
* ``homepage`` - link to homepage, string, optional.
|
||||
* ``link_path`` - prefix for HTML links, string, required.
|
||||
* ``template_path`` - path to Jinja2 template, string, required.
|
||||
* ``template`` - Jinja2 template name, string, required.
|
||||
* ``template_type`` - ``parse_mode`` to be passed to telegram API, one of ``MarkdownV2``, ``HTML``, ``Markdown``, string, optional, default ``HTML``.
|
||||
* ``templates`` - path to templates directories, space separated list of strings, required.
|
||||
* ``timeout`` - HTTP request timeout in seconds, int, optional, default is ``30``.
|
||||
|
||||
``upload`` group
|
||||
@ -291,20 +300,21 @@ Type will be read from several sources:
|
||||
``github`` type
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
This feature requires Github key creation (see below). Section name must be either ``github`` (plus optional architecture name, e.g. ``github:x86_64``) or random name with ``type`` set.
|
||||
This feature requires GitHub key creation (see below). Section name must be either ``github`` (plus optional architecture name, e.g. ``github:x86_64``) or random name with ``type`` set.
|
||||
|
||||
* ``type`` - type of the upload, string, optional, must be set to ``github`` if exists.
|
||||
* ``owner`` - Github repository owner, string, required.
|
||||
* ``password`` - created Github API key. In order to create it do the following:
|
||||
* ``owner`` - GitHub repository owner, string, required.
|
||||
* ``password`` - created GitHub API key. In order to create it do the following:
|
||||
|
||||
#. Go to `settings page <https://github.com/settings/profile>`_.
|
||||
#. Switch to `developers settings <https://github.com/settings/apps>`_.
|
||||
#. Switch to `personal access tokens <https://github.com/settings/tokens>`_.
|
||||
#. Generate new token. Required scope is ``public_repo`` (or ``repo`` for private repository support).
|
||||
|
||||
* ``repository`` - Github repository name, string, required. Repository must be created before any action and must have active branch (e.g. with readme).
|
||||
* ``repository`` - GitHub repository name, string, required. Repository must be created before any action and must have active branch (e.g. with readme).
|
||||
* ``timeout`` - HTTP request timeout in seconds, int, optional, default is ``30``.
|
||||
* ``username`` - Github authorization user, string, required. Basically the same as ``owner``.
|
||||
* ``use_full_release_name`` - if set to ``yes``, the release will contain both repository name and architecture, and only architecture otherwise, boolean, optional, default ``no`` (legacy behavior).
|
||||
* ``username`` - GitHub authorization user, string, required. Basically the same as ``owner``.
|
||||
|
||||
``remote-service`` type
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -328,9 +338,10 @@ Requires ``rsync`` package to be installed. Do not forget to configure ssh for u
|
||||
|
||||
Requires ``boto3`` library to be installed. Section name must be either ``s3`` (plus optional architecture name, e.g. ``s3:x86_64``) or random name with ``type`` set.
|
||||
|
||||
* ``type`` - type of the upload, string, optional, must be set to ``github`` if exists.
|
||||
* ``type`` - type of the upload, string, optional, must be set to ``s3`` if exists.
|
||||
* ``access_key`` - AWS access key ID, string, required.
|
||||
* ``bucket`` - bucket name (e.g. ``bucket``), string, required.
|
||||
* ``chunk_size`` - chunk size for calculating entity tags, int, optional, default 8 * 1024 * 1024.
|
||||
* ``object_path`` - path prefix for stored objects, string, optional. If none set, the prefix as in repository tree will be used.
|
||||
* ``region`` - bucket region (e.g. ``eu-central-1``), string, required.
|
||||
* ``secret_key`` - AWS secret access key, string, required.
|
133
docs/faq.rst
133
docs/faq.rst
@ -17,8 +17,8 @@ TL;DR
|
||||
.. code-block:: shell
|
||||
|
||||
yay -S ahriman
|
||||
ahriman -a x86_64 service-setup --packager "ahriman bot <ahriman@example.com>" --repository "repository"
|
||||
systemctl enable --now ahriman@x86_64.timer
|
||||
ahriman -a x86_64 -r aur-clone service-setup --packager "ahriman bot <ahriman@example.com>"
|
||||
systemctl enable --now ahriman@x86_64-aur-clone.timer
|
||||
|
||||
Long answer
|
||||
"""""""""""
|
||||
@ -32,7 +32,7 @@ There is special command which can be used in order to validate current configur
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
ahriman -a x86_64 service-config-validate --exit-code
|
||||
ahriman service-config-validate --exit-code
|
||||
|
||||
This command will print found errors, based on `cerberus <https://docs.python-cerberus.org/>`_, e.g.:
|
||||
|
||||
@ -71,7 +71,7 @@ states that default build command is ``extra-x86_64-build``. But if there is sec
|
||||
[build:i686]
|
||||
build_command = extra-i686-build
|
||||
|
||||
the ``extra-i686-build`` command will be used for ``i686`` architecture.
|
||||
the ``extra-i686-build`` command will be used for ``i686`` architecture. You can also override settings for different repositories and architectures; in this case section names will be ``build:aur-clone`` (repository name only) and ``build:aur-clone:i686`` (both repository name and architecture).
|
||||
|
||||
How to generate build reports
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -121,7 +121,7 @@ How do I add new package
|
||||
|
||||
sudo -u ahriman ahriman package-add ahriman --now
|
||||
|
||||
``--now`` flag is totally optional and just run ``repo-update`` subcommand after the registering the new package, Thus the extended flow is the following:
|
||||
``--now`` flag is totally optional and just run ``repo-update`` subcommand after the registering the new package. Thus the extended flow is the following:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
@ -209,7 +209,7 @@ So it is the same as adding any other package, but due to restrictions you must
|
||||
|
||||
sudo -u ahriman ahriman package-add pacman -s repository
|
||||
|
||||
This feature is heavily depends on local pacman cache. In order to use this feature it is recommended to either run ``pacman -Sy`` before the interaction or configure timer for this.
|
||||
This feature is heavily depends on local pacman cache. In order to use this feature it is recommended to either run ``pacman -Sy`` before the interaction or use internal application cache with ``--refresh`` flag.
|
||||
|
||||
Package build fails because it cannot validate PGP signature of source files
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -317,7 +317,7 @@ Add the following lines to your ``pacman.conf``:
|
||||
.. code-block:: ini
|
||||
|
||||
[repository]
|
||||
Server = file:///var/lib/ahriman/repository/x86_64
|
||||
Server = file:///var/lib/ahriman/repository/$repo/$arch
|
||||
|
||||
(You might need to add ``SigLevel`` option according to the pacman documentation.)
|
||||
|
||||
@ -359,7 +359,14 @@ Example of the status page configuration is the following (status service is usi
|
||||
Docker image
|
||||
------------
|
||||
|
||||
We provide official images which can be found under ``arcan1s/ahriman`` repository. Docker image is being updated on each commit to master as well as on each version. If you would like to use last (probably unstable) build you can use ``edge`` tag or ``latest`` for any tagged versions; otherwise you can use any version tag available.
|
||||
We provide official images which can be found under:
|
||||
|
||||
* docker registry ``arcan1s/ahriman``;
|
||||
* ghcr.io registry ``ghcr.io/arcan1s/ahriman``;
|
||||
|
||||
These images are totally identical.
|
||||
|
||||
Docker image is being updated on each commit to master as well as on each version. If you would like to use last (probably unstable) build you can use ``edge`` tag or ``latest`` for any tagged versions; otherwise you can use any version tag available.
|
||||
|
||||
The default action (in case if no arguments provided) is ``repo-update``. Basically the idea is to run container, e.g.:
|
||||
|
||||
@ -395,6 +402,8 @@ The following environment variables are supported:
|
||||
* ``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_POSTSETUP_COMMAND`` - if set, the command which will be called (as root) after the setup command, but before any other actions.
|
||||
* ``AHRIMAN_PRESETUP_COMMAND`` - if set, the command which will be called (as root) right before the setup command.
|
||||
* ``AHRIMAN_REPOSITORY`` - repository name, default is ``aur-clone``.
|
||||
* ``AHRIMAN_REPOSITORY_SERVER`` - optional override for the repository url. Useful if you would like to download packages from remote instead of local filesystem.
|
||||
* ``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.
|
||||
@ -422,7 +431,7 @@ This command uses same rules as ``repo-update``, thus, e.g. requires ``--privile
|
||||
Web service setup
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
Well for that you would need to have web container instance running forever; it can be achieved by the following command:
|
||||
For that you would need to have web container instance running forever; it can be achieved by the following command:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
@ -444,6 +453,20 @@ 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
|
||||
|
||||
Mutli-repository web service
|
||||
""""""""""""""""""""""""""""
|
||||
|
||||
Idea is pretty same as to just run web service. However, it is required to run setup commands for each repository, except for one which is specified by ``AHRIMAN_REPOSITORY`` and ``AHRIMAN_ARCHITECTURE ` variables.
|
||||
|
||||
In order to create configuration for additional repositories, the ``AHRIMAN_POSTSETUP_COMMAND`` variable should be used, e.g.:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
docker run --privileged -p 8080:8080 -e AHRIMAN_PORT=8080 -e AHRIMAN_UNIX_SOCKET=/var/lib/ahriman/ahriman/ahriman-web.sock -e AHRIMAN_POSTSETUP_COMMAND="ahriman --architecture x86_64 --repository aur-clone-v2 service-setup --build-as-user ahriman --packager 'ahriman bot <ahriman@example.com>'" -v /path/to/local/repo:/var/lib/ahriman arcan1s/ahriman:latest
|
||||
|
||||
The command above will also create configuration for the repository named ``aur-clone-v2``.
|
||||
|
||||
Note, however, that the command above is only required in case if the service is going to be used to run subprocesses. Otherwise, everything else (web interface, status, etc) will be handled as usual.
|
||||
|
||||
Non-x86_64 architecture setup
|
||||
-----------------------------
|
||||
@ -456,22 +479,22 @@ 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:
|
||||
First, considering having base Arch Linux system, we need to install keyring for the specified repositories, e.g.:
|
||||
|
||||
.. 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
|
||||
wget http://pool.mirror.archlinux32.org/i686/core/archlinux32-keyring-20230705-1.0-any.pkg.tar.zst
|
||||
pacman -U archlinux32-keyring-20230705-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:
|
||||
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, e.g.:
|
||||
|
||||
.. 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
|
||||
wget http://pool.mirror.archlinux32.org/i686/extra/devtools-20221208-1.2-any.pkg.tar.zst
|
||||
pacman -U devtools-20221208-1.2-any.pkg.tar.zst
|
||||
|
||||
Alternatively, you can create your own ``makepkg`` configuration and save it as ``/usr/share/devtools/makepkg-i686.conf``.
|
||||
Alternatively, you can create your own ``makepkg`` configuration and save it as ``/usr/share/devtools/makepkg.conf.d/i686.conf``.
|
||||
|
||||
#.
|
||||
Setup repository as usual:
|
||||
@ -485,6 +508,9 @@ In this example we are going to use files and packages which are provided by off
|
||||
* ``--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.
|
||||
|
||||
#.
|
||||
That's all Folks!
|
||||
|
||||
Docker container setup
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@ -510,8 +536,8 @@ There are two possible ways to achieve same setup, by using docker container. Th
|
||||
.. 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
|
||||
RUN wget http://pool.mirror.archlinux32.org/i686/extra/devtools-20221208-1.2-any.pkg.tar.zst && pacman --noconfirm -U devtools-20221208-1.2-any.pkg.tar.zst
|
||||
RUN wget http://pool.mirror.archlinux32.org/i686/core/archlinux32-keyring-20230705-1.0-any.pkg.tar.zst && pacman --noconfirm -U archlinux32-keyring-20230705-1.0-any.pkg.tar.zst
|
||||
|
||||
#.
|
||||
At that point you should have full ``Dockerfile`` like:
|
||||
@ -523,8 +549,8 @@ There are two possible ways to achieve same setup, by using docker container. Th
|
||||
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
|
||||
RUN wget http://pool.mirror.archlinux32.org/i686/extra/devtools-20221208-1.2-any.pkg.tar.zst && pacman --noconfirm -U devtools-20221208-1.2-any.pkg.tar.zst
|
||||
RUN wget http://pool.mirror.archlinux32.org/i686/core/archlinux32-keyring-20230705-1.0-any.pkg.tar.zst && pacman --noconfirm -U archlinux32-keyring-20230705-1.0-any.pkg.tar.zst
|
||||
|
||||
#.
|
||||
After that you can build you own container, e.g.:
|
||||
@ -554,8 +580,8 @@ There are several choices:
|
||||
.. code-block::
|
||||
|
||||
server {
|
||||
location /x86_64 {
|
||||
root /var/lib/ahriman/repository/x86_64;
|
||||
location / {
|
||||
root /var/lib/ahriman/repository/;
|
||||
autoindex on;
|
||||
}
|
||||
}
|
||||
@ -571,7 +597,7 @@ There are several choices:
|
||||
[rsync]
|
||||
remote = 192.168.0.1:/srv/repo
|
||||
|
||||
After that just add ``/srv/repo`` to the ``pacman.conf`` as usual. You can also upload to S3 (e.g. ``Server = https://s3.eu-central-1.amazonaws.com/repository/x86_64``) or to Github (e.g. ``Server = https://github.com/ahriman/repository/releases/download/x86_64``).
|
||||
After that just add ``/srv/repo`` to the ``pacman.conf`` as usual. You can also upload to S3 (``Server = https://s3.eu-central-1.amazonaws.com/repository/aur-clone/x86_64``) or to Github (``Server = https://github.com/ahriman/repository/releases/download/aur-clone-x86_64``).
|
||||
|
||||
How to sync to S3
|
||||
^^^^^^^^^^^^^^^^^
|
||||
@ -632,6 +658,23 @@ How to sync to S3
|
||||
region = eu-central-1
|
||||
secret_key = ...
|
||||
|
||||
S3 with SSL
|
||||
"""""""""""
|
||||
|
||||
In order to configure S3 on custom domain with SSL (and some other features, like redirects), the CloudFront should be used.
|
||||
|
||||
#. Configure S3 as described above.
|
||||
#. In bucket properties, enable static website hosting with hosting type "Host a static website".
|
||||
#. Go to AWS Certificate Manager and create public ceritificate on your domain. Validate domain as suggested.
|
||||
#. Go to CloudFront and create distribution. The following settings are required:
|
||||
|
||||
* Origin domain choose S3 bucket.
|
||||
* Tick use website endpoint.
|
||||
* Disable caching.
|
||||
* Select issued certificate.
|
||||
|
||||
#. Point DNS record to CloudFront address.
|
||||
|
||||
How to sync to Github releases
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@ -676,7 +719,7 @@ How to report by email
|
||||
|
||||
[email]
|
||||
host = smtp.example.com
|
||||
link_path = http://example.com/x86_64
|
||||
link_path = http://example.com/aur-clone/x86_64
|
||||
password = ...
|
||||
port = 465
|
||||
receivers = me@example.com
|
||||
@ -702,10 +745,10 @@ How to generate index page for S3
|
||||
target = html
|
||||
|
||||
[html]
|
||||
path = /var/lib/ahriman/repository/x86_64/index.html
|
||||
link_path = http://example.com/x86_64
|
||||
path = /var/lib/ahriman/repository/aur-clone/x86_64/index.html
|
||||
link_path = http://example.com/aur-clone/x86_64
|
||||
|
||||
After these steps ``index.html`` file will be automatically synced to S3
|
||||
After these steps ``index.html`` file will be automatically synced to S3.
|
||||
|
||||
How to post build report to telegram
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -741,7 +784,7 @@ How to post build report to telegram
|
||||
[telegram]
|
||||
api_key = aaAAbbBBccCC
|
||||
chat_id = @ahriman
|
||||
link_path = http://example.com/x86_64
|
||||
link_path = http://example.com/aur-clone/x86_64
|
||||
|
||||
``api_key`` is the one sent by `@BotFather <https://t.me/botfather>`_, ``chat_id`` is the value retrieved from previous step.
|
||||
|
||||
@ -756,7 +799,7 @@ If you did everything fine you should receive the message with the next update.
|
||||
Distributed builds
|
||||
------------------
|
||||
|
||||
The service allows to run build on multiple machines and collect packages on main node. There are multiple ways to achieve it, this section describes officially supported methods.
|
||||
The service allows to run build on multiple machines and collect packages on main node. There are several ways to achieve it, this section describes officially supported methods.
|
||||
|
||||
Remote synchronization and remote server call
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -933,7 +976,7 @@ Command to run worker node:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
docker run --privileged -v worker.ini:/etc/ahriman.ini.d/overrides.ini -it arcan1s/ahriman:latest package-add arhiman --now
|
||||
docker run --privileged -v worker.ini:/etc/ahriman.ini.d/overrides.ini -it arcan1s/ahriman:latest package-add ahriman --now
|
||||
|
||||
The command above will successfully build ``ahriman`` package, upload it on master node and, finally, will update master node repository.
|
||||
|
||||
@ -1046,7 +1089,7 @@ How to setup web service
|
||||
port = 8080
|
||||
|
||||
#.
|
||||
Start the web service ``systemctl enable --now ahriman-web@x86_64``.
|
||||
Start the web service ``systemctl enable --now ahriman-web``.
|
||||
|
||||
How to enable basic authorization
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -1059,7 +1102,7 @@ How to enable basic authorization
|
||||
yay -S --asdeps python-aiohttp-security python-aiohttp-session python-cryptography
|
||||
|
||||
#.
|
||||
Configure the service to enable authorization (``salt`` can be generated as any random string):
|
||||
Configure the service to enable authorization (``salt`` can be generated as any random string and optional):
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
@ -1087,7 +1130,7 @@ How to enable basic authorization
|
||||
|
||||
sudo -u ahriman ahriman user-add -r full api
|
||||
|
||||
This command will ask for the password, just type it in stdin; *do not* leave the field blank, user will not be able to authorize, and finally configure the application:
|
||||
This command will ask for the password, just type it in stdin; **do not** leave the field blank, user will not be able to authorize, and finally configure the application:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
@ -1103,7 +1146,7 @@ How to enable basic authorization
|
||||
sudo -u ahriman ahriman user-add -r full my-first-user
|
||||
|
||||
#.
|
||||
Restart web service ``systemctl restart ahriman-web@x86_64``.
|
||||
Restart web service ``systemctl restart ahriman-web``.
|
||||
|
||||
How to enable OAuth authorization
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -1149,7 +1192,7 @@ How to enable OAuth authorization
|
||||
When it will ask for the password leave it blank.
|
||||
|
||||
#.
|
||||
Restart web service ``systemctl restart ahriman-web@x86_64``.
|
||||
Restart web service ``systemctl restart ahriman-web``.
|
||||
|
||||
How to implement own interface
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -1265,12 +1308,28 @@ You can also ask to forward logs to ``stderr``, just set ``--log-handler`` flag,
|
||||
|
||||
ahriman --log-handler console ...
|
||||
|
||||
You can even configure logging as you wish, but kindly refer to python ``logging`` module `configuration <https://docs.python.org/3/library/logging.config.html>`_. The application uses java concept to log messages, e.g. class ``Application`` imported from ``ahriman.application.application`` package will have logger called ``ahriman.application.application.Application``. In order to e.g. change logger name for whole application package it is possible to change values for ``ahriman.application`` package; thus editing ``ahriman`` logger configuration will change logging for whole application (unless there are overrides for another logger).
|
||||
You can even configure logging as you wish, but kindly refer to python ``logging`` module `configuration <https://docs.python.org/3/library/logging.config.html>`_.
|
||||
|
||||
The application uses java concept to log messages, e.g. class ``Application`` imported from ``ahriman.application.application`` package will have logger called ``ahriman.application.application.Application``. In order to e.g. change logger name for whole application package it is possible to change values for ``ahriman.application`` package; thus editing ``ahriman`` logger configuration will change logging for whole application (unless there are overrides for another logger).
|
||||
|
||||
Html customization
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
It is possible to customize html templates. In order to do so, create files somewhere (refer to Jinja2 documentation and the service source code for available parameters) and put ``template_path`` to configuration pointing to this directory.
|
||||
It is possible to customize html templates. In order to do so, create files somewhere (refer to Jinja2 documentation and the service source code for available parameters) and prepend ``templates`` with value pointing to this directory.
|
||||
|
||||
In addition, default html templates supports style customization out-of-box. In order to customize style, just put file named ``user-style.jinja2`` to the templates directory.
|
||||
|
||||
Web API extension
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
The application loads web views dynamically, so it is possible relatively easy extend its API. In order to do so:
|
||||
|
||||
#. Create view class which is derived from ``ahriman.web.views.base.BaseView`` class.
|
||||
#. Create implementation for this class.
|
||||
#. Put file into ``ahriman.web.views`` package.
|
||||
#. Restart application.
|
||||
|
||||
For more details about implementation and possibilities, kindly refer to module documentation and source code and `aiohttp documentation <https://docs.aiohttp.org/en/stable/>`_.
|
||||
|
||||
I did not find my question
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -34,6 +34,7 @@ Contents
|
||||
configuration
|
||||
command-line
|
||||
faq
|
||||
migration
|
||||
architecture
|
||||
advanced-usage
|
||||
triggers
|
||||
|
68
docs/migration.rst
Normal file
68
docs/migration.rst
Normal file
@ -0,0 +1,68 @@
|
||||
Manual migrations
|
||||
=================
|
||||
|
||||
Normally most of migrations are handled automatically after application start. However, some upgrades require manual interventions; this document describes them.
|
||||
|
||||
Upgrades to breakpoints
|
||||
-----------------------
|
||||
|
||||
To 2.9.0
|
||||
^^^^^^^^
|
||||
|
||||
This release includes major upgrade for the newest devtools and archlinux repository structure. In order to upgrade package need to:
|
||||
|
||||
#. Upgrade to the latest major release of python (3.11) (required by other changes).
|
||||
#. Upgrade devtools to the latest release.
|
||||
#. Backup your settings, ``/etc/ahriman.ini.d/00-setup-overrides.ini`` by default.
|
||||
#. Run setup command (i.e. ``ahriman service-setup``) again with the same arguments as you used before. This step can be done manually by moving ``devtools`` configuration (something like ``/usr/share/devtools/pacman-ahriman*.conf``) to new location ``/usr/share/devtools/pacman.conf.d/`` under name ``ahriman.conf``. After that make sure to remove any ``community`` mentions from configurations (e.g. ``/usr/share/devtools/pacman.conf.d/ahriman.conf``, ``/etc/ahriman.ini``) if there were any. The only thing which will change is ``devtools`` configuration.
|
||||
#. Remove build chroot as it is incompatible, e.g. ``sudo ahriman service-clean --chroot``.
|
||||
#. Run ``sudo -u ahriman ahriman update --no-aur --no-local --no-manual -yy`` in order to update local databases.
|
||||
|
||||
To 2.12.0
|
||||
^^^^^^^^^
|
||||
|
||||
This release includes paths migration. Unlike usual case, no automatic migration is performed because it might break user configuration. The following noticeable changes have been made:
|
||||
|
||||
* Path to pre-built packages now includes repository name, i.e. it has been changed from ``/var/lib/ahriman/packages/x86_64`` to ``/var/lib/ahriman/packages/aur-clone/x86_64``.
|
||||
* Path to pacman databases now includes repository name too, it has been changed from ``/var/lib/ahriman/pacman/x86_64`` to ``/var/lib/ahriman/pacman/aur-clone/x86_64``.
|
||||
* Path to repository itself also includes repository name, from ``/var/lib/ahriman/repository/x86_64`` to ``/var/lib/ahriman/repository/aur-clone/x86_64``.
|
||||
|
||||
In order to migrate to new filesystem tree the following actions are required:
|
||||
|
||||
#.
|
||||
Stop and disable all services, e.g. timer and web service:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
sudo systemctl disable --now ahriman@x86_64.timer
|
||||
sudo systemctl disable --now ahriman-web@x86_64
|
||||
|
||||
#.
|
||||
Create directory tree. It can be done by running ``ahriman service-tree-migrate`` subcommand. It performs copying between the old repository tree and the new one. Alternatively you can copy directories by hands.
|
||||
|
||||
#.
|
||||
Edit configuration in case if anything is pointing to the old path, e.g. HTML report generation, in the way in which it will be pointed to directory inside repository specific one, e.g. ``/var/lib/ahriman/repository/x86_64`` to ``/var/lib/ahriman/repository/aur-clone/x86_64``.
|
||||
|
||||
#.
|
||||
Edit devtools pacman configuration (``/usr/share/devtools/pacman.conf.d/ahriman-x86_64.conf`` by default) replacing ``Server`` with path to your repository, e.g.:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[aur-clone]
|
||||
SigLevel = Optional TrustAll
|
||||
Server = file:///var/lib/ahriman/repository/aur-clone/x86_64
|
||||
|
||||
Alternatively it can be done by running ``service-setup`` command again.
|
||||
|
||||
#. If you didn't run setup command on the previous step, make sure to remove architecture reference from ``web`` section (if any).
|
||||
|
||||
#.
|
||||
Make sure to update remote synchronization services if any. Almost all of them rely on current repository tree by default, so you need to setup either redirects or configure to synchronize to the old locations (e.g. ``object_path`` option for S3 synchronization).
|
||||
|
||||
#.
|
||||
Enable and start services again. Unit template parameter should include both repository architecture and name, dash separated, e.g. ``x86_64-aur-clone``:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
sudo systemctl enable --now ahriman@x86_64-aur-clone.timer
|
||||
sudo systemctl enable --now ahriman-web
|
@ -10,7 +10,7 @@ Initial setup
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
sudo ahriman -a x86_64 service-setup ...
|
||||
sudo ahriman -a x86_64 -r aur-clone service-setup ...
|
||||
|
||||
``service-setup`` literally does the following steps:
|
||||
|
||||
@ -29,26 +29,26 @@ Initial setup
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
ln -s /usr/bin/archbuild /usr/local/bin/ahriman-x86_64-build
|
||||
ln -s /usr/bin/archbuild /usr/local/bin/aur-clone-x86_64-build
|
||||
|
||||
#.
|
||||
Create configuration file (same as previous ``{name}.conf``):
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
cp /usr/share/devtools/pacman.conf.d/{extra,ahriman}.conf
|
||||
cp /usr/share/devtools/pacman.conf.d/{extra,aur-clone}.conf
|
||||
|
||||
#.
|
||||
Change configuration file, add your own repository, add multilib repository etc:
|
||||
|
||||
.. 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.conf.d/ahriman.conf
|
||||
echo '[multilib]' | tee -a /usr/share/devtools/pacman.conf.d/aur-clone-x86_64.conf
|
||||
echo 'Include = /etc/pacman.d/mirrorlist' | tee -a /usr/share/devtools/pacman.conf.d/aur-clone-x86_64.conf
|
||||
|
||||
echo '[aur-clone]' | tee -a /usr/share/devtools/pacman-ahriman.conf
|
||||
echo 'SigLevel = Optional TrustAll' | tee -a /usr/share/devtools/pacman.conf.d/ahriman.conf
|
||||
echo 'Server = file:///var/lib/ahriman/repository/$arch' | tee -a /usr/share/devtools/pacman.conf.d/ahriman.conf
|
||||
echo '[aur-clone]' | tee -a /usr/share/devtools/pacman.conf.d/aur-clone-x86_64.conf
|
||||
echo 'SigLevel = Optional TrustAll' | tee -a /usr/share/devtools/pacman.conf.d/aur-clone-x86_64.conf
|
||||
echo 'Server = file:///var/lib/ahriman/repository/$repo/$arch' | tee -a /usr/share/devtools/pacman.conf.d/aur-clone-x86_64.conf
|
||||
|
||||
#.
|
||||
Set ``build_command`` option to point to your command:
|
||||
@ -56,14 +56,14 @@ Initial setup
|
||||
.. 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 'build_command = aur-clone-x86_64-build' | tee -a /etc/ahriman.ini.d/build.ini
|
||||
|
||||
#.
|
||||
Configure ``/etc/sudoers.d/ahriman`` to allow running command without a password:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
echo 'Cmnd_Alias CARCHBUILD_CMD = /usr/local/bin/ahriman-x86_64-build *' | tee -a /etc/sudoers.d/ahriman
|
||||
echo 'Cmnd_Alias CARCHBUILD_CMD = /usr/local/bin/aur-clone-x86_64-build *' | tee -a /etc/sudoers.d/ahriman
|
||||
echo 'ahriman ALL=(ALL) NOPASSWD:SETENV: CARCHBUILD_CMD' | tee -a /etc/sudoers.d/ahriman
|
||||
chmod 400 /etc/sudoers.d/ahriman
|
||||
|
||||
@ -74,20 +74,20 @@ Initial setup
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
systemctl enable --now ahriman@x86_64.timer
|
||||
systemctl enable --now ahriman@x86_64-aur-clone.timer
|
||||
|
||||
#.
|
||||
Start and enable status page:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
systemctl enable --now ahriman-web@x86_64
|
||||
systemctl enable --now ahriman-web
|
||||
|
||||
#.
|
||||
Add packages by using ``ahriman package-add {package}`` command:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
sudo -u ahriman ahriman -a x86_64 package-add ahriman --now --refresh
|
||||
sudo -u ahriman ahriman package-add ahriman --now --refresh
|
||||
|
||||
The ``--refresh`` flag is required in order to handle local database update.
|
||||
|
@ -95,8 +95,8 @@ As it has been mentioned, our trigger must derive from specific class:
|
||||
|
||||
class SlackReporter(Trigger):
|
||||
|
||||
def __init__(self, architecture, configuration):
|
||||
Trigger.__init__(self, architecture, configuration)
|
||||
def __init__(self, repository_id, configuration):
|
||||
Trigger.__init__(self, repository_id, configuration)
|
||||
self.slack_url = configuration.get("slack", "url")
|
||||
self.channel = configuration.get("slack", "channel")
|
||||
self.username = configuration.get("slack", "username")
|
||||
@ -120,8 +120,8 @@ Obviously you can implement the specified method in class, but for guide purpose
|
||||
|
||||
class SlackReporter(Trigger):
|
||||
|
||||
def __init__(self, architecture, configuration):
|
||||
Trigger.__init__(self, architecture, configuration)
|
||||
def __init__(self, repository_id, configuration):
|
||||
Trigger.__init__(self, repository_id, configuration)
|
||||
self.slack_url = configuration.get("slack", "url")
|
||||
self.channel = configuration.get("slack", "channel")
|
||||
self.username = configuration.get("slack", "username")
|
||||
@ -132,7 +132,7 @@ Obviously you can implement the specified method in class, but for guide purpose
|
||||
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``).
|
||||
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.SlackReporter``).
|
||||
|
||||
After that run application as usual and receive notification in your slack channel.
|
||||
|
||||
|
@ -46,7 +46,7 @@ package() {
|
||||
python -m installer --destdir="$pkgdir" "dist/$pkgname-$pkgver-py3-none-any.whl"
|
||||
|
||||
# thanks too PEP517, which we all wanted, you need to install data files manually nowadays
|
||||
pushd package && find . -type f -exec install -Dm644 "{}" "$pkgdir/usr/{}" \; && popd
|
||||
pushd package && find . \( -type f -or -type l \) -exec install -Dm644 "{}" "$pkgdir/usr/{}" \; && popd
|
||||
|
||||
# keep usr/share configs as reference and copy them to /etc
|
||||
install -Dm644 "$pkgdir/usr/share/$pkgname/settings/ahriman.ini" "$pkgdir/etc/ahriman.ini"
|
||||
|
@ -1,10 +1,11 @@
|
||||
post_upgrade() {
|
||||
local breakpoints=(
|
||||
2.9.0-1
|
||||
2.12.0-1
|
||||
)
|
||||
|
||||
for v in "${breakpoints[@]}"; do
|
||||
if [[ $(vercmp "$v" "$2") -eq 1 ]]; then
|
||||
if [[ $(vercmp "$v" "$2") -ne "-1" ]]; then
|
||||
"_${v//[.-]/_}_changes"
|
||||
fi
|
||||
done
|
||||
@ -20,6 +21,22 @@ It was found that you were upgrading from old-devtools package to the new one, w
|
||||
* remove build chroot: sudo rm -r /var/lib/ahriman/chroot/ahriman-x86_64/;
|
||||
* update local databases: sudo -u ahriman ahriman update --no-aur --no-local --no-manual -yy;
|
||||
|
||||
For more information kindly refer to changelog https://github.com/arcan1s/ahriman/releases/tag/2.9.0
|
||||
For more information kindly refer to migration notes https://ahriman.readthedocs.io/en/stable/migration.html
|
||||
EOF
|
||||
}
|
||||
|
||||
_2_12_0_1_changes() {
|
||||
cat << EOF
|
||||
Whereas old tree is still supported it is highly recommended to migrate to the new one:
|
||||
|
||||
* stop and disable all services;
|
||||
* run service-tree-migrate as ahriman user;
|
||||
* edit configuration to avoid pointing to the old paths;
|
||||
* update devtools pacman configuration (e.g. /usr/share/devtools/pacman.conf.d/ahriman-x86_64.conf) with new repository path;
|
||||
* update synchronization services in order to support new paths (or setup redirects);
|
||||
* enable web and timer services again by using x86_64-aur-clone suffix, where x86_64 is your architecture and
|
||||
aur-clone is repository name;
|
||||
|
||||
For more information kindly refer to migration notes https://ahriman.readthedocs.io/en/stable/migration.html
|
||||
EOF
|
||||
}
|
||||
|
12
package/lib/systemd/system/ahriman-web.service
Normal file
12
package/lib/systemd/system/ahriman-web.service
Normal file
@ -0,0 +1,12 @@
|
||||
[Unit]
|
||||
Description=ArcH linux ReposItory MANager web server
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/bin/ahriman web
|
||||
User=ahriman
|
||||
Group=ahriman
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
@ -1,12 +0,0 @@
|
||||
[Unit]
|
||||
Description=ArcH linux ReposItory MANager web server (%I architecture)
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
ExecStart=/usr/bin/ahriman --architecture %i web
|
||||
User=ahriman
|
||||
Group=ahriman
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
1
package/lib/systemd/system/ahriman-web@.service
Symbolic link
1
package/lib/systemd/system/ahriman-web@.service
Symbolic link
@ -0,0 +1 @@
|
||||
ahriman-web.service
|
@ -1,7 +1,7 @@
|
||||
[Unit]
|
||||
Description=ArcH linux ReposItory MANager (%I architecture)
|
||||
Description=ArcH linux ReposItory MANager (%i)
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/bin/ahriman --architecture %i repo-update --refresh
|
||||
ExecStart=/usr/bin/ahriman --repository-id "%I" repo-update --refresh
|
||||
User=ahriman
|
||||
Group=ahriman
|
@ -1,5 +1,5 @@
|
||||
[Unit]
|
||||
Description=ArcH linux ReposItory MANager timer (%I architecture)
|
||||
Description=ArcH linux ReposItory MANager timer (%i)
|
||||
|
||||
[Timer]
|
||||
OnCalendar=daily
|
||||
|
@ -1,6 +1,7 @@
|
||||
[settings]
|
||||
include = ahriman.ini.d
|
||||
logging = ahriman.ini.d/logging.ini
|
||||
apply_migrations = yes
|
||||
database = /var/lib/ahriman/ahriman.db
|
||||
suppress_http_log_errors = yes
|
||||
|
||||
@ -20,7 +21,6 @@ allow_read_only = yes
|
||||
|
||||
[build]
|
||||
archbuild_flags =
|
||||
build_command = extra-x86_64-build
|
||||
ignore_packages =
|
||||
makechrootpkg_flags =
|
||||
makepkg_flags = --nocolor --ignorearch
|
||||
@ -29,7 +29,6 @@ triggers_known = ahriman.core.gitremote.RemotePullTrigger ahriman.core.gitremote
|
||||
vcs_allowed_age = 604800
|
||||
|
||||
[repository]
|
||||
name = aur-clone
|
||||
root = /var/lib/ahriman
|
||||
|
||||
[sign]
|
||||
@ -55,14 +54,17 @@ use_utf = yes
|
||||
|
||||
[email]
|
||||
no_empty_report = yes
|
||||
template_path = /usr/share/ahriman/templates/email-index.jinja2
|
||||
template = email-index.jinja2
|
||||
templates = /usr/share/ahriman/templates
|
||||
ssl = disabled
|
||||
|
||||
[html]
|
||||
template_path = /usr/share/ahriman/templates/repo-index.jinja2
|
||||
template = repo-index.jinja2
|
||||
templates = /usr/share/ahriman/templates
|
||||
|
||||
[telegram]
|
||||
template_path = /usr/share/ahriman/templates/telegram-index.jinja2
|
||||
template = telegram-index.jinja2
|
||||
templates = /usr/share/ahriman/templates
|
||||
|
||||
[upload]
|
||||
target =
|
||||
|
@ -1,13 +1,14 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>{{ repository }}</title>
|
||||
<title>ahriman</title>
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<link rel="shortcut icon" href="/static/favicon.ico">
|
||||
|
||||
{% include "utils/style.jinja2" %}
|
||||
{% include "user-style.jinja2" ignore missing %}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@ -15,7 +16,22 @@
|
||||
{% include "utils/bootstrap-scripts.jinja2" %}
|
||||
|
||||
<div class="container">
|
||||
<h1 id="badge-repository">ahriman</h1>
|
||||
<nav class="navbar navbar-expand-lg">
|
||||
<div class="navbar-brand"><img src="/static/logo.svg" width="30" height="30" alt=""> ahriman</div>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbar-supported-content" aria-controls="navbar-supported-content" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div id="navbar-supported-content" class="collapse navbar-collapse">
|
||||
<ul id="repositories" class="nav nav-tabs">
|
||||
{% for repository in repositories %}
|
||||
<li class="nav-item">
|
||||
<a id="{{ repository.id }}-lnk" class="nav-link" href="#{{ repository.id }}" data-repository="{{ repository.repository }}" data-architecture="{{ repository.architecture }}">{{ repository.repository }} ({{ repository.architecture }})</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<div id="alert-placeholder" class="toast-container p3 top-0 start-50 translate-middle-x"></div>
|
||||
@ -30,28 +46,28 @@
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li>
|
||||
<button id="package-add-btn" class="btn dropdown-item" data-bs-toggle="modal" data-bs-target="#package-add-modal" hidden>
|
||||
<button id="package-add-button" class="btn dropdown-item" data-bs-toggle="modal" data-bs-target="#package-add-modal" hidden>
|
||||
<i class="bi bi-plus"></i> add
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button id="package-update-btn" class="btn dropdown-item" onclick="updatePackages()" hidden>
|
||||
<button id="package-update-button" class="btn dropdown-item" onclick="updatePackages()" hidden>
|
||||
<i class="bi bi-play"></i> update
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button id="package-rebuild-btn" class="btn dropdown-item" data-bs-toggle="modal" data-bs-target="#package-rebuild-modal" hidden>
|
||||
<button id="package-rebuild-button" class="btn dropdown-item" data-bs-toggle="modal" data-bs-target="#package-rebuild-modal" hidden>
|
||||
<i class="bi bi-arrow-clockwise"></i> rebuild
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button id="package-remove-btn" class="btn dropdown-item" onclick="removePackages()" disabled hidden>
|
||||
<button id="package-remove-button" class="btn dropdown-item" onclick="removePackages()" disabled hidden>
|
||||
<i class="bi bi-trash"></i> remove
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<button id="key-import-btn" type="button" class="btn btn-info" data-bs-toggle="modal" data-bs-target="#key-import-modal" hidden>
|
||||
<button id="key-import-button" type="button" class="btn btn-info" data-bs-toggle="modal" data-bs-target="#key-import-modal" hidden>
|
||||
<i class="bi bi-key"></i> import key
|
||||
</button>
|
||||
{% endif %}
|
||||
@ -116,7 +132,7 @@
|
||||
{% if auth.enabled %}
|
||||
<ul class="nav">
|
||||
{% if auth.username is none %}
|
||||
<li>{{ auth.control|safe }}</li>
|
||||
<li>{{ auth.control | safe }}</li>
|
||||
{% else %}
|
||||
<li>
|
||||
<form action="/api/v1/logout" method="post">
|
||||
|
@ -8,21 +8,21 @@
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group row">
|
||||
<label for="key-fingerprint-input" class="col-sm-2 col-form-label">fingerprint</label>
|
||||
<label for="key-import-fingerprint-input" class="col-sm-2 col-form-label">fingerprint</label>
|
||||
<div class="col-sm-10">
|
||||
<input id="key-fingerprint-input" type="text" class="form-control" placeholder="PGP key fingerprint" name="key" required>
|
||||
<input id="key-import-fingerprint-input" type="text" class="form-control" placeholder="PGP key fingerprint" name="key" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="key-server-input" class="col-sm-2 col-form-label">key server</label>
|
||||
<label for="key-import-server-input" class="col-sm-2 col-form-label">key server</label>
|
||||
<div class="col-sm-10">
|
||||
<input id="key-server-input" type="text" class="form-control" placeholder="PGP key server" name="server" value="keyserver.ubuntu.com" required>
|
||||
<input id="key-import-server-input" type="text" class="form-control" placeholder="PGP key server" name="server" value="keyserver.ubuntu.com" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-2"></div>
|
||||
<div class="col-sm-10">
|
||||
<pre class="language-less"><samp id="key-body-input" class="pre-scrollable language-less"></samp><button id="key-copy-btn" type="button" class="btn language-less" onclick="copyPgpKey()"><i class="bi bi-clipboard"></i> copy</button></pre>
|
||||
<pre class="language-less"><samp id="key-import-body-input" class="pre-scrollable language-less"></samp><button id="key-import-copy-button" type="button" class="btn language-less" onclick="copyPgpKey()"><i class="bi bi-clipboard"></i> copy</button></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -39,24 +39,24 @@
|
||||
const keyImportModal = $("#key-import-modal");
|
||||
const keyImportForm = $("#key-import-form");
|
||||
keyImportModal.on("hidden.bs.modal", () => {
|
||||
keyBodyInput.text("");
|
||||
keyImportBodyInput.text("");
|
||||
keyImportForm.trigger("reset");
|
||||
});
|
||||
|
||||
const keyBodyInput = $("#key-body-input");
|
||||
const keyCopyButton = $("#key-copy-btn");
|
||||
const keyImportBodyInput = $("#key-import-body-input");
|
||||
const keyImportCopyButton = $("#key-import-copy-button");
|
||||
|
||||
const keyFingerprintInput = $("#key-fingerprint-input");
|
||||
const keyServerInput = $("#key-server-input");
|
||||
const keyImportFingerprintInput = $("#key-import-fingerprint-input");
|
||||
const keyImportServerInput = $("#key-import-server-input");
|
||||
|
||||
async function copyPgpKey() {
|
||||
const logs = keyBodyInput.text();
|
||||
await copyToClipboard(logs, keyCopyButton);
|
||||
const logs = keyImportBodyInput.text();
|
||||
await copyToClipboard(logs, keyImportCopyButton);
|
||||
}
|
||||
|
||||
function fetchPgpKey() {
|
||||
const key = keyFingerprintInput.val();
|
||||
const server = keyServerInput.val();
|
||||
const key = keyImportFingerprintInput.val();
|
||||
const server = keyImportServerInput.val();
|
||||
|
||||
if (key && server) {
|
||||
$.ajax({
|
||||
@ -64,14 +64,14 @@
|
||||
data: {"key": key, "server": server},
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
success: response => { keyBodyInput.text(response.key); },
|
||||
success: response => { keyImportBodyInput.text(response.key); },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function importPgpKey() {
|
||||
const key = keyFingerprintInput.val();
|
||||
const server = keyServerInput.val();
|
||||
const key = keyImportFingerprintInput.val();
|
||||
const server = keyImportServerInput.val();
|
||||
|
||||
if (key && server) {
|
||||
$.ajax({
|
||||
|
@ -8,18 +8,18 @@
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group row">
|
||||
<label for="username" class="col-sm-2 col-form-label">username</label>
|
||||
<div class="col-sm-10">
|
||||
<input id="username" type="text" class="form-control" placeholder="enter username" name="username" required>
|
||||
<label for="login-username" class="col-sm-4 col-form-label">username</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="login-username" type="text" class="form-control" placeholder="enter username" name="username" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="password" class="col-sm-2 col-form-label">password</label>
|
||||
<div class="col-sm-10">
|
||||
<label for="login-password" class="col-sm-4 col-form-label">password</label>
|
||||
<div class="col-sm-8">
|
||||
<div class="input-group">
|
||||
<input id="password" type="password" class="form-control" placeholder="enter password" name="password" required>
|
||||
<input id="login-password" type="password" class="form-control" placeholder="enter password" name="password" required>
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-outline-secondary" type="button" onclick="showPassword()"><i id="show-hide-password-btn" class="bi bi-eye"></i></button>
|
||||
<button class="btn btn-outline-secondary" type="button" onclick="showPassword()"><i id="login-show-hide-password-button" class="bi bi-eye"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -34,8 +34,8 @@
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const passwordInput = $("#password");
|
||||
const showHidePasswordButton = $("#show-hide-password-btn");
|
||||
const passwordInput = $("#login-password");
|
||||
const showHidePasswordButton = $("#login-show-hide-password-button");
|
||||
|
||||
function showPassword() {
|
||||
if (passwordInput.attr("type") === "password") {
|
||||
|
@ -8,10 +8,20 @@
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group row">
|
||||
<label for="package-input" class="col-sm-2 col-form-label">package</label>
|
||||
<div class="col-sm-10">
|
||||
<input id="package-input" type="text" list="known-packages-dlist" autocomplete="off" class="form-control" placeholder="AUR package" name="package" required>
|
||||
<datalist id="known-packages-dlist"></datalist>
|
||||
<label for="package-add-repository-input" class="col-sm-4 col-form-label">repository</label>
|
||||
<div class="col-sm-8">
|
||||
<select id="package-add-repository-input" class="form-control" name="repository" required>
|
||||
{% for repository in repositories %}
|
||||
<option value="{{ repository.id }}" data-repository="{{ repository.repository }}" data-architecture="{{ repository.architecture }}">{{ repository.repository }} ({{ repository.architecture }})</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="package-add-input" class="col-sm-4 col-form-label">package</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="package-add-input" type="text" list="known-packages-dlist" autocomplete="off" class="form-control" placeholder="AUR package" name="package" required>
|
||||
<datalist id="package-add-known-packages-dlist"></datalist>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -27,14 +37,19 @@
|
||||
<script>
|
||||
const packageAddModal = $("#package-add-modal");
|
||||
const packageAddForm = $("#package-add-form");
|
||||
packageAddModal.on("shown.bs.modal", () => {
|
||||
$(`#package-add-repository-input option[value="${repository.architecture}-${repository.repository}"]`).prop("selected", true);
|
||||
|
||||
});
|
||||
packageAddModal.on("hidden.bs.modal", () => { packageAddForm.trigger("reset"); });
|
||||
|
||||
const packageInput = $("#package-input");
|
||||
const knownPackagesList = $("#known-packages-dlist");
|
||||
packageInput.keyup(() => {
|
||||
clearTimeout(packageInput.data("timeout"));
|
||||
packageInput.data("timeout", setTimeout($.proxy(() => {
|
||||
const value = packageInput.val();
|
||||
const packageAddInput = $("#package-add-input");
|
||||
const packageAddRepositoryInput = $("#package-add-repository-input");
|
||||
const packageAddKnownPackagesList = $("#package-add-known-packages-dlist");
|
||||
packageAddInput.keyup(() => {
|
||||
clearTimeout(packageAddInput.data("timeout"));
|
||||
packageAddInput.data("timeout", setTimeout($.proxy(() => {
|
||||
const value = packageAddInput.val();
|
||||
|
||||
if (value.length >= 3) {
|
||||
$.ajax({
|
||||
@ -49,7 +64,7 @@
|
||||
option.innerText = `${pkg.package} (${pkg.description})`;
|
||||
return option;
|
||||
});
|
||||
knownPackagesList.empty().append(options);
|
||||
packageAddKnownPackagesList.empty().append(options);
|
||||
},
|
||||
});
|
||||
}
|
||||
@ -57,22 +72,24 @@
|
||||
});
|
||||
|
||||
function packagesAdd() {
|
||||
const packages = packageInput.val();
|
||||
const packages = packageAddInput.val();
|
||||
const repository = getRepositorySelector(packageAddRepositoryInput);
|
||||
if (packages) {
|
||||
packageAddModal.modal("hide");
|
||||
const onSuccess = update => `Packages ${update} have been added`;
|
||||
const onFailure = error => `Package addition failed: ${error}`;
|
||||
doPackageAction("/api/v1/service/add", [packages], onSuccess, onFailure);
|
||||
doPackageAction("/api/v1/service/add", [packages], repository, onSuccess, onFailure);
|
||||
}
|
||||
}
|
||||
|
||||
function packagesRequest() {
|
||||
const packages = packageInput.val();
|
||||
const packages = packageAddInput.val();
|
||||
const repository = getRepositorySelector(packageAddRepositoryInput);
|
||||
if (packages) {
|
||||
packageAddModal.modal("hide");
|
||||
const onSuccess = update => `Packages ${update} have been requested`;
|
||||
const onFailure = error => `Package request failed: ${error}`;
|
||||
doPackageAction("/api/v1/service/request", [packages], onSuccess, onFailure);
|
||||
doPackageAction("/api/v1/service/request", [packages], repository, onSuccess, onFailure);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -6,7 +6,7 @@
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<pre class="language-logs"><samp id="package-info-logs-input" class="pre-scrollable language-logs"></samp><button id="logs-copy-btn" type="button" class="btn language-logs" onclick="copyLogs()"><i class="bi bi-clipboard"></i> copy</button></pre>
|
||||
<pre class="language-logs"><samp id="package-info-logs-input" class="pre-scrollable language-logs"></samp><button id="package-info-logs-copy-button" type="button" class="btn language-logs" onclick="copyLogs()"><i class="bi bi-clipboard"></i> copy</button></pre>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" onclick="showLogs()"><i class="bi bi-arrow-clockwise"></i> reload</button>
|
||||
@ -22,7 +22,7 @@
|
||||
const packageInfo = $("#package-info");
|
||||
|
||||
const packageInfoLogsInput = $("#package-info-logs-input");
|
||||
const packageInfoLogsCopyButton = $("#logs-copy-btn");
|
||||
const packageInfoLogsCopyButton = $("#package-info-logs-copy-button");
|
||||
|
||||
async function copyLogs() {
|
||||
const logs = packageInfoLogsInput.text();
|
||||
@ -45,12 +45,20 @@
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
url: `/api/v1/packages/${packageBase}/logs`,
|
||||
url: `/api/v2/packages/${packageBase}/logs`,
|
||||
data: {
|
||||
architecture: repository.architecture,
|
||||
repository: repository.repository,
|
||||
},
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
success: response => {
|
||||
packageInfo.text(`${response.package_base} ${response.status.status} at ${new Date(1000 * response.status.timestamp).toISOString()}`);
|
||||
packageInfoLogsInput.text(response.logs);
|
||||
const logs = response.logs.map(log_record => {
|
||||
const [timestamp, record] = log_record;
|
||||
return `[${new Date(1000 * timestamp).toISOString()}] ${record}`;
|
||||
});
|
||||
packageInfoLogsInput.text(logs.join("\n"));
|
||||
|
||||
packageInfoModalHeader.removeClass();
|
||||
packageInfoModalHeader.addClass("modal-header");
|
||||
|
@ -8,9 +8,19 @@
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group row">
|
||||
<label for="dependency-input" class="col-sm-4 col-form-label">dependency</label>
|
||||
<label for="package-rebuild-repository-input" class="col-sm-4 col-form-label">repository</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="dependency-input" type="text" class="form-control" placeholder="packages dependency" name="package" required>
|
||||
<select id="package-rebuild-repository-input" class="form-control" name="repository" required>
|
||||
{% for repository in repositories %}
|
||||
<option value="{{ repository.id }}" data-repository="{{ repository.repository }}" data-architecture="{{ repository.architecture }}">{{ repository.repository }} ({{ repository.architecture }})</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="package-rebuild-dependency-input" class="col-sm-4 col-form-label">dependency</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="package-rebuild-dependency-input" type="text" class="form-control" placeholder="packages dependency" name="package" required>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -25,17 +35,23 @@
|
||||
<script>
|
||||
const packageRebuildModal = $("#package-rebuild-modal");
|
||||
const packageRebuildForm = $("#package-rebuild-form");
|
||||
packageRebuildModal.on("shown.bs.modal", () => {
|
||||
$(`#package-rebuild-repository-input option[value="${repository.architecture}-${repository.repository}"]`).prop("selected", true);
|
||||
|
||||
});
|
||||
packageRebuildModal.on("hidden.bs.modal", () => { packageRebuildForm.trigger("reset"); });
|
||||
|
||||
const dependencyInput = $("#dependency-input");
|
||||
const packageRebuildDependencyInput = $("#package-rebuild-dependency-input");
|
||||
const packageRebuildRepositoryInput = $("#package-rebuild-repository-input");
|
||||
|
||||
function packagesRebuild() {
|
||||
const packages = dependencyInput.val();
|
||||
const packages = packageRebuildDependencyInput.val();
|
||||
const repository = getRepositorySelector(packageRebuildRepositoryInput);
|
||||
if (packages) {
|
||||
packageRebuildModal.modal("hide");
|
||||
const onSuccess = update => `Repository rebuild has been run for packages which depend on ${update}`;
|
||||
const onFailure = error => `Repository rebuild failed: ${error}`;
|
||||
doPackageAction("/api/v1/service/rebuild", [packages], onSuccess, onFailure);
|
||||
doPackageAction("/api/v1/service/rebuild", [packages], repository, onSuccess, onFailure);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -1,9 +1,21 @@
|
||||
<script>
|
||||
const keyImportButton = $("#key-import-btn");
|
||||
const packageAddButton = $("#package-add-btn");
|
||||
const packageRebuildButton = $("#package-rebuild-btn");
|
||||
const packageRemoveButton = $("#package-remove-btn");
|
||||
const packageUpdateButton = $("#package-update-btn");
|
||||
const keyImportButton = $("#key-import-button");
|
||||
const packageAddButton = $("#package-add-button");
|
||||
const packageRebuildButton = $("#package-rebuild-button");
|
||||
const packageRemoveButton = $("#package-remove-button");
|
||||
const packageUpdateButton = $("#package-update-button");
|
||||
|
||||
let repository = null;
|
||||
$("#repositories a").on("click", (event) => {
|
||||
const element = event.target;
|
||||
repository = {
|
||||
architecture: element.dataset.architecture,
|
||||
repository: element.dataset.repository,
|
||||
};
|
||||
packageUpdateButton.html(`<i class="bi bi-play"></i> update ${safe(repository.repository)} (${safe(repository.architecture)})`);
|
||||
$(`#${element.id}`).tab("show");
|
||||
reload();
|
||||
});
|
||||
|
||||
const table = $("#packages");
|
||||
table.on("check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table", () => {
|
||||
@ -35,13 +47,17 @@
|
||||
});
|
||||
});
|
||||
|
||||
const repositoryBadge = $("#badge-repository");
|
||||
const statusBadge = $("#badge-status");
|
||||
const versionBadge = $("#badge-version");
|
||||
|
||||
function doPackageAction(uri, packages, successText, failureText) {
|
||||
function doPackageAction(uri, packages, repository, successText, failureText) {
|
||||
const queryParams = $.param({
|
||||
architecture: repository.architecture,
|
||||
repository: repository.repository,
|
||||
}); // it will never be empty btw
|
||||
|
||||
$.ajax({
|
||||
url: uri,
|
||||
url: `${uri}?${queryParams}`,
|
||||
data: JSON.stringify({packages: packages}),
|
||||
type: "POST",
|
||||
contentType: "application/json",
|
||||
@ -62,16 +78,22 @@
|
||||
function removePackages() {
|
||||
const onSuccess = update => `Packages ${update} have been removed`;
|
||||
const onFailure = error => `Could not remove packages: ${error}`;
|
||||
doPackageAction("/api/v1/service/remove", getSelection(), onSuccess, onFailure);
|
||||
doPackageAction("/api/v1/service/remove", getSelection(), repository, onSuccess, onFailure);
|
||||
}
|
||||
|
||||
function selectRepository() {
|
||||
const fragment = window.location.hash.replace("#", "") || "{{ repositories[0].id }}";
|
||||
const element = $(`#${fragment}-lnk`);
|
||||
element.click();
|
||||
}
|
||||
|
||||
function updatePackages() {
|
||||
const currentSelection = getSelection();
|
||||
const [url, onSuccess] = currentSelection.length === 0
|
||||
? ["/api/v1/service/update", _ => "Repository update has been run"]
|
||||
? ["/api/v1/service/update", _ => `Repository update has been run`]
|
||||
: ["/api/v1/service/add", update => `Run update for packages ${update}`];
|
||||
const onFailure = error => `Packages update failed: ${error}`;
|
||||
doPackageAction(url, currentSelection, onSuccess, onFailure);
|
||||
doPackageAction(url, currentSelection, repository, onSuccess, onFailure);
|
||||
}
|
||||
|
||||
function hideControls(hidden) {
|
||||
@ -95,6 +117,10 @@
|
||||
|
||||
$.ajax({
|
||||
url: "/api/v1/packages",
|
||||
data: {
|
||||
architecture: repository.architecture,
|
||||
repository: repository.repository,
|
||||
},
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
success: response => {
|
||||
@ -149,10 +175,13 @@
|
||||
|
||||
$.ajax({
|
||||
url: "/api/v1/status",
|
||||
data: {
|
||||
architecture: repository.architecture,
|
||||
repository: repository.repository,
|
||||
},
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
success: response => {
|
||||
repositoryBadge.text(`${response.repository} ${response.architecture}`);
|
||||
versionBadge.html(`<i class="bi bi-github"></i> ahriman ${safe(response.version)}`);
|
||||
|
||||
statusBadge
|
||||
@ -189,9 +218,17 @@
|
||||
return extractDataList(table.bootstrapTable("getData"), "packager");
|
||||
}
|
||||
|
||||
function getRepositorySelector(selector) {
|
||||
const selected = selector.find(":selected");
|
||||
return {
|
||||
architecture: selected.data("architecture"),
|
||||
repository: selected.data("repository"),
|
||||
};
|
||||
}
|
||||
|
||||
$(() => {
|
||||
table.bootstrapTable({});
|
||||
statusBadge.popover();
|
||||
reload();
|
||||
selectRepository();
|
||||
});
|
||||
</script>
|
@ -7,6 +7,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
{% include "utils/style.jinja2" %}
|
||||
{% include "user-style.jinja2" ignore missing %}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
@ -8,6 +8,7 @@
|
||||
<link rel="shortcut icon" href="/static/favicon.ico">
|
||||
|
||||
{% include "utils/style.jinja2" %}
|
||||
{% include "user-style.jinja2" ignore missing %}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
@ -6,6 +6,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
{% include "utils/style.jinja2" %}
|
||||
{% include "user-style.jinja2" ignore missing %}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@ -73,9 +74,9 @@ SigLevel = Database{% if has_repo_signed %}Required{% else %}Never{% endif %} Pa
|
||||
<td>{{ package.architecture }}</td>
|
||||
<td>{{ package.description }}</td>
|
||||
<td><a href="{{ package.url }}" title="{{ package.name }} upstream url">{{ package.url }}</a></td>
|
||||
<td>{{ package.licenses|join("<br>"|safe) }}</td>
|
||||
<td>{{ package.groups|join("<br>"|safe) }}</td>
|
||||
<td>{{ package.depends|join("<br>"|safe) }}</td>
|
||||
<td>{{ package.licenses | join("<br>" | safe) }}</td>
|
||||
<td>{{ package.groups | join("<br>" | safe) }}</td>
|
||||
<td>{{ package.depends | join("<br>" | safe) }}</td>
|
||||
<td>{{ package.archive_size }}</td>
|
||||
<td>{{ package.installed_size }}</td>
|
||||
<td>{{ package.build_date }}</td>
|
||||
|
70
package/share/ahriman/templates/static/logo.svg
Normal file
70
package/share/ahriman/templates/static/logo.svg
Normal file
@ -0,0 +1,70 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="256.000000pt" height="256.000000pt" viewBox="0 0 256.000000 256.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
|
||||
<g transform="translate(0.000000,256.000000) scale(0.100000,-0.100000)"
|
||||
fill="#000000" stroke="none">
|
||||
<path d="M1019 2546 c-51 -18 -92 -49 -136 -103 -34 -41 -83 -73 -112 -73 -6
|
||||
0 4 22 20 49 17 27 30 54 28 59 -7 17 -153 -102 -176 -143 -13 -23 -30 -40
|
||||
-40 -40 -15 0 -18 9 -18 61 0 49 6 73 33 125 l33 64 -42 -40 c-50 -49 -82 -97
|
||||
-98 -150 -31 -102 -43 -125 -77 -146 -19 -11 -48 -42 -65 -67 -17 -26 -62 -76
|
||||
-100 -112 -69 -66 -69 -66 -69 -120 0 -30 5 -62 10 -70 5 -8 10 -10 10 -4 0 7
|
||||
21 35 46 63 69 77 154 95 154 33 0 -42 -27 -126 -50 -155 l-21 -26 25 -7 c34
|
||||
-8 63 10 86 56 27 53 74 105 127 142 42 29 44 32 38 68 -6 33 -3 40 22 60 25
|
||||
20 36 22 96 17 83 -7 121 5 137 43 7 16 19 31 28 34 10 3 -9 3 -40 1 -65 -6
|
||||
-84 8 -48 37 34 27 118 24 180 -7 57 -29 115 -32 150 -8 l24 17 -24 6 c-14 3
|
||||
-27 14 -28 24 -4 17 1 18 46 13 58 -7 118 -34 147 -67 38 -44 107 -80 149 -80
|
||||
36 1 38 2 21 12 -41 23 -115 108 -115 133 0 13 58 -27 94 -64 42 -43 86 -58
|
||||
133 -46 28 7 28 7 6 18 -13 5 -23 19 -23 29 0 14 6 19 23 16 17 -2 32 -23 62
|
||||
-85 48 -99 63 -115 123 -141 97 -41 101 -40 50 16 -54 60 -80 113 -76 149 l3
|
||||
26 58 -47 c61 -50 87 -89 87 -131 0 -43 27 -93 59 -109 38 -20 37 -21 36 11 0
|
||||
45 24 38 47 -14 19 -41 22 -63 20 -146 -2 -91 0 -103 25 -148 45 -83 54 -83
|
||||
47 2 -6 74 11 155 32 153 20 -2 47 -101 48 -179 1 -65 -3 -88 -22 -122 -24
|
||||
-46 -28 -98 -10 -138 14 -30 24 -32 31 -5 8 30 37 25 37 -6 0 -53 -23 -113
|
||||
-62 -160 -52 -63 -58 -81 -58 -167 l0 -72 35 65 c40 75 98 135 103 107 4 -19
|
||||
-37 -114 -69 -158 -11 -16 -49 -46 -85 -66 -64 -37 -94 -76 -94 -122 0 -20 1
|
||||
-21 24 -6 19 13 25 13 35 2 17 -21 -15 -43 -73 -51 -85 -11 -126 -26 -164 -61
|
||||
-35 -31 -80 -95 -67 -95 3 0 29 12 57 26 52 26 168 45 168 28 0 -12 -92 -91
|
||||
-123 -105 -20 -9 -34 -8 -71 6 -52 20 -104 14 -130 -14 -17 -19 -17 -20 6 -23
|
||||
12 -2 24 -11 26 -20 4 -22 -37 -23 -189 -7 -99 11 -104 10 -151 -12 -26 -13
|
||||
-48 -27 -48 -30 0 -3 25 -16 55 -28 30 -13 55 -26 55 -31 0 -8 -73 -20 -119
|
||||
-20 -44 0 -99 20 -130 46 -37 31 -87 46 -124 38 l-27 -6 22 -18 c16 -13 20
|
||||
-22 12 -29 -18 -19 -125 42 -174 100 -45 53 -95 82 -165 95 l-40 7 52 -41 c96
|
||||
-76 114 -128 31 -86 -105 52 -120 69 -147 172 -9 31 -21 48 -44 62 -41 25 -61
|
||||
26 -49 2 5 -9 7 -23 5 -29 -10 -27 -32 -11 -57 39 -21 43 -26 66 -26 132 0 71
|
||||
-4 87 -29 131 -32 55 -80 106 -67 71 21 -58 18 -206 -4 -206 -5 0 -30 43 -56
|
||||
95 l-48 96 17 47 c21 57 21 89 2 122 -14 25 -14 25 -15 3 0 -14 -6 -23 -16
|
||||
-23 -14 0 -16 8 -10 53 4 28 18 70 31 92 14 22 31 55 40 73 18 37 32 152 19
|
||||
152 -5 0 -17 -21 -28 -46 -18 -45 -61 -104 -75 -104 -4 0 -4 32 0 72 6 55 16
|
||||
83 40 122 24 37 34 66 37 108 6 75 -1 91 -22 51 -16 -32 -48 -44 -61 -23 -8
|
||||
12 22 69 40 76 19 8 41 43 65 105 l21 52 -29 -29 c-16 -16 -48 -40 -71 -54
|
||||
-23 -14 -56 -45 -72 -69 -28 -43 -29 -47 -29 -175 0 -186 -12 -220 -43 -122
|
||||
-10 29 -15 62 -11 72 4 14 -2 11 -20 -9 -31 -33 -33 -65 -7 -115 21 -40 38
|
||||
-112 27 -112 -16 0 -58 35 -71 59 l-14 26 -1 -37 c0 -24 13 -63 36 -108 39
|
||||
-76 51 -155 24 -155 -8 0 -20 16 -27 35 l-11 35 -7 -29 c-11 -40 11 -127 43
|
||||
-175 15 -22 56 -72 90 -111 70 -78 66 -86 -28 -51 -71 27 -60 7 30 -54 71 -48
|
||||
106 -93 86 -112 -4 -4 -46 12 -93 37 -110 58 -109 58 -87 20 29 -49 70 -81
|
||||
188 -145 114 -63 148 -94 126 -120 -13 -16 -52 -6 -82 22 -28 25 -21 0 11 -44
|
||||
45 -63 100 -83 259 -99 154 -15 221 -29 272 -54 l35 -18 -35 -6 c-56 -10 -164
|
||||
-26 -175 -26 -5 -1 15 -10 45 -21 62 -23 124 -27 255 -15 72 6 94 5 109 -7 28
|
||||
-21 11 -37 -42 -38 l-47 -1 40 -19 c63 -31 153 -22 244 25 80 41 166 66 224
|
||||
66 l38 0 -26 -35 c-15 -19 -48 -48 -73 -66 l-47 -31 72 4 c71 4 72 4 130 59
|
||||
66 64 104 86 160 95 27 4 42 2 50 -8 16 -19 4 -34 -43 -58 l-39 -19 54 -1 c71
|
||||
0 129 28 181 88 22 26 68 80 102 120 35 41 74 89 87 108 13 19 26 33 28 31 2
|
||||
-2 -3 -46 -12 -98 -20 -128 -20 -128 26 -73 52 63 64 91 83 196 18 108 39 150
|
||||
69 146 23 -3 27 -20 14 -70 -11 -42 18 -25 49 28 34 58 41 139 20 222 -21 84
|
||||
-21 83 19 172 19 43 38 99 41 125 l7 46 38 -68 39 -68 0 88 c0 80 -3 93 -35
|
||||
157 -41 80 -47 140 -15 140 11 0 26 -12 34 -27 15 -27 15 -27 16 35 0 54 -4
|
||||
70 -29 105 -16 23 -49 57 -74 76 -56 42 -111 153 -122 248 l-7 63 58 -26 c32
|
||||
-14 71 -35 86 -45 40 -29 35 -10 -18 60 -34 45 -65 72 -117 103 -118 69 -153
|
||||
102 -141 132 9 22 25 20 68 -9 42 -28 43 -26 14 26 -36 65 -136 119 -217 119
|
||||
-48 0 -233 88 -211 100 8 4 44 11 80 14 129 14 130 15 58 47 -62 29 -64 29
|
||||
-198 23 -121 -6 -138 -5 -153 11 -25 24 -6 43 46 47 l42 3 -35 20 c-25 13 -53
|
||||
19 -98 19 -54 0 -74 -6 -143 -42 -76 -39 -139 -54 -139 -33 0 6 45 32 100 60
|
||||
l99 50 -55 7 c-76 9 -111 2 -214 -46 -99 -46 -155 -51 -155 -15 0 14 12 24 44
|
||||
36 40 14 42 16 20 22 -37 10 -80 8 -120 -7z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.7 KiB |
@ -59,7 +59,7 @@
|
||||
const [minDate, maxDate] = text.split(" - ");
|
||||
const buildDate = asOfStartOfDay(new Date(value));
|
||||
|
||||
return (buildDate >= asOfStartOfDay(new Date(minDate))) && (buildDate <= asOfStartOfDay(new Date(maxDate)));
|
||||
return (buildDate >= new Date(minDate)) && (buildDate <= new Date(maxDate));
|
||||
}
|
||||
|
||||
function filterList(index, value, field, data) {
|
||||
|
@ -1,8 +1,8 @@
|
||||
# AUTOMATICALLY GENERATED by `shtab`
|
||||
|
||||
_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-create-keyring' 'repo-create-mirrorlist' '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_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-create-keyring' 'repo-create-mirrorlist' '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-repositories' 'service-setup' 'init' 'repo-init' 'repo-setup' 'setup' 'service-shell' 'shell' 'service-tree-migrate' 'user-add' 'user-list' 'user-remove' 'web')
|
||||
|
||||
_shtab_ahriman_option_strings=('-h' '--help' '-a' '--architecture' '-c' '--configuration' '--force' '-l' '--lock' '--log-handler' '--report' '--no-report' '-q' '--quiet' '--unsafe' '--wait-timeout' '-V' '--version')
|
||||
_shtab_ahriman_option_strings=('-h' '--help' '-a' '--architecture' '-c' '--configuration' '--force' '-l' '--lock' '--log-handler' '-q' '--quiet' '--report' '--no-report' '-r' '--repository' '--unsafe' '--wait-timeout' '-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_help_option_strings=('-h' '--help')
|
||||
@ -50,29 +50,31 @@ _shtab_ahriman_update_option_strings=('-h' '--help' '--aur' '--no-aur' '--depend
|
||||
_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_option_strings=('-h' '--help' '--info' '--no-info' '--secure' '--no-secure')
|
||||
_shtab_ahriman_config_option_strings=('-h' '--help' '--info' '--no-info' '--secure' '--no-secure')
|
||||
_shtab_ahriman_repo_config_option_strings=('-h' '--help' '--info' '--no-info' '--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' '--generate-salt' '--no-generate-salt' '--makeflags-jobs' '--no-makeflags-jobs' '--mirror' '--multilib' '--no-multilib' '--packager' '--repository' '--server' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket')
|
||||
_shtab_ahriman_init_option_strings=('-h' '--help' '--build-as-user' '--build-command' '--from-configuration' '--generate-salt' '--no-generate-salt' '--makeflags-jobs' '--no-makeflags-jobs' '--mirror' '--multilib' '--no-multilib' '--packager' '--repository' '--server' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket')
|
||||
_shtab_ahriman_repo_init_option_strings=('-h' '--help' '--build-as-user' '--build-command' '--from-configuration' '--generate-salt' '--no-generate-salt' '--makeflags-jobs' '--no-makeflags-jobs' '--mirror' '--multilib' '--no-multilib' '--packager' '--repository' '--server' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket')
|
||||
_shtab_ahriman_repo_setup_option_strings=('-h' '--help' '--build-as-user' '--build-command' '--from-configuration' '--generate-salt' '--no-generate-salt' '--makeflags-jobs' '--no-makeflags-jobs' '--mirror' '--multilib' '--no-multilib' '--packager' '--repository' '--server' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket')
|
||||
_shtab_ahriman_setup_option_strings=('-h' '--help' '--build-as-user' '--build-command' '--from-configuration' '--generate-salt' '--no-generate-salt' '--makeflags-jobs' '--no-makeflags-jobs' '--mirror' '--multilib' '--no-multilib' '--packager' '--repository' '--server' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket')
|
||||
_shtab_ahriman_service_repositories_option_strings=('-h' '--help' '--id-only' '--no-id-only')
|
||||
_shtab_ahriman_service_setup_option_strings=('-h' '--help' '--build-as-user' '--from-configuration' '--generate-salt' '--no-generate-salt' '--makeflags-jobs' '--no-makeflags-jobs' '--mirror' '--multilib' '--no-multilib' '--packager' '--server' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket')
|
||||
_shtab_ahriman_init_option_strings=('-h' '--help' '--build-as-user' '--from-configuration' '--generate-salt' '--no-generate-salt' '--makeflags-jobs' '--no-makeflags-jobs' '--mirror' '--multilib' '--no-multilib' '--packager' '--server' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket')
|
||||
_shtab_ahriman_repo_init_option_strings=('-h' '--help' '--build-as-user' '--from-configuration' '--generate-salt' '--no-generate-salt' '--makeflags-jobs' '--no-makeflags-jobs' '--mirror' '--multilib' '--no-multilib' '--packager' '--server' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket')
|
||||
_shtab_ahriman_repo_setup_option_strings=('-h' '--help' '--build-as-user' '--from-configuration' '--generate-salt' '--no-generate-salt' '--makeflags-jobs' '--no-makeflags-jobs' '--mirror' '--multilib' '--no-multilib' '--packager' '--server' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket')
|
||||
_shtab_ahriman_setup_option_strings=('-h' '--help' '--build-as-user' '--from-configuration' '--generate-salt' '--no-generate-salt' '--makeflags-jobs' '--no-makeflags-jobs' '--mirror' '--multilib' '--no-multilib' '--packager' '--server' '--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' '--key' '--packager' '-p' '--password' '-r' '--role')
|
||||
_shtab_ahriman_user_list_option_strings=('-h' '--help' '-e' '--exit-code' '-r' '--role')
|
||||
_shtab_ahriman_service_tree_migrate_option_strings=('-h' '--help')
|
||||
_shtab_ahriman_user_add_option_strings=('-h' '--help' '--key' '--packager' '-p' '--password' '-R' '--role')
|
||||
_shtab_ahriman_user_list_option_strings=('-h' '--help' '-e' '--exit-code' '-R' '--role')
|
||||
_shtab_ahriman_user_remove_option_strings=('-h' '--help')
|
||||
_shtab_ahriman_web_option_strings=('-h' '--help')
|
||||
|
||||
|
||||
|
||||
_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-create-keyring' 'repo-create-mirrorlist' '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_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-create-keyring' 'repo-create-mirrorlist' '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-repositories' 'service-setup' 'init' 'repo-init' 'repo-setup' 'setup' 'service-shell' 'shell' 'service-tree-migrate' 'user-add' 'user-list' 'user-remove' 'web')
|
||||
_shtab_ahriman___log_handler_choices=('console' 'syslog' 'journald')
|
||||
_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')
|
||||
@ -101,19 +103,19 @@ _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__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')
|
||||
_shtab_ahriman_user_list__R_choices=('unauthorized' 'read' 'reporter' 'full')
|
||||
_shtab_ahriman_user_list___role_choices=('unauthorized' 'read' 'reporter' 'full')
|
||||
|
||||
_shtab_ahriman_pos_0_nargs=A...
|
||||
_shtab_ahriman__h_nargs=0
|
||||
_shtab_ahriman___help_nargs=0
|
||||
_shtab_ahriman___force_nargs=0
|
||||
_shtab_ahriman___report_nargs=0
|
||||
_shtab_ahriman___no_report_nargs=0
|
||||
_shtab_ahriman__q_nargs=0
|
||||
_shtab_ahriman___quiet_nargs=0
|
||||
_shtab_ahriman___report_nargs=0
|
||||
_shtab_ahriman___no_report_nargs=0
|
||||
_shtab_ahriman___unsafe_nargs=0
|
||||
_shtab_ahriman__V_nargs=0
|
||||
_shtab_ahriman___version_nargs=0
|
||||
@ -399,14 +401,20 @@ _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___info_nargs=0
|
||||
_shtab_ahriman_service_config___no_info_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___info_nargs=0
|
||||
_shtab_ahriman_config___no_info_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___info_nargs=0
|
||||
_shtab_ahriman_repo_config___no_info_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
|
||||
@ -425,6 +433,10 @@ _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_repositories__h_nargs=0
|
||||
_shtab_ahriman_service_repositories___help_nargs=0
|
||||
_shtab_ahriman_service_repositories___id_only_nargs=0
|
||||
_shtab_ahriman_service_repositories___no_id_only_nargs=0
|
||||
_shtab_ahriman_service_setup__h_nargs=0
|
||||
_shtab_ahriman_service_setup___help_nargs=0
|
||||
_shtab_ahriman_service_setup___generate_salt_nargs=0
|
||||
@ -473,6 +485,8 @@ _shtab_ahriman_shell__h_nargs=0
|
||||
_shtab_ahriman_shell___help_nargs=0
|
||||
_shtab_ahriman_shell__v_nargs=0
|
||||
_shtab_ahriman_shell___verbose_nargs=0
|
||||
_shtab_ahriman_service_tree_migrate__h_nargs=0
|
||||
_shtab_ahriman_service_tree_migrate___help_nargs=0
|
||||
_shtab_ahriman_user_add__h_nargs=0
|
||||
_shtab_ahriman_user_add___help_nargs=0
|
||||
_shtab_ahriman_user_list__h_nargs=0
|
||||
|
@ -1,16 +1,16 @@
|
||||
.TH AHRIMAN "1" "2023\-08\-26" "ahriman" "Generated Python Manual"
|
||||
.TH AHRIMAN "1" "2023\-10\-09" "ahriman" "Generated Python Manual"
|
||||
.SH NAME
|
||||
ahriman
|
||||
.SH SYNOPSIS
|
||||
.B ahriman
|
||||
[-h] [-a ARCHITECTURE] [-c CONFIGURATION] [--force] [-l LOCK] [--log-handler {console,syslog,journald}] [--report | --no-report] [-q] [--unsafe] [--wait-timeout WAIT_TIMEOUT] [-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-create-keyring,repo-create-mirrorlist,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} ...
|
||||
[-h] [-a ARCHITECTURE] [-c CONFIGURATION] [--force] [-l LOCK] [--log-handler {console,syslog,journald}] [-q] [--report | --no-report] [-r REPOSITORY] [--unsafe] [--wait-timeout WAIT_TIMEOUT] [-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-create-keyring,repo-create-mirrorlist,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-repositories,service-setup,init,repo-init,repo-setup,setup,service-shell,shell,service-tree-migrate,user-add,user-list,user-remove,web} ...
|
||||
.SH DESCRIPTION
|
||||
ArcH linux ReposItory MANager
|
||||
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
\fB\-a\fR \fI\,ARCHITECTURE\/\fR, \fB\-\-architecture\fR \fI\,ARCHITECTURE\/\fR
|
||||
target architectures. For several subcommands it can be used multiple times
|
||||
filter by target architecture
|
||||
|
||||
.TP
|
||||
\fB\-c\fR \fI\,CONFIGURATION\/\fR, \fB\-\-configuration\fR \fI\,CONFIGURATION\/\fR
|
||||
@ -28,13 +28,17 @@ lock file
|
||||
\fB\-\-log\-handler\fR \fI\,{console,syslog,journald}\/\fR
|
||||
explicit log handler specification. If none set, the handler will be guessed from environment
|
||||
|
||||
.TP
|
||||
\fB\-q\fR, \fB\-\-quiet\fR
|
||||
force disable any logging
|
||||
|
||||
.TP
|
||||
\fB\-\-report\fR, \fB\-\-no\-report\fR
|
||||
force enable or disable reporting to web service
|
||||
|
||||
.TP
|
||||
\fB\-q\fR, \fB\-\-quiet\fR
|
||||
force disable any logging
|
||||
\fB\-r\fR \fI\,REPOSITORY\/\fR, \fB\-\-repository\fR \fI\,REPOSITORY\/\fR
|
||||
filter by target repository
|
||||
|
||||
.TP
|
||||
\fB\-\-unsafe\fR
|
||||
@ -151,12 +155,18 @@ validate system configuration
|
||||
\fBahriman\fR \fI\,service\-key\-import\/\fR
|
||||
import PGP key
|
||||
.TP
|
||||
\fBahriman\fR \fI\,service\-repositories\/\fR
|
||||
show repositories
|
||||
.TP
|
||||
\fBahriman\fR \fI\,service\-setup\/\fR
|
||||
initial service configuration
|
||||
.TP
|
||||
\fBahriman\fR \fI\,service\-shell\/\fR
|
||||
invoke python shell
|
||||
.TP
|
||||
\fBahriman\fR \fI\,service\-tree\-migrate\/\fR
|
||||
migrate repository tree
|
||||
.TP
|
||||
\fBahriman\fR \fI\,user\-add\/\fR
|
||||
create or update user
|
||||
.TP
|
||||
@ -657,11 +667,23 @@ clear directory with built packages
|
||||
clear directory with pacman local database cache
|
||||
|
||||
.SH COMMAND \fI\,'ahriman service\-config'\/\fR
|
||||
usage: ahriman service\-config [\-h] [\-\-secure | \-\-no\-secure]
|
||||
usage: ahriman service\-config [\-h] [\-\-info | \-\-no\-info] [\-\-secure | \-\-no\-secure] [section] [key]
|
||||
|
||||
dump configuration for the specified architecture
|
||||
|
||||
.TP
|
||||
\fBsection\fR
|
||||
filter settings by section
|
||||
|
||||
.TP
|
||||
\fBkey\fR
|
||||
filter settings by key
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman service\-config'\/\fR
|
||||
.TP
|
||||
\fB\-\-info\fR, \fB\-\-no\-info\fR
|
||||
show additional information, e.g. configuration files
|
||||
|
||||
.TP
|
||||
\fB\-\-secure\fR, \fB\-\-no\-secure\fR
|
||||
hide passwords and secrets from output
|
||||
@ -690,12 +712,21 @@ PGP key to import from public server
|
||||
\fB\-\-key\-server\fR \fI\,KEY_SERVER\/\fR
|
||||
key server for key import
|
||||
|
||||
.SH COMMAND \fI\,'ahriman service\-repositories'\/\fR
|
||||
usage: ahriman service\-repositories [\-h] [\-\-id\-only | \-\-no\-id\-only]
|
||||
|
||||
list all available repositories
|
||||
|
||||
.SH OPTIONS \fI\,'ahriman service\-repositories'\/\fR
|
||||
.TP
|
||||
\fB\-\-id\-only\fR, \fB\-\-no\-id\-only\fR
|
||||
show machine readable identifier instead
|
||||
|
||||
.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] [\-\-generate\-salt | \-\-no\-generate\-salt]
|
||||
[\-\-makeflags\-jobs | \-\-no\-makeflags\-jobs] [\-\-mirror MIRROR] [\-\-multilib | \-\-no\-multilib]
|
||||
\-\-packager PACKAGER \-\-repository REPOSITORY [\-\-server SERVER] [\-\-sign\-key SIGN_KEY]
|
||||
[\-\-sign\-target {disabled,packages,repository}] [\-\-web\-port WEB_PORT]
|
||||
usage: ahriman service\-setup [\-h] [\-\-build\-as\-user BUILD_AS_USER] [\-\-from\-configuration FROM_CONFIGURATION]
|
||||
[\-\-generate\-salt | \-\-no\-generate\-salt] [\-\-makeflags\-jobs | \-\-no\-makeflags\-jobs]
|
||||
[\-\-mirror MIRROR] [\-\-multilib | \-\-no\-multilib] \-\-packager PACKAGER [\-\-server SERVER]
|
||||
[\-\-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
|
||||
@ -705,10 +736,6 @@ create initial service configuration, requires root
|
||||
\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
|
||||
@ -733,10 +760,6 @@ add or do not multilib repository
|
||||
\fB\-\-packager\fR \fI\,PACKAGER\/\fR
|
||||
packager name and email
|
||||
|
||||
.TP
|
||||
\fB\-\-repository\fR \fI\,REPOSITORY\/\fR
|
||||
repository name
|
||||
|
||||
.TP
|
||||
\fB\-\-server\fR \fI\,SERVER\/\fR
|
||||
server to be used for devtools. If none set, local files will be used
|
||||
@ -766,8 +789,13 @@ drop into python shell
|
||||
\fBcode\fR
|
||||
instead of dropping into shell, just execute the specified code
|
||||
|
||||
.SH COMMAND \fI\,'ahriman service\-tree\-migrate'\/\fR
|
||||
usage: ahriman service\-tree\-migrate [\-h]
|
||||
|
||||
migrate repository tree between versions
|
||||
|
||||
.SH COMMAND \fI\,'ahriman user\-add'\/\fR
|
||||
usage: ahriman user\-add [\-h] [\-\-key KEY] [\-\-packager PACKAGER] [\-p PASSWORD] [\-r {unauthorized,read,reporter,full}]
|
||||
usage: ahriman user\-add [\-h] [\-\-key KEY] [\-\-packager PACKAGER] [\-p PASSWORD] [\-R {unauthorized,read,reporter,full}]
|
||||
username
|
||||
|
||||
update user for web services with the given password and role. In case if password was not entered it will be asked interactively
|
||||
@ -791,11 +819,11 @@ user password. Blank password will be treated as empty password, which is in par
|
||||
authorization type.
|
||||
|
||||
.TP
|
||||
\fB\-r\fR \fI\,{unauthorized,read,reporter,full}\/\fR, \fB\-\-role\fR \fI\,{unauthorized,read,reporter,full}\/\fR
|
||||
\fB\-R\fR \fI\,{unauthorized,read,reporter,full}\/\fR, \fB\-\-role\fR \fI\,{unauthorized,read,reporter,full}\/\fR
|
||||
user access level
|
||||
|
||||
.SH COMMAND \fI\,'ahriman user\-list'\/\fR
|
||||
usage: ahriman user\-list [\-h] [\-e] [\-r {unauthorized,read,reporter,full}] [username]
|
||||
usage: ahriman user\-list [\-h] [\-e] [\-R {unauthorized,read,reporter,full}] [username]
|
||||
|
||||
list users from the user mapping and their roles
|
||||
|
||||
@ -809,7 +837,7 @@ filter users by username
|
||||
return non\-zero exit status if result is empty
|
||||
|
||||
.TP
|
||||
\fB\-r\fR \fI\,{unauthorized,read,reporter,full}\/\fR, \fB\-\-role\fR \fI\,{unauthorized,read,reporter,full}\/\fR
|
||||
\fB\-R\fR \fI\,{unauthorized,read,reporter,full}\/\fR, \fB\-\-role\fR \fI\,{unauthorized,read,reporter,full}\/\fR
|
||||
filter users by role
|
||||
|
||||
.SH COMMAND \fI\,'ahriman user\-remove'\/\fR
|
||||
|
@ -57,8 +57,10 @@ _shtab_ahriman_commands() {
|
||||
"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-repositories:list all available repositories"
|
||||
"service-setup:create initial service configuration, requires root"
|
||||
"service-shell:drop into python shell"
|
||||
"service-tree-migrate:migrate repository tree between versions"
|
||||
"setup:create initial service configuration, requires root"
|
||||
"shell:drop into python shell"
|
||||
"sign:(re-)sign packages and repository database according to current settings"
|
||||
@ -77,13 +79,14 @@ _shtab_ahriman_commands() {
|
||||
|
||||
_shtab_ahriman_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"*"{-a,--architecture}"[target architectures. For several subcommands it can be used multiple times (default\: None)]:architecture:"
|
||||
{-a,--architecture}"[filter by target architecture (default\: None)]:architecture:"
|
||||
{-c,--configuration}"[configuration path (default\: \/etc\/ahriman.ini)]:configuration:"
|
||||
"--force[force run, remove file lock (default\: False)]"
|
||||
{-l,--lock}"[lock file (default\: \/tmp\/ahriman.lock)]:lock:"
|
||||
"--log-handler[explicit log handler specification. If none set, the handler will be guessed from environment (default\: None)]:log_handler:(console syslog journald)"
|
||||
{--report,--no-report}"[force enable or disable reporting to web service (default\: True)]:report:"
|
||||
{-q,--quiet}"[force disable any logging (default\: False)]"
|
||||
{--report,--no-report}"[force enable or disable reporting to web service (default\: True)]:report:"
|
||||
{-r,--repository}"[filter by target repository (default\: None)]:repository:"
|
||||
"--unsafe[allow to run ahriman as non-ahriman user. Some actions might be unavailable (default\: False)]"
|
||||
"--wait-timeout[wait for lock to be free. Negative value will lead to immediate application run even if there is lock file. In case of zero value, the application will wait infinitely (default\: -1)]:wait_timeout:"
|
||||
"(- : *)"{-V,--version}"[show program\'s version number and exit]"
|
||||
@ -128,7 +131,10 @@ _shtab_ahriman_clean_options=(
|
||||
|
||||
_shtab_ahriman_config_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{--info,--no-info}"[show additional information, e.g. configuration files (default\: True)]:info:"
|
||||
{--secure,--no-secure}"[hide passwords and secrets from output (default\: True)]:secure:"
|
||||
":filter settings by section (default\: None):"
|
||||
":filter settings by key (default\: None):"
|
||||
)
|
||||
|
||||
_shtab_ahriman_config_validate_options=(
|
||||
@ -169,14 +175,12 @@ _shtab_ahriman_help_version_options=(
|
||||
_shtab_ahriman_init_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"--build-as-user[force makepkg user to the specific one (default\: None)]:build_as_user:"
|
||||
"--build-command[build command prefix (default\: ahriman)]:build_command:"
|
||||
"--from-configuration[path to default devtools pacman configuration (default\: \/usr\/share\/devtools\/pacman.conf.d\/extra.conf)]:from_configuration:"
|
||||
{--generate-salt,--no-generate-salt}"[generate salt for user passwords (default\: False)]:generate_salt:"
|
||||
{--makeflags-jobs,--no-makeflags-jobs}"[append MAKEFLAGS variable with parallelism set to number of cores (default\: True)]:makeflags_jobs:"
|
||||
"--mirror[use the specified explicitly mirror instead of including mirrorlist (default\: None)]:mirror:"
|
||||
{--multilib,--no-multilib}"[add or do not multilib repository (default\: True)]:multilib:"
|
||||
"--packager[packager name and email (default\: None)]:packager:"
|
||||
"--repository[repository name (default\: None)]:repository:"
|
||||
"--server[server to be used for devtools. If none set, local files will be used (default\: None)]:server:"
|
||||
"--sign-key[sign key id (default\: None)]:sign_key:"
|
||||
"*--sign-target[sign options (default\: None)]:sign_target:(disabled packages repository)"
|
||||
@ -310,7 +314,10 @@ _shtab_ahriman_repo_clean_options=(
|
||||
|
||||
_shtab_ahriman_repo_config_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{--info,--no-info}"[show additional information, e.g. configuration files (default\: True)]:info:"
|
||||
{--secure,--no-secure}"[hide passwords and secrets from output (default\: True)]:secure:"
|
||||
":filter settings by section (default\: None):"
|
||||
":filter settings by key (default\: None):"
|
||||
)
|
||||
|
||||
_shtab_ahriman_repo_config_validate_options=(
|
||||
@ -340,14 +347,12 @@ _shtab_ahriman_repo_daemon_options=(
|
||||
_shtab_ahriman_repo_init_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"--build-as-user[force makepkg user to the specific one (default\: None)]:build_as_user:"
|
||||
"--build-command[build command prefix (default\: ahriman)]:build_command:"
|
||||
"--from-configuration[path to default devtools pacman configuration (default\: \/usr\/share\/devtools\/pacman.conf.d\/extra.conf)]:from_configuration:"
|
||||
{--generate-salt,--no-generate-salt}"[generate salt for user passwords (default\: False)]:generate_salt:"
|
||||
{--makeflags-jobs,--no-makeflags-jobs}"[append MAKEFLAGS variable with parallelism set to number of cores (default\: True)]:makeflags_jobs:"
|
||||
"--mirror[use the specified explicitly mirror instead of including mirrorlist (default\: None)]:mirror:"
|
||||
{--multilib,--no-multilib}"[add or do not multilib repository (default\: True)]:multilib:"
|
||||
"--packager[packager name and email (default\: None)]:packager:"
|
||||
"--repository[repository name (default\: None)]:repository:"
|
||||
"--server[server to be used for devtools. If none set, local files will be used (default\: None)]:server:"
|
||||
"--sign-key[sign key id (default\: None)]:sign_key:"
|
||||
"*--sign-target[sign options (default\: None)]:sign_target:(disabled packages repository)"
|
||||
@ -384,14 +389,12 @@ _shtab_ahriman_repo_restore_options=(
|
||||
_shtab_ahriman_repo_setup_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"--build-as-user[force makepkg user to the specific one (default\: None)]:build_as_user:"
|
||||
"--build-command[build command prefix (default\: ahriman)]:build_command:"
|
||||
"--from-configuration[path to default devtools pacman configuration (default\: \/usr\/share\/devtools\/pacman.conf.d\/extra.conf)]:from_configuration:"
|
||||
{--generate-salt,--no-generate-salt}"[generate salt for user passwords (default\: False)]:generate_salt:"
|
||||
{--makeflags-jobs,--no-makeflags-jobs}"[append MAKEFLAGS variable with parallelism set to number of cores (default\: True)]:makeflags_jobs:"
|
||||
"--mirror[use the specified explicitly mirror instead of including mirrorlist (default\: None)]:mirror:"
|
||||
{--multilib,--no-multilib}"[add or do not multilib repository (default\: True)]:multilib:"
|
||||
"--packager[packager name and email (default\: None)]:packager:"
|
||||
"--repository[repository name (default\: None)]:repository:"
|
||||
"--server[server to be used for devtools. If none set, local files will be used (default\: None)]:server:"
|
||||
"--sign-key[sign key id (default\: None)]:sign_key:"
|
||||
"*--sign-target[sign options (default\: None)]:sign_target:(disabled packages repository)"
|
||||
@ -461,7 +464,10 @@ _shtab_ahriman_service_clean_options=(
|
||||
|
||||
_shtab_ahriman_service_config_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{--info,--no-info}"[show additional information, e.g. configuration files (default\: True)]:info:"
|
||||
{--secure,--no-secure}"[hide passwords and secrets from output (default\: True)]:secure:"
|
||||
":filter settings by section (default\: None):"
|
||||
":filter settings by key (default\: None):"
|
||||
)
|
||||
|
||||
_shtab_ahriman_service_config_validate_options=(
|
||||
@ -475,17 +481,20 @@ _shtab_ahriman_service_key_import_options=(
|
||||
":PGP key to import from public server:"
|
||||
)
|
||||
|
||||
_shtab_ahriman_service_repositories_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{--id-only,--no-id-only}"[show machine readable identifier instead (default\: False)]:id_only:"
|
||||
)
|
||||
|
||||
_shtab_ahriman_service_setup_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"--build-as-user[force makepkg user to the specific one (default\: None)]:build_as_user:"
|
||||
"--build-command[build command prefix (default\: ahriman)]:build_command:"
|
||||
"--from-configuration[path to default devtools pacman configuration (default\: \/usr\/share\/devtools\/pacman.conf.d\/extra.conf)]:from_configuration:"
|
||||
{--generate-salt,--no-generate-salt}"[generate salt for user passwords (default\: False)]:generate_salt:"
|
||||
{--makeflags-jobs,--no-makeflags-jobs}"[append MAKEFLAGS variable with parallelism set to number of cores (default\: True)]:makeflags_jobs:"
|
||||
"--mirror[use the specified explicitly mirror instead of including mirrorlist (default\: None)]:mirror:"
|
||||
{--multilib,--no-multilib}"[add or do not multilib repository (default\: True)]:multilib:"
|
||||
"--packager[packager name and email (default\: None)]:packager:"
|
||||
"--repository[repository name (default\: None)]:repository:"
|
||||
"--server[server to be used for devtools. If none set, local files will be used (default\: None)]:server:"
|
||||
"--sign-key[sign key id (default\: None)]:sign_key:"
|
||||
"*--sign-target[sign options (default\: None)]:sign_target:(disabled packages repository)"
|
||||
@ -498,17 +507,19 @@ _shtab_ahriman_service_shell_options=(
|
||||
":instead of dropping into shell, just execute the specified code (default\: None):"
|
||||
)
|
||||
|
||||
_shtab_ahriman_service_tree_migrate_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
)
|
||||
|
||||
_shtab_ahriman_setup_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
"--build-as-user[force makepkg user to the specific one (default\: None)]:build_as_user:"
|
||||
"--build-command[build command prefix (default\: ahriman)]:build_command:"
|
||||
"--from-configuration[path to default devtools pacman configuration (default\: \/usr\/share\/devtools\/pacman.conf.d\/extra.conf)]:from_configuration:"
|
||||
{--generate-salt,--no-generate-salt}"[generate salt for user passwords (default\: False)]:generate_salt:"
|
||||
{--makeflags-jobs,--no-makeflags-jobs}"[append MAKEFLAGS variable with parallelism set to number of cores (default\: True)]:makeflags_jobs:"
|
||||
"--mirror[use the specified explicitly mirror instead of including mirrorlist (default\: None)]:mirror:"
|
||||
{--multilib,--no-multilib}"[add or do not multilib repository (default\: True)]:multilib:"
|
||||
"--packager[packager name and email (default\: None)]:packager:"
|
||||
"--repository[repository name (default\: None)]:repository:"
|
||||
"--server[server to be used for devtools. If none set, local files will be used (default\: None)]:server:"
|
||||
"--sign-key[sign key id (default\: None)]:sign_key:"
|
||||
"*--sign-target[sign options (default\: None)]:sign_target:(disabled packages repository)"
|
||||
@ -565,14 +576,14 @@ _shtab_ahriman_user_add_options=(
|
||||
"--key[optional PGP key used by this user. The private key must be imported (default\: None)]:key:"
|
||||
"--packager[optional packager id used for build process in form of \`Name Surname \<mail\@example.com\>\` (default\: None)]:packager:"
|
||||
{-p,--password}"[user password. Blank password will be treated as empty password, which is in particular must be used for OAuth2 authorization type. (default\: None)]:password:"
|
||||
{-r,--role}"[user access level (default\: UserAccess.Read)]:role:(unauthorized read reporter full)"
|
||||
{-R,--role}"[user access level (default\: UserAccess.Read)]:role:(unauthorized read reporter full)"
|
||||
":username for web service:"
|
||||
)
|
||||
|
||||
_shtab_ahriman_user_list_options=(
|
||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||
{-e,--exit-code}"[return non-zero exit status if result is empty (default\: False)]"
|
||||
{-r,--role}"[filter users by role (default\: None)]:role:(unauthorized read reporter full)"
|
||||
{-R,--role}"[filter users by role (default\: None)]:role:(unauthorized read reporter full)"
|
||||
":filter users by username (default\: None):"
|
||||
)
|
||||
|
||||
@ -656,8 +667,10 @@ _shtab_ahriman() {
|
||||
service-config) _arguments -C -s $_shtab_ahriman_service_config_options ;;
|
||||
service-config-validate) _arguments -C -s $_shtab_ahriman_service_config_validate_options ;;
|
||||
service-key-import) _arguments -C -s $_shtab_ahriman_service_key_import_options ;;
|
||||
service-repositories) _arguments -C -s $_shtab_ahriman_service_repositories_options ;;
|
||||
service-setup) _arguments -C -s $_shtab_ahriman_service_setup_options ;;
|
||||
service-shell) _arguments -C -s $_shtab_ahriman_service_shell_options ;;
|
||||
service-tree-migrate) _arguments -C -s $_shtab_ahriman_service_tree_migrate_options ;;
|
||||
setup) _arguments -C -s $_shtab_ahriman_setup_options ;;
|
||||
shell) _arguments -C -s $_shtab_ahriman_shell_options ;;
|
||||
sign) _arguments -C -s $_shtab_ahriman_sign_options ;;
|
||||
|
@ -69,8 +69,7 @@ def _parser() -> argparse.ArgumentParser:
|
||||
parser = argparse.ArgumentParser(prog="ahriman", description="ArcH linux ReposItory MANager",
|
||||
epilog="Argument list can also be read from file by using @ prefix.",
|
||||
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("-a", "--architecture", help="filter by target architecture")
|
||||
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")
|
||||
@ -79,9 +78,13 @@ def _parser() -> argparse.ArgumentParser:
|
||||
parser.add_argument("--log-handler", help="explicit log handler specification. If none set, the handler will be "
|
||||
"guessed from environment",
|
||||
type=LogHandler, choices=enum_values(LogHandler))
|
||||
parser.add_argument("-q", "--quiet", help="force disable any logging", action="store_true")
|
||||
parser.add_argument("--report", help="force enable or disable reporting to web service",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
parser.add_argument("-q", "--quiet", help="force disable any logging", action="store_true")
|
||||
parser.add_argument("-r", "--repository", help="filter by target repository")
|
||||
# special secret argument for systemd unit. The issue is that systemd doesn't allow multiple arguments to template
|
||||
# name. This parameter accepts [[arch]-repo] in order to keep backward compatibility
|
||||
parser.add_argument("--repository-id", help=argparse.SUPPRESS)
|
||||
parser.add_argument("--unsafe", help="allow to run ahriman as non-ahriman user. Some actions might be unavailable",
|
||||
action="store_true")
|
||||
parser.add_argument("--wait-timeout", help="wait for lock to be free. Negative value will lead to "
|
||||
@ -90,7 +93,7 @@ def _parser() -> argparse.ArgumentParser:
|
||||
type=int, default=-1)
|
||||
parser.add_argument("-V", "--version", action="version", version=__version__)
|
||||
|
||||
subparsers = parser.add_subparsers(title="command", help="command to run", dest="command", required=True)
|
||||
subparsers = parser.add_subparsers(title="command", help="command to run", dest="command")
|
||||
|
||||
_set_aur_search_parser(subparsers)
|
||||
_set_help_parser(subparsers)
|
||||
@ -125,8 +128,10 @@ def _parser() -> argparse.ArgumentParser:
|
||||
_set_service_config_parser(subparsers)
|
||||
_set_service_config_validate_parser(subparsers)
|
||||
_set_service_key_import_parser(subparsers)
|
||||
_set_service_repositories(subparsers)
|
||||
_set_service_setup_parser(subparsers)
|
||||
_set_service_shell_parser(subparsers)
|
||||
_set_service_tree_migrate_parser(subparsers)
|
||||
_set_user_add_parser(subparsers)
|
||||
_set_user_list_parser(subparsers)
|
||||
_set_user_remove_parser(subparsers)
|
||||
@ -155,7 +160,8 @@ def _set_aur_search_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
parser.add_argument("--sort-by", help="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",
|
||||
default="name", choices=sorted(handlers.Search.SORT_FIELDS))
|
||||
parser.set_defaults(handler=handlers.Search, architecture=[""], lock=None, report=False, quiet=True, unsafe=True)
|
||||
parser.set_defaults(handler=handlers.Search, architecture="", lock=None, quiet=True, report=False,
|
||||
repository="", unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
@ -173,8 +179,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, quiet=True, report=False, repository="",
|
||||
unsafe=True, parser=_parser)
|
||||
return parser
|
||||
|
||||
|
||||
@ -192,8 +198,8 @@ def _set_help_commands_unsafe_parser(root: SubParserAction) -> argparse.Argument
|
||||
description="list unsafe commands as defined in default args", formatter_class=_formatter)
|
||||
parser.add_argument("command", help="instead of showing commands, just test command line for unsafe subcommand "
|
||||
"and return 0 in case if command is safe and 1 otherwise", nargs="*")
|
||||
parser.set_defaults(handler=handlers.UnsafeCommands, architecture=[""], lock=None, report=False, quiet=True,
|
||||
unsafe=True, parser=_parser)
|
||||
parser.set_defaults(handler=handlers.UnsafeCommands, architecture="", lock=None, quiet=True, report=False,
|
||||
repository="", unsafe=True, parser=_parser)
|
||||
return parser
|
||||
|
||||
|
||||
@ -211,8 +217,8 @@ def _set_help_updates_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
description="request AUR for current version and compare with current service version",
|
||||
formatter_class=_formatter)
|
||||
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)
|
||||
parser.set_defaults(handler=handlers.ServiceUpdates, architecture="", lock=None, quiet=True, report=False,
|
||||
repository="", unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
@ -228,7 +234,8 @@ def _set_help_version_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
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)
|
||||
parser.set_defaults(handler=handlers.Versions, architecture="", lock=None, quiet=True, report=False,
|
||||
repository="", unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
@ -310,7 +317,7 @@ def _set_package_status_parser(root: SubParserAction) -> argparse.ArgumentParser
|
||||
action=argparse.BooleanOptionalAction, default=False)
|
||||
parser.add_argument("-s", "--status", help="filter packages by status",
|
||||
type=BuildStatusEnum, choices=enum_values(BuildStatusEnum))
|
||||
parser.set_defaults(handler=handlers.Status, lock=None, report=False, quiet=True, unsafe=True)
|
||||
parser.set_defaults(handler=handlers.Status, lock=None, quiet=True, report=False, unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
@ -330,7 +337,7 @@ def _set_package_status_remove_parser(root: SubParserAction) -> argparse.Argumen
|
||||
"clears the status page.",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("package", help="remove specified packages from status page", nargs="+")
|
||||
parser.set_defaults(handler=handlers.StatusUpdate, action=Action.Remove, lock=None, report=False, quiet=True,
|
||||
parser.set_defaults(handler=handlers.StatusUpdate, action=Action.Remove, lock=None, quiet=True, report=False,
|
||||
unsafe=True)
|
||||
return parser
|
||||
|
||||
@ -352,7 +359,7 @@ def _set_package_status_update_parser(root: SubParserAction) -> argparse.Argumen
|
||||
nargs="*")
|
||||
parser.add_argument("-s", "--status", help="new package build status",
|
||||
type=BuildStatusEnum, choices=enum_values(BuildStatusEnum), default=BuildStatusEnum.Success)
|
||||
parser.set_defaults(handler=handlers.StatusUpdate, action=Action.Update, lock=None, report=False, quiet=True,
|
||||
parser.set_defaults(handler=handlers.StatusUpdate, action=Action.Update, lock=None, quiet=True, report=False,
|
||||
unsafe=True)
|
||||
return parser
|
||||
|
||||
@ -379,7 +386,8 @@ def _set_patch_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"it must end with ()")
|
||||
parser.add_argument("patch", help="path to file which contains function or variable value. If not set, "
|
||||
"the value will be read from stdin", type=Path, nargs="?")
|
||||
parser.set_defaults(handler=handlers.Patch, action=Action.Update, architecture=[""], lock=None, report=False)
|
||||
parser.set_defaults(handler=handlers.Patch, action=Action.Update, architecture="", lock=None, report=False,
|
||||
repository="")
|
||||
return parser
|
||||
|
||||
|
||||
@ -399,8 +407,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,
|
||||
unsafe=True)
|
||||
parser.set_defaults(handler=handlers.Patch, action=Action.List, architecture="", lock=None, report=False,
|
||||
repository="", unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
@ -421,7 +429,8 @@ def _set_patch_remove_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"to remove only specified PKGBUILD variables. In case if not set, "
|
||||
"it will remove all patches related to the package",
|
||||
action="append")
|
||||
parser.set_defaults(handler=handlers.Patch, action=Action.Remove, architecture=[""], lock=None, report=False)
|
||||
parser.set_defaults(handler=handlers.Patch, action=Action.Remove, architecture="", lock=None, report=False,
|
||||
repository="")
|
||||
return parser
|
||||
|
||||
|
||||
@ -445,8 +454,8 @@ def _set_patch_set_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
parser.add_argument("package", help="path to directory with changed files for patch addition/update", type=Path)
|
||||
parser.add_argument("-t", "--track", help="files which has to be tracked", action="append",
|
||||
default=["*.diff", "*.patch"])
|
||||
parser.set_defaults(handler=handlers.Patch, action=Action.Update, architecture=[""], lock=None, report=False,
|
||||
variable=None)
|
||||
parser.set_defaults(handler=handlers.Patch, action=Action.Update, architecture="", lock=None, report=False,
|
||||
repository="", variable=None)
|
||||
return parser
|
||||
|
||||
|
||||
@ -463,7 +472,8 @@ def _set_repo_backup_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
parser = root.add_parser("repo-backup", help="backup repository data",
|
||||
description="backup repository settings and database", formatter_class=_formatter)
|
||||
parser.add_argument("path", help="path of the output archive", type=Path)
|
||||
parser.set_defaults(handler=handlers.Backup, architecture=[""], lock=None, report=False, unsafe=True)
|
||||
parser.set_defaults(handler=handlers.Backup, architecture="", lock=None, report=False, repository="",
|
||||
unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
@ -642,7 +652,8 @@ def _set_repo_restore_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
description="restore settings and database", formatter_class=_formatter)
|
||||
parser.add_argument("path", help="path of the input archive", type=Path)
|
||||
parser.add_argument("-o", "--output", help="root path of the extracted files", type=Path, default=Path("/"))
|
||||
parser.set_defaults(handler=handlers.Restore, architecture=[""], lock=None, report=False, unsafe=True)
|
||||
parser.set_defaults(handler=handlers.Restore, architecture="", lock=None, report=False, repository="",
|
||||
unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
@ -679,8 +690,8 @@ def _set_repo_status_update_parser(root: SubParserAction) -> argparse.ArgumentPa
|
||||
description="update repository status on the status page", formatter_class=_formatter)
|
||||
parser.add_argument("-s", "--status", help="new status",
|
||||
type=BuildStatusEnum, choices=enum_values(BuildStatusEnum), default=BuildStatusEnum.Success)
|
||||
parser.set_defaults(handler=handlers.StatusUpdate, action=Action.Update, lock=None, report=False, package=[],
|
||||
quiet=True, unsafe=True)
|
||||
parser.set_defaults(handler=handlers.StatusUpdate, action=Action.Update, lock=None, package=[], quiet=True,
|
||||
report=False, unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
@ -717,7 +728,7 @@ def _set_repo_tree_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("-p", "--partitions", help="also divide packages by independent partitions",
|
||||
type=int, default=1)
|
||||
parser.set_defaults(handler=handlers.Structure, lock=None, report=False, quiet=True, unsafe=True)
|
||||
parser.set_defaults(handler=handlers.Structure, lock=None, quiet=True, report=False, unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
@ -818,9 +829,13 @@ def _set_service_config_parser(root: SubParserAction) -> argparse.ArgumentParser
|
||||
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("section", help="filter settings by section", nargs="?")
|
||||
parser.add_argument("key", help="filter settings by key", nargs="?")
|
||||
parser.add_argument("--info", help="show additional information, e.g. configuration files",
|
||||
action=argparse.BooleanOptionalAction, default=True)
|
||||
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)
|
||||
parser.set_defaults(handler=handlers.Dump, lock=None, quiet=True, report=False, unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
@ -840,7 +855,7 @@ def _set_service_config_validate_parser(root: SubParserAction) -> argparse.Argum
|
||||
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)
|
||||
parser.set_defaults(handler=handlers.Validate, lock=None, quiet=True, report=False, unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
@ -863,7 +878,27 @@ def _set_service_key_import_parser(root: SubParserAction) -> argparse.ArgumentPa
|
||||
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.set_defaults(handler=handlers.KeyImport, architecture="", lock=None, report=False, repository="")
|
||||
return parser
|
||||
|
||||
|
||||
def _set_service_repositories(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for repositories listing
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("service-repositories", help="show repositories",
|
||||
description="list all available repositories",
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("--id-only", help="show machine readable identifier instead",
|
||||
action=argparse.BooleanOptionalAction, default=False)
|
||||
parser.set_defaults(handler=handlers.Repositories, architecture="", lock=None, report=False, repository="",
|
||||
unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
@ -883,7 +918,6 @@ def _set_service_setup_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
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.conf.d" / "extra.conf")
|
||||
parser.add_argument("--generate-salt", help="generate salt for user passwords",
|
||||
@ -894,14 +928,13 @@ def _set_service_setup_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
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("--server", help="server to be used for devtools. If none set, local files will be used")
|
||||
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)
|
||||
parser.set_defaults(handler=handlers.Setup, lock=None, quiet=True, report=False, unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
@ -923,6 +956,22 @@ def _set_service_shell_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
return parser
|
||||
|
||||
|
||||
def _set_service_tree_migrate_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for tree migration subcommand
|
||||
|
||||
Args:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
Returns:
|
||||
argparse.ArgumentParser: created argument parser
|
||||
"""
|
||||
parser = root.add_parser("service-tree-migrate", help="migrate repository tree",
|
||||
description="migrate repository tree between versions", formatter_class=_formatter)
|
||||
parser.set_defaults(handler=handlers.TreeMigrate, lock=None, quiet=True, report=False)
|
||||
return parser
|
||||
|
||||
|
||||
def _set_user_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"""
|
||||
add parser for create user subcommand
|
||||
@ -943,10 +992,10 @@ def _set_user_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
"`Name Surname <mail@example.com>`")
|
||||
parser.add_argument("-p", "--password", help="user password. Blank password will be treated as empty password, "
|
||||
"which is in particular must be used for OAuth2 authorization type.")
|
||||
parser.add_argument("-r", "--role", help="user access level",
|
||||
parser.add_argument("-R", "--role", help="user access level",
|
||||
type=UserAccess, choices=enum_values(UserAccess), default=UserAccess.Read)
|
||||
parser.set_defaults(handler=handlers.Users, action=Action.Update, architecture=[""], lock=None, report=False,
|
||||
quiet=True)
|
||||
parser.set_defaults(handler=handlers.Users, action=Action.Update, architecture="", lock=None, quiet=True,
|
||||
report=False, repository="")
|
||||
return parser
|
||||
|
||||
|
||||
@ -965,9 +1014,9 @@ def _set_user_list_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
formatter_class=_formatter)
|
||||
parser.add_argument("username", help="filter users by username", nargs="?")
|
||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty", action="store_true")
|
||||
parser.add_argument("-r", "--role", help="filter users by role", type=UserAccess, choices=enum_values(UserAccess))
|
||||
parser.set_defaults(handler=handlers.Users, action=Action.List, architecture=[""], lock=None, report=False,
|
||||
quiet=True, unsafe=True)
|
||||
parser.add_argument("-R", "--role", help="filter users by role", type=UserAccess, choices=enum_values(UserAccess))
|
||||
parser.set_defaults(handler=handlers.Users, action=Action.List, architecture="", lock=None, quiet=True,
|
||||
report=False, repository="", unsafe=True)
|
||||
return parser
|
||||
|
||||
|
||||
@ -985,8 +1034,8 @@ def _set_user_remove_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||
description="remove user from the user mapping and update the configuration",
|
||||
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,
|
||||
quiet=True)
|
||||
parser.set_defaults(handler=handlers.Users, action=Action.Remove, architecture="", lock=None, quiet=True,
|
||||
report=False, repository="")
|
||||
return parser
|
||||
|
||||
|
||||
@ -1001,8 +1050,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=Path(tempfile.gettempdir()) / "ahriman-web.lock", report=False,
|
||||
parser=_parser)
|
||||
parser.set_defaults(handler=handlers.Web, architecture="", lock=Path(tempfile.gettempdir()) / "ahriman-web.lock",
|
||||
report=False, repository="", parser=_parser)
|
||||
return parser
|
||||
|
||||
|
||||
@ -1016,5 +1065,8 @@ def run() -> int:
|
||||
args_parser = _parser()
|
||||
args = args_parser.parse_args()
|
||||
|
||||
if args.command is None: # in case of empty command we would like to print help message
|
||||
args_parser.exit(status=2, message=args_parser.format_help())
|
||||
|
||||
handler: handlers.Handler = args.handler
|
||||
return handler.execute(args)
|
||||
|
@ -37,9 +37,10 @@ class Application(ApplicationPackages, ApplicationRepository):
|
||||
|
||||
>>> from ahriman.core.configuration import Configuration
|
||||
>>> from ahriman.models.package_source import PackageSource
|
||||
>>> from ahriman.models.repository_id import RepositoryId
|
||||
>>>
|
||||
>>> configuration = Configuration()
|
||||
>>> application = Application("x86_64", configuration, report=True)
|
||||
>>> application = Application(RepositoryId("x86_64", "x86_64"), configuration, report=True)
|
||||
>>> # add packages to build queue
|
||||
>>> application.add(["ahriman"], PackageSource.AUR)
|
||||
>>>
|
||||
@ -104,8 +105,7 @@ class Application(ApplicationPackages, ApplicationRepository):
|
||||
tree = Tree.resolve(packages)
|
||||
for level in tree:
|
||||
for package in level:
|
||||
UpdatePrinter(package, local_versions.get(package.base)).print(
|
||||
verbose=True, log_fn=log_fn, separator=" -> ")
|
||||
UpdatePrinter(package, local_versions.get(package.base))(verbose=True, log_fn=log_fn, separator=" -> ")
|
||||
|
||||
def with_dependencies(self, packages: list[Package], *, process_dependencies: bool) -> list[Package]:
|
||||
"""
|
||||
@ -146,7 +146,7 @@ class Application(ApplicationPackages, ApplicationRepository):
|
||||
# there is local cache, load package from it
|
||||
package = Package.from_build(source_dir, self.repository.architecture, username)
|
||||
else:
|
||||
package = Package.from_aur(package_name, self.repository.pacman, username)
|
||||
package = Package.from_aur(package_name, username)
|
||||
with_dependencies[package.base] = package
|
||||
|
||||
# register package in local database
|
||||
|
@ -63,7 +63,7 @@ class ApplicationPackages(ApplicationProperties):
|
||||
source(str): package base name
|
||||
username(str | None): optional override of username for build process
|
||||
"""
|
||||
package = Package.from_aur(source, self.repository.pacman, username)
|
||||
package = Package.from_aur(source, username)
|
||||
self.database.build_queue_insert(package)
|
||||
self.database.remote_update(package)
|
||||
|
||||
|
@ -22,6 +22,7 @@ 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
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
|
||||
class ApplicationProperties(LazyLogging):
|
||||
@ -29,26 +30,36 @@ class ApplicationProperties(LazyLogging):
|
||||
application base properties class
|
||||
|
||||
Attributes:
|
||||
architecture(str): repository architecture
|
||||
configuration(Configuration): configuration instance
|
||||
database(SQLite): database instance
|
||||
repository(Repository): repository instance
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
"""
|
||||
|
||||
def __init__(self, architecture: str, configuration: Configuration, *, report: bool,
|
||||
def __init__(self, repository_id: RepositoryId, configuration: Configuration, *, report: bool,
|
||||
refresh_pacman_database: PacmanSynchronization = PacmanSynchronization.Disabled) -> None:
|
||||
"""
|
||||
default constructor
|
||||
|
||||
Args:
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
refresh_pacman_database(PacmanSynchronization, optional): pacman database synchronization level
|
||||
(Default value = PacmanSynchronization.Disabled)
|
||||
"""
|
||||
self.configuration = configuration
|
||||
self.architecture = architecture
|
||||
self.repository_id = repository_id
|
||||
self.database = SQLite.load(configuration)
|
||||
self.repository = Repository.load(architecture, configuration, self.database, report=report,
|
||||
self.repository = Repository.load(repository_id, configuration, self.database, report=report,
|
||||
refresh_pacman_database=refresh_pacman_database)
|
||||
|
||||
@property
|
||||
def architecture(self) -> str:
|
||||
"""
|
||||
repository architecture for backward compatibility
|
||||
|
||||
Returns:
|
||||
str: repository architecture
|
||||
"""
|
||||
return self.repository_id.architecture
|
||||
|
@ -104,7 +104,7 @@ class ApplicationRepository(ApplicationProperties):
|
||||
packages: list[str] = []
|
||||
for single in probe.packages:
|
||||
try:
|
||||
_ = Package.from_aur(single, self.repository.pacman, None)
|
||||
_ = Package.from_aur(single, None)
|
||||
except Exception:
|
||||
packages.append(single)
|
||||
return packages
|
||||
|
@ -30,6 +30,7 @@ from ahriman.application.handlers.patch import Patch
|
||||
from ahriman.application.handlers.rebuild import Rebuild
|
||||
from ahriman.application.handlers.remove import Remove
|
||||
from ahriman.application.handlers.remove_unknown import RemoveUnknown
|
||||
from ahriman.application.handlers.repositories import Repositories
|
||||
from ahriman.application.handlers.restore import Restore
|
||||
from ahriman.application.handlers.search import Search
|
||||
from ahriman.application.handlers.service_updates import ServiceUpdates
|
||||
@ -39,6 +40,7 @@ from ahriman.application.handlers.sign import Sign
|
||||
from ahriman.application.handlers.status import Status
|
||||
from ahriman.application.handlers.status_update import StatusUpdate
|
||||
from ahriman.application.handlers.structure import Structure
|
||||
from ahriman.application.handlers.tree_migrate import TreeMigrate
|
||||
from ahriman.application.handlers.triggers import Triggers
|
||||
from ahriman.application.handlers.unsafe_commands import UnsafeCommands
|
||||
from ahriman.application.handlers.update import Update
|
||||
|
@ -23,6 +23,7 @@ from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.packagers import Packagers
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
|
||||
class Add(Handler):
|
||||
@ -31,17 +32,18 @@ class Add(Handler):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
application = Application(architecture, configuration, report=report, refresh_pacman_database=args.refresh)
|
||||
application = Application(repository_id, configuration, report=report, refresh_pacman_database=args.refresh)
|
||||
application.on_start()
|
||||
application.add(args.package, args.source, args.username)
|
||||
if not args.now:
|
||||
|
@ -26,6 +26,7 @@ from tarfile import TarFile
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.database import SQLite
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
|
||||
class Backup(Handler):
|
||||
@ -33,16 +34,17 @@ class Backup(Handler):
|
||||
backup packages handler
|
||||
"""
|
||||
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
|
@ -22,6 +22,7 @@ import argparse
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
|
||||
class Clean(Handler):
|
||||
@ -30,17 +31,18 @@ class Clean(Handler):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
application = Application(architecture, configuration, report=report)
|
||||
application = Application(repository_id, configuration, report=report)
|
||||
application.on_start()
|
||||
application.clean(cache=args.cache, chroot=args.chroot, manual=args.manual, packages=args.packages,
|
||||
pacman=args.pacman)
|
||||
|
@ -22,6 +22,7 @@ import threading
|
||||
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
|
||||
class Daemon(Handler):
|
||||
@ -30,19 +31,20 @@ class Daemon(Handler):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
from ahriman.application.handlers import Update
|
||||
Update.run(args, architecture, configuration, report=report)
|
||||
timer = threading.Timer(args.interval, Daemon.run, args=[args, architecture, configuration],
|
||||
Update.run(args, repository_id, configuration, report=report)
|
||||
timer = threading.Timer(args.interval, Daemon.run, args=[args, repository_id, configuration],
|
||||
kwargs={"report": report})
|
||||
timer.start()
|
||||
timer.join()
|
||||
|
@ -22,6 +22,7 @@ import argparse
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.formatters import ConfigurationPathsPrinter, ConfigurationPrinter, StringPrinter
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
|
||||
class Dump(Handler):
|
||||
@ -29,25 +30,32 @@ class Dump(Handler):
|
||||
dump configuration handler
|
||||
"""
|
||||
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
root, _ = configuration.check_loaded()
|
||||
ConfigurationPathsPrinter(root, configuration.includes).print(verbose=True, separator=" = ")
|
||||
if args.info:
|
||||
root, _ = configuration.check_loaded()
|
||||
ConfigurationPathsPrinter(root, configuration.includes)(verbose=True, separator=" = ")
|
||||
|
||||
# empty line
|
||||
StringPrinter("").print(verbose=False)
|
||||
|
||||
dump = configuration.dump()
|
||||
for section, values in sorted(dump.items()):
|
||||
ConfigurationPrinter(section, values).print(verbose=not args.secure, separator=" = ")
|
||||
match (args.section, args.key):
|
||||
case None, None: # full configuration
|
||||
dump = configuration.dump()
|
||||
for section, values in sorted(dump.items()):
|
||||
ConfigurationPrinter(section, values)(verbose=not args.secure, separator=" = ")
|
||||
case section, None: # section only
|
||||
values = dict(configuration.items(section)) if configuration.has_section(section) else {}
|
||||
ConfigurationPrinter(section, values)(verbose=not args.secure, separator=" = ")
|
||||
case section, key: # key only
|
||||
value = configuration.get(section, key, fallback="")
|
||||
StringPrinter(value)(verbose=False)
|
||||
|
@ -20,12 +20,14 @@
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from collections.abc import Iterable
|
||||
from multiprocessing import Pool
|
||||
|
||||
from ahriman.application.lock import Lock
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.exceptions import ExitCode, MissingArchitectureError, MultipleArchitecturesError
|
||||
from ahriman.core.log import Log
|
||||
from ahriman.core.log.log_loader import LogLoader
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
from ahriman.models.repository_paths import RepositoryPaths
|
||||
|
||||
|
||||
@ -34,7 +36,6 @@ class Handler:
|
||||
base handler class for command callbacks
|
||||
|
||||
Attributes:
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN(bool): (class attribute) allow defining architecture from existing repositories
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN(bool): (class attribute) allow running with multiple architectures
|
||||
|
||||
Examples:
|
||||
@ -46,60 +47,28 @@ class Handler:
|
||||
>>> Add.execute(args)
|
||||
"""
|
||||
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = True
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN = True
|
||||
|
||||
@classmethod
|
||||
def architectures_extract(cls, args: argparse.Namespace) -> list[str]:
|
||||
"""
|
||||
get known architectures
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
|
||||
Returns:
|
||||
list[str]: list of architectures for which tree is created
|
||||
|
||||
Raises:
|
||||
MissingArchitectureError: if no architecture set and automatic detection is not allowed or failed
|
||||
"""
|
||||
if not cls.ALLOW_AUTO_ARCHITECTURE_RUN and args.architecture is None:
|
||||
# for some parsers (e.g. config) we need to run with specific architecture
|
||||
# for those cases architecture must be set explicitly
|
||||
raise MissingArchitectureError(args.command)
|
||||
if args.architecture: # architecture is specified explicitly
|
||||
return sorted(set(args.architecture))
|
||||
|
||||
configuration = Configuration()
|
||||
configuration.load(args.configuration)
|
||||
# wtf???
|
||||
root = configuration.getpath("repository", "root") # pylint: disable=assignment-from-no-return
|
||||
architectures = RepositoryPaths.known_architectures(root)
|
||||
|
||||
if not architectures: # well we did not find anything
|
||||
raise MissingArchitectureError(args.command)
|
||||
return sorted(architectures)
|
||||
|
||||
@classmethod
|
||||
def call(cls, args: argparse.Namespace, architecture: str) -> bool:
|
||||
def call(cls, args: argparse.Namespace, repository_id: RepositoryId) -> bool:
|
||||
"""
|
||||
additional function to wrap all calls for multiprocessing library
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
|
||||
Returns:
|
||||
bool: True on success, False otherwise
|
||||
"""
|
||||
try:
|
||||
configuration = Configuration.from_path(args.configuration, architecture)
|
||||
configuration = Configuration.from_path(args.configuration, repository_id)
|
||||
|
||||
log_handler = Log.handler(args.log_handler)
|
||||
Log.load(configuration, log_handler, quiet=args.quiet, report=args.report)
|
||||
log_handler = LogLoader.handler(args.log_handler)
|
||||
LogLoader.load(repository_id, configuration, log_handler, quiet=args.quiet, report=args.report)
|
||||
|
||||
with Lock(args, architecture, configuration):
|
||||
cls.run(args, architecture, configuration, report=args.report)
|
||||
with Lock(args, repository_id, configuration):
|
||||
cls.run(args, repository_id, configuration, report=args.report)
|
||||
|
||||
return True
|
||||
except ExitCode:
|
||||
@ -123,28 +92,29 @@ class Handler:
|
||||
Raises:
|
||||
MultipleArchitecturesError: if more than one architecture supplied and no multi architecture supported
|
||||
"""
|
||||
architectures = cls.architectures_extract(args)
|
||||
repositories = cls.repositories_extract(args)
|
||||
|
||||
# actually we do not have to spawn another process if it is single-process application, do we?
|
||||
if len(architectures) > 1:
|
||||
if len(repositories) > 1:
|
||||
if not cls.ALLOW_MULTI_ARCHITECTURE_RUN:
|
||||
raise MultipleArchitecturesError(args.command)
|
||||
raise MultipleArchitecturesError(args.command, repositories)
|
||||
|
||||
with Pool(len(architectures)) as pool:
|
||||
result = pool.starmap(cls.call, [(args, architecture) for architecture in architectures])
|
||||
with Pool(len(repositories)) as pool:
|
||||
result = pool.starmap(cls.call, [(args, repository_id) for repository_id in repositories])
|
||||
else:
|
||||
result = [cls.call(args, architectures.pop())]
|
||||
result = [cls.call(args, repositories.pop())]
|
||||
|
||||
return 0 if all(result) else 1
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
|
||||
@ -167,3 +137,57 @@ class Handler:
|
||||
"""
|
||||
if enabled and predicate:
|
||||
raise ExitCode
|
||||
|
||||
@staticmethod
|
||||
def repositories_extract(args: argparse.Namespace) -> list[RepositoryId]:
|
||||
"""
|
||||
get known architectures
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
|
||||
Returns:
|
||||
list[RepositoryId]: list of repository names and architectures for which tree is created
|
||||
|
||||
Raises:
|
||||
MissingArchitectureError: if no architecture set and automatic detection is not allowed or failed
|
||||
"""
|
||||
configuration = Configuration()
|
||||
configuration.load(args.configuration)
|
||||
# pylint, wtf???
|
||||
root = configuration.getpath("repository", "root") # pylint: disable=assignment-from-no-return
|
||||
|
||||
# preparse systemd repository-id argument
|
||||
# we are using unescaped values, so / is not allowed here, because it is impossible to separate if from dashes
|
||||
if args.repository_id is not None:
|
||||
separator = "/" if "/" in args.repository_id else "-" # systemd and non-systemd identifiers
|
||||
# repository parts is optional for backward compatibility
|
||||
architecture, *repository_parts = args.repository_id.split(separator)
|
||||
args.architecture = architecture
|
||||
if repository_parts:
|
||||
args.repository = "-".join(repository_parts) # replace slash with dash
|
||||
|
||||
# extract repository names first
|
||||
if (from_args := args.repository) is not None:
|
||||
repositories: Iterable[str] = [from_args]
|
||||
elif (from_filesystem := RepositoryPaths.known_repositories(root)):
|
||||
repositories = from_filesystem
|
||||
else: # try to read configuration now
|
||||
repositories = [configuration.get("repository", "name")]
|
||||
|
||||
# extract architecture names
|
||||
if (architecture := args.architecture) is not None:
|
||||
parsed = set(
|
||||
RepositoryId(architecture, repository)
|
||||
for repository in repositories
|
||||
)
|
||||
else: # try to read from file system
|
||||
parsed = set(
|
||||
RepositoryId(architecture, repository)
|
||||
for repository in repositories
|
||||
for architecture in RepositoryPaths.known_architectures(root, repository)
|
||||
)
|
||||
|
||||
if not parsed:
|
||||
raise MissingArchitectureError(args.command)
|
||||
return sorted(parsed)
|
||||
|
@ -21,6 +21,7 @@ import argparse
|
||||
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
|
||||
class Help(Handler):
|
||||
@ -28,16 +29,17 @@ class Help(Handler):
|
||||
help handler
|
||||
"""
|
||||
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
|
@ -22,6 +22,7 @@ import argparse
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
|
||||
class KeyImport(Handler):
|
||||
@ -29,18 +30,19 @@ class KeyImport(Handler):
|
||||
key import packages handler
|
||||
"""
|
||||
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
application = Application(architecture, configuration, report=report)
|
||||
application = Application(repository_id, configuration, report=report)
|
||||
application.repository.sign.key_import(args.key_server, args.key)
|
||||
|
@ -30,6 +30,7 @@ from ahriman.core.formatters import PatchPrinter
|
||||
from ahriman.models.action import Action
|
||||
from ahriman.models.package import Package
|
||||
from ahriman.models.pkgbuild_patch import PkgbuildPatch
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
|
||||
class Patch(Handler):
|
||||
@ -37,18 +38,21 @@ class Patch(Handler):
|
||||
patch control handler
|
||||
"""
|
||||
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
application = Application(architecture, configuration, report=report)
|
||||
application = Application(repository_id, configuration, report=report)
|
||||
application.on_start()
|
||||
|
||||
match args.action:
|
||||
@ -56,7 +60,7 @@ class Patch(Handler):
|
||||
patch = Patch.patch_create_from_function(args.variable, args.patch)
|
||||
Patch.patch_set_create(application, args.package, patch)
|
||||
case Action.Update:
|
||||
package_base, patch = Patch.patch_create_from_diff(args.package, architecture, args.track)
|
||||
package_base, patch = Patch.patch_create_from_diff(args.package, repository_id.architecture, args.track)
|
||||
Patch.patch_set_create(application, package_base, patch)
|
||||
case Action.List:
|
||||
Patch.patch_set_list(application, args.package, args.variable, args.exit_code)
|
||||
@ -114,7 +118,7 @@ class Patch(Handler):
|
||||
application.database.patches_insert(package_base, patch)
|
||||
|
||||
@staticmethod
|
||||
def patch_set_list(application: Application, package_base: str | None, variables: list[str],
|
||||
def patch_set_list(application: Application, package_base: str | None, variables: list[str] | None,
|
||||
exit_code: bool) -> None:
|
||||
"""
|
||||
list patches available for the package base
|
||||
@ -122,23 +126,23 @@ class Patch(Handler):
|
||||
Args:
|
||||
application(Application): application instance
|
||||
package_base(str | None): package base
|
||||
variables(list[str]): extract patches only for specified PKGBUILD variables
|
||||
variables(list[str] | None): 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)
|
||||
Patch.check_if_empty(exit_code, not patches)
|
||||
|
||||
for base, patch in patches.items():
|
||||
PatchPrinter(base, patch).print(verbose=True, separator=" = ")
|
||||
PatchPrinter(base, patch)(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) -> 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] | None): remove patches only for specified PKGBUILD variables
|
||||
"""
|
||||
application.database.patches_remove(package_base, variables)
|
||||
|
@ -24,6 +24,7 @@ from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.build_status import BuildStatusEnum
|
||||
from ahriman.models.package import Package
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
|
||||
class Rebuild(Handler):
|
||||
@ -32,21 +33,22 @@ class Rebuild(Handler):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
application = Application(architecture, configuration, report=report)
|
||||
application = Application(repository_id, configuration, report=report)
|
||||
application.on_start()
|
||||
|
||||
packages = Rebuild.extract_packages(application, args.status, from_database=args.from_database)
|
||||
updates = application.repository.packages_depend_on(packages, args.depends_on or None)
|
||||
updates = application.repository.packages_depend_on(packages, args.depends_on)
|
||||
|
||||
Rebuild.check_if_empty(args.exit_code, not updates)
|
||||
if args.dry_run:
|
||||
|
@ -22,6 +22,7 @@ import argparse
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
|
||||
class Remove(Handler):
|
||||
@ -30,16 +31,17 @@ class Remove(Handler):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
application = Application(architecture, configuration, report=report)
|
||||
application = Application(repository_id, configuration, report=report)
|
||||
application.on_start()
|
||||
application.remove(args.package)
|
||||
|
@ -23,6 +23,7 @@ from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.formatters import StringPrinter
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
|
||||
class RemoveUnknown(Handler):
|
||||
@ -31,23 +32,24 @@ class RemoveUnknown(Handler):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
application = Application(architecture, configuration, report=report)
|
||||
application = Application(repository_id, configuration, report=report)
|
||||
application.on_start()
|
||||
unknown_packages = application.unknown()
|
||||
|
||||
if args.dry_run:
|
||||
for package in sorted(unknown_packages):
|
||||
StringPrinter(package).print(verbose=False)
|
||||
StringPrinter(package)(verbose=False)
|
||||
return
|
||||
|
||||
application.remove(unknown_packages)
|
||||
|
54
src/ahriman/application/handlers/repositories.py
Normal file
54
src/ahriman/application/handlers/repositories.py
Normal file
@ -0,0 +1,54 @@
|
||||
#
|
||||
# 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.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.formatters import RepositoryPrinter
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
|
||||
class Repositories(Handler):
|
||||
"""
|
||||
repositories listing handler
|
||||
"""
|
||||
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
dummy_args = argparse.Namespace(
|
||||
architecture=None,
|
||||
configuration=args.configuration,
|
||||
repository=None,
|
||||
repository_id=None,
|
||||
)
|
||||
for repository in cls.repositories_extract(dummy_args):
|
||||
RepositoryPrinter(repository)(verbose=not args.id_only)
|
@ -23,6 +23,7 @@ from tarfile import TarFile
|
||||
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
|
||||
class Restore(Handler):
|
||||
@ -30,16 +31,17 @@ class Restore(Handler):
|
||||
restore packages handler
|
||||
"""
|
||||
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
|
@ -22,13 +22,13 @@ import argparse
|
||||
from dataclasses import fields
|
||||
from collections.abc import Callable, Iterable
|
||||
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.alpm.remote import AUR, Official
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.exceptions import OptionError
|
||||
from ahriman.core.formatters import AurPrinter
|
||||
from ahriman.models.aur_package import AURPackage
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
|
||||
class Search(Handler):
|
||||
@ -39,7 +39,7 @@ class Search(Handler):
|
||||
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"
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
||||
SORT_FIELDS = {
|
||||
field.name
|
||||
for field in fields(AURPackage)
|
||||
@ -47,26 +47,25 @@ class Search(Handler):
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
application = Application(architecture, configuration, report=report)
|
||||
|
||||
official_packages_list = Official.multisearch(*args.search, pacman=application.repository.pacman)
|
||||
aur_packages_list = AUR.multisearch(*args.search, pacman=application.repository.pacman)
|
||||
official_packages_list = Official.multisearch(*args.search)
|
||||
aur_packages_list = AUR.multisearch(*args.search)
|
||||
Search.check_if_empty(args.exit_code, not official_packages_list and not aur_packages_list)
|
||||
|
||||
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(verbose=args.info)
|
||||
AurPrinter(package)(verbose=args.info)
|
||||
|
||||
@staticmethod
|
||||
def sort(packages: Iterable[AURPackage], sort_by: str) -> list[AURPackage]:
|
||||
|
@ -20,11 +20,11 @@
|
||||
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
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
|
||||
class ServiceUpdates(Handler):
|
||||
@ -32,22 +32,21 @@ class ServiceUpdates(Handler):
|
||||
service updates handler
|
||||
"""
|
||||
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
application = Application(architecture, configuration, report=report)
|
||||
|
||||
remote = Package.from_aur("ahriman", application.repository.pacman, None)
|
||||
remote = Package.from_aur("ahriman", None)
|
||||
_, release = remote.version.rsplit("-", 1) # we don't store pkgrel locally, so we just append it
|
||||
local_version = f"{__version__}-{release}"
|
||||
|
||||
@ -57,5 +56,5 @@ class ServiceUpdates(Handler):
|
||||
if same_version:
|
||||
return
|
||||
|
||||
UpdatePrinter(remote, local_version).print(verbose=True, separator=" -> ")
|
||||
UpdatePrinter(remote, local_version)(verbose=True, separator=" -> ")
|
||||
ServiceUpdates.check_if_empty(args.exit_code, not same_version)
|
||||
|
@ -25,6 +25,8 @@ from pwd import getpwuid
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.exceptions import MissingArchitectureError
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
from ahriman.models.repository_paths import RepositoryPaths
|
||||
from ahriman.models.user import User
|
||||
|
||||
@ -39,103 +41,107 @@ class Setup(Handler):
|
||||
SUDOERS_DIR_PATH(Path): (class attribute) path to sudoers.d includes directory
|
||||
"""
|
||||
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io
|
||||
|
||||
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, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
Setup.configuration_create_ahriman(args, architecture, args.repository, configuration)
|
||||
# special check for args to avoid auto definition for setup command
|
||||
if args.architecture is None or args.repository is None:
|
||||
raise MissingArchitectureError(args.command)
|
||||
|
||||
Setup.configuration_create_ahriman(args, repository_id, configuration)
|
||||
configuration.reload()
|
||||
|
||||
application = Application(architecture, configuration, report=report)
|
||||
application = Application(repository_id, configuration, report=report)
|
||||
|
||||
Setup.configuration_create_makepkg(args.packager, args.makeflags_jobs, application.repository.paths)
|
||||
Setup.executable_create(application.repository.paths, args.build_command, architecture)
|
||||
Setup.executable_create(application.repository.paths, repository_id)
|
||||
repository_server = f"file://{application.repository.paths.repository}" if args.server is None else args.server
|
||||
Setup.configuration_create_devtools(args.build_command, architecture, args.from_configuration, args.mirror,
|
||||
args.multilib, args.repository, repository_server)
|
||||
Setup.configuration_create_sudo(application.repository.paths, args.build_command, architecture)
|
||||
Setup.configuration_create_devtools(
|
||||
repository_id, args.from_configuration, args.mirror, args.multilib, repository_server)
|
||||
Setup.configuration_create_sudo(application.repository.paths, repository_id)
|
||||
|
||||
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:
|
||||
def build_command(root: Path, repository_id: RepositoryId) -> 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
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
|
||||
Returns:
|
||||
Path: valid devtools command name
|
||||
"""
|
||||
return root / f"{prefix}-{architecture}-build"
|
||||
return root / f"{repository_id.name}-{repository_id.architecture}-build"
|
||||
|
||||
@staticmethod
|
||||
def configuration_create_ahriman(args: argparse.Namespace, architecture: str, repository: str,
|
||||
def configuration_create_ahriman(args: argparse.Namespace, repository_id: RepositoryId,
|
||||
root: Configuration) -> None:
|
||||
"""
|
||||
create service specific configuration
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
repository(str): repository name
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
root(Configuration): root configuration instance
|
||||
"""
|
||||
configuration = Configuration()
|
||||
|
||||
section = Configuration.section_name("build", architecture)
|
||||
build_command = Setup.build_command(root.repository_paths.root, args.build_command, architecture)
|
||||
section = Configuration.section_name("build", repository_id.name, repository_id.architecture)
|
||||
build_command = Setup.build_command(root.repository_paths.root, repository_id)
|
||||
configuration.set_option(section, "build_command", str(build_command))
|
||||
configuration.set_option("repository", "name", repository)
|
||||
configuration.set_option("repository", "name", repository_id.name) # backward compatibility for docker
|
||||
if args.build_as_user is not None:
|
||||
configuration.set_option(section, "makechrootpkg_flags", f"-U {args.build_as_user}")
|
||||
|
||||
section = Configuration.section_name("alpm", architecture)
|
||||
section = Configuration.section_name("alpm", repository_id.name, repository_id.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)
|
||||
section = Configuration.section_name("sign", repository_id.name, repository_id.architecture)
|
||||
if args.sign_key is not None:
|
||||
configuration.set_option(section, "target", " ".join([target.name.lower() for target in args.sign_target]))
|
||||
sign_targets = args.sign_target or []
|
||||
configuration.set_option(section, "target", " ".join([target.name.lower() for target in sign_targets]))
|
||||
configuration.set_option(section, "key", args.sign_key)
|
||||
|
||||
section = Configuration.section_name("web", architecture)
|
||||
if args.web_port is not None:
|
||||
configuration.set_option(section, "port", str(args.web_port))
|
||||
configuration.set_option("web", "port", str(args.web_port))
|
||||
if args.web_unix_socket is not None:
|
||||
configuration.set_option(section, "unix_socket", str(args.web_unix_socket))
|
||||
configuration.set_option("web", "unix_socket", str(args.web_unix_socket))
|
||||
|
||||
if args.generate_salt:
|
||||
configuration.set_option("auth", "salt", User.generate_password(20))
|
||||
|
||||
target = root.include / "00-setup-overrides.ini"
|
||||
(root.include / "00-setup-overrides.ini").unlink(missing_ok=True) # remove old-style configuration
|
||||
target = root.include / f"00-setup-overrides-{repository_id.id}.ini"
|
||||
with target.open("w") as ahriman_configuration:
|
||||
configuration.write(ahriman_configuration)
|
||||
|
||||
@staticmethod
|
||||
def configuration_create_devtools(prefix: str, architecture: str, source: Path, mirror: str | None,
|
||||
multilib: bool, repository: str, repository_server: str) -> None:
|
||||
def configuration_create_devtools(repository_id: RepositoryId, source: Path, mirror: str | None,
|
||||
multilib: bool, repository_server: str) -> None:
|
||||
"""
|
||||
create configuration for devtools based on ``source`` configuration
|
||||
|
||||
@ -143,12 +149,10 @@ 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
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
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
|
||||
repository_server(str): url of the repository
|
||||
"""
|
||||
# allow_no_value=True is required because pacman uses boolean configuration in which just keys present
|
||||
@ -156,14 +160,14 @@ 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[method-assign]
|
||||
configuration.optionxform = lambda optionstr: optionstr # 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
|
||||
configuration.read(source)
|
||||
|
||||
# set our architecture now
|
||||
configuration.set_option("options", "Architecture", architecture)
|
||||
configuration.set_option("options", "Architecture", repository_id.architecture)
|
||||
|
||||
# add multilib
|
||||
if multilib:
|
||||
@ -178,10 +182,10 @@ class Setup(Handler):
|
||||
configuration.set_option(section, "Server", mirror)
|
||||
|
||||
# add repository itself
|
||||
configuration.set_option(repository, "SigLevel", "Never") # we don't care
|
||||
configuration.set_option(repository, "Server", repository_server)
|
||||
configuration.set_option(repository_id.name, "SigLevel", "Never") # we don't care
|
||||
configuration.set_option(repository_id.name, "Server", repository_server)
|
||||
|
||||
target = source.parent / f"{prefix}-{architecture}.conf"
|
||||
target = source.parent / f"{repository_id.name}-{repository_id.architecture}.conf"
|
||||
with target.open("w") as devtools_configuration:
|
||||
configuration.write(devtools_configuration)
|
||||
|
||||
@ -205,31 +209,29 @@ 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(paths: RepositoryPaths, repository_id: RepositoryId) -> 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
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
"""
|
||||
command = Setup.build_command(paths.root, prefix, architecture)
|
||||
sudoers_file = Setup.build_command(Setup.SUDOERS_DIR_PATH, prefix, architecture)
|
||||
command = Setup.build_command(paths.root, repository_id)
|
||||
sudoers_file = Setup.build_command(Setup.SUDOERS_DIR_PATH, repository_id)
|
||||
sudoers_file.write_text(f"ahriman ALL=(ALL) NOPASSWD:SETENV: {command} *\n", encoding="utf8")
|
||||
sudoers_file.chmod(0o400) # security!
|
||||
|
||||
@staticmethod
|
||||
def executable_create(paths: RepositoryPaths, prefix: str, architecture: str) -> None:
|
||||
def executable_create(paths: RepositoryPaths, repository_id: RepositoryId) -> None:
|
||||
"""
|
||||
create executable for the service
|
||||
|
||||
Args:
|
||||
paths(RepositoryPaths): repository paths instance
|
||||
prefix(str): command prefix in {prefix}-{architecture}-build
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
"""
|
||||
command = Setup.build_command(paths.root, prefix, architecture)
|
||||
command = Setup.build_command(paths.root, repository_id)
|
||||
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
|
||||
|
@ -26,6 +26,7 @@ from pathlib import Path
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.formatters import StringPrinter
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
|
||||
class Shell(Handler):
|
||||
@ -33,24 +34,31 @@ class Shell(Handler):
|
||||
python shell handler
|
||||
"""
|
||||
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN = False
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
if args.verbose:
|
||||
# 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)
|
||||
local_variables = {"architecture": architecture, "configuration": configuration}
|
||||
StringPrinter(path.read_text(encoding="utf8"))(verbose=False)
|
||||
|
||||
local_variables = {
|
||||
"architecture": repository_id.architecture,
|
||||
"configuration": configuration,
|
||||
"repository_id": repository_id,
|
||||
}
|
||||
|
||||
if args.code is None:
|
||||
code.interact(local=local_variables)
|
||||
else:
|
||||
|
@ -22,6 +22,7 @@ import argparse
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
|
||||
class Sign(Handler):
|
||||
@ -30,14 +31,15 @@ class Sign(Handler):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
Application(architecture, configuration, report=report).sign(args.package)
|
||||
Application(repository_id, configuration, report=report).sign(args.package)
|
||||
|
@ -27,6 +27,7 @@ from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.formatters import PackagePrinter, StatusPrinter
|
||||
from ahriman.models.build_status import BuildStatus
|
||||
from ahriman.models.package import Package
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
|
||||
class Status(Handler):
|
||||
@ -34,24 +35,25 @@ class Status(Handler):
|
||||
package status handler
|
||||
"""
|
||||
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
# we are using reporter here
|
||||
client = Application(architecture, configuration, report=True).repository.reporter
|
||||
client = Application(repository_id, configuration, report=True).repository.reporter
|
||||
if args.ahriman:
|
||||
service_status = client.status_get()
|
||||
StatusPrinter(service_status.status).print(verbose=args.info)
|
||||
StatusPrinter(service_status.status)(verbose=args.info)
|
||||
if args.package:
|
||||
packages: list[tuple[Package, BuildStatus]] = sum(
|
||||
(client.package_get(base) for base in args.package),
|
||||
@ -65,4 +67,4 @@ class Status(Handler):
|
||||
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(verbose=args.info)
|
||||
PackagePrinter(package, package_status)(verbose=args.info)
|
||||
|
@ -23,6 +23,7 @@ from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.action import Action
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
|
||||
class StatusUpdate(Handler):
|
||||
@ -30,27 +31,32 @@ class StatusUpdate(Handler):
|
||||
status update handler
|
||||
"""
|
||||
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
# we are using reporter here
|
||||
client = Application(architecture, configuration, report=True).repository.reporter
|
||||
application = Application(repository_id, configuration, report=True)
|
||||
client = application.repository.reporter
|
||||
|
||||
match args.action:
|
||||
case Action.Update if args.package:
|
||||
# update packages statuses
|
||||
for package in args.package:
|
||||
client.package_update(package, args.status)
|
||||
packages = application.repository.packages()
|
||||
for base in args.package:
|
||||
if (local := next((package for package in packages if package.base == base), None)) is not None:
|
||||
client.package_add(local, args.status)
|
||||
else:
|
||||
client.package_update(base, args.status)
|
||||
case Action.Update:
|
||||
# update service status
|
||||
client.status_update(args.status)
|
||||
|
@ -24,6 +24,7 @@ from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.formatters import StringPrinter, TreePrinter
|
||||
from ahriman.core.tree import Tree
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
|
||||
class Structure(Handler):
|
||||
@ -31,28 +32,29 @@ class Structure(Handler):
|
||||
dump repository structure handler
|
||||
"""
|
||||
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
application = Application(architecture, configuration, report=report)
|
||||
application = Application(repository_id, configuration, report=report)
|
||||
partitions = Tree.partition(application.repository.packages(), count=args.partitions)
|
||||
|
||||
for partition_id, partition in enumerate(partitions):
|
||||
StringPrinter(f"partition #{partition_id}").print(verbose=False)
|
||||
StringPrinter(f"partition #{partition_id}")(verbose=False)
|
||||
|
||||
tree = Tree.resolve(partition)
|
||||
for num, level in enumerate(tree):
|
||||
TreePrinter(num, level).print(verbose=True, separator=" ")
|
||||
TreePrinter(num, level)(verbose=True, separator=" ")
|
||||
|
||||
# empty line
|
||||
StringPrinter("").print(verbose=False)
|
||||
StringPrinter("")(verbose=False)
|
||||
|
68
src/ahriman/application/handlers/tree_migrate.py
Normal file
68
src/ahriman/application/handlers/tree_migrate.py
Normal file
@ -0,0 +1,68 @@
|
||||
#
|
||||
# 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.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
from ahriman.models.repository_paths import RepositoryPaths
|
||||
|
||||
|
||||
class TreeMigrate(Handler):
|
||||
"""
|
||||
tree migration handler
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
current_tree = configuration.repository_paths
|
||||
target_tree = RepositoryPaths(current_tree.root, current_tree.repository_id, _force_current_tree=True)
|
||||
|
||||
# create repository tree
|
||||
target_tree.tree_create()
|
||||
# perform migration
|
||||
TreeMigrate.tree_move(current_tree, target_tree)
|
||||
|
||||
@staticmethod
|
||||
def tree_move(from_tree: RepositoryPaths, to_tree: RepositoryPaths) -> None:
|
||||
"""
|
||||
move files between trees. Trees must be created in advance
|
||||
|
||||
Args:
|
||||
from_tree(RepositoryPaths): old repository tree
|
||||
to_tree(RepositoryPaths): new repository tree
|
||||
"""
|
||||
# we don't care about devtools chroot
|
||||
for attribute in (
|
||||
RepositoryPaths.packages,
|
||||
RepositoryPaths.pacman,
|
||||
RepositoryPaths.repository,
|
||||
):
|
||||
attribute.fget(from_tree).rename(attribute.fget(to_tree)) # type: ignore[attr-defined]
|
@ -22,6 +22,7 @@ import argparse
|
||||
from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
from ahriman.models.result import Result
|
||||
|
||||
|
||||
@ -31,19 +32,20 @@ class Triggers(Handler):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
application = Application(architecture, configuration, report=report)
|
||||
application = Application(repository_id, configuration, report=report)
|
||||
if args.trigger:
|
||||
loader = application.repository.triggers
|
||||
loader.triggers = [loader.load_trigger(trigger, architecture, configuration) for trigger in args.trigger]
|
||||
loader.triggers = [loader.load_trigger(trigger, repository_id, configuration) for trigger in args.trigger]
|
||||
application.on_start()
|
||||
application.on_result(Result())
|
||||
|
@ -22,6 +22,7 @@ import argparse
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.formatters import StringPrinter
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
|
||||
class UnsafeCommands(Handler):
|
||||
@ -29,16 +30,17 @@ class UnsafeCommands(Handler):
|
||||
unsafe command help parser
|
||||
"""
|
||||
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
@ -48,7 +50,7 @@ class UnsafeCommands(Handler):
|
||||
UnsafeCommands.check_unsafe(args.command, unsafe_commands, parser)
|
||||
else:
|
||||
for command in unsafe_commands:
|
||||
StringPrinter(command).print(verbose=True)
|
||||
StringPrinter(command)(verbose=True)
|
||||
|
||||
@staticmethod
|
||||
def check_unsafe(command: list[str], unsafe_commands: list[str], parser: argparse.ArgumentParser) -> None:
|
||||
|
@ -25,6 +25,7 @@ from ahriman.application.application import Application
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.models.packagers import Packagers
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
|
||||
class Update(Handler):
|
||||
@ -33,17 +34,18 @@ class Update(Handler):
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
application = Application(architecture, configuration, report=report, refresh_pacman_database=args.refresh)
|
||||
application = Application(repository_id, configuration, report=report, refresh_pacman_database=args.refresh)
|
||||
application.on_start()
|
||||
packages = application.updates(args.package, aur=args.aur, local=args.local, manual=args.manual, vcs=args.vcs)
|
||||
Update.check_if_empty(args.exit_code, not packages)
|
||||
|
@ -26,6 +26,7 @@ from ahriman.core.database import SQLite
|
||||
from ahriman.core.exceptions import PasswordError
|
||||
from ahriman.core.formatters import UserPrinter
|
||||
from ahriman.models.action import Action
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
from ahriman.models.user import User
|
||||
|
||||
|
||||
@ -34,16 +35,17 @@ class Users(Handler):
|
||||
user management handler
|
||||
"""
|
||||
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
@ -59,7 +61,7 @@ class Users(Handler):
|
||||
users = database.user_list(args.username, args.role)
|
||||
Users.check_if_empty(args.exit_code, not users)
|
||||
for user in users:
|
||||
UserPrinter(user).print(verbose=True)
|
||||
UserPrinter(user)(verbose=True)
|
||||
case Action.Remove:
|
||||
database.user_remove(args.username)
|
||||
|
||||
|
@ -29,6 +29,7 @@ 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
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
|
||||
class Validate(Handler):
|
||||
@ -36,37 +37,38 @@ class Validate(Handler):
|
||||
configuration validator handler
|
||||
"""
|
||||
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
schema = Validate.schema(architecture, configuration)
|
||||
schema = Validate.schema(repository_id, 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)
|
||||
ValidationPrinter(node, errors)(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:
|
||||
def schema(repository_id: RepositoryId, configuration: Configuration) -> ConfigurationSchema:
|
||||
"""
|
||||
get schema with triggers
|
||||
|
||||
Args:
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
|
||||
Returns:
|
||||
@ -85,12 +87,12 @@ class Validate(Handler):
|
||||
continue
|
||||
|
||||
# default settings if any
|
||||
for schema_name, schema in trigger_class.configuration_schema(architecture, None).items():
|
||||
for schema_name, schema in trigger_class.configuration_schema(repository_id, 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():
|
||||
for schema_name, schema in trigger_class.configuration_schema(repository_id, configuration).items():
|
||||
root[schema_name] = Validate.schema_merge(root.get(schema_name, {}), copy.deepcopy(schema))
|
||||
|
||||
return root
|
||||
|
@ -28,6 +28,7 @@ from ahriman import __version__
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.formatters import VersionPrinter
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
|
||||
class Versions(Handler):
|
||||
@ -38,24 +39,25 @@ class Versions(Handler):
|
||||
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"
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
||||
PEP423_PACKAGE_NAME = re.compile(r"^[A-Za-z0-9._-]+")
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
VersionPrinter(f"Module version {__version__}",
|
||||
{"Python": sys.version}).print(verbose=False, separator=" ")
|
||||
{"Python": sys.version})(verbose=False, separator=" ")
|
||||
packages = Versions.package_dependencies("ahriman")
|
||||
VersionPrinter("Installed packages", dict(packages)).print(verbose=False, separator=" ")
|
||||
VersionPrinter("Installed packages", dict(packages))(verbose=False, separator=" ")
|
||||
|
||||
@staticmethod
|
||||
def package_dependencies(root: str) -> Generator[tuple[str, str], None, None]:
|
||||
|
@ -24,6 +24,7 @@ from collections.abc import Generator
|
||||
from ahriman.application.handlers import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
from ahriman.core.spawn import Spawn
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
|
||||
|
||||
class Web(Handler):
|
||||
@ -31,28 +32,35 @@ class Web(Handler):
|
||||
web server handler
|
||||
"""
|
||||
|
||||
ALLOW_AUTO_ARCHITECTURE_RUN = False
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # required to be able to spawn external processes
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, architecture: str, configuration: Configuration, *, report: bool) -> None:
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
# we are using local import for optional dependencies
|
||||
from ahriman.web.web import run_server, setup_service
|
||||
from ahriman.web.web import run_server, setup_server
|
||||
|
||||
spawner_args = Web.extract_arguments(args, architecture, configuration)
|
||||
spawner = Spawn(args.parser(), architecture, list(spawner_args))
|
||||
spawner_args = Web.extract_arguments(args, configuration)
|
||||
spawner = Spawn(args.parser(), list(spawner_args))
|
||||
spawner.start()
|
||||
|
||||
application = setup_service(architecture, configuration, spawner)
|
||||
dummy_args = argparse.Namespace(
|
||||
architecture=None,
|
||||
configuration=args.configuration,
|
||||
repository=None,
|
||||
repository_id=None,
|
||||
)
|
||||
repositories = cls.repositories_extract(dummy_args)
|
||||
application = setup_server(configuration, spawner, repositories)
|
||||
run_server(application)
|
||||
|
||||
# terminate spawn process at the last
|
||||
@ -60,21 +68,17 @@ class Web(Handler):
|
||||
spawner.join()
|
||||
|
||||
@staticmethod
|
||||
def extract_arguments(args: argparse.Namespace, architecture: str,
|
||||
configuration: Configuration) -> Generator[str, None, None]:
|
||||
def extract_arguments(args: argparse.Namespace, configuration: Configuration) -> Generator[str, None, None]:
|
||||
"""
|
||||
extract list of arguments used for current command, except for command specific ones
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
configuration(Configuration): configuration instance
|
||||
|
||||
Returns:
|
||||
Generator[str, None, None]: command line arguments which were used for this specific command
|
||||
"""
|
||||
# read architecture from the same argument list
|
||||
yield from ["--architecture", architecture]
|
||||
# read configuration path from current settings
|
||||
if (configuration_path := configuration.path) is not None:
|
||||
yield from ["--configuration", str(configuration_path)]
|
||||
|
@ -30,6 +30,7 @@ from ahriman.core.log import LazyLogging
|
||||
from ahriman.core.status.client import Client
|
||||
from ahriman.core.util import check_user
|
||||
from ahriman.models.build_status import BuildStatusEnum
|
||||
from ahriman.models.repository_id import RepositoryId
|
||||
from ahriman.models.waiter import Waiter
|
||||
|
||||
|
||||
@ -50,32 +51,34 @@ class Lock(LazyLogging):
|
||||
The common flow is to create instance in ``with`` block and handle exceptions after all::
|
||||
|
||||
>>> from ahriman.core.configuration import Configuration
|
||||
>>> from ahriman.models.repository_id import RepositoryId
|
||||
>>>
|
||||
>>> configuration = Configuration()
|
||||
>>> try:
|
||||
>>> with Lock(args, "x86_64", configuration):
|
||||
>>> with Lock(args, RepositoryId("x86_64", "aur-clone"), configuration):
|
||||
>>> perform_actions()
|
||||
>>> except Exception as exception:
|
||||
>>> handle_exceptions(exception)
|
||||
"""
|
||||
|
||||
def __init__(self, args: argparse.Namespace, architecture: str, configuration: Configuration) -> None:
|
||||
def __init__(self, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration) -> None:
|
||||
"""
|
||||
default constructor
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
"""
|
||||
self.path: Path | None = \
|
||||
args.lock.with_stem(f"{args.lock.stem}_{architecture}") if args.lock is not None else None
|
||||
args.lock.with_stem(f"{args.lock.stem}_{repository_id.id}") if args.lock is not None else None
|
||||
|
||||
self.force: bool = args.force
|
||||
self.unsafe: bool = args.unsafe
|
||||
self.wait_timeout: int = args.wait_timeout
|
||||
|
||||
self.paths = configuration.repository_paths
|
||||
self.reporter = Client.load(configuration, report=args.report)
|
||||
self.reporter = Client.load(repository_id, configuration, report=args.report)
|
||||
|
||||
def check_version(self) -> None:
|
||||
"""
|
||||
|
@ -22,12 +22,14 @@ import shutil
|
||||
from collections.abc import Callable, Generator
|
||||
from functools import cached_property
|
||||
from pathlib import Path
|
||||
from pyalpm import DB, Handle, Package, SIG_PACKAGE, error as PyalpmError # type: ignore[import]
|
||||
from pyalpm import DB, Handle, Package, SIG_PACKAGE, error as PyalpmError # type: ignore[import-not-found]
|
||||
from string import Template
|
||||
|
||||
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_id import RepositoryId
|
||||
from ahriman.models.repository_paths import RepositoryPaths
|
||||
|
||||
|
||||
@ -36,18 +38,18 @@ class Pacman(LazyLogging):
|
||||
alpm wrapper
|
||||
"""
|
||||
|
||||
def __init__(self, architecture: str, configuration: Configuration, *,
|
||||
def __init__(self, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
refresh_database: PacmanSynchronization) -> None:
|
||||
"""
|
||||
default constructor
|
||||
|
||||
Args:
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
refresh_database(PacmanSynchronization): synchronize local cache to remote
|
||||
"""
|
||||
self.__create_handle_fn: Callable[[], Handle] = lambda: self.__create_handle(
|
||||
architecture, configuration, refresh_database=refresh_database)
|
||||
repository_id, configuration, refresh_database=refresh_database)
|
||||
|
||||
@cached_property
|
||||
def handle(self) -> Handle:
|
||||
@ -59,13 +61,13 @@ class Pacman(LazyLogging):
|
||||
"""
|
||||
return self.__create_handle_fn()
|
||||
|
||||
def __create_handle(self, architecture: str, configuration: Configuration, *,
|
||||
def __create_handle(self, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
refresh_database: PacmanSynchronization) -> Handle:
|
||||
"""
|
||||
create lazy handle function
|
||||
|
||||
Args:
|
||||
architecture(str): repository architecture
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
refresh_database(PacmanSynchronization): synchronize local cache to remote
|
||||
|
||||
@ -81,7 +83,7 @@ class Pacman(LazyLogging):
|
||||
|
||||
handle = Handle(str(root), str(database_path))
|
||||
for repository in configuration.getlist("alpm", "repositories"):
|
||||
database = self.database_init(handle, repository, mirror, architecture)
|
||||
database = self.database_init(handle, repository, mirror, repository_id.architecture)
|
||||
self.database_copy(handle, database, pacman_root, paths, use_ahriman_cache=use_ahriman_cache)
|
||||
|
||||
if use_ahriman_cache and refresh_database:
|
||||
@ -113,6 +115,7 @@ class Pacman(LazyLogging):
|
||||
dst = repository_database(pacman_db_path)
|
||||
if dst.is_file():
|
||||
return # file already exists, do not copy
|
||||
dst.parent.mkdir(mode=0o755, exist_ok=True) # create sync directory if it doesn't exist
|
||||
src = repository_database(pacman_root)
|
||||
if not src.is_file():
|
||||
self.logger.warning("repository %s is set to be used, however, no working copy was found", database.name)
|
||||
@ -136,8 +139,14 @@ class Pacman(LazyLogging):
|
||||
"""
|
||||
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)]
|
||||
variables = {
|
||||
"arch": architecture,
|
||||
"repo": repository,
|
||||
}
|
||||
database.servers = [Template(mirror).safe_substitute(variables)]
|
||||
|
||||
return database
|
||||
|
||||
def database_sync(self, handle: Handle, *, force: bool) -> None:
|
||||
|
@ -113,13 +113,13 @@ class AUR(Remote):
|
||||
response = self.make_request("GET", self.DEFAULT_RPC_URL, params=query)
|
||||
return self.parse_response(response.json())
|
||||
|
||||
def package_info(self, package_name: str, *, pacman: Pacman) -> AURPackage:
|
||||
def package_info(self, package_name: str, *, pacman: Pacman | None) -> AURPackage:
|
||||
"""
|
||||
get package info by its name
|
||||
|
||||
Args:
|
||||
package_name(str): package name to search
|
||||
pacman(Pacman): alpm wrapper instance
|
||||
pacman(Pacman | None): alpm wrapper instance, required for official repositories search
|
||||
|
||||
Returns:
|
||||
AURPackage: package which match the package name
|
||||
@ -133,13 +133,13 @@ class AUR(Remote):
|
||||
except StopIteration:
|
||||
raise UnknownPackageError(package_name) from None
|
||||
|
||||
def package_search(self, *keywords: str, pacman: Pacman) -> list[AURPackage]:
|
||||
def package_search(self, *keywords: str, pacman: Pacman | None) -> list[AURPackage]:
|
||||
"""
|
||||
search package in AUR web
|
||||
|
||||
Args:
|
||||
*keywords(str): keywords to search
|
||||
pacman(Pacman): alpm wrapper instance
|
||||
pacman(Pacman | None): alpm wrapper instance, required for official repositories search
|
||||
|
||||
Returns:
|
||||
list[AURPackage]: list of packages which match the criteria
|
||||
|
@ -107,13 +107,13 @@ class Official(Remote):
|
||||
response = self.make_request("GET", self.DEFAULT_RPC_URL, params=query)
|
||||
return self.parse_response(response.json())
|
||||
|
||||
def package_info(self, package_name: str, *, pacman: Pacman) -> AURPackage:
|
||||
def package_info(self, package_name: str, *, pacman: Pacman | None) -> AURPackage:
|
||||
"""
|
||||
get package info by its name
|
||||
|
||||
Args:
|
||||
package_name(str): package name to search
|
||||
pacman(Pacman): alpm wrapper instance
|
||||
pacman(Pacman | None): alpm wrapper instance, required for official repositories search
|
||||
|
||||
Returns:
|
||||
AURPackage: package which match the package name
|
||||
@ -127,13 +127,13 @@ class Official(Remote):
|
||||
except StopIteration:
|
||||
raise UnknownPackageError(package_name) from None
|
||||
|
||||
def package_search(self, *keywords: str, pacman: Pacman) -> list[AURPackage]:
|
||||
def package_search(self, *keywords: str, pacman: Pacman | None) -> list[AURPackage]:
|
||||
"""
|
||||
search package in AUR web
|
||||
|
||||
Args:
|
||||
*keywords(str): keywords to search
|
||||
pacman(Pacman): alpm wrapper instance
|
||||
pacman(Pacman | None): alpm wrapper instance, required for official repositories search
|
||||
|
||||
Returns:
|
||||
list[AURPackage]: list of packages which match the criteria
|
||||
|
@ -38,13 +38,13 @@ class OfficialSyncdb(Official):
|
||||
Still we leave search function based on the official repositories RPC.
|
||||
"""
|
||||
|
||||
def package_info(self, package_name: str, *, pacman: Pacman) -> AURPackage:
|
||||
def package_info(self, package_name: str, *, pacman: Pacman | None) -> AURPackage:
|
||||
"""
|
||||
get package info by its name
|
||||
|
||||
Args:
|
||||
package_name(str): package name to search
|
||||
pacman(Pacman): alpm wrapper instance
|
||||
pacman(Pacman | None): alpm wrapper instance, required for official repositories search
|
||||
|
||||
Returns:
|
||||
AURPackage: package which match the package name
|
||||
@ -52,6 +52,9 @@ class OfficialSyncdb(Official):
|
||||
Raises:
|
||||
UnknownPackageError: package doesn't exist
|
||||
"""
|
||||
if pacman is None:
|
||||
raise UnknownPackageError(package_name)
|
||||
|
||||
try:
|
||||
return next(AURPackage.from_pacman(package) for package in pacman.package_get(package_name))
|
||||
except StopIteration:
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user