Bug #278729 - Inside dep_zapdeps(), account for USE dependencies in some
authorZac Medico <zmedico@gentoo.org>
Thu, 27 Aug 2009 07:14:37 +0000 (07:14 -0000)
committerZac Medico <zmedico@gentoo.org>
Thu, 27 Aug 2009 07:14:37 +0000 (07:14 -0000)
cases where USE settings can adversely affect || preference evaluation. This
requires invalid atoms to be dropped inside _expand_new_virtuals() since we
only want real Atom instances inside dep_zapdeps(). Unlike previous attempts
to solve this bug, cases such as || ( foo[a] foo[b] ) should now be correctly
handled.

svn path=/main/trunk/; revision=14165

pym/portage/__init__.py

index 8669dd7f88680151e66f776cb19bdfad2e3db9a7..9f251882b2046aac8759f70a9a2162ec5c953b63 100644 (file)
@@ -7452,6 +7452,9 @@ def _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, myroot="/",
                                if portage.dep._dep_check_strict:
                                        raise portage.exception.ParseError(
                                                _("invalid atom: '%s'") % x)
+                               else:
+                                       # Only real Atom instances are allowed past this point.
+                                       continue
                        else:
                                if x.blocker and x.blocker.overlap.forbid and \
                                        eapi in ("0", "1") and portage.dep._dep_check_strict:
@@ -7638,6 +7641,7 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None):
 
        preferred_installed = []
        preferred_in_graph = []
+       preferred_unsatisfied_use = []
        preferred_any_slot = []
        preferred_non_installed = []
        other = []
@@ -7669,19 +7673,35 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None):
                        continue
 
                all_available = True
+               all_use_satisfied = True
                versions = {}
                for atom in atoms:
                        if atom[:1] == "!":
                                continue
-                       avail_pkg = mydbapi.match(atom)
+                       # Ignore USE dependencies here since we don't want USE
+                       # settings to adversely affect || preference evaluation.
+                       avail_pkg = mydbapi.match(atom.without_use)
                        if avail_pkg:
                                avail_pkg = avail_pkg[-1] # highest (ascending order)
                                avail_slot = "%s:%s" % (dep_getkey(atom),
                                        mydbapi.aux_get(avail_pkg, ["SLOT"])[0])
                        if not avail_pkg:
                                all_available = False
+                               all_use_satisfied = False
                                break
 
+                       if atom.use:
+                               avail_pkg_use = mydbapi.match(atom)
+                               if not avail_pkg_use:
+                                       all_use_satisfied = False
+                               else:
+                                       # highest (ascending order)
+                                       avail_pkg_use = avail_pkg_use[-1]
+                                       if avail_pkg_use != avail_pkg:
+                                               avail_pkg = avail_pkg_use
+                                               avail_slot = "%s:%s" % (dep_getkey(atom),
+                                                       mydbapi.aux_get(avail_pkg, ["SLOT"])[0])
+
                        versions[avail_slot] = avail_pkg
 
                this_choice = (atoms, versions, all_available)
@@ -7705,13 +7725,17 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None):
                                                not slot_atom.startswith("virtual/"):
                                                all_installed_slots = False
                                                break
-                       if graph_db is None and all_installed:
-                               if all_installed_slots:
-                                       preferred_installed.append(this_choice)
+                       if graph_db is None:
+                               if all_use_satisfied:
+                                       if all_installed:
+                                               if all_installed_slots:
+                                                       preferred_installed.append(this_choice)
+                                               else:
+                                                       preferred_any_slot.append(this_choice)
+                                       else:
+                                               preferred_non_installed.append(this_choice)
                                else:
-                                       preferred_any_slot.append(this_choice)
-                       elif graph_db is None:
-                               preferred_non_installed.append(this_choice)
+                                       other.append(this_choice)
                        else:
                                all_in_graph = True
                                for slot_atom in versions:
@@ -7720,9 +7744,10 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None):
                                                not slot_atom.startswith("virtual/"):
                                                all_in_graph = False
                                                break
+                               circular_atom = None
                                if all_in_graph:
                                        if parent is None or priority is None:
-                                               preferred_in_graph.append(this_choice)
+                                               pass
                                        elif priority.buildtime:
                                                # Check if the atom would result in a direct circular
                                                # dependency and try to avoid that if it seems likely
@@ -7730,7 +7755,6 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None):
                                                # buildtime deps that aren't already satisfied by an
                                                # installed package.
                                                cpv_slot_list = [parent]
-                                               circular_atom = None
                                                for atom in atoms:
                                                        if "!" == atom[:1]:
                                                                continue
@@ -7743,25 +7767,32 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None):
                                                        if match_from_list(atom, cpv_slot_list):
                                                                circular_atom = atom
                                                                break
-                                               if circular_atom is None:
+                               if circular_atom is not None:
+                                       other.append(this_choice)
+                               else:
+                                       if all_use_satisfied:
+                                               if all_in_graph:
                                                        preferred_in_graph.append(this_choice)
+                                               elif all_installed:
+                                                       if all_installed_slots:
+                                                               preferred_installed.append(this_choice)
+                                                       else:
+                                                               preferred_any_slot.append(this_choice)
                                                else:
-                                                       other.append(this_choice)
+                                                       preferred_non_installed.append(this_choice)
                                        else:
-                                               preferred_in_graph.append(this_choice)
-                               else:
-                                       if all_installed:
-                                               if all_installed_slots:
-                                                       preferred_installed.append(this_choice)
+                                               if all_in_graph or all_installed:
+                                                       preferred_unsatisfied_use.append(this_choice)
                                                else:
-                                                       preferred_any_slot.append(this_choice)
-                                       else:
-                                               preferred_non_installed.append(this_choice)
+                                                       other.append(this_choice)
                else:
                        other.append(this_choice)
 
+       # preferred_unsatisfied_use must come after preferred_non_installed
+       # for correct ordering in cases like || ( foo[a] foo[b] ).
        preferred = preferred_in_graph + preferred_installed + \
-               preferred_any_slot + preferred_non_installed + other
+               preferred_any_slot + preferred_non_installed + \
+               preferred_unsatisfied_use + other
 
        for allow_masked in (False, True):
                for atoms, versions, all_available in preferred: