Example #1
0
    def getUseMask(self, pkg=None, stable=None):
        if pkg is None:
            return frozenset(stack_lists(self._usemask_list, incremental=True))

        slot = None
        cp = getattr(pkg, "cp", None)
        if cp is None:
            slot = dep_getslot(pkg)
            repo = dep_getrepo(pkg)
            pkg = _pkg_str(remove_slot(pkg), slot=slot, repo=repo)
            cp = pkg.cp

        if stable is None:
            stable = self._isStable(pkg)

        usemask = []

        if hasattr(pkg, "repo") and pkg.repo != Package.UNKNOWN_REPO:
            repos = []
            try:
                repos.extend(repo.name
                             for repo in self.repositories[pkg.repo].masters)
            except KeyError:
                pass
            repos.append(pkg.repo)
            for repo in repos:
                usemask.append(self._repo_usemask_dict.get(repo, {}))
                if stable:
                    usemask.append(self._repo_usestablemask_dict.get(repo, {}))
                cpdict = self._repo_pusemask_dict.get(repo, {}).get(cp)
                if cpdict:
                    pkg_usemask = ordered_by_atom_specificity(cpdict, pkg)
                    if pkg_usemask:
                        usemask.extend(pkg_usemask)
                if stable:
                    cpdict = self._repo_pusestablemask_dict.get(repo,
                                                                {}).get(cp)
                    if cpdict:
                        pkg_usemask = ordered_by_atom_specificity(cpdict, pkg)
                        if pkg_usemask:
                            usemask.extend(pkg_usemask)

        for i, pusemask_dict in enumerate(self._pusemask_list):
            if self._usemask_list[i]:
                usemask.append(self._usemask_list[i])
            if stable and self._usestablemask_list[i]:
                usemask.append(self._usestablemask_list[i])
            cpdict = pusemask_dict.get(cp)
            if cpdict:
                pkg_usemask = ordered_by_atom_specificity(cpdict, pkg)
                if pkg_usemask:
                    usemask.extend(pkg_usemask)
            if stable:
                cpdict = self._pusestablemask_list[i].get(cp)
                if cpdict:
                    pkg_usemask = ordered_by_atom_specificity(cpdict, pkg)
                    if pkg_usemask:
                        usemask.extend(pkg_usemask)

        return frozenset(stack_lists(usemask, incremental=True))
Example #2
0
	def getUseForce(self, pkg=None):
		if pkg is None:
			return frozenset(stack_lists(
				self._useforce_list, incremental=True))

		cp = getattr(pkg, "cp", None)
		if cp is None:
			cp = cpv_getkey(remove_slot(pkg))
		useforce = []
		if hasattr(pkg, "repo") and pkg.repo != Package.UNKNOWN_REPO:
			repos = []
			try:
				repos.extend(repo.name for repo in
					self.repositories[pkg.repo].masters)
			except KeyError:
				pass
			repos.append(pkg.repo)
			for repo in repos:
				useforce.append(self._repo_useforce_dict.get(repo, {}))
				cpdict = self._repo_puseforce_dict.get(repo, {}).get(cp)
				if cpdict:
					pkg_useforce = ordered_by_atom_specificity(cpdict, pkg)
					if pkg_useforce:
						useforce.extend(pkg_useforce)
		for i, puseforce_dict in enumerate(self._puseforce_list):
			if self._useforce_list[i]:
				useforce.append(self._useforce_list[i])
			cpdict = puseforce_dict.get(cp)
			if cpdict:
				pkg_useforce = ordered_by_atom_specificity(cpdict, pkg)
				if pkg_useforce:
					useforce.extend(pkg_useforce)
		return frozenset(stack_lists(useforce, incremental=True))
