@@ -1935,16 +1935,9 @@ def _process_slot_conflicts(self):
19351935 # conflicts (or by blind luck).
19361936 raise self._unknown_internal_error()
19371937
1938- # Both _process_slot_conflict and _slot_operator_trigger_reinstalls
1939- # can call _slot_operator_update_probe, which requires that
1940- # self._dynamic_config._blocked_pkgs has been initialized by a
1941- # call to the _validate_blockers method.
19421938 for conflict in self._dynamic_config._package_tracker.slot_conflicts():
19431939 self._process_slot_conflict(conflict)
19441940
1945- if self._dynamic_config._allow_backtracking:
1946- self._slot_operator_trigger_reinstalls()
1947-
19481941 def _process_slot_conflict(self, conflict):
19491942 """
19501943 Process slot conflict data to identify specific atoms which
@@ -2900,50 +2893,50 @@ def _replace_installed_atom(self, inst_pkg):
29002893
29012894 return None
29022895
2903- def _slot_operator_trigger_reinstalls (self):
2896+ def _slot_operator_trigger_backtracking (self, dep ):
29042897 """
2905- Search for packages with slot- operator deps on older slots, and schedule
2906- rebuilds if they can link to a newer slot that's in the graph .
2898+ Trigger backtracking for slot operator issues if needed.
2899+ Return True if this triggers backtracking, and False otherwise .
29072900 """
2901+ if not self._dynamic_config._allow_backtracking:
2902+ return False
2903+
2904+ atom = dep.atom
2905+
2906+ if not (atom.soname or atom.slot_operator_built):
2907+ new_child_slot = self._slot_change_probe(dep)
2908+ if new_child_slot is not None:
2909+ self._slot_change_backtrack(dep, new_child_slot)
2910+ return True
2911+
2912+ if not (dep.parent and isinstance(dep.parent, Package) and dep.parent.built):
2913+ return False
29082914
29092915 rebuild_if_new_slot = (
29102916 self._dynamic_config.myparams.get("rebuild_if_new_slot", "y") == "y"
29112917 )
29122918
2913- for slot_key, slot_info in self._dynamic_config._slot_operator_deps.items():
2914- for dep in slot_info:
2915- atom = dep.atom
2916-
2917- if not (atom.soname or atom.slot_operator_built):
2918- new_child_slot = self._slot_change_probe(dep)
2919- if new_child_slot is not None:
2920- self._slot_change_backtrack(dep, new_child_slot)
2921- continue
2922-
2923- if not (
2924- dep.parent and isinstance(dep.parent, Package) and dep.parent.built
2925- ):
2926- continue
2919+ # If the parent is not installed, check if it needs to be
2920+ # rebuilt against an installed instance, since otherwise
2921+ # it could trigger downgrade of an installed instance as
2922+ # in bug #652938.
2923+ want_update_probe = dep.want_update or not dep.parent.installed
2924+
2925+ # Check for slot update first, since we don't want to
2926+ # trigger reinstall of the child package when a newer
2927+ # slot will be used instead.
2928+ if rebuild_if_new_slot and want_update_probe:
2929+ new_dep = self._slot_operator_update_probe(dep, new_child_slot=True)
2930+ if new_dep is not None:
2931+ self._slot_operator_update_backtrack(dep, new_child_slot=new_dep.child)
2932+ return True
29272933
2928- # If the parent is not installed, check if it needs to be
2929- # rebuilt against an installed instance, since otherwise
2930- # it could trigger downgrade of an installed instance as
2931- # in bug #652938.
2932- want_update_probe = dep.want_update or not dep.parent.installed
2933-
2934- # Check for slot update first, since we don't want to
2935- # trigger reinstall of the child package when a newer
2936- # slot will be used instead.
2937- if rebuild_if_new_slot and want_update_probe:
2938- new_dep = self._slot_operator_update_probe(dep, new_child_slot=True)
2939- if new_dep is not None:
2940- self._slot_operator_update_backtrack(
2941- dep, new_child_slot=new_dep.child
2942- )
2934+ if want_update_probe:
2935+ if self._slot_operator_update_probe(dep):
2936+ self._slot_operator_update_backtrack(dep)
2937+ return True
29432938
2944- if want_update_probe:
2945- if self._slot_operator_update_probe(dep):
2946- self._slot_operator_update_backtrack(dep)
2939+ return False
29472940
29482941 def _reinstall_for_flags(
29492942 self, pkg, forced_flags, orig_use, orig_iuse, cur_use, cur_iuse
@@ -3434,44 +3427,6 @@ def _add_pkg(self, pkg, dep):
34343427 raise
34353428 del e
34363429
3437- # NOTE: REQUIRED_USE checks are delayed until after
3438- # package selection, since we want to prompt the user
3439- # for USE adjustment rather than have REQUIRED_USE
3440- # affect package selection and || dep choices.
3441- if (
3442- not pkg.built
3443- and pkg._metadata.get("REQUIRED_USE")
3444- and eapi_has_required_use(pkg.eapi)
3445- ):
3446- required_use_is_sat = check_required_use(
3447- pkg._metadata["REQUIRED_USE"],
3448- self._pkg_use_enabled(pkg),
3449- pkg.iuse.is_valid_flag,
3450- eapi=pkg.eapi,
3451- )
3452- if not required_use_is_sat:
3453- if dep.atom is not None and dep.parent is not None:
3454- self._add_parent_atom(pkg, (dep.parent, dep.atom))
3455-
3456- if arg_atoms:
3457- for parent_atom in arg_atoms:
3458- parent, atom = parent_atom
3459- self._add_parent_atom(pkg, parent_atom)
3460-
3461- atom = dep.atom
3462- if atom is None:
3463- atom = Atom("=" + pkg.cpv)
3464- self._dynamic_config._unsatisfied_deps_for_display.append(
3465- ((pkg.root, atom), {"myparent": dep.parent, "show_req_use": pkg})
3466- )
3467- self._dynamic_config._required_use_unsatisfied = True
3468- self._dynamic_config._skip_restart = True
3469- # Add pkg to digraph in order to enable autounmask messages
3470- # for this package, which is useful when autounmask USE
3471- # changes have violated REQUIRED_USE.
3472- self._dynamic_config.digraph.add(pkg, dep.parent, priority=priority)
3473- return 0
3474-
34753430 if not pkg.onlydeps:
34763431 existing_node, existing_node_matches = self._check_slot_conflict(
34773432 pkg, dep.atom
@@ -3630,6 +3585,43 @@ def _add_pkg(self, pkg, dep):
36303585 and (dep.atom.soname or dep.atom.slot_operator == "=")
36313586 ):
36323587 self._add_slot_operator_dep(dep)
3588+ if self._slot_operator_trigger_backtracking(dep):
3589+ # Drop slot operator deps that trigger backtracking, since
3590+ # they may be irrelevant and therefore we don't want to
3591+ # enforce the REQUIRED_USE check that comes below (bug 964705).
3592+ # Since backtracking has been triggered, the _need_restart flag
3593+ # is set and this depgraph is only useful for collecting
3594+ # backtracking parameters at this point, so it is acceptable to
3595+ # drop dependencies as needed. It would not be acceptable to
3596+ # abort depgraph creation here, since that would not scale well
3597+ # for large numbers of slot operator rebuilds.
3598+ return 1
3599+
3600+ # NOTE: REQUIRED_USE checks are delayed until after
3601+ # package selection, since we want to prompt the user
3602+ # for USE adjustment rather than have REQUIRED_USE
3603+ # affect package selection and || dep choices.
3604+ if (
3605+ not pkg.built
3606+ and pkg._metadata.get("REQUIRED_USE")
3607+ and eapi_has_required_use(pkg.eapi)
3608+ ):
3609+ required_use_is_sat = check_required_use(
3610+ pkg._metadata["REQUIRED_USE"],
3611+ self._pkg_use_enabled(pkg),
3612+ pkg.iuse.is_valid_flag,
3613+ eapi=pkg.eapi,
3614+ )
3615+ if not required_use_is_sat:
3616+ atom = dep.atom
3617+ if atom is None:
3618+ atom = Atom("=" + pkg.cpv)
3619+ self._dynamic_config._unsatisfied_deps_for_display.append(
3620+ ((pkg.root, atom), {"myparent": dep.parent, "show_req_use": pkg})
3621+ )
3622+ self._dynamic_config._required_use_unsatisfied = True
3623+ self._dynamic_config._skip_restart = True
3624+ return 0
36333625
36343626 recurse = deep is True or not self._too_deep(self._depth_increment(depth, n=1))
36353627 dep_stack = self._dynamic_config._dep_stack
0 commit comments