On Sun, 20 Nov 2016 15:56:54 -0800 Zac Medico <zmed...@gentoo.org> wrote:
> When selecting packages to determine which choices have upgrades > or downgrades relative to other choices, make the package selections > internally consistent by choosing a package that satisfies all atoms > in the choice which match a package in the same slot. > > Also, fix the Atom.match() method to handle _pkg_str instances, > since dep_zapdeps can pass in _pkg_str instances instead of Package > instances. > > X-Gentoo-Bug: 600346 > X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=600346 > --- > [PATCH v2] fixes incorrect logic in dep_zapdeps > > pym/portage/dep/__init__.py | 16 ++++++++++++---- > pym/portage/dep/dep_check.py | 28 ++++++++++++++++++++++++++-- > 2 files changed, 38 insertions(+), 6 deletions(-) > > diff --git a/pym/portage/dep/__init__.py b/pym/portage/dep/__init__.py > index 5dd1638..968ff5b 100644 > --- a/pym/portage/dep/__init__.py > +++ b/pym/portage/dep/__init__.py > @@ -1603,10 +1603,18 @@ class Atom(_unicode): > if pkg.cp == self.cp: > return bool(match_from_list(self, [pkg])) > else: > - for provided_cp in pkg.provided_cps: > - if provided_cp == self.cp: > - return bool(match_from_list( > - > self.replace(self.cp, provided_cp, 1), [pkg])) > + try: > + provided_cps = pkg.provided_cps > + except AttributeError: > + # Since _pkg_str instances lack > PROVIDE metadata, > + # just ignore this case (PROVIDE has > been deprecated > + # for years). > + pass > + else: > + for provided_cp in provided_cps: > + if provided_cp == self.cp: > + return > bool(match_from_list( > + > self.replace(self.cp, provided_cp, 1), [pkg])) return False > > _extended_cp_re_cache = {} > diff --git a/pym/portage/dep/dep_check.py > b/pym/portage/dep/dep_check.py index 9d2ca4b..737d2b1 100644 > --- a/pym/portage/dep/dep_check.py > +++ b/pym/portage/dep/dep_check.py > @@ -5,6 +5,7 @@ from __future__ import unicode_literals > > __all__ = ['dep_check', 'dep_eval', 'dep_wordreduce', 'dep_zapdeps'] > > +import collections > import logging > import operator > > @@ -354,6 +355,7 @@ def dep_zapdeps(unreduced, reduced, myroot, > use_binaries=0, trees=None): all_use_satisfied = True > all_use_unmasked = True > conflict_downgrade = False > + slot_atoms = collections.defaultdict(list) > slot_map = {} > cp_map = {} > for atom in atoms: > @@ -418,9 +420,31 @@ def dep_zapdeps(unreduced, reduced, myroot, > use_binaries=0, trees=None): avail_slot = Atom("%s:%s" % (atom.cp, > avail_pkg.slot)) > slot_map[avail_slot] = avail_pkg > + slot_atoms[avail_slot].append(atom) > highest_cpv = cp_map.get(avail_pkg.cp) > - if highest_cpv is None or \ > - vercmp(avail_pkg.version, > highest_cpv.version) > 0: > + all_match_current = None > + all_match_previous = None > + if (highest_cpv is not None and > + highest_cpv.slot == avail_pkg.slot): > + # If possible, make the package > selection internally > + # consistent by choosing a package > that satisfies all > + # atoms which match a package in the > same slot. Later on, > + # the package version chosen here is > used in the > + # has_upgrade/has_downgrade logic to > prefer choices with > + # upgrades, and a package choice > that is not internally > + # consistent will lead the > has_upgrade/has_downgrade logic > + # to produce invalid results (see > bug 600346). > + all_match_current = > all(a.match(avail_pkg) > + for a in > slot_atoms[avail_slot]) > + all_match_previous = > all(a.match(highest_cpv) > + for a in > slot_atoms[avail_slot]) > + if all_match_previous and not > all_match_current: > + continue > + > + current_higher = (highest_cpv is None or > + vercmp(avail_pkg.version, > highest_cpv.version) > 0) + > + if current_higher or (all_match_current and > not all_match_previous): cp_map[avail_pkg.cp] = avail_pkg > > this_choice = _dep_choice(atoms=atoms, > slot_map=slot_map, looks good -- Brian Dolbec <dolsen>