From dadfe65ce753ba8a8bdb5e38d7929135526edbd5 Mon Sep 17 00:00:00 2001 From: Marek Blaha Date: Thu, 31 Aug 2023 13:18:03 +0200 Subject: [PATCH] hawkey.subject: get_best_selectors only obsoleters of latest In situation where a package exists in multiple versions and some older version is being obsoleted, any of obsoleters was considered a valid solution. The result could be really misleading. For example let's have this package set: systemd-udev-1.0 systemd-udev-2.0 Obsoletes: systemd-udev < 2 systemd-boot-unsigned-2.0 Obsoletes: systemd-udev < 2 In this case `dnf install systemd-udev` may lead to installation of systemd-boot-unsigned which is probably not what the user expected. The reason is the split in the upgrade-path created by obsolete and both branches - systemd-udev-2.0 and systemd-boot-unsigned-2.0 are considered valid. With this patch install command takes into account only obsoleters of the best version of the package so the `dnf install systemd-udev` results in correct installation of systemd-udev-2.0 package. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2183279 Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2176263 --- python/hawkey/__init__.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/python/hawkey/__init__.py b/python/hawkey/__init__.py index 45bdc3a..1ec1ef4 100644 --- a/python/hawkey/__init__.py +++ b/python/hawkey/__init__.py @@ -291,13 +291,13 @@ class Subject(_hawkey.Subject): # after movement of base.install() or base.distro_sync() return [] + installed_query = q.installed() if not self._filename_pattern and is_glob_pattern(self.pattern) \ or solution['nevra'] and solution['nevra'].name is None: with_obsoletes = False if obsoletes and solution['nevra'] and solution['nevra'].has_just_name(): with_obsoletes = True - installed_query = q.installed() if reponame: q = q.filter(reponame=reponame) available_query = q.available() @@ -309,13 +309,24 @@ class Subject(_hawkey.Subject): sltrs = [] for name, pkgs_list in q._name_dict().items(): if with_obsoletes: + # If there is no installed package in the pkgs_list, add only + # obsoleters of the latest versions. Otherwise behave consistently + # with upgrade and add all obsoleters. + # See https://bugzilla.redhat.com/show_bug.cgi?id=2176263 + # for details of the problem. + obsoletes_query = base.sack.query().filterm(pkg=pkgs_list) + if not obsoletes_query.installed(): + obsoletes_query.filterm(latest_per_arch_by_priority=True) pkgs_list = pkgs_list + base.sack.query().filter( - obsoletes=pkgs_list).run() + obsoletes=obsoletes_query).run() sltrs.append(self._list_or_query_to_selector(base.sack, pkgs_list)) return sltrs else: if obsoletes and solution['nevra'] and solution['nevra'].has_just_name(): - q = q.union(base.sack.query().filter(obsoletes=q)) + if installed_query: + q = q.union(base.sack.query().filter(obsoletes=q)) + else: + q = q.union(base.sack.query().filter(obsoletes=q.filter(latest_per_arch_by_priority=True))) installed_query = q.installed() if reports: -- libgit2 1.6.4