Skip to content

Commit

Permalink
Use package_version_cmp to compare package versions
Browse files Browse the repository at this point in the history
Signed-off-by: Rodolfo Olivieri <rolivier@redhat.com>
  • Loading branch information
r0x0d committed Apr 26, 2022
1 parent 3e84e02 commit 74b12c5
Show file tree
Hide file tree
Showing 4 changed files with 217 additions and 124 deletions.
52 changes: 9 additions & 43 deletions convert2rhel/checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,17 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.


import functools
import itertools
import logging
import os
import re

from convert2rhel import grub
from convert2rhel.pkghandler import call_yum_cmd, get_installed_pkg_objects, get_pkg_fingerprint
from convert2rhel.pkghandler import call_yum_cmd, get_installed_pkg_objects, get_pkg_fingerprint, package_version_cmp
from convert2rhel.systeminfo import system_info
from convert2rhel.toolopts import tool_opts
from convert2rhel.utils import convert_to_int_or_zero, get_file_content, run_subprocess
from convert2rhel.utils import get_file_content, run_subprocess


logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -330,50 +330,16 @@ def get_most_recent_unique_kernel_pkgs(pkgs):
list_of_sorted_pkgs = []
for distinct_kernel_pkgs in pkgs_groups:
if distinct_kernel_pkgs[0].startswith(("kernel", "kmod")):
list_of_sorted_pkgs.append(max(distinct_kernel_pkgs[1], key=_repos_version_key))
list_of_sorted_pkgs.append(
max(
distinct_kernel_pkgs[1],
key=functools.cmp_to_key(package_version_cmp),
)
)

return tuple(list_of_sorted_pkgs)


def _repos_version_key(pkg_name):
"""Identify the version key in a given package name.
Consider the following pkg_name that will be passed to this function::
pkg_name = 'kernel-core-0:4.18.0-240.10.1.el8_3.x86_64'
The output of this will be a tuple containing the package version in a tuple::
result = _repos_version_key(pkg_name=pkg_name)
print(result)
# (4, 18, 0, 240, 10, 1)
The function will ignore the package name as it is not an important information here
and will only care about the version that is tied to it's name.
:param pkg_name: The package to extract the version
:type pkg_name: str
:return: A tuple containing the package version.
:rtype: tuple[int]
:raises SystemExit: Raises SytemExit if it can't find the version in the pkg_name.
"""
# TODO(r0x0d): This should be moved to repo.py or utils.py?
try:
rpm_version = KERNEL_REPO_RE.search(pkg_name).group("version")
except AttributeError:
logger.critical(
"Unexpected package: %s\n Couldn't find the version of the given package.",
pkg_name,
)
else:
return tuple(
map(
convert_to_int_or_zero,
KERNEL_REPO_VER_SPLIT_RE.split(rpm_version),
)
)


def get_rhel_kmods_keys(rhel_kmods_str):
return set(
_get_kmod_comparison_key(kmod_path)
Expand Down
51 changes: 50 additions & 1 deletion convert2rhel/pkghandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -768,7 +768,14 @@ def replace_non_rhel_installed_kernel(version):
output, ret_code = utils.run_subprocess(
# The --nodeps is needed as some kernels depend on system-release (alias for redhat-release) and that package
# is not installed at this stage.
["rpm", "-i", "--force", "--nodeps", "--replacepkgs", "%s*" % os.path.join(utils.TMP_DIR, pkg)],
[
"rpm",
"-i",
"--force",
"--nodeps",
"--replacepkgs",
"%s*" % os.path.join(utils.TMP_DIR, pkg),
],
print_output=False,
)
if ret_code != 0:
Expand Down Expand Up @@ -968,3 +975,45 @@ def get_pkg_names_from_rpm_paths(rpm_paths):
for rpm_path in rpm_paths:
pkg_names.append(utils.get_package_name_from_rpm(rpm_path))
return pkg_names


def package_version_cmp(pkg_1, pkg_2):
"""Compare the version key in a given package name.
Consider the following variables that will be passed to this function::
pkg_1 = 'kernel-core-0:4.18.0-240.10.1.el8_3.x86_64'
pkg_2 = 'kernel-core-0:4.18.0-239.0.0.el8_3.x86_64'
The output of this will be a tuple containing the package version in a tuple::
result = package_version_cmp(pkg_1, pkg_2)
print("Result is: %s" % result)
# Result is: -1
The function will ignore the package name as it is not an important information here
and will only care about the version that is tied to it's name.
:param pkg_1: The first package to extract the version
:type pkg_1: str
:param pkg_2: The second package to extract the version
:type pkg_2: str
:return: An integer resulting in the package comparision
:rtype: int
"""
pkg_ver_components = []
for pkg in pkg_1, pkg_2:
# Remove the package name and split the rest between epoch + version and release + arch
epoch_version, release_arch = pkg.rsplit("-", 2)[-2:]
# Separate the (optional) epoch from the version
epoch_version = epoch_version.split(":", 1)
if len(epoch_version) == 1:
epoch = "0"
version = epoch_version[0]
else:
epoch, version = epoch_version
# Discard the arch
release = release_arch.rsplit(".", 1)[0]
pkg_ver_components.append((epoch, version, release))

return rpm.labelCompare(pkg_ver_components[0], pkg_ver_components[1])
77 changes: 17 additions & 60 deletions convert2rhel/unit_tests/checks_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,10 +333,10 @@ def test_get_loaded_kmods(monkeypatch):


@pytest.mark.parametrize(
("repoquery_f_stub", "repoquery_l_stub", "exception"),
("repoquery_f_stub", "repoquery_l_stub"),
(
(REPOQUERY_F_STUB_GOOD, REPOQUERY_L_STUB_GOOD, None),
(REPOQUERY_F_STUB_BAD, REPOQUERY_L_STUB_GOOD, SystemExit),
(REPOQUERY_F_STUB_GOOD, REPOQUERY_L_STUB_GOOD),
(REPOQUERY_F_STUB_BAD, REPOQUERY_L_STUB_GOOD),
),
)
@centos8
Expand All @@ -345,7 +345,6 @@ def test_get_rhel_supported_kmods(
pretend_os,
repoquery_f_stub,
repoquery_l_stub,
exception,
):
run_subprocess_mock = mock.Mock(
side_effect=run_subprocess_side_effect(
Expand All @@ -364,24 +363,21 @@ def test_get_rhel_supported_kmods(
"run_subprocess",
value=run_subprocess_mock,
)
if exception:
with pytest.raises(exception):
checks.get_rhel_supported_kmods()
else:
res = checks.get_rhel_supported_kmods()
assert res == set(
(
"kernel/lib/a.ko",
"kernel/lib/a.ko.xz",
"kernel/lib/b.ko.xz",
"kernel/lib/c.ko.xz",
"kernel/lib/c.ko",
)

res = checks.get_rhel_supported_kmods()
assert res == set(
(
"kernel/lib/a.ko",
"kernel/lib/a.ko.xz",
"kernel/lib/b.ko.xz",
"kernel/lib/c.ko.xz",
"kernel/lib/c.ko",
)
)


@pytest.mark.parametrize(
("pkgs", "exp_res", "exception"),
("pkgs", "exp_res"),
(
(
(
Expand All @@ -394,67 +390,47 @@ def test_get_rhel_supported_kmods(
"kernel-core-0:4.18.0-240.15.1.el8_3.x86_64",
"kernel-debug-core-0:4.18.0-240.15.1.el8_3.x86_64",
),
None,
),
(
(
"kmod-core-0:4.18.0-240.10.1.el8_3.x86_64",
"kmod-core-0:4.18.0-240.15.1.el8_3.x86_64",
),
("kmod-core-0:4.18.0-240.15.1.el8_3.x86_64",),
None,
),
(
(
"not-expected-core-0:4.18.0-240.10.1.el8_3.x86_64",
"kmod-core-0:4.18.0-240.15.1.el8_3.x86_64",
),
("kmod-core-0:4.18.0-240.15.1.el8_3.x86_64",),
None,
),
(
(
"kernel-core-0:4.18.0-240.beta5.1.el8_3.x86_64",
"kernel-core-0:4.18.0-240.15.1.el8_3.x86_64",
),
("kernel-core-0:4.18.0-240.15.1.el8_3.x86_64",),
None,
),
(
(
"kernel-core-0:4.18.0-240.15.beta5.1.el8_3.x86_64",
"kernel-core-0:4.18.0-240.15.1.el8_3.x86_64",
),
("kernel-core-0:4.18.0-240.15.1.el8_3.x86_64",),
None,
),
(
(
"kernel-core-0:4.18.0-240.16.beta5.1.el8_3.x86_64",
"kernel-core-0:4.18.0-240.15.1.el8_3.x86_64",
),
("kernel-core-0:4.18.0-240.16.beta5.1.el8_3.x86_64",),
None,
),
(("kernel_bad_package:111111",), (), SystemExit),
(
(
"kernel-core-0:4.18.0-240.15.1.el8_3.x86_64",
"kernel_bad_package:111111",
"kernel-core-0:4.18.0-240.15.1.el8_3.x86_64",
),
(),
SystemExit,
),
),
)
def test_get_most_recent_unique_kernel_pkgs(pkgs, exp_res, exception):
if not exception:
most_recent_pkgs = tuple(checks.get_most_recent_unique_kernel_pkgs(pkgs))
assert exp_res == most_recent_pkgs
else:
with pytest.raises(exception):
tuple(checks.get_most_recent_unique_kernel_pkgs(pkgs))
def test_get_most_recent_unique_kernel_pkgs(pkgs, exp_res):
most_recent_pkgs = tuple(checks.get_most_recent_unique_kernel_pkgs(pkgs))
assert exp_res == most_recent_pkgs


@pytest.mark.parametrize(
Expand Down Expand Up @@ -853,22 +829,3 @@ def test_custom_repos_are_invalid(self):
self.assertEqual(len(checks.logger.critical_msgs), 1)
self.assertEqual(len(checks.logger.info_msgs), 0)
self.assertTrue("Unable to access the repositories passed through " in checks.logger.critical_msgs[0])


@pytest.mark.parametrize(
("pkg_name", "expected"),
(
("kernel-core-0:4.18.0-240.10.1.el8_3.x86_64", (4, 18, 0, 240, 10, 1)),
(
"kernel-debug-1:4.19.1-270.11.2.el8_3.x86_64",
(4, 19, 1, 270, 11, 2),
),
),
)
def test_repos_version_key(pkg_name, expected):
assert checks._repos_version_key(pkg_name=pkg_name) == expected


def test_repos_version_key_system_exit():
with pytest.raises(SystemExit):
checks._repos_version_key("kernel-core.el8_3.x86_64")
Loading

0 comments on commit 74b12c5

Please # to comment.