Example #3
0
	def getUseMask(self, pkg=None, stable=None):
		if pkg is None:
			return frozenset(stack_lists(
				self._usemask_list, incremental=True))

		slot = None
		cp = getattr(pkg, "cp", None)
		if cp is None:
			slot = dep_getslot(pkg)
			repo = dep_getrepo(pkg)
			pkg = _pkg_str(remove_slot(pkg), slot=slot, repo=repo)
			cp = pkg.cp

		if stable is None:
			stable = self._isStable(pkg)

		usemask = []

		if hasattr(pkg, "repo") and pkg.repo != Package.UNKNOWN_REPO:
			repos = []
			try:
				repos.extend(repo.name for repo in
					self.repositories[pkg.repo].masters)
			except KeyError:
				pass
			repos.append(pkg.repo)
			for repo in repos:
				usemask.append(self._repo_usemask_dict.get(repo, {}))
				if stable:
					usemask.append(self._repo_usestablemask_dict.get(repo, {}))
				cpdict = self._repo_pusemask_dict.get(repo, {}).get(cp)
				if cpdict:
					pkg_usemask = ordered_by_atom_specificity(cpdict, pkg)
					if pkg_usemask:
						usemask.extend(pkg_usemask)
				if stable:
					cpdict = self._repo_pusestablemask_dict.get(repo, {}).get(cp)
					if cpdict:
						pkg_usemask = ordered_by_atom_specificity(cpdict, pkg)
						if pkg_usemask:
							usemask.extend(pkg_usemask)

		for i, pusemask_dict in enumerate(self._pusemask_list):
			if self._usemask_list[i]:
				usemask.append(self._usemask_list[i])
			if stable and self._usestablemask_list[i]:
				usemask.append(self._usestablemask_list[i])
			cpdict = pusemask_dict.get(cp)
			if cpdict:
				pkg_usemask = ordered_by_atom_specificity(cpdict, pkg)
				if pkg_usemask:
					usemask.extend(pkg_usemask)
			if stable:
				cpdict = self._pusestablemask_list[i].get(cp)
				if cpdict:
					pkg_usemask = ordered_by_atom_specificity(cpdict, pkg)
					if pkg_usemask:
						usemask.extend(pkg_usemask)

		return frozenset(stack_lists(usemask, incremental=True))
Example #4
0
    def getUseAliases(self, pkg):
        if hasattr(pkg, "eapi") and not eapi_has_use_aliases(pkg.eapi):
            return {}

        cp = getattr(pkg, "cp", None)
        if cp is None:
            slot = dep_getslot(pkg)
            repo = dep_getrepo(pkg)
            pkg = _pkg_str(remove_slot(pkg), slot=slot, repo=repo)
            cp = pkg.cp

        usealiases = {}

        if hasattr(pkg, "repo") and pkg.repo != Package.UNKNOWN_REPO:
            repos = []
            try:
                repos.extend(repo.name
                             for repo in self.repositories[pkg.repo].masters)
            except KeyError:
                pass
            repos.append(pkg.repo)
            for repo in repos:
                usealiases_dict = self._repo_usealiases_dict.get(repo, {})
                for real_flag, aliases in usealiases_dict.items():
                    for alias in aliases:
                        if any(alias in v for k, v in usealiases.items()
                               if k != real_flag):
                            writemsg(
                                _("--- Duplicated USE flag alias for '%s%s%s': '%s'\n"
                                  ) %
                                (pkg.cpv, _repo_separator, pkg.repo, alias),
                                noiselevel=-1,
                            )
                        else:
                            usealiases.setdefault(real_flag, []).append(alias)
                cp_usealiases_dict = self._repo_pusealiases_dict.get(
                    repo, {}).get(cp)
                if cp_usealiases_dict:
                    usealiases_dict_list = ordered_by_atom_specificity(
                        cp_usealiases_dict, pkg)
                    for usealiases_dict in usealiases_dict_list:
                        for real_flag, aliases in usealiases_dict.items():
                            for alias in aliases:
                                if any(alias in v
                                       for k, v in usealiases.items()
                                       if k != real_flag):
                                    writemsg(
                                        _("--- Duplicated USE flag alias for '%s%s%s': '%s'\n"
                                          ) % (pkg.cpv, _repo_separator,
                                               pkg.repo, alias),
                                        noiselevel=-1,
                                    )
                                else:
                                    usealiases.setdefault(real_flag,
                                                          []).append(alias)

        return usealiases
