mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-08-30 21:39: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
|
||||
pacman -Syyu --noconfirm
|
||||
# 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
|
||||
pacman -S --noconfirm --asdeps base-devel python-build python-flit python-installer python-tox python-wheel
|
||||
# optional dependencies
|
||||
|
@ -35,8 +35,8 @@ RUN pacman -S --noconfirm --asdeps \
|
||||
devtools \
|
||||
git \
|
||||
pyalpm \
|
||||
python-bcrypt \
|
||||
python-inflection \
|
||||
python-passlib \
|
||||
python-pyelftools \
|
||||
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.
|
||||
* ``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
|
||||
--------
|
||||
|
@ -34,7 +34,7 @@ Contents
|
||||
configuration
|
||||
command-line
|
||||
faq/index
|
||||
migration
|
||||
migrations/index
|
||||
architecture
|
||||
advanced-usage
|
||||
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
|
||||
^^^^^^^^^
|
||||
---------
|
||||
|
||||
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')
|
||||
url="https://github.com/arcan1s/ahriman"
|
||||
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')
|
||||
optdepends=('python-aioauth-client: web server with OAuth2 authorization'
|
||||
'python-aiohttp: web server'
|
||||
@ -42,9 +42,6 @@ package() {
|
||||
|
||||
python -m installer --destdir="$pkgdir" "dist/$pkgname-$pkgver-py3-none-any.whl"
|
||||
|
||||
# thanks too PEP517, which we all wanted, you need to install data files manually nowadays
|
||||
pushd package && find . \( -type f -or -type l \) -exec install -Dm644 "{}" "$pkgdir/usr/{}" \; && popd
|
||||
|
||||
# keep usr/share configs as reference and copy them to /etc
|
||||
install -Dm644 "$pkgdir/usr/share/$pkgname/settings/ahriman.ini" "$pkgdir/etc/ahriman.ini"
|
||||
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.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;
|
||||
* 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
|
||||
}
|
||||
|
||||
@ -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,
|
||||
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
|
||||
}
|
||||
|
@ -17,8 +17,8 @@ authors = [
|
||||
]
|
||||
|
||||
dependencies = [
|
||||
"bcrypt",
|
||||
"inflection",
|
||||
"passlib",
|
||||
"pyelftools",
|
||||
"requests",
|
||||
]
|
||||
@ -100,3 +100,6 @@ include = [
|
||||
exclude = [
|
||||
"package/archlinux",
|
||||
]
|
||||
|
||||
[tool.flit.external-data]
|
||||
directory = "package"
|
||||
|
@ -89,7 +89,8 @@ Start web service (requires additional configuration):
|
||||
|
||||
handlers_root = Path(__file__).parent / "handlers"
|
||||
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.set_defaults(handler=handler, parser=_parser)
|
||||
|
||||
|
@ -34,50 +34,6 @@ class Add(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
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
@ -112,3 +68,49 @@ class Add(Handler):
|
||||
application.print_updates(packages, log_fn=application.logger.info)
|
||||
result = application.update(packages, packagers, bump_pkgrel=args.increment)
|
||||
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
|
||||
|
||||
@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
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
@ -70,6 +53,23 @@ class Backup(Handler):
|
||||
for backup_path in backup_paths:
|
||||
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
|
||||
def get_paths(configuration: Configuration) -> set[Path]:
|
||||
"""
|
||||
@ -100,3 +100,5 @@ class Backup(Handler):
|
||||
paths.add(gnupg_home)
|
||||
|
||||
return paths
|
||||
|
||||
arguments = [_set_repo_backup_parser]
|
||||
|
@ -35,19 +35,6 @@ class Change(Handler):
|
||||
|
||||
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
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
@ -108,3 +95,5 @@ class Change(Handler):
|
||||
parser.add_argument("package", help="package base")
|
||||
parser.set_defaults(action=Action.Remove, exit_code=False, lock=None, quiet=True, report=False, unsafe=True)
|
||||
return parser
|
||||
|
||||
arguments = [_set_package_changes_parser, _set_package_changes_remove_parser]
|
||||
|
@ -31,15 +31,32 @@ class Clean(Handler):
|
||||
"""
|
||||
|
||||
@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:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
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",
|
||||
description="remove local caches",
|
||||
@ -56,21 +73,6 @@ class Clean(Handler):
|
||||
parser.add_argument("--pacman", help="clear directory with pacman local database cache",
|
||||
action=argparse.BooleanOptionalAction, default=False)
|
||||
parser.set_defaults(lock=None, quiet=True, unsafe=True)
|
||||
return [parser]
|
||||
return parser
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
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)
|
||||
arguments = [_set_service_clean_parser]
|
||||
|
@ -35,26 +35,6 @@ class Copy(Handler):
|
||||
|
||||
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
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
@ -87,6 +67,26 @@ class Copy(Handler):
|
||||
if args.remove:
|
||||
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
|
||||
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)
|
||||
)
|
||||
application.reporter.package_update(package, BuildStatusEnum.Pending)
|
||||
|
||||
arguments = [_set_package_copy_parser]
|
||||
|
@ -36,15 +36,40 @@ class Daemon(Handler):
|
||||
"""
|
||||
|
||||
@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:
|
||||
root(SubParserAction): subparsers for the commands
|
||||
|
||||
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",
|
||||
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",
|
||||
action="count", default=False)
|
||||
parser.set_defaults(exit_code=False, lock=Path("ahriman-daemon.pid"), package=[])
|
||||
return [parser]
|
||||
return parser
|
||||
|
||||
@classmethod
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
"""
|
||||
callback for command line
|
||||
|
||||
Args:
|
||||
args(argparse.Namespace): command line args
|
||||
repository_id(RepositoryId): repository unique identifier
|
||||
configuration(Configuration): configuration instance
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
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)
|
||||
arguments = [_set_repo_daemon_parser]
|
||||
|
@ -32,28 +32,6 @@ class Dump(Handler):
|
||||
|
||||
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
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
@ -81,3 +59,27 @@ class Dump(Handler):
|
||||
case section, key: # key only
|
||||
value = configuration.get(section, key, fallback="")
|
||||
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:
|
||||
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:
|
||||
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
|
||||
|
||||
@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
|
||||
arguments: list[Callable[[SubParserAction], argparse.ArgumentParser]]
|
||||
|
||||
@classmethod
|
||||
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
|
||||
|
||||
@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
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
@ -65,3 +48,22 @@ class Help(Handler):
|
||||
parser.parse_args(["--help"])
|
||||
else:
|
||||
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
|
||||
|
||||
@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
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
@ -68,3 +46,27 @@ class KeyImport(Handler):
|
||||
"""
|
||||
application = Application(repository_id, configuration, report=report)
|
||||
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
|
||||
|
||||
@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
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
@ -267,3 +249,10 @@ class Patch(Handler):
|
||||
application.reporter.package_patches_remove(package_base, variable)
|
||||
else:
|
||||
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
|
||||
"""
|
||||
|
||||
@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
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
@ -92,6 +60,38 @@ class Rebuild(Handler):
|
||||
result = application.update(packages, Packagers(args.username), bump_pkgrel=args.increment)
|
||||
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
|
||||
def extract_packages(application: Application, status: BuildStatusEnum | None, *,
|
||||
from_database: bool) -> list[Package]:
|
||||
@ -114,3 +114,5 @@ class Rebuild(Handler):
|
||||
]
|
||||
|
||||
return application.repository.packages()
|
||||
|
||||
arguments = [_set_repo_rebuild_parser]
|
||||
|
@ -30,22 +30,6 @@ class Remove(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
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
@ -61,3 +45,21 @@ class Remove(Handler):
|
||||
application = Application(repository_id, configuration, report=report)
|
||||
application.on_start()
|
||||
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
|
||||
"""
|
||||
|
||||
@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
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
@ -69,3 +53,21 @@ class RemoveUnknown(Handler):
|
||||
return
|
||||
|
||||
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
|
||||
|
||||
@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
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
@ -70,3 +52,23 @@ class Repositories(Handler):
|
||||
)
|
||||
for repository in cls.repositories_extract(dummy_args):
|
||||
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
|
||||
|
||||
@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
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
@ -66,3 +48,23 @@ class Restore(Handler):
|
||||
"""
|
||||
with tarfile.open(args.path) as archive:
|
||||
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
|
||||
|
||||
@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
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
@ -68,6 +49,25 @@ class Run(Handler):
|
||||
status = Run.run_command(shlex.split(command), parser)
|
||||
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
|
||||
def run_command(command: list[str], parser: argparse.ArgumentParser) -> bool:
|
||||
"""
|
||||
@ -83,3 +83,5 @@ class Run(Handler):
|
||||
args = parser.parse_args(command)
|
||||
handler: Handler = args.handler
|
||||
return handler.execute(args) == 0
|
||||
|
||||
arguments = [_set_service_run]
|
||||
|
@ -46,33 +46,6 @@ class Search(Handler):
|
||||
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
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
@ -95,6 +68,33 @@ class Search(Handler):
|
||||
for package in Search.sort(packages_list, args.sort_by):
|
||||
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
|
||||
def sort(packages: Iterable[AURPackage], sort_by: str) -> list[AURPackage]:
|
||||
"""
|
||||
@ -117,3 +117,5 @@ class Search(Handler):
|
||||
comparator: Callable[[AURPackage], tuple[str, str]] =\
|
||||
lambda package: (getattr(package, sort_by), package.name)
|
||||
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
|
||||
|
||||
@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
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
@ -76,3 +58,23 @@ class ServiceUpdates(Handler):
|
||||
|
||||
UpdatePrinter(remote, local_version)(verbose=True, separator=" -> ")
|
||||
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"
|
||||
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
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
@ -120,6 +82,44 @@ class Setup(Handler):
|
||||
# lazy database sync
|
||||
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
|
||||
def build_command(root: Path, repository_id: RepositoryId) -> Path:
|
||||
"""
|
||||
@ -280,3 +280,5 @@ class Setup(Handler):
|
||||
command.unlink(missing_ok=True)
|
||||
command.symlink_to(Setup.ARCHBUILD_COMMAND_PATH)
|
||||
paths.chown(command) # we would like to keep owner inside ahriman's home
|
||||
|
||||
arguments = [_set_service_setup_parser]
|
||||
|
@ -36,24 +36,6 @@ class Shell(Handler):
|
||||
|
||||
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
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
@ -81,3 +63,23 @@ class Shell(Handler):
|
||||
code.interact(local=local_variables)
|
||||
else:
|
||||
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
|
||||
"""
|
||||
|
||||
@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
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
@ -60,3 +43,22 @@ class Sign(Handler):
|
||||
report(bool): force enable or disable reporting
|
||||
"""
|
||||
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
|
||||
|
||||
@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
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
@ -92,6 +68,30 @@ class Statistics(Handler):
|
||||
case _:
|
||||
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
|
||||
def event_stats(event_type: str, events: list[Event]) -> None:
|
||||
"""
|
||||
@ -192,3 +192,5 @@ class Statistics(Handler):
|
||||
# chart if enabled
|
||||
if chart_path is not None:
|
||||
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
|
||||
|
||||
@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
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
@ -95,3 +69,31 @@ class Status(Handler):
|
||||
lambda item: args.status is None or item[1].status == args.status
|
||||
for package, package_status in sorted(filter(filter_fn, packages), key=comparator):
|
||||
PackagePrinter(package, package_status)(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
|
||||
|
||||
@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
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
@ -136,3 +119,9 @@ class StatusUpdate(Handler):
|
||||
type=BuildStatusEnum, choices=enum_values(BuildStatusEnum), default=BuildStatusEnum.Success)
|
||||
parser.set_defaults(action=Action.Update, lock=None, package=[], quiet=True, report=False, unsafe=True)
|
||||
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
|
||||
|
||||
@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
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
@ -76,3 +58,23 @@ class Structure(Handler):
|
||||
|
||||
# empty line
|
||||
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
|
||||
"""
|
||||
|
||||
@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
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
@ -66,6 +50,22 @@ class TreeMigrate(Handler):
|
||||
# perform migration
|
||||
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
|
||||
def tree_move(from_tree: RepositoryPaths, to_tree: RepositoryPaths) -> None:
|
||||
"""
|
||||
@ -82,3 +82,5 @@ class TreeMigrate(Handler):
|
||||
RepositoryPaths.repository,
|
||||
):
|
||||
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
|
||||
"""
|
||||
|
||||
@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
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
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 "
|
||||
"specified ones in order of mention", nargs="*")
|
||||
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
|
||||
|
||||
@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
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
@ -71,6 +52,25 @@ class UnsafeCommands(Handler):
|
||||
for command in unsafe_commands:
|
||||
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
|
||||
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)
|
||||
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"))
|
||||
|
||||
arguments = [_set_help_commands_unsafe_parser]
|
||||
|
@ -34,19 +34,6 @@ class 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
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
@ -165,3 +152,8 @@ class Update(Handler):
|
||||
def inner(line: str) -> None:
|
||||
return print(line) if dry_run else application.logger.info(line) # pylint: disable=bad-builtin
|
||||
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
|
||||
|
||||
@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
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
@ -178,3 +161,9 @@ class Users(Handler):
|
||||
|
||||
return User(username=args.username, password=password, access=args.role,
|
||||
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
|
||||
|
||||
@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
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
@ -82,6 +63,25 @@ class Validate(Handler):
|
||||
# as we reach this part it means that we always have errors
|
||||
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
|
||||
def schema(repository_id: RepositoryId, configuration: Configuration) -> ConfigurationSchema:
|
||||
"""
|
||||
@ -155,3 +155,5 @@ class Validate(Handler):
|
||||
Validate.schema_merge(value, schema[key])
|
||||
|
||||
return schema
|
||||
|
||||
arguments = [_set_service_config_validate_parser]
|
||||
|
@ -42,22 +42,6 @@ class Versions(Handler):
|
||||
ALLOW_MULTI_ARCHITECTURE_RUN = False # system-wide action
|
||||
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
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
@ -75,6 +59,22 @@ class Versions(Handler):
|
||||
packages = Versions.package_dependencies("ahriman")
|
||||
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
|
||||
def package_dependencies(root: str) -> Generator[tuple[str, str], None, None]:
|
||||
"""
|
||||
@ -112,3 +112,5 @@ class Versions(Handler):
|
||||
yield distribution.name, distribution.version
|
||||
except metadata.PackageNotFoundError:
|
||||
continue
|
||||
|
||||
arguments = [_set_help_version_parser]
|
||||
|
@ -36,21 +36,6 @@ class Web(Handler):
|
||||
|
||||
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
|
||||
def run(cls, args: argparse.Namespace, repository_id: RepositoryId, configuration: Configuration, *,
|
||||
report: bool) -> None:
|
||||
@ -87,6 +72,21 @@ class Web(Handler):
|
||||
spawner.stop()
|
||||
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
|
||||
def extract_arguments(args: argparse.Namespace, configuration: Configuration) -> Generator[str, None, None]:
|
||||
"""
|
||||
@ -116,3 +116,5 @@ class Web(Handler):
|
||||
# arguments from configuration
|
||||
if (wait_timeout := configuration.getint("web", "wait_timeout", fallback=None)) is not None:
|
||||
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
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
import bcrypt
|
||||
|
||||
from dataclasses import dataclass, replace
|
||||
from passlib.hash import sha512_crypt
|
||||
from secrets import token_urlsafe as generate_password
|
||||
from typing import Self
|
||||
|
||||
@ -67,8 +68,6 @@ class User:
|
||||
packager_id: str | None = None
|
||||
key: str | None = None
|
||||
|
||||
_HASHER = sha512_crypt
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
"""
|
||||
remove empty fields
|
||||
@ -101,10 +100,9 @@ class User:
|
||||
bool: ``True`` in case if password matches, ``False`` otherwise
|
||||
"""
|
||||
try:
|
||||
verified: bool = self._HASHER.verify(password + salt, self.password)
|
||||
return bcrypt.checkpw((password + salt).encode("utf8"), self.password.encode("utf8"))
|
||||
except ValueError:
|
||||
verified = False # the absence of evidence is not the evidence of absence (c) Gin Rummy
|
||||
return verified
|
||||
return False # the absence of evidence is not the evidence of absence (c) Gin Rummy
|
||||
|
||||
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
|
||||
# when we do not store any password here
|
||||
return self
|
||||
password_hash: str = self._HASHER.hash(self.password + salt)
|
||||
return replace(self, password=password_hash)
|
||||
password_hash = bcrypt.hashpw((self.password + salt).encode("utf8"), bcrypt.gensalt())
|
||||
return replace(self, password=password_hash.decode("utf8"))
|
||||
|
||||
def verify_access(self, required: UserAccess) -> bool:
|
||||
"""
|
||||
|
@ -3,7 +3,6 @@ import pytest
|
||||
|
||||
from pathlib import Path
|
||||
from pytest_mock import MockerFixture
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
from ahriman.application.handlers.handler import Handler
|
||||
from ahriman.core.configuration import Configuration
|
||||
@ -12,14 +11,6 @@ from ahriman.models.log_handler import LogHandler
|
||||
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:
|
||||
"""
|
||||
must call inside lock
|
||||
|
Reference in New Issue
Block a user