mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-08-31 13:59:56 +00:00
Compare commits
3 Commits
499efb9dbc
...
b36bcb194b
Author | SHA1 | Date | |
---|---|---|---|
b36bcb194b | |||
b167df904b | |||
cd0ac7a7bd |
2
.github/workflows/setup.sh
vendored
2
.github/workflows/setup.sh
vendored
@ -10,7 +10,7 @@ echo -e '[arcanisrepo]\nServer = https://repo.arcanis.me/$arch\nSigLevel = Never
|
|||||||
# refresh the image
|
# refresh the image
|
||||||
pacman -Syyu --noconfirm
|
pacman -Syyu --noconfirm
|
||||||
# main dependencies
|
# main dependencies
|
||||||
pacman -S --noconfirm devtools git pyalpm python-inflection python-passlib python-pyelftools python-requests python-systemd sudo
|
pacman -S --noconfirm devtools git pyalpm python-bcrypt python-inflection python-pyelftools python-requests python-systemd sudo
|
||||||
# make dependencies
|
# make dependencies
|
||||||
pacman -S --noconfirm --asdeps base-devel python-build python-flit python-installer python-tox python-wheel
|
pacman -S --noconfirm --asdeps base-devel python-build python-flit python-installer python-tox python-wheel
|
||||||
# optional dependencies
|
# optional dependencies
|
||||||
|
@ -35,8 +35,8 @@ RUN pacman -S --noconfirm --asdeps \
|
|||||||
devtools \
|
devtools \
|
||||||
git \
|
git \
|
||||||
pyalpm \
|
pyalpm \
|
||||||
|
python-bcrypt \
|
||||||
python-inflection \
|
python-inflection \
|
||||||
python-passlib \
|
|
||||||
python-pyelftools \
|
python-pyelftools \
|
||||||
python-requests \
|
python-requests \
|
||||||
&& \
|
&& \
|
||||||
|
@ -147,7 +147,7 @@ There are multiple subdirectories, some of them are commons for any repository,
|
|||||||
* ``pacman/{repository}/{architecture}`` is the repository and architecture specific caches for pacman's databases.
|
* ``pacman/{repository}/{architecture}`` is the repository and architecture specific caches for pacman's databases.
|
||||||
* ``repository/{repository}/{architecture}`` is a repository packages directory.
|
* ``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>`.
|
Normally you should avoid direct interaction with the application tree. For tree migration process refer to the :doc:`migration notes <migrations/index>`.
|
||||||
|
|
||||||
Database
|
Database
|
||||||
--------
|
--------
|
||||||
|
@ -34,7 +34,7 @@ Contents
|
|||||||
configuration
|
configuration
|
||||||
command-line
|
command-line
|
||||||
faq/index
|
faq/index
|
||||||
migration
|
migrations/index
|
||||||
architecture
|
architecture
|
||||||
advanced-usage
|
advanced-usage
|
||||||
triggers
|
triggers
|
||||||
|
@ -1,25 +1,5 @@
|
|||||||
Manual migrations
|
|
||||||
=================
|
|
||||||
|
|
||||||
Normally the most of migrations are handled automatically after application start, however, some upgrades require manual interventions; this document describes them.
|
|
||||||
|
|
||||||
Upgrades to breakpoints
|
|
||||||
-----------------------
|
|
||||||
|
|
||||||
To 2.9.0
|
|
||||||
^^^^^^^^
|
|
||||||
|
|
||||||
This release includes major upgrade for the newest devtools and archlinux repository structure. In order to upgrade package need to:
|
|
||||||
|
|
||||||
#. Upgrade to the latest major release of python (3.11) (required by other changes).
|
|
||||||
#. Upgrade devtools to the latest release.
|
|
||||||
#. Backup local settings, ``/etc/ahriman.ini.d/00-setup-overrides.ini`` by default.
|
|
||||||
#. Run setup command (i.e. ``ahriman service-setup``) again with the same arguments as 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
|
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:
|
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:
|
||||||
|
|
16
docs/migrations/2.16.0.rst
Normal file
16
docs/migrations/2.16.0.rst
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
To 2.16.0
|
||||||
|
---------
|
||||||
|
|
||||||
|
This release replaces ``passlib`` dependency with ``bcrypt``.
|
||||||
|
|
||||||
|
The reason behind this change is that python developers have deprecated and scheduled for removal ``crypt`` module, which is used by ``passlib``. (By the way, they recommend to use ``passlib`` as a replacement.) Unfortunately, it appears that ``passlib`` is unmaintained (see `the issue <https://foss.heptapod.net/python-libs/passlib/-/issues/187>`__), so the only solution is to migrate to anoher library.
|
||||||
|
|
||||||
|
Because passwords are stored as hashes, it is near to impossible to shadow change passwords in database, the manual intervention is required if:
|
||||||
|
|
||||||
|
#. Authentication is used.
|
||||||
|
#. Notification provider is ``configuration`` or a user with explicitly set password exists.
|
||||||
|
|
||||||
|
Manual steps might look as:
|
||||||
|
|
||||||
|
#. Get list of users with their roles ``ahriman user-list``.
|
||||||
|
#. For each user run update command, i.e. ``ahriman user-add <username> -R <role>``. Type password when it will be requested.
|
11
docs/migrations/2.9.0.rst
Normal file
11
docs/migrations/2.9.0.rst
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
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 local settings, ``/etc/ahriman.ini.d/00-setup-overrides.ini`` by default.
|
||||||
|
#. Run setup command (i.e. ``ahriman service-setup``) again with the same arguments as 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.
|
14
docs/migrations/index.rst
Normal file
14
docs/migrations/index.rst
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
Manual migrations
|
||||||
|
=================
|
||||||
|
|
||||||
|
Normally the most of migrations are handled automatically after application start, however, some upgrades require manual interventions; this document describes them.
|
||||||
|
|
||||||
|
Upgrades to breakpoints
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
2.9.0
|
||||||
|
2.12.0
|
||||||
|
2.16.0
|
@ -7,7 +7,7 @@ pkgdesc="ArcH linux ReposItory MANager"
|
|||||||
arch=('any')
|
arch=('any')
|
||||||
url="https://github.com/arcan1s/ahriman"
|
url="https://github.com/arcan1s/ahriman"
|
||||||
license=('GPL3')
|
license=('GPL3')
|
||||||
depends=('devtools>=1:1.0.0' 'git' 'pyalpm' 'python-inflection' 'python-passlib' 'python-pyelftools' 'python-requests')
|
depends=('devtools>=1:1.0.0' 'git' 'pyalpm' 'python-bcrypt' 'python-inflection' 'python-pyelftools' 'python-requests')
|
||||||
makedepends=('python-build' 'python-flit' 'python-installer' 'python-wheel')
|
makedepends=('python-build' 'python-flit' 'python-installer' 'python-wheel')
|
||||||
optdepends=('python-aioauth-client: web server with OAuth2 authorization'
|
optdepends=('python-aioauth-client: web server with OAuth2 authorization'
|
||||||
'python-aiohttp: web server'
|
'python-aiohttp: web server'
|
||||||
@ -42,9 +42,6 @@ package() {
|
|||||||
|
|
||||||
python -m installer --destdir="$pkgdir" "dist/$pkgname-$pkgver-py3-none-any.whl"
|
python -m installer --destdir="$pkgdir" "dist/$pkgname-$pkgver-py3-none-any.whl"
|
||||||
|
|
||||||
# thanks too PEP517, which we all wanted, you need to install data files manually nowadays
|
|
||||||
pushd package && find . \( -type f -or -type l \) -exec install -Dm644 "{}" "$pkgdir/usr/{}" \; && popd
|
|
||||||
|
|
||||||
# keep usr/share configs as reference and copy them to /etc
|
# keep usr/share configs as reference and copy them to /etc
|
||||||
install -Dm644 "$pkgdir/usr/share/$pkgname/settings/ahriman.ini" "$pkgdir/etc/ahriman.ini"
|
install -Dm644 "$pkgdir/usr/share/$pkgname/settings/ahriman.ini" "$pkgdir/etc/ahriman.ini"
|
||||||
install -Dm644 "$pkgdir/usr/share/$pkgname/settings/ahriman.ini.d/logging.ini" "$pkgdir/etc/ahriman.ini.d/logging.ini"
|
install -Dm644 "$pkgdir/usr/share/$pkgname/settings/ahriman.ini.d/logging.ini" "$pkgdir/etc/ahriman.ini.d/logging.ini"
|
||||||
@ -52,7 +49,3 @@ package() {
|
|||||||
install -Dm644 "$srcdir/$pkgname.sysusers" "$pkgdir/usr/lib/sysusers.d/$pkgname.conf"
|
install -Dm644 "$srcdir/$pkgname.sysusers" "$pkgdir/usr/lib/sysusers.d/$pkgname.conf"
|
||||||
install -Dm644 "$srcdir/$pkgname.tmpfiles" "$pkgdir/usr/lib/tmpfiles.d/$pkgname.conf"
|
install -Dm644 "$srcdir/$pkgname.tmpfiles" "$pkgdir/usr/lib/tmpfiles.d/$pkgname.conf"
|
||||||
}
|
}
|
||||||
|
|
||||||
sha512sums=('19841842641520b573cdde6cb80a7cfcd69756d323fdfeebc2eee2d264a1325ead4ab2f8383bb369f7896bfc1de59d7358f133f4afeb90a9b9f0695f482a58d0'
|
|
||||||
'53d37efec812afebf86281716259f9ea78a307b83897166c72777251c3eebcb587ecee375d907514781fb2a5c808cbb24ef9f3f244f12740155d0603bf213131'
|
|
||||||
'62b2eccc352d33853ef243c9cddd63663014aa97b87242f1b5bc5099a7dbd69ff3821f24ffc58e1b7f2387bd4e9e9712cc4c67f661b1724ad99cdf09b3717794')
|
|
||||||
|
@ -21,7 +21,7 @@ It was found that there was an upgrade from old devtools package to the new one,
|
|||||||
* remove build chroot, e.g.: ahriman service-clean --chroot;
|
* remove build chroot, e.g.: ahriman service-clean --chroot;
|
||||||
* update local databases: ahriman update --no-aur --no-local --no-manual -yy.
|
* update local databases: ahriman update --no-aur --no-local --no-manual -yy.
|
||||||
|
|
||||||
For more information kindly refer to migration notes https://ahriman.readthedocs.io/en/stable/migration.html.
|
For more information kindly refer to migration notes https://ahriman.readthedocs.io/en/stable/migrations/2.9.0.html.
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,6 +37,16 @@ Whereas old local tree is still supported it is highly recommended to migrate to
|
|||||||
* enable web and timer services again by using x86_64-aur suffix,
|
* enable web and timer services again by using x86_64-aur suffix,
|
||||||
where x86_64 is the repository architecture and aur is the repository name.
|
where x86_64 is the repository architecture and aur is the repository name.
|
||||||
|
|
||||||
For more information kindly refer to migration notes https://ahriman.readthedocs.io/en/stable/migration.html.
|
For more information kindly refer to migration notes https://ahriman.readthedocs.io/en/stable/migrations/2.12.0.html.
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
_2_16_0_1_changes() {
|
||||||
|
cat << EOF
|
||||||
|
In order to prepare to python 3.13 the project now uses bcrypt instead of passlib for generating and validating
|
||||||
|
passwords, because the passlib seems to be unmaintained and will be broken since then. If you are using password
|
||||||
|
authentication, you'd need to generate passwords again.
|
||||||
|
|
||||||
|
For more information kindly refer to migration notes https://ahriman.readthedocs.io/en/stable/migrations/2.16.0.html.
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,8 @@ authors = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"bcrypt",
|
||||||
"inflection",
|
"inflection",
|
||||||
"passlib",
|
|
||||||
"pyelftools",
|
"pyelftools",
|
||||||
"requests",
|
"requests",
|
||||||
]
|
]
|
||||||
@ -100,3 +100,6 @@ include = [
|
|||||||
exclude = [
|
exclude = [
|
||||||
"package/archlinux",
|
"package/archlinux",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[tool.flit.external-data]
|
||||||
|
directory = "package"
|
||||||
|
@ -89,7 +89,8 @@ Start web service (requires additional configuration):
|
|||||||
|
|
||||||
handlers_root = Path(__file__).parent / "handlers"
|
handlers_root = Path(__file__).parent / "handlers"
|
||||||
for handler in implementations(handlers_root, "ahriman.application.handlers", Handler):
|
for handler in implementations(handlers_root, "ahriman.application.handlers", Handler):
|
||||||
for subparser in handler.arguments(subparsers):
|
for subparser_parser in handler.arguments:
|
||||||
|
subparser = subparser_parser(subparsers)
|
||||||
subparser.formatter_class = _HelpFormatter
|
subparser.formatter_class = _HelpFormatter
|
||||||
subparser.set_defaults(handler=handler, parser=_parser)
|
subparser.set_defaults(handler=handler, parser=_parser)
|
||||||
|
|
||||||
|
@ -34,50 +34,6 @@ class Add(Handler):
|
|||||||
add packages handler
|
add packages handler
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
|
||||||
"""
|
|
||||||
add parser(s) for the subcommand
|
|
||||||
|
|
||||||
Args:
|
|
||||||
root(SubParserAction): subparsers for the commands
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
|
||||||
"""
|
|
||||||
parser = root.add_parser("package-add", aliases=["add", "package-update"], help="add package",
|
|
||||||
description="add existing or new package to the build queue",
|
|
||||||
epilog="This subcommand should be used for new package addition. "
|
|
||||||
"It also supports flag --now in case if you would like to build "
|
|
||||||
"the package immediately. You can add new package from one of "
|
|
||||||
"supported sources:\n\n"
|
|
||||||
"1. If it is already built package you can specify the path to the archive.\n"
|
|
||||||
"2. You can also add built packages from the directory (e.g. during the "
|
|
||||||
"migration from another repository source).\n"
|
|
||||||
"3. It is also possible to add package from local PKGBUILD, but in this case "
|
|
||||||
"it will be ignored during the next automatic updates.\n"
|
|
||||||
"4. Ahriman supports downloading archives from remote (e.g. HTTP) sources.\n"
|
|
||||||
"5. Finally you can add package from AUR.")
|
|
||||||
parser.add_argument("package", help="package source (base name, path to local files, remote URL)", nargs="+")
|
|
||||||
parser.add_argument("--changes", help="calculate changes from the latest known commit if available",
|
|
||||||
action=argparse.BooleanOptionalAction, default=True)
|
|
||||||
parser.add_argument("--dependencies", help="process missing package dependencies",
|
|
||||||
action=argparse.BooleanOptionalAction, default=True)
|
|
||||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty",
|
|
||||||
action="store_true")
|
|
||||||
parser.add_argument("--increment", help="increment package release (pkgrel) version on duplicate",
|
|
||||||
action=argparse.BooleanOptionalAction, default=True)
|
|
||||||
parser.add_argument("-n", "--now", help="run update function after", action="store_true")
|
|
||||||
parser.add_argument("-y", "--refresh", help="download fresh package databases from the mirror before actions, "
|
|
||||||
"-yy to force refresh even if up to date",
|
|
||||||
action="count", default=False)
|
|
||||||
parser.add_argument("-s", "--source", help="explicitly specify the package source for this command",
|
|
||||||
type=PackageSource, choices=enum_values(PackageSource), default=PackageSource.Auto)
|
|
||||||
parser.add_argument("-u", "--username", help="build as user", default=extract_user())
|
|
||||||
parser.add_argument("-v", "--variable", help="apply specified makepkg variables to the next build",
|
|
||||||
action="append")
|
|
||||||
return [parser]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
report: bool) -> None:
|
report: bool) -> None:
|
||||||
@ -112,3 +68,49 @@ class Add(Handler):
|
|||||||
application.print_updates(packages, log_fn=application.logger.info)
|
application.print_updates(packages, log_fn=application.logger.info)
|
||||||
result = application.update(packages, packagers, bump_pkgrel=args.increment)
|
result = application.update(packages, packagers, bump_pkgrel=args.increment)
|
||||||
Add.check_status(args.exit_code, not result.is_empty)
|
Add.check_status(args.exit_code, not result.is_empty)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _set_package_add_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
|
"""
|
||||||
|
add parser for package addition subcommand
|
||||||
|
|
||||||
|
Args:
|
||||||
|
root(SubParserAction): subparsers for the commands
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
argparse.ArgumentParser: created argument parser
|
||||||
|
"""
|
||||||
|
parser = root.add_parser("package-add", aliases=["add", "package-update"], help="add package",
|
||||||
|
description="add existing or new package to the build queue",
|
||||||
|
epilog="This subcommand should be used for new package addition. "
|
||||||
|
"It also supports flag --now in case if you would like to build "
|
||||||
|
"the package immediately. You can add new package from one of "
|
||||||
|
"supported sources:\n\n"
|
||||||
|
"1. If it is already built package you can specify the path to the archive.\n"
|
||||||
|
"2. You can also add built packages from the directory (e.g. during the "
|
||||||
|
"migration from another repository source).\n"
|
||||||
|
"3. It is also possible to add package from local PKGBUILD, but in this case "
|
||||||
|
"it will be ignored during the next automatic updates.\n"
|
||||||
|
"4. Ahriman supports downloading archives from remote (e.g. HTTP) sources.\n"
|
||||||
|
"5. Finally you can add package from AUR.")
|
||||||
|
parser.add_argument("package", help="package source (base name, path to local files, remote URL)", nargs="+")
|
||||||
|
parser.add_argument("--changes", help="calculate changes from the latest known commit if available",
|
||||||
|
action=argparse.BooleanOptionalAction, default=True)
|
||||||
|
parser.add_argument("--dependencies", help="process missing package dependencies",
|
||||||
|
action=argparse.BooleanOptionalAction, default=True)
|
||||||
|
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty",
|
||||||
|
action="store_true")
|
||||||
|
parser.add_argument("--increment", help="increment package release (pkgrel) version on duplicate",
|
||||||
|
action=argparse.BooleanOptionalAction, default=True)
|
||||||
|
parser.add_argument("-n", "--now", help="run update function after", action="store_true")
|
||||||
|
parser.add_argument("-y", "--refresh", help="download fresh package databases from the mirror before actions, "
|
||||||
|
"-yy to force refresh even if up to date",
|
||||||
|
action="count", default=False)
|
||||||
|
parser.add_argument("-s", "--source", help="explicitly specify the package source for this command",
|
||||||
|
type=PackageSource, choices=enum_values(PackageSource), default=PackageSource.Auto)
|
||||||
|
parser.add_argument("-u", "--username", help="build as user", default=extract_user())
|
||||||
|
parser.add_argument("-v", "--variable", help="apply specified makepkg variables to the next build",
|
||||||
|
action="append")
|
||||||
|
return parser
|
||||||
|
|
||||||
|
arguments = [_set_package_add_parser]
|
||||||
|
@ -36,23 +36,6 @@ class Backup(Handler):
|
|||||||
|
|
||||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
|
||||||
"""
|
|
||||||
add parser(s) for the subcommand
|
|
||||||
|
|
||||||
Args:
|
|
||||||
root(SubParserAction): subparsers for the commands
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
|
||||||
"""
|
|
||||||
parser = root.add_parser("repo-backup", help="backup repository data",
|
|
||||||
description="backup repository settings and database")
|
|
||||||
parser.add_argument("path", help="path of the output archive", type=Path)
|
|
||||||
parser.set_defaults(architecture="", lock=None, report=False, repository="", unsafe=True)
|
|
||||||
return [parser]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
report: bool) -> None:
|
report: bool) -> None:
|
||||||
@ -70,6 +53,23 @@ class Backup(Handler):
|
|||||||
for backup_path in backup_paths:
|
for backup_path in backup_paths:
|
||||||
archive.add(backup_path)
|
archive.add(backup_path)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _set_repo_backup_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
|
"""
|
||||||
|
add parser for repository backup subcommand
|
||||||
|
|
||||||
|
Args:
|
||||||
|
root(SubParserAction): subparsers for the commands
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
argparse.ArgumentParser: created argument parser
|
||||||
|
"""
|
||||||
|
parser = root.add_parser("repo-backup", help="backup repository data",
|
||||||
|
description="backup repository settings and database")
|
||||||
|
parser.add_argument("path", help="path of the output archive", type=Path)
|
||||||
|
parser.set_defaults(architecture="", lock=None, report=False, repository="", unsafe=True)
|
||||||
|
return parser
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_paths(configuration: Configuration) -> set[Path]:
|
def get_paths(configuration: Configuration) -> set[Path]:
|
||||||
"""
|
"""
|
||||||
@ -100,3 +100,5 @@ class Backup(Handler):
|
|||||||
paths.add(gnupg_home)
|
paths.add(gnupg_home)
|
||||||
|
|
||||||
return paths
|
return paths
|
||||||
|
|
||||||
|
arguments = [_set_repo_backup_parser]
|
||||||
|
@ -35,19 +35,6 @@ class Change(Handler):
|
|||||||
|
|
||||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io
|
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
|
||||||
"""
|
|
||||||
add parser(s) for the subcommand
|
|
||||||
|
|
||||||
Args:
|
|
||||||
root(SubParserAction): subparsers for the commands
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
|
||||||
"""
|
|
||||||
return [cls._set_package_changes_parser(root), cls._set_package_changes_remove_parser(root)]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
report: bool) -> None:
|
report: bool) -> None:
|
||||||
@ -108,3 +95,5 @@ class Change(Handler):
|
|||||||
parser.add_argument("package", help="package base")
|
parser.add_argument("package", help="package base")
|
||||||
parser.set_defaults(action=Action.Remove, exit_code=False, lock=None, quiet=True, report=False, unsafe=True)
|
parser.set_defaults(action=Action.Remove, exit_code=False, lock=None, quiet=True, report=False, unsafe=True)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
arguments = [_set_package_changes_parser, _set_package_changes_remove_parser]
|
||||||
|
@ -31,15 +31,32 @@ class Clean(Handler):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
|
report: bool) -> None:
|
||||||
"""
|
"""
|
||||||
add parser(s) for the subcommand
|
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
|
||||||
|
"""
|
||||||
|
application = Application(repository_id, configuration, report=report)
|
||||||
|
application.on_start()
|
||||||
|
application.clean(cache=args.cache, chroot=args.chroot, manual=args.manual, packages=args.packages,
|
||||||
|
pacman=args.pacman)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _set_service_clean_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
|
"""
|
||||||
|
add parser for repository clean subcommand
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
root(SubParserAction): subparsers for the commands
|
root(SubParserAction): subparsers for the commands
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
argparse.ArgumentParser: created argument parser
|
||||||
"""
|
"""
|
||||||
parser = root.add_parser("service-clean", aliases=["clean", "repo-clean"], help="clean local caches",
|
parser = root.add_parser("service-clean", aliases=["clean", "repo-clean"], help="clean local caches",
|
||||||
description="remove local caches",
|
description="remove local caches",
|
||||||
@ -56,21 +73,6 @@ class Clean(Handler):
|
|||||||
parser.add_argument("--pacman", help="clear directory with pacman local database cache",
|
parser.add_argument("--pacman", help="clear directory with pacman local database cache",
|
||||||
action=argparse.BooleanOptionalAction, default=False)
|
action=argparse.BooleanOptionalAction, default=False)
|
||||||
parser.set_defaults(lock=None, quiet=True, unsafe=True)
|
parser.set_defaults(lock=None, quiet=True, unsafe=True)
|
||||||
return [parser]
|
return parser
|
||||||
|
|
||||||
@classmethod
|
arguments = [_set_service_clean_parser]
|
||||||
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
|
|
||||||
"""
|
|
||||||
application = Application(repository_id, configuration, report=report)
|
|
||||||
application.on_start()
|
|
||||||
application.clean(cache=args.cache, chroot=args.chroot, manual=args.manual, packages=args.packages,
|
|
||||||
pacman=args.pacman)
|
|
||||||
|
@ -35,26 +35,6 @@ class Copy(Handler):
|
|||||||
|
|
||||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting action
|
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting action
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
|
||||||
"""
|
|
||||||
add parser(s) for the subcommand
|
|
||||||
|
|
||||||
Args:
|
|
||||||
root(SubParserAction): subparsers for the commands
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
|
||||||
"""
|
|
||||||
parser = root.add_parser("package-copy", aliases=["copy"], help="copy package from another repository",
|
|
||||||
description="copy package and its metadata from another repository")
|
|
||||||
parser.add_argument("source", help="source repository name")
|
|
||||||
parser.add_argument("package", help="package base", nargs="+")
|
|
||||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty",
|
|
||||||
action="store_true")
|
|
||||||
parser.add_argument("--remove", help="remove package from the source repository after", action="store_true")
|
|
||||||
return [parser]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
report: bool) -> None:
|
report: bool) -> None:
|
||||||
@ -87,6 +67,26 @@ class Copy(Handler):
|
|||||||
if args.remove:
|
if args.remove:
|
||||||
source_application.remove(args.package)
|
source_application.remove(args.package)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _set_package_copy_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
|
"""
|
||||||
|
add parser for package copy subcommand
|
||||||
|
|
||||||
|
Args:
|
||||||
|
root(SubParserAction): subparsers for the commands
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
argparse.ArgumentParser: created argument parser
|
||||||
|
"""
|
||||||
|
parser = root.add_parser("package-copy", aliases=["copy"], help="copy package from another repository",
|
||||||
|
description="copy package and its metadata from another repository")
|
||||||
|
parser.add_argument("source", help="source repository name")
|
||||||
|
parser.add_argument("package", help="package base", nargs="+")
|
||||||
|
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty",
|
||||||
|
action="store_true")
|
||||||
|
parser.add_argument("--remove", help="remove package from the source repository after", action="store_true")
|
||||||
|
return parser
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def copy_package(package: Package, application: Application, source_application: Application) -> None:
|
def copy_package(package: Package, application: Application, source_application: Application) -> None:
|
||||||
"""
|
"""
|
||||||
@ -113,3 +113,5 @@ class Copy(Handler):
|
|||||||
package.base, source_application.reporter.package_dependencies_get(package.base)
|
package.base, source_application.reporter.package_dependencies_get(package.base)
|
||||||
)
|
)
|
||||||
application.reporter.package_update(package, BuildStatusEnum.Pending)
|
application.reporter.package_update(package, BuildStatusEnum.Pending)
|
||||||
|
|
||||||
|
arguments = [_set_package_copy_parser]
|
||||||
|
@ -36,15 +36,40 @@ class Daemon(Handler):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
|
report: bool) -> None:
|
||||||
"""
|
"""
|
||||||
add parser(s) for the subcommand
|
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
|
||||||
|
"""
|
||||||
|
application = Application(repository_id, configuration, report=report, refresh_pacman_database=args.refresh)
|
||||||
|
if args.partitions:
|
||||||
|
iterator = UpdatesIterator(application, args.interval)
|
||||||
|
else:
|
||||||
|
iterator = FixedUpdatesIterator(application, args.interval)
|
||||||
|
|
||||||
|
for packages in iterator:
|
||||||
|
if packages is None:
|
||||||
|
continue # nothing to check case
|
||||||
|
|
||||||
|
args.package = packages
|
||||||
|
Update.run(args, repository_id, configuration, report=report)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _set_repo_daemon_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
|
"""
|
||||||
|
add parser for daemon subcommand
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
root(SubParserAction): subparsers for the commands
|
root(SubParserAction): subparsers for the commands
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
argparse.ArgumentParser: created argument parser
|
||||||
"""
|
"""
|
||||||
parser = root.add_parser("repo-daemon", aliases=["daemon"], help="run application as daemon",
|
parser = root.add_parser("repo-daemon", aliases=["daemon"], help="run application as daemon",
|
||||||
description="start process which periodically will run update process")
|
description="start process which periodically will run update process")
|
||||||
@ -76,29 +101,6 @@ class Daemon(Handler):
|
|||||||
"-yy to force refresh even if up to date",
|
"-yy to force refresh even if up to date",
|
||||||
action="count", default=False)
|
action="count", default=False)
|
||||||
parser.set_defaults(exit_code=False, lock=Path("ahriman-daemon.pid"), package=[])
|
parser.set_defaults(exit_code=False, lock=Path("ahriman-daemon.pid"), package=[])
|
||||||
return [parser]
|
return parser
|
||||||
|
|
||||||
@classmethod
|
arguments = [_set_repo_daemon_parser]
|
||||||
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
|
|
||||||
"""
|
|
||||||
application = Application(repository_id, configuration, report=report, refresh_pacman_database=args.refresh)
|
|
||||||
if args.partitions:
|
|
||||||
iterator = UpdatesIterator(application, args.interval)
|
|
||||||
else:
|
|
||||||
iterator = FixedUpdatesIterator(application, args.interval)
|
|
||||||
|
|
||||||
for packages in iterator:
|
|
||||||
if packages is None:
|
|
||||||
continue # nothing to check case
|
|
||||||
|
|
||||||
args.package = packages
|
|
||||||
Update.run(args, repository_id, configuration, report=report)
|
|
||||||
|
@ -32,28 +32,6 @@ class Dump(Handler):
|
|||||||
|
|
||||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io
|
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
|
||||||
"""
|
|
||||||
add parser(s) for the subcommand
|
|
||||||
|
|
||||||
Args:
|
|
||||||
root(SubParserAction): subparsers for the commands
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
|
||||||
"""
|
|
||||||
parser = root.add_parser("service-config", aliases=["config", "repo-config"], help="dump configuration",
|
|
||||||
description="dump configuration for the specified architecture")
|
|
||||||
parser.add_argument("section", help="filter settings by section", nargs="?")
|
|
||||||
parser.add_argument("key", help="filter settings by key", nargs="?")
|
|
||||||
parser.add_argument("--info", help="show additional information, e.g. configuration files",
|
|
||||||
action=argparse.BooleanOptionalAction, default=True)
|
|
||||||
parser.add_argument("--secure", help="hide passwords and secrets from output",
|
|
||||||
action=argparse.BooleanOptionalAction, default=True)
|
|
||||||
parser.set_defaults(lock=None, quiet=True, report=False, unsafe=True)
|
|
||||||
return [parser]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
report: bool) -> None:
|
report: bool) -> None:
|
||||||
@ -81,3 +59,27 @@ class Dump(Handler):
|
|||||||
case section, key: # key only
|
case section, key: # key only
|
||||||
value = configuration.get(section, key, fallback="")
|
value = configuration.get(section, key, fallback="")
|
||||||
StringPrinter(value)(verbose=False)
|
StringPrinter(value)(verbose=False)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _set_service_config_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
|
"""
|
||||||
|
add parser for config subcommand
|
||||||
|
|
||||||
|
Args:
|
||||||
|
root(SubParserAction): subparsers for the commands
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
argparse.ArgumentParser: created argument parser
|
||||||
|
"""
|
||||||
|
parser = root.add_parser("service-config", aliases=["config", "repo-config"], help="dump configuration",
|
||||||
|
description="dump configuration for the specified architecture")
|
||||||
|
parser.add_argument("section", help="filter settings by section", nargs="?")
|
||||||
|
parser.add_argument("key", help="filter settings by key", nargs="?")
|
||||||
|
parser.add_argument("--info", help="show additional information, e.g. configuration files",
|
||||||
|
action=argparse.BooleanOptionalAction, default=True)
|
||||||
|
parser.add_argument("--secure", help="hide passwords and secrets from output",
|
||||||
|
action=argparse.BooleanOptionalAction, default=True)
|
||||||
|
parser.set_defaults(lock=None, quiet=True, report=False, unsafe=True)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
arguments = [_set_service_config_parser]
|
||||||
|
@ -46,6 +46,8 @@ class Handler:
|
|||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
ALLOW_MULTI_ARCHITECTURE_RUN(bool): (class attribute) allow running with multiple architectures
|
ALLOW_MULTI_ARCHITECTURE_RUN(bool): (class attribute) allow running with multiple architectures
|
||||||
|
arguments(list[Callable[[SubParserAction], argparse.ArgumentParser]]): (class attribute) argument parser
|
||||||
|
methods, which will be called to create command line parsers
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
Wrapper for all command line actions, though each derived class implements :func:`run()` method, it usually
|
Wrapper for all command line actions, though each derived class implements :func:`run()` method, it usually
|
||||||
@ -57,22 +59,7 @@ class Handler:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
ALLOW_MULTI_ARCHITECTURE_RUN = True
|
ALLOW_MULTI_ARCHITECTURE_RUN = True
|
||||||
|
arguments: list[Callable[[SubParserAction], argparse.ArgumentParser]]
|
||||||
@classmethod
|
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
|
||||||
"""
|
|
||||||
add parser(s) for the subcommand
|
|
||||||
|
|
||||||
Args:
|
|
||||||
root(SubParserAction): subparsers for the commands
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
NotImplementedError: not implemented method
|
|
||||||
"""
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def call(cls, args: argparse.Namespace, repository_id: RepositoryId) -> bool:
|
def call(cls, args: argparse.Namespace, repository_id: RepositoryId) -> bool:
|
||||||
|
@ -31,23 +31,6 @@ class Help(Handler):
|
|||||||
|
|
||||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
|
||||||
"""
|
|
||||||
add parser(s) for the subcommand
|
|
||||||
|
|
||||||
Args:
|
|
||||||
root(SubParserAction): subparsers for the commands
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
|
||||||
"""
|
|
||||||
parser = root.add_parser("help", help="show help message",
|
|
||||||
description="show help message for application or command and exit")
|
|
||||||
parser.add_argument("subcommand", help="show help message for specific command", nargs="?")
|
|
||||||
parser.set_defaults(architecture="", lock=None, quiet=True, report=False, repository="", unsafe=True)
|
|
||||||
return [parser]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
report: bool) -> None:
|
report: bool) -> None:
|
||||||
@ -65,3 +48,22 @@ class Help(Handler):
|
|||||||
parser.parse_args(["--help"])
|
parser.parse_args(["--help"])
|
||||||
else:
|
else:
|
||||||
parser.parse_args([args.subcommand, "--help"])
|
parser.parse_args([args.subcommand, "--help"])
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _set_help_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
|
"""
|
||||||
|
add parser for listing help subcommand
|
||||||
|
|
||||||
|
Args:
|
||||||
|
root(SubParserAction): subparsers for the commands
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
argparse.ArgumentParser: created argument parser
|
||||||
|
"""
|
||||||
|
parser = root.add_parser("help", help="show help message",
|
||||||
|
description="show help message for application or command and exit")
|
||||||
|
parser.add_argument("subcommand", help="show help message for specific command", nargs="?")
|
||||||
|
parser.set_defaults(architecture="", lock=None, quiet=True, report=False, repository="", unsafe=True)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
arguments = [_set_help_parser]
|
||||||
|
@ -32,28 +32,6 @@ class KeyImport(Handler):
|
|||||||
|
|
||||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
|
||||||
"""
|
|
||||||
add parser(s) for the subcommand
|
|
||||||
|
|
||||||
Args:
|
|
||||||
root(SubParserAction): subparsers for the commands
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
|
||||||
"""
|
|
||||||
parser = root.add_parser("service-key-import", aliases=["key-import"], help="import PGP key",
|
|
||||||
description="import PGP key from public sources to the repository user",
|
|
||||||
epilog="By default ahriman runs build process with package sources validation "
|
|
||||||
"(in case if signature and keys are available in PKGBUILD). This process will "
|
|
||||||
"fail in case if key is not known for build user. This subcommand can be used "
|
|
||||||
"in order to import the PGP key to user keychain.")
|
|
||||||
parser.add_argument("--key-server", help="key server for key import", default="keyserver.ubuntu.com")
|
|
||||||
parser.add_argument("key", help="PGP key to import from public server")
|
|
||||||
parser.set_defaults(architecture="", lock=None, report=False, repository="")
|
|
||||||
return [parser]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
report: bool) -> None:
|
report: bool) -> None:
|
||||||
@ -68,3 +46,27 @@ class KeyImport(Handler):
|
|||||||
"""
|
"""
|
||||||
application = Application(repository_id, configuration, report=report)
|
application = Application(repository_id, configuration, report=report)
|
||||||
application.repository.sign.key_import(args.key_server, args.key)
|
application.repository.sign.key_import(args.key_server, args.key)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _set_service_key_import_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
|
"""
|
||||||
|
add parser for key import subcommand
|
||||||
|
|
||||||
|
Args:
|
||||||
|
root(SubParserAction): subparsers for the commands
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
argparse.ArgumentParser: created argument parser
|
||||||
|
"""
|
||||||
|
parser = root.add_parser("service-key-import", aliases=["key-import"], help="import PGP key",
|
||||||
|
description="import PGP key from public sources to the repository user",
|
||||||
|
epilog="By default ahriman runs build process with package sources validation "
|
||||||
|
"(in case if signature and keys are available in PKGBUILD). This process will "
|
||||||
|
"fail in case if key is not known for build user. This subcommand can be used "
|
||||||
|
"in order to import the PGP key to user keychain.")
|
||||||
|
parser.add_argument("--key-server", help="key server for key import", default="keyserver.ubuntu.com")
|
||||||
|
parser.add_argument("key", help="PGP key to import from public server")
|
||||||
|
parser.set_defaults(architecture="", lock=None, report=False, repository="")
|
||||||
|
return parser
|
||||||
|
|
||||||
|
arguments = [_set_service_key_import_parser]
|
||||||
|
@ -40,24 +40,6 @@ class Patch(Handler):
|
|||||||
|
|
||||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
|
||||||
"""
|
|
||||||
add parser(s) for the subcommand
|
|
||||||
|
|
||||||
Args:
|
|
||||||
root(SubParserAction): subparsers for the commands
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
|
||||||
"""
|
|
||||||
return [
|
|
||||||
cls._set_patch_add_parser(root),
|
|
||||||
cls._set_patch_list_parser(root),
|
|
||||||
cls._set_patch_remove_parser(root),
|
|
||||||
cls._set_patch_set_add_parser(root),
|
|
||||||
]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
report: bool) -> None:
|
report: bool) -> None:
|
||||||
@ -267,3 +249,10 @@ class Patch(Handler):
|
|||||||
application.reporter.package_patches_remove(package_base, variable)
|
application.reporter.package_patches_remove(package_base, variable)
|
||||||
else:
|
else:
|
||||||
application.reporter.package_patches_remove(package_base, None) # just pass as is
|
application.reporter.package_patches_remove(package_base, None) # just pass as is
|
||||||
|
|
||||||
|
arguments = [
|
||||||
|
_set_patch_add_parser,
|
||||||
|
_set_patch_list_parser,
|
||||||
|
_set_patch_remove_parser,
|
||||||
|
_set_patch_set_add_parser,
|
||||||
|
]
|
||||||
|
@ -34,38 +34,6 @@ class Rebuild(Handler):
|
|||||||
make world handler
|
make world handler
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
|
||||||
"""
|
|
||||||
add parser(s) for the subcommand
|
|
||||||
|
|
||||||
Args:
|
|
||||||
root(SubParserAction): subparsers for the commands
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
|
||||||
"""
|
|
||||||
parser = root.add_parser("repo-rebuild", aliases=["rebuild"], help="rebuild repository",
|
|
||||||
description="force rebuild whole repository")
|
|
||||||
parser.add_argument("--depends-on", help="only rebuild packages that depend on specified packages",
|
|
||||||
action="append")
|
|
||||||
parser.add_argument("--dry-run", help="just perform check for packages without rebuild process itself",
|
|
||||||
action="store_true")
|
|
||||||
parser.add_argument("--from-database",
|
|
||||||
help="read packages from database instead of filesystem. This feature in particular is "
|
|
||||||
"required in case if you would like to restore repository from another repository "
|
|
||||||
"instance. Note, however, that in order to restore packages you need to have original "
|
|
||||||
"ahriman instance run with web service and have run repo-update at least once.",
|
|
||||||
action="store_true")
|
|
||||||
parser.add_argument("--increment", help="increment package release (pkgrel) on duplicate",
|
|
||||||
action=argparse.BooleanOptionalAction, default=True)
|
|
||||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty",
|
|
||||||
action="store_true")
|
|
||||||
parser.add_argument("-s", "--status", help="filter packages by status. Requires --from-database to be set",
|
|
||||||
type=BuildStatusEnum, choices=enum_values(BuildStatusEnum))
|
|
||||||
parser.add_argument("-u", "--username", help="build as user", default=extract_user())
|
|
||||||
return [parser]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
report: bool) -> None:
|
report: bool) -> None:
|
||||||
@ -92,6 +60,38 @@ class Rebuild(Handler):
|
|||||||
result = application.update(packages, Packagers(args.username), bump_pkgrel=args.increment)
|
result = application.update(packages, Packagers(args.username), bump_pkgrel=args.increment)
|
||||||
Rebuild.check_status(args.exit_code, not result.is_empty)
|
Rebuild.check_status(args.exit_code, not result.is_empty)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _set_repo_rebuild_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
|
"""
|
||||||
|
add parser for repository rebuild subcommand
|
||||||
|
|
||||||
|
Args:
|
||||||
|
root(SubParserAction): subparsers for the commands
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
argparse.ArgumentParser: created argument parser
|
||||||
|
"""
|
||||||
|
parser = root.add_parser("repo-rebuild", aliases=["rebuild"], help="rebuild repository",
|
||||||
|
description="force rebuild whole repository")
|
||||||
|
parser.add_argument("--depends-on", help="only rebuild packages that depend on specified packages",
|
||||||
|
action="append")
|
||||||
|
parser.add_argument("--dry-run", help="just perform check for packages without rebuild process itself",
|
||||||
|
action="store_true")
|
||||||
|
parser.add_argument("--from-database",
|
||||||
|
help="read packages from database instead of filesystem. This feature in particular is "
|
||||||
|
"required in case if you would like to restore repository from another repository "
|
||||||
|
"instance. Note, however, that in order to restore packages you need to have original "
|
||||||
|
"ahriman instance run with web service and have run repo-update at least once.",
|
||||||
|
action="store_true")
|
||||||
|
parser.add_argument("--increment", help="increment package release (pkgrel) on duplicate",
|
||||||
|
action=argparse.BooleanOptionalAction, default=True)
|
||||||
|
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty",
|
||||||
|
action="store_true")
|
||||||
|
parser.add_argument("-s", "--status", help="filter packages by status. Requires --from-database to be set",
|
||||||
|
type=BuildStatusEnum, choices=enum_values(BuildStatusEnum))
|
||||||
|
parser.add_argument("-u", "--username", help="build as user", default=extract_user())
|
||||||
|
return parser
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def extract_packages(application: Application, status: BuildStatusEnum | None, *,
|
def extract_packages(application: Application, status: BuildStatusEnum | None, *,
|
||||||
from_database: bool) -> list[Package]:
|
from_database: bool) -> list[Package]:
|
||||||
@ -114,3 +114,5 @@ class Rebuild(Handler):
|
|||||||
]
|
]
|
||||||
|
|
||||||
return application.repository.packages()
|
return application.repository.packages()
|
||||||
|
|
||||||
|
arguments = [_set_repo_rebuild_parser]
|
||||||
|
@ -30,22 +30,6 @@ class Remove(Handler):
|
|||||||
remove packages handler
|
remove packages handler
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
|
||||||
"""
|
|
||||||
add parser(s) for the subcommand
|
|
||||||
|
|
||||||
Args:
|
|
||||||
root(SubParserAction): subparsers for the commands
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
|
||||||
"""
|
|
||||||
parser = root.add_parser("package-remove", aliases=["remove"], help="remove package",
|
|
||||||
description="remove package from the repository")
|
|
||||||
parser.add_argument("package", help="package name or base", nargs="+")
|
|
||||||
return [parser]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
report: bool) -> None:
|
report: bool) -> None:
|
||||||
@ -61,3 +45,21 @@ class Remove(Handler):
|
|||||||
application = Application(repository_id, configuration, report=report)
|
application = Application(repository_id, configuration, report=report)
|
||||||
application.on_start()
|
application.on_start()
|
||||||
application.remove(args.package)
|
application.remove(args.package)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _set_package_remove_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
|
"""
|
||||||
|
add parser for package removal subcommand
|
||||||
|
|
||||||
|
Args:
|
||||||
|
root(SubParserAction): subparsers for the commands
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
argparse.ArgumentParser: created argument parser
|
||||||
|
"""
|
||||||
|
parser = root.add_parser("package-remove", aliases=["remove"], help="remove package",
|
||||||
|
description="remove package from the repository")
|
||||||
|
parser.add_argument("package", help="package name or base", nargs="+")
|
||||||
|
return parser
|
||||||
|
|
||||||
|
arguments = [_set_package_remove_parser]
|
||||||
|
@ -31,22 +31,6 @@ class RemoveUnknown(Handler):
|
|||||||
remove unknown packages handler
|
remove unknown packages handler
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
|
||||||
"""
|
|
||||||
add parser(s) for the subcommand
|
|
||||||
|
|
||||||
Args:
|
|
||||||
root(SubParserAction): subparsers for the commands
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
|
||||||
"""
|
|
||||||
parser = root.add_parser("repo-remove-unknown", aliases=["remove-unknown"], help="remove unknown packages",
|
|
||||||
description="remove packages which are missing in AUR and do not have local PKGBUILDs")
|
|
||||||
parser.add_argument("--dry-run", help="just perform check for packages without removal", action="store_true")
|
|
||||||
return [parser]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
report: bool) -> None:
|
report: bool) -> None:
|
||||||
@ -69,3 +53,21 @@ class RemoveUnknown(Handler):
|
|||||||
return
|
return
|
||||||
|
|
||||||
application.remove(unknown_packages)
|
application.remove(unknown_packages)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _set_repo_remove_unknown_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
|
"""
|
||||||
|
add parser for remove unknown packages subcommand
|
||||||
|
|
||||||
|
Args:
|
||||||
|
root(SubParserAction): subparsers for the commands
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
argparse.ArgumentParser: created argument parser
|
||||||
|
"""
|
||||||
|
parser = root.add_parser("repo-remove-unknown", aliases=["remove-unknown"], help="remove unknown packages",
|
||||||
|
description="remove packages which are missing in AUR and do not have local PKGBUILDs")
|
||||||
|
parser.add_argument("--dry-run", help="just perform check for packages without removal", action="store_true")
|
||||||
|
return parser
|
||||||
|
|
||||||
|
arguments = [_set_repo_remove_unknown_parser]
|
||||||
|
@ -32,24 +32,6 @@ class Repositories(Handler):
|
|||||||
|
|
||||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
|
||||||
"""
|
|
||||||
add parser(s) for the subcommand
|
|
||||||
|
|
||||||
Args:
|
|
||||||
root(SubParserAction): subparsers for the commands
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
|
||||||
"""
|
|
||||||
parser = root.add_parser("service-repositories", help="show repositories",
|
|
||||||
description="list all available repositories")
|
|
||||||
parser.add_argument("--id-only", help="show machine readable identifier instead",
|
|
||||||
action=argparse.BooleanOptionalAction, default=False)
|
|
||||||
parser.set_defaults(architecture="", lock=None, report=False, repository="", unsafe=True)
|
|
||||||
return [parser]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
report: bool) -> None:
|
report: bool) -> None:
|
||||||
@ -70,3 +52,23 @@ class Repositories(Handler):
|
|||||||
)
|
)
|
||||||
for repository in cls.repositories_extract(dummy_args):
|
for repository in cls.repositories_extract(dummy_args):
|
||||||
RepositoryPrinter(repository)(verbose=not args.id_only)
|
RepositoryPrinter(repository)(verbose=not args.id_only)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _set_service_repositories(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
|
"""
|
||||||
|
add parser for repositories listing
|
||||||
|
|
||||||
|
Args:
|
||||||
|
root(SubParserAction): subparsers for the commands
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
argparse.ArgumentParser: created argument parser
|
||||||
|
"""
|
||||||
|
parser = root.add_parser("service-repositories", help="show repositories",
|
||||||
|
description="list all available repositories")
|
||||||
|
parser.add_argument("--id-only", help="show machine readable identifier instead",
|
||||||
|
action=argparse.BooleanOptionalAction, default=False)
|
||||||
|
parser.set_defaults(architecture="", lock=None, report=False, repository="", unsafe=True)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
arguments = [_set_service_repositories]
|
||||||
|
@ -34,24 +34,6 @@ class Restore(Handler):
|
|||||||
|
|
||||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
|
||||||
"""
|
|
||||||
add parser(s) for the subcommand
|
|
||||||
|
|
||||||
Args:
|
|
||||||
root(SubParserAction): subparsers for the commands
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
|
||||||
"""
|
|
||||||
parser = root.add_parser("repo-restore", help="restore repository data",
|
|
||||||
description="restore settings and database")
|
|
||||||
parser.add_argument("path", help="path of the input archive", type=Path)
|
|
||||||
parser.add_argument("-o", "--output", help="root path of the extracted files", type=Path, default=Path("/"))
|
|
||||||
parser.set_defaults(architecture="", lock=None, report=False, repository="", unsafe=True)
|
|
||||||
return [parser]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
report: bool) -> None:
|
report: bool) -> None:
|
||||||
@ -66,3 +48,23 @@ class Restore(Handler):
|
|||||||
"""
|
"""
|
||||||
with tarfile.open(args.path) as archive:
|
with tarfile.open(args.path) as archive:
|
||||||
archive.extractall(path=args.output) # nosec
|
archive.extractall(path=args.output) # nosec
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _set_repo_restore_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
|
"""
|
||||||
|
add parser for repository restore subcommand
|
||||||
|
|
||||||
|
Args:
|
||||||
|
root(SubParserAction): subparsers for the commands
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
argparse.ArgumentParser: created argument parser
|
||||||
|
"""
|
||||||
|
parser = root.add_parser("repo-restore", help="restore repository data",
|
||||||
|
description="restore settings and database")
|
||||||
|
parser.add_argument("path", help="path of the input archive", type=Path)
|
||||||
|
parser.add_argument("-o", "--output", help="root path of the extracted files", type=Path, default=Path("/"))
|
||||||
|
parser.set_defaults(architecture="", lock=None, report=False, repository="", unsafe=True)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
arguments = [_set_repo_restore_parser]
|
||||||
|
@ -32,25 +32,6 @@ class Run(Handler):
|
|||||||
|
|
||||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
|
||||||
"""
|
|
||||||
add parser(s) for the subcommand
|
|
||||||
|
|
||||||
Args:
|
|
||||||
root(SubParserAction): subparsers for the commands
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
|
||||||
"""
|
|
||||||
parser = root.add_parser("service-run", aliases=["run"], help="run multiple commands",
|
|
||||||
description="run multiple commands on success run of the previous command",
|
|
||||||
epilog="Commands must be quoted by using usual bash rules. Processes will be spawned "
|
|
||||||
"under the same user as this command.")
|
|
||||||
parser.add_argument("command", help="command to be run (quoted) without ``ahriman``", nargs="+")
|
|
||||||
parser.set_defaults(architecture="", lock=None, report=False, repository="", unsafe=True)
|
|
||||||
return [parser]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
report: bool) -> None:
|
report: bool) -> None:
|
||||||
@ -68,6 +49,25 @@ class Run(Handler):
|
|||||||
status = Run.run_command(shlex.split(command), parser)
|
status = Run.run_command(shlex.split(command), parser)
|
||||||
Run.check_status(True, status)
|
Run.check_status(True, status)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _set_service_run(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
|
"""
|
||||||
|
add parser for multicommand
|
||||||
|
|
||||||
|
Args:
|
||||||
|
root(SubParserAction): subparsers for the commands
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
argparse.ArgumentParser: created argument parser
|
||||||
|
"""
|
||||||
|
parser = root.add_parser("service-run", aliases=["run"], help="run multiple commands",
|
||||||
|
description="run multiple commands on success run of the previous command",
|
||||||
|
epilog="Commands must be quoted by using usual bash rules. Processes will be spawned "
|
||||||
|
"under the same user as this command.")
|
||||||
|
parser.add_argument("command", help="command to be run (quoted) without ``ahriman``", nargs="+")
|
||||||
|
parser.set_defaults(architecture="", lock=None, report=False, repository="", unsafe=True)
|
||||||
|
return parser
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run_command(command: list[str], parser: argparse.ArgumentParser) -> bool:
|
def run_command(command: list[str], parser: argparse.ArgumentParser) -> bool:
|
||||||
"""
|
"""
|
||||||
@ -83,3 +83,5 @@ class Run(Handler):
|
|||||||
args = parser.parse_args(command)
|
args = parser.parse_args(command)
|
||||||
handler: Handler = args.handler
|
handler: Handler = args.handler
|
||||||
return handler.execute(args) == 0
|
return handler.execute(args) == 0
|
||||||
|
|
||||||
|
arguments = [_set_service_run]
|
||||||
|
@ -46,33 +46,6 @@ class Search(Handler):
|
|||||||
if field.default_factory is not list
|
if field.default_factory is not list
|
||||||
}
|
}
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
|
||||||
"""
|
|
||||||
add parser(s) for the subcommand
|
|
||||||
|
|
||||||
Args:
|
|
||||||
root(SubParserAction): subparsers for the commands
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
|
||||||
"""
|
|
||||||
parser = root.add_parser("aur-search", aliases=["search"], help="search for package",
|
|
||||||
description="search for package in AUR using API")
|
|
||||||
parser.add_argument("search",
|
|
||||||
help="search terms, can be specified multiple times, the result will match all terms",
|
|
||||||
nargs="+")
|
|
||||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty",
|
|
||||||
action="store_true")
|
|
||||||
parser.add_argument("--info", help="show additional package information",
|
|
||||||
action=argparse.BooleanOptionalAction, default=False)
|
|
||||||
parser.add_argument("--sort-by",
|
|
||||||
help="sort field by this field. In case if two packages have the same value of "
|
|
||||||
"the specified field, they will be always sorted by name",
|
|
||||||
default="name", choices=sorted(Search.SORT_FIELDS))
|
|
||||||
parser.set_defaults(architecture="", lock=None, quiet=True, report=False, repository="", unsafe=True)
|
|
||||||
return [parser]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
report: bool) -> None:
|
report: bool) -> None:
|
||||||
@ -95,6 +68,33 @@ class Search(Handler):
|
|||||||
for package in Search.sort(packages_list, args.sort_by):
|
for package in Search.sort(packages_list, args.sort_by):
|
||||||
AurPrinter(package)(verbose=args.info)
|
AurPrinter(package)(verbose=args.info)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _set_aur_search_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
|
"""
|
||||||
|
add parser for AUR search subcommand
|
||||||
|
|
||||||
|
Args:
|
||||||
|
root(SubParserAction): subparsers for the commands
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
argparse.ArgumentParser: created argument parser
|
||||||
|
"""
|
||||||
|
parser = root.add_parser("aur-search", aliases=["search"], help="search for package",
|
||||||
|
description="search for package in AUR using API")
|
||||||
|
parser.add_argument("search",
|
||||||
|
help="search terms, can be specified multiple times, the result will match all terms",
|
||||||
|
nargs="+")
|
||||||
|
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if result is empty",
|
||||||
|
action="store_true")
|
||||||
|
parser.add_argument("--info", help="show additional package information",
|
||||||
|
action=argparse.BooleanOptionalAction, default=False)
|
||||||
|
parser.add_argument("--sort-by",
|
||||||
|
help="sort field by this field. In case if two packages have the same value of "
|
||||||
|
"the specified field, they will be always sorted by name",
|
||||||
|
default="name", choices=sorted(Search.SORT_FIELDS))
|
||||||
|
parser.set_defaults(architecture="", lock=None, quiet=True, report=False, repository="", unsafe=True)
|
||||||
|
return parser
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def sort(packages: Iterable[AURPackage], sort_by: str) -> list[AURPackage]:
|
def sort(packages: Iterable[AURPackage], sort_by: str) -> list[AURPackage]:
|
||||||
"""
|
"""
|
||||||
@ -117,3 +117,5 @@ class Search(Handler):
|
|||||||
comparator: Callable[[AURPackage], tuple[str, str]] =\
|
comparator: Callable[[AURPackage], tuple[str, str]] =\
|
||||||
lambda package: (getattr(package, sort_by), package.name)
|
lambda package: (getattr(package, sort_by), package.name)
|
||||||
return sorted(packages, key=comparator)
|
return sorted(packages, key=comparator)
|
||||||
|
|
||||||
|
arguments = [_set_aur_search_parser]
|
||||||
|
@ -34,24 +34,6 @@ class ServiceUpdates(Handler):
|
|||||||
|
|
||||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
|
||||||
"""
|
|
||||||
add parser(s) for the subcommand
|
|
||||||
|
|
||||||
Args:
|
|
||||||
root(SubParserAction): subparsers for the commands
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
|
||||||
"""
|
|
||||||
parser = root.add_parser("help-updates", help="check for service updates",
|
|
||||||
description="request AUR for current version and compare with current service version")
|
|
||||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit code if updates available",
|
|
||||||
action="store_true")
|
|
||||||
parser.set_defaults(architecture="", lock=None, quiet=True, report=False, repository="", unsafe=True)
|
|
||||||
return [parser]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
report: bool) -> None:
|
report: bool) -> None:
|
||||||
@ -76,3 +58,23 @@ class ServiceUpdates(Handler):
|
|||||||
|
|
||||||
UpdatePrinter(remote, local_version)(verbose=True, separator=" -> ")
|
UpdatePrinter(remote, local_version)(verbose=True, separator=" -> ")
|
||||||
ServiceUpdates.check_status(args.exit_code, same_version)
|
ServiceUpdates.check_status(args.exit_code, same_version)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _set_help_updates_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
|
"""
|
||||||
|
add parser for service update check subcommand
|
||||||
|
|
||||||
|
Args:
|
||||||
|
root(SubParserAction): subparsers for the commands
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
argparse.ArgumentParser: created argument parser
|
||||||
|
"""
|
||||||
|
parser = root.add_parser("help-updates", help="check for service updates",
|
||||||
|
description="request AUR for current version and compare with current service version")
|
||||||
|
parser.add_argument("-e", "--exit-code", help="return non-zero exit code if updates available",
|
||||||
|
action="store_true")
|
||||||
|
parser.set_defaults(architecture="", lock=None, quiet=True, report=False, repository="", unsafe=True)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
arguments = [_set_help_updates_parser]
|
||||||
|
@ -50,44 +50,6 @@ class Setup(Handler):
|
|||||||
MIRRORLIST_PATH = Path("/") / "etc" / "pacman.d" / "mirrorlist"
|
MIRRORLIST_PATH = Path("/") / "etc" / "pacman.d" / "mirrorlist"
|
||||||
SUDOERS_DIR_PATH = Path("/") / "etc" / "sudoers.d"
|
SUDOERS_DIR_PATH = Path("/") / "etc" / "sudoers.d"
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
|
||||||
"""
|
|
||||||
add parser(s) for the subcommand
|
|
||||||
|
|
||||||
Args:
|
|
||||||
root(SubParserAction): subparsers for the commands
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
|
||||||
"""
|
|
||||||
parser = root.add_parser("service-setup", aliases=["init", "repo-init", "repo-setup", "setup"],
|
|
||||||
help="initial service configuration",
|
|
||||||
description="create initial service configuration, requires root",
|
|
||||||
epilog="Create minimal configuration for the service according to provided options.")
|
|
||||||
parser.add_argument("--build-as-user", help="force makepkg user to the specific one")
|
|
||||||
parser.add_argument("--from-configuration", help="path to default devtools pacman configuration",
|
|
||||||
type=Path,
|
|
||||||
default=Path("/") / "usr" / "share" / "devtools" / "pacman.conf.d" / "extra.conf")
|
|
||||||
parser.add_argument("--generate-salt", help="generate salt for user passwords",
|
|
||||||
action=argparse.BooleanOptionalAction, default=False)
|
|
||||||
parser.add_argument("--makeflags-jobs",
|
|
||||||
help="append MAKEFLAGS variable with parallelism set to number of cores",
|
|
||||||
action=argparse.BooleanOptionalAction, default=True)
|
|
||||||
parser.add_argument("--mirror", help="use the specified explicitly mirror instead of including mirrorlist")
|
|
||||||
parser.add_argument("--multilib", help="add or do not multilib repository",
|
|
||||||
action=argparse.BooleanOptionalAction, default=True)
|
|
||||||
parser.add_argument("--packager", help="packager name and email", required=True)
|
|
||||||
parser.add_argument("--server", help="server to be used for devtools. If none set, local files will be used")
|
|
||||||
parser.add_argument("--sign-key", help="sign key id")
|
|
||||||
parser.add_argument("--sign-target", help="sign options", action="append",
|
|
||||||
type=SignSettings.from_option, choices=enum_values(SignSettings))
|
|
||||||
parser.add_argument("--web-port", help="port of the web service", type=int)
|
|
||||||
parser.add_argument("--web-unix-socket", help="path to unix socket used for interprocess communications",
|
|
||||||
type=Path)
|
|
||||||
parser.set_defaults(lock=None, quiet=True, report=False, unsafe=True)
|
|
||||||
return [parser]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
report: bool) -> None:
|
report: bool) -> None:
|
||||||
@ -120,6 +82,44 @@ class Setup(Handler):
|
|||||||
# lazy database sync
|
# lazy database sync
|
||||||
application.repository.pacman.handle # pylint: disable=pointless-statement
|
application.repository.pacman.handle # pylint: disable=pointless-statement
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _set_service_setup_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
|
"""
|
||||||
|
add parser for setup subcommand
|
||||||
|
|
||||||
|
Args:
|
||||||
|
root(SubParserAction): subparsers for the commands
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
argparse.ArgumentParser: created argument parser
|
||||||
|
"""
|
||||||
|
parser = root.add_parser("service-setup", aliases=["init", "repo-init", "repo-setup", "setup"],
|
||||||
|
help="initial service configuration",
|
||||||
|
description="create initial service configuration, requires root",
|
||||||
|
epilog="Create minimal configuration for the service according to provided options.")
|
||||||
|
parser.add_argument("--build-as-user", help="force makepkg user to the specific one")
|
||||||
|
parser.add_argument("--from-configuration", help="path to default devtools pacman configuration",
|
||||||
|
type=Path,
|
||||||
|
default=Path("/") / "usr" / "share" / "devtools" / "pacman.conf.d" / "extra.conf")
|
||||||
|
parser.add_argument("--generate-salt", help="generate salt for user passwords",
|
||||||
|
action=argparse.BooleanOptionalAction, default=False)
|
||||||
|
parser.add_argument("--makeflags-jobs",
|
||||||
|
help="append MAKEFLAGS variable with parallelism set to number of cores",
|
||||||
|
action=argparse.BooleanOptionalAction, default=True)
|
||||||
|
parser.add_argument("--mirror", help="use the specified explicitly mirror instead of including mirrorlist")
|
||||||
|
parser.add_argument("--multilib", help="add or do not multilib repository",
|
||||||
|
action=argparse.BooleanOptionalAction, default=True)
|
||||||
|
parser.add_argument("--packager", help="packager name and email", required=True)
|
||||||
|
parser.add_argument("--server", help="server to be used for devtools. If none set, local files will be used")
|
||||||
|
parser.add_argument("--sign-key", help="sign key id")
|
||||||
|
parser.add_argument("--sign-target", help="sign options", action="append",
|
||||||
|
type=SignSettings.from_option, choices=enum_values(SignSettings))
|
||||||
|
parser.add_argument("--web-port", help="port of the web service", type=int)
|
||||||
|
parser.add_argument("--web-unix-socket", help="path to unix socket used for interprocess communications",
|
||||||
|
type=Path)
|
||||||
|
parser.set_defaults(lock=None, quiet=True, report=False, unsafe=True)
|
||||||
|
return parser
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def build_command(root: Path, repository_id: RepositoryId) -> Path:
|
def build_command(root: Path, repository_id: RepositoryId) -> Path:
|
||||||
"""
|
"""
|
||||||
@ -280,3 +280,5 @@ class Setup(Handler):
|
|||||||
command.unlink(missing_ok=True)
|
command.unlink(missing_ok=True)
|
||||||
command.symlink_to(Setup.ARCHBUILD_COMMAND_PATH)
|
command.symlink_to(Setup.ARCHBUILD_COMMAND_PATH)
|
||||||
paths.chown(command) # we would like to keep owner inside ahriman's home
|
paths.chown(command) # we would like to keep owner inside ahriman's home
|
||||||
|
|
||||||
|
arguments = [_set_service_setup_parser]
|
||||||
|
@ -36,24 +36,6 @@ class Shell(Handler):
|
|||||||
|
|
||||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io
|
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
|
||||||
"""
|
|
||||||
add parser(s) for the subcommand
|
|
||||||
|
|
||||||
Args:
|
|
||||||
root(SubParserAction): subparsers for the commands
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
|
||||||
"""
|
|
||||||
parser = root.add_parser("service-shell", aliases=["shell"], help="invoke python shell",
|
|
||||||
description="drop into python shell")
|
|
||||||
parser.add_argument("code", help="instead of dropping into shell, just execute the specified code", nargs="?")
|
|
||||||
parser.add_argument("-v", "--verbose", help=argparse.SUPPRESS, action="store_true")
|
|
||||||
parser.set_defaults(lock=None, report=False)
|
|
||||||
return [parser]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
report: bool) -> None:
|
report: bool) -> None:
|
||||||
@ -81,3 +63,23 @@ class Shell(Handler):
|
|||||||
code.interact(local=local_variables)
|
code.interact(local=local_variables)
|
||||||
else:
|
else:
|
||||||
code.InteractiveConsole(locals=local_variables).runcode(args.code)
|
code.InteractiveConsole(locals=local_variables).runcode(args.code)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _set_service_shell_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
|
"""
|
||||||
|
add parser for shell subcommand
|
||||||
|
|
||||||
|
Args:
|
||||||
|
root(SubParserAction): subparsers for the commands
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
argparse.ArgumentParser: created argument parser
|
||||||
|
"""
|
||||||
|
parser = root.add_parser("service-shell", aliases=["shell"], help="invoke python shell",
|
||||||
|
description="drop into python shell")
|
||||||
|
parser.add_argument("code", help="instead of dropping into shell, just execute the specified code", nargs="?")
|
||||||
|
parser.add_argument("-v", "--verbose", help=argparse.SUPPRESS, action="store_true")
|
||||||
|
parser.set_defaults(lock=None, report=False)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
arguments = [_set_service_shell_parser]
|
||||||
|
@ -30,23 +30,6 @@ class Sign(Handler):
|
|||||||
(re-)sign handler
|
(re-)sign handler
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
|
||||||
"""
|
|
||||||
add parser(s) for the subcommand
|
|
||||||
|
|
||||||
Args:
|
|
||||||
root(SubParserAction): subparsers for the commands
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
|
||||||
"""
|
|
||||||
parser = root.add_parser("repo-sign", aliases=["sign"], help="sign packages",
|
|
||||||
description="(re-)sign packages and repository database according to current settings",
|
|
||||||
epilog="Sign repository and/or packages as configured.")
|
|
||||||
parser.add_argument("package", help="sign only specified packages", nargs="*")
|
|
||||||
return [parser]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
report: bool) -> None:
|
report: bool) -> None:
|
||||||
@ -60,3 +43,22 @@ class Sign(Handler):
|
|||||||
report(bool): force enable or disable reporting
|
report(bool): force enable or disable reporting
|
||||||
"""
|
"""
|
||||||
Application(repository_id, configuration, report=report).sign(args.package)
|
Application(repository_id, configuration, report=report).sign(args.package)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _set_repo_sign_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
|
"""
|
||||||
|
add parser for sign subcommand
|
||||||
|
|
||||||
|
Args:
|
||||||
|
root(SubParserAction): subparsers for the commands
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
argparse.ArgumentParser: created argument parser
|
||||||
|
"""
|
||||||
|
parser = root.add_parser("repo-sign", aliases=["sign"], help="sign packages",
|
||||||
|
description="(re-)sign packages and repository database according to current settings",
|
||||||
|
epilog="Sign repository and/or packages as configured.")
|
||||||
|
parser.add_argument("package", help="sign only specified packages", nargs="*")
|
||||||
|
return parser
|
||||||
|
|
||||||
|
arguments = [_set_repo_sign_parser]
|
||||||
|
@ -40,30 +40,6 @@ class Statistics(Handler):
|
|||||||
|
|
||||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io
|
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
|
||||||
"""
|
|
||||||
add parser(s) for the subcommand
|
|
||||||
|
|
||||||
Args:
|
|
||||||
root(SubParserAction): subparsers for the commands
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
|
||||||
"""
|
|
||||||
parser = root.add_parser("repo-statistics", help="repository statistics",
|
|
||||||
description="fetch repository statistics")
|
|
||||||
parser.add_argument("package", help="fetch only events for the specified package", nargs="?")
|
|
||||||
parser.add_argument("--chart", help="create updates chart and save it to the specified path", type=Path)
|
|
||||||
parser.add_argument("-e", "--event", help="event type filter",
|
|
||||||
type=EventType, choices=enum_values(EventType), default=EventType.PackageUpdated)
|
|
||||||
parser.add_argument("--from-date", help="only fetch events which are newer than the date")
|
|
||||||
parser.add_argument("--limit", help="limit response by specified amount of events", type=int, default=-1)
|
|
||||||
parser.add_argument("--offset", help="skip specified amount of events", type=int, default=0)
|
|
||||||
parser.add_argument("--to-date", help="only fetch events which are older than the date")
|
|
||||||
parser.set_defaults(lock=None, quiet=True, report=False, unsafe=True)
|
|
||||||
return [parser]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
report: bool) -> None:
|
report: bool) -> None:
|
||||||
@ -92,6 +68,30 @@ class Statistics(Handler):
|
|||||||
case _:
|
case _:
|
||||||
Statistics.stats_for_package(args.event, events, args.chart)
|
Statistics.stats_for_package(args.event, events, args.chart)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _set_repo_statistics_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
|
"""
|
||||||
|
add parser for repository statistics subcommand
|
||||||
|
|
||||||
|
Args:
|
||||||
|
root(SubParserAction): subparsers for the commands
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
argparse.ArgumentParser: created argument parser
|
||||||
|
"""
|
||||||
|
parser = root.add_parser("repo-statistics", help="repository statistics",
|
||||||
|
description="fetch repository statistics")
|
||||||
|
parser.add_argument("package", help="fetch only events for the specified package", nargs="?")
|
||||||
|
parser.add_argument("--chart", help="create updates chart and save it to the specified path", type=Path)
|
||||||
|
parser.add_argument("-e", "--event", help="event type filter",
|
||||||
|
type=EventType, choices=enum_values(EventType), default=EventType.PackageUpdated)
|
||||||
|
parser.add_argument("--from-date", help="only fetch events which are newer than the date")
|
||||||
|
parser.add_argument("--limit", help="limit response by specified amount of events", type=int, default=-1)
|
||||||
|
parser.add_argument("--offset", help="skip specified amount of events", type=int, default=0)
|
||||||
|
parser.add_argument("--to-date", help="only fetch events which are older than the date")
|
||||||
|
parser.set_defaults(lock=None, quiet=True, report=False, unsafe=True)
|
||||||
|
return parser
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def event_stats(event_type: str, events: list[Event]) -> None:
|
def event_stats(event_type: str, events: list[Event]) -> None:
|
||||||
"""
|
"""
|
||||||
@ -192,3 +192,5 @@ class Statistics(Handler):
|
|||||||
# chart if enabled
|
# chart if enabled
|
||||||
if chart_path is not None:
|
if chart_path is not None:
|
||||||
Statistics.plot_packages(event_type, by_object_id, chart_path)
|
Statistics.plot_packages(event_type, by_object_id, chart_path)
|
||||||
|
|
||||||
|
arguments = [_set_repo_statistics_parser]
|
||||||
|
@ -38,32 +38,6 @@ class Status(Handler):
|
|||||||
|
|
||||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io
|
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
|
||||||
"""
|
|
||||||
add parser(s) for the subcommand
|
|
||||||
|
|
||||||
Args:
|
|
||||||
root(SubParserAction): subparsers for the commands
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
|
||||||
"""
|
|
||||||
parser = root.add_parser("package-status", aliases=["status"], help="get package status",
|
|
||||||
description="request status of the package",
|
|
||||||
epilog="This command requests package status from the web interface "
|
|
||||||
"if it is available.")
|
|
||||||
parser.add_argument("package", help="filter status by package base", nargs="*")
|
|
||||||
parser.add_argument("--ahriman", help="get service status itself", 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("--info", help="show additional package information",
|
|
||||||
action=argparse.BooleanOptionalAction, default=False)
|
|
||||||
parser.add_argument("-s", "--status", help="filter packages by status",
|
|
||||||
type=BuildStatusEnum, choices=enum_values(BuildStatusEnum))
|
|
||||||
parser.set_defaults(lock=None, quiet=True, report=False, unsafe=True)
|
|
||||||
return [parser]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
report: bool) -> None:
|
report: bool) -> None:
|
||||||
@ -95,3 +69,31 @@ class Status(Handler):
|
|||||||
lambda item: args.status is None or item[1].status == args.status
|
lambda item: args.status is None or item[1].status == args.status
|
||||||
for package, package_status in sorted(filter(filter_fn, packages), key=comparator):
|
for package, package_status in sorted(filter(filter_fn, packages), key=comparator):
|
||||||
PackagePrinter(package, package_status)(verbose=args.info)
|
PackagePrinter(package, package_status)(verbose=args.info)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _set_package_status_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
|
"""
|
||||||
|
add parser for package status subcommand
|
||||||
|
|
||||||
|
Args:
|
||||||
|
root(SubParserAction): subparsers for the commands
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
argparse.ArgumentParser: created argument parser
|
||||||
|
"""
|
||||||
|
parser = root.add_parser("package-status", aliases=["status"], help="get package status",
|
||||||
|
description="request status of the package",
|
||||||
|
epilog="This command requests package status from the web interface "
|
||||||
|
"if it is available.")
|
||||||
|
parser.add_argument("package", help="filter status by package base", nargs="*")
|
||||||
|
parser.add_argument("--ahriman", help="get service status itself", 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("--info", help="show additional package information",
|
||||||
|
action=argparse.BooleanOptionalAction, default=False)
|
||||||
|
parser.add_argument("-s", "--status", help="filter packages by status",
|
||||||
|
type=BuildStatusEnum, choices=enum_values(BuildStatusEnum))
|
||||||
|
parser.set_defaults(lock=None, quiet=True, report=False, unsafe=True)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
arguments = [_set_package_status_parser]
|
||||||
|
@ -35,23 +35,6 @@ class StatusUpdate(Handler):
|
|||||||
|
|
||||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io
|
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
|
||||||
"""
|
|
||||||
add parser(s) for the subcommand
|
|
||||||
|
|
||||||
Args:
|
|
||||||
root(SubParserAction): subparsers for the commands
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
|
||||||
"""
|
|
||||||
return [
|
|
||||||
cls._set_package_status_remove_parser(root),
|
|
||||||
cls._set_package_status_update_parser(root),
|
|
||||||
cls._set_repo_status_update_parser(root),
|
|
||||||
]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
report: bool) -> None:
|
report: bool) -> None:
|
||||||
@ -136,3 +119,9 @@ class StatusUpdate(Handler):
|
|||||||
type=BuildStatusEnum, choices=enum_values(BuildStatusEnum), default=BuildStatusEnum.Success)
|
type=BuildStatusEnum, choices=enum_values(BuildStatusEnum), default=BuildStatusEnum.Success)
|
||||||
parser.set_defaults(action=Action.Update, lock=None, package=[], quiet=True, report=False, unsafe=True)
|
parser.set_defaults(action=Action.Update, lock=None, package=[], quiet=True, report=False, unsafe=True)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
arguments = [
|
||||||
|
_set_package_status_remove_parser,
|
||||||
|
_set_package_status_update_parser,
|
||||||
|
_set_repo_status_update_parser,
|
||||||
|
]
|
||||||
|
@ -34,24 +34,6 @@ class Structure(Handler):
|
|||||||
|
|
||||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io
|
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
|
||||||
"""
|
|
||||||
add parser(s) for the subcommand
|
|
||||||
|
|
||||||
Args:
|
|
||||||
root(SubParserAction): subparsers for the commands
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
|
||||||
"""
|
|
||||||
parser = root.add_parser("repo-tree", help="dump repository tree",
|
|
||||||
description="dump repository tree based on packages dependencies")
|
|
||||||
parser.add_argument("-p", "--partitions", help="also divide packages by independent partitions",
|
|
||||||
type=int, default=1)
|
|
||||||
parser.set_defaults(lock=None, quiet=True, report=False, unsafe=True)
|
|
||||||
return [parser]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
report: bool) -> None:
|
report: bool) -> None:
|
||||||
@ -76,3 +58,23 @@ class Structure(Handler):
|
|||||||
|
|
||||||
# empty line
|
# empty line
|
||||||
StringPrinter("")(verbose=False)
|
StringPrinter("")(verbose=False)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _set_repo_tree_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
|
"""
|
||||||
|
add parser for repository tree subcommand
|
||||||
|
|
||||||
|
Args:
|
||||||
|
root(SubParserAction): subparsers for the commands
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
argparse.ArgumentParser: created argument parser
|
||||||
|
"""
|
||||||
|
parser = root.add_parser("repo-tree", help="dump repository tree",
|
||||||
|
description="dump repository tree based on packages dependencies")
|
||||||
|
parser.add_argument("-p", "--partitions", help="also divide packages by independent partitions",
|
||||||
|
type=int, default=1)
|
||||||
|
parser.set_defaults(lock=None, quiet=True, report=False, unsafe=True)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
arguments = [_set_repo_tree_parser]
|
||||||
|
@ -30,22 +30,6 @@ class TreeMigrate(Handler):
|
|||||||
tree migration handler
|
tree migration handler
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
|
||||||
"""
|
|
||||||
add parser(s) for the subcommand
|
|
||||||
|
|
||||||
Args:
|
|
||||||
root(SubParserAction): subparsers for the commands
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
|
||||||
"""
|
|
||||||
parser = root.add_parser("service-tree-migrate", help="migrate repository tree",
|
|
||||||
description="migrate repository tree between versions")
|
|
||||||
parser.set_defaults(lock=None, quiet=True, report=False)
|
|
||||||
return [parser]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
report: bool) -> None:
|
report: bool) -> None:
|
||||||
@ -66,6 +50,22 @@ class TreeMigrate(Handler):
|
|||||||
# perform migration
|
# perform migration
|
||||||
TreeMigrate.tree_move(current_tree, target_tree)
|
TreeMigrate.tree_move(current_tree, target_tree)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
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")
|
||||||
|
parser.set_defaults(lock=None, quiet=True, report=False)
|
||||||
|
return parser
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def tree_move(from_tree: RepositoryPaths, to_tree: RepositoryPaths) -> None:
|
def tree_move(from_tree: RepositoryPaths, to_tree: RepositoryPaths) -> None:
|
||||||
"""
|
"""
|
||||||
@ -82,3 +82,5 @@ class TreeMigrate(Handler):
|
|||||||
RepositoryPaths.repository,
|
RepositoryPaths.repository,
|
||||||
):
|
):
|
||||||
attribute.fget(from_tree).rename(attribute.fget(to_tree)) # type: ignore[attr-defined]
|
attribute.fget(from_tree).rename(attribute.fget(to_tree)) # type: ignore[attr-defined]
|
||||||
|
|
||||||
|
arguments = [_set_service_tree_migrate_parser]
|
||||||
|
@ -31,25 +31,6 @@ class Triggers(Handler):
|
|||||||
triggers handlers
|
triggers handlers
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
|
||||||
"""
|
|
||||||
add parser(s) for the subcommand
|
|
||||||
|
|
||||||
Args:
|
|
||||||
root(SubParserAction): subparsers for the commands
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
|
||||||
"""
|
|
||||||
return [
|
|
||||||
cls._set_repo_create_keyring_parser(root),
|
|
||||||
cls._set_repo_create_mirrorlist_parser(root),
|
|
||||||
cls._set_repo_report_parser(root),
|
|
||||||
cls._set_repo_sync_parser(root),
|
|
||||||
cls._set_repo_triggers_parser(root),
|
|
||||||
]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
report: bool) -> None:
|
report: bool) -> None:
|
||||||
@ -155,3 +136,11 @@ class Triggers(Handler):
|
|||||||
parser.add_argument("trigger", help="instead of running all triggers as set by configuration, just process "
|
parser.add_argument("trigger", help="instead of running all triggers as set by configuration, just process "
|
||||||
"specified ones in order of mention", nargs="*")
|
"specified ones in order of mention", nargs="*")
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
arguments = [
|
||||||
|
_set_repo_create_keyring_parser,
|
||||||
|
_set_repo_create_mirrorlist_parser,
|
||||||
|
_set_repo_report_parser,
|
||||||
|
_set_repo_sync_parser,
|
||||||
|
_set_repo_triggers_parser,
|
||||||
|
]
|
||||||
|
@ -32,25 +32,6 @@ class UnsafeCommands(Handler):
|
|||||||
|
|
||||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
|
||||||
"""
|
|
||||||
add parser(s) for the subcommand
|
|
||||||
|
|
||||||
Args:
|
|
||||||
root(SubParserAction): subparsers for the commands
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
|
||||||
"""
|
|
||||||
parser = root.add_parser("help-commands-unsafe", help="list unsafe commands",
|
|
||||||
description="list unsafe commands as defined in default args")
|
|
||||||
parser.add_argument("subcommand",
|
|
||||||
help="instead of showing commands, just test command line for unsafe subcommand "
|
|
||||||
"and return 0 in case if command is safe and 1 otherwise", nargs="*")
|
|
||||||
parser.set_defaults(architecture="", lock=None, quiet=True, report=False, repository="", unsafe=True)
|
|
||||||
return [parser]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
report: bool) -> None:
|
report: bool) -> None:
|
||||||
@ -71,6 +52,25 @@ class UnsafeCommands(Handler):
|
|||||||
for command in unsafe_commands:
|
for command in unsafe_commands:
|
||||||
StringPrinter(command)(verbose=True)
|
StringPrinter(command)(verbose=True)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _set_help_commands_unsafe_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
|
"""
|
||||||
|
add parser for listing unsafe commands
|
||||||
|
|
||||||
|
Args:
|
||||||
|
root(SubParserAction): subparsers for the commands
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
argparse.ArgumentParser: created argument parser
|
||||||
|
"""
|
||||||
|
parser = root.add_parser("help-commands-unsafe", help="list unsafe commands",
|
||||||
|
description="list unsafe commands as defined in default args")
|
||||||
|
parser.add_argument("subcommand",
|
||||||
|
help="instead of showing commands, just test command line for unsafe subcommand "
|
||||||
|
"and return 0 in case if command is safe and 1 otherwise", nargs="*")
|
||||||
|
parser.set_defaults(architecture="", lock=None, quiet=True, report=False, repository="", unsafe=True)
|
||||||
|
return parser
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def check_unsafe(command: list[str], unsafe_commands: list[str], parser: argparse.ArgumentParser) -> None:
|
def check_unsafe(command: list[str], unsafe_commands: list[str], parser: argparse.ArgumentParser) -> None:
|
||||||
"""
|
"""
|
||||||
@ -100,3 +100,5 @@ class UnsafeCommands(Handler):
|
|||||||
subparser = next((action for action in parser._actions if isinstance(action, argparse._SubParsersAction)), None)
|
subparser = next((action for action in parser._actions if isinstance(action, argparse._SubParsersAction)), None)
|
||||||
actions = subparser.choices if subparser is not None else {}
|
actions = subparser.choices if subparser is not None else {}
|
||||||
return sorted(action_name for action_name, action in actions.items() if action.get_default("unsafe"))
|
return sorted(action_name for action_name, action in actions.items() if action.get_default("unsafe"))
|
||||||
|
|
||||||
|
arguments = [_set_help_commands_unsafe_parser]
|
||||||
|
@ -34,19 +34,6 @@ class Update(Handler):
|
|||||||
package update handler
|
package update handler
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
|
||||||
"""
|
|
||||||
add parser(s) for the subcommand
|
|
||||||
|
|
||||||
Args:
|
|
||||||
root(SubParserAction): subparsers for the commands
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
|
||||||
"""
|
|
||||||
return [cls._set_repo_check_parser(root), cls._set_repo_update_parser(root)]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
report: bool) -> None:
|
report: bool) -> None:
|
||||||
@ -165,3 +152,8 @@ class Update(Handler):
|
|||||||
def inner(line: str) -> None:
|
def inner(line: str) -> None:
|
||||||
return print(line) if dry_run else application.logger.info(line) # pylint: disable=bad-builtin
|
return print(line) if dry_run else application.logger.info(line) # pylint: disable=bad-builtin
|
||||||
return inner
|
return inner
|
||||||
|
|
||||||
|
arguments = [
|
||||||
|
_set_repo_check_parser,
|
||||||
|
_set_repo_update_parser,
|
||||||
|
]
|
||||||
|
@ -39,23 +39,6 @@ class Users(Handler):
|
|||||||
|
|
||||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
|
||||||
"""
|
|
||||||
add parser(s) for the subcommand
|
|
||||||
|
|
||||||
Args:
|
|
||||||
root(SubParserAction): subparsers for the commands
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
|
||||||
"""
|
|
||||||
return [
|
|
||||||
cls._set_user_add_parser(root),
|
|
||||||
cls._set_user_list_parser(root),
|
|
||||||
cls._set_user_remove_parser(root),
|
|
||||||
]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
report: bool) -> None:
|
report: bool) -> None:
|
||||||
@ -178,3 +161,9 @@ class Users(Handler):
|
|||||||
|
|
||||||
return User(username=args.username, password=password, access=args.role,
|
return User(username=args.username, password=password, access=args.role,
|
||||||
packager_id=args.packager, key=args.key)
|
packager_id=args.packager, key=args.key)
|
||||||
|
|
||||||
|
arguments = [
|
||||||
|
_set_user_add_parser,
|
||||||
|
_set_user_list_parser,
|
||||||
|
_set_user_remove_parser,
|
||||||
|
]
|
||||||
|
@ -38,25 +38,6 @@ class Validate(Handler):
|
|||||||
|
|
||||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io
|
ALLOW_MULTI_ARCHITECTURE_RUN = False # conflicting io
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
|
||||||
"""
|
|
||||||
add parser(s) for the subcommand
|
|
||||||
|
|
||||||
Args:
|
|
||||||
root(SubParserAction): subparsers for the commands
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
|
||||||
"""
|
|
||||||
parser = root.add_parser("service-config-validate", aliases=["config-validate", "repo-config-validate"],
|
|
||||||
help="validate system configuration",
|
|
||||||
description="validate configuration and print found errors")
|
|
||||||
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if configuration is invalid",
|
|
||||||
action="store_true")
|
|
||||||
parser.set_defaults(lock=None, quiet=True, report=False, unsafe=True)
|
|
||||||
return [parser]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
report: bool) -> None:
|
report: bool) -> None:
|
||||||
@ -82,6 +63,25 @@ class Validate(Handler):
|
|||||||
# as we reach this part it means that we always have errors
|
# as we reach this part it means that we always have errors
|
||||||
Validate.check_status(args.exit_code, False)
|
Validate.check_status(args.exit_code, False)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _set_service_config_validate_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
|
"""
|
||||||
|
add parser for config validation subcommand
|
||||||
|
|
||||||
|
Args:
|
||||||
|
root(SubParserAction): subparsers for the commands
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
argparse.ArgumentParser: created argument parser
|
||||||
|
"""
|
||||||
|
parser = root.add_parser("service-config-validate", aliases=["config-validate", "repo-config-validate"],
|
||||||
|
help="validate system configuration",
|
||||||
|
description="validate configuration and print found errors")
|
||||||
|
parser.add_argument("-e", "--exit-code", help="return non-zero exit status if configuration is invalid",
|
||||||
|
action="store_true")
|
||||||
|
parser.set_defaults(lock=None, quiet=True, report=False, unsafe=True)
|
||||||
|
return parser
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def schema(repository_id: RepositoryId, configuration: Configuration) -> ConfigurationSchema:
|
def schema(repository_id: RepositoryId, configuration: Configuration) -> ConfigurationSchema:
|
||||||
"""
|
"""
|
||||||
@ -155,3 +155,5 @@ class Validate(Handler):
|
|||||||
Validate.schema_merge(value, schema[key])
|
Validate.schema_merge(value, schema[key])
|
||||||
|
|
||||||
return schema
|
return schema
|
||||||
|
|
||||||
|
arguments = [_set_service_config_validate_parser]
|
||||||
|
@ -42,22 +42,6 @@ class Versions(Handler):
|
|||||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
||||||
PEP423_PACKAGE_NAME = re.compile(r"^[A-Za-z0-9._-]+")
|
PEP423_PACKAGE_NAME = re.compile(r"^[A-Za-z0-9._-]+")
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
|
||||||
"""
|
|
||||||
add parser(s) for the subcommand
|
|
||||||
|
|
||||||
Args:
|
|
||||||
root(SubParserAction): subparsers for the commands
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
|
||||||
"""
|
|
||||||
parser = root.add_parser("help-version", aliases=["version"], help="application version",
|
|
||||||
description="print application and its dependencies versions")
|
|
||||||
parser.set_defaults(architecture="", lock=None, quiet=True, report=False, repository="", unsafe=True)
|
|
||||||
return [parser]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
report: bool) -> None:
|
report: bool) -> None:
|
||||||
@ -75,6 +59,22 @@ class Versions(Handler):
|
|||||||
packages = Versions.package_dependencies("ahriman")
|
packages = Versions.package_dependencies("ahriman")
|
||||||
VersionPrinter("Installed packages", dict(packages))(verbose=False, separator=" ")
|
VersionPrinter("Installed packages", dict(packages))(verbose=False, separator=" ")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _set_help_version_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
|
"""
|
||||||
|
add parser for version subcommand
|
||||||
|
|
||||||
|
Args:
|
||||||
|
root(SubParserAction): subparsers for the commands
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
argparse.ArgumentParser: created argument parser
|
||||||
|
"""
|
||||||
|
parser = root.add_parser("help-version", aliases=["version"], help="application version",
|
||||||
|
description="print application and its dependencies versions")
|
||||||
|
parser.set_defaults(architecture="", lock=None, quiet=True, report=False, repository="", unsafe=True)
|
||||||
|
return parser
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def package_dependencies(root: str) -> Generator[tuple[str, str], None, None]:
|
def package_dependencies(root: str) -> Generator[tuple[str, str], None, None]:
|
||||||
"""
|
"""
|
||||||
@ -112,3 +112,5 @@ class Versions(Handler):
|
|||||||
yield distribution.name, distribution.version
|
yield distribution.name, distribution.version
|
||||||
except metadata.PackageNotFoundError:
|
except metadata.PackageNotFoundError:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
arguments = [_set_help_version_parser]
|
||||||
|
@ -36,21 +36,6 @@ class Web(Handler):
|
|||||||
|
|
||||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def arguments(cls, root: SubParserAction) -> list[argparse.ArgumentParser]:
|
|
||||||
"""
|
|
||||||
add parser(s) for the subcommand
|
|
||||||
|
|
||||||
Args:
|
|
||||||
root(SubParserAction): subparsers for the commands
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
list[argparse.ArgumentParser]: created argument parser
|
|
||||||
"""
|
|
||||||
parser = root.add_parser("web", help="web server", description="start web server")
|
|
||||||
parser.set_defaults(architecture="", lock=Path("ahriman-web.pid"), report=False, repository="")
|
|
||||||
return [parser]
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||||
report: bool) -> None:
|
report: bool) -> None:
|
||||||
@ -87,6 +72,21 @@ class Web(Handler):
|
|||||||
spawner.stop()
|
spawner.stop()
|
||||||
spawner.join()
|
spawner.join()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _set_web_parser(root: SubParserAction) -> argparse.ArgumentParser:
|
||||||
|
"""
|
||||||
|
add parser for web subcommand
|
||||||
|
|
||||||
|
Args:
|
||||||
|
root(SubParserAction): subparsers for the commands
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
argparse.ArgumentParser: created argument parser
|
||||||
|
"""
|
||||||
|
parser = root.add_parser("web", help="web server", description="start web server")
|
||||||
|
parser.set_defaults(architecture="", lock=Path("ahriman-web.pid"), report=False, repository="")
|
||||||
|
return parser
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def extract_arguments(args: argparse.Namespace, configuration: Configuration) -> Generator[str, None, None]:
|
def extract_arguments(args: argparse.Namespace, configuration: Configuration) -> Generator[str, None, None]:
|
||||||
"""
|
"""
|
||||||
@ -116,3 +116,5 @@ class Web(Handler):
|
|||||||
# arguments from configuration
|
# arguments from configuration
|
||||||
if (wait_timeout := configuration.getint("web", "wait_timeout", fallback=None)) is not None:
|
if (wait_timeout := configuration.getint("web", "wait_timeout", fallback=None)) is not None:
|
||||||
yield from ["--wait-timeout", str(wait_timeout)]
|
yield from ["--wait-timeout", str(wait_timeout)]
|
||||||
|
|
||||||
|
arguments = [_set_web_parser]
|
||||||
|
@ -17,8 +17,9 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
import bcrypt
|
||||||
|
|
||||||
from dataclasses import dataclass, replace
|
from dataclasses import dataclass, replace
|
||||||
from passlib.hash import sha512_crypt
|
|
||||||
from secrets import token_urlsafe as generate_password
|
from secrets import token_urlsafe as generate_password
|
||||||
from typing import Self
|
from typing import Self
|
||||||
|
|
||||||
@ -67,8 +68,6 @@ class User:
|
|||||||
packager_id: str | None = None
|
packager_id: str | None = None
|
||||||
key: str | None = None
|
key: str | None = None
|
||||||
|
|
||||||
_HASHER = sha512_crypt
|
|
||||||
|
|
||||||
def __post_init__(self) -> None:
|
def __post_init__(self) -> None:
|
||||||
"""
|
"""
|
||||||
remove empty fields
|
remove empty fields
|
||||||
@ -101,10 +100,9 @@ class User:
|
|||||||
bool: ``True`` in case if password matches, ``False`` otherwise
|
bool: ``True`` in case if password matches, ``False`` otherwise
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
verified: bool = self._HASHER.verify(password + salt, self.password)
|
return bcrypt.checkpw((password + salt).encode("utf8"), self.password.encode("utf8"))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
verified = False # the absence of evidence is not the evidence of absence (c) Gin Rummy
|
return False # the absence of evidence is not the evidence of absence (c) Gin Rummy
|
||||||
return verified
|
|
||||||
|
|
||||||
def hash_password(self, salt: str) -> Self:
|
def hash_password(self, salt: str) -> Self:
|
||||||
"""
|
"""
|
||||||
@ -120,8 +118,8 @@ class User:
|
|||||||
# in case of empty password we leave it empty. This feature is used by any external (like OAuth) provider
|
# in case of empty password we leave it empty. This feature is used by any external (like OAuth) provider
|
||||||
# when we do not store any password here
|
# when we do not store any password here
|
||||||
return self
|
return self
|
||||||
password_hash: str = self._HASHER.hash(self.password + salt)
|
password_hash = bcrypt.hashpw((self.password + salt).encode("utf8"), bcrypt.gensalt())
|
||||||
return replace(self, password=password_hash)
|
return replace(self, password=password_hash.decode("utf8"))
|
||||||
|
|
||||||
def verify_access(self, required: UserAccess) -> bool:
|
def verify_access(self, required: UserAccess) -> bool:
|
||||||
"""
|
"""
|
||||||
|
@ -3,7 +3,6 @@ import pytest
|
|||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from pytest_mock import MockerFixture
|
from pytest_mock import MockerFixture
|
||||||
from unittest.mock import MagicMock
|
|
||||||
|
|
||||||
from ahriman.application.handlers.handler import Handler
|
from ahriman.application.handlers.handler import Handler
|
||||||
from ahriman.core.configuration import Configuration
|
from ahriman.core.configuration import Configuration
|
||||||
@ -12,14 +11,6 @@ from ahriman.models.log_handler import LogHandler
|
|||||||
from ahriman.models.repository_id import RepositoryId
|
from ahriman.models.repository_id import RepositoryId
|
||||||
|
|
||||||
|
|
||||||
def test_arguments() -> None:
|
|
||||||
"""
|
|
||||||
must raise NotImplemented for missing arguments method
|
|
||||||
"""
|
|
||||||
with pytest.raises(NotImplementedError):
|
|
||||||
Handler.arguments(MagicMock())
|
|
||||||
|
|
||||||
|
|
||||||
def test_call(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
|
def test_call(args: argparse.Namespace, configuration: Configuration, mocker: MockerFixture) -> None:
|
||||||
"""
|
"""
|
||||||
must call inside lock
|
must call inside lock
|
||||||
|
Reference in New Issue
Block a user