Example #5
0
    def getUseAliases(self, pkg):
        if hasattr(pkg, "eapi") and not eapi_has_use_aliases(pkg.eapi):
            return {}

        cp = getattr(pkg, "cp", None)
        if cp is None:
            slot = dep_getslot(pkg)
            repo = dep_getrepo(pkg)
            pkg = _pkg_str(remove_slot(pkg), slot=slot, repo=repo)
            cp = pkg.cp

        usealiases = {}

        if hasattr(pkg, "repo") and pkg.repo != Package.UNKNOWN_REPO:
            repos = []
            try:
                if self.repositories[pkg.repo].use_aliases_masters is not None:
                    masters = self.repositories[pkg.repo].use_aliases_masters
                else:
                    masters = self.repositories[pkg.repo].masters
                repos.extend(repo.name for repo in masters)
            except KeyError:
                pass
            repos.append(pkg.repo)
            for repo in repos:
                usealiases_dict = self._repo_usealiases_dict.get(repo, {})
                for real_flag, aliases in usealiases_dict.items():
                    for alias in aliases:
                        if any(alias in v for k, v in usealiases.items() if k != real_flag):
                            writemsg(
                                _("--- Duplicated USE flag alias for '%s%s%s': '%s'\n")
                                % (pkg.cpv, _repo_separator, pkg.repo, alias),
                                noiselevel=-1,
                            )
                        else:
                            usealiases.setdefault(real_flag, []).append(alias)
                cp_usealiases_dict = self._repo_pusealiases_dict.get(repo, {}).get(cp)
                if cp_usealiases_dict:
                    usealiases_dict_list = ordered_by_atom_specificity(cp_usealiases_dict, pkg)
                    for usealiases_dict in usealiases_dict_list:
                        for real_flag, aliases in usealiases_dict.items():
                            for alias in aliases:
                                if any(alias in v for k, v in usealiases.items() if k != real_flag):
                                    writemsg(
                                        _("--- Duplicated USE flag alias for '%s%s%s': '%s'\n")
                                        % (pkg.cpv, _repo_separator, pkg.repo, alias),
                                        noiselevel=-1,
                                    )
                                else:
                                    usealiases.setdefault(real_flag, []).append(alias)

        return usealiases
Example #6
0
 def getPUSE(self, pkg):
     cp = getattr(pkg, "cp", None)
     if cp is None:
         cp = cpv_getkey(remove_slot(pkg))
     ret = ""
     cpdict = self._pusedict.get(cp)
     if cpdict:
         puse_matches = ordered_by_atom_specificity(cpdict, pkg)
         if puse_matches:
             puse_list = []
             for x in puse_matches:
                 puse_list.extend(x)
             ret = " ".join(puse_list)
     return ret
Example #7
0
	def getPUSE(self, pkg):
		cp = getattr(pkg, "cp", None)
		if cp is None:
			cp = cpv_getkey(remove_slot(pkg))
		ret = ""
		cpdict = self._pusedict.get(cp)
		if cpdict:
			puse_matches = ordered_by_atom_specificity(cpdict, pkg)
			if puse_matches:
				puse_list = []
				for x in puse_matches:
					puse_list.extend(x)
				ret = " ".join(puse_list)
		return ret
Example #8
0
 def getPUSE(self, pkg):
     cp = getattr(pkg, "cp", None)
     if cp is None:
         slot = dep_getslot(pkg)
         repo = dep_getrepo(pkg)
         pkg = _pkg_str(remove_slot(pkg), slot=slot, repo=repo)
         cp = pkg.cp
     ret = ""
     cpdict = self._pusedict.get(cp)
     if cpdict:
         puse_matches = ordered_by_atom_specificity(cpdict, pkg)
         if puse_matches:
             puse_list = []
             for x in puse_matches:
                 puse_list.extend(x)
             ret = " ".join(puse_list)
     return ret
Example #9
0
	def getPUSE(self, pkg):
		cp = getattr(pkg, "cp", None)
		if cp is None:
			slot = dep_getslot(pkg)
			repo = dep_getrepo(pkg)
			pkg = _pkg_str(remove_slot(pkg), slot=slot, repo=repo)
			cp = pkg.cp
		ret = ""
		cpdict = self._pusedict.get(cp)
		if cpdict:
			puse_matches = ordered_by_atom_specificity(cpdict, pkg)
			if puse_matches:
				puse_list = []
				for x in puse_matches:
					puse_list.extend(x)
				ret = " ".join(puse_list)
		return ret
