1 # Copyright 1999-2012 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
8 from portage import digraph
9 from portage._sets.base import InternalPackageSet
11 from _emerge.BlockerCache import BlockerCache
12 from _emerge.Package import Package
13 from _emerge.show_invalid_depstring_notice import show_invalid_depstring_notice
15 if sys.hexversion >= 0x3000000:
18 class BlockerDB(object):
20 def __init__(self, fake_vartree):
21 root_config = fake_vartree._root_config
22 self._root_config = root_config
23 self._vartree = root_config.trees["vartree"]
24 self._portdb = root_config.trees["porttree"].dbapi
26 self._dep_check_trees = None
27 self._fake_vartree = fake_vartree
28 self._dep_check_trees = {
29 self._vartree.settings["EROOT"] : {
30 "porttree" : fake_vartree,
31 "vartree" : fake_vartree,
34 def findInstalledBlockers(self, new_pkg):
36 Search for installed run-time blockers in the root where
37 new_pkg is planned to be installed. This ignores build-time
38 blockers, since new_pkg is assumed to be built already.
40 blocker_cache = BlockerCache(None,
42 dep_keys = Package._runtime_keys
43 settings = self._vartree.settings
44 stale_cache = set(blocker_cache)
45 fake_vartree = self._fake_vartree
46 dep_check_trees = self._dep_check_trees
47 vardb = fake_vartree.dbapi
48 installed_pkgs = list(vardb)
50 for inst_pkg in installed_pkgs:
51 stale_cache.discard(inst_pkg.cpv)
52 cached_blockers = blocker_cache.get(inst_pkg.cpv)
53 if cached_blockers is not None and \
54 cached_blockers.counter != inst_pkg.counter:
55 cached_blockers = None
56 if cached_blockers is not None:
57 blocker_atoms = cached_blockers.atoms
59 # Use aux_get() to trigger FakeVartree global
60 # updates on *DEPEND when appropriate.
61 depstr = " ".join(vardb.aux_get(inst_pkg.cpv, dep_keys))
62 success, atoms = portage.dep_check(depstr,
63 vardb, settings, myuse=inst_pkg.use.enabled,
64 trees=dep_check_trees, myroot=inst_pkg.root)
66 pkg_location = os.path.join(inst_pkg.root,
67 portage.VDB_PATH, inst_pkg.category, inst_pkg.pf)
68 portage.writemsg("!!! %s/*DEPEND: %s\n" % \
69 (pkg_location, atoms), noiselevel=-1)
72 blocker_atoms = [atom for atom in atoms \
73 if atom.startswith("!")]
75 blocker_cache[inst_pkg.cpv] = \
76 blocker_cache.BlockerData(inst_pkg.counter, blocker_atoms)
77 for cpv in stale_cache:
78 del blocker_cache[cpv]
81 blocker_parents = digraph()
83 for pkg in installed_pkgs:
84 for blocker_atom in blocker_cache[pkg.cpv].atoms:
85 blocker_atom = blocker_atom.lstrip("!")
86 blocker_atoms.append(blocker_atom)
87 blocker_parents.add(blocker_atom, pkg)
89 blocker_atoms = InternalPackageSet(initial_atoms=blocker_atoms)
91 for atom in blocker_atoms.iterAtomsForPackage(new_pkg):
92 blocking_pkgs.update(blocker_parents.parent_nodes(atom))
94 # Check for blockers in the other direction.
95 depstr = " ".join(new_pkg._metadata[k] for k in dep_keys)
96 success, atoms = portage.dep_check(depstr,
97 vardb, settings, myuse=new_pkg.use.enabled,
98 trees=dep_check_trees, myroot=new_pkg.root)
100 # We should never get this far with invalid deps.
101 show_invalid_depstring_notice(new_pkg, depstr, atoms)
104 blocker_atoms = [atom.lstrip("!") for atom in atoms \
107 blocker_atoms = InternalPackageSet(initial_atoms=blocker_atoms)
108 for inst_pkg in installed_pkgs:
110 next(blocker_atoms.iterAtomsForPackage(inst_pkg))
111 except (portage.exception.InvalidDependString, StopIteration):
113 blocking_pkgs.add(inst_pkg)
117 def discardBlocker(self, pkg):
118 """Discard a package from the list of potential blockers.
119 This will match any package(s) with identical cpv or cp:slot."""
120 for cpv_match in self._fake_vartree.dbapi.match_pkgs("=%s" % (pkg.cpv,)):
121 if cpv_match.cp == pkg.cp:
122 self._fake_vartree.cpv_discard(cpv_match)
123 for slot_match in self._fake_vartree.dbapi.match_pkgs(pkg.slot_atom):
124 if slot_match.cp == pkg.cp:
125 self._fake_vartree.cpv_discard(slot_match)