add ability to check for service updates

This commit is contained in:
Evgenii Alekseev 2023-01-11 16:28:28 +02:00
parent 00ca06ffab
commit 419da3db89
9 changed files with 203 additions and 7 deletions

View File

@ -3,7 +3,7 @@
ahriman
.SH SYNOPSIS
.B ahriman
[-h] [-a ARCHITECTURE] [-c CONFIGURATION] [--force] [-l LOCK] [--report | --no-report] [-q] [--unsafe] [-V] {aur-search,search,help,help-commands-unsafe,help-version,version,package-add,add,package-update,package-remove,remove,package-status,status,package-status-remove,package-status-update,status-update,patch-add,patch-list,patch-remove,patch-set-add,repo-backup,repo-check,check,repo-daemon,daemon,repo-rebuild,rebuild,repo-remove-unknown,remove-unknown,repo-report,report,repo-restore,repo-sign,sign,repo-status-update,repo-sync,sync,repo-tree,repo-triggers,repo-update,update,service-clean,clean,repo-clean,service-config,config,repo-config,service-config-validate,config-validate,repo-config-validate,service-key-import,key-import,service-setup,init,repo-init,repo-setup,setup,service-shell,shell,user-add,user-list,user-remove,web} ...
[-h] [-a ARCHITECTURE] [-c CONFIGURATION] [--force] [-l LOCK] [--report | --no-report] [-q] [--unsafe] [-V] {aur-search,search,help,help-commands-unsafe,help-updates,help-version,version,package-add,add,package-update,package-remove,remove,package-status,status,package-status-remove,package-status-update,status-update,patch-add,patch-list,patch-remove,patch-set-add,repo-backup,repo-check,check,repo-daemon,daemon,repo-rebuild,rebuild,repo-remove-unknown,remove-unknown,repo-report,report,repo-restore,repo-sign,sign,repo-status-update,repo-sync,sync,repo-tree,repo-triggers,repo-update,update,service-clean,clean,repo-clean,service-config,config,repo-config,service-config-validate,config-validate,repo-config-validate,service-key-import,key-import,service-setup,init,repo-init,repo-setup,setup,service-shell,shell,user-add,user-list,user-remove,web} ...
.SH DESCRIPTION
ArcH linux ReposItory MANager
@ -52,6 +52,9 @@ show help message
\fBahriman\fR \fI\,help\-commands\-unsafe\/\fR
list unsafe commands
.TP
\fBahriman\fR \fI\,help\-updates\/\fR
check for service updates
.TP
\fBahriman\fR \fI\,help\-version\/\fR
application version
.TP
@ -196,6 +199,16 @@ list unsafe commands as defined in default args
instead of showing commands, just test command line for unsafe subcommand and return 0 in case if command is safe and 1
otherwise
.SH COMMAND \fI\,'ahriman help\-updates'\/\fR
usage: ahriman help\-updates [\-h] [\-e]
request AUR for current version and compare with current service version
.SH OPTIONS \fI\,'ahriman help\-updates'\/\fR
.TP
\fB\-e\fR, \fB\-\-exit\-code\fR
return non\-zero exit code if updates available
.SH COMMAND \fI\,'ahriman help\-version'\/\fR
usage: ahriman help\-version [\-h]

View File

@ -116,6 +116,14 @@ ahriman.application.handlers.search module
:no-undoc-members:
:show-inheritance:
ahriman.application.handlers.service\_updates module
----------------------------------------------------
.. automodule:: ahriman.application.handlers.service_updates
:members:
:no-undoc-members:
:show-inheritance:
ahriman.application.handlers.setup module
-----------------------------------------

View File

