commit: a5078e5774932103d4ad367de4c6bf130a6da34f Author: Zac Medico <zmedico <AT> gentoo <DOT> org> AuthorDate: Mon Jan 15 23:10:03 2024 +0000 Commit: Zac Medico <zmedico <AT> gentoo <DOT> org> CommitDate: Tue Jan 16 16:01:53 2024 +0000 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=a5078e57
emerge: backtrack consistently regardless of --fetchonly Make the _accept_blocker_conflicts method always return True when backtracking is enabled, so that backtracking results will be identical regardless of options that _accept_blocker_conflicts treats specially. This way, conflicts will only be accepted when backtracking is disabled or all backtracking tries have been exhausted. Make --nodeps imply --backtrack=0, since backtracking is only useful with dependencies. Make _eliminate_rebuilds return early if there are slot conflicts, since the merge list is invalid anyway, and its possible that state inconsistencies could trigger unexpected exceptions as in bug 922038. Make the KeyError from bug 922038 a warning, and include relevant information to help trace the inconsistency back to the _eliminate_rebuilds method or some other source like _solve_non_slot_operator_slot_conflicts. Bug: https://bugs.gentoo.org/161422 Bug: https://bugs.gentoo.org/607252 Bug: https://bugs.gentoo.org/675748 Bug: https://bugs.gentoo.org/922038 Signed-off-by: Zac Medico <zmedico <AT> gentoo.org> lib/_emerge/depgraph.py | 63 +++++++++++++++++++++++++++++++++++++++++++++---- man/emerge.1 | 5 ++-- 2 files changed, 61 insertions(+), 7 deletions(-) diff --git a/lib/_emerge/depgraph.py b/lib/_emerge/depgraph.py index b859e68224..7491d970c3 100644 --- a/lib/_emerge/depgraph.py +++ b/lib/_emerge/depgraph.py @@ -1,4 +1,4 @@ -# Copyright 1999-2023 Gentoo Authors +# Copyright 1999-2024 Gentoo Authors # Distributed under the terms of the GNU General Public License v2 import errno @@ -3674,9 +3674,19 @@ class depgraph: careful to obey the user's wishes if they have explicitly requested for a package to be rebuilt or reinstalled for some reason. """ - if "empty" in self._dynamic_config.myparams: + # Skip for slot conflicts since the merge list is not valid + # anyway, and possible state inconsistencies can trigger + # unexpected exceptions as in bug 922038. + if "empty" in self._dynamic_config.myparams or any( + self._dynamic_config._package_tracker.slot_conflicts() + ): return False + # Track packages that we remove from the graph during + # this method call, in order to help trace any detected + # inconsistency back to this method or some other source + # such as _solve_non_slot_operator_slot_conflicts. + removed = [] modified = False selective = "selective" in self._dynamic_config.myparams for root, atom in self._dynamic_config._slot_operator_replace_installed: @@ -3777,11 +3787,45 @@ class depgraph: modified = True parent_atoms = [] for parent, parent_atom in self._dynamic_config._parent_atoms[pkg]: - priorities = self._dynamic_config.digraph.nodes[pkg][1][parent][:] + try: + priorities = self._dynamic_config.digraph.nodes[pkg][1][parent][ + : + ] + except KeyError: + optional_msg = " ({} previously removed from graph)" + warnings.warn( + f"_eliminate_rebuilds inconsistency: parent priorities missing for {parent} -> {pkg} edge"( + optional_msg.format("parent and child") + if parent in removed and pkg in removed + else optional_msg.format("parent") + if parent in removed + else optional_msg.format("child") + if pkg in removed + else "" + ) + ) + priorities = [] parent_atoms.append((parent, parent_atom, priorities)) child_parents = {} for child in self._dynamic_config.digraph.child_nodes(pkg): - priorities = self._dynamic_config.digraph.nodes[child][1][pkg][:] + try: + priorities = self._dynamic_config.digraph.nodes[child][1][pkg][ + : + ] + except KeyError: + optional_msg = " ({} previously removed from graph)" + warnings.warn( + f"_eliminate_rebuilds inconsistency: parent priorities missing for {pkg} -> {child} edge"( + optional_msg.format("parent and child") + if pkg in removed and child in removed + else optional_msg.format("parent") + if pkg in removed + else optional_msg.format("child") + if child in removed + else "" + ) + ) + priorities = [] child_parents[child] = ( [ atom @@ -3793,6 +3837,7 @@ class depgraph: priorities, ) self._remove_pkg(pkg, remove_orphans=False) + removed.append(pkg) for parent, atom, priorities in parent_atoms: self._add_parent_atom(installed_instance, (parent, atom)) for priority in priorities: @@ -8881,6 +8926,13 @@ class depgraph: return True def _accept_blocker_conflicts(self): + """ + Always returns False when backtracking is enabled, for + consistent results. When backtracking is disabled, returns + True for options that tolerate conflicts. + """ + if self._dynamic_config._allow_backtracking: + return False acceptable = False for x in ("--buildpkgonly", "--fetchonly", "--fetch-all-uri", "--nodeps"): if x in self._frozen_config.myopts: @@ -11752,7 +11804,8 @@ def _backtrack_depgraph( ) -> tuple[Any, depgraph, list[str], int, int]: debug = "--debug" in myopts mydepgraph = None - max_retries = myopts.get("--backtrack", 20) + nodeps = "--nodeps" in myopts + max_retries = 0 if nodeps else myopts.get("--backtrack", 20) max_depth = max(1, (max_retries + 1) // 2) allow_backtracking = max_retries > 0 backtracker = Backtracker(max_depth) diff --git a/man/emerge.1 b/man/emerge.1 index e18bc9e257..43dc3f26b1 100644 --- a/man/emerge.1 +++ b/man/emerge.1 @@ -1,4 +1,4 @@ -.TH "EMERGE" "1" "Mar 2023" "Portage @VERSION@" "Portage" +.TH "EMERGE" "1" "Jan 2024" "Portage @VERSION@" "Portage" .SH "NAME" emerge \- Command\-line interface to the Portage system .SH "SYNOPSIS" @@ -747,7 +747,8 @@ file to always be merged. .TP .BR \-\-nodeps ", " \-O Merges specified packages without merging any dependencies. Note that -the build may fail if the dependencies aren't satisfied. +the build may fail if the dependencies aren't satisfied. This option +implies \fB--backtrack=0\fR. .TP .BR \-\-noreplace ", " \-n Skips the packages specified on the command\-line that have already
