From 7d2ca5743f0bb550e198d3a097937e2e4c3f4883 Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Fri, 19 Sep 2008 03:28:20 +0000 Subject: [PATCH] Implement the new EAPI 2 blocker behavior, including !!atom sytax which forbids temporary simultaneous installation of conflicting packages. svn path=/main/trunk/; revision=11517 --- bin/repoman | 9 +++++++-- pym/_emerge/__init__.py | 44 +++++++++++++++++++++++++++-------------- pym/portage/dep.py | 38 +++++++++++++++++++++++++++++------ 3 files changed, 68 insertions(+), 23 deletions(-) diff --git a/bin/repoman b/bin/repoman index 932cf4c99..7e997d3d1 100755 --- a/bin/repoman +++ b/bin/repoman @@ -1256,8 +1256,6 @@ for x in scanlist: badsyntax.append("'%s' not a valid atom" % token) else: is_blocker = atom.blocker - if atom.blocker: - atom = portage.dep.Atom(atom[1:]) if mytype == "DEPEND" and \ not is_blocker and \ @@ -1284,6 +1282,13 @@ for x in scanlist: (relative_path + ": %s use dependency" + \ " not supported with EAPI='%s':" + \ " '%s'") % (mytype, eapi, atom)) + if atom.blocker and atom.blocker.overlap.forbid \ + and eapi in ("0", "1"): + stats['EAPI.incompatible'] += 1 + fails['EAPI.incompatible'].append( + (relative_path + ": %s new blocker syntax" + \ + " not supported with EAPI='%s':" + \ + " '%s'") % (mytype, eapi, atom)) type_list.extend([mytype] * (len(badsyntax) - len(type_list))) diff --git a/pym/_emerge/__init__.py b/pym/_emerge/__init__.py index 8f951cb92..5c5aaa731 100644 --- a/pym/_emerge/__init__.py +++ b/pym/_emerge/__init__.py @@ -1386,7 +1386,7 @@ class Task(SlotObject): class Blocker(Task): __hash__ = Task.__hash__ - __slots__ = ("root", "atom", "cp", "satisfied") + __slots__ = ("root", "atom", "cp", "eapi", "satisfied") def __init__(self, **kwargs): Task.__init__(self, **kwargs) @@ -1396,7 +1396,7 @@ class Blocker(Task): hash_key = getattr(self, "_hash_key", None) if hash_key is None: self._hash_key = \ - ("blocks", self.root, self.atom) + ("blocks", self.root, self.atom, self.eapi) return self._hash_key class Package(Task): @@ -4384,7 +4384,9 @@ class depgraph(object): return 1 # The blocker applies to the root where # the parent is or will be installed. - blocker = Blocker(atom=dep.atom, root=dep.parent.root) + blocker = Blocker(atom=dep.atom, + eapi=dep.parent.metadata["EAPI"], + root=dep.parent.root) self._blocker_parents.add(blocker, dep.parent) return 1 dep_pkg, existing_node = self._select_package(dep.root, dep.atom, @@ -4642,15 +4644,14 @@ class depgraph(object): for atom in selected_atoms: try: - blocker = atom.startswith("!") - if blocker: - atom = atom[1:] + atom = portage.dep.Atom(atom) + mypriority = dep_priority.copy() - if not blocker and vardb.match(atom): + if not atom.blocker and vardb.match(atom): mypriority.satisfied = True if not self._add_dep(Dependency(atom=atom, - blocker=blocker, depth=depth, parent=pkg, + blocker=atom.blocker, depth=depth, parent=pkg, priority=mypriority, root=dep_root), allow_unsatisfied=allow_unsatisfied): return 0 @@ -5802,7 +5803,7 @@ class depgraph(object): except KeyError: pass if blockers is not None: - blockers = set("!" + blocker.atom \ + blockers = set(str(blocker.atom) \ for blocker in blockers) # If this node has any blockers, create a "nomerge" @@ -5880,7 +5881,8 @@ class depgraph(object): blocker_cache.BlockerData(counter, blocker_atoms) if blocker_atoms: for myatom in blocker_atoms: - blocker = Blocker(atom=myatom[1:], root=myroot) + blocker = Blocker(atom=portage.dep.Atom(myatom), + eapi=pkg.metadata["EAPI"], root=myroot) self._blocker_parents.add(blocker, pkg) for cpv in stale_cache: del blocker_cache[cpv] @@ -5899,7 +5901,7 @@ class depgraph(object): self.spinner.update() root_config = self.roots[blocker.root] virtuals = root_config.settings.getvirtuals() - mytype, myroot, mydep = blocker + myroot = blocker.root initial_db = self.trees[myroot]["vartree"].dbapi final_db = self.mydbapi[myroot] @@ -6370,7 +6372,18 @@ class depgraph(object): if self.digraph.contains(inst_pkg): continue - if running_root == task.root: + forbid_overlap = False + heuristic_overlap = False + for blocker in myblocker_uninstalls.parent_nodes(task): + if blocker.eapi in ("0", "1"): + heuristic_overlap = True + elif blocker.atom.blocker.overlap.forbid: + forbid_overlap = True + break + if forbid_overlap and running_root == task.root: + continue + + if heuristic_overlap and running_root == task.root: # Never uninstall sys-apps/portage or it's essential # dependencies, except through replacement. try: @@ -6570,7 +6583,8 @@ class depgraph(object): # will be temporarily installed simultaneously. for blocker in solved_blockers: retlist.append(Blocker(atom=blocker.atom, - root=blocker.root, satisfied=True)) + root=blocker.root, eapi=blocker.eapi, + satisfied=True)) unsolvable_blockers = set(self._unsolvable_blockers.leaf_nodes()) for node in myblocker_uninstalls.root_nodes(): @@ -6939,7 +6953,7 @@ class depgraph(object): if x.satisfied: counters.blocks_satisfied += 1 resolved = portage.key_expand( - pkg_key, mydb=vardb, settings=pkgsettings) + str(x.atom).lstrip("!"), mydb=vardb, settings=pkgsettings) if "--columns" in self.myopts and "--quiet" in self.myopts: addl += " " + colorize(blocker_style, resolved) else: @@ -6952,7 +6966,7 @@ class depgraph(object): if resolved!=x[2]: addl += colorize(blocker_style, " (\"%s\" is blocking %s)") % \ - (pkg_key, block_parents) + (str(x.atom).lstrip("!"), block_parents) else: addl += colorize(blocker_style, " (is blocking %s)") % block_parents diff --git a/pym/portage/dep.py b/pym/portage/dep.py index adbde5f6d..b36a6bf5a 100644 --- a/pym/portage/dep.py +++ b/pym/portage/dep.py @@ -489,14 +489,34 @@ class Atom(object): __slots__ = ("__weakref__", "blocker", "cp", "cpv", "operator", "slot", "use") + _str_methods + class _blocker(object): + __slots__ = ("overlap",) + + class _overlap(object): + __slots__ = ("forbid",) + + def __init__(self, forbid=False): + self.forbid = forbid + + def __init__(self, forbid_overlap=False): + self.overlap = self._overlap(forbid=forbid_overlap) + def __init__(self, s): if not isvalidatom(s, allow_blockers=True): raise InvalidAtom(s) for x in self._str_methods: setattr(self, x, getattr(s, x)) - self.blocker = "!" == s[:1] - if self.blocker: - s = s[1:] + + blocker = "!" == s[:1] + if blocker: + self.blocker = self._blocker(forbid_overlap=("!" == s[1:2])) + if self.blocker.overlap.forbid: + s = s[2:] + else: + s = s[1:] + else: + self.blocker = False + self.cp = dep_getkey(s) self.cpv = dep_getcpv(s) self.slot = dep_getslot(s) @@ -586,7 +606,10 @@ def dep_getcpv(mydep): if mydep and mydep[-1] == "*": mydep = mydep[:-1] if mydep and mydep[0] == "!": - mydep = mydep[1:] + if mydep[1:2] == "!": + mydep = mydep[2:] + else: + mydep = mydep[1:] if mydep[:2] in [">=", "<="]: mydep = mydep[2:] elif mydep[:1] in "=<>~": @@ -720,8 +743,11 @@ def isvalidatom(atom, allow_blockers=False): global _invalid_atom_chars_regexp if _invalid_atom_chars_regexp.search(atom): return 0 - if allow_blockers and atom.startswith("!"): - atom = atom[1:] + if allow_blockers and atom[:1] == "!": + if atom[1:2] == "!": + atom = atom[2:] + else: + atom = atom[1:] try: use = dep_getusedeps(atom) -- 2.26.2