def _get_all_provides(vardb): """ Get all of the sonames provided by all of the installed packages. This does not bother to acquire a lock, since its pretty safe to assume that any packages merged or unmerged while this function is running must be irrelevant. @param vardb: an installed package database @type vardb: vardbapi @rtype: frozenset @return: a frozenset od SonameAtom instances provided by all installed packages """ all_provides = [] for cpv in vardb.cpv_all(): try: provides, = vardb.aux_get(cpv, ['PROVIDES']) except KeyError: # Since we don't hold a lock, assume this is due to a # concurrent unmerge, and PROVIDES from the unmerged package # are most likely negligible due to topologically sorted # merge order. Also, note that it's possible for aux_get # to succeed and return empty PROVIDES metadata if the file # disappears (due to unmerge) before it can be read. pass else: if provides: all_provides.extend(parse_soname_deps(provides)) return frozenset(all_provides)
def _get_unresolved_soname_deps(metadata_dir, all_provides): """ Get files with unresolved soname dependencies. @param metadata_dir: directory containing package metadata files named REQUIRES and NEEDED.ELF.2 @type metadata_dir: str @param all_provides: a frozenset on SonameAtom instances provided by all installed packages @type all_provides: frozenset @rtype: list @return: list of tuple(filename, tuple(unresolved sonames)) """ try: with io.open(_unicode_encode(os.path.join(metadata_dir, 'REQUIRES'), encoding=_encodings['fs'], errors='strict'), mode='rt', encoding=_encodings['repo.content'], errors='strict') as f: requires = frozenset(parse_soname_deps(f.read())) except EnvironmentError: return [] unresolved_by_category = {} for atom in requires: if atom not in all_provides: unresolved_by_category.setdefault(atom.multilib_category, set()).add(atom.soname) needed_filename = os.path.join(metadata_dir, "NEEDED.ELF.2") with io.open(_unicode_encode(needed_filename, encoding=_encodings['fs'], errors='strict'), mode='rt', encoding=_encodings['repo.content'], errors='strict') as f: needed = f.readlines() unresolved_by_file = [] for l in needed: l = l.rstrip("\n") if not l: continue entry = NeededEntry.parse(needed_filename, l) missing = unresolved_by_category.get(entry.multilib_category) if not missing: continue # NOTE: This can contain some false positives in the case of # missing DT_RPATH settings, since it's possible that a subset # package files have the desired DT_RPATH settings. However, # since reported sonames are unresolved for at least some file(s), # false positives or this sort should not be not too annoying. missing = [soname for soname in entry.needed if soname in missing] if missing: unresolved_by_file.append((entry.filename, tuple(missing))) return unresolved_by_file
def _validate_deps(self): """ Validate deps. This does not trigger USE calculation since that is expensive for ebuilds and therefore we want to avoid doing it unnecessarily (like for masked packages). """ eapi = self.eapi dep_eapi = eapi dep_valid_flag = self.iuse.is_valid_flag if self.installed: # Ignore EAPI.incompatible and conditionals missing # from IUSE for installed packages since these issues # aren't relevant now (re-evaluate when new EAPIs are # deployed). dep_eapi = None dep_valid_flag = None validated_atoms = [] for k in self._dep_keys: v = self._metadata.get(k) if not v: continue try: atoms = use_reduce(v, eapi=dep_eapi, matchall=True, is_valid_flag=dep_valid_flag, token_class=Atom, flat=True) except InvalidDependString as e: self._metadata_exception(k, e) else: validated_atoms.extend(atoms) if not self.built: for atom in atoms: if not isinstance(atom, Atom): continue if atom.slot_operator_built: e = InvalidDependString( _("Improper context for slot-operator " "\"built\" atom syntax: %s") % (atom.unevaluated_atom,)) self._metadata_exception(k, e) self._validated_atoms = tuple(set(atom for atom in validated_atoms if isinstance(atom, Atom))) for k in self._use_conditional_misc_keys: v = self._metadata.get(k) if not v: continue try: use_reduce(v, eapi=dep_eapi, matchall=True, is_valid_flag=dep_valid_flag) except InvalidDependString as e: self._metadata_exception(k, e) k = 'REQUIRED_USE' v = self._metadata.get(k) if v and not self.built: if not _get_eapi_attrs(eapi).required_use: self._invalid_metadata('EAPI.incompatible', "REQUIRED_USE set, but EAPI='%s' doesn't allow it" % eapi) else: try: check_required_use(v, (), self.iuse.is_valid_flag, eapi=eapi) except InvalidDependString as e: self._invalid_metadata(k + ".syntax", "%s: %s" % (k, e)) k = 'SRC_URI' v = self._metadata.get(k) if v: try: use_reduce(v, is_src_uri=True, eapi=eapi, matchall=True, is_valid_flag=self.iuse.is_valid_flag) except InvalidDependString as e: if not self.installed: self._metadata_exception(k, e) if self.built: k = 'PROVIDES' try: self._provides = frozenset( parse_soname_deps(self._metadata[k])) except InvalidData as e: self._invalid_metadata(k + ".syntax", "%s: %s" % (k, e)) k = 'REQUIRES' try: self._requires = frozenset( parse_soname_deps(self._metadata[k])) except InvalidData as e: self._invalid_metadata(k + ".syntax", "%s: %s" % (k, e))
def _validate_deps(self): """ Validate deps. This does not trigger USE calculation since that is expensive for ebuilds and therefore we want to avoid doing it unnecessarily (like for masked packages). """ eapi = self.eapi dep_eapi = eapi dep_valid_flag = self.iuse.is_valid_flag if self.installed: # Ignore EAPI.incompatible and conditionals missing # from IUSE for installed packages since these issues # aren't relevant now (re-evaluate when new EAPIs are # deployed). dep_eapi = None dep_valid_flag = None validated_atoms = [] for k in self._dep_keys: v = self._metadata.get(k) if not v: continue try: atoms = use_reduce(v, eapi=dep_eapi, matchall=True, is_valid_flag=dep_valid_flag, token_class=Atom, flat=True) except InvalidDependString as e: self._metadata_exception(k, e) else: validated_atoms.extend(atoms) if not self.built: for atom in atoms: if not isinstance(atom, Atom): continue if atom.slot_operator_built: e = InvalidDependString( _("Improper context for slot-operator " "\"built\" atom syntax: %s") % (atom.unevaluated_atom,)) self._metadata_exception(k, e) self._validated_atoms = tuple(set(atom for atom in validated_atoms if isinstance(atom, Atom))) k = 'PROVIDE' v = self._metadata.get(k) if v: try: use_reduce(v, eapi=dep_eapi, matchall=True, is_valid_flag=dep_valid_flag, token_class=Atom) except InvalidDependString as e: self._invalid_metadata("PROVIDE.syntax", "%s: %s" % (k, e)) for k in self._use_conditional_misc_keys: v = self._metadata.get(k) if not v: continue try: use_reduce(v, eapi=dep_eapi, matchall=True, is_valid_flag=dep_valid_flag) except InvalidDependString as e: self._metadata_exception(k, e) k = 'REQUIRED_USE' v = self._metadata.get(k) if v and not self.built: if not _get_eapi_attrs(eapi).required_use: self._invalid_metadata('EAPI.incompatible', "REQUIRED_USE set, but EAPI='%s' doesn't allow it" % eapi) else: try: check_required_use(v, (), self.iuse.is_valid_flag, eapi=eapi) except InvalidDependString as e: self._invalid_metadata(k + ".syntax", "%s: %s" % (k, e)) k = 'SRC_URI' v = self._metadata.get(k) if v: try: use_reduce(v, is_src_uri=True, eapi=eapi, matchall=True, is_valid_flag=self.iuse.is_valid_flag) except InvalidDependString as e: if not self.installed: self._metadata_exception(k, e) if self.built: k = 'PROVIDES' try: self._provides = frozenset( parse_soname_deps(self._metadata[k])) except InvalidData as e: self._invalid_metadata(k + ".syntax", "%s: %s" % (k, e)) k = 'REQUIRES' try: self._requires = frozenset( parse_soname_deps(self._metadata[k])) except InvalidData as e: self._invalid_metadata(k + ".syntax", "%s: %s" % (k, e))