mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-11-17 14:03:41 +00:00
Compare commits
13 Commits
554827cc57
...
2.12.0
| Author | SHA1 | Date | |
|---|---|---|---|
| 53aedbb9aa | |||
| c941226a9b | |||
| 69cbbfce65 | |||
| 52d69fa9f6 | |||
| 279ac785a1 | |||
| f51b8e2358 | |||
| b116e6fa07 | |||
| 7b667c8157 | |||
| c51463d36b | |||
| 79947af013 | |||
| e6d6cb006b | |||
| f553cc059a | |||
| c99d4f6f0f |
@ -67,7 +67,7 @@ ignored-modules=
|
|||||||
|
|
||||||
# Python code to execute, usually for sys.path manipulation such as
|
# Python code to execute, usually for sys.path manipulation such as
|
||||||
# pygtk.require().
|
# pygtk.require().
|
||||||
#init-hook=
|
init-hook='import sys; sys.path.append("pylint_plugins")'
|
||||||
|
|
||||||
# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the
|
# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the
|
||||||
# number of processors available to use, and will cap the count on Windows to
|
# number of processors available to use, and will cap the count on Windows to
|
||||||
@ -81,7 +81,8 @@ limit-inference-results=100
|
|||||||
|
|
||||||
# List of plugins (as comma separated values of python module names) to load,
|
# List of plugins (as comma separated values of python module names) to load,
|
||||||
# usually to register additional checkers.
|
# usually to register additional checkers.
|
||||||
load-plugins=
|
load-plugins=pylint.extensions.docparams,
|
||||||
|
definition_order,
|
||||||
|
|
||||||
# Pickle collected data for later comparisons.
|
# Pickle collected data for later comparisons.
|
||||||
persistent=yes
|
persistent=yes
|
||||||
@ -227,7 +228,7 @@ name-group=
|
|||||||
|
|
||||||
# Regular expression which should only match function or class names that do
|
# Regular expression which should only match function or class names that do
|
||||||
# not require a docstring.
|
# not require a docstring.
|
||||||
no-docstring-rgx=^_
|
no-docstring-rgx=
|
||||||
|
|
||||||
# List of decorators that produce properties, such as abc.abstractproperty. Add
|
# List of decorators that produce properties, such as abc.abstractproperty. Add
|
||||||
# to this list to register other decorators that produce valid properties.
|
# to this list to register other decorators that produce valid properties.
|
||||||
|
|||||||
@ -26,7 +26,7 @@ In order to resolve all difficult cases the `autopep8` is used. You can perform
|
|||||||
Again, the most checks can be performed by `make check` command, though some additional guidelines must be applied:
|
Again, the most checks can be performed by `make check` command, though some additional guidelines must be applied:
|
||||||
|
|
||||||
* Every class, every function (including private and protected), every attribute must be documented. The project follows [Google style documentation](https://google.github.io/styleguide/pyguide.html). The only exception is local functions.
|
* Every class, every function (including private and protected), every attribute must be documented. The project follows [Google style documentation](https://google.github.io/styleguide/pyguide.html). The only exception is local functions.
|
||||||
* Correct way to document function, if section is empty, e.g. no notes or there are no args, it should be omitted:
|
* Correct way to document function (if a section is empty, e.g. no notes or there are no args, it should be omitted) is the following:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
def foo(argument: str, *, flag: bool = False) -> int:
|
def foo(argument: str, *, flag: bool = False) -> int:
|
||||||
@ -43,7 +43,8 @@ Again, the most checks can be performed by `make check` command, though some add
|
|||||||
flag(bool, optional): a flag (Default value = False)
|
flag(bool, optional): a flag (Default value = False)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
int: result
|
int: result with
|
||||||
|
long description
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RuntimeError: a local function error occurs
|
RuntimeError: a local function error occurs
|
||||||
@ -64,7 +65,7 @@ Again, the most checks can be performed by `make check` command, though some add
|
|||||||
```python
|
```python
|
||||||
class Clazz(BaseClazz):
|
class Clazz(BaseClazz):
|
||||||
"""
|
"""
|
||||||
brand-new implementation of ``BaseClazz``
|
brand-new implementation of :class:`BaseClazz`
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
CLAZZ_ATTRIBUTE(int): (class attribute) a brand-new class attribute
|
CLAZZ_ATTRIBUTE(int): (class attribute) a brand-new class attribute
|
||||||
@ -92,7 +93,7 @@ Again, the most checks can be performed by `make check` command, though some add
|
|||||||
|
|
||||||
* 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 `typinng.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 `typinng.Optional` (e.g. `str | None` instead of `Optional[str]`).
|
||||||
* `classmethod` should always return `Self`. In case of mypy warning (e.g. if there is a branch in which function doesn't return the instance of `cls`) consider using `staticmethod` instead.
|
* `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.
|
||||||
* Recommended order of function definitions in class:
|
* Recommended order of function definitions in class:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
@ -121,10 +122,12 @@ Again, the most checks can be performed by `make check` command, though some add
|
|||||||
def __hash__(self) -> int: ... # basically any magic (or look-alike) method
|
def __hash__(self) -> int: ... # basically any magic (or look-alike) method
|
||||||
```
|
```
|
||||||
|
|
||||||
Methods inside one group should be ordered alphabetically, the only exception is `__init__` method (`__post__init__` for dataclasses) which should be defined first. For test methods it is recommended to follow the order in which functions are defined.
|
Methods inside one group should be ordered alphabetically, the only exceptions are `__init__` (`__post_init__` for dataclasses) and `__new__` methods which should be defined first. For test methods it is recommended to follow the order in which functions are defined.
|
||||||
|
|
||||||
Though, we would like to highlight abstract methods (i.e. ones which raise `NotImplementedError`), we still keep in global order at the moment.
|
Though, we would like to highlight abstract methods (i.e. ones which raise `NotImplementedError`), we still keep in global order at the moment.
|
||||||
|
|
||||||
|
For the most cases there is custom `pylint` plugin, which performs checks automatically.
|
||||||
|
|
||||||
* Abstract methods must raise `NotImplementedError` instead of using `abc.abstractmethod`. The reason behind this restriction is the fact that we have class/static abstract methods for those we need to define their attribute first making the code harder to read.
|
* Abstract methods must raise `NotImplementedError` instead of using `abc.abstractmethod`. The reason behind this restriction is the fact that we have class/static abstract methods for those we need to define their attribute first making the code harder to read.
|
||||||
* For any path interactions `pathlib.Path` must be used.
|
* For any path interactions `pathlib.Path` must be used.
|
||||||
* Configuration interactions must go through `ahriman.core.configuration.Configuration` class instance.
|
* Configuration interactions must go through `ahriman.core.configuration.Configuration` class instance.
|
||||||
@ -167,7 +170,7 @@ Again, the most checks can be performed by `make check` command, though some add
|
|||||||
* No global variable is allowed outside of `ahriman` module. `ahriman.core.context` is also special case.
|
* No global variable is allowed outside of `ahriman` module. `ahriman.core.context` is also special case.
|
||||||
* Single quotes are not allowed. The reason behind this restriction is the fact that docstrings must be written by using double quotes only, and we would like to make style consistent.
|
* Single quotes are not allowed. The reason behind this restriction is the fact that docstrings must be written by using double quotes only, and we would like to make style consistent.
|
||||||
* If your class writes anything to log, the `ahriman.core.log.LazyLogging` trait must be used.
|
* If your class writes anything to log, the `ahriman.core.log.LazyLogging` trait must be used.
|
||||||
* Web API methods must be documented by using `aiohttp_apispec` library. Schema testing mostly should be implemented in related view class tests. Recommended example for documentation (excluding comments):
|
* 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
|
import aiohttp_apispec
|
||||||
@ -191,6 +194,7 @@ Again, the most checks can be performed by `make check` command, though some add
|
|||||||
class Foo(BaseView):
|
class Foo(BaseView):
|
||||||
|
|
||||||
POST_PERMISSION = ...
|
POST_PERMISSION = ...
|
||||||
|
ROUTES = ...
|
||||||
|
|
||||||
@aiohttp_apispec.docs(
|
@aiohttp_apispec.docs(
|
||||||
tags=["Tag"],
|
tags=["Tag"],
|
||||||
@ -216,6 +220,7 @@ Again, the most checks can be performed by `make check` command, though some add
|
|||||||
|
|
||||||
* It is allowed to change web API to add new fields or remove optional ones. However, in case of model changes, new API version must be introduced.
|
* It is allowed to change web API to add new fields or remove optional ones. However, in case of model changes, new API version must be introduced.
|
||||||
* On the other hand, it is allowed to change method signatures, however, it is recommended to add new parameters as optional if possible. Deprecated API can be dropped during major release.
|
* On the other hand, it is allowed to change method signatures, however, it is recommended to add new parameters as optional if possible. Deprecated API can be dropped during major release.
|
||||||
|
* Enumerations (`Enum` classes) are allowed and recommended. However, it is recommended to use `StrEnum` class if there are from/to string conversions and `IntEnum` otherwise.
|
||||||
|
|
||||||
### Other checks
|
### Other checks
|
||||||
|
|
||||||
|
|||||||
2
Makefile
2
Makefile
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
PROJECT := ahriman
|
PROJECT := ahriman
|
||||||
|
|
||||||
FILES := AUTHORS CONTRIBUTING.md COPYING Makefile README.md SECURITY.md docs package pyproject.toml src tox.ini web.png
|
FILES := AUTHORS CONTRIBUTING.md COPYING README.md SECURITY.md package pyproject.toml src web.png
|
||||||
TARGET_FILES := $(addprefix $(PROJECT)/, $(FILES))
|
TARGET_FILES := $(addprefix $(PROJECT)/, $(FILES))
|
||||||
IGNORE_FILES := package/archlinux src/.mypy_cache
|
IGNORE_FILES := package/archlinux src/.mypy_cache
|
||||||
|
|
||||||
|
|||||||
14
README.md
14
README.md
@ -4,39 +4,39 @@
|
|||||||
[](https://github.com/arcan1s/ahriman/actions/workflows/setup.yml)
|
[](https://github.com/arcan1s/ahriman/actions/workflows/setup.yml)
|
||||||
[](https://hub.docker.com/r/arcan1s/ahriman)
|
[](https://hub.docker.com/r/arcan1s/ahriman)
|
||||||
[](https://www.codefactor.io/repository/github/arcan1s/ahriman)
|
[](https://www.codefactor.io/repository/github/arcan1s/ahriman)
|
||||||
[](https://ahriman.readthedocs.io/?badge=latest)
|
[](https://ahriman.readthedocs.io)
|
||||||
|
|
||||||
Wrapper for managing custom repository inspired by [repo-scripts](https://github.com/arcan1s/repo-scripts).
|
Wrapper for managing custom repository inspired by [repo-scripts](https://github.com/arcan1s/repo-scripts).
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
* Install-configure-forget manager for the very own repository.
|
* Install-configure-forget manager for the very own repository.
|
||||||
* Multi-architecture support.
|
* Multi architecture and repository support.
|
||||||
* Dependency manager.
|
* Dependency manager.
|
||||||
* VCS packages support.
|
* VCS packages support.
|
||||||
* Official repository support.
|
* Official repository support.
|
||||||
* Ability to patch AUR packages and even create package from local PKGBUILDs.
|
* Ability to patch AUR packages and even create package from local PKGBUILDs.
|
||||||
* Various rebuild options with ability to automatically bump package version.
|
* Various rebuild options with ability to automatically bump package version.
|
||||||
* Sign support with gpg (repository, package), multiple packagers support.
|
* Sign support with gpg (repository, package), multiple packagers support.
|
||||||
* Triggers for repository updates, e.g. synchronization to remote services (rsync, s3 and github) and report generation (email, html, telegram).
|
* Triggers for repository updates, e.g. synchronization to remote services (rsync, S3 and GitHub) and report generation (email, html, telegram).
|
||||||
* Repository status interface with optional authorization and control options:
|
* Repository status interface with optional authorization and control options:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Installation and run
|
## Installation and run
|
||||||
|
|
||||||
For installation details kindly refer to the [documentation](https://ahriman.readthedocs.io/en/latest/setup.html). For application commands it is possible to get information by using `--help`/`help` command or by using man page ([web version](https://ahriman.readthedocs.io/en/latest/command-line.html)).
|
For installation details kindly refer to the [documentation](https://ahriman.readthedocs.io/en/stable/setup.html). For application commands it is possible to get information by using `--help`/`help` command or by using man page ([web version](https://ahriman.readthedocs.io/en/stable/command-line.html)).
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
Every available option is described in the [documentation](https://ahriman.readthedocs.io/en/latest/configuration.html).
|
Every available option is described in the [documentation](https://ahriman.readthedocs.io/en/stable/configuration.html).
|
||||||
|
|
||||||
The application provides reasonable defaults which allow to use it out-of-box; however additional steps (like configuring build toolchain and sudoers) are recommended and can be easily achieved by following install instructions.
|
The application provides reasonable defaults which allow to use it out-of-box; however additional steps (like configuring build toolchain and sudoers) are recommended and can be easily achieved by following install instructions.
|
||||||
|
|
||||||
## [FAQ](https://ahriman.readthedocs.io/en/latest/faq.html)
|
## [FAQ](https://ahriman.readthedocs.io/en/stable/faq.html)
|
||||||
|
|
||||||
## Live demos
|
## Live demos
|
||||||
|
|
||||||
* [Build status page](https://ahriman-demo.arcanis.me). You can log in as `demo` user by using `demo` password. However, you will not be able to run tasks. [HTTP API documentation](https://ahriman-demo.arcanis.me/api-docs) is also available.
|
* [Build status page](https://ahriman-demo.arcanis.me). You can log in as `demo` user by using `demo` password. However, you will not be able to run tasks. [HTTP API documentation](https://ahriman-demo.arcanis.me/api-docs) is also available.
|
||||||
* [Repository index](http://repo.arcanis.me/arcanisrepo/x86_64/).
|
* [Repository index](https://repo.arcanis.me/arcanisrepo/x86_64/).
|
||||||
* [Telegram feed](https://t.me/arcanisrepo).
|
* [Telegram feed](https://t.me/arcanisrepo).
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
|
Before Width: | Height: | Size: 839 KiB After Width: | Height: | Size: 1.0 MiB |
@ -116,6 +116,14 @@ ahriman.application.handlers.restore module
|
|||||||
:no-undoc-members:
|
:no-undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
|
ahriman.application.handlers.run module
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
.. automodule:: ahriman.application.handlers.run
|
||||||
|
:members:
|
||||||
|
:no-undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
ahriman.application.handlers.search module
|
ahriman.application.handlers.search module
|
||||||
------------------------------------------
|
------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@ -100,6 +100,14 @@ ahriman.web.schemas.package\_names\_schema module
|
|||||||
:no-undoc-members:
|
:no-undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
|
ahriman.web.schemas.package\_patch\_schema module
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
.. automodule:: ahriman.web.schemas.package_patch_schema
|
||||||
|
:members:
|
||||||
|
:no-undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
ahriman.web.schemas.package\_properties\_schema module
|
ahriman.web.schemas.package\_properties\_schema module
|
||||||
------------------------------------------------------
|
------------------------------------------------------
|
||||||
|
|
||||||
@ -132,6 +140,22 @@ ahriman.web.schemas.pagination\_schema module
|
|||||||
:no-undoc-members:
|
:no-undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
|
ahriman.web.schemas.patch\_name\_schema module
|
||||||
|
----------------------------------------------
|
||||||
|
|
||||||
|
.. automodule:: ahriman.web.schemas.patch_name_schema
|
||||||
|
:members:
|
||||||
|
:no-undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
ahriman.web.schemas.patch\_schema module
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
.. automodule:: ahriman.web.schemas.patch_schema
|
||||||
|
:members:
|
||||||
|
:no-undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
ahriman.web.schemas.pgp\_key\_id\_schema module
|
ahriman.web.schemas.pgp\_key\_id\_schema module
|
||||||
-----------------------------------------------
|
-----------------------------------------------
|
||||||
|
|
||||||
@ -204,6 +228,14 @@ 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:
|
||||||
|
|
||||||
Module contents
|
Module contents
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
|||||||
@ -30,6 +30,14 @@ ahriman.web.views.index module
|
|||||||
:no-undoc-members:
|
:no-undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
|
ahriman.web.views.static module
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
.. automodule:: ahriman.web.views.static
|
||||||
|
:members:
|
||||||
|
:no-undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
Module contents
|
Module contents
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,22 @@ ahriman.web.views.v1.status.packages module
|
|||||||
:no-undoc-members:
|
:no-undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
|
ahriman.web.views.v1.status.patch module
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
.. automodule:: ahriman.web.views.v1.status.patch
|
||||||
|
:members:
|
||||||
|
:no-undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
|
ahriman.web.views.v1.status.patches module
|
||||||
|
------------------------------------------
|
||||||
|
|
||||||
|
.. automodule:: ahriman.web.views.v1.status.patches
|
||||||
|
:members:
|
||||||
|
:no-undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
ahriman.web.views.v1.status.repositories module
|
ahriman.web.views.v1.status.repositories module
|
||||||
-----------------------------------------------
|
-----------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@ -7,21 +7,21 @@ Features
|
|||||||
--------
|
--------
|
||||||
|
|
||||||
* Install-configure-forget manager for the very own repository.
|
* Install-configure-forget manager for the very own repository.
|
||||||
* Multi-architecture support.
|
* Multi architecture and repository support.
|
||||||
* Dependency manager.
|
* Dependency manager.
|
||||||
* VCS packages support.
|
* VCS packages support.
|
||||||
* Official repository support.
|
* Official repository support.
|
||||||
* Ability to patch AUR packages and even create package from local PKGBUILDs.
|
* Ability to patch AUR packages and even create package from local PKGBUILDs.
|
||||||
* Various rebuild options with ability to automatically bump package version.
|
* Various rebuild options with ability to automatically bump package version.
|
||||||
* Sign support with gpg (repository, package), multiple packagers support.
|
* Sign support with gpg (repository, package), multiple packagers support.
|
||||||
* Triggers for repository updates, e.g. synchronization to remote services (rsync, s3 and github) and report generation (email, html, telegram).
|
* Triggers for repository updates, e.g. synchronization to remote services (rsync, S3 and GitHub) and report generation (email, html, telegram).
|
||||||
* Repository status interface with optional authorization and control options.
|
* Repository status interface with optional authorization and control options.
|
||||||
|
|
||||||
Live demos
|
Live demos
|
||||||
----------
|
----------
|
||||||
|
|
||||||
* `Build status page <https://ahriman-demo.arcanis.me>`_. You can login as ``demo`` user by using ``demo`` password. Note, however, you will not be able to run tasks. `HTTP API documentation <https://ahriman-demo.arcanis.me/api-docs>`_ is also available.
|
* `Build status page <https://ahriman-demo.arcanis.me>`_. You can login as ``demo`` user by using ``demo`` password. Note, however, you will not be able to run tasks. `HTTP API documentation <https://ahriman-demo.arcanis.me/api-docs>`_ is also available.
|
||||||
* `Repository index <http://repo.arcanis.me/x86_64/index.html>`_.
|
* `Repository index <https://repo.arcanis.me/x86_64/index.html>`_.
|
||||||
* `Telegram feed <https://t.me/arcanisrepo>`_.
|
* `Telegram feed <https://t.me/arcanisrepo>`_.
|
||||||
|
|
||||||
Contents
|
Contents
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
Manual migrations
|
Manual migrations
|
||||||
=================
|
=================
|
||||||
|
|
||||||
Normally most of migrations are handled automatically after application start. However, some upgrades require manual interventions; this document describes them.
|
Normally the most of migrations are handled automatically after application start, however, some upgrades require manual interventions; this document describes them.
|
||||||
|
|
||||||
Upgrades to breakpoints
|
Upgrades to breakpoints
|
||||||
-----------------------
|
-----------------------
|
||||||
@ -13,8 +13,8 @@ This release includes major upgrade for the newest devtools and archlinux reposi
|
|||||||
|
|
||||||
#. Upgrade to the latest major release of python (3.11) (required by other changes).
|
#. Upgrade to the latest major release of python (3.11) (required by other changes).
|
||||||
#. Upgrade devtools to the latest release.
|
#. Upgrade devtools to the latest release.
|
||||||
#. Backup your settings, ``/etc/ahriman.ini.d/00-setup-overrides.ini`` by default.
|
#. Backup local settings, ``/etc/ahriman.ini.d/00-setup-overrides.ini`` by default.
|
||||||
#. Run setup command (i.e. ``ahriman service-setup``) again with the same arguments as you used before. This step can be done manually by moving ``devtools`` configuration (something like ``/usr/share/devtools/pacman-ahriman*.conf``) to new location ``/usr/share/devtools/pacman.conf.d/`` under name ``ahriman.conf``. After that make sure to remove any ``community`` mentions from configurations (e.g. ``/usr/share/devtools/pacman.conf.d/ahriman.conf``, ``/etc/ahriman.ini``) if there were any. The only thing which will change is ``devtools`` configuration.
|
#. Run setup command (i.e. ``ahriman service-setup``) again with the same arguments as used before. This step can be done manually by moving ``devtools`` configuration (something like ``/usr/share/devtools/pacman-ahriman*.conf``) to new location ``/usr/share/devtools/pacman.conf.d/`` under name ``ahriman.conf``. After that make sure to remove any ``community`` mentions from configurations (e.g. ``/usr/share/devtools/pacman.conf.d/ahriman.conf``, ``/etc/ahriman.ini``) if there were any. The only thing which will change is ``devtools`` configuration.
|
||||||
#. Remove build chroot as it is incompatible, e.g. ``sudo ahriman service-clean --chroot``.
|
#. Remove build chroot as it is incompatible, e.g. ``sudo ahriman service-clean --chroot``.
|
||||||
#. Run ``sudo -u ahriman ahriman update --no-aur --no-local --no-manual -yy`` in order to update local databases.
|
#. Run ``sudo -u ahriman ahriman update --no-aur --no-local --no-manual -yy`` in order to update local databases.
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ This release includes paths migration. Unlike usual case, no automatic migration
|
|||||||
* Path to pacman databases now includes repository name too, it has been changed from ``/var/lib/ahriman/pacman/x86_64`` to ``/var/lib/ahriman/pacman/aur-clone/x86_64``.
|
* Path to pacman databases now includes repository name too, it has been changed from ``/var/lib/ahriman/pacman/x86_64`` to ``/var/lib/ahriman/pacman/aur-clone/x86_64``.
|
||||||
* Path to repository itself also includes repository name, from ``/var/lib/ahriman/repository/x86_64`` to ``/var/lib/ahriman/repository/aur-clone/x86_64``.
|
* Path to repository itself also includes repository name, from ``/var/lib/ahriman/repository/x86_64`` to ``/var/lib/ahriman/repository/aur-clone/x86_64``.
|
||||||
|
|
||||||
In order to migrate to new filesystem tree the following actions are required:
|
In order to migrate to the new filesystem tree the following actions are required:
|
||||||
|
|
||||||
#.
|
#.
|
||||||
Stop and disable all services, e.g. timer and web service:
|
Stop and disable all services, e.g. timer and web service:
|
||||||
@ -38,13 +38,13 @@ In order to migrate to new filesystem tree the following actions are required:
|
|||||||
sudo systemctl disable --now ahriman-web@x86_64
|
sudo systemctl disable --now ahriman-web@x86_64
|
||||||
|
|
||||||
#.
|
#.
|
||||||
Create directory tree. It can be done by running ``ahriman service-tree-migrate`` subcommand. It performs copying between the old repository tree and the new one. Alternatively you can copy directories by hands.
|
Create directory tree. It can be done by running ``ahriman service-tree-migrate`` subcommand. It performs copying between the old repository tree and the new one. Alternatively directories can be copied by hands.
|
||||||
|
|
||||||
#.
|
#.
|
||||||
Edit configuration in case if anything is pointing to the old path, e.g. HTML report generation, in the way in which it will be pointed to directory inside repository specific one, e.g. ``/var/lib/ahriman/repository/x86_64`` to ``/var/lib/ahriman/repository/aur-clone/x86_64``.
|
Edit configuration in case if anything is pointing to the old path, e.g. HTML report generation, in the way in which it will point to the directory inside repository specific one, e.g. ``/var/lib/ahriman/repository/x86_64`` to ``/var/lib/ahriman/repository/aur-clone/x86_64``.
|
||||||
|
|
||||||
#.
|
#.
|
||||||
Edit devtools pacman configuration (``/usr/share/devtools/pacman.conf.d/ahriman-x86_64.conf`` by default) replacing ``Server`` with path to your repository, e.g.:
|
Run setup command (i.e. ``ahriman service-setup``) again with the same arguments as used before. This step can be done manually by editing devtools pacman configuration (``/usr/share/devtools/pacman.conf.d/ahriman-x86_64.conf`` by default) replacing ``Server`` with path to the repository, e.g.:
|
||||||
|
|
||||||
.. code-block:: ini
|
.. code-block:: ini
|
||||||
|
|
||||||
@ -52,15 +52,13 @@ In order to migrate to new filesystem tree the following actions are required:
|
|||||||
SigLevel = Optional TrustAll
|
SigLevel = Optional TrustAll
|
||||||
Server = file:///var/lib/ahriman/repository/aur-clone/x86_64
|
Server = file:///var/lib/ahriman/repository/aur-clone/x86_64
|
||||||
|
|
||||||
Alternatively it can be done by running ``service-setup`` command again.
|
In case of manual interventions make sure to remove architecture reference from ``web`` sections (if any) to avoid ambiguity.
|
||||||
|
|
||||||
#. If you didn't run setup command on the previous step, make sure to remove architecture reference from ``web`` section (if any).
|
|
||||||
|
|
||||||
#.
|
#.
|
||||||
Make sure to update remote synchronization services if any. Almost all of them rely on current repository tree by default, so you need to setup either redirects or configure to synchronize to the old locations (e.g. ``object_path`` option for S3 synchronization).
|
Make sure to update remote synchronization services if any. Almost all of them rely on current repository tree by default, so it is required to setup either redirects or configure to synchronize to the old locations (e.g. ``object_path`` option for S3 synchronization).
|
||||||
|
|
||||||
#.
|
#.
|
||||||
Enable and start services again. Unit template parameter should include both repository architecture and name, dash separated, e.g. ``x86_64-aur-clone``:
|
Enable and start services again. Unit template parameter should include both repository architecture and name, dash separated, e.g. ``x86_64-aur-clone``, where ``x86_64`` is the repository architecture and ``aur-clone`` is the repository name:
|
||||||
|
|
||||||
.. code-block:: shell
|
.. code-block:: shell
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
# Maintainer: Evgeniy Alekseev
|
# Maintainer: Evgeniy Alekseev
|
||||||
|
|
||||||
pkgname='ahriman'
|
pkgname='ahriman'
|
||||||
pkgver=2.11.0
|
pkgver=2.12.0
|
||||||
pkgrel=1
|
pkgrel=1
|
||||||
pkgdesc="ArcH linux ReposItory MANager"
|
pkgdesc="ArcH linux ReposItory MANager"
|
||||||
arch=('any')
|
arch=('any')
|
||||||
|
|||||||
@ -13,30 +13,30 @@ post_upgrade() {
|
|||||||
|
|
||||||
_2_9_0_1_changes() {
|
_2_9_0_1_changes() {
|
||||||
cat << EOF
|
cat << EOF
|
||||||
It was found that you were upgrading from old-devtools package to the new one, which requires manual intervention:
|
It was found that there was an upgrade from old devtools package to the new one, which requires manual intervention:
|
||||||
|
|
||||||
* make sure that devtools are upgraded to the latest release;
|
* make sure that devtools are upgraded to the latest release;
|
||||||
* merge service configuration if required;
|
* merge upstream configuration into local configuration (e.g. by using pacdiff);
|
||||||
* run setup command (i.e. sudo ahriman service-setup) with the same arguments as you did before;
|
* run setup command (i.e. ahriman service-setup) with the same arguments as did before;
|
||||||
* remove build chroot: sudo rm -r /var/lib/ahriman/chroot/ahriman-x86_64/;
|
* remove build chroot, e.g.: ahriman service-clean --chroot;
|
||||||
* update local databases: sudo -u ahriman ahriman update --no-aur --no-local --no-manual -yy;
|
* update local databases: ahriman update --no-aur --no-local --no-manual -yy.
|
||||||
|
|
||||||
For more information kindly refer to migration notes https://ahriman.readthedocs.io/en/stable/migration.html
|
For more information kindly refer to migration notes https://ahriman.readthedocs.io/en/stable/migration.html.
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
_2_12_0_1_changes() {
|
_2_12_0_1_changes() {
|
||||||
cat << EOF
|
cat << EOF
|
||||||
Whereas old tree is still supported it is highly recommended to migrate to the new one:
|
Whereas old local tree is still supported it is highly recommended to migrate to the new one:
|
||||||
|
|
||||||
* stop and disable all services;
|
* stop and disable all services;
|
||||||
* run service-tree-migrate as ahriman user;
|
* run service-tree-migrate as ahriman user;
|
||||||
* edit configuration to avoid pointing to the old paths;
|
* edit local configuration to avoid pointing to the old paths;
|
||||||
* update devtools pacman configuration (e.g. /usr/share/devtools/pacman.conf.d/ahriman-x86_64.conf) with new repository path;
|
* run setup command (i.e. ahriman service-setup) with the same arguments as did before;
|
||||||
* update synchronization services in order to support new paths (or setup redirects);
|
* update remote services in order to support new paths (or setup redirects) if any;
|
||||||
* enable web and timer services again by using x86_64-aur-clone suffix, where x86_64 is your architecture and
|
* enable web and timer services again by using x86_64-aur-clone suffix,
|
||||||
aur-clone is repository name;
|
where x86_64 is the repository architecture and aur-clone is the repository name.
|
||||||
|
|
||||||
For more information kindly refer to migration notes https://ahriman.readthedocs.io/en/stable/migration.html
|
For more information kindly refer to migration notes https://ahriman.readthedocs.io/en/stable/migration.html.
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,10 +6,8 @@
|
|||||||
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
<!-- Embed elements Elements via Web Component -->
|
<!-- Embed elements Elements via Web Component -->
|
||||||
<script src="https://unpkg.com/@stoplight/elements/web-components.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/@stoplight/elements@7.13.7/web-components.min.js" integrity="sha384-aKMPitODat9Dqj3Mva9Rs9jS5Z3KPSW0sFlAOazuULJMFYhAfmORI5SlH9aWIst8" crossorigin="anonymous" type="application/javascript"></script>
|
||||||
<link rel="stylesheet" href="https://unpkg.com/@stoplight/elements/styles.min.css" type="text/css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@stoplight/elements@7.13.7/styles.min.css" integrity="sha384-wPzTs1aFAoGq9gqp9NAs2YVTkFXcU2d6Bx11aKRFhVw2B7o1bCwaV9pGHTlUfD2+" crossorigin="anonymous" type="text/css">
|
||||||
|
|
||||||
<link rel="shortcut icon" href="/static/favicon.ico">
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
|
|||||||
@ -5,8 +5,6 @@
|
|||||||
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
<link rel="shortcut icon" href="/static/favicon.ico">
|
|
||||||
|
|
||||||
{% include "utils/style.jinja2" %}
|
{% include "utils/style.jinja2" %}
|
||||||
{% include "user-style.jinja2" ignore missing %}
|
{% include "user-style.jinja2" ignore missing %}
|
||||||
</head>
|
</head>
|
||||||
@ -18,15 +16,15 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<nav class="navbar navbar-expand-lg">
|
<nav class="navbar navbar-expand-lg">
|
||||||
<div class="navbar-brand"><img src="/static/logo.svg" width="30" height="30" alt=""> ahriman</div>
|
<div class="navbar-brand"><img src="/static/logo.svg" width="30" height="30" alt=""> ahriman</div>
|
||||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbar-supported-content" aria-controls="navbar-supported-content" aria-expanded="false" aria-label="Toggle navigation">
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#repositories-navbar-supported-content" aria-controls="repositories-navbar-supported-content" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
<span class="navbar-toggler-icon"></span>
|
<span class="navbar-toggler-icon"></span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div id="navbar-supported-content" class="collapse navbar-collapse">
|
<div id="repositories-navbar-supported-content" 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">
|
||||||
<a id="{{ repository.id }}-lnk" class="nav-link" href="#{{ repository.id }}" data-repository="{{ repository.repository }}" data-architecture="{{ repository.architecture }}">{{ repository.repository }} ({{ repository.architecture }})</a>
|
<a id="{{ repository.id }}-link" class="nav-link" href="#{{ repository.id }}" data-repository="{{ repository.repository }}" data-architecture="{{ repository.architecture }}">{{ repository.repository }} ({{ repository.architecture }})</a>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
@ -42,7 +40,7 @@
|
|||||||
|
|
||||||
{% 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">
|
||||||
<i class="bi bi-box"></i> packages
|
<i class="bi bi-box"></i><span class="d-none d-sm-inline"> packages</span>
|
||||||
</button>
|
</button>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
<li>
|
<li>
|
||||||
@ -68,12 +66,12 @@
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<button id="key-import-button" type="button" class="btn btn-info" data-bs-toggle="modal" data-bs-target="#key-import-modal" hidden>
|
<button id="key-import-button" type="button" class="btn btn-info" data-bs-toggle="modal" data-bs-target="#key-import-modal" hidden>
|
||||||
<i class="bi bi-key"></i> import key
|
<i class="bi bi-key"></i><span class="d-none d-sm-inline"> import key</span>
|
||||||
</button>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<button type="button" class="btn btn-secondary" onclick="reload()">
|
<button type="button" class="btn btn-secondary" onclick="reload()">
|
||||||
<i class="bi bi-arrow-clockwise"></i> reload
|
<i class="bi bi-arrow-clockwise"></i><span class="d-none d-sm-inline"> reload</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -131,10 +131,10 @@
|
|||||||
return {patches: patches};
|
return {patches: patches};
|
||||||
}
|
}
|
||||||
|
|
||||||
function packagesAdd(packages, patches) {
|
function packagesAdd(packages, patches, repository) {
|
||||||
packages = packages ?? packageAddInput.val();
|
packages = packages ?? packageAddInput.val();
|
||||||
patches = patches ?? patchesParse();
|
patches = patches ?? patchesParse();
|
||||||
const repository = getRepositorySelector(packageAddRepositoryInput);
|
repository = repository ?? getRepositorySelector(packageAddRepositoryInput);
|
||||||
|
|
||||||
if (packages) {
|
if (packages) {
|
||||||
packageAddModal.modal("hide");
|
packageAddModal.modal("hide");
|
||||||
|
|||||||
@ -6,31 +6,32 @@
|
|||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="close"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class="form-group row">
|
<div class="form-group row mt-2">
|
||||||
<div class="input-group">
|
<div class="col-4 col-lg-1" style="text-align: right">version</div>
|
||||||
<table class="table table-borderless">
|
<div id="package-info-version" class="col-8 col-lg-5"></div>
|
||||||
<tbody>
|
<div class="col-4 col-lg-1" style="text-align: right">packager</div>
|
||||||
<tr>
|
<div id="package-info-packager" class="col-8 col-lg-5"></div>
|
||||||
<td style="width: 10%; text-align: right">version</td>
|
</div>
|
||||||
<td id="package-info-version" style="width: 40%"></td>
|
|
||||||
<td style="width: 10%; text-align: right">packager</td>
|
<div class="form-group row mt-2">
|
||||||
<td id="package-info-packager" style="width: 40%"></td>
|
<div class="col-4 col-lg-1" style="text-align: right">groups</div>
|
||||||
</tr>
|
<div id="package-info-groups" class="col-8 col-lg-5"></div>
|
||||||
<tr>
|
<div class="col-4 col-lg-1" style="text-align: right">licenses</div>
|
||||||
<td style="width: 10%; text-align: right">groups</td>
|
<div id="package-info-licenses" class="col-8 col-lg-5"></div>
|
||||||
<td id="package-info-groups" style="width: 40%"></td>
|
</div>
|
||||||
<td style="width: 10%; text-align: right">licenses</td>
|
|
||||||
<td id="package-info-licenses" style="width: 40%"></td>
|
<div class="form-group row mt-2">
|
||||||
</tr>
|
<div class="col-4 col-lg-1" style="text-align: right">upstream</div>
|
||||||
<tr>
|
<div id="package-info-upstream-url" class="col-8 col-lg-5"></div>
|
||||||
<td style="width: 10%; text-align: right">packages</td>
|
<div class="col-4 col-lg-1" style="text-align: right">AUR</div>
|
||||||
<td id="package-info-packages" style="width: 40%"></td>
|
<div id="package-info-aur-url" class="col-8 col-lg-5"></div>
|
||||||
<td style="width: 10%; text-align: right">depends</td>
|
</div>
|
||||||
<td id="package-info-depends" style="width: 40%"></td>
|
|
||||||
</tr>
|
<div class="form-group row mt-2">
|
||||||
</tbody>
|
<div class="col-4 col-lg-1" style="text-align: right">packages</div>
|
||||||
</table>
|
<div id="package-info-packages" class="col-8 col-lg-5"></div>
|
||||||
</div>
|
<div class="col-4 col-lg-1" style="text-align: right">depends</div>
|
||||||
|
<div id="package-info-depends" class="col-8 col-lg-5"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr class="col-12">
|
<hr class="col-12">
|
||||||
@ -44,10 +45,10 @@
|
|||||||
<pre class="language-logs"><samp id="package-info-logs-input" class="pre-scrollable language-logs"></samp><button id="package-info-logs-copy-button" type="button" class="btn language-logs" onclick="copyLogs()"><i class="bi bi-clipboard"></i> copy</button></pre>
|
<pre class="language-logs"><samp id="package-info-logs-input" class="pre-scrollable language-logs"></samp><button id="package-info-logs-copy-button" type="button" class="btn language-logs" onclick="copyLogs()"><i class="bi bi-clipboard"></i> copy</button></pre>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="submit" class="btn btn-success" onclick="packageInfoUpdate()" data-bs-dismiss="modal"><i class="bi bi-play"></i> update</button>
|
<button id="package-info-update-button" type="submit" class="btn btn-success" onclick="packageInfoUpdate()" data-bs-dismiss="modal" hidden><i class="bi bi-play"></i><span class="d-none d-sm-inline"> update</span></button>
|
||||||
<button type="submit" class="btn btn-danger" onclick="packageInfoRemove()" data-bs-dismiss="modal"><i class="bi bi-trash"></i> remove</button>
|
<button id="package-info-remove-button" type="submit" class="btn btn-danger" onclick="packageInfoRemove()" data-bs-dismiss="modal" hidden><i class="bi bi-trash"></i><span class="d-none d-sm-inline"> remove</span></button>
|
||||||
<button type="button" class="btn btn-secondary" onclick="showPackageInfo()"><i class="bi bi-arrow-clockwise"></i> reload</button>
|
<button type="button" class="btn btn-secondary" onclick="showPackageInfo()"><i class="bi bi-arrow-clockwise"></i><span class="d-none d-sm-inline"> reload</span></button>
|
||||||
<button type="button" class="btn btn-primary" data-bs-dismiss="modal"><i class="bi bi-x"></i> close</button>
|
<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>
|
||||||
</div>
|
</div>
|
||||||
@ -58,26 +59,34 @@
|
|||||||
const packageInfoModalHeader = $("#package-info-modal-header");
|
const packageInfoModalHeader = $("#package-info-modal-header");
|
||||||
const packageInfo = $("#package-info");
|
const packageInfo = $("#package-info");
|
||||||
packageInfoModal.on("hidden.bs.modal", () => {
|
packageInfoModal.on("hidden.bs.modal", () => {
|
||||||
|
packageInfoAurUrl.empty();
|
||||||
packageInfoDepends.empty();
|
packageInfoDepends.empty();
|
||||||
packageInfoGroups.empty();
|
packageInfoGroups.empty();
|
||||||
packageInfoLicenses.empty();
|
packageInfoLicenses.empty();
|
||||||
packageInfoPackager.empty();
|
packageInfoPackager.empty();
|
||||||
packageInfoPackages.empty();
|
packageInfoPackages.empty();
|
||||||
|
packageInfoUpstreamUrl.empty();
|
||||||
packageInfoVersion.empty();
|
packageInfoVersion.empty();
|
||||||
|
|
||||||
packageInfoVariablesDiv.empty();
|
packageInfoVariablesDiv.empty();
|
||||||
|
|
||||||
|
packageInfoLogsInput.empty();
|
||||||
|
|
||||||
packageInfoModal.trigger("reset");
|
packageInfoModal.trigger("reset");
|
||||||
|
|
||||||
|
hideInfoControls(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
const packageInfoLogsInput = $("#package-info-logs-input");
|
const packageInfoLogsInput = $("#package-info-logs-input");
|
||||||
const packageInfoLogsCopyButton = $("#package-info-logs-copy-button");
|
const packageInfoLogsCopyButton = $("#package-info-logs-copy-button");
|
||||||
|
|
||||||
|
const packageInfoAurUrl = $("#package-info-aur-url");
|
||||||
const packageInfoDepends = $("#package-info-depends");
|
const packageInfoDepends = $("#package-info-depends");
|
||||||
const packageInfoGroups = $("#package-info-groups");
|
const packageInfoGroups = $("#package-info-groups");
|
||||||
const packageInfoLicenses = $("#package-info-licenses");
|
const packageInfoLicenses = $("#package-info-licenses");
|
||||||
const packageInfoPackager = $("#package-info-packager");
|
const packageInfoPackager = $("#package-info-packager");
|
||||||
const packageInfoPackages = $("#package-info-packages");
|
const packageInfoPackages = $("#package-info-packages");
|
||||||
|
const packageInfoUpstreamUrl = $("#package-info-upstream-url");
|
||||||
const packageInfoVersion = $("#package-info-version");
|
const packageInfoVersion = $("#package-info-version");
|
||||||
|
|
||||||
const packageInfoVariablesDiv = $("#package-info-variables-div");
|
const packageInfoVariablesDiv = $("#package-info-variables-div");
|
||||||
@ -87,6 +96,11 @@
|
|||||||
await copyToClipboard(logs, packageInfoLogsCopyButton);
|
await copyToClipboard(logs, packageInfoLogsCopyButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function hideInfoControls(hidden) {
|
||||||
|
packageInfoRemoveButton.attr("hidden", hidden);
|
||||||
|
packageInfoUpdateButton.attr("hidden", hidden);
|
||||||
|
}
|
||||||
|
|
||||||
function insertVariable(packageBase, variable) {
|
function insertVariable(packageBase, variable) {
|
||||||
const variableInput = document.createElement("div");
|
const variableInput = document.createElement("div");
|
||||||
variableInput.classList.add("input-group");
|
variableInput.classList.add("input-group");
|
||||||
@ -167,6 +181,8 @@
|
|||||||
success: response => {
|
success: response => {
|
||||||
const description = response.find(Boolean);
|
const description = response.find(Boolean);
|
||||||
const packages = Object.keys(description.package.packages);
|
const packages = Object.keys(description.package.packages);
|
||||||
|
const aurUrl = description.package.remote.web_url;
|
||||||
|
const upstreamUrls = Object.values(description.package.packages).map(single => single.url);
|
||||||
|
|
||||||
packageInfo.text(`${description.package.base} ${description.status.status} at ${new Date(1000 * description.status.timestamp).toISOStringShort()}`);
|
packageInfo.text(`${description.package.base} ${description.status.status} at ${new Date(1000 * description.status.timestamp).toISOStringShort()}`);
|
||||||
|
|
||||||
@ -174,6 +190,7 @@
|
|||||||
packageInfoModalHeader.addClass("modal-header");
|
packageInfoModalHeader.addClass("modal-header");
|
||||||
headerClass(description.status.status).forEach(clz => packageInfoModalHeader.addClass(clz));
|
headerClass(description.status.status).forEach(clz => packageInfoModalHeader.addClass(clz));
|
||||||
|
|
||||||
|
packageInfoAurUrl.html(aurUrl ? safeLink(aurUrl, aurUrl, "AUR link").outerHTML : "");
|
||||||
packageInfoDepends.html(listToTable(
|
packageInfoDepends.html(listToTable(
|
||||||
Object.values(description.package.packages)
|
Object.values(description.package.packages)
|
||||||
.reduce((accumulator, currentValue) => {
|
.reduce((accumulator, currentValue) => {
|
||||||
@ -186,9 +203,15 @@
|
|||||||
packageInfoLicenses.html(listToTable(extractListProperties(description.package, "licenses")));
|
packageInfoLicenses.html(listToTable(extractListProperties(description.package, "licenses")));
|
||||||
packageInfoPackager.text(description.package.packager);
|
packageInfoPackager.text(description.package.packager);
|
||||||
packageInfoPackages.html(listToTable(packages));
|
packageInfoPackages.html(listToTable(packages));
|
||||||
|
packageInfoUpstreamUrl.html(upstreamUrls.map(url => safeLink(url, url, "upstream link").outerHTML).join("<br>"));
|
||||||
packageInfoVersion.text(description.package.version);
|
packageInfoVersion.text(description.package.version);
|
||||||
|
|
||||||
|
hideInfoControls(false);
|
||||||
|
},
|
||||||
|
error: (jqXHR, _, errorThrown) => {
|
||||||
|
hideInfoControls(true);
|
||||||
|
onFailure(jqXHR, null, errorThrown);
|
||||||
},
|
},
|
||||||
error: onFailure,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,7 +235,7 @@
|
|||||||
|
|
||||||
function packageInfoUpdate() {
|
function packageInfoUpdate() {
|
||||||
const packageBase = packageInfoModal.data("package");
|
const packageBase = packageInfoModal.data("package");
|
||||||
if (packageBase) return packagesAdd(packageBase, []);
|
if (packageBase) return packagesAdd(packageBase, [], repository);
|
||||||
}
|
}
|
||||||
|
|
||||||
function showPackageInfo(packageBase) {
|
function showPackageInfo(packageBase) {
|
||||||
|
|||||||
@ -5,6 +5,9 @@
|
|||||||
const packageRemoveButton = $("#package-remove-button");
|
const packageRemoveButton = $("#package-remove-button");
|
||||||
const packageUpdateButton = $("#package-update-button");
|
const packageUpdateButton = $("#package-update-button");
|
||||||
|
|
||||||
|
const packageInfoRemoveButton = $("#package-info-remove-button");
|
||||||
|
const packageInfoUpdateButton = $("#package-info-update-button");
|
||||||
|
|
||||||
let repository = null;
|
let repository = null;
|
||||||
$("#repositories a").on("click", (event) => {
|
$("#repositories a").on("click", (event) => {
|
||||||
const element = event.target;
|
const element = event.target;
|
||||||
@ -12,7 +15,7 @@
|
|||||||
architecture: element.dataset.architecture,
|
architecture: element.dataset.architecture,
|
||||||
repository: element.dataset.repository,
|
repository: element.dataset.repository,
|
||||||
};
|
};
|
||||||
packageUpdateButton.html(`<i class="bi bi-play"></i> update ${safe(repository.repository)} (${safe(repository.architecture)})`);
|
packageUpdateButton.html(`<i class="bi bi-play"></i> update<span class="d-none d-sm-inline"> ${safe(repository.repository)} (${safe(repository.architecture)})</span>`);
|
||||||
$(`#${element.id}`).tab("show");
|
$(`#${element.id}`).tab("show");
|
||||||
reload();
|
reload();
|
||||||
});
|
});
|
||||||
@ -146,7 +149,7 @@
|
|||||||
const web_url = description.package.remote.web_url;
|
const web_url = description.package.remote.web_url;
|
||||||
return {
|
return {
|
||||||
id: package_base,
|
id: package_base,
|
||||||
base: web_url ? `<a href="${safe(web_url)}" title="${safe(package_base)}">${safe(package_base)}</a>` : safe(package_base),
|
base: web_url ? safeLink(web_url, package_base, package_base).outerHTML : safe(package_base),
|
||||||
version: safe(description.package.version),
|
version: safe(description.package.version),
|
||||||
packager: description.package.packager ? safe(description.package.packager) : "",
|
packager: description.package.packager ? safe(description.package.packager) : "",
|
||||||
packages: listToTable(Object.keys(description.package.packages)),
|
packages: listToTable(Object.keys(description.package.packages)),
|
||||||
@ -202,7 +205,7 @@
|
|||||||
|
|
||||||
function selectRepository() {
|
function selectRepository() {
|
||||||
const fragment = window.location.hash.replace("#", "") || "{{ repositories[0].id }}";
|
const fragment = window.location.hash.replace("#", "") || "{{ repositories[0].id }}";
|
||||||
const element = $(`#${fragment}-lnk`);
|
const element = $(`#${fragment}-link`);
|
||||||
element.click();
|
element.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,8 +5,6 @@
|
|||||||
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
<link rel="shortcut icon" href="/static/favicon.ico">
|
|
||||||
|
|
||||||
{% include "utils/style.jinja2" %}
|
{% include "utils/style.jinja2" %}
|
||||||
{% include "user-style.jinja2" ignore missing %}
|
{% include "user-style.jinja2" ignore missing %}
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<script src="https://cdn.jsdelivr.net/npm/jquery@3.7.0/dist/jquery.min.js" integrity="sha384-NXgwF8Kv9SSAr+jemKKcbvQsz+teULH/a5UNJvZc6kP47hZgl62M1vGnw6gHQhb1" crossorigin="anonymous" type="application/javascript"></script>
|
<script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js" integrity="sha384-1H217gwSVyLSIfaLxHbE7dRb3v4mYCKbpQvzx0cegeju1MVsGrX5xXxAvs/HgeFs" crossorigin="anonymous" type="application/javascript"></script>
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/moment@2.29.4/moment.min.js" integrity="sha384-8hHkOkbWN1TLWwet/jpbJ0zbx3FJDeYJgQ8dX1mRrv/vfCfHCqFSFZYCgaMML3z9" crossorigin="anonymous" type="application/javascript"></script>
|
<script src="https://cdn.jsdelivr.net/npm/moment@2.29.4/moment.min.js" integrity="sha384-8hHkOkbWN1TLWwet/jpbJ0zbx3FJDeYJgQ8dX1mRrv/vfCfHCqFSFZYCgaMML3z9" crossorigin="anonymous" type="application/javascript"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/daterangepicker@3.1.0/daterangepicker.min.js" integrity="sha384-u4eJN1VWrTf/FnYYQJo2kqJyVxEQf5UmWY4iUcNAoLenOEtEuCkfwc5bKvZOWBi5" crossorigin="anonymous" type="application/javascript"></script>
|
<script src="https://cdn.jsdelivr.net/npm/daterangepicker@3.1.0/daterangepicker.min.js" integrity="sha384-u4eJN1VWrTf/FnYYQJo2kqJyVxEQf5UmWY4iUcNAoLenOEtEuCkfwc5bKvZOWBi5" crossorigin="anonymous" type="application/javascript"></script>
|
||||||
@ -8,14 +8,12 @@
|
|||||||
<script src="https://cdn.jsdelivr.net/npm/jquery-resizable-columns@0.2.3/dist/jquery.resizableColumns.min.js" integrity="sha384-IazMVNyYoUNx6357fWJoqtHYUWWCNHIXxFVtbpVgvImQNWuRP2WbHPaIb3QF8j97" crossorigin="anonymous" type="application/javascript"></script>
|
<script src="https://cdn.jsdelivr.net/npm/jquery-resizable-columns@0.2.3/dist/jquery.resizableColumns.min.js" integrity="sha384-IazMVNyYoUNx6357fWJoqtHYUWWCNHIXxFVtbpVgvImQNWuRP2WbHPaIb3QF8j97" crossorigin="anonymous" type="application/javascript"></script>
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js" integrity="sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r" crossorigin="anonymous" type="application/javascript"></script>
|
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js" integrity="sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r" crossorigin="anonymous" type="application/javascript"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.min.js" integrity="sha384-cuYeSxntonz0PPNlHhBs68uyIAVpIIOZZ5JqeqvYYIcEL727kskC66kF92t6Xl2V" crossorigin="anonymous" type="application/javascript"></script>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.min.js" integrity="sha384-BBtl+eGJRgqQAUMxJ7pMwbEyER4l1g+O15P+16Ep7Q9Q+zqX6gSbd85u4mG4QzX+" crossorigin="anonymous" type="application/javascript"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap-table@1.22.1/dist/bootstrap-table.min.js" integrity="sha384-GVLHfbEvuGA/RFiQ3MK2ClEJkWYJXABg55t9LpoDPZFGIsSq8xhFlQydm5poV2jW" crossorigin="anonymous" type="application/javascript"></script>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap-table@1.22.1/dist/bootstrap-table.min.js" integrity="sha384-GVLHfbEvuGA/RFiQ3MK2ClEJkWYJXABg55t9LpoDPZFGIsSq8xhFlQydm5poV2jW" crossorigin="anonymous" type="application/javascript"></script>
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap-table@1.21.4/dist/extensions/export/bootstrap-table-export.min.js" integrity="sha384-jeldDadm+qM2RwGER3qVqxFgWVpAEJ7Jie+0rlYj8ni3KkQA654T8TSXDtol022X" crossorigin="anonymous" type="application/javascript"></script>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap-table@1.22.1/dist/extensions/export/bootstrap-table-export.min.js" integrity="sha384-g9OAB1Moamcy8+l1Q/tajHlMf6NTkS79ehKLTYbA80aQRbRhFCjrSuezv+FE2Kwe" crossorigin="anonymous" type="application/javascript"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap-table@1.22.1/dist/extensions/resizable/bootstrap-table-resizable.js" integrity="sha384-wd8Vc6Febikdnsnk9vthRWRvMwffw246vhqiqNO3aSNe1maTEA07Vh3zAQiSyDji" crossorigin="anonymous" type="application/javascript"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap-table@1.21.4/dist/extensions/resizable/bootstrap-table-resizable.js" integrity="sha384-wd8Vc6Febikdnsnk9vthRWRvMwffw246vhqiqNO3aSNe1maTEA07Vh3zAQiSyDji" crossorigin="anonymous" type="application/javascript"></script>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap-table@1.22.1/dist/extensions/filter-control/bootstrap-table-filter-control.js" integrity="sha384-NIqcjpr/3eZI1iNzz7hgT5rgp70qFUzkZffeCgVva9gi80B5vqcm7gn+8QvlWxko" crossorigin="anonymous" type="application/javascript"></script>
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap-table@1.21.4/dist/extensions/filter-control/bootstrap-table-filter-control.js" integrity="sha384-B6xNXlSOaOFxjlKo9OW3htbox+9/DcaEcjPPEi1+pTMwH5Tzc/s2wNTYriHz7Tb8" crossorigin="anonymous" type="application/javascript"></script>
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
async function copyToClipboard(text, button) {
|
async function copyToClipboard(text, button) {
|
||||||
@ -81,8 +79,17 @@
|
|||||||
.replace(/"/g, """);
|
.replace(/"/g, """);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// because I'm tired of safe element generation
|
||||||
|
function safeLink(url, text, title) {
|
||||||
|
const element = document.createElement("a");
|
||||||
|
element.href = url;
|
||||||
|
element.innerText = text;
|
||||||
|
if (title) element.title = title;
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
Date.prototype.toISOStringShort = function() {
|
Date.prototype.toISOStringShort = function() {
|
||||||
const pad = number => String(number).padStart(2, "0");
|
const pad = number => String(number).padStart(2, "0");
|
||||||
return `${this.getFullYear()}-${pad(this.getMonth())}-${pad(this.getDate())} ${pad(this.getHours())}:${pad(this.getMinutes())}:${pad(this.getSeconds())}`;
|
return `${this.getFullYear()}-${pad(this.getMonth() + 1)}-${pad(this.getDate())} ${pad(this.getHours())}:${pad(this.getMinutes())}:${pad(this.getSeconds())}`;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous" type="text/css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous" type="text/css">
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.4/font/bootstrap-icons.css" integrity="sha384-LrVLJJYk9OiJmjNDakUBU7kS9qCT8wk1j2OU7ncpsfB3QS37UPdkCuq3ZD1MugNY" crossorigin="anonymous" type="text/css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css" integrity="sha384-4LISF5TTJX/fLmGSxO53rV4miRxdg84mZsxmO8Rx5jGtp/LbrixFETvWa5a6sESd" crossorigin="anonymous" type="text/css">
|
||||||
|
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-table@1.21.4/dist/bootstrap-table.min.css" integrity="sha384-pTEAhytv7JmEG2D7qiW5gY0lI5EKZ9n3CNmj6Qp+U3qhnmH2qnnN9KJbVwbtMHN0" crossorigin="anonymous" type="text/css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-table@1.22.1/dist/bootstrap-table.min.css" integrity="sha384-sN3NwxbjH33ZidqZnPmX+nQ5IF+LoiI7HvZSoZj5wGacmu0/q4RJfsN0xqN+LIa5" crossorigin="anonymous" type="text/css">
|
||||||
|
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/jquery-resizable-columns@0.2.3/dist/jquery.resizableColumns.css" integrity="sha384-1sLxvR8mXzjhvFY9f8mzXl97DNLepeZ0PnRiMMdm/rQsKjsrPZPJxYle2wwT2PMg" crossorigin="anonymous" type="text/css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/jquery-resizable-columns@0.2.3/dist/jquery.resizableColumns.css" integrity="sha384-1sLxvR8mXzjhvFY9f8mzXl97DNLepeZ0PnRiMMdm/rQsKjsrPZPJxYle2wwT2PMg" crossorigin="anonymous" type="text/css">
|
||||||
|
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-table@1.21.4/dist/extensions/filter-control/bootstrap-table-filter-control.css" integrity="sha384-4Glx18jZ0Un+yDG6KUpYJ/af8hkssJ02jRASuFv23gfCl0mTXaVMPI9cB4cn3GvE" crossorigin="anonymous" type="text/css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-table@1.22.1/dist/extensions/filter-control/bootstrap-table-filter-control.css" integrity="sha384-4Glx18jZ0Un+yDG6KUpYJ/af8hkssJ02jRASuFv23gfCl0mTXaVMPI9cB4cn3GvE" crossorigin="anonymous" type="text/css">
|
||||||
|
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootswatch@5.2.3/dist/cosmo/bootstrap.min.css" integrity="sha384-P1PBFVifKf1Ww0gS5B8A0siIeDpcFd4uU7S68LA1XMdE0R+y1WN3DR4HcLc9csRC" crossorigin="anonymous" type="text/css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootswatch@5.3.2/dist/cosmo/bootstrap.min.css" integrity="sha384-RfV5VNj9uqyOdZbN0hFNmoq56291KK2Y4iKhoRAbcfBfjYlpasjxK6TefPjxiAiN" crossorigin="anonymous" type="text/css">
|
||||||
|
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/daterangepicker@3.1.0/daterangepicker.css" integrity="sha384-zLkQsiLfAQqGeIJeKLC+rcCR1YoYaQFLCL7cLDUoKE1ajKJzySpjzWGfYS2vjSG+" crossorigin="anonymous" type="text/css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/daterangepicker@3.1.0/daterangepicker.css" integrity="sha384-zLkQsiLfAQqGeIJeKLC+rcCR1YoYaQFLCL7cLDUoKE1ajKJzySpjzWGfYS2vjSG+" crossorigin="anonymous" type="text/css">
|
||||||
|
|
||||||
|
|||||||
@ -1,18 +1,18 @@
|
|||||||
# AUTOMATICALLY GENERATED by `shtab`
|
# AUTOMATICALLY GENERATED by `shtab`
|
||||||
|
|
||||||
_shtab_ahriman_subparsers=('aur-search' 'search' 'help' 'help-commands-unsafe' 'help-updates' 'help-version' 'version' 'package-add' 'add' 'package-update' 'package-remove' 'remove' 'package-status' 'status' 'package-status-remove' 'package-status-update' 'status-update' 'patch-add' 'patch-list' 'patch-remove' 'patch-set-add' 'repo-backup' 'repo-check' 'check' 'repo-create-keyring' 'repo-create-mirrorlist' 'repo-daemon' 'daemon' 'repo-rebuild' 'rebuild' 'repo-remove-unknown' 'remove-unknown' 'repo-report' 'report' 'repo-restore' 'repo-sign' 'sign' 'repo-status-update' 'repo-sync' 'sync' 'repo-tree' 'repo-triggers' 'repo-update' 'update' 'service-clean' 'clean' 'repo-clean' 'service-config' 'config' 'repo-config' 'service-config-validate' 'config-validate' 'repo-config-validate' 'service-key-import' 'key-import' 'service-repositories' 'service-setup' 'init' 'repo-init' 'repo-setup' 'setup' 'service-shell' 'shell' 'service-tree-migrate' 'user-add' 'user-list' 'user-remove' 'web')
|
_shtab_ahriman_subparsers=('aur-search' 'search' 'help-commands-unsafe' 'help' 'help-updates' 'help-version' 'version' 'package-add' 'add' 'package-update' 'package-remove' 'remove' 'package-status' 'status' 'package-status-remove' 'package-status-update' 'status-update' 'patch-add' 'patch-list' 'patch-remove' 'patch-set-add' 'repo-backup' 'repo-check' 'check' 'repo-create-keyring' 'repo-create-mirrorlist' 'repo-daemon' 'daemon' 'repo-rebuild' 'rebuild' 'repo-remove-unknown' 'remove-unknown' 'repo-report' 'report' 'repo-restore' 'repo-sign' 'sign' 'repo-status-update' 'repo-sync' 'sync' 'repo-tree' 'repo-triggers' 'repo-update' 'update' 'service-clean' 'clean' 'repo-clean' 'service-config' 'config' 'repo-config' 'service-config-validate' 'config-validate' 'repo-config-validate' 'service-key-import' 'key-import' 'service-repositories' 'service-run' 'run' 'service-setup' 'init' 'repo-init' 'repo-setup' 'setup' 'service-shell' 'shell' 'service-tree-migrate' 'user-add' 'user-list' 'user-remove' 'web')
|
||||||
|
|
||||||
_shtab_ahriman_option_strings=('-h' '--help' '-a' '--architecture' '-c' '--configuration' '--force' '-l' '--lock' '--log-handler' '-q' '--quiet' '--report' '--no-report' '-r' '--repository' '--unsafe' '--wait-timeout' '-V' '--version')
|
_shtab_ahriman_option_strings=('-h' '--help' '-a' '--architecture' '-c' '--configuration' '--force' '-l' '--lock' '--log-handler' '-q' '--quiet' '--report' '--no-report' '-r' '--repository' '--unsafe' '--wait-timeout' '-V' '--version')
|
||||||
_shtab_ahriman_aur_search_option_strings=('-h' '--help' '-e' '--exit-code' '--info' '--no-info' '--sort-by')
|
_shtab_ahriman_aur_search_option_strings=('-h' '--help' '-e' '--exit-code' '--info' '--no-info' '--sort-by')
|
||||||
_shtab_ahriman_search_option_strings=('-h' '--help' '-e' '--exit-code' '--info' '--no-info' '--sort-by')
|
_shtab_ahriman_search_option_strings=('-h' '--help' '-e' '--exit-code' '--info' '--no-info' '--sort-by')
|
||||||
_shtab_ahriman_help_option_strings=('-h' '--help')
|
|
||||||
_shtab_ahriman_help_commands_unsafe_option_strings=('-h' '--help')
|
_shtab_ahriman_help_commands_unsafe_option_strings=('-h' '--help')
|
||||||
|
_shtab_ahriman_help_option_strings=('-h' '--help')
|
||||||
_shtab_ahriman_help_updates_option_strings=('-h' '--help' '-e' '--exit-code')
|
_shtab_ahriman_help_updates_option_strings=('-h' '--help' '-e' '--exit-code')
|
||||||
_shtab_ahriman_help_version_option_strings=('-h' '--help')
|
_shtab_ahriman_help_version_option_strings=('-h' '--help')
|
||||||
_shtab_ahriman_version_option_strings=('-h' '--help')
|
_shtab_ahriman_version_option_strings=('-h' '--help')
|
||||||
_shtab_ahriman_package_add_option_strings=('-h' '--help' '--dependencies' '--no-dependencies' '-e' '--exit-code' '--increment' '--no-increment' '-n' '--now' '-y' '--refresh' '-s' '--source' '-u' '--username')
|
_shtab_ahriman_package_add_option_strings=('-h' '--help' '--dependencies' '--no-dependencies' '-e' '--exit-code' '--increment' '--no-increment' '-n' '--now' '-y' '--refresh' '-s' '--source' '-u' '--username' '-v' '--variable')
|
||||||
_shtab_ahriman_add_option_strings=('-h' '--help' '--dependencies' '--no-dependencies' '-e' '--exit-code' '--increment' '--no-increment' '-n' '--now' '-y' '--refresh' '-s' '--source' '-u' '--username')
|
_shtab_ahriman_add_option_strings=('-h' '--help' '--dependencies' '--no-dependencies' '-e' '--exit-code' '--increment' '--no-increment' '-n' '--now' '-y' '--refresh' '-s' '--source' '-u' '--username' '-v' '--variable')
|
||||||
_shtab_ahriman_package_update_option_strings=('-h' '--help' '--dependencies' '--no-dependencies' '-e' '--exit-code' '--increment' '--no-increment' '-n' '--now' '-y' '--refresh' '-s' '--source' '-u' '--username')
|
_shtab_ahriman_package_update_option_strings=('-h' '--help' '--dependencies' '--no-dependencies' '-e' '--exit-code' '--increment' '--no-increment' '-n' '--now' '-y' '--refresh' '-s' '--source' '-u' '--username' '-v' '--variable')
|
||||||
_shtab_ahriman_package_remove_option_strings=('-h' '--help')
|
_shtab_ahriman_package_remove_option_strings=('-h' '--help')
|
||||||
_shtab_ahriman_remove_option_strings=('-h' '--help')
|
_shtab_ahriman_remove_option_strings=('-h' '--help')
|
||||||
_shtab_ahriman_package_status_option_strings=('-h' '--help' '--ahriman' '-e' '--exit-code' '--info' '--no-info' '-s' '--status')
|
_shtab_ahriman_package_status_option_strings=('-h' '--help' '--ahriman' '-e' '--exit-code' '--info' '--no-info' '-s' '--status')
|
||||||
@ -59,6 +59,8 @@ _shtab_ahriman_repo_config_validate_option_strings=('-h' '--help' '-e' '--exit-c
|
|||||||
_shtab_ahriman_service_key_import_option_strings=('-h' '--help' '--key-server')
|
_shtab_ahriman_service_key_import_option_strings=('-h' '--help' '--key-server')
|
||||||
_shtab_ahriman_key_import_option_strings=('-h' '--help' '--key-server')
|
_shtab_ahriman_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_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_init_option_strings=('-h' '--help' '--build-as-user' '--from-configuration' '--generate-salt' '--no-generate-salt' '--makeflags-jobs' '--no-makeflags-jobs' '--mirror' '--multilib' '--no-multilib' '--packager' '--server' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket')
|
_shtab_ahriman_init_option_strings=('-h' '--help' '--build-as-user' '--from-configuration' '--generate-salt' '--no-generate-salt' '--makeflags-jobs' '--no-makeflags-jobs' '--mirror' '--multilib' '--no-multilib' '--packager' '--server' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket')
|
||||||
_shtab_ahriman_repo_init_option_strings=('-h' '--help' '--build-as-user' '--from-configuration' '--generate-salt' '--no-generate-salt' '--makeflags-jobs' '--no-makeflags-jobs' '--mirror' '--multilib' '--no-multilib' '--packager' '--server' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket')
|
_shtab_ahriman_repo_init_option_strings=('-h' '--help' '--build-as-user' '--from-configuration' '--generate-salt' '--no-generate-salt' '--makeflags-jobs' '--no-makeflags-jobs' '--mirror' '--multilib' '--no-multilib' '--packager' '--server' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket')
|
||||||
@ -74,7 +76,7 @@ _shtab_ahriman_web_option_strings=('-h' '--help')
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
_shtab_ahriman_pos_0_choices=('aur-search' 'search' 'help' 'help-commands-unsafe' 'help-updates' 'help-version' 'version' 'package-add' 'add' 'package-update' 'package-remove' 'remove' 'package-status' 'status' 'package-status-remove' 'package-status-update' 'status-update' 'patch-add' 'patch-list' 'patch-remove' 'patch-set-add' 'repo-backup' 'repo-check' 'check' 'repo-create-keyring' 'repo-create-mirrorlist' 'repo-daemon' 'daemon' 'repo-rebuild' 'rebuild' 'repo-remove-unknown' 'remove-unknown' 'repo-report' 'report' 'repo-restore' 'repo-sign' 'sign' 'repo-status-update' 'repo-sync' 'sync' 'repo-tree' 'repo-triggers' 'repo-update' 'update' 'service-clean' 'clean' 'repo-clean' 'service-config' 'config' 'repo-config' 'service-config-validate' 'config-validate' 'repo-config-validate' 'service-key-import' 'key-import' 'service-repositories' 'service-setup' 'init' 'repo-init' 'repo-setup' 'setup' 'service-shell' 'shell' 'service-tree-migrate' 'user-add' 'user-list' 'user-remove' 'web')
|
_shtab_ahriman_pos_0_choices=('aur-search' 'search' 'help-commands-unsafe' 'help' 'help-updates' 'help-version' 'version' 'package-add' 'add' 'package-update' 'package-remove' 'remove' 'package-status' 'status' 'package-status-remove' 'package-status-update' 'status-update' 'patch-add' 'patch-list' 'patch-remove' 'patch-set-add' 'repo-backup' 'repo-check' 'check' 'repo-create-keyring' 'repo-create-mirrorlist' 'repo-daemon' 'daemon' 'repo-rebuild' 'rebuild' 'repo-remove-unknown' 'remove-unknown' 'repo-report' 'report' 'repo-restore' 'repo-sign' 'sign' 'repo-status-update' 'repo-sync' 'sync' 'repo-tree' 'repo-triggers' 'repo-update' 'update' 'service-clean' 'clean' 'repo-clean' 'service-config' 'config' 'repo-config' 'service-config-validate' 'config-validate' 'repo-config-validate' 'service-key-import' 'key-import' 'service-repositories' 'service-run' 'run' 'service-setup' 'init' 'repo-init' 'repo-setup' 'setup' 'service-shell' 'shell' 'service-tree-migrate' 'user-add' 'user-list' 'user-remove' 'web')
|
||||||
_shtab_ahriman___log_handler_choices=('console' 'syslog' 'journald')
|
_shtab_ahriman___log_handler_choices=('console' 'syslog' 'journald')
|
||||||
_shtab_ahriman_aur_search___sort_by_choices=('description' 'first_submitted' 'id' 'last_modified' 'maintainer' 'name' 'num_votes' 'out_of_date' 'package_base' 'package_base_id' 'popularity' 'repository' 'submitter' 'url' 'url_path' 'version')
|
_shtab_ahriman_aur_search___sort_by_choices=('description' 'first_submitted' 'id' 'last_modified' 'maintainer' 'name' 'num_votes' 'out_of_date' 'package_base' 'package_base_id' 'popularity' 'repository' 'submitter' 'url' 'url_path' 'version')
|
||||||
_shtab_ahriman_search___sort_by_choices=('description' 'first_submitted' 'id' 'last_modified' 'maintainer' 'name' 'num_votes' 'out_of_date' 'package_base' 'package_base_id' 'popularity' 'repository' 'submitter' 'url' 'url_path' 'version')
|
_shtab_ahriman_search___sort_by_choices=('description' 'first_submitted' 'id' 'last_modified' 'maintainer' 'name' 'num_votes' 'out_of_date' 'package_base' 'package_base_id' 'popularity' 'repository' 'submitter' 'url' 'url_path' 'version')
|
||||||
@ -133,11 +135,11 @@ _shtab_ahriman_search__e_nargs=0
|
|||||||
_shtab_ahriman_search___exit_code_nargs=0
|
_shtab_ahriman_search___exit_code_nargs=0
|
||||||
_shtab_ahriman_search___info_nargs=0
|
_shtab_ahriman_search___info_nargs=0
|
||||||
_shtab_ahriman_search___no_info_nargs=0
|
_shtab_ahriman_search___no_info_nargs=0
|
||||||
_shtab_ahriman_help__h_nargs=0
|
|
||||||
_shtab_ahriman_help___help_nargs=0
|
|
||||||
_shtab_ahriman_help_commands_unsafe_pos_0_nargs=*
|
_shtab_ahriman_help_commands_unsafe_pos_0_nargs=*
|
||||||
_shtab_ahriman_help_commands_unsafe__h_nargs=0
|
_shtab_ahriman_help_commands_unsafe__h_nargs=0
|
||||||
_shtab_ahriman_help_commands_unsafe___help_nargs=0
|
_shtab_ahriman_help_commands_unsafe___help_nargs=0
|
||||||
|
_shtab_ahriman_help__h_nargs=0
|
||||||
|
_shtab_ahriman_help___help_nargs=0
|
||||||
_shtab_ahriman_help_updates__h_nargs=0
|
_shtab_ahriman_help_updates__h_nargs=0
|
||||||
_shtab_ahriman_help_updates___help_nargs=0
|
_shtab_ahriman_help_updates___help_nargs=0
|
||||||
_shtab_ahriman_help_updates__e_nargs=0
|
_shtab_ahriman_help_updates__e_nargs=0
|
||||||
@ -437,6 +439,12 @@ _shtab_ahriman_service_repositories__h_nargs=0
|
|||||||
_shtab_ahriman_service_repositories___help_nargs=0
|
_shtab_ahriman_service_repositories___help_nargs=0
|
||||||
_shtab_ahriman_service_repositories___id_only_nargs=0
|
_shtab_ahriman_service_repositories___id_only_nargs=0
|
||||||
_shtab_ahriman_service_repositories___no_id_only_nargs=0
|
_shtab_ahriman_service_repositories___no_id_only_nargs=0
|
||||||
|
_shtab_ahriman_service_run_pos_0_nargs=+
|
||||||
|
_shtab_ahriman_service_run__h_nargs=0
|
||||||
|
_shtab_ahriman_service_run___help_nargs=0
|
||||||
|
_shtab_ahriman_run_pos_0_nargs=+
|
||||||
|
_shtab_ahriman_run__h_nargs=0
|
||||||
|
_shtab_ahriman_run___help_nargs=0
|
||||||
_shtab_ahriman_service_setup__h_nargs=0
|
_shtab_ahriman_service_setup__h_nargs=0
|
||||||
_shtab_ahriman_service_setup___help_nargs=0
|
_shtab_ahriman_service_setup___help_nargs=0
|
||||||
_shtab_ahriman_service_setup___generate_salt_nargs=0
|
_shtab_ahriman_service_setup___generate_salt_nargs=0
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
.TH AHRIMAN "1" "2023\-10\-09" "ahriman" "Generated Python Manual"
|
.TH AHRIMAN "1" "2023\-11\-06" "ahriman" "Generated Python Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
ahriman
|
ahriman
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
.B ahriman
|
.B ahriman
|
||||||
[-h] [-a ARCHITECTURE] [-c CONFIGURATION] [--force] [-l LOCK] [--log-handler {console,syslog,journald}] [-q] [--report | --no-report] [-r REPOSITORY] [--unsafe] [--wait-timeout WAIT_TIMEOUT] [-V] {aur-search,search,help,help-commands-unsafe,help-updates,help-version,version,package-add,add,package-update,package-remove,remove,package-status,status,package-status-remove,package-status-update,status-update,patch-add,patch-list,patch-remove,patch-set-add,repo-backup,repo-check,check,repo-create-keyring,repo-create-mirrorlist,repo-daemon,daemon,repo-rebuild,rebuild,repo-remove-unknown,remove-unknown,repo-report,report,repo-restore,repo-sign,sign,repo-status-update,repo-sync,sync,repo-tree,repo-triggers,repo-update,update,service-clean,clean,repo-clean,service-config,config,repo-config,service-config-validate,config-validate,repo-config-validate,service-key-import,key-import,service-repositories,service-setup,init,repo-init,repo-setup,setup,service-shell,shell,service-tree-migrate,user-add,user-list,user-remove,web} ...
|
[-h] [-a ARCHITECTURE] [-c CONFIGURATION] [--force] [-l LOCK] [--log-handler {console,syslog,journald}] [-q] [--report | --no-report] [-r REPOSITORY] [--unsafe] [--wait-timeout WAIT_TIMEOUT] [-V] {aur-search,search,help-commands-unsafe,help,help-updates,help-version,version,package-add,add,package-update,package-remove,remove,package-status,status,package-status-remove,package-status-update,status-update,patch-add,patch-list,patch-remove,patch-set-add,repo-backup,repo-check,check,repo-create-keyring,repo-create-mirrorlist,repo-daemon,daemon,repo-rebuild,rebuild,repo-remove-unknown,remove-unknown,repo-report,report,repo-restore,repo-sign,sign,repo-status-update,repo-sync,sync,repo-tree,repo-triggers,repo-update,update,service-clean,clean,repo-clean,service-config,config,repo-config,service-config-validate,config-validate,repo-config-validate,service-key-import,key-import,service-repositories,service-run,run,service-setup,init,repo-init,repo-setup,setup,service-shell,shell,service-tree-migrate,user-add,user-list,user-remove,web} ...
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
ArcH linux ReposItory MANager
|
ArcH linux ReposItory MANager
|
||||||
|
|
||||||
@ -59,12 +59,12 @@ COMMAND
|
|||||||
\fBahriman\fR \fI\,aur\-search\/\fR
|
\fBahriman\fR \fI\,aur\-search\/\fR
|
||||||
search for package
|
search for package
|
||||||
.TP
|
.TP
|
||||||
\fBahriman\fR \fI\,help\/\fR
|
|
||||||
show help message
|
|
||||||
.TP
|
|
||||||
\fBahriman\fR \fI\,help\-commands\-unsafe\/\fR
|
\fBahriman\fR \fI\,help\-commands\-unsafe\/\fR
|
||||||
list unsafe commands
|
list unsafe commands
|
||||||
.TP
|
.TP
|
||||||
|
\fBahriman\fR \fI\,help\/\fR
|
||||||
|
show help message
|
||||||
|
.TP
|
||||||
\fBahriman\fR \fI\,help\-updates\/\fR
|
\fBahriman\fR \fI\,help\-updates\/\fR
|
||||||
check for service updates
|
check for service updates
|
||||||
.TP
|
.TP
|
||||||
@ -158,6 +158,9 @@ import PGP key
|
|||||||
\fBahriman\fR \fI\,service\-repositories\/\fR
|
\fBahriman\fR \fI\,service\-repositories\/\fR
|
||||||
show repositories
|
show repositories
|
||||||
.TP
|
.TP
|
||||||
|
\fBahriman\fR \fI\,service\-run\/\fR
|
||||||
|
run multiple commands
|
||||||
|
.TP
|
||||||
\fBahriman\fR \fI\,service\-setup\/\fR
|
\fBahriman\fR \fI\,service\-setup\/\fR
|
||||||
initial service configuration
|
initial service configuration
|
||||||
.TP
|
.TP
|
||||||
@ -204,15 +207,6 @@ show additional package information
|
|||||||
sort field by this field. In case if two packages have the same value of the specified field, they will be always sorted
|
sort field by this field. In case if two packages have the same value of the specified field, they will be always sorted
|
||||||
by name
|
by name
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman help'\/\fR
|
|
||||||
usage: ahriman help [\-h] [command]
|
|
||||||
|
|
||||||
show help message for application or command and exit
|
|
||||||
|
|
||||||
.TP
|
|
||||||
\fBcommand\fR
|
|
||||||
show help message for specific command
|
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman help\-commands\-unsafe'\/\fR
|
.SH COMMAND \fI\,'ahriman help\-commands\-unsafe'\/\fR
|
||||||
usage: ahriman help\-commands\-unsafe [\-h] [command ...]
|
usage: ahriman help\-commands\-unsafe [\-h] [command ...]
|
||||||
|
|
||||||
@ -223,6 +217,15 @@ list unsafe commands as defined in default args
|
|||||||
instead of showing commands, just test command line for unsafe subcommand and return 0 in case if command is safe and 1
|
instead of showing commands, just test command line for unsafe subcommand and return 0 in case if command is safe and 1
|
||||||
otherwise
|
otherwise
|
||||||
|
|
||||||
|
.SH COMMAND \fI\,'ahriman help'\/\fR
|
||||||
|
usage: ahriman help [\-h] [command]
|
||||||
|
|
||||||
|
show help message for application or command and exit
|
||||||
|
|
||||||
|
.TP
|
||||||
|
\fBcommand\fR
|
||||||
|
show help message for specific command
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman help\-updates'\/\fR
|
.SH COMMAND \fI\,'ahriman help\-updates'\/\fR
|
||||||
usage: ahriman help\-updates [\-h] [\-e]
|
usage: ahriman help\-updates [\-h] [\-e]
|
||||||
|
|
||||||
@ -240,7 +243,7 @@ print application and its dependencies versions
|
|||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman package\-add'\/\fR
|
.SH COMMAND \fI\,'ahriman package\-add'\/\fR
|
||||||
usage: ahriman package\-add [\-h] [\-\-dependencies | \-\-no\-dependencies] [\-e] [\-\-increment | \-\-no\-increment] [\-n] [\-y]
|
usage: ahriman package\-add [\-h] [\-\-dependencies | \-\-no\-dependencies] [\-e] [\-\-increment | \-\-no\-increment] [\-n] [\-y]
|
||||||
[\-s {auto,archive,aur,directory,local,remote,repository}] [\-u USERNAME]
|
[\-s {auto,archive,aur,directory,local,remote,repository}] [\-u USERNAME] [\-v VARIABLE]
|
||||||
package [package ...]
|
package [package ...]
|
||||||
|
|
||||||
add existing or new package to the build queue
|
add existing or new package to the build queue
|
||||||
@ -278,6 +281,10 @@ explicitly specify the package source for this command
|
|||||||
\fB\-u\fR \fI\,USERNAME\/\fR, \fB\-\-username\fR \fI\,USERNAME\/\fR
|
\fB\-u\fR \fI\,USERNAME\/\fR, \fB\-\-username\fR \fI\,USERNAME\/\fR
|
||||||
build as user
|
build as user
|
||||||
|
|
||||||
|
.TP
|
||||||
|
\fB\-v\fR \fI\,VARIABLE\/\fR, \fB\-\-variable\fR \fI\,VARIABLE\/\fR
|
||||||
|
apply specified makepkg variables to the next build
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman package\-remove'\/\fR
|
.SH COMMAND \fI\,'ahriman package\-remove'\/\fR
|
||||||
usage: ahriman package\-remove [\-h] package [package ...]
|
usage: ahriman package\-remove [\-h] package [package ...]
|
||||||
|
|
||||||
@ -722,6 +729,15 @@ list all available repositories
|
|||||||
\fB\-\-id\-only\fR, \fB\-\-no\-id\-only\fR
|
\fB\-\-id\-only\fR, \fB\-\-no\-id\-only\fR
|
||||||
show machine readable identifier instead
|
show machine readable identifier instead
|
||||||
|
|
||||||
|
.SH COMMAND \fI\,'ahriman service\-run'\/\fR
|
||||||
|
usage: ahriman service\-run [\-h] command [command ...]
|
||||||
|
|
||||||
|
run multiple commands on success run of the previous command
|
||||||
|
|
||||||
|
.TP
|
||||||
|
\fBcommand\fR
|
||||||
|
command to be run (quoted) without ``ahriman``
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman service\-setup'\/\fR
|
.SH COMMAND \fI\,'ahriman service\-setup'\/\fR
|
||||||
usage: ahriman service\-setup [\-h] [\-\-build\-as\-user BUILD_AS_USER] [\-\-from\-configuration FROM_CONFIGURATION]
|
usage: ahriman service\-setup [\-h] [\-\-build\-as\-user BUILD_AS_USER] [\-\-from\-configuration FROM_CONFIGURATION]
|
||||||
[\-\-generate\-salt | \-\-no\-generate\-salt] [\-\-makeflags\-jobs | \-\-no\-makeflags\-jobs]
|
[\-\-generate\-salt | \-\-no\-generate\-salt] [\-\-makeflags\-jobs | \-\-no\-makeflags\-jobs]
|
||||||
|
|||||||
@ -52,12 +52,14 @@ _shtab_ahriman_commands() {
|
|||||||
"repo-triggers:run triggers on empty build result as configured by settings"
|
"repo-triggers:run triggers on empty build result as configured by settings"
|
||||||
"repo-update:check for packages updates and run build process if requested"
|
"repo-update:check for packages updates and run build process if requested"
|
||||||
"report:generate repository report according to current settings"
|
"report:generate repository report according to current settings"
|
||||||
|
"run:run multiple commands on success run of the previous command"
|
||||||
"search:search for package in AUR using API"
|
"search:search for package in AUR using API"
|
||||||
"service-clean:remove local caches"
|
"service-clean:remove local caches"
|
||||||
"service-config:dump configuration for the specified architecture"
|
"service-config:dump configuration for the specified architecture"
|
||||||
"service-config-validate:validate configuration and print found errors"
|
"service-config-validate:validate configuration and print found errors"
|
||||||
"service-key-import:import PGP key from public sources to the repository user"
|
"service-key-import:import PGP key from public sources to the repository user"
|
||||||
"service-repositories:list all available repositories"
|
"service-repositories:list all available repositories"
|
||||||
|
"service-run:run multiple commands on success run of the previous command"
|
||||||
"service-setup:create initial service configuration, requires root"
|
"service-setup:create initial service configuration, requires root"
|
||||||
"service-shell:drop into python shell"
|
"service-shell:drop into python shell"
|
||||||
"service-tree-migrate:migrate repository tree between versions"
|
"service-tree-migrate:migrate repository tree between versions"
|
||||||
@ -99,8 +101,9 @@ _shtab_ahriman_add_options=(
|
|||||||
{--increment,--no-increment}"[increment package release (pkgrel) version on duplicate (default\: True)]:increment:"
|
{--increment,--no-increment}"[increment package release (pkgrel) version on duplicate (default\: True)]:increment:"
|
||||||
{-n,--now}"[run update function after (default\: False)]"
|
{-n,--now}"[run update function after (default\: False)]"
|
||||||
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date (default\: False)]"
|
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date (default\: False)]"
|
||||||
{-s,--source}"[explicitly specify the package source for this command (default\: PackageSource.Auto)]:source:(auto archive aur directory local remote repository)"
|
{-s,--source}"[explicitly specify the package source for this command (default\: auto)]:source:(auto archive aur directory local remote repository)"
|
||||||
{-u,--username}"[build as user (default\: None)]:username:"
|
{-u,--username}"[build as user (default\: None)]:username:"
|
||||||
|
"*"{-v,--variable}"[apply specified makepkg variables to the next build (default\: None)]:variable:"
|
||||||
"(*):package source (base name, path to local files, remote URL):"
|
"(*):package source (base name, path to local files, remote URL):"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -201,8 +204,9 @@ _shtab_ahriman_package_add_options=(
|
|||||||
{--increment,--no-increment}"[increment package release (pkgrel) version on duplicate (default\: True)]:increment:"
|
{--increment,--no-increment}"[increment package release (pkgrel) version on duplicate (default\: True)]:increment:"
|
||||||
{-n,--now}"[run update function after (default\: False)]"
|
{-n,--now}"[run update function after (default\: False)]"
|
||||||
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date (default\: False)]"
|
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date (default\: False)]"
|
||||||
{-s,--source}"[explicitly specify the package source for this command (default\: PackageSource.Auto)]:source:(auto archive aur directory local remote repository)"
|
{-s,--source}"[explicitly specify the package source for this command (default\: auto)]:source:(auto archive aur directory local remote repository)"
|
||||||
{-u,--username}"[build as user (default\: None)]:username:"
|
{-u,--username}"[build as user (default\: None)]:username:"
|
||||||
|
"*"{-v,--variable}"[apply specified makepkg variables to the next build (default\: None)]:variable:"
|
||||||
"(*):package source (base name, path to local files, remote URL):"
|
"(*):package source (base name, path to local files, remote URL):"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -227,7 +231,7 @@ _shtab_ahriman_package_status_remove_options=(
|
|||||||
|
|
||||||
_shtab_ahriman_package_status_update_options=(
|
_shtab_ahriman_package_status_update_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{-s,--status}"[new package build status (default\: BuildStatusEnum.Success)]:status:(unknown pending building failed success)"
|
{-s,--status}"[new package build status (default\: success)]:status:(unknown pending building failed success)"
|
||||||
"(*)::set status for specified packages. If no packages supplied, service status will be updated (default\: None):"
|
"(*)::set status for specified packages. If no packages supplied, service status will be updated (default\: None):"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -238,8 +242,9 @@ _shtab_ahriman_package_update_options=(
|
|||||||
{--increment,--no-increment}"[increment package release (pkgrel) version on duplicate (default\: True)]:increment:"
|
{--increment,--no-increment}"[increment package release (pkgrel) version on duplicate (default\: True)]:increment:"
|
||||||
{-n,--now}"[run update function after (default\: False)]"
|
{-n,--now}"[run update function after (default\: False)]"
|
||||||
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date (default\: False)]"
|
"*"{-y,--refresh}"[download fresh package databases from the mirror before actions, -yy to force refresh even if up to date (default\: False)]"
|
||||||
{-s,--source}"[explicitly specify the package source for this command (default\: PackageSource.Auto)]:source:(auto archive aur directory local remote repository)"
|
{-s,--source}"[explicitly specify the package source for this command (default\: auto)]:source:(auto archive aur directory local remote repository)"
|
||||||
{-u,--username}"[build as user (default\: None)]:username:"
|
{-u,--username}"[build as user (default\: None)]:username:"
|
||||||
|
"*"{-v,--variable}"[apply specified makepkg variables to the next build (default\: None)]:variable:"
|
||||||
"(*):package source (base name, path to local files, remote URL):"
|
"(*):package source (base name, path to local files, remote URL):"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -409,7 +414,7 @@ _shtab_ahriman_repo_sign_options=(
|
|||||||
|
|
||||||
_shtab_ahriman_repo_status_update_options=(
|
_shtab_ahriman_repo_status_update_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{-s,--status}"[new status (default\: BuildStatusEnum.Success)]:status:(unknown pending building failed success)"
|
{-s,--status}"[new status (default\: success)]:status:(unknown pending building failed success)"
|
||||||
)
|
)
|
||||||
|
|
||||||
_shtab_ahriman_repo_sync_options=(
|
_shtab_ahriman_repo_sync_options=(
|
||||||
@ -445,6 +450,11 @@ _shtab_ahriman_report_options=(
|
|||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
_shtab_ahriman_run_options=(
|
||||||
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
|
"(*):command to be run (quoted) without \`\`ahriman\`\`:"
|
||||||
|
)
|
||||||
|
|
||||||
_shtab_ahriman_search_options=(
|
_shtab_ahriman_search_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{-e,--exit-code}"[return non-zero exit status if result is empty (default\: False)]"
|
{-e,--exit-code}"[return non-zero exit status if result is empty (default\: False)]"
|
||||||
@ -486,6 +496,11 @@ _shtab_ahriman_service_repositories_options=(
|
|||||||
{--id-only,--no-id-only}"[show machine readable identifier instead (default\: False)]:id_only:"
|
{--id-only,--no-id-only}"[show machine readable identifier instead (default\: False)]:id_only:"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
_shtab_ahriman_service_run_options=(
|
||||||
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
|
"(*):command to be run (quoted) without \`\`ahriman\`\`:"
|
||||||
|
)
|
||||||
|
|
||||||
_shtab_ahriman_service_setup_options=(
|
_shtab_ahriman_service_setup_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
"--build-as-user[force makepkg user to the specific one (default\: None)]:build_as_user:"
|
"--build-as-user[force makepkg user to the specific one (default\: None)]:build_as_user:"
|
||||||
@ -548,7 +563,7 @@ _shtab_ahriman_status_options=(
|
|||||||
|
|
||||||
_shtab_ahriman_status_update_options=(
|
_shtab_ahriman_status_update_options=(
|
||||||
"(- : *)"{-h,--help}"[show this help message and exit]"
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
{-s,--status}"[new package build status (default\: BuildStatusEnum.Success)]:status:(unknown pending building failed success)"
|
{-s,--status}"[new package build status (default\: success)]:status:(unknown pending building failed success)"
|
||||||
"(*)::set status for specified packages. If no packages supplied, service status will be updated (default\: None):"
|
"(*)::set status for specified packages. If no packages supplied, service status will be updated (default\: None):"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -576,7 +591,7 @@ _shtab_ahriman_user_add_options=(
|
|||||||
"--key[optional PGP key used by this user. The private key must be imported (default\: None)]:key:"
|
"--key[optional PGP key used by this user. The private key must be imported (default\: None)]:key:"
|
||||||
"--packager[optional packager id used for build process in form of \`Name Surname \<mail\@example.com\>\` (default\: None)]:packager:"
|
"--packager[optional packager id used for build process in form of \`Name Surname \<mail\@example.com\>\` (default\: None)]:packager:"
|
||||||
{-p,--password}"[user password. Blank password will be treated as empty password, which is in particular must be used for OAuth2 authorization type. (default\: None)]:password:"
|
{-p,--password}"[user password. Blank password will be treated as empty password, which is in particular must be used for OAuth2 authorization type. (default\: None)]:password:"
|
||||||
{-R,--role}"[user access level (default\: UserAccess.Read)]:role:(unauthorized read reporter full)"
|
{-R,--role}"[user access level (default\: read)]:role:(unauthorized read reporter full)"
|
||||||
":username for web service:"
|
":username for web service:"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -662,12 +677,14 @@ _shtab_ahriman() {
|
|||||||
repo-triggers) _arguments -C -s $_shtab_ahriman_repo_triggers_options ;;
|
repo-triggers) _arguments -C -s $_shtab_ahriman_repo_triggers_options ;;
|
||||||
repo-update) _arguments -C -s $_shtab_ahriman_repo_update_options ;;
|
repo-update) _arguments -C -s $_shtab_ahriman_repo_update_options ;;
|
||||||
report) _arguments -C -s $_shtab_ahriman_report_options ;;
|
report) _arguments -C -s $_shtab_ahriman_report_options ;;
|
||||||
|
run) _arguments -C -s $_shtab_ahriman_run_options ;;
|
||||||
search) _arguments -C -s $_shtab_ahriman_search_options ;;
|
search) _arguments -C -s $_shtab_ahriman_search_options ;;
|
||||||
service-clean) _arguments -C -s $_shtab_ahriman_service_clean_options ;;
|
service-clean) _arguments -C -s $_shtab_ahriman_service_clean_options ;;
|
||||||
service-config) _arguments -C -s $_shtab_ahriman_service_config_options ;;
|
service-config) _arguments -C -s $_shtab_ahriman_service_config_options ;;
|
||||||
service-config-validate) _arguments -C -s $_shtab_ahriman_service_config_validate_options ;;
|
service-config-validate) _arguments -C -s $_shtab_ahriman_service_config_validate_options ;;
|
||||||
service-key-import) _arguments -C -s $_shtab_ahriman_service_key_import_options ;;
|
service-key-import) _arguments -C -s $_shtab_ahriman_service_key_import_options ;;
|
||||||
service-repositories) _arguments -C -s $_shtab_ahriman_service_repositories_options ;;
|
service-repositories) _arguments -C -s $_shtab_ahriman_service_repositories_options ;;
|
||||||
|
service-run) _arguments -C -s $_shtab_ahriman_service_run_options ;;
|
||||||
service-setup) _arguments -C -s $_shtab_ahriman_service_setup_options ;;
|
service-setup) _arguments -C -s $_shtab_ahriman_service_setup_options ;;
|
||||||
service-shell) _arguments -C -s $_shtab_ahriman_service_shell_options ;;
|
service-shell) _arguments -C -s $_shtab_ahriman_service_shell_options ;;
|
||||||
service-tree-migrate) _arguments -C -s $_shtab_ahriman_service_tree_migrate_options ;;
|
service-tree-migrate) _arguments -C -s $_shtab_ahriman_service_tree_migrate_options ;;
|
||||||
|
|||||||
207
pylint_plugins/definition_order.py
Normal file
207
pylint_plugins/definition_order.py
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2021-2023 ahriman team.
|
||||||
|
#
|
||||||
|
# This file is part of ahriman
|
||||||
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
from astroid import nodes
|
||||||
|
from collections.abc import Iterable
|
||||||
|
from enum import StrEnum
|
||||||
|
from pylint.checkers import BaseRawFileChecker
|
||||||
|
from pylint.lint import PyLinter
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
|
class MethodTypeOrder(StrEnum):
|
||||||
|
"""
|
||||||
|
method type enumeration
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
Class(MethodTypeOrder): (class attribute) class method
|
||||||
|
Init(MethodTypeOrder): (class attribute) initialization method
|
||||||
|
Magic(MethodTypeOrder): (class attribute) other magical methods
|
||||||
|
New(MethodTypeOrder): (class attribute) constructor method
|
||||||
|
Normal(MethodTypeOrder): (class attribute) usual method
|
||||||
|
Property(MethodTypeOrder): (class attribute) property method
|
||||||
|
Static(MethodTypeOrder): (class attribute) static method
|
||||||
|
"""
|
||||||
|
|
||||||
|
Class = "classmethod"
|
||||||
|
Init = "init"
|
||||||
|
Magic = "magic"
|
||||||
|
New = "new"
|
||||||
|
Normal = "regular"
|
||||||
|
Property = "property"
|
||||||
|
Static = "staticmethod"
|
||||||
|
|
||||||
|
|
||||||
|
class DefinitionOrder(BaseRawFileChecker):
|
||||||
|
"""
|
||||||
|
check if methods are defined in recommended order
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
DECORATED_METHODS_ORDER(list[str]): (class attribute) predefined list of known function decorators
|
||||||
|
"""
|
||||||
|
|
||||||
|
DECORATED_METHODS_ORDER = {
|
||||||
|
"cached_property": MethodTypeOrder.Property,
|
||||||
|
"classmethod": MethodTypeOrder.Class,
|
||||||
|
"property": MethodTypeOrder.Property,
|
||||||
|
"staticmethod": MethodTypeOrder.Static,
|
||||||
|
}
|
||||||
|
|
||||||
|
name = "method-ordering"
|
||||||
|
msgs = {
|
||||||
|
"W6001": (
|
||||||
|
"Invalid method order %s, expected %s",
|
||||||
|
"methods-out-of-order",
|
||||||
|
"Methods are defined out of recommended order.",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
options = (
|
||||||
|
(
|
||||||
|
"method-type-order",
|
||||||
|
{
|
||||||
|
"default": [
|
||||||
|
"new",
|
||||||
|
"init",
|
||||||
|
"property",
|
||||||
|
"classmethod",
|
||||||
|
"staticmethod",
|
||||||
|
"regular",
|
||||||
|
"magic",
|
||||||
|
],
|
||||||
|
"type": "csv",
|
||||||
|
"metavar": "<comma-separated types>",
|
||||||
|
"help": "Method types order to check.",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def methods(source: Iterable[Any], start_lineno: int = 0) -> list[nodes.FunctionDef]:
|
||||||
|
"""
|
||||||
|
extract function nodes from list of raw nodes
|
||||||
|
|
||||||
|
Args:
|
||||||
|
source(Iterable[Any]): all available nodes
|
||||||
|
start_lineno(int, optional): minimal allowed line number (Default value = 0)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list[nodes.FunctionDef]: list of function nodes
|
||||||
|
"""
|
||||||
|
def is_defined_function(function: Any) -> bool:
|
||||||
|
return isinstance(function, nodes.FunctionDef) \
|
||||||
|
and function.lineno is not None \
|
||||||
|
and function.lineno >= start_lineno
|
||||||
|
|
||||||
|
return list(filter(is_defined_function, source))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resolve_type(function: nodes.FunctionDef) -> MethodTypeOrder:
|
||||||
|
"""
|
||||||
|
resolve type of the function
|
||||||
|
|
||||||
|
Args:
|
||||||
|
function(nodes.FunctionDef): function definition
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
MethodTypeOrder: resolved function type
|
||||||
|
"""
|
||||||
|
# init methods
|
||||||
|
if function.name in ("__new__",):
|
||||||
|
return MethodTypeOrder.New
|
||||||
|
if function.name in ("__init__", "__post_init__"):
|
||||||
|
return MethodTypeOrder.Init
|
||||||
|
|
||||||
|
# decorated methods
|
||||||
|
decorators = []
|
||||||
|
if function.decorators is not None:
|
||||||
|
decorators = [getattr(decorator, "name", None) for decorator in function.decorators.get_children()]
|
||||||
|
for decorator in decorators:
|
||||||
|
if decorator in DefinitionOrder.DECORATED_METHODS_ORDER:
|
||||||
|
return DefinitionOrder.DECORATED_METHODS_ORDER[decorator]
|
||||||
|
|
||||||
|
# magic methods
|
||||||
|
if function.name.startswith("__") and function.name.endswith("__"):
|
||||||
|
return MethodTypeOrder.Magic
|
||||||
|
|
||||||
|
# normal method
|
||||||
|
return MethodTypeOrder.Normal
|
||||||
|
|
||||||
|
def check_class(self, clazz: nodes.ClassDef) -> None:
|
||||||
|
"""
|
||||||
|
check class functions ordering
|
||||||
|
|
||||||
|
Args:
|
||||||
|
clazz(nodes.ClassDef): class definition
|
||||||
|
"""
|
||||||
|
methods = self.methods(clazz.values(), clazz.lineno)
|
||||||
|
self.check_functions(methods)
|
||||||
|
|
||||||
|
def check_functions(self, functions: list[nodes.FunctionDef]) -> None:
|
||||||
|
"""
|
||||||
|
check global functions ordering
|
||||||
|
|
||||||
|
Args:
|
||||||
|
functions(list[nodes.FunctionDef]): list of functions in their defined order
|
||||||
|
"""
|
||||||
|
for real, expected in zip(functions, sorted(functions, key=self.comparator)):
|
||||||
|
if real == expected:
|
||||||
|
continue
|
||||||
|
self.add_message("methods-out-of-order", line=real.lineno, args=(real.name, expected.name))
|
||||||
|
break
|
||||||
|
|
||||||
|
def comparator(self, function: nodes.FunctionDef) -> tuple[int, str]:
|
||||||
|
"""
|
||||||
|
compare key for sorting function
|
||||||
|
|
||||||
|
Args:
|
||||||
|
function(nodes.FunctionDef): function definition
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
tuple[int, str]: comparison key for the specified function definition
|
||||||
|
"""
|
||||||
|
function_type = self.resolve_type(function)
|
||||||
|
try:
|
||||||
|
function_type_index = self.linter.config.method_type_order.index(function_type)
|
||||||
|
except ValueError:
|
||||||
|
function_type_index = 10 # not in the list
|
||||||
|
|
||||||
|
return function_type_index, function.name
|
||||||
|
|
||||||
|
def process_module(self, node: nodes.Module) -> None:
|
||||||
|
"""
|
||||||
|
process module
|
||||||
|
|
||||||
|
Args:
|
||||||
|
node(nodes.Module): module node to check
|
||||||
|
"""
|
||||||
|
# check global methods
|
||||||
|
self.check_functions(self.methods(node.values()))
|
||||||
|
# check class definitions
|
||||||
|
for clazz in filter(lambda method: isinstance(method, nodes.ClassDef), node.values()):
|
||||||
|
self.check_class(clazz)
|
||||||
|
|
||||||
|
|
||||||
|
def register(linter: PyLinter) -> None:
|
||||||
|
"""
|
||||||
|
register custom checker
|
||||||
|
|
||||||
|
Args:
|
||||||
|
linter(PyLinter): linter in which checker should be registered
|
||||||
|
"""
|
||||||
|
linter.register_checker(DefinitionOrder(linter))
|
||||||
@ -40,7 +40,7 @@ check = [
|
|||||||
"mypy",
|
"mypy",
|
||||||
"pylint",
|
"pylint",
|
||||||
]
|
]
|
||||||
docs = [
|
docs = [
|
||||||
"Sphinx",
|
"Sphinx",
|
||||||
"argparse-manpage",
|
"argparse-manpage",
|
||||||
"pydeps",
|
"pydeps",
|
||||||
|
|||||||
@ -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.11.0"
|
__version__ = "2.12.0"
|
||||||
|
|||||||
@ -96,8 +96,8 @@ def _parser() -> argparse.ArgumentParser:
|
|||||||
subparsers = parser.add_subparsers(title="command", help="command to run", dest="command")
|
subparsers = parser.add_subparsers(title="command", help="command to run", dest="command")
|
||||||
|
|
||||||
_set_aur_search_parser(subparsers)
|
_set_aur_search_parser(subparsers)
|
||||||
_set_help_parser(subparsers)
|
|
||||||
_set_help_commands_unsafe_parser(subparsers)
|
_set_help_commands_unsafe_parser(subparsers)
|
||||||
|
_set_help_parser(subparsers)
|
||||||
_set_help_updates_parser(subparsers)
|
_set_help_updates_parser(subparsers)
|
||||||
_set_help_version_parser(subparsers)
|
_set_help_version_parser(subparsers)
|
||||||
_set_package_add_parser(subparsers)
|
_set_package_add_parser(subparsers)
|
||||||
@ -166,25 +166,6 @@ def _set_aur_search_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
|||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
def _set_help_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
|
||||||
"""
|
|
||||||
add parser for listing help subcommand
|
|
||||||
|
|
||||||
Args:
|
|
||||||
root(SubParserAction): subparsers for the commands
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
argparse.ArgumentParser: created argument parser
|
|
||||||
"""
|
|
||||||
parser = root.add_parser("help", help="show help message",
|
|
||||||
description="show help message for application or command and exit",
|
|
||||||
formatter_class=_formatter)
|
|
||||||
parser.add_argument("command", help="show help message for specific command", nargs="?")
|
|
||||||
parser.set_defaults(handler=handlers.Help, architecture="", lock=None, quiet=True, report=False, repository="",
|
|
||||||
unsafe=True, parser=_parser)
|
|
||||||
return parser
|
|
||||||
|
|
||||||
|
|
||||||
def _set_help_commands_unsafe_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
def _set_help_commands_unsafe_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
"""
|
"""
|
||||||
add parser for listing unsafe commands
|
add parser for listing unsafe commands
|
||||||
@ -204,6 +185,25 @@ def _set_help_commands_unsafe_parser(root: SubParserAction) -> argparse.Argument
|
|||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
|
def _set_help_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
|
"""
|
||||||
|
add parser for listing help subcommand
|
||||||
|
|
||||||
|
Args:
|
||||||
|
root(SubParserAction): subparsers for the commands
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
argparse.ArgumentParser: created argument parser
|
||||||
|
"""
|
||||||
|
parser = root.add_parser("help", help="show help message",
|
||||||
|
description="show help message for application or command and exit",
|
||||||
|
formatter_class=_formatter)
|
||||||
|
parser.add_argument("command", help="show help message for specific command", nargs="?")
|
||||||
|
parser.set_defaults(handler=handlers.Help, architecture="", lock=None, quiet=True, report=False, repository="",
|
||||||
|
unsafe=True, parser=_parser)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
|
||||||
def _set_help_updates_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
def _set_help_updates_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
"""
|
"""
|
||||||
add parser for service update check subcommand
|
add parser for service update check subcommand
|
||||||
|
|||||||
@ -32,8 +32,8 @@ class Application(ApplicationPackages, ApplicationRepository):
|
|||||||
base application class
|
base application class
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
This class groups ``Repository`` methods into specific method which process all supposed actions caused by
|
This class groups :class:`ahriman.core.repository.repository.Repository` methods into specific method which
|
||||||
underlying action. E.g.::
|
process all supposed actions caused by underlying action. E.g.::
|
||||||
|
|
||||||
>>> from ahriman.core.configuration import Configuration
|
>>> from ahriman.core.configuration import Configuration
|
||||||
>>> from ahriman.models.package_source import PackageSource
|
>>> from ahriman.models.package_source import PackageSource
|
||||||
@ -49,8 +49,8 @@ class Application(ApplicationPackages, ApplicationRepository):
|
|||||||
>>> # updates for specified packages
|
>>> # updates for specified packages
|
||||||
>>> application.update(updates)
|
>>> application.update(updates)
|
||||||
|
|
||||||
In case if specific actions or their order are required, the direct access to ``Repository`` must
|
In case if specific actions or their order are required, the direct access to
|
||||||
be used instead.
|
:class:`ahriman.core.repository.repository.Repository` must be used instead.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _known_packages(self) -> set[str]:
|
def _known_packages(self) -> set[str]:
|
||||||
@ -117,7 +117,7 @@ class Application(ApplicationPackages, ApplicationRepository):
|
|||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
list[Package]: updated packages list. Packager for dependencies will be copied from
|
list[Package]: updated packages list. Packager for dependencies will be copied from
|
||||||
original package
|
original package
|
||||||
"""
|
"""
|
||||||
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
|
||||||
|
|||||||
@ -39,8 +39,8 @@ class Handler:
|
|||||||
ALLOW_MULTI_ARCHITECTURE_RUN(bool): (class attribute) allow running with multiple architectures
|
ALLOW_MULTI_ARCHITECTURE_RUN(bool): (class attribute) allow running with multiple architectures
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
Wrapper for all command line actions, though each derived class implements ``run`` method, it usually must not
|
Wrapper for all command line actions, though each derived class implements :func:`run()` method, it usually
|
||||||
be called directly. The recommended way is to call ``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 import Add
|
||||||
>>>
|
>>>
|
||||||
|
|||||||
@ -67,8 +67,8 @@ class Versions(Handler):
|
|||||||
Args:
|
Args:
|
||||||
root(str): root package name
|
root(str): root package name
|
||||||
|
|
||||||
Returns:
|
Yields:
|
||||||
Generator[tuple[str, str], None, None]: map of installed dependency to its version
|
tuple[str, str]: map of installed dependency to its version
|
||||||
"""
|
"""
|
||||||
def dependencies_by_key(key: str) -> Generator[str, None, None]:
|
def dependencies_by_key(key: str) -> Generator[str, None, None]:
|
||||||
# in importlib it returns requires in the following format
|
# in importlib it returns requires in the following format
|
||||||
|
|||||||
@ -76,8 +76,8 @@ class Web(Handler):
|
|||||||
args(argparse.Namespace): command line args
|
args(argparse.Namespace): command line args
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
|
|
||||||
Returns:
|
Yields:
|
||||||
Generator[str, None, None]: command line arguments which were used for this specific command
|
str: command line arguments which were used for this specific command
|
||||||
"""
|
"""
|
||||||
# read configuration path from current settings
|
# read configuration path from current settings
|
||||||
if (configuration_path := configuration.path) is not None:
|
if (configuration_path := configuration.path) is not None:
|
||||||
|
|||||||
@ -80,6 +80,13 @@ class Lock(LazyLogging):
|
|||||||
self.paths = configuration.repository_paths
|
self.paths = configuration.repository_paths
|
||||||
self.reporter = Client.load(repository_id, configuration, report=args.report)
|
self.reporter = Client.load(repository_id, configuration, report=args.report)
|
||||||
|
|
||||||
|
def check_user(self) -> None:
|
||||||
|
"""
|
||||||
|
check if current user is actually owner of ahriman root
|
||||||
|
"""
|
||||||
|
check_user(self.paths, unsafe=self.unsafe)
|
||||||
|
self.paths.tree_create()
|
||||||
|
|
||||||
def check_version(self) -> None:
|
def check_version(self) -> None:
|
||||||
"""
|
"""
|
||||||
check web server version
|
check web server version
|
||||||
@ -89,13 +96,6 @@ class Lock(LazyLogging):
|
|||||||
self.logger.warning("status watcher version mismatch, our %s, their %s",
|
self.logger.warning("status watcher version mismatch, our %s, their %s",
|
||||||
__version__, status.version)
|
__version__, status.version)
|
||||||
|
|
||||||
def check_user(self) -> None:
|
|
||||||
"""
|
|
||||||
check if current user is actually owner of ahriman root
|
|
||||||
"""
|
|
||||||
check_user(self.paths, unsafe=self.unsafe)
|
|
||||||
self.paths.tree_create()
|
|
||||||
|
|
||||||
def clear(self) -> None:
|
def clear(self) -> None:
|
||||||
"""
|
"""
|
||||||
remove lock file
|
remove lock file
|
||||||
|
|||||||
@ -28,15 +28,16 @@ class Remote(SyncHttpClient):
|
|||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
These classes are designed to be used without instancing. In order to achieve it several class methods are
|
These classes are designed to be used without instancing. In order to achieve it several class methods are
|
||||||
provided: ``info``, ``multisearch`` and ``search``. Thus, the basic flow is the following::
|
provided: :func:`info()`, :func:`multisearch()` and :func:`search()`. Thus, the basic flow is the following::
|
||||||
|
|
||||||
>>> from ahriman.core.alpm.remote import AUR, Official
|
>>> from ahriman.core.alpm.remote import AUR, Official
|
||||||
>>>
|
>>>
|
||||||
>>> package = AUR.info("ahriman", pacman=pacman)
|
>>> package = AUR.info("ahriman", pacman=pacman)
|
||||||
>>> search_result = Official.multisearch("pacman", "manager", pacman=pacman)
|
>>> search_result = Official.multisearch("pacman", "manager", pacman=pacman)
|
||||||
|
|
||||||
Differnece between ``search`` and ``multisearch`` is that ``search`` passes all arguments to underlying wrapper
|
Differnece between :func:`search()` and :func:`multisearch()` is that :func:`search()` passes all arguments to
|
||||||
directly, whereas ``multisearch`` splits search one by one and finds intersection between search results.
|
underlying wrapper directly, whereas :func:`multisearch()` splits search one by one and finds intersection
|
||||||
|
between search results.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@ -45,8 +45,8 @@ class Configuration(configparser.RawConfigParser):
|
|||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
Configuration class provides additional method in order to handle application configuration. Since this class is
|
Configuration class provides additional method in order to handle application configuration. Since this class is
|
||||||
derived from built-in ``configparser.RawConfigParser`` class, the same flow is applicable here. Nevertheless,
|
derived from built-in :class:`configparser.RawConfigParser` class, the same flow is applicable here.
|
||||||
it is recommended to use ``from_path`` class method which also calls initialization methods::
|
Nevertheless, it is recommended to use :func:`from_path` class method which also calls initialization methods::
|
||||||
|
|
||||||
>>> from pathlib import Path
|
>>> from pathlib import Path
|
||||||
>>>
|
>>>
|
||||||
@ -57,12 +57,13 @@ class Configuration(configparser.RawConfigParser):
|
|||||||
The configuration instance loaded in this way will contain only sections which are defined for the specified
|
The configuration instance loaded in this way will contain only sections which are defined for the specified
|
||||||
architecture according to the merge rules. Moreover, the architecture names will be removed from section names.
|
architecture according to the merge rules. Moreover, the architecture names will be removed from section names.
|
||||||
|
|
||||||
In order to get current settings, the ``check_loaded`` method can be used. This method will raise an
|
In order to get current settings, the :func:`check_loaded` method can be used. This method will raise an
|
||||||
``InitializeError`` in case if configuration was not yet loaded::
|
:exc:`ahriman.core.exceptions.InitializeError` in case if configuration was not yet loaded::
|
||||||
|
|
||||||
>>> path, repository_id = configuration.check_loaded()
|
>>> path, repository_id = configuration.check_loaded()
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
_LEGACY_ARCHITECTURE_SPECIFIC_SECTIONS = ["web"]
|
||||||
ARCHITECTURE_SPECIFIC_SECTIONS = ["alpm", "build", "sign"]
|
ARCHITECTURE_SPECIFIC_SECTIONS = ["alpm", "build", "sign"]
|
||||||
SYSTEM_CONFIGURATION_PATH = Path(sys.prefix) / "share" / "ahriman" / "settings" / "ahriman.ini"
|
SYSTEM_CONFIGURATION_PATH = Path(sys.prefix) / "share" / "ahriman" / "settings" / "ahriman.ini"
|
||||||
converters: dict[str, Callable[[str], Any]] # typing guard
|
converters: dict[str, Callable[[str], Any]] # typing guard
|
||||||
@ -72,7 +73,7 @@ class Configuration(configparser.RawConfigParser):
|
|||||||
default constructor. In the most cases must not be called directly
|
default constructor. In the most cases must not be called directly
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
allow_no_value(bool, optional): copies ``configparser.RawConfigParser`` behaviour. In case if it is set
|
allow_no_value(bool, optional): copies :class:`configparser.RawConfigParser` behaviour. In case if it is set
|
||||||
to ``True``, the keys without values will be allowed (Default value = False)
|
to ``True``, the keys without values will be allowed (Default value = False)
|
||||||
"""
|
"""
|
||||||
configparser.RawConfigParser.__init__(
|
configparser.RawConfigParser.__init__(
|
||||||
@ -160,25 +161,6 @@ class Configuration(configparser.RawConfigParser):
|
|||||||
configuration.merge_sections(repository_id)
|
configuration.merge_sections(repository_id)
|
||||||
return configuration
|
return configuration
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def override_sections(section: str, repository_id: RepositoryId) -> list[str]:
|
|
||||||
"""
|
|
||||||
extract override sections
|
|
||||||
|
|
||||||
Args:
|
|
||||||
section(str): section name
|
|
||||||
repository_id(RepositoryId): repository unique identifier
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[str]: architecture and repository specific sections in correct order
|
|
||||||
"""
|
|
||||||
# the valid order is global < per architecture < per repository < per repository and architecture
|
|
||||||
return [
|
|
||||||
Configuration.section_name(section, repository_id.architecture), # architecture specific override
|
|
||||||
Configuration.section_name(section, repository_id.name), # override with repository name
|
|
||||||
Configuration.section_name(section, repository_id.name, repository_id.architecture), # both
|
|
||||||
]
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def section_name(section: str, *suffixes: str | None) -> str:
|
def section_name(section: str, *suffixes: str | None) -> str:
|
||||||
"""
|
"""
|
||||||
@ -315,7 +297,7 @@ class Configuration(configparser.RawConfigParser):
|
|||||||
"""
|
"""
|
||||||
self.repository_id = repository_id
|
self.repository_id = repository_id
|
||||||
|
|
||||||
for section in self.ARCHITECTURE_SPECIFIC_SECTIONS:
|
for section in self.ARCHITECTURE_SPECIFIC_SECTIONS + self._LEGACY_ARCHITECTURE_SPECIFIC_SECTIONS:
|
||||||
for specific in self.override_sections(section, repository_id):
|
for specific in self.override_sections(section, repository_id):
|
||||||
if self.has_section(specific):
|
if self.has_section(specific):
|
||||||
# if there is no such section it means that there is no overrides for this arch,
|
# if there is no such section it means that there is no overrides for this arch,
|
||||||
@ -330,6 +312,26 @@ class Configuration(configparser.RawConfigParser):
|
|||||||
continue
|
continue
|
||||||
self.remove_section(foreign)
|
self.remove_section(foreign)
|
||||||
|
|
||||||
|
def override_sections(self, section: str, repository_id: RepositoryId) -> list[str]:
|
||||||
|
"""
|
||||||
|
extract override sections
|
||||||
|
|
||||||
|
Args:
|
||||||
|
section(str): section name
|
||||||
|
repository_id(RepositoryId): repository unique identifier
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
list[str]: architecture and repository specific sections in correct order
|
||||||
|
"""
|
||||||
|
if repository_id.is_empty: # special case, guess sections from configuration
|
||||||
|
return sorted(specific for specific in self.sections() if specific.startswith(f"{section}:"))
|
||||||
|
# the valid order is global < per architecture < per repository < per repository and architecture
|
||||||
|
return [
|
||||||
|
Configuration.section_name(section, repository_id.architecture), # architecture specific override
|
||||||
|
Configuration.section_name(section, repository_id.name), # override with repository name
|
||||||
|
Configuration.section_name(section, repository_id.name, repository_id.architecture), # both
|
||||||
|
]
|
||||||
|
|
||||||
def reload(self) -> None:
|
def reload(self) -> None:
|
||||||
"""
|
"""
|
||||||
reload configuration if possible or raise exception otherwise
|
reload configuration if possible or raise exception otherwise
|
||||||
@ -342,7 +344,7 @@ class Configuration(configparser.RawConfigParser):
|
|||||||
|
|
||||||
def set_option(self, section: str, option: str, value: str) -> None:
|
def set_option(self, section: str, option: str, value: str) -> None:
|
||||||
"""
|
"""
|
||||||
set option. Unlike default ``configparser.RawConfigParser.set`` it also creates section if it does not exist
|
set option. Unlike default :func:`configparser.RawConfigParser.set` it also creates section if it does not exist
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
section(str): section name
|
section(str): section name
|
||||||
|
|||||||
@ -46,6 +46,6 @@ class ShellInterpolator(configparser.Interpolation):
|
|||||||
"""
|
"""
|
||||||
# At the moment it seems that it is the most legit way to handle environment variables
|
# At the moment it seems that it is the most legit way to handle environment variables
|
||||||
# Template behaviour is literally the same as shell
|
# Template behaviour is literally the same as shell
|
||||||
# In addition, we are using shell-like variables in some cases (see ``alpm.mirror`` option), thus we would like
|
# In addition, we are using shell-like variables in some cases (see :attr:`alpm.mirror` option),
|
||||||
# to keep them alive
|
# thus we would like to keep them alive
|
||||||
return Template(value).safe_substitute(os.environ)
|
return Template(value).safe_substitute(os.environ)
|
||||||
|
|||||||
@ -21,6 +21,7 @@ from sqlite3 import Connection
|
|||||||
|
|
||||||
from ahriman.core.database.operations import Operations
|
from ahriman.core.database.operations import Operations
|
||||||
from ahriman.models.package import Package
|
from ahriman.models.package import Package
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
class BuildOperations(Operations):
|
class BuildOperations(Operations):
|
||||||
@ -28,13 +29,16 @@ class BuildOperations(Operations):
|
|||||||
operations for build queue functions
|
operations for build queue functions
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def build_queue_clear(self, package_base: str | None) -> None:
|
def build_queue_clear(self, package_base: str | None, repository_id: RepositoryId | None = None) -> None:
|
||||||
"""
|
"""
|
||||||
remove packages from build queue
|
remove packages from build queue
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
package_base(str | None): optional filter by package base
|
package_base(str | None): optional filter by package base
|
||||||
|
repository_id(RepositoryId, optional): repository unique identifier override (Default value = None)
|
||||||
"""
|
"""
|
||||||
|
repository_id = repository_id or self._repository_id
|
||||||
|
|
||||||
def run(connection: Connection) -> None:
|
def run(connection: Connection) -> None:
|
||||||
connection.execute(
|
connection.execute(
|
||||||
"""
|
"""
|
||||||
@ -43,36 +47,44 @@ class BuildOperations(Operations):
|
|||||||
""",
|
""",
|
||||||
{
|
{
|
||||||
"package_base": package_base,
|
"package_base": package_base,
|
||||||
"repository": self._repository_id.id,
|
"repository": repository_id.id,
|
||||||
})
|
})
|
||||||
|
|
||||||
return self.with_connection(run, commit=True)
|
return self.with_connection(run, commit=True)
|
||||||
|
|
||||||
def build_queue_get(self) -> list[Package]:
|
def build_queue_get(self, repository_id: RepositoryId | None = None) -> list[Package]:
|
||||||
"""
|
"""
|
||||||
retrieve packages from build queue
|
retrieve packages from build queue
|
||||||
|
|
||||||
|
Args:
|
||||||
|
repository_id(RepositoryId, optional): repository unique identifier override (Default value = None)
|
||||||
|
|
||||||
Return:
|
Return:
|
||||||
list[Package]: list of packages to be built
|
list[Package]: list of packages to be built
|
||||||
"""
|
"""
|
||||||
|
repository_id = repository_id or self._repository_id
|
||||||
|
|
||||||
def run(connection: Connection) -> list[Package]:
|
def run(connection: Connection) -> list[Package]:
|
||||||
return [
|
return [
|
||||||
Package.from_json(row["properties"])
|
Package.from_json(row["properties"])
|
||||||
for row in connection.execute(
|
for row in connection.execute(
|
||||||
"""select properties from build_queue where repository = :repository""",
|
"""select properties from build_queue where repository = :repository""",
|
||||||
{"repository": self._repository_id.id}
|
{"repository": repository_id.id}
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
return self.with_connection(run)
|
return self.with_connection(run)
|
||||||
|
|
||||||
def build_queue_insert(self, package: Package) -> None:
|
def build_queue_insert(self, package: Package, repository_id: RepositoryId | None = None) -> None:
|
||||||
"""
|
"""
|
||||||
insert packages to build queue
|
insert packages to build queue
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
package(Package): package to be inserted
|
package(Package): package to be inserted
|
||||||
|
repository_id(RepositoryId, optional): repository unique identifier override (Default value = None)
|
||||||
"""
|
"""
|
||||||
|
repository_id = repository_id or self._repository_id
|
||||||
|
|
||||||
def run(connection: Connection) -> None:
|
def run(connection: Connection) -> None:
|
||||||
connection.execute(
|
connection.execute(
|
||||||
"""
|
"""
|
||||||
@ -86,7 +98,7 @@ class BuildOperations(Operations):
|
|||||||
{
|
{
|
||||||
"package_base": package.base,
|
"package_base": package.base,
|
||||||
"properties": package.view(),
|
"properties": package.view(),
|
||||||
"repository": self._repository_id.id,
|
"repository": repository_id.id,
|
||||||
})
|
})
|
||||||
|
|
||||||
return self.with_connection(run, commit=True)
|
return self.with_connection(run, commit=True)
|
||||||
|
|||||||
@ -302,26 +302,35 @@ class PackageOperations(Operations):
|
|||||||
|
|
||||||
return self.with_connection(lambda connection: list(run(connection)))
|
return self.with_connection(lambda connection: list(run(connection)))
|
||||||
|
|
||||||
def remote_update(self, package: Package) -> None:
|
def remote_update(self, package: Package, repository_id: RepositoryId | None = None) -> None:
|
||||||
"""
|
"""
|
||||||
update package remote source
|
update package remote source
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
package(Package): package properties
|
package(Package): package properties
|
||||||
|
repository_id(RepositoryId, optional): repository unique identifier override (Default value = None)
|
||||||
"""
|
"""
|
||||||
return self.with_connection(
|
repository_id = repository_id or self._repository_id
|
||||||
lambda connection: self._package_update_insert_base(connection, package, self._repository_id),
|
|
||||||
commit=True)
|
|
||||||
|
|
||||||
def remotes_get(self) -> dict[str, RemoteSource]:
|
def run(connection: Connection) -> None:
|
||||||
|
self._package_update_insert_base(connection, package, repository_id)
|
||||||
|
|
||||||
|
return self.with_connection(run, commit=True)
|
||||||
|
|
||||||
|
def remotes_get(self, repository_id: RepositoryId | None = None) -> dict[str, RemoteSource]:
|
||||||
"""
|
"""
|
||||||
get packages remotes based on current settings
|
get packages remotes based on current settings
|
||||||
|
|
||||||
|
Args:
|
||||||
|
repository_id(RepositoryId, optional): repository unique identifier override (Default value = None)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
dict[str, RemoteSource]: map of package base to its remote sources
|
dict[str, RemoteSource]: map of package base to its remote sources
|
||||||
"""
|
"""
|
||||||
|
repository_id = repository_id or self._repository_id
|
||||||
|
|
||||||
def run(connection: Connection) -> dict[str, Package]:
|
def run(connection: Connection) -> dict[str, Package]:
|
||||||
return self._packages_get_select_package_bases(connection, self._repository_id)
|
return self._packages_get_select_package_bases(connection, repository_id)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
package_base: package.remote
|
package_base: package.remote
|
||||||
|
|||||||
@ -35,7 +35,7 @@ class SQLite(AuthOperations, BuildOperations, LogsOperations, PackageOperations,
|
|||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
Database wrapper must be used together with migration and SQLite3 setup. In order to perform it there is
|
Database wrapper must be used together with migration and SQLite3 setup. In order to perform it there is
|
||||||
``load`` class method::
|
:func:`load()` class method::
|
||||||
|
|
||||||
>>> from ahriman.core.configuration import Configuration
|
>>> from ahriman.core.configuration import Configuration
|
||||||
>>>
|
>>>
|
||||||
|
|||||||
@ -62,7 +62,7 @@ class BuildError(RuntimeError):
|
|||||||
|
|
||||||
class CalledProcessError(subprocess.CalledProcessError):
|
class CalledProcessError(subprocess.CalledProcessError):
|
||||||
"""
|
"""
|
||||||
like ``subprocess.CalledProcessError``, but better
|
like :exc:`subprocess.CalledProcessError`, but better
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, status_code: int, process: list[str], stderr: str) -> None:
|
def __init__(self, status_code: int, process: list[str], stderr: str) -> None:
|
||||||
|
|||||||
@ -57,6 +57,7 @@ class Printer:
|
|||||||
"""
|
"""
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
# pylint: disable=redundant-returns-doc
|
||||||
def title(self) -> str | None:
|
def title(self) -> str | None:
|
||||||
"""
|
"""
|
||||||
generate entry title from content
|
generate entry title from content
|
||||||
@ -68,7 +69,7 @@ class Printer:
|
|||||||
|
|
||||||
def __call__(self, *, verbose: bool, log_fn: Callable[[str], None] = _print, separator: str = ": ") -> None:
|
def __call__(self, *, verbose: bool, log_fn: Callable[[str], None] = _print, separator: str = ": ") -> None:
|
||||||
"""
|
"""
|
||||||
print content. Shortcut for ``Printer.print``
|
print content. Shortcut for :func:`print()`
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
verbose(bool): print all fields
|
verbose(bool): print all fields
|
||||||
|
|||||||
@ -67,7 +67,7 @@ class FilteredAccessLogger(AccessLogger):
|
|||||||
Args:
|
Args:
|
||||||
request(BaseRequest): http reqeust descriptor
|
request(BaseRequest): http reqeust descriptor
|
||||||
response(StreamResponse): streaming response object
|
response(StreamResponse): streaming response object
|
||||||
time(float):
|
time(float): log record timestamp
|
||||||
"""
|
"""
|
||||||
if self.is_logs_post(request) \
|
if self.is_logs_post(request) \
|
||||||
or self.is_process_get(request):
|
or self.is_process_get(request):
|
||||||
|
|||||||
@ -27,8 +27,8 @@ from ahriman.models.repository_id import RepositoryId
|
|||||||
|
|
||||||
class HttpLogHandler(logging.Handler):
|
class HttpLogHandler(logging.Handler):
|
||||||
"""
|
"""
|
||||||
handler for the http logging. Because default ``logging.handlers.HTTPHandler`` does not support cookies
|
handler for the http logging. Because default :class:`logging.handlers.HTTPHandler` does not support cookies
|
||||||
authorization, we have to implement own handler which overrides the ``logging.handlers.HTTPHandler.emit`` method
|
authorization, we have to implement own handler which overrides the :func:`logging.handlers.HTTPHandler.emit` method
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
reporter(Client): build status reporter instance
|
reporter(Client): build status reporter instance
|
||||||
|
|||||||
@ -46,9 +46,11 @@ class LogLoader:
|
|||||||
def handler(selected: LogHandler | None) -> LogHandler:
|
def handler(selected: LogHandler | None) -> LogHandler:
|
||||||
"""
|
"""
|
||||||
try to guess default log handler. In case if ``selected`` is set, it will return specified value with appended
|
try to guess default log handler. In case if ``selected`` is set, it will return specified value with appended
|
||||||
_handler suffix. Otherwise, it will try to import journald handler and returns ``journald_handler`` if library
|
_handler suffix. Otherwise, it will try to import journald handler and returns
|
||||||
is available. Otherwise, it will check if there is ``/dev/log`` device and returns ``syslog_handler`` in this
|
:attr:`ahriman.models.log_handler.LogHandler.Journald` if library is available. Otherwise, it will check if
|
||||||
case. And, finally, it will fall back to ``console_handler`` if none were found
|
there is ``/dev/log`` device and returns :attr:`ahriman.models.log_handler.LogHandler.Syslog` in this
|
||||||
|
case. And, finally, it will fall back to :attr:`ahriman.models.log_handler.LogHandler.Console`
|
||||||
|
if none were found
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
selected(LogHandler | None): user specified handler if any
|
selected(LogHandler | None): user specified handler if any
|
||||||
|
|||||||
@ -37,14 +37,14 @@ class Report(LazyLogging):
|
|||||||
repository_id(RepositoryId): repository unique identifier
|
repository_id(RepositoryId): repository unique identifier
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
``Report`` classes provide several method in order to operate with the report generation and additional class
|
:class:`Report` subclasses provide several method in order to operate with the report generation and additional
|
||||||
method ``load`` which can be used in order to determine right report instance::
|
class method :func:`load()` which can be used in order to determine right report instance::
|
||||||
|
|
||||||
>>> configuration = Configuration()
|
>>> configuration = Configuration()
|
||||||
>>> report = Report.load(RepositoryId("x86_64", "aur-clone"), configuration, "email")
|
>>> report = Report.load(RepositoryId("x86_64", "aur-clone"), configuration, "email")
|
||||||
|
|
||||||
The ``generate`` method can be used in order to perform the report itself, whereas ``run`` method handles
|
The :func:`generate()` method can be used in order to perform the report itself, whereas :func:`run()` method
|
||||||
exception and raises ``ReportFailed`` instead::
|
handles exception and raises :exc:`ahriman.core.exceptions.ReportError` instead::
|
||||||
|
|
||||||
>>> try:
|
>>> try:
|
||||||
>>> report.generate([], Result())
|
>>> report.generate([], Result())
|
||||||
|
|||||||
@ -213,7 +213,7 @@ class GPG(SyncHttpClient):
|
|||||||
sign repository if required by configuration
|
sign repository if required by configuration
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
More likely you just want to pass ``repository_sign_args`` to repo wrapper
|
More likely you just want to pass :attr:`repository_sign_args` to repo wrapper
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
path(Path): path to repository database
|
path(Path): path to repository database
|
||||||
|
|||||||
@ -83,7 +83,8 @@ class Spawn(Thread, LazyLogging):
|
|||||||
helper to run external process
|
helper to run external process
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
callback(Callable[[argparse.Namespace, str], bool]): application run function (i.e. ``Handler.call`` method)
|
callback(Callable[[argparse.Namespace, str], bool]): application run function
|
||||||
|
(i.e. :func:`ahriman.application.handlers.handler.Handler.call()` method)
|
||||||
args(argparse.Namespace): command line arguments
|
args(argparse.Namespace): command line arguments
|
||||||
repository_id(RepositoryId): repository unique identifier
|
repository_id(RepositoryId): repository unique identifier
|
||||||
process_id(str): process unique identifier
|
process_id(str): process unique identifier
|
||||||
@ -149,7 +150,7 @@ class Spawn(Thread, LazyLogging):
|
|||||||
check if given process is alive
|
check if given process is alive
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
process_id(str): process id to be checked as returned by ``Spawn._spawn_process``
|
process_id(str): process id to be checked as returned by :func:`_spawn_process()`
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
bool: True in case if process still counts as active and False otherwise
|
bool: True in case if process still counts as active and False otherwise
|
||||||
|
|||||||
@ -104,7 +104,7 @@ class Client:
|
|||||||
|
|
||||||
def package_update(self, package_base: str, status: BuildStatusEnum) -> None:
|
def package_update(self, package_base: str, status: BuildStatusEnum) -> None:
|
||||||
"""
|
"""
|
||||||
update package build status. Unlike ``add`` it does not update package properties
|
update package build status. Unlike :func:`package_add()` it does not update package properties
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
package_base(str): package base to update
|
package_base(str): package base to update
|
||||||
|
|||||||
@ -33,8 +33,8 @@ class Watcher(LazyLogging):
|
|||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
database(SQLite): database instance
|
database(SQLite): database instance
|
||||||
known(dict[str, tuple[Package, BuildStatus]]): list of known packages. For the most cases ``packages`` should
|
known(dict[str, tuple[Package, BuildStatus]]): list of known packages. For the most cases :attr:`packages`
|
||||||
be used instead
|
should be used instead
|
||||||
repository_id(RepositoryId): repository unique identifier
|
repository_id(RepositoryId): repository unique identifier
|
||||||
status(BuildStatus): daemon status
|
status(BuildStatus): daemon status
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -245,7 +245,7 @@ class WebClient(Client, SyncHttpClient):
|
|||||||
|
|
||||||
def package_update(self, package_base: str, status: BuildStatusEnum) -> None:
|
def package_update(self, package_base: str, status: BuildStatusEnum) -> None:
|
||||||
"""
|
"""
|
||||||
update package build status. Unlike ``add`` it does not update package properties
|
update package build status. Unlike :func:`package_add()` it does not update package properties
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
package_base(str): package base to update
|
package_base(str): package base to update
|
||||||
|
|||||||
@ -182,7 +182,7 @@ class Tree:
|
|||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
list[list[Package]]: list of packages lists based on their dependencies. The amount of elements in each
|
list[list[Package]]: list of packages lists based on their dependencies. The amount of elements in each
|
||||||
sublist is less or equal to ``count``
|
sublist is less or equal to ``count``
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
PartitionError: in case if it is impossible to divide tree by specified amount of partitions
|
PartitionError: in case if it is impossible to divide tree by specified amount of partitions
|
||||||
|
|||||||
@ -88,8 +88,8 @@ class TriggerLoader(LazyLogging):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def known_triggers(configuration: Configuration) -> list[str]:
|
def known_triggers(configuration: Configuration) -> list[str]:
|
||||||
"""
|
"""
|
||||||
read configuration and return list of known triggers. Unlike ``selected_triggers`` this option is used mainly
|
read configuration and return list of known triggers. Unlike :func:`selected_triggers()` this option is used
|
||||||
for configuration and validation and mentioned triggers are not being executed automatically
|
mainly for configuration and validation and mentioned triggers are not being executed automatically
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
configuration(Configuration): configuration instance
|
configuration(Configuration): configuration instance
|
||||||
@ -141,7 +141,7 @@ class TriggerLoader(LazyLogging):
|
|||||||
"""
|
"""
|
||||||
self.logger.info("load module %s from path %s", implementation, module_path)
|
self.logger.info("load module %s from path %s", implementation, module_path)
|
||||||
# basically this method is called only if ``module_path`` exists and is file.
|
# basically this method is called only if ``module_path`` exists and is file.
|
||||||
# Thus, this method should never throw ``FileNotFoundError`` exception
|
# Thus, this method should never throw :exc:`FileNotFoundError` exception
|
||||||
loader = machinery.SourceFileLoader(implementation, module_path)
|
loader = machinery.SourceFileLoader(implementation, module_path)
|
||||||
module = ModuleType(loader.name)
|
module = ModuleType(loader.name)
|
||||||
loader.exec_module(module)
|
loader.exec_module(module)
|
||||||
|
|||||||
@ -95,21 +95,6 @@ class GitHub(Upload, HttpUpload):
|
|||||||
with path.open("rb") as archive:
|
with path.open("rb") as archive:
|
||||||
self.make_request("POST", url, params=[("name", path.name)], data=archive, headers=headers)
|
self.make_request("POST", url, params=[("name", path.name)], data=archive, headers=headers)
|
||||||
|
|
||||||
def get_local_files(self, path: Path) -> dict[Path, str]:
|
|
||||||
"""
|
|
||||||
get all local files and their calculated checksums
|
|
||||||
|
|
||||||
Args:
|
|
||||||
path(Path): local path to sync
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
dict[Path, str]: map of path objects to its checksum
|
|
||||||
"""
|
|
||||||
return {
|
|
||||||
local_file: self.calculate_hash(local_file)
|
|
||||||
for local_file in walk(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
def files_remove(self, release: dict[str, Any], local_files: dict[Path, str], remote_files: dict[str, str]) -> None:
|
def files_remove(self, release: dict[str, Any], local_files: dict[Path, str], remote_files: dict[str, str]) -> None:
|
||||||
"""
|
"""
|
||||||
remove files from GitHub
|
remove files from GitHub
|
||||||
@ -140,6 +125,21 @@ class GitHub(Upload, HttpUpload):
|
|||||||
continue
|
continue
|
||||||
self.asset_upload(release, local_file)
|
self.asset_upload(release, local_file)
|
||||||
|
|
||||||
|
def get_local_files(self, path: Path) -> dict[Path, str]:
|
||||||
|
"""
|
||||||
|
get all local files and their calculated checksums
|
||||||
|
|
||||||
|
Args:
|
||||||
|
path(Path): local path to sync
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict[Path, str]: map of path objects to its checksum
|
||||||
|
"""
|
||||||
|
return {
|
||||||
|
local_file: self.calculate_hash(local_file)
|
||||||
|
for local_file in walk(path)
|
||||||
|
}
|
||||||
|
|
||||||
def release_create(self) -> dict[str, Any]:
|
def release_create(self) -> dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
create empty release
|
create empty release
|
||||||
|
|||||||
@ -87,6 +87,20 @@ class S3(Upload):
|
|||||||
suffix = f"-{len(md5s)}" if len(md5s) > 1 else ""
|
suffix = f"-{len(md5s)}" if len(md5s) > 1 else ""
|
||||||
return f"{checksum.hexdigest()}{suffix}"
|
return f"{checksum.hexdigest()}{suffix}"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def files_remove(local_files: dict[Path, str], remote_objects: dict[Path, Any]) -> None:
|
||||||
|
"""
|
||||||
|
remove files which have been removed locally
|
||||||
|
|
||||||
|
Args:
|
||||||
|
local_files(dict[Path, str]): map of local path object to its checksum
|
||||||
|
remote_objects(dict[Path, Any]): map of remote path object to the remote s3 object
|
||||||
|
"""
|
||||||
|
for local_file, remote_object in remote_objects.items():
|
||||||
|
if local_file in local_files:
|
||||||
|
continue
|
||||||
|
remote_object.delete()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_bucket(configuration: Configuration, section: str) -> Any:
|
def get_bucket(configuration: Configuration, section: str) -> Any:
|
||||||
"""
|
"""
|
||||||
@ -105,20 +119,6 @@ class S3(Upload):
|
|||||||
aws_secret_access_key=configuration.get(section, "secret_key"))
|
aws_secret_access_key=configuration.get(section, "secret_key"))
|
||||||
return client.Bucket(configuration.get(section, "bucket"))
|
return client.Bucket(configuration.get(section, "bucket"))
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def files_remove(local_files: dict[Path, str], remote_objects: dict[Path, Any]) -> None:
|
|
||||||
"""
|
|
||||||
remove files which have been removed locally
|
|
||||||
|
|
||||||
Args:
|
|
||||||
local_files(dict[Path, str]): map of local path object to its checksum
|
|
||||||
remote_objects(dict[Path, Any]): map of remote path object to the remote s3 object
|
|
||||||
"""
|
|
||||||
for local_file, remote_object in remote_objects.items():
|
|
||||||
if local_file in local_files:
|
|
||||||
continue
|
|
||||||
remote_object.delete()
|
|
||||||
|
|
||||||
def files_upload(self, path: Path, local_files: dict[Path, str], remote_objects: dict[Path, Any]) -> None:
|
def files_upload(self, path: Path, local_files: dict[Path, str], remote_objects: dict[Path, Any]) -> None:
|
||||||
"""
|
"""
|
||||||
upload changed files to s3
|
upload changed files to s3
|
||||||
|
|||||||
@ -39,14 +39,14 @@ class Upload(LazyLogging):
|
|||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
These classes provide the way to upload packages to remote sources as it is described in their implementations.
|
These classes provide the way to upload packages to remote sources as it is described in their implementations.
|
||||||
Basic flow includes class instantiating by using the ``load`` method and then calling the ``run`` method which
|
Basic flow includes class instantiating by using the :func:`load` method and then calling the :func:`run` method
|
||||||
wraps any internal exceptions into the ``SyncFailed`` exception::
|
which wraps any internal exceptions into the :exc:`ahriman.core.exceptions.SynchronizationError` exception::
|
||||||
|
|
||||||
>>> configuration = Configuration()
|
>>> configuration = Configuration()
|
||||||
>>> upload = Upload.load(RepositoryId("x86_64", "aur-clone"), configuration, "s3")
|
>>> upload = Upload.load(RepositoryId("x86_64", "aur-clone"), configuration, "s3")
|
||||||
>>> upload.run(configuration.repository_paths.repository, [])
|
>>> upload.run(configuration.repository_paths.repository, [])
|
||||||
|
|
||||||
Or in case if direct access to exception is required, the ``sync`` method can be used::
|
Or in case if direct access to exception is required, the :func:`sync` method can be used::
|
||||||
|
|
||||||
>>> try:
|
>>> try:
|
||||||
>>> upload.sync(configuration.repository_paths.repository, [])
|
>>> upload.sync(configuration.repository_paths.repository, [])
|
||||||
|
|||||||
@ -76,8 +76,8 @@ def check_output(*args: str, exception: Exception | Callable[[int, list[str], st
|
|||||||
Args:
|
Args:
|
||||||
*args(str): command line arguments
|
*args(str): command line arguments
|
||||||
exception(Exception | Callable[[int, list[str], str, str]] | None, optional): exception which has to be raised
|
exception(Exception | Callable[[int, list[str], str, str]] | None, optional): exception which has to be raised
|
||||||
instead of default subprocess exception. If callable us is supplied, the ``subprocess.CalledProcessError``
|
instead of default subprocess exception. If callable us is supplied, the
|
||||||
arguments will be passed (Default value = None)
|
:exc:`subprocess.CalledProcessError` arguments will be passed (Default value = None)
|
||||||
cwd(Path | None, optional): current working directory (Default value = None)
|
cwd(Path | None, optional): current working directory (Default value = None)
|
||||||
input_data(str | None, optional): data which will be written to command stdin (Default value = None)
|
input_data(str | None, optional): data which will be written to command stdin (Default value = None)
|
||||||
logger(logging.Logger | None, optional): logger to log command result if required (Default value = None)
|
logger(logging.Logger | None, optional): logger to log command result if required (Default value = None)
|
||||||
@ -412,7 +412,7 @@ def srcinfo_property(key: str, srcinfo: dict[str, Any], package_srcinfo: dict[st
|
|||||||
default: Any = None) -> Any:
|
default: Any = None) -> Any:
|
||||||
"""
|
"""
|
||||||
extract property from SRCINFO. This method extracts property from package if this property is presented in
|
extract property from SRCINFO. This method extracts property from package if this property is presented in
|
||||||
``package``. Otherwise, it looks for the same property in root srcinfo. If none found, the default value will be
|
``srcinfo``. Otherwise, it looks for the same property in root srcinfo. If none found, the default value will be
|
||||||
returned
|
returned
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -430,9 +430,9 @@ def srcinfo_property(key: str, srcinfo: dict[str, Any], package_srcinfo: dict[st
|
|||||||
def srcinfo_property_list(key: str, srcinfo: dict[str, Any], package_srcinfo: dict[str, Any], *,
|
def srcinfo_property_list(key: str, srcinfo: dict[str, Any], package_srcinfo: dict[str, Any], *,
|
||||||
architecture: str | None = None) -> list[Any]:
|
architecture: str | None = None) -> list[Any]:
|
||||||
"""
|
"""
|
||||||
extract list property from SRCINFO. Unlike ``srcinfo_property`` it supposes that default return value is always
|
extract list property from SRCINFO. Unlike :func:`srcinfo_property()` it supposes that default return value is
|
||||||
empty list. If ``architecture`` is supplied, then it will try to lookup for architecture specific values and will
|
always empty list. If ``architecture`` is supplied, then it will try to lookup for architecture specific values and
|
||||||
append it at the end of result
|
will append it at the end of result
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
key(str): key to extract
|
key(str): key to extract
|
||||||
@ -468,7 +468,7 @@ def trim_package(package_name: str) -> str:
|
|||||||
|
|
||||||
def unquote(source: str) -> str:
|
def unquote(source: str) -> str:
|
||||||
"""
|
"""
|
||||||
like ``shlex.quote``, but opposite
|
like :func:`shlex.quote()`, but opposite
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
source(str): source string to remove quotes
|
source(str): source string to remove quotes
|
||||||
@ -520,7 +520,8 @@ def walk(directory_path: Path) -> Generator[Path, None, None]:
|
|||||||
Path: all found files in given directory with full path
|
Path: all found files in given directory with full path
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
Since the ``pathlib`` module does not provide an alternative to ``os.walk``, this wrapper can be used instead::
|
Since the :mod:`pathlib` module does not provide an alternative to :func:`os.walk()`, this wrapper
|
||||||
|
can be used instead::
|
||||||
|
|
||||||
>>> from pathlib import Path
|
>>> from pathlib import Path
|
||||||
>>>
|
>>>
|
||||||
|
|||||||
@ -17,10 +17,10 @@
|
|||||||
# 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 enum import Enum
|
from enum import StrEnum
|
||||||
|
|
||||||
|
|
||||||
class Action(str, Enum):
|
class Action(StrEnum):
|
||||||
"""
|
"""
|
||||||
base action enumeration
|
base action enumeration
|
||||||
|
|
||||||
|
|||||||
@ -59,7 +59,7 @@ class AURPackage:
|
|||||||
keywords(list[str]): list of package keywords
|
keywords(list[str]): list of package keywords
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
Mainly this class must be used from class methods instead of default ``__init__``::
|
Mainly this class must be used from class methods instead of default :func:`__init__()`::
|
||||||
|
|
||||||
>>> package = AURPackage.from_json(metadata) # load package from json dump
|
>>> package = AURPackage.from_json(metadata) # load package from json dump
|
||||||
>>> # ...or alternatively...
|
>>> # ...or alternatively...
|
||||||
|
|||||||
@ -19,10 +19,10 @@
|
|||||||
#
|
#
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from enum import Enum
|
from enum import StrEnum
|
||||||
|
|
||||||
|
|
||||||
class AuthSettings(str, Enum):
|
class AuthSettings(StrEnum):
|
||||||
"""
|
"""
|
||||||
web authorization type
|
web authorization type
|
||||||
|
|
||||||
|
|||||||
@ -18,13 +18,13 @@
|
|||||||
# 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 dataclasses import dataclass, field, fields
|
from dataclasses import dataclass, field, fields
|
||||||
from enum import Enum
|
from enum import StrEnum
|
||||||
from typing import Any, Self
|
from typing import Any, Self
|
||||||
|
|
||||||
from ahriman.core.util import filter_json, pretty_datetime, utcnow
|
from ahriman.core.util import filter_json, pretty_datetime, utcnow
|
||||||
|
|
||||||
|
|
||||||
class BuildStatusEnum(str, Enum):
|
class BuildStatusEnum(StrEnum):
|
||||||
"""
|
"""
|
||||||
build status enumeration
|
build status enumeration
|
||||||
|
|
||||||
|
|||||||
@ -17,10 +17,10 @@
|
|||||||
# 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 enum import Enum
|
from enum import StrEnum
|
||||||
|
|
||||||
|
|
||||||
class LogHandler(str, Enum):
|
class LogHandler(StrEnum):
|
||||||
"""
|
"""
|
||||||
log handler as described by default configuration
|
log handler as described by default configuration
|
||||||
|
|
||||||
|
|||||||
@ -66,11 +66,13 @@ class Package(LazyLogging):
|
|||||||
it will probably miss file descriptions (in case if there are multiple packages which belong to the base).
|
it will probably miss file descriptions (in case if there are multiple packages which belong to the base).
|
||||||
|
|
||||||
The specific class load method must be defined based on the source provided. The following methods (mostly) must
|
The specific class load method must be defined based on the source provided. The following methods (mostly) must
|
||||||
be used: ``from_archive``, ``from_aur``, ``from_build``, ``from_official`` for sources
|
be used: :func:`from_archive()`, :func:`from_aur()`, :func:`from_build()`, :func:`from_official()` for sources
|
||||||
``PackageSource.Archive``, ``PackageSource.AUR``, ``PackageSource.Local`` and ``PackageSource.Repository``
|
:attr:`ahriman.models.package_source.PackageSource.Archive`,
|
||||||
repsectively:
|
:attr:`ahriman.models.package_source.PackageSource.AUR`,
|
||||||
|
:attr:`ahriman.models.package_source.PackageSource.Local` and
|
||||||
|
:attr:`ahriman.models.package_source.PackageSource.Repository` repsectively:
|
||||||
|
|
||||||
>>> ahriman_package = Package.from_aur("ahriman", pacman)
|
>>> ahriman_package = Package.from_aur("ahriman")
|
||||||
>>> pacman_package = Package.from_official("pacman", pacman)
|
>>> pacman_package = Package.from_official("pacman", pacman)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -354,9 +356,9 @@ class Package(LazyLogging):
|
|||||||
Args:
|
Args:
|
||||||
path(Path): path to package sources directory
|
path(Path): path to package sources directory
|
||||||
|
|
||||||
Returns:
|
Yields:
|
||||||
Generator[Path, None, None]: list of paths of files which belong to the package and distributed together
|
Path: list of paths of files which belong to the package and distributed together with this tarball.
|
||||||
with this tarball. All paths are relative to the ``path``
|
All paths are relative to the ``path``
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
PackageInfoError: if there are parsing errors
|
PackageInfoError: if there are parsing errors
|
||||||
@ -540,7 +542,7 @@ class Package(LazyLogging):
|
|||||||
def next_pkgrel(self, local_version: str) -> str | None:
|
def next_pkgrel(self, local_version: str) -> str | None:
|
||||||
"""
|
"""
|
||||||
generate next pkgrel variable. The package release will be incremented if ``local_version`` is more or equal to
|
generate next pkgrel variable. The package release will be incremented if ``local_version`` is more or equal to
|
||||||
the ``Package.version``; in this case the function will return new pkgrel value, otherwise ``None`` will be
|
the :attr:`version`; in this case the function will return new pkgrel value, otherwise ``None`` will be
|
||||||
returned
|
returned
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -548,8 +550,8 @@ class Package(LazyLogging):
|
|||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
str | None: new generated package release version if any. In case if the release contains dot (e.g. 1.2),
|
str | None: new generated package release version if any. In case if the release contains dot (e.g. 1.2),
|
||||||
the minor part will be incremented by 1. If the release does not contain major.minor notation, the minor version
|
the minor part will be incremented by 1. If the release does not contain major.minor notation, the minor
|
||||||
equals to 1 will be appended
|
version equals to 1 will be appended
|
||||||
"""
|
"""
|
||||||
epoch, pkgver, _ = parse_version(self.version)
|
epoch, pkgver, _ = parse_version(self.version)
|
||||||
local_epoch, local_pkgver, local_pkgrel = parse_version(local_version)
|
local_epoch, local_pkgver, local_pkgrel = parse_version(local_version)
|
||||||
|
|||||||
@ -48,8 +48,9 @@ class PackageDescription:
|
|||||||
url(str | None): package url
|
url(str | None): package url
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
Unlike the ``Package`` class, this implementation only holds properties. The recommended way to deal with it is
|
Unlike the :class:`ahriman.models.package.Package` class, this implementation only holds properties.
|
||||||
to read data based on the source type - either json or ``pyalpm.Package`` instance::
|
The recommended way to deal with it is to read data based on the source type - either json or
|
||||||
|
:class:`pyalpm.Package` instance::
|
||||||
|
|
||||||
>>> description = PackageDescription.from_json(dump)
|
>>> description = PackageDescription.from_json(dump)
|
||||||
>>>
|
>>>
|
||||||
|
|||||||
@ -19,7 +19,7 @@
|
|||||||
#
|
#
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from enum import Enum
|
from enum import StrEnum
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ from ahriman.core.util import package_like
|
|||||||
from ahriman.models.repository_paths import RepositoryPaths
|
from ahriman.models.repository_paths import RepositoryPaths
|
||||||
|
|
||||||
|
|
||||||
class PackageSource(str, Enum):
|
class PackageSource(StrEnum):
|
||||||
"""
|
"""
|
||||||
package source for addition enumeration
|
package source for addition enumeration
|
||||||
|
|
||||||
@ -41,11 +41,13 @@ class PackageSource(str, Enum):
|
|||||||
Repository(PackageSource): (class attribute) source is official repository
|
Repository(PackageSource): (class attribute) source is official repository
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
In case if source is unknown the ``resolve()`` and the source descriptor is available method must be used::
|
In case if source is unknown the :func:`resolve()` and the source
|
||||||
|
descriptor is available method must be used::
|
||||||
|
|
||||||
>>> real_source = PackageSource.Auto.resolve("ahriman", configuration.repository_paths)
|
>>> real_source = PackageSource.Auto.resolve("ahriman", configuration.repository_paths)
|
||||||
|
|
||||||
the code above will ensure that the presudo-source ``PackageSource.Auto`` will not be processed later.
|
the code above will ensure that the presudo-source :attr:`Auto`
|
||||||
|
will not be processed later.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Auto = "auto"
|
Auto = "auto"
|
||||||
|
|||||||
@ -17,10 +17,10 @@
|
|||||||
# 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 enum import Enum
|
from enum import IntEnum
|
||||||
|
|
||||||
|
|
||||||
class PacmanSynchronization(int, Enum):
|
class PacmanSynchronization(IntEnum):
|
||||||
"""
|
"""
|
||||||
pacman database synchronization flag
|
pacman database synchronization flag
|
||||||
|
|
||||||
|
|||||||
@ -19,10 +19,10 @@
|
|||||||
#
|
#
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from enum import Enum
|
from enum import StrEnum
|
||||||
|
|
||||||
|
|
||||||
class ReportSettings(str, Enum):
|
class ReportSettings(StrEnum):
|
||||||
"""
|
"""
|
||||||
report targets enumeration
|
report targets enumeration
|
||||||
|
|
||||||
|
|||||||
@ -34,16 +34,6 @@ class RepositoryId:
|
|||||||
architecture: str
|
architecture: str
|
||||||
name: str
|
name: str
|
||||||
|
|
||||||
@property
|
|
||||||
def is_empty(self) -> bool:
|
|
||||||
"""
|
|
||||||
check if all data is supplied for the loading
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: True in case if architecture or name are not set and False otherwise
|
|
||||||
"""
|
|
||||||
return not self.architecture or not self.name
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def id(self) -> str:
|
def id(self) -> str:
|
||||||
"""
|
"""
|
||||||
@ -56,6 +46,16 @@ class RepositoryId:
|
|||||||
return ""
|
return ""
|
||||||
return f"{self.architecture}-{self.name}" # basically the same as used for command line
|
return f"{self.architecture}-{self.name}" # basically the same as used for command line
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_empty(self) -> bool:
|
||||||
|
"""
|
||||||
|
check if all data is supplied for the loading
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True in case if architecture or name are not set and False otherwise
|
||||||
|
"""
|
||||||
|
return not self.architecture or not self.name
|
||||||
|
|
||||||
def query(self) -> list[tuple[str, str]]:
|
def query(self) -> list[tuple[str, str]]:
|
||||||
"""
|
"""
|
||||||
generate query parameters
|
generate query parameters
|
||||||
|
|||||||
@ -75,7 +75,7 @@ class RepositoryPaths(LazyLogging):
|
|||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Path: relative path which contains only architecture segment in case if legacy tree is used and repository
|
Path: relative path which contains only architecture segment in case if legacy tree is used and repository
|
||||||
name and architecture otherwise
|
name and architecture otherwise
|
||||||
"""
|
"""
|
||||||
if not self._force_current_tree:
|
if not self._force_current_tree:
|
||||||
if (self._repository_root / self.repository_id.architecture).is_dir():
|
if (self._repository_root / self.repository_id.architecture).is_dir():
|
||||||
@ -181,7 +181,7 @@ class RepositoryPaths(LazyLogging):
|
|||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
set[str]: list of repository names for which there is created tree. Returns empty set in case if repository
|
set[str]: list of repository names for which there is created tree. Returns empty set in case if repository
|
||||||
is loaded in legacy mode
|
is loaded in legacy mode
|
||||||
"""
|
"""
|
||||||
# simply walk through the root. In case if there are subdirectories, emit the name
|
# simply walk through the root. In case if there are subdirectories, emit the name
|
||||||
def walk(paths: RepositoryPaths) -> Generator[str, None, None]:
|
def walk(paths: RepositoryPaths) -> Generator[str, None, None]:
|
||||||
|
|||||||
@ -19,10 +19,10 @@
|
|||||||
#
|
#
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from enum import Enum
|
from enum import StrEnum
|
||||||
|
|
||||||
|
|
||||||
class SignSettings(str, Enum):
|
class SignSettings(StrEnum):
|
||||||
"""
|
"""
|
||||||
sign targets enumeration
|
sign targets enumeration
|
||||||
|
|
||||||
|
|||||||
@ -19,10 +19,10 @@
|
|||||||
#
|
#
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from enum import Enum
|
from enum import StrEnum
|
||||||
|
|
||||||
|
|
||||||
class SmtpSSLSettings(str, Enum):
|
class SmtpSSLSettings(StrEnum):
|
||||||
"""
|
"""
|
||||||
SMTP SSL mode enumeration
|
SMTP SSL mode enumeration
|
||||||
|
|
||||||
|
|||||||
@ -19,10 +19,10 @@
|
|||||||
#
|
#
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from enum import Enum
|
from enum import StrEnum
|
||||||
|
|
||||||
|
|
||||||
class UploadSettings(str, Enum):
|
class UploadSettings(StrEnum):
|
||||||
"""
|
"""
|
||||||
remote synchronization targets enumeration
|
remote synchronization targets enumeration
|
||||||
|
|
||||||
|
|||||||
@ -43,7 +43,8 @@ class User:
|
|||||||
>>> password = User.generate_password(24)
|
>>> password = User.generate_password(24)
|
||||||
>>> user = User(username="ahriman", password=password, access=UserAccess.Full)
|
>>> user = User(username="ahriman", password=password, access=UserAccess.Full)
|
||||||
|
|
||||||
Since the password supplied may be plain text, the ``hash_password`` method can be used to hash the password::
|
Since the password supplied may be plain text, the :func:`hash_password()` method can be used to hash
|
||||||
|
the password::
|
||||||
|
|
||||||
>>> user = user.hash_password("salt")
|
>>> user = user.hash_password("salt")
|
||||||
|
|
||||||
|
|||||||
@ -19,10 +19,10 @@
|
|||||||
#
|
#
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from enum import Enum
|
from enum import StrEnum
|
||||||
|
|
||||||
|
|
||||||
class UserAccess(str, Enum):
|
class UserAccess(StrEnum):
|
||||||
"""
|
"""
|
||||||
web user access enumeration
|
web user access enumeration
|
||||||
|
|
||||||
|
|||||||
@ -48,8 +48,8 @@ class Waiter:
|
|||||||
check if timer is out
|
check if timer is out
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
bool: True in case current monotonic time is more than ``Waiter.start_time`` and
|
bool: True in case current monotonic time is more than :attr:`start_time` and :attr:`wait_timeout`
|
||||||
``Waiter.wait_timeout`` doesn't equal to 0
|
doesn't equal to 0
|
||||||
"""
|
"""
|
||||||
since_start: float = time.monotonic() - self.start_time
|
since_start: float = time.monotonic() - self.start_time
|
||||||
return self.wait_timeout != 0 and since_start > self.wait_timeout
|
return self.wait_timeout != 0 and since_start > self.wait_timeout
|
||||||
|
|||||||
@ -41,8 +41,8 @@ def _dynamic_routes(module_root: Path) -> dict[str, Type[View]]:
|
|||||||
Returns:
|
Returns:
|
||||||
dict[str, Type[View]]: map of the route to its view
|
dict[str, Type[View]]: map of the route to its view
|
||||||
"""
|
"""
|
||||||
def is_base_view(clz: Any) -> TypeGuard[Type[BaseView]]:
|
def is_base_view(clazz: Any) -> TypeGuard[Type[BaseView]]:
|
||||||
return isinstance(clz, type) and issubclass(clz, BaseView)
|
return isinstance(clazz, type) and issubclass(clazz, BaseView)
|
||||||
|
|
||||||
routes: dict[str, Type[View]] = {}
|
routes: dict[str, Type[View]] = {}
|
||||||
for module_info in _modules(module_root):
|
for module_info in _modules(module_root):
|
||||||
@ -68,7 +68,7 @@ def _module(module_info: ModuleInfo) -> ModuleType:
|
|||||||
ModuleType: loaded module
|
ModuleType: loaded module
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
ValueError: if loader is not an instance of ``SourceFileLoader``
|
ValueError: if loader is not an instance of :class:`importlib.machinery.SourceFileLoader`
|
||||||
"""
|
"""
|
||||||
module_spec = module_info.module_finder.find_spec(module_info.name, None)
|
module_spec = module_info.module_finder.find_spec(module_info.name, None)
|
||||||
if module_spec is None:
|
if module_spec is None:
|
||||||
|
|||||||
@ -189,7 +189,7 @@ class BaseView(View, CorsViewMixin):
|
|||||||
"""
|
"""
|
||||||
get_method: Callable[..., Awaitable[StreamResponse]] | None = getattr(self, "get", None)
|
get_method: Callable[..., Awaitable[StreamResponse]] | None = getattr(self, "get", None)
|
||||||
# using if/else in order to suppress mypy warning which doesn't know that
|
# using if/else in order to suppress mypy warning which doesn't know that
|
||||||
# ``_raise_allowed_methods`` raises exception
|
# :func:`aiohttp.web.View._raise_allowed_methods()` raises exception
|
||||||
if get_method is not None:
|
if get_method is not None:
|
||||||
# there is a bug in pylint, see https://github.com/pylint-dev/pylint/issues/6005
|
# there is a bug in pylint, see https://github.com/pylint-dev/pylint/issues/6005
|
||||||
response = await get_method()
|
response = await get_method()
|
||||||
|
|||||||
44
src/ahriman/web/views/static.py
Normal file
44
src/ahriman/web/views/static.py
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2021-2023 ahriman team.
|
||||||
|
#
|
||||||
|
# This file is part of ahriman
|
||||||
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
from aiohttp.web import HTTPFound
|
||||||
|
|
||||||
|
from ahriman.models.user_access import UserAccess
|
||||||
|
from ahriman.web.views.base import BaseView
|
||||||
|
|
||||||
|
|
||||||
|
class StaticView(BaseView):
|
||||||
|
"""
|
||||||
|
special workaround for static files redirection (e.g. favicon)
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
GET_PERMISSION(UserAccess): (class attribute) get permissions of self
|
||||||
|
"""
|
||||||
|
|
||||||
|
GET_PERMISSION = UserAccess.Unauthorized
|
||||||
|
ROUTES = ["/favicon.ico"]
|
||||||
|
|
||||||
|
async def get(self) -> None:
|
||||||
|
"""
|
||||||
|
process get request. No parameters supported here
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
HTTPFound: on success response
|
||||||
|
"""
|
||||||
|
raise HTTPFound(f"/static{self.request.path}")
|
||||||
@ -104,36 +104,6 @@ def test_subparsers_aur_search_option_repository(parser: argparse.ArgumentParser
|
|||||||
assert args.repository == ""
|
assert args.repository == ""
|
||||||
|
|
||||||
|
|
||||||
def test_subparsers_help(parser: argparse.ArgumentParser) -> None:
|
|
||||||
"""
|
|
||||||
help command must imply architecture list, lock, quiet, report, repository, unsafe and parser
|
|
||||||
"""
|
|
||||||
args = parser.parse_args(["help"])
|
|
||||||
assert args.architecture == ""
|
|
||||||
assert args.lock is None
|
|
||||||
assert args.quiet
|
|
||||||
assert not args.report
|
|
||||||
assert args.repository == ""
|
|
||||||
assert args.unsafe
|
|
||||||
assert args.parser is not None and args.parser()
|
|
||||||
|
|
||||||
|
|
||||||
def test_subparsers_help_option_architecture(parser: argparse.ArgumentParser) -> None:
|
|
||||||
"""
|
|
||||||
help command must correctly parse architecture list
|
|
||||||
"""
|
|
||||||
args = parser.parse_args(["-a", "x86_64", "help"])
|
|
||||||
assert args.architecture == ""
|
|
||||||
|
|
||||||
|
|
||||||
def test_subparsers_help_option_repository(parser: argparse.ArgumentParser) -> None:
|
|
||||||
"""
|
|
||||||
help command must correctly parse repository list
|
|
||||||
"""
|
|
||||||
args = parser.parse_args(["-r", "repo", "help"])
|
|
||||||
assert args.repository == ""
|
|
||||||
|
|
||||||
|
|
||||||
def test_subparsers_help_commands_unsafe(parser: argparse.ArgumentParser) -> None:
|
def test_subparsers_help_commands_unsafe(parser: argparse.ArgumentParser) -> None:
|
||||||
"""
|
"""
|
||||||
help-commands-unsafe command must imply architecture list, lock, quiet, report, repository, unsafe and parser
|
help-commands-unsafe command must imply architecture list, lock, quiet, report, repository, unsafe and parser
|
||||||
@ -164,6 +134,36 @@ def test_subparsers_help_commands_unsafe_option_repository(parser: argparse.Argu
|
|||||||
assert args.repository == ""
|
assert args.repository == ""
|
||||||
|
|
||||||
|
|
||||||
|
def test_subparsers_help(parser: argparse.ArgumentParser) -> None:
|
||||||
|
"""
|
||||||
|
help command must imply architecture list, lock, quiet, report, repository, unsafe and parser
|
||||||
|
"""
|
||||||
|
args = parser.parse_args(["help"])
|
||||||
|
assert args.architecture == ""
|
||||||
|
assert args.lock is None
|
||||||
|
assert args.quiet
|
||||||
|
assert not args.report
|
||||||
|
assert args.repository == ""
|
||||||
|
assert args.unsafe
|
||||||
|
assert args.parser is not None and args.parser()
|
||||||
|
|
||||||
|
|
||||||
|
def test_subparsers_help_option_architecture(parser: argparse.ArgumentParser) -> None:
|
||||||
|
"""
|
||||||
|
help command must correctly parse architecture list
|
||||||
|
"""
|
||||||
|
args = parser.parse_args(["-a", "x86_64", "help"])
|
||||||
|
assert args.architecture == ""
|
||||||
|
|
||||||
|
|
||||||
|
def test_subparsers_help_option_repository(parser: argparse.ArgumentParser) -> None:
|
||||||
|
"""
|
||||||
|
help command must correctly parse repository list
|
||||||
|
"""
|
||||||
|
args = parser.parse_args(["-r", "repo", "help"])
|
||||||
|
assert args.repository == ""
|
||||||
|
|
||||||
|
|
||||||
def test_subparsers_help_updates(parser: argparse.ArgumentParser) -> None:
|
def test_subparsers_help_updates(parser: argparse.ArgumentParser) -> None:
|
||||||
"""
|
"""
|
||||||
help-updates command must imply architecture list, lock, quiet, report, repository, and unsafe
|
help-updates command must imply architecture list, lock, quiet, report, repository, and unsafe
|
||||||
|
|||||||
@ -30,30 +30,6 @@ def test_path(args: argparse.Namespace, configuration: Configuration) -> None:
|
|||||||
Lock(args, repository_id, configuration).path # special case
|
Lock(args, repository_id, configuration).path # special case
|
||||||
|
|
||||||
|
|
||||||
def test_check_version(lock: Lock, mocker: MockerFixture) -> None:
|
|
||||||
"""
|
|
||||||
must check version correctly
|
|
||||||
"""
|
|
||||||
mocker.patch("ahriman.core.status.client.Client.status_get",
|
|
||||||
return_value=InternalStatus(status=BuildStatus(), version=__version__))
|
|
||||||
logging_mock = mocker.patch("logging.Logger.warning")
|
|
||||||
|
|
||||||
lock.check_version()
|
|
||||||
logging_mock.assert_not_called()
|
|
||||||
|
|
||||||
|
|
||||||
def test_check_version_mismatch(lock: Lock, mocker: MockerFixture) -> None:
|
|
||||||
"""
|
|
||||||
must check mismatched version correctly
|
|
||||||
"""
|
|
||||||
mocker.patch("ahriman.core.status.client.Client.status_get",
|
|
||||||
return_value=InternalStatus(status=BuildStatus(), version="version"))
|
|
||||||
logging_mock = mocker.patch("logging.Logger.warning")
|
|
||||||
|
|
||||||
lock.check_version()
|
|
||||||
logging_mock.assert_called_once() # we do not check logging arguments
|
|
||||||
|
|
||||||
|
|
||||||
def test_check_user(lock: Lock, mocker: MockerFixture) -> None:
|
def test_check_user(lock: Lock, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must check user correctly
|
must check user correctly
|
||||||
@ -84,6 +60,30 @@ def test_check_user_unsafe(lock: Lock, mocker: MockerFixture) -> None:
|
|||||||
lock.check_user()
|
lock.check_user()
|
||||||
|
|
||||||
|
|
||||||
|
def test_check_version(lock: Lock, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must check version correctly
|
||||||
|
"""
|
||||||
|
mocker.patch("ahriman.core.status.client.Client.status_get",
|
||||||
|
return_value=InternalStatus(status=BuildStatus(), version=__version__))
|
||||||
|
logging_mock = mocker.patch("logging.Logger.warning")
|
||||||
|
|
||||||
|
lock.check_version()
|
||||||
|
logging_mock.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
|
def test_check_version_mismatch(lock: Lock, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must check mismatched version correctly
|
||||||
|
"""
|
||||||
|
mocker.patch("ahriman.core.status.client.Client.status_get",
|
||||||
|
return_value=InternalStatus(status=BuildStatus(), version="version"))
|
||||||
|
logging_mock = mocker.patch("logging.Logger.warning")
|
||||||
|
|
||||||
|
lock.check_version()
|
||||||
|
logging_mock.assert_called_once() # we do not check logging arguments
|
||||||
|
|
||||||
|
|
||||||
def test_clear(lock: Lock) -> None:
|
def test_clear(lock: Lock) -> None:
|
||||||
"""
|
"""
|
||||||
must remove lock file
|
must remove lock file
|
||||||
|
|||||||
@ -61,17 +61,6 @@ def test_from_path_file_missing(repository_id: RepositoryId, mocker: MockerFixtu
|
|||||||
read_mock.assert_called_once_with(configuration.SYSTEM_CONFIGURATION_PATH)
|
read_mock.assert_called_once_with(configuration.SYSTEM_CONFIGURATION_PATH)
|
||||||
|
|
||||||
|
|
||||||
def test_override_sections(repository_id: RepositoryId) -> None:
|
|
||||||
"""
|
|
||||||
must correctly generate override section names
|
|
||||||
"""
|
|
||||||
assert Configuration.override_sections("build", repository_id) == [
|
|
||||||
"build:x86_64",
|
|
||||||
"build:aur-clone",
|
|
||||||
"build:aur-clone:x86_64",
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def test_section_name(configuration: Configuration) -> None:
|
def test_section_name(configuration: Configuration) -> None:
|
||||||
"""
|
"""
|
||||||
must return architecture specific group
|
must return architecture specific group
|
||||||
@ -384,6 +373,26 @@ def test_merge_sections_priority(configuration: Configuration) -> None:
|
|||||||
assert configuration.get("build", "key4") == "key4_value1"
|
assert configuration.get("build", "key4") == "key4_value1"
|
||||||
|
|
||||||
|
|
||||||
|
def test_override_sections(configuration: Configuration, repository_id: RepositoryId) -> None:
|
||||||
|
"""
|
||||||
|
must correctly generate override section names
|
||||||
|
"""
|
||||||
|
assert configuration.override_sections("build", repository_id) == [
|
||||||
|
"build:x86_64",
|
||||||
|
"build:aur-clone",
|
||||||
|
"build:aur-clone:x86_64",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def test_override_sections_empty(configuration: Configuration) -> None:
|
||||||
|
"""
|
||||||
|
must look up for sections if repository identifier is empty
|
||||||
|
"""
|
||||||
|
configuration.set_option("web:x86_64", "port", "8080")
|
||||||
|
configuration.set_option("web:i686", "port", "8080")
|
||||||
|
assert configuration.override_sections("web", RepositoryId("", "")) == ["web:i686", "web:x86_64"]
|
||||||
|
|
||||||
|
|
||||||
def test_reload(configuration: Configuration, mocker: MockerFixture) -> None:
|
def test_reload(configuration: Configuration, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must reload configuration
|
must reload configuration
|
||||||
|
|||||||
@ -19,12 +19,10 @@ def test_build_queue_insert_clear_multi(database: SQLite, package_ahriman: Packa
|
|||||||
must clear all packages from queue for specific repository
|
must clear all packages from queue for specific repository
|
||||||
"""
|
"""
|
||||||
database.build_queue_insert(package_ahriman)
|
database.build_queue_insert(package_ahriman)
|
||||||
database._repository_id = RepositoryId("i686", database._repository_id.name)
|
database.build_queue_insert(package_ahriman, RepositoryId("i686", database._repository_id.name))
|
||||||
database.build_queue_insert(package_ahriman)
|
|
||||||
|
|
||||||
database.build_queue_clear(None)
|
database.build_queue_clear(None)
|
||||||
database._repository_id = RepositoryId("x86_64", database._repository_id.name)
|
assert database.build_queue_get(RepositoryId("i686", database._repository_id.name)) == [package_ahriman]
|
||||||
assert database.build_queue_get() == [package_ahriman]
|
|
||||||
|
|
||||||
|
|
||||||
def test_build_queue_insert_clear_specific(database: SQLite, package_ahriman: Package,
|
def test_build_queue_insert_clear_specific(database: SQLite, package_ahriman: Package,
|
||||||
@ -68,19 +66,15 @@ def test_build_queue_insert_multi(database: SQLite, package_ahriman: Package) ->
|
|||||||
assert database.build_queue_get() == [package_ahriman]
|
assert database.build_queue_get() == [package_ahriman]
|
||||||
|
|
||||||
package_ahriman.version = "2"
|
package_ahriman.version = "2"
|
||||||
database._repository_id = RepositoryId("i686", database._repository_id.name)
|
database.build_queue_insert(package_ahriman, RepositoryId("i686", database._repository_id.name))
|
||||||
database.build_queue_insert(package_ahriman)
|
assert database.build_queue_get(RepositoryId("i686", database._repository_id.name)) == [package_ahriman]
|
||||||
assert database.build_queue_get() == [package_ahriman]
|
|
||||||
|
|
||||||
package_ahriman.version = "1"
|
package_ahriman.version = "1"
|
||||||
database._repository_id = RepositoryId("x86_64", database._repository_id.name)
|
assert database.build_queue_get(RepositoryId("x86_64", database._repository_id.name)) == [package_ahriman]
|
||||||
assert database.build_queue_get() == [package_ahriman]
|
|
||||||
|
|
||||||
package_ahriman.version = "3"
|
package_ahriman.version = "3"
|
||||||
database._repository_id = RepositoryId(database._repository_id.architecture, "repo")
|
database.build_queue_insert(package_ahriman, RepositoryId(database._repository_id.architecture, "repo"))
|
||||||
database.build_queue_insert(package_ahriman)
|
assert database.build_queue_get(RepositoryId(database._repository_id.architecture, "repo")) == [package_ahriman]
|
||||||
assert database.build_queue_get() == [package_ahriman]
|
|
||||||
|
|
||||||
package_ahriman.version = "1"
|
package_ahriman.version = "1"
|
||||||
database._repository_id = RepositoryId(database._repository_id.architecture, "aur-clone")
|
|
||||||
assert database.build_queue_get() == [package_ahriman]
|
assert database.build_queue_get() == [package_ahriman]
|
||||||
|
|||||||
@ -89,15 +89,6 @@ def test_asset_upload_empty_mimetype(github: GitHub, github_release: dict[str, A
|
|||||||
headers={"Content-Type": "application/octet-stream"})
|
headers={"Content-Type": "application/octet-stream"})
|
||||||
|
|
||||||
|
|
||||||
def test_get_local_files(github: GitHub, resource_path_root: Path, mocker: MockerFixture) -> None:
|
|
||||||
"""
|
|
||||||
must get all local files recursively
|
|
||||||
"""
|
|
||||||
walk_mock = mocker.patch("ahriman.core.util.walk")
|
|
||||||
github.get_local_files(resource_path_root)
|
|
||||||
walk_mock.assert_called()
|
|
||||||
|
|
||||||
|
|
||||||
def test_files_remove(github: GitHub, github_release: dict[str, Any], mocker: MockerFixture) -> None:
|
def test_files_remove(github: GitHub, github_release: dict[str, Any], mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must remove files from the remote
|
must remove files from the remote
|
||||||
@ -137,6 +128,15 @@ def test_files_upload_empty(github: GitHub, github_release: dict[str, Any], mock
|
|||||||
upload_mock.assert_not_called()
|
upload_mock.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_local_files(github: GitHub, resource_path_root: Path, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must get all local files recursively
|
||||||
|
"""
|
||||||
|
walk_mock = mocker.patch("ahriman.core.util.walk")
|
||||||
|
github.get_local_files(resource_path_root)
|
||||||
|
walk_mock.assert_called()
|
||||||
|
|
||||||
|
|
||||||
def test_release_create(github: GitHub, mocker: MockerFixture) -> None:
|
def test_release_create(github: GitHub, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must create release
|
must create release
|
||||||
|
|||||||
@ -3,6 +3,14 @@ import pytest
|
|||||||
from ahriman.models.repository_id import RepositoryId
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
|
def test_id() -> None:
|
||||||
|
"""
|
||||||
|
must correctly generate id
|
||||||
|
"""
|
||||||
|
assert RepositoryId("", "").id == ""
|
||||||
|
assert RepositoryId("arch", "repo").id == "arch-repo"
|
||||||
|
|
||||||
|
|
||||||
def test_is_empty() -> None:
|
def test_is_empty() -> None:
|
||||||
"""
|
"""
|
||||||
must check if repository id is empty or not
|
must check if repository id is empty or not
|
||||||
@ -13,14 +21,6 @@ def test_is_empty() -> None:
|
|||||||
assert not RepositoryId("arch", "repo").is_empty
|
assert not RepositoryId("arch", "repo").is_empty
|
||||||
|
|
||||||
|
|
||||||
def test_id() -> None:
|
|
||||||
"""
|
|
||||||
must correctly generate id
|
|
||||||
"""
|
|
||||||
assert RepositoryId("", "").id == ""
|
|
||||||
assert RepositoryId("arch", "repo").id == "arch-repo"
|
|
||||||
|
|
||||||
|
|
||||||
def test_query() -> None:
|
def test_query() -> None:
|
||||||
"""
|
"""
|
||||||
must generate query request parameters
|
must generate query request parameters
|
||||||
|
|||||||
31
tests/ahriman/web/views/test_view_static.py
Normal file
31
tests/ahriman/web/views/test_view_static.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import pytest
|
||||||
|
|
||||||
|
from aiohttp.test_utils import TestClient
|
||||||
|
|
||||||
|
from ahriman.models.user_access import UserAccess
|
||||||
|
from ahriman.web.views.static import StaticView
|
||||||
|
|
||||||
|
|
||||||
|
async def test_get_permission() -> None:
|
||||||
|
"""
|
||||||
|
must return correct permission for the request
|
||||||
|
"""
|
||||||
|
for method in ("GET",):
|
||||||
|
request = pytest.helpers.request("", "", method)
|
||||||
|
assert await StaticView.get_permission(request) == UserAccess.Unauthorized
|
||||||
|
|
||||||
|
|
||||||
|
def test_routes() -> None:
|
||||||
|
"""
|
||||||
|
must return correct routes
|
||||||
|
"""
|
||||||
|
assert StaticView.ROUTES == ["/favicon.ico"]
|
||||||
|
|
||||||
|
|
||||||
|
async def test_get(client_with_auth: TestClient) -> None:
|
||||||
|
"""
|
||||||
|
must generate status page correctly (/)
|
||||||
|
"""
|
||||||
|
response = await client_with_auth.get("/favicon.ico", allow_redirects=False)
|
||||||
|
assert response.status == 302
|
||||||
|
assert response.headers["Location"] == "/static/favicon.ico"
|
||||||
Reference in New Issue
Block a user