Example #10
0
    def getUseMask(self, pkg=None):
        if pkg is None:
            return frozenset(stack_lists(self._usemask_list, incremental=True))

        cp = getattr(pkg, "cp", None)
        if cp is None:
            cp = cpv_getkey(remove_slot(pkg))
        usemask = []
        for i, pusemask_dict in enumerate(self._pusemask_list):
            if self._usemask_list[i]:
                usemask.append(self._usemask_list[i])
            cpdict = pusemask_dict.get(cp)
            if cpdict:
                pkg_usemask = ordered_by_atom_specificity(cpdict, pkg)
                if pkg_usemask:
                    usemask.extend(pkg_usemask)
        return frozenset(stack_lists(usemask, incremental=True))
Example #11
0
	def getUseForce(self, pkg=None):
		if pkg is None:
			return frozenset(stack_lists(
				self._useforce_list, incremental=True))

		cp = getattr(pkg, "cp", None)
		if cp is None:
			cp = cpv_getkey(remove_slot(pkg))
		useforce = []
		for i, puseforce_dict in enumerate(self._puseforce_list):
			if self._useforce_list[i]:
				useforce.append(self._useforce_list[i])
			cpdict = puseforce_dict.get(cp)
			if cpdict:
				pkg_useforce = ordered_by_atom_specificity(cpdict, pkg)
				if pkg_useforce:
					useforce.extend(pkg_useforce)
		return frozenset(stack_lists(useforce, incremental=True))
Example #12
0
    def getUseForce(self, pkg=None):
        if pkg is None:
            return frozenset(stack_lists(self._useforce_list,
                                         incremental=True))

        cp = getattr(pkg, "cp", None)
        if cp is None:
            slot = dep_getslot(pkg)
            repo = dep_getrepo(pkg)
            pkg = _pkg_str(remove_slot(pkg), slot=slot, repo=repo)
            cp = pkg.cp

        try:
            stable = pkg.stable
        except AttributeError:
            # KEYWORDS is unavailable (prior to "depend" phase)
            stable = False

        useforce = []

        if hasattr(pkg, "repo") and pkg.repo != Package.UNKNOWN_REPO:
            repos = []
            try:
                repos.extend(repo.name
                             for repo in self.repositories[pkg.repo].masters)
            except KeyError:
                pass
            repos.append(pkg.repo)
            for repo in repos:
                useforce.append(self._repo_useforce_dict.get(repo, {}))
                if stable:
                    useforce.append(
                        self._repo_usestableforce_dict.get(repo, {}))
                cpdict = self._repo_puseforce_dict.get(repo, {}).get(cp)
                if cpdict:
                    pkg_useforce = ordered_by_atom_specificity(cpdict, pkg)
                    if pkg_useforce:
                        useforce.extend(pkg_useforce)
                if stable:
                    cpdict = self._repo_pusestableforce_dict.get(repo,
                                                                 {}).get(cp)
                    if cpdict:
                        pkg_useforce = ordered_by_atom_specificity(cpdict, pkg)
                        if pkg_useforce:
                            useforce.extend(pkg_useforce)

        for i, puseforce_dict in enumerate(self._puseforce_list):
            if self._useforce_list[i]:
                useforce.append(self._useforce_list[i])
            if stable and self._usestableforce_list[i]:
                useforce.append(self._usestableforce_list[i])
            cpdict = puseforce_dict.get(cp)
            if cpdict:
                pkg_useforce = ordered_by_atom_specificity(cpdict, pkg)
                if pkg_useforce:
                    useforce.extend(pkg_useforce)
            if stable:
                cpdict = self._pusestableforce_list[i].get(cp)
                if cpdict:
                    pkg_useforce = ordered_by_atom_specificity(cpdict, pkg)
                    if pkg_useforce:
                        useforce.extend(pkg_useforce)

        return frozenset(stack_lists(useforce, incremental=True))
