commit 25a1cf0a8f0002b16d6ef9c24d530019fd88fd64
Author: Michal Domonkos <mdomonko@redhat.com>
Date: Wed May 16 17:40:22 2018 +0200
update(): honor multilib_policy for obsoletes. BZ 1477574
When a package migrates from noarch to arch during an update, we usually
don't want to install all the newly available multilib arches.
For "yum install", this is already controlled by multilib_policy, even
if the noarch package is already installed (since yum will try to update
it). However, with "yum update", multilib_policy isn't checked.
This commit adds the check to update() so that "yum update" works the
same as "yum install" in the noarch->arch scenario.
Tests calling "update" without arguments now need to specify
multilib_policy='all'.
diff --git a/test/simpleobsoletestests.py b/test/simpleobsoletestests.py
index 6cede1e0..a26a5d42 100644
--- a/test/simpleobsoletestests.py
+++ b/test/simpleobsoletestests.py
@@ -38,7 +38,8 @@ class SimpleObsoletesTests(OperationsTests):
def testObsoletenoarchToi386(self):
p = self.pkgs
- res, msg = self.runOperation(['update'], [p.installed_noarch], [p.obsoletes_i386])
+ res, msg = self.runOperation(['update'], [p.installed_noarch], [p.obsoletes_i386],
+ {'multilib_policy': 'all'})
self.assert_(res=='ok', msg)
self.assertResult((p.obsoletes_i386,))
def testObsoletenoarchToi386ForDependency(self):
@@ -50,7 +51,8 @@ class SimpleObsoletesTests(OperationsTests):
def testObsoletenoarchTox86_64(self):
p = self.pkgs
- res, msg = self.runOperation(['update'], [p.installed_noarch], [p.obsoletes_x86_64])
+ res, msg = self.runOperation(['update'], [p.installed_noarch], [p.obsoletes_x86_64],
+ {'multilib_policy': 'all'})
self.assert_(res=='ok', msg)
self.assertResult((p.obsoletes_x86_64,))
def testObsoletenoarchTox86_64ForDependency(self):
@@ -62,7 +64,8 @@ class SimpleObsoletesTests(OperationsTests):
def testObsoletenoarchToMultiarch(self):
p = self.pkgs
- res, msg = self.runOperation(['update'], [p.installed_noarch], [p.obsoletes_i386, p.obsoletes_x86_64])
+ res, msg = self.runOperation(['update'], [p.installed_noarch], [p.obsoletes_i386, p.obsoletes_x86_64],
+ {'multilib_policy': 'all'})
self.assert_(res=='ok', msg)
if new_behavior:
self.assertResult((p.obsoletes_x86_64,), (p.obsoletes_i386,))
diff --git a/yum/__init__.py b/yum/__init__.py
index a156a6a6..7b7293f3 100644
--- a/yum/__init__.py
+++ b/yum/__init__.py
@@ -4779,6 +4779,21 @@ much more problems).
return False
return True
+ def _valid_obsoleter_arch(self, obsoleter, obsoletee):
+ """Return whether this obsoleter meets multilib_policy in case we are
+ dealing with the noarch->arch obsoletion case."""
+ if not self.arch.multilib or self.conf.multilib_policy != 'best':
+ # Install everything
+ return True
+ if obsoletee.arch != 'noarch' or obsoleter.arch == 'noarch':
+ # We do respect any arch->(no)arch obsoletions (having
+ # obsoletee.i386 installed on x86_64, you'd still expect
+ # obsoleter.i386 to replace it, even if you have
+ # multilib_policy=best).
+ return True
+ # noarch->arch case
+ return obsoleter.arch in self.arch.legit_multi_arches
+
def install(self, po=None, **kwargs):
"""Mark the specified item for installation. If a package
object is given, mark it for installation. Otherwise, mark
@@ -5146,10 +5161,12 @@ much more problems).
allow_missing=True)
if obsoleting_pkg is None:
continue
+ installed_pkg = self.getInstalledPackageObject(installed)
+ if not self._valid_obsoleter_arch(obsoleting_pkg, installed_pkg):
+ continue
topkg = self._test_loop(obsoleting_pkg, self._pkg2obspkg)
if topkg is not None:
obsoleting_pkg = topkg
- installed_pkg = self.getInstalledPackageObject(installed)
txmbr = self.tsInfo.addObsoleting(obsoleting_pkg, installed_pkg)
self.tsInfo.addObsoleted(installed_pkg, obsoleting_pkg)
if requiringPo:
@@ -5183,6 +5200,7 @@ much more problems).
instpkgs = []
availpkgs = []
+ arch_specified = True
if po: # just a po
if po.repoid == 'installed':
instpkgs.append(po)
@@ -5244,6 +5262,8 @@ much more problems).
self.logger.critical(_('No Match for argument: %s') % to_unicode(arg))
if not self.conf.skip_missing_names_on_update:
raise Errors.UpdateMissingNameError, _('Not tolerating missing names on update, stopping.')
+
+ arch_specified = '.' in kwargs['pattern']
else: # we have kwargs, sort them out.
nevra_dict = self._nevra_kwarg_parse(kwargs)
@@ -5296,12 +5316,16 @@ much more problems).
allow_missing=True)
if obsoleting_pkg is None:
continue
+ if not arch_specified and not self._valid_obsoleter_arch(obsoleting_pkg, installed_pkg):
+ continue
obs_pkgs.append(obsoleting_pkg)
# NOTE: Broekn wrt. repoid
for obsoleting_pkg in packagesNewestByName(obs_pkgs):
tx_return.extend(self.install(po=obsoleting_pkg))
for available_pkg in availpkgs:
for obsoleted_pkg in self._find_obsoletees(available_pkg):
+ if not arch_specified and not self._valid_obsoleter_arch(available_pkg, obsoleted_pkg):
+ continue
obsoleted = obsoleted_pkg.pkgtup
txmbr = self.tsInfo.addObsoleting(available_pkg, obsoleted_pkg)
if requiringPo: