in world since system atoms can only match one slot while world atoms can
be greedy with respect to slots. Unslotted system packages will not be
stored in world."""
- arg_atom = args_set.findAtomForPackage(pkg_key, metadata)
+ pkg = Package(cpv=pkg_key, metadata=metadata)
+ arg_atom = args_set.findAtomForPackage(pkg)
if not arg_atom:
return None
cp = portage.dep_getkey(arg_atom)
if len(matched_slots) == 1:
new_world_atom = slot_atom
- if new_world_atom == sets["world"].findAtomForPackage(pkg_key, metadata):
+ if new_world_atom == sets["world"].findAtomForPackage(pkg):
# Both atoms would be identical, so there's nothing to add.
return None
if not slotted:
# Unlike world atoms, system atoms are not greedy for slots, so they
# can't be safely excluded from world if they are slotted.
- system_atom = sets["system"].findAtomForPackage(pkg_key, metadata)
+ system_atom = sets["system"].findAtomForPackage(pkg)
if system_atom:
if not portage.dep_getkey(system_atom).startswith("virtual/"):
return None
def __init__(self, atom=None, **kwargs):
DependencyArg.__init__(self, **kwargs)
self.atom = atom
+ if not isinstance(self.atom, portage.dep.Atom):
+ self.atom = portage.dep.Atom(self.atom)
self.set = (self.atom, )
class PackageArg(DependencyArg):
def __init__(self, package=None, **kwargs):
DependencyArg.__init__(self, **kwargs)
self.package = package
- self.atom = "=" + package.cpv
+ self.atom = portage.dep.Atom("=" + package.cpv)
self.set = (self.atom, )
class SetArg(DependencyArg):
pkg_system = False
pkg_world = False
try:
- pkg_system = system_set.findAtomForPackage(pkg_key, metadata)
- pkg_world = world_set.findAtomForPackage(pkg_key, metadata)
+ pkg_system = system_set.findAtomForPackage(pkg)
+ pkg_world = world_set.findAtomForPackage(pkg)
if not (oneshot or pkg_world) and \
myroot == self.target_root and \
- favorites_set.findAtomForPackage(pkg_key, metadata):
+ favorites_set.findAtomForPackage(pkg):
# Maybe it will be added to world now.
if create_world_atom(pkg_key, metadata,
favorites_set, root_config):
#buildsyspkg: Check if we need to _force_ binary package creation
issyspkg = ("buildsyspkg" in myfeat) \
and x[0] != "blocks" \
- and system_set.findAtomForPackage(pkg_key, metadata) \
+ and system_set.findAtomForPackage(pkg) \
and "--buildpkg" not in self.myopts
if x[0] in ["ebuild","blocks"]:
if x[0] == "blocks" and "--fetchonly" not in self.myopts:
#need to check for errors
if not buildpkgonly:
if not (fetchonly or oneshot or pretend) and \
- args_set.findAtomForPackage(pkg_key, metadata):
+ args_set.findAtomForPackage(pkg):
world_set.lock()
world_set.load() # maybe it's changed on disk
myfavkey = create_world_atom(pkg_key, metadata,
# to remove those.
filtered_pkgs = []
for pkg in pkgs:
- metadata = dict(izip(metadata_keys,
- vardb.aux_get(pkg, metadata_keys)))
arg_atom = None
try:
- arg_atom = args_set.findAtomForPackage(pkg, metadata)
+ arg_atom = args_set.findAtomForPackage(
+ pkg_cache[("installed", myroot, pkg, "nomerge")])
except portage.exception.InvalidDependString, e:
file_path = os.path.join(
myroot, portage.VDB_PATH, pkg, "PROVIDE")
if action == "depclean":
if myfiles:
for pkg in vardb.cpv_all():
- metadata = dict(izip(metadata_keys,
- vardb.aux_get(pkg, metadata_keys)))
arg_atom = None
try:
- arg_atom = args_set.findAtomForPackage(pkg, metadata)
+ arg_atom = args_set.findAtomForPackage(
+ pkg_cache[("installed", myroot, pkg, "nomerge")])
except portage.exception.InvalidDependString:
# this error has already been displayed by now
continue
if kwargs["use_binaries"]:
portdb = trees[myroot]["bintree"].dbapi
myvirtuals = mysettings.getvirtuals()
+ myuse = kwargs["myuse"]
for x in mysplit:
if x == "||":
newsplit.append(x)
newsplit.append(_expand_new_virtuals(x, edebug, mydbapi,
mysettings, myroot=myroot, trees=trees, **kwargs))
continue
- if portage.dep._dep_check_strict and \
- not isvalidatom(x, allow_blockers=True):
- raise portage.exception.ParseError(
- "invalid atom: '%s'" % x)
+
+ if not isinstance(x, portage.dep.Atom):
+ try:
+ x = portage.dep.Atom(x)
+ except portage.exception.InvalidAtom:
+ if portage.dep._dep_check_strict:
+ raise portage.exception.ParseError(
+ "invalid atom: '%s'" % x)
+
+ if isinstance(x, portage.dep.Atom) and x.use:
+ if x.use.conditional:
+ evaluated_atom = portage.dep.remove_slot(x)
+ if x.slot:
+ evaluated_atom += ":%s" % x.slot
+ evaluated_atom += str(x.use.evaluate_conditionals(myuse))
+ x = portage.dep.Atom(evaluated_atom)
+
mykey = dep_getkey(x)
if not mykey.startswith("virtual/"):
newsplit.append(x)
myindex = orig_dep.index(mydep)
prefix = orig_dep[:myindex]
postfix = orig_dep[myindex+len(mydep):]
- return portage.dep.Atom(prefix + cpv_expand(
- mydep, mydb=mydb, use_cache=use_cache, settings=settings) + postfix)
+ expanded = cpv_expand(mydep, mydb=mydb,
+ use_cache=use_cache, settings=settings)
+ try:
+ return portage.dep.Atom(prefix + expanded + postfix)
+ except portage.exception.InvalidAtom:
+ # Missing '=' prefix is allowed for backward compatibility.
+ if not isvalidatom("=" + prefix + expanded + postfix):
+ raise
+ return portage.dep.Atom("=" + prefix + expanded + postfix)
def dep_check(depstring, mydbapi, mysettings, use="yes", mode=None, myuse=None,
use_cache=1, use_binaries=0, myroot="/", trees=None):
mydep = dep_expand(origdep, mydb=self, settings=self.mysettings)
mykey = dep_getkey(mydep)
- myslot = dep_getslot(mydep)
if level == "list-visible":
#a list of all visible packages, not called directly (just by xmatch())
#myval = self.visible(self.cp_list(mykey))
continue
if not eapi_is_supported(metadata["EAPI"]):
continue
- if myslot and myslot != metadata["SLOT"]:
+ if mydep.slot and mydep.slot != metadata["SLOT"]:
continue
if settings.getMissingKeywords(cpv, metadata):
continue
else:
print "ERROR: xmatch doesn't handle", level, "query!"
raise KeyError
- if myslot is not None and isinstance(myval, list):
- slotmatches = []
- for cpv in myval:
- try:
- if self.aux_get(cpv, ["SLOT"])[0] == myslot:
- slotmatches.append(cpv)
- except KeyError:
- pass # ebuild masked by corruption
- myval = slotmatches
+
if self.frozen and (level not in ["match-list", "bestmatch-list"]):
self.xcache[level][mydep] = myval
if origdep and origdep != mydep:
#
import re, sys, types
+from itertools import chain
import portage.exception
from portage.exception import InvalidData, InvalidAtom
from portage.versions import catpkgsplit, catsplit, pkgcmp, pkgsplit, ververify
def __init__(self, use):
enabled_flags = []
disabled_flags = []
+ conditional_enabled = []
+ conditional_disabled = []
for x in use:
if "-" == x[:1]:
- disabled_flags.append(x[1:])
+ if "?" == x[-1:]:
+ conditional_disabled.append(x[1:-1])
+ else:
+ disabled_flags.append(x[1:])
else:
- enabled_flags.append(x)
+ if "?" == x[-1:]:
+ conditional_enabled.append(x[:-1])
+ else:
+ enabled_flags.append(x)
+ self.tokens = use
+ if not isinstance(self.tokens, tuple):
+ self.tokens = tuple(self.tokens)
self.enabled = frozenset(enabled_flags)
self.disabled = frozenset(disabled_flags)
- self.required = self.enabled.union(self.disabled)
+ self.conditional_enabled = frozenset(conditional_enabled)
+ self.conditional_disabled = frozenset(conditional_disabled)
+ self.conditional = self.conditional_enabled.union(
+ self.conditional_disabled)
+ self.required = frozenset(chain(self.enabled, self.disabled,
+ self.conditional_enabled, self.conditional_disabled))
+
+ def __str__(self):
+ return "".join("[%s]" % x for x in self.tokens)
+
+ def evaluate_conditionals(self, use):
+ """
+ Create a new instance with conditionals evaluated as follows:
+
+ parent state conditional result
+ x x? x
+ -x x? -x
+ x -x? -x
+ -x -x? x
+ """
+ tokens = []
+ tokens.extend(self.enabled)
+ tokens.extend("-" + x for x in self.disabled)
+ tokens.extend(self.conditional_enabled.intersection(use))
+ tokens.extend("-" + x for x in self.conditional_enabled.difference(use))
+ tokens.extend("-" + x for x in self.conditional_disabled.intersection(use))
+ tokens.extend(self.conditional_disabled.difference(use))
+ return _use_dep(tokens)
class Atom(str):
@return: List of use flags ( or [] if no flags exist )
"""
use = getattr(depend, "use", None)
- if use is not None:
- return use
+ if use is not None and hasattr(use, "tokens"):
+ return use.tokens
use_list = []
open_bracket = depend.find('[')
# -1 = failure (think c++ string::npos)
open_bracket = depend.find( '[', open_bracket+1 )
return tuple(use_list)
-_invalid_atom_chars_regexp = re.compile("[()|?@]")
+_valid_category = re.compile("^\w[\w-]*")
+_invalid_atom_chars_regexp = re.compile("[()|@]")
def isvalidatom(atom, allow_blockers=False):
"""
return 0
if allow_blockers and atom.startswith("!"):
atom = atom[1:]
- try:
- mycpv_cps = catpkgsplit(dep_getcpv(atom))
- except InvalidData:
- return 0
+ cpv = dep_getcpv(atom)
+ if cpv:
+ if _valid_category.match(catsplit(cpv)[0]) is None:
+ return 0
+ mycpv_cps = catpkgsplit(cpv)
+ else:
+ mycpv_cps = None
operator = get_operator(atom)
if operator:
if operator[0] in "<>" and remove_slot(atom).endswith("*"):
# $Id$
from portage import cpv_getkey, flatten
-from portage.dep import isvalidatom, match_from_list, \
+from portage.dep import Atom, isvalidatom, match_from_list, \
best_match_to_list, dep_getkey, use_reduce, paren_reduce
from portage.exception import InvalidAtom
return self._nonatoms.copy()
def _setAtoms(self, atoms):
- atoms = map(str.strip, atoms)
+ self._atoms.clear()
self._nonatoms.clear()
- for a in atoms[:]:
- if a == "":
- atoms.remove(a)
- elif not isvalidatom(a):
- atoms.remove(a)
+ for a in atoms:
+ a = a.strip()
+ if not a:
+ continue
+ try:
+ self._atoms.add(Atom(a))
+ except InvalidAtom:
self._nonatoms.add(a)
- self._atoms = set(atoms)
self._updateAtomMap()
def load(self):
self._atommap[cp].add(a)
# Not sure if this one should really be in PackageSet
- def findAtomForPackage(self, cpv, metadata):
+ def findAtomForPackage(self, pkg):
"""Return the best match for a given package from the arguments, or
None if there are no matches. This matches virtual arguments against
the PROVIDE metadata. This can raise an InvalidDependString exception
if an error occurs while parsing PROVIDE."""
- cpv_slot = "%s:%s" % (cpv, metadata["SLOT"])
- cp = dep_getkey(cpv)
- self._load() # make sure the atoms are loaded
- atoms = self._atommap.get(cp)
- if atoms:
- best_match = best_match_to_list(cpv_slot, atoms)
- if best_match:
- return best_match
- if not metadata["PROVIDE"]:
+ atoms = list(self.iterAtomsForPackage(pkg))
+ if not atoms:
return None
- provides = flatten(use_reduce(paren_reduce(metadata["PROVIDE"]),
- uselist=metadata["USE"].split()))
- for provide in provides:
- provided_cp = dep_getkey(provide)
- atoms = self._atommap.get(provided_cp)
- if atoms:
- atoms = list(atoms)
- transformed_atoms = [atom.replace(provided_cp, cp) for atom in atoms]
- best_match = best_match_to_list(cpv_slot, transformed_atoms)
- if best_match:
- return atoms[transformed_atoms.index(best_match)]
- return None
+ return best_match_to_list(pkg.cpv_slot, atoms)
def iterAtomsForPackage(self, pkg):
"""
test_cps = ['sys-apps/portage','virtual/portage']
test_versions = ['1.0', '1.0-r1','2.3_p4','1.0_alpha57']
test_slots = [ None, '1','gentoo-sources-2.6.17','spankywashere']
-test_usedeps = ['foo','-bar', ['foo','bar'],['foo','-bar'] ]
+test_usedeps = ['foo','-bar', ('foo','bar'),
+ ('foo','-bar'), ('foo?', '-bar?') ]
cpv += version
if slot:
cpv += ":" + slot
- if isinstance( use, list ):
+ if isinstance(use, tuple):
for u in use:
cpv = cpv + "[" + u + "]"
self.assertEqual( dep_getusedeps(
else:
if len(use):
self.assertEqual( dep_getusedeps(
- cpv + "[" + use + "]" ), [use] )
+ cpv + "[" + use + "]" ), (use,) )
else:
self.assertEqual( dep_getusedeps(
- cpv + "[" + use + "]" ), [] )
+ cpv + "[" + use + "]" ), () )
"""
def testIsValidAtom(self):
-
- self.todo = True
+
tests = [ ( "sys-apps/portage", True ),
( "=sys-apps/portage-2.1", True ),
( "=sys-apps/portage-2.1*", True ),
( "sys-apps/portage:foo", True ),
( "sys-apps/portage-2.1:foo", False ),
( "sys-apps/portage-2.1:", False ),
+ ( "=sys-apps/portage-2.2*:foo[bar][-baz][doc?][-build?]", True ),
( ">~cate-gory/foo-1.0", False ),
- ( ">~category/foo-1.0", True ),
- ( "<~category/foo-1.0", True ),
+ ( ">~category/foo-1.0", False ),
+ ( "<~category/foo-1.0", False ),
( "###cat/foo-1.0", False ),
( "~sys-apps/portage", False ),
( "portage", False ) ]
1. If each exists, it returns [cat, pkgname, version, rev]
2. If cat is not specificed in mydata, cat will be "null"
3. if rev does not exist it will be '-r0'
- 4. If cat is invalid (specified but has incorrect syntax)
- an InvalidData Exception will be thrown
"""
-
- # Categories may contain a-zA-z0-9+_- but cannot start with -
- import portage.dep
+
try:
if not catcache[mydata]:
return None