mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-04-24 15:27:17 +00:00
Compare commits
25 Commits
Author | SHA1 | Date | |
---|---|---|---|
d283dccc1e | |||
8a4e900ab9 | |||
fa6cf8ce36 | |||
a706fbb751 | |||
9a23f5c79d | |||
aaab9069bf | |||
f00b575641 | |||
6f57ed550b | |||
08640d9108 | |||
65324633b4 | |||
ed67898012 | |||
a1a8dd68e8 | |||
a9505386c2 | |||
a07b20bf50 | |||
ed70897c39 | |||
0423c3e67c | |||
571f62327f | |||
286ff4bcef | |||
0660c33de3 | |||
c8421e97ee | |||
bc2288afc1 | |||
503c8b0355 | |||
6738f9206d | |||
f865e998b0 | |||
4880ca4fee |
2
.github/workflows/setup.sh
vendored
2
.github/workflows/setup.sh
vendored
@ -18,7 +18,7 @@ if [[ -z $MINIMAL_INSTALL ]]; then
|
|||||||
# web server
|
# web server
|
||||||
pacman -S --noconfirm python-aioauth-client python-aiohttp python-aiohttp-apispec-git python-aiohttp-cors python-aiohttp-jinja2 python-aiohttp-security python-aiohttp-session python-cryptography python-jinja
|
pacman -S --noconfirm python-aioauth-client python-aiohttp python-aiohttp-apispec-git python-aiohttp-cors python-aiohttp-jinja2 python-aiohttp-security python-aiohttp-session python-cryptography python-jinja
|
||||||
# additional features
|
# additional features
|
||||||
pacman -S --noconfirm gnupg python-boto3 python-cerberus python-matplotlib rsync
|
pacman -S --noconfirm gnupg ipython python-boto3 python-cerberus python-matplotlib rsync
|
||||||
fi
|
fi
|
||||||
# FIXME since 1.0.4 devtools requires dbus to be run, which doesn't work now in container
|
# FIXME since 1.0.4 devtools requires dbus to be run, which doesn't work now in container
|
||||||
cp "docker/systemd-nspawn.sh" "/usr/local/bin/systemd-nspawn"
|
cp "docker/systemd-nspawn.sh" "/usr/local/bin/systemd-nspawn"
|
||||||
|
@ -305,7 +305,7 @@ max-branches=12
|
|||||||
max-locals=15
|
max-locals=15
|
||||||
|
|
||||||
# Maximum number of parents for a class (see R0901).
|
# Maximum number of parents for a class (see R0901).
|
||||||
max-parents=7
|
max-parents=15
|
||||||
|
|
||||||
# Maximum number of public methods for a class (see R0904).
|
# Maximum number of public methods for a class (see R0904).
|
||||||
max-public-methods=20
|
max-public-methods=20
|
||||||
|
@ -80,7 +80,7 @@ Again, the most checks can be performed by `tox` command, though some additional
|
|||||||
>>> clazz = Clazz()
|
>>> clazz = Clazz()
|
||||||
"""
|
"""
|
||||||
|
|
||||||
CLAZZ_ATTRIBUTE = 42
|
CLAZZ_ATTRIBUTE: ClassVar[int] = 42
|
||||||
|
|
||||||
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
||||||
"""
|
"""
|
||||||
@ -96,6 +96,7 @@ Again, the most checks can be performed by `tox` command, though some additional
|
|||||||
* Type annotations are the must, even for local functions. For the function argument `self` (for instance methods) and `cls` (for class methods) should not be annotated.
|
* Type annotations are the must, even for local functions. For the function argument `self` (for instance methods) and `cls` (for class methods) should not be annotated.
|
||||||
* For collection types built-in classes must be used if possible (e.g. `dict` instead of `typing.Dict`, `tuple` instead of `typing.Tuple`). In case if built-in type is not available, but `collections.abc` provides interface, it must be used (e.g. `collections.abc.Awaitable` instead of `typing.Awaitable`, `collections.abc.Iterable` instead of `typing.Iterable`). For union classes, the bar operator (`|`) must be used (e.g. `float | int` instead of `typing.Union[float, int]`), which also includes `typing.Optional` (e.g. `str | None` instead of `Optional[str]`).
|
* For collection types built-in classes must be used if possible (e.g. `dict` instead of `typing.Dict`, `tuple` instead of `typing.Tuple`). In case if built-in type is not available, but `collections.abc` provides interface, it must be used (e.g. `collections.abc.Awaitable` instead of `typing.Awaitable`, `collections.abc.Iterable` instead of `typing.Iterable`). For union classes, the bar operator (`|`) must be used (e.g. `float | int` instead of `typing.Union[float, int]`), which also includes `typing.Optional` (e.g. `str | None` instead of `Optional[str]`).
|
||||||
* `classmethod` should (almost) always return `Self`. In case of mypy warning (e.g. if there is a branch in which function doesn't return the instance of `cls`) consider using `staticmethod` instead.
|
* `classmethod` should (almost) always return `Self`. In case of mypy warning (e.g. if there is a branch in which function doesn't return the instance of `cls`) consider using `staticmethod` instead.
|
||||||
|
* Class attributes must be decorated as `ClassVar[...]`.
|
||||||
* Recommended order of function definitions in class:
|
* Recommended order of function definitions in class:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
@ -175,11 +176,10 @@ Again, the most checks can be performed by `tox` command, though some additional
|
|||||||
* Web API methods must be documented by using `aiohttp_apispec` library. The schema testing mostly should be implemented in related view class tests. Recommended example for documentation (excluding comments):
|
* Web API methods must be documented by using `aiohttp_apispec` library. The schema testing mostly should be implemented in related view class tests. Recommended example for documentation (excluding comments):
|
||||||
|
|
||||||
```python
|
```python
|
||||||
import aiohttp_apispec
|
|
||||||
|
|
||||||
from marshmallow import Schema, fields
|
from marshmallow import Schema, fields
|
||||||
|
|
||||||
from ahriman.web.schemas import AuthSchema, ErrorSchema, PackageNameSchema, PaginationSchema
|
from ahriman.web.apispec.decorators import apidocs
|
||||||
|
from ahriman.web.schemas import PackageNameSchema, PaginationSchema
|
||||||
from ahriman.web.views.base import BaseView
|
from ahriman.web.views.base import BaseView
|
||||||
|
|
||||||
|
|
||||||
@ -198,25 +198,17 @@ Again, the most checks can be performed by `tox` command, though some additional
|
|||||||
POST_PERMISSION = ...
|
POST_PERMISSION = ...
|
||||||
ROUTES = ...
|
ROUTES = ...
|
||||||
|
|
||||||
@aiohttp_apispec.docs(
|
@apidocs(
|
||||||
tags=["Tag"],
|
tags=["Tag"],
|
||||||
summary="Do foo",
|
summary="Do foo",
|
||||||
description="Extended description of the method which does foo",
|
description="Extended description of the method which does foo",
|
||||||
responses={
|
error_400_enabled=True, # exception raised by this method
|
||||||
200: {"description": "Success response", "schema": ResponseSchema},
|
error_404_description="Repository is unknown",
|
||||||
204: {"description": "Success response"}, # example without json schema response
|
schema=ResponseSchema, # leave empty if no responses here
|
||||||
400: {"description": "Bad data is supplied", "schema": ErrorSchema}, # exception raised by this method
|
match_schema=PackageNameSchema,
|
||||||
401: {"description": "Authorization required", "schema": ErrorSchema}, # should be always presented
|
query_schema=PaginationSchema,
|
||||||
403: {"description": "Access is forbidden", "schema": ErrorSchema}, # should be always presented
|
body_schema=RequestSchema(many=True),
|
||||||
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: ...
|
async def post(self) -> None: ...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -108,9 +108,7 @@ RUN cp "/etc/pacman.d/mirrorlist" "/etc/pacman.d/mirrorlist.orig" && \
|
|||||||
sed -i "s/SigLevel *=.*/SigLevel = Optional/g" "/etc/pacman.conf" && \
|
sed -i "s/SigLevel *=.*/SigLevel = Optional/g" "/etc/pacman.conf" && \
|
||||||
pacman -Sy
|
pacman -Sy
|
||||||
## install package and its optional dependencies
|
## install package and its optional dependencies
|
||||||
RUN pacman -S --noconfirm \
|
RUN pacman -S --noconfirm ahriman
|
||||||
--assume-installed python-aiohttp-apispec=3.0.0 \
|
|
||||||
ahriman
|
|
||||||
RUN pacman -S --noconfirm --asdeps \
|
RUN pacman -S --noconfirm --asdeps \
|
||||||
python-aioauth-client \
|
python-aioauth-client \
|
||||||
python-aiohttp-apispec-git \
|
python-aiohttp-apispec-git \
|
||||||
|
3632
docs/_static/architecture.dot
vendored
3632
docs/_static/architecture.dot
vendored
File diff suppressed because it is too large
Load Diff
@ -29,6 +29,14 @@ ahriman.application.help\_formatter module
|
|||||||
:no-undoc-members:
|
:no-undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
|
ahriman.application.interactive\_shell module
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
.. automodule:: ahriman.application.interactive_shell
|
||||||
|
:members:
|
||||||
|
:no-undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
ahriman.application.lock module
|
ahriman.application.lock module
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
||||||
|
@ -124,6 +124,14 @@ ahriman.core.database.migrations.m014\_auditlog module
|
|||||||
:no-undoc-members:
|
:no-undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
|
ahriman.core.database.migrations.m015\_logs\_process\_id module
|
||||||
|
---------------------------------------------------------------
|
||||||
|
|
||||||
|
.. automodule:: ahriman.core.database.migrations.m015_logs_process_id
|
||||||
|
:members:
|
||||||
|
:no-undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
Module contents
|
Module contents
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
@ -92,6 +92,14 @@ ahriman.core.formatters.repository\_printer module
|
|||||||
:no-undoc-members:
|
:no-undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
|
ahriman.core.formatters.repository\_stats\_printer module
|
||||||
|
---------------------------------------------------------
|
||||||
|
|
||||||
|
.. automodule:: ahriman.core.formatters.repository_stats_printer
|
||||||
|
:members:
|
||||||
|
:no-undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
ahriman.core.formatters.status\_printer module
|
ahriman.core.formatters.status\_printer module
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
|
|
||||||
|
@ -100,6 +100,14 @@ ahriman.models.log\_handler module
|
|||||||
:no-undoc-members:
|
:no-undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
|
ahriman.models.log\_record module
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
.. automodule:: ahriman.models.log_record
|
||||||
|
:members:
|
||||||
|
:no-undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
ahriman.models.log\_record\_id module
|
ahriman.models.log\_record\_id module
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|
||||||
@ -236,6 +244,14 @@ ahriman.models.repository\_paths module
|
|||||||
:no-undoc-members:
|
:no-undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
|
ahriman.models.repository\_stats module
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
.. automodule:: ahriman.models.repository_stats
|
||||||
|
:members:
|
||||||
|
:no-undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
ahriman.models.result module
|
ahriman.models.result module
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
@ -252,6 +268,14 @@ ahriman.models.scan\_paths module
|
|||||||
:no-undoc-members:
|
:no-undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
|
ahriman.models.series\_statistics module
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
.. automodule:: ahriman.models.series_statistics
|
||||||
|
:members:
|
||||||
|
:no-undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
ahriman.models.sign\_settings module
|
ahriman.models.sign\_settings module
|
||||||
------------------------------------
|
------------------------------------
|
||||||
|
|
||||||
|
29
docs/ahriman.web.apispec.rst
Normal file
29
docs/ahriman.web.apispec.rst
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
ahriman.web.apispec package
|
||||||
|
===========================
|
||||||
|
|
||||||
|
Submodules
|
||||||
|
----------
|
||||||
|
|
||||||
|
ahriman.web.apispec.decorators module
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
.. automodule:: ahriman.web.apispec.decorators
|
||||||
|
:members:
|
||||||
|
:no-undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
ahriman.web.apispec.info module
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
.. automodule:: ahriman.web.apispec.info
|
||||||
|
:members:
|
||||||
|
:no-undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
Module contents
|
||||||
|
---------------
|
||||||
|
|
||||||
|
.. automodule:: ahriman.web.apispec
|
||||||
|
:members:
|
||||||
|
:no-undoc-members:
|
||||||
|
:show-inheritance:
|
@ -7,6 +7,7 @@ Subpackages
|
|||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 4
|
:maxdepth: 4
|
||||||
|
|
||||||
|
ahriman.web.apispec
|
||||||
ahriman.web.middlewares
|
ahriman.web.middlewares
|
||||||
ahriman.web.schemas
|
ahriman.web.schemas
|
||||||
ahriman.web.views
|
ahriman.web.views
|
||||||
@ -14,14 +15,6 @@ Subpackages
|
|||||||
Submodules
|
Submodules
|
||||||
----------
|
----------
|
||||||
|
|
||||||
ahriman.web.apispec module
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
.. automodule:: ahriman.web.apispec
|
|
||||||
:members:
|
|
||||||
:no-undoc-members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
ahriman.web.cors module
|
ahriman.web.cors module
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
|
@ -116,6 +116,14 @@ ahriman.web.schemas.login\_schema module
|
|||||||
:no-undoc-members:
|
:no-undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
|
ahriman.web.schemas.logs\_rotate\_schema module
|
||||||
|
-----------------------------------------------
|
||||||
|
|
||||||
|
.. automodule:: ahriman.web.schemas.logs_rotate_schema
|
||||||
|
:members:
|
||||||
|
:no-undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
ahriman.web.schemas.logs\_schema module
|
ahriman.web.schemas.logs\_schema module
|
||||||
---------------------------------------
|
---------------------------------------
|
||||||
|
|
||||||
@ -260,6 +268,14 @@ ahriman.web.schemas.repository\_id\_schema module
|
|||||||
:no-undoc-members:
|
:no-undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
|
ahriman.web.schemas.repository\_stats\_schema module
|
||||||
|
----------------------------------------------------
|
||||||
|
|
||||||
|
.. automodule:: ahriman.web.schemas.repository_stats_schema
|
||||||
|
:members:
|
||||||
|
:no-undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
ahriman.web.schemas.search\_schema module
|
ahriman.web.schemas.search\_schema module
|
||||||
-----------------------------------------
|
-----------------------------------------
|
||||||
|
|
||||||
@ -284,14 +300,6 @@ ahriman.web.schemas.update\_flags\_schema module
|
|||||||
:no-undoc-members:
|
:no-undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
ahriman.web.schemas.versioned\_log\_schema module
|
|
||||||
-------------------------------------------------
|
|
||||||
|
|
||||||
.. automodule:: ahriman.web.schemas.versioned_log_schema
|
|
||||||
:members:
|
|
||||||
:no-undoc-members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
ahriman.web.schemas.worker\_schema module
|
ahriman.web.schemas.worker\_schema module
|
||||||
-----------------------------------------
|
-----------------------------------------
|
||||||
|
|
||||||
|
@ -12,6 +12,14 @@ ahriman.web.views.v1.service.add module
|
|||||||
:no-undoc-members:
|
:no-undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
|
ahriman.web.views.v1.service.logs module
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
.. automodule:: ahriman.web.views.v1.service.logs
|
||||||
|
:members:
|
||||||
|
:no-undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
ahriman.web.views.v1.service.pgp module
|
ahriman.web.views.v1.service.pgp module
|
||||||
---------------------------------------
|
---------------------------------------
|
||||||
|
|
||||||
|
@ -81,6 +81,7 @@ Base configuration settings.
|
|||||||
* ``apply_migrations`` - perform database migrations on the application start, boolean, optional, default ``yes``. Useful if you are using git version. Note, however, that this option must be changed only if you know what to do and going to handle migrations manually.
|
* ``apply_migrations`` - perform database migrations on the application start, boolean, optional, default ``yes``. Useful if you are using git version. Note, however, that this option must be changed only if you know what to do and going to handle migrations manually.
|
||||||
* ``database`` - path to the application SQLite database, string, required.
|
* ``database`` - path to the application SQLite database, string, required.
|
||||||
* ``include`` - path to directory with configuration files overrides, string, optional. Files will be read in alphabetical order.
|
* ``include`` - path to directory with configuration files overrides, string, optional. Files will be read in alphabetical order.
|
||||||
|
* ``keep_last_logs`` - amount of build logs to be kept for each package, integer, optional ,default ``0``. Logs will be cleared at the end of each process.
|
||||||
* ``logging`` - path to logging configuration, string, required. Check ``logging.ini`` for reference.
|
* ``logging`` - path to logging configuration, string, required. Check ``logging.ini`` for reference.
|
||||||
|
|
||||||
``alpm:*`` groups
|
``alpm:*`` groups
|
||||||
@ -217,7 +218,7 @@ Mirrorlist generator plugin
|
|||||||
``remote-pull`` group
|
``remote-pull`` group
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
Remote git source synchronization settings. Unlike ``Upload`` triggers those triggers are used for PKGBUILD synchronization - fetch from remote repository PKGBUILDs before updating process.
|
Remote git source synchronization settings. Unlike ``upload`` triggers those triggers are used for PKGBUILD synchronization - fetch from remote repository PKGBUILDs before updating process.
|
||||||
|
|
||||||
It supports authorization; to do so you'd need to prefix the URL with authorization part, e.g. ``https://key:token@github.com/arcan1s/ahriman.git``. It is highly recommended to use application tokens instead of your user authorization details. Alternatively, you can use any other option supported by git, e.g.:
|
It supports authorization; to do so you'd need to prefix the URL with authorization part, e.g. ``https://key:token@github.com/arcan1s/ahriman.git``. It is highly recommended to use application tokens instead of your user authorization details. Alternatively, you can use any other option supported by git, e.g.:
|
||||||
|
|
||||||
|
@ -56,6 +56,13 @@ Though originally I've created ahriman by trying to improve the project, it stil
|
|||||||
|
|
||||||
It is automation tools for ``repoctl`` mentioned above. Except for using shell it looks pretty cool and also offers some additional features like patches, remote synchronization (isn't it?) and reporting.
|
It is automation tools for ``repoctl`` mentioned above. Except for using shell it looks pretty cool and also offers some additional features like patches, remote synchronization (isn't it?) and reporting.
|
||||||
|
|
||||||
|
`AURCache <https://github.com/Lukas-Heiligenbrunner/AURCache>`__
|
||||||
|
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
|
||||||
|
|
||||||
|
That's really cool project if you are looking for simple service to build AUR packages. It provides very informative dashboard and easy to configure and use. However, it doesn't provide direct way to control build process (e.g. it is neither trivial to build packages for architectures which are not supported by default nor to change build flags).
|
||||||
|
|
||||||
|
Also this application relies on docker setup (e.g. builders are only available as special docker containers). In addition, it uses ``paru`` to build packages instead of ``devtools``.
|
||||||
|
|
||||||
How to check service logs
|
How to check service logs
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
@ -12,17 +12,20 @@ Initial setup
|
|||||||
|
|
||||||
sudo ahriman -a x86_64 -r aur service-setup ...
|
sudo ahriman -a x86_64 -r aur service-setup ...
|
||||||
|
|
||||||
``service-setup`` literally does the following steps:
|
.. admonition:: Details
|
||||||
|
:collapsible: closed
|
||||||
|
|
||||||
#.
|
``service-setup`` literally does the following steps:
|
||||||
Create ``/var/lib/ahriman/.makepkg.conf`` with ``makepkg.conf`` overrides if required (at least you might want to set ``PACKAGER``):
|
|
||||||
|
|
||||||
.. code-block:: shell
|
#.
|
||||||
|
Create ``/var/lib/ahriman/.makepkg.conf`` with ``makepkg.conf`` overrides if required (at least you might want to set ``PACKAGER``):
|
||||||
|
|
||||||
echo 'PACKAGER="ahriman bot <ahriman@example.com>"' | sudo -u ahriman tee -a /var/lib/ahriman/.makepkg.conf
|
.. code-block:: shell
|
||||||
|
|
||||||
#.
|
echo 'PACKAGER="ahriman bot <ahriman@example.com>"' | sudo -u ahriman tee -a /var/lib/ahriman/.makepkg.conf
|
||||||
Configure build tools (it is required for correct dependency management system):
|
|
||||||
|
#.
|
||||||
|
Configure build tools (it is required for correct dependency management system):
|
||||||
|
|
||||||
#.
|
#.
|
||||||
Create build command (you can choose any name for command, basically it should be ``{name}-{arch}-build``):
|
Create build command (you can choose any name for command, basically it should be ``{name}-{arch}-build``):
|
||||||
@ -67,7 +70,7 @@ Initial setup
|
|||||||
echo 'ahriman ALL=(ALL) NOPASSWD:SETENV: CARCHBUILD_CMD' | tee -a /etc/sudoers.d/ahriman
|
echo 'ahriman ALL=(ALL) NOPASSWD:SETENV: CARCHBUILD_CMD' | tee -a /etc/sudoers.d/ahriman
|
||||||
chmod 400 /etc/sudoers.d/ahriman
|
chmod 400 /etc/sudoers.d/ahriman
|
||||||
|
|
||||||
This command supports several arguments, kindly refer to its help message.
|
This command supports several arguments, kindly refer to its help message.
|
||||||
|
|
||||||
#.
|
#.
|
||||||
Start and enable ``ahriman@.timer`` via ``systemctl``:
|
Start and enable ``ahriman@.timer`` via ``systemctl``:
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
pkgbase='ahriman'
|
pkgbase='ahriman'
|
||||||
pkgname=('ahriman' 'ahriman-core' 'ahriman-triggers' 'ahriman-web')
|
pkgname=('ahriman' 'ahriman-core' 'ahriman-triggers' 'ahriman-web')
|
||||||
pkgver=2.16.0
|
pkgver=2.17.1
|
||||||
pkgrel=1
|
pkgrel=1
|
||||||
pkgdesc="ArcH linux ReposItory MANager"
|
pkgdesc="ArcH linux ReposItory MANager"
|
||||||
arch=('any')
|
arch=('any')
|
||||||
@ -30,6 +30,7 @@ package_ahriman-core() {
|
|||||||
pkgname='ahriman-core'
|
pkgname='ahriman-core'
|
||||||
optdepends=('ahriman-triggers: additional extensions for the application'
|
optdepends=('ahriman-triggers: additional extensions for the application'
|
||||||
'ahriman-web: web server'
|
'ahriman-web: web server'
|
||||||
|
'ipython: an enhanced shell interpreter'
|
||||||
'python-boto3: sync to s3'
|
'python-boto3: sync to s3'
|
||||||
'python-cerberus: configuration validator'
|
'python-cerberus: configuration validator'
|
||||||
'python-matplotlib: usage statistics chart'
|
'python-matplotlib: usage statistics chart'
|
||||||
@ -71,8 +72,9 @@ package_ahriman-triggers() {
|
|||||||
package_ahriman-web() {
|
package_ahriman-web() {
|
||||||
pkgname='ahriman-web'
|
pkgname='ahriman-web'
|
||||||
pkgdesc="ArcH linux ReposItory MANager, web server"
|
pkgdesc="ArcH linux ReposItory MANager, web server"
|
||||||
depends=("$pkgbase-core=$pkgver" 'python-aiohttp-apispec>=3.0.0' 'python-aiohttp-cors' 'python-aiohttp-jinja2')
|
depends=("$pkgbase-core=$pkgver" 'python-aiohttp-cors' 'python-aiohttp-jinja2')
|
||||||
optdepends=('python-aioauth-client: OAuth2 authorization support'
|
optdepends=('python-aioauth-client: OAuth2 authorization support'
|
||||||
|
'python-aiohttp-apispec>=3.0.0: autogenerated API documentation'
|
||||||
'python-aiohttp-security: authorization support'
|
'python-aiohttp-security: authorization support'
|
||||||
'python-aiohttp-session: authorization support'
|
'python-aiohttp-session: authorization support'
|
||||||
'python-cryptography: authorization support')
|
'python-cryptography: authorization support')
|
||||||
|
@ -7,6 +7,8 @@ logging = ahriman.ini.d/logging.ini
|
|||||||
;apply_migrations = yes
|
;apply_migrations = yes
|
||||||
; Path to the application SQLite database.
|
; Path to the application SQLite database.
|
||||||
database = ${repository:root}/ahriman.db
|
database = ${repository:root}/ahriman.db
|
||||||
|
; Keep last build logs for each package
|
||||||
|
keep_last_logs = 5
|
||||||
|
|
||||||
[alpm]
|
[alpm]
|
||||||
; Path to pacman system database cache.
|
; Path to pacman system database cache.
|
||||||
|
@ -15,12 +15,12 @@
|
|||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<nav class="navbar navbar-expand-lg">
|
<nav class="navbar navbar-expand-lg">
|
||||||
<div class="navbar-brand"><img src="/static/logo.svg" width="30" height="30" alt=""></div>
|
<div class="navbar-brand"><a href="https://github.com/arcan1s/ahriman" title="logo"><img src="/static/logo.svg" width="30" height="30" alt=""></a></div>
|
||||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#repositories-navbar-supported-content" aria-controls="repositories-navbar-supported-content" aria-expanded="false" aria-label="Toggle navigation">
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#repositories-navbar" aria-controls="repositories-navbar" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
<span class="navbar-toggler-icon"></span>
|
<span class="navbar-toggler-icon"></span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div id="repositories-navbar-supported-content" class="collapse navbar-collapse">
|
<div id="repositories-navbar" class="collapse navbar-collapse">
|
||||||
<ul id="repositories" class="nav nav-tabs">
|
<ul id="repositories" class="nav nav-tabs">
|
||||||
{% for repository in repositories %}
|
{% for repository in repositories %}
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
@ -36,7 +36,9 @@
|
|||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div id="toolbar" class="dropdown">
|
<div id="toolbar" class="dropdown">
|
||||||
<a id="badge-status" tabindex="0" role="button" class="btn btn-outline-secondary" data-bs-toggle="popover" data-bs-trigger="focus" data-bs-content="no run data"><i class="bi bi-info-circle"></i></a>
|
<button id="dashboard-button" type="button" class="btn btn-outline-secondary" data-bs-toggle="modal" data-bs-target="#dashboard-modal">
|
||||||
|
<i class="bi bi-info-circle"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
{% if not auth.enabled or auth.username is not none %}
|
{% if not auth.enabled or auth.username is not none %}
|
||||||
<button type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
<button type="button" class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
@ -119,7 +121,9 @@
|
|||||||
<li><a id="badge-version" class="nav-link" href="https://github.com/arcan1s/ahriman" title="sources"><i class="bi bi-github"></i> ahriman</a></li>
|
<li><a id="badge-version" class="nav-link" href="https://github.com/arcan1s/ahriman" title="sources"><i class="bi bi-github"></i> ahriman</a></li>
|
||||||
<li><a class="nav-link" href="https://github.com/arcan1s/ahriman/releases" title="releases list">releases</a></li>
|
<li><a class="nav-link" href="https://github.com/arcan1s/ahriman/releases" title="releases list">releases</a></li>
|
||||||
<li><a class="nav-link" href="https://github.com/arcan1s/ahriman/issues" title="issues tracker">report a bug</a></li>
|
<li><a class="nav-link" href="https://github.com/arcan1s/ahriman/issues" title="issues tracker">report a bug</a></li>
|
||||||
<li><a class="nav-link" href="/api-docs" title="API documentation">api</a></li>
|
{% if docs_enabled %}
|
||||||
|
<li><a class="nav-link" href="/api-docs" title="API documentation">api</a></li>
|
||||||
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
{% if index_url is not none %}
|
{% if index_url is not none %}
|
||||||
@ -150,6 +154,7 @@
|
|||||||
|
|
||||||
{% include "build-status/alerts.jinja2" %}
|
{% include "build-status/alerts.jinja2" %}
|
||||||
|
|
||||||
|
{% include "build-status/dashboard.jinja2" %}
|
||||||
{% include "build-status/package-add-modal.jinja2" %}
|
{% include "build-status/package-add-modal.jinja2" %}
|
||||||
{% include "build-status/package-rebuild-modal.jinja2" %}
|
{% include "build-status/package-rebuild-modal.jinja2" %}
|
||||||
{% include "build-status/key-import-modal.jinja2" %}
|
{% include "build-status/key-import-modal.jinja2" %}
|
||||||
|
@ -0,0 +1,76 @@
|
|||||||
|
<div id="dashboard-modal" tabindex="-1" role="dialog" class="modal fade">
|
||||||
|
<div class="modal-dialog modal-xl" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div id="dashboard-modal-header" class="modal-header">
|
||||||
|
<h4 class="modal-title">System health</h4>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="form-group row mt-2">
|
||||||
|
<div class="col-4 col-lg-2" style="text-align: right">Repository name</div>
|
||||||
|
<div id="dashboard-name" class="col-8 col-lg-3"></div>
|
||||||
|
<div class="col-4 col-lg-2" style="text-align: right">Repository architecture</div>
|
||||||
|
<div id="dashboard-architecture" class="col-8 col-lg-3"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group row mt-2">
|
||||||
|
<div class="col-4 col-lg-2" style="text-align: right">Current status</div>
|
||||||
|
<div id="dashboard-status" class="col-8 col-lg-3"></div>
|
||||||
|
<div class="col-4 col-lg-2" style="text-align: right">Updated at</div>
|
||||||
|
<div id="dashboard-status-timestamp" class="col-8 col-lg-3"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="dashboard-canvas" class="form-group row mt-2">
|
||||||
|
<div class="col-8 col-lg-6">
|
||||||
|
<canvas id="dashboard-packages-count-chart"></canvas>
|
||||||
|
</div>
|
||||||
|
<div class="col-8 col-lg-6">
|
||||||
|
<canvas id="dashboard-packages-statuses-chart"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-primary" data-bs-dismiss="modal"><i class="bi bi-x"></i><span class="d-none d-sm-inline"> close</span></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const dashboardModal = document.getElementById("dashboard-modal");
|
||||||
|
const dashboardModalHeader = document.getElementById("dashboard-modal-header");
|
||||||
|
|
||||||
|
const dashboardName = document.getElementById("dashboard-name");
|
||||||
|
const dashboardArchitecture = document.getElementById("dashboard-architecture");
|
||||||
|
const dashboardStatus = document.getElementById("dashboard-status");
|
||||||
|
const dashboardStatusTimestamp = document.getElementById("dashboard-status-timestamp");
|
||||||
|
|
||||||
|
const dashboardCanvas = document.getElementById("dashboard-canvas");
|
||||||
|
const dashboardPackagesStatusesChartCanvas = document.getElementById("dashboard-packages-statuses-chart");
|
||||||
|
let dashboardPackagesStatusesChart = null;
|
||||||
|
const dashboardPackagesCountChartCanvas = document.getElementById("dashboard-packages-count-chart");
|
||||||
|
let dashboardPackagesCountChart = null;
|
||||||
|
|
||||||
|
ready(_ => {
|
||||||
|
dashboardPackagesStatusesChart = new Chart(dashboardPackagesStatusesChartCanvas, {
|
||||||
|
type: "pie",
|
||||||
|
data: {},
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
dashboardPackagesCountChart = new Chart(dashboardPackagesCountChartCanvas, {
|
||||||
|
type: "bar",
|
||||||
|
data: {},
|
||||||
|
options: {
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
responsive: true,
|
||||||
|
scales: {
|
||||||
|
x: {
|
||||||
|
stacked: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
@ -59,7 +59,17 @@
|
|||||||
</nav>
|
</nav>
|
||||||
<div class="tab-content" id="nav-tabContent">
|
<div class="tab-content" id="nav-tabContent">
|
||||||
<div id="package-info-logs" class="tab-pane fade show active" role="tabpanel" aria-labelledby="package-info-logs-button" tabindex="0">
|
<div id="package-info-logs" class="tab-pane fade show active" role="tabpanel" aria-labelledby="package-info-logs-button" tabindex="0">
|
||||||
<pre class="language-console"><code id="package-info-logs-input" class="pre-scrollable language-console"></code><button id="package-info-logs-copy-button" type="button" class="btn language-console" onclick="copyLogs()"><i class="bi bi-clipboard"></i> copy</button></pre>
|
<div class="row">
|
||||||
|
<div class="col-1 dropend">
|
||||||
|
<button id="package-info-logs-dropdown" class="btn dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
|
<i class="bi bi-list"></i>
|
||||||
|
</button>
|
||||||
|
<nav id="package-info-logs-versions" class="dropdown-menu" aria-labelledby="package-info-logs-dropdown"></nav>
|
||||||
|
</div>
|
||||||
|
<div class="col-11">
|
||||||
|
<pre class="language-console"><code id="package-info-logs-input" class="pre-scrollable language-console"></code><button id="package-info-logs-copy-button" type="button" class="btn language-console" onclick="copyLogs()"><i class="bi bi-clipboard"></i> copy</button></pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="package-info-changes" class="tab-pane fade" role="tabpanel" aria-labelledby="package-info-changes-button" tabindex="0">
|
<div id="package-info-changes" class="tab-pane fade" role="tabpanel" aria-labelledby="package-info-changes-button" tabindex="0">
|
||||||
<pre class="language-diff"><code id="package-info-changes-input" class="pre-scrollable language-diff"></code><button id="package-info-changes-copy-button" type="button" class="btn language-diff" onclick="copyChanges()"><i class="bi bi-clipboard"></i> copy</button></pre>
|
<pre class="language-diff"><code id="package-info-changes-input" class="pre-scrollable language-diff"></code><button id="package-info-changes-copy-button" type="button" class="btn language-diff" onclick="copyChanges()"><i class="bi bi-clipboard"></i> copy</button></pre>
|
||||||
@ -100,6 +110,7 @@
|
|||||||
const packageInfoModalHeader = document.getElementById("package-info-modal-header");
|
const packageInfoModalHeader = document.getElementById("package-info-modal-header");
|
||||||
const packageInfo = document.getElementById("package-info");
|
const packageInfo = document.getElementById("package-info");
|
||||||
|
|
||||||
|
const packageInfoLogsVersions = document.getElementById("package-info-logs-versions");
|
||||||
const packageInfoLogsInput = document.getElementById("package-info-logs-input");
|
const packageInfoLogsInput = document.getElementById("package-info-logs-input");
|
||||||
const packageInfoLogsCopyButton = document.getElementById("package-info-logs-copy-button");
|
const packageInfoLogsCopyButton = document.getElementById("package-info-logs-copy-button");
|
||||||
|
|
||||||
@ -285,25 +296,51 @@
|
|||||||
convert: response => response.json(),
|
convert: response => response.json(),
|
||||||
},
|
},
|
||||||
data => {
|
data => {
|
||||||
const logs = data.map(log_record => {
|
const selectors = Object
|
||||||
return `[${new Date(1000 * log_record.created).toISOString()}] ${log_record.message}`;
|
.values(
|
||||||
});
|
data.reduce((acc, log_record) => {
|
||||||
packageInfoLogsInput.textContent = logs.join("\n");
|
const id = `${log_record.version}-${log_record.process_id}`;
|
||||||
highlight(packageInfoLogsInput);
|
if (acc[id])
|
||||||
|
acc[id].created = Math.min(log_record.created, acc[id].created);
|
||||||
|
else
|
||||||
|
acc[id] = log_record;
|
||||||
|
return acc;
|
||||||
|
}, {})
|
||||||
|
)
|
||||||
|
.sort(({created: left}, {created: right}) =>
|
||||||
|
right - left
|
||||||
|
)
|
||||||
|
.map(version => {
|
||||||
|
const link = document.createElement("a");
|
||||||
|
link.classList.add("dropdown-item");
|
||||||
|
|
||||||
|
link.textContent = new Date(1000 * version.created).toISOStringShort();
|
||||||
|
link.href = "#";
|
||||||
|
link.onclick = _ => {
|
||||||
|
const logs = data
|
||||||
|
.filter(log_record => log_record.version === version.version && log_record.process_id === version.process_id)
|
||||||
|
.map(log_record => `[${new Date(1000 * log_record.created).toISOString()}] ${log_record.message}`);
|
||||||
|
|
||||||
|
packageInfoLogsInput.textContent = logs.join("\n");
|
||||||
|
highlight(packageInfoLogsInput);
|
||||||
|
|
||||||
|
Array.from(packageInfoLogsVersions.children).forEach(el => el.classList.remove("active"));
|
||||||
|
link.classList.add("active");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
return link;
|
||||||
|
});
|
||||||
|
|
||||||
|
packageInfoLogsVersions.replaceChildren(...selectors);
|
||||||
|
selectors.find(Boolean)?.click();
|
||||||
},
|
},
|
||||||
onFailure,
|
onFailure,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadPackage(packageBase, onFailure) {
|
function loadPackage(packageBase, onFailure) {
|
||||||
const headerClass = status => {
|
|
||||||
if (status === "pending") return ["bg-warning"];
|
|
||||||
if (status === "building") return ["bg-warning"];
|
|
||||||
if (status === "failed") return ["bg-danger", "text-white"];
|
|
||||||
if (status === "success") return ["bg-success", "text-white"];
|
|
||||||
return ["bg-secondary", "text-white"];
|
|
||||||
};
|
|
||||||
|
|
||||||
makeRequest(
|
makeRequest(
|
||||||
`/api/v1/packages/${packageBase}`,
|
`/api/v1/packages/${packageBase}`,
|
||||||
{
|
{
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
// so far bootstrap-table only operates with jquery elements
|
// so far bootstrap-table only operates with jquery elements
|
||||||
const table = $(document.getElementById("packages"));
|
const table = $(document.getElementById("packages"));
|
||||||
|
|
||||||
const statusBadge = document.getElementById("badge-status");
|
const dashboardButton = document.getElementById("dashboard-button");
|
||||||
const versionBadge = document.getElementById("badge-version");
|
const versionBadge = document.getElementById("badge-version");
|
||||||
|
|
||||||
function doPackageAction(uri, packages, repository, successText, failureText, data) {
|
function doPackageAction(uri, packages, repository, successText, failureText, data) {
|
||||||
@ -141,14 +141,62 @@
|
|||||||
data => {
|
data => {
|
||||||
versionBadge.innerHTML = `<i class="bi bi-github"></i> ahriman ${safe(data.version)}`;
|
versionBadge.innerHTML = `<i class="bi bi-github"></i> ahriman ${safe(data.version)}`;
|
||||||
|
|
||||||
statusBadge.classList.remove(...statusBadge.classList);
|
dashboardButton.classList.remove(...dashboardButton.classList);
|
||||||
statusBadge.classList.add("btn");
|
dashboardButton.classList.add("btn");
|
||||||
statusBadge.classList.add(badgeClass(data.status.status));
|
dashboardButton.classList.add(badgeClass(data.status.status));
|
||||||
|
|
||||||
const popover = bootstrap.Popover.getOrCreateInstance(statusBadge);
|
dashboardModalHeader.classList.remove(...dashboardModalHeader.classList);
|
||||||
popover.dispose();
|
dashboardModalHeader.classList.add("modal-header");
|
||||||
statusBadge.dataset.bsContent = `${data.status.status} at ${new Date(1000 * data.status.timestamp).toISOStringShort()}`;
|
headerClass(data.status.status).forEach(clz => dashboardModalHeader.classList.add(clz));
|
||||||
bootstrap.Popover.getOrCreateInstance(statusBadge);
|
|
||||||
|
dashboardName.textContent = data.repository;
|
||||||
|
dashboardArchitecture.textContent = data.architecture;
|
||||||
|
dashboardStatus.textContent = data.status.status;
|
||||||
|
dashboardStatusTimestamp.textContent = new Date(1000 * data.status.timestamp).toISOStringShort();
|
||||||
|
|
||||||
|
if (dashboardPackagesStatusesChart) {
|
||||||
|
const labels = [
|
||||||
|
"unknown",
|
||||||
|
"pending",
|
||||||
|
"building",
|
||||||
|
"failed",
|
||||||
|
"success",
|
||||||
|
];
|
||||||
|
dashboardPackagesStatusesChart.config.data = {
|
||||||
|
labels: labels,
|
||||||
|
datasets: [{
|
||||||
|
label: "packages in status",
|
||||||
|
data: labels.map(label => data.packages[label]),
|
||||||
|
backgroundColor: [
|
||||||
|
"rgb(55, 58, 60)",
|
||||||
|
"rgb(255, 117, 24)",
|
||||||
|
"rgb(255, 117, 24)",
|
||||||
|
"rgb(255, 0, 57)",
|
||||||
|
"rgb(63, 182, 24)", // copy-paste from current style
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
};
|
||||||
|
dashboardPackagesStatusesChart.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dashboardPackagesCountChart) {
|
||||||
|
dashboardPackagesCountChart.config.data = {
|
||||||
|
labels: ["packages"],
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: "archives",
|
||||||
|
data: [data.stats.packages],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "bases",
|
||||||
|
data: [data.stats.bases],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
dashboardPackagesCountChart.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
dashboardCanvas.hidden = data.status.total > 0;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -227,7 +275,6 @@
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
bootstrap.Popover.getOrCreateInstance(statusBadge);
|
|
||||||
selectRepository();
|
selectRepository();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -58,6 +58,14 @@
|
|||||||
return value.includes(dataList[index].toLowerCase());
|
return value.includes(dataList[index].toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function headerClass(status) {
|
||||||
|
if (status === "pending") return ["bg-warning"];
|
||||||
|
if (status === "building") return ["bg-warning"];
|
||||||
|
if (status === "failed") return ["bg-danger", "text-white"];
|
||||||
|
if (status === "success") return ["bg-success", "text-white"];
|
||||||
|
return ["bg-secondary", "text-white"];
|
||||||
|
}
|
||||||
|
|
||||||
function listToTable(data) {
|
function listToTable(data) {
|
||||||
return Array.from(new Set(data))
|
return Array.from(new Set(data))
|
||||||
.sort()
|
.sort()
|
||||||
|
@ -64,10 +64,10 @@ _shtab_ahriman_service_key_import_option_strings=('-h' '--help' '--key-server')
|
|||||||
_shtab_ahriman_service_repositories_option_strings=('-h' '--help' '--id-only' '--no-id-only')
|
_shtab_ahriman_service_repositories_option_strings=('-h' '--help' '--id-only' '--no-id-only')
|
||||||
_shtab_ahriman_service_run_option_strings=('-h' '--help')
|
_shtab_ahriman_service_run_option_strings=('-h' '--help')
|
||||||
_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_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_service_shell_option_strings=('-h' '--help')
|
_shtab_ahriman_service_shell_option_strings=('-h' '--help' '-o' '--output')
|
||||||
_shtab_ahriman_service_tree_migrate_option_strings=('-h' '--help')
|
_shtab_ahriman_service_tree_migrate_option_strings=('-h' '--help')
|
||||||
_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_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_shell_option_strings=('-h' '--help')
|
_shtab_ahriman_shell_option_strings=('-h' '--help' '-o' '--output')
|
||||||
_shtab_ahriman_sign_option_strings=('-h' '--help')
|
_shtab_ahriman_sign_option_strings=('-h' '--help')
|
||||||
_shtab_ahriman_status_option_strings=('-h' '--help' '--ahriman' '-e' '--exit-code' '--info' '--no-info' '-s' '--status')
|
_shtab_ahriman_status_option_strings=('-h' '--help' '--ahriman' '-e' '--exit-code' '--info' '--no-info' '-s' '--status')
|
||||||
_shtab_ahriman_status_update_option_strings=('-h' '--help' '-s' '--status')
|
_shtab_ahriman_status_update_option_strings=('-h' '--help' '-s' '--status')
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.TH AHRIMAN "1" "2024\-12\-01" "ahriman" "Generated Python Manual"
|
.TH AHRIMAN "1" "2025\-01\-05" "ahriman" "Generated Python Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
ahriman
|
ahriman
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -940,7 +940,7 @@ port of the web service
|
|||||||
path to unix socket used for interprocess communications
|
path to unix socket used for interprocess communications
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman service\-shell'\/\fR
|
.SH COMMAND \fI\,'ahriman service\-shell'\/\fR
|
||||||
usage: ahriman service\-shell [\-h] [code]
|
usage: ahriman service\-shell [\-h] [\-o OUTPUT] [code]
|
||||||
|
|
||||||
drop into python shell
|
drop into python shell
|
||||||
|
|
||||||
@ -948,6 +948,11 @@ drop into python shell
|
|||||||
\fBcode\fR
|
\fBcode\fR
|
||||||
instead of dropping into shell, just execute the specified code
|
instead of dropping into shell, just execute the specified code
|
||||||
|
|
||||||
|
.SH OPTIONS \fI\,'ahriman service\-shell'\/\fR
|
||||||
|
.TP
|
||||||
|
\fB\-o\fR \fI\,OUTPUT\/\fR, \fB\-\-output\fR \fI\,OUTPUT\/\fR
|
||||||
|
output commands and result to the file
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman service\-tree\-migrate'\/\fR
|
.SH COMMAND \fI\,'ahriman service\-tree\-migrate'\/\fR
|
||||||
usage: ahriman service\-tree\-migrate [\-h]
|
usage: ahriman service\-tree\-migrate [\-h]
|
||||||
|
|
||||||
|
@ -583,6 +583,7 @@ _shtab_ahriman_service_setup_options=(
|
|||||||
|
|
||||||
_shtab_ahriman_service_shell_options=(
|
_shtab_ahriman_service_shell_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
|
{-o,--output}"[output commands and result to the file (default\: None)]:output:"
|
||||||
":instead of dropping into shell, just execute the specified code (default\: None):"
|
":instead of dropping into shell, just execute the specified code (default\: None):"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -608,6 +609,7 @@ _shtab_ahriman_setup_options=(
|
|||||||
|
|
||||||
_shtab_ahriman_shell_options=(
|
_shtab_ahriman_shell_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
|
{-o,--output}"[output commands and result to the file (default\: None)]:output:"
|
||||||
":instead of dropping into shell, just execute the specified code (default\: None):"
|
":instead of dropping into shell, just execute the specified code (default\: None):"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -60,6 +60,9 @@ pacman = [
|
|||||||
s3 = [
|
s3 = [
|
||||||
"boto3",
|
"boto3",
|
||||||
]
|
]
|
||||||
|
shell = [
|
||||||
|
"IPython"
|
||||||
|
]
|
||||||
stats = [
|
stats = [
|
||||||
"matplotlib",
|
"matplotlib",
|
||||||
]
|
]
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
@ -17,4 +17,4 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
__version__ = "2.16.0"
|
__version__ = "2.17.1"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
@ -117,7 +117,7 @@ class Application(ApplicationPackages, ApplicationRepository):
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
packages(list[Package]): list of source packages of which dependencies have to be processed
|
packages(list[Package]): list of source packages of which dependencies have to be processed
|
||||||
process_dependencies(bool): if no set, dependencies will not be processed
|
process_dependencies(bool): if set to ``False``, dependencies will not be processed
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
list[Package]: updated packages list. Packager for dependencies will be copied from the original package
|
list[Package]: updated packages list. Packager for dependencies will be copied from the original package
|
||||||
@ -130,6 +130,9 @@ class Application(ApplicationPackages, ApplicationRepository):
|
|||||||
>>> packages = application.with_dependencies(packages, process_dependencies=True)
|
>>> packages = application.with_dependencies(packages, process_dependencies=True)
|
||||||
>>> application.print_updates(packages, log_fn=print)
|
>>> application.print_updates(packages, log_fn=print)
|
||||||
"""
|
"""
|
||||||
|
if not process_dependencies or not packages:
|
||||||
|
return packages
|
||||||
|
|
||||||
def missing_dependencies(source: Iterable[Package]) -> dict[str, str | None]:
|
def missing_dependencies(source: Iterable[Package]) -> dict[str, str | None]:
|
||||||
# append list of known packages with packages which are in current sources
|
# append list of known packages with packages which are in current sources
|
||||||
satisfied_packages = known_packages | {
|
satisfied_packages = known_packages | {
|
||||||
@ -145,22 +148,29 @@ class Application(ApplicationPackages, ApplicationRepository):
|
|||||||
if dependency not in satisfied_packages
|
if dependency not in satisfied_packages
|
||||||
}
|
}
|
||||||
|
|
||||||
if not process_dependencies or not packages:
|
def new_packages(root: Package) -> dict[str, Package]:
|
||||||
return packages
|
portion = {root.base: root}
|
||||||
|
while missing := missing_dependencies(portion.values()):
|
||||||
|
for package_name, packager in missing.items():
|
||||||
|
if (source_dir := self.repository.paths.cache_for(package_name)).is_dir():
|
||||||
|
# there is local cache, load package from it
|
||||||
|
leaf = Package.from_build(source_dir, self.repository.architecture, packager)
|
||||||
|
else:
|
||||||
|
leaf = Package.from_aur(package_name, packager)
|
||||||
|
portion[leaf.base] = leaf
|
||||||
|
|
||||||
|
# register package in the database
|
||||||
|
self.repository.reporter.set_unknown(leaf)
|
||||||
|
|
||||||
|
return portion
|
||||||
|
|
||||||
known_packages = self._known_packages()
|
known_packages = self._known_packages()
|
||||||
with_dependencies = {package.base: package for package in packages}
|
with_dependencies: dict[str, Package] = {}
|
||||||
|
for package in packages:
|
||||||
while missing := missing_dependencies(with_dependencies.values()):
|
with self.in_package_context(package.base, package.version): # use the same context for the logger
|
||||||
for package_name, username in missing.items():
|
try:
|
||||||
if (source_dir := self.repository.paths.cache_for(package_name)).is_dir():
|
with_dependencies |= new_packages(package)
|
||||||
# there is local cache, load package from it
|
except Exception:
|
||||||
package = Package.from_build(source_dir, self.repository.architecture, username)
|
self.logger.exception("could not process dependencies of %s, skip the package", package.base)
|
||||||
else:
|
|
||||||
package = Package.from_aur(package_name, username)
|
|
||||||
with_dependencies[package.base] = package
|
|
||||||
|
|
||||||
# register package in the database
|
|
||||||
self.repository.reporter.set_unknown(package)
|
|
||||||
|
|
||||||
return list(with_dependencies.values())
|
return list(with_dependencies.values())
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
@ -22,7 +22,7 @@ import logging
|
|||||||
|
|
||||||
from collections.abc import Callable, Iterable
|
from collections.abc import Callable, Iterable
|
||||||
from multiprocessing import Pool
|
from multiprocessing import Pool
|
||||||
from typing import TypeVar
|
from typing import ClassVar, TypeVar
|
||||||
|
|
||||||
from ahriman.application.lock import Lock
|
from ahriman.application.lock import Lock
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
@ -53,13 +53,13 @@ class Handler:
|
|||||||
Wrapper for all command line actions, though each derived class implements :func:`run()` method, it usually
|
Wrapper for all command line actions, though each derived class implements :func:`run()` method, it usually
|
||||||
must not be called directly. The recommended way is to call :func:`execute()` class method, e.g.::
|
must not be called directly. The recommended way is to call :func:`execute()` class method, e.g.::
|
||||||
|
|
||||||
>>> from ahriman.application.handlers import Add
|
>>> from ahriman.application.handlers.add import Add
|
||||||
>>>
|
>>>
|
||||||
>>> Add.execute(args)
|
>>> Add.execute(args)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
ALLOW_MULTI_ARCHITECTURE_RUN = True
|
ALLOW_MULTI_ARCHITECTURE_RUN: ClassVar[bool] = True
|
||||||
arguments: list[Callable[[SubParserAction], argparse.ArgumentParser]]
|
arguments: ClassVar[list[Callable[[SubParserAction], argparse.ArgumentParser]]]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def call(cls, args: argparse.Namespace, repository_id: RepositoryId) -> bool:
|
def call(cls, args: argparse.Namespace, repository_id: RepositoryId) -> bool:
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
@ -21,6 +21,7 @@ import argparse
|
|||||||
|
|
||||||
from collections.abc import Callable, Iterable
|
from collections.abc import Callable, Iterable
|
||||||
from dataclasses import fields
|
from dataclasses import fields
|
||||||
|
from typing import ClassVar
|
||||||
|
|
||||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||||
from ahriman.core.alpm.remote import AUR, Official
|
from ahriman.core.alpm.remote import AUR, Official
|
||||||
@ -40,7 +41,7 @@ class Search(Handler):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
||||||
SORT_FIELDS = {
|
SORT_FIELDS: ClassVar[set[str]] = {
|
||||||
field.name
|
field.name
|
||||||
for field in fields(AURPackage)
|
for field in fields(AURPackage)
|
||||||
if field.default_factory is not list
|
if field.default_factory is not list
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
@ -21,6 +21,7 @@ import argparse
|
|||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from pwd import getpwuid
|
from pwd import getpwuid
|
||||||
|
from typing import ClassVar
|
||||||
from urllib.parse import quote_plus as url_encode
|
from urllib.parse import quote_plus as url_encode
|
||||||
|
|
||||||
from ahriman.application.application import Application
|
from ahriman.application.application import Application
|
||||||
@ -46,9 +47,9 @@ class Setup(Handler):
|
|||||||
|
|
||||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io
|
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io
|
||||||
|
|
||||||
ARCHBUILD_COMMAND_PATH = Path("/") / "usr" / "bin" / "archbuild"
|
ARCHBUILD_COMMAND_PATH: ClassVar[Path] = Path("/") / "usr" / "bin" / "archbuild"
|
||||||
MIRRORLIST_PATH = Path("/") / "etc" / "pacman.d" / "mirrorlist"
|
MIRRORLIST_PATH: ClassVar[Path] = Path("/") / "etc" / "pacman.d" / "mirrorlist"
|
||||||
SUDOERS_DIR_PATH = Path("/") / "etc" / "sudoers.d"
|
SUDOERS_DIR_PATH: ClassVar[Path] = Path("/") / "etc" / "sudoers.d"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
@ -18,12 +18,12 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
import argparse
|
import argparse
|
||||||
import code
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||||
|
from ahriman.application.interactive_shell import InteractiveShell
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.formatters import StringPrinter
|
from ahriman.core.formatters import StringPrinter
|
||||||
from ahriman.models.repository_id import RepositoryId
|
from ahriman.models.repository_id import RepositoryId
|
||||||
@ -58,11 +58,13 @@ class Shell(Handler):
|
|||||||
"configuration": configuration,
|
"configuration": configuration,
|
||||||
"repository_id": repository_id,
|
"repository_id": repository_id,
|
||||||
}
|
}
|
||||||
|
console = InteractiveShell(locals=local_variables)
|
||||||
|
|
||||||
if args.code is None:
|
match args.code:
|
||||||
code.interact(local=local_variables)
|
case None:
|
||||||
else:
|
console.interact()
|
||||||
code.InteractiveConsole(locals=local_variables).runcode(args.code)
|
case snippet:
|
||||||
|
console.runcode(snippet)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _set_service_shell_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
def _set_service_shell_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
@ -79,6 +81,7 @@ class Shell(Handler):
|
|||||||
description="drop into python shell")
|
description="drop into python shell")
|
||||||
parser.add_argument("code", help="instead of dropping into shell, just execute the specified code", nargs="?")
|
parser.add_argument("code", help="instead of dropping into shell, just execute the specified code", nargs="?")
|
||||||
parser.add_argument("-v", "--verbose", help=argparse.SUPPRESS, action="store_true")
|
parser.add_argument("-v", "--verbose", help=argparse.SUPPRESS, action="store_true")
|
||||||
|
parser.add_argument("-o", "--output", help="output commands and result to the file", type=Path)
|
||||||
parser.set_defaults(lock=None, report=False)
|
parser.set_defaults(lock=None, report=False)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
@ -27,7 +27,7 @@ from pathlib import Path
|
|||||||
from ahriman.application.application import Application
|
from ahriman.application.application import Application
|
||||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.formatters import EventStatsPrinter, PackageStatsPrinter
|
from ahriman.core.formatters import EventStatsPrinter, PackageStatsPrinter, RepositoryStatsPrinter
|
||||||
from ahriman.core.utils import enum_values, pretty_datetime
|
from ahriman.core.utils import enum_values, pretty_datetime
|
||||||
from ahriman.models.event import Event, EventType
|
from ahriman.models.event import Event, EventType
|
||||||
from ahriman.models.repository_id import RepositoryId
|
from ahriman.models.repository_id import RepositoryId
|
||||||
@ -64,6 +64,7 @@ class Statistics(Handler):
|
|||||||
|
|
||||||
match args.package:
|
match args.package:
|
||||||
case None:
|
case None:
|
||||||
|
RepositoryStatsPrinter(repository_id, application.reporter.statistics())(verbose=True)
|
||||||
Statistics.stats_per_package(args.event, events, args.chart)
|
Statistics.stats_per_package(args.event, events, args.chart)
|
||||||
case _:
|
case _:
|
||||||
Statistics.stats_for_package(args.event, events, args.chart)
|
Statistics.stats_for_package(args.event, events, args.chart)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
@ -23,6 +23,7 @@ import sys
|
|||||||
|
|
||||||
from collections.abc import Generator
|
from collections.abc import Generator
|
||||||
from importlib import metadata
|
from importlib import metadata
|
||||||
|
from typing import ClassVar
|
||||||
|
|
||||||
from ahriman import __version__
|
from ahriman import __version__
|
||||||
from ahriman.application.handlers.handler import Handler, SubParserAction
|
from ahriman.application.handlers.handler import Handler, SubParserAction
|
||||||
@ -36,11 +37,11 @@ class Versions(Handler):
|
|||||||
version handler
|
version handler
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
PEP423_PACKAGE_NAME(str): (class attribute) special regex for valid PEP423 package name
|
PEP423_PACKAGE_NAME(re.Pattern[str]): (class attribute) special regex for valid PEP423 package name
|
||||||
"""
|
"""
|
||||||
|
|
||||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
||||||
PEP423_PACKAGE_NAME = re.compile(r"^[A-Za-z0-9._-]+")
|
PEP423_PACKAGE_NAME: ClassVar[re.Pattern[str]] = re.compile(r"^[A-Za-z0-9._-]+")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
60
src/ahriman/application/interactive_shell.py
Normal file
60
src/ahriman/application/interactive_shell.py
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
|
#
|
||||||
|
# This file is part of ahriman
|
||||||
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
from code import InteractiveConsole
|
||||||
|
from importlib.util import find_spec
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
|
class InteractiveShell(InteractiveConsole):
|
||||||
|
"""
|
||||||
|
wrapper around :class:`code.InteractiveConsole` to pass :func:`interact()` to IPython shell
|
||||||
|
"""
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def has_ipython() -> bool:
|
||||||
|
"""
|
||||||
|
check if IPython shell is available
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: ``True`` if IPython shell is available, ``False`` otherwise
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
return find_spec("IPython.terminal.embed") is not None
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def interact(self, *args: Any, **kwargs: Any) -> None:
|
||||||
|
"""
|
||||||
|
pass controller to IPython shell
|
||||||
|
|
||||||
|
Args:
|
||||||
|
*args(Any): positional arguments
|
||||||
|
**kwargs(Any): keyword arguments
|
||||||
|
"""
|
||||||
|
if self.has_ipython():
|
||||||
|
from IPython.terminal.embed import InteractiveShellEmbed
|
||||||
|
|
||||||
|
shell = InteractiveShellEmbed(user_ns=self.locals) # type: ignore[no-untyped-call]
|
||||||
|
shell.show_banner() # type: ignore[no-untyped-call]
|
||||||
|
shell.interact() # type: ignore[no-untyped-call]
|
||||||
|
else:
|
||||||
|
# fallback to default
|
||||||
|
import readline # pylint: disable=unused-import
|
||||||
|
InteractiveConsole.interact(self, *args, **kwargs)
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
@ -23,6 +23,7 @@ import shutil
|
|||||||
from email.utils import parsedate_to_datetime
|
from email.utils import parsedate_to_datetime
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from pyalpm import DB # type: ignore[import-not-found]
|
from pyalpm import DB # type: ignore[import-not-found]
|
||||||
|
from typing import ClassVar
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
@ -41,7 +42,7 @@ class PacmanDatabase(SyncHttpClient):
|
|||||||
sync_files_database(bool): sync files database
|
sync_files_database(bool): sync files database
|
||||||
"""
|
"""
|
||||||
|
|
||||||
LAST_MODIFIED_HEADER = "Last-Modified"
|
LAST_MODIFIED_HEADER: ClassVar[str] = "Last-Modified"
|
||||||
|
|
||||||
def __init__(self, database: DB, configuration: Configuration) -> None:
|
def __init__(self, database: DB, configuration: Configuration) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
@ -34,13 +34,14 @@ class PkgbuildToken(StrEnum):
|
|||||||
well-known tokens dictionary
|
well-known tokens dictionary
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
ArrayEnds(PkgbuildToken): (class attribute) array ends token
|
ArrayEnds(PkgbuildToken): array ends token
|
||||||
ArrayStarts(PkgbuildToken): (class attribute) array starts token
|
ArrayStarts(PkgbuildToken): array starts token
|
||||||
Comma(PkgbuildToken): (class attribute) comma token
|
Comma(PkgbuildToken): comma token
|
||||||
Comment(PkgbuildToken): (class attribute) comment token
|
Comment(PkgbuildToken): comment token
|
||||||
FunctionDeclaration(PkgbuildToken): (class attribute) function declaration token
|
FunctionDeclaration(PkgbuildToken): function declaration token
|
||||||
FunctionEnds(PkgbuildToken): (class attribute) function ends token
|
FunctionEnds(PkgbuildToken): function ends token
|
||||||
FunctionStarts(PkgbuildToken): (class attribute) function starts token
|
FunctionStarts(PkgbuildToken): function starts token
|
||||||
|
NewLine(PkgbuildToken): new line token
|
||||||
"""
|
"""
|
||||||
|
|
||||||
ArrayStarts = "("
|
ArrayStarts = "("
|
||||||
@ -54,6 +55,8 @@ class PkgbuildToken(StrEnum):
|
|||||||
FunctionStarts = "{"
|
FunctionStarts = "{"
|
||||||
FunctionEnds = "}"
|
FunctionEnds = "}"
|
||||||
|
|
||||||
|
NewLine = "\n"
|
||||||
|
|
||||||
|
|
||||||
class PkgbuildParser(shlex.shlex):
|
class PkgbuildParser(shlex.shlex):
|
||||||
"""
|
"""
|
||||||
@ -174,31 +177,18 @@ class PkgbuildParser(shlex.shlex):
|
|||||||
Returns:
|
Returns:
|
||||||
bool: ``True`` if the previous element of the stream is a quote or escaped and ``False`` otherwise
|
bool: ``True`` if the previous element of the stream is a quote or escaped and ``False`` otherwise
|
||||||
"""
|
"""
|
||||||
# wrapper around reading utf symbols from random position of the stream
|
|
||||||
def read_last() -> tuple[int, str]:
|
|
||||||
while (position := self._io.tell()) > 0:
|
|
||||||
try:
|
|
||||||
return position, self._io.read(1)
|
|
||||||
except UnicodeDecodeError:
|
|
||||||
self._io.seek(position - 1)
|
|
||||||
|
|
||||||
raise PkgbuildParserError("reached starting position, no valid symbols found")
|
|
||||||
|
|
||||||
current_position = self._io.tell()
|
current_position = self._io.tell()
|
||||||
|
|
||||||
last_char = penultimate_char = None
|
last_char = penultimate_char = None
|
||||||
index = current_position - 1
|
index = current_position - 1
|
||||||
while index > 0:
|
while index > 0:
|
||||||
self._io.seek(index)
|
index, last_char = self._read_last(index)
|
||||||
|
|
||||||
index, last_char = read_last()
|
|
||||||
if last_char.isspace():
|
if last_char.isspace():
|
||||||
index -= 1
|
index -= 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if index > 1:
|
if index > 1:
|
||||||
self._io.seek(index - 1)
|
_, penultimate_char = self._read_last(index - 1)
|
||||||
_, penultimate_char = read_last()
|
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
@ -227,7 +217,7 @@ class PkgbuildParser(shlex.shlex):
|
|||||||
case PkgbuildToken.ArrayEnds:
|
case PkgbuildToken.ArrayEnds:
|
||||||
break
|
break
|
||||||
case comment if comment.startswith(PkgbuildToken.Comment):
|
case comment if comment.startswith(PkgbuildToken.Comment):
|
||||||
self.instream.readline()
|
self._read_comment()
|
||||||
continue
|
continue
|
||||||
|
|
||||||
yield token
|
yield token
|
||||||
@ -268,7 +258,7 @@ class PkgbuildParser(shlex.shlex):
|
|||||||
if counter == 0:
|
if counter == 0:
|
||||||
break
|
break
|
||||||
case comment if comment.startswith(PkgbuildToken.Comment):
|
case comment if comment.startswith(PkgbuildToken.Comment):
|
||||||
self.instream.readline()
|
self._read_comment()
|
||||||
|
|
||||||
if not 0 < start_position < end_position:
|
if not 0 < start_position < end_position:
|
||||||
raise PkgbuildParserError("function body wasn't found")
|
raise PkgbuildParserError("function body wasn't found")
|
||||||
@ -304,7 +294,7 @@ class PkgbuildParser(shlex.shlex):
|
|||||||
return
|
return
|
||||||
|
|
||||||
if token.startswith(PkgbuildToken.Comment):
|
if token.startswith(PkgbuildToken.Comment):
|
||||||
self.instream.readline()
|
self._read_comment()
|
||||||
return
|
return
|
||||||
|
|
||||||
match self.get_token():
|
match self.get_token():
|
||||||
@ -332,6 +322,44 @@ class PkgbuildParser(shlex.shlex):
|
|||||||
case other if other is not None:
|
case other if other is not None:
|
||||||
yield from self._parse_token(other)
|
yield from self._parse_token(other)
|
||||||
|
|
||||||
|
def _read_comment(self) -> None:
|
||||||
|
"""
|
||||||
|
read comment from the current position. This method doesn't check comment itself, just read the stream
|
||||||
|
until the comment line ends
|
||||||
|
"""
|
||||||
|
_, last_symbol = self._read_last()
|
||||||
|
if last_symbol != PkgbuildToken.NewLine:
|
||||||
|
self.instream.readline()
|
||||||
|
|
||||||
|
def _read_last(self, initial_index: int | None = None) -> tuple[int, str]:
|
||||||
|
"""
|
||||||
|
wrapper around read to read the last symbol from the input stream. This method is designed to process UTF-8
|
||||||
|
symbols correctly. This method does not reset current stream position
|
||||||
|
|
||||||
|
Args:
|
||||||
|
initial_index(int | None, optional): initial index to start reading from. If none set, the previous position
|
||||||
|
will be used (Default value = None)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
tuple[int, str]: last symbol and its position in the stream
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
PkgbuildParserError: in case if stream reached starting position, but no valid symbols were found
|
||||||
|
"""
|
||||||
|
if initial_index is None:
|
||||||
|
initial_index = self._io.tell() - 1
|
||||||
|
if initial_index < 0:
|
||||||
|
raise PkgbuildParserError("stream is on starting position")
|
||||||
|
self._io.seek(initial_index)
|
||||||
|
|
||||||
|
while (position := self._io.tell()) > 0:
|
||||||
|
try:
|
||||||
|
return position, self._io.read(1)
|
||||||
|
except UnicodeDecodeError:
|
||||||
|
self._io.seek(position - 1)
|
||||||
|
|
||||||
|
raise PkgbuildParserError("reached starting position, no valid symbols found")
|
||||||
|
|
||||||
def parse(self) -> Generator[PkgbuildPatch, None, None]:
|
def parse(self) -> Generator[PkgbuildPatch, None, None]:
|
||||||
"""
|
"""
|
||||||
parse source stream and yield parsed entries
|
parse source stream and yield parsed entries
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
@ -17,7 +17,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
from typing import Any
|
from typing import Any, ClassVar
|
||||||
|
|
||||||
from ahriman.core.alpm.pacman import Pacman
|
from ahriman.core.alpm.pacman import Pacman
|
||||||
from ahriman.core.alpm.remote.remote import Remote
|
from ahriman.core.alpm.remote.remote import Remote
|
||||||
@ -35,9 +35,9 @@ class AUR(Remote):
|
|||||||
DEFAULT_RPC_VERSION(str): (class attribute) default AUR RPC version
|
DEFAULT_RPC_VERSION(str): (class attribute) default AUR RPC version
|
||||||
"""
|
"""
|
||||||
|
|
||||||
DEFAULT_AUR_URL = "https://aur.archlinux.org"
|
DEFAULT_AUR_URL: ClassVar[str] = "https://aur.archlinux.org"
|
||||||
DEFAULT_RPC_URL = f"{DEFAULT_AUR_URL}/rpc"
|
DEFAULT_RPC_URL: ClassVar[str] = f"{DEFAULT_AUR_URL}/rpc"
|
||||||
DEFAULT_RPC_VERSION = "5"
|
DEFAULT_RPC_VERSION: ClassVar[str] = "5"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def remote_git_url(cls, package_base: str, repository: str) -> str:
|
def remote_git_url(cls, package_base: str, repository: str) -> str:
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
@ -17,7 +17,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
from typing import Any
|
from typing import Any, ClassVar
|
||||||
|
|
||||||
from ahriman.core.alpm.pacman import Pacman
|
from ahriman.core.alpm.pacman import Pacman
|
||||||
from ahriman.core.alpm.remote.remote import Remote
|
from ahriman.core.alpm.remote.remote import Remote
|
||||||
@ -36,10 +36,10 @@ class Official(Remote):
|
|||||||
DEFAULT_RPC_URL(str): (class attribute) default archlinux repositories RPC url
|
DEFAULT_RPC_URL(str): (class attribute) default archlinux repositories RPC url
|
||||||
"""
|
"""
|
||||||
|
|
||||||
DEFAULT_ARCHLINUX_GIT_URL = "https://gitlab.archlinux.org"
|
DEFAULT_ARCHLINUX_GIT_URL: ClassVar[str] = "https://gitlab.archlinux.org"
|
||||||
DEFAULT_ARCHLINUX_URL = "https://archlinux.org"
|
DEFAULT_ARCHLINUX_URL: ClassVar[str] = "https://archlinux.org"
|
||||||
DEFAULT_SEARCH_REPOSITORIES = ["Core", "Extra", "Multilib"]
|
DEFAULT_SEARCH_REPOSITORIES: ClassVar[list[str]] = ["Core", "Extra", "Multilib"]
|
||||||
DEFAULT_RPC_URL = "https://archlinux.org/packages/search/json"
|
DEFAULT_RPC_URL: ClassVar[str] = "https://archlinux.org/packages/search/json"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def remote_git_url(cls, package_base: str, repository: str) -> str:
|
def remote_git_url(cls, package_base: str, repository: str) -> str:
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
@ -19,9 +19,8 @@
|
|||||||
#
|
#
|
||||||
try:
|
try:
|
||||||
import aiohttp_security
|
import aiohttp_security
|
||||||
_has_aiohttp_security = True
|
|
||||||
except ImportError:
|
except ImportError:
|
||||||
_has_aiohttp_security = False
|
aiohttp_security = None # type: ignore[assignment]
|
||||||
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
@ -40,7 +39,7 @@ async def authorized_userid(*args: Any, **kwargs: Any) -> Any:
|
|||||||
Returns:
|
Returns:
|
||||||
Any: ``None`` in case if no aiohttp_security module found and function call otherwise
|
Any: ``None`` in case if no aiohttp_security module found and function call otherwise
|
||||||
"""
|
"""
|
||||||
if _has_aiohttp_security:
|
if aiohttp_security is not None:
|
||||||
return await aiohttp_security.authorized_userid(*args, **kwargs) # pylint: disable=no-value-for-parameter
|
return await aiohttp_security.authorized_userid(*args, **kwargs) # pylint: disable=no-value-for-parameter
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -56,7 +55,7 @@ async def check_authorized(*args: Any, **kwargs: Any) -> Any:
|
|||||||
Returns:
|
Returns:
|
||||||
Any: ``None`` in case if no aiohttp_security module found and function call otherwise
|
Any: ``None`` in case if no aiohttp_security module found and function call otherwise
|
||||||
"""
|
"""
|
||||||
if _has_aiohttp_security:
|
if aiohttp_security is not None:
|
||||||
return await aiohttp_security.check_authorized(*args, **kwargs) # pylint: disable=no-value-for-parameter
|
return await aiohttp_security.check_authorized(*args, **kwargs) # pylint: disable=no-value-for-parameter
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -72,7 +71,7 @@ async def forget(*args: Any, **kwargs: Any) -> Any:
|
|||||||
Returns:
|
Returns:
|
||||||
Any: ``None`` in case if no aiohttp_security module found and function call otherwise
|
Any: ``None`` in case if no aiohttp_security module found and function call otherwise
|
||||||
"""
|
"""
|
||||||
if _has_aiohttp_security:
|
if aiohttp_security is not None:
|
||||||
return await aiohttp_security.forget(*args, **kwargs) # pylint: disable=no-value-for-parameter
|
return await aiohttp_security.forget(*args, **kwargs) # pylint: disable=no-value-for-parameter
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -88,6 +87,6 @@ async def remember(*args: Any, **kwargs: Any) -> Any:
|
|||||||
Returns:
|
Returns:
|
||||||
Any: ``None`` in case if no aiohttp_security module found and function call otherwise
|
Any: ``None`` in case if no aiohttp_security module found and function call otherwise
|
||||||
"""
|
"""
|
||||||
if _has_aiohttp_security:
|
if aiohttp_security is not None:
|
||||||
return await aiohttp_security.remember(*args, **kwargs) # pylint: disable=no-value-for-parameter
|
return await aiohttp_security.remember(*args, **kwargs) # pylint: disable=no-value-for-parameter
|
||||||
return None
|
return None
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
@ -136,7 +136,7 @@ class PackageArchive:
|
|||||||
dependencies, roots = self.depends_on_paths()
|
dependencies, roots = self.depends_on_paths()
|
||||||
installed_packages = self.installed_packages()
|
installed_packages = self.installed_packages()
|
||||||
# build list of packages, which contains both the package itself and (possible) debug packages
|
# build list of packages, which contains both the package itself and (possible) debug packages
|
||||||
packages = list(self.package.packages) + [f"{package}-debug" for package in self.package.packages]
|
packages = list(self.package.packages) + [f"{self.package.base}-debug"]
|
||||||
|
|
||||||
# build initial map of file path -> packages containing this path
|
# build initial map of file path -> packages containing this path
|
||||||
# in fact, keys will contain all libraries the package linked to and all directories it contains
|
# in fact, keys will contain all libraries the package linked to and all directories it contains
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
@ -21,6 +21,7 @@ import shutil
|
|||||||
|
|
||||||
from collections.abc import Generator
|
from collections.abc import Generator
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import ClassVar
|
||||||
|
|
||||||
from ahriman.core.exceptions import CalledProcessError
|
from ahriman.core.exceptions import CalledProcessError
|
||||||
from ahriman.core.log import LazyLogging
|
from ahriman.core.log import LazyLogging
|
||||||
@ -42,9 +43,9 @@ class Sources(LazyLogging):
|
|||||||
GITCONFIG(dict[str, str]): (class attribute) git config options to suppress annoying hints
|
GITCONFIG(dict[str, str]): (class attribute) git config options to suppress annoying hints
|
||||||
"""
|
"""
|
||||||
|
|
||||||
DEFAULT_BRANCH = "master" # default fallback branch
|
DEFAULT_BRANCH: ClassVar[str] = "master" # default fallback branch
|
||||||
DEFAULT_COMMIT_AUTHOR = ("ahriman", "ahriman@localhost")
|
DEFAULT_COMMIT_AUTHOR: ClassVar[tuple[str, str]] = ("ahriman", "ahriman@localhost")
|
||||||
GITCONFIG = {
|
GITCONFIG: ClassVar[dict[str, str]] = {
|
||||||
"init.defaultBranch": DEFAULT_BRANCH,
|
"init.defaultBranch": DEFAULT_BRANCH,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021-2024 ahriman team.
|
# Copyright (c) 2021-2025 ahriman team.
|
||||||
#
|
#
|
||||||
# This file is part of ahriman
|
# This file is part of ahriman
|
||||||
# (see https://github.com/arcan1s/ahriman).
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
@ -149,8 +149,11 @@ class Task(LazyLogging):
|
|||||||
str | None: current commit sha if available
|
str | None: current commit sha if available
|
||||||
"""
|
"""
|
||||||
last_commit_sha = Sources.load(sources_dir, self.package, patches, self.paths)
|
last_commit_sha = Sources.load(sources_dir, self.package, patches, self.paths)
|
||||||
if local_version is None:
|
if self.package.is_vcs: # if package is VCS, then make sure to update PKGBUILD to the latest version
|
||||||
return last_commit_sha # there is no local package or pkgrel increment is disabled
|
self.build(sources_dir, dry_run=True)
|
||||||
|
|
||||||
|
if local_version is None: # there is no local package or pkgrel increment is disabled
|
||||||
|
return last_commit_sha
|
||||||
|
|
||||||
# load fresh package
|
# load fresh package
|
||||||
loaded_package = Package.from_build(sources_dir, self.architecture, None)
|
loaded_package = Package.from_build(sources_dir, self.architecture, None)
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user