@ -1,12 +1,13 @@
# AUTOMATICALLY GENERATED by `shtab`
_shtab_ahriman_subparsers=('aur-search' 'search' 'help' 'help-commands-unsafe' 'help-version' 'version' 'package-add' 'add' 'package-update' 'package-remove' 'remove' 'package-status' 'status' 'package-status-remove' 'package-status-update' 'status-update' 'patch-add' 'patch-list' 'patch-remove' 'patch-set-add' 'repo-backup' 'repo-check' 'check' 'repo-daemon' 'daemon' 'repo-rebuild' 'rebuild' 'repo-remove-unknown' 'remove-unknown' 'repo-report' 'report' 'repo-restore' 'repo-sign' 'sign' 'repo-status-update' 'repo-sync' 'sync' 'repo-tree' 'repo-triggers' 'repo-update' 'update' 'service-clean' 'clean' 'repo-clean' 'service-config' 'config' 'repo-config' 'service-config-validate' 'config-validate' 'repo-config-validate' 'service-key-import' 'key-import' 'service-setup' 'init' 'repo-init' 'repo-setup' 'setup' 'service-shell' 'shell' 'user-add' 'user-list' 'user-remove' 'web')
_shtab_ahriman_subparsers=('aur-search' 'search' 'help' 'help-commands-unsafe' 'help-updates' 'help-version' 'version' 'package-add' 'add' 'package-update' 'package-remove' 'remove' 'package-status' 'status' 'package-status-remove' 'package-status-update' 'status-update' 'patch-add' 'patch-list' 'patch-remove' 'patch-set-add' 'repo-backup' 'repo-check' 'check' 'repo-daemon' 'daemon' 'repo-rebuild' 'rebuild' 'repo-remove-unknown' 'remove-unknown' 'repo-report' 'report' 'repo-restore' 'repo-sign' 'sign' 'repo-status-update' 'repo-sync' 'sync' 'repo-tree' 'repo-triggers' 'repo-update' 'update' 'service-clean' 'clean' 'repo-clean' 'service-config' 'config' 'repo-config' 'service-config-validate' 'config-validate' 'repo-config-validate' 'service-key-import' 'key-import' 'service-setup' 'init' 'repo-init' 'repo-setup' 'setup' 'service-shell' 'shell' 'user-add' 'user-list' 'user-remove' 'web')
_shtab_ahriman_option_strings=('-h' '--help' '-a' '--architecture' '-c' '--configuration' '--force' '-l' '--lock' '--report' '--no-report' '-q' '--quiet' '--unsafe' '-V' '--version')
_shtab_ahriman_aur_search_option_strings=('-h' '--help' '-e' '--exit-code' '--info' '--no-info' '--sort-by')
_shtab_ahriman_search_option_strings=('-h' '--help' '-e' '--exit-code' '--info' '--no-info' '--sort-by')
_shtab_ahriman_help_option_strings=('-h' '--help')
_shtab_ahriman_help_commands_unsafe_option_strings=('-h' '--help' '--command')
_shtab_ahriman_help_updates_option_strings=('-h' '--help' '-e' '--exit-code')
_shtab_ahriman_help_version_option_strings=('-h' '--help')
_shtab_ahriman_version_option_strings=('-h' '--help')
_shtab_ahriman_package_add_option_strings=('-h' '--help' '-e' '--exit-code' '-n' '--now' '-y' '--refresh' '-s' '--source' '--without-dependencies')
@ -69,7 +70,7 @@ _shtab_ahriman_web_option_strings=('-h' '--help')
_shtab_ahriman_pos_0_choices=('aur-search' 'search' 'help' 'help-commands-unsafe' 'help-version' 'version' 'package-add' 'add' 'package-update' 'package-remove' 'remove' 'package-status' 'status' 'package-status-remove' 'package-status-update' 'status-update' 'patch-add' 'patch-list' 'patch-remove' 'patch-set-add' 'repo-backup' 'repo-check' 'check' 'repo-daemon' 'daemon' 'repo-rebuild' 'rebuild' 'repo-remove-unknown' 'remove-unknown' 'repo-report' 'report' 'repo-restore' 'repo-sign' 'sign' 'repo-status-update' 'repo-sync' 'sync' 'repo-tree' 'repo-triggers' 'repo-update' 'update' 'service-clean' 'clean' 'repo-clean' 'service-config' 'config' 'repo-config' 'service-config-validate' 'config-validate' 'repo-config-validate' 'service-key-import' 'key-import' 'service-setup' 'init' 'repo-init' 'repo-setup' 'setup' 'service-shell' 'shell' 'user-add' 'user-list' 'user-remove' 'web')
_shtab_ahriman_pos_0_choices=('aur-search' 'search' 'help' 'help-commands-unsafe' 'help-updates' 'help-version' 'version' 'package-add' 'add' 'package-update' 'package-remove' 'remove' 'package-status' 'status' 'package-status-remove' 'package-status-update' 'status-update' 'patch-add' 'patch-list' 'patch-remove' 'patch-set-add' 'repo-backup' 'repo-check' 'check' 'repo-daemon' 'daemon' 'repo-rebuild' 'rebuild' 'repo-remove-unknown' 'remove-unknown' 'repo-report' 'report' 'repo-restore' 'repo-sign' 'sign' 'repo-status-update' 'repo-sync' 'sync' 'repo-tree' 'repo-triggers' 'repo-update' 'update' 'service-clean' 'clean' 'repo-clean' 'service-config' 'config' 'repo-config' 'service-config-validate' 'config-validate' 'repo-config-validate' 'service-key-import' 'key-import' 'service-setup' 'init' 'repo-init' 'repo-setup' 'setup' 'service-shell' 'shell' 'user-add' 'user-list' 'user-remove' 'web')
_shtab_ahriman_aur_search___sort_by_choices=('description' 'first_submitted' 'id' 'last_modified' 'maintainer' 'name' 'num_votes' 'out_of_date' 'package_base' 'package_base_id' 'popularity' 'repository' 'url' 'url_path' 'version')
_shtab_ahriman_search___sort_by_choices=('description' 'first_submitted' 'id' 'last_modified' 'maintainer' 'name' 'num_votes' 'out_of_date' 'package_base' 'package_base_id' 'popularity' 'repository' 'url' 'url_path' 'version')
_shtab_ahriman_package_add__s_choices=('auto' 'archive' 'aur' 'directory' 'local' 'remote' 'repository')
@ -127,6 +128,10 @@ _shtab_ahriman_help__h_nargs=0
_shtab_ahriman_help___help_nargs=0
_shtab_ahriman_help_commands_unsafe__h_nargs=0
_shtab_ahriman_help_commands_unsafe___help_nargs=0
_shtab_ahriman_help_updates__h_nargs=0
_shtab_ahriman_help_updates___help_nargs=0
_shtab_ahriman_help_updates__e_nargs=0
_shtab_ahriman_help_updates___exit_code_nargs=0
_shtab_ahriman_help_version__h_nargs=0
_shtab_ahriman_help_version___help_nargs=0
_shtab_ahriman_version__h_nargs=0