Example #13
0
	def getUseForce(self, pkg=None):
		if pkg is None:
			return frozenset(stack_lists(
				self._useforce_list, incremental=True))

		cp = getattr(pkg, "cp", None)
		if cp is None:
			slot = dep_getslot(pkg)
			repo = dep_getrepo(pkg)
			pkg = _pkg_str(remove_slot(pkg), slot=slot, repo=repo)
			cp = pkg.cp

		try:
			stable = pkg.stable
		except AttributeError:
			# KEYWORDS is unavailable (prior to "depend" phase)
			stable = False

		useforce = []

		if hasattr(pkg, "repo") and pkg.repo != Package.UNKNOWN_REPO:
			repos = []
			try:
				repos.extend(repo.name for repo in
					self.repositories[pkg.repo].masters)
			except KeyError:
				pass
			repos.append(pkg.repo)
			for repo in repos:
				useforce.append(self._repo_useforce_dict.get(repo, {}))
				if stable:
					useforce.append(self._repo_usestableforce_dict.get(repo, {}))
				cpdict = self._repo_puseforce_dict.get(repo, {}).get(cp)
				if cpdict:
					pkg_useforce = ordered_by_atom_specificity(cpdict, pkg)
					if pkg_useforce:
						useforce.extend(pkg_useforce)
				if stable:
					cpdict = self._repo_pusestableforce_dict.get(repo, {}).get(cp)
					if cpdict:
						pkg_useforce = ordered_by_atom_specificity(cpdict, pkg)
						if pkg_useforce:
							useforce.extend(pkg_useforce)

		for i, puseforce_dict in enumerate(self._puseforce_list):
			if self._useforce_list[i]:
				useforce.append(self._useforce_list[i])
			if stable and self._usestableforce_list[i]:
				useforce.append(self._usestableforce_list[i])
			cpdict = puseforce_dict.get(cp)
			if cpdict:
				pkg_useforce = ordered_by_atom_specificity(cpdict, pkg)
				if pkg_useforce:
					useforce.extend(pkg_useforce)
			if stable:
				cpdict = self._pusestableforce_list[i].get(cp)
				if cpdict:
					pkg_useforce = ordered_by_atom_specificity(cpdict, pkg)
					if pkg_useforce:
						useforce.extend(pkg_useforce)

		return frozenset(stack_lists(useforce, incremental=True))
