Example #1
0
	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)
Example #3
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
Example #5
0
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
Example #7
0
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
Example #8
0
 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
Example #9
0
    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)
Example #10
0
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
Example #11
0
	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
Example #12
0
 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
Example #13
0
	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
Example #14
0
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:])
Example #15
0
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:])
Example #16
0
 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
Example #17
0
	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
Example #18
0
	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)
Example #19
0
	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]
Example #20
0
    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]
Example #21
0
	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([])
Example #23
0
 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([])
Example #24
0
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
Example #25
0
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")
Example #26
0
    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
Example #27
0
    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
Example #28
0
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 _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
Example #30
0
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 __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
Example #34
0
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
Example #35
0
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
Example #36
0
    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
Example #37
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
Example #38
0
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
Example #39
0
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
Example #40
0
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
Example #41
0
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
Example #42
0
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
Example #44
0
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
Example #45
0
 def category(self):
     return catpkgsplit(self.cpv)[0]
Example #46
0
 def version(self):
     return catpkgsplit(self.cpv)[2]
Example #47
0
 def name(self):
     return catpkgsplit(self.cpv)[1]
Example #48
0
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
Example #49
0
 def revision(self):
     my_cpv = catpkgsplit(self.cpv)
     return 0 if len(my_cpv) == 3 else int(my_cpv[3][1:])
Example #50
0
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
Example #52
0
 def version(self):
     _, _, v, r = catpkgsplit(self.cpv)
     return f'{v}-{r}'