View File

@ -14,6 +14,7 @@ _shtab_ahriman_commands() {
"daemon:start process which periodically will run update process"
"help:show help message for application or command and exit"
"help-commands-unsafe:list unsafe commands as defined in default args"
"help-updates:request AUR for current version and compare with current service version"
"help-version:print application and its dependencies versions"
"init:create initial service configuration, requires root"
"key-import:import PGP key from public sources to the repository user"
@ -148,6 +149,11 @@ _shtab_ahriman_help_commands_unsafe_options=(
"--command[instead of showing commands, just test command line for unsafe subcommand and return 0 in case if command is safe and 1 otherwise]:command:"
)
_shtab_ahriman_help_updates_options=(
"(- : *)"{-h,--help}"[show this help message and exit]"
{-e,--exit-code}"[return non-zero exit code if updates available]"
)
_shtab_ahriman_help_version_options=(
"(- : *)"{-h,--help}"[show this help message and exit]"
)
@ -555,6 +561,7 @@ _shtab_ahriman() {
daemon) _arguments -C $_shtab_ahriman_daemon_options ;;
help) _arguments -C $_shtab_ahriman_help_options ;;
help-commands-unsafe) _arguments -C $_shtab_ahriman_help_commands_unsafe_options ;;
help-updates) _arguments -C $_shtab_ahriman_help_updates_options ;;
help-version) _arguments -C $_shtab_ahriman_help_version_options ;;
init) _arguments -C $_shtab_ahriman_init_options ;;
key-import) _arguments -C $_shtab_ahriman_key_import_options ;;

View File

@ -86,6 +86,7 @@ def _parser() -> argparse.ArgumentParser:
_set_aur_search_parser(subparsers)
_set_help_parser(subparsers)
_set_help_commands_unsafe_parser(subparsers)
_set_help_updates_parser(subparsers)
_set_help_version_parser(subparsers)
_set_package_add_parser(subparsers)
_set_package_remove_parser(subparsers)
@ -161,8 +162,8 @@ def _set_help_parser(root: SubParserAction) -> argparse.ArgumentParser:
description="show help message for application or command and exit",
formatter_class=_formatter)
parser.add_argument("command", help="show help message for specific command", nargs="?")
parser.set_defaults(handler=handlers.Help, architecture=[""], lock=None, report=False, quiet=True,
unsafe=True, parser=_parser)
parser.set_defaults(handler=handlers.Help, architecture=[""], lock=None, report=False, quiet=True, unsafe=True,
parser=_parser)
return parser
@ -185,6 +186,25 @@ def _set_help_commands_unsafe_parser(root: SubParserAction) -> argparse.Argument
return parser
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",
formatter_class=_formatter)
parser.add_argument("-e", "--exit-code", help="return non-zero exit code if updates available", action="store_true")
parser.set_defaults(handler=handlers.ServiceUpdates, architecture=[""], lock=None, report=False, quiet=True,
unsafe=True)
return parser
def _set_help_version_parser(root: SubParserAction) -> argparse.ArgumentParser:
"""
add parser for version subcommand
@ -197,8 +217,7 @@ def _set_help_version_parser(root: SubParserAction) -> argparse.ArgumentParser:
"""
parser = root.add_parser("help-version", aliases=["version"], help="application version",
description="print application and its dependencies versions", formatter_class=_formatter)
parser.set_defaults(handler=handlers.Versions, architecture=[""], lock=None, report=False, quiet=True,
unsafe=True)
parser.set_defaults(handler=handlers.Versions, architecture=[""], lock=None, report=False, quiet=True, unsafe=True)
return parser

