diff --git a/src/ahriman/application/application/application.py b/src/ahriman/application/application/application.py
index 3c453ca8..fdf8c63e 100644
--- a/src/ahriman/application/application/application.py
+++ b/src/ahriman/application/application/application.py
@@ -17,10 +17,12 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
#
-from collections.abc import Iterable
+from collections.abc import Callable, Iterable
from ahriman.application.application.application_packages import ApplicationPackages
from ahriman.application.application.application_repository import ApplicationRepository
+from ahriman.core.formatters import UpdatePrinter
+from ahriman.core.tree import Tree
from ahriman.models.package import Package
from ahriman.models.result import Result
@@ -89,6 +91,22 @@ class Application(ApplicationPackages, ApplicationRepository):
"""
self.repository.triggers.on_stop()
+ def print_updates(self, packages: list[Package], *, log_fn: Callable[[str], None]) -> None:
+ """
+ print list of packages to be built. This method will build dependency tree and print updates accordingly
+
+ Args:
+ packages(list[Package]): package list to be printed
+ log_fn(Callable[[str], None]): logger function to log updates
+ """
+ local_versions = {package.base: package.version for package in self.repository.packages()}
+
+ tree = Tree.resolve(packages)
+ for level in tree:
+ for package in level:
+ UpdatePrinter(package, local_versions.get(package.base)).print(
+ verbose=True, log_fn=log_fn, separator=" -> ")
+
def with_dependencies(self, packages: list[Package], *, process_dependencies: bool) -> list[Package]:
"""
add missing dependencies to list of packages
@@ -126,5 +144,8 @@ class Application(ApplicationPackages, ApplicationRepository):
for package_name, username in missing.items():
package = Package.from_aur(package_name, self.repository.pacman, username)
with_dependencies[package.base] = package
+ # register package in local database
+ self.database.remote_update(package)
+ self.repository.reporter.set_unknown(package)
return list(with_dependencies.values())
diff --git a/src/ahriman/application/application/application_repository.py b/src/ahriman/application/application/application_repository.py
index 6d67d5ae..827faeaa 100644
--- a/src/ahriman/application/application/application_repository.py
+++ b/src/ahriman/application/application/application_repository.py
@@ -17,12 +17,11 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
#
-from collections.abc import Callable, Iterable
+from collections.abc import Iterable
from pathlib import Path
from ahriman.application.application.application_properties import ApplicationProperties
from ahriman.core.build_tools.sources import Sources
-from ahriman.core.formatters import UpdatePrinter
from ahriman.core.tree import Tree
from ahriman.models.package import Package
from ahriman.models.packagers import Packagers
@@ -158,7 +157,7 @@ class ApplicationRepository(ApplicationProperties):
return build_result
def updates(self, filter_packages: Iterable[str], *,
- aur: bool, local: bool, manual: bool, vcs: bool, log_fn: Callable[[str], None]) -> list[Package]:
+ aur: bool, local: bool, manual: bool, vcs: bool) -> list[Package]:
"""
get list of packages to run update process
@@ -168,7 +167,6 @@ class ApplicationRepository(ApplicationProperties):
local(bool): enable or disable checking of local packages for updates
manual(bool): include or exclude manual updates
vcs(bool): enable or disable checking of VCS packages
- log_fn(Callable[[str], None]): logger function to log updates
Returns:
list[Package]: list of out-of-dated packages
@@ -182,14 +180,4 @@ class ApplicationRepository(ApplicationProperties):
if manual:
updates.update({package.base: package for package in self.repository.updates_manual()})
- local_versions = {package.base: package.version for package in self.repository.packages()}
- updated_packages = [package for _, package in sorted(updates.items())]
-
- # reorder updates according to the dependency tree
- tree = Tree.resolve(updated_packages)
- for level in tree:
- for package in level:
- UpdatePrinter(package, local_versions.get(package.base)).print(
- verbose=True, log_fn=log_fn, separator=" -> ")
-
- return updated_packages
+ return [package for _, package in sorted(updates.items())]
diff --git a/src/ahriman/application/handlers/add.py b/src/ahriman/application/handlers/add.py
index 95a79c92..dcca843b 100644
--- a/src/ahriman/application/handlers/add.py
+++ b/src/ahriman/application/handlers/add.py
@@ -50,10 +50,10 @@ class Add(Handler):
if not args.now:
return
- packages = application.updates(args.package, aur=False, local=False, manual=True, vcs=False,
- log_fn=application.logger.info)
+ packages = application.updates(args.package, aur=False, local=False, manual=True, vcs=False)
packages = application.with_dependencies(packages, process_dependencies=args.dependencies)
packagers = Packagers(args.username, {package.base: package.packager for package in packages})
+ application.print_updates(packages, log_fn=application.logger.info)
result = application.update(packages, packagers)
Add.check_if_empty(args.exit_code, result.is_empty)
diff --git a/src/ahriman/application/handlers/rebuild.py b/src/ahriman/application/handlers/rebuild.py
index e00ac5ee..735a0134 100644
--- a/src/ahriman/application/handlers/rebuild.py
+++ b/src/ahriman/application/handlers/rebuild.py
@@ -22,7 +22,6 @@ import argparse
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.build_status import BuildStatusEnum
from ahriman.models.package import Package
@@ -53,8 +52,7 @@ class Rebuild(Handler):
Rebuild.check_if_empty(args.exit_code, not updates)
if args.dry_run:
- for package in updates:
- UpdatePrinter(package, package.version).print(verbose=True)
+ application.print_updates(updates, log_fn=print)
return
result = application.update(updates, args.username)
diff --git a/src/ahriman/application/handlers/update.py b/src/ahriman/application/handlers/update.py
index 77f2cb79..3ffd0cbb 100644
--- a/src/ahriman/application/handlers/update.py
+++ b/src/ahriman/application/handlers/update.py
@@ -48,8 +48,7 @@ class Update(Handler):
application = Application(architecture, configuration, report=report, unsafe=unsafe,
refresh_pacman_database=args.refresh)
application.on_start()
- packages = application.updates(args.package, aur=args.aur, local=args.local, manual=args.manual, vcs=args.vcs,
- log_fn=Update.log_fn(application, args.dry_run))
+ packages = application.updates(args.package, aur=args.aur, local=args.local, manual=args.manual, vcs=args.vcs)
Update.check_if_empty(args.exit_code, not packages)
if args.dry_run:
return
@@ -57,6 +56,7 @@ class Update(Handler):
packages = application.with_dependencies(packages, process_dependencies=args.dependencies)
packagers = Packagers(args.username, {package.base: package.packager for package in packages})
+ application.print_updates(packages, log_fn=application.logger.info)
result = application.update(packages, packagers)
Update.check_if_empty(args.exit_code, result.is_empty)
diff --git a/tests/ahriman/application/application/test_application.py b/tests/ahriman/application/application/test_application.py
index 2cf922ed..c6275df9 100644
--- a/tests/ahriman/application/application/test_application.py
+++ b/tests/ahriman/application/application/test_application.py
@@ -2,6 +2,7 @@ from pytest_mock import MockerFixture
from unittest.mock import MagicMock, call as MockCall
from ahriman.application.application import Application
+from ahriman.core.tree import Leaf, Tree
from ahriman.models.package import Package
from ahriman.models.result import Result
@@ -47,6 +48,19 @@ def test_on_stop(application: Application, mocker: MockerFixture) -> None:
triggers_mock.assert_called_once_with()
+def test_print_updates(application: Application, package_ahriman: Package, mocker: MockerFixture) -> None:
+ """
+ must print updates
+ """
+ tree = Tree([Leaf(package_ahriman)])
+ mocker.patch("ahriman.core.repository.repository.Repository.packages", return_value=[package_ahriman])
+ mocker.patch("ahriman.core.tree.Tree.resolve", return_value=tree.levels())
+ print_mock = mocker.patch("ahriman.core.formatters.Printer.print")
+
+ application.print_updates([package_ahriman], log_fn=print)
+ print_mock.assert_called_once_with(verbose=True, log_fn=print, separator=" -> ")
+
+
def test_with_dependencies(application: Application, package_ahriman: Package, package_python_schedule: Package,
mocker: MockerFixture) -> None:
"""
@@ -75,6 +89,8 @@ def test_with_dependencies(application: Application, package_ahriman: Package, p
package_mock = mocker.patch("ahriman.models.package.Package.from_aur", side_effect=lambda *args: packages[args[0]])
packages_mock = mocker.patch("ahriman.application.application.Application._known_packages",
return_value={"devtools", "python-build", "python-pytest"})
+ update_remote_mock = mocker.patch("ahriman.core.database.SQLite.remote_update")
+ status_client_mock = mocker.patch("ahriman.core.status.client.Client.set_unknown")
result = application.with_dependencies([package_ahriman], process_dependencies=True)
assert {package.base: package for package in result} == packages
@@ -85,6 +101,17 @@ def test_with_dependencies(application: Application, package_ahriman: Package, p
], any_order=True)
packages_mock.assert_called_once_with()
+ update_remote_mock.assert_has_calls([
+ MockCall(package_python_schedule),
+ MockCall(packages["python"]),
+ MockCall(packages["python-installer"]),
+ ], any_order=True)
+ status_client_mock.assert_has_calls([
+ MockCall(package_python_schedule),
+ MockCall(packages["python"]),
+ MockCall(packages["python-installer"]),
+ ], any_order=True)
+
def test_with_dependencies_skip(application: Application, package_ahriman: Package, mocker: MockerFixture) -> None:
"""
diff --git a/tests/ahriman/application/application/test_application_repository.py b/tests/ahriman/application/application/test_application_repository.py
index 2bc613a2..8cc77552 100644
--- a/tests/ahriman/application/application/test_application_repository.py
+++ b/tests/ahriman/application/application/test_application_repository.py
@@ -197,16 +197,12 @@ def test_updates_all(application_repository: ApplicationRepository, package_ahri
"""
must get updates for all
"""
- tree = Tree([Leaf(package_ahriman)])
-
- mocker.patch("ahriman.core.tree.Tree.resolve", return_value=tree.levels())
- mocker.patch("ahriman.core.repository.repository.Repository.packages", return_value=[])
updates_aur_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_aur",
return_value=[package_ahriman])
updates_local_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_local")
updates_manual_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_manual")
- application_repository.updates([], aur=True, local=True, manual=True, vcs=True, log_fn=print)
+ application_repository.updates([], aur=True, local=True, manual=True, vcs=True)
updates_aur_mock.assert_called_once_with([], vcs=True)
updates_local_mock.assert_called_once_with(vcs=True)
updates_manual_mock.assert_called_once_with()
@@ -216,12 +212,11 @@ def test_updates_disabled(application_repository: ApplicationRepository, mocker:
"""
must get updates without anything
"""
- mocker.patch("ahriman.core.repository.repository.Repository.packages", return_value=[])
updates_aur_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_aur")
updates_local_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_local")
updates_manual_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_manual")
- application_repository.updates([], aur=False, local=False, manual=False, vcs=True, log_fn=print)
+ application_repository.updates([], aur=False, local=False, manual=False, vcs=True)
updates_aur_mock.assert_not_called()
updates_local_mock.assert_not_called()
updates_manual_mock.assert_not_called()
@@ -231,12 +226,11 @@ def test_updates_no_aur(application_repository: ApplicationRepository, mocker: M
"""
must get updates without aur
"""
- mocker.patch("ahriman.core.repository.repository.Repository.packages", return_value=[])
updates_aur_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_aur")
updates_local_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_local")
updates_manual_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_manual")
- application_repository.updates([], aur=False, local=True, manual=True, vcs=True, log_fn=print)
+ application_repository.updates([], aur=False, local=True, manual=True, vcs=True)
updates_aur_mock.assert_not_called()
updates_local_mock.assert_called_once_with(vcs=True)
updates_manual_mock.assert_called_once_with()
@@ -246,12 +240,11 @@ def test_updates_no_local(application_repository: ApplicationRepository, mocker:
"""
must get updates without local packages
"""
- mocker.patch("ahriman.core.repository.repository.Repository.packages", return_value=[])
updates_aur_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_aur")
updates_local_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_local")
updates_manual_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_manual")
- application_repository.updates([], aur=True, local=False, manual=True, vcs=True, log_fn=print)
+ application_repository.updates([], aur=True, local=False, manual=True, vcs=True)
updates_aur_mock.assert_called_once_with([], vcs=True)
updates_local_mock.assert_not_called()
updates_manual_mock.assert_called_once_with()
@@ -261,12 +254,11 @@ def test_updates_no_manual(application_repository: ApplicationRepository, mocker
"""
must get updates without manual
"""
- mocker.patch("ahriman.core.repository.repository.Repository.packages", return_value=[])
updates_aur_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_aur")
updates_local_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_local")
updates_manual_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_manual")
- application_repository.updates([], aur=True, local=True, manual=False, vcs=True, log_fn=print)
+ application_repository.updates([], aur=True, local=True, manual=False, vcs=True)
updates_aur_mock.assert_called_once_with([], vcs=True)
updates_local_mock.assert_called_once_with(vcs=True)
updates_manual_mock.assert_not_called()
@@ -276,12 +268,11 @@ def test_updates_no_vcs(application_repository: ApplicationRepository, mocker: M
"""
must get updates without VCS
"""
- mocker.patch("ahriman.core.repository.repository.Repository.packages", return_value=[])
updates_aur_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_aur")
updates_local_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_local")
updates_manual_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_manual")
- application_repository.updates([], aur=True, local=True, manual=True, vcs=False, log_fn=print)
+ application_repository.updates([], aur=True, local=True, manual=True, vcs=False)
updates_aur_mock.assert_called_once_with([], vcs=False)
updates_local_mock.assert_called_once_with(vcs=False)
updates_manual_mock.assert_called_once_with()
@@ -291,12 +282,11 @@ def test_updates_with_filter(application_repository: ApplicationRepository, mock
"""
must get updates with filter
"""
- mocker.patch("ahriman.core.repository.repository.Repository.packages", return_value=[])
updates_aur_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_aur")
updates_local_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_local")
updates_manual_mock = mocker.patch("ahriman.core.repository.update_handler.UpdateHandler.updates_manual")
- application_repository.updates(["filter"], aur=True, local=True, manual=True, vcs=True, log_fn=print)
+ application_repository.updates(["filter"], aur=True, local=True, manual=True, vcs=True)
updates_aur_mock.assert_called_once_with(["filter"], vcs=True)
updates_local_mock.assert_called_once_with(vcs=True)
updates_manual_mock.assert_called_once_with()
diff --git a/tests/ahriman/application/handlers/test_handler_add.py b/tests/ahriman/application/handlers/test_handler_add.py
index 5e10e930..0dca4650 100644
--- a/tests/ahriman/application/handlers/test_handler_add.py
+++ b/tests/ahriman/application/handlers/test_handler_add.py
@@ -65,14 +65,15 @@ def test_run_with_updates(args: argparse.Namespace, configuration: Configuration
updates_mock = mocker.patch("ahriman.application.application.Application.updates", return_value=[package_ahriman])
dependencies_mock = mocker.patch("ahriman.application.application.Application.with_dependencies",
return_value=[package_ahriman])
+ print_mock = mocker.patch("ahriman.application.application.Application.print_updates")
Add.run(args, "x86_64", configuration, report=False, unsafe=False)
- updates_mock.assert_called_once_with(args.package, aur=False, local=False, manual=True, vcs=False,
- log_fn=pytest.helpers.anyvar(int))
+ updates_mock.assert_called_once_with(args.package, aur=False, local=False, manual=True, vcs=False)
application_mock.assert_called_once_with([package_ahriman],
Packagers(args.username, {package_ahriman.base: "packager"}))
dependencies_mock.assert_called_once_with([package_ahriman], process_dependencies=args.dependencies)
check_mock.assert_called_once_with(False, False)
+ print_mock.assert_called_once_with([package_ahriman], log_fn=pytest.helpers.anyvar(int))
def test_run_empty_exception(args: argparse.Namespace, configuration: Configuration, repository: Repository,
@@ -88,6 +89,7 @@ def test_run_empty_exception(args: argparse.Namespace, configuration: Configurat
mocker.patch("ahriman.application.application.Application.update", return_value=Result())
mocker.patch("ahriman.application.application.Application.with_dependencies")
mocker.patch("ahriman.application.application.Application.updates")
+ mocker.patch("ahriman.application.application.Application.print_updates")
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
Add.run(args, "x86_64", configuration, report=False, unsafe=False)
diff --git a/tests/ahriman/application/handlers/test_handler_rebuild.py b/tests/ahriman/application/handlers/test_handler_rebuild.py
index 1918cb66..6a3b84c3 100644
--- a/tests/ahriman/application/handlers/test_handler_rebuild.py
+++ b/tests/ahriman/application/handlers/test_handler_rebuild.py
@@ -66,6 +66,7 @@ def test_run_extract_packages(args: argparse.Namespace, configuration: Configura
args.dry_run = True
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.application.application.Application.add")
+ mocker.patch("ahriman.application.application.Application.print_updates")
extract_mock = mocker.patch("ahriman.application.handlers.Rebuild.extract_packages", return_value=[])
Rebuild.run(args, "x86_64", configuration, report=False, unsafe=False)
@@ -83,10 +84,12 @@ def test_run_dry_run(args: argparse.Namespace, configuration: Configuration, rep
mocker.patch("ahriman.application.handlers.Rebuild.extract_packages", return_value=[package_ahriman])
application_mock = mocker.patch("ahriman.application.application.Application.update")
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
+ print_mock = mocker.patch("ahriman.application.application.Application.print_updates")
Rebuild.run(args, "x86_64", configuration, report=False, unsafe=False)
application_mock.assert_not_called()
check_mock.assert_called_once_with(False, False)
+ print_mock.assert_called_once_with([package_ahriman], log_fn=pytest.helpers.anyvar(int))
def test_run_filter(args: argparse.Namespace, configuration: Configuration, repository: Repository,
@@ -131,6 +134,7 @@ def test_run_update_empty_exception(args: argparse.Namespace, configuration: Con
mocker.patch("ahriman.core.repository.Repository.load", return_value=repository)
mocker.patch("ahriman.application.handlers.Rebuild.extract_packages")
mocker.patch("ahriman.core.repository.repository.Repository.packages_depend_on", return_value=[])
+ mocker.patch("ahriman.application.application.Application.print_updates")
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
Rebuild.run(args, "x86_64", configuration, report=False, unsafe=False)
diff --git a/tests/ahriman/application/handlers/test_handler_update.py b/tests/ahriman/application/handlers/test_handler_update.py
index 8ce3898f..496fac11 100644
--- a/tests/ahriman/application/handlers/test_handler_update.py
+++ b/tests/ahriman/application/handlers/test_handler_update.py
@@ -51,15 +51,16 @@ def test_run(args: argparse.Namespace, package_ahriman: Package, configuration:
return_value=[package_ahriman])
updates_mock = mocker.patch("ahriman.application.application.Application.updates", return_value=[package_ahriman])
on_start_mock = mocker.patch("ahriman.application.application.Application.on_start")
+ print_mock = mocker.patch("ahriman.application.application.Application.print_updates")
Update.run(args, "x86_64", configuration, report=False, unsafe=False)
application_mock.assert_called_once_with([package_ahriman],
Packagers(args.username, {package_ahriman.base: "packager"}))
- updates_mock.assert_called_once_with(args.package, aur=args.aur, local=args.local, manual=args.manual, vcs=args.vcs,
- log_fn=pytest.helpers.anyvar(int))
+ updates_mock.assert_called_once_with(args.package, aur=args.aur, local=args.local, manual=args.manual, vcs=args.vcs)
dependencies_mock.assert_called_once_with([package_ahriman], process_dependencies=args.dependencies)
check_mock.assert_has_calls([MockCall(False, False), MockCall(False, False)])
on_start_mock.assert_called_once_with()
+ print_mock.assert_called_once_with([package_ahriman], log_fn=pytest.helpers.anyvar(int))
def test_run_empty_exception(args: argparse.Namespace, configuration: Configuration, repository: Repository,
@@ -89,6 +90,7 @@ def test_run_update_empty_exception(args: argparse.Namespace, package_ahriman: P
mocker.patch("ahriman.application.application.Application.update", return_value=Result())
mocker.patch("ahriman.application.application.Application.updates", return_value=[package_ahriman])
mocker.patch("ahriman.application.application.Application.with_dependencies", return_value=[package_ahriman])
+ mocker.patch("ahriman.application.application.Application.print_updates")
check_mock = mocker.patch("ahriman.application.handlers.Handler.check_if_empty")
Update.run(args, "x86_64", configuration, report=False, unsafe=False)
@@ -108,8 +110,7 @@ def test_run_dry_run(args: argparse.Namespace, configuration: Configuration, rep
updates_mock = mocker.patch("ahriman.application.application.Application.updates")
Update.run(args, "x86_64", configuration, report=False, unsafe=False)
- updates_mock.assert_called_once_with(args.package, aur=args.aur, local=args.local, manual=args.manual, vcs=args.vcs,
- log_fn=pytest.helpers.anyvar(int))
+ updates_mock.assert_called_once_with(args.package, aur=args.aur, local=args.local, manual=args.manual, vcs=args.vcs)
application_mock.assert_not_called()
check_mock.assert_called_once_with(False, pytest.helpers.anyvar(int))