diff --git a/tests/unit/artifact/test_copr_repository.py b/tests/unit/artifact/test_copr_repository.py index d15cbc5a3e..aaedabbcf0 100644 --- a/tests/unit/artifact/test_copr_repository.py +++ b/tests/unit/artifact/test_copr_repository.py @@ -2,6 +2,8 @@ import pytest +from tmt.package_managers._rpm import RpmVersion + @pytest.mark.parametrize( ("raw_id", "expected"), @@ -68,8 +70,8 @@ def test_enumerate_artifacts( mock_guest.package_manager = mock_package_manager mock_package_manager.list_packages.return_value = [ - 'tmt-1.69.0-1.fc42.noarch', - 'tmt-all-0:1.69.0-1.fc42.noarch', + RpmVersion.from_nevra('tmt-1.69.0-1.fc42.noarch'), + RpmVersion.from_nevra('tmt-all-0:1.69.0-1.fc42.noarch'), ] provider = artifact_provider("copr.repository:@teemtee/stable") diff --git a/tmt/package_managers/__init__.py b/tmt/package_managers/__init__.py index 874a608097..2ef2ca8f44 100644 --- a/tmt/package_managers/__init__.py +++ b/tmt/package_managers/__init__.py @@ -499,21 +499,14 @@ def install_repository(self, repository: "Repository") -> CommandOutput: """ return self.guest.execute(self.engine.install_repository(repository)) - def list_packages(self, repository: "Repository") -> list[str]: + def list_packages(self, repository: "Repository") -> list[Version]: """ List packages available in the specified repository. :param repository: The repository to query. - :returns: A list of package names available in the repository. + :returns: A list of versions available in the repository. """ - script = self.engine.list_packages(repository) - output = self.guest.execute(script) - stdout = output.stdout - - if stdout is None: - raise GeneralError("Repository query provided no output") - - return stdout.strip().splitlines() + raise NotImplementedError def get_package_origin(self, packages: Iterable[str]) -> 'dict[str, PackageOrigin]': """ diff --git a/tmt/package_managers/dnf.py b/tmt/package_managers/dnf.py index 436ea8d58d..a426ee172c 100644 --- a/tmt/package_managers/dnf.py +++ b/tmt/package_managers/dnf.py @@ -11,6 +11,7 @@ PackageManager, PackageManagerEngine, Repository, + Version, escape_installables, provides_package_manager, ) @@ -242,6 +243,19 @@ class Dnf(PackageManager[DnfEngine]): # the `dnf` family just stays below it. probe_priority = 50 + def list_packages(self, repository: Repository) -> list[Version]: + from tmt.package_managers._rpm import RpmVersion + + script = self.engine.list_packages(repository) + output = self.guest.execute(script) + stdout = output.stdout + + if stdout is None: + raise GeneralError("Repository query provided no output") + + stripped_lines = (line.strip() for line in stdout.strip().splitlines()) + return [RpmVersion.from_nevra(line) for line in stripped_lines if line] + def check_presence(self, *installables: Installable) -> dict[Installable, bool]: try: output = self.guest.execute(self.engine.check_presence(*installables)) diff --git a/tmt/steps/prepare/artifact/providers/__init__.py b/tmt/steps/prepare/artifact/providers/__init__.py index 07335bd048..bc81b0db1f 100644 --- a/tmt/steps/prepare/artifact/providers/__init__.py +++ b/tmt/steps/prepare/artifact/providers/__init__.py @@ -15,7 +15,6 @@ from tmt.container import container from tmt.guest import Guest from tmt.package_managers import Repository, Version -from tmt.package_managers._rpm import RpmVersion from tmt.plugins import PluginRegistry from tmt.utils import Path, ShellScript @@ -110,7 +109,7 @@ def __init__(self, raw_id: str, repository_priority: int, logger: tmt.log.Logger self.sanitized_id = tmt.utils.sanitize_name(raw_id, allow_slash=False) self.id = self._extract_provider_id(raw_id) - self._artifacts = [] + self._artifacts: list[ArtifactInfo] = [] @classmethod @abstractmethod @@ -229,9 +228,7 @@ def get_repositories(self) -> list['Repository']: """ return [] - def enumerate_artifacts( - self, guest: Guest - ) -> None: # TODO: refactor this once the NEVRA parsing is centralized. + def enumerate_artifacts(self, guest: Guest) -> None: """ Enumerate artifacts from repositories returned by :py:meth:`get_repositories` and populate :py:attr:`_artifacts`. Call this after repositories are installed. @@ -241,7 +238,7 @@ def enumerate_artifacts( """ for repository in self.get_repositories(): try: - nevras = guest.package_manager.list_packages(repository) + packages = guest.package_manager.list_packages(repository) except tmt.utils.RunError as error: tmt.utils.show_exception_as_warning( exception=error, @@ -249,27 +246,17 @@ def enumerate_artifacts( logger=self.logger, ) continue - count = 0 - for nevra in nevras: - nevra = nevra.strip() - if not nevra: - continue - try: - self._artifacts.append( - ArtifactInfo( - version=RpmVersion.from_nevra(nevra), - provider=self, - location=repository.name, - ) + for rpm_version in packages: + self._artifacts.append( + ArtifactInfo( + version=rpm_version, + provider=self, + location=repository.name, ) - count += 1 - except ValueError as error: - tmt.utils.show_exception_as_warning( - exception=error, - message=f"Could not parse NEVRA '{nevra}'.", - logger=self.logger, - ) - self.logger.debug(f"Enumerated {count} packages from repository '{repository.name}'.") + ) + self.logger.debug( + f"Enumerated {len(packages)} packages from repository '{repository.name}'." + ) # B027: "... is an empty method in an abstract base class, but has # no abstract decorator" - expected, it's a default implementation