From: Zac Medico Date: Sat, 9 Dec 2006 23:10:47 +0000 (-0000) Subject: This patch cleans up the blocker validation logic. Unlike the previous implementatio... X-Git-Tag: v2.1.2~339 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=365e2909116d8fcf3db16e3c04cbb07c7a22944e;p=portage.git This patch cleans up the blocker validation logic. Unlike the previous implementation, this one carefully considers each parent/block package relationship in order to ensure that no unresolved blocks slip through. svn path=/main/trunk/; revision=5245 --- diff --git a/bin/emerge b/bin/emerge index 77de52d25..9970ad0e8 100755 --- a/bin/emerge +++ b/bin/emerge @@ -1439,72 +1439,72 @@ class depgraph: for blocker in self.blocker_parents.keys(): mytype, myroot, mydep = blocker - vardb = self.trees[myroot]["vartree"].dbapi - blocked_pkgs = vardb.match(mydep) - blocked_after_update = self.mydbapi[myroot].match(mydep) - if not blocked_pkgs and not blocked_after_update: + initial_db = self.trees[myroot]["vartree"].dbapi + final_db = self.mydbapi[myroot] + blocked_initial = initial_db.match(mydep) + blocked_final = final_db.match(mydep) + if not blocked_initial and not blocked_final: del self.blocker_parents[blocker] - else: - """It may be possible to circumvent this block via correct - ordering of upgrades. If necessary, create hard deps to - enforce correct merge order.""" - fakedb = self.mydbapi[myroot] - new_pkgs = [] - unresolvable = False - for cpv in blocked_pkgs: - myslot = vardb.aux_get(cpv, ["SLOT"])[0] - myslot_atom = "%s:%s" % (portage.dep_getkey(cpv), myslot) - mymatches = fakedb.match(myslot_atom) - if mymatches: - new_pkgs.append((myslot_atom, mymatches[0])) - else: - """There's an installed package that's blocked and - there's no upgrade found to invalidate it, so leave - this blocker in the digraph.""" - unresolvable = True - break - if unresolvable: - # Keep trying to invalidate as many blockers as possible. - continue - - for parent in list(self.blocker_parents[blocker]): - ptype, proot, pcpv, pstatus = parent - pdbapi = self.trees[proot][self.pkg_tree_map[ptype]].dbapi - pslot = pdbapi.aux_get(pcpv, ["SLOT"])[0] - pslot_atom = "%s:%s" % (portage.dep_getkey(pcpv), pslot) - depends_on_merge_order = False - for myslot_atom, pkg in new_pkgs: - if pslot_atom == myslot_atom: - """A merge within a slot invalidates the block, - so the order does not need to be enforced.""" + continue + blocked_slots_initial = {} + blocked_slots_final = {} + for cpv in blocked_initial: + blocked_slots_initial[cpv] = \ + "%s:%s" % (portage.dep_getkey(cpv), + initial_db.aux_get(cpv, ["SLOT"])[0]) + for cpv in blocked_final: + blocked_slots_final[cpv] = \ + "%s:%s" % (portage.dep_getkey(cpv), + final_db.aux_get(cpv, ["SLOT"])[0]) + for parent in list(self.blocker_parents[blocker]): + ptype, proot, pcpv, pstatus = parent + pdbapi = self.trees[proot][self.pkg_tree_map[ptype]].dbapi + pslot = pdbapi.aux_get(pcpv, ["SLOT"])[0] + pslot_atom = "%s:%s" % (portage.dep_getkey(pcpv), pslot) + unresolved_blocks = False + depends_on_order = set() + for cpv in blocked_initial: + slot_atom = blocked_slots_initial[cpv] + if slot_atom == pslot_atom: + # The parent blocks an initial package in the same + # slot as itself. The merge/nomerge status of neither + # node matters. In any case, this particular block is + # automatically resolved. + continue + if slot_atom not in blocked_slots_final.values(): + upgrade_matches = final_db.match(slot_atom) + if upgrade_matches: + # Apparently an upgrade may be able to invalidate + # this block. + upgrade_node = \ + self.pkg_node_map[proot][upgrade_matches[0]] + depends_on_order.add(upgrade_node) continue - if pkg in blocked_after_update: - """This isn't a case of a package blocking itself, - and the block is still valid in the final state, so - this one is unresolvable.""" - unresolvable = True - break + # None of the above blocker resolutions techniques apply, + # so apparently this one is unresolvable. + unresolved_blocks = True + for cpv in blocked_final: + slot_atom = blocked_slots_final[cpv] + if slot_atom == pslot_atom: + # The parent blocks itself, so the merge order does not + # need to be enforced. + continue + # None of the above blocker resolutions techniques apply, + # so apparently this one is unresolvable. + unresolved_blocks = True + if not unresolved_blocks and depends_on_order: + for node in depends_on_order: # Enforce correct merge order with a hard dep. - node = self.pkg_node_map[proot][pkg] self.digraph.addnode(node, parent, priority=DepPriority(buildtime=True)) - """Count references to this blocker so that it can be - invalidated after nodes referencing it have been merged.""" + # Count references to this blocker so that it can be + # invalidated after nodes referencing it have been + # merged. self.blocker_digraph.addnode(node, blocker) - depends_on_merge_order = True - if unresolvable: - break - elif not depends_on_merge_order: - self.blocker_parents[blocker].remove(parent) - if unresolvable: - """This blocker can not be solved, so make sure that it is - removed from the digraph if it has already been added.""" - if self.blocker_digraph.contains(blocker): - self.blocker_digraph.remove(blocker) - # Keep trying to invalidate as many blockers as possible. - continue - if not self.blocker_parents[blocker]: - del self.blocker_parents[blocker] + if not unresolved_blocks and not depends_on_order: + self.blocker_parents[blocker].remove(parent) + if not self.blocker_parents[blocker]: + del self.blocker_parents[blocker] # Validate blockers that depend on merge order. if not self.blocker_digraph.empty(): self.altlist()