diff options
-rw-r--r-- | pym/_emerge/depgraph.py | 69 | ||||
-rw-r--r-- | pym/portage/tests/resolver/test_virtual_slot.py | 47 |
2 files changed, 105 insertions, 11 deletions
diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py index 6a04a7971..1e311e8f7 100644 --- a/pym/_emerge/depgraph.py +++ b/pym/_emerge/depgraph.py @@ -2500,24 +2500,36 @@ class depgraph(object): # account for masking and USE settings. _autounmask_backup = self._dynamic_config._autounmask self._dynamic_config._autounmask = False - mytrees["pkg_use_enabled"] = self._pkg_use_enabled + # backup state for restoration, in case of recursive + # calls to this method + backup_state = mytrees.copy() try: + # clear state from previous call, in case this + # call is recursive (we have a backup, that we + # will use to restore it later) + mytrees.pop("pkg_use_enabled", None) + mytrees.pop("parent", None) + mytrees.pop("atom_graph", None) + mytrees.pop("priority", None) + + mytrees["pkg_use_enabled"] = self._pkg_use_enabled if parent is not None: - trees[root]["parent"] = parent - trees[root]["atom_graph"] = atom_graph + mytrees["parent"] = parent + mytrees["atom_graph"] = atom_graph if priority is not None: - trees[root]["priority"] = priority + mytrees["priority"] = priority + mycheck = portage.dep_check(depstring, None, pkgsettings, myuse=myuse, myroot=root, trees=trees) finally: + # restore state self._dynamic_config._autounmask = _autounmask_backup - del mytrees["pkg_use_enabled"] - if parent is not None: - trees[root].pop("parent") - trees[root].pop("atom_graph") - if priority is not None: - trees[root].pop("priority") + mytrees.pop("pkg_use_enabled", None) + mytrees.pop("parent", None) + mytrees.pop("atom_graph", None) + mytrees.pop("priority", None) + mytrees.update(backup_state) if not mycheck[0]: raise portage.exception.InvalidDependString(mycheck[1]) if parent is None: @@ -2611,6 +2623,38 @@ class depgraph(object): continue yield atom + def _virt_deps_visible(self, pkg, ignore_use=False): + """ + Assumes pkg is a virtual package. Traverses virtual deps recursively + and returns True if all deps are visible, False otherwise. This is + useful for checking if it will be necessary to expand virtual slots, + for cases like bug #382557. + """ + try: + rdepend = self._select_atoms( + pkg.root, pkg.metadata.get("RDEPEND", ""), + myuse=self._pkg_use_enabled(pkg), + parent=pkg, priority=self._priority(runtime=True)) + except InvalidDependString as e: + if not pkg.installed: + raise + writemsg_level("!!! Invalid RDEPEND in " + \ + "'%svar/db/pkg/%s/RDEPEND': %s\n" % \ + (pkg.root, pkg.cpv, e), + noiselevel=-1, level=logging.ERROR) + return False + + for atoms in rdepend.values(): + for atom in atoms: + if ignore_use: + atom = atom.without_use + pkg, existing = self._select_package( + pkg.root, atom) + if pkg is None or not self._pkg_visibility_check(pkg): + return False + + return True + def _get_dep_chain(self, start_node, target_atom=None, unsatisfied_dependency=False): """ @@ -6540,7 +6584,10 @@ class _dep_check_composite_db(dbapi): if pkg is not None and \ atom.slot is None and \ - pkg.cp.startswith("virtual/"): + pkg.cp.startswith("virtual/") and \ + ("--update" not in self._depgraph._frozen_config.myopts or + not ret or + not self._depgraph._virt_deps_visible(pkg, ignore_use=True)): # For new-style virtual lookahead that occurs inside dep_check() # for bug #141118, examine all slots. This is needed so that newer # slots will not unnecessarily be pulled in when a satisfying lower diff --git a/pym/portage/tests/resolver/test_virtual_slot.py b/pym/portage/tests/resolver/test_virtual_slot.py index 40ed73b11..fb242011d 100644 --- a/pym/portage/tests/resolver/test_virtual_slot.py +++ b/pym/portage/tests/resolver/test_virtual_slot.py @@ -44,3 +44,50 @@ class VirtualSlotResolverTestCase(TestCase): self.assertEqual(test_case.test_success, True, test_case.fail_msg) finally: playground.cleanup() + + def testVirtualSlotUpdate(self): + + ebuilds = { + "dev-java/oracle-jdk-bin-1.7.0" : {"SLOT": "1.7", "LICENSE": "TEST"}, + "dev-java/sun-jdk-1.6.0" : {"SLOT": "1.6", "LICENSE": "TEST"}, + "dev-java/icedtea-6.1.10.3" : {"SLOT": "6"}, + "dev-java/icedtea-7" : {"SLOT": "7"}, + "app-misc/java-app-1": {"RDEPEND": ">=virtual/jdk-1.6.0"}, + "virtual/jdk-1.6.0": {"SLOT": "1.6", "RDEPEND": "|| ( =dev-java/icedtea-6* =dev-java/sun-jdk-1.6.0* )"}, + "virtual/jdk-1.7.0": {"SLOT": "1.7", "RDEPEND": "|| ( =dev-java/icedtea-7* =dev-java/oracle-jdk-bin-1.7.0* )"}, + } + + installed = { + "app-misc/java-app-1": {"RDEPEND": ">=virtual/jdk-1.6.0"}, + "dev-java/icedtea-6.1.10.3" : {"SLOT": "6"}, + "virtual/jdk-1.6.0": {"SLOT" : "1.6", "RDEPEND": "|| ( =dev-java/icedtea-6* =dev-java/sun-jdk-1.6.0* )"}, + } + + world = ("app-misc/java-app",) + + test_cases = ( + # Pull in the virtual/jdk-1.7.0 slot update since its dependencies + # can only be satisfied by an unmasked package. + ResolverPlaygroundTestCase( + ["@world"], + options = {"--update" : True, "--deep" : True}, + success = True, + mergelist = ["dev-java/icedtea-7", "virtual/jdk-1.7.0"]), + + # Bug #275945 - Don't pull in the virtual/jdk-1.7.0 slot update + # unless --update is enabled. + ResolverPlaygroundTestCase( + ["@world"], + options = {"--selective" : True, "--deep" : True}, + success = True, + mergelist = []), + ) + + 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() |