commit 25a1cf0a8f0002b16d6ef9c24d530019fd88fd64 Author: Michal Domonkos 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: