diff options
-rw-r--r-- | pym/_emerge/__init__.py | 70 | ||||
-rw-r--r-- | pym/portage/dep.py | 51 | ||||
-rw-r--r-- | pym/portage/sets/base.py | 4 |
3 files changed, 100 insertions, 25 deletions
diff --git a/pym/_emerge/__init__.py b/pym/_emerge/__init__.py index 2616c1be7..1d3fc5f76 100644 --- a/pym/_emerge/__init__.py +++ b/pym/_emerge/__init__.py @@ -1268,7 +1268,8 @@ class Package(Task): __slots__ = ("built", "cpv", "depth", "installed", "metadata", "onlydeps", "operation", "root", "type_name", - "category", "cp", "cpv_slot", "pf", "pv_split", "slot_atom") + "category", "cp", "cpv_slot", "cpv_split", + "pf", "pv_split", "slot", "slot_atom", "use") metadata_keys = [ "CHOST", "COUNTER", "DEPEND", "EAPI", "IUSE", "KEYWORDS", @@ -1277,11 +1278,43 @@ class Package(Task): def __init__(self, **kwargs): Task.__init__(self, **kwargs) + self.metadata = self._metadata_wrapper(self, self.metadata) self.cp = portage.cpv_getkey(self.cpv) - self.slot_atom = "%s:%s" % (self.cp, self.metadata["SLOT"]) - self.cpv_slot = "%s:%s" % (self.cpv, self.metadata["SLOT"]) + self.slot = self.metadata["SLOT"] + self.slot_atom = portage.dep.Atom("%s:%s" % \ + (self.cp, self.metadata["SLOT"])) + + # This used to be "%s:%s" % (self.cpv, self.slot) but now + # is's just a reference to self since match_from_list() + # now supports Package references. + self.cpv_slot = self + self.category, self.pf = portage.catsplit(self.cpv) - self.pv_split = portage.catpkgsplit(self.cpv)[1:] + self.cpv_split = portage.catpkgsplit(self.cpv) + self.pv_split = self.cpv_split[1:] + self.use = self._use(self.metadata["USE"].split()) + + class _use(object): + def __init__(self, use): + self.enabled = frozenset(use) + + class _metadata_wrapper(dict): + """ + Detect metadata updates and synchronize Package attributes. + """ + def __init__(self, pkg, metadata): + dict.__init__(self, metadata.iteritems()) + self._pkg = pkg + + def __setitem__(self, k, v): + dict.__setitem__(self, k, v) + if k == "USE": + self._pkg.use = self._pkg._use(v.split()) + + def _metadata_setitem(self, k, v): + self._metadata_setitem_orig(k, v) + if k == "USE": + self.use = self._use(self) def _get_hash_key(self): hash_key = getattr(self, "_hash_key", None) @@ -3035,18 +3068,7 @@ class depgraph(object): installed=installed, metadata=metadata, onlydeps=onlydeps, root=root, type_name=pkg_type) self._pkg_cache[pkg] = pkg - myarg = None - if root == self.target_root: - try: - myarg = self._iter_atoms_for_pkg(pkg).next() - except StopIteration: - pass - except portage.exception.InvalidDependString: - if not installed: - # masked by corruption - continue - if not installed and myarg: - found_available_arg = True + if not installed or (installed and matched_packages): # Only enforce visibility on installed packages # if there is at least one other visible package @@ -3085,6 +3107,22 @@ class depgraph(object): # it's expensive. pkgsettings.setcpv(cpv, mydb=pkg.metadata) pkg.metadata["USE"] = pkgsettings["PORTAGE_USE"] + + myarg = None + if root == self.target_root: + try: + # Ebuild USE must have been calculated prior + # to this point, in case atoms have USE deps. + myarg = self._iter_atoms_for_pkg(pkg).next() + except StopIteration: + pass + except portage.exception.InvalidDependString: + if not installed: + # masked by corruption + continue + if not installed and myarg: + found_available_arg = True + if atom.use and not pkg.built: use = pkg.metadata["USE"].split() if atom.use.enabled.difference(use): diff --git a/pym/portage/dep.py b/pym/portage/dep.py index 75d4f4c47..ae6363d07 100644 --- a/pym/portage/dep.py +++ b/pym/portage/dep.py @@ -759,6 +759,9 @@ def match_from_list(mydep, candidate_list): @return: A list of package atoms that match the given package atom """ + if not candidate_list: + return [] + from portage.util import writemsg if "!" == mydep[:1]: mydep = mydep[1:] @@ -791,13 +794,21 @@ def match_from_list(mydep, candidate_list): if operator is None: for x in candidate_list: - if dep_getkey(x) != mycpv: + cp = getattr(x, "cp", None) + if cp is None: + cp = dep_getkey(x) + if cp != mycpv: continue mylist.append(x) elif operator == "=": # Exact match - mylist = [cpv for cpv in candidate_list if \ - cpvequal(remove_slot(cpv), mycpv)] + for x in candidate_list: + xcpv = getattr(x, "cpv", None) + if xcpv is None: + xcpv = dep_getcpv(x) + if not cpvequal(xcpv, mycpv): + continue + mylist.append(x) elif operator == "=*": # glob match # XXX: Nasty special casing for leading zeros @@ -809,7 +820,9 @@ def match_from_list(mydep, candidate_list): myver = "0"+myver mycpv = mysplit[0]+"/"+mysplit[1]+"-"+myver for x in candidate_list: - xs = catpkgsplit(remove_slot(x)) + xs = getattr(x, "cpv_split", None) + if xs is None: + xs = catpkgsplit(remove_slot(x)) myver = xs[2].lstrip("0") if not myver or not myver[0].isdigit(): myver = "0"+myver @@ -819,7 +832,9 @@ def match_from_list(mydep, candidate_list): elif operator == "~": # version, any revision, match for x in candidate_list: - xs = catpkgsplit(remove_slot(x)) + xs = getattr(x, "cpv_split", None) + if xs is None: + xs = catpkgsplit(remove_slot(x)) if xs is None: raise InvalidData(x) if not cpvequal(xs[0]+"/"+xs[1]+"-"+xs[2], mycpv_cps[0]+"/"+mycpv_cps[1]+"-"+mycpv_cps[2]): @@ -831,8 +846,13 @@ def match_from_list(mydep, candidate_list): elif operator in [">", ">=", "<", "<="]: mysplit = ["%s/%s" % (cat, pkg), ver, rev] for x in candidate_list: + xs = getattr(x, "cpv_split", None) + if xs is None: + xs = catpkgsplit(remove_slot(x)) + xcat, xpkg, xver, xrev = xs + xs = ["%s/%s" % (xcat, xpkg), xver, xrev] try: - result = pkgcmp(pkgsplit(remove_slot(x)), mysplit) + result = pkgcmp(xs, mysplit) except ValueError: # pkgcmp may return ValueError during int() conversion writemsg("\nInvalid package name: %s\n" % x, noiselevel=-1) raise @@ -859,9 +879,26 @@ def match_from_list(mydep, candidate_list): candidate_list = mylist mylist = [] for x in candidate_list: - xslot = dep_getslot(x) + xslot = getattr(x, "slot", None) + if xslot is None and isinstance(x, basestring): + xslot = dep_getslot(x) if xslot is not None and xslot != slot: continue mylist.append(x) + if mydep.use: + candidate_list = mylist + mylist = [] + for x in candidate_list: + # Note: IUSE intersection is neglected here since there + # is currently no way to access implicit IUSE. However, IUSE + # filtering can be added elsewhere in the chain. + use = getattr(x, "use", None) + if use is not None: + if mydep.use.enabled.difference(use.enabled): + continue + if mydep.use.disabled.intersection(use.enabled): + continue + mylist.append(x) + return mylist diff --git a/pym/portage/sets/base.py b/pym/portage/sets/base.py index ac77e95c3..3f85965bc 100644 --- a/pym/portage/sets/base.py +++ b/pym/portage/sets/base.py @@ -108,7 +108,7 @@ class PackageSet(object): atoms = list(self.iterAtomsForPackage(pkg)) if not atoms: return None - return best_match_to_list(pkg.cpv_slot, atoms) + return best_match_to_list(pkg, atoms) def iterAtomsForPackage(self, pkg): """ @@ -116,7 +116,7 @@ class PackageSet(object): arguments against the PROVIDE metadata. This will raise an InvalidDependString exception if PROVIDE is invalid. """ - cpv_slot_list = ["%s:%s" % (pkg.cpv, pkg.metadata["SLOT"])] + cpv_slot_list = [pkg] cp = cpv_getkey(pkg.cpv) self._load() # make sure the atoms are loaded atoms = self._atommap.get(cp) |