def mapPathsToAtoms(self, paths, exclude_paths=None): """ All paths must have $EROOT stripped from the left side. """ rValue = set() vardb = self._db aux_get = vardb.aux_get aux_keys = ["SLOT"] if exclude_paths is None: for link, p in vardb._owners.iter_owners(paths): cat, pn = catpkgsplit(link.mycpv)[:2] slot, = aux_get(link.mycpv, aux_keys) rValue.add("%s/%s:%s" % (cat, pn, slot)) else: all_paths = set() all_paths.update(paths) all_paths.update(exclude_paths) exclude_atoms = set() for link, p in vardb._owners.iter_owners(all_paths): cat, pn = catpkgsplit(link.mycpv)[:2] slot, = aux_get(link.mycpv, aux_keys) atom = "%s/%s:%s" % (cat, pn, slot) rValue.add(atom) if p in exclude_paths: exclude_atoms.add(atom) rValue.difference_update(exclude_atoms) return rValue
def cpvequal(cpv1, cpv2): """ @param cpv1: CategoryPackageVersion (no operators) Example: "sys-apps/portage-2.1" @type cpv1: String @param cpv2: CategoryPackageVersion (no operators) Example: "sys-apps/portage-2.1" @type cpv2: String @rtype: Boolean @returns: 1. True if cpv1 = cpv2 2. False Otherwise 3. Throws PortageException if cpv1 or cpv2 is not a CPV Example Usage: >>> from portage.dep import cpvequal >>> cpvequal("sys-apps/portage-2.1","sys-apps/portage-2.1") >>> True """ split1 = catpkgsplit(cpv1) split2 = catpkgsplit(cpv2) if not split1 or not split2: raise portage.exception.PortageException(_("Invalid data '%s, %s', parameter was not a CPV") % (cpv1, cpv2)) if split1[0] != split2[0]: return False return (pkgcmp(split1[1:], split2[1:]) == 0)
def getMinUpgrade(vulnerableList, unaffectedList, portdbapi, vardbapi, minimize=True): """ Checks if the systemstate is matching an atom in I{vulnerableList} and returns string describing the lowest version for the package that matches an atom in I{unaffectedList} and is greater than the currently installed version or None if the system is not affected. Both I{vulnerableList} and I{unaffectedList} should have the same base package. @type vulnerableList: List of Strings @param vulnerableList: atoms matching vulnerable package versions @type unaffectedList: List of Strings @param unaffectedList: atoms matching unaffected package versions @type portdbapi: portage.dbapi.porttree.portdbapi @param portdbapi: Ebuild repository @type vardbapi: portage.dbapi.vartree.vardbapi @param vardbapi: Installed package repository @type minimize: Boolean @param minimize: True for a least-change upgrade, False for emerge-like algorithm @rtype: String | None @return: the lowest unaffected version that is greater than the installed version. """ rValue = None v_installed = [] u_installed = [] for v in vulnerableList: v_installed += match(v, vardbapi) for u in unaffectedList: u_installed += match(u, vardbapi) install_unaffected = True for i in v_installed: if i not in u_installed: install_unaffected = False if install_unaffected: return rValue for u in unaffectedList: mylist = match(u, portdbapi, match_type="match-all") for c in mylist: c_pv = catpkgsplit(c) i_pv = catpkgsplit(best(v_installed)) if pkgcmp(c_pv[1:], i_pv[1:]) > 0 \ and (rValue == None \ or not match("="+rValue, portdbapi) \ or (minimize ^ (pkgcmp(c_pv[1:], catpkgsplit(rValue)[1:]) > 0)) \ and match("="+c, portdbapi)) \ and portdbapi.aux_get(c, ["SLOT"]) == vardbapi.aux_get(best(v_installed), ["SLOT"]): rValue = c_pv[0]+"/"+c_pv[1]+"-"+c_pv[2] if c_pv[3] != "r0": # we don't like -r0 for display rValue += "-"+c_pv[3] return rValue
def catpkgsplit(cpv): split = catpkgsplit(cpv) if not split: split = catpkgsplit('%s-0' % (cpv, )) if not split: return split c, p, v, r = split if r != 'r0' or cpv[-3:] == 'r0': v = '%s-%s' % (v, r) return c, p, v
def _calc_changelog(ebuildpath, current, next): if ebuildpath == None or not os.path.exists(ebuildpath): return [] current = "-".join(catpkgsplit(current)[1:]) if current.endswith("-r0"): current = current[:-3] next = "-".join(catpkgsplit(next)[1:]) if next.endswith("-r0"): next = next[:-3] changelogdir = os.path.dirname(ebuildpath) changelogs = ["ChangeLog"] # ChangeLog-YYYY (see bug #389611) changelogs.extend(sorted((fn for fn in os.listdir(changelogdir) if fn.startswith("ChangeLog-")), reverse=True)) divisions = [] found_current = False for fn in changelogs: changelogpath = os.path.join(changelogdir, fn) try: with io.open( _unicode_encode(changelogpath, encoding=_encodings["fs"], errors="strict"), mode="r", encoding=_encodings["repo.content"], errors="replace", ) as f: changelog = f.read() except EnvironmentError: return [] for node in _find_changelog_tags(changelog): if node[0] == current: found_current = True break else: divisions.append(node) if found_current: break if not found_current: return [] # print 'XX from',current,'to',next # for div,text in divisions: print 'XX',div # skip entries for all revisions above the one we are about to emerge for i in range(len(divisions)): if divisions[i][0] == next: divisions = divisions[i:] break return divisions
def _reduce(self, atomlist): mydict = {} for atom in atomlist[:]: cpv = self._portdbapi.xmatch("match-all", atom)[0] slot = self._portdbapi.aux_get(cpv, ["SLOT"])[0] cps = "/".join(catpkgsplit(cpv)[0:2]) + ":" + slot if not cps in mydict: mydict[cps] = (atom, cpv) else: other_cpv = mydict[cps][1] if pkgcmp(catpkgsplit(cpv)[1:], catpkgsplit(other_cpv)[1:]) > 0: atomlist.remove(mydict[cps][0]) mydict[cps] = (atom, cpv) return atomlist
def _calc_changelog(ebuildpath,current,next): if ebuildpath == None or not os.path.exists(ebuildpath): return [] current = '-'.join(catpkgsplit(current)[1:]) if current.endswith('-r0'): current = current[:-3] next = '-'.join(catpkgsplit(next)[1:]) if next.endswith('-r0'): next = next[:-3] changelogdir = os.path.dirname(ebuildpath) changelogs = ['ChangeLog'] # ChangeLog-YYYY (see bug #389611) changelogs.extend(sorted((fn for fn in os.listdir(changelogdir) if fn.startswith('ChangeLog-')), reverse=True)) divisions = [] found_current = False for fn in changelogs: changelogpath = os.path.join(changelogdir, fn) try: with io.open(_unicode_encode(changelogpath, encoding=_encodings['fs'], errors='strict'), mode='r', encoding=_encodings['repo.content'], errors='replace') as f: changelog = f.read() except EnvironmentError: return [] for node in _find_changelog_tags(changelog): if node[0] == current: found_current = True break else: divisions.append(node) if found_current: break if not found_current: return [] #print 'XX from',current,'to',next #for div,text in divisions: print 'XX',div # skip entries for all revisions above the one we are about to emerge for i in range(len(divisions)): if divisions[i][0]==next: divisions = divisions[i:] break return divisions
def validateLogfile(package, config_, target): # pylint: disable=too-many-locals try: my_root = os.path.join('/usr/targets', os.getenv('CURRENT_TARGET', target), 'root/') my_trees = create_trees(config_root=my_root, target_root=my_root) portage_db = my_trees[my_root]['vartree'].dbapi [cpv] = portage_db.match(package) except (InvalidAtom, ValueError): return None if not cpv: return None [license_] = portage_db.aux_get(cpv, ['LICENSE']) if license_.lower() != 'wyplay': return None category, name, version, revision = catpkgsplit(cpv) logfile = '%s:%s-%s%s:' % (category, name, version, str() if revision == 'r0' else '-%s' % revision) try: file_ = next(fname for fname in os.listdir(config_['PORT_LOGDIR']) if fname.startswith(logfile)) except StopIteration: return None filepath = os.path.abspath(os.path.join(config_['PORT_LOGDIR'], file_)) with open(filepath, 'r') as fd: compiler_pattern = r'^\s?%s-g' % config_['CHOST'] try: line = next(l for l in fd if re.match(compiler_pattern, l)) except StopIteration: return None return list(v for k, v in [(' -Wall ', 'NO_WALL'), (' -Wextra ', 'NO_WEXTRA')] if k not in line)
def get_slotted_cps(cpvs, logger): """Uses portage to reduce the cpv list into a cp:slot list and returns it """ from portage.versions import catpkgsplit from portage import portdb cps = [] for cpv in cpvs: parts = catpkgsplit(cpv) if not parts: logger.warning(('\t' + red("Failed to split the following pkg: " "%s, not a valid cat/pkg-ver" %cpv))) continue cp = parts[0] + '/' + parts[1] try: slot = portdb.aux_get(cpv, ["SLOT"]) except KeyError: match, slot = get_best_match(cpv, cp, logger) if not match: logger.warning('\t' + red("Installed package: " "%s is no longer available" %cp)) continue if slot[0]: cps.append(cp + ":" + slot[0]) else: cps.append(cp) return cps
def mapPathsToAtoms(self, paths): rValue = set() for link, p in self.dbapi._owners.iter_owners(paths): cat, pn = catpkgsplit(link.mycpv)[:2] slot = self.dbapi.aux_get(link.mycpv, ["SLOT"])[0] rValue.add("%s/%s:%s" % (cat, pn, slot)) return rValue
def convert_myoldbest(myoldbest): """converts and colorizes a version list to a string @param myoldbest: list @rtype string. """ # Convert myoldbest from a list to a string. myoldbest_str = "" if myoldbest: versions = [] for pos, pkg in enumerate(myoldbest): key = catpkgsplit(pkg.cpv)[2] + \ "-" + catpkgsplit(pkg.cpv)[3] if key[-3:] == "-r0": key = key[:-3] versions.append(key) myoldbest_str = blue("["+", ".join(versions)+"]") return myoldbest_str
def compare_strs(pkg1, pkg2): """Similar to the builtin cmp, but for package strings. Usually called as: package_list.sort(cpv.compare_strs) An alternative is to use the CPV descriptor from gentoolkit.cpv: >>> cpvs = sorted(CPV(x) for x in package_list) @see: >>> help(cmp) """ pkg1 = catpkgsplit(pkg1) pkg2 = catpkgsplit(pkg2) if pkg1[0] != pkg2[0]: return -1 if pkg1[0] < pkg2[0] else 1 elif pkg1[1] != pkg2[1]: return -1 if pkg1[1] < pkg2[1] else 1 else: return pkgcmp(pkg1[1:], pkg2[1:])
def compare_strs(pkg1, pkg2): """Similar to the builtin cmp, but for package strings. Usually called as: package_list.sort(cpv.compare_strs) An alternative is to use the CPV descriptor from gentoolkit.cpv: >>> package_list = ['sys-apps/portage-9999', 'media-video/ffmpeg-9999'] >>> cpvs = sorted(CPV(x) for x in package_list) @see: >>> help(cmp) """ pkg1 = catpkgsplit(pkg1) pkg2 = catpkgsplit(pkg2) if pkg1[0] != pkg2[0]: return -1 if pkg1[0] < pkg2[0] else 1 elif pkg1[1] != pkg2[1]: return -1 if pkg1[1] < pkg2[1] else 1 else: return pkgcmp(pkg1[1:], pkg2[1:])
def mapPathsToAtoms(self, paths): rValue = set() vardb = self._db aux_get = vardb.aux_get aux_keys = ["SLOT"] for link, p in vardb._owners.iter_owners(paths): cat, pn = catpkgsplit(link.mycpv)[:2] slot, = aux_get(link.mycpv, aux_keys) rValue.add("%s/%s:%s" % (cat, pn, slot)) return rValue
def load(self): atoms = [] xmatch = self._portdb.xmatch xmatch_level = "bestmatch-visible" cp_list = self._vardb.cp_list aux_get = self._vardb.aux_get aux_keys = ["SLOT"] for cp in self._vardb.cp_all(): for cpv in cp_list(cp): slot, = aux_get(cpv, aux_keys) slot_atom = "%s:%s" % (cp, slot) ebuild = xmatch(xmatch_level, slot_atom) if not ebuild: continue ebuild_split = catpkgsplit(ebuild)[1:] installed_split = catpkgsplit(cpv)[1:] if pkgcmp(installed_split, ebuild_split) > 0: atoms.append(slot_atom) self._setAtoms(atoms)
def get_ver_str(pkg): """Obtains the version string @param pkg: _emerge.Package.Package instance @rtype string """ ver_str = list(catpkgsplit(pkg.cpv)[2:]) if ver_str[1] == "r0": ver_str[1] = "" else: ver_str[1] = "-" + ver_str[1] return ver_str[0]+ver_str[1]
def get_ver_str(pkg): """Obtains the version string @param pkg: _emerge.Package.Package instance @rtype string """ ver_str = list(catpkgsplit(pkg.cpv)[2:]) if ver_str[1] == "r0": ver_str[1] = "" else: ver_str[1] = "-" + ver_str[1] return ver_str[0] + ver_str[1]
def convert_myoldbest(self, pkg, myoldbest): """converts and colorizes a version list to a string @param pkg: _emerge.Package.Package instance @param myoldbest: list @rtype string. """ # Convert myoldbest from a list to a string. myoldbest_str = "" if myoldbest: versions = [] for pos, old_pkg in enumerate(myoldbest): key = catpkgsplit(old_pkg.cpv)[2] + "-" + catpkgsplit(old_pkg.cpv)[3] if key[-3:] == "-r0": key = key[:-3] if self.conf.verbosity == 3 and not self.quiet_repo_display and (self.verbose_main_repo_display or any(x.repo != self.portdb.repositories.mainRepo().name for x in myoldbest + [pkg])): key += _repo_separator + old_pkg.repo versions.append(key) myoldbest_str = blue("["+", ".join(versions)+"]") return myoldbest_str
def __init__(self, atom): atom = Atom(atom) self.cp = atom.cp self.cpv = atom.cpv self.cpv_split = catpkgsplit(self.cpv) self.slot = atom.slot if atom.use: self.use = self._use_class(atom.use.enabled) self.iuse = self._iuse_class(atom.use.required) else: self.use = self._use_class([]) self.iuse = self._iuse_class([])
def gen_structure(dbapi, repo_name): trees = [getcwd()] ret = {} for cp in dbapi.cp_all(trees=trees): cpvlist = dbapi.cp_list(cp, mytree=trees) category, pkgname = catpkgsplit(cpvlist[0])[:2] cat = ret.setdefault(category, {}) pn = cat.setdefault(pkgname, {}) pn["data"] = dbapi.aux_get(cpvlist[-1], WANT_DATA) pn["versions"] = [cpv_getversion(cpv) for cpv in cpvlist] return ret
def package_version_ebuild(request, overlay, cpv): category, package, version, revision = catpkgsplit(cpv) pkg = get_object_or_404(Package, category=category, name=package) obj = get_object_or_404(Version, package=pkg, version=version, revision=revision, overlay=overlay) if obj.ebuild_path: try: with open(obj.ebuild_path) as ebuild_file: content = ebuild_file.read() except IOError: return HttpResponseNotFound() else: return HttpResponseNotFound() return HttpResponse(content, content_type="text/plain")
def convert_myoldbest(self, pkg, myoldbest): """converts and colorizes a version list to a string @param pkg: _emerge.Package.Package instance @param myoldbest: list @rtype string. """ # Convert myoldbest from a list to a string. myoldbest_str = "" if myoldbest: versions = [] for pos, old_pkg in enumerate(myoldbest): key = catpkgsplit(old_pkg.cpv)[2] + "-" + catpkgsplit( old_pkg.cpv)[3] if key[-3:] == "-r0": key = key[:-3] if self.conf.verbosity == 3 and not self.quiet_repo_display and ( self.verbose_main_repo_display or any( x.repo != self.portdb.repositories.mainRepo().name for x in myoldbest + [pkg])): key += _repo_separator + old_pkg.repo versions.append(key) myoldbest_str = blue("[" + ", ".join(versions) + "]") return myoldbest_str
def _getCP(self, pkg): # drop ><= from the beginning if pkg[0] in (">", "<", "="): pkg = pkg[1:] if pkg[0] == "=": pkg = pkg[1:] dotPos = pkg.find(":") bracketPos = pkg.find("[") if dotPos > 0: pkg = pkg[0:dotPos] elif bracketPos > 0: pkg = pkg[0:bracketPos] res = catpkgsplit(pkg) if res: return res[0] + "/" + res[1] return pkg
def pkgsplit(pkgname): """ Custom pkgsplit """ cpv={'cat':'','pkg':'','ver':''} cpvr = catpkgsplit(pkgname) if cpvr is None: pkgsplit = pkgname.split('/') cpv['cat'] = pkgsplit[0] cpv['pkg'] = pkgsplit[1] else: cpv['cat'] = cpvr[0] cpv['pkg'] = cpvr[1] cpv['ver'] = cpvr[2] if cpvr[3] != 'r0': cpv['ver'] = cpv['ver'] + '-' + cpvr[3] return cpv
def __init__(self, atom): atom = Atom(atom, allow_repo=True) self.cp = atom.cp slot = atom.slot if atom.sub_slot: slot = "%s/%s" % (slot, atom.sub_slot) if not slot: slot = "0" self.cpv = _pkg_str(atom.cpv, slot=slot, repo=atom.repo) self.cpv_split = catpkgsplit(self.cpv) self.slot = self.cpv.slot self.sub_slot = self.cpv.sub_slot self.repo = atom.repo if atom.use: self.use = self._use_class(atom.use.enabled) self.iuse = self._iuse_class(atom.use.required) else: self.use = self._use_class([]) self.iuse = self._iuse_class([])
def __init__(self, atom): atom = Atom(atom, allow_repo=True) self.cp = atom.cp slot = atom.slot if atom.sub_slot: slot = "%s/%s" % (slot, atom.sub_slot) if not slot: slot = '0' self.cpv = _pkg_str(atom.cpv, slot=slot, repo=atom.repo) self.cpv_split = catpkgsplit(self.cpv) self.slot = self.cpv.slot self.sub_slot = self.cpv.sub_slot self.repo = atom.repo if atom.use: self.use = self._use_class(atom.use.enabled) self.iuse = self._iuse_class(atom.use.required) else: self.use = self._use_class([]) self.iuse = self._iuse_class([])
def dep_getkey(mydep): """ Return the category/package-name of a depstring. Example usage: >>> dep_getkey('=media-libs/test-3.0') 'media-libs/test' @param mydep: The depstring to retrieve the category/package-name of @type mydep: String @rtype: String @return: The package category/package-name """ if isinstance(mydep, Atom): return mydep.cp try: return Atom(mydep).cp except InvalidAtom: try: atom = Atom('=' + mydep) except InvalidAtom: pass else: warnings.warn(_("invalid input to %s: '%s', use %s instead") % \ ('portage.dep.dep_getkey()', mydep, 'portage.cpv_getkey()'), DeprecationWarning, stacklevel=2) return atom.cp # Fall back to legacy code for backward compatibility. warnings.warn(_("%s is deprecated, use %s instead") % \ ('portage.dep.dep_getkey()', 'portage.dep.Atom.cp'), DeprecationWarning, stacklevel=2) mydep = dep_getcpv(mydep) if mydep and isspecific(mydep): mysplit = catpkgsplit(mydep) if not mysplit: return mydep return mysplit[0] + "/" + mysplit[1] else: return mydep
def get_slotted_cps(cpvs, logger): """Uses portage to reduce the cpv list into a cp:slot list and returns it """ cps = [] for cpv in cpvs: parts = catpkgsplit(cpv) cp = parts[0] + '/' + parts[1] try: slot = portdb.aux_get(cpv, ["SLOT"]) except KeyError: match, slot = get_best_match(cpv, cp, logger) if not match: logger.warn(red("Installed package: " "%s is no longer available" %cp)) continue if slot[0]: cps.append(cp + ":" + slot[0]) else: cps.append(cp) return cps
def get_slotted_cps(cpvs, logger): """Uses portage to reduce the cpv list into a cp:slot list and returns it """ cps = [] for cpv in cpvs: parts = catpkgsplit(cpv) cp = parts[0] + '/' + parts[1] try: slot = portdb.aux_get(cpv, ["SLOT"]) except KeyError: match, slot = get_best_match(cpv, cp, logger) if not match: logger.warn( red("Installed package: " "%s is no longer available" % cp)) continue if slot[0]: cps.append(cp + ":" + slot[0]) else: cps.append(cp) return cps
def _process(self, var_tree, cpv, debug=False): cat, pkg, ver, rev = catpkgsplit(cpv) package_name = "%s/%s" % (cat, pkg) if rev == 'r0': version_revision = ver else: version_revision = "%s-%s" % (ver, rev) SLOT, KEYWORDS, repo, IUSE, USE = \ var_tree.dbapi.aux_get(cpv, ['SLOT', 'KEYWORDS', 'repository', 'IUSE', 'USE']) # Perform privacy check and filtering installed_from = [repo, ] if is_private_package_atom('=' + cpv, installed_from=installed_from, debug=debug): return None repo = installed_from[0] ACCEPT_KEYWORDS = portage.settings['ACCEPT_KEYWORDS'] ARCH = portage.settings['ARCH'] keyword_status = self._keyword_status(ARCH, ACCEPT_KEYWORDS, KEYWORDS) unmasked = PackageUnmask().hits(cpv) # A package that is (1) installed and (2) not unmasked # cannot be masked so we skip the next line's checks masked = unmasked and (PackageMask().hits(cpv) or \ ProfilePackageMask().hits(cpv)) # World set test if SLOT != '0': world_set_test = '%s/%s:%s' % (cat, pkg, SLOT) else: world_set_test = '%s/%s' % (cat, pkg) is_in_world = world_set_test in WorldSet().get() # Use flags if self._publish_installed_packages_use_flags: iuse_list = tuple(x.lstrip("+-") for x in IUSE.split()) count_all = len(set(iuse_list)) package_use_set = set(filter(self.is_known_use_flag, USE.split())) package_iuse_set = set(filter(self.is_known_use_flag, iuse_list)) enabled_flags = package_use_set & package_iuse_set disabled_flags = package_iuse_set - package_use_set package_flags = sorted(enabled_flags) + ['-' + e for e in sorted(disabled_flags)] count_non_private = len(package_flags) count_private = count_all - count_non_private self._private_use_flags = self._private_use_flags + count_private self._non_private_use_flags = self._non_private_use_flags + count_non_private else: package_flags = tuple() if not self._publish_repos: repo = 'WITHHELD' entry = [package_name, version_revision, SLOT, keyword_status, masked, unmasked, is_in_world, repo, package_flags] return entry
def getMinUpgrade(vulnerableList, unaffectedList, portdbapi, vardbapi, minimize=True): """ Checks if the systemstate is matching an atom in I{vulnerableList} and returns string describing the lowest version for the package that matches an atom in I{unaffectedList} and is greater than the currently installed version or None if the system is not affected. Both I{vulnerableList} and I{unaffectedList} should have the same base package. @type vulnerableList: List of Strings @param vulnerableList: atoms matching vulnerable package versions @type unaffectedList: List of Strings @param unaffectedList: atoms matching unaffected package versions @type portdbapi: portage.dbapi.porttree.portdbapi @param portdbapi: Ebuild repository @type vardbapi: portage.dbapi.vartree.vardbapi @param vardbapi: Installed package repository @type minimize: Boolean @param minimize: True for a least-change upgrade, False for emerge-like algorithm @rtype: String | None @return: the lowest unaffected version that is greater than the installed version. """ rValue = None v_installed = [] u_installed = [] for v in vulnerableList: v_installed += match(v, vardbapi) for u in unaffectedList: u_installed += match(u, vardbapi) install_unaffected = True for i in v_installed: if i not in u_installed: install_unaffected = False if install_unaffected: return rValue for u in unaffectedList: mylist = match(u, portdbapi, match_type="match-all") for c in mylist: c_pv = catpkgsplit(c) i_pv = catpkgsplit(best(v_installed)) if pkgcmp(c_pv[1:], i_pv[1:]) > 0 \ and (rValue == None \ or not match("="+rValue, portdbapi) \ or (minimize ^ (pkgcmp(c_pv[1:], catpkgsplit(rValue)[1:]) > 0)) \ and match("="+c, portdbapi)) \ and portdbapi.aux_get(c, ["SLOT"]) == vardbapi.aux_get(best(v_installed), ["SLOT"]): rValue = c_pv[0] + "/" + c_pv[1] + "-" + c_pv[2] if c_pv[3] != "r0": # we don't like -r0 for display rValue += "-" + c_pv[3] return rValue
def getmaskingreason(mycpv, metadata=None, settings=None, portdb=None, return_location=False, myrepo=None): """ If specified, the myrepo argument is assumed to be valid. This should be a safe assumption since portdbapi methods always return valid repo names and valid "repository" metadata from aux_get. """ if settings is None: settings = portage.settings if portdb is None: portdb = portage.portdb mysplit = catpkgsplit(mycpv) if not mysplit: raise ValueError(_("invalid CPV: %s") % mycpv) if metadata is None: db_keys = list(portdb._aux_cache_keys) try: metadata = dict( zip(db_keys, portdb.aux_get(mycpv, db_keys, myrepo=myrepo))) except KeyError: if not portdb.cpv_exists(mycpv): raise else: if myrepo is None: myrepo = _gen_valid_repo(metadata["repository"]) elif myrepo is None: myrepo = metadata.get("repository") if myrepo is not None: myrepo = _gen_valid_repo(metadata["repository"]) if metadata is not None and not portage.eapi_is_supported( metadata["EAPI"]): # Return early since otherwise we might produce invalid # results given that the EAPI is not supported. Also, # metadata is mostly useless in this case since it doesn't # contain essential things like SLOT. if return_location: return (None, None) return None # Sometimes we can't access SLOT or repository due to corruption. pkg = mycpv try: pkg.slot except AttributeError: pkg = _pkg_str(mycpv, metadata=metadata, repo=myrepo) cpv_slot_list = [pkg] mycp = pkg.cp locations = [] if pkg.repo in settings.repositories: for repo in settings.repositories[pkg.repo].masters + ( settings.repositories[pkg.repo], ): locations.append(os.path.join(repo.location, "profiles")) locations.extend(settings.profiles) locations.append( os.path.join(settings["PORTAGE_CONFIGROOT"], USER_CONFIG_PATH)) locations.reverse() pmasklists = [] for profile in locations: pmask_filename = os.path.join(profile, "package.mask") node = None for l, recursive_filename in grablines(pmask_filename, recursive=1, remember_source_file=True): if node is None or node[0] != recursive_filename: node = (recursive_filename, []) pmasklists.append(node) node[1].append(l) pmaskdict = settings._mask_manager._pmaskdict if mycp in pmaskdict: for x in pmaskdict[mycp]: if match_from_list(x, cpv_slot_list): x = x.without_repo for pmask in pmasklists: comment = "" comment_valid = -1 pmask_filename = pmask[0] for i in range(len(pmask[1])): l = pmask[1][i].strip() try: l_atom = Atom(l, allow_repo=True, allow_wildcard=True).without_repo except InvalidAtom: l_atom = None if l == "": comment = "" comment_valid = -1 elif l[0] == "#": comment += l + "\n" comment_valid = i + 1 elif l_atom == x: if comment_valid != i: comment = "" if return_location: return (comment, pmask_filename) return comment elif comment_valid != -1: # Apparently this comment applies to multiple masks, so # it remains valid until a blank line is encountered. comment_valid += 1 if return_location: return (None, None) return None
def _calc_changelog(ebuildpath, current, next): if ebuildpath == None or not os.path.exists(ebuildpath): return [] current = "-".join(catpkgsplit(current)[1:]) if current.endswith("-r0"): current = current[:-3] next = "-".join(catpkgsplit(next)[1:]) if next.endswith("-r0"): next = next[:-3] changelogdir = os.path.dirname(ebuildpath) changelogs = ["ChangeLog"] # ChangeLog-YYYY (see bug #389611) changelogs.extend(sorted((fn for fn in os.listdir(changelogdir) if fn.startswith("ChangeLog-")), reverse=True)) divisions = [] found_current = False for fn in changelogs: changelogpath = os.path.join(changelogdir, fn) try: with io.open( _unicode_encode(changelogpath, encoding=_encodings["fs"], errors="strict"), mode="r", encoding=_encodings["repo.content"], errors="replace", ) as f: changelog = f.read() except EnvironmentError: return [] for node in _find_changelog_tags(changelog): if node[0] == current: found_current = True break else: divisions.append(node) if found_current: break if not found_current: return [] # print 'XX from',current,'to',next # for div,text in divisions: print 'XX',div # skip entries for all revisions above the one we are about to emerge later_rev_index = None for i, node in enumerate(divisions): if node[0] == next: if later_rev_index is not None: first_node = divisions[later_rev_index] # Discard the later revision and the first ChangeLog entry # that follows it. We want to display all the entries after # that first entry, as discussed in bug #373009. trimmed_lines = [] iterator = iter(first_node[1]) for l in iterator: if not l: # end of the first entry that's discarded break first_node = (None, list(iterator)) divisions = [first_node] + divisions[later_rev_index + 1 :] break if node[0] is not None: later_rev_index = i output = [] prev_blank = False prev_rev = False for rev, lines in divisions: if rev is not None: if not (prev_blank or prev_rev): output.append("\n") output.append(bold("*" + rev) + "\n") prev_rev = True prev_blank = False if lines: prev_rev = False if not prev_blank: output.append("\n") for l in lines: output.append(l + "\n") output.append("\n") prev_blank = True return output
def getmaskingreason(mycpv, metadata=None, settings=None, portdb=None, return_location=False, myrepo=None): """ If specified, the myrepo argument is assumed to be valid. This should be a safe assumption since portdbapi methods always return valid repo names and valid "repository" metadata from aux_get. """ if settings is None: settings = portage.settings if portdb is None: portdb = portage.portdb mysplit = catpkgsplit(mycpv) if not mysplit: raise ValueError(_("invalid CPV: %s") % mycpv) if metadata is None: db_keys = list(portdb._aux_cache_keys) try: metadata = dict(zip(db_keys, portdb.aux_get(mycpv, db_keys, myrepo=myrepo))) except KeyError: if not portdb.cpv_exists(mycpv): raise else: if myrepo is None: myrepo = _gen_valid_repo(metadata["repository"]) elif myrepo is None: myrepo = metadata.get("repository") if myrepo is not None: myrepo = _gen_valid_repo(metadata["repository"]) if metadata is not None and not portage.eapi_is_supported(metadata["EAPI"]): # Return early since otherwise we might produce invalid # results given that the EAPI is not supported. Also, # metadata is mostly useless in this case since it doesn't # contain essential things like SLOT. if return_location: return (None, None) else: return None # Sometimes we can't access SLOT or repository due to corruption. pkg = mycpv if metadata is not None: pkg = "".join((mycpv, _slot_separator, metadata["SLOT"])) # At this point myrepo should be None, a valid name, or # Package.UNKNOWN_REPO which we ignore. if myrepo is not None and myrepo != Package.UNKNOWN_REPO: pkg = "".join((pkg, _repo_separator, myrepo)) cpv_slot_list = [pkg] mycp = mysplit[0] + "/" + mysplit[1] # XXX- This is a temporary duplicate of code from the config constructor. locations = [os.path.join(settings["PORTDIR"], "profiles")] locations.extend(settings.profiles) for ov in settings["PORTDIR_OVERLAY"].split(): profdir = os.path.join(normalize_path(ov), "profiles") if os.path.isdir(profdir): locations.append(profdir) locations.append(os.path.join(settings["PORTAGE_CONFIGROOT"], USER_CONFIG_PATH)) locations.reverse() pmasklists = [] for profile in locations: pmask_filename = os.path.join(profile, "package.mask") node = None for l, recursive_filename in grablines(pmask_filename, recursive=1, remember_source_file=True): if node is None or node[0] != recursive_filename: node = (recursive_filename, []) pmasklists.append(node) node[1].append(l) pmaskdict = settings._mask_manager._pmaskdict if mycp in pmaskdict: for x in pmaskdict[mycp]: if match_from_list(x, cpv_slot_list): x = x.without_repo for pmask in pmasklists: comment = "" comment_valid = -1 pmask_filename = pmask[0] for i in range(len(pmask[1])): l = pmask[1][i].strip() try: l_atom = Atom(l, allow_repo=True, allow_wildcard=True).without_repo except InvalidAtom: l_atom = None if l == "": comment = "" comment_valid = -1 elif l[0] == "#": comment += l + "\n" comment_valid = i + 1 elif l_atom == x: if comment_valid != i: comment = "" if return_location: return (comment, pmask_filename) else: return comment elif comment_valid != -1: # Apparently this comment applies to multiple masks, so # it remains valid until a blank line is encountered. comment_valid += 1 if return_location: return (None, None) else: return None
def getmaskingreason(mycpv, metadata=None, settings=None, portdb=None, return_location=False): if settings is None: settings = portage.settings if portdb is None: portdb = portage.portdb mysplit = catpkgsplit(mycpv) if not mysplit: raise ValueError(_("invalid CPV: %s") % mycpv) if metadata is None: db_keys = list(portdb._aux_cache_keys) try: metadata = dict(zip(db_keys, portdb.aux_get(mycpv, db_keys))) except KeyError: if not portdb.cpv_exists(mycpv): raise if metadata is None: # Can't access SLOT due to corruption. cpv_slot_list = [mycpv] else: cpv_slot_list = ["%s:%s" % (mycpv, metadata["SLOT"])] mycp=mysplit[0]+"/"+mysplit[1] # XXX- This is a temporary duplicate of code from the config constructor. locations = [os.path.join(settings["PORTDIR"], "profiles")] locations.extend(settings.profiles) for ov in settings["PORTDIR_OVERLAY"].split(): profdir = os.path.join(normalize_path(ov), "profiles") if os.path.isdir(profdir): locations.append(profdir) locations.append(os.path.join(settings["PORTAGE_CONFIGROOT"], USER_CONFIG_PATH)) locations.reverse() pmasklists = [(x, grablines(os.path.join(x, "package.mask"), recursive=1)) for x in locations] pmaskdict = settings._mask_manager._pmaskdict if mycp in pmaskdict: for x in pmaskdict[mycp]: if match_from_list(x, cpv_slot_list): for pmask in pmasklists: comment = "" comment_valid = -1 pmask_filename = os.path.join(pmask[0], "package.mask") for i in range(len(pmask[1])): l = pmask[1][i].strip() if l == "": comment = "" comment_valid = -1 elif l[0] == "#": comment += (l+"\n") comment_valid = i + 1 elif l == x: if comment_valid != i: comment = "" if return_location: return (comment, pmask_filename) else: return comment elif comment_valid != -1: # Apparently this comment applies to muliple masks, so # it remains valid until a blank line is encountered. comment_valid += 1 if return_location: return (None, None) else: return None
def getmaskingreason(mycpv, metadata=None, settings=None, portdb=None, return_location=False, myrepo=None): """ If specified, the myrepo argument is assumed to be valid. This should be a safe assumption since portdbapi methods always return valid repo names and valid "repository" metadata from aux_get. """ if settings is None: settings = portage.settings if portdb is None: portdb = portage.portdb mysplit = catpkgsplit(mycpv) if not mysplit: raise ValueError(_("invalid CPV: %s") % mycpv) if metadata is None: db_keys = list(portdb._aux_cache_keys) try: metadata = dict( zip(db_keys, portdb.aux_get(mycpv, db_keys, myrepo=myrepo))) except KeyError: if not portdb.cpv_exists(mycpv): raise else: if myrepo is None: myrepo = _gen_valid_repo(metadata["repository"]) elif myrepo is None: myrepo = metadata.get("repository") if myrepo is not None: myrepo = _gen_valid_repo(metadata["repository"]) if metadata is not None and \ not portage.eapi_is_supported(metadata["EAPI"]): # Return early since otherwise we might produce invalid # results given that the EAPI is not supported. Also, # metadata is mostly useless in this case since it doesn't # contain essential things like SLOT. if return_location: return (None, None) else: return None # Sometimes we can't access SLOT or repository due to corruption. pkg = mycpv if metadata is not None: pkg = "".join((mycpv, _slot_separator, metadata["SLOT"])) # At this point myrepo should be None, a valid name, or # Package.UNKNOWN_REPO which we ignore. if myrepo is not None and myrepo != Package.UNKNOWN_REPO: pkg = "".join((pkg, _repo_separator, myrepo)) cpv_slot_list = [pkg] mycp = mysplit[0] + "/" + mysplit[1] # XXX- This is a temporary duplicate of code from the config constructor. locations = [os.path.join(settings["PORTDIR"], "profiles")] locations.extend(settings.profiles) for ov in settings["PORTDIR_OVERLAY"].split(): profdir = os.path.join(normalize_path(ov), "profiles") if os.path.isdir(profdir): locations.append(profdir) locations.append( os.path.join(settings["PORTAGE_CONFIGROOT"], USER_CONFIG_PATH)) locations.reverse() pmasklists = [] for profile in locations: pmask_filename = os.path.join(profile, "package.mask") pmasklists.append( (pmask_filename, grablines(pmask_filename, recursive=1))) pmaskdict = settings._mask_manager._pmaskdict if mycp in pmaskdict: for x in pmaskdict[mycp]: if match_from_list(x, cpv_slot_list): x = x.without_repo for pmask in pmasklists: comment = "" comment_valid = -1 pmask_filename = pmask[0] for i in range(len(pmask[1])): l = pmask[1][i].strip() try: l_atom = Atom(l, allow_repo=True, allow_wildcard=True).without_repo except InvalidAtom: l_atom = None if l == "": comment = "" comment_valid = -1 elif l[0] == "#": comment += (l + "\n") comment_valid = i + 1 elif l_atom == x: if comment_valid != i: comment = "" if return_location: return (comment, pmask_filename) else: return comment elif comment_valid != -1: # Apparently this comment applies to multiple masks, so # it remains valid until a blank line is encountered. comment_valid += 1 if return_location: return (None, None) else: return None
def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None): """ Takes an unreduced and reduced deplist and removes satisfied dependencies. Returned deplist contains steps that must be taken to satisfy dependencies. """ if trees is None: trees = portage.db writemsg("ZapDeps -- %s\n" % (use_binaries), 2) if not reduced or unreduced == ["||"] or dep_eval(reduced): return [] if unreduced[0] != "||": unresolved = [] for x, satisfied in zip(unreduced, reduced): if isinstance(x, list): unresolved += dep_zapdeps(x, satisfied, myroot, use_binaries=use_binaries, trees=trees) elif not satisfied: unresolved.append(x) return unresolved # We're at a ( || atom ... ) type level and need to make a choice deps = unreduced[1:] satisfieds = reduced[1:] # Our preference order is for an the first item that: # a) contains all unmasked packages with the same key as installed packages # b) contains all unmasked packages # c) contains masked installed packages # d) is the first item preferred_installed = [] preferred_in_graph = [] preferred_any_slot = [] preferred_non_installed = [] unsat_use_in_graph = [] unsat_use_installed = [] unsat_use_non_installed = [] other = [] # unsat_use_* must come after preferred_non_installed # for correct ordering in cases like || ( foo[a] foo[b] ). choice_bins = ( preferred_in_graph, preferred_installed, preferred_any_slot, preferred_non_installed, unsat_use_in_graph, unsat_use_installed, unsat_use_non_installed, other, ) # Alias the trees we'll be checking availability against parent = trees[myroot].get("parent") priority = trees[myroot].get("priority") graph_db = trees[myroot].get("graph_db") vardb = None if "vartree" in trees[myroot]: vardb = trees[myroot]["vartree"].dbapi if use_binaries: mydbapi = trees[myroot]["bintree"].dbapi else: mydbapi = trees[myroot]["porttree"].dbapi # Sort the deps into installed, not installed but already # in the graph and other, not installed and not in the graph # and other, with values of [[required_atom], availablility] for x, satisfied in zip(deps, satisfieds): if isinstance(x, list): atoms = dep_zapdeps(x, satisfied, myroot, use_binaries=use_binaries, trees=trees) else: atoms = [x] if vardb is None: # When called by repoman, we can simply return the first choice # because dep_eval() handles preference selection. return atoms all_available = True all_use_satisfied = True slot_map = {} cp_map = {} for atom in atoms: if atom.blocker: continue # Ignore USE dependencies here since we don't want USE # settings to adversely affect || preference evaluation. avail_pkg = mydbapi.match(atom.without_use) if avail_pkg: avail_pkg = avail_pkg[-1] # highest (ascending order) avail_slot = Atom("%s:%s" % (atom.cp, mydbapi.aux_get(avail_pkg, ["SLOT"])[0])) if not avail_pkg: all_available = False all_use_satisfied = False break if atom.use: avail_pkg_use = mydbapi.match(atom) if not avail_pkg_use: all_use_satisfied = False else: # highest (ascending order) avail_pkg_use = avail_pkg_use[-1] if avail_pkg_use != avail_pkg: avail_pkg = avail_pkg_use avail_slot = Atom("%s:%s" % (atom.cp, mydbapi.aux_get(avail_pkg, ["SLOT"])[0])) slot_map[avail_slot] = avail_pkg pkg_cp = cpv_getkey(avail_pkg) highest_cpv = cp_map.get(pkg_cp) if highest_cpv is None or \ pkgcmp(catpkgsplit(avail_pkg)[1:], catpkgsplit(highest_cpv)[1:]) > 0: cp_map[pkg_cp] = avail_pkg this_choice = (atoms, slot_map, cp_map, all_available) if all_available: # The "all installed" criterion is not version or slot specific. # If any version of a package is already in the graph then we # assume that it is preferred over other possible packages choices. all_installed = True for atom in set(Atom(atom.cp) for atom in atoms \ if not atom.blocker): # New-style virtuals have zero cost to install. if not vardb.match(atom) and not atom.startswith("virtual/"): all_installed = False break all_installed_slots = False if all_installed: all_installed_slots = True for slot_atom in slot_map: # New-style virtuals have zero cost to install. if not vardb.match(slot_atom) and \ not slot_atom.startswith("virtual/"): all_installed_slots = False break if graph_db is None: if all_use_satisfied: if all_installed: if all_installed_slots: preferred_installed.append(this_choice) else: preferred_any_slot.append(this_choice) else: preferred_non_installed.append(this_choice) else: if all_installed_slots: unsat_use_installed.append(this_choice) else: unsat_use_non_installed.append(this_choice) else: all_in_graph = True for slot_atom in slot_map: # New-style virtuals have zero cost to install. if not graph_db.match(slot_atom) and \ not slot_atom.startswith("virtual/"): all_in_graph = False break circular_atom = None if all_in_graph: if parent is None or priority is None: pass elif priority.buildtime: # Check if the atom would result in a direct circular # dependency and try to avoid that if it seems likely # to be unresolvable. This is only relevant for # buildtime deps that aren't already satisfied by an # installed package. cpv_slot_list = [parent] for atom in atoms: if atom.blocker: continue if vardb.match(atom): # If the atom is satisfied by an installed # version then it's not a circular dep. continue if atom.cp != parent.cp: continue if match_from_list(atom, cpv_slot_list): circular_atom = atom break if circular_atom is not None: other.append(this_choice) else: if all_use_satisfied: if all_in_graph: preferred_in_graph.append(this_choice) elif all_installed: if all_installed_slots: preferred_installed.append(this_choice) else: preferred_any_slot.append(this_choice) else: preferred_non_installed.append(this_choice) else: if all_in_graph: unsat_use_in_graph.append(this_choice) elif all_installed_slots: unsat_use_installed.append(this_choice) else: unsat_use_non_installed.append(this_choice) else: other.append(this_choice) # Prefer choices which contain upgrades to higher slots. This helps # for deps such as || ( foo:1 foo:2 ), where we want to prefer the # atom which matches the higher version rather than the atom furthest # to the left. Sorting is done separately for each of choice_bins, so # as not to interfere with the ordering of the bins. Because of the # bin separation, the main function of this code is to allow # --depclean to remove old slots (rather than to pull in new slots). for choices in choice_bins: if len(choices) < 2: continue for choice_1 in choices[1:]: atoms_1, slot_map_1, cp_map_1, all_available_1 = choice_1 cps = set(cp_map_1) for choice_2 in choices: if choice_1 is choice_2: # choice_1 will not be promoted, so move on break atoms_2, slot_map_2, cp_map_2, all_available_2 = choice_2 intersecting_cps = cps.intersection(cp_map_2) if not intersecting_cps: continue has_upgrade = False has_downgrade = False for cp in intersecting_cps: version_1 = cp_map_1[cp] version_2 = cp_map_2[cp] difference = pkgcmp(catpkgsplit(version_1)[1:], catpkgsplit(version_2)[1:]) if difference != 0: if difference > 0: has_upgrade = True else: has_downgrade = True break if has_upgrade and not has_downgrade: # promote choice_1 in front of choice_2 choices.remove(choice_1) index_2 = choices.index(choice_2) choices.insert(index_2, choice_1) break for allow_masked in (False, True): for choices in choice_bins: for atoms, slot_map, cp_map, all_available in choices: if all_available or allow_masked: return atoms assert(False) # This point should not be reachable
def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None): """ Takes an unreduced and reduced deplist and removes satisfied dependencies. Returned deplist contains steps that must be taken to satisfy dependencies. """ if trees is None: trees = portage.db writemsg("ZapDeps -- %s\n" % (use_binaries), 2) if not reduced or unreduced == ["||"] or dep_eval(reduced): return [] if unreduced[0] != "||": unresolved = [] for x, satisfied in zip(unreduced, reduced): if isinstance(x, list): unresolved += dep_zapdeps(x, satisfied, myroot, use_binaries=use_binaries, trees=trees) elif not satisfied: unresolved.append(x) return unresolved # We're at a ( || atom ... ) type level and need to make a choice deps = unreduced[1:] satisfieds = reduced[1:] # Our preference order is for an the first item that: # a) contains all unmasked packages with the same key as installed packages # b) contains all unmasked packages # c) contains masked installed packages # d) is the first item preferred_installed = [] preferred_in_graph = [] preferred_any_slot = [] preferred_non_installed = [] unsat_use_in_graph = [] unsat_use_installed = [] unsat_use_non_installed = [] other = [] # unsat_use_* must come after preferred_non_installed # for correct ordering in cases like || ( foo[a] foo[b] ). choice_bins = ( preferred_in_graph, preferred_installed, preferred_any_slot, preferred_non_installed, unsat_use_in_graph, unsat_use_installed, unsat_use_non_installed, other, ) # Alias the trees we'll be checking availability against parent = trees[myroot].get("parent") priority = trees[myroot].get("priority") graph_db = trees[myroot].get("graph_db") vardb = None if "vartree" in trees[myroot]: vardb = trees[myroot]["vartree"].dbapi if use_binaries: mydbapi = trees[myroot]["bintree"].dbapi else: mydbapi = trees[myroot]["porttree"].dbapi # Sort the deps into installed, not installed but already # in the graph and other, not installed and not in the graph # and other, with values of [[required_atom], availablility] for x, satisfied in zip(deps, satisfieds): if isinstance(x, list): atoms = dep_zapdeps(x, satisfied, myroot, use_binaries=use_binaries, trees=trees) else: atoms = [x] if vardb is None: # When called by repoman, we can simply return the first choice # because dep_eval() handles preference selection. return atoms all_available = True all_use_satisfied = True slot_map = {} cp_map = {} for atom in atoms: if atom.blocker: continue # Ignore USE dependencies here since we don't want USE # settings to adversely affect || preference evaluation. avail_pkg = mydbapi.match(atom.without_use) if avail_pkg: avail_pkg = avail_pkg[-1] # highest (ascending order) avail_slot = Atom( "%s:%s" % (atom.cp, mydbapi.aux_get(avail_pkg, ["SLOT"])[0])) if not avail_pkg: all_available = False all_use_satisfied = False break if atom.use: avail_pkg_use = mydbapi.match(atom) if not avail_pkg_use: all_use_satisfied = False else: # highest (ascending order) avail_pkg_use = avail_pkg_use[-1] if avail_pkg_use != avail_pkg: avail_pkg = avail_pkg_use avail_slot = Atom( "%s:%s" % (atom.cp, mydbapi.aux_get(avail_pkg, ["SLOT"])[0])) slot_map[avail_slot] = avail_pkg pkg_cp = cpv_getkey(avail_pkg) highest_cpv = cp_map.get(pkg_cp) if highest_cpv is None or \ pkgcmp(catpkgsplit(avail_pkg)[1:], catpkgsplit(highest_cpv)[1:]) > 0: cp_map[pkg_cp] = avail_pkg this_choice = (atoms, slot_map, cp_map, all_available) if all_available: # The "all installed" criterion is not version or slot specific. # If any version of a package is already in the graph then we # assume that it is preferred over other possible packages choices. all_installed = True for atom in set(Atom(atom.cp) for atom in atoms \ if not atom.blocker): # New-style virtuals have zero cost to install. if not vardb.match(atom) and not atom.startswith("virtual/"): all_installed = False break all_installed_slots = False if all_installed: all_installed_slots = True for slot_atom in slot_map: # New-style virtuals have zero cost to install. if not vardb.match(slot_atom) and \ not slot_atom.startswith("virtual/"): all_installed_slots = False break if graph_db is None: if all_use_satisfied: if all_installed: if all_installed_slots: preferred_installed.append(this_choice) else: preferred_any_slot.append(this_choice) else: preferred_non_installed.append(this_choice) else: if all_installed_slots: unsat_use_installed.append(this_choice) else: unsat_use_non_installed.append(this_choice) else: all_in_graph = True for slot_atom in slot_map: # New-style virtuals have zero cost to install. if not graph_db.match(slot_atom) and \ not slot_atom.startswith("virtual/"): all_in_graph = False break circular_atom = None if all_in_graph: if parent is None or priority is None: pass elif priority.buildtime: # Check if the atom would result in a direct circular # dependency and try to avoid that if it seems likely # to be unresolvable. This is only relevant for # buildtime deps that aren't already satisfied by an # installed package. cpv_slot_list = [parent] for atom in atoms: if atom.blocker: continue if vardb.match(atom): # If the atom is satisfied by an installed # version then it's not a circular dep. continue if atom.cp != parent.cp: continue if match_from_list(atom, cpv_slot_list): circular_atom = atom break if circular_atom is not None: other.append(this_choice) else: if all_use_satisfied: if all_in_graph: preferred_in_graph.append(this_choice) elif all_installed: if all_installed_slots: preferred_installed.append(this_choice) else: preferred_any_slot.append(this_choice) else: preferred_non_installed.append(this_choice) else: if all_in_graph: unsat_use_in_graph.append(this_choice) elif all_installed_slots: unsat_use_installed.append(this_choice) else: unsat_use_non_installed.append(this_choice) else: other.append(this_choice) # Prefer choices which contain upgrades to higher slots. This helps # for deps such as || ( foo:1 foo:2 ), where we want to prefer the # atom which matches the higher version rather than the atom furthest # to the left. Sorting is done separately for each of choice_bins, so # as not to interfere with the ordering of the bins. Because of the # bin separation, the main function of this code is to allow # --depclean to remove old slots (rather than to pull in new slots). for choices in choice_bins: if len(choices) < 2: continue for choice_1 in choices[1:]: atoms_1, slot_map_1, cp_map_1, all_available_1 = choice_1 cps = set(cp_map_1) for choice_2 in choices: if choice_1 is choice_2: # choice_1 will not be promoted, so move on break atoms_2, slot_map_2, cp_map_2, all_available_2 = choice_2 intersecting_cps = cps.intersection(cp_map_2) if not intersecting_cps: continue has_upgrade = False has_downgrade = False for cp in intersecting_cps: version_1 = cp_map_1[cp] version_2 = cp_map_2[cp] difference = pkgcmp( catpkgsplit(version_1)[1:], catpkgsplit(version_2)[1:]) if difference != 0: if difference > 0: has_upgrade = True else: has_downgrade = True break if has_upgrade and not has_downgrade: # promote choice_1 in front of choice_2 choices.remove(choice_1) index_2 = choices.index(choice_2) choices.insert(index_2, choice_1) break for allow_masked in (False, True): for choices in choice_bins: for atoms, slot_map, cp_map, all_available in choices: if all_available or allow_masked: return atoms assert (False) # This point should not be reachable
def category(self): return catpkgsplit(self.cpv)[0]
def version(self): return catpkgsplit(self.cpv)[2]
def name(self): return catpkgsplit(self.cpv)[1]
def getmaskingstatus(mycpv, settings=None, portdb=None): if settings is None: settings = config(clone=portage.settings) if portdb is None: portdb = portage.portdb metadata = None installed = False if not isinstance(mycpv, basestring): # emerge passed in a Package instance pkg = mycpv mycpv = pkg.cpv metadata = pkg.metadata installed = pkg.installed mysplit = catpkgsplit(mycpv) if not mysplit: raise ValueError(_("invalid CPV: %s") % mycpv) if metadata is None: db_keys = list(portdb._aux_cache_keys) try: metadata = dict(zip(db_keys, portdb.aux_get(mycpv, db_keys))) except KeyError: if not portdb.cpv_exists(mycpv): raise return ["corruption"] if "?" in metadata["LICENSE"]: settings.setcpv(mycpv, mydb=metadata) metadata["USE"] = settings["PORTAGE_USE"] else: metadata["USE"] = "" rValue = [] # profile checking if settings._getProfileMaskAtom(mycpv, metadata): rValue.append("profile") # package.mask checking if settings._getMaskAtom(mycpv, metadata): rValue.append("package.mask") # keywords checking eapi = metadata["EAPI"] mygroups = settings._getKeywords(mycpv, metadata) licenses = metadata["LICENSE"] properties = metadata["PROPERTIES"] if eapi.startswith("-"): eapi = eapi[1:] if not eapi_is_supported(eapi): return ["EAPI %s" % eapi] elif _eapi_is_deprecated(eapi) and not installed: return ["EAPI %s" % eapi] egroups = settings.configdict["backupenv"].get("ACCEPT_KEYWORDS", "").split() pgroups = settings["ACCEPT_KEYWORDS"].split() myarch = settings["ARCH"] if pgroups and myarch not in pgroups: """For operating systems other than Linux, ARCH is not necessarily a valid keyword.""" myarch = pgroups[0].lstrip("~") cp = cpv_getkey(mycpv) pkgdict = settings.pkeywordsdict.get(cp) matches = False if pkgdict: cpv_slot_list = ["%s:%s" % (mycpv, metadata["SLOT"])] for atom, pkgkeywords in pkgdict.items(): if match_from_list(atom, cpv_slot_list): matches = True pgroups.extend(pkgkeywords) if matches or egroups: pgroups.extend(egroups) inc_pgroups = set() for x in pgroups: if x.startswith("-"): if x == "-*": inc_pgroups.clear() else: inc_pgroups.discard(x[1:]) else: inc_pgroups.add(x) pgroups = inc_pgroups del inc_pgroups kmask = "missing" if '**' in pgroups: kmask = None else: for keyword in pgroups: if keyword in mygroups: kmask = None break if kmask: for gp in mygroups: if gp == "*": kmask = None break elif gp == "-" + myarch and myarch in pgroups: kmask = "-" + myarch break elif gp == "~" + myarch and myarch in pgroups: kmask = "~" + myarch break try: missing_licenses = settings._getMissingLicenses(mycpv, metadata) if missing_licenses: allowed_tokens = set(["||", "(", ")"]) allowed_tokens.update(missing_licenses) license_split = licenses.split() license_split = [x for x in license_split \ if x in allowed_tokens] msg = license_split[:] msg.append("license(s)") rValue.append(" ".join(msg)) except portage.exception.InvalidDependString as e: rValue.append("LICENSE: " + str(e)) try: missing_properties = settings._getMissingProperties(mycpv, metadata) if missing_properties: allowed_tokens = set(["||", "(", ")"]) allowed_tokens.update(missing_properties) properties_split = properties.split() properties_split = [x for x in properties_split \ if x in allowed_tokens] msg = properties_split[:] msg.append("properties") rValue.append(" ".join(msg)) except portage.exception.InvalidDependString as e: rValue.append("PROPERTIES: " + str(e)) # Only show KEYWORDS masks for installed packages # if they're not masked for any other reason. if kmask and (not installed or not rValue): rValue.append(kmask + " keyword") return rValue
def revision(self): my_cpv = catpkgsplit(self.cpv) return 0 if len(my_cpv) == 3 else int(my_cpv[3][1:])
def _getmaskingstatus(mycpv, settings, portdb, myrepo=None): metadata = None installed = False if not isinstance(mycpv, basestring): # emerge passed in a Package instance pkg = mycpv mycpv = pkg.cpv metadata = pkg.metadata installed = pkg.installed mysplit = catpkgsplit(mycpv) if not mysplit: raise ValueError(_("invalid CPV: %s") % mycpv) if metadata is None: db_keys = list(portdb._aux_cache_keys) try: metadata = dict( zip(db_keys, portdb.aux_get(mycpv, db_keys, myrepo=myrepo))) except KeyError: if not portdb.cpv_exists(mycpv): raise return [_MaskReason("corruption", "corruption")] if "?" in metadata["LICENSE"]: settings.setcpv(mycpv, mydb=metadata) metadata["USE"] = settings["PORTAGE_USE"] else: metadata["USE"] = "" rValue = [] # package.mask checking if settings._getMaskAtom(mycpv, metadata): rValue.append( _MaskReason("package.mask", "package.mask", _UnmaskHint("p_mask", None))) # keywords checking eapi = metadata["EAPI"] mygroups = settings._getKeywords(mycpv, metadata) licenses = metadata["LICENSE"] properties = metadata["PROPERTIES"] if eapi.startswith("-"): eapi = eapi[1:] if not eapi_is_supported(eapi): return [_MaskReason("EAPI", "EAPI %s" % eapi)] elif _eapi_is_deprecated(eapi) and not installed: return [_MaskReason("EAPI", "EAPI %s" % eapi)] egroups = settings.configdict["backupenv"].get("ACCEPT_KEYWORDS", "").split() global_accept_keywords = settings.get("ACCEPT_KEYWORDS", "") pgroups = global_accept_keywords.split() myarch = settings["ARCH"] if pgroups and myarch not in pgroups: """For operating systems other than Linux, ARCH is not necessarily a valid keyword.""" myarch = pgroups[0].lstrip("~") # NOTE: This logic is copied from KeywordsManager.getMissingKeywords(). unmaskgroups = settings._keywords_manager.getPKeywords( mycpv, metadata["SLOT"], metadata["repository"], global_accept_keywords) pgroups.extend(unmaskgroups) if unmaskgroups or egroups: pgroups = settings._keywords_manager._getEgroups(egroups, pgroups) else: pgroups = set(pgroups) kmask = "missing" kmask_hint = None if '**' in pgroups: kmask = None else: for keyword in pgroups: if keyword in mygroups: kmask = None break if kmask: for gp in mygroups: if gp == "*": kmask = None break elif gp == "-" + myarch and myarch in pgroups: kmask = "-" + myarch break elif gp == "~" + myarch and myarch in pgroups: kmask = "~" + myarch kmask_hint = _UnmaskHint("unstable keyword", kmask) break if kmask == "missing": kmask_hint = _UnmaskHint("unstable keyword", "**") try: missing_licenses = settings._getMissingLicenses(mycpv, metadata) if missing_licenses: allowed_tokens = set(["||", "(", ")"]) allowed_tokens.update(missing_licenses) license_split = licenses.split() license_split = [x for x in license_split \ if x in allowed_tokens] msg = license_split[:] msg.append("license(s)") rValue.append( _MaskReason("LICENSE", " ".join(msg), _UnmaskHint("license", set(missing_licenses)))) except portage.exception.InvalidDependString as e: rValue.append(_MaskReason("invalid", "LICENSE: " + str(e))) try: missing_properties = settings._getMissingProperties(mycpv, metadata) if missing_properties: allowed_tokens = set(["||", "(", ")"]) allowed_tokens.update(missing_properties) properties_split = properties.split() properties_split = [x for x in properties_split \ if x in allowed_tokens] msg = properties_split[:] msg.append("properties") rValue.append(_MaskReason("PROPERTIES", " ".join(msg))) except portage.exception.InvalidDependString as e: rValue.append(_MaskReason("invalid", "PROPERTIES: " + str(e))) # Only show KEYWORDS masks for installed packages # if they're not masked for any other reason. if kmask and (not installed or not rValue): rValue.append( _MaskReason("KEYWORDS", kmask + " keyword", unmask_hint=kmask_hint)) return rValue
def _calc_changelog(ebuildpath,current,next): # pylint: disable=redefined-builtin if ebuildpath == None or not os.path.exists(ebuildpath): return [] current = '-'.join(catpkgsplit(current)[1:]) if current.endswith('-r0'): current = current[:-3] next = '-'.join(catpkgsplit(next)[1:]) if next.endswith('-r0'): next = next[:-3] changelogdir = os.path.dirname(ebuildpath) changelogs = ['ChangeLog'] # ChangeLog-YYYY (see bug #389611) changelogs.extend(sorted((fn for fn in os.listdir(changelogdir) if fn.startswith('ChangeLog-')), reverse=True)) divisions = [] found_current = False for fn in changelogs: changelogpath = os.path.join(changelogdir, fn) try: with io.open(_unicode_encode(changelogpath, encoding=_encodings['fs'], errors='strict'), mode='r', encoding=_encodings['repo.content'], errors='replace') as f: changelog = f.read() except EnvironmentError: return [] for node in _find_changelog_tags(changelog): if node[0] == current: found_current = True break else: divisions.append(node) if found_current: break if not found_current: return [] #print 'XX from',current,'to',next #for div,text in divisions: print 'XX',div # skip entries for all revisions above the one we are about to emerge later_rev_index = None for i, node in enumerate(divisions): if node[0] == next: if later_rev_index is not None: first_node = divisions[later_rev_index] # Discard the later revision and the first ChangeLog entry # that follows it. We want to display all the entries after # that first entry, as discussed in bug #373009. trimmed_lines = [] iterator = iter(first_node[1]) for l in iterator: if not l: # end of the first entry that's discarded break first_node = (None, list(iterator)) divisions = [first_node] + divisions[later_rev_index+1:] break if node[0] is not None: later_rev_index = i output = [] prev_blank = False prev_rev = False for rev, lines in divisions: if rev is not None: if not (prev_blank or prev_rev): output.append("\n") output.append(bold('*' + rev) + '\n') prev_rev = True prev_blank = False if lines: prev_rev = False if not prev_blank: output.append("\n") for l in lines: output.append(l + "\n") output.append("\n") prev_blank = True return output
def version(self): _, _, v, r = catpkgsplit(self.cpv) return f'{v}-{r}'