summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2008-09-19 03:28:20 +0000
committerZac Medico <zmedico@gentoo.org>2008-09-19 03:28:20 +0000
commit7d2ca5743f0bb550e198d3a097937e2e4c3f4883 (patch)
tree54c0e25167335d585533d7d68005ef7ddb73f557
parent1a2e26ac7cfeccca2c26e9d1dd1ee32f94c3021c (diff)
downloadportage-7d2ca5743f0bb550e198d3a097937e2e4c3f4883.tar.gz
portage-7d2ca5743f0bb550e198d3a097937e2e4c3f4883.tar.bz2
portage-7d2ca5743f0bb550e198d3a097937e2e4c3f4883.zip
Implement the new EAPI 2 blocker behavior, including !!atom sytax which
forbids temporary simultaneous installation of conflicting packages. svn path=/main/trunk/; revision=11517
-rwxr-xr-xbin/repoman9
-rw-r--r--pym/_emerge/__init__.py44
-rw-r--r--pym/portage/dep.py38
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)