mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-04-24 23:37:18 +00:00
add migration docs and ability to migrate tree automatically
This commit is contained in:
parent
0eebcc5740
commit
1b5bfe5088
@ -172,6 +172,14 @@ ahriman.application.handlers.structure module
|
|||||||
:no-undoc-members:
|
:no-undoc-members:
|
||||||
:show-inheritance:
|
:show-inheritance:
|
||||||
|
|
||||||
|
ahriman.application.handlers.tree\_migrate module
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
.. automodule:: ahriman.application.handlers.tree_migrate
|
||||||
|
:members:
|
||||||
|
:no-undoc-members:
|
||||||
|
:show-inheritance:
|
||||||
|
|
||||||
ahriman.application.handlers.triggers module
|
ahriman.application.handlers.triggers module
|
||||||
--------------------------------------------
|
--------------------------------------------
|
||||||
|
|
||||||
|
@ -102,6 +102,53 @@ All subcommands are divided into several groups depending on the role they are d
|
|||||||
|
|
||||||
For historical reasons and in order to keep backward compatibility some subcommands have aliases to their shorter forms or even other groups, but the service doesn't guarantee that they will remain unchanged.
|
For historical reasons and in order to keep backward compatibility some subcommands have aliases to their shorter forms or even other groups, but the service doesn't guarantee that they will remain unchanged.
|
||||||
|
|
||||||
|
Filesystem tree
|
||||||
|
---------------
|
||||||
|
|
||||||
|
The application supports two types of trees, one is for legacy configuration (when there were no repository name explicit configuration available) and another one is for new-style tree. This document describes only new-style tree in order to avoid deprecated structure.
|
||||||
|
|
||||||
|
Having default root as ``/var/lib/ahriman`` (differs from container though), the directory structure is the following:
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
|
||||||
|
/var/lib/ahriman/
|
||||||
|
├── ahriman.db
|
||||||
|
├── cache
|
||||||
|
├── chroot
|
||||||
|
│ └── aur-clone
|
||||||
|
├── packages
|
||||||
|
│ └── aur-clone
|
||||||
|
│ └── x86_64
|
||||||
|
├── pacman
|
||||||
|
│ └── aur-clone
|
||||||
|
│ └── x86_64
|
||||||
|
│ ├── local
|
||||||
|
│ │ └── ALPM_DB_VERSION
|
||||||
|
│ └── sync
|
||||||
|
│ ├── core.db
|
||||||
|
│ ├── extra.db
|
||||||
|
│ └── multilib.db
|
||||||
|
│
|
||||||
|
└── repository
|
||||||
|
└── aur-clone
|
||||||
|
└── x86_64
|
||||||
|
├── aur-clone.db -> aur-clone.db.tar.gz
|
||||||
|
├── aur-clone.db.tar.gz
|
||||||
|
├── aur-clone.files -> aur-clone.files.tar.gz
|
||||||
|
└── aur-clone.files.tar.gz
|
||||||
|
|
||||||
|
There are multiple subdirectories, some of them are commons for any repository, but some of them are not.
|
||||||
|
|
||||||
|
* ``cache`` is a directory with locally stored PKGBUILD's and VCS packages. It is common for all repositories and architectures.
|
||||||
|
* ``chroot/{repository}`` is a chroot directory for ``devtools``. It is specific for each repository, but shared for different architectures inside (the ``devtools`` handles architectures automatically).
|
||||||
|
* ``packages/{repository}/{architecture}`` is a directory with prebuilt packages. When package is built, first it will be uploaded to this directory and later will be handled by update process. It is architecture and repository specific.
|
||||||
|
* ``pacman/{repository}/{architecture}`` is repository and architecture specific caches for pacman's databases.
|
||||||
|
* ``repository/{repository}/{architecture}`` is a repository packages directory.
|
||||||
|
|
||||||
|
Normally you should avoid direct interaction with the application tree.
|
||||||
|
|
||||||
|
For tree migration process refer to the :doc:`migration notes <migration>`.
|
||||||
|
|
||||||
Database
|
Database
|
||||||
--------
|
--------
|
||||||
|
|
||||||
|
60
docs/faq.rst
60
docs/faq.rst
@ -71,7 +71,7 @@ states that default build command is ``extra-x86_64-build``. But if there is sec
|
|||||||
[build:i686]
|
[build:i686]
|
||||||
build_command = extra-i686-build
|
build_command = extra-i686-build
|
||||||
|
|
||||||
the ``extra-i686-build`` command will be used for ``i686`` architecture.
|
the ``extra-i686-build`` command will be used for ``i686`` architecture. You can also override settings for different repositories and architectures; in this case section names will be ``build:aur-clone`` (repository name only) and ``build:aur-clone:i686`` (both repository name and architecture).
|
||||||
|
|
||||||
How to generate build reports
|
How to generate build reports
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
@ -121,7 +121,7 @@ How do I add new package
|
|||||||
|
|
||||||
sudo -u ahriman ahriman package-add ahriman --now
|
sudo -u ahriman ahriman package-add ahriman --now
|
||||||
|
|
||||||
``--now`` flag is totally optional and just run ``repo-update`` subcommand after the registering the new package, Thus the extended flow is the following:
|
``--now`` flag is totally optional and just run ``repo-update`` subcommand after the registering the new package. Thus the extended flow is the following:
|
||||||
|
|
||||||
.. code-block:: shell
|
.. code-block:: shell
|
||||||
|
|
||||||
@ -209,7 +209,7 @@ So it is the same as adding any other package, but due to restrictions you must
|
|||||||
|
|
||||||
sudo -u ahriman ahriman package-add pacman -s repository
|
sudo -u ahriman ahriman package-add pacman -s repository
|
||||||
|
|
||||||
This feature is heavily depends on local pacman cache. In order to use this feature it is recommended to either run ``pacman -Sy`` before the interaction or configure timer for this.
|
This feature is heavily depends on local pacman cache. In order to use this feature it is recommended to either run ``pacman -Sy`` before the interaction or use internal application cache with ``--refresh`` flag.
|
||||||
|
|
||||||
Package build fails because it cannot validate PGP signature of source files
|
Package build fails because it cannot validate PGP signature of source files
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
@ -359,7 +359,14 @@ Example of the status page configuration is the following (status service is usi
|
|||||||
Docker image
|
Docker image
|
||||||
------------
|
------------
|
||||||
|
|
||||||
We provide official images which can be found under ``arcan1s/ahriman`` repository. Docker image is being updated on each commit to master as well as on each version. If you would like to use last (probably unstable) build you can use ``edge`` tag or ``latest`` for any tagged versions; otherwise you can use any version tag available.
|
We provide official images which can be found under:
|
||||||
|
|
||||||
|
* docker registry ``arcan1s/ahriman``;
|
||||||
|
* ghcr.io registry ``ghcr.io/arcan1s/ahriman``;
|
||||||
|
|
||||||
|
These images are totally identical.
|
||||||
|
|
||||||
|
Docker image is being updated on each commit to master as well as on each version. If you would like to use last (probably unstable) build you can use ``edge`` tag or ``latest`` for any tagged versions; otherwise you can use any version tag available.
|
||||||
|
|
||||||
The default action (in case if no arguments provided) is ``repo-update``. Basically the idea is to run container, e.g.:
|
The default action (in case if no arguments provided) is ``repo-update``. Basically the idea is to run container, e.g.:
|
||||||
|
|
||||||
@ -456,22 +463,22 @@ Physical server setup
|
|||||||
In this example we are going to use files and packages which are provided by official repositories of the used architecture. Note, that versions might be different, thus you need to find correct versions on the distribution web site, e.g. `archlinux32 packages <https://www.archlinux32.org/packages/>`_.
|
In this example we are going to use files and packages which are provided by official repositories of the used architecture. Note, that versions might be different, thus you need to find correct versions on the distribution web site, e.g. `archlinux32 packages <https://www.archlinux32.org/packages/>`_.
|
||||||
|
|
||||||
#.
|
#.
|
||||||
First, considering having base Arch Linux system, we need to install keyring for the specified repositories:
|
First, considering having base Arch Linux system, we need to install keyring for the specified repositories, e.g.:
|
||||||
|
|
||||||
.. code-block:: shell
|
.. code-block:: shell
|
||||||
|
|
||||||
wget http://pool.mirror.archlinux32.org/i686/core/archlinux32-keyring-20220927-1.0-any.pkg.tar.zst
|
wget http://pool.mirror.archlinux32.org/i686/core/archlinux32-keyring-20230705-1.0-any.pkg.tar.zst
|
||||||
pacman -U archlinux32-keyring-20220927-1.0-any.pkg.tar.zst
|
pacman -U archlinux32-keyring-20230705-1.0-any.pkg.tar.zst
|
||||||
|
|
||||||
#.
|
#.
|
||||||
In order to run ``devtools`` scripts for custom architecture they also need specific ``makepkg`` configuration, it can be retrieved by installing the ``devtools`` package of the distribution:
|
In order to run ``devtools`` scripts for custom architecture they also need specific ``makepkg`` configuration, it can be retrieved by installing the ``devtools`` package of the distribution, e.g.:
|
||||||
|
|
||||||
.. code-block:: shell
|
.. code-block:: shell
|
||||||
|
|
||||||
wget http://pool.mirror.archlinux32.org/i686/extra/devtools-20221208-1.0-any.pkg.tar.zst
|
wget http://pool.mirror.archlinux32.org/i686/extra/devtools-20221208-1.2-any.pkg.tar.zst
|
||||||
pacman -U devtools-20221208-1.0-any.pkg.tar.zst
|
pacman -U devtools-20221208-1.2-any.pkg.tar.zst
|
||||||
|
|
||||||
Alternatively, you can create your own ``makepkg`` configuration and save it as ``/usr/share/devtools/makepkg-i686.conf``.
|
Alternatively, you can create your own ``makepkg`` configuration and save it as ``/usr/share/devtools/makepkg.conf.d/i686.conf``.
|
||||||
|
|
||||||
#.
|
#.
|
||||||
Setup repository as usual:
|
Setup repository as usual:
|
||||||
@ -485,6 +492,9 @@ In this example we are going to use files and packages which are provided by off
|
|||||||
* ``--mirror`` - link to the mirrors which will be used instead of official repositories.
|
* ``--mirror`` - link to the mirrors which will be used instead of official repositories.
|
||||||
* ``--no-multilib`` - in the example we are using i686 architecture for which multilib repository doesn't exist.
|
* ``--no-multilib`` - in the example we are using i686 architecture for which multilib repository doesn't exist.
|
||||||
|
|
||||||
|
#.
|
||||||
|
That's all Folks!
|
||||||
|
|
||||||
Docker container setup
|
Docker container setup
|
||||||
^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
@ -510,8 +520,8 @@ There are two possible ways to achieve same setup, by using docker container. Th
|
|||||||
.. code-block:: dockerfile
|
.. code-block:: dockerfile
|
||||||
|
|
||||||
RUN pacman --noconfirm -Sy wget
|
RUN pacman --noconfirm -Sy wget
|
||||||
RUN wget http://pool.mirror.archlinux32.org/i686/extra/devtools-20221208-1.0-any.pkg.tar.zst && pacman --noconfirm -U devtools-20221208-1.0-any.pkg.tar.zst
|
RUN wget http://pool.mirror.archlinux32.org/i686/extra/devtools-20221208-1.2-any.pkg.tar.zst && pacman --noconfirm -U devtools-20221208-1.2-any.pkg.tar.zst
|
||||||
RUN wget http://pool.mirror.archlinux32.org/i686/core/archlinux32-keyring-20220927-1.0-any.pkg.tar.zst && pacman --noconfirm -U archlinux32-keyring-20220927-1.0-any.pkg.tar.zst
|
RUN wget http://pool.mirror.archlinux32.org/i686/core/archlinux32-keyring-20230705-1.0-any.pkg.tar.zst && pacman --noconfirm -U archlinux32-keyring-20230705-1.0-any.pkg.tar.zst
|
||||||
|
|
||||||
#.
|
#.
|
||||||
At that point you should have full ``Dockerfile`` like:
|
At that point you should have full ``Dockerfile`` like:
|
||||||
@ -523,8 +533,8 @@ There are two possible ways to achieve same setup, by using docker container. Th
|
|||||||
RUN pacman-key --init
|
RUN pacman-key --init
|
||||||
|
|
||||||
RUN pacman --noconfirm -Sy wget
|
RUN pacman --noconfirm -Sy wget
|
||||||
RUN wget http://pool.mirror.archlinux32.org/i686/extra/devtools-20221208-1.0-any.pkg.tar.zst && pacman --noconfirm -U devtools-20221208-1.0-any.pkg.tar.zst
|
RUN wget http://pool.mirror.archlinux32.org/i686/extra/devtools-20221208-1.2-any.pkg.tar.zst && pacman --noconfirm -U devtools-20221208-1.2-any.pkg.tar.zst
|
||||||
RUN wget http://pool.mirror.archlinux32.org/i686/core/archlinux32-keyring-20220927-1.0-any.pkg.tar.zst && pacman --noconfirm -U archlinux32-keyring-20220927-1.0-any.pkg.tar.zst
|
RUN wget http://pool.mirror.archlinux32.org/i686/core/archlinux32-keyring-20230705-1.0-any.pkg.tar.zst && pacman --noconfirm -U archlinux32-keyring-20230705-1.0-any.pkg.tar.zst
|
||||||
|
|
||||||
#.
|
#.
|
||||||
After that you can build you own container, e.g.:
|
After that you can build you own container, e.g.:
|
||||||
@ -554,8 +564,8 @@ There are several choices:
|
|||||||
.. code-block::
|
.. code-block::
|
||||||
|
|
||||||
server {
|
server {
|
||||||
location /aur-clone/x86_64 {
|
location / {
|
||||||
root /var/lib/ahriman/repository/aur-clone/x86_64;
|
root /var/lib/ahriman/repository/;
|
||||||
autoindex on;
|
autoindex on;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -571,7 +581,7 @@ There are several choices:
|
|||||||
[rsync]
|
[rsync]
|
||||||
remote = 192.168.0.1:/srv/repo
|
remote = 192.168.0.1:/srv/repo
|
||||||
|
|
||||||
After that just add ``/srv/repo`` to the ``pacman.conf`` as usual. You can also upload to S3 (e.g. ``Server = https://s3.eu-central-1.amazonaws.com/repository/aur-clone/x86_64``) or to Github (e.g. ``Server = https://github.com/ahriman/repository/releases/download/aur-clone-x86_64``).
|
After that just add ``/srv/repo`` to the ``pacman.conf`` as usual. You can also upload to S3 (``Server = https://s3.eu-central-1.amazonaws.com/repository/aur-clone/x86_64``) or to Github (``Server = https://github.com/ahriman/repository/releases/download/aur-clone-x86_64``).
|
||||||
|
|
||||||
How to sync to S3
|
How to sync to S3
|
||||||
^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^
|
||||||
@ -705,7 +715,7 @@ How to generate index page for S3
|
|||||||
path = /var/lib/ahriman/repository/aur-clone/x86_64/index.html
|
path = /var/lib/ahriman/repository/aur-clone/x86_64/index.html
|
||||||
link_path = http://example.com/aur-clone/x86_64
|
link_path = http://example.com/aur-clone/x86_64
|
||||||
|
|
||||||
After these steps ``index.html`` file will be automatically synced to S3
|
After these steps ``index.html`` file will be automatically synced to S3.
|
||||||
|
|
||||||
How to post build report to telegram
|
How to post build report to telegram
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
@ -756,7 +766,7 @@ If you did everything fine you should receive the message with the next update.
|
|||||||
Distributed builds
|
Distributed builds
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
The service allows to run build on multiple machines and collect packages on main node. There are multiple ways to achieve it, this section describes officially supported methods.
|
The service allows to run build on multiple machines and collect packages on main node. There are several ways to achieve it, this section describes officially supported methods.
|
||||||
|
|
||||||
Remote synchronization and remote server call
|
Remote synchronization and remote server call
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
@ -933,7 +943,7 @@ Command to run worker node:
|
|||||||
|
|
||||||
.. code-block:: shell
|
.. code-block:: shell
|
||||||
|
|
||||||
docker run --privileged -v worker.ini:/etc/ahriman.ini.d/overrides.ini -it arcan1s/ahriman:latest package-add arhiman --now
|
docker run --privileged -v worker.ini:/etc/ahriman.ini.d/overrides.ini -it arcan1s/ahriman:latest package-add ahriman --now
|
||||||
|
|
||||||
The command above will successfully build ``ahriman`` package, upload it on master node and, finally, will update master node repository.
|
The command above will successfully build ``ahriman`` package, upload it on master node and, finally, will update master node repository.
|
||||||
|
|
||||||
@ -1059,7 +1069,7 @@ How to enable basic authorization
|
|||||||
yay -S --asdeps python-aiohttp-security python-aiohttp-session python-cryptography
|
yay -S --asdeps python-aiohttp-security python-aiohttp-session python-cryptography
|
||||||
|
|
||||||
#.
|
#.
|
||||||
Configure the service to enable authorization (``salt`` can be generated as any random string):
|
Configure the service to enable authorization (``salt`` can be generated as any random string and optional):
|
||||||
|
|
||||||
.. code-block:: ini
|
.. code-block:: ini
|
||||||
|
|
||||||
@ -1087,7 +1097,7 @@ How to enable basic authorization
|
|||||||
|
|
||||||
sudo -u ahriman ahriman user-add -r full api
|
sudo -u ahriman ahriman user-add -r full api
|
||||||
|
|
||||||
This command will ask for the password, just type it in stdin; *do not* leave the field blank, user will not be able to authorize, and finally configure the application:
|
This command will ask for the password, just type it in stdin; **do not** leave the field blank, user will not be able to authorize, and finally configure the application:
|
||||||
|
|
||||||
.. code-block:: ini
|
.. code-block:: ini
|
||||||
|
|
||||||
@ -1265,7 +1275,9 @@ You can also ask to forward logs to ``stderr``, just set ``--log-handler`` flag,
|
|||||||
|
|
||||||
ahriman --log-handler console ...
|
ahriman --log-handler console ...
|
||||||
|
|
||||||
You can even configure logging as you wish, but kindly refer to python ``logging`` module `configuration <https://docs.python.org/3/library/logging.config.html>`_. The application uses java concept to log messages, e.g. class ``Application`` imported from ``ahriman.application.application`` package will have logger called ``ahriman.application.application.Application``. In order to e.g. change logger name for whole application package it is possible to change values for ``ahriman.application`` package; thus editing ``ahriman`` logger configuration will change logging for whole application (unless there are overrides for another logger).
|
You can even configure logging as you wish, but kindly refer to python ``logging`` module `configuration <https://docs.python.org/3/library/logging.config.html>`_.
|
||||||
|
|
||||||
|
The application uses java concept to log messages, e.g. class ``Application`` imported from ``ahriman.application.application`` package will have logger called ``ahriman.application.application.Application``. In order to e.g. change logger name for whole application package it is possible to change values for ``ahriman.application`` package; thus editing ``ahriman`` logger configuration will change logging for whole application (unless there are overrides for another logger).
|
||||||
|
|
||||||
Html customization
|
Html customization
|
||||||
^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^
|
||||||
|
52
docs/migration.rst
Normal file
52
docs/migration.rst
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
Manual migrations
|
||||||
|
=================
|
||||||
|
|
||||||
|
Normally most of migrations are handled automatically after application start. However, some upgrades require manual interventions; this document describes them.
|
||||||
|
|
||||||
|
Upgrades from versions
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
To 2.9.0
|
||||||
|
^^^^^^^^
|
||||||
|
|
||||||
|
This release includes major upgrade for the newest devtools and archlinux repository structure. In order to upgrade package need to:
|
||||||
|
|
||||||
|
#. Upgrade to the latest major release of python (3.11) (required by other changes).
|
||||||
|
#. Upgrade devtools to the latest release.
|
||||||
|
#. Backup your settings, ``/etc/ahriman.ini.d/00-setup-overrides.ini`` by default.
|
||||||
|
#. Run setup command (i.e. ``ahriman service-setup``) again with the same arguments as you used before. This step can be done manually by moving ``devtools`` configuration (something like ``/usr/share/devtools/pacman-ahriman*.conf``) to new location ``/usr/share/devtools/pacman.conf.d/`` under name ``ahriman.conf``. After that make sure to remove any ``community`` mentions from configurations (e.g. ``/usr/share/devtools/pacman.conf.d/ahriman.conf``, ``/etc/ahriman.ini``) if there were any. The only thing which will change is ``devtools`` configuration.
|
||||||
|
#. Remove build chroot as it is incompatible, e.g. ``sudo ahriman service-clean --chroot``.
|
||||||
|
#. Run ``sudo -u ahriman ahriman update --no-aur --no-local --no-manual -yy`` in order to update local databases.
|
||||||
|
|
||||||
|
To 2.12.0
|
||||||
|
^^^^^^^^^
|
||||||
|
|
||||||
|
This release includes paths migration. Unlike usual case, no automatic migration is performed because it might break user configuration. The following noticeable changes have been made:
|
||||||
|
|
||||||
|
* Path to pre-built packages now includes repository name, i.e. it has been changed from ``/var/lib/ahriman/packages/x86_64`` to ``/var/lib/ahriman/packages/aur-clone/x86_64``.
|
||||||
|
* Path to pacman databases now includes repository name too, it has been changed from ``/var/lib/ahriman/pacman/x86_64`` to ``/var/lib/ahriman/pacman/aur-clone/x86_64``.
|
||||||
|
* Path to repository itself also includes repository name, from ``/var/lib/ahriman/repository/x86_64`` to ``/var/lib/ahriman/repository/aur-clone/x86_64``.
|
||||||
|
|
||||||
|
In order to migrate to new filesystem tree the following actions are required:
|
||||||
|
|
||||||
|
#.
|
||||||
|
Stop and disable all services, e.g. timer and web service:
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
sudo systemctl disable --now ahriman@x86_64.timer
|
||||||
|
sudo systemctl disable --now ahriman-web@x86_64
|
||||||
|
|
||||||
|
#.
|
||||||
|
Create directory tree. It can be done by running ``ahriman service-tree-migrate`` subcommand. It performs copying between the old repository tree and the new one. Alternatively you can copy directories by hands.
|
||||||
|
|
||||||
|
#.
|
||||||
|
Edit configuration in case if anything is pointing to the old path, e.g. HTML report generation, in the way in which it will be pointed to directory inside repository specific one, e.g. ``/var/lib/ahriman/repository/x86_64`` to ``/var/lib/ahriman/repository/aur-clone/x86_64``.
|
||||||
|
|
||||||
|
#.
|
||||||
|
Enable and start services again. Unit template parameter should include both repository architecture and name, dash separated, e.g. ``x86_64-aur-clone``:
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
sudo systemctl enable --now ahriman@x86_64-aur-clone.timer
|
||||||
|
sudo systemctl enable --now ahriman-web@x86_64-aur-clone
|
@ -1,6 +1,7 @@
|
|||||||
post_upgrade() {
|
post_upgrade() {
|
||||||
local breakpoints=(
|
local breakpoints=(
|
||||||
2.9.0-1
|
2.9.0-1
|
||||||
|
2.12.0-1
|
||||||
)
|
)
|
||||||
|
|
||||||
for v in "${breakpoints[@]}"; do
|
for v in "${breakpoints[@]}"; do
|
||||||
@ -20,6 +21,20 @@ It was found that you were upgrading from old-devtools package to the new one, w
|
|||||||
* remove build chroot: sudo rm -r /var/lib/ahriman/chroot/ahriman-x86_64/;
|
* remove build chroot: sudo rm -r /var/lib/ahriman/chroot/ahriman-x86_64/;
|
||||||
* update local databases: sudo -u ahriman ahriman update --no-aur --no-local --no-manual -yy;
|
* update local databases: sudo -u ahriman ahriman update --no-aur --no-local --no-manual -yy;
|
||||||
|
|
||||||
For more information kindly refer to changelog https://github.com/arcan1s/ahriman/releases/tag/2.9.0
|
For more information kindly refer to migration notes https://ahriman.readthedocs.io/en/stable/migration.html
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
_2_12_0_1_changes() {
|
||||||
|
cat << EOF
|
||||||
|
Whereas old tree is still supported it is highly recommended to migrate to the new one:
|
||||||
|
|
||||||
|
* stop and disable all services;
|
||||||
|
* run service-tree-migrate as ahriman user;
|
||||||
|
* edit configuration to avoid pointing to the old paths;
|
||||||
|
* enable web and timer services again by using x86_64-aur-clone suffix, where x86_64 is your architecture and
|
||||||
|
aur-clone is repository name;
|
||||||
|
|
||||||
|
For more information kindly refer to migration notes https://ahriman.readthedocs.io/en/stable/migration.html
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
# 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-setup' 'init' 'repo-init' 'repo-setup' 'setup' 'service-shell' 'shell' 'user-add' 'user-list' 'user-remove' 'web')
|
_shtab_ahriman_subparsers=('aur-search' 'search' 'help' 'help-commands-unsafe' 'help-updates' 'help-version' 'version' 'package-add' 'add' 'package-update' 'package-remove' 'remove' 'package-status' 'status' 'package-status-remove' 'package-status-update' 'status-update' 'patch-add' 'patch-list' 'patch-remove' 'patch-set-add' 'repo-backup' 'repo-check' 'check' 'repo-create-keyring' 'repo-create-mirrorlist' 'repo-daemon' 'daemon' 'repo-rebuild' 'rebuild' 'repo-remove-unknown' 'remove-unknown' 'repo-report' 'report' 'repo-restore' 'repo-sign' 'sign' 'repo-status-update' 'repo-sync' 'sync' 'repo-tree' 'repo-triggers' 'repo-update' 'update' 'service-clean' 'clean' 'repo-clean' 'service-config' 'config' 'repo-config' 'service-config-validate' 'config-validate' 'repo-config-validate' 'service-key-import' 'key-import' 'service-setup' 'init' 'repo-init' 'repo-setup' 'setup' 'service-shell' 'shell' 'service-tree-migrate' 'user-add' 'user-list' 'user-remove' 'web')
|
||||||
|
|
||||||
_shtab_ahriman_option_strings=('-h' '--help' '-a' '--architecture' '-c' '--configuration' '--force' '-l' '--lock' '--log-handler' '--report' '--no-report' '-r' '--repository' '-q' '--quiet' '--unsafe' '--wait-timeout' '-V' '--version')
|
_shtab_ahriman_option_strings=('-h' '--help' '-a' '--architecture' '-c' '--configuration' '--force' '-l' '--lock' '--log-handler' '-q' '--quiet' '--report' '--no-report' '-r' '--repository' '--unsafe' '--wait-timeout' '-V' '--version')
|
||||||
_shtab_ahriman_aur_search_option_strings=('-h' '--help' '-e' '--exit-code' '--info' '--no-info' '--sort-by')
|
_shtab_ahriman_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_option_strings=('-h' '--help')
|
||||||
@ -65,6 +65,7 @@ _shtab_ahriman_repo_setup_option_strings=('-h' '--help' '--build-as-user' '--fro
|
|||||||
_shtab_ahriman_setup_option_strings=('-h' '--help' '--build-as-user' '--from-configuration' '--generate-salt' '--no-generate-salt' '--makeflags-jobs' '--no-makeflags-jobs' '--mirror' '--multilib' '--no-multilib' '--packager' '--server' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket')
|
_shtab_ahriman_setup_option_strings=('-h' '--help' '--build-as-user' '--from-configuration' '--generate-salt' '--no-generate-salt' '--makeflags-jobs' '--no-makeflags-jobs' '--mirror' '--multilib' '--no-multilib' '--packager' '--server' '--sign-key' '--sign-target' '--web-port' '--web-unix-socket')
|
||||||
_shtab_ahriman_service_shell_option_strings=('-h' '--help')
|
_shtab_ahriman_service_shell_option_strings=('-h' '--help')
|
||||||
_shtab_ahriman_shell_option_strings=('-h' '--help')
|
_shtab_ahriman_shell_option_strings=('-h' '--help')
|
||||||
|
_shtab_ahriman_service_tree_migrate_option_strings=('-h' '--help')
|
||||||
_shtab_ahriman_user_add_option_strings=('-h' '--help' '--key' '--packager' '-p' '--password' '-R' '--role')
|
_shtab_ahriman_user_add_option_strings=('-h' '--help' '--key' '--packager' '-p' '--password' '-R' '--role')
|
||||||
_shtab_ahriman_user_list_option_strings=('-h' '--help' '-e' '--exit-code' '-R' '--role')
|
_shtab_ahriman_user_list_option_strings=('-h' '--help' '-e' '--exit-code' '-R' '--role')
|
||||||
_shtab_ahriman_user_remove_option_strings=('-h' '--help')
|
_shtab_ahriman_user_remove_option_strings=('-h' '--help')
|
||||||
@ -72,7 +73,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-setup' 'init' 'repo-init' 'repo-setup' 'setup' 'service-shell' 'shell' 'user-add' 'user-list' 'user-remove' 'web')
|
_shtab_ahriman_pos_0_choices=('aur-search' 'search' 'help' 'help-commands-unsafe' 'help-updates' 'help-version' 'version' 'package-add' 'add' 'package-update' 'package-remove' 'remove' 'package-status' 'status' 'package-status-remove' 'package-status-update' 'status-update' 'patch-add' 'patch-list' 'patch-remove' 'patch-set-add' 'repo-backup' 'repo-check' 'check' 'repo-create-keyring' 'repo-create-mirrorlist' 'repo-daemon' 'daemon' 'repo-rebuild' 'rebuild' 'repo-remove-unknown' 'remove-unknown' 'repo-report' 'report' 'repo-restore' 'repo-sign' 'sign' 'repo-status-update' 'repo-sync' 'sync' 'repo-tree' 'repo-triggers' 'repo-update' 'update' 'service-clean' 'clean' 'repo-clean' 'service-config' 'config' 'repo-config' 'service-config-validate' 'config-validate' 'repo-config-validate' 'service-key-import' 'key-import' 'service-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')
|
||||||
@ -110,10 +111,10 @@ _shtab_ahriman_pos_0_nargs=A...
|
|||||||
_shtab_ahriman__h_nargs=0
|
_shtab_ahriman__h_nargs=0
|
||||||
_shtab_ahriman___help_nargs=0
|
_shtab_ahriman___help_nargs=0
|
||||||
_shtab_ahriman___force_nargs=0
|
_shtab_ahriman___force_nargs=0
|
||||||
_shtab_ahriman___report_nargs=0
|
|
||||||
_shtab_ahriman___no_report_nargs=0
|
|
||||||
_shtab_ahriman__q_nargs=0
|
_shtab_ahriman__q_nargs=0
|
||||||
_shtab_ahriman___quiet_nargs=0
|
_shtab_ahriman___quiet_nargs=0
|
||||||
|
_shtab_ahriman___report_nargs=0
|
||||||
|
_shtab_ahriman___no_report_nargs=0
|
||||||
_shtab_ahriman___unsafe_nargs=0
|
_shtab_ahriman___unsafe_nargs=0
|
||||||
_shtab_ahriman__V_nargs=0
|
_shtab_ahriman__V_nargs=0
|
||||||
_shtab_ahriman___version_nargs=0
|
_shtab_ahriman___version_nargs=0
|
||||||
@ -473,6 +474,8 @@ _shtab_ahriman_shell__h_nargs=0
|
|||||||
_shtab_ahriman_shell___help_nargs=0
|
_shtab_ahriman_shell___help_nargs=0
|
||||||
_shtab_ahriman_shell__v_nargs=0
|
_shtab_ahriman_shell__v_nargs=0
|
||||||
_shtab_ahriman_shell___verbose_nargs=0
|
_shtab_ahriman_shell___verbose_nargs=0
|
||||||
|
_shtab_ahriman_service_tree_migrate__h_nargs=0
|
||||||
|
_shtab_ahriman_service_tree_migrate___help_nargs=0
|
||||||
_shtab_ahriman_user_add__h_nargs=0
|
_shtab_ahriman_user_add__h_nargs=0
|
||||||
_shtab_ahriman_user_add___help_nargs=0
|
_shtab_ahriman_user_add___help_nargs=0
|
||||||
_shtab_ahriman_user_list__h_nargs=0
|
_shtab_ahriman_user_list__h_nargs=0
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
.TH AHRIMAN "1" "2023\-09\-01" "ahriman" "Generated Python Manual"
|
.TH AHRIMAN "1" "2023\-09\-02" "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}] [--report | --no-report] [-r REPOSITORY] [-q] [--unsafe] [--wait-timeout WAIT_TIMEOUT] [-V] {aur-search,search,help,help-commands-unsafe,help-updates,help-version,version,package-add,add,package-update,package-remove,remove,package-status,status,package-status-remove,package-status-update,status-update,patch-add,patch-list,patch-remove,patch-set-add,repo-backup,repo-check,check,repo-create-keyring,repo-create-mirrorlist,repo-daemon,daemon,repo-rebuild,rebuild,repo-remove-unknown,remove-unknown,repo-report,report,repo-restore,repo-sign,sign,repo-status-update,repo-sync,sync,repo-tree,repo-triggers,repo-update,update,service-clean,clean,repo-clean,service-config,config,repo-config,service-config-validate,config-validate,repo-config-validate,service-key-import,key-import,service-setup,init,repo-init,repo-setup,setup,service-shell,shell,user-add,user-list,user-remove,web} ...
|
[-h] [-a ARCHITECTURE] [-c CONFIGURATION] [--force] [-l LOCK] [--log-handler {console,syslog,journald}] [-q] [--report | --no-report] [-r REPOSITORY] [--unsafe] [--wait-timeout WAIT_TIMEOUT] [-V] {aur-search,search,help,help-commands-unsafe,help-updates,help-version,version,package-add,add,package-update,package-remove,remove,package-status,status,package-status-remove,package-status-update,status-update,patch-add,patch-list,patch-remove,patch-set-add,repo-backup,repo-check,check,repo-create-keyring,repo-create-mirrorlist,repo-daemon,daemon,repo-rebuild,rebuild,repo-remove-unknown,remove-unknown,repo-report,report,repo-restore,repo-sign,sign,repo-status-update,repo-sync,sync,repo-tree,repo-triggers,repo-update,update,service-clean,clean,repo-clean,service-config,config,repo-config,service-config-validate,config-validate,repo-config-validate,service-key-import,key-import,service-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
|
||||||
|
|
||||||
@ -28,6 +28,10 @@ lock file
|
|||||||
\fB\-\-log\-handler\fR \fI\,{console,syslog,journald}\/\fR
|
\fB\-\-log\-handler\fR \fI\,{console,syslog,journald}\/\fR
|
||||||
explicit log handler specification. If none set, the handler will be guessed from environment
|
explicit log handler specification. If none set, the handler will be guessed from environment
|
||||||
|
|
||||||
|
.TP
|
||||||
|
\fB\-q\fR, \fB\-\-quiet\fR
|
||||||
|
force disable any logging
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-report\fR, \fB\-\-no\-report\fR
|
\fB\-\-report\fR, \fB\-\-no\-report\fR
|
||||||
force enable or disable reporting to web service
|
force enable or disable reporting to web service
|
||||||
@ -36,10 +40,6 @@ force enable or disable reporting to web service
|
|||||||
\fB\-r\fR \fI\,REPOSITORY\/\fR, \fB\-\-repository\fR \fI\,REPOSITORY\/\fR
|
\fB\-r\fR \fI\,REPOSITORY\/\fR, \fB\-\-repository\fR \fI\,REPOSITORY\/\fR
|
||||||
target repository. For several subcommands it can be used multiple times
|
target repository. For several subcommands it can be used multiple times
|
||||||
|
|
||||||
.TP
|
|
||||||
\fB\-q\fR, \fB\-\-quiet\fR
|
|
||||||
force disable any logging
|
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-unsafe\fR
|
\fB\-\-unsafe\fR
|
||||||
allow to run ahriman as non\-ahriman user. Some actions might be unavailable
|
allow to run ahriman as non\-ahriman user. Some actions might be unavailable
|
||||||
@ -161,6 +161,9 @@ initial service configuration
|
|||||||
\fBahriman\fR \fI\,service\-shell\/\fR
|
\fBahriman\fR \fI\,service\-shell\/\fR
|
||||||
invoke python shell
|
invoke python shell
|
||||||
.TP
|
.TP
|
||||||
|
\fBahriman\fR \fI\,service\-tree\-migrate\/\fR
|
||||||
|
migrate repository tree
|
||||||
|
.TP
|
||||||
\fBahriman\fR \fI\,user\-add\/\fR
|
\fBahriman\fR \fI\,user\-add\/\fR
|
||||||
create or update user
|
create or update user
|
||||||
.TP
|
.TP
|
||||||
@ -761,6 +764,11 @@ drop into python shell
|
|||||||
\fBcode\fR
|
\fBcode\fR
|
||||||
instead of dropping into shell, just execute the specified code
|
instead of dropping into shell, just execute the specified code
|
||||||
|
|
||||||
|
.SH COMMAND \fI\,'ahriman service\-tree\-migrate'\/\fR
|
||||||
|
usage: ahriman service\-tree\-migrate [\-h]
|
||||||
|
|
||||||
|
migrate repository tree between versions
|
||||||
|
|
||||||
.SH COMMAND \fI\,'ahriman user\-add'\/\fR
|
.SH COMMAND \fI\,'ahriman user\-add'\/\fR
|
||||||
usage: ahriman user\-add [\-h] [\-\-key KEY] [\-\-packager PACKAGER] [\-p PASSWORD] [\-R {unauthorized,read,reporter,full}]
|
usage: ahriman user\-add [\-h] [\-\-key KEY] [\-\-packager PACKAGER] [\-p PASSWORD] [\-R {unauthorized,read,reporter,full}]
|
||||||
username
|
username
|
||||||
|
@ -59,6 +59,7 @@ _shtab_ahriman_commands() {
|
|||||||
"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-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"
|
||||||
"setup:create initial service configuration, requires root"
|
"setup:create initial service configuration, requires root"
|
||||||
"shell:drop into python shell"
|
"shell:drop into python shell"
|
||||||
"sign:(re-)sign packages and repository database according to current settings"
|
"sign:(re-)sign packages and repository database according to current settings"
|
||||||
@ -82,9 +83,9 @@ _shtab_ahriman_options=(
|
|||||||
"--force[force run, remove file lock (default\: False)]"
|
"--force[force run, remove file lock (default\: False)]"
|
||||||
{-l,--lock}"[lock file (default\: \/tmp\/ahriman.lock)]:lock:"
|
{-l,--lock}"[lock file (default\: \/tmp\/ahriman.lock)]:lock:"
|
||||||
"--log-handler[explicit log handler specification. If none set, the handler will be guessed from environment (default\: None)]:log_handler:(console syslog journald)"
|
"--log-handler[explicit log handler specification. If none set, the handler will be guessed from environment (default\: None)]:log_handler:(console syslog journald)"
|
||||||
|
{-q,--quiet}"[force disable any logging (default\: False)]"
|
||||||
{--report,--no-report}"[force enable or disable reporting to web service (default\: True)]:report:"
|
{--report,--no-report}"[force enable or disable reporting to web service (default\: True)]:report:"
|
||||||
"*"{-r,--repository}"[target repository. For several subcommands it can be used multiple times (default\: None)]:repository:"
|
"*"{-r,--repository}"[target repository. For several subcommands it can be used multiple times (default\: None)]:repository:"
|
||||||
{-q,--quiet}"[force disable any logging (default\: False)]"
|
|
||||||
"--unsafe[allow to run ahriman as non-ahriman user. Some actions might be unavailable (default\: False)]"
|
"--unsafe[allow to run ahriman as non-ahriman user. Some actions might be unavailable (default\: False)]"
|
||||||
"--wait-timeout[wait for lock to be free. Negative value will lead to immediate application run even if there is lock file. In case of zero value, the application will wait infinitely (default\: -1)]:wait_timeout:"
|
"--wait-timeout[wait for lock to be free. Negative value will lead to immediate application run even if there is lock file. In case of zero value, the application will wait infinitely (default\: -1)]:wait_timeout:"
|
||||||
"(- : *)"{-V,--version}"[show program\'s version number and exit]"
|
"(- : *)"{-V,--version}"[show program\'s version number and exit]"
|
||||||
@ -491,6 +492,10 @@ _shtab_ahriman_service_shell_options=(
|
|||||||
":instead of dropping into shell, just execute the specified code (default\: None):"
|
":instead of dropping into shell, just execute the specified code (default\: None):"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
_shtab_ahriman_service_tree_migrate_options=(
|
||||||
|
"(- : *)"{-h,--help}"[show this help message and exit]"
|
||||||
|
)
|
||||||
|
|
||||||
_shtab_ahriman_setup_options=(
|
_shtab_ahriman_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:"
|
||||||
@ -649,6 +654,7 @@ _shtab_ahriman() {
|
|||||||
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-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 ;;
|
||||||
setup) _arguments -C -s $_shtab_ahriman_setup_options ;;
|
setup) _arguments -C -s $_shtab_ahriman_setup_options ;;
|
||||||
shell) _arguments -C -s $_shtab_ahriman_shell_options ;;
|
shell) _arguments -C -s $_shtab_ahriman_shell_options ;;
|
||||||
sign) _arguments -C -s $_shtab_ahriman_sign_options ;;
|
sign) _arguments -C -s $_shtab_ahriman_sign_options ;;
|
||||||
|
@ -79,6 +79,7 @@ def _parser() -> argparse.ArgumentParser:
|
|||||||
parser.add_argument("--log-handler", help="explicit log handler specification. If none set, the handler will be "
|
parser.add_argument("--log-handler", help="explicit log handler specification. If none set, the handler will be "
|
||||||
"guessed from environment",
|
"guessed from environment",
|
||||||
type=LogHandler, choices=enum_values(LogHandler))
|
type=LogHandler, choices=enum_values(LogHandler))
|
||||||
|
parser.add_argument("-q", "--quiet", help="force disable any logging", action="store_true")
|
||||||
parser.add_argument("--report", help="force enable or disable reporting to web service",
|
parser.add_argument("--report", help="force enable or disable reporting to web service",
|
||||||
action=argparse.BooleanOptionalAction, default=True)
|
action=argparse.BooleanOptionalAction, default=True)
|
||||||
parser.add_argument("-r", "--repository", help="target repository. For several subcommands it can be used "
|
parser.add_argument("-r", "--repository", help="target repository. For several subcommands it can be used "
|
||||||
@ -86,7 +87,6 @@ def _parser() -> argparse.ArgumentParser:
|
|||||||
# special secret argument for systemd unit. The issue is that systemd doesn't allow multiple arguments to template
|
# special secret argument for systemd unit. The issue is that systemd doesn't allow multiple arguments to template
|
||||||
# name. This parameter accepts [[arch]-repo] in order to keep backward compatibility
|
# name. This parameter accepts [[arch]-repo] in order to keep backward compatibility
|
||||||
parser.add_argument("--repository-id", help=argparse.SUPPRESS)
|
parser.add_argument("--repository-id", help=argparse.SUPPRESS)
|
||||||
parser.add_argument("-q", "--quiet", help="force disable any logging", action="store_true")
|
|
||||||
parser.add_argument("--unsafe", help="allow to run ahriman as non-ahriman user. Some actions might be unavailable",
|
parser.add_argument("--unsafe", help="allow to run ahriman as non-ahriman user. Some actions might be unavailable",
|
||||||
action="store_true")
|
action="store_true")
|
||||||
parser.add_argument("--wait-timeout", help="wait for lock to be free. Negative value will lead to "
|
parser.add_argument("--wait-timeout", help="wait for lock to be free. Negative value will lead to "
|
||||||
@ -132,6 +132,7 @@ def _parser() -> argparse.ArgumentParser:
|
|||||||
_set_service_key_import_parser(subparsers)
|
_set_service_key_import_parser(subparsers)
|
||||||
_set_service_setup_parser(subparsers)
|
_set_service_setup_parser(subparsers)
|
||||||
_set_service_shell_parser(subparsers)
|
_set_service_shell_parser(subparsers)
|
||||||
|
_set_service_tree_migrate_parser(subparsers)
|
||||||
_set_user_add_parser(subparsers)
|
_set_user_add_parser(subparsers)
|
||||||
_set_user_list_parser(subparsers)
|
_set_user_list_parser(subparsers)
|
||||||
_set_user_remove_parser(subparsers)
|
_set_user_remove_parser(subparsers)
|
||||||
@ -160,8 +161,8 @@ def _set_aur_search_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
|||||||
parser.add_argument("--sort-by", help="sort field by this field. In case if two packages have the same value of "
|
parser.add_argument("--sort-by", help="sort field by this field. In case if two packages have the same value of "
|
||||||
"the specified field, they will be always sorted by name",
|
"the specified field, they will be always sorted by name",
|
||||||
default="name", choices=sorted(handlers.Search.SORT_FIELDS))
|
default="name", choices=sorted(handlers.Search.SORT_FIELDS))
|
||||||
parser.set_defaults(handler=handlers.Search, architecture=[""], lock=None, report=False, repository=[""],
|
parser.set_defaults(handler=handlers.Search, architecture=[""], lock=None, quiet=True, report=False,
|
||||||
quiet=True, unsafe=True)
|
repository=[""], unsafe=True)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
@ -179,7 +180,7 @@ def _set_help_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
|||||||
description="show help message for application or command and exit",
|
description="show help message for application or command and exit",
|
||||||
formatter_class=_formatter)
|
formatter_class=_formatter)
|
||||||
parser.add_argument("command", help="show help message for specific command", nargs="?")
|
parser.add_argument("command", help="show help message for specific command", nargs="?")
|
||||||
parser.set_defaults(handler=handlers.Help, architecture=[""], lock=None, report=False, repository=[""], quiet=True,
|
parser.set_defaults(handler=handlers.Help, architecture=[""], lock=None, quiet=True, report=False, repository=[""],
|
||||||
unsafe=True, parser=_parser)
|
unsafe=True, parser=_parser)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
@ -198,8 +199,8 @@ def _set_help_commands_unsafe_parser(root: SubParserAction) -> argparse.Argument
|
|||||||
description="list unsafe commands as defined in default args", formatter_class=_formatter)
|
description="list unsafe commands as defined in default args", formatter_class=_formatter)
|
||||||
parser.add_argument("command", help="instead of showing commands, just test command line for unsafe subcommand "
|
parser.add_argument("command", help="instead of showing commands, just test command line for unsafe subcommand "
|
||||||
"and return 0 in case if command is safe and 1 otherwise", nargs="*")
|
"and return 0 in case if command is safe and 1 otherwise", nargs="*")
|
||||||
parser.set_defaults(handler=handlers.UnsafeCommands, architecture=[""], lock=None, report=False, repository=[""],
|
parser.set_defaults(handler=handlers.UnsafeCommands, architecture=[""], lock=None, quiet=True, report=False,
|
||||||
quiet=True, unsafe=True, parser=_parser)
|
repository=[""], unsafe=True, parser=_parser)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
@ -217,8 +218,8 @@ def _set_help_updates_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
|||||||
description="request AUR for current version and compare with current service version",
|
description="request AUR for current version and compare with current service version",
|
||||||
formatter_class=_formatter)
|
formatter_class=_formatter)
|
||||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit code if updates available", action="store_true")
|
parser.add_argument("-e", "--exit-code", help="return non-zero exit code if updates available", action="store_true")
|
||||||
parser.set_defaults(handler=handlers.ServiceUpdates, architecture=[""], lock=None, report=False, repository=[""],
|
parser.set_defaults(handler=handlers.ServiceUpdates, architecture=[""], lock=None, quiet=True, report=False,
|
||||||
quiet=True, unsafe=True)
|
repository=[""], unsafe=True)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
@ -234,8 +235,8 @@ def _set_help_version_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
|||||||
"""
|
"""
|
||||||
parser = root.add_parser("help-version", aliases=["version"], help="application version",
|
parser = root.add_parser("help-version", aliases=["version"], help="application version",
|
||||||
description="print application and its dependencies versions", formatter_class=_formatter)
|
description="print application and its dependencies versions", formatter_class=_formatter)
|
||||||
parser.set_defaults(handler=handlers.Versions, architecture=[""], lock=None, report=False, repository=[""],
|
parser.set_defaults(handler=handlers.Versions, architecture=[""], lock=None, quiet=True, report=False,
|
||||||
quiet=True, unsafe=True)
|
repository=[""], unsafe=True)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
@ -317,7 +318,7 @@ def _set_package_status_parser(root: SubParserAction) -> argparse.ArgumentParser
|
|||||||
action=argparse.BooleanOptionalAction, default=False)
|
action=argparse.BooleanOptionalAction, default=False)
|
||||||
parser.add_argument("-s", "--status", help="filter packages by status",
|
parser.add_argument("-s", "--status", help="filter packages by status",
|
||||||
type=BuildStatusEnum, choices=enum_values(BuildStatusEnum))
|
type=BuildStatusEnum, choices=enum_values(BuildStatusEnum))
|
||||||
parser.set_defaults(handler=handlers.Status, lock=None, report=False, quiet=True, unsafe=True)
|
parser.set_defaults(handler=handlers.Status, lock=None, quiet=True, report=False, unsafe=True)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
@ -337,7 +338,7 @@ def _set_package_status_remove_parser(root: SubParserAction) -> argparse.Argumen
|
|||||||
"clears the status page.",
|
"clears the status page.",
|
||||||
formatter_class=_formatter)
|
formatter_class=_formatter)
|
||||||
parser.add_argument("package", help="remove specified packages from status page", nargs="+")
|
parser.add_argument("package", help="remove specified packages from status page", nargs="+")
|
||||||
parser.set_defaults(handler=handlers.StatusUpdate, action=Action.Remove, lock=None, report=False, quiet=True,
|
parser.set_defaults(handler=handlers.StatusUpdate, action=Action.Remove, lock=None, quiet=True, report=False,
|
||||||
unsafe=True)
|
unsafe=True)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
@ -359,7 +360,7 @@ def _set_package_status_update_parser(root: SubParserAction) -> argparse.Argumen
|
|||||||
nargs="*")
|
nargs="*")
|
||||||
parser.add_argument("-s", "--status", help="new package build status",
|
parser.add_argument("-s", "--status", help="new package build status",
|
||||||
type=BuildStatusEnum, choices=enum_values(BuildStatusEnum), default=BuildStatusEnum.Success)
|
type=BuildStatusEnum, choices=enum_values(BuildStatusEnum), default=BuildStatusEnum.Success)
|
||||||
parser.set_defaults(handler=handlers.StatusUpdate, action=Action.Update, lock=None, report=False, quiet=True,
|
parser.set_defaults(handler=handlers.StatusUpdate, action=Action.Update, lock=None, quiet=True, report=False,
|
||||||
unsafe=True)
|
unsafe=True)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
@ -690,8 +691,8 @@ def _set_repo_status_update_parser(root: SubParserAction) -> argparse.ArgumentPa
|
|||||||
description="update repository status on the status page", formatter_class=_formatter)
|
description="update repository status on the status page", formatter_class=_formatter)
|
||||||
parser.add_argument("-s", "--status", help="new status",
|
parser.add_argument("-s", "--status", help="new status",
|
||||||
type=BuildStatusEnum, choices=enum_values(BuildStatusEnum), default=BuildStatusEnum.Success)
|
type=BuildStatusEnum, choices=enum_values(BuildStatusEnum), default=BuildStatusEnum.Success)
|
||||||
parser.set_defaults(handler=handlers.StatusUpdate, action=Action.Update, lock=None, package=[], report=False,
|
parser.set_defaults(handler=handlers.StatusUpdate, action=Action.Update, lock=None, package=[], quiet=True,
|
||||||
quiet=True, unsafe=True)
|
report=False, unsafe=True)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
@ -728,7 +729,7 @@ def _set_repo_tree_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
|||||||
formatter_class=_formatter)
|
formatter_class=_formatter)
|
||||||
parser.add_argument("-p", "--partitions", help="also divide packages by independent partitions",
|
parser.add_argument("-p", "--partitions", help="also divide packages by independent partitions",
|
||||||
type=int, default=1)
|
type=int, default=1)
|
||||||
parser.set_defaults(handler=handlers.Structure, lock=None, report=False, quiet=True, unsafe=True)
|
parser.set_defaults(handler=handlers.Structure, lock=None, quiet=True, report=False, unsafe=True)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
@ -831,7 +832,7 @@ def _set_service_config_parser(root: SubParserAction) -> argparse.ArgumentParser
|
|||||||
formatter_class=_formatter)
|
formatter_class=_formatter)
|
||||||
parser.add_argument("--secure", help="hide passwords and secrets from output",
|
parser.add_argument("--secure", help="hide passwords and secrets from output",
|
||||||
action=argparse.BooleanOptionalAction, default=True)
|
action=argparse.BooleanOptionalAction, default=True)
|
||||||
parser.set_defaults(handler=handlers.Dump, lock=None, report=False, quiet=True, unsafe=True)
|
parser.set_defaults(handler=handlers.Dump, lock=None, quiet=True, report=False, unsafe=True)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
@ -851,7 +852,7 @@ def _set_service_config_validate_parser(root: SubParserAction) -> argparse.Argum
|
|||||||
formatter_class=_formatter)
|
formatter_class=_formatter)
|
||||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if configuration is invalid",
|
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if configuration is invalid",
|
||||||
action="store_true")
|
action="store_true")
|
||||||
parser.set_defaults(handler=handlers.Validate, lock=None, report=False, quiet=True, unsafe=True)
|
parser.set_defaults(handler=handlers.Validate, lock=None, quiet=True, report=False, unsafe=True)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
@ -910,7 +911,7 @@ def _set_service_setup_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
|||||||
type=SignSettings.from_option, choices=enum_values(SignSettings))
|
type=SignSettings.from_option, choices=enum_values(SignSettings))
|
||||||
parser.add_argument("--web-port", help="port of the web service", type=int)
|
parser.add_argument("--web-port", help="port of the web service", type=int)
|
||||||
parser.add_argument("--web-unix-socket", help="path to unix socket used for interprocess communications", type=Path)
|
parser.add_argument("--web-unix-socket", help="path to unix socket used for interprocess communications", type=Path)
|
||||||
parser.set_defaults(handler=handlers.Setup, lock=None, report=False, quiet=True, unsafe=True)
|
parser.set_defaults(handler=handlers.Setup, lock=None, quiet=True, report=False, unsafe=True)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
@ -932,6 +933,22 @@ def _set_service_shell_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
|||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
|
def _set_service_tree_migrate_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
|
"""
|
||||||
|
add parser for tree migration subcommand
|
||||||
|
|
||||||
|
Args:
|
||||||
|
root(SubParserAction): subparsers for the commands
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
argparse.ArgumentParser: created argument parser
|
||||||
|
"""
|
||||||
|
parser = root.add_parser("service-tree-migrate", help="migrate repository tree",
|
||||||
|
description="migrate repository tree between versions", formatter_class=_formatter)
|
||||||
|
parser.set_defaults(handler=handlers.TreeMigrate, lock=None, quiet=True, report=False)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
|
||||||
def _set_user_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
def _set_user_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
"""
|
"""
|
||||||
add parser for create user subcommand
|
add parser for create user subcommand
|
||||||
@ -954,8 +971,8 @@ def _set_user_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
|||||||
"which is in particular must be used for OAuth2 authorization type.")
|
"which is in particular must be used for OAuth2 authorization type.")
|
||||||
parser.add_argument("-R", "--role", help="user access level",
|
parser.add_argument("-R", "--role", help="user access level",
|
||||||
type=UserAccess, choices=enum_values(UserAccess), default=UserAccess.Read)
|
type=UserAccess, choices=enum_values(UserAccess), default=UserAccess.Read)
|
||||||
parser.set_defaults(handler=handlers.Users, action=Action.Update, architecture=[""], lock=None, report=False,
|
parser.set_defaults(handler=handlers.Users, action=Action.Update, architecture=[""], lock=None, quiet=True,
|
||||||
repository=[""], quiet=True)
|
report=False, repository=[""])
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
@ -975,8 +992,8 @@ def _set_user_list_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
|||||||
parser.add_argument("username", help="filter users by username", nargs="?")
|
parser.add_argument("username", help="filter users by username", nargs="?")
|
||||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty", action="store_true")
|
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty", action="store_true")
|
||||||
parser.add_argument("-R", "--role", help="filter users by role", type=UserAccess, choices=enum_values(UserAccess))
|
parser.add_argument("-R", "--role", help="filter users by role", type=UserAccess, choices=enum_values(UserAccess))
|
||||||
parser.set_defaults(handler=handlers.Users, action=Action.List, architecture=[""], lock=None, report=False,
|
parser.set_defaults(handler=handlers.Users, action=Action.List, architecture=[""], lock=None, quiet=True,
|
||||||
repository=[""], quiet=True, unsafe=True)
|
report=False, repository=[""], unsafe=True)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
@ -994,8 +1011,8 @@ def _set_user_remove_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
|||||||
description="remove user from the user mapping and update the configuration",
|
description="remove user from the user mapping and update the configuration",
|
||||||
formatter_class=_formatter)
|
formatter_class=_formatter)
|
||||||
parser.add_argument("username", help="username for web service")
|
parser.add_argument("username", help="username for web service")
|
||||||
parser.set_defaults(handler=handlers.Users, action=Action.Remove, architecture=[""], lock=None, report=False,
|
parser.set_defaults(handler=handlers.Users, action=Action.Remove, architecture=[""], lock=None, quiet=True,
|
||||||
repository=[""], quiet=True)
|
report=False, repository=[""])
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@ from ahriman.application.handlers.sign import Sign
|
|||||||
from ahriman.application.handlers.status import Status
|
from ahriman.application.handlers.status import Status
|
||||||
from ahriman.application.handlers.status_update import StatusUpdate
|
from ahriman.application.handlers.status_update import StatusUpdate
|
||||||
from ahriman.application.handlers.structure import Structure
|
from ahriman.application.handlers.structure import Structure
|
||||||
|
from ahriman.application.handlers.tree_migrate import TreeMigrate
|
||||||
from ahriman.application.handlers.triggers import Triggers
|
from ahriman.application.handlers.triggers import Triggers
|
||||||
from ahriman.application.handlers.unsafe_commands import UnsafeCommands
|
from ahriman.application.handlers.unsafe_commands import UnsafeCommands
|
||||||
from ahriman.application.handlers.update import Update
|
from ahriman.application.handlers.update import Update
|
||||||
|
@ -25,7 +25,7 @@ from multiprocessing import Pool
|
|||||||
from ahriman.application.lock import Lock
|
from ahriman.application.lock import Lock
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.exceptions import ExitCode, MissingArchitectureError, MultipleArchitecturesError
|
from ahriman.core.exceptions import ExitCode, MissingArchitectureError, MultipleArchitecturesError
|
||||||
from ahriman.core.log import Log
|
from ahriman.core.log.log_loader import LogLoader
|
||||||
from ahriman.models.repository_id import RepositoryId
|
from ahriman.models.repository_id import RepositoryId
|
||||||
from ahriman.models.repository_paths import RepositoryPaths
|
from ahriman.models.repository_paths import RepositoryPaths
|
||||||
|
|
||||||
@ -63,8 +63,8 @@ class Handler:
|
|||||||
try:
|
try:
|
||||||
configuration = Configuration.from_path(args.configuration, repository_id)
|
configuration = Configuration.from_path(args.configuration, repository_id)
|
||||||
|
|
||||||
log_handler = Log.handler(args.log_handler)
|
log_handler = LogLoader.handler(args.log_handler)
|
||||||
Log.load(configuration, log_handler, quiet=args.quiet, report=args.report)
|
LogLoader.load(configuration, log_handler, quiet=args.quiet, report=args.report)
|
||||||
|
|
||||||
with Lock(args, repository_id, configuration):
|
with Lock(args, repository_id, configuration):
|
||||||
cls.run(args, repository_id, configuration, report=args.report)
|
cls.run(args, repository_id, configuration, report=args.report)
|
||||||
|
68
src/ahriman/application/handlers/tree_migrate.py
Normal file
68
src/ahriman/application/handlers/tree_migrate.py
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2021-2023 ahriman team.
|
||||||
|
#
|
||||||
|
# This file is part of ahriman
|
||||||
|
# (see https://github.com/arcan1s/ahriman).
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
from ahriman.application.handlers import Handler
|
||||||
|
from ahriman.core.configuration import Configuration
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
from ahriman.models.repository_paths import RepositoryPaths
|
||||||
|
|
||||||
|
|
||||||
|
class TreeMigrate(Handler):
|
||||||
|
"""
|
||||||
|
tree migration handler
|
||||||
|
"""
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
|
report: bool) -> None:
|
||||||
|
"""
|
||||||
|
callback for command line
|
||||||
|
|
||||||
|
Args:
|
||||||
|
args(argparse.Namespace): command line args
|
||||||
|
repository_id(RepositoryId): repository unique identifier
|
||||||
|
configuration(Configuration): configuration instance
|
||||||
|
report(bool): force enable or disable reporting
|
||||||
|
"""
|
||||||
|
current_tree = configuration.repository_paths
|
||||||
|
target_tree = RepositoryPaths(current_tree.root, current_tree.repository_id, _force_current_tree=True)
|
||||||
|
|
||||||
|
# create repository tree
|
||||||
|
target_tree.tree_create()
|
||||||
|
# perform migration
|
||||||
|
TreeMigrate.tree_move(current_tree, target_tree)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def tree_move(from_tree: RepositoryPaths, to_tree: RepositoryPaths) -> None:
|
||||||
|
"""
|
||||||
|
move files between trees. Trees must be created in advance
|
||||||
|
|
||||||
|
Args:
|
||||||
|
from_tree(RepositoryPaths): old repository tree
|
||||||
|
to_tree(RepositoryPaths): new repository tree
|
||||||
|
"""
|
||||||
|
# we don't care about devtools chroot
|
||||||
|
for attribute in (
|
||||||
|
RepositoryPaths.packages,
|
||||||
|
RepositoryPaths.pacman,
|
||||||
|
RepositoryPaths.repository,
|
||||||
|
):
|
||||||
|
attribute.fget(from_tree).rename(attribute.fget(to_tree)) # type: ignore[attr-defined]
|
@ -115,6 +115,7 @@ class Pacman(LazyLogging):
|
|||||||
dst = repository_database(pacman_db_path)
|
dst = repository_database(pacman_db_path)
|
||||||
if dst.is_file():
|
if dst.is_file():
|
||||||
return # file already exists, do not copy
|
return # file already exists, do not copy
|
||||||
|
dst.parent.mkdir(mode=0o755, exist_ok=True) # create sync directory if it doesn't exist
|
||||||
src = repository_database(pacman_root)
|
src = repository_database(pacman_root)
|
||||||
if not src.is_file():
|
if not src.is_file():
|
||||||
self.logger.warning("repository %s is set to be used, however, no working copy was found", database.name)
|
self.logger.warning("repository %s is set to be used, however, no working copy was found", database.name)
|
||||||
|
@ -18,4 +18,3 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
from ahriman.core.log.lazy_logging import LazyLogging
|
from ahriman.core.log.lazy_logging import LazyLogging
|
||||||
from ahriman.core.log.log import Log
|
|
||||||
|
@ -27,7 +27,7 @@ from ahriman.core.log.http_log_handler import HttpLogHandler
|
|||||||
from ahriman.models.log_handler import LogHandler
|
from ahriman.models.log_handler import LogHandler
|
||||||
|
|
||||||
|
|
||||||
class Log:
|
class LogLoader:
|
||||||
"""
|
"""
|
||||||
simple static method class which setups application loggers
|
simple static method class which setups application loggers
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ class Log:
|
|||||||
del JournalHandler
|
del JournalHandler
|
||||||
return LogHandler.Journald # journald import was found
|
return LogHandler.Journald # journald import was found
|
||||||
except ImportError:
|
except ImportError:
|
||||||
if Log.DEFAULT_SYSLOG_DEVICE.exists():
|
if LogLoader.DEFAULT_SYSLOG_DEVICE.exists():
|
||||||
return LogHandler.Syslog
|
return LogHandler.Syslog
|
||||||
return LogHandler.Console
|
return LogHandler.Console
|
||||||
|
|
||||||
@ -94,7 +94,7 @@ class Log:
|
|||||||
fileConfig(log_configuration, disable_existing_loggers=True)
|
fileConfig(log_configuration, disable_existing_loggers=True)
|
||||||
logging.debug("using %s logger", default_handler)
|
logging.debug("using %s logger", default_handler)
|
||||||
except Exception:
|
except Exception:
|
||||||
logging.basicConfig(filename=None, format=Log.DEFAULT_LOG_FORMAT, level=Log.DEFAULT_LOG_LEVEL)
|
logging.basicConfig(filename=None, format=LogLoader.DEFAULT_LOG_FORMAT, level=LogLoader.DEFAULT_LOG_LEVEL)
|
||||||
logging.exception("could not load logging from configuration, fallback to stderr")
|
logging.exception("could not load logging from configuration, fallback to stderr")
|
||||||
|
|
||||||
HttpLogHandler.load(configuration, report=report)
|
HttpLogHandler.load(configuration, report=report)
|
@ -34,6 +34,16 @@ 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
|
||||||
|
|
||||||
def __lt__(self, other: Any) -> bool:
|
def __lt__(self, other: Any) -> bool:
|
||||||
"""
|
"""
|
||||||
comparison operator for sorting
|
comparison operator for sorting
|
||||||
|
@ -21,16 +21,17 @@ import os
|
|||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
from collections.abc import Generator
|
from collections.abc import Generator
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass, field
|
||||||
from functools import cached_property
|
from functools import cached_property
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from ahriman.core.exceptions import PathError
|
from ahriman.core.exceptions import PathError
|
||||||
|
from ahriman.core.log import LazyLogging
|
||||||
from ahriman.models.repository_id import RepositoryId
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class RepositoryPaths:
|
class RepositoryPaths(LazyLogging):
|
||||||
"""
|
"""
|
||||||
repository paths holder. For the most operations with paths you want to use this object
|
repository paths holder. For the most operations with paths you want to use this object
|
||||||
|
|
||||||
@ -55,6 +56,7 @@ class RepositoryPaths:
|
|||||||
|
|
||||||
root: Path
|
root: Path
|
||||||
repository_id: RepositoryId
|
repository_id: RepositoryId
|
||||||
|
_force_current_tree: bool = field(default=False, kw_only=True)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _repository_root(self) -> Path:
|
def _repository_root(self) -> Path:
|
||||||
@ -75,8 +77,10 @@ class RepositoryPaths:
|
|||||||
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 (self._repository_root / self.repository_id.architecture).is_dir():
|
if (self._repository_root / self.repository_id.architecture).is_dir():
|
||||||
return Path(self.repository_id.architecture)
|
self.logger.warning("using legacy per architecture tree")
|
||||||
|
return Path(self.repository_id.architecture) # legacy tree suffix
|
||||||
return Path(self.repository_id.name) / self.repository_id.architecture
|
return Path(self.repository_id.name) / self.repository_id.architecture
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -257,11 +261,13 @@ class RepositoryPaths:
|
|||||||
"""
|
"""
|
||||||
create ahriman working tree
|
create ahriman working tree
|
||||||
"""
|
"""
|
||||||
|
if self.repository_id.is_empty:
|
||||||
|
return # do not even try to create tree in case if no repository id set
|
||||||
for directory in (
|
for directory in (
|
||||||
self.cache,
|
self.cache,
|
||||||
self.chroot,
|
self.chroot,
|
||||||
self.packages,
|
self.packages,
|
||||||
self.pacman / "sync", # we need sync directory in order to be able to copy databases
|
self.pacman,
|
||||||
self.repository,
|
self.repository,
|
||||||
):
|
):
|
||||||
directory.mkdir(mode=0o755, parents=True, exist_ok=True)
|
directory.mkdir(mode=0o755, parents=True, exist_ok=True)
|
||||||
|
@ -21,8 +21,8 @@ def test_call(args: argparse.Namespace, configuration: Configuration, mocker: Mo
|
|||||||
args.report = False
|
args.report = False
|
||||||
mocker.patch("ahriman.application.handlers.Handler.run")
|
mocker.patch("ahriman.application.handlers.Handler.run")
|
||||||
configuration_mock = mocker.patch("ahriman.core.configuration.Configuration.from_path", return_value=configuration)
|
configuration_mock = mocker.patch("ahriman.core.configuration.Configuration.from_path", return_value=configuration)
|
||||||
log_handler_mock = mocker.patch("ahriman.core.log.Log.handler", return_value=args.log_handler)
|
log_handler_mock = mocker.patch("ahriman.core.log.log_loader.LogLoader.handler", return_value=args.log_handler)
|
||||||
log_load_mock = mocker.patch("ahriman.core.log.Log.load")
|
log_load_mock = mocker.patch("ahriman.core.log.log_loader.LogLoader.load")
|
||||||
enter_mock = mocker.patch("ahriman.application.lock.Lock.__enter__")
|
enter_mock = mocker.patch("ahriman.application.lock.Lock.__enter__")
|
||||||
exit_mock = mocker.patch("ahriman.application.lock.Lock.__exit__")
|
exit_mock = mocker.patch("ahriman.application.lock.Lock.__exit__")
|
||||||
|
|
||||||
|
@ -0,0 +1,42 @@
|
|||||||
|
import argparse
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
from pytest_mock import MockerFixture
|
||||||
|
from unittest.mock import call as MockCall
|
||||||
|
|
||||||
|
from ahriman.application.handlers import TreeMigrate
|
||||||
|
from ahriman.core.configuration import Configuration
|
||||||
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
from ahriman.models.repository_paths import RepositoryPaths
|
||||||
|
|
||||||
|
|
||||||
|
def test_run(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must run command
|
||||||
|
"""
|
||||||
|
tree_create_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.tree_create")
|
||||||
|
application_mock = mocker.patch("ahriman.application.handlers.TreeMigrate.tree_move")
|
||||||
|
_, repository_id = configuration.check_loaded()
|
||||||
|
old_paths = configuration.repository_paths
|
||||||
|
new_paths = RepositoryPaths(old_paths.root, old_paths.repository_id, _force_current_tree=True)
|
||||||
|
|
||||||
|
TreeMigrate.run(args, repository_id, configuration, report=False)
|
||||||
|
tree_create_mock.assert_called_once_with()
|
||||||
|
application_mock.assert_called_once_with(old_paths, new_paths)
|
||||||
|
|
||||||
|
|
||||||
|
def test_move_tree(mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must move tree
|
||||||
|
"""
|
||||||
|
rename_mock = mocker.patch("pathlib.Path.rename", autospec=True)
|
||||||
|
root = Path("local")
|
||||||
|
from_paths = RepositoryPaths(root, RepositoryId("arch", ""))
|
||||||
|
to_paths = RepositoryPaths(root, RepositoryId("arch", "repo"))
|
||||||
|
|
||||||
|
TreeMigrate.tree_move(from_paths, to_paths)
|
||||||
|
rename_mock.assert_has_calls([
|
||||||
|
MockCall(from_paths.packages, to_paths.packages),
|
||||||
|
MockCall(from_paths.pacman, to_paths.pacman),
|
||||||
|
MockCall(from_paths.repository, to_paths.repository),
|
||||||
|
])
|
@ -93,14 +93,14 @@ def test_parser_option_repository_multiple(parser: argparse.ArgumentParser) -> N
|
|||||||
|
|
||||||
def test_subparsers_aur_search(parser: argparse.ArgumentParser) -> None:
|
def test_subparsers_aur_search(parser: argparse.ArgumentParser) -> None:
|
||||||
"""
|
"""
|
||||||
aur-search command must imply architecture list, lock, report, repository, quiet and unsafe
|
aur-search command must imply architecture list, lock, quiet, report, repository and unsafe
|
||||||
"""
|
"""
|
||||||
args = parser.parse_args(["aur-search", "ahriman"])
|
args = parser.parse_args(["aur-search", "ahriman"])
|
||||||
assert args.architecture == [""]
|
assert args.architecture == [""]
|
||||||
assert args.lock is None
|
assert args.lock is None
|
||||||
|
assert args.quiet
|
||||||
assert not args.report
|
assert not args.report
|
||||||
assert args.repository == [""]
|
assert args.repository == [""]
|
||||||
assert args.quiet
|
|
||||||
assert args.unsafe
|
assert args.unsafe
|
||||||
|
|
||||||
|
|
||||||
@ -122,14 +122,14 @@ def test_subparsers_aur_search_option_repository(parser: argparse.ArgumentParser
|
|||||||
|
|
||||||
def test_subparsers_help(parser: argparse.ArgumentParser) -> None:
|
def test_subparsers_help(parser: argparse.ArgumentParser) -> None:
|
||||||
"""
|
"""
|
||||||
help command must imply architecture list, lock, report, repository, quiet, unsafe and parser
|
help command must imply architecture list, lock, quiet, report, repository, unsafe and parser
|
||||||
"""
|
"""
|
||||||
args = parser.parse_args(["help"])
|
args = parser.parse_args(["help"])
|
||||||
assert args.architecture == [""]
|
assert args.architecture == [""]
|
||||||
assert args.lock is None
|
assert args.lock is None
|
||||||
|
assert args.quiet
|
||||||
assert not args.report
|
assert not args.report
|
||||||
assert args.repository == [""]
|
assert args.repository == [""]
|
||||||
assert args.quiet
|
|
||||||
assert args.unsafe
|
assert args.unsafe
|
||||||
assert args.parser is not None and args.parser()
|
assert args.parser is not None and args.parser()
|
||||||
|
|
||||||
@ -152,14 +152,14 @@ def test_subparsers_help_option_repository(parser: argparse.ArgumentParser) -> N
|
|||||||
|
|
||||||
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, report, repository, quiet, unsafe and parser
|
help-commands-unsafe command must imply architecture list, lock, quiet, report, repository, unsafe and parser
|
||||||
"""
|
"""
|
||||||
args = parser.parse_args(["help-commands-unsafe"])
|
args = parser.parse_args(["help-commands-unsafe"])
|
||||||
assert args.architecture == [""]
|
assert args.architecture == [""]
|
||||||
assert args.lock is None
|
assert args.lock is None
|
||||||
|
assert args.quiet
|
||||||
assert not args.report
|
assert not args.report
|
||||||
assert args.repository == [""]
|
assert args.repository == [""]
|
||||||
assert args.quiet
|
|
||||||
assert args.unsafe
|
assert args.unsafe
|
||||||
assert args.parser is not None and args.parser()
|
assert args.parser is not None and args.parser()
|
||||||
|
|
||||||
@ -182,14 +182,14 @@ def test_subparsers_help_commands_unsafe_option_repository(parser: argparse.Argu
|
|||||||
|
|
||||||
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, report, repository, quiet and unsafe
|
help-updates command must imply architecture list, lock, quiet, report, repository, and unsafe
|
||||||
"""
|
"""
|
||||||
args = parser.parse_args(["help-updates"])
|
args = parser.parse_args(["help-updates"])
|
||||||
assert args.architecture == [""]
|
assert args.architecture == [""]
|
||||||
assert args.lock is None
|
assert args.lock is None
|
||||||
|
assert args.quiet
|
||||||
assert not args.report
|
assert not args.report
|
||||||
assert args.repository == [""]
|
assert args.repository == [""]
|
||||||
assert args.quiet
|
|
||||||
assert args.unsafe
|
assert args.unsafe
|
||||||
|
|
||||||
|
|
||||||
@ -211,14 +211,14 @@ def test_subparsers_help_updates_option_repository(parser: argparse.ArgumentPars
|
|||||||
|
|
||||||
def test_subparsers_help_version(parser: argparse.ArgumentParser) -> None:
|
def test_subparsers_help_version(parser: argparse.ArgumentParser) -> None:
|
||||||
"""
|
"""
|
||||||
help-version command must imply architecture, lock, report, repository, quiet and unsafe
|
help-version command must imply architecture, lock, quiet, report, repository and unsafe
|
||||||
"""
|
"""
|
||||||
args = parser.parse_args(["help-version"])
|
args = parser.parse_args(["help-version"])
|
||||||
assert args.architecture == [""]
|
assert args.architecture == [""]
|
||||||
assert args.lock is None
|
assert args.lock is None
|
||||||
|
assert args.quiet
|
||||||
assert not args.report
|
assert not args.report
|
||||||
assert args.repository == [""]
|
assert args.repository == [""]
|
||||||
assert args.quiet
|
|
||||||
assert args.unsafe
|
assert args.unsafe
|
||||||
|
|
||||||
|
|
||||||
@ -292,42 +292,42 @@ def test_subparsers_package_remove_option_repository(parser: argparse.ArgumentPa
|
|||||||
|
|
||||||
def test_subparsers_package_status(parser: argparse.ArgumentParser) -> None:
|
def test_subparsers_package_status(parser: argparse.ArgumentParser) -> None:
|
||||||
"""
|
"""
|
||||||
package-status command must imply lock, report, quiet and unsafe
|
package-status command must imply lock, quiet, report and unsafe
|
||||||
"""
|
"""
|
||||||
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "package-status"])
|
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "package-status"])
|
||||||
assert args.architecture == ["x86_64"]
|
assert args.architecture == ["x86_64"]
|
||||||
assert args.lock is None
|
assert args.lock is None
|
||||||
|
assert args.quiet
|
||||||
assert not args.report
|
assert not args.report
|
||||||
assert args.repository == ["repo"]
|
assert args.repository == ["repo"]
|
||||||
assert args.quiet
|
|
||||||
assert args.unsafe
|
assert args.unsafe
|
||||||
|
|
||||||
|
|
||||||
def test_subparsers_package_status_remove(parser: argparse.ArgumentParser) -> None:
|
def test_subparsers_package_status_remove(parser: argparse.ArgumentParser) -> None:
|
||||||
"""
|
"""
|
||||||
package-status-remove command must imply action, lock, report, quiet and unsafe
|
package-status-remove command must imply action, lock, quiet, report and unsafe
|
||||||
"""
|
"""
|
||||||
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "package-status-remove", "ahriman"])
|
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "package-status-remove", "ahriman"])
|
||||||
assert args.architecture == ["x86_64"]
|
assert args.architecture == ["x86_64"]
|
||||||
assert args.action == Action.Remove
|
assert args.action == Action.Remove
|
||||||
assert args.lock is None
|
assert args.lock is None
|
||||||
|
assert args.quiet
|
||||||
assert not args.report
|
assert not args.report
|
||||||
assert args.repository == ["repo"]
|
assert args.repository == ["repo"]
|
||||||
assert args.quiet
|
|
||||||
assert args.unsafe
|
assert args.unsafe
|
||||||
|
|
||||||
|
|
||||||
def test_subparsers_package_status_update(parser: argparse.ArgumentParser) -> None:
|
def test_subparsers_package_status_update(parser: argparse.ArgumentParser) -> None:
|
||||||
"""
|
"""
|
||||||
package-status-update command must imply action, lock, report, quiet and unsafe
|
package-status-update command must imply action, lock, quiet, report and unsafe
|
||||||
"""
|
"""
|
||||||
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "package-status-update"])
|
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "package-status-update"])
|
||||||
assert args.architecture == ["x86_64"]
|
assert args.architecture == ["x86_64"]
|
||||||
assert args.action == Action.Update
|
assert args.action == Action.Update
|
||||||
assert args.lock is None
|
assert args.lock is None
|
||||||
|
assert args.quiet
|
||||||
assert not args.report
|
assert not args.report
|
||||||
assert args.repository == ["repo"]
|
assert args.repository == ["repo"]
|
||||||
assert args.quiet
|
|
||||||
assert args.unsafe
|
assert args.unsafe
|
||||||
|
|
||||||
|
|
||||||
@ -805,16 +805,16 @@ def test_subparsers_repo_sign_option_repository(parser: argparse.ArgumentParser)
|
|||||||
|
|
||||||
def test_subparsers_repo_status_update(parser: argparse.ArgumentParser) -> None:
|
def test_subparsers_repo_status_update(parser: argparse.ArgumentParser) -> None:
|
||||||
"""
|
"""
|
||||||
re[p-status-update command must imply action, lock, report, package, quiet and unsafe
|
re[p-status-update command must imply action, lock, quiet, report, package and unsafe
|
||||||
"""
|
"""
|
||||||
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "package-status-update"])
|
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "package-status-update"])
|
||||||
assert args.architecture == ["x86_64"]
|
assert args.architecture == ["x86_64"]
|
||||||
assert args.action == Action.Update
|
assert args.action == Action.Update
|
||||||
assert args.lock is None
|
assert args.lock is None
|
||||||
|
assert args.quiet
|
||||||
assert not args.report
|
assert not args.report
|
||||||
assert args.repository == ["repo"]
|
assert args.repository == ["repo"]
|
||||||
assert not args.package
|
assert not args.package
|
||||||
assert args.quiet
|
|
||||||
assert args.unsafe
|
assert args.unsafe
|
||||||
|
|
||||||
|
|
||||||
@ -858,12 +858,12 @@ def test_subparsers_repo_sync_option_repository(parser: argparse.ArgumentParser)
|
|||||||
|
|
||||||
def test_subparsers_repo_tree(parser: argparse.ArgumentParser) -> None:
|
def test_subparsers_repo_tree(parser: argparse.ArgumentParser) -> None:
|
||||||
"""
|
"""
|
||||||
repo-tree command must imply lock, report, quiet and unsafe
|
repo-tree command must imply lock, quiet, report and unsafe
|
||||||
"""
|
"""
|
||||||
args = parser.parse_args(["repo-tree"])
|
args = parser.parse_args(["repo-tree"])
|
||||||
assert args.lock is None
|
assert args.lock is None
|
||||||
assert not args.report
|
|
||||||
assert args.quiet
|
assert args.quiet
|
||||||
|
assert not args.report
|
||||||
assert args.unsafe
|
assert args.unsafe
|
||||||
|
|
||||||
|
|
||||||
@ -980,27 +980,27 @@ def test_subparsers_service_clean_option_repository(parser: argparse.ArgumentPar
|
|||||||
|
|
||||||
def test_subparsers_service_config(parser: argparse.ArgumentParser) -> None:
|
def test_subparsers_service_config(parser: argparse.ArgumentParser) -> None:
|
||||||
"""
|
"""
|
||||||
service-config command must imply lock, report, quiet and unsafe
|
service-config command must imply lock, quiet, report and unsafe
|
||||||
"""
|
"""
|
||||||
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "service-config"])
|
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "service-config"])
|
||||||
assert args.architecture == ["x86_64"]
|
assert args.architecture == ["x86_64"]
|
||||||
assert args.lock is None
|
assert args.lock is None
|
||||||
|
assert args.quiet
|
||||||
assert not args.report
|
assert not args.report
|
||||||
assert args.repository == ["repo"]
|
assert args.repository == ["repo"]
|
||||||
assert args.quiet
|
|
||||||
assert args.unsafe
|
assert args.unsafe
|
||||||
|
|
||||||
|
|
||||||
def test_subparsers_service_config_validate(parser: argparse.ArgumentParser) -> None:
|
def test_subparsers_service_config_validate(parser: argparse.ArgumentParser) -> None:
|
||||||
"""
|
"""
|
||||||
service-config-validate command must imply lock, report, quiet and unsafe
|
service-config-validate command must imply lock, quiet, report and unsafe
|
||||||
"""
|
"""
|
||||||
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "service-config-validate"])
|
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "service-config-validate"])
|
||||||
assert args.architecture == ["x86_64"]
|
assert args.architecture == ["x86_64"]
|
||||||
assert args.lock is None
|
assert args.lock is None
|
||||||
|
assert args.quiet
|
||||||
assert not args.report
|
assert not args.report
|
||||||
assert args.repository == ["repo"]
|
assert args.repository == ["repo"]
|
||||||
assert args.quiet
|
|
||||||
assert args.unsafe
|
assert args.unsafe
|
||||||
|
|
||||||
|
|
||||||
@ -1033,14 +1033,14 @@ def test_subparsers_service_key_import_option_repository(parser: argparse.Argume
|
|||||||
|
|
||||||
def test_subparsers_service_setup(parser: argparse.ArgumentParser) -> None:
|
def test_subparsers_service_setup(parser: argparse.ArgumentParser) -> None:
|
||||||
"""
|
"""
|
||||||
service-setup command must imply lock, report, quiet and unsafe
|
service-setup command must imply lock, quiet, report and unsafe
|
||||||
"""
|
"""
|
||||||
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "service-setup", "--packager", "John Doe <john@doe.com>"])
|
args = parser.parse_args(["-a", "x86_64", "-r", "repo", "service-setup", "--packager", "John Doe <john@doe.com>"])
|
||||||
assert args.architecture == ["x86_64"]
|
assert args.architecture == ["x86_64"]
|
||||||
assert args.lock is None
|
assert args.lock is None
|
||||||
|
assert args.quiet
|
||||||
assert not args.report
|
assert not args.report
|
||||||
assert args.repository == ["repo"]
|
assert args.repository == ["repo"]
|
||||||
assert args.quiet
|
|
||||||
assert args.unsafe
|
assert args.unsafe
|
||||||
|
|
||||||
|
|
||||||
@ -1091,17 +1091,27 @@ def test_subparsers_service_shell(parser: argparse.ArgumentParser) -> None:
|
|||||||
assert not args.report
|
assert not args.report
|
||||||
|
|
||||||
|
|
||||||
|
def test_subparsers_service_tree_migrate(parser: argparse.ArgumentParser) -> None:
|
||||||
|
"""
|
||||||
|
service-tree-migrate command must imply lock, quiet and report
|
||||||
|
"""
|
||||||
|
args = parser.parse_args(["service-tree-migrate"])
|
||||||
|
assert args.lock is None
|
||||||
|
assert args.quiet
|
||||||
|
assert not args.report
|
||||||
|
|
||||||
|
|
||||||
def test_subparsers_user_add(parser: argparse.ArgumentParser) -> None:
|
def test_subparsers_user_add(parser: argparse.ArgumentParser) -> None:
|
||||||
"""
|
"""
|
||||||
user-add command must imply action, architecture, lock, report, repository and quiet
|
user-add command must imply action, architecture, lock, quiet, report and repository
|
||||||
"""
|
"""
|
||||||
args = parser.parse_args(["user-add", "username"])
|
args = parser.parse_args(["user-add", "username"])
|
||||||
assert args.action == Action.Update
|
assert args.action == Action.Update
|
||||||
assert args.architecture == [""]
|
assert args.architecture == [""]
|
||||||
assert args.lock is None
|
assert args.lock is None
|
||||||
|
assert args.quiet
|
||||||
assert not args.report
|
assert not args.report
|
||||||
assert args.repository == [""]
|
assert args.repository == [""]
|
||||||
assert args.quiet
|
|
||||||
|
|
||||||
|
|
||||||
def test_subparsers_user_add_option_architecture(parser: argparse.ArgumentParser) -> None:
|
def test_subparsers_user_add_option_architecture(parser: argparse.ArgumentParser) -> None:
|
||||||
@ -1132,15 +1142,15 @@ def test_subparsers_user_add_option_role(parser: argparse.ArgumentParser) -> Non
|
|||||||
|
|
||||||
def test_subparsers_user_list(parser: argparse.ArgumentParser) -> None:
|
def test_subparsers_user_list(parser: argparse.ArgumentParser) -> None:
|
||||||
"""
|
"""
|
||||||
user-list command must imply action, architecture, lock, report, repository, quiet and unsafe
|
user-list command must imply action, architecture, lock, quiet, report, repository and unsafe
|
||||||
"""
|
"""
|
||||||
args = parser.parse_args(["user-list"])
|
args = parser.parse_args(["user-list"])
|
||||||
assert args.action == Action.List
|
assert args.action == Action.List
|
||||||
assert args.architecture == [""]
|
assert args.architecture == [""]
|
||||||
assert args.lock is None
|
assert args.lock is None
|
||||||
|
assert args.quiet
|
||||||
assert not args.report
|
assert not args.report
|
||||||
assert args.repository == [""]
|
assert args.repository == [""]
|
||||||
assert args.quiet
|
|
||||||
assert args.unsafe
|
assert args.unsafe
|
||||||
|
|
||||||
|
|
||||||
@ -1170,15 +1180,15 @@ def test_subparsers_user_list_option_role(parser: argparse.ArgumentParser) -> No
|
|||||||
|
|
||||||
def test_subparsers_user_remove(parser: argparse.ArgumentParser) -> None:
|
def test_subparsers_user_remove(parser: argparse.ArgumentParser) -> None:
|
||||||
"""
|
"""
|
||||||
user-remove command must imply action, architecture, lock, report, repository and quiet
|
user-remove command must imply action, architecture, lock, quiet, report and repository
|
||||||
"""
|
"""
|
||||||
args = parser.parse_args(["user-remove", "username"])
|
args = parser.parse_args(["user-remove", "username"])
|
||||||
assert args.action == Action.Remove
|
assert args.action == Action.Remove
|
||||||
assert args.architecture == [""]
|
assert args.architecture == [""]
|
||||||
assert args.lock is None
|
assert args.lock is None
|
||||||
|
assert args.quiet
|
||||||
assert not args.report
|
assert not args.report
|
||||||
assert args.repository == [""]
|
assert args.repository == [""]
|
||||||
assert args.quiet
|
|
||||||
|
|
||||||
|
|
||||||
def test_subparsers_user_remove_option_architecture(parser: argparse.ArgumentParser) -> None:
|
def test_subparsers_user_remove_option_architecture(parser: argparse.ArgumentParser) -> None:
|
||||||
|
@ -58,10 +58,12 @@ def test_database_copy(pacman: Pacman, repository_paths: RepositoryPaths, mocker
|
|||||||
mocker.patch("pathlib.Path.is_dir", return_value=True)
|
mocker.patch("pathlib.Path.is_dir", return_value=True)
|
||||||
# root database exists, local database does not
|
# root database exists, local database does not
|
||||||
mocker.patch("pathlib.Path.is_file", autospec=True, side_effect=lambda p: p.is_relative_to(path))
|
mocker.patch("pathlib.Path.is_file", autospec=True, side_effect=lambda p: p.is_relative_to(path))
|
||||||
|
mkdir_mock = mocker.patch("pathlib.Path.mkdir")
|
||||||
copy_mock = mocker.patch("shutil.copy")
|
copy_mock = mocker.patch("shutil.copy")
|
||||||
chown_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.chown")
|
chown_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.chown")
|
||||||
|
|
||||||
pacman.database_copy(pacman.handle, database, path, repository_paths, use_ahriman_cache=True)
|
pacman.database_copy(pacman.handle, database, path, repository_paths, use_ahriman_cache=True)
|
||||||
|
mkdir_mock.assert_called_once_with(mode=0o755, exist_ok=True)
|
||||||
copy_mock.assert_called_once_with(path / "sync" / "core.db", dst_path)
|
copy_mock.assert_called_once_with(path / "sync" / "core.db", dst_path)
|
||||||
chown_mock.assert_called_once_with(dst_path)
|
chown_mock.assert_called_once_with(dst_path)
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ from pytest_mock import MockerFixture
|
|||||||
from systemd.journal import JournalHandler
|
from systemd.journal import JournalHandler
|
||||||
|
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
from ahriman.core.log import Log
|
from ahriman.core.log.log_loader import LogLoader
|
||||||
from ahriman.models.log_handler import LogHandler
|
from ahriman.models.log_handler import LogHandler
|
||||||
|
|
||||||
|
|
||||||
@ -15,14 +15,14 @@ def test_handler() -> None:
|
|||||||
"""
|
"""
|
||||||
must extract journald handler if available
|
must extract journald handler if available
|
||||||
"""
|
"""
|
||||||
assert Log.handler(None) == LogHandler.Journald
|
assert LogLoader.handler(None) == LogHandler.Journald
|
||||||
|
|
||||||
|
|
||||||
def test_handler_selected() -> None:
|
def test_handler_selected() -> None:
|
||||||
"""
|
"""
|
||||||
must return selected log handler
|
must return selected log handler
|
||||||
"""
|
"""
|
||||||
assert Log.handler(LogHandler.Console) == LogHandler.Console
|
assert LogLoader.handler(LogHandler.Console) == LogHandler.Console
|
||||||
|
|
||||||
|
|
||||||
def test_handler_syslog(mocker: MockerFixture) -> None:
|
def test_handler_syslog(mocker: MockerFixture) -> None:
|
||||||
@ -31,7 +31,7 @@ def test_handler_syslog(mocker: MockerFixture) -> None:
|
|||||||
"""
|
"""
|
||||||
mocker.patch("pathlib.Path.exists", return_value=True)
|
mocker.patch("pathlib.Path.exists", return_value=True)
|
||||||
mocker.patch.dict(sys.modules, {"systemd.journal": None})
|
mocker.patch.dict(sys.modules, {"systemd.journal": None})
|
||||||
assert Log.handler(None) == LogHandler.Syslog
|
assert LogLoader.handler(None) == LogHandler.Syslog
|
||||||
|
|
||||||
|
|
||||||
def test_handler_console(mocker: MockerFixture) -> None:
|
def test_handler_console(mocker: MockerFixture) -> None:
|
||||||
@ -40,17 +40,17 @@ def test_handler_console(mocker: MockerFixture) -> None:
|
|||||||
"""
|
"""
|
||||||
mocker.patch("pathlib.Path.exists", return_value=False)
|
mocker.patch("pathlib.Path.exists", return_value=False)
|
||||||
mocker.patch.dict(sys.modules, {"systemd.journal": None})
|
mocker.patch.dict(sys.modules, {"systemd.journal": None})
|
||||||
assert Log.handler(None) == LogHandler.Console
|
assert LogLoader.handler(None) == LogHandler.Console
|
||||||
|
|
||||||
|
|
||||||
def test_load(configuration: Configuration, mocker: MockerFixture) -> None:
|
def test_load(configuration: Configuration, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must load logging
|
must load logging
|
||||||
"""
|
"""
|
||||||
logging_mock = mocker.patch("ahriman.core.log.log.fileConfig", side_effect=fileConfig)
|
logging_mock = mocker.patch("ahriman.core.log.log_loader.fileConfig", side_effect=fileConfig)
|
||||||
http_log_mock = mocker.patch("ahriman.core.log.http_log_handler.HttpLogHandler.load")
|
http_log_mock = mocker.patch("ahriman.core.log.http_log_handler.HttpLogHandler.load")
|
||||||
|
|
||||||
Log.load(configuration, LogHandler.Journald, quiet=False, report=False)
|
LogLoader.load(configuration, LogHandler.Journald, quiet=False, report=False)
|
||||||
logging_mock.assert_called_once_with(pytest.helpers.anyvar(int), disable_existing_loggers=True)
|
logging_mock.assert_called_once_with(pytest.helpers.anyvar(int), disable_existing_loggers=True)
|
||||||
http_log_mock.assert_called_once_with(configuration, report=False)
|
http_log_mock.assert_called_once_with(configuration, report=False)
|
||||||
assert all(isinstance(handler, JournalHandler) for handler in logging.getLogger().handlers)
|
assert all(isinstance(handler, JournalHandler) for handler in logging.getLogger().handlers)
|
||||||
@ -60,8 +60,8 @@ def test_load_fallback(configuration: Configuration, mocker: MockerFixture) -> N
|
|||||||
"""
|
"""
|
||||||
must fall back to stderr without errors
|
must fall back to stderr without errors
|
||||||
"""
|
"""
|
||||||
mocker.patch("ahriman.core.log.log.fileConfig", side_effect=PermissionError())
|
mocker.patch("ahriman.core.log.log_loader.fileConfig", side_effect=PermissionError())
|
||||||
Log.load(configuration, LogHandler.Journald, quiet=False, report=False)
|
LogLoader.load(configuration, LogHandler.Journald, quiet=False, report=False)
|
||||||
|
|
||||||
|
|
||||||
def test_load_quiet(configuration: Configuration, mocker: MockerFixture) -> None:
|
def test_load_quiet(configuration: Configuration, mocker: MockerFixture) -> None:
|
||||||
@ -69,5 +69,5 @@ def test_load_quiet(configuration: Configuration, mocker: MockerFixture) -> None
|
|||||||
must disable logging in case if quiet flag set
|
must disable logging in case if quiet flag set
|
||||||
"""
|
"""
|
||||||
disable_mock = mocker.patch("logging.disable")
|
disable_mock = mocker.patch("logging.disable")
|
||||||
Log.load(configuration, LogHandler.Journald, quiet=True, report=False)
|
LogLoader.load(configuration, LogHandler.Journald, quiet=True, report=False)
|
||||||
disable_mock.assert_called_once_with(logging.WARNING)
|
disable_mock.assert_called_once_with(logging.WARNING)
|
@ -3,6 +3,16 @@ import pytest
|
|||||||
from ahriman.models.repository_id import RepositoryId
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
|
def test_is_empty() -> None:
|
||||||
|
"""
|
||||||
|
must check if repository id is empty or not
|
||||||
|
"""
|
||||||
|
assert RepositoryId("", "").is_empty
|
||||||
|
assert RepositoryId("arch", "").is_empty
|
||||||
|
assert RepositoryId("", "repo").is_empty
|
||||||
|
assert not RepositoryId("arch", "repo").is_empty
|
||||||
|
|
||||||
|
|
||||||
def test_lt() -> None:
|
def test_lt() -> None:
|
||||||
"""
|
"""
|
||||||
must correctly compare instances
|
must correctly compare instances
|
||||||
|
@ -31,12 +31,24 @@ def test_suffix(repository_id: RepositoryId, mocker: MockerFixture) -> None:
|
|||||||
"""
|
"""
|
||||||
must correctly define suffix
|
must correctly define suffix
|
||||||
"""
|
"""
|
||||||
is_dir_mock = mocker.patch("pathlib.Path.is_dir", autospec=True, return_value=True)
|
is_dir_mock = mocker.patch("pathlib.Path.is_dir", autospec=True)
|
||||||
assert RepositoryPaths(Path("root"), repository_id)._suffix == Path(repository_id.architecture)
|
|
||||||
is_dir_mock.assert_called_once_with(Path("root") / "repository" / repository_id.architecture)
|
|
||||||
|
|
||||||
mocker.patch("pathlib.Path.is_dir", return_value=False)
|
is_dir_mock.return_value = True
|
||||||
assert RepositoryPaths(Path("root"), repository_id)._suffix == Path(repository_id.name) / repository_id.architecture
|
instance = RepositoryPaths(Path("root"), repository_id)
|
||||||
|
assert instance._suffix == Path(repository_id.architecture)
|
||||||
|
|
||||||
|
is_dir_mock.return_value = False
|
||||||
|
instance = RepositoryPaths(Path("root"), repository_id)
|
||||||
|
assert instance._suffix == Path(repository_id.name) / repository_id.architecture
|
||||||
|
|
||||||
|
is_dir_mock.return_value = True
|
||||||
|
instance = RepositoryPaths(Path("root"), repository_id, _force_current_tree=True)
|
||||||
|
assert instance._suffix == Path(repository_id.name) / repository_id.architecture
|
||||||
|
|
||||||
|
is_dir_mock.assert_has_calls([
|
||||||
|
MockCall(Path("root") / "repository" / repository_id.architecture),
|
||||||
|
MockCall(Path("root") / "repository" / repository_id.architecture),
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
def test_root_owner(repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
|
def test_root_owner(repository_paths: RepositoryPaths, mocker: MockerFixture) -> None:
|
||||||
@ -270,20 +282,29 @@ def test_tree_create(repository_paths: RepositoryPaths, mocker: MockerFixture) -
|
|||||||
prop
|
prop
|
||||||
for prop in dir(repository_paths)
|
for prop in dir(repository_paths)
|
||||||
if not prop.startswith("_")
|
if not prop.startswith("_")
|
||||||
and not prop.endswith("_for")
|
and not callable(getattr(repository_paths, prop))
|
||||||
and prop not in ("chown",
|
and prop not in ("logger_name",
|
||||||
"known_architectures",
|
"logger",
|
||||||
"known_repositories",
|
|
||||||
"owner",
|
|
||||||
"repository_id",
|
"repository_id",
|
||||||
"root",
|
"root",
|
||||||
"root_owner",
|
"root_owner")
|
||||||
"tree_clear",
|
|
||||||
"tree_create")
|
|
||||||
}
|
}
|
||||||
mkdir_mock = mocker.patch("pathlib.Path.mkdir")
|
mkdir_mock = mocker.patch("pathlib.Path.mkdir")
|
||||||
chown_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.chown")
|
chown_mock = mocker.patch("ahriman.models.repository_paths.RepositoryPaths.chown")
|
||||||
|
|
||||||
|
print(paths)
|
||||||
|
|
||||||
repository_paths.tree_create()
|
repository_paths.tree_create()
|
||||||
mkdir_mock.assert_has_calls([MockCall(mode=0o755, parents=True, exist_ok=True) for _ in paths], any_order=True)
|
mkdir_mock.assert_has_calls([MockCall(mode=0o755, parents=True, exist_ok=True) for _ in paths], any_order=True)
|
||||||
chown_mock.assert_has_calls([MockCall(pytest.helpers.anyvar(int)) for _ in paths], any_order=True)
|
chown_mock.assert_has_calls([MockCall(pytest.helpers.anyvar(int)) for _ in paths], any_order=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_tree_create_skip(mocker: MockerFixture) -> None:
|
||||||
|
"""
|
||||||
|
must skip tree creation if repository id is not set
|
||||||
|
"""
|
||||||
|
mkdir_mock = mocker.patch("pathlib.Path.mkdir")
|
||||||
|
repository_paths = RepositoryPaths(Path("local"), RepositoryId("", ""))
|
||||||
|
|
||||||
|
repository_paths.tree_create()
|
||||||
|
mkdir_mock.assert_not_called()
|
||||||
|
Loading…
Reference in New Issue
Block a user