def _expand_new_virtuals(mysplit, edebug, mydbapi, mysettings, myroot="/",
	trees=None, use_mask=None, use_force=None, **kwargs):
	"""
	In order to solve bug #141118, recursively expand new-style virtuals so
	as to collapse one or more levels of indirection, generating an expanded
	search space. In dep_zapdeps, new-style virtuals will be assigned
	zero cost regardless of whether or not they are currently installed. Virtual
	blockers are supported but only when the virtual expands to a single
	atom because it wouldn't necessarily make sense to block all the components
	of a compound virtual.  When more than one new-style virtual is matched,
	the matches are sorted from highest to lowest versions and the atom is
	expanded to || ( highest match ... lowest match )."""
	newsplit = []
	mytrees = trees[myroot]
	portdb = mytrees["porttree"].dbapi
	atom_graph = mytrees.get("atom_graph")
	parent = mytrees.get("parent")
	virt_parent = mytrees.get("virt_parent")
	graph_parent = None
	eapi = None
	if parent is not None:
		if virt_parent is not None:
			graph_parent = virt_parent
			eapi = virt_parent[0].metadata['EAPI']
		else:
			graph_parent = parent
			eapi = parent.metadata["EAPI"]
	repoman = not mysettings.local_config
	if kwargs["use_binaries"]:
		portdb = trees[myroot]["bintree"].dbapi
	myvirtuals = mysettings.getvirtuals()
	pprovideddict = mysettings.pprovideddict
	myuse = kwargs["myuse"]
	for x in mysplit:
		if x == "||":
			newsplit.append(x)
			continue
		elif isinstance(x, list):
			newsplit.append(_expand_new_virtuals(x, edebug, mydbapi,
				mysettings, myroot=myroot, trees=trees, use_mask=use_mask,
				use_force=use_force, **kwargs))
			continue

		if not isinstance(x, Atom):
			try:
				x = Atom(x)
			except InvalidAtom:
				if portage.dep._dep_check_strict:
					raise ParseError(
						_("invalid atom: '%s'") % x)
				else:
					# Only real Atom instances are allowed past this point.
					continue
			else:
				if x.blocker and x.blocker.overlap.forbid and \
					eapi in ("0", "1") and portage.dep._dep_check_strict:
					raise ParseError(
						_("invalid atom: '%s'") % (x,))
				if x.use and eapi in ("0", "1") and \
					portage.dep._dep_check_strict:
					raise ParseError(
						_("invalid atom: '%s'") % (x,))

		if repoman and x.use and x.use.conditional:
			evaluated_atom = remove_slot(x)
			if x.slot:
				evaluated_atom += ":%s" % x.slot
			evaluated_atom += str(x.use._eval_qa_conditionals(
				use_mask, use_force))
			x = Atom(evaluated_atom)

		if not repoman :
			if 'lib32' not in x and portage.dep_getkey(x) not in mysettings.get("NO_AUTO_FLAG", None):
				if ']' in x:
					x = str(x).replace(']',',lib32?]')
				else:
					x = str(x) + '[lib32?]'
				try:
					x = portage.dep.Atom(x)
				except portage.exception.InvalidAtom:
					if portage.dep._dep_check_strict:
						raise portage.exception.ParseError(
							"invalid atom: '%s'" % x)

			if myuse is not None and isinstance(x, Atom) and x.use:
				if x.use.conditional:
					x = x.evaluate_conditionals(myuse)

		mykey = x.cp
		if not mykey.startswith("virtual/"):
			newsplit.append(x)
			if atom_graph is not None:
				atom_graph.add(x, graph_parent)
			continue
		mychoices = myvirtuals.get(mykey, [])
		if x.blocker:
			# Virtual blockers are no longer expanded here since
			# the un-expanded virtual atom is more useful for
			# maintaining a cache of blocker atoms.
			newsplit.append(x)
			if atom_graph is not None:
				atom_graph.add(x, graph_parent)
			continue

		if repoman or not hasattr(portdb, 'match_pkgs'):
			if portdb.cp_list(x.cp):
				newsplit.append(x)
			else:
				# TODO: Add PROVIDE check for repoman.
				a = []
				for y in mychoices:
					a.append(Atom(x.replace(x.cp, y.cp, 1)))
				if not a:
					newsplit.append(x)
				elif len(a) == 1:
					newsplit.append(a[0])
				else:
					newsplit.append(['||'] + a)
			continue

		pkgs = []
		# Ignore USE deps here, since otherwise we might not
		# get any matches. Choices with correct USE settings
		# will be preferred in dep_zapdeps().
		matches = portdb.match_pkgs(x.without_use)
		# Use descending order to prefer higher versions.
		matches.reverse()
		for pkg in matches:
			# only use new-style matches
			if pkg.cp.startswith("virtual/"):
				pkgs.append(pkg)
		if not (pkgs or mychoices):
			# This one couldn't be expanded as a new-style virtual.  Old-style
			# virtuals have already been expanded by dep_virtual, so this one
			# is unavailable and dep_zapdeps will identify it as such.  The
			# atom is not eliminated here since it may still represent a
			# dependency that needs to be satisfied.
			newsplit.append(x)
			if atom_graph is not None:
				atom_graph.add(x, graph_parent)
			continue

		a = []
		for pkg in pkgs:
			virt_atom = '=' + pkg.cpv
			if x.use:
				virt_atom += str(x.use)
			virt_atom = Atom(virt_atom)
			# According to GLEP 37, RDEPEND is the only dependency
			# type that is valid for new-style virtuals. Repoman
			# should enforce this.
			depstring = pkg.metadata['RDEPEND']
			pkg_kwargs = kwargs.copy()
			pkg_kwargs["myuse"] = pkg.use.enabled
			if edebug:
				writemsg_level(_("Virtual Parent:      %s\n") \
					% (pkg,), noiselevel=-1, level=logging.DEBUG)
				writemsg_level(_("Virtual Depstring:   %s\n") \
					% (depstring,), noiselevel=-1, level=logging.DEBUG)

			# Set EAPI used for validation in dep_check() recursion.
			mytrees["virt_parent"] = (pkg, virt_atom)

			try:
				mycheck = dep_check(depstring, mydbapi, mysettings,
					myroot=myroot, trees=trees, **pkg_kwargs)
			finally:
				# Restore previous EAPI after recursion.
				if virt_parent is not None:
					mytrees["virt_parent"] = virt_parent
				else:
					del mytrees["virt_parent"]

			if not mycheck[0]:
				raise ParseError(
					"%s: %s '%s'" % (y[0], mycheck[1], depstring))

			# pull in the new-style virtual
			mycheck[1].append(virt_atom)
			a.append(mycheck[1])
			if atom_graph is not None:
				atom_graph.add(virt_atom, graph_parent)
		# Plain old-style virtuals.  New-style virtuals are preferred.
		if not pkgs:
				for y in mychoices:
					new_atom = Atom(x.replace(x.cp, y.cp, 1))
					matches = portdb.match(new_atom)
					# portdb is an instance of depgraph._dep_check_composite_db, so
					# USE conditionals are already evaluated.
					if matches and mykey in \
						portdb.aux_get(matches[-1], ['PROVIDE'])[0].split():
						a.append(new_atom)
						if atom_graph is not None:
							atom_graph.add(new_atom, graph_parent)

		if not a and mychoices:
			# Check for a virtual package.provided match.
			for y in mychoices:
				new_atom = Atom(x.replace(x.cp, y.cp, 1))
				if match_from_list(new_atom,
					pprovideddict.get(new_atom.cp, [])):
					a.append(new_atom)
					if atom_graph is not None:
						atom_graph.add(new_atom, graph_parent)

		if not a:
			newsplit.append(x)
			if atom_graph is not None:
				atom_graph.add(x, graph_parent)
		elif len(a) == 1:
			newsplit.append(a[0])
		else:
			newsplit.append(['||'] + a)

	return newsplit
