# Copyright 1999-2019 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2

from __future__ import division, print_function, unicode_literals

import collections
import errno
import functools
import io
import logging
import stat
import sys
import textwrap
import warnings
from collections import deque, OrderedDict
from itertools import chain

import portage
from portage import os
from portage import _unicode_decode, _unicode_encode, _encodings
from portage.const import PORTAGE_PACKAGE_ATOM, USER_CONFIG_PATH, VCS_DIRS
from portage.dbapi import dbapi
from portage.dbapi.dep_expand import dep_expand
from portage.dbapi.DummyTree import DummyTree
from portage.dbapi.IndexedPortdb import IndexedPortdb
from portage.dbapi._similar_name_search import similar_name_search
from portage.dep import Atom, best_match_to_list, extract_affecting_use, \
	check_required_use, human_readable_required_use, match_from_list, \
	_repo_separator
from portage.dep._slot_operator import (ignore_built_slot_operator_deps,
	strip_slots)
from portage.eapi import eapi_has_strong_blocks, eapi_has_required_use, \
	_get_eapi_attrs
from portage.exception import (InvalidAtom, InvalidData, InvalidDependString,
	PackageNotFound, PortageException)
from portage.localization import _
from portage.output import colorize, create_color_func, \
	darkgreen, green
bad = create_color_func("BAD")
from portage.package.ebuild.config import _get_feature_flags
from portage.package.ebuild.getmaskingstatus import \
	_getmaskingstatus, _MaskReason
from portage._sets import SETPREFIX
from portage._sets.base import InternalPackageSet
from portage.util import ConfigProtect, shlex_split, new_protect_filename
from portage.util import cmp_sort_key, writemsg, writemsg_stdout
from portage.util import ensure_dirs
from portage.util import writemsg_level, write_atomic
from portage.util.digraph import digraph
from portage.util.futures import asyncio
from portage.util._async.TaskScheduler import TaskScheduler
from portage.util._eventloop.EventLoop import EventLoop
from portage.util._eventloop.global_event_loop import global_event_loop
from portage.versions import _pkg_str, catpkgsplit

from _emerge.AtomArg import AtomArg
from _emerge.Blocker import Blocker
from _emerge.BlockerCache import BlockerCache
from _emerge.BlockerDepPriority import BlockerDepPriority
from .chk_updated_cfg_files import chk_updated_cfg_files
from _emerge.countdown import countdown
from _emerge.create_world_atom import create_world_atom
from _emerge.Dependency import Dependency
from _emerge.DependencyArg import DependencyArg
from _emerge.DepPriority import DepPriority
from _emerge.DepPriorityNormalRange import DepPriorityNormalRange
from _emerge.DepPrioritySatisfiedRange import DepPrioritySatisfiedRange
from _emerge.EbuildMetadataPhase import EbuildMetadataPhase
from _emerge.FakeVartree import FakeVartree
from _emerge._find_deep_system_runtime_deps import _find_deep_system_runtime_deps
from _emerge.is_valid_package_atom import insert_category_into_atom, \
	is_valid_package_atom
from _emerge.Package import Package
from _emerge.PackageArg import PackageArg
from _emerge.PackageVirtualDbapi import PackageVirtualDbapi
from _emerge.RootConfig import RootConfig
from _emerge.search import search
from _emerge.SetArg import SetArg
from _emerge.show_invalid_depstring_notice import show_invalid_depstring_notice
from _emerge.UnmergeDepPriority import UnmergeDepPriority
from _emerge.UseFlagDisplay import pkg_use_display
from _emerge.UserQuery import UserQuery

from _emerge.resolver.backtracking import Backtracker, BacktrackParameter
from _emerge.resolver.DbapiProvidesIndex import DbapiProvidesIndex
from _emerge.resolver.package_tracker import PackageTracker, PackageTrackerDbapiWrapper
from _emerge.resolver.slot_collision import slot_conflict_handler
from _emerge.resolver.circular_dependency import circular_dependency_handler
from _emerge.resolver.output import Display, format_unmatched_atom

if sys.hexversion >= 0x3000000:
	basestring = str
	long = int
	_unicode = str
else:
	_unicode = unicode

class _scheduler_graph_config(object):
	def __init__(self, trees, pkg_cache, graph, mergelist):
		self.trees = trees
		self.pkg_cache = pkg_cache
		self.graph = graph
		self.mergelist = mergelist

def _wildcard_set(atoms):
	pkgs = InternalPackageSet(allow_wildcard=True)
	for x in atoms:
		try:
			x = Atom(x, allow_wildcard=True, allow_repo=False)
		except portage.exception.InvalidAtom:
			x = Atom("*/" + x, allow_wildcard=True, allow_repo=False)
		pkgs.add(x)
	return pkgs

class _frozen_depgraph_config(object):

	def __init__(self, settings, trees, myopts, params, spinner):
		self.settings = settings
		self.target_root = settings["EROOT"]
		self.myopts = myopts
		self.edebug = 0
		if settings.get("PORTAGE_DEBUG", "") == "1":
			self.edebug = 1
		self.spinner = spinner
		self.requested_depth = params.get("deep", 0)
		self._running_root = trees[trees._running_eroot]["root_config"]
		self.pkgsettings = {}
		self.trees = {}
		self._trees_orig = trees
		self.roots = {}
		# All Package instances
		self._pkg_cache = {}
		self._highest_license_masked = {}
		# We can't know that an soname dep is unsatisfied if there are
		# any unbuilt ebuilds in the graph, since unbuilt ebuilds have
		# no soname data. Therefore, only enable soname dependency
		# resolution if --usepkgonly is enabled, or for removal actions.
		self.soname_deps_enabled = (
			("--usepkgonly" in myopts or "remove" in params) and
			params.get("ignore_soname_deps") != "y")
		dynamic_deps = "dynamic_deps" in params
		ignore_built_slot_operator_deps = myopts.get(
			"--ignore-built-slot-operator-deps", "n") == "y"
		for myroot in trees:
			self.trees[myroot] = {}
			# Create a RootConfig instance that references
			# the FakeVartree instead of the real one.
			self.roots[myroot] = RootConfig(
				trees[myroot]["vartree"].settings,
				self.trees[myroot],
				trees[myroot]["root_config"].setconfig)
			for tree in ("porttree", "bintree"):
				self.trees[myroot][tree] = trees[myroot][tree]
			self.trees[myroot]["vartree"] = \
				FakeVartree(trees[myroot]["root_config"],
					pkg_cache=self._pkg_cache,
					pkg_root_config=self.roots[myroot],
					dynamic_deps=dynamic_deps,
					ignore_built_slot_operator_deps=ignore_built_slot_operator_deps,
					soname_deps=self.soname_deps_enabled)
			self.pkgsettings[myroot] = portage.config(
				clone=self.trees[myroot]["vartree"].settings)
			if self.soname_deps_enabled and "remove" not in params:
				self.trees[myroot]["bintree"] = DummyTree(
					DbapiProvidesIndex(trees[myroot]["bintree"].dbapi))

		if params.get("ignore_world", False):
			self._required_set_names = set()
		else:
			self._required_set_names = set(["world"])

		atoms = ' '.join(myopts.get("--exclude", [])).split()
		self.excluded_pkgs = _wildcard_set(atoms)
		atoms = ' '.join(myopts.get("--reinstall-atoms", [])).split()
		self.reinstall_atoms = _wildcard_set(atoms)
		atoms = ' '.join(myopts.get("--usepkg-exclude", [])).split()
		self.usepkg_exclude = _wildcard_set(atoms)
		atoms = ' '.join(myopts.get("--useoldpkg-atoms", [])).split()
		self.useoldpkg_atoms = _wildcard_set(atoms)
		atoms = ' '.join(myopts.get("--rebuild-exclude", [])).split()
		self.rebuild_exclude = _wildcard_set(atoms)
		atoms = ' '.join(myopts.get("--rebuild-ignore", [])).split()
		self.rebuild_ignore = _wildcard_set(atoms)

		self.rebuild_if_new_rev = "--rebuild-if-new-rev" in myopts
		self.rebuild_if_new_ver = "--rebuild-if-new-ver" in myopts
		self.rebuild_if_unbuilt = "--rebuild-if-unbuilt" in myopts

class _depgraph_sets(object):
	def __init__(self):
		# contains all sets added to the graph
		self.sets = {}
		# contains non-set atoms given as arguments
		self.sets['__non_set_args__'] = InternalPackageSet(allow_repo=True)
		# contains all atoms from all sets added to the graph, including
		# atoms given as arguments
		self.atoms = InternalPackageSet(allow_repo=True)
		self.atom_arg_map = {}

class _rebuild_config(object):
	def __init__(self, frozen_config, backtrack_parameters):
		self._graph = digraph()
		self._frozen_config = frozen_config
		self.rebuild_list = backtrack_parameters.rebuild_list.copy()
		self.orig_rebuild_list = self.rebuild_list.copy()
		self.reinstall_list = backtrack_parameters.reinstall_list.copy()
		self.rebuild_if_new_rev = frozen_config.rebuild_if_new_rev
		self.rebuild_if_new_ver = frozen_config.rebuild_if_new_ver
		self.rebuild_if_unbuilt = frozen_config.rebuild_if_unbuilt
		self.rebuild = (self.rebuild_if_new_rev or self.rebuild_if_new_ver or
			self.rebuild_if_unbuilt)

	def add(self, dep_pkg, dep):
		parent = dep.collapsed_parent
		priority = dep.collapsed_priority
		rebuild_exclude = self._frozen_config.rebuild_exclude
		rebuild_ignore = self._frozen_config.rebuild_ignore
		if (self.rebuild and isinstance(parent, Package) and
			parent.built and priority.buildtime and
			isinstance(dep_pkg, Package) and
			not rebuild_exclude.findAtomForPackage(parent) and
			not rebuild_ignore.findAtomForPackage(dep_pkg)):
			self._graph.add(dep_pkg, parent, priority)

	def _needs_rebuild(self, dep_pkg):
		"""Check whether packages that depend on dep_pkg need to be rebuilt."""
		dep_root_slot = (dep_pkg.root, dep_pkg.slot_atom)
		if dep_pkg.built or dep_root_slot in self.orig_rebuild_list:
			return False

		if self.rebuild_if_unbuilt:
			# dep_pkg is being installed from source, so binary
			# packages for parents are invalid. Force rebuild
			return True

		trees = self._frozen_config.trees
		vardb = trees[dep_pkg.root]["vartree"].dbapi
		if self.rebuild_if_new_rev:
			# Parent packages are valid if a package with the same
			# cpv is already installed.
			return dep_pkg.cpv not in vardb.match(dep_pkg.slot_atom)

		# Otherwise, parent packages are valid if a package with the same
		# version (excluding revision) is already installed.
		assert self.rebuild_if_new_ver
		cpv_norev = catpkgsplit(dep_pkg.cpv)[:-1]
		for inst_cpv in vardb.match(dep_pkg.slot_atom):
			inst_cpv_norev = catpkgsplit(inst_cpv)[:-1]
			if inst_cpv_norev == cpv_norev:
				return False

		return True

	def _trigger_rebuild(self, parent, build_deps):
		root_slot = (parent.root, parent.slot_atom)
		if root_slot in self.rebuild_list:
			return False
		trees = self._frozen_config.trees
		reinstall = False
		for slot_atom, dep_pkg in build_deps.items():
			dep_root_slot = (dep_pkg.root, slot_atom)
			if self._needs_rebuild(dep_pkg):
				self.rebuild_list.add(root_slot)
				return True
			elif ("--usepkg" in self._frozen_config.myopts and
				(dep_root_slot in self.reinstall_list or
				dep_root_slot in self.rebuild_list or
				not dep_pkg.installed)):

				# A direct rebuild dependency is being installed. We
				# should update the parent as well to the latest binary,
				# if that binary is valid.
				#
				# To validate the binary, we check whether all of the
				# rebuild dependencies are present on the same binhost.
				#
				# 1) If parent is present on the binhost, but one of its
				#    rebuild dependencies is not, then the parent should
				#    be rebuilt from source.
				# 2) Otherwise, the parent binary is assumed to be valid,
				#    because all of its rebuild dependencies are
				#    consistent.
				bintree = trees[parent.root]["bintree"]
				uri = bintree.get_pkgindex_uri(parent.cpv)
				dep_uri = bintree.get_pkgindex_uri(dep_pkg.cpv)
				bindb = bintree.dbapi
				if self.rebuild_if_new_ver and uri and uri != dep_uri:
					cpv_norev = catpkgsplit(dep_pkg.cpv)[:-1]
					for cpv in bindb.match(dep_pkg.slot_atom):
						if cpv_norev == catpkgsplit(cpv)[:-1]:
							dep_uri = bintree.get_pkgindex_uri(cpv)
							if uri == dep_uri:
								break
				if uri and uri != dep_uri:
					# 1) Remote binary package is invalid because it was
					#    built without dep_pkg. Force rebuild.
					self.rebuild_list.add(root_slot)
					return True
				elif (parent.installed and
					root_slot not in self.reinstall_list):
					try:
						bin_build_time, = bindb.aux_get(parent.cpv,
							["BUILD_TIME"])
					except KeyError:
						continue
					if bin_build_time != _unicode(parent.build_time):
						# 2) Remote binary package is valid, and local package
						#    is not up to date. Force reinstall.
						reinstall = True
		if reinstall:
			self.reinstall_list.add(root_slot)
		return reinstall

	def trigger_rebuilds(self):
		"""
		Trigger rebuilds where necessary. If pkgA has been updated, and pkgB
		depends on pkgA at both build-time and run-time, pkgB needs to be
		rebuilt.
		"""
		need_restart = False
		graph = self._graph
		build_deps = {}

		leaf_nodes = deque(graph.leaf_nodes())

		# Trigger rebuilds bottom-up (starting with the leaves) so that parents
		# will always know which children are being rebuilt.
		while graph:
			if not leaf_nodes:
				# We'll have to drop an edge. This should be quite rare.
				leaf_nodes.append(graph.order[-1])

			node = leaf_nodes.popleft()
			if node not in graph:
				# This can be triggered by circular dependencies.
				continue
			slot_atom = node.slot_atom

			# Remove our leaf node from the graph, keeping track of deps.
			parents = graph.parent_nodes(node)
			graph.remove(node)
			node_build_deps = build_deps.get(node, {})
			for parent in parents:
				if parent == node:
					# Ignore a direct cycle.
					continue
				parent_bdeps = build_deps.setdefault(parent, {})
				parent_bdeps[slot_atom] = node
				if not graph.child_nodes(parent):
					leaf_nodes.append(parent)

			# Trigger rebuilds for our leaf node. Because all of our children
			# have been processed, the build_deps will be completely filled in,
			# and self.rebuild_list / self.reinstall_list will tell us whether
			# any of our children need to be rebuilt or reinstalled.
			if self._trigger_rebuild(node, node_build_deps):
				need_restart = True

		return need_restart


class _use_changes(tuple):
	def __new__(cls, new_use, new_changes, required_use_satisfied=True):
		obj = tuple.__new__(cls, [new_use, new_changes])
		obj.required_use_satisfied = required_use_satisfied
		return obj


class _dynamic_depgraph_config(object):

	"""
	``dynamic_depgraph_config`` is an object that is used to collect settings and important data structures that are
	used in calculating Portage dependencies. Each depgraph created by the depgraph.py code gets its own
	``dynamic_depgraph_config``, whereas ``frozen_depgraph_config`` is shared among all depgraphs.

	**self.digraph**

	Of particular importance is the instance variable ``self.digraph``, which is an instance of
	``portage.util.digraph``, a directed graph data structure. ``portage.util.digraph`` is used for a variety of
	purposes in the Portage codebase, but in this particular scenario as ``self.digraph``, it is used to create a
	dependency tree of Portage packages. So for ``self.digraph``, each *node* of the directed graph is a ``Package``,
	while *edges* connect nodes and each edge can have a Priority. The Priority setting is used to help resolve
	circular dependencies, and should be interpreted in the direction of parent to child.

	Conceptually, think of ``self.digraph`` as containing user-specified packages or sets at the very top, with
	dependencies hanging down as children, and dependencies of those children as children of children, etc. The depgraph
	is intended to model dependency relationships, not the order that packages should be installed.

	**resolving the digraph**

	To convert a digraph to an ordered list of packages to merge in an order where all dependencies are properly
	satisfied, we would first start by looking at leaf nodes, which are nodes that have no dependencies of their own. We
	could then traverse the digraph upwards from the leaf nodes, towards the parents. Along the way, depending on emerge
	options, we could make decisions what packages should be installed or rebuilt. This is how ``self.digraph`` is used
	in the code.

	**digraph creation**

	The ``depgraph.py`` code creates the digraph by first adding emerge arguments to the digraph as the main parents,
	so if ``@world`` is specified, then the world set is added as the main parents. Then, ``emerge`` will determine
	the dependencies of these packages, and depending on what options are passed to ``emerge``, will look at installed
	packages, binary packages and available ebuilds that could be merged to satisfy dependencies, and these will be
	added as children in the digraph. Children of children will be added as dependencies as needed, depending on the
	depth setting used by ``emerge``.

	As the digraph is created, it is perfectly fine for Packages to be added to the digraph that conflict with one
	another. After the digraph has been fully populated to the necessary depth, code within ``depgraph.py`` will
	identify any conflicts that are modeled within the digraph and determine the best way to handle them.

	"""

	def __init__(self, depgraph, myparams, allow_backtracking, backtrack_parameters):
		self.myparams = myparams.copy()
		self._vdb_loaded = False
		self._allow_backtracking = allow_backtracking
		# Maps nodes to the reasons they were selected for reinstallation.
		self._reinstall_nodes = {}
		# Contains a filtered view of preferred packages that are selected
		# from available repositories.
		self._filtered_trees = {}
		# Contains installed packages and new packages that have been added
		# to the graph.
		self._graph_trees = {}
		# Caches visible packages returned from _select_package, for use in
		# depgraph._iter_atoms_for_pkg() SLOT logic.
		self._visible_pkgs = {}
		#contains the args created by select_files
		self._initial_arg_list = []
		self.digraph = portage.digraph()
		# manages sets added to the graph
		self.sets = {}
		# contains all nodes pulled in by self.sets
		self._set_nodes = set()
		# Contains only Blocker -> Uninstall edges
		self._blocker_uninstalls = digraph()
		# Contains only Package -> Blocker edges
		self._blocker_parents = digraph()
		# Contains only irrelevant Package -> Blocker edges
		self._irrelevant_blockers = digraph()
		# Contains only unsolvable Package -> Blocker edges
		self._unsolvable_blockers = digraph()
		# Contains all Blocker -> Blocked Package edges
		# Do not initialize this until the depgraph _validate_blockers
		# method is called, so that the _in_blocker_conflict method can
		# assert that _validate_blockers has been called first.
		self._blocked_pkgs = None
		# Contains world packages that have been protected from
		# uninstallation but may not have been added to the graph
		# if the graph is not complete yet.
		self._blocked_world_pkgs = {}
		# Contains packages whose dependencies have been traversed.
		# This use used to check if we have accounted for blockers
		# relevant to a package.
		self._traversed_pkg_deps = set()
		self._parent_atoms = {}
		self._slot_conflict_handler = None
		self._circular_dependency_handler = None
		self._serialized_tasks_cache = None
		self._scheduler_graph = None
		self._displayed_list = None
		self._pprovided_args = []
		self._missing_args = []
		self._masked_installed = set()
		self._masked_license_updates = set()
		self._unsatisfied_deps_for_display = []
		self._unsatisfied_blockers_for_display = None
		self._circular_deps_for_display = None
		self._dep_stack = []
		self._dep_disjunctive_stack = []
		self._unsatisfied_deps = []
		self._initially_unsatisfied_deps = []
		self._ignored_deps = []
		self._highest_pkg_cache = {}
		self._highest_pkg_cache_cp_map = {}
		self._flatten_atoms_cache = {}
		self._changed_deps_pkgs = {}

		# Binary packages that have been rejected because their USE
		# didn't match the user's config. It maps packages to a set
		# of flags causing the rejection.
		self.ignored_binaries = {}

		self._needed_unstable_keywords = backtrack_parameters.needed_unstable_keywords
		self._needed_p_mask_changes = backtrack_parameters.needed_p_mask_changes
		self._needed_license_changes = backtrack_parameters.needed_license_changes
		self._needed_use_config_changes = backtrack_parameters.needed_use_config_changes
		self._runtime_pkg_mask = backtrack_parameters.runtime_pkg_mask
		self._slot_operator_replace_installed = backtrack_parameters.slot_operator_replace_installed
		self._prune_rebuilds = backtrack_parameters.prune_rebuilds
		self._need_restart = False
		self._need_config_reload = False
		# For conditions that always require user intervention, such as
		# unsatisfied REQUIRED_USE (currently has no autounmask support).
		self._skip_restart = False
		self._backtrack_infos = {}

		self._buildpkgonly_deps_unsatisfied = False
		self._autounmask = depgraph._frozen_config.myopts.get('--autounmask') != 'n'
		self._displayed_autounmask = False
		self._success_without_autounmask = False
		self._autounmask_backtrack_disabled = False
		self._required_use_unsatisfied = False
		self._traverse_ignored_deps = False
		self._complete_mode = False
		self._slot_operator_deps = {}
		self._installed_sonames = collections.defaultdict(list)
		self._package_tracker = PackageTracker(
			soname_deps=depgraph._frozen_config.soname_deps_enabled)
		# Track missed updates caused by solved conflicts.
		self._conflict_missed_update = collections.defaultdict(dict)

		for myroot in depgraph._frozen_config.trees:
			self.sets[myroot] = _depgraph_sets()
			vardb = depgraph._frozen_config.trees[myroot]["vartree"].dbapi
			# This dbapi instance will model the state that the vdb will
			# have after new packages have been installed.
			fakedb = PackageTrackerDbapiWrapper(myroot, self._package_tracker)

			def graph_tree():
				pass
			graph_tree.dbapi = fakedb
			self._graph_trees[myroot] = {}
			self._filtered_trees[myroot] = {}
			# Substitute the graph tree for the vartree in dep_check() since we
			# want atom selections to be consistent with package selections
			# have already been made.
			self._graph_trees[myroot]["porttree"]   = graph_tree
			self._graph_trees[myroot]["vartree"]    = graph_tree
			self._graph_trees[myroot]["graph_db"]   = graph_tree.dbapi
			self._graph_trees[myroot]["graph"]      = self.digraph
			self._graph_trees[myroot]["want_update_pkg"] = depgraph._want_update_pkg
			self._graph_trees[myroot]["downgrade_probe"] = depgraph._downgrade_probe
			def filtered_tree():
				pass
			filtered_tree.dbapi = _dep_check_composite_db(depgraph, myroot)
			self._filtered_trees[myroot]["porttree"] = filtered_tree
			self._visible_pkgs[myroot] = PackageVirtualDbapi(vardb.settings)

			# Passing in graph_tree as the vartree here could lead to better
			# atom selections in some cases by causing atoms for packages that
			# have been added to the graph to be preferred over other choices.
			# However, it can trigger atom selections that result in
			# unresolvable direct circular dependencies. For example, this
			# happens with gwydion-dylan which depends on either itself or
			# gwydion-dylan-bin. In case gwydion-dylan is not yet installed,
			# gwydion-dylan-bin needs to be selected in order to avoid a
			# an unresolvable direct circular dependency.
			#
			# To solve the problem described above, pass in "graph_db" so that
			# packages that have been added to the graph are distinguishable
			# from other available packages and installed packages. Also, pass
			# the parent package into self._select_atoms() calls so that
			# unresolvable direct circular dependencies can be detected and
			# avoided when possible.
			self._filtered_trees[myroot]["graph_db"] = graph_tree.dbapi
			self._filtered_trees[myroot]["graph"]    = self.digraph
			self._filtered_trees[myroot]["vartree"] = \
				depgraph._frozen_config.trees[myroot]["vartree"]
			self._filtered_trees[myroot]["want_update_pkg"] = depgraph._want_update_pkg
			self._filtered_trees[myroot]["downgrade_probe"] = depgraph._downgrade_probe

			dbs = []
			#               (db, pkg_type, built, installed, db_keys)
			if "remove" in self.myparams:
				# For removal operations, use _dep_check_composite_db
				# for availability and visibility checks. This provides
				# consistency with install operations, so we don't
				# get install/uninstall cycles like in bug #332719.
				self._graph_trees[myroot]["porttree"] = filtered_tree
			else:
				if "--usepkgonly" not in depgraph._frozen_config.myopts:
					portdb = depgraph._frozen_config.trees[myroot]["porttree"].dbapi
					db_keys = list(portdb._aux_cache_keys)
					dbs.append((portdb, "ebuild", False, False, db_keys))

				if "--usepkg" in depgraph._frozen_config.myopts:
					bindb  = depgraph._frozen_config.trees[myroot]["bintree"].dbapi
					db_keys = list(bindb._aux_cache_keys)
					dbs.append((bindb,  "binary", True, False, db_keys))

			vardb  = depgraph._frozen_config.trees[myroot]["vartree"].dbapi
			db_keys = list(depgraph._frozen_config._trees_orig[myroot
				]["vartree"].dbapi._aux_cache_keys)
			dbs.append((vardb, "installed", True, True, db_keys))
			self._filtered_trees[myroot]["dbs"] = dbs

class depgraph(object):

	# Represents the depth of a node that is unreachable from explicit
	# user arguments (or their deep dependencies). Such nodes are pulled
	# in by the _complete_graph method.
	_UNREACHABLE_DEPTH = object()

	pkg_tree_map = RootConfig.pkg_tree_map

	def __init__(self, settings, trees, myopts, myparams, spinner,
		frozen_config=None, backtrack_parameters=BacktrackParameter(), allow_backtracking=False):
		if frozen_config is None:
			frozen_config = _frozen_depgraph_config(settings, trees,
			myopts, myparams, spinner)
		self._frozen_config = frozen_config
		self._dynamic_config = _dynamic_depgraph_config(self, myparams,
			allow_backtracking, backtrack_parameters)
		self._rebuild = _rebuild_config(frozen_config, backtrack_parameters)

		self._select_atoms = self._select_atoms_highest_available
		self._select_package = self._select_pkg_highest_available

		self._event_loop = asyncio._safe_loop()

		self._select_atoms_parent = None

		self.query = UserQuery(myopts).query

	def _index_binpkgs(self):
		for root in self._frozen_config.trees:
			bindb = self._frozen_config.trees[root]["bintree"].dbapi
			if bindb._provides_index:
				# don't repeat this when backtracking
				continue
			root_config = self._frozen_config.roots[root]
			for cpv in self._frozen_config._trees_orig[
				root]["bintree"].dbapi.cpv_all():
				bindb._provides_inject(
					self._pkg(cpv, "binary", root_config))

	def _load_vdb(self):
		"""
		Load installed package metadata if appropriate. This used to be called
		from the constructor, but that wasn't very nice since this procedure
		is slow and it generates spinner output. So, now it's called on-demand
		by various methods when necessary.
		"""

		if self._dynamic_config._vdb_loaded:
			return

		for myroot in self._frozen_config.trees:

			dynamic_deps = "dynamic_deps" in self._dynamic_config.myparams
			preload_installed_pkgs = \
				"--nodeps" not in self._frozen_config.myopts

			fake_vartree = self._frozen_config.trees[myroot]["vartree"]
			if not fake_vartree.dbapi:
				# This needs to be called for the first depgraph, but not for
				# backtracking depgraphs that share the same frozen_config.
				fake_vartree.sync()

				# FakeVartree.sync() populates virtuals, and we want
				# self.pkgsettings to have them populated too.
				self._frozen_config.pkgsettings[myroot] = \
					portage.config(clone=fake_vartree.settings)

			if preload_installed_pkgs:
				vardb = fake_vartree.dbapi

				if not dynamic_deps:
					for pkg in vardb:
						self._dynamic_config._package_tracker.add_installed_pkg(pkg)
						self._add_installed_sonames(pkg)
				else:
					max_jobs = self._frozen_config.myopts.get("--jobs")
					max_load = self._frozen_config.myopts.get("--load-average")
					scheduler = TaskScheduler(
						self._dynamic_deps_preload(fake_vartree),
						max_jobs=max_jobs,
						max_load=max_load,
						event_loop=fake_vartree._portdb._event_loop)
					scheduler.start()
					scheduler.wait()

		self._dynamic_config._vdb_loaded = True

	def _dynamic_deps_preload(self, fake_vartree):
		portdb = fake_vartree._portdb
		for pkg in fake_vartree.dbapi:
			self._spinner_update()
			self._dynamic_config._package_tracker.add_installed_pkg(pkg)
			self._add_installed_sonames(pkg)
			ebuild_path, repo_path = \
				portdb.findname2(pkg.cpv, myrepo=pkg.repo)
			if ebuild_path is None:
				fake_vartree.dynamic_deps_preload(pkg, None)
				continue
			metadata, ebuild_hash = portdb._pull_valid_cache(
				pkg.cpv, ebuild_path, repo_path)
			if metadata is not None:
				fake_vartree.dynamic_deps_preload(pkg, metadata)
			else:
				proc =  EbuildMetadataPhase(cpv=pkg.cpv,
					ebuild_hash=ebuild_hash,
					portdb=portdb, repo_path=repo_path,
					settings=portdb.doebuild_settings)
				proc.addExitListener(
					self._dynamic_deps_proc_exit(pkg, fake_vartree))
				yield proc

	class _dynamic_deps_proc_exit(object):

		__slots__ = ('_pkg', '_fake_vartree')

		def __init__(self, pkg, fake_vartree):
			self._pkg = pkg
			self._fake_vartree = fake_vartree

		def __call__(self, proc):
			metadata = None
			if proc.returncode == os.EX_OK:
				metadata = proc.metadata
			self._fake_vartree.dynamic_deps_preload(self._pkg, metadata)

	def _spinner_update(self):
		if self._frozen_config.spinner:
			self._frozen_config.spinner.update()

	def _compute_abi_rebuild_info(self):
		"""
		Fill self._forced_rebuilds with packages that cause rebuilds.
		"""

		debug = "--debug" in self._frozen_config.myopts
		installed_sonames = self._dynamic_config._installed_sonames
		package_tracker = self._dynamic_config._package_tracker

		# Get all atoms that might have caused a forced rebuild.
		atoms = {}
		for s in self._dynamic_config._initial_arg_list:
			if s.force_reinstall:
				root = s.root_config.root
				atoms.setdefault(root, set()).update(s.pset)

		if debug:
			writemsg_level("forced reinstall atoms:\n",
				level=logging.DEBUG, noiselevel=-1)

			for root in atoms:
				writemsg_level("   root: %s\n" % root,
					level=logging.DEBUG, noiselevel=-1)
				for atom in atoms[root]:
					writemsg_level("      atom: %s\n" % atom,
						level=logging.DEBUG, noiselevel=-1)
			writemsg_level("\n\n",
				level=logging.DEBUG, noiselevel=-1)

		# Go through all slot operator deps and check if one of these deps
		# has a parent that is matched by one of the atoms from above.
		forced_rebuilds = {}

		for root, rebuild_atoms in atoms.items():

			for slot_atom in rebuild_atoms:

				inst_pkg, reinst_pkg = \
					self._select_pkg_from_installed(root, slot_atom)

				if inst_pkg is reinst_pkg or reinst_pkg is None:
					continue

				if (inst_pkg is not None and
					inst_pkg.requires is not None):
					for atom in inst_pkg.requires:
						initial_providers = installed_sonames.get(
							(root, atom))
						if initial_providers is None:
							continue
						final_provider = next(
							package_tracker.match(root, atom),
							None)
						if final_provider:
							continue
						for provider in initial_providers:
							# Find the replacement child.
							child = next((pkg for pkg in
								package_tracker.match(
								root, provider.slot_atom)
								if not pkg.installed), None)

							if child is None:
								continue

							forced_rebuilds.setdefault(
								root, {}).setdefault(
								child, set()).add(inst_pkg)

				# Generate pseudo-deps for any slot-operator deps of
				# inst_pkg. Its deps aren't in _slot_operator_deps
				# because it hasn't been added to the graph, but we
				# are interested in any rebuilds that it triggered.
				built_slot_op_atoms = []
				if inst_pkg is not None:
					selected_atoms = self._select_atoms_probe(
						inst_pkg.root, inst_pkg)
					for atom in selected_atoms:
						if atom.slot_operator_built:
							built_slot_op_atoms.append(atom)

					if not built_slot_op_atoms:
						continue

				# Use a cloned list, since we may append to it below.
				deps = self._dynamic_config._slot_operator_deps.get(
					(root, slot_atom), [])[:]

				if built_slot_op_atoms and reinst_pkg is not None:
					for child in self._dynamic_config.digraph.child_nodes(
						reinst_pkg):

						if child.installed:
							continue

						for atom in built_slot_op_atoms:
							# NOTE: Since atom comes from inst_pkg, and
							# reinst_pkg is the replacement parent, there's
							# no guarantee that atom will completely match
							# child. So, simply use atom.cp and atom.slot
							# for matching.
							if atom.cp != child.cp:
								continue
							if atom.slot and atom.slot != child.slot:
								continue
							deps.append(Dependency(atom=atom, child=child,
								root=child.root, parent=reinst_pkg))

				for dep in deps:
					if dep.child.installed:
						# Find the replacement child.
						child = next((pkg for pkg in
							self._dynamic_config._package_tracker.match(
							dep.root, dep.child.slot_atom)
							if not pkg.installed), None)

						if child is None:
							continue

						inst_child = dep.child

					else:
						child = dep.child
						inst_child = self._select_pkg_from_installed(
							child.root, child.slot_atom)[0]

					# Make sure the child's slot/subslot has changed. If it
					# hasn't, then another child has forced this rebuild.
					if inst_child and inst_child.slot == child.slot and \
						inst_child.sub_slot == child.sub_slot:
						continue

					if dep.parent.installed:
						# Find the replacement parent.
						parent = next((pkg for pkg in
							self._dynamic_config._package_tracker.match(
							dep.parent.root, dep.parent.slot_atom)
							if not pkg.installed), None)

						if parent is None:
							continue

					else:
						parent = dep.parent

					# The child has forced a rebuild of the parent
					forced_rebuilds.setdefault(root, {}
						).setdefault(child, set()).add(parent)

		if debug:
			writemsg_level("slot operator dependencies:\n",
				level=logging.DEBUG, noiselevel=-1)

			for (root, slot_atom), deps in self._dynamic_config._slot_operator_deps.items():
				writemsg_level("   (%s, %s)\n" % \
					(root, slot_atom), level=logging.DEBUG, noiselevel=-1)
				for dep in deps:
					writemsg_level("      parent: %s\n" % dep.parent, level=logging.DEBUG, noiselevel=-1)
					writemsg_level("        child: %s (%s)\n" % (dep.child, dep.priority), level=logging.DEBUG, noiselevel=-1)

			writemsg_level("\n\n",
				level=logging.DEBUG, noiselevel=-1)


			writemsg_level("forced rebuilds:\n",
				level=logging.DEBUG, noiselevel=-1)

			for root in forced_rebuilds:
				writemsg_level("   root: %s\n" % root,
					level=logging.DEBUG, noiselevel=-1)
				for child in forced_rebuilds[root]:
					writemsg_level("      child: %s\n" % child,
						level=logging.DEBUG, noiselevel=-1)
					for parent in forced_rebuilds[root][child]:
						writemsg_level("         parent: %s\n" % parent,
							level=logging.DEBUG, noiselevel=-1)
			writemsg_level("\n\n",
				level=logging.DEBUG, noiselevel=-1)

		self._forced_rebuilds = forced_rebuilds

	def _show_abi_rebuild_info(self):

		if not self._forced_rebuilds:
			return

		writemsg_stdout("\nThe following packages are causing rebuilds:\n\n", noiselevel=-1)

		for root in self._forced_rebuilds:
			for child in self._forced_rebuilds[root]:
				writemsg_stdout("  %s causes rebuilds for:\n" % (child,), noiselevel=-1)
				for parent in self._forced_rebuilds[root][child]:
					writemsg_stdout("    %s\n" % (parent,), noiselevel=-1)

	def _eliminate_ignored_binaries(self):
		"""
		Eliminate any package from self._dynamic_config.ignored_binaries
		for which a more optimal alternative exists.
		"""
		for pkg in list(self._dynamic_config.ignored_binaries):

			for selected_pkg in self._dynamic_config._package_tracker.match(
				pkg.root, pkg.slot_atom):

				if selected_pkg > pkg:
					self._dynamic_config.ignored_binaries.pop(pkg)
					break

				# NOTE: The Package.__ge__ implementation accounts for
				# differences in build_time, so the warning about "ignored"
				# packages will be triggered if both packages are the same
				# version and selected_pkg is not the most recent build.
				if (selected_pkg.type_name == "binary" and
					selected_pkg >= pkg):
					self._dynamic_config.ignored_binaries.pop(pkg)
					break

				if selected_pkg.installed and \
					selected_pkg.cpv == pkg.cpv and \
					selected_pkg.build_time == pkg.build_time:
					# We don't care about ignored binaries when an
					# identical installed instance is selected to
					# fill the slot.
					self._dynamic_config.ignored_binaries.pop(pkg)
					break

	def _ignored_binaries_autounmask_backtrack(self):
		"""
		Check if there are ignored binaries that would have been
		accepted with the current autounmask USE changes.

		@rtype: bool
		@return: True if there are unnecessary rebuilds that
			can be avoided by backtracking
		"""
		if not all([
			self._dynamic_config._allow_backtracking,
			self._dynamic_config._needed_use_config_changes,
			self._dynamic_config.ignored_binaries]):
			return False

		self._eliminate_ignored_binaries()

		# _eliminate_ignored_binaries may have eliminated
		# all of the ignored binaries
		if not self._dynamic_config.ignored_binaries:
			return False

		use_changes = collections.defaultdict(
			functools.partial(collections.defaultdict, dict))
		for pkg, (new_use, changes) in self._dynamic_config._needed_use_config_changes.items():
			if pkg in self._dynamic_config.digraph:
				use_changes[pkg.root][pkg.slot_atom] = (pkg, new_use)

		for pkg in self._dynamic_config.ignored_binaries:
			selected_pkg, new_use = use_changes[pkg.root].get(
				pkg.slot_atom, (None, None))
			if new_use is None:
				continue

			if new_use != pkg.use.enabled:
				continue

			if selected_pkg > pkg:
				continue

			return True

		return False

	def _changed_deps_report(self):
		"""
		Report ebuilds for which the ebuild dependencies have
		changed since the installed instance was built. This is
		completely silent in the following cases:

		  * --changed-deps or --dynamic-deps is enabled
		  * none of the packages with changed deps are in the graph
		"""
		if (self._dynamic_config.myparams.get("changed_deps", "n") == "y" or
			"dynamic_deps" in self._dynamic_config.myparams):
			return

		report_pkgs = []
		for pkg, ebuild in self._dynamic_config._changed_deps_pkgs.items():
			if pkg.repo != ebuild.repo:
				continue
			report_pkgs.append((pkg, ebuild))

		if not report_pkgs:
			return

		# TODO: Detect and report various issues:
		# - packages with unsatisfiable dependencies
		# - packages involved directly in slot or blocker conflicts
		# - direct parents of conflict packages
		# - packages that prevent upgrade of dependencies to latest versions
		graph = self._dynamic_config.digraph
		in_graph = False
		for pkg, ebuild in report_pkgs:
			if pkg in graph:
				in_graph = True
				break

		# Packages with changed deps are harmless if they're not in the
		# graph, so it's safe to silently ignore them. This suppresses
		# noise for the unaffected user, even though some of the changed
		# dependencies might be worthy of revision bumps.
		if not in_graph:
			return

		writemsg("\n%s\n\n" % colorize("WARN",
			"!!! Detected ebuild dependency change(s) without revision bump:"),
			noiselevel=-1)

		for pkg, ebuild in report_pkgs:
			writemsg("    %s::%s" % (pkg.cpv, pkg.repo), noiselevel=-1)
			if pkg.root_config.settings["ROOT"] != "/":
				writemsg(" for %s" % (pkg.root,), noiselevel=-1)
			writemsg("\n", noiselevel=-1)

		msg = []
		if '--quiet' not in self._frozen_config.myopts:
			msg.extend([
			"",
			"NOTE: Refer to the following page for more information about dependency",
			"      change(s) without revision bump:",
			"",
			"          https://wiki.gentoo.org/wiki/Project:Portage/Changed_Deps",
			"",
			"      In order to suppress reports about dependency changes, add",
			"      --changed-deps-report=n to the EMERGE_DEFAULT_OPTS variable in",
			"      '/etc/portage/make.conf'.",
			])

		# Include this message for --quiet mode, since the user may be experiencing
		# problems that are solvable by using --changed-deps.
		msg.extend([
			"",
			"HINT: In order to avoid problems involving changed dependencies, use the",
			"      --changed-deps option to automatically trigger rebuilds when changed",
			"      dependencies are detected. Refer to the emerge man page for more",
			"      information about this option.",
		])

		for line in msg:
			if line:
				line = colorize("INFORM", line)
			writemsg(line + "\n", noiselevel=-1)

	def _show_ignored_binaries(self):
		"""
		Show binaries that have been ignored because their USE didn't
		match the user's config.
		"""
		if not self._dynamic_config.ignored_binaries \
			or '--quiet' in self._frozen_config.myopts:
			return

		self._eliminate_ignored_binaries()

		ignored_binaries = {}

		for pkg in self._dynamic_config.ignored_binaries:
			for reason, info in self._dynamic_config.\
				ignored_binaries[pkg].items():
				ignored_binaries.setdefault(reason, {})[pkg] = info

		if self._dynamic_config.myparams.get(
			"binpkg_respect_use") in ("y", "n"):
			ignored_binaries.pop("respect_use", None)

		if self._dynamic_config.myparams.get(
			"binpkg_changed_deps") in ("y", "n"):
			ignored_binaries.pop("changed_deps", None)

		if not ignored_binaries:
			return

		self._show_merge_list()

		if ignored_binaries.get("respect_use"):
			self._show_ignored_binaries_respect_use(
				ignored_binaries["respect_use"])

		if ignored_binaries.get("changed_deps"):
			self._show_ignored_binaries_changed_deps(
				ignored_binaries["changed_deps"])

	def _show_ignored_binaries_respect_use(self, respect_use):

		writemsg("\n!!! The following binary packages have been ignored " + \
				"due to non matching USE:\n\n", noiselevel=-1)

		for pkg, flags in respect_use.items():
			flag_display = []
			for flag in sorted(flags):
				if flag not in pkg.use.enabled:
					flag = "-" + flag
				flag_display.append(flag)
			flag_display = " ".join(flag_display)
			# The user can paste this line into package.use
			writemsg("    =%s %s" % (pkg.cpv, flag_display), noiselevel=-1)
			if pkg.root_config.settings["ROOT"] != "/":
				writemsg(" # for %s" % (pkg.root,), noiselevel=-1)
			writemsg("\n", noiselevel=-1)

		msg = [
			"",
			"NOTE: The --binpkg-respect-use=n option will prevent emerge",
			"      from ignoring these binary packages if possible.",
			"      Using --binpkg-respect-use=y will silence this warning."
		]

		for line in msg:
			if line:
				line = colorize("INFORM", line)
			writemsg(line + "\n", noiselevel=-1)

	def _show_ignored_binaries_changed_deps(self, changed_deps):

		writemsg("\n!!! The following binary packages have been "
			"ignored due to changed dependencies:\n\n",
			noiselevel=-1)

		for pkg in changed_deps:
			msg = "     %s%s%s" % (pkg.cpv, _repo_separator, pkg.repo)
			if pkg.root_config.settings["ROOT"] != "/":
				msg += " for %s" % pkg.root
			writemsg("%s\n" % msg, noiselevel=-1)

		msg = [
			"",
			"NOTE: The --binpkg-changed-deps=n option will prevent emerge",
			"      from ignoring these binary packages if possible.",
			"      Using --binpkg-changed-deps=y will silence this warning."
		]

		for line in msg:
			if line:
				line = colorize("INFORM", line)
			writemsg(line + "\n", noiselevel=-1)

	def _get_missed_updates(self):

		# In order to minimize noise, show only the highest
		# missed update from each SLOT.
		missed_updates = {}
		for pkg, mask_reasons in \
			chain(self._dynamic_config._runtime_pkg_mask.items(),
				self._dynamic_config._conflict_missed_update.items()):
			if pkg.installed:
				# Exclude installed here since we only
				# want to show available updates.
				continue
			missed_update = True
			any_selected = False
			for chosen_pkg in self._dynamic_config._package_tracker.match(
				pkg.root, pkg.slot_atom):
				any_selected = True
				if chosen_pkg > pkg or (not chosen_pkg.installed and \
					chosen_pkg.version == pkg.version):
					missed_update = False
					break
			if any_selected and missed_update:
				k = (pkg.root, pkg.slot_atom)
				if k in missed_updates:
					other_pkg, mask_type, parent_atoms = missed_updates[k]
					if other_pkg > pkg:
						continue
				for mask_type, parent_atoms in mask_reasons.items():
					if not parent_atoms:
						continue
					missed_updates[k] = (pkg, mask_type, parent_atoms)
					break

		return missed_updates

	def _show_missed_update(self):

		missed_updates = self._get_missed_updates()

		if not missed_updates:
			return

		missed_update_types = {}
		for pkg, mask_type, parent_atoms in missed_updates.values():
			missed_update_types.setdefault(mask_type,
				[]).append((pkg, parent_atoms))

		if '--quiet' in self._frozen_config.myopts and \
			'--debug' not in self._frozen_config.myopts:
			missed_update_types.pop("slot conflict", None)
			missed_update_types.pop("missing dependency", None)

		self._show_missed_update_slot_conflicts(
			missed_update_types.get("slot conflict"))

		self._show_missed_update_unsatisfied_dep(
			missed_update_types.get("missing dependency"))

	def _show_missed_update_unsatisfied_dep(self, missed_updates):

		if not missed_updates:
			return

		self._show_merge_list()
		backtrack_masked = []

		for pkg, parent_atoms in missed_updates:

			try:
				for parent, root, atom in parent_atoms:
					self._show_unsatisfied_dep(root, atom, myparent=parent,
						check_backtrack=True)
			except self._backtrack_mask:
				# This is displayed below in abbreviated form.
				backtrack_masked.append((pkg, parent_atoms))
				continue

			writemsg("\n!!! The following update has been skipped " + \
				"due to unsatisfied dependencies:\n\n", noiselevel=-1)

			writemsg(str(pkg.slot_atom), noiselevel=-1)
			if pkg.root_config.settings["ROOT"] != "/":
				writemsg(" for %s" % (pkg.root,), noiselevel=-1)
			writemsg("\n\n", noiselevel=-1)

			selected_pkg = next(self._dynamic_config._package_tracker.match(
				pkg.root, pkg.slot_atom), None)

			writemsg("  selected: %s\n" % (selected_pkg,), noiselevel=-1)
			writemsg("  skipped: %s (see unsatisfied dependency below)\n"
				% (pkg,), noiselevel=-1)

			for parent, root, atom in parent_atoms:
				self._show_unsatisfied_dep(root, atom, myparent=parent)
				writemsg("\n", noiselevel=-1)

		if backtrack_masked:
			# These are shown in abbreviated form, in order to avoid terminal
			# flooding from mask messages as reported in bug #285832.
			writemsg("\n!!! The following update(s) have been skipped " + \
				"due to unsatisfied dependencies\n" + \
				"!!! triggered by backtracking:\n\n", noiselevel=-1)
			for pkg, parent_atoms in backtrack_masked:
				writemsg(str(pkg.slot_atom), noiselevel=-1)
				if pkg.root_config.settings["ROOT"] != "/":
					writemsg(" for %s" % (pkg.root,), noiselevel=-1)
				writemsg("\n", noiselevel=-1)

	def _show_missed_update_slot_conflicts(self, missed_updates):

		if not missed_updates:
			return

		self._show_merge_list()
		msg = []
		msg.append("\nWARNING: One or more updates/rebuilds have been " + \
			"skipped due to a dependency conflict:\n\n")

		indent = "  "
		for pkg, parent_atoms in missed_updates:
			msg.append(str(pkg.slot_atom))
			if pkg.root_config.settings["ROOT"] != "/":
				msg.append(" for %s" % (pkg.root,))
			msg.append("\n\n")

			msg.append(indent)
			msg.append(str(pkg))
			msg.append(" conflicts with\n")

			for parent, atom in parent_atoms:
				if isinstance(parent,
					(PackageArg, AtomArg)):
					# For PackageArg and AtomArg types, it's
					# redundant to display the atom attribute.
					msg.append(2*indent)
					msg.append(str(parent))
					msg.append("\n")
				else:
					# Display the specific atom from SetArg or
					# Package types.
					atom, marker = format_unmatched_atom(
						pkg, atom, self._pkg_use_enabled)

					msg.append(2*indent)
					msg.append("%s required by %s\n" % (atom, parent))
					msg.append(2*indent)
					msg.append(marker)
					msg.append("\n")
			msg.append("\n")

		writemsg("".join(msg), noiselevel=-1)

	def _show_slot_collision_notice(self):
		"""Show an informational message advising the user to mask one of the
		the packages. In some cases it may be possible to resolve this
		automatically, but support for backtracking (removal nodes that have
		already been selected) will be required in order to handle all possible
		cases.
		"""

		if not any(self._dynamic_config._package_tracker.slot_conflicts()):
			return

		self._show_merge_list()

		if self._dynamic_config._slot_conflict_handler is None:
			self._dynamic_config._slot_conflict_handler = slot_conflict_handler(self)
		handler = self._dynamic_config._slot_conflict_handler

		conflict = handler.get_conflict()
		writemsg(conflict, noiselevel=-1)

		explanation = handler.get_explanation()
		if explanation:
			writemsg(explanation, noiselevel=-1)
			return

		if "--quiet" in self._frozen_config.myopts:
			return

		msg = []
		msg.append("It may be possible to solve this problem ")
		msg.append("by using package.mask to prevent one of ")
		msg.append("those packages from being selected. ")
		msg.append("However, it is also possible that conflicting ")
		msg.append("dependencies exist such that they are impossible to ")
		msg.append("satisfy simultaneously.  If such a conflict exists in ")
		msg.append("the dependencies of two different packages, then those ")
		msg.append("packages can not be installed simultaneously.")
		backtrack_opt = self._frozen_config.myopts.get('--backtrack')
		if not self._dynamic_config._allow_backtracking and \
			(backtrack_opt is None or \
			(backtrack_opt > 0 and backtrack_opt < 30)):
			msg.append(" You may want to try a larger value of the ")
			msg.append("--backtrack option, such as --backtrack=30, ")
			msg.append("in order to see if that will solve this conflict ")
			msg.append("automatically.")

		for line in textwrap.wrap(''.join(msg), 70):
			writemsg(line + '\n', noiselevel=-1)
		writemsg('\n', noiselevel=-1)

		msg = []
		msg.append("For more information, see MASKED PACKAGES ")
		msg.append("section in the emerge man page or refer ")
		msg.append("to the Gentoo Handbook.")
		for line in textwrap.wrap(''.join(msg), 70):
			writemsg(line + '\n', noiselevel=-1)
		writemsg('\n', noiselevel=-1)

	def _solve_non_slot_operator_slot_conflicts(self):
		"""
		This function solves slot conflicts which can
		be solved by simply choosing one of the conflicting
		and removing all the other ones.
		It is able to solve somewhat more complex cases where
		conflicts can only be solved simultaniously.
		"""
		debug = "--debug" in self._frozen_config.myopts

		# List all conflicts. Ignore those that involve slot operator rebuilds
		# as the logic there needs special slot conflict behavior which isn't
		# provided by this function.
		conflicts = []
		for conflict in self._dynamic_config._package_tracker.slot_conflicts():
			slot_key = conflict.root, conflict.atom
			if slot_key not in self._dynamic_config._slot_operator_replace_installed:
				conflicts.append(conflict)

		if not conflicts:
			return

		if debug:
			writemsg_level(
				"\n!!! Slot conflict handler started.\n",
				level=logging.DEBUG, noiselevel=-1)

		# Get a set of all conflicting packages.
		conflict_pkgs = set()
		for conflict in conflicts:
			conflict_pkgs.update(conflict)

		# Get the list of other packages which are only
		# required by conflict packages.
		indirect_conflict_candidates = set()
		for pkg in conflict_pkgs:
			indirect_conflict_candidates.update(self._dynamic_config.digraph.child_nodes(pkg))
		indirect_conflict_candidates.difference_update(conflict_pkgs)

		indirect_conflict_pkgs = set()
		while indirect_conflict_candidates:
			pkg = indirect_conflict_candidates.pop()

			only_conflict_parents = True
			for parent, atom in self._dynamic_config._parent_atoms.get(pkg, []):
				if parent not in conflict_pkgs and parent not in indirect_conflict_pkgs:
					only_conflict_parents = False
					break
			if not only_conflict_parents:
				continue

			indirect_conflict_pkgs.add(pkg)
			for child in self._dynamic_config.digraph.child_nodes(pkg):
				if child in conflict_pkgs or child in indirect_conflict_pkgs:
					continue
				indirect_conflict_candidates.add(child)

		# Create a graph containing the conflict packages
		# and a special 'non_conflict_node' that represents
		# all non-conflict packages.
		conflict_graph = digraph()

		non_conflict_node = "(non-conflict package)"
		conflict_graph.add(non_conflict_node, None)

		for pkg in chain(conflict_pkgs, indirect_conflict_pkgs):
			conflict_graph.add(pkg, None)

		# Add parent->child edges for each conflict package.
		# Parents, which aren't conflict packages are represented
		# by 'non_conflict_node'.
		# If several conflicting packages are matched, but not all,
		# add a tuple with the matched packages to the graph.
		class or_tuple(tuple):
			"""
			Helper class for debug printing.
			"""
			def __str__(self):
				return "(%s)" % ",".join(str(pkg) for pkg in self)

		non_matching_forced = set()
		for conflict in conflicts:
			if debug:
				writemsg_level("   conflict:\n", level=logging.DEBUG, noiselevel=-1)
				writemsg_level("      root: %s\n" % conflict.root, level=logging.DEBUG, noiselevel=-1)
				writemsg_level("      atom: %s\n" % conflict.atom, level=logging.DEBUG, noiselevel=-1)
				for pkg in conflict:
					writemsg_level("      pkg: %s\n" % pkg, level=logging.DEBUG, noiselevel=-1)

			all_parent_atoms = set()
			highest_pkg = None
			inst_pkg = None
			for pkg in conflict:
				if pkg.installed:
					inst_pkg = pkg
				if highest_pkg is None or highest_pkg < pkg:
					highest_pkg = pkg
				all_parent_atoms.update(
					self._dynamic_config._parent_atoms.get(pkg, []))

			for parent, atom in all_parent_atoms:
				is_arg_parent = (inst_pkg is not None and
					not self._want_installed_pkg(inst_pkg))
				is_non_conflict_parent = parent not in conflict_pkgs and \
					parent not in indirect_conflict_pkgs

				if debug:
					writemsg_level("      parent: %s\n" % parent, level=logging.DEBUG, noiselevel=-1)
					writemsg_level("      arg, non-conflict: %s, %s\n" % (is_arg_parent, is_non_conflict_parent),
						level=logging.DEBUG, noiselevel=-1)
					writemsg_level("         atom: %s\n" % atom, level=logging.DEBUG, noiselevel=-1)

				if is_non_conflict_parent:
					parent = non_conflict_node

				matched = []
				for pkg in conflict:
					if (pkg is highest_pkg and
						not highest_pkg.installed and
						inst_pkg is not None and
						inst_pkg.sub_slot != highest_pkg.sub_slot and
						not self._downgrade_probe(highest_pkg)):
						# If an upgrade is desired, force the highest
						# version into the graph (bug #531656).
						non_matching_forced.add(highest_pkg)

					if atom.match(pkg.with_use(
						self._pkg_use_enabled(pkg))) and \
						not (is_arg_parent and pkg.installed):
						matched.append(pkg)

				if debug:
					for match in matched:
						writemsg_level("         match: %s\n" % match, level=logging.DEBUG, noiselevel=-1)

				if len(matched) > 1:
					# Even if all packages match, this parent must still
					# be added to the conflict_graph. Otherwise, we risk
					# removing all of these packages from the depgraph,
					# which could cause a missed update (bug #522084).
					conflict_graph.add(or_tuple(matched), parent)
				elif len(matched) == 1:
					conflict_graph.add(matched[0], parent)
				else:
					# This typically means that autounmask broke a
					# USE-dep, but it could also be due to the slot
					# not matching due to multislot (bug #220341).
					# Either way, don't try to solve this conflict.
					# Instead, force them all into the graph so that
					# they are protected from removal.
					non_matching_forced.update(conflict)
					if debug:
						for pkg in conflict:
							writemsg_level("         non-match: %s\n" % pkg,
								level=logging.DEBUG, noiselevel=-1)

		for pkg in indirect_conflict_pkgs:
			for parent, atom in self._dynamic_config._parent_atoms.get(pkg, []):
				if parent not in conflict_pkgs and \
					parent not in indirect_conflict_pkgs:
					parent = non_conflict_node
				conflict_graph.add(pkg, parent)

		if debug:
			writemsg_level(
				"\n!!! Slot conflict graph:\n",
				level=logging.DEBUG, noiselevel=-1)
			conflict_graph.debug_print()

		# Now select required packages. Collect them in the
		# 'forced' set.
		forced = set([non_conflict_node])
		forced.update(non_matching_forced)
		unexplored = set([non_conflict_node])
		# or_tuples get special handling. We first explore
		# all packages in the hope of having forced one of
		# the packages in the tuple. This way we don't have
		# to choose one.
		unexplored_tuples = set()
		explored_nodes = set()

		while unexplored:
			while True:
				try:
					node = unexplored.pop()
				except KeyError:
					break
				for child in conflict_graph.child_nodes(node):
					# Don't explore a node more than once, in order
					# to avoid infinite recursion. The forced set
					# cannot be used for this purpose, since it can
					# contain unexplored nodes from non_matching_forced.
					if child in explored_nodes:
						continue
					explored_nodes.add(child)
					forced.add(child)
					if isinstance(child, Package):
						unexplored.add(child)
					else:
						unexplored_tuples.add(child)

			# Now handle unexplored or_tuples. Move on with packages
			# once we had to choose one.
			while unexplored_tuples:
				nodes = unexplored_tuples.pop()
				if any(node in forced for node in nodes):
					# At least one of the packages in the
					# tuple is already forced, which means the
					# dependency represented by this tuple
					# is satisfied.
					continue

				# We now have to choose one of packages in the tuple.
				# In theory one could solve more conflicts if we'd be
				# able to try different choices here, but that has lots
				# of other problems. For now choose the package that was
				# pulled first, as this should be the most desirable choice
				# (otherwise it wouldn't have been the first one).
				forced.add(nodes[0])
				unexplored.add(nodes[0])
				break

		# Remove 'non_conflict_node' and or_tuples from 'forced'.
		forced = set(pkg for pkg in forced if isinstance(pkg, Package))

		# Add dependendencies of forced packages.
		stack = list(forced)
		traversed = set()
		while stack:
			pkg = stack.pop()
			traversed.add(pkg)
			for child in conflict_graph.child_nodes(pkg):
				if (isinstance(child, Package) and
					child not in traversed):
					forced.add(child)
					stack.append(child)

		non_forced = set(pkg for pkg in conflict_pkgs if pkg not in forced)

		if debug:
			writemsg_level(
				"\n!!! Slot conflict solution:\n",
				level=logging.DEBUG, noiselevel=-1)
			for conflict in conflicts:
				writemsg_level(
					"   Conflict: (%s, %s)\n" % (conflict.root, conflict.atom),
					level=logging.DEBUG, noiselevel=-1)
				for pkg in conflict:
					if pkg in forced:
						writemsg_level(
							"      keep:   %s\n" % pkg,
							level=logging.DEBUG, noiselevel=-1)
					else:
						writemsg_level(
							"      remove: %s\n" % pkg,
							level=logging.DEBUG, noiselevel=-1)

		broken_packages = set()
		for pkg in non_forced:
			for parent, atom in self._dynamic_config._parent_atoms.get(pkg, []):
				if isinstance(parent, Package) and parent not in non_forced:
					# Non-forcing set args are expected to be a parent of all
					# packages in the conflict.
					broken_packages.add(parent)
			self._remove_pkg(pkg)

		# Process the dependencies of choosen conflict packages
		# again to  properly account for blockers.
		broken_packages.update(forced)

		# Filter out broken packages which have been removed during
		# recursive removal in self._remove_pkg.
		broken_packages = list(pkg for pkg in broken_packages if pkg in broken_packages \
			if self._dynamic_config._package_tracker.contains(pkg, installed=False))

		self._dynamic_config._dep_stack.extend(broken_packages)

		if broken_packages:
			# Process dependencies. This cannot fail because we just ensured that
			# the remaining packages satisfy all dependencies.
			self._create_graph()

		# Record missed updates.
		for conflict in conflicts:
			if not any(pkg in non_forced for pkg in conflict):
				continue
			for pkg in conflict:
				if pkg not in non_forced:
					continue

				for other in conflict:
					if other is pkg:
						continue

					for parent, atom in self._dynamic_config._parent_atoms.get(other, []):
						if not atom.match(pkg.with_use(self._pkg_use_enabled(pkg))):
							self._dynamic_config._conflict_missed_update[pkg].setdefault(
								"slot conflict", set())
							self._dynamic_config._conflict_missed_update[pkg]["slot conflict"].add(
								(parent, atom))


	def _process_slot_conflicts(self):
		"""
		If there are any slot conflicts and backtracking is enabled,
		_complete_graph should complete the graph before this method
		is called, so that all relevant reverse dependencies are
		available for use in backtracking decisions.
		"""

		self._solve_non_slot_operator_slot_conflicts()

		if not self._validate_blockers():
			# Blockers don't trigger the _skip_restart flag, since
			# backtracking may solve blockers when it solves slot
			# conflicts (or by blind luck).
			raise self._unknown_internal_error()

		# Both _process_slot_conflict and _slot_operator_trigger_reinstalls
		# can call _slot_operator_update_probe, which requires that
		# self._dynamic_config._blocked_pkgs has been initialized by a
		# call to the _validate_blockers method.
		for conflict in self._dynamic_config._package_tracker.slot_conflicts():
			self._process_slot_conflict(conflict)

		if self._dynamic_config._allow_backtracking:
			self._slot_operator_trigger_reinstalls()

	def _process_slot_conflict(self, conflict):
		"""
		Process slot conflict data to identify specific atoms which
		lead to conflict. These atoms only match a subset of the
		packages that have been pulled into a given slot.
		"""
		root = conflict.root
		slot_atom = conflict.atom
		slot_nodes = conflict.pkgs

		debug = "--debug" in self._frozen_config.myopts

		slot_parent_atoms = set()
		for pkg in slot_nodes:
			parent_atoms = self._dynamic_config._parent_atoms.get(pkg)
			if not parent_atoms:
				continue
			slot_parent_atoms.update(parent_atoms)

		conflict_pkgs = []
		conflict_atoms = {}
		for pkg in slot_nodes:

			if self._dynamic_config._allow_backtracking and \
				pkg in self._dynamic_config._runtime_pkg_mask:
				if debug:
					writemsg_level(
						"!!! backtracking loop detected: %s %s\n" % \
						(pkg,
						self._dynamic_config._runtime_pkg_mask[pkg]),
						level=logging.DEBUG, noiselevel=-1)

			parent_atoms = self._dynamic_config._parent_atoms.get(pkg)
			if parent_atoms is None:
				parent_atoms = set()
				self._dynamic_config._parent_atoms[pkg] = parent_atoms

			all_match = True
			for parent_atom in slot_parent_atoms:
				if parent_atom in parent_atoms:
					continue
				parent, atom = parent_atom
				if atom.match(pkg.with_use(self._pkg_use_enabled(pkg))):
					parent_atoms.add(parent_atom)
				else:
					all_match = False
					conflict_atoms.setdefault(parent_atom, set()).add(pkg)

			if not all_match:
				conflict_pkgs.append(pkg)

		if conflict_pkgs and \
			self._dynamic_config._allow_backtracking and \
			not self._accept_blocker_conflicts():
			remaining = []
			for pkg in conflict_pkgs:
				if self._slot_conflict_backtrack_abi(pkg,
					slot_nodes, conflict_atoms):
					backtrack_infos = self._dynamic_config._backtrack_infos
					config = backtrack_infos.setdefault("config", {})
					config.setdefault("slot_conflict_abi", set()).add(pkg)
				else:
					remaining.append(pkg)
			if remaining:
				self._slot_confict_backtrack(root, slot_atom,
					slot_parent_atoms, remaining)

	def _slot_confict_backtrack(self, root, slot_atom,
		all_parents, conflict_pkgs):

		debug = "--debug" in self._frozen_config.myopts
		existing_node = next(self._dynamic_config._package_tracker.match(
			root, slot_atom, installed=False))
		if existing_node not in conflict_pkgs:
			# Even though all parent atoms match existing_node,
			# consider masking it in order to avoid a missed update
			# as in bug 692746.
			conflict_pkgs.append(existing_node)
		# In order to avoid a missed update, first mask lower versions
		# that conflict with higher versions (the backtracker visits
		# these in reverse order).
		conflict_pkgs.sort(reverse=True)
		backtrack_data = []
		for to_be_masked in conflict_pkgs:
			# For missed update messages, find out which
			# atoms matched to_be_selected that did not
			# match to_be_masked.
			parent_atoms = \
				self._dynamic_config._parent_atoms.get(to_be_masked, set())
			conflict_atoms = set(parent_atom for parent_atom in all_parents \
				if parent_atom not in parent_atoms)
			backtrack_data.append((to_be_masked, conflict_atoms))

		to_be_masked = backtrack_data[-1][0]

		self._dynamic_config._backtrack_infos.setdefault(
			"slot conflict", []).append(backtrack_data)
		self._dynamic_config._need_restart = True
		if debug:
			msg = []
			msg.append("")
			msg.append("")
			msg.append("backtracking due to slot conflict:")
			msg.append("   first package:  %s" % existing_node)
			msg.append("  package to mask: %s" % to_be_masked)
			msg.append("      slot: %s" % slot_atom)
			msg.append("   parents: %s" % ", ".join( \
				"(%s, '%s')" % (ppkg, atom) for ppkg, atom in all_parents))
			msg.append("")
			writemsg_level("".join("%s\n" % l for l in msg),
				noiselevel=-1, level=logging.DEBUG)

	def _slot_conflict_backtrack_abi(self, pkg, slot_nodes, conflict_atoms):
		"""
		If one or more conflict atoms have a slot/sub-slot dep that can be resolved
		by rebuilding the parent package, then schedule the rebuild via
		backtracking, and return True. Otherwise, return False.
		"""

		found_update = False
		for parent_atom, conflict_pkgs in conflict_atoms.items():
			parent, atom = parent_atom

			if not isinstance(parent, Package):
				continue

			if not parent.built:
				continue

			if not atom.soname and not (
				atom.package and atom.slot_operator_built):
				continue

			for other_pkg in slot_nodes:
				if other_pkg in conflict_pkgs:
					continue

				dep = Dependency(atom=atom, child=other_pkg,
					parent=parent, root=pkg.root)

				new_dep = \
					self._slot_operator_update_probe_slot_conflict(dep)
				if new_dep is not None:
					self._slot_operator_update_backtrack(dep,
						new_dep=new_dep)
					found_update = True

		return found_update

	def _slot_change_probe(self, dep):
		"""
		@rtype: bool
		@return: True if dep.child should be rebuilt due to a change
			in sub-slot (without revbump, as in bug #456208).
		"""
		if not (isinstance(dep.parent, Package) and \
			not dep.parent.built and dep.child.built):
			return None

		root_config = self._frozen_config.roots[dep.root]
		matches = []
		try:
			matches.append(self._pkg(dep.child.cpv, "ebuild",
				root_config, myrepo=dep.child.repo))
		except PackageNotFound:
			pass

		for unbuilt_child in chain(matches,
			self._iter_match_pkgs(root_config, "ebuild",
			Atom("=%s" % (dep.child.cpv,)))):
			if unbuilt_child in self._dynamic_config._runtime_pkg_mask:
				continue
			if self._frozen_config.excluded_pkgs.findAtomForPackage(
				unbuilt_child,
				modified_use=self._pkg_use_enabled(unbuilt_child)):
				continue
			if not self._pkg_visibility_check(unbuilt_child):
				continue
			break
		else:
			return None

		if unbuilt_child.slot == dep.child.slot and \
			unbuilt_child.sub_slot == dep.child.sub_slot:
			return None

		return unbuilt_child

	def _slot_change_backtrack(self, dep, new_child_slot):
		child = dep.child
		if "--debug" in self._frozen_config.myopts:
			msg = []
			msg.append("")
			msg.append("")
			msg.append("backtracking due to slot/sub-slot change:")
			msg.append("   child package:  %s" % child)
			msg.append("      child slot:  %s/%s" %
				(child.slot, child.sub_slot))
			msg.append("       new child:  %s" % new_child_slot)
			msg.append("  new child slot:  %s/%s" %
				(new_child_slot.slot, new_child_slot.sub_slot))
			msg.append("   parent package: %s" % dep.parent)
			msg.append("   atom: %s" % dep.atom)
			msg.append("")
			writemsg_level("\n".join(msg),
				noiselevel=-1, level=logging.DEBUG)
		backtrack_infos = self._dynamic_config._backtrack_infos
		config = backtrack_infos.setdefault("config", {})

		# mask unwanted binary packages if necessary
		masks = {}
		if not child.installed:
			masks.setdefault(dep.child, {})["slot_operator_mask_built"] = None
		if masks:
			config.setdefault("slot_operator_mask_built", {}).update(masks)

		# trigger replacement of installed packages if necessary
		reinstalls = set()
		if child.installed:
			replacement_atom = self._replace_installed_atom(child)
			if replacement_atom is not None:
				reinstalls.add((child.root, replacement_atom))
		if reinstalls:
			config.setdefault("slot_operator_replace_installed",
				set()).update(reinstalls)

		self._dynamic_config._need_restart = True

	def _slot_operator_update_backtrack(self, dep, new_child_slot=None,
		new_dep=None):
		if new_child_slot is None:
			child = dep.child
		else:
			child = new_child_slot
		if "--debug" in self._frozen_config.myopts:
			msg = []
			msg.append("")
			msg.append("")
			msg.append("backtracking due to missed slot abi update:")
			msg.append("   child package:  %s" % child)
			if new_child_slot is not None:
				msg.append("   new child slot package:  %s" % new_child_slot)
			msg.append("   parent package: %s" % dep.parent)
			if new_dep is not None:
				msg.append("   new parent pkg: %s" % new_dep.parent)
			msg.append("   atom: %s" % dep.atom)
			msg.append("")
			writemsg_level("\n".join(msg),
				noiselevel=-1, level=logging.DEBUG)
		backtrack_infos = self._dynamic_config._backtrack_infos
		config = backtrack_infos.setdefault("config", {})

		# mask unwanted binary packages if necessary
		abi_masks = {}
		if new_child_slot is None:
			if not child.installed:
				abi_masks.setdefault(child, {})["slot_operator_mask_built"] = None
		if not dep.parent.installed:
			abi_masks.setdefault(dep.parent, {})["slot_operator_mask_built"] = None
		if abi_masks:
			config.setdefault("slot_operator_mask_built", {}).update(abi_masks)

		# trigger replacement of installed packages if necessary
		abi_reinstalls = set()
		if dep.parent.installed:
			if new_dep is not None:
				replacement_atom = new_dep.parent.slot_atom
			else:
				replacement_atom = self._replace_installed_atom(dep.parent)
			if replacement_atom is not None:
				abi_reinstalls.add((dep.parent.root, replacement_atom))
		if new_child_slot is None and child.installed:
			replacement_atom = self._replace_installed_atom(child)
			if replacement_atom is not None:
				abi_reinstalls.add((child.root, replacement_atom))
		if abi_reinstalls:
			config.setdefault("slot_operator_replace_installed",
				set()).update(abi_reinstalls)

		self._dynamic_config._need_restart = True

	def _slot_operator_update_probe_slot_conflict(self, dep):
		new_dep = self._slot_operator_update_probe(dep, slot_conflict=True)

		if new_dep is not None:
			return new_dep

		if self._dynamic_config._autounmask is True:

			for autounmask_level in self._autounmask_levels():

				new_dep = self._slot_operator_update_probe(dep,
					slot_conflict=True, autounmask_level=autounmask_level)

				if new_dep is not None:
					return new_dep

		return None

	def _slot_operator_update_probe(self, dep, new_child_slot=False,
		slot_conflict=False, autounmask_level=None):
		"""
		slot/sub-slot := operators tend to prevent updates from getting pulled in,
		since installed packages pull in packages with the slot/sub-slot that they
		were built against. Detect this case so that we can schedule rebuilds
		and reinstalls when appropriate.
		NOTE: This function only searches for updates that involve upgrades
			to higher versions, since the logic required to detect when a
			downgrade would be desirable is not implemented.
		"""

		if dep.child.installed and \
			self._frozen_config.excluded_pkgs.findAtomForPackage(dep.child,
			modified_use=self._pkg_use_enabled(dep.child)):
			return None

		if dep.parent.installed and \
			self._frozen_config.excluded_pkgs.findAtomForPackage(dep.parent,
			modified_use=self._pkg_use_enabled(dep.parent)):
			return None

		debug = "--debug" in self._frozen_config.myopts
		selective = "selective" in self._dynamic_config.myparams
		want_downgrade = None
		want_downgrade_parent = None

		def check_reverse_dependencies(existing_pkg, candidate_pkg,
			replacement_parent=None):
			"""
			Check if candidate_pkg satisfies all of existing_pkg's non-
			slot operator parents.
			"""
			built_slot_operator_parents = set()
			for parent, atom in self._dynamic_config._parent_atoms.get(existing_pkg, []):
				if atom.soname or atom.slot_operator_built:
					built_slot_operator_parents.add(parent)

			for parent, atom in self._dynamic_config._parent_atoms.get(existing_pkg, []):
				if isinstance(parent, Package):
					if parent in built_slot_operator_parents:
						# This parent may need to be rebuilt, so its
						# dependencies aren't necessarily relevant.
						continue

					if replacement_parent is not None and \
						(replacement_parent.slot_atom == parent.slot_atom
						or replacement_parent.cpv == parent.cpv):
						# This parent is irrelevant because we intend to
						# replace it with replacement_parent.
						continue

					if any(pkg is not parent and
						(pkg.slot_atom == parent.slot_atom or
						pkg.cpv == parent.cpv) for pkg in
						self._dynamic_config._package_tracker.match(
						parent.root, Atom(parent.cp))):
						# This parent may need to be eliminated due to a
						# slot conflict,  so its dependencies aren't
						# necessarily relevant.
						continue

					if (not self._too_deep(parent.depth) and
						not self._frozen_config.excluded_pkgs.
						findAtomForPackage(parent,
						modified_use=self._pkg_use_enabled(parent))):
						# Check for common reasons that the parent's
						# dependency might be irrelevant.
						if self._upgrade_available(parent):
							# This parent could be replaced by
							# an upgrade (bug 584626).
							continue
						if parent.installed and self._in_blocker_conflict(parent):
							# This parent could be uninstalled in order
							# to solve a blocker conflict (bug 612772).
							continue
						if self._dynamic_config.digraph.has_edge(parent,
							existing_pkg):
							# There is a direct circular dependency between
							# parent and existing_pkg. This type of
							# relationship tends to prevent updates
							# of packages (bug 612874). Since candidate_pkg
							# is available, we risk a missed update if we
							# don't try to eliminate this parent from the
							# graph. Therefore, we give candidate_pkg a
							# chance, and assume that it will be masked
							# by backtracking if necessary.
							continue

				atom_set = InternalPackageSet(initial_atoms=(atom,),
					allow_repo=True)
				if not atom_set.findAtomForPackage(candidate_pkg,
					modified_use=self._pkg_use_enabled(candidate_pkg)):
					return False
			return True


		for replacement_parent in self._iter_similar_available(dep.parent,
			dep.parent.slot_atom, autounmask_level=autounmask_level):

			if replacement_parent is dep.parent:
				continue

			if replacement_parent < dep.parent:
				if want_downgrade_parent is None:
					want_downgrade_parent = self._downgrade_probe(
						dep.parent)
				if not want_downgrade_parent:
					continue

			if not check_reverse_dependencies(dep.parent, replacement_parent):
				continue

			selected_atoms = None

			try:
				atoms = self._flatten_atoms(replacement_parent,
					self._pkg_use_enabled(replacement_parent))
			except InvalidDependString:
				continue

			if replacement_parent.requires is not None:
				atoms = list(atoms)
				atoms.extend(replacement_parent.requires)

			# List of list of child,atom pairs for each atom.
			replacement_candidates = []
			# Set of all packages all atoms can agree on.
			all_candidate_pkgs = None

			for atom in atoms:
				# The _select_atoms_probe method is expensive, so initialization
				# of this variable is only performed on demand.
				atom_not_selected = None

				if not atom.package:
					unevaluated_atom = None
					if atom.match(dep.child):
						# We are searching for a replacement_parent
						# atom that will pull in a different child,
						# so continue checking the rest of the atoms.
						continue
				else:

					if atom.blocker or \
						atom.cp != dep.child.cp:
						continue

					# Discard USE deps, we're only searching for an
					# approximate pattern, and dealing with USE states
					# is too complex for this purpose.
					unevaluated_atom = atom.unevaluated_atom
					atom = atom.without_use

					if replacement_parent.built and \
						portage.dep._match_slot(atom, dep.child):
						# We are searching for a replacement_parent
						# atom that will pull in a different child,
						# so continue checking the rest of the atoms.
						continue

				candidate_pkg_atoms = []
				candidate_pkgs = []
				for pkg in self._iter_similar_available(
					dep.child, atom):
					if (dep.atom.package and
						pkg.slot == dep.child.slot and
						pkg.sub_slot == dep.child.sub_slot):
						# If slot/sub-slot is identical, then there's
						# no point in updating.
						continue
					if new_child_slot:
						if pkg.slot == dep.child.slot:
							continue
						if pkg < dep.child:
							# the new slot only matters if the
							# package version is higher
							continue
					else:
						if pkg.slot != dep.child.slot:
							continue
						if pkg < dep.child:
							if want_downgrade is None:
								want_downgrade = self._downgrade_probe(dep.child)
							# be careful not to trigger a rebuild when
							# the only version available with a
							# different slot_operator is an older version
							if not want_downgrade:
								continue
						if pkg.version == dep.child.version and not dep.child.built:
							continue

					insignificant = False
					if not slot_conflict and \
						selective and \
						dep.parent.installed and \
						dep.child.installed and \
						dep.parent >= replacement_parent and \
						dep.child.cpv == pkg.cpv:
						# Then can happen if the child's sub-slot changed
						# without a revision bump. The sub-slot change is
						# considered insignificant until one of its parent
						# packages needs to be rebuilt (which may trigger a
						# slot conflict).
						insignificant = True

					if (not insignificant and
						unevaluated_atom is not None):
						# Evaluate USE conditionals and || deps, in order
						# to see if this atom is really desirable, since
						# otherwise we may trigger an undesirable rebuild
						# as in bug #460304.
						if selected_atoms is None:
							selected_atoms = self._select_atoms_probe(
								dep.child.root, replacement_parent)
						atom_not_selected = unevaluated_atom not in selected_atoms
						if atom_not_selected:
							break

					if not insignificant and \
						check_reverse_dependencies(dep.child, pkg,
							replacement_parent=replacement_parent):

						candidate_pkg_atoms.append(
							(pkg, unevaluated_atom or atom))
						candidate_pkgs.append(pkg)

				# When unevaluated_atom is None, it means that atom is
				# an soname atom which is unconditionally selected, and
				# _select_atoms_probe is not applicable.
				if atom_not_selected is None and unevaluated_atom is not None:
					if selected_atoms is None:
						selected_atoms = self._select_atoms_probe(
							dep.child.root, replacement_parent)
					atom_not_selected = unevaluated_atom not in selected_atoms

				if atom_not_selected:
					continue
				replacement_candidates.append(candidate_pkg_atoms)
				if all_candidate_pkgs is None:
					all_candidate_pkgs = set(candidate_pkgs)
				else:
					all_candidate_pkgs.intersection_update(candidate_pkgs)

			if not all_candidate_pkgs:
				# If the atoms that connect parent and child can't agree on
				# any replacement child, we can't do anything.
				continue

			# Now select one of the pkgs as replacement. This is as easy as
			# selecting the highest version.
			# The more complicated part is to choose an atom for the
			# new Dependency object. Choose the one which ranked the selected
			# parent highest.
			selected = None
			for candidate_pkg_atoms in replacement_candidates:
				for i, (pkg, atom) in enumerate(candidate_pkg_atoms):
					if pkg not in all_candidate_pkgs:
						continue
					if selected is None or \
						selected[0] < pkg or \
						(selected[0] is pkg and i < selected[2]):
						selected = (pkg, atom, i)

			if debug:
				msg = []
				msg.append("")
				msg.append("")
				msg.append("slot_operator_update_probe:")
				msg.append("   existing child package:  %s" % dep.child)
				msg.append("   existing parent package: %s" % dep.parent)
				msg.append("   new child package:  %s" % selected[0])
				msg.append("   new parent package: %s" % replacement_parent)
				msg.append("")
				writemsg_level("\n".join(msg),
					noiselevel=-1, level=logging.DEBUG)

			return Dependency(parent=replacement_parent,
				child=selected[0], atom=selected[1])

		if debug:
			msg = []
			msg.append("")
			msg.append("")
			msg.append("slot_operator_update_probe:")
			msg.append("   existing child package:  %s" % dep.child)
			msg.append("   existing parent package: %s" % dep.parent)
			msg.append("   new child package:  %s" % None)
			msg.append("   new parent package: %s" % None)
			msg.append("")
			writemsg_level("\n".join(msg),
				noiselevel=-1, level=logging.DEBUG)

		return None

	def _slot_operator_unsatisfied_probe(self, dep):

		if dep.parent.installed and \
			self._frozen_config.excluded_pkgs.findAtomForPackage(dep.parent,
			modified_use=self._pkg_use_enabled(dep.parent)):
			return False

		debug = "--debug" in self._frozen_config.myopts

		for replacement_parent in self._iter_similar_available(dep.parent,
			dep.parent.slot_atom):

			for atom in replacement_parent.validated_atoms:
				if not atom.slot_operator == "=" or \
					atom.blocker or \
					atom.cp != dep.atom.cp:
					continue

				# Discard USE deps, we're only searching for an approximate
				# pattern, and dealing with USE states is too complex for
				# this purpose.
				atom = atom.without_use

				pkg, existing_node = self._select_package(dep.root, atom,
					onlydeps=dep.onlydeps)

				if pkg is not None:

					if debug:
						msg = []
						msg.append("")
						msg.append("")
						msg.append("slot_operator_unsatisfied_probe:")
						msg.append("   existing parent package: %s" % dep.parent)
						msg.append("   existing parent atom: %s" % dep.atom)
						msg.append("   new parent package: %s" % replacement_parent)
						msg.append("   new child package:  %s" % pkg)
						msg.append("")
						writemsg_level("\n".join(msg),
							noiselevel=-1, level=logging.DEBUG)

					return True

		if debug:
			msg = []
			msg.append("")
			msg.append("")
			msg.append("slot_operator_unsatisfied_probe:")
			msg.append("   existing parent package: %s" % dep.parent)
			msg.append("   existing parent atom: %s" % dep.atom)
			msg.append("   new parent package: %s" % None)
			msg.append("   new child package:  %s" % None)
			msg.append("")
			writemsg_level("\n".join(msg),
				noiselevel=-1, level=logging.DEBUG)

		return False

	def _slot_operator_unsatisfied_backtrack(self, dep):

		parent = dep.parent

		if "--debug" in self._frozen_config.myopts:
			msg = []
			msg.append("")
			msg.append("")
			msg.append("backtracking due to unsatisfied "
				"built slot-operator dep:")
			msg.append("   parent package: %s" % parent)
			msg.append("   atom: %s" % dep.atom)
			msg.append("")
			writemsg_level("\n".join(msg),
				noiselevel=-1, level=logging.DEBUG)

		backtrack_infos = self._dynamic_config._backtrack_infos
		config = backtrack_infos.setdefault("config", {})

		# mask unwanted binary packages if necessary
		masks = {}
		if not parent.installed:
			masks.setdefault(parent, {})["slot_operator_mask_built"] = None
		if masks:
			config.setdefault("slot_operator_mask_built", {}).update(masks)

		# trigger replacement of installed packages if necessary
		reinstalls = set()
		if parent.installed:
			replacement_atom = self._replace_installed_atom(parent)
			if replacement_atom is not None:
				reinstalls.add((parent.root, replacement_atom))
		if reinstalls:
			config.setdefault("slot_operator_replace_installed",
				set()).update(reinstalls)

		self._dynamic_config._need_restart = True

	def _in_blocker_conflict(self, pkg):
		"""
		Check if pkg is involved in a blocker conflict. This method
		only works after the _validate_blockers method has been called.
		"""

		if (self._dynamic_config._blocked_pkgs is None
			and not self._validate_blockers()):
			raise self._unknown_internal_error()

		if pkg in self._dynamic_config._blocked_pkgs:
			return True

		if pkg in self._dynamic_config._blocker_parents:
			return True

		return False

	def _upgrade_available(self, pkg):
		"""
		Detect cases where an upgrade of the given package is available
		within the same slot.
		"""
		for available_pkg in self._iter_similar_available(pkg,
			pkg.slot_atom):
			if available_pkg > pkg:
				return True

		return False

	def _downgrade_probe(self, pkg):
		"""
		Detect cases where a downgrade of the given package is considered
		desirable due to the current version being masked or unavailable.
		"""
		available_pkg = None
		for available_pkg in self._iter_similar_available(pkg,
			pkg.slot_atom):
			if available_pkg >= pkg:
				# There's an available package of the same or higher
				# version, so downgrade seems undesirable.
				return False

		return available_pkg is not None

	def _select_atoms_probe(self, root, pkg):
		selected_atoms = []
		use = self._pkg_use_enabled(pkg)
		for k in pkg._dep_keys:
			v = pkg._metadata.get(k)
			if not v:
				continue
			selected_atoms.extend(self._select_atoms(
				root, v, myuse=use, parent=pkg)[pkg])
		return frozenset(x.unevaluated_atom for
			x in selected_atoms)

	def _flatten_atoms(self, pkg, use):
		"""
		Evaluate all dependency atoms of the given package, and return
		them as a frozenset. For performance, results are cached.

		@param pkg: a Package instance
		@type pkg: Package
		@param pkg: set of enabled USE flags
		@type pkg: frozenset
		@rtype: frozenset
		@return: set of evaluated atoms
		"""

		cache_key = (pkg, use)

		try:
			return self._dynamic_config._flatten_atoms_cache[cache_key]
		except KeyError:
			pass

		atoms = []

		for dep_key in pkg._dep_keys:
			dep_string = pkg._metadata[dep_key]
			if not dep_string:
				continue

			dep_string = portage.dep.use_reduce(
				dep_string, uselist=use,
				is_valid_flag=pkg.iuse.is_valid_flag,
				flat=True, token_class=Atom, eapi=pkg.eapi)

			atoms.extend(token for token in dep_string
				if isinstance(token, Atom))

		atoms = frozenset(atoms)

		self._dynamic_config._flatten_atoms_cache[cache_key] = atoms
		return atoms

	def _iter_similar_available(self, graph_pkg, atom, autounmask_level=None):
		"""
		Given a package that's in the graph, do a rough check to
		see if a similar package is available to install. The given
		graph_pkg itself may be yielded only if it's not installed.
		"""

		usepkgonly = "--usepkgonly" in self._frozen_config.myopts
		useoldpkg_atoms = self._frozen_config.useoldpkg_atoms
		use_ebuild_visibility = self._frozen_config.myopts.get(
			'--use-ebuild-visibility', 'n') != 'n'

		for pkg in self._iter_match_pkgs_any(
			graph_pkg.root_config, atom):
			if pkg.cp != graph_pkg.cp:
				# discard old-style virtual match
				continue
			if pkg.installed:
				continue
			if pkg in self._dynamic_config._runtime_pkg_mask:
				continue
			if self._frozen_config.excluded_pkgs.findAtomForPackage(pkg,
				modified_use=self._pkg_use_enabled(pkg)):
				continue
			if pkg.built:
				if self._equiv_binary_installed(pkg):
					continue
				if not (not use_ebuild_visibility and
					(usepkgonly or useoldpkg_atoms.findAtomForPackage(
					pkg, modified_use=self._pkg_use_enabled(pkg)))) and \
					not self._equiv_ebuild_visible(pkg,
					autounmask_level=autounmask_level):
					continue
			if not self._pkg_visibility_check(pkg,
				autounmask_level=autounmask_level):
				continue
			yield pkg

	def _replace_installed_atom(self, inst_pkg):
		"""
		Given an installed package, generate an atom suitable for
		slot_operator_replace_installed backtracking info. The replacement
		SLOT may differ from the installed SLOT, so first search by cpv.
		"""
		built_pkgs = []
		for pkg in self._iter_similar_available(inst_pkg,
			Atom("=%s" % inst_pkg.cpv)):
			if not pkg.built:
				return pkg.slot_atom
			elif not pkg.installed:
				# avoid using SLOT from a built instance
				built_pkgs.append(pkg)

		for pkg in self._iter_similar_available(inst_pkg, inst_pkg.slot_atom):
			if not pkg.built:
				return pkg.slot_atom
			elif not pkg.installed:
				# avoid using SLOT from a built instance
				built_pkgs.append(pkg)

		if built_pkgs:
			best_version = None
			for pkg in built_pkgs:
				if best_version is None or pkg > best_version:
					best_version = pkg
			return best_version.slot_atom

		return None

	def _slot_operator_trigger_reinstalls(self):
		"""
		Search for packages with slot-operator deps on older slots, and schedule
		rebuilds if they can link to a newer slot that's in the graph.
		"""

		rebuild_if_new_slot = self._dynamic_config.myparams.get(
			"rebuild_if_new_slot", "y") == "y"

		for slot_key, slot_info in self._dynamic_config._slot_operator_deps.items():

			for dep in slot_info:

				atom = dep.atom

				if not (atom.soname or atom.slot_operator_built):
					new_child_slot = self._slot_change_probe(dep)
					if new_child_slot is not None:
						self._slot_change_backtrack(dep, new_child_slot)
					continue

				if not (dep.parent and
					isinstance(dep.parent, Package) and dep.parent.built):
					continue

				# If the parent is not installed, check if it needs to be
				# rebuilt against an installed instance, since otherwise
				# it could trigger downgrade of an installed instance as
				# in bug #652938.
				want_update_probe = dep.want_update or not dep.parent.installed

				# Check for slot update first, since we don't want to
				# trigger reinstall of the child package when a newer
				# slot will be used instead.
				if rebuild_if_new_slot and want_update_probe:
					new_dep = self._slot_operator_update_probe(dep,
						new_child_slot=True)
					if new_dep is not None:
						self._slot_operator_update_backtrack(dep,
							new_child_slot=new_dep.child)

				if want_update_probe:
					if self._slot_operator_update_probe(dep):
						self._slot_operator_update_backtrack(dep)

	def _reinstall_for_flags(self, pkg, forced_flags,
		orig_use, orig_iuse, cur_use, cur_iuse):
		"""Return a set of flags that trigger reinstallation, or None if there
		are no such flags."""

		# binpkg_respect_use: Behave like newuse by default. If newuse is
		# False and changed_use is True, then behave like changed_use.
		binpkg_respect_use = (pkg.built and
			self._dynamic_config.myparams.get("binpkg_respect_use")
			in ("y", "auto"))
		newuse = "--newuse" in self._frozen_config.myopts
		changed_use = "changed-use" == self._frozen_config.myopts.get("--reinstall")
		feature_flags = _get_feature_flags(
			_get_eapi_attrs(pkg.eapi))

		if newuse or (binpkg_respect_use and not changed_use):
			flags = set(orig_iuse.symmetric_difference(
				cur_iuse).difference(forced_flags))
			flags.update(orig_iuse.intersection(orig_use).symmetric_difference(
				cur_iuse.intersection(cur_use)))
			flags.difference_update(feature_flags)
			if flags:
				return flags

		elif changed_use or binpkg_respect_use:
			flags = set(orig_iuse.intersection(orig_use).symmetric_difference(
				cur_iuse.intersection(cur_use)))
			flags.difference_update(feature_flags)
			if flags:
				return flags
		return None

	def _changed_deps(self, pkg):

		ebuild = None
		try:
			ebuild = self._pkg(pkg.cpv, "ebuild",
				pkg.root_config, myrepo=pkg.repo)
		except PackageNotFound:
			# Use first available instance of the same version.
			for ebuild in self._iter_match_pkgs(
				pkg.root_config, "ebuild", Atom("=" + pkg.cpv)):
				break

		if ebuild is None:
			changed = False
		else:
			if self._dynamic_config.myparams.get("bdeps") in ("y", "auto"):
				depvars = Package._dep_keys
			else:
				depvars = Package._runtime_keys

			# Use _raw_metadata, in order to avoid interaction
			# with --dynamic-deps.
			try:
				built_deps = []
				for k in depvars:
					dep_struct = portage.dep.use_reduce(
						pkg._raw_metadata[k], uselist=pkg.use.enabled,
						eapi=pkg.eapi, token_class=Atom)
					strip_slots(dep_struct)
					built_deps.append(dep_struct)
			except InvalidDependString:
				changed = True
			else:
				unbuilt_deps = []
				for k in depvars:
					dep_struct = portage.dep.use_reduce(
						ebuild._raw_metadata[k],
						uselist=pkg.use.enabled,
						eapi=ebuild.eapi, token_class=Atom)
					strip_slots(dep_struct)
					unbuilt_deps.append(dep_struct)

				changed = built_deps != unbuilt_deps

				if (changed and pkg.installed and
					self._dynamic_config.myparams.get("changed_deps_report")):
					self._dynamic_config._changed_deps_pkgs[pkg] = ebuild

		return changed

	def _changed_slot(self, pkg):
		ebuild = self._equiv_ebuild(pkg)
		return ebuild is not None and (ebuild.slot, ebuild.sub_slot) != (pkg.slot, pkg.sub_slot)

	def _create_graph(self, allow_unsatisfied=False):
		dep_stack = self._dynamic_config._dep_stack
		dep_disjunctive_stack = self._dynamic_config._dep_disjunctive_stack
		while dep_stack or dep_disjunctive_stack:
			self._spinner_update()
			while dep_stack:
				dep = dep_stack.pop()
				if isinstance(dep, Package):
					if not self._add_pkg_deps(dep,
						allow_unsatisfied=allow_unsatisfied):
						return 0
					continue
				if not self._add_dep(dep, allow_unsatisfied=allow_unsatisfied):
					return 0
			if dep_disjunctive_stack:
				if not self._pop_disjunction(allow_unsatisfied):
					return 0
		return 1

	def _expand_set_args(self, input_args, add_to_digraph=False):
		"""
		Iterate over a list of DependencyArg instances and yield all
		instances given in the input together with additional SetArg
		instances that are generated from nested sets.
		@param input_args: An iterable of DependencyArg instances
		@type input_args: Iterable
		@param add_to_digraph: If True then add SetArg instances
			to the digraph, in order to record parent -> child
			relationships from nested sets
		@type add_to_digraph: Boolean
		@rtype: Iterable
		@return: All args given in the input together with additional
			SetArg instances that are generated from nested sets
		"""

		traversed_set_args = set()

		for arg in input_args:
			if not isinstance(arg, SetArg):
				yield arg
				continue

			root_config = arg.root_config
			depgraph_sets = self._dynamic_config.sets[root_config.root]
			arg_stack = [arg]
			while arg_stack:
				arg = arg_stack.pop()
				if arg in traversed_set_args:
					continue

				# If a node with the same hash already exists in
				# the digraph, preserve the existing instance which
				# may have a different reset_depth attribute
				# (distiguishes user arguments from sets added for
				# another reason such as complete mode).
				arg = self._dynamic_config.digraph.get(arg, arg)
				traversed_set_args.add(arg)

				if add_to_digraph:
					self._dynamic_config.digraph.add(arg, None,
						priority=BlockerDepPriority.instance)

				yield arg

				# Traverse nested sets and add them to the stack
				# if they're not already in the graph. Also, graph
				# edges between parent and nested sets.
				for token in arg.pset.getNonAtoms():
					if not token.startswith(SETPREFIX):
						continue
					s = token[len(SETPREFIX):]
					nested_set = depgraph_sets.sets.get(s)
					if nested_set is None:
						nested_set = root_config.sets.get(s)
					if nested_set is not None:
						# Propagate the reset_depth attribute from
						# parent set to nested set.
						nested_arg = SetArg(arg=token, pset=nested_set,
							reset_depth=arg.reset_depth,
							root_config=root_config)

						# Preserve instances already in the graph (same
						# reason as for the "arg" variable above).
						nested_arg = self._dynamic_config.digraph.get(
							nested_arg, nested_arg)
						arg_stack.append(nested_arg)
						if add_to_digraph:
							self._dynamic_config.digraph.add(nested_arg, arg,
								priority=BlockerDepPriority.instance)
							depgraph_sets.sets[nested_arg.name] = nested_arg.pset

	def _add_dep(self, dep, allow_unsatisfied=False):
		debug = "--debug" in self._frozen_config.myopts
		buildpkgonly = "--buildpkgonly" in self._frozen_config.myopts
		nodeps = "--nodeps" in self._frozen_config.myopts
		if dep.blocker:

			# Slot collision nodes are not allowed to block other packages since
			# blocker validation is only able to account for one package per slot.
			is_slot_conflict_parent = any(dep.parent in conflict.pkgs[1:] for conflict in \
				self._dynamic_config._package_tracker.slot_conflicts())
			if not buildpkgonly and \
				not nodeps and \
				not dep.collapsed_priority.ignored and \
				not dep.collapsed_priority.optional and \
				not is_slot_conflict_parent:
				if dep.parent.onlydeps:
					# It's safe to ignore blockers if the
					# parent is an --onlydeps node.
					return 1
				# The blocker applies to the root where
				# the parent is or will be installed.
				blocker = Blocker(atom=dep.atom,
					eapi=dep.parent.eapi,
					priority=dep.priority, root=dep.parent.root)
				self._dynamic_config._blocker_parents.add(blocker, dep.parent)
			return 1

		if dep.child is None:
			dep_pkg, existing_node = self._select_package(dep.root, dep.atom,
				onlydeps=dep.onlydeps)
		else:
			# The caller has selected a specific package
			# via self._minimize_packages().
			dep_pkg = dep.child
			existing_node = next(self._dynamic_config._package_tracker.match(
				dep.root, dep_pkg.slot_atom, installed=False), None)

		if not dep_pkg:
			if (dep.collapsed_priority.optional or
				dep.collapsed_priority.ignored):
				# This is an unnecessary build-time dep.
				return 1

			# NOTE: For removal actions, allow_unsatisfied is always
			# True since all existing removal actions traverse all
			# installed deps deeply via the _complete_graph method,
			# which calls _create_graph with allow_unsatisfied = True.
			if allow_unsatisfied:
				self._dynamic_config._unsatisfied_deps.append(dep)
				return 1

			# The following case occurs when
			# _solve_non_slot_operator_slot_conflicts calls
			# _create_graph. In this case, ignore unsatisfied deps for
			# installed packages only if their depth is beyond the depth
			# requested by the user and the dep was initially
			# unsatisfied (not broken by a slot conflict in the current
			# graph). See bug #520950.
			# NOTE: The value of dep.parent.depth is guaranteed to be
			# either an integer or _UNREACHABLE_DEPTH, where
			# _UNREACHABLE_DEPTH indicates that the parent has been
			# pulled in by the _complete_graph method (rather than by
			# explicit arguments or their deep dependencies). These
			# cases must be distinguished because depth is meaningless
			# for packages that are not reachable as deep dependencies
			# of arguments.
			if (self._dynamic_config._complete_mode and
				isinstance(dep.parent, Package) and
				dep.parent.installed and
				(dep.parent.depth is self._UNREACHABLE_DEPTH or
				(self._frozen_config.requested_depth is not True and
				dep.parent.depth >= self._frozen_config.requested_depth))):
				inst_pkg, in_graph = \
					self._select_pkg_from_installed(dep.root, dep.atom)
				if inst_pkg is None:
					self._dynamic_config._initially_unsatisfied_deps.append(dep)
					return 1

			self._dynamic_config._unsatisfied_deps_for_display.append(
				((dep.root, dep.atom), {"myparent":dep.parent}))

			# The parent node should not already be in
			# runtime_pkg_mask, since that would trigger an
			# infinite backtracking loop.
			if self._dynamic_config._allow_backtracking:
				if (dep.parent not in self._dynamic_config._runtime_pkg_mask and
					dep.atom.package and dep.atom.slot_operator_built and
					self._slot_operator_unsatisfied_probe(dep)):
					self._slot_operator_unsatisfied_backtrack(dep)
					return 1
				else:
					# This is for backward-compatibility with previous
					# behavior, so that installed packages with unsatisfied
					# dependencies trigger an error message but do not
					# cause the dependency calculation to fail. Only do
					# this if the parent is already in the runtime package
					# mask, since otherwise we need to backtrack.
					if (dep.parent.installed and
						dep.parent in self._dynamic_config._runtime_pkg_mask and
						not any(self._iter_match_pkgs_any(
						dep.parent.root_config, dep.atom))):
						self._dynamic_config._initially_unsatisfied_deps.append(dep)
						return 1

					# Do not backtrack if only USE have to be changed in
					# order to satisfy the dependency. Note that when
					# want_restart_for_use_change sets the need_restart
					# flag, it causes _select_pkg_highest_available to
					# return None, and eventually we come through here
					# and skip the "missing dependency" backtracking path.
					dep_pkg, existing_node = \
						self._select_package(dep.root,
							dep.atom.without_use if dep.atom.package
							else dep.atom, onlydeps=dep.onlydeps)
					if dep_pkg is None:

						# In order to suppress the sort of aggressive
						# backtracking that can trigger undesirable downgrades
						# as in bug 693836, do not backtrack if there's an
						# available package which was involved in a slot
						# conflict and satisfied all involved parent atoms.
						for dep_pkg, reasons in self._dynamic_config._runtime_pkg_mask.items():
							if (dep.atom.match(dep_pkg) and
								len(reasons) == 1 and
								not reasons.get("slot conflict", True)):
								self._dynamic_config._skip_restart = True
								return 0

						self._dynamic_config._backtrack_infos["missing dependency"] = dep
						self._dynamic_config._need_restart = True
						if debug:
							msg = []
							msg.append("")
							msg.append("")
							msg.append("backtracking due to unsatisfied dep:")
							msg.append("    parent: %s" % dep.parent)
							msg.append("  priority: %s" % dep.priority)
							msg.append("      root: %s" % dep.root)
							msg.append("      atom: %s" % dep.atom)
							msg.append("")
							writemsg_level("".join("%s\n" % l for l in msg),
								noiselevel=-1, level=logging.DEBUG)

			return 0

		self._rebuild.add(dep_pkg, dep)

		ignore = dep.collapsed_priority.ignored and \
			not self._dynamic_config._traverse_ignored_deps
		if not ignore and not self._add_pkg(dep_pkg, dep):
			return 0
		return 1

	def _check_slot_conflict(self, pkg, atom):
		existing_node = next(self._dynamic_config._package_tracker.match(
			pkg.root, pkg.slot_atom, installed=False), None)

		matches = None
		if existing_node:
			matches = pkg.cpv == existing_node.cpv
			if pkg != existing_node and \
				atom is not None:
				matches = atom.match(existing_node.with_use(
					self._pkg_use_enabled(existing_node)))

		return (existing_node, matches)

	def _add_pkg(self, pkg, dep):
		"""
		Adds a package to the depgraph, queues dependencies, and handles
		slot conflicts.
		"""
		debug = "--debug" in self._frozen_config.myopts
		myparent = None
		priority = None
		depth = 0
		if dep is None:
			dep = Dependency()
		else:
			myparent = dep.parent
			priority = dep.priority
			depth = dep.depth
		if priority is None:
			priority = DepPriority()

		if debug:
			writemsg_level(
				"\n%s%s %s\n" % ("Child:".ljust(15), pkg,
				pkg_use_display(pkg, self._frozen_config.myopts,
				modified_use=self._pkg_use_enabled(pkg))),
				level=logging.DEBUG, noiselevel=-1)
			if isinstance(myparent,
				(PackageArg, AtomArg)):
				# For PackageArg and AtomArg types, it's
				# redundant to display the atom attribute.
				writemsg_level(
					"%s%s\n" % ("Parent Dep:".ljust(15), myparent),
					level=logging.DEBUG, noiselevel=-1)
			else:
				# Display the specific atom from SetArg or
				# Package types.
				uneval = ""
				if (dep.atom and dep.atom.package and
					dep.atom is not dep.atom.unevaluated_atom):
					uneval = " (%s)" % (dep.atom.unevaluated_atom,)
				writemsg_level(
					"%s%s%s required by %s\n" %
					("Parent Dep:".ljust(15), dep.atom, uneval, myparent),
					level=logging.DEBUG, noiselevel=-1)

		# Ensure that the dependencies of the same package
		# are never processed more than once.
		previously_added = pkg in self._dynamic_config.digraph

		pkgsettings = self._frozen_config.pkgsettings[pkg.root]

		arg_atoms = None
		if True:
			try:
				arg_atoms = list(self._iter_atoms_for_pkg(pkg))
			except portage.exception.InvalidDependString as e:
				if not pkg.installed:
					# should have been masked before it was selected
					raise
				del e

		# NOTE: REQUIRED_USE checks are delayed until after
		# package selection, since we want to prompt the user
		# for USE adjustment rather than have REQUIRED_USE
		# affect package selection and || dep choices.
		if not pkg.built and pkg._metadata.get("REQUIRED_USE") and \
			eapi_has_required_use(pkg.eapi):
			required_use_is_sat = check_required_use(
				pkg._metadata["REQUIRED_USE"],
				self._pkg_use_enabled(pkg),
				pkg.iuse.is_valid_flag,
				eapi=pkg.eapi)
			if not required_use_is_sat:
				if dep.atom is not None and dep.parent is not None:
					self._add_parent_atom(pkg, (dep.parent, dep.atom))

				if arg_atoms:
					for parent_atom in arg_atoms:
						parent, atom = parent_atom
						self._add_parent_atom(pkg, parent_atom)

				atom = dep.atom
				if atom is None:
					atom = Atom("=" + pkg.cpv)
				self._dynamic_config._unsatisfied_deps_for_display.append(
					((pkg.root, atom),
					{"myparent" : dep.parent, "show_req_use" : pkg}))
				self._dynamic_config._required_use_unsatisfied = True
				self._dynamic_config._skip_restart = True
				# Add pkg to digraph in order to enable autounmask messages
				# for this package, which is useful when autounmask USE
				# changes have violated REQUIRED_USE.
				self._dynamic_config.digraph.add(pkg, dep.parent, priority=priority)
				return 0

		if not pkg.onlydeps:

			existing_node, existing_node_matches = \
				self._check_slot_conflict(pkg, dep.atom)
			if existing_node:
				if existing_node_matches:
					# The existing node can be reused.
					if pkg != existing_node:
						pkg = existing_node
						previously_added = True
						try:
							arg_atoms = list(self._iter_atoms_for_pkg(pkg))
						except InvalidDependString as e:
							if not pkg.installed:
								# should have been masked before
								# it was selected
								raise

						if debug:
							writemsg_level(
								"%s%s %s\n" % ("Re-used Child:".ljust(15),
								pkg, pkg_use_display(pkg,
								self._frozen_config.myopts,
								modified_use=self._pkg_use_enabled(pkg))),
								level=logging.DEBUG, noiselevel=-1)

				else:
					if debug:
						writemsg_level(
							"%s%s %s\n" % ("Slot Conflict:".ljust(15),
							existing_node, pkg_use_display(existing_node,
							self._frozen_config.myopts,
							modified_use=self._pkg_use_enabled(existing_node))),
							level=logging.DEBUG, noiselevel=-1)

			if not previously_added:
				self._dynamic_config._package_tracker.add_pkg(pkg)
				self._dynamic_config._filtered_trees[pkg.root]["porttree"].dbapi._clear_cache()
				self._check_masks(pkg)
				self._prune_highest_pkg_cache(pkg)

			if not pkg.installed:
				# Allow this package to satisfy old-style virtuals in case it
				# doesn't already. Any pre-existing providers will be preferred
				# over this one.
				try:
					pkgsettings.setinst(pkg.cpv, pkg._metadata)
					# For consistency, also update the global virtuals.
					settings = self._frozen_config.roots[pkg.root].settings
					settings.unlock()
					settings.setinst(pkg.cpv, pkg._metadata)
					settings.lock()
				except portage.exception.InvalidDependString:
					if not pkg.installed:
						# should have been masked before it was selected
						raise

		if arg_atoms:
			self._dynamic_config._set_nodes.add(pkg)

		# Do this even for onlydeps, so that the
		# parent/child relationship is always known in case
		# self._show_slot_collision_notice() needs to be called later.
		# If a direct circular dependency is not an unsatisfied
		# buildtime dependency then drop it here since otherwise
		# it can skew the merge order calculation in an unwanted
		# way.
		if pkg != dep.parent or \
			(priority.buildtime and not priority.satisfied):
			self._dynamic_config.digraph.add(pkg,
				dep.parent, priority=priority)
			if dep.atom is not None and dep.parent is not None:
				self._add_parent_atom(pkg, (dep.parent, dep.atom))

		if arg_atoms:
			for parent_atom in arg_atoms:
				parent, atom = parent_atom
				self._dynamic_config.digraph.add(pkg, parent, priority=priority)
				self._add_parent_atom(pkg, parent_atom)

		# This section determines whether we go deeper into dependencies or not.
		# We want to go deeper on a few occasions:
		# Installing package A, we need to make sure package A's deps are met.
		# emerge --deep <pkgspec>; we need to recursively check dependencies of pkgspec
		# If we are in --nodeps (no recursion) mode, we obviously only check 1 level of dependencies.
		if arg_atoms and depth != 0:
			for parent, atom in arg_atoms:
				if parent.reset_depth:
					depth = 0
					break

		if previously_added and depth != 0 and \
			isinstance(pkg.depth, int):
			# Use pkg.depth if it is less than depth.
			if isinstance(depth, int):
				depth = min(pkg.depth, depth)
			else:
				# depth is _UNREACHABLE_DEPTH and pkg.depth is
				# an int, so use the int because it's considered
				# to be less than _UNREACHABLE_DEPTH.
				depth = pkg.depth

		pkg.depth = depth
		deep = self._dynamic_config.myparams.get("deep", 0)
		update = "--update" in self._frozen_config.myopts

		dep.want_update = (not self._dynamic_config._complete_mode and
			(arg_atoms or update) and
			not self._too_deep(depth))

		dep.child = pkg
		if not pkg.onlydeps and dep.atom and (
			dep.atom.soname or
			dep.atom.slot_operator == "="):
			self._add_slot_operator_dep(dep)

		recurse = (deep is True or
			not self._too_deep(self._depth_increment(depth, n=1)))
		dep_stack = self._dynamic_config._dep_stack
		if "recurse" not in self._dynamic_config.myparams:
			return 1
		elif pkg.installed and not recurse:
			dep_stack = self._dynamic_config._ignored_deps

		self._spinner_update()

		if not previously_added:
			dep_stack.append(pkg)
		return 1

	def _add_installed_sonames(self, pkg):
		if (self._frozen_config.soname_deps_enabled and
			pkg.provides is not None):
			for atom in pkg.provides:
				self._dynamic_config._installed_sonames[
					(pkg.root, atom)].append(pkg)

	def _add_pkg_soname_deps(self, pkg, allow_unsatisfied=False):
		if (self._frozen_config.soname_deps_enabled and
			pkg.requires is not None):
			if isinstance(pkg.depth, int):
				depth = pkg.depth + 1
			else:
				depth = pkg.depth
			soname_provided = self._frozen_config.roots[
				pkg.root].settings.soname_provided
			for atom in pkg.requires:
				if atom in soname_provided:
					continue
				dep = Dependency(atom=atom, blocker=False, depth=depth,
					parent=pkg, priority=self._priority(runtime=True),
					root=pkg.root)
				if not self._add_dep(dep,
					allow_unsatisfied=allow_unsatisfied):
					return False
		return True

	def _remove_pkg(self, pkg):
		"""
		Remove a package and all its then parentless digraph
		children from all depgraph datastructures.
		"""
		debug = "--debug" in self._frozen_config.myopts
		if debug:
			writemsg_level(
				"Removing package: %s\n" % pkg,
				level=logging.DEBUG, noiselevel=-1)

		try:
			children = [child for child in self._dynamic_config.digraph.child_nodes(pkg) \
				if child is not pkg]
			self._dynamic_config.digraph.remove(pkg)
		except KeyError:
			children = []

		self._dynamic_config._package_tracker.discard_pkg(pkg)

		self._dynamic_config._parent_atoms.pop(pkg, None)
		self._dynamic_config._set_nodes.discard(pkg)

		for child in children:
			try:
				self._dynamic_config._parent_atoms[child] = set((parent, atom) \
					for (parent, atom) in self._dynamic_config._parent_atoms[child] \
					if parent is not pkg)
			except KeyError:
				pass

		# Remove slot operator dependencies.
		slot_key = (pkg.root, pkg.slot_atom)
		if slot_key in self._dynamic_config._slot_operator_deps:
			self._dynamic_config._slot_operator_deps[slot_key] = \
				[dep for dep in self._dynamic_config._slot_operator_deps[slot_key] \
				if dep.child is not pkg]
			if not self._dynamic_config._slot_operator_deps[slot_key]:
				del self._dynamic_config._slot_operator_deps[slot_key]

		# Remove blockers.
		self._dynamic_config._blocker_parents.discard(pkg)
		self._dynamic_config._irrelevant_blockers.discard(pkg)
		self._dynamic_config._unsolvable_blockers.discard(pkg)
		if self._dynamic_config._blocked_pkgs is not None:
			self._dynamic_config._blocked_pkgs.discard(pkg)
		self._dynamic_config._blocked_world_pkgs.pop(pkg, None)

		for child in children:
			if child in self._dynamic_config.digraph and \
				not self._dynamic_config.digraph.parent_nodes(child):
				self._remove_pkg(child)

		# Clear caches.
		self._dynamic_config._filtered_trees[pkg.root]["porttree"].dbapi._clear_cache()
		self._dynamic_config._highest_pkg_cache.clear()
		self._dynamic_config._highest_pkg_cache_cp_map.clear()


	def _check_masks(self, pkg):

		slot_key = (pkg.root, pkg.slot_atom)

		# Check for upgrades in the same slot that are
		# masked due to a LICENSE change in a newer
		# version that is not masked for any other reason.
		other_pkg = self._frozen_config._highest_license_masked.get(slot_key)
		if other_pkg is not None and pkg < other_pkg:
			self._dynamic_config._masked_license_updates.add(other_pkg)

	def _add_parent_atom(self, pkg, parent_atom):
		parent_atoms = self._dynamic_config._parent_atoms.get(pkg)
		if parent_atoms is None:
			parent_atoms = set()
			self._dynamic_config._parent_atoms[pkg] = parent_atoms
		parent_atoms.add(parent_atom)

	def _add_slot_operator_dep(self, dep):
		slot_key = (dep.root, dep.child.slot_atom)
		slot_info = self._dynamic_config._slot_operator_deps.get(slot_key)
		if slot_info is None:
			slot_info = []
			self._dynamic_config._slot_operator_deps[slot_key] = slot_info
		slot_info.append(dep)

	def _add_pkg_deps(self, pkg, allow_unsatisfied=False):

		if not self._add_pkg_soname_deps(pkg,
			allow_unsatisfied=allow_unsatisfied):
			return False

		myroot = pkg.root
		metadata = pkg._metadata
		removal_action = "remove" in self._dynamic_config.myparams
		eapi_attrs = _get_eapi_attrs(pkg.eapi)

		edepend={}
		for k in Package._dep_keys:
			edepend[k] = metadata[k]

		use_enabled = self._pkg_use_enabled(pkg)

		with_test_deps = not removal_action and \
			"with_test_deps" in \
			self._dynamic_config.myparams and \
			pkg.depth == 0 and \
			"test" not in use_enabled and \
			pkg.iuse.is_valid_flag("test") and \
			self._is_argument(pkg)

		if with_test_deps:
			use_enabled = set(use_enabled)
			use_enabled.add("test")

		if not pkg.built and \
			"--buildpkgonly" in self._frozen_config.myopts and \
			"deep" not in self._dynamic_config.myparams:
			edepend["RDEPEND"] = ""
			edepend["PDEPEND"] = ""

		if pkg.onlydeps and \
			self._frozen_config.myopts.get("--onlydeps-with-rdeps") == 'n':
			edepend["RDEPEND"] = ""
			edepend["PDEPEND"] = ""

		ignore_build_time_deps = False
		if pkg.built and not removal_action:
			if self._dynamic_config.myparams.get("bdeps") in ("y", "auto"):
				# Pull in build time deps as requested, but marked them as
				# "optional" since they are not strictly required. This allows
				# more freedom in the merge order calculation for solving
				# circular dependencies. Don't convert to PDEPEND since that
				# could make --with-bdeps=y less effective if it is used to
				# adjust merge order to prevent built_with_use() calls from
				# failing.
				pass
			else:
				ignore_build_time_deps = True

		if removal_action and self._dynamic_config.myparams.get("bdeps", "y") == "n":
			# Removal actions never traverse ignored buildtime
			# dependencies, so it's safe to discard them early.
			edepend["DEPEND"] = ""
			edepend["BDEPEND"] = ""
			edepend["HDEPEND"] = ""
			ignore_build_time_deps = True

		ignore_depend_deps = ignore_build_time_deps
		ignore_bdepend_deps = ignore_build_time_deps
		ignore_hdepend_deps = ignore_build_time_deps

		if removal_action:
			depend_root = myroot
		else:
			if eapi_attrs.hdepend:
				depend_root = myroot
			elif eapi_attrs.bdepend:
				depend_root = pkg.root_config.settings["ESYSROOT"]
			else:
				depend_root = self._frozen_config._running_root.root
				root_deps = self._frozen_config.myopts.get("--root-deps")
				if root_deps is not None:
					if root_deps is True:
						depend_root = myroot
					elif root_deps == "rdeps":
						ignore_depend_deps = True

		# If rebuild mode is not enabled, it's safe to discard ignored
		# build-time dependencies. If you want these deps to be traversed
		# in "complete" mode then you need to specify --with-bdeps=y.
		if not self._rebuild.rebuild:
			if ignore_depend_deps:
				edepend["DEPEND"] = ""
			if ignore_bdepend_deps:
				edepend["BDEPEND"] = ""
			if ignore_hdepend_deps:
				edepend["HDEPEND"] = ""

		# Since build-time deps tend to be a superset of run-time deps, order
		# dep processing such that build-time deps are popped from
		# _dep_disjunctive_stack first, so that choices for build-time
		# deps influence choices for run-time deps (bug 639346).
		deps = (
			(myroot, edepend["RDEPEND"],
				self._priority(runtime=True)),
			(myroot, edepend["PDEPEND"],
				self._priority(runtime_post=True)),
			(depend_root, edepend["DEPEND"],
				self._priority(buildtime=True,
				optional=(pkg.built or ignore_depend_deps),
				ignored=ignore_depend_deps)),
			(self._frozen_config._running_root.root, edepend["HDEPEND"],
				self._priority(buildtime=True,
				optional=(pkg.built or ignore_hdepend_deps),
				ignored=ignore_hdepend_deps)),
			(self._frozen_config._running_root.root, edepend["BDEPEND"],
				self._priority(buildtime=True,
				optional=(pkg.built or ignore_bdepend_deps),
				ignored=ignore_bdepend_deps)),
		)

		debug = "--debug" in self._frozen_config.myopts

		for dep_root, dep_string, dep_priority in deps:
				if not dep_string:
					continue
				if debug:
					writemsg_level("\nParent:    %s\n" % (pkg,),
						noiselevel=-1, level=logging.DEBUG)
					writemsg_level("Depstring: %s\n" % (dep_string,),
						noiselevel=-1, level=logging.DEBUG)
					writemsg_level("Priority:  %s\n" % (dep_priority,),
						noiselevel=-1, level=logging.DEBUG)

				try:
					dep_string = portage.dep.use_reduce(dep_string,
						uselist=use_enabled,
						is_valid_flag=pkg.iuse.is_valid_flag,
						opconvert=True, token_class=Atom,
						eapi=pkg.eapi)
				except portage.exception.InvalidDependString as e:
					if not pkg.installed:
						# should have been masked before it was selected
						raise
					del e

					# Try again, but omit the is_valid_flag argument, since
					# invalid USE conditionals are a common problem and it's
					# practical to ignore this issue for installed packages.
					try:
						dep_string = portage.dep.use_reduce(dep_string,
							uselist=use_enabled,
							opconvert=True, token_class=Atom,
							eapi=pkg.eapi)
					except portage.exception.InvalidDependString as e:
						self._dynamic_config._masked_installed.add(pkg)
						del e
						continue

				try:
					dep_string = list(self._queue_disjunctive_deps(
						pkg, dep_root, dep_priority, dep_string))
				except portage.exception.InvalidDependString as e:
					if pkg.installed:
						self._dynamic_config._masked_installed.add(pkg)
						del e
						continue

					# should have been masked before it was selected
					raise

				if not dep_string:
					continue

				if not self._add_pkg_dep_string(
					pkg, dep_root, dep_priority, dep_string,
					allow_unsatisfied):
					return 0

		self._dynamic_config._traversed_pkg_deps.add(pkg)
		return 1

	def _add_pkg_dep_string(self, pkg, dep_root, dep_priority, dep_string,
		allow_unsatisfied):
		_autounmask_backup = self._dynamic_config._autounmask
		if dep_priority.optional or dep_priority.ignored:
			# Temporarily disable autounmask for deps that
			# don't necessarily need to be satisfied.
			self._dynamic_config._autounmask = False
		try:
			return self._wrapped_add_pkg_dep_string(
				pkg, dep_root, dep_priority, dep_string,
				allow_unsatisfied)
		finally:
			self._dynamic_config._autounmask = _autounmask_backup

	def _ignore_dependency(self, atom, pkg, child, dep, mypriority, recurse_satisfied):
		"""
		In some cases, dep_check will return deps that shouldn't
		be processed any further, so they are identified and
		discarded here. Try to discard as few as possible since
		discarded dependencies reduce the amount of information
		available for optimization of merge order.
		Don't ignore dependencies if pkg has a slot operator dependency on the child
		and the child has changed slot/sub_slot.
		"""
		if not mypriority.satisfied:
			return False
		slot_operator_rebuild = False
		if atom.slot_operator == '=' and \
			(pkg.root, pkg.slot_atom) in self._dynamic_config._slot_operator_replace_installed and \
			mypriority.satisfied is not child and \
			mypriority.satisfied.installed and \
			child and \
			not child.installed and \
			(child.slot != mypriority.satisfied.slot or child.sub_slot != mypriority.satisfied.sub_slot):
			slot_operator_rebuild = True

		return not atom.blocker and \
			not recurse_satisfied and \
			mypriority.satisfied.visible and \
			dep.child is not None and \
			not dep.child.installed and \
			not any(self._dynamic_config._package_tracker.match(
				dep.child.root, dep.child.slot_atom, installed=False)) and \
			not slot_operator_rebuild

	def _wrapped_add_pkg_dep_string(self, pkg, dep_root, dep_priority,
		dep_string, allow_unsatisfied):
		if isinstance(pkg.depth, int):
			depth = pkg.depth + 1
		else:
			depth = pkg.depth

		deep = self._dynamic_config.myparams.get("deep", 0)
		recurse_satisfied = deep is True or depth <= deep
		debug = "--debug" in self._frozen_config.myopts
		strict = pkg.type_name != "installed"

		if debug:
			writemsg_level("\nParent:    %s\n" % (pkg,),
				noiselevel=-1, level=logging.DEBUG)
			dep_repr = portage.dep.paren_enclose(dep_string,
				unevaluated_atom=True, opconvert=True)
			writemsg_level("Depstring: %s\n" % (dep_repr,),
				noiselevel=-1, level=logging.DEBUG)
			writemsg_level("Priority:  %s\n" % (dep_priority,),
				noiselevel=-1, level=logging.DEBUG)

		try:
			selected_atoms = self._select_atoms(dep_root,
				dep_string, myuse=self._pkg_use_enabled(pkg), parent=pkg,
				strict=strict, priority=dep_priority)
		except portage.exception.InvalidDependString:
			if pkg.installed:
				self._dynamic_config._masked_installed.add(pkg)
				return 1

			# should have been masked before it was selected
			raise

		if debug:
			writemsg_level("Candidates: %s\n" % \
				([str(x) for x in selected_atoms[pkg]],),
				noiselevel=-1, level=logging.DEBUG)

		root_config = self._frozen_config.roots[dep_root]
		vardb = root_config.trees["vartree"].dbapi
		traversed_virt_pkgs = set()

		reinstall_atoms = self._frozen_config.reinstall_atoms
		for atom, child in self._minimize_children(
			pkg, dep_priority, root_config, selected_atoms[pkg]):

			# If this was a specially generated virtual atom
			# from dep_check, map it back to the original, in
			# order to avoid distortion in places like display
			# or conflict resolution code.
			is_virt = hasattr(atom, '_orig_atom')
			atom = getattr(atom, '_orig_atom', atom)

			if atom.blocker and \
				(dep_priority.optional or dep_priority.ignored):
				# For --with-bdeps, ignore build-time only blockers
				# that originate from built packages.
				continue

			mypriority = dep_priority.copy()
			if not atom.blocker:

				if atom.slot_operator == "=":
					if mypriority.buildtime:
						mypriority.buildtime_slot_op = True
					if mypriority.runtime:
						mypriority.runtime_slot_op = True

				inst_pkgs = [inst_pkg for inst_pkg in
					reversed(vardb.match_pkgs(atom))
					if not reinstall_atoms.findAtomForPackage(inst_pkg,
							modified_use=self._pkg_use_enabled(inst_pkg))]
				if inst_pkgs:
					for inst_pkg in inst_pkgs:
						if self._pkg_visibility_check(inst_pkg):
							# highest visible
							mypriority.satisfied = inst_pkg
							break
					if not mypriority.satisfied:
						# none visible, so use highest
						mypriority.satisfied = inst_pkgs[0]

			dep = Dependency(atom=atom,
				blocker=atom.blocker, child=child, depth=depth, parent=pkg,
				priority=mypriority, root=dep_root)

			# In some cases, dep_check will return deps that shouldn't
			# be processed any further, so they are identified and
			# discarded here. Try to discard as few as possible since
			# discarded dependencies reduce the amount of information
			# available for optimization of merge order.
			ignored = False
			if self._ignore_dependency(atom, pkg, child, dep, mypriority, recurse_satisfied):
				myarg = None
				try:
					myarg = next(self._iter_atoms_for_pkg(dep.child), None)
				except InvalidDependString:
					if not dep.child.installed:
						raise

				if myarg is None:
					# Existing child selection may not be valid unless
					# it's added to the graph immediately, since "complete"
					# mode may select a different child later.
					ignored = True
					dep.child = None
					self._dynamic_config._ignored_deps.append(dep)

			if not ignored:
				if dep_priority.ignored and \
					not self._dynamic_config._traverse_ignored_deps:
					if is_virt and dep.child is not None:
						traversed_virt_pkgs.add(dep.child)
					dep.child = None
					self._dynamic_config._ignored_deps.append(dep)
				else:
					if not self._add_dep(dep,
						allow_unsatisfied=allow_unsatisfied):
						return 0
					if is_virt and dep.child is not None:
						traversed_virt_pkgs.add(dep.child)

		selected_atoms.pop(pkg)

		# Add selected indirect virtual deps to the graph. This
		# takes advantage of circular dependency avoidance that's done
		# by dep_zapdeps. We preserve actual parent/child relationships
		# here in order to avoid distorting the dependency graph like
		# <=portage-2.1.6.x did.
		for virt_dep, atoms in selected_atoms.items():

			virt_pkg = virt_dep.child
			if virt_pkg not in traversed_virt_pkgs:
				continue

			if debug:
				writemsg_level("\nCandidates: %s: %s\n" % \
					(virt_pkg.cpv, [str(x) for x in atoms]),
					noiselevel=-1, level=logging.DEBUG)

			if not dep_priority.ignored or \
				self._dynamic_config._traverse_ignored_deps:

				inst_pkgs = [inst_pkg for inst_pkg in
					reversed(vardb.match_pkgs(virt_dep.atom))
					if not reinstall_atoms.findAtomForPackage(inst_pkg,
							modified_use=self._pkg_use_enabled(inst_pkg))]
				if inst_pkgs:
					for inst_pkg in inst_pkgs:
						if self._pkg_visibility_check(inst_pkg):
							# highest visible
							virt_dep.priority.satisfied = inst_pkg
							break
					if not virt_dep.priority.satisfied:
						# none visible, so use highest
						virt_dep.priority.satisfied = inst_pkgs[0]

				if not self._add_pkg(virt_pkg, virt_dep):
					return 0

			for atom, child in self._minimize_children(
				pkg, self._priority(runtime=True), root_config, atoms):

				# If this was a specially generated virtual atom
				# from dep_check, map it back to the original, in
				# order to avoid distortion in places like display
				# or conflict resolution code.
				is_virt = hasattr(atom, '_orig_atom')
				atom = getattr(atom, '_orig_atom', atom)

				# This is a GLEP 37 virtual, so its deps are all runtime.
				mypriority = self._priority(runtime=True)
				if not atom.blocker:
					inst_pkgs = [inst_pkg for inst_pkg in
						reversed(vardb.match_pkgs(atom))
						if not reinstall_atoms.findAtomForPackage(inst_pkg,
								modified_use=self._pkg_use_enabled(inst_pkg))]
					if inst_pkgs:
						for inst_pkg in inst_pkgs:
							if self._pkg_visibility_check(inst_pkg):
								# highest visible
								mypriority.satisfied = inst_pkg
								break
						if not mypriority.satisfied:
							# none visible, so use highest
							mypriority.satisfied = inst_pkgs[0]

				# Dependencies of virtuals are considered to have the
				# same depth as the virtual itself.
				dep = Dependency(atom=atom,
					blocker=atom.blocker, child=child, depth=virt_dep.depth,
					parent=virt_pkg, priority=mypriority, root=dep_root,
					collapsed_parent=pkg, collapsed_priority=dep_priority)

				ignored = False
				if self._ignore_dependency(atom, pkg, child, dep, mypriority, recurse_satisfied):
					myarg = None
					try:
						myarg = next(self._iter_atoms_for_pkg(dep.child), None)
					except InvalidDependString:
						if not dep.child.installed:
							raise

					if myarg is None:
						ignored = True
						dep.child = None
						self._dynamic_config._ignored_deps.append(dep)

				if not ignored:
					if dep_priority.ignored and \
						not self._dynamic_config._traverse_ignored_deps:
						if is_virt and dep.child is not None:
							traversed_virt_pkgs.add(dep.child)
						dep.child = None
						self._dynamic_config._ignored_deps.append(dep)
					else:
						if not self._add_dep(dep,
							allow_unsatisfied=allow_unsatisfied):
							return 0
						if is_virt and dep.child is not None:
							traversed_virt_pkgs.add(dep.child)

		if debug:
			writemsg_level("\nExiting... %s\n" % (pkg,),
				noiselevel=-1, level=logging.DEBUG)

		return 1

	def _minimize_children(self, parent, priority, root_config, atoms):
		"""
		Selects packages to satisfy the given atoms, and minimizes the
		number of selected packages. This serves to identify and eliminate
		redundant package selections when multiple atoms happen to specify
		a version range.
		"""

		atom_pkg_map = {}

		for atom in atoms:
			if atom.blocker:
				yield (atom, None)
				continue
			dep_pkg, existing_node = self._select_package(
				root_config.root, atom, parent=parent)
			if dep_pkg is None:
				yield (atom, None)
				continue
			atom_pkg_map[atom] = dep_pkg

		if len(atom_pkg_map) < 2:
			for item in atom_pkg_map.items():
				yield item
			return

		cp_pkg_map = {}
		pkg_atom_map = {}
		for atom, pkg in atom_pkg_map.items():
			pkg_atom_map.setdefault(pkg, set()).add(atom)
			cp_pkg_map.setdefault(pkg.cp, set()).add(pkg)

		for pkgs in cp_pkg_map.values():
			if len(pkgs) < 2:
				for pkg in pkgs:
					for atom in pkg_atom_map[pkg]:
						yield (atom, pkg)
				continue

			# Use a digraph to identify and eliminate any
			# redundant package selections.
			atom_pkg_graph = digraph()
			cp_atoms = set()
			for pkg1 in pkgs:
				for atom in pkg_atom_map[pkg1]:
					cp_atoms.add(atom)
					atom_pkg_graph.add(pkg1, atom)
					atom_set = InternalPackageSet(initial_atoms=(atom,),
						allow_repo=True)
					for pkg2 in pkgs:
						if pkg2 is pkg1:
							continue
						if atom_set.findAtomForPackage(pkg2, modified_use=self._pkg_use_enabled(pkg2)):
							atom_pkg_graph.add(pkg2, atom)

			# In order for the following eliminate_pkg loop to produce
			# deterministic results, the order of the pkgs list must
			# not be random (bug 631894). Prefer to eliminate installed
			# packages first, in case rebuilds are needed, and also sort
			# in ascending order so that older versions are eliminated
			# first.
			pkgs = (sorted(pkg for pkg in pkgs if pkg.installed) +
				sorted(pkg for pkg in pkgs if not pkg.installed))

			for pkg in pkgs:
				eliminate_pkg = True
				for atom in atom_pkg_graph.parent_nodes(pkg):
					if len(atom_pkg_graph.child_nodes(atom)) < 2:
						eliminate_pkg = False
						break
				if eliminate_pkg:
					atom_pkg_graph.remove(pkg)

			# Yield ~, =*, < and <= atoms first, since those are more likely to
			# cause slot conflicts, and we want those atoms to be displayed
			# in the resulting slot conflict message (see bug #291142).
			# Give similar treatment to slot/sub-slot atoms.
			conflict_atoms = []
			normal_atoms = []
			abi_atoms = []
			for atom in cp_atoms:
				if atom.slot_operator_built:
					abi_atoms.append(atom)
					continue
				conflict = False
				for child_pkg in atom_pkg_graph.child_nodes(atom):
					existing_node, matches = \
						self._check_slot_conflict(child_pkg, atom)
					if existing_node and not matches:
						conflict = True
						break
				if conflict:
					conflict_atoms.append(atom)
				else:
					normal_atoms.append(atom)

			for atom in chain(abi_atoms, conflict_atoms, normal_atoms):
				child_pkgs = atom_pkg_graph.child_nodes(atom)
				# if more than one child, yield highest version
				if len(child_pkgs) > 1:
					child_pkgs.sort()
				yield (atom, child_pkgs[-1])

	def _queue_disjunctive_deps(self, pkg, dep_root, dep_priority, dep_struct):
		"""
		Queue disjunctive (virtual and ||) deps in self._dynamic_config._dep_disjunctive_stack.
		Yields non-disjunctive deps. Raises InvalidDependString when
		necessary.
		"""
		for x in dep_struct:
			if isinstance(x, list):
				if x and x[0] == "||":
					self._queue_disjunction(pkg, dep_root, dep_priority, [x])
				else:
					for y in self._queue_disjunctive_deps(
						pkg, dep_root, dep_priority, x):
						yield y
			else:
				# Note: Eventually this will check for PROPERTIES=virtual
				# or whatever other metadata gets implemented for this
				# purpose.
				if x.cp.startswith('virtual/'):
					self._queue_disjunction(pkg, dep_root, dep_priority, [x])
				else:
					yield x

	def _queue_disjunction(self, pkg, dep_root, dep_priority, dep_struct):
		self._dynamic_config._dep_disjunctive_stack.append(
			(pkg, dep_root, dep_priority, dep_struct))

	def _pop_disjunction(self, allow_unsatisfied):
		"""
		Pop one disjunctive dep from self._dynamic_config._dep_disjunctive_stack, and use it to
		populate self._dynamic_config._dep_stack.
		"""
		pkg, dep_root, dep_priority, dep_struct = \
			self._dynamic_config._dep_disjunctive_stack.pop()
		if not self._add_pkg_dep_string(
			pkg, dep_root, dep_priority, dep_struct, allow_unsatisfied):
			return 0
		return 1

	def _priority(self, **kwargs):
		if "remove" in self._dynamic_config.myparams:
			priority_constructor = UnmergeDepPriority
		else:
			priority_constructor = DepPriority
		return priority_constructor(**kwargs)

	def _dep_expand(self, root_config, atom_without_category):
		"""
		@param root_config: a root config instance
		@type root_config: RootConfig
		@param atom_without_category: an atom without a category component
		@type atom_without_category: String
		@rtype: list
		@return: a list of atoms containing categories (possibly empty)
		"""
		null_cp = portage.dep_getkey(insert_category_into_atom(
			atom_without_category, "null"))
		cat, atom_pn = portage.catsplit(null_cp)

		dbs = self._dynamic_config._filtered_trees[root_config.root]["dbs"]
		categories = set()
		for db, pkg_type, built, installed, db_keys in dbs:
			for cat in db.categories:
				if db.cp_list("%s/%s" % (cat, atom_pn)):
					categories.add(cat)

		deps = []
		for cat in categories:
			deps.append(Atom(insert_category_into_atom(
				atom_without_category, cat), allow_repo=True))
		return deps

	def _have_new_virt(self, root, atom_cp):
		ret = False
		for db, pkg_type, built, installed, db_keys in \
			self._dynamic_config._filtered_trees[root]["dbs"]:
			if db.cp_list(atom_cp):
				ret = True
				break
		return ret

	def _iter_atoms_for_pkg(self, pkg):
		depgraph_sets = self._dynamic_config.sets[pkg.root]
		atom_arg_map = depgraph_sets.atom_arg_map
		for atom in depgraph_sets.atoms.iterAtomsForPackage(pkg):
			if atom.cp != pkg.cp and \
				self._have_new_virt(pkg.root, atom.cp):
				continue
			visible_pkgs = \
				self._dynamic_config._visible_pkgs[pkg.root].match_pkgs(atom)
			visible_pkgs.reverse() # descending order
			higher_slot = None
			for visible_pkg in visible_pkgs:
				if visible_pkg.cp != atom.cp:
					continue
				if pkg >= visible_pkg:
					# This is descending order, and we're not
					# interested in any versions <= pkg given.
					break
				if pkg.slot_atom != visible_pkg.slot_atom:
					higher_slot = visible_pkg
					break
			if higher_slot is not None:
				continue
			for arg in atom_arg_map[(atom, pkg.root)]:
				if isinstance(arg, PackageArg) and \
					arg.package != pkg:
					continue
				yield arg, atom

	def select_files(self, args):
		# Use the global event loop for spinner progress
		# indication during file owner lookups (bug #461412).
		def spinner_cb():
			self._frozen_config.spinner.update()
			spinner_cb.handle = self._event_loop.call_soon(spinner_cb)

		spinner_cb.handle = None
		try:
			spinner = self._frozen_config.spinner
			if spinner is not None and \
				spinner.update is not spinner.update_quiet:
				spinner_cb.handle = self._event_loop.call_soon(spinner_cb)
			return self._select_files(args)
		finally:
			if spinner_cb.handle is not None:
				spinner_cb.handle.cancel()

	def _select_files(self, myfiles):
		"""Given a list of .tbz2s, .ebuilds sets, and deps, populate
		self._dynamic_config._initial_arg_list and call self._resolve to create the
		appropriate depgraph and return a favorite list."""
		self._load_vdb()
		if (self._frozen_config.soname_deps_enabled and
			"remove" not in self._dynamic_config.myparams):
			self._index_binpkgs()
		debug = "--debug" in self._frozen_config.myopts
		root_config = self._frozen_config.roots[self._frozen_config.target_root]
		sets = root_config.sets
		depgraph_sets = self._dynamic_config.sets[root_config.root]
		myfavorites=[]
		eroot = root_config.root
		root = root_config.settings['ROOT']
		vardb = self._frozen_config.trees[eroot]["vartree"].dbapi
		real_vardb = self._frozen_config._trees_orig[eroot]["vartree"].dbapi
		portdb = self._frozen_config.trees[eroot]["porttree"].dbapi
		bindb = self._frozen_config.trees[eroot]["bintree"].dbapi
		pkgsettings = self._frozen_config.pkgsettings[eroot]
		args = []
		onlydeps = "--onlydeps" in self._frozen_config.myopts
		lookup_owners = []
		for x in myfiles:
			ext = os.path.splitext(x)[1]
			if ext==".tbz2":
				if not os.path.exists(x):
					if os.path.exists(
						os.path.join(pkgsettings["PKGDIR"], "All", x)):
						x = os.path.join(pkgsettings["PKGDIR"], "All", x)
					elif os.path.exists(
						os.path.join(pkgsettings["PKGDIR"], x)):
						x = os.path.join(pkgsettings["PKGDIR"], x)
					else:
						writemsg("\n\n!!! Binary package '"+str(x)+"' does not exist.\n", noiselevel=-1)
						writemsg("!!! Please ensure the tbz2 exists as specified.\n\n", noiselevel=-1)
						return 0, myfavorites
				mytbz2=portage.xpak.tbz2(x)
				mykey = None
				cat = mytbz2.getfile("CATEGORY")
				if cat is not None:
					cat = _unicode_decode(cat.strip(),
						encoding=_encodings['repo.content'])
					mykey = cat + "/" + os.path.basename(x)[:-5]

				if mykey is None:
					writemsg(colorize("BAD", "\n*** Package is missing CATEGORY metadata: %s.\n\n" % x), noiselevel=-1)
					self._dynamic_config._skip_restart = True
					return 0, myfavorites

				x = os.path.realpath(x)
				for pkg in self._iter_match_pkgs(root_config, "binary", Atom('=%s' % mykey)):
					if x == os.path.realpath(bindb.bintree.getname(pkg.cpv)):
						break
				else:
					writemsg("\n%s\n\n" % colorize("BAD",
						"*** " + _("You need to adjust PKGDIR to emerge "
						"this package: %s") % x), noiselevel=-1)
					self._dynamic_config._skip_restart = True
					return 0, myfavorites

				args.append(PackageArg(arg=x, package=pkg,
					root_config=root_config))
			elif ext==".ebuild":
				ebuild_path = portage.util.normalize_path(os.path.abspath(x))
				pkgdir = os.path.dirname(ebuild_path)
				tree_root = os.path.dirname(os.path.dirname(pkgdir))
				cp = pkgdir[len(tree_root)+1:]
				error_msg = ("\n\n!!! '%s' is not in a valid ebuild repository "
					"hierarchy or does not exist\n") % x
				if not portage.isvalidatom(cp):
					writemsg(error_msg, noiselevel=-1)
					return 0, myfavorites
				cat = portage.catsplit(cp)[0]
				mykey = cat + "/" + os.path.basename(ebuild_path[:-7])
				if not portage.isvalidatom("="+mykey):
					writemsg(error_msg, noiselevel=-1)
					return 0, myfavorites
				ebuild_path = portdb.findname(mykey)
				if ebuild_path:
					if ebuild_path != os.path.join(os.path.realpath(tree_root),
						cp, os.path.basename(ebuild_path)):
						writemsg(colorize("BAD", "\n*** You need to adjust repos.conf to emerge this package.\n\n"), noiselevel=-1)
						self._dynamic_config._skip_restart = True
						return 0, myfavorites
					if mykey not in portdb.xmatch(
						"match-visible", portage.cpv_getkey(mykey)):
						writemsg(colorize("BAD", "\n*** You are emerging a masked package. It is MUCH better to use\n"), noiselevel=-1)
						writemsg(colorize("BAD", "*** /etc/portage/package.* to accomplish this. See portage(5) man\n"), noiselevel=-1)
						writemsg(colorize("BAD", "*** page for details.\n"), noiselevel=-1)
						countdown(int(self._frozen_config.settings["EMERGE_WARNING_DELAY"]),
							"Continuing...")
				else:
					writemsg(error_msg, noiselevel=-1)
					return 0, myfavorites
				pkg = self._pkg(mykey, "ebuild", root_config,
					onlydeps=onlydeps, myrepo=portdb.getRepositoryName(
					os.path.dirname(os.path.dirname(os.path.dirname(ebuild_path)))))
				args.append(PackageArg(arg=x, package=pkg,
					root_config=root_config))
			elif x.startswith(os.path.sep):
				if not x.startswith(eroot):
					portage.writemsg(("\n\n!!! '%s' does not start with" + \
						" $EROOT.\n") % x, noiselevel=-1)
					self._dynamic_config._skip_restart = True
					return 0, []
				# Queue these up since it's most efficient to handle
				# multiple files in a single iter_owners() call.
				lookup_owners.append(x)
			elif x.startswith("." + os.sep) or \
				x.startswith(".." + os.sep):
				f = os.path.abspath(x)
				if not f.startswith(eroot):
					portage.writemsg(("\n\n!!! '%s' (resolved from '%s') does not start with" + \
						" $EROOT.\n") % (f, x), noiselevel=-1)
					self._dynamic_config._skip_restart = True
					return 0, []
				lookup_owners.append(f)
			else:
				if x in ("system", "world"):
					x = SETPREFIX + x
				if x.startswith(SETPREFIX):
					s = x[len(SETPREFIX):]
					if s not in sets:
						raise portage.exception.PackageSetNotFound(s)
					if s in depgraph_sets.sets:
						continue

					try:
						set_atoms = root_config.setconfig.getSetAtoms(s)
					except portage.exception.PackageSetNotFound as e:
						writemsg_level("\n\n", level=logging.ERROR,
							noiselevel=-1)
						for pset in list(depgraph_sets.sets.values()) + [sets[s]]:
							for error_msg in pset.errors:
								writemsg_level("%s\n" % (error_msg,),
									level=logging.ERROR, noiselevel=-1)

						writemsg_level(("emerge: the given set '%s' "
							"contains a non-existent set named '%s'.\n") % \
							(s, e), level=logging.ERROR, noiselevel=-1)
						if s in ('world', 'selected') and \
							SETPREFIX + e.value in sets['selected']:
							writemsg_level(("Use `emerge --deselect %s%s` to "
								"remove this set from world_sets.\n") %
								(SETPREFIX, e,), level=logging.ERROR,
								noiselevel=-1)
						writemsg_level("\n", level=logging.ERROR,
							noiselevel=-1)
						return False, myfavorites

					pset = sets[s]
					depgraph_sets.sets[s] = pset
					args.append(SetArg(arg=x, pset=pset,
						root_config=root_config))
					continue
				if not is_valid_package_atom(x, allow_repo=True):
					portage.writemsg("\n\n!!! '%s' is not a valid package atom.\n" % x,
						noiselevel=-1)
					portage.writemsg("!!! Please check ebuild(5) for full details.\n")
					portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
					self._dynamic_config._skip_restart = True
					return (0,[])
				# Don't expand categories or old-style virtuals here unless
				# necessary. Expansion of old-style virtuals here causes at
				# least the following problems:
				#   1) It's more difficult to determine which set(s) an atom
				#      came from, if any.
				#   2) It takes away freedom from the resolver to choose other
				#      possible expansions when necessary.
				if "/" in x.split(":")[0]:
					args.append(AtomArg(arg=x, atom=Atom(x, allow_repo=True),
						root_config=root_config))
					continue
				expanded_atoms = self._dep_expand(root_config, x)
				installed_cp_set = set()
				for atom in expanded_atoms:
					if vardb.cp_list(atom.cp):
						installed_cp_set.add(atom.cp)

				if len(installed_cp_set) > 1:
					non_virtual_cps = set()
					for atom_cp in installed_cp_set:
						if not atom_cp.startswith("virtual/"):
							non_virtual_cps.add(atom_cp)
					if len(non_virtual_cps) == 1:
						installed_cp_set = non_virtual_cps

				if len(expanded_atoms) > 1 and len(installed_cp_set) == 1:
					installed_cp = next(iter(installed_cp_set))
					for atom in expanded_atoms:
						if atom.cp == installed_cp:
							available = False
							for pkg in self._iter_match_pkgs_any(
								root_config, atom.without_use,
								onlydeps=onlydeps):
								if not pkg.installed:
									available = True
									break
							if available:
								expanded_atoms = [atom]
								break

				# If a non-virtual package and one or more virtual packages
				# are in expanded_atoms, use the non-virtual package.
				if len(expanded_atoms) > 1:
					number_of_virtuals = 0
					for expanded_atom in expanded_atoms:
						if expanded_atom.cp.startswith("virtual/"):
							number_of_virtuals += 1
						else:
							candidate = expanded_atom
					if len(expanded_atoms) - number_of_virtuals == 1:
						expanded_atoms = [ candidate ]

				if len(expanded_atoms) > 1:
					writemsg("\n\n", noiselevel=-1)
					ambiguous_package_name(x, expanded_atoms, root_config,
						self._frozen_config.spinner, self._frozen_config.myopts)
					self._dynamic_config._skip_restart = True
					return False, myfavorites
				if expanded_atoms:
					atom = expanded_atoms[0]
				else:
					null_atom = Atom(insert_category_into_atom(x, "null"),
						allow_repo=True)
					cat, atom_pn = portage.catsplit(null_atom.cp)
					virts_p = root_config.settings.get_virts_p().get(atom_pn)
					if virts_p:
						# Allow the depgraph to choose which virtual.
						atom = Atom(null_atom.replace('null/', 'virtual/', 1),
							allow_repo=True)
					else:
						atom = null_atom

				if atom.use and atom.use.conditional:
					writemsg(
						("\n\n!!! '%s' contains a conditional " + \
						"which is not allowed.\n") % (x,), noiselevel=-1)
					writemsg("!!! Please check ebuild(5) for full details.\n")
					self._dynamic_config._skip_restart = True
					return (0,[])

				args.append(AtomArg(arg=x, atom=atom,
					root_config=root_config))

		if lookup_owners:
			relative_paths = []
			search_for_multiple = False
			if len(lookup_owners) > 1:
				search_for_multiple = True

			for x in lookup_owners:
				if not search_for_multiple and os.path.isdir(x):
					search_for_multiple = True
				relative_paths.append(x[len(root)-1:])

			owners = set()
			for pkg, relative_path in \
				real_vardb._owners.iter_owners(relative_paths):
				owners.add(pkg.mycpv)
				if not search_for_multiple:
					break

			if not owners:
				portage.writemsg(("\n\n!!! '%s' is not claimed " + \
					"by any package.\n") % lookup_owners[0], noiselevel=-1)
				self._dynamic_config._skip_restart = True
				return 0, []

			for cpv in owners:
				pkg = vardb._pkg_str(cpv, None)
				atom = Atom("%s:%s" % (pkg.cp, pkg.slot))
				args.append(AtomArg(arg=atom, atom=atom,
					root_config=root_config))

		if "--update" in self._frozen_config.myopts:
			# In some cases, the greedy slots behavior can pull in a slot that
			# the user would want to uninstall due to it being blocked by a
			# newer version in a different slot. Therefore, it's necessary to
			# detect and discard any that should be uninstalled. Each time
			# that arguments are updated, package selections are repeated in
			# order to ensure consistency with the current arguments:
			#
			#  1) Initialize args
			#  2) Select packages and generate initial greedy atoms
			#  3) Update args with greedy atoms
			#  4) Select packages and generate greedy atoms again, while
			#     accounting for any blockers between selected packages
			#  5) Update args with revised greedy atoms

			self._set_args(args)
			greedy_args = []
			for arg in args:
				greedy_args.append(arg)
				if not isinstance(arg, AtomArg):
					continue
				for atom in self._greedy_slots(arg.root_config, arg.atom):
					greedy_args.append(
						AtomArg(arg=arg.arg, atom=atom,
							root_config=arg.root_config))

			self._set_args(greedy_args)
			del greedy_args

			# Revise greedy atoms, accounting for any blockers
			# between selected packages.
			revised_greedy_args = []
			for arg in args:
				revised_greedy_args.append(arg)
				if not isinstance(arg, AtomArg):
					continue
				for atom in self._greedy_slots(arg.root_config, arg.atom,
					blocker_lookahead=True):
					revised_greedy_args.append(
						AtomArg(arg=arg.arg, atom=atom,
							root_config=arg.root_config))
			args = revised_greedy_args
			del revised_greedy_args

		args.extend(self._gen_reinstall_sets())
		self._set_args(args)

		myfavorites = set(myfavorites)
		for arg in args:
			if isinstance(arg, (AtomArg, PackageArg)):
				myfavorites.add(arg.atom)
			elif isinstance(arg, SetArg):
				if not arg.internal:
					myfavorites.add(arg.arg)
		myfavorites = list(myfavorites)

		if debug:
			portage.writemsg("\n", noiselevel=-1)
		# Order needs to be preserved since a feature of --nodeps
		# is to allow the user to force a specific merge order.
		self._dynamic_config._initial_arg_list = args[:]

		return self._resolve(myfavorites)

	def _gen_reinstall_sets(self):

		atom_list = []
		for root, atom in self._rebuild.rebuild_list:
			atom_list.append((root, '__auto_rebuild__', atom))
		for root, atom in self._rebuild.reinstall_list:
			atom_list.append((root, '__auto_reinstall__', atom))
		for root, atom in self._dynamic_config._slot_operator_replace_installed:
			atom_list.append((root, '__auto_slot_operator_replace_installed__', atom))

		set_dict = {}
		for root, set_name, atom in atom_list:
			set_dict.setdefault((root, set_name), []).append(atom)

		for (root, set_name), atoms in set_dict.items():
			yield SetArg(arg=(SETPREFIX + set_name),
				# Set reset_depth=False here, since we don't want these
				# special sets to interact with depth calculations (see
				# the emerge --deep=DEPTH option), though we want them
				# to behave like normal arguments in most other respects.
				pset=InternalPackageSet(initial_atoms=atoms),
				force_reinstall=True,
				internal=True,
				reset_depth=False,
				root_config=self._frozen_config.roots[root])

	def _resolve(self, myfavorites):
		"""Given self._dynamic_config._initial_arg_list, pull in the root nodes,
		call self._creategraph to process theier deps and return
		a favorite list."""
		debug = "--debug" in self._frozen_config.myopts
		onlydeps = "--onlydeps" in self._frozen_config.myopts
		myroot = self._frozen_config.target_root
		pkgsettings = self._frozen_config.pkgsettings[myroot]
		pprovideddict = pkgsettings.pprovideddict
		virtuals = pkgsettings.getvirtuals()
		args = self._dynamic_config._initial_arg_list[:]

		for arg in self._expand_set_args(args, add_to_digraph=True):
			for atom in arg.pset.getAtoms():
				self._spinner_update()
				dep = Dependency(atom=atom, onlydeps=onlydeps,
					root=myroot, parent=arg)
				try:
					pprovided = pprovideddict.get(atom.cp)
					if pprovided and portage.match_from_list(atom, pprovided):
						# A provided package has been specified on the command line.
						self._dynamic_config._pprovided_args.append((arg, atom))
						continue
					if isinstance(arg, PackageArg):
						if not self._add_pkg(arg.package, dep) or \
							not self._create_graph():
							if not self.need_restart():
								writemsg(("\n\n!!! Problem " + \
									"resolving dependencies for %s\n") % \
									arg.arg, noiselevel=-1)
							return 0, myfavorites
						continue
					if debug:
						writemsg_level("\n      Arg: %s\n     Atom: %s\n" %
							(arg, atom), noiselevel=-1, level=logging.DEBUG)
					pkg, existing_node = self._select_package(
						myroot, atom, onlydeps=onlydeps)
					if not pkg:
						pprovided_match = False
						for virt_choice in virtuals.get(atom.cp, []):
							expanded_atom = portage.dep.Atom(
								atom.replace(atom.cp, virt_choice.cp, 1))
							pprovided = pprovideddict.get(expanded_atom.cp)
							if pprovided and \
								portage.match_from_list(expanded_atom, pprovided):
								# A provided package has been
								# specified on the command line.
								self._dynamic_config._pprovided_args.append((arg, atom))
								pprovided_match = True
								break
						if pprovided_match:
							continue

						excluded = False
						for any_match in self._iter_match_pkgs_any(
							self._frozen_config.roots[myroot], atom):
							if self._frozen_config.excluded_pkgs.findAtomForPackage(
								any_match, modified_use=self._pkg_use_enabled(any_match)):
								excluded = True
								break
						if excluded:
							continue

						if not (isinstance(arg, SetArg) and \
							arg.name in ("selected", "world")):
							self._dynamic_config._unsatisfied_deps_for_display.append(
								((myroot, atom), {"myparent" : arg}))
							return 0, myfavorites

						self._dynamic_config._missing_args.append((arg, atom))
						continue
					if atom.cp != pkg.cp:
						# For old-style virtuals, we need to repeat the
						# package.provided check against the selected package.
						expanded_atom = atom.replace(atom.cp, pkg.cp)
						pprovided = pprovideddict.get(pkg.cp)
						if pprovided and \
							portage.match_from_list(expanded_atom, pprovided):
							# A provided package has been
							# specified on the command line.
							self._dynamic_config._pprovided_args.append((arg, atom))
							continue
					if pkg.installed and \
						"selective" not in self._dynamic_config.myparams and \
						not self._frozen_config.excluded_pkgs.findAtomForPackage(
						pkg, modified_use=self._pkg_use_enabled(pkg)):
						self._dynamic_config._unsatisfied_deps_for_display.append(
							((myroot, atom), {"myparent" : arg}))
						# Previous behavior was to bail out in this case, but
						# since the dep is satisfied by the installed package,
						# it's more friendly to continue building the graph
						# and just show a warning message. Therefore, only bail
						# out here if the atom is not from either the system or
						# world set.
						if not (isinstance(arg, SetArg) and \
							arg.name in ("selected", "system", "world")):
							return 0, myfavorites

					# Add the selected package to the graph as soon as possible
					# so that later dep_check() calls can use it as feedback
					# for making more consistent atom selections.
					if not self._add_pkg(pkg, dep):
						if self.need_restart():
							pass
						elif isinstance(arg, SetArg):
							writemsg(("\n\n!!! Problem resolving " + \
								"dependencies for %s from %s\n") % \
								(atom, arg.arg), noiselevel=-1)
						else:
							writemsg(("\n\n!!! Problem resolving " + \
								"dependencies for %s\n") % \
								(atom,), noiselevel=-1)
						return 0, myfavorites

				except SystemExit as e:
					raise # Needed else can't exit
				except Exception as e:
					writemsg("\n\n!!! Problem in '%s' dependencies.\n" % atom, noiselevel=-1)
					writemsg("!!! %s %s\n" % (str(e), str(getattr(e, "__module__", None))))
					raise

		# Now that the root packages have been added to the graph,
		# process the dependencies.
		if not self._create_graph():
			self._apply_parent_use_changes()
			return 0, myfavorites

		try:
			self.altlist()
		except self._unknown_internal_error:
			return False, myfavorites

		have_slot_conflict = any(self._dynamic_config._package_tracker.slot_conflicts())
		if (have_slot_conflict and
			not self._accept_blocker_conflicts()) or \
			(self._dynamic_config._allow_backtracking and
			"slot conflict" in self._dynamic_config._backtrack_infos):
			return False, myfavorites

		if self._rebuild.trigger_rebuilds():
			backtrack_infos = self._dynamic_config._backtrack_infos
			config = backtrack_infos.setdefault("config", {})
			config["rebuild_list"] = self._rebuild.rebuild_list
			config["reinstall_list"] = self._rebuild.reinstall_list
			self._dynamic_config._need_restart = True
			return False, myfavorites

		if "config" in self._dynamic_config._backtrack_infos and \
			("slot_operator_mask_built" in self._dynamic_config._backtrack_infos["config"] or
			"slot_operator_replace_installed" in self._dynamic_config._backtrack_infos["config"]) and \
			self.need_restart():
			return False, myfavorites

		if not self._dynamic_config._prune_rebuilds and \
			self._dynamic_config._slot_operator_replace_installed and \
			self._get_missed_updates():
			# When there are missed updates, we might have triggered
			# some unnecessary rebuilds (see bug #439688). So, prune
			# all the rebuilds and backtrack with the problematic
			# updates masked. The next backtrack run should pull in
			# any rebuilds that are really needed, and this
			# prune_rebuilds path should never be entered more than
			# once in a series of backtracking nodes (in order to
			# avoid a backtracking loop).
			backtrack_infos = self._dynamic_config._backtrack_infos
			config = backtrack_infos.setdefault("config", {})
			config["prune_rebuilds"] = True
			self._dynamic_config._need_restart = True
			return False, myfavorites

		if self.need_restart():
			# want_restart_for_use_change triggers this
			return False, myfavorites

		if "--fetchonly" not in self._frozen_config.myopts and \
			"--buildpkgonly" in self._frozen_config.myopts:
			graph_copy = self._dynamic_config.digraph.copy()
			removed_nodes = set()
			for node in graph_copy:
				if not isinstance(node, Package) or \
					node.operation == "nomerge":
					removed_nodes.add(node)
			graph_copy.difference_update(removed_nodes)
			if not graph_copy.hasallzeros(ignore_priority = \
				DepPrioritySatisfiedRange.ignore_medium):
				self._dynamic_config._buildpkgonly_deps_unsatisfied = True
				self._dynamic_config._skip_restart = True
				return False, myfavorites

		if (not self._dynamic_config._prune_rebuilds and
			self._ignored_binaries_autounmask_backtrack()):
			config = self._dynamic_config._backtrack_infos.setdefault("config", {})
			config["prune_rebuilds"] = True
			self._dynamic_config._need_restart = True
			return False, myfavorites

		# Any failures except those due to autounmask *alone* should return
		# before this point, since the success_without_autounmask flag that's
		# set below is reserved for cases where there are *zero* other
		# problems. For reference, see backtrack_depgraph, where it skips the
		# get_best_run() call when success_without_autounmask is True.
		if self._have_autounmask_changes():
			#We failed if the user needs to change the configuration
			self._dynamic_config._success_without_autounmask = True
			if (self._frozen_config.myopts.get("--autounmask-continue") is True and
				"--pretend" not in self._frozen_config.myopts):
				# This will return false if it fails or if the user
				# aborts via --ask.
				if self._display_autounmask(autounmask_continue=True):
					self._apply_autounmask_continue_state()
					self._dynamic_config._need_config_reload = True
					return True, myfavorites
			return False, myfavorites

		# We're true here unless we are missing binaries.
		return (True, myfavorites)

	def _apply_autounmask_continue_state(self):
		"""
		Apply autounmask changes to Package instances, so that their
		state will be consistent configuration file changes.
		"""
		for node in self._dynamic_config._serialized_tasks_cache:
			if isinstance(node, Package):
				effective_use = self._pkg_use_enabled(node)
				if effective_use != node.use.enabled:
					node._metadata['USE'] = ' '.join(effective_use)

	def _apply_parent_use_changes(self):
		"""
		For parents with unsatisfied conditional dependencies, translate
		USE change suggestions into autounmask changes.
		"""
		if (self._dynamic_config._unsatisfied_deps_for_display and
			self._dynamic_config._autounmask):
			remaining_items = []
			for item in self._dynamic_config._unsatisfied_deps_for_display:
				pargs, kwargs = item
				kwargs = kwargs.copy()
				kwargs['collect_use_changes'] = True
				if not self._show_unsatisfied_dep(*pargs, **kwargs):
					remaining_items.append(item)
			if len(remaining_items) != len(self._dynamic_config._unsatisfied_deps_for_display):
				self._dynamic_config._unsatisfied_deps_for_display = remaining_items

	def _set_args(self, args):
		"""
		Create the "__non_set_args__" package set from atoms and packages given as
		arguments. This method can be called multiple times if necessary.
		The package selection cache is automatically invalidated, since
		arguments influence package selections.
		"""

		set_atoms = {}
		non_set_atoms = {}
		for root in self._dynamic_config.sets:
			depgraph_sets = self._dynamic_config.sets[root]
			depgraph_sets.sets.setdefault('__non_set_args__',
				InternalPackageSet(allow_repo=True)).clear()
			depgraph_sets.atoms.clear()
			depgraph_sets.atom_arg_map.clear()
			set_atoms[root] = []
			non_set_atoms[root] = []

		# We don't add set args to the digraph here since that
		# happens at a later stage and we don't want to make
		# any state changes here that aren't reversed by a
		# another call to this method.
		for arg in self._expand_set_args(args, add_to_digraph=False):
			atom_arg_map = self._dynamic_config.sets[
				arg.root_config.root].atom_arg_map
			if isinstance(arg, SetArg):
				atom_group = set_atoms[arg.root_config.root]
			else:
				atom_group = non_set_atoms[arg.root_config.root]

			for atom in arg.pset.getAtoms():
				atom_group.append(atom)
				atom_key = (atom, arg.root_config.root)
				refs = atom_arg_map.get(atom_key)
				if refs is None:
					refs = []
					atom_arg_map[atom_key] = refs
				if arg not in refs:
					refs.append(arg)

		for root in self._dynamic_config.sets:
			depgraph_sets = self._dynamic_config.sets[root]
			depgraph_sets.atoms.update(chain(set_atoms.get(root, []),
				non_set_atoms.get(root, [])))
			depgraph_sets.sets['__non_set_args__'].update(
				non_set_atoms.get(root, []))

		# Invalidate the package selection cache, since
		# arguments influence package selections.
		self._dynamic_config._highest_pkg_cache.clear()
		self._dynamic_config._highest_pkg_cache_cp_map.clear()
		for trees in self._dynamic_config._filtered_trees.values():
			trees["porttree"].dbapi._clear_cache()

	def _greedy_slots(self, root_config, atom, blocker_lookahead=False):
		"""
		Return a list of slot atoms corresponding to installed slots that
		differ from the slot of the highest visible match. When
		blocker_lookahead is True, slot atoms that would trigger a blocker
		conflict are automatically discarded, potentially allowing automatic
		uninstallation of older slots when appropriate.
		"""
		highest_pkg, in_graph = self._select_package(root_config.root, atom)
		if highest_pkg is None:
			return []
		vardb = root_config.trees["vartree"].dbapi
		slots = set()
		for cpv in vardb.match(atom):
			# don't mix new virtuals with old virtuals
			pkg = vardb._pkg_str(cpv, None)
			if pkg.cp == highest_pkg.cp:
				slots.add(pkg.slot)

		slots.add(highest_pkg.slot)
		if len(slots) == 1:
			return []
		greedy_pkgs = []
		slots.remove(highest_pkg.slot)
		while slots:
			slot = slots.pop()
			slot_atom = portage.dep.Atom("%s:%s" % (highest_pkg.cp, slot))
			pkg, in_graph = self._select_package(root_config.root, slot_atom)
			if pkg is not None and \
				pkg.cp == highest_pkg.cp and pkg < highest_pkg:
				greedy_pkgs.append(pkg)
		if not greedy_pkgs:
			return []
		if not blocker_lookahead:
			return [pkg.slot_atom for pkg in greedy_pkgs]

		blockers = {}
		blocker_dep_keys = Package._dep_keys
		for pkg in greedy_pkgs + [highest_pkg]:
			dep_str = " ".join(pkg._metadata[k] for k in blocker_dep_keys)
			try:
				selected_atoms = self._select_atoms(
					pkg.root, dep_str, self._pkg_use_enabled(pkg),
					parent=pkg, strict=True)
			except portage.exception.InvalidDependString:
				continue
			blocker_atoms = []
			for atoms in selected_atoms.values():
				blocker_atoms.extend(x for x in atoms if x.blocker)
			blockers[pkg] = InternalPackageSet(initial_atoms=blocker_atoms)

		if highest_pkg not in blockers:
			return []

		# filter packages with invalid deps
		greedy_pkgs = [pkg for pkg in greedy_pkgs if pkg in blockers]

		# filter packages that conflict with highest_pkg
		greedy_pkgs = [pkg for pkg in greedy_pkgs if not \
			(blockers[highest_pkg].findAtomForPackage(pkg, modified_use=self._pkg_use_enabled(pkg)) or \
			blockers[pkg].findAtomForPackage(highest_pkg, modified_use=self._pkg_use_enabled(highest_pkg)))]

		if not greedy_pkgs:
			return []

		# If two packages conflict, discard the lower version.
		discard_pkgs = set()
		greedy_pkgs.sort(reverse=True)
		for i in range(len(greedy_pkgs) - 1):
			pkg1 = greedy_pkgs[i]
			if pkg1 in discard_pkgs:
				continue
			for j in range(i + 1, len(greedy_pkgs)):
				pkg2 = greedy_pkgs[j]
				if pkg2 in discard_pkgs:
					continue
				if blockers[pkg1].findAtomForPackage(pkg2, modified_use=self._pkg_use_enabled(pkg2)) or \
					blockers[pkg2].findAtomForPackage(pkg1, modified_use=self._pkg_use_enabled(pkg1)):
					# pkg1 > pkg2
					discard_pkgs.add(pkg2)

		return [pkg.slot_atom for pkg in greedy_pkgs \
			if pkg not in discard_pkgs]

	def _select_atoms_from_graph(self, *pargs, **kwargs):
		"""
		Prefer atoms matching packages that have already been
		added to the graph or those that are installed and have
		not been scheduled for replacement.
		"""
		kwargs["trees"] = self._dynamic_config._graph_trees
		return self._select_atoms_highest_available(*pargs, **kwargs)

	def _select_atoms_highest_available(self, root, depstring,
		myuse=None, parent=None, strict=True, trees=None, priority=None):
		"""This will raise InvalidDependString if necessary. If trees is
		None then self._dynamic_config._filtered_trees is used."""

		if not isinstance(depstring, list):
			eapi = None
			is_valid_flag = None
			if parent is not None:
				eapi = parent.eapi
				if not parent.installed:
					is_valid_flag = parent.iuse.is_valid_flag
			depstring = portage.dep.use_reduce(depstring,
				uselist=myuse, opconvert=True, token_class=Atom,
				is_valid_flag=is_valid_flag, eapi=eapi)

		if (self._dynamic_config.myparams.get(
			"ignore_built_slot_operator_deps", "n") == "y" and
			parent and parent.built):
			ignore_built_slot_operator_deps(depstring)

		pkgsettings = self._frozen_config.pkgsettings[root]
		if trees is None:
			trees = self._dynamic_config._filtered_trees
		mytrees = trees[root]
		atom_graph = digraph()
		if True:
			# Temporarily disable autounmask so that || preferences
			# account for masking and USE settings.
			_autounmask_backup = self._dynamic_config._autounmask
			self._dynamic_config._autounmask = False
			# backup state for restoration, in case of recursive
			# calls to this method
			backup_parent = self._select_atoms_parent
			backup_state = mytrees.copy()
			try:
				# clear state from previous call, in case this
				# call is recursive (we have a backup, that we
				# will use to restore it later)
				self._select_atoms_parent = None
				mytrees.pop("pkg_use_enabled", None)
				mytrees.pop("parent", None)
				mytrees.pop("atom_graph", None)
				mytrees.pop("priority", None)

				mytrees["pkg_use_enabled"] = self._pkg_use_enabled
				if parent is not None:
					self._select_atoms_parent = parent
					mytrees["parent"] = parent
					mytrees["atom_graph"] = atom_graph
				if priority is not None:
					mytrees["priority"] = priority

				mycheck = portage.dep_check(depstring, None,
					pkgsettings, myuse=myuse,
					myroot=root, trees=trees)
			finally:
				# restore state
				self._dynamic_config._autounmask = _autounmask_backup
				self._select_atoms_parent = backup_parent
				mytrees.pop("pkg_use_enabled", None)
				mytrees.pop("parent", None)
				mytrees.pop("atom_graph", None)
				mytrees.pop("priority", None)
				mytrees.update(backup_state)
			if not mycheck[0]:
				raise portage.exception.InvalidDependString(mycheck[1])
		if parent is None:
			selected_atoms = mycheck[1]
		elif parent not in atom_graph:
			selected_atoms = {parent : mycheck[1]}
		else:
			# Recursively traversed virtual dependencies, and their
			# direct dependencies, are considered to have the same
			# depth as direct dependencies.
			if isinstance(parent.depth, int):
				virt_depth = parent.depth + 1
			else:
				# The depth may be None when called via
				# _select_atoms_probe, or it may be
				# _UNREACHABLE_DEPTH for complete mode.
				virt_depth = parent.depth

			chosen_atom_ids = frozenset(chain(
				(id(atom) for atom in mycheck[1]),
				(id(atom._orig_atom) for atom in mycheck[1]
					if hasattr(atom, '_orig_atom')),
			))
			selected_atoms = OrderedDict()
			node_stack = [(parent, None, None)]
			traversed_nodes = set()
			while node_stack:
				node, node_parent, parent_atom = node_stack.pop()
				traversed_nodes.add(node)
				if node is parent:
					k = parent
				else:
					if node_parent is parent:
						if priority is None:
							node_priority = None
						else:
							node_priority = priority.copy()
					else:
						# virtuals only have runtime deps
						node_priority = self._priority(runtime=True)

					k = Dependency(atom=parent_atom,
						blocker=parent_atom.blocker, child=node,
						depth=virt_depth, parent=node_parent,
						priority=node_priority, root=node.root)

				child_atoms = []
				selected_atoms[k] = child_atoms
				for atom_node in atom_graph.child_nodes(node):
					child_atom = atom_node[0]
					if id(child_atom) not in chosen_atom_ids:
						continue
					child_atoms.append(child_atom)
					for child_node in atom_graph.child_nodes(atom_node):
						if child_node in traversed_nodes:
							continue
						if not portage.match_from_list(
							child_atom, [child_node]):
							# Typically this means that the atom
							# specifies USE deps that are unsatisfied
							# by the selected package. The caller will
							# record this as an unsatisfied dependency
							# when necessary.
							continue
						node_stack.append((child_node, node, child_atom))

		return selected_atoms

	def _expand_virt_from_graph(self, root, atom):
		if not isinstance(atom, Atom):
			atom = Atom(atom)

		if not atom.cp.startswith("virtual/"):
			yield atom
			return

		any_match = False
		for pkg in self._dynamic_config._package_tracker.match(root, atom):
			try:
				rdepend = self._select_atoms_from_graph(
					pkg.root, pkg._metadata.get("RDEPEND", ""),
					myuse=self._pkg_use_enabled(pkg),
					parent=pkg, strict=False)
			except InvalidDependString as e:
				writemsg_level("!!! Invalid RDEPEND in " + \
					"'%svar/db/pkg/%s/RDEPEND': %s\n" % \
					(pkg.root, pkg.cpv, e),
					noiselevel=-1, level=logging.ERROR)
				continue

			for atoms in rdepend.values():
				for atom in atoms:
					if hasattr(atom, "_orig_atom"):
						# Ignore virtual atoms since we're only
						# interested in expanding the real atoms.
						continue
					yield atom

			any_match = True

		if not any_match:
			yield atom

	def _virt_deps_visible(self, pkg, ignore_use=False):
		"""
		Assumes pkg is a virtual package. Traverses virtual deps recursively
		and returns True if all deps are visible, False otherwise. This is
		useful for checking if it will be necessary to expand virtual slots,
		for cases like bug #382557.
		"""
		try:
			rdepend = self._select_atoms(
				pkg.root, pkg._metadata.get("RDEPEND", ""),
				myuse=self._pkg_use_enabled(pkg),
				parent=pkg, priority=self._priority(runtime=True))
		except InvalidDependString as e:
			if not pkg.installed:
				raise
			writemsg_level("!!! Invalid RDEPEND in " + \
				"'%svar/db/pkg/%s/RDEPEND': %s\n" % \
				(pkg.root, pkg.cpv, e),
				noiselevel=-1, level=logging.ERROR)
			return False

		for atoms in rdepend.values():
			for atom in atoms:
				if ignore_use:
					atom = atom.without_use
				pkg, existing = self._select_package(
					pkg.root, atom)
				if pkg is None or not self._pkg_visibility_check(pkg):
					return False

		return True

	def _get_dep_chain(self, start_node, target_atom=None,
		unsatisfied_dependency=False):
		"""
		Returns a list of (atom, node_type) pairs that represent a dep chain.
		If target_atom is None, the first package shown is pkg's parent.
		If target_atom is not None the first package shown is pkg.
		If unsatisfied_dependency is True, the first parent is select who's
		dependency is not satisfied by 'pkg'. This is need for USE changes.
		(Does not support target_atom.)
		"""
		traversed_nodes = set()
		dep_chain = []
		node = start_node
		child = None
		all_parents = self._dynamic_config._parent_atoms
		graph = self._dynamic_config.digraph

		def format_pkg(pkg):
			pkg_name = "%s%s%s" % (pkg.cpv, _repo_separator, pkg.repo)
			return pkg_name

		if target_atom is not None and isinstance(node, Package):
			affecting_use = set()
			for dep_str in Package._dep_keys:
				try:
					affecting_use.update(extract_affecting_use(
						node._metadata[dep_str], target_atom,
						eapi=node.eapi))
				except InvalidDependString:
					if not node.installed:
						raise
			affecting_use.difference_update(node.use.mask, node.use.force)
			pkg_name = format_pkg(node)

			if affecting_use:
				usedep = []
				for flag in affecting_use:
					if flag in self._pkg_use_enabled(node):
						usedep.append(flag)
					else:
						usedep.append("-"+flag)
				pkg_name += "[%s]" % ",".join(usedep)

			dep_chain.append((pkg_name, node.type_name))


		# To build a dep chain for the given package we take
		# "random" parents form the digraph, except for the
		# first package, because we want a parent that forced
		# the corresponding change (i.e '>=foo-2', instead 'foo').

		traversed_nodes.add(start_node)

		start_node_parent_atoms = {}
		for ppkg, patom in all_parents.get(node, []):
			# Get a list of suitable atoms. For use deps
			# (aka unsatisfied_dependency is not None) we
			# need that the start_node doesn't match the atom.
			if not unsatisfied_dependency or \
				not patom.match(start_node):
				start_node_parent_atoms.setdefault(patom, []).append(ppkg)

		if start_node_parent_atoms:
			# If there are parents in all_parents then use one of them.
			# If not, then this package got pulled in by an Arg and
			# will be correctly handled by the code that handles later
			# packages in the dep chain.
			if (any(not x.package for x in start_node_parent_atoms) and
				any(x.package for x in start_node_parent_atoms)):
				for x in list(start_node_parent_atoms):
					if not x.package:
						del start_node_parent_atoms[x]
			if next(iter(start_node_parent_atoms)).package:
				best_match = best_match_to_list(node.cpv,
					start_node_parent_atoms)
			else:
				best_match = next(iter(start_node_parent_atoms))

			child = node
			for ppkg in start_node_parent_atoms[best_match]:
				node = ppkg
				if ppkg in self._dynamic_config._initial_arg_list:
					# Stop if reached the top level of the dep chain.
					break

		while node is not None:
			traversed_nodes.add(node)

			if node not in graph:
				# The parent is not in the graph due to backtracking.
				break

			elif isinstance(node, DependencyArg):
				if graph.parent_nodes(node):
					node_type = "set"
				else:
					node_type = "argument"
				dep_chain.append(("%s" % (node,), node_type))

			elif node is not start_node:
				for ppkg, patom in all_parents[child]:
					if ppkg == node:
						if child is start_node and unsatisfied_dependency and \
							patom.match(child):
							# This atom is satisfied by child, there must be another atom.
							continue
						atom = (patom.unevaluated_atom
							if patom.package else patom)
						break

				dep_strings = set()
				priorities = graph.nodes[node][0].get(child)
				if priorities is None:
					# This edge comes from _parent_atoms and was not added to
					# the graph, and _parent_atoms does not contain priorities.
					for k in Package._dep_keys:
						dep_strings.add(node._metadata[k])
				else:
					for priority in priorities:
						if priority.buildtime:
							for k in Package._buildtime_keys:
								dep_strings.add(node._metadata[k])
						if priority.runtime:
							dep_strings.add(node._metadata["RDEPEND"])
						if priority.runtime_post:
							dep_strings.add(node._metadata["PDEPEND"])

				affecting_use = set()
				for dep_str in dep_strings:
					try:
						affecting_use.update(extract_affecting_use(
							dep_str, atom, eapi=node.eapi))
					except InvalidDependString:
						if not node.installed:
							raise

				#Don't show flags as 'affecting' if the user can't change them,
				affecting_use.difference_update(node.use.mask, \
					node.use.force)

				pkg_name = format_pkg(node)
				if affecting_use:
					usedep = []
					for flag in affecting_use:
						if flag in self._pkg_use_enabled(node):
							usedep.append(flag)
						else:
							usedep.append("-"+flag)
					pkg_name += "[%s]" % ",".join(usedep)

				dep_chain.append((pkg_name, node.type_name))

			# When traversing to parents, prefer arguments over packages
			# since arguments are root nodes. Never traverse the same
			# package twice, in order to prevent an infinite loop.
			child = node
			selected_parent = None
			parent_arg = None
			parent_merge = None
			parent_unsatisfied = None

			for parent in self._dynamic_config.digraph.parent_nodes(node):
				if parent in traversed_nodes:
					continue
				if isinstance(parent, DependencyArg):
					parent_arg = parent
				else:
					if isinstance(parent, Package) and \
						parent.operation == "merge":
						parent_merge = parent
					if unsatisfied_dependency and node is start_node:
						# Make sure that pkg doesn't satisfy parent's dependency.
						# This ensures that we select the correct parent for use
						# flag changes.
						for ppkg, atom in all_parents[start_node]:
							if parent is ppkg:
								if not atom.match(start_node):
									parent_unsatisfied = parent
								break
					else:
						selected_parent = parent

			if parent_unsatisfied is not None:
				selected_parent = parent_unsatisfied
			elif parent_merge is not None:
				# Prefer parent in the merge list (bug #354747).
				selected_parent = parent_merge
			elif parent_arg is not None:
				if self._dynamic_config.digraph.parent_nodes(parent_arg):
					selected_parent = parent_arg
				else:
					dep_chain.append(("%s" % (parent_arg,), "argument"))
					selected_parent = None

			node = selected_parent
		return dep_chain

	def _get_dep_chain_as_comment(self, pkg, unsatisfied_dependency=False):
		dep_chain = self._get_dep_chain(pkg, unsatisfied_dependency=unsatisfied_dependency)
		display_list = []
		for node, node_type in dep_chain:
			if node_type == "argument":
				display_list.append("required by %s (argument)" % node)
			else:
				display_list.append("required by %s" % node)

		msg = "# " + "\n# ".join(display_list) + "\n"
		return msg


	def _show_unsatisfied_dep(self, root, atom, myparent=None, arg=None,
		check_backtrack=False, check_autounmask_breakage=False, show_req_use=None,
		collect_use_changes=False):
		"""
		When check_backtrack=True, no output is produced and
		the method either returns or raises _backtrack_mask if
		a matching package has been masked by backtracking.
		"""
		backtrack_mask = False
		autounmask_broke_use_dep = False
		if atom.package:
			xinfo = '"%s"' % atom.unevaluated_atom
			atom_without_use = atom.without_use
		else:
			xinfo = '"%s"' % atom
			atom_without_use = None

		if arg:
			xinfo='"%s"' % arg
		if isinstance(myparent, AtomArg):
			xinfo = '"%s"' % (myparent,)
		# Discard null/ from failed cpv_expand category expansion.
		xinfo = xinfo.replace("null/", "")
		if root != self._frozen_config._running_root.root:
			xinfo = "%s for %s" % (xinfo, root)
		masked_packages = []
		missing_use = []
		missing_use_adjustable = set()
		required_use_unsatisfied = []
		masked_pkg_instances = set()
		have_eapi_mask = False
		pkgsettings = self._frozen_config.pkgsettings[root]
		root_config = self._frozen_config.roots[root]
		portdb = self._frozen_config.roots[root].trees["porttree"].dbapi
		vardb = self._frozen_config.roots[root].trees["vartree"].dbapi
		bindb = self._frozen_config.roots[root].trees["bintree"].dbapi
		dbs = self._dynamic_config._filtered_trees[root]["dbs"]
		use_ebuild_visibility = self._frozen_config.myopts.get(
			'--use-ebuild-visibility', 'n') != 'n'

		for db, pkg_type, built, installed, db_keys in dbs:
			if installed:
				continue
			if atom.soname:
				if not isinstance(db, DbapiProvidesIndex):
					continue
				cpv_list = db.match(atom)
			elif hasattr(db, "xmatch"):
				cpv_list = db.xmatch("match-all-cpv-only", atom.without_use)
			else:
				cpv_list = db.match(atom.without_use)

			if atom.soname:
				repo_list = [None]
			elif atom.repo is None and hasattr(db, "getRepositories"):
				repo_list = db.getRepositories(catpkg=atom.cp)
			else:
				repo_list = [atom.repo]

			# descending order
			cpv_list.reverse()
			for cpv in cpv_list:
				for repo in repo_list:
					if not db.cpv_exists(cpv, myrepo=repo):
						continue

					metadata, mreasons  = get_mask_info(root_config, cpv, pkgsettings, db, pkg_type, \
						built, installed, db_keys, myrepo=repo, _pkg_use_enabled=self._pkg_use_enabled)
					if metadata is not None and \
						portage.eapi_is_supported(metadata["EAPI"]):
						if not repo:
							repo = metadata.get('repository')
						pkg = self._pkg(cpv, pkg_type, root_config,
							installed=installed, myrepo=repo)
						# pkg._metadata contains calculated USE for ebuilds,
						# required later for getMissingLicenses.
						metadata = pkg._metadata
						if pkg.invalid:
							# Avoid doing any operations with packages that
							# have invalid metadata. It would be unsafe at
							# least because it could trigger unhandled
							# exceptions in places like check_required_use().
							masked_packages.append(
								(root_config, pkgsettings, cpv, repo, metadata, mreasons))
							continue
						if atom.soname and not atom.match(pkg):
							continue
						if (atom_without_use is not None and
							not atom_without_use.match(pkg)):
							continue
						if pkg in self._dynamic_config._runtime_pkg_mask:
							backtrack_reasons = \
								self._dynamic_config._runtime_pkg_mask[pkg]
							mreasons.append('backtracking: %s' % \
								', '.join(sorted(backtrack_reasons)))
							backtrack_mask = True
						if not mreasons and self._frozen_config.excluded_pkgs.findAtomForPackage(pkg, \
							modified_use=self._pkg_use_enabled(pkg)):
							mreasons = ["exclude option"]
						if mreasons:
							masked_pkg_instances.add(pkg)
						if atom.package and atom.unevaluated_atom.use:
							try:
								if not pkg.iuse.is_valid_flag(atom.unevaluated_atom.use.required) \
									or atom.violated_conditionals(self._pkg_use_enabled(pkg), pkg.iuse.is_valid_flag).use:
									missing_use.append(pkg)
									if atom.match(pkg):
										autounmask_broke_use_dep = True
									if not mreasons:
										continue
							except InvalidAtom:
								writemsg("violated_conditionals raised " + \
									"InvalidAtom: '%s' parent: %s" % \
									(atom, myparent), noiselevel=-1)
								raise
						if not mreasons and \
							not pkg.built and \
							pkg._metadata.get("REQUIRED_USE") and \
							eapi_has_required_use(pkg.eapi):
							if not check_required_use(
								pkg._metadata["REQUIRED_USE"],
								self._pkg_use_enabled(pkg),
								pkg.iuse.is_valid_flag,
								eapi=pkg.eapi):
								required_use_unsatisfied.append(pkg)
								continue

						root_slot = (pkg.root, pkg.slot_atom)
						if pkg.built and root_slot in self._rebuild.rebuild_list:
							mreasons = ["need to rebuild from source"]
						elif pkg.installed and root_slot in self._rebuild.reinstall_list:
							mreasons = ["need to rebuild from source"]
						elif (pkg.built and not mreasons and
							self._dynamic_config.ignored_binaries.get(
							pkg, {}).get("respect_use")):
							mreasons = ["use flag configuration mismatch"]
						elif (pkg.built and not mreasons and
							self._dynamic_config.ignored_binaries.get(
							pkg, {}).get("changed_deps")):
							mreasons = ["changed deps"]
						elif (pkg.built and use_ebuild_visibility and
							not self._equiv_ebuild_visible(pkg)):
							equiv_ebuild = self._equiv_ebuild(pkg)
							if equiv_ebuild is None:
								if portdb.cpv_exists(pkg.cpv):
									mreasons = ["ebuild corrupt"]
								else:
									mreasons = ["ebuild not available"]
							elif not mreasons:
								mreasons = get_masking_status(
									equiv_ebuild, pkgsettings, root_config,
									use=self._pkg_use_enabled(equiv_ebuild))
								if mreasons:
									metadata = equiv_ebuild._metadata

					masked_packages.append(
						(root_config, pkgsettings, cpv, repo, metadata, mreasons))

		if check_backtrack:
			if backtrack_mask:
				raise self._backtrack_mask()
			else:
				return

		if check_autounmask_breakage:
			if autounmask_broke_use_dep:
				raise self._autounmask_breakage()
			else:
				return

		missing_use_reasons = []
		missing_iuse_reasons = []
		for pkg in missing_use:
			use = self._pkg_use_enabled(pkg)
			missing_iuse = []
			#Use the unevaluated atom here, because some flags might have gone
			#lost during evaluation.
			required_flags = atom.unevaluated_atom.use.required
			missing_iuse = pkg.iuse.get_missing_iuse(required_flags)

			mreasons = []
			if missing_iuse:
				mreasons.append("Missing IUSE: %s" % " ".join(missing_iuse))
				missing_iuse_reasons.append((pkg, mreasons))
			else:
				need_enable = sorted(atom.use.enabled.difference(use).intersection(pkg.iuse.all))
				need_disable = sorted(atom.use.disabled.intersection(use).intersection(pkg.iuse.all))

				untouchable_flags = \
					frozenset(chain(pkg.use.mask, pkg.use.force))
				if any(x in untouchable_flags for x in
					chain(need_enable, need_disable)):
					continue

				missing_use_adjustable.add(pkg)
				required_use = pkg._metadata.get("REQUIRED_USE")
				required_use_warning = ""
				if required_use:
					old_use = self._pkg_use_enabled(pkg)
					new_use = set(self._pkg_use_enabled(pkg))
					for flag in need_enable:
						new_use.add(flag)
					for flag in need_disable:
						new_use.discard(flag)
					if check_required_use(required_use, old_use,
						pkg.iuse.is_valid_flag, eapi=pkg.eapi) \
						and not check_required_use(required_use, new_use,
						pkg.iuse.is_valid_flag, eapi=pkg.eapi):
							required_use_warning = ", this change violates use flag constraints " + \
								"defined by %s: '%s'" % (pkg.cpv, human_readable_required_use(required_use))

				if need_enable or need_disable:
					changes = []
					changes.extend(colorize("red", "+" + x) \
						for x in need_enable)
					changes.extend(colorize("blue", "-" + x) \
						for x in need_disable)
					mreasons.append("Change USE: %s" % " ".join(changes) + required_use_warning)
					missing_use_reasons.append((pkg, mreasons))

			if not missing_iuse and myparent and atom.unevaluated_atom.use.conditional:
				# Lets see if the violated use deps are conditional.
				# If so, suggest to change them on the parent.

				# If the child package is masked then a change to
				# parent USE is not a valid solution (a normal mask
				# message should be displayed instead).
				if pkg in masked_pkg_instances:
					continue

				mreasons = []
				violated_atom = atom.unevaluated_atom.violated_conditionals(self._pkg_use_enabled(pkg), \
					pkg.iuse.is_valid_flag, self._pkg_use_enabled(myparent))
				if not (violated_atom.use.enabled or violated_atom.use.disabled):
					#all violated use deps are conditional
					changes = []
					conditional = violated_atom.use.conditional
					involved_flags = set(chain(conditional.equal, conditional.not_equal, \
						conditional.enabled, conditional.disabled))

					untouchable_flags = \
						frozenset(chain(myparent.use.mask, myparent.use.force))
					if any(x in untouchable_flags for x in involved_flags):
						continue

					required_use = myparent._metadata.get("REQUIRED_USE")
					required_use_warning = ""
					if required_use:
						old_use = self._pkg_use_enabled(myparent)
						new_use = set(self._pkg_use_enabled(myparent))
						for flag in involved_flags:
							if flag in old_use:
								new_use.discard(flag)
							else:
								new_use.add(flag)
						if check_required_use(required_use, old_use,
							myparent.iuse.is_valid_flag,
							eapi=myparent.eapi) and \
							not check_required_use(required_use, new_use,
							myparent.iuse.is_valid_flag,
							eapi=myparent.eapi):
								required_use_warning = ", this change violates use flag constraints " + \
									"defined by %s: '%s'" % (myparent.cpv, \
									human_readable_required_use(required_use))

					target_use = {}
					for flag in involved_flags:
						if flag in self._pkg_use_enabled(myparent):
							target_use[flag] = False
							changes.append(colorize("blue", "-" + flag))
						else:
							target_use[flag] = True
							changes.append(colorize("red", "+" + flag))

					if collect_use_changes and not required_use_warning:
						previous_changes = self._dynamic_config._needed_use_config_changes.get(myparent)
						self._pkg_use_enabled(myparent, target_use=target_use)
						if previous_changes is not self._dynamic_config._needed_use_config_changes.get(myparent):
							return True

					mreasons.append("Change USE: %s" % " ".join(changes) + required_use_warning)
					if (myparent, mreasons) not in missing_use_reasons:
						missing_use_reasons.append((myparent, mreasons))

		if collect_use_changes:
			return False

		unmasked_use_reasons = [(pkg, mreasons) for (pkg, mreasons) \
			in missing_use_reasons if pkg not in masked_pkg_instances]

		unmasked_iuse_reasons = [(pkg, mreasons) for (pkg, mreasons) \
			in missing_iuse_reasons if pkg not in masked_pkg_instances]

		show_missing_use = False
		if unmasked_use_reasons:
			# Only show the latest version.
			show_missing_use = []
			pkg_reason = None
			parent_reason = None
			for pkg, mreasons in unmasked_use_reasons:
				if pkg is myparent:
					if parent_reason is None:
						#This happens if a use change on the parent
						#leads to a satisfied conditional use dep.
						parent_reason = (pkg, mreasons)
				elif pkg_reason is None:
					#Don't rely on the first pkg in unmasked_use_reasons,
					#being the highest version of the dependency.
					pkg_reason = (pkg, mreasons)
			if pkg_reason:
				show_missing_use.append(pkg_reason)
			if parent_reason:
				show_missing_use.append(parent_reason)

		elif unmasked_iuse_reasons:
			masked_with_iuse = False
			for pkg in masked_pkg_instances:
				#Use atom.unevaluated here, because some flags might have gone
				#lost during evaluation.
				if not pkg.iuse.get_missing_iuse(atom.unevaluated_atom.use.required):
					# Package(s) with required IUSE are masked,
					# so display a normal masking message.
					masked_with_iuse = True
					break
			if not masked_with_iuse:
				show_missing_use = unmasked_iuse_reasons

		if required_use_unsatisfied:
			# If there's a higher unmasked version in missing_use_adjustable
			# then we want to show that instead.
			for pkg in missing_use_adjustable:
				if pkg not in masked_pkg_instances and \
					pkg > required_use_unsatisfied[0]:
					required_use_unsatisfied = False
					break

		mask_docs = False

		if show_req_use is None and required_use_unsatisfied:
			# We have an unmasked package that only requires USE adjustment
			# in order to satisfy REQUIRED_USE, and nothing more. We assume
			# that the user wants the latest version, so only the first
			# instance is displayed.
			show_req_use = required_use_unsatisfied[0]

		if show_req_use is not None:

			pkg = show_req_use
			output_cpv = pkg.cpv + _repo_separator + pkg.repo
			writemsg("\n!!! " + \
				colorize("BAD", "The ebuild selected to satisfy ") + \
				colorize("INFORM", xinfo) + \
				colorize("BAD", " has unmet requirements.") + "\n",
				noiselevel=-1)
			use_display = pkg_use_display(pkg, self._frozen_config.myopts)
			writemsg("- %s %s\n" % (output_cpv, use_display),
				noiselevel=-1)
			writemsg("\n  The following REQUIRED_USE flag constraints " + \
				"are unsatisfied:\n", noiselevel=-1)
			reduced_noise = check_required_use(
				pkg._metadata["REQUIRED_USE"],
				self._pkg_use_enabled(pkg),
				pkg.iuse.is_valid_flag,
				eapi=pkg.eapi).tounicode()
			writemsg("    %s\n" % \
				human_readable_required_use(reduced_noise),
				noiselevel=-1)
			normalized_required_use = \
				" ".join(pkg._metadata["REQUIRED_USE"].split())
			if reduced_noise != normalized_required_use:
				writemsg("\n  The above constraints " + \
					"are a subset of the following complete expression:\n",
					noiselevel=-1)
				writemsg("    %s\n" % \
					human_readable_required_use(normalized_required_use),
					noiselevel=-1)
			writemsg("\n", noiselevel=-1)

		elif show_missing_use:
			writemsg("\nemerge: there are no ebuilds built with USE flags to satisfy "+green(xinfo)+".\n", noiselevel=-1)
			writemsg("!!! One of the following packages is required to complete your request:\n", noiselevel=-1)
			for pkg, mreasons in show_missing_use:
				writemsg("- "+pkg.cpv+_repo_separator+pkg.repo+" ("+", ".join(mreasons)+")\n", noiselevel=-1)

		elif masked_packages:
			writemsg("\n!!! " + \
				colorize("BAD", "All ebuilds that could satisfy ") + \
				colorize("INFORM", xinfo) + \
				colorize("BAD", " have been masked.") + "\n", noiselevel=-1)
			writemsg("!!! One of the following masked packages is required to complete your request:\n", noiselevel=-1)
			have_eapi_mask = show_masked_packages(masked_packages)
			if have_eapi_mask:
				writemsg("\n", noiselevel=-1)
				msg = ("The current version of portage supports " + \
					"EAPI '%s'. You must upgrade to a newer version" + \
					" of portage before EAPI masked packages can" + \
					" be installed.") % portage.const.EAPI
				writemsg("\n".join(textwrap.wrap(msg, 75)), noiselevel=-1)
			writemsg("\n", noiselevel=-1)
			mask_docs = True
		else:
			cp_exists = False
			if atom.package and not atom.cp.startswith("null/"):
				for pkg in self._iter_match_pkgs_any(
					root_config, Atom(atom.cp)):
					cp_exists = True
					break

			writemsg("\nemerge: there are no %s to satisfy " %
				("binary packages" if
				self._frozen_config.myopts.get("--usepkgonly", "y") == True
				else "ebuilds") + green(xinfo) + ".\n", noiselevel=-1)
			if isinstance(myparent, AtomArg) and \
				not cp_exists and \
				self._frozen_config.myopts.get(
				"--misspell-suggestions", "y") != "n":

				writemsg("\nemerge: searching for similar names..."
					, noiselevel=-1)

				search_index = self._frozen_config.myopts.get("--search-index", "y") != "n"
				# fakedbapi is indexed
				dbs = [vardb]
				if "--usepkgonly" not in self._frozen_config.myopts:
					dbs.append(IndexedPortdb(portdb) if search_index else portdb)
				if "--usepkg" in self._frozen_config.myopts:
					# bindbapi is indexed
					dbs.append(bindb)

				matches = similar_name_search(dbs, atom)

				if len(matches) == 1:
					writemsg("\nemerge: Maybe you meant " + matches[0] + "?\n"
						, noiselevel=-1)
				elif len(matches) > 1:
					writemsg(
						"\nemerge: Maybe you meant any of these: %s?\n" % \
						(", ".join(matches),), noiselevel=-1)
				else:
					# Generally, this would only happen if
					# all dbapis are empty.
					writemsg(" nothing similar found.\n"
						, noiselevel=-1)
		msg = []
		if not isinstance(myparent, AtomArg):
			# It's redundant to show parent for AtomArg since
			# it's the same as 'xinfo' displayed above.
			dep_chain = self._get_dep_chain(myparent, atom)
			for node, node_type in dep_chain:
				msg.append('(dependency required by "%s" [%s])' % \
						(colorize('INFORM', "%s" % (node)), node_type))

		if msg:
			writemsg("\n".join(msg), noiselevel=-1)
			writemsg("\n", noiselevel=-1)

		if mask_docs:
			show_mask_docs()
			writemsg("\n", noiselevel=-1)

	def _iter_match_pkgs_any(self, root_config, atom, onlydeps=False):
		for db, pkg_type, built, installed, db_keys in \
			self._dynamic_config._filtered_trees[root_config.root]["dbs"]:
			for pkg in self._iter_match_pkgs(root_config,
				pkg_type, atom, onlydeps=onlydeps):
				yield pkg

	def _iter_match_pkgs(self, root_config, pkg_type, atom,
		onlydeps=False):
		if atom.package:
			return self._iter_match_pkgs_atom(root_config, pkg_type,
				atom, onlydeps=onlydeps)
		else:
			return self._iter_match_pkgs_soname(root_config, pkg_type,
				atom, onlydeps=onlydeps)

	def _iter_match_pkgs_soname(self, root_config, pkg_type, atom,
		onlydeps=False):
		db = root_config.trees[self.pkg_tree_map[pkg_type]].dbapi
		installed = pkg_type == 'installed'

		if isinstance(db, DbapiProvidesIndex):
			# descending order
			for cpv in reversed(db.match(atom)):
				yield self._pkg(cpv, pkg_type, root_config,
					installed=installed, onlydeps=onlydeps)

	def _iter_match_pkgs_atom(self, root_config, pkg_type, atom,
		onlydeps=False):
		"""
		Iterate over Package instances of pkg_type matching the given atom.
		This does not check visibility and it also does not match USE for
		unbuilt ebuilds since USE are lazily calculated after visibility
		checks (to avoid the expense when possible).
		"""

		db = root_config.trees[self.pkg_tree_map[pkg_type]].dbapi
		atom_exp = dep_expand(atom, mydb=db, settings=root_config.settings)
		cp_list = db.cp_list(atom_exp.cp)
		matched_something = False
		installed = pkg_type == 'installed'

		if cp_list:
			atom_set = InternalPackageSet(initial_atoms=(atom,),
				allow_repo=True)

			# descending order
			cp_list.reverse()
			for cpv in cp_list:
				# Call match_from_list on one cpv at a time, in order
				# to avoid unnecessary match_from_list comparisons on
				# versions that are never yielded from this method.
				if match_from_list(atom_exp, [cpv]):
					try:
						pkg = self._pkg(cpv, pkg_type, root_config,
							installed=installed, onlydeps=onlydeps,
							myrepo=getattr(cpv, 'repo', None))
					except portage.exception.PackageNotFound:
						pass
					else:
						# A cpv can be returned from dbapi.match() as an
						# old-style virtual match even in cases when the
						# package does not actually PROVIDE the virtual.
						# Filter out any such false matches here.

						# Make sure that cpv from the current repo satisfies the atom.
						# This might not be the case if there are several repos with
						# the same cpv, but different metadata keys, like SLOT.
						# Also, parts of the match that require metadata access
						# are deferred until we have cached the metadata in a
						# Package instance.
						if not atom_set.findAtomForPackage(pkg,
							modified_use=self._pkg_use_enabled(pkg)):
							continue
						matched_something = True
						yield pkg

		# USE=multislot can make an installed package appear as if
		# it doesn't satisfy a slot dependency. Rebuilding the ebuild
		# won't do any good as long as USE=multislot is enabled since
		# the newly built package still won't have the expected slot.
		# Therefore, assume that such SLOT dependencies are already
		# satisfied rather than forcing a rebuild.
		if not matched_something and installed and \
			atom.slot is not None and not atom.slot_operator_built:

			if "remove" in self._dynamic_config.myparams:
				# We need to search the portdbapi, which is not in our
				# normal dbs list, in order to find the real SLOT.
				portdb = self._frozen_config.trees[root_config.root]["porttree"].dbapi
				db_keys = list(portdb._aux_cache_keys)
				dbs = [(portdb, "ebuild", False, False, db_keys)]
			else:
				dbs = self._dynamic_config._filtered_trees[root_config.root]["dbs"]

			cp_list = db.cp_list(atom_exp.cp)
			if cp_list:
				atom_set = InternalPackageSet(
					initial_atoms=(atom.without_slot,), allow_repo=True)
				atom_exp_without_slot = atom_exp.without_slot
				cp_list.reverse()
				for cpv in cp_list:
					if not match_from_list(atom_exp_without_slot, [cpv]):
						continue
					slot_available = False
					for other_db, other_type, other_built, \
						other_installed, other_keys in dbs:
						try:
							if portage.dep._match_slot(atom,
								other_db._pkg_str(_unicode(cpv), None)):
								slot_available = True
								break
						except (KeyError, InvalidData):
							pass
					if not slot_available:
						continue
					inst_pkg = self._pkg(cpv, "installed",
						root_config, installed=installed, myrepo=atom.repo)
					# Remove the slot from the atom and verify that
					# the package matches the resulting atom.
					if atom_set.findAtomForPackage(inst_pkg):
						yield inst_pkg
						return

	def _select_pkg_highest_available(self, root, atom, onlydeps=False, parent=None):
		if atom.package:
			cache_key = (root, atom, atom.unevaluated_atom, onlydeps,
				self._dynamic_config._autounmask)
			self._dynamic_config._highest_pkg_cache_cp_map.\
				setdefault((root, atom.cp), []).append(cache_key)
		else:
			cache_key = (root, atom, onlydeps,
				self._dynamic_config._autounmask)
			self._dynamic_config._highest_pkg_cache_cp_map.\
				setdefault((root, atom), []).append(cache_key)
		ret = self._dynamic_config._highest_pkg_cache.get(cache_key)
		if ret is not None:
			return ret
		ret = self._select_pkg_highest_available_imp(root, atom, onlydeps=onlydeps, parent=parent)
		self._dynamic_config._highest_pkg_cache[cache_key] = ret
		pkg, existing = ret
		if pkg is not None:
			if self._pkg_visibility_check(pkg) and \
				not (pkg.installed and pkg.masks):
				self._dynamic_config._visible_pkgs[pkg.root].cpv_inject(pkg)
		return ret

	def _is_argument(self, pkg):
		for arg, atom in self._iter_atoms_for_pkg(pkg):
			if isinstance(arg, (AtomArg, PackageArg)):
				return True
		return False

	def _prune_highest_pkg_cache(self, pkg):
		cache = self._dynamic_config._highest_pkg_cache
		key_map = self._dynamic_config._highest_pkg_cache_cp_map
		for cp in pkg.provided_cps:
			for cache_key in key_map.pop((pkg.root, cp), []):
				cache.pop(cache_key, None)
		if pkg.provides is not None:
			for atom in pkg.provides:
				for cache_key in key_map.pop((pkg.root, atom), []):
					cache.pop(cache_key, None)

	def _want_installed_pkg(self, pkg):
		"""
		Given an installed package returned from select_pkg, return
		True if the user has not explicitly requested for this package
		to be replaced (typically via an atom on the command line).
		"""
		if self._frozen_config.excluded_pkgs.findAtomForPackage(pkg,
			modified_use=self._pkg_use_enabled(pkg)):
			return True

		arg = False
		try:
			for arg, atom in self._iter_atoms_for_pkg(pkg):
				if arg.force_reinstall:
					return False
		except InvalidDependString:
			pass

		if "selective" in self._dynamic_config.myparams:
			return True

		return not arg

	def _want_update_pkg(self, parent, pkg):

		if self._frozen_config.excluded_pkgs.findAtomForPackage(pkg,
			modified_use=self._pkg_use_enabled(pkg)):
			return False

		arg_atoms = None
		try:
			arg_atoms = list(self._iter_atoms_for_pkg(pkg))
		except InvalidDependString:
			if not pkg.installed:
				# should have been masked before it was selected
				raise

		depth = parent.depth or 0
		if isinstance(depth, int):
			depth += 1

		if arg_atoms:
			for arg, atom in arg_atoms:
				if arg.reset_depth:
					depth = 0
					break

		update = "--update" in self._frozen_config.myopts

		return (not self._dynamic_config._complete_mode and
			(arg_atoms or update) and
			not self._too_deep(depth))

	def _too_deep(self, depth):
		"""
		Check if a package depth is deeper than the max allowed depth.

		@param depth: the depth of a particular package
		@type depth: int or _UNREACHABLE_DEPTH
		@rtype: bool
		@return: True if the package is deeper than the max allowed depth
		"""
		deep = self._dynamic_config.myparams.get("deep", 0)
		if depth is self._UNREACHABLE_DEPTH:
			return True
		elif deep is True:
			return False
		else:
			# All non-integer cases are handled above,
			# so both values must be int type.
			return depth > deep

	def _depth_increment(self, depth, n=1):
		"""
		Return depth + n if depth is an int, otherwise return depth.

		@param depth: the depth of a particular package
		@type depth: int or _UNREACHABLE_DEPTH
		@param n: number to add (default is 1)
		@type n: int
		@rtype: int or _UNREACHABLE_DEPTH
		@return: depth + 1 or _UNREACHABLE_DEPTH
		"""
		return depth + n if isinstance(depth, int) else depth

	def _equiv_ebuild(self, pkg):
		try:
			return self._pkg(
				pkg.cpv, "ebuild", pkg.root_config, myrepo=pkg.repo)
		except portage.exception.PackageNotFound:
			return next(self._iter_match_pkgs(pkg.root_config,
				"ebuild", Atom("=%s" % (pkg.cpv,))), None)

	def _equiv_ebuild_visible(self, pkg, autounmask_level=None):
		try:
			pkg_eb = self._pkg(
				pkg.cpv, "ebuild", pkg.root_config, myrepo=pkg.repo)
		except portage.exception.PackageNotFound:
			pkg_eb_visible = False
			for pkg_eb in self._iter_match_pkgs(pkg.root_config,
				"ebuild", Atom("=%s" % (pkg.cpv,))):
				if self._pkg_visibility_check(pkg_eb, autounmask_level):
					pkg_eb_visible = True
					break
			if not pkg_eb_visible:
				return False
		else:
			if not self._pkg_visibility_check(pkg_eb, autounmask_level):
				return False

		return True

	def _equiv_binary_installed(self, pkg):
		build_time = pkg.build_time
		if not build_time:
			return False

		try:
			inst_pkg = self._pkg(pkg.cpv, "installed",
				pkg.root_config, installed=True)
		except PackageNotFound:
			return False

		return build_time == inst_pkg.build_time

	class _AutounmaskLevel(object):
		__slots__ = ("allow_use_changes", "allow_unstable_keywords", "allow_license_changes", \
			"allow_missing_keywords", "allow_unmasks")

		def __init__(self):
			self.allow_use_changes = False
			self.allow_license_changes = False
			self.allow_unstable_keywords = False
			self.allow_missing_keywords = False
			self.allow_unmasks = False

	def _autounmask_levels(self):
		"""
		Iterate over the different allowed things to unmask.

		0. USE
		1. USE + license
		2. USE + ~arch + license
		3. USE + ~arch + license + missing keywords
		4. USE + license + masks
		5. USE + ~arch + license + masks
		6. USE + ~arch + license + missing keywords + masks

		Some thoughts:
			* Do least invasive changes first.
			* Try unmasking alone before unmasking + missing keywords
				to avoid -9999 versions if possible
		"""

		if self._dynamic_config._autounmask is not True:
			return

		autounmask_keep_keywords = self._frozen_config.myopts.get("--autounmask-keep-keywords", "n") != "n"
		autounmask_keep_masks = self._frozen_config.myopts.get("--autounmask-keep-masks", "n") != "n"
		autounmask_level = self._AutounmaskLevel()

		autounmask_level.allow_use_changes = True
		yield autounmask_level

		autounmask_level.allow_license_changes = True
		yield autounmask_level

		if not autounmask_keep_keywords:
			autounmask_level.allow_unstable_keywords = True
			yield autounmask_level

		if not (autounmask_keep_keywords or autounmask_keep_masks):
			autounmask_level.allow_unstable_keywords = True
			autounmask_level.allow_missing_keywords = True
			yield autounmask_level

		if not autounmask_keep_masks:
			# 4. USE + license + masks
			# Try to respect keywords while discarding
			# package.mask (see bug #463394).
			autounmask_level.allow_unstable_keywords = False
			autounmask_level.allow_missing_keywords = False
			autounmask_level.allow_unmasks = True
			yield autounmask_level

		if not (autounmask_keep_keywords or autounmask_keep_masks):
			autounmask_level.allow_unstable_keywords = True

			for missing_keyword, unmask in ((False, True), (True, True)):

				autounmask_level.allow_missing_keywords = missing_keyword
				autounmask_level.allow_unmasks = unmask

				yield autounmask_level


	def _select_pkg_highest_available_imp(self, root, atom, onlydeps=False, parent=None):
		pkg, existing = self._wrapped_select_pkg_highest_available_imp(
			root, atom, onlydeps=onlydeps, parent=parent)

		default_selection = (pkg, existing)

		if self._dynamic_config._autounmask is True:
			if pkg is not None and \
				pkg.installed and \
				not self._want_installed_pkg(pkg):
				pkg = None

			# Temporarily reset _need_restart state, in order to
			# avoid interference as reported in bug #459832.
			earlier_need_restart = self._dynamic_config._need_restart
			self._dynamic_config._need_restart = False
			try:
				for autounmask_level in self._autounmask_levels():
					if pkg is not None:
						break

					pkg, existing = \
						self._wrapped_select_pkg_highest_available_imp(
							root, atom, onlydeps=onlydeps,
							autounmask_level=autounmask_level, parent=parent)

					if pkg is not None and \
						pkg.installed and \
						not self._want_installed_pkg(pkg):
						pkg = None

				if self._dynamic_config._need_restart:
					return None, None
			finally:
				if earlier_need_restart:
					self._dynamic_config._need_restart = True

		if pkg is None:
			# This ensures that we can fall back to an installed package
			# that may have been rejected in the autounmask path above.
			return default_selection

		return pkg, existing

	def _pkg_visibility_check(self, pkg, autounmask_level=None, trust_graph=True):

		if pkg.visible:
			return True

		if trust_graph and pkg in self._dynamic_config.digraph:
			# Sometimes we need to temporarily disable
			# dynamic_config._autounmask, but for overall
			# consistency in dependency resolution, in most
			# cases we want to treat packages in the graph
			# as though they are visible.
			return True

		if not self._dynamic_config._autounmask or autounmask_level is None:
			return False

		pkgsettings = self._frozen_config.pkgsettings[pkg.root]
		root_config = self._frozen_config.roots[pkg.root]
		mreasons = _get_masking_status(pkg, pkgsettings, root_config, use=self._pkg_use_enabled(pkg))

		masked_by_unstable_keywords = False
		masked_by_missing_keywords = False
		missing_licenses = None
		masked_by_something_else = False
		masked_by_p_mask = False

		for reason in mreasons:
			hint = reason.unmask_hint

			if hint is None:
				masked_by_something_else = True
			elif hint.key == "unstable keyword":
				masked_by_unstable_keywords = True
				if hint.value == "**":
					masked_by_missing_keywords = True
			elif hint.key == "p_mask":
				masked_by_p_mask = True
			elif hint.key == "license":
				missing_licenses = hint.value
			else:
				masked_by_something_else = True

		if masked_by_something_else:
			return False

		if pkg in self._dynamic_config._needed_unstable_keywords:
			#If the package is already keyworded, remove the mask.
			masked_by_unstable_keywords = False
			masked_by_missing_keywords = False

		if pkg in self._dynamic_config._needed_p_mask_changes:
			#If the package is already keyworded, remove the mask.
			masked_by_p_mask = False

		if missing_licenses:
			#If the needed licenses are already unmasked, remove the mask.
			missing_licenses.difference_update(self._dynamic_config._needed_license_changes.get(pkg, set()))

		if not (masked_by_unstable_keywords or masked_by_p_mask or missing_licenses):
			#Package has already been unmasked.
			return True

		if (masked_by_unstable_keywords and not autounmask_level.allow_unstable_keywords) or \
			(masked_by_missing_keywords and not autounmask_level.allow_missing_keywords) or \
			(masked_by_p_mask and not autounmask_level.allow_unmasks) or \
			(missing_licenses and not autounmask_level.allow_license_changes):
			#We are not allowed to do the needed changes.
			return False

		if masked_by_unstable_keywords:
			self._dynamic_config._needed_unstable_keywords.add(pkg)
			backtrack_infos = self._dynamic_config._backtrack_infos
			backtrack_infos.setdefault("config", {})
			backtrack_infos["config"].setdefault("needed_unstable_keywords", set())
			backtrack_infos["config"]["needed_unstable_keywords"].add(pkg)

		if masked_by_p_mask:
			self._dynamic_config._needed_p_mask_changes.add(pkg)
			backtrack_infos = self._dynamic_config._backtrack_infos
			backtrack_infos.setdefault("config", {})
			backtrack_infos["config"].setdefault("needed_p_mask_changes", set())
			backtrack_infos["config"]["needed_p_mask_changes"].add(pkg)

		if missing_licenses:
			self._dynamic_config._needed_license_changes.setdefault(pkg, set()).update(missing_licenses)
			backtrack_infos = self._dynamic_config._backtrack_infos
			backtrack_infos.setdefault("config", {})
			backtrack_infos["config"].setdefault("needed_license_changes", set())
			backtrack_infos["config"]["needed_license_changes"].add((pkg, frozenset(missing_licenses)))

		return True

	def _pkg_use_enabled(self, pkg, target_use=None):
		"""
		If target_use is None, returns pkg.use.enabled + changes in _needed_use_config_changes.
		If target_use is given, the need changes are computed to make the package useable.
		Example: target_use = { "foo": True, "bar": False }
		The flags target_use must be in the pkg's IUSE.
		@rtype: frozenset
		@return: set of effectively enabled USE flags, including changes
			made by autounmask
		"""
		if pkg.built:
			return pkg.use.enabled
		needed_use_config_change = self._dynamic_config._needed_use_config_changes.get(pkg)

		if target_use is None:
			if needed_use_config_change is None:
				return pkg.use.enabled
			else:
				return needed_use_config_change[0]

		if needed_use_config_change is not None:
			old_use = needed_use_config_change[0]
			new_use = set()
			old_changes = needed_use_config_change[1]
			new_changes = old_changes.copy()
		else:
			old_use = pkg.use.enabled
			new_use = set()
			old_changes = {}
			new_changes = {}

		for flag, state in target_use.items():
			real_flag = pkg.iuse.get_real_flag(flag)
			if real_flag is None:
				# Triggered by use-dep defaults.
				continue
			if state:
				if real_flag not in old_use:
					if new_changes.get(real_flag) == False:
						return old_use
					new_changes[real_flag] = True
				new_use.add(flag)
			else:
				if real_flag in old_use:
					if new_changes.get(real_flag) == True:
						return old_use
					new_changes[real_flag] = False
		new_use.update(old_use.difference(target_use))

		def want_restart_for_use_change(pkg, new_use):
			if pkg not in self._dynamic_config.digraph.nodes:
				return False

			for key in Package._dep_keys + ("LICENSE",):
				dep = pkg._metadata[key]
				old_val = set(portage.dep.use_reduce(dep, pkg.use.enabled, is_valid_flag=pkg.iuse.is_valid_flag, flat=True))
				new_val = set(portage.dep.use_reduce(dep, new_use, is_valid_flag=pkg.iuse.is_valid_flag, flat=True))

				if old_val != new_val:
					return True

			parent_atoms = self._dynamic_config._parent_atoms.get(pkg)
			if not parent_atoms:
				return False

			new_use, changes = self._dynamic_config._needed_use_config_changes.get(pkg)
			for ppkg, atom in parent_atoms:
				if not atom.use:
					continue

				# Backtrack only if changes break a USE dependency.
				enabled = atom.use.enabled
				disabled = atom.use.disabled
				for k, v in changes.items():
					want_enabled = k in enabled
					if (want_enabled or k in disabled) and want_enabled != v:
						return True

			return False

		# Always return frozenset since the result needs to be
		# hashable (see bug #531112).
		new_use = frozenset(new_use)

		if new_changes != old_changes:
			#Don't do the change if it violates REQUIRED_USE.
			required_use_satisfied = True
			required_use = pkg._metadata.get("REQUIRED_USE")
			if required_use and check_required_use(required_use, old_use,
				pkg.iuse.is_valid_flag, eapi=pkg.eapi) and \
				not check_required_use(required_use, new_use,
				pkg.iuse.is_valid_flag, eapi=pkg.eapi):
				required_use_satisfied = False

			if any(x in pkg.use.mask for x in new_changes) or \
				any(x in pkg.use.force for x in new_changes):
				return old_use

			changes = _use_changes(new_use, new_changes,
				required_use_satisfied=required_use_satisfied)
			self._dynamic_config._needed_use_config_changes[pkg] = changes
			backtrack_infos = self._dynamic_config._backtrack_infos
			backtrack_infos.setdefault("config", {})
			backtrack_infos["config"].setdefault("needed_use_config_changes", [])
			backtrack_infos["config"]["needed_use_config_changes"].append((pkg, changes))
			if want_restart_for_use_change(pkg, new_use):
				self._dynamic_config._need_restart = True
		return new_use

	def _wrapped_select_pkg_highest_available_imp(self, root, atom, onlydeps=False, autounmask_level=None, parent=None):
		root_config = self._frozen_config.roots[root]
		pkgsettings = self._frozen_config.pkgsettings[root]
		dbs = self._dynamic_config._filtered_trees[root]["dbs"]
		vardb = self._frozen_config.roots[root].trees["vartree"].dbapi
		# List of acceptable packages, ordered by type preference.
		matched_packages = []
		highest_version = None
		atom_cp = None
		have_new_virt = None
		if atom.package:
			atom_cp = atom.cp
			have_new_virt = (atom_cp.startswith("virtual/") and
				self._have_new_virt(root, atom_cp))

		existing_node = None
		myeb = None
		rebuilt_binaries = 'rebuilt_binaries' in self._dynamic_config.myparams
		usepkg = "--usepkg" in self._frozen_config.myopts
		usepkgonly = "--usepkgonly" in self._frozen_config.myopts
		empty = "empty" in self._dynamic_config.myparams
		selective = "selective" in self._dynamic_config.myparams
		reinstall = False
		avoid_update = "--update" not in self._frozen_config.myopts
		dont_miss_updates = "--update" in self._frozen_config.myopts
		use_ebuild_visibility = self._frozen_config.myopts.get(
			'--use-ebuild-visibility', 'n') != 'n'
		reinstall_atoms = self._frozen_config.reinstall_atoms
		usepkg_exclude = self._frozen_config.usepkg_exclude
		useoldpkg_atoms = self._frozen_config.useoldpkg_atoms
		matched_oldpkg = []
		# Behavior of the "selective" parameter depends on
		# whether or not a package matches an argument atom.
		# If an installed package provides an old-style
		# virtual that is no longer provided by an available
		# package, the installed package may match an argument
		# atom even though none of the available packages do.
		# Therefore, "selective" logic does not consider
		# whether or not an installed package matches an
		# argument atom. It only considers whether or not
		# available packages match argument atoms, which is
		# represented by the found_available_arg flag.
		found_available_arg = False
		packages_with_invalid_use_config = []
		for find_existing_node in True, False:
			if existing_node:
				break
			for db, pkg_type, built, installed, db_keys in dbs:
				if existing_node:
					break
				if installed and not find_existing_node:
					want_reinstall = reinstall or empty or \
						(found_available_arg and not selective)
					if want_reinstall and matched_packages:
						continue

				# For unbuilt ebuilds, ignore USE deps for the initial
				# match since we want to ensure that updates aren't
				# missed solely due to the user's USE configuration.
				for pkg in self._iter_match_pkgs(root_config, pkg_type,
					atom.without_use if (atom.package and not built) else atom,
					onlydeps=onlydeps):
					if have_new_virt is True and pkg.cp != atom_cp:
						# pull in a new-style virtual instead
						continue
					if pkg in self._dynamic_config._runtime_pkg_mask:
						# The package has been masked by the backtracking logic
						continue
					root_slot = (pkg.root, pkg.slot_atom)
					if pkg.built and root_slot in self._rebuild.rebuild_list:
						continue
					if (pkg.installed and
						root_slot in self._rebuild.reinstall_list):
						continue

					if not pkg.installed and \
						self._frozen_config.excluded_pkgs.findAtomForPackage(pkg, \
							modified_use=self._pkg_use_enabled(pkg)):
						continue

					if built and not installed and usepkg_exclude.findAtomForPackage(pkg, \
						modified_use=self._pkg_use_enabled(pkg)):
						break

					useoldpkg = useoldpkg_atoms.findAtomForPackage(pkg, \
						modified_use=self._pkg_use_enabled(pkg))

					if packages_with_invalid_use_config and (not built or not useoldpkg) and \
						(not pkg.installed or dont_miss_updates):
						# Check if a higher version was rejected due to user
						# USE configuration. The packages_with_invalid_use_config
						# list only contains unbuilt ebuilds since USE can't
						# be changed for built packages.
						higher_version_rejected = False
						repo_priority = pkg.repo_priority
						for rejected in packages_with_invalid_use_config:
							if rejected.cp != pkg.cp:
								continue
							if rejected > pkg:
								higher_version_rejected = True
								break
							if portage.dep.cpvequal(rejected.cpv, pkg.cpv):
								# If version is identical then compare
								# repo priority (see bug #350254).
								rej_repo_priority = rejected.repo_priority
								if rej_repo_priority is not None and \
									(repo_priority is None or
									rej_repo_priority > repo_priority):
									higher_version_rejected = True
									break
						if higher_version_rejected:
							continue

					cpv = pkg.cpv
					reinstall_for_flags = None

					if not pkg.installed or \
						(matched_packages and not avoid_update):
						# Only enforce visibility on installed packages
						# if there is at least one other visible package
						# available. By filtering installed masked packages
						# here, packages that have been masked since they
						# were installed can be automatically downgraded
						# to an unmasked version. NOTE: This code needs to
						# be consistent with masking behavior inside
						# _dep_check_composite_db, in order to prevent
						# incorrect choices in || deps like bug #351828.

						if not self._pkg_visibility_check(pkg, autounmask_level):
							continue

						# Enable upgrade or downgrade to a version
						# with visible KEYWORDS when the installed
						# version is masked by KEYWORDS, but never
						# reinstall the same exact version only due
						# to a KEYWORDS mask. See bug #252167.

						identical_binary = False
						if pkg.type_name != "ebuild" and matched_packages:
							# Don't re-install a binary package that is
							# identical to the currently installed package
							# (see bug #354441).
							if usepkg and pkg.installed:
								for selected_pkg in matched_packages:
									if selected_pkg.type_name == "binary" and \
										selected_pkg.cpv == pkg.cpv and \
										selected_pkg.build_time == \
										pkg.build_time:
										identical_binary = True
										break

						if (not identical_binary and pkg.built and
							(use_ebuild_visibility or matched_packages)):
								# If the ebuild no longer exists or it's
								# keywords have been dropped, reject built
								# instances (installed or binary).
								# If --usepkgonly is enabled, assume that
								# the ebuild status should be ignored unless
								# --use-ebuild-visibility has been specified.
								if not use_ebuild_visibility and (usepkgonly or useoldpkg):
									if pkg.installed and pkg.masks:
										continue
								elif not self._equiv_ebuild_visible(pkg,
									autounmask_level=autounmask_level):
									continue

					# Calculation of USE for unbuilt ebuilds is relatively
					# expensive, so it is only performed lazily, after the
					# above visibility checks are complete.

					myarg = None
					try:
						for myarg, myarg_atom in self._iter_atoms_for_pkg(pkg):
							if myarg.force_reinstall:
								reinstall = True
								break
					except InvalidDependString:
						if not installed:
							# masked by corruption
							continue
					if not installed and myarg:
						found_available_arg = True

					if atom.package and atom.unevaluated_atom.use:
						#Make sure we don't miss a 'missing IUSE'.
						if pkg.iuse.get_missing_iuse(atom.unevaluated_atom.use.required):
							# Don't add this to packages_with_invalid_use_config
							# since IUSE cannot be adjusted by the user.
							continue

					if atom.package and atom.use is not None:

						if autounmask_level and autounmask_level.allow_use_changes and not pkg.built:
							target_use = {}
							for flag in atom.use.enabled:
								target_use[flag] = True
							for flag in atom.use.disabled:
								target_use[flag] = False
							use = self._pkg_use_enabled(pkg, target_use)
						else:
							use = self._pkg_use_enabled(pkg)

						use_match = True
						can_adjust_use = not pkg.built
						is_valid_flag = pkg.iuse.is_valid_flag
						missing_enabled = frozenset(x for x in
							atom.use.missing_enabled if not is_valid_flag(x))
						missing_disabled = frozenset(x for x in
							atom.use.missing_disabled if not is_valid_flag(x))

						if atom.use.enabled:
							if any(x in atom.use.enabled for x in missing_disabled):
								use_match = False
								can_adjust_use = False
							need_enabled = atom.use.enabled.difference(use)
							if need_enabled:
								need_enabled = need_enabled.difference(missing_enabled)
								if need_enabled:
									use_match = False
									if can_adjust_use:
										if any(x in pkg.use.mask for x in need_enabled):
											can_adjust_use = False

						if atom.use.disabled:
							if any(x in atom.use.disabled for x in missing_enabled):
								use_match = False
								can_adjust_use = False
							need_disabled = atom.use.disabled.intersection(use)
							if need_disabled:
								need_disabled = need_disabled.difference(missing_disabled)
								if need_disabled:
									use_match = False
									if can_adjust_use:
										if any(x in pkg.use.force and x not in
											pkg.use.mask for x in need_disabled):
											can_adjust_use = False

						if not use_match:
							if can_adjust_use:
								# Above we must ensure that this package has
								# absolutely no use.force, use.mask, or IUSE
								# issues that the user typically can't make
								# adjustments to solve (see bug #345979).
								# FIXME: Conditional USE deps complicate
								# issues. This code currently excludes cases
								# in which the user can adjust the parent
								# package's USE in order to satisfy the dep.
								packages_with_invalid_use_config.append(pkg)
							continue

					if atom_cp is None or pkg.cp == atom_cp:
						if highest_version is None:
							highest_version = pkg
						elif pkg > highest_version:
							highest_version = pkg
					# At this point, we've found the highest visible
					# match from the current repo. Any lower versions
					# from this repo are ignored, so this so the loop
					# will always end with a break statement below
					# this point.
					if find_existing_node:
						# Use reversed iteration in order to get
						# descending order here, so that the highest
						# version involved in a slot conflict is
						# selected. This is needed for correct operation
						# of conflict_downgrade logic in the dep_zapdeps
						# function (see bug 554070).
						e_pkg = next(reversed(list(
							self._dynamic_config._package_tracker.match(
							root, pkg.slot_atom, installed=False))), None)

						if not e_pkg:
							break

						# Use PackageSet.findAtomForPackage()
						# for PROVIDE support.
						if atom.match(e_pkg.with_use(
							self._pkg_use_enabled(e_pkg))):
							if highest_version and \
								(atom_cp is None or
								e_pkg.cp == atom_cp) and \
								e_pkg < highest_version and \
								e_pkg.slot_atom != highest_version.slot_atom:
								# There is a higher version available in a
								# different slot, so this existing node is
								# irrelevant.
								pass
							else:
								matched_packages.append(e_pkg)
								existing_node = e_pkg
						break
					# Compare built package to current config and
					# reject the built package if necessary.
					reinstall_use = ("--newuse" in self._frozen_config.myopts or \
						"--reinstall" in self._frozen_config.myopts)
					changed_deps = (
						self._dynamic_config.myparams.get(
						"changed_deps", "n") != "n")
					changed_deps_report = self._dynamic_config.myparams.get(
						"changed_deps_report")
					binpkg_changed_deps = (
						self._dynamic_config.myparams.get(
						"binpkg_changed_deps", "n") != "n")
					respect_use = self._dynamic_config.myparams.get("binpkg_respect_use") in ("y", "auto")
					if built and not useoldpkg and \
						(not installed or matched_packages) and \
						not (installed and
						self._frozen_config.excluded_pkgs.findAtomForPackage(pkg,
						modified_use=self._pkg_use_enabled(pkg))):
						if myeb and "--newrepo" in self._frozen_config.myopts and myeb.repo != pkg.repo:
							break
						elif self._dynamic_config.myparams.get("changed_slot") and self._changed_slot(pkg):
							if installed:
								break
							else:
								# Continue searching for a binary package
								# with the desired SLOT metadata.
								continue
						elif reinstall_use or (not installed and respect_use):
							iuses = pkg.iuse.all
							old_use = self._pkg_use_enabled(pkg)
							if myeb:
								now_use = self._pkg_use_enabled(myeb)
								forced_flags = set(chain(
									myeb.use.force, myeb.use.mask))
							else:
								pkgsettings.setcpv(pkg)
								now_use = pkgsettings["PORTAGE_USE"].split()
								forced_flags = set(chain(
									pkgsettings.useforce, pkgsettings.usemask))
							cur_iuse = iuses
							if myeb and not usepkgonly and not useoldpkg:
								cur_iuse = myeb.iuse.all
							reinstall_for_flags = self._reinstall_for_flags(pkg,
								forced_flags, old_use, iuses, now_use, cur_iuse)
							if reinstall_for_flags:
								if not pkg.installed:
									self._dynamic_config.\
										ignored_binaries.setdefault(
										pkg, {}).setdefault(
										"respect_use", set()).update(
										reinstall_for_flags)
									# Continue searching for a binary
									# package instance built with the
									# desired USE settings.
									continue
								break

						installed_changed_deps = False
						if installed and (changed_deps or changed_deps_report):
							installed_changed_deps = self._changed_deps(pkg)

						if ((installed_changed_deps and changed_deps) or
							(not installed and binpkg_changed_deps and
							self._changed_deps(pkg))):
							if not installed:
								self._dynamic_config.\
									ignored_binaries.setdefault(
									pkg, {})["changed_deps"] = True
								# Continue searching for a binary
								# package instance built with the
								# desired USE settings.
								continue
							break

					# Compare current config to installed package
					# and do not reinstall if possible.
					if not installed and not useoldpkg and cpv in vardb.match(atom):
						inst_pkg = vardb.match_pkgs(
							Atom('=' + pkg.cpv))[0]
						if "--newrepo" in self._frozen_config.myopts and pkg.repo != inst_pkg.repo:
							reinstall = True
						elif reinstall_use:
							forced_flags = set()
							forced_flags.update(pkg.use.force)
							forced_flags.update(pkg.use.mask)
							old_use = inst_pkg.use.enabled
							old_iuse = inst_pkg.iuse.all
							cur_use = self._pkg_use_enabled(pkg)
							cur_iuse = pkg.iuse.all
							reinstall_for_flags = \
								self._reinstall_for_flags(pkg,
								forced_flags, old_use, old_iuse,
								cur_use, cur_iuse)
							if reinstall_for_flags:
								reinstall = True
					if reinstall_atoms.findAtomForPackage(pkg, \
							modified_use=self._pkg_use_enabled(pkg)):
						reinstall = True
					if not built:
						myeb = pkg
					elif useoldpkg:
						matched_oldpkg.append(pkg)
					matched_packages.append(pkg)
					if reinstall_for_flags:
						self._dynamic_config._reinstall_nodes[pkg] = \
							reinstall_for_flags
					break

		if not matched_packages:
			return None, None

		if "--debug" in self._frozen_config.myopts:
			for pkg in matched_packages:
				portage.writemsg("%s %s%s%s\n" % \
					((pkg.type_name + ":").rjust(10),
					pkg.cpv, _repo_separator, pkg.repo), noiselevel=-1)

		# Filter out any old-style virtual matches if they are
		# mixed with new-style virtual matches.
		cp = atom_cp
		if len(matched_packages) > 1 and \
			cp is not None and \
			"virtual" == portage.catsplit(cp)[0]:
			for pkg in matched_packages:
				if pkg.cp != cp:
					continue
				# Got a new-style virtual, so filter
				# out any old-style virtuals.
				matched_packages = [pkg for pkg in matched_packages \
					if pkg.cp == cp]
				break

		if existing_node is not None and \
			existing_node in matched_packages:
			return existing_node, existing_node

		if len(matched_packages) > 1:
			if parent is not None and \
				(parent.root, parent.slot_atom) in self._dynamic_config._slot_operator_replace_installed:
				# We're forcing a rebuild of the parent because we missed some
				# update because of a slot operator dep.
				if atom.slot_operator == "=" and atom.sub_slot is None:
					# This one is a slot operator dep. Exclude the installed packages if a newer non-installed
					# pkg exists.
					highest_installed = None
					for pkg in matched_packages:
						if pkg.installed:
							if highest_installed is None or pkg.version > highest_installed.version:
								highest_installed = pkg

					if highest_installed and self._want_update_pkg(parent, highest_installed):
						non_installed = [pkg for pkg in matched_packages \
							if not pkg.installed and pkg.version > highest_installed.version]

						if non_installed:
							matched_packages = non_installed

			if rebuilt_binaries:
				inst_pkg = None
				built_pkg = None
				unbuilt_pkg = None
				for pkg in matched_packages:
					if pkg.installed:
						inst_pkg = pkg
					elif pkg.built:
						built_pkg = pkg
					else:
						if unbuilt_pkg is None or pkg > unbuilt_pkg:
							unbuilt_pkg = pkg
				if built_pkg is not None and inst_pkg is not None:
					# Only reinstall if binary package BUILD_TIME is
					# non-empty, in order to avoid cases like to
					# bug #306659 where BUILD_TIME fields are missing
					# in local and/or remote Packages file.
					built_timestamp = built_pkg.build_time
					installed_timestamp = inst_pkg.build_time

					if unbuilt_pkg is not None and unbuilt_pkg > built_pkg:
						pass
					elif "--rebuilt-binaries-timestamp" in self._frozen_config.myopts:
						minimal_timestamp = self._frozen_config.myopts["--rebuilt-binaries-timestamp"]
						if built_timestamp and \
							built_timestamp > installed_timestamp and \
							built_timestamp >= minimal_timestamp:
							return built_pkg, existing_node
					else:
						#Don't care if the binary has an older BUILD_TIME than the installed
						#package. This is for closely tracking a binhost.
						#Use --rebuilt-binaries-timestamp 0 if you want only newer binaries
						#pulled in here.
						if built_timestamp and \
							built_timestamp != installed_timestamp:
							return built_pkg, existing_node

			inst_pkg = None
			for pkg in matched_packages:
				if pkg.installed:
					inst_pkg = pkg
				if pkg.installed and pkg.invalid:
					matched_packages = [x for x in \
						matched_packages if x is not pkg]

			if (inst_pkg is not None and parent is not None and
				not self._want_update_pkg(parent, inst_pkg)):
				return inst_pkg, existing_node

			if avoid_update:
				for pkg in matched_packages:
					if pkg.installed and self._pkg_visibility_check(pkg, autounmask_level):
						return pkg, existing_node

			visible_matches = []
			if matched_oldpkg:
				visible_matches = [pkg.cpv for pkg in matched_oldpkg \
					if self._pkg_visibility_check(pkg, autounmask_level)]
			if not visible_matches:
				visible_matches = [pkg.cpv for pkg in matched_packages \
					if self._pkg_visibility_check(pkg, autounmask_level)]
			if visible_matches:
				bestmatch = portage.best(visible_matches)
			else:
				# all are masked, so ignore visibility
				bestmatch = portage.best([pkg.cpv for pkg in matched_packages])
			matched_packages = [pkg for pkg in matched_packages \
				if portage.dep.cpvequal(pkg.cpv, bestmatch)]

		# ordered by type preference ("ebuild" type is the last resort)
		return  matched_packages[-1], existing_node

	def _select_pkg_from_graph(self, root, atom, onlydeps=False, parent=None):
		"""
		Select packages that have already been added to the graph or
		those that are installed and have not been scheduled for
		replacement.
		"""
		graph_db = self._dynamic_config._graph_trees[root]["porttree"].dbapi
		matches = graph_db.match_pkgs(atom)
		if not matches:
			return None, None

		# There may be multiple matches, and they may
		# conflict with eachother, so choose the highest
		# version that has already been added to the graph.
		for pkg in reversed(matches):
			if pkg in self._dynamic_config.digraph:
				return pkg, pkg

		# Fall back to installed packages
		return self._select_pkg_from_installed(root, atom, onlydeps=onlydeps, parent=parent)

	def _select_pkg_from_installed(self, root, atom, onlydeps=False, parent=None):
		"""
		Select packages that are installed.
		"""
		matches = list(self._iter_match_pkgs(self._frozen_config.roots[root],
			"installed", atom))
		if not matches:
			return None, None
		if len(matches) > 1:
			matches.reverse() # ascending order
			unmasked = [pkg for pkg in matches if \
				self._pkg_visibility_check(pkg)]
			if unmasked:
				if len(unmasked) == 1:
					matches = unmasked
				else:
					# Account for packages with masks (like KEYWORDS masks)
					# that are usually ignored in visibility checks for
					# installed packages, in order to handle cases like
					# bug #350285.
					unmasked = [pkg for pkg in matches if not pkg.masks]
					if unmasked:
						matches = unmasked
						if len(matches) > 1:
							# Now account for packages for which existing
							# ebuilds are masked or unavailable (bug #445506).
							unmasked = [pkg for pkg in matches if
								self._equiv_ebuild_visible(pkg)]
							if unmasked:
								matches = unmasked

		pkg = matches[-1] # highest match
		in_graph = next(self._dynamic_config._package_tracker.match(
			root, pkg.slot_atom, installed=False), None)

		return pkg, in_graph

	def _complete_graph(self, required_sets=None):
		"""
		Add any deep dependencies of required sets (args, system, world) that
		have not been pulled into the graph yet. This ensures that the graph
		is consistent such that initially satisfied deep dependencies are not
		broken in the new graph. Initially unsatisfied dependencies are
		irrelevant since we only want to avoid breaking dependencies that are
		initially satisfied.

		Since this method can consume enough time to disturb users, it is
		currently only enabled by the --complete-graph option.

		@param required_sets: contains required sets (currently only used
			for depclean and prune removal operations)
		@type required_sets: dict
		"""
		if "--buildpkgonly" in self._frozen_config.myopts or \
			"recurse" not in self._dynamic_config.myparams:
			return 1

		complete_if_new_use = self._dynamic_config.myparams.get(
			"complete_if_new_use", "y") == "y"
		complete_if_new_ver = self._dynamic_config.myparams.get(
			"complete_if_new_ver", "y") == "y"
		rebuild_if_new_slot = self._dynamic_config.myparams.get(
			"rebuild_if_new_slot", "y") == "y"
		complete_if_new_slot = rebuild_if_new_slot

		if "complete" not in self._dynamic_config.myparams and \
			(complete_if_new_use or
			complete_if_new_ver or complete_if_new_slot):
			# Enable complete mode if an installed package will change somehow.
			use_change = False
			version_change = False
			for node in self._dynamic_config.digraph:
				if not isinstance(node, Package) or \
					node.operation != "merge":
					continue
				vardb = self._frozen_config.roots[
					node.root].trees["vartree"].dbapi

				if complete_if_new_use or complete_if_new_ver:
					inst_pkg = vardb.match_pkgs(node.slot_atom)
					if inst_pkg and inst_pkg[0].cp == node.cp:
						inst_pkg = inst_pkg[0]
						if complete_if_new_ver:
							if inst_pkg < node or node < inst_pkg:
								version_change = True
								break
							elif not (inst_pkg.slot == node.slot and
								inst_pkg.sub_slot == node.sub_slot):
								# slot/sub-slot change without revbump gets
								# similar treatment to a version change
								version_change = True
								break

						# Intersect enabled USE with IUSE, in order to
						# ignore forced USE from implicit IUSE flags, since
						# they're probably irrelevant and they are sensitive
						# to use.mask/force changes in the profile.
						if complete_if_new_use and \
							(node.iuse.all != inst_pkg.iuse.all or
							self._pkg_use_enabled(node).intersection(node.iuse.all) !=
							self._pkg_use_enabled(inst_pkg).intersection(inst_pkg.iuse.all)):
							use_change = True
							break

				if complete_if_new_slot:
					cp_list = vardb.match_pkgs(Atom(node.cp))
					if (cp_list and cp_list[0].cp == node.cp and
						not any(node.slot == pkg.slot and
						node.sub_slot == pkg.sub_slot for pkg in cp_list)):
						version_change = True
						break

			if use_change or version_change:
				self._dynamic_config.myparams["complete"] = True

		if "complete" not in self._dynamic_config.myparams:
			return 1

		self._load_vdb()

		# Put the depgraph into a mode that causes it to only
		# select packages that have already been added to the
		# graph or those that are installed and have not been
		# scheduled for replacement. Also, toggle the "deep"
		# parameter so that all dependencies are traversed and
		# accounted for.
		self._dynamic_config._complete_mode = True
		self._select_atoms = self._select_atoms_from_graph
		if "remove" in self._dynamic_config.myparams:
			self._select_package = self._select_pkg_from_installed
		else:
			self._select_package = self._select_pkg_from_graph
			self._dynamic_config._traverse_ignored_deps = True
		already_deep = self._dynamic_config.myparams.get("deep") is True
		if not already_deep:
			self._dynamic_config.myparams["deep"] = True

		# Invalidate the package selection cache, since
		# _select_package has just changed implementations.
		for trees in self._dynamic_config._filtered_trees.values():
			trees["porttree"].dbapi._clear_cache()

		args = self._dynamic_config._initial_arg_list[:]
		for root in self._frozen_config.roots:
			if root != self._frozen_config.target_root and \
				("remove" in self._dynamic_config.myparams or
				self._frozen_config.myopts.get("--root-deps") is not None):
				# Only pull in deps for the relevant root.
				continue
			depgraph_sets = self._dynamic_config.sets[root]
			required_set_names = self._frozen_config._required_set_names.copy()
			remaining_args = required_set_names.copy()
			if required_sets is None or root not in required_sets:
				pass
			else:
				# Removal actions may override sets with temporary
				# replacements that have had atoms removed in order
				# to implement --deselect behavior.
				required_set_names = set(required_sets[root])
				depgraph_sets.sets.clear()
				depgraph_sets.sets.update(required_sets[root])
			if "remove" not in self._dynamic_config.myparams and \
				root == self._frozen_config.target_root and \
				already_deep:
				remaining_args.difference_update(depgraph_sets.sets)
			if not remaining_args and \
				not self._dynamic_config._ignored_deps and \
				not self._dynamic_config._dep_stack:
				continue
			root_config = self._frozen_config.roots[root]
			for s in required_set_names:
				pset = depgraph_sets.sets.get(s)
				if pset is None:
					pset = root_config.sets[s]
				atom = SETPREFIX + s
				args.append(SetArg(arg=atom, pset=pset,
					reset_depth=False, root_config=root_config))

		self._set_args(args)
		for arg in self._expand_set_args(args, add_to_digraph=True):
			for atom in arg.pset.getAtoms():
				self._dynamic_config._dep_stack.append(
					Dependency(atom=atom, root=arg.root_config.root,
						parent=arg, depth=self._UNREACHABLE_DEPTH))

		if True:
			if self._dynamic_config._ignored_deps:
				self._dynamic_config._dep_stack.extend(self._dynamic_config._ignored_deps)
				self._dynamic_config._ignored_deps = []
			if not self._create_graph(allow_unsatisfied=True):
				return 0
			# Check the unsatisfied deps to see if any initially satisfied deps
			# will become unsatisfied due to an upgrade. Initially unsatisfied
			# deps are irrelevant since we only want to avoid breaking deps
			# that are initially satisfied.
			while self._dynamic_config._unsatisfied_deps:
				dep = self._dynamic_config._unsatisfied_deps.pop()
				vardb = self._frozen_config.roots[
					dep.root].trees["vartree"].dbapi
				matches = vardb.match_pkgs(dep.atom)
				if not matches:
					self._dynamic_config._initially_unsatisfied_deps.append(dep)
					continue
				# An scheduled installation broke a deep dependency.
				# Add the installed package to the graph so that it
				# will be appropriately reported as a slot collision
				# (possibly solvable via backtracking).
				pkg = matches[-1] # highest match

				if (self._dynamic_config._allow_backtracking and
					not self._want_installed_pkg(pkg) and (dep.atom.soname or (
					dep.atom.package and dep.atom.slot_operator_built))):
					# If pkg was already scheduled for rebuild by the previous
					# calculation, then pulling in the installed instance will
					# trigger a slot conflict that may go unsolved. Therefore,
					# trigger a rebuild of the parent if appropriate.
					dep.child = pkg
					new_dep = self._slot_operator_update_probe(dep)
					if new_dep is not None:
						self._slot_operator_update_backtrack(
							dep, new_dep=new_dep)
						continue

				if not self._add_pkg(pkg, dep):
					return 0
				if not self._create_graph(allow_unsatisfied=True):
					return 0
		return 1

	def _pkg(self, cpv, type_name, root_config, installed=False,
		onlydeps=False, myrepo = None):
		"""
		Get a package instance from the cache, or create a new
		one if necessary. Raises PackageNotFound from aux_get if it
		failures for some reason (package does not exist or is
		corrupt).
		"""

		# Ensure that we use the specially optimized RootConfig instance
		# that refers to FakeVartree instead of the real vartree.
		root_config = self._frozen_config.roots[root_config.root]
		pkg = self._frozen_config._pkg_cache.get(
			Package._gen_hash_key(cpv=cpv, type_name=type_name,
			repo_name=myrepo, root_config=root_config,
			installed=installed, onlydeps=onlydeps))
		if pkg is None and onlydeps and not installed:
			# Maybe it already got pulled in as a "merge" node.
			for candidate in self._dynamic_config._package_tracker.match(
				root_config.root, Atom("="+cpv)):
				if candidate.type_name == type_name and \
					candidate.repo_name == myrepo and \
					candidate.root_config is root_config and \
					candidate.installed == installed and \
					not candidate.onlydeps:
					pkg = candidate

		if pkg is None:
			tree_type = self.pkg_tree_map[type_name]
			db = root_config.trees[tree_type].dbapi
			db_keys = list(self._frozen_config._trees_orig[root_config.root][
				tree_type].dbapi._aux_cache_keys)

			try:
				metadata = zip(db_keys, db.aux_get(cpv, db_keys, myrepo=myrepo))
			except KeyError:
				raise portage.exception.PackageNotFound(cpv)

			# Ensure that this cpv is linked to the correct db, since the
			# caller might have passed in a cpv from a different db, in
			# order get an instance from this db with the same cpv.
			# If db has a _db attribute, use that instead, in order to
			# to use the underlying db of DbapiProvidesIndex or similar.
			db = getattr(db, '_db', db)
			if getattr(cpv, '_db', None) is not db:
				cpv = _pkg_str(cpv, db=db)

			pkg = Package(built=(type_name != "ebuild"), cpv=cpv,
				installed=installed, metadata=metadata, onlydeps=onlydeps,
				root_config=root_config, type_name=type_name)

			self._frozen_config._pkg_cache[pkg] = pkg

			if not self._pkg_visibility_check(pkg) and \
				'LICENSE' in pkg.masks and len(pkg.masks) == 1:
				slot_key = (pkg.root, pkg.slot_atom)
				other_pkg = self._frozen_config._highest_license_masked.get(slot_key)
				if other_pkg is None or pkg > other_pkg:
					self._frozen_config._highest_license_masked[slot_key] = pkg

		return pkg

	def _validate_blockers(self):
		"""Remove any blockers from the digraph that do not match any of the
		packages within the graph.  If necessary, create hard deps to ensure
		correct merge order such that mutually blocking packages are never
		installed simultaneously. Also add runtime blockers from all installed
		packages if any of them haven't been added already (bug 128809).

		Normally, this method is called only after the graph is complete, and
		after _solve_non_slot_operator_slot_conflicts has had an opportunity
		to solve slot conflicts (possibly removing some blockers). It can also
		be called earlier, in order to get a preview of the blocker data, but
		then it needs to be called again after the graph is complete.
		"""

		# The _in_blocker_conflict method needs to assert that this method
		# has been called before it, by checking that it is not None.
		self._dynamic_config._blocked_pkgs = digraph()

		if "--buildpkgonly" in self._frozen_config.myopts or \
			"--nodeps" in self._frozen_config.myopts:
			return True

		if True:
			# Pull in blockers from all installed packages that haven't already
			# been pulled into the depgraph, in order to ensure that they are
			# respected (bug 128809). Due to the performance penalty that is
			# incurred by all the additional dep_check calls that are required,
			# blockers returned from dep_check are cached on disk by the
			# BlockerCache class.

			# For installed packages, always ignore blockers from DEPEND since
			# only runtime dependencies should be relevant for packages that
			# are already built.
			dep_keys = Package._runtime_keys
			for myroot in self._frozen_config.trees:

				if self._frozen_config.myopts.get("--root-deps") is not None and \
					myroot != self._frozen_config.target_root:
					continue

				vardb = self._frozen_config.trees[myroot]["vartree"].dbapi
				pkgsettings = self._frozen_config.pkgsettings[myroot]
				root_config = self._frozen_config.roots[myroot]
				final_db = PackageTrackerDbapiWrapper(
					myroot, self._dynamic_config._package_tracker)

				blocker_cache = BlockerCache(myroot, vardb)
				stale_cache = set(blocker_cache)
				for pkg in vardb:
					cpv = pkg.cpv
					stale_cache.discard(cpv)
					pkg_in_graph = self._dynamic_config.digraph.contains(pkg)
					pkg_deps_added = \
						pkg in self._dynamic_config._traversed_pkg_deps

					# Check for masked installed packages. Only warn about
					# packages that are in the graph in order to avoid warning
					# about those that will be automatically uninstalled during
					# the merge process or by --depclean. Always warn about
					# packages masked by license, since the user likely wants
					# to adjust ACCEPT_LICENSE.
					if pkg in self._dynamic_config._package_tracker:
						if not self._pkg_visibility_check(pkg,
							trust_graph=False) and \
							(pkg_in_graph or 'LICENSE' in pkg.masks):
							self._dynamic_config._masked_installed.add(pkg)
						else:
							self._check_masks(pkg)

					blocker_atoms = None
					blockers = None
					if pkg_deps_added:
						blockers = []
						try:
							blockers.extend(
								self._dynamic_config._blocker_parents.child_nodes(pkg))
						except KeyError:
							pass
						try:
							blockers.extend(
								self._dynamic_config._irrelevant_blockers.child_nodes(pkg))
						except KeyError:
							pass
						if blockers:
							# Select just the runtime blockers.
							blockers = [blocker for blocker in blockers \
								if blocker.priority.runtime or \
								blocker.priority.runtime_post]
					if blockers is not None:
						blockers = set(blocker.atom for blocker in blockers)

					# If this node has any blockers, create a "nomerge"
					# node for it so that they can be enforced.
					self._spinner_update()
					blocker_data = blocker_cache.get(cpv)
					if blocker_data is not None and \
						blocker_data.counter != pkg.counter:
						blocker_data = None

					# If blocker data from the graph is available, use
					# it to validate the cache and update the cache if
					# it seems invalid.
					if blocker_data is not None and \
						blockers is not None:
						if not blockers.symmetric_difference(
							blocker_data.atoms):
							continue
						blocker_data = None

					if blocker_data is None and \
						blockers is not None:
						# Re-use the blockers from the graph.
						blocker_atoms = sorted(blockers)
						blocker_data = \
							blocker_cache.BlockerData(pkg.counter, blocker_atoms)
						blocker_cache[pkg.cpv] = blocker_data
						continue

					if blocker_data:
						blocker_atoms = [Atom(atom) for atom in blocker_data.atoms]
					else:
						# Use aux_get() to trigger FakeVartree global
						# updates on *DEPEND when appropriate.
						depstr = " ".join(vardb.aux_get(pkg.cpv, dep_keys))
						# It is crucial to pass in final_db here in order to
						# optimize dep_check calls by eliminating atoms via
						# dep_wordreduce and dep_eval calls.
						try:
							success, atoms = portage.dep_check(depstr,
								final_db, pkgsettings, myuse=self._pkg_use_enabled(pkg),
								trees=self._dynamic_config._graph_trees, myroot=myroot)
						except SystemExit:
							raise
						except Exception as e:
							# This is helpful, for example, if a ValueError
							# is thrown from cpv_expand due to multiple
							# matches (this can happen if an atom lacks a
							# category).
							show_invalid_depstring_notice(
								pkg, "%s" % (e,))
							del e
							raise
						if not success:
							replacement_pkgs = self._dynamic_config._package_tracker.match(
								myroot, pkg.slot_atom)
							if any(replacement_pkg.operation == "merge" for
								replacement_pkg in replacement_pkgs):
								# This package is being replaced anyway, so
								# ignore invalid dependencies so as not to
								# annoy the user too much (otherwise they'd be
								# forced to manually unmerge it first).
								continue
							show_invalid_depstring_notice(pkg, atoms)
							return False
						blocker_atoms = [myatom for myatom in atoms \
							if myatom.blocker]
						blocker_atoms.sort()
						blocker_cache[cpv] = \
							blocker_cache.BlockerData(pkg.counter, blocker_atoms)
					if blocker_atoms:
						try:
							for atom in blocker_atoms:
								blocker = Blocker(atom=atom,
									eapi=pkg.eapi,
									priority=self._priority(runtime=True),
									root=myroot)
								self._dynamic_config._blocker_parents.add(blocker, pkg)
						except portage.exception.InvalidAtom as e:
							depstr = " ".join(vardb.aux_get(pkg.cpv, dep_keys))
							show_invalid_depstring_notice(
								pkg, "Invalid Atom: %s" % (e,))
							return False
				for cpv in stale_cache:
					del blocker_cache[cpv]
				blocker_cache.flush()
				del blocker_cache

		# Discard any "uninstall" tasks scheduled by previous calls
		# to this method, since those tasks may not make sense given
		# the current graph state.
		previous_uninstall_tasks = self._dynamic_config._blocker_uninstalls.leaf_nodes()
		if previous_uninstall_tasks:
			self._dynamic_config._blocker_uninstalls = digraph()
			self._dynamic_config.digraph.difference_update(previous_uninstall_tasks)

		# Revert state from previous calls.
		self._dynamic_config._blocker_parents.update(
			self._dynamic_config._irrelevant_blockers)
		self._dynamic_config._irrelevant_blockers.clear()
		self._dynamic_config._unsolvable_blockers.clear()

		for blocker in self._dynamic_config._blocker_parents.leaf_nodes():
			self._spinner_update()
			root_config = self._frozen_config.roots[blocker.root]
			virtuals = root_config.settings.getvirtuals()
			myroot = blocker.root
			initial_db = self._frozen_config.trees[myroot]["vartree"].dbapi

			provider_virtual = False
			if blocker.cp in virtuals and \
				not self._have_new_virt(blocker.root, blocker.cp):
				provider_virtual = True

			# Use this to check PROVIDE for each matched package
			# when necessary.
			atom_set = InternalPackageSet(
				initial_atoms=[blocker.atom])

			if provider_virtual:
				atoms = []
				for provider_entry in virtuals[blocker.cp]:
					atoms.append(Atom(blocker.atom.replace(
						blocker.cp, provider_entry.cp, 1)))
			else:
				atoms = [blocker.atom]

			blocked_initial = set()
			for atom in atoms:
				for pkg in initial_db.match_pkgs(atom):
					if atom_set.findAtomForPackage(pkg, modified_use=self._pkg_use_enabled(pkg)):
						blocked_initial.add(pkg)

			blocked_final = set()
			for atom in atoms:
				for pkg in self._dynamic_config._package_tracker.match(myroot, atom):
					if atom_set.findAtomForPackage(pkg, modified_use=self._pkg_use_enabled(pkg)):
						blocked_final.add(pkg)

			if not blocked_initial and not blocked_final:
				parent_pkgs = self._dynamic_config._blocker_parents.parent_nodes(blocker)
				self._dynamic_config._blocker_parents.remove(blocker)
				# Discard any parents that don't have any more blockers.
				for pkg in parent_pkgs:
					self._dynamic_config._irrelevant_blockers.add(blocker, pkg)
					if not self._dynamic_config._blocker_parents.child_nodes(pkg):
						self._dynamic_config._blocker_parents.remove(pkg)
				continue
			for parent in self._dynamic_config._blocker_parents.parent_nodes(blocker):
				unresolved_blocks = False
				depends_on_order = set()
				for pkg in blocked_initial:
					if pkg.slot_atom == parent.slot_atom and \
						not blocker.atom.blocker.overlap.forbid:
						# New !!atom blockers do not allow temporary
						# simulaneous installation, so unlike !atom
						# blockers, !!atom blockers aren't ignored
						# when they match other packages occupying
						# the same slot.
						continue
					if parent.installed:
						# Two currently installed packages conflict with
						# eachother. Ignore this case since the damage
						# is already done and this would be likely to
						# confuse users if displayed like a normal blocker.
						continue

					self._dynamic_config._blocked_pkgs.add(pkg, blocker)

					if parent.operation == "merge":
						# Maybe the blocked package can be replaced or simply
						# unmerged to resolve this block.
						depends_on_order.add((pkg, parent))
						continue
					# None of the above blocker resolutions techniques apply,
					# so apparently this one is unresolvable.
					unresolved_blocks = True
				for pkg in blocked_final:
					if pkg.slot_atom == parent.slot_atom and \
						not blocker.atom.blocker.overlap.forbid:
						# New !!atom blockers do not allow temporary
						# simulaneous installation, so unlike !atom
						# blockers, !!atom blockers aren't ignored
						# when they match other packages occupying
						# the same slot.
						continue
					if parent.operation == "nomerge" and \
						pkg.operation == "nomerge":
						# This blocker will be handled the next time that a
						# merge of either package is triggered.
						continue

					self._dynamic_config._blocked_pkgs.add(pkg, blocker)

					# Maybe the blocking package can be
					# unmerged to resolve this block.
					if parent.operation == "merge" and pkg.installed:
						depends_on_order.add((pkg, parent))
						continue
					elif parent.operation == "nomerge":
						depends_on_order.add((parent, pkg))
						continue
					# None of the above blocker resolutions techniques apply,
					# so apparently this one is unresolvable.
					unresolved_blocks = True

				# Make sure we don't unmerge any package that have been pulled
				# into the graph.
				if not unresolved_blocks and depends_on_order:
					for inst_pkg, inst_task in depends_on_order:
						if self._dynamic_config.digraph.contains(inst_pkg) and \
							self._dynamic_config.digraph.parent_nodes(inst_pkg):
							unresolved_blocks = True
							break

				if not unresolved_blocks and depends_on_order:
					for inst_pkg, inst_task in depends_on_order:
						uninst_task = Package(built=inst_pkg.built,
							cpv=inst_pkg.cpv, installed=inst_pkg.installed,
							metadata=inst_pkg._metadata,
							operation="uninstall",
							root_config=inst_pkg.root_config,
							type_name=inst_pkg.type_name)
						# Enforce correct merge order with a hard dep.
						self._dynamic_config.digraph.addnode(uninst_task, inst_task,
							priority=BlockerDepPriority.instance)
						# Count references to this blocker so that it can be
						# invalidated after nodes referencing it have been
						# merged.
						self._dynamic_config._blocker_uninstalls.addnode(uninst_task, blocker)
				if not unresolved_blocks and not depends_on_order:
					self._dynamic_config._irrelevant_blockers.add(blocker, parent)
					self._dynamic_config._blocker_parents.remove_edge(blocker, parent)
					if not self._dynamic_config._blocker_parents.parent_nodes(blocker):
						self._dynamic_config._blocker_parents.remove(blocker)
					if not self._dynamic_config._blocker_parents.child_nodes(parent):
						self._dynamic_config._blocker_parents.remove(parent)
				if unresolved_blocks:
					self._dynamic_config._unsolvable_blockers.add(blocker, parent)

		return True

	def _accept_blocker_conflicts(self):
		acceptable = False
		for x in ("--buildpkgonly", "--fetchonly",
			"--fetch-all-uri", "--nodeps"):
			if x in self._frozen_config.myopts:
				acceptable = True
				break
		return acceptable

	def _merge_order_bias(self, mygraph):
		"""
		For optimal leaf node selection, promote deep system runtime deps and
		order nodes from highest to lowest overall reference count.
		"""

		node_info = {}
		for node in mygraph.order:
			node_info[node] = len(mygraph.parent_nodes(node))
		deep_system_deps = _find_deep_system_runtime_deps(mygraph)

		def cmp_merge_preference(node1, node2):

			if node1.operation == 'uninstall':
				if node2.operation == 'uninstall':
					return 0
				return 1

			if node2.operation == 'uninstall':
				if node1.operation == 'uninstall':
					return 0
				return -1

			node1_sys = node1 in deep_system_deps
			node2_sys = node2 in deep_system_deps
			if node1_sys != node2_sys:
				if node1_sys:
					return -1
				return 1

			return node_info[node2] - node_info[node1]

		mygraph.order.sort(key=cmp_sort_key(cmp_merge_preference))

	def altlist(self, reversed=DeprecationWarning):

		if reversed is not DeprecationWarning:
			warnings.warn("The reversed parameter of "
				"_emerge.depgraph.depgraph.altlist() is deprecated",
				DeprecationWarning, stacklevel=2)

		while self._dynamic_config._serialized_tasks_cache is None:
			self._resolve_conflicts()
			try:
				self._dynamic_config._serialized_tasks_cache, self._dynamic_config._scheduler_graph = \
					self._serialize_tasks()
			except self._serialize_tasks_retry:
				pass

		retlist = self._dynamic_config._serialized_tasks_cache
		if reversed is not DeprecationWarning and reversed:
			# TODO: remove the "reversed" parameter (builtin name collision)
			retlist = list(retlist)
			retlist.reverse()
			retlist = tuple(retlist)

		return retlist

	def _implicit_libc_deps(self, mergelist, graph):
		"""
		Create implicit dependencies on libc, in order to ensure that libc
		is installed as early as possible (see bug #303567).
		"""
		libc_pkgs = {}
		implicit_libc_roots = (self._frozen_config._running_root.root,)
		for root in implicit_libc_roots:
			vardb = self._frozen_config.trees[root]["vartree"].dbapi
			for atom in self._expand_virt_from_graph(root,
				portage.const.LIBC_PACKAGE_ATOM):
				if atom.blocker:
					continue
				for pkg in self._dynamic_config._package_tracker.match(root, atom):
					if pkg.operation == "merge" and \
						not vardb.cpv_exists(pkg.cpv):
						libc_pkgs.setdefault(pkg.root, set()).add(pkg)

		if not libc_pkgs:
			return

		earlier_libc_pkgs = set()

		for pkg in mergelist:
			if not isinstance(pkg, Package):
				# a satisfied blocker
				continue
			root_libc_pkgs = libc_pkgs.get(pkg.root)
			if root_libc_pkgs is not None and \
				pkg.operation == "merge":
				if pkg in root_libc_pkgs:
					earlier_libc_pkgs.add(pkg)
				else:
					for libc_pkg in root_libc_pkgs:
						if libc_pkg in earlier_libc_pkgs:
							graph.add(libc_pkg, pkg,
								priority=DepPriority(buildtime=True))

	def schedulerGraph(self):
		"""
		The scheduler graph is identical to the normal one except that
		uninstall edges are reversed in specific cases that require
		conflicting packages to be temporarily installed simultaneously.
		This is intended for use by the Scheduler in it's parallelization
		logic. It ensures that temporary simultaneous installation of
		conflicting packages is avoided when appropriate (especially for
		!!atom blockers), but allowed in specific cases that require it.

		Note that this method calls break_refs() which alters the state of
		internal Package instances such that this depgraph instance should
		not be used to perform any more calculations.
		"""

		# NOTE: altlist initializes self._dynamic_config._scheduler_graph
		mergelist = self.altlist()
		self._implicit_libc_deps(mergelist,
			self._dynamic_config._scheduler_graph)

		# Break DepPriority.satisfied attributes which reference
		# installed Package instances.
		for parents, children, node in \
			self._dynamic_config._scheduler_graph.nodes.values():
			for priorities in chain(parents.values(), children.values()):
				for priority in priorities:
					if priority.satisfied:
						priority.satisfied = True

		pkg_cache = self._frozen_config._pkg_cache
		graph = self._dynamic_config._scheduler_graph
		trees = self._frozen_config.trees
		pruned_pkg_cache = {}
		for key, pkg in pkg_cache.items():
			if pkg in graph or \
				(pkg.installed and pkg in trees[pkg.root]['vartree'].dbapi):
				pruned_pkg_cache[key] = pkg

		for root in trees:
			trees[root]['vartree']._pkg_cache = pruned_pkg_cache

		self.break_refs()
		sched_config = \
			_scheduler_graph_config(trees, pruned_pkg_cache, graph, mergelist)

		return sched_config

	def break_refs(self):
		"""
		Break any references in Package instances that lead back to the depgraph.
		This is useful if you want to hold references to packages without also
		holding the depgraph on the heap. It should only be called after the
		depgraph and _frozen_config will not be used for any more calculations.
		"""
		for root_config in self._frozen_config.roots.values():
			root_config.update(self._frozen_config._trees_orig[
				root_config.root]["root_config"])
			# Both instances are now identical, so discard the
			# original which should have no other references.
			self._frozen_config._trees_orig[
				root_config.root]["root_config"] = root_config

	def _resolve_conflicts(self):

		if "complete" not in self._dynamic_config.myparams and \
			self._dynamic_config._allow_backtracking and \
			any(self._dynamic_config._package_tracker.slot_conflicts()) and \
			not self._accept_blocker_conflicts():
			self._dynamic_config.myparams["complete"] = True

		if not self._complete_graph():
			raise self._unknown_internal_error()

		self._process_slot_conflicts()

	def _serialize_tasks(self):

		debug = "--debug" in self._frozen_config.myopts

		if debug:
			writemsg("\ndigraph:\n\n", noiselevel=-1)
			self._dynamic_config.digraph.debug_print()
			writemsg("\n", noiselevel=-1)

		scheduler_graph = self._dynamic_config.digraph.copy()

		if '--nodeps' in self._frozen_config.myopts:
			# Preserve the package order given on the command line.
			return ([node for node in scheduler_graph \
				if isinstance(node, Package) \
				and node.operation == 'merge'], scheduler_graph)

		mygraph=self._dynamic_config.digraph.copy()

		removed_nodes = set()

		# Prune off all DependencyArg instances since they aren't
		# needed, and because of nested sets this is faster than doing
		# it with multiple digraph.root_nodes() calls below. This also
		# takes care of nested sets that have circular references,
		# which wouldn't be matched by digraph.root_nodes().
		for node in mygraph:
			if isinstance(node, DependencyArg):
				removed_nodes.add(node)
		if removed_nodes:
			mygraph.difference_update(removed_nodes)
			removed_nodes.clear()

		# Prune "nomerge" root nodes if nothing depends on them, since
		# otherwise they slow down merge order calculation. Don't remove
		# non-root nodes since they help optimize merge order in some cases
		# such as revdep-rebuild.

		while True:
			for node in mygraph.root_nodes():
				if not isinstance(node, Package) or \
					node.installed or node.onlydeps:
					removed_nodes.add(node)
			if removed_nodes:
				self._spinner_update()
				mygraph.difference_update(removed_nodes)
			if not removed_nodes:
				break
			removed_nodes.clear()
		self._merge_order_bias(mygraph)
		def cmp_circular_bias(n1, n2):
			"""
			RDEPEND is stronger than PDEPEND and this function
			measures such a strength bias within a circular
			dependency relationship.
			"""
			n1_n2_medium = n2 in mygraph.child_nodes(n1,
				ignore_priority=priority_range.ignore_medium_soft)
			n2_n1_medium = n1 in mygraph.child_nodes(n2,
				ignore_priority=priority_range.ignore_medium_soft)
			if n1_n2_medium == n2_n1_medium:
				return 0
			elif n1_n2_medium:
				return 1
			return -1
		myblocker_uninstalls = self._dynamic_config._blocker_uninstalls.copy()
		retlist=[]
		# Contains uninstall tasks that have been scheduled to
		# occur after overlapping blockers have been installed.
		scheduled_uninstalls = set()
		# Contains any Uninstall tasks that have been ignored
		# in order to avoid the circular deps code path. These
		# correspond to blocker conflicts that could not be
		# resolved.
		ignored_uninstall_tasks = set()
		have_uninstall_task = False
		complete = "complete" in self._dynamic_config.myparams
		ignore_world = self._dynamic_config.myparams.get("ignore_world", False)
		asap_nodes = []

		def get_nodes(**kwargs):
			"""
			Returns leaf nodes excluding Uninstall instances
			since those should be executed as late as possible.
			"""
			return [node for node in mygraph.leaf_nodes(**kwargs) \
				if isinstance(node, Package) and \
					(node.operation != "uninstall" or \
					node in scheduled_uninstalls)]

		# sys-apps/portage needs special treatment if ROOT="/"
		running_root = self._frozen_config._running_root.root
		runtime_deps = InternalPackageSet(
			initial_atoms=[PORTAGE_PACKAGE_ATOM])
		running_portage = self._frozen_config.trees[running_root]["vartree"].dbapi.match_pkgs(
			Atom(PORTAGE_PACKAGE_ATOM))
		replacement_portage = list(self._dynamic_config._package_tracker.match(
			running_root, Atom(PORTAGE_PACKAGE_ATOM)))

		if running_portage:
			running_portage = running_portage[0]
		else:
			running_portage = None

		if replacement_portage:
			replacement_portage = replacement_portage[0]
		else:
			replacement_portage = None

		if replacement_portage == running_portage:
			replacement_portage = None

		if running_portage is not None:
			try:
				portage_rdepend = self._select_atoms_highest_available(
					running_root, running_portage._metadata["RDEPEND"],
					myuse=self._pkg_use_enabled(running_portage),
					parent=running_portage, strict=False)
			except portage.exception.InvalidDependString as e:
				portage.writemsg("!!! Invalid RDEPEND in " + \
					"'%svar/db/pkg/%s/RDEPEND': %s\n" % \
					(running_root, running_portage.cpv, e), noiselevel=-1)
				del e
				portage_rdepend = {running_portage : []}
			for atoms in portage_rdepend.values():
				runtime_deps.update(atom for atom in atoms \
					if not atom.blocker)

		# Merge libc asap, in order to account for implicit
		# dependencies. See bug #303567.
		implicit_libc_roots = (running_root,)
		for root in implicit_libc_roots:
			libc_pkgs = set()
			vardb = self._frozen_config.trees[root]["vartree"].dbapi
			for atom in self._expand_virt_from_graph(root,
				portage.const.LIBC_PACKAGE_ATOM):
				if atom.blocker:
					continue

				for pkg in self._dynamic_config._package_tracker.match(root, atom):
					if pkg.operation == "merge" and \
						not vardb.cpv_exists(pkg.cpv):
						libc_pkgs.add(pkg)

			if libc_pkgs:
				# If there's also an os-headers upgrade, we need to
				# pull that in first. See bug #328317.
				for atom in self._expand_virt_from_graph(root,
					portage.const.OS_HEADERS_PACKAGE_ATOM):
					if atom.blocker:
						continue

					for pkg in self._dynamic_config._package_tracker.match(root, atom):
						if pkg.operation == "merge" and \
							not vardb.cpv_exists(pkg.cpv):
							asap_nodes.append(pkg)

				asap_nodes.extend(libc_pkgs)

		def gather_deps(ignore_priority, mergeable_nodes,
			selected_nodes, node):
			"""
			Recursively gather a group of nodes that RDEPEND on
			eachother. This ensures that they are merged as a group
			and get their RDEPENDs satisfied as soon as possible.
			"""
			if node in selected_nodes:
				return True
			if node not in mergeable_nodes:
				return False
			if node == replacement_portage and any(
				getattr(rdep, 'operation', None) != 'uninstall'
				for rdep in mygraph.child_nodes(node,
				ignore_priority=priority_range.ignore_medium_soft)):
				# Make sure that portage always has all of its
				# RDEPENDs installed first, but ignore uninstalls
				# (these occur when new portage blocks older repoman).
				return False
			selected_nodes.add(node)
			for child in mygraph.child_nodes(node,
				ignore_priority=ignore_priority):
				if not gather_deps(ignore_priority,
					mergeable_nodes, selected_nodes, child):
					return False
			return True

		def ignore_uninst_or_med(priority):
			if priority is BlockerDepPriority.instance:
				return True
			return priority_range.ignore_medium(priority)

		def ignore_uninst_or_med_soft(priority):
			if priority is BlockerDepPriority.instance:
				return True
			return priority_range.ignore_medium_soft(priority)

		tree_mode = "--tree" in self._frozen_config.myopts
		# Tracks whether or not the current iteration should prefer asap_nodes
		# if available.  This is set to False when the previous iteration
		# failed to select any nodes.  It is reset whenever nodes are
		# successfully selected.
		prefer_asap = True

		# Controls whether or not the current iteration should drop edges that
		# are "satisfied" by installed packages, in order to solve circular
		# dependencies. The deep runtime dependencies of installed packages are
		# not checked in this case (bug #199856), so it must be avoided
		# whenever possible.
		drop_satisfied = False

		# State of variables for successive iterations that loosen the
		# criteria for node selection.
		#
		# iteration   prefer_asap   drop_satisfied
		# 1           True          False
		# 2           False         False
		# 3           False         True
		#
		# If no nodes are selected on the last iteration, it is due to
		# unresolved blockers or circular dependencies.

		while mygraph:
			self._spinner_update()
			selected_nodes = None
			ignore_priority = None
			if drop_satisfied or (prefer_asap and asap_nodes):
				priority_range = DepPrioritySatisfiedRange
			else:
				priority_range = DepPriorityNormalRange
			if prefer_asap and asap_nodes:
				# ASAP nodes are merged before their soft deps. Go ahead and
				# select root nodes here if necessary, since it's typical for
				# the parent to have been removed from the graph already.
				asap_nodes = [node for node in asap_nodes \
					if mygraph.contains(node)]
				for i in range(priority_range.SOFT,
					priority_range.MEDIUM_SOFT + 1):
					ignore_priority = priority_range.ignore_priority[i]
					for node in asap_nodes:
						if not mygraph.child_nodes(node,
							ignore_priority=ignore_priority):
							selected_nodes = [node]
							asap_nodes.remove(node)
							break
					if selected_nodes:
						break

			if not selected_nodes and \
				not (prefer_asap and asap_nodes):
				for i in range(priority_range.NONE,
					priority_range.MEDIUM_SOFT + 1):
					ignore_priority = priority_range.ignore_priority[i]
					nodes = get_nodes(ignore_priority=ignore_priority)
					if nodes:
						# If there is a mixture of merges and uninstalls,
						# do the uninstalls first.
						good_uninstalls = None
						if len(nodes) > 1:
							good_uninstalls = []
							for node in nodes:
								if node.operation == "uninstall":
									good_uninstalls.append(node)

							if good_uninstalls:
								nodes = good_uninstalls
							else:
								nodes = nodes

						if good_uninstalls or len(nodes) == 1 or \
							(ignore_priority is None and \
							not asap_nodes and not tree_mode):
							# Greedily pop all of these nodes since no
							# relationship has been ignored. This optimization
							# destroys --tree output, so it's disabled in tree
							# mode.
							selected_nodes = nodes
						else:
							# For optimal merge order:
							#  * Only pop one node.
							#  * Removing a root node (node without a parent)
							#    will not produce a leaf node, so avoid it.
							#  * It's normal for a selected uninstall to be a
							#    root node, so don't check them for parents.
							if asap_nodes:
								prefer_asap_parents = (True, False)
							else:
								prefer_asap_parents = (False,)
							for check_asap_parent in prefer_asap_parents:
								if check_asap_parent:
									for node in nodes:
										parents = mygraph.parent_nodes(node,
											ignore_priority=DepPrioritySatisfiedRange.ignore_soft)
										if any(x in asap_nodes for x in parents):
											selected_nodes = [node]
											break
								else:
									for node in nodes:
										if mygraph.parent_nodes(node):
											selected_nodes = [node]
											break
								if selected_nodes:
									break
						if selected_nodes:
							break

			if not selected_nodes:
				nodes = get_nodes(ignore_priority=priority_range.ignore_medium)
				if nodes:
					mergeable_nodes = set(nodes)
					if prefer_asap and asap_nodes:
						nodes = asap_nodes
					# When gathering the nodes belonging to a runtime cycle,
					# we want to minimize the number of nodes gathered, since
					# this tends to produce a more optimal merge order.
					# Ignoring all medium_soft deps serves this purpose.
					# In the case of multiple runtime cycles, where some cycles
					# may depend on smaller independent cycles, it's optimal
					# to merge smaller independent cycles before other cycles
					# that depend on them. Therefore, we search for the
					# smallest cycle in order to try and identify and prefer
					# these smaller independent cycles.
					ignore_priority = priority_range.ignore_medium_soft
					smallest_cycle = None
					for node in nodes:
						if not mygraph.parent_nodes(node):
							continue
						selected_nodes = set()
						if gather_deps(ignore_priority,
							mergeable_nodes, selected_nodes, node):
							if smallest_cycle is None or \
								len(selected_nodes) < len(smallest_cycle):
								smallest_cycle = selected_nodes

					selected_nodes = smallest_cycle

					if selected_nodes is not None:
						cycle_digraph = mygraph.copy()
						cycle_digraph.difference_update([x for x in
							cycle_digraph if x not in selected_nodes])

						leaves = cycle_digraph.leaf_nodes()
						if leaves:
							# NOTE: This case should only be triggered when
							# prefer_asap is True, since otherwise these
							# leaves would have been selected to merge
							# before this point. Since these "leaves" may
							# actually have some low-priority dependencies
							# that we have intentionally ignored, select
							# only one node here, so that merge order
							# accounts for as many dependencies as possible.
							selected_nodes = [leaves[0]]

						if debug:
							writemsg("\nruntime cycle digraph (%s nodes):\n\n" %
								(len(selected_nodes),), noiselevel=-1)
							cycle_digraph.debug_print()
							writemsg("\n", noiselevel=-1)

							if leaves:
								writemsg("runtime cycle leaf: %s\n\n" %
									(selected_nodes[0],), noiselevel=-1)

					if prefer_asap and asap_nodes and not selected_nodes:
						# We failed to find any asap nodes to merge, so ignore
						# them for the next iteration.
						prefer_asap = False
						continue

			if selected_nodes and ignore_priority is not None:
				# Try to merge ignored medium_soft deps as soon as possible
				# if they're not satisfied by installed packages.
				for node in selected_nodes:
					children = set(mygraph.child_nodes(node))
					soft = children.difference(
						mygraph.child_nodes(node,
						ignore_priority=DepPrioritySatisfiedRange.ignore_soft))
					medium_soft = children.difference(
						mygraph.child_nodes(node,
							ignore_priority = \
							DepPrioritySatisfiedRange.ignore_medium_soft))
					medium_soft.difference_update(soft)
					for child in medium_soft:
						if child in selected_nodes:
							continue
						if child in asap_nodes:
							continue
						# Merge PDEPEND asap for bug #180045.
						asap_nodes.append(child)

			if selected_nodes and len(selected_nodes) > 1:
				if not isinstance(selected_nodes, list):
					selected_nodes = list(selected_nodes)
				selected_nodes.sort(key=cmp_sort_key(cmp_circular_bias))

			if not selected_nodes and myblocker_uninstalls:
				# An Uninstall task needs to be executed in order to
				# avoid conflict if possible.

				if drop_satisfied:
					priority_range = DepPrioritySatisfiedRange
				else:
					priority_range = DepPriorityNormalRange

				mergeable_nodes = get_nodes(
					ignore_priority=ignore_uninst_or_med)

				min_parent_deps = None
				uninst_task = None

				for task in myblocker_uninstalls.leaf_nodes():
					# Do some sanity checks so that system or world packages
					# don't get uninstalled inappropriately here (only really
					# necessary when --complete-graph has not been enabled).

					if task in ignored_uninstall_tasks:
						continue

					if task in scheduled_uninstalls:
						# It's been scheduled but it hasn't
						# been executed yet due to dependence
						# on installation of blocking packages.
						continue

					root_config = self._frozen_config.roots[task.root]
					inst_pkg = self._pkg(task.cpv, "installed", root_config,
						installed=True)

					if self._dynamic_config.digraph.contains(inst_pkg):
						continue

					forbid_overlap = False
					heuristic_overlap = False
					for blocker in myblocker_uninstalls.parent_nodes(task):
						if not eapi_has_strong_blocks(blocker.eapi):
							heuristic_overlap = True
						elif blocker.atom.blocker.overlap.forbid:
							forbid_overlap = True
							break
					if forbid_overlap and running_root == task.root:
						continue

					if heuristic_overlap and running_root == task.root:
						# Never uninstall sys-apps/portage or it's essential
						# dependencies, except through replacement.
						try:
							runtime_dep_atoms = \
								list(runtime_deps.iterAtomsForPackage(task))
						except portage.exception.InvalidDependString as e:
							portage.writemsg("!!! Invalid PROVIDE in " + \
								"'%svar/db/pkg/%s/PROVIDE': %s\n" % \
								(task.root, task.cpv, e), noiselevel=-1)
							del e
							continue

						# Don't uninstall a runtime dep if it appears
						# to be the only suitable one installed.
						skip = False
						vardb = root_config.trees["vartree"].dbapi
						for atom in runtime_dep_atoms:
							other_version = None
							for pkg in vardb.match_pkgs(atom):
								if pkg.cpv == task.cpv and \
									pkg.counter == task.counter:
									continue
								other_version = pkg
								break
							if other_version is None:
								skip = True
								break
						if skip:
							continue

						# For packages in the system set, don't take
						# any chances. If the conflict can't be resolved
						# by a normal replacement operation then abort.
						skip = False
						try:
							for atom in root_config.sets[
								"system"].iterAtomsForPackage(task):
								skip = True
								break
						except portage.exception.InvalidDependString as e:
							portage.writemsg("!!! Invalid PROVIDE in " + \
								"'%svar/db/pkg/%s/PROVIDE': %s\n" % \
								(task.root, task.cpv, e), noiselevel=-1)
							del e
							skip = True
						if skip:
							continue

					# Note that the world check isn't always
					# necessary since self._complete_graph() will
					# add all packages from the system and world sets to the
					# graph. This just allows unresolved conflicts to be
					# detected as early as possible, which makes it possible
					# to avoid calling self._complete_graph() when it is
					# unnecessary due to blockers triggering an abortion.
					if not (complete or ignore_world):
						# For packages in the world set, go ahead an uninstall
						# when necessary, as long as the atom will be satisfied
						# in the final state.
						skip = False
						try:
							for atom in root_config.sets[
								"selected"].iterAtomsForPackage(task):
								satisfied = False
								for pkg in self._dynamic_config._package_tracker.match(task.root, atom):
									if pkg == inst_pkg:
										continue
									satisfied = True
									break
								if not satisfied:
									skip = True
									self._dynamic_config._blocked_world_pkgs[inst_pkg] = atom
									break
						except portage.exception.InvalidDependString as e:
							portage.writemsg("!!! Invalid PROVIDE in " + \
								"'%svar/db/pkg/%s/PROVIDE': %s\n" % \
								(task.root, task.cpv, e), noiselevel=-1)
							del e
							skip = True
						if skip:
							continue

					# Check the deps of parent nodes to ensure that
					# the chosen task produces a leaf node. Maybe
					# this can be optimized some more to make the
					# best possible choice, but the current algorithm
					# is simple and should be near optimal for most
					# common cases.
					self._spinner_update()
					mergeable_parent = False
					parent_deps = set()
					parent_deps.add(task)
					for parent in mygraph.parent_nodes(task):
						parent_deps.update(mygraph.child_nodes(parent,
							ignore_priority=priority_range.ignore_medium_soft))
						if min_parent_deps is not None and \
							len(parent_deps) >= min_parent_deps:
							# This task is no better than a previously selected
							# task, so abort search now in order to avoid wasting
							# any more cpu time on this task. This increases
							# performance dramatically in cases when there are
							# hundreds of blockers to solve, like when
							# upgrading to a new slot of kde-meta.
							mergeable_parent = None
							break
						if parent in mergeable_nodes and \
							gather_deps(ignore_uninst_or_med_soft,
							mergeable_nodes, set(), parent):
							mergeable_parent = True

					if not mergeable_parent:
						continue

					if min_parent_deps is None or \
						len(parent_deps) < min_parent_deps:
						min_parent_deps = len(parent_deps)
						uninst_task = task

					if uninst_task is not None and min_parent_deps == 1:
						# This is the best possible result, so so abort search
						# now in order to avoid wasting any more cpu time.
						break

				if uninst_task is not None:
					# The uninstall is performed only after blocking
					# packages have been merged on top of it. File
					# collisions between blocking packages are detected
					# and removed from the list of files to be uninstalled.
					scheduled_uninstalls.add(uninst_task)
					parent_nodes = mygraph.parent_nodes(uninst_task)

					# Reverse the parent -> uninstall edges since we want
					# to do the uninstall after blocking packages have
					# been merged on top of it.
					mygraph.remove(uninst_task)
					for blocked_pkg in parent_nodes:
						mygraph.add(blocked_pkg, uninst_task,
							priority=BlockerDepPriority.instance)
						scheduler_graph.remove_edge(uninst_task, blocked_pkg)
						scheduler_graph.add(blocked_pkg, uninst_task,
							priority=BlockerDepPriority.instance)

					# Sometimes a merge node will render an uninstall
					# node unnecessary (due to occupying the same SLOT),
					# and we want to avoid executing a separate uninstall
					# task in that case.
					for slot_node in self._dynamic_config._package_tracker.match(
						uninst_task.root, uninst_task.slot_atom):
						if slot_node.operation == "merge":
							mygraph.add(slot_node, uninst_task,
								priority=BlockerDepPriority.instance)

					# Reset the state variables for leaf node selection and
					# continue trying to select leaf nodes.
					prefer_asap = True
					drop_satisfied = False
					continue

			if not selected_nodes:
				# Only select root nodes as a last resort. This case should
				# only trigger when the graph is nearly empty and the only
				# remaining nodes are isolated (no parents or children). Since
				# the nodes must be isolated, ignore_priority is not needed.
				selected_nodes = get_nodes()

			if not selected_nodes and not drop_satisfied:
				drop_satisfied = True
				continue

			if not selected_nodes and myblocker_uninstalls:
				# If possible, drop an uninstall task here in order to avoid
				# the circular deps code path. The corresponding blocker will
				# still be counted as an unresolved conflict.
				uninst_task = None
				for node in myblocker_uninstalls.leaf_nodes():
					try:
						mygraph.remove(node)
					except KeyError:
						pass
					else:
						uninst_task = node
						ignored_uninstall_tasks.add(node)
						break

				if uninst_task is not None:
					# Reset the state variables for leaf node selection and
					# continue trying to select leaf nodes.
					prefer_asap = True
					drop_satisfied = False
					continue

			if not selected_nodes:
				self._dynamic_config._circular_deps_for_display = mygraph
				self._dynamic_config._skip_restart = True
				raise self._unknown_internal_error()

			# At this point, we've succeeded in selecting one or more nodes, so
			# reset state variables for leaf node selection.
			prefer_asap = True
			drop_satisfied = False

			mygraph.difference_update(selected_nodes)

			for node in selected_nodes:
				if isinstance(node, Package) and \
					node.operation == "nomerge":
					continue

				# Handle interactions between blockers
				# and uninstallation tasks.
				solved_blockers = set()
				uninst_task = None
				if isinstance(node, Package) and \
					"uninstall" == node.operation:
					have_uninstall_task = True
					uninst_task = node
				else:
					vardb = self._frozen_config.trees[node.root]["vartree"].dbapi
					inst_pkg = vardb.match_pkgs(node.slot_atom)
					if inst_pkg:
						# The package will be replaced by this one, so remove
						# the corresponding Uninstall task if necessary.
						inst_pkg = inst_pkg[0]
						uninst_task = Package(built=inst_pkg.built,
							cpv=inst_pkg.cpv, installed=inst_pkg.installed,
							metadata=inst_pkg._metadata,
							operation="uninstall",
							root_config=inst_pkg.root_config,
							type_name=inst_pkg.type_name)
						try:
							mygraph.remove(uninst_task)
						except KeyError:
							pass

				if uninst_task is not None and \
					uninst_task not in ignored_uninstall_tasks and \
					myblocker_uninstalls.contains(uninst_task):
					blocker_nodes = myblocker_uninstalls.parent_nodes(uninst_task)
					myblocker_uninstalls.remove(uninst_task)
					# Discard any blockers that this Uninstall solves.
					for blocker in blocker_nodes:
						if not myblocker_uninstalls.child_nodes(blocker):
							myblocker_uninstalls.remove(blocker)
							if blocker not in \
								self._dynamic_config._unsolvable_blockers:
								solved_blockers.add(blocker)

				retlist.append(node)

				if (isinstance(node, Package) and \
					"uninstall" == node.operation) or \
					(uninst_task is not None and \
					uninst_task in scheduled_uninstalls):
					# Include satisfied blockers in the merge list
					# since the user might be interested and also
					# it serves as an indicator that blocking packages
					# will be temporarily installed simultaneously.
					for blocker in solved_blockers:
						retlist.append(blocker)

		unsolvable_blockers = set(self._dynamic_config._unsolvable_blockers.leaf_nodes())
		for node in myblocker_uninstalls.root_nodes():
			unsolvable_blockers.add(node)

		# If any Uninstall tasks need to be executed in order
		# to avoid a conflict, complete the graph with any
		# dependencies that may have been initially
		# neglected (to ensure that unsafe Uninstall tasks
		# are properly identified and blocked from execution).
		if have_uninstall_task and \
			not complete and \
			not unsolvable_blockers:
			self._dynamic_config.myparams["complete"] = True
			if '--debug' in self._frozen_config.myopts:
				msg = []
				msg.append("enabling 'complete' depgraph mode " + \
					"due to uninstall task(s):")
				msg.append("")
				for node in retlist:
					if isinstance(node, Package) and \
						node.operation == 'uninstall':
						msg.append("\t%s" % (node,))
				writemsg_level("\n%s\n" % \
					"".join("%s\n" % line for line in msg),
					level=logging.DEBUG, noiselevel=-1)
			raise self._serialize_tasks_retry("")

		# Set satisfied state on blockers, but not before the
		# above retry path, since we don't want to modify the
		# state in that case.
		for node in retlist:
			if isinstance(node, Blocker):
				node.satisfied = True

		for blocker in unsolvable_blockers:
			retlist.append(blocker)

		retlist = tuple(retlist)

		if unsolvable_blockers and \
			not self._accept_blocker_conflicts():
			self._dynamic_config._unsatisfied_blockers_for_display = unsolvable_blockers
			self._dynamic_config._serialized_tasks_cache = retlist
			self._dynamic_config._scheduler_graph = scheduler_graph
			# Blockers don't trigger the _skip_restart flag, since
			# backtracking may solve blockers when it solves slot
			# conflicts (or by blind luck).
			raise self._unknown_internal_error()

		have_slot_conflict = any(self._dynamic_config._package_tracker.slot_conflicts())
		if have_slot_conflict and \
			not self._accept_blocker_conflicts():
			self._dynamic_config._serialized_tasks_cache = retlist
			self._dynamic_config._scheduler_graph = scheduler_graph
			raise self._unknown_internal_error()

		return retlist, scheduler_graph

	def _show_circular_deps(self, mygraph):
		self._dynamic_config._circular_dependency_handler = \
			circular_dependency_handler(self, mygraph)
		handler = self._dynamic_config._circular_dependency_handler

		self._frozen_config.myopts.pop("--quiet", None)
		self._frozen_config.myopts["--verbose"] = True
		self._frozen_config.myopts["--tree"] = True
		portage.writemsg("\n\n", noiselevel=-1)
		self.display(handler.merge_list)
		prefix = colorize("BAD", " * ")
		portage.writemsg("\n", noiselevel=-1)
		portage.writemsg(prefix + "Error: circular dependencies:\n",
			noiselevel=-1)
		portage.writemsg("\n", noiselevel=-1)

		if handler.circular_dep_message is None:
			handler.debug_print()
			portage.writemsg("\n", noiselevel=-1)

		if handler.circular_dep_message is not None:
			portage.writemsg(handler.circular_dep_message, noiselevel=-1)

		suggestions = handler.suggestions
		if suggestions:
			writemsg("\n\nIt might be possible to break this cycle\n", noiselevel=-1)
			if len(suggestions) == 1:
				writemsg("by applying the following change:\n", noiselevel=-1)
			else:
				writemsg("by applying " + colorize("bold", "any of") + \
					" the following changes:\n", noiselevel=-1)
			writemsg("".join(suggestions), noiselevel=-1)
			writemsg("\nNote that this change can be reverted, once the package has" + \
				" been installed.\n", noiselevel=-1)
			if handler.large_cycle_count:
				writemsg("\nNote that the dependency graph contains a lot of cycles.\n" + \
					"Several changes might be required to resolve all cycles.\n" + \
					"Temporarily changing some use flag for all packages might be the better option.\n", noiselevel=-1)
		else:
			writemsg("\n\n", noiselevel=-1)
			writemsg(prefix + "Note that circular dependencies " + \
				"can often be avoided by temporarily\n", noiselevel=-1)
			writemsg(prefix + "disabling USE flags that trigger " + \
				"optional dependencies.\n", noiselevel=-1)

	def _show_merge_list(self):
		if self._dynamic_config._serialized_tasks_cache is not None and \
			not (self._dynamic_config._displayed_list is not None and \
			self._dynamic_config._displayed_list is self._dynamic_config._serialized_tasks_cache):
			self.display(self._dynamic_config._serialized_tasks_cache)

	def _show_unsatisfied_blockers(self, blockers):
		self._show_merge_list()
		msg = "Error: The above package list contains " + \
			"packages which cannot be installed " + \
			"at the same time on the same system."
		prefix = colorize("BAD", " * ")
		portage.writemsg("\n", noiselevel=-1)
		for line in textwrap.wrap(msg, 70):
			portage.writemsg(prefix + line + "\n", noiselevel=-1)

		# Display the conflicting packages along with the packages
		# that pulled them in. This is helpful for troubleshooting
		# cases in which blockers don't solve automatically and
		# the reasons are not apparent from the normal merge list
		# display.

		conflict_pkgs = {}
		for blocker in blockers:
			for pkg in chain(self._dynamic_config._blocked_pkgs.child_nodes(blocker), \
				self._dynamic_config._blocker_parents.parent_nodes(blocker)):

				is_slot_conflict_pkg = False
				for conflict in self._dynamic_config._package_tracker.slot_conflicts():
					if conflict.root == pkg.root and conflict.atom == pkg.slot_atom:
						is_slot_conflict_pkg = True
						break
				if is_slot_conflict_pkg:
					# The slot conflict display has better noise reduction
					# than the unsatisfied blockers display, so skip
					# unsatisfied blockers display for packages involved
					# directly in slot conflicts (see bug #385391).
					continue
				parent_atoms = self._dynamic_config._parent_atoms.get(pkg)
				if not parent_atoms:
					atom = self._dynamic_config._blocked_world_pkgs.get(pkg)
					if atom is not None:
						parent_atoms = set([("@selected", atom)])
				if parent_atoms:
					conflict_pkgs[pkg] = parent_atoms

		if conflict_pkgs:
			# Reduce noise by pruning packages that are only
			# pulled in by other conflict packages.
			pruned_pkgs = set()
			for pkg, parent_atoms in conflict_pkgs.items():
				relevant_parent = False
				for parent, atom in parent_atoms:
					if parent not in conflict_pkgs:
						relevant_parent = True
						break
				if not relevant_parent:
					pruned_pkgs.add(pkg)
			for pkg in pruned_pkgs:
				del conflict_pkgs[pkg]

		if conflict_pkgs:
			msg = []
			msg.append("\n")
			indent = "  "
			for pkg, parent_atoms in conflict_pkgs.items():

				# Prefer packages that are not directly involved in a conflict.
				# It can be essential to see all the packages here, so don't
				# omit any. If the list is long, people can simply use a pager.
				preferred_parents = set()
				for parent_atom in parent_atoms:
					parent, atom = parent_atom
					if parent not in conflict_pkgs:
						preferred_parents.add(parent_atom)

				ordered_list = list(preferred_parents)
				if len(parent_atoms) > len(ordered_list):
					for parent_atom in parent_atoms:
						if parent_atom not in preferred_parents:
							ordered_list.append(parent_atom)

				msg.append(indent + "%s pulled in by\n" % pkg)

				for parent_atom in ordered_list:
					parent, atom = parent_atom
					msg.append(2*indent)
					if isinstance(parent,
						(PackageArg, AtomArg)):
						# For PackageArg and AtomArg types, it's
						# redundant to display the atom attribute.
						msg.append(str(parent))
					else:
						# Display the specific atom from SetArg or
						# Package types.
						if atom.package and atom != atom.unevaluated_atom:
							# Show the unevaluated atom, since it can reveal
							# issues with conditional use-flags missing
							# from IUSE.
							msg.append("%s (%s) required by %s" %
								(atom.unevaluated_atom, atom, parent))
						else:
							msg.append("%s required by %s" % (atom, parent))
					msg.append("\n")

				msg.append("\n")

			writemsg("".join(msg), noiselevel=-1)

		if "--quiet" not in self._frozen_config.myopts:
			show_blocker_docs_link()

	def display(self, mylist, favorites=[], verbosity=None):

		# This is used to prevent display_problems() from
		# redundantly displaying this exact same merge list
		# again via _show_merge_list().
		self._dynamic_config._displayed_list = mylist

		if "--tree" in self._frozen_config.myopts:
			mylist = tuple(reversed(mylist))

		display = Display()

		return display(self, mylist, favorites, verbosity)

	def _display_autounmask(self, autounmask_continue=False):
		"""
		Display --autounmask message and optionally write it to config files
		(using CONFIG_PROTECT). The message includes the comments and the changes.
		"""

		if self._dynamic_config._displayed_autounmask:
			return

		self._dynamic_config._displayed_autounmask = True

		ask = "--ask" in self._frozen_config.myopts
		autounmask_write = autounmask_continue or \
				self._frozen_config.myopts.get("--autounmask-write",
								   ask) is True
		autounmask_unrestricted_atoms = \
			self._frozen_config.myopts.get("--autounmask-unrestricted-atoms", "n") == True
		quiet = "--quiet" in self._frozen_config.myopts
		pretend = "--pretend" in self._frozen_config.myopts
		enter_invalid = '--ask-enter-invalid' in self._frozen_config.myopts

		def check_if_latest(pkg, check_visibility=False):
			is_latest = True
			is_latest_in_slot = True
			dbs = self._dynamic_config._filtered_trees[pkg.root]["dbs"]
			root_config = self._frozen_config.roots[pkg.root]

			for db, pkg_type, built, installed, db_keys in dbs:
				for other_pkg in self._iter_match_pkgs(root_config, pkg_type, Atom(pkg.cp)):
					if (check_visibility and
						not self._pkg_visibility_check(other_pkg)):
						continue
					if other_pkg.cp != pkg.cp:
						# old-style PROVIDE virtual means there are no
						# normal matches for this pkg_type
						break
					if other_pkg > pkg:
						is_latest = False
						if other_pkg.slot_atom == pkg.slot_atom:
							is_latest_in_slot = False
							break
					else:
						# iter_match_pkgs yields highest version first, so
						# there's no need to search this pkg_type any further
						break

				if not is_latest_in_slot:
					break

			return is_latest, is_latest_in_slot

		#Set of roots we have autounmask changes for.
		roots = set()

		masked_by_missing_keywords = False
		unstable_keyword_msg = {}
		for pkg in self._dynamic_config._needed_unstable_keywords:
			self._show_merge_list()
			if pkg in self._dynamic_config.digraph:
				root = pkg.root
				roots.add(root)
				unstable_keyword_msg.setdefault(root, [])
				is_latest, is_latest_in_slot = check_if_latest(pkg)
				pkgsettings = self._frozen_config.pkgsettings[pkg.root]
				mreasons = _get_masking_status(pkg, pkgsettings, pkg.root_config,
					use=self._pkg_use_enabled(pkg))
				for reason in mreasons:
					if reason.unmask_hint and \
						reason.unmask_hint.key == 'unstable keyword':
						keyword = reason.unmask_hint.value
						if keyword == "**":
							masked_by_missing_keywords = True

						unstable_keyword_msg[root].append(self._get_dep_chain_as_comment(pkg))
						if autounmask_unrestricted_atoms:
							if is_latest:
								unstable_keyword_msg[root].append(">=%s %s\n" % (pkg.cpv, keyword))
							elif is_latest_in_slot:
								unstable_keyword_msg[root].append(">=%s:%s %s\n" % (pkg.cpv, pkg.slot, keyword))
							else:
								unstable_keyword_msg[root].append("=%s %s\n" % (pkg.cpv, keyword))
						else:
							unstable_keyword_msg[root].append("=%s %s\n" % (pkg.cpv, keyword))

		p_mask_change_msg = {}
		for pkg in self._dynamic_config._needed_p_mask_changes:
			self._show_merge_list()
			if pkg in self._dynamic_config.digraph:
				root = pkg.root
				roots.add(root)
				p_mask_change_msg.setdefault(root, [])
				is_latest, is_latest_in_slot = check_if_latest(pkg)
				pkgsettings = self._frozen_config.pkgsettings[pkg.root]
				mreasons = _get_masking_status(pkg, pkgsettings, pkg.root_config,
					use=self._pkg_use_enabled(pkg))
				for reason in mreasons:
					if reason.unmask_hint and \
						reason.unmask_hint.key == 'p_mask':
						keyword = reason.unmask_hint.value

						comment, filename = portage.getmaskingreason(
							pkg.cpv, metadata=pkg._metadata,
							settings=pkgsettings,
							portdb=pkg.root_config.trees["porttree"].dbapi,
							return_location=True)

						p_mask_change_msg[root].append(self._get_dep_chain_as_comment(pkg))
						if filename:
							p_mask_change_msg[root].append("# %s:\n" % filename)
						if comment:
							comment = [line for line in
								comment.splitlines() if line]
							for line in comment:
								p_mask_change_msg[root].append("%s\n" % line)
						if autounmask_unrestricted_atoms:
							if is_latest:
								p_mask_change_msg[root].append(">=%s\n" % pkg.cpv)
							elif is_latest_in_slot:
								p_mask_change_msg[root].append(">=%s:%s\n" % (pkg.cpv, pkg.slot))
							else:
								p_mask_change_msg[root].append("=%s\n" % pkg.cpv)
						else:
							p_mask_change_msg[root].append("=%s\n" % pkg.cpv)

		use_changes_msg = {}
		for pkg, needed_use_config_change in self._dynamic_config._needed_use_config_changes.items():
			self._show_merge_list()
			if pkg in self._dynamic_config.digraph:
				root = pkg.root
				roots.add(root)
				use_changes_msg.setdefault(root, [])
				# NOTE: For USE changes, call check_if_latest with
				# check_visibility=True, since we want to generate
				# a >= atom if possible. Don't do this for keyword
				# or mask changes, since that may cause undesired
				# versions to be unmasked! See bug #536392.
				is_latest, is_latest_in_slot = check_if_latest(
					pkg, check_visibility=True)
				changes = needed_use_config_change[1]
				adjustments = []
				for flag, state in changes.items():
					if state:
						adjustments.append(flag)
					else:
						adjustments.append("-" + flag)
				use_changes_msg[root].append(self._get_dep_chain_as_comment(pkg, unsatisfied_dependency=True))
				if is_latest:
					use_changes_msg[root].append(">=%s %s\n" % (pkg.cpv, " ".join(adjustments)))
				elif is_latest_in_slot:
					use_changes_msg[root].append(">=%s:%s %s\n" % (pkg.cpv, pkg.slot, " ".join(adjustments)))
				else:
					use_changes_msg[root].append("=%s %s\n" % (pkg.cpv, " ".join(adjustments)))

		license_msg = {}
		for pkg, missing_licenses in self._dynamic_config._needed_license_changes.items():
			self._show_merge_list()
			if pkg in self._dynamic_config.digraph:
				root = pkg.root
				roots.add(root)
				license_msg.setdefault(root, [])
				is_latest, is_latest_in_slot = check_if_latest(pkg)

				license_msg[root].append(self._get_dep_chain_as_comment(pkg))
				if is_latest:
					license_msg[root].append(">=%s %s\n" % (pkg.cpv, " ".join(sorted(missing_licenses))))
				elif is_latest_in_slot:
					license_msg[root].append(">=%s:%s %s\n" % (pkg.cpv, pkg.slot, " ".join(sorted(missing_licenses))))
				else:
					license_msg[root].append("=%s %s\n" % (pkg.cpv, " ".join(sorted(missing_licenses))))

		def find_config_file(abs_user_config, file_name):
			"""
			Searches /etc/portage for an appropriate file to append changes to.
			If the file_name is a file it is returned, if it is a directory, the
			last file in it is returned. Order of traversal is the identical to
			portage.util.grablines(recursive=True).

			file_name - String containing a file name like "package.use"
			return value - String. Absolute path of file to write to. None if
			no suitable file exists.
			"""
			file_path = os.path.join(abs_user_config, file_name)

			try:
				os.lstat(file_path)
			except OSError as e:
				if e.errno == errno.ENOENT:
					# The file doesn't exist, so we'll
					# simply create it.
					return file_path

				# Disk or file system trouble?
				return None

			last_file_path = None
			stack = [file_path]
			while stack:
				p = stack.pop()
				try:
					st = os.stat(p)
				except OSError:
					pass
				else:
					if stat.S_ISREG(st.st_mode):
						last_file_path = p
					elif stat.S_ISDIR(st.st_mode):
						if os.path.basename(p) in VCS_DIRS:
							continue
						try:
							contents = os.listdir(p)
						except OSError:
							pass
						else:
							contents.sort(reverse=True)
							for child in contents:
								if child.startswith(".") or \
									child.endswith("~"):
									continue
								stack.append(os.path.join(p, child))
			# If the directory is empty add a file with name
			# pattern file_name.default
			if last_file_path is None:
				last_file_path = os.path.join(file_path, file_path, "zz-autounmask")
				with open(last_file_path, "a+") as default:
					default.write("# " + file_name)

			return last_file_path

		write_to_file = autounmask_write and not pretend
		#Make sure we have a file to write to before doing any write.
		file_to_write_to = {}
		problems = []
		if write_to_file:
			for root in roots:
				settings = self._frozen_config.roots[root].settings
				abs_user_config = os.path.join(
					settings["PORTAGE_CONFIGROOT"], USER_CONFIG_PATH)

				if root in unstable_keyword_msg:
					if not os.path.exists(os.path.join(abs_user_config,
						"package.keywords")):
						filename = "package.accept_keywords"
					else:
						filename = "package.keywords"
					file_to_write_to[(abs_user_config, "package.keywords")] = \
						find_config_file(abs_user_config, filename)

				if root in p_mask_change_msg:
					file_to_write_to[(abs_user_config, "package.unmask")] = \
						find_config_file(abs_user_config, "package.unmask")

				if root in use_changes_msg:
					file_to_write_to[(abs_user_config, "package.use")] = \
						find_config_file(abs_user_config, "package.use")

				if root in license_msg:
					file_to_write_to[(abs_user_config, "package.license")] = \
						find_config_file(abs_user_config, "package.license")

			for (abs_user_config, f), path in file_to_write_to.items():
				if path is None:
					problems.append("!!! No file to write for '%s'\n" % os.path.join(abs_user_config, f))

			write_to_file = not problems

		def format_msg(lines):
			lines = lines[:]
			for i, line in enumerate(lines):
				if line.startswith("#"):
					continue
				lines[i] = colorize("INFORM", line.rstrip()) + "\n"
			return "".join(lines)

		for root in roots:
			settings = self._frozen_config.roots[root].settings
			abs_user_config = os.path.join(
				settings["PORTAGE_CONFIGROOT"], USER_CONFIG_PATH)

			if len(roots) > 1:
				writemsg("\nFor %s:\n" % abs_user_config, noiselevel=-1)

			def _writemsg(reason, file):
				writemsg(('\nThe following %s are necessary to proceed:\n'
				          ' (see "%s" in the portage(5) man page for more details)\n')
				         % (colorize('BAD', reason), file), noiselevel=-1)

			if root in unstable_keyword_msg:
				_writemsg('keyword changes', 'package.accept_keywords')
				writemsg(format_msg(unstable_keyword_msg[root]), noiselevel=-1)

			if root in p_mask_change_msg:
				_writemsg('mask changes', 'package.unmask')
				writemsg(format_msg(p_mask_change_msg[root]), noiselevel=-1)

			if root in use_changes_msg:
				_writemsg('USE changes', 'package.use')
				writemsg(format_msg(use_changes_msg[root]), noiselevel=-1)

			if root in license_msg:
				_writemsg('license changes', 'package.license')
				writemsg(format_msg(license_msg[root]), noiselevel=-1)

		protect_obj = {}
		if write_to_file and not autounmask_continue:
			for root in roots:
				settings = self._frozen_config.roots[root].settings
				protect_obj[root] = ConfigProtect(
					settings["PORTAGE_CONFIGROOT"],
					shlex_split(settings.get("CONFIG_PROTECT", "")),
					shlex_split(settings.get("CONFIG_PROTECT_MASK", "")),
					case_insensitive=("case-insensitive-fs"
					in settings.features))

		def write_changes(root, changes, file_to_write_to):
			file_contents = None
			try:
				with io.open(
					_unicode_encode(file_to_write_to,
					encoding=_encodings['fs'], errors='strict'),
					mode='r', encoding=_encodings['content'],
					errors='replace') as f:
					file_contents = f.readlines()
			except IOError as e:
				if e.errno == errno.ENOENT:
					file_contents = []
				else:
					problems.append("!!! Failed to read '%s': %s\n" % \
						(file_to_write_to, e))
			if file_contents is not None:
				file_contents.extend(changes)
				if (not autounmask_continue and
					protect_obj[root].isprotected(file_to_write_to)):
					# We want to force new_protect_filename to ensure
					# that the user will see all our changes via
					# dispatch-conf, even if file_to_write_to doesn't
					# exist yet, so we specify force=True.
					file_to_write_to = new_protect_filename(file_to_write_to,
						force=True)
				try:
					write_atomic(file_to_write_to, "".join(file_contents))
				except PortageException:
					problems.append("!!! Failed to write '%s'\n" % file_to_write_to)

		if not quiet and (p_mask_change_msg or masked_by_missing_keywords):
			msg = [
				"",
				"NOTE: The --autounmask-keep-masks option will prevent emerge",
				"      from creating package.unmask or ** keyword changes."
			]
			for line in msg:
				if line:
					line = colorize("INFORM", line)
				writemsg(line + "\n", noiselevel=-1)

		if ask and write_to_file and file_to_write_to:
			prompt = "\nWould you like to add these " + \
				"changes to your config files?"
			if self.query(prompt, enter_invalid) == 'No':
				write_to_file = False

		if write_to_file and file_to_write_to:
			for root in roots:
				settings = self._frozen_config.roots[root].settings
				abs_user_config = os.path.join(
					settings["PORTAGE_CONFIGROOT"], USER_CONFIG_PATH)
				ensure_dirs(abs_user_config)

				if root in unstable_keyword_msg:
					write_changes(root, unstable_keyword_msg[root],
						file_to_write_to.get((abs_user_config, "package.keywords")))

				if root in p_mask_change_msg:
					write_changes(root, p_mask_change_msg[root],
						file_to_write_to.get((abs_user_config, "package.unmask")))

				if root in use_changes_msg:
					write_changes(root, use_changes_msg[root],
						file_to_write_to.get((abs_user_config, "package.use")))

				if root in license_msg:
					write_changes(root, license_msg[root],
						file_to_write_to.get((abs_user_config, "package.license")))

		if problems:
			writemsg("\nThe following problems occurred while writing autounmask changes:\n", \
				noiselevel=-1)
			writemsg("".join(problems), noiselevel=-1)
		elif write_to_file and roots:
			writemsg("\nAutounmask changes successfully written.\n",
				noiselevel=-1)
			if autounmask_continue:
				return True
			for root in roots:
				chk_updated_cfg_files(root,
					[os.path.join(os.sep, USER_CONFIG_PATH)])
		elif not pretend and not autounmask_write and roots:
			writemsg("\nUse --autounmask-write to write changes to config files (honoring\n"
				"CONFIG_PROTECT). Carefully examine the list of proposed changes,\n"
				"paying special attention to mask or keyword changes that may expose\n"
				"experimental or unstable packages.\n",
				noiselevel=-1)

		if self._dynamic_config._autounmask_backtrack_disabled:
			msg = [
				"In order to avoid wasting time, backtracking has terminated early",
				"due to the above autounmask change(s). The --autounmask-backtrack=y",
				"option can be used to force further backtracking, but there is no",
				"guarantee that it will produce a solution.",
			]
			writemsg("\n", noiselevel=-1)
			for line in msg:
				writemsg(" %s %s\n" % (colorize("WARN", "*"), line),
					noiselevel=-1)

	def display_problems(self):
		"""
		Display problems with the dependency graph such as slot collisions.
		This is called internally by display() to show the problems _after_
		the merge list where it is most likely to be seen, but if display()
		is not going to be called then this method should be called explicitly
		to ensure that the user is notified of problems with the graph.
		"""

		if self._dynamic_config._circular_deps_for_display is not None:
			self._show_circular_deps(
				self._dynamic_config._circular_deps_for_display)

		unresolved_conflicts = False
		have_slot_conflict = any(self._dynamic_config._package_tracker.slot_conflicts())
		if have_slot_conflict:
			unresolved_conflicts = True
			self._show_slot_collision_notice()
		if self._dynamic_config._unsatisfied_blockers_for_display is not None:
			unresolved_conflicts = True
			self._show_unsatisfied_blockers(
				self._dynamic_config._unsatisfied_blockers_for_display)

		# Only show missed updates if there are no unresolved conflicts,
		# since they may be irrelevant after the conflicts are solved.
		if not unresolved_conflicts:
			self._show_missed_update()

		if self._frozen_config.myopts.get("--verbose-slot-rebuilds", 'y') != 'n':
			self._compute_abi_rebuild_info()
			self._show_abi_rebuild_info()

		self._show_ignored_binaries()

		self._changed_deps_report()

		self._display_autounmask()

		for depgraph_sets in self._dynamic_config.sets.values():
			for pset in depgraph_sets.sets.values():
				for error_msg in pset.errors:
					writemsg_level("%s\n" % (error_msg,),
						level=logging.ERROR, noiselevel=-1)

		# TODO: Add generic support for "set problem" handlers so that
		# the below warnings aren't special cases for world only.

		if self._dynamic_config._missing_args:
			world_problems = False
			if "world" in self._dynamic_config.sets[
				self._frozen_config.target_root].sets:
				# Filter out indirect members of world (from nested sets)
				# since only direct members of world are desired here.
				world_set = self._frozen_config.roots[self._frozen_config.target_root].sets["selected"]
				for arg, atom in self._dynamic_config._missing_args:
					if arg.name in ("selected", "world") and atom in world_set:
						world_problems = True
						break

			if world_problems:
				writemsg("\n!!! Problems have been " + \
					"detected with your world file\n",
					noiselevel=-1)
				writemsg("!!! Please run " + \
					green("emaint --check world")+"\n\n",
					noiselevel=-1)

		if self._dynamic_config._missing_args:
			writemsg("\n" + colorize("BAD", "!!!") + \
				" Ebuilds for the following packages are either all\n",
				noiselevel=-1)
			writemsg(colorize("BAD", "!!!") + \
				" masked or don't exist:\n",
				noiselevel=-1)
			writemsg(" ".join(str(atom) for arg, atom in \
				self._dynamic_config._missing_args) + "\n",
				noiselevel=-1)

		if self._dynamic_config._pprovided_args:
			arg_refs = {}
			for arg, atom in self._dynamic_config._pprovided_args:
				if isinstance(arg, SetArg):
					parent = arg.name
					arg_atom = (atom, atom)
				else:
					parent = "args"
					arg_atom = (arg.arg, atom)
				refs = arg_refs.setdefault(arg_atom, [])
				if parent not in refs:
					refs.append(parent)
			msg = []
			msg.append(bad("\nWARNING: "))
			if len(self._dynamic_config._pprovided_args) > 1:
				msg.append("Requested packages will not be " + \
					"merged because they are listed in\n")
			else:
				msg.append("A requested package will not be " + \
					"merged because it is listed in\n")
			msg.append("package.provided:\n\n")
			problems_sets = set()
			for (arg, atom), refs in arg_refs.items():
				ref_string = ""
				if refs:
					problems_sets.update(refs)
					refs.sort()
					ref_string = ", ".join(["'%s'" % name for name in refs])
					ref_string = " pulled in by " + ref_string
				msg.append("  %s%s\n" % (colorize("INFORM", str(arg)), ref_string))
			msg.append("\n")
			if "selected" in problems_sets or "world" in problems_sets:
				msg.append("This problem can be solved in one of the following ways:\n\n")
				msg.append("  A) Use emaint to clean offending packages from world (if not installed).\n")
				msg.append("  B) Uninstall offending packages (cleans them from world).\n")
				msg.append("  C) Remove offending entries from package.provided.\n\n")
				msg.append("The best course of action depends on the reason that an offending\n")
				msg.append("package.provided entry exists.\n\n")
			writemsg("".join(msg), noiselevel=-1)

		masked_packages = []
		for pkg in self._dynamic_config._masked_license_updates:
			root_config = pkg.root_config
			pkgsettings = self._frozen_config.pkgsettings[pkg.root]
			mreasons = get_masking_status(pkg, pkgsettings, root_config, use=self._pkg_use_enabled(pkg))
			masked_packages.append((root_config, pkgsettings,
				pkg.cpv, pkg.repo, pkg._metadata, mreasons))
		if masked_packages:
			writemsg("\n" + colorize("BAD", "!!!") + \
				" The following updates are masked by LICENSE changes:\n",
				noiselevel=-1)
			show_masked_packages(masked_packages)
			show_mask_docs()
			writemsg("\n", noiselevel=-1)

		masked_packages = []
		for pkg in self._dynamic_config._masked_installed:
			root_config = pkg.root_config
			pkgsettings = self._frozen_config.pkgsettings[pkg.root]
			mreasons = get_masking_status(pkg, pkgsettings, root_config, use=self._pkg_use_enabled)
			masked_packages.append((root_config, pkgsettings,
				pkg.cpv, pkg.repo, pkg._metadata, mreasons))
		if masked_packages:
			writemsg("\n" + colorize("BAD", "!!!") + \
				" The following installed packages are masked:\n",
				noiselevel=-1)
			show_masked_packages(masked_packages)
			show_mask_docs()
			writemsg("\n", noiselevel=-1)

		for pargs, kwargs in self._dynamic_config._unsatisfied_deps_for_display:
			self._show_unsatisfied_dep(*pargs, **kwargs)

		if self._dynamic_config._buildpkgonly_deps_unsatisfied:
			self._show_merge_list()
			writemsg("\n!!! --buildpkgonly requires all "
				"dependencies to be merged.\n", noiselevel=-1)
			writemsg("!!! Cannot merge requested packages. "
				"Merge deps and try again.\n\n", noiselevel=-1)

	def saveNomergeFavorites(self):
		"""Find atoms in favorites that are not in the mergelist and add them
		to the world file if necessary."""
		for x in ("--buildpkgonly", "--fetchonly", "--fetch-all-uri",
			"--oneshot", "--onlydeps", "--pretend"):
			if x in self._frozen_config.myopts:
				return
		root_config = self._frozen_config.roots[self._frozen_config.target_root]
		world_set = root_config.sets["selected"]

		world_locked = False
		if hasattr(world_set, "lock"):
			world_set.lock()
			world_locked = True

		if hasattr(world_set, "load"):
			world_set.load() # maybe it's changed on disk

		args_set = self._dynamic_config.sets[
			self._frozen_config.target_root].sets['__non_set_args__']
		added_favorites = set()
		for x in self._dynamic_config._set_nodes:
			if x.operation != "nomerge":
				continue

			if x.root != root_config.root:
				continue

			try:
				myfavkey = create_world_atom(x, args_set, root_config)
				if myfavkey:
					if myfavkey in added_favorites:
						continue
					added_favorites.add(myfavkey)
			except portage.exception.InvalidDependString as e:
				writemsg("\n\n!!! '%s' has invalid PROVIDE: %s\n" % \
					(x.cpv, e), noiselevel=-1)
				writemsg("!!! see '%s'\n\n" % os.path.join(
					x.root, portage.VDB_PATH, x.cpv, "PROVIDE"), noiselevel=-1)
				del e
		all_added = []
		for arg in self._dynamic_config._initial_arg_list:
			if not isinstance(arg, SetArg):
				continue
			if arg.root_config.root != root_config.root:
				continue
			if arg.internal:
				# __auto_* sets
				continue
			k = arg.name
			if k in ("selected", "world") or \
				not root_config.sets[k].world_candidate:
				continue
			s = SETPREFIX + k
			if s in world_set:
				continue
			all_added.append(SETPREFIX + k)
		all_added.extend(added_favorites)
		all_added.sort()
		if all_added:
			skip = False
			if "--ask" in self._frozen_config.myopts:
				writemsg_stdout("\n", noiselevel=-1)
				for a in all_added:
					writemsg_stdout(" %s %s\n" % (colorize("GOOD", "*"), a),
						noiselevel=-1)
				writemsg_stdout("\n", noiselevel=-1)
				prompt = "Would you like to add these packages to your world " \
					"favorites?"
				enter_invalid = '--ask-enter-invalid' in \
					self._frozen_config.myopts
				if self.query(prompt, enter_invalid) == "No":
					skip = True

			if not skip:
				for a in all_added:
					if a.startswith(SETPREFIX):
						filename = "world_sets"
					else:
						filename = "world"
					writemsg_stdout(
						">>> Recording %s in \"%s\" favorites file...\n" %
						(colorize("INFORM", _unicode(a)), filename), noiselevel=-1)
				world_set.update(all_added)

		if world_locked:
			world_set.unlock()

	def _loadResumeCommand(self, resume_data, skip_masked=True,
		skip_missing=True):
		"""
		Add a resume command to the graph and validate it in the process.  This
		will raise a PackageNotFound exception if a package is not available.
		"""

		self._load_vdb()

		if not isinstance(resume_data, dict):
			return False

		mergelist = resume_data.get("mergelist")
		if not isinstance(mergelist, list):
			mergelist = []

		favorites = resume_data.get("favorites")
		if isinstance(favorites, list):
			args = self._load_favorites(favorites)
		else:
			args = []

		serialized_tasks = []
		masked_tasks = []
		for x in mergelist:
			if not (isinstance(x, list) and len(x) == 4):
				continue
			pkg_type, myroot, pkg_key, action = x
			if pkg_type not in self.pkg_tree_map:
				continue
			if action != "merge":
				continue
			root_config = self._frozen_config.roots[myroot]

			# Use the resume "favorites" list to see if a repo was specified
			# for this package.
			depgraph_sets = self._dynamic_config.sets[root_config.root]
			repo = None
			for atom in depgraph_sets.atoms.getAtoms():
				if atom.repo and portage.dep.match_from_list(atom, [pkg_key]):
					repo = atom.repo
					break

			atom = "=" + pkg_key
			if repo:
				atom = atom + _repo_separator + repo

			try:
				atom = Atom(atom, allow_repo=True)
			except InvalidAtom:
				continue

			pkg = None
			for pkg in self._iter_match_pkgs(root_config, pkg_type, atom):
				if not self._pkg_visibility_check(pkg) or \
					self._frozen_config.excluded_pkgs.findAtomForPackage(pkg,
						modified_use=self._pkg_use_enabled(pkg)):
					continue
				break

			if pkg is None:
				# It does no exist or it is corrupt.
				if skip_missing:
					# TODO: log these somewhere
					continue
				raise portage.exception.PackageNotFound(pkg_key)

			if "merge" == pkg.operation and \
				self._frozen_config.excluded_pkgs.findAtomForPackage(pkg, \
					modified_use=self._pkg_use_enabled(pkg)):
				continue

			if "merge" == pkg.operation and not self._pkg_visibility_check(pkg):
				if skip_masked:
					masked_tasks.append(Dependency(root=pkg.root, parent=pkg))
				else:
					self._dynamic_config._unsatisfied_deps_for_display.append(
						((pkg.root, "="+pkg.cpv), {"myparent":None}))

			self._dynamic_config._package_tracker.add_pkg(pkg)
			serialized_tasks.append(pkg)
			self._spinner_update()

		if self._dynamic_config._unsatisfied_deps_for_display:
			return False

		if not serialized_tasks or "--nodeps" in self._frozen_config.myopts:
			self._dynamic_config._serialized_tasks_cache = serialized_tasks
			self._dynamic_config._scheduler_graph = self._dynamic_config.digraph
		else:
			self._select_package = self._select_pkg_from_graph
			self._dynamic_config.myparams["selective"] = True
			# Always traverse deep dependencies in order to account for
			# potentially unsatisfied dependencies of installed packages.
			# This is necessary for correct --keep-going or --resume operation
			# in case a package from a group of circularly dependent packages
			# fails. In this case, a package which has recently been installed
			# may have an unsatisfied circular dependency (pulled in by
			# PDEPEND, for example). So, even though a package is already
			# installed, it may not have all of it's dependencies satisfied, so
			# it may not be usable. If such a package is in the subgraph of
			# deep depenedencies of a scheduled build, that build needs to
			# be cancelled. In order for this type of situation to be
			# recognized, deep traversal of dependencies is required.
			self._dynamic_config.myparams["deep"] = True

			for task in serialized_tasks:
				if isinstance(task, Package) and \
					task.operation == "merge":
					if not self._add_pkg(task, None):
						return False

			# Packages for argument atoms need to be explicitly
			# added via _add_pkg() so that they are included in the
			# digraph (needed at least for --tree display).
			for arg in self._expand_set_args(args, add_to_digraph=True):
				for atom in arg.pset.getAtoms():
					pkg, existing_node = self._select_package(
						arg.root_config.root, atom)
					if existing_node is None and \
						pkg is not None:
						if not self._add_pkg(pkg, Dependency(atom=atom,
							root=pkg.root, parent=arg)):
							return False

			# Allow unsatisfied deps here to avoid showing a masking
			# message for an unsatisfied dep that isn't necessarily
			# masked.
			if not self._create_graph(allow_unsatisfied=True):
				return False

			unsatisfied_deps = []
			for dep in self._dynamic_config._unsatisfied_deps:
				if not isinstance(dep.parent, Package):
					continue
				if dep.parent.operation == "merge":
					unsatisfied_deps.append(dep)
					continue

				# For unsatisfied deps of installed packages, only account for
				# them if they are in the subgraph of dependencies of a package
				# which is scheduled to be installed.
				unsatisfied_install = False
				traversed = set()
				dep_stack = self._dynamic_config.digraph.parent_nodes(dep.parent)
				while dep_stack:
					node = dep_stack.pop()
					if not isinstance(node, Package):
						continue
					if node.operation == "merge":
						unsatisfied_install = True
						break
					if node in traversed:
						continue
					traversed.add(node)
					dep_stack.extend(self._dynamic_config.digraph.parent_nodes(node))

				if unsatisfied_install:
					unsatisfied_deps.append(dep)

			if masked_tasks or unsatisfied_deps:
				# This probably means that a required package
				# was dropped via --skipfirst. It makes the
				# resume list invalid, so convert it to a
				# UnsatisfiedResumeDep exception.
				raise self.UnsatisfiedResumeDep(self,
					masked_tasks + unsatisfied_deps)
			self._dynamic_config._serialized_tasks_cache = None
			try:
				self.altlist()
			except self._unknown_internal_error:
				return False

		return True

	def _load_favorites(self, favorites):
		"""
		Use a list of favorites to resume state from a
		previous select_files() call. This creates similar
		DependencyArg instances to those that would have
		been created by the original select_files() call.
		This allows Package instances to be matched with
		DependencyArg instances during graph creation.
		"""
		root_config = self._frozen_config.roots[self._frozen_config.target_root]
		sets = root_config.sets
		depgraph_sets = self._dynamic_config.sets[root_config.root]
		args = []
		for x in favorites:
			if not isinstance(x, basestring):
				continue
			if x in ("system", "world"):
				x = SETPREFIX + x
			if x.startswith(SETPREFIX):
				s = x[len(SETPREFIX):]
				if s not in sets:
					continue
				if s in depgraph_sets.sets:
					continue
				pset = sets[s]
				depgraph_sets.sets[s] = pset
				args.append(SetArg(arg=x, pset=pset,
					root_config=root_config))
			else:
				try:
					x = Atom(x, allow_repo=True)
				except portage.exception.InvalidAtom:
					continue
				args.append(AtomArg(arg=x, atom=x,
					root_config=root_config))

		self._set_args(args)
		return args

	class UnsatisfiedResumeDep(portage.exception.PortageException):
		"""
		A dependency of a resume list is not installed. This
		can occur when a required package is dropped from the
		merge list via --skipfirst.
		"""
		def __init__(self, depgraph, value):
			portage.exception.PortageException.__init__(self, value)
			self.depgraph = depgraph

	class _internal_exception(portage.exception.PortageException):
		def __init__(self, value=""):
			portage.exception.PortageException.__init__(self, value)

	class _unknown_internal_error(_internal_exception):
		"""
		Used by the depgraph internally to terminate graph creation.
		The specific reason for the failure should have been dumped
		to stderr, unfortunately, the exact reason for the failure
		may not be known.
		"""

	class _serialize_tasks_retry(_internal_exception):
		"""
		This is raised by the _serialize_tasks() method when it needs to
		be called again for some reason. The only case that it's currently
		used for is when neglected dependencies need to be added to the
		graph in order to avoid making a potentially unsafe decision.
		"""

	class _backtrack_mask(_internal_exception):
		"""
		This is raised by _show_unsatisfied_dep() when it's called with
		check_backtrack=True and a matching package has been masked by
		backtracking.
		"""

	class _autounmask_breakage(_internal_exception):
		"""
		This is raised by _show_unsatisfied_dep() when it's called with
		check_autounmask_breakage=True and a matching package has been
		been disqualified due to autounmask changes.
		"""

	def need_restart(self):
		return self._dynamic_config._need_restart and \
			not self._dynamic_config._skip_restart

	def need_config_change(self):
		"""
		Returns true if backtracking should terminate due to a needed
		configuration change.
		"""
		if (self._dynamic_config._success_without_autounmask or
			self._dynamic_config._required_use_unsatisfied):
			return True

		if (self._dynamic_config._slot_conflict_handler is None and
			not self._accept_blocker_conflicts() and
			any(self._dynamic_config._package_tracker.slot_conflicts())):
			self._dynamic_config._slot_conflict_handler = slot_conflict_handler(self)
			if self._dynamic_config._slot_conflict_handler.changes:
				# Terminate backtracking early if the slot conflict
				# handler finds some changes to suggest. The case involving
				# sci-libs/L and sci-libs/M in SlotCollisionTestCase will
				# otherwise fail with --autounmask-backtrack=n, since
				# backtracking will eventually lead to some autounmask
				# changes. Changes suggested by the slot conflict handler
				# are more likely to be useful.
				return True

		if (self._dynamic_config._allow_backtracking and
			self._frozen_config.myopts.get("--autounmask-backtrack") != 'y' and
			self._have_autounmask_changes()):

			if (self._frozen_config.myopts.get("--autounmask-continue") is True and
				self._frozen_config.myopts.get("--autounmask-backtrack") != 'n'):
				# --autounmask-continue implies --autounmask-backtrack=y behavior,
				# for backward compatibility.
				return False

			# This disables backtracking when there are autounmask
			# config changes. The display_problems method will notify
			# the user that --autounmask-backtrack=y can be used to
			# force backtracking in this case.
			self._dynamic_config._autounmask_backtrack_disabled = True
			return True

		return False

	def _have_autounmask_changes(self):
		digraph_nodes = self._dynamic_config.digraph.nodes
		return (any(x in digraph_nodes for x in
			self._dynamic_config._needed_unstable_keywords) or
			any(x in digraph_nodes for x in
			self._dynamic_config._needed_p_mask_changes) or
			any(x in digraph_nodes for x in
			self._dynamic_config._needed_use_config_changes) or
			any(x in digraph_nodes for x in
			self._dynamic_config._needed_license_changes))

	def need_config_reload(self):
		return self._dynamic_config._need_config_reload

	def autounmask_breakage_detected(self):
		try:
			for pargs, kwargs in self._dynamic_config._unsatisfied_deps_for_display:
				self._show_unsatisfied_dep(
					*pargs, check_autounmask_breakage=True, **kwargs)
		except self._autounmask_breakage:
			return True
		return False

	def get_backtrack_infos(self):
		return self._dynamic_config._backtrack_infos


class _dep_check_composite_db(dbapi):
	"""
	A dbapi-like interface that is optimized for use in dep_check() calls.
	This is built on top of the existing depgraph package selection logic.
	Some packages that have been added to the graph may be masked from this
	view in order to influence the atom preference selection that occurs
	via dep_check().
	"""
	def __init__(self, depgraph, root):
		dbapi.__init__(self)
		self._depgraph = depgraph
		self._root = root
		self._match_cache = {}
		self._cpv_pkg_map = {}

	def _clear_cache(self):
		self._match_cache.clear()
		self._cpv_pkg_map.clear()

	def cp_list(self, cp):
		"""
		Emulate cp_list just so it can be used to check for existence
		of new-style virtuals. Since it's a waste of time to return
		more than one cpv for this use case, a maximum of one cpv will
		be returned.
		"""
		if isinstance(cp, Atom):
			atom = cp
		else:
			atom = Atom(cp)
		ret = []
		for pkg in self._depgraph._iter_match_pkgs_any(
			self._depgraph._frozen_config.roots[self._root], atom):
			if pkg.cp == cp:
				ret.append(pkg.cpv)
				break

		return ret

	def match_pkgs(self, atom):
		cache_key = (atom, atom.unevaluated_atom)
		ret = self._match_cache.get(cache_key)
		if ret is not None:
			for pkg in ret:
				self._cpv_pkg_map[pkg.cpv] = pkg
			return ret[:]

		atom_set = InternalPackageSet(initial_atoms=(atom,))
		ret = []
		pkg, existing = self._depgraph._select_package(self._root, atom)

		if pkg is not None and self._visible(pkg, atom_set):
			ret.append(pkg)

		if pkg is not None and \
			atom.sub_slot is None and \
			pkg.cp.startswith("virtual/") and \
			(("remove" not in self._depgraph._dynamic_config.myparams and
			"--update" not in self._depgraph._frozen_config.myopts) or
			not ret):
			# For new-style virtual lookahead that occurs inside dep_check()
			# for bug #141118, examine all slots. This is needed so that newer
			# slots will not unnecessarily be pulled in when a satisfying lower
			# slot is already installed. For example, if virtual/jdk-1.5 is
			# satisfied via gcj-jdk then there's no need to pull in a newer
			# slot to satisfy a virtual/jdk dependency, unless --update is
			# enabled.
			sub_slots = set()
			resolved_sub_slots = set()
			for virt_pkg in self._depgraph._iter_match_pkgs_any(
				self._depgraph._frozen_config.roots[self._root], atom):
				if virt_pkg.cp != pkg.cp:
					continue
				sub_slots.add((virt_pkg.slot, virt_pkg.sub_slot))

			sub_slot_key = (pkg.slot, pkg.sub_slot)
			if ret:
				# We've added pkg to ret already, and only one package
				# per slot/sub_slot is desired here.
				sub_slots.discard(sub_slot_key)
				resolved_sub_slots.add(sub_slot_key)
			else:
				sub_slots.add(sub_slot_key)

			while sub_slots:
				slot, sub_slot = sub_slots.pop()
				slot_atom = atom.with_slot("%s/%s" % (slot, sub_slot))
				pkg, existing = self._depgraph._select_package(
					self._root, slot_atom)
				if not pkg:
					continue
				if not self._visible(pkg, atom_set,
					avoid_slot_conflict=False):
					# Try to force a virtual update to be pulled in
					# when appropriate for bug #526160.
					selected = pkg
					for candidate in \
						self._iter_virt_update(pkg, atom_set):

						if candidate.slot != slot:
							continue

						if (candidate.slot, candidate.sub_slot) in \
							resolved_sub_slots:
							continue

						if selected is None or \
							selected < candidate:
							selected = candidate

					if selected is pkg:
						continue
					pkg = selected

				resolved_sub_slots.add((pkg.slot, pkg.sub_slot))
				ret.append(pkg)

			if len(ret) > 1:
				ret = sorted(set(ret))

		self._match_cache[cache_key] = ret
		for pkg in ret:
			self._cpv_pkg_map[pkg.cpv] = pkg
		return ret[:]

	def _visible(self, pkg, atom_set, avoid_slot_conflict=True,
		probe_virt_update=True):
		if pkg.installed and not self._depgraph._want_installed_pkg(pkg):
			return False
		if pkg.installed and \
			(pkg.masks or not self._depgraph._pkg_visibility_check(pkg)):
			# Account for packages with masks (like KEYWORDS masks)
			# that are usually ignored in visibility checks for
			# installed packages, in order to handle cases like
			# bug #350285.
			myopts = self._depgraph._frozen_config.myopts
			use_ebuild_visibility = myopts.get(
				'--use-ebuild-visibility', 'n') != 'n'
			avoid_update = "--update" not in myopts and \
				"remove" not in self._depgraph._dynamic_config.myparams
			usepkgonly = "--usepkgonly" in myopts
			if not avoid_update:
				if not use_ebuild_visibility and usepkgonly:
					return False
				elif not self._depgraph._equiv_ebuild_visible(pkg):
					return False

		if pkg.cp.startswith("virtual/"):

			if not self._depgraph._virt_deps_visible(
				pkg, ignore_use=True):
				return False

			if probe_virt_update and \
				self._have_virt_update(pkg, atom_set):
				# Force virtual updates to be pulled in when appropriate
				# for bug #526160.
				return False

		if not avoid_slot_conflict:
			# This is useful when trying to pull in virtual updates,
			# since we don't want another instance that was previously
			# pulled in to mask an update that we're trying to pull
			# into the same slot.
			return True

		# Use reversed iteration in order to get descending order here,
		# so that the highest version involved in a slot conflict is
		# selected (see bug 554070).
		in_graph = next(reversed(list(
			self._depgraph._dynamic_config._package_tracker.match(
			self._root, pkg.slot_atom, installed=False))), None)

		if in_graph is None:
			# Mask choices for packages which are not the highest visible
			# version within their slot (since they usually trigger slot
			# conflicts).
			highest_visible, in_graph = self._depgraph._select_package(
				self._root, pkg.slot_atom)
			# Note: highest_visible is not necessarily the real highest
			# visible, especially when --update is not enabled, so use
			# < operator instead of !=.
			if (highest_visible is not None and pkg < highest_visible
				and atom_set.findAtomForPackage(highest_visible,
				modified_use=self._depgraph._pkg_use_enabled(highest_visible))):
				return False
		elif in_graph != pkg:
			# Mask choices for packages that would trigger a slot
			# conflict with a previously selected package.
			if not atom_set.findAtomForPackage(in_graph,
				modified_use=self._depgraph._pkg_use_enabled(in_graph)):
				# Only mask if the graph package matches the given
				# atom (fixes bug #515230).
				return True
			return False
		return True

	def _iter_virt_update(self, pkg, atom_set):

		if self._depgraph._select_atoms_parent is not None and \
			self._depgraph._want_update_pkg(
				self._depgraph._select_atoms_parent, pkg):

			for new_child in self._depgraph._iter_similar_available(
				pkg, next(iter(atom_set))):

				if not self._depgraph._virt_deps_visible(
					new_child, ignore_use=True):
					continue

				if not self._visible(new_child, atom_set,
					avoid_slot_conflict=False,
					probe_virt_update=False):
					continue

				yield new_child

	def _have_virt_update(self, pkg, atom_set):

		for new_child in self._iter_virt_update(pkg, atom_set):
			if pkg < new_child:
				return True

		return False

	def aux_get(self, cpv, wants):
		metadata = self._cpv_pkg_map[cpv]._metadata
		return [metadata.get(x, "") for x in wants]

	def match(self, atom):
		return [pkg.cpv for pkg in self.match_pkgs(atom)]

def ambiguous_package_name(arg, atoms, root_config, spinner, myopts):

	if "--quiet" in myopts:
		writemsg("!!! The short ebuild name \"%s\" is ambiguous. Please specify\n" % arg, noiselevel=-1)
		writemsg("!!! one of the following fully-qualified ebuild names instead:\n\n", noiselevel=-1)
		for cp in sorted(set(portage.dep_getkey(atom) for atom in atoms)):
			writemsg("    " + colorize("INFORM", cp) + "\n", noiselevel=-1)
		return

	s = search(root_config, spinner, "--searchdesc" in myopts,
		"--quiet" not in myopts, "--usepkg" in myopts,
		"--usepkgonly" in myopts, search_index = False)
	null_cp = portage.dep_getkey(insert_category_into_atom(
		arg, "null"))
	cat, atom_pn = portage.catsplit(null_cp)
	s.searchkey = atom_pn
	for cp in sorted(set(portage.dep_getkey(atom) for atom in atoms)):
		s.addCP(cp)
	s.output()
	writemsg("!!! The short ebuild name \"%s\" is ambiguous. Please specify\n" % arg, noiselevel=-1)
	writemsg("!!! one of the above fully-qualified ebuild names instead.\n\n", noiselevel=-1)

def _spinner_start(spinner, myopts):
	if spinner is None:
		return
	if "--quiet" not in myopts and \
		("--pretend" in myopts or "--ask" in myopts or \
		"--tree" in myopts or "--verbose" in myopts):
		action = ""
		if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
			action = "fetched"
		elif "--buildpkgonly" in myopts:
			action = "built"
		else:
			action = "merged"
		if "--tree" in myopts and action != "fetched": # Tree doesn't work with fetching
			if "--unordered-display" in myopts:
				portage.writemsg_stdout("\n" + \
					darkgreen("These are the packages that " + \
					"would be %s:" % action) + "\n\n")
			else:
				portage.writemsg_stdout("\n" + \
					darkgreen("These are the packages that " + \
					"would be %s, in reverse order:" % action) + "\n\n")
		else:
			portage.writemsg_stdout("\n" + \
				darkgreen("These are the packages that " + \
				"would be %s, in order:" % action) + "\n\n")

	show_spinner = "--quiet" not in myopts and "--nodeps" not in myopts
	if not show_spinner:
		spinner.update = spinner.update_quiet

	if show_spinner:
		portage.writemsg_stdout("Calculating dependencies  ")

def _spinner_stop(spinner):
	if spinner is None or \
		spinner.update == spinner.update_quiet:
		return

	if spinner.update != spinner.update_basic:
		# update_basic is used for non-tty output,
		# so don't output backspaces in that case.
		portage.writemsg_stdout("\b\b")

	portage.writemsg_stdout("... done!\n")

def backtrack_depgraph(settings, trees, myopts, myparams,
	myaction, myfiles, spinner):
	"""
	Raises PackageSetNotFound if myfiles contains a missing package set.
	"""
	_spinner_start(spinner, myopts)
	try:
		return _backtrack_depgraph(settings, trees, myopts, myparams,
			myaction, myfiles, spinner)
	finally:
		_spinner_stop(spinner)


def _backtrack_depgraph(settings, trees, myopts, myparams, myaction, myfiles, spinner):

	debug = "--debug" in myopts
	mydepgraph = None
	max_retries = myopts.get('--backtrack', 10)
	max_depth = max(1, (max_retries + 1) // 2)
	allow_backtracking = max_retries > 0
	backtracker = Backtracker(max_depth)
	backtracked = 0

	frozen_config = _frozen_depgraph_config(settings, trees,
		myopts, myparams, spinner)

	while backtracker:

		if debug and mydepgraph is not None:
			writemsg_level(
				"\n\nbacktracking try %s \n\n" % \
				backtracked, noiselevel=-1, level=logging.DEBUG)
			mydepgraph.display_problems()

		backtrack_parameters = backtracker.get()
		if debug and backtrack_parameters.runtime_pkg_mask:
			writemsg_level(
				"\n\nruntime_pkg_mask: %s \n\n" %
				backtrack_parameters.runtime_pkg_mask,
				noiselevel=-1, level=logging.DEBUG)

		mydepgraph = depgraph(settings, trees, myopts, myparams, spinner,
			frozen_config=frozen_config,
			allow_backtracking=allow_backtracking,
			backtrack_parameters=backtrack_parameters)
		success, favorites = mydepgraph.select_files(myfiles)

		if success or mydepgraph.need_config_change():
			break
		elif not allow_backtracking:
			break
		elif backtracked >= max_retries:
			break
		elif mydepgraph.need_restart():
			backtracked += 1
			backtracker.feedback(mydepgraph.get_backtrack_infos())
		elif backtracker:
			backtracked += 1

	if not (success or mydepgraph.need_config_change()) and backtracked:

		if debug:
			writemsg_level(
				"\n\nbacktracking aborted after %s tries\n\n" % \
				backtracked, noiselevel=-1, level=logging.DEBUG)
			mydepgraph.display_problems()

		mydepgraph = depgraph(settings, trees, myopts, myparams, spinner,
			frozen_config=frozen_config,
			allow_backtracking=False,
			backtrack_parameters=backtracker.get_best_run())
		success, favorites = mydepgraph.select_files(myfiles)

	if not success and mydepgraph.autounmask_breakage_detected():
		if debug:
			writemsg_level(
				"\n\nautounmask breakage detected\n\n",
				noiselevel=-1, level=logging.DEBUG)
			mydepgraph.display_problems()
		myopts["--autounmask"] = "n"
		mydepgraph = depgraph(settings, trees, myopts, myparams, spinner,
			frozen_config=frozen_config, allow_backtracking=False)
		success, favorites = mydepgraph.select_files(myfiles)

	return (success, mydepgraph, favorites)


def resume_depgraph(settings, trees, mtimedb, myopts, myparams, spinner):
	"""
	Raises PackageSetNotFound if myfiles contains a missing package set.
	"""
	_spinner_start(spinner, myopts)
	try:
		return _resume_depgraph(settings, trees, mtimedb, myopts,
			myparams, spinner)
	finally:
		_spinner_stop(spinner)

def _resume_depgraph(settings, trees, mtimedb, myopts, myparams, spinner):
	"""
	Construct a depgraph for the given resume list. This will raise
	PackageNotFound or depgraph.UnsatisfiedResumeDep when necessary.
	TODO: Return reasons for dropped_tasks, for display/logging.
	@rtype: tuple
	@return: (success, depgraph, dropped_tasks)
	"""
	skip_masked = True
	skip_unsatisfied = True
	mergelist = mtimedb["resume"]["mergelist"]
	dropped_tasks = {}
	frozen_config = _frozen_depgraph_config(settings, trees,
		myopts, myparams, spinner)
	while True:
		mydepgraph = depgraph(settings, trees,
			myopts, myparams, spinner, frozen_config=frozen_config)
		try:
			success = mydepgraph._loadResumeCommand(mtimedb["resume"],
				skip_masked=skip_masked)
		except depgraph.UnsatisfiedResumeDep as e:
			if not skip_unsatisfied:
				raise

			graph = mydepgraph._dynamic_config.digraph
			unsatisfied_parents = {}
			traversed_nodes = set()
			unsatisfied_stack = [(dep.parent, dep.atom) for dep in e.value]
			while unsatisfied_stack:
				pkg, atom = unsatisfied_stack.pop()
				if atom is not None and \
					mydepgraph._select_pkg_from_installed(
					pkg.root, atom)[0] is not None:
					continue
				atoms = unsatisfied_parents.get(pkg)
				if atoms is None:
					atoms = []
					unsatisfied_parents[pkg] = atoms
				if atom is not None:
					atoms.append(atom)
				if pkg in traversed_nodes:
					continue
				traversed_nodes.add(pkg)

				# If this package was pulled in by a parent
				# package scheduled for merge, removing this
				# package may cause the the parent package's
				# dependency to become unsatisfied.
				for parent_node, atom in \
					mydepgraph._dynamic_config._parent_atoms.get(pkg, []):
					if not isinstance(parent_node, Package) \
						or parent_node.operation not in ("merge", "nomerge"):
						continue
					# We need to traverse all priorities here, in order to
					# ensure that a package with an unsatisfied depenedency
					# won't get pulled in, even indirectly via a soft
					# dependency.
					unsatisfied_stack.append((parent_node, atom))

			unsatisfied_tuples = frozenset(tuple(parent_node)
				for parent_node in unsatisfied_parents
				if isinstance(parent_node, Package))
			pruned_mergelist = []
			for x in mergelist:
				if isinstance(x, list) and \
					tuple(x) not in unsatisfied_tuples:
					pruned_mergelist.append(x)

			# If the mergelist doesn't shrink then this loop is infinite.
			if len(pruned_mergelist) == len(mergelist):
				# This happens if a package can't be dropped because
				# it's already installed, but it has unsatisfied PDEPEND.
				raise
			mergelist[:] = pruned_mergelist

			# Exclude installed packages that have been removed from the graph due
			# to failure to build/install runtime dependencies after the dependent
			# package has already been installed.
			dropped_tasks.update((pkg, atoms) for pkg, atoms in \
				unsatisfied_parents.items() if pkg.operation != "nomerge")

			del e, graph, traversed_nodes, \
				unsatisfied_parents, unsatisfied_stack
			continue
		else:
			break
	return (success, mydepgraph, dropped_tasks)

def get_mask_info(root_config, cpv, pkgsettings,
	db, pkg_type, built, installed, db_keys, myrepo = None, _pkg_use_enabled=None):
	try:
		metadata = dict(zip(db_keys,
			db.aux_get(cpv, db_keys, myrepo=myrepo)))
	except KeyError:
		metadata = None

	if metadata is None:
		mreasons = ["corruption"]
	else:
		eapi = metadata['EAPI']
		if not portage.eapi_is_supported(eapi):
			mreasons = ['EAPI %s' % eapi]
		else:
			pkg = Package(type_name=pkg_type, root_config=root_config,
				cpv=cpv, built=built, installed=installed, metadata=metadata)

			modified_use = None
			if _pkg_use_enabled is not None:
				modified_use = _pkg_use_enabled(pkg)

			mreasons = get_masking_status(pkg, pkgsettings, root_config, myrepo=myrepo, use=modified_use)

	return metadata, mreasons

def show_masked_packages(masked_packages):
	shown_licenses = set()
	shown_comments = set()
	# Maybe there is both an ebuild and a binary. Only
	# show one of them to avoid redundant appearance.
	shown_cpvs = set()
	have_eapi_mask = False
	for (root_config, pkgsettings, cpv, repo,
		metadata, mreasons) in masked_packages:
		output_cpv = cpv
		if repo:
			output_cpv += _repo_separator + repo
		if output_cpv in shown_cpvs:
			continue
		shown_cpvs.add(output_cpv)
		eapi_masked = metadata is not None and \
			not portage.eapi_is_supported(metadata["EAPI"])
		if eapi_masked:
			have_eapi_mask = True
			# When masked by EAPI, metadata is mostly useless since
			# it doesn't contain essential things like SLOT.
			metadata = None
		comment, filename = None, None
		if not eapi_masked and \
			"package.mask" in mreasons:
			comment, filename = \
				portage.getmaskingreason(
				cpv, metadata=metadata,
				settings=pkgsettings,
				portdb=root_config.trees["porttree"].dbapi,
				return_location=True)
		missing_licenses = []
		if not eapi_masked and metadata is not None:
			try:
				missing_licenses = \
					pkgsettings._getMissingLicenses(
						cpv, metadata)
			except portage.exception.InvalidDependString:
				# This will have already been reported
				# above via mreasons.
				pass

		writemsg("- "+output_cpv+" (masked by: "+", ".join(mreasons)+")\n",
			noiselevel=-1)

		if comment and comment not in shown_comments:
			writemsg(filename + ":\n" + comment + "\n",
				noiselevel=-1)
			shown_comments.add(comment)
		portdb = root_config.trees["porttree"].dbapi
		for l in missing_licenses:
			if l in shown_licenses:
				continue
			l_path = portdb.findLicensePath(l)
			if l_path is None:
				continue
			msg = ("A copy of the '%s' license" + \
			" is located at '%s'.\n\n") % (l, l_path)
			writemsg(msg, noiselevel=-1)
			shown_licenses.add(l)
	return have_eapi_mask

def show_mask_docs():
	writemsg("For more information, see the MASKED PACKAGES "
		"section in the emerge\n", noiselevel=-1)
	writemsg("man page or refer to the Gentoo Handbook.\n", noiselevel=-1)

def show_blocker_docs_link():
	writemsg("\nFor more information about " + bad("Blocked Packages") + ", please refer to the following\n", noiselevel=-1)
	writemsg("section of the Gentoo Linux x86 Handbook (architecture is irrelevant):\n\n", noiselevel=-1)
	writemsg("https://wiki.gentoo.org/wiki/Handbook:X86/Working/Portage#Blocked_packages\n\n", noiselevel=-1)

def get_masking_status(pkg, pkgsettings, root_config, myrepo=None, use=None):
	return [mreason.message for \
		mreason in _get_masking_status(pkg, pkgsettings, root_config, myrepo=myrepo, use=use)]

def _get_masking_status(pkg, pkgsettings, root_config, myrepo=None, use=None):
	mreasons = _getmaskingstatus(
		pkg, settings=pkgsettings,
		portdb=root_config.trees["porttree"].dbapi, myrepo=myrepo)

	if not pkg.installed:
		if not pkgsettings._accept_chost(pkg.cpv, pkg._metadata):
			mreasons.append(_MaskReason("CHOST", "CHOST: %s" % \
				pkg._metadata["CHOST"]))

	if pkg.invalid:
		for msgs in pkg.invalid.values():
			for msg in msgs:
				mreasons.append(
					_MaskReason("invalid", "invalid: %s" % (msg,)))

	if not pkg._metadata["SLOT"]:
		mreasons.append(
			_MaskReason("invalid", "SLOT: undefined"))

	return mreasons