View File

@ -32,6 +32,7 @@ from ahriman.application.handlers.remove import Remove
from ahriman.application.handlers.remove_unknown import RemoveUnknown
from ahriman.application.handlers.restore import Restore
from ahriman.application.handlers.search import Search
from ahriman.application.handlers.service_updates import ServiceUpdates
from ahriman.application.handlers.setup import Setup
from ahriman.application.handlers.shell import Shell
from ahriman.application.handlers.sign import Sign

View File

@ -0,0 +1,65 @@
#
# Copyright (c) 2021-2023 ahriman team.
#
# This file is part of ahriman
# (see https://github.com/arcan1s/ahriman).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import argparse
from typing import Type
from ahriman import version
from ahriman.application.application import Application
from ahriman.application.handlers import Handler
from ahriman.core.configuration import Configuration
from ahriman.core.formatters import UpdatePrinter
from ahriman.models.package import Package
class ServiceUpdates(Handler):
"""
service updates handler
"""
ALLOW_AUTO_ARCHITECTURE_RUN = False # it should be called only as "no-architecture"
@classmethod
def run(cls: Type[Handler], args: argparse.Namespace, architecture: str, configuration: Configuration, *,
report: bool, unsafe: bool) -> None:
"""
callback for command line
Args:
args(argparse.Namespace): command line args
architecture(str): repository architecture
configuration(Configuration): configuration instance
report(bool): force enable or disable reporting
unsafe(bool): if set no user check will be performed before path creation
"""
application = Application(architecture, configuration, report=report, unsafe=unsafe)
remote = Package.from_aur("ahriman", application.repository.pacman)
release = remote.version.rsplit("-", 1)[-1] # we don't store pkgrel locally, so we just append it
local_version = f"{version.__version__}-{release}"
# technically we would like to compare versions, but it is fine to raise an exception in case if locally
# installed package is newer than in AUR
same_version = remote.version == local_version
if same_version:
return
UpdatePrinter(remote, local_version).print(verbose=True, separator=" -> ")
ServiceUpdates.check_if_empty(args.exit_code, not same_version)

View File

@ -0,0 +1,58 @@
import argparse
from pytest_mock import MockerFixture
from ahriman import version
from ahriman.application.handlers import ServiceUpdates
from ahriman.core.configuration import Configuration
from ahriman.core.repository import Repository
from ahriman.models.package import Package
def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
default arguments for these test cases
Args:
args(argparse.Namespace): command line arguments fixture
Returns:
argparse.Namespace: generated arguments for these test cases
"""
args.exit_code = False
return args
def test_run(args: argparse.Namespace, configuration: Configuration, repository: Repository,
package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must run command
"""
package_ahriman.version = "0.0.0"
args = _default_args(args)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
package_mock = mocker.patch("ahriman.models.package.Package.from_aur", return_value=package_ahriman)
application_mock = mocker.patch("ahriman.core.formatters.Printer.print")
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
ServiceUpdates.run(args, "x86_64", configuration, report=False, unsafe=False)
package_mock.assert_called_once_with(package_ahriman.base, repository.pacman)
application_mock.assert_called_once_with(verbose=True, separator=" -> ")
check_mock.assert_called_once_with(args.exit_code, True)
def test_run_skip(args: argparse.Namespace, configuration: Configuration, repository: Repository,
package_ahriman: Package, mocker: MockerFixture) -> None:
"""
must do not perform any actions if package is up-to-date
"""
package_ahriman.version = f"{version.__version__}-1"
args = _default_args(args)
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.models.package.Package.from_aur", return_value=package_ahriman)
application_mock = mocker.patch("ahriman.core.formatters.Printer.print")
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
ServiceUpdates.run(args, "x86_64", configuration, report=False, unsafe=False)
application_mock.assert_not_called()
check_mock.assert_not_called()

View File

@ -107,6 +107,26 @@ def test_subparsers_help_commands_unsafe_architecture(parser: argparse.ArgumentP
assert args.architecture == [""]
def test_subparsers_help_updates(parser: argparse.ArgumentParser) -> None:
"""
help-updates command must imply architecture list, lock, report, quiet and unsafe
"""
args = parser.parse_args(["help-updates"])
assert args.architecture == [""]
assert args.lock is None
assert not args.report
assert args.quiet
assert args.unsafe
def test_subparsers_help_updates_architecture(parser: argparse.ArgumentParser) -> None:
"""
help-updates command must correctly parse architecture list
"""
args = parser.parse_args(["-a", "x86_64", "help-updates"])
assert args.architecture == [""]
def test_subparsers_help_version(parser: argparse.ArgumentParser) -> None:
"""
help-version command must imply architecture, lock, report, quiet and unsafe