On Fri, 17 Mar 2017 01:18:19 -0700 Zac Medico <zmed...@gentoo.org> wrote:
> Fix check_reverse_dependencies to ignore direct circular dependencies, > since these dependencies tend to prevent updates of packages. This > solves a missed update from llvm:0 to llvm:4 when clang is not in the > world file, as demonstrated by the included test case. > > X-Gentoo-bug: 612874 > X-Gentoo-bug-url: https://bugs.gentoo.org/show_bug.cgi?id=612874 > --- > pym/_emerge/depgraph.py | 31 > ++++++++++++----- .../resolver/test_slot_operator_exclusive_slots.py > | 39 ++++++++++++++++++++++ > pym/portage/util/digraph.py | 6 ++++ 3 files > changed, 68 insertions(+), 8 deletions(-) > > diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py > index f4145d0..e94b96c 100644 > --- a/pym/_emerge/depgraph.py > +++ b/pym/_emerge/depgraph.py > @@ -1844,14 +1844,29 @@ class depgraph(object): > if (not > self._too_deep(parent.depth) and not > self._frozen_config.excluded_pkgs. findAtomForPackage(parent, > - > modified_use=self._pkg_use_enabled(parent)) and > - > (self._upgrade_available(parent) or > - (parent.installed > and self._in_blocker_conflict(parent)))): > - # This parent may be > irrelevant, since an > - # update is > available (see bug 584626), or > - # it could be > uninstalled in order to solve > - # a blocker conflict > (bug 612772). > - continue > + > modified_use=self._pkg_use_enabled(parent))): > + # Check for common > reasons that the parent's > + # dependency might > be irrelevant. > + if > self._upgrade_available(parent): > + # This > parent could be replaced by > + # an upgrade > (bug 584626). > + continue > + if parent.installed > and self._in_blocker_conflict(parent): > + # This > parent could be uninstalled in order > + # to solve a > blocker conflict (bug 612772). > + continue > + if > self._dynamic_config.digraph.has_edge(parent, > + > existing_pkg): > + # There is a > direct circular dependency between > + # parent and > existing_pkg. This type of > + # > relationship tends to prevent updates > + # of > packages (bug 612874). Since candidate_pkg > + # is > available, we risk a missed update if we > + # don't try > to eliminate this parent from the > + # graph. > Therefore, we give candidate_pkg a > + # chance, > and assume that it will be masked > + # by > backtracking if necessary. > + continue > > atom_set = > InternalPackageSet(initial_atoms=(atom,), allow_repo=True) > diff --git > a/pym/portage/tests/resolver/test_slot_operator_exclusive_slots.py > b/pym/portage/tests/resolver/test_slot_operator_exclusive_slots.py > index 2ab379c..689ed31 100644 --- > a/pym/portage/tests/resolver/test_slot_operator_exclusive_slots.py > +++ > b/pym/portage/tests/resolver/test_slot_operator_exclusive_slots.py @@ > -107,3 +107,42 @@ class SlotOperatorExclusiveSlotsTestCase(TestCase): > test_case.fail_msg) finally: playground.cleanup() + > + > + world = ["media-libs/mesa"] > + > + test_cases = ( > + > + # Test bug #612874, where a direct circular > dependency > + # between llvm-3.9.1 and clang-3.9.1-r100 > causes a > + # missed update from llvm:0 to llvm:4. Since > llvm:4 does > + # not have a dependency on clang, the > upgrade from llvm:0 > + # to llvm:4 makes the installed > sys-devel/clang-3.9.1-r100 > + # instance eligible for removal by emerge > --depclean, which > + # explains why clang does not appear in the > mergelist. > + ResolverPlaygroundTestCase( > + ["@world"], > + options = {"--update": True, > "--deep": True}, > + success = True, > + ambiguous_merge_order = True, > + mergelist = [ > + 'sys-devel/llvm-4.0.0', > + ( > + 'media-libs/mesa-17.0.1', > + > '[uninstall]sys-devel/llvm-3.9.1', > + '!sys-devel/llvm:0', > + ) > + ], > + ), > + > + ) > + > + playground = ResolverPlayground(ebuilds=ebuilds, > + installed=installed, world=world) > + try: > + for test_case in test_cases: > + playground.run_TestCase(test_case) > + > self.assertEqual(test_case.test_success, True, > + test_case.fail_msg) > + finally: > + playground.cleanup() > diff --git a/pym/portage/util/digraph.py b/pym/portage/util/digraph.py > index 4a9cb43..b6be0c9 100644 > --- a/pym/portage/util/digraph.py > +++ b/pym/portage/util/digraph.py > @@ -93,6 +93,12 @@ class digraph(object): > del self.nodes[node] > self.order = order > > + def has_edge(self, child, parent): > + """ > + Return True if the given edge exists. > + """ > + return child in self.nodes[parent][0] > + > def remove_edge(self, child, parent): > """ > Remove edge in the direction from child to parent. > Note that it is Looks good -- Brian Dolbec <dolsen>