Example #15
0
def _expand_new_virtuals(mysplit,
                         edebug,
                         mydbapi,
                         mysettings,
                         myroot="/",
                         trees=None,
                         use_mask=None,
                         use_force=None,
                         **kwargs):
    """
	In order to solve bug #141118, recursively expand new-style virtuals so
	as to collapse one or more levels of indirection, generating an expanded
	search space. In dep_zapdeps, new-style virtuals will be assigned
	zero cost regardless of whether or not they are currently installed. Virtual
	blockers are supported but only when the virtual expands to a single
	atom because it wouldn't necessarily make sense to block all the components
	of a compound virtual.  When more than one new-style virtual is matched,
	the matches are sorted from highest to lowest versions and the atom is
	expanded to || ( highest match ... lowest match )."""
    newsplit = []
    mytrees = trees[myroot]
    portdb = mytrees["porttree"].dbapi
    atom_graph = mytrees.get("atom_graph")
    parent = mytrees.get("parent")
    virt_parent = mytrees.get("virt_parent")
    graph_parent = None
    eapi = None
    if parent is not None:
        if virt_parent is not None:
            graph_parent = virt_parent
            eapi = virt_parent[0].metadata['EAPI']
        else:
            graph_parent = parent
            eapi = parent.metadata["EAPI"]
    repoman = not mysettings.local_config
    if kwargs["use_binaries"]:
        portdb = trees[myroot]["bintree"].dbapi
    myvirtuals = mysettings.getvirtuals()
    pprovideddict = mysettings.pprovideddict
    myuse = kwargs["myuse"]
    for x in mysplit:
        if x == "||":
            newsplit.append(x)
            continue
        elif isinstance(x, list):
            newsplit.append(
                _expand_new_virtuals(x,
                                     edebug,
                                     mydbapi,
                                     mysettings,
                                     myroot=myroot,
                                     trees=trees,
                                     use_mask=use_mask,
                                     use_force=use_force,
                                     **kwargs))
            continue

        if not isinstance(x, Atom):
            try:
                x = Atom(x)
            except InvalidAtom:
                if portage.dep._dep_check_strict:
                    raise ParseError(_("invalid atom: '%s'") % x)
                else:
                    # Only real Atom instances are allowed past this point.
                    continue
            else:
                if x.blocker and x.blocker.overlap.forbid and \
                 eapi in ("0", "1") and portage.dep._dep_check_strict:
                    raise ParseError(_("invalid atom: '%s'") % (x, ))
                if x.use and eapi in ("0", "1") and \
                 portage.dep._dep_check_strict:
                    raise ParseError(_("invalid atom: '%s'") % (x, ))

        if repoman and x.use and x.use.conditional:
            evaluated_atom = remove_slot(x)
            if x.slot:
                evaluated_atom += ":%s" % x.slot
            evaluated_atom += str(
                x.use._eval_qa_conditionals(use_mask, use_force))
            x = Atom(evaluated_atom)

        if not repoman and \
         myuse is not None and isinstance(x, Atom) and x.use:
            if x.use.conditional:
                x = x.evaluate_conditionals(myuse)

        mykey = x.cp
        if not mykey.startswith("virtual/"):
            newsplit.append(x)
            if atom_graph is not None:
                atom_graph.add(x, graph_parent)
            continue
        mychoices = myvirtuals.get(mykey, [])
        if x.blocker:
            # Virtual blockers are no longer expanded here since
            # the un-expanded virtual atom is more useful for
            # maintaining a cache of blocker atoms.
            newsplit.append(x)
            if atom_graph is not None:
                atom_graph.add(x, graph_parent)
            continue

        if repoman or not hasattr(portdb, 'match_pkgs'):
            if portdb.cp_list(x.cp):
                newsplit.append(x)
            else:
                # TODO: Add PROVIDE check for repoman.
                a = []
                for y in mychoices:
                    a.append(Atom(x.replace(x.cp, y.cp, 1)))
                if not a:
                    newsplit.append(x)
                elif len(a) == 1:
                    newsplit.append(a[0])
                else:
                    newsplit.append(['||'] + a)
            continue

        pkgs = []
        # Ignore USE deps here, since otherwise we might not
        # get any matches. Choices with correct USE settings
        # will be preferred in dep_zapdeps().
        matches = portdb.match_pkgs(x.without_use)
        # Use descending order to prefer higher versions.
        matches.reverse()
        for pkg in matches:
            # only use new-style matches
            if pkg.cp.startswith("virtual/"):
                pkgs.append(pkg)
        if not (pkgs or mychoices):
            # This one couldn't be expanded as a new-style virtual.  Old-style
            # virtuals have already been expanded by dep_virtual, so this one
            # is unavailable and dep_zapdeps will identify it as such.  The
            # atom is not eliminated here since it may still represent a
            # dependency that needs to be satisfied.
            newsplit.append(x)
            if atom_graph is not None:
                atom_graph.add(x, graph_parent)
            continue

        a = []
        for pkg in pkgs:
            virt_atom = '=' + pkg.cpv
            if x.use:
                virt_atom += str(x.use)
            virt_atom = Atom(virt_atom)
            # According to GLEP 37, RDEPEND is the only dependency
            # type that is valid for new-style virtuals. Repoman
            # should enforce this.
            depstring = pkg.metadata['RDEPEND']
            pkg_kwargs = kwargs.copy()
            pkg_kwargs["myuse"] = pkg.use.enabled
            if edebug:
                writemsg_level(_("Virtual Parent:      %s\n") \
                 % (pkg,), noiselevel=-1, level=logging.DEBUG)
                writemsg_level(_("Virtual Depstring:   %s\n") \
                 % (depstring,), noiselevel=-1, level=logging.DEBUG)

            # Set EAPI used for validation in dep_check() recursion.
            mytrees["virt_parent"] = (pkg, virt_atom)

            try:
                mycheck = dep_check(depstring,
                                    mydbapi,
                                    mysettings,
                                    myroot=myroot,
                                    trees=trees,
                                    **pkg_kwargs)
            finally:
                # Restore previous EAPI after recursion.
                if virt_parent is not None:
                    mytrees["virt_parent"] = virt_parent
                else:
                    del mytrees["virt_parent"]

            if not mycheck[0]:
                raise ParseError("%s: %s '%s'" % (y[0], mycheck[1], depstring))

            # pull in the new-style virtual
            mycheck[1].append(virt_atom)
            a.append(mycheck[1])
            if atom_graph is not None:
                atom_graph.add(virt_atom, graph_parent)
        # Plain old-style virtuals.  New-style virtuals are preferred.
        if not pkgs:
            for y in mychoices:
                new_atom = Atom(x.replace(x.cp, y.cp, 1))
                matches = portdb.match(new_atom)
                # portdb is an instance of depgraph._dep_check_composite_db, so
                # USE conditionals are already evaluated.
                if matches and mykey in \
                 portdb.aux_get(matches[-1], ['PROVIDE'])[0].split():
                    a.append(new_atom)
                    if atom_graph is not None:
                        atom_graph.add(new_atom, graph_parent)

        if not a and mychoices:
            # Check for a virtual package.provided match.
            for y in mychoices:
                new_atom = Atom(x.replace(x.cp, y.cp, 1))
                if match_from_list(new_atom,
                                   pprovideddict.get(new_atom.cp, [])):
                    a.append(new_atom)
                    if atom_graph is not None:
                        atom_graph.add(new_atom, graph_parent)

        if not a:
            newsplit.append(x)
            if atom_graph is not None:
                atom_graph.add(x, graph_parent)
        elif len(a) == 1:
            newsplit.append(a[0])
        else:
            newsplit.append(['||'] + a)

    return newsplit