public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
From: "Michael Haubenwallner" <haubi@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Subject: [gentoo-commits] repo/proj/prefix:master commit in: sys-apps/portage/, sys-apps/portage/files/
Date: Mon, 25 Mar 2019 14:20:19 +0000 (UTC)	[thread overview]
Message-ID: <1553515292.beae731778eee1216ad4d94d52935617598320ae.haubi@gentoo> (raw)

commit:     beae731778eee1216ad4d94d52935617598320ae
Author:     Michael Haubenwallner <haubi <AT> gentoo <DOT> org>
AuthorDate: Fri Mar 22 16:30:51 2019 +0000
Commit:     Michael Haubenwallner <haubi <AT> gentoo <DOT> org>
CommitDate: Mon Mar 25 12:01:32 2019 +0000
URL:        https://gitweb.gentoo.org/repo/proj/prefix.git/commit/?id=beae7317

sys-apps/portage: replace prefix-chaining patch

All the prefix-chaining patches do not apply any more.  This has
switched over to FEATURES=stacked-prefix, and again switched over to
USE=prefix-stack.  Current prefix-portage is at FEATURES=stacked-prefix,
so there still is a patch necessary, although unconditionally now.
Bug: https://bugs.gentoo.org/658572
Package-Manager: Portage-2.3.62-prefix, Repoman-2.3.12

Signed-off-by: Michael Haubenwallner <haubi <AT> gentoo.org>

 .../files/portage-2.2.14-prefix-chaining.patch     | 873 -------------------
 .../files/portage-2.3.18-prefix-chaining.patch     | 927 ---------------------
 .../files/portage-2.3.40-prefix-chaining.patch     | 921 --------------------
 .../files/portage-2.3.62-prefix-stack.patch        |  80 ++
 .../files/portage-2.3.8-prefix-chaining.patch      | 927 ---------------------
 sys-apps/portage/metadata.xml                      |   1 -
 sys-apps/portage/portage-2.3.52.2.ebuild           |   6 +-
 sys-apps/portage/portage-2.3.55.1.ebuild           |   4 +-
 ...2.3.55.1.ebuild => portage-2.3.62-r00.1.ebuild} |   5 +-
 sys-apps/portage/portage-2.3.62.ebuild             |   4 +-
 10 files changed, 86 insertions(+), 3662 deletions(-)

diff --git a/sys-apps/portage/files/portage-2.2.14-prefix-chaining.patch b/sys-apps/portage/files/portage-2.2.14-prefix-chaining.patch
deleted file mode 100644
index 5c38795bb2..0000000000
--- a/sys-apps/portage/files/portage-2.2.14-prefix-chaining.patch
+++ /dev/null
@@ -1,873 +0,0 @@
-diff -ru prefix-portage-2.2.14.orig/bin/install-qa-check.d/05prefix prefix-portage-2.2.14/bin/install-qa-check.d/05prefix
---- prefix-portage-2.2.14.orig/bin/install-qa-check.d/05prefix	2014-09-28 19:31:20.000000000 +0200
-+++ prefix-portage-2.2.14/bin/install-qa-check.d/05prefix	2015-06-17 10:08:15.074682823 +0200
-@@ -79,16 +79,42 @@
- 		# unprefixed shebang, is the script directly in $PATH or an init
- 		# script?
- 		if [[ ":${PATH}:${EPREFIX}/etc/init.d:" == *":${fp}:"* ]] ; then
--			if [[ -e ${EROOT}${line[0]} || -e ${ED}${line[0]} ]] ; then
-+			all_epfs="$PORTAGE_READONLY_EPREFIXES:$EPREFIX:$EROOT:$ED"
-+			save_IFS=$IFS
-+			IFS=:
-+			epfs=( $all_epfs )
-+			IFS=$save_IFS
-+
-+			found=
-+			for x in "${epfs[@]}"; do
-+				[[ -z "${x}" ]] && continue
-+				check="${x}${line[0]}"
-+
-+				# might already contain a prefix
-+				if [[ "${line[0]}" == "${x}"* ]]; then
-+					check="${line[0]}"
-+				fi
-+
-+				if [[ -e ${check} ]]; then
-+					found="${check}"
-+				fi
-+			done
-+
-+			if [[ -n ${found} ]] ; then
- 				# is it unprefixed, but we can just fix it because a
- 				# prefixed variant exists
- 				eqawarn "prefixing shebang of ${fn#${D}}"
-+
-+				if [[ ${found} == "${ED}"* || ${found} == "${EROOT}"* ]]; then
-+					found="${EPREFIX}${line[0]}"
-+				fi
-+
- 				# statement is made idempotent on purpose, because
- 				# symlinks may point to the same target, and hence the
- 				# same real file may be sedded multiple times since we
- 				# read the shebangs in one go upfront for performance
- 				# reasons
--				sed -i -e '1s:^#! \?'"${line[0]}"':#!'"${EPREFIX}"${line[0]}':' "${rf}"
-+				sed -i -e '1s:^#! \?'"${line[0]}"':#!'"${found}"':' "${rf}"
- 				continue
- 			else
- 				# this is definitely wrong: script in $PATH and invalid shebang
-diff -ru prefix-portage-2.2.14.orig/bin/phase-helpers.sh prefix-portage-2.2.14/bin/phase-helpers.sh
---- prefix-portage-2.2.14.orig/bin/phase-helpers.sh	2014-09-28 19:12:31.000000000 +0200
-+++ prefix-portage-2.2.14/bin/phase-helpers.sh	2015-06-17 10:24:28.997164214 +0200
-@@ -758,6 +758,10 @@
- 		"${PORTAGE_BIN_PATH}/ebuild-helpers/portageq" has_version "${eroot}" "${atom}"
- 	fi
- 	local retval=$?
-+	if [[ ${retval} -eq 1 && -n ${READONLY_EPREFIX} ]]; then
-+		${SHELL} -c "EPREFIX='${READONLY_EPREFIX%:*}' EPYTHON= '${READONLY_EPREFIX%:*}'/usr/lib/portage/bin/portageq has_version '${READONLY_EPREFIX%:*}' '${atom}'"
-+		retval=$?
-+	fi
- 	case "${retval}" in
- 		0|1)
- 			return ${retval}
-@@ -817,6 +821,10 @@
- 		"${PORTAGE_BIN_PATH}/ebuild-helpers/portageq" best_version "${eroot}" "${atom}"
- 	fi
- 	local retval=$?
-+	if [[ ${retval} -eq 1 && -n ${READONLY_EPREFIX} ]]; then
-+		${SHELL} -c "EPREFIX='${READONLY_EPREFIX%:*}' EPYTHON= '${READONLY_EPREFIX%:*}'/usr/lib/portage/bin/portageq best_version '${READONLY_EPREFIX%:*}' '${atom}'"
-+		retval=$?
-+	fi
- 	case "${retval}" in
- 		0|1)
- 			return ${retval}
-@@ -846,6 +854,10 @@
- 			output=$("${PORTAGE_BIN_PATH}/ebuild-helpers/portageq" master_repositories "${EROOT}" "${repository}")
- 		fi
- 		retval=$?
-+		if [[ ${retval} -eq 1 && -n ${READONLY_EPREFIX} ]]; then
-+			output=$(${SHELL} -c "EPREFIX='${READONLY_EPREFIX%:*}' EPYTHON= '${READONLY_EPREFIX%:*}'/usr/lib/portage/bin/portageq master_repositories '${READONLY_EPREFIX%:*}' '${repository}'")
-+			retval=$?
-+		fi
- 		[[ -n ${output} ]] && echo "${output}"
- 		case "${retval}" in
- 			0|1)
-@@ -877,6 +889,10 @@
- 			output=$("${PORTAGE_BIN_PATH}/ebuild-helpers/portageq" get_repo_path "${EROOT}" "${repository}")
- 		fi
- 		retval=$?
-+		if [[ ${retval} -eq 1 && -n ${READONLY_EPREFIX} ]]; then
-+			output=$(${SHELL} -c "EPREFIX='${READONLY_EPREFIX%:*}' EPYTHON= '${READONLY_EPREFIX%:*}'/usr/lib/portage/bin/portageq repository_path '${READONLY_EPREFIX%:*}' '${repository}'")
-+			retval=$?
-+		fi
- 		[[ -n ${output} ]] && echo "${output}"
- 		case "${retval}" in
- 			0|1)
-@@ -907,6 +923,10 @@
- 			output=$("${PORTAGE_BIN_PATH}/ebuild-helpers/portageq" available_eclasses "${EROOT}" "${repository}")
- 		fi
- 		retval=$?
-+		if [[ ${retval} -eq 1 && -n ${READONLY_EPREFIX} ]]; then
-+			output=$(${SHELL} -c "EPREFIX='${READONLY_EPREFIX%:*}' EPYTHON= '${READONLY_EPREFIX%:*}'/usr/lib/portage/bin/portageq available_eclasses '${READONLY_EPREFIX%:*}' '${repository}'")
-+			retval=$?
-+		fi
- 		[[ -n ${output} ]] && echo "${output}"
- 		case "${retval}" in
- 			0|1)
-@@ -937,6 +957,10 @@
- 		else
- 			output=$("${PORTAGE_BIN_PATH}/ebuild-helpers/portageq" eclass_path "${EROOT}" "${repository}" "${eclass}")
- 		fi
-+		if [[ ${retval} -eq 1 && -n ${READONLY_EPREFIX} ]]; then
-+			output=$(${SHELL} -c "EPREFIX='${READONLY_EPREFIX%:*}' EPYTHON= '${READONLY_EPREFIX%:*}'/usr/lib/portage/bin/portageq eclass_path '${READONLY_EPREFIX%:*}' '${repository}' '${eclass}'")
-+			retval=$?
-+		fi
- 		retval=$?
- 		[[ -n ${output} ]] && echo "${output}"
- 		case "${retval}" in
-@@ -968,6 +992,10 @@
- 		else
- 			output=$("${PORTAGE_BIN_PATH}/ebuild-helpers/portageq" license_path "${EROOT}" "${repository}" "${license}")
- 		fi
-+		if [[ ${retval} -eq 1 && -n ${READONLY_EPREFIX} ]]; then
-+			output=(${SHELL} -c "EPREFIX='${READONLY_EPREFIX%:*}' EPYTHON= '${READONLY_EPREFIX%:*}'/usr/lib/portage/bin/portageq license_path '${READONLY_EPREFIX%:*}' '${repository}' '${license}'")
-+			retval=$?
-+		fi
- 		retval=$?
- 		[[ -n ${output} ]] && echo "${output}"
- 		case "${retval}" in
-Only in prefix-portage-2.2.14/bin: phase-helpers.sh.orig
-diff -ru prefix-portage-2.2.14.orig/pym/_emerge/actions.py prefix-portage-2.2.14/pym/_emerge/actions.py
---- prefix-portage-2.2.14.orig/pym/_emerge/actions.py	2014-10-02 20:48:26.000000000 +0200
-+++ prefix-portage-2.2.14/pym/_emerge/actions.py	2015-06-17 10:24:28.997164214 +0200
-@@ -38,7 +38,7 @@
- from portage import shutil
- from portage import eapi_is_supported, _encodings, _unicode_decode
- from portage.cache.cache_errors import CacheError
--from portage.const import EPREFIX
-+from portage.const import EPREFIX, BPREFIX
- from portage.const import GLOBAL_CONFIG_PATH, VCS_DIRS, _DEPCLEAN_LIB_CHECK_DEFAULT
- from portage.const import SUPPORTED_BINPKG_FORMATS, TIMESTAMP_FORMAT
- from portage.dbapi.dep_expand import dep_expand
-@@ -62,6 +62,7 @@
- from portage.util._async.run_main_scheduler import run_main_scheduler
- from portage.util._async.SchedulerInterface import SchedulerInterface
- from portage.util._eventloop.global_event_loop import global_event_loop
-+from portage.util._path import exists_raise_eaccess
- from portage._global_updates import _global_updates
- 
- from _emerge.clear_caches import clear_caches
-@@ -2629,7 +2630,8 @@
- 				out.eerror(line)
- 			return exitcode
- 	elif repo.sync_type == "cvs":
--		if not os.path.exists(EPREFIX + "/usr/bin/cvs"):
-+		cvs_bin = portage.process.find_binary("cvs")
-+		if cvs_bin is None:
- 			print("!!! %s/usr/bin/cvs does not exist, so CVS support is disabled." % (EPREFIX))
- 			print("!!! Type \"emerge %s\" to enable CVS support." % portage.const.CVS_PACKAGE_ATOM)
- 			return os.EX_UNAVAILABLE
-@@ -2697,6 +2699,13 @@
- 			writemsg_level(" %s spawn failed of %s\n" % (bad("*"), postsync,),
- 				level=logging.ERROR, noiselevel=-1)
- 
-+	postsync = os.path.join(BPREFIX, portage.USER_CONFIG_PATH, "bin", "post_sync")
-+	if os.access(postsync, os.X_OK):
-+		retval = portage.process.spawn([postsync, dosyncuri], env=settings.environ())
-+		if retval != os.EX_OK:
-+			writemsg_level(" %s spawn failed of %s\n" % (bad("*"), postsync,),
-+				level=logging.ERROR, noiselevel=-1)
-+
- 	return os.EX_OK
- 
- def action_uninstall(settings, trees, ldpath_mtimes,
-@@ -3413,6 +3422,9 @@
- 	if portage.const.EPREFIX:
- 		global_config_path = os.path.join(portage.const.EPREFIX,
- 				portage.const.GLOBAL_CONFIG_PATH.lstrip(os.sep))
-+		if not exists_raise_eaccess(global_config_path) and portage.const.BPREFIX:
-+			global_config_path = os.path.join(portage.const.BPREFIX,
-+                    portage.const.GLOBAL_CONFIG_PATH.lstrip(os.sep))
- 	msg.append("        This usually means that '%s'" % \
- 		(os.path.join(global_config_path, "sets/portage.conf"),))
- 	msg.append("        is missing or corrupt.")
-Only in prefix-portage-2.2.14/pym/_emerge: actions.py.orig
-diff -ru prefix-portage-2.2.14.orig/pym/_emerge/depgraph.py prefix-portage-2.2.14/pym/_emerge/depgraph.py
---- prefix-portage-2.2.14.orig/pym/_emerge/depgraph.py	2014-11-12 18:26:12.000000000 +0100
-+++ prefix-portage-2.2.14/pym/_emerge/depgraph.py	2015-06-17 10:19:41.254082296 +0200
-@@ -2743,23 +2743,24 @@
- 				edepend["HDEPEND"] = ""
- 
- 		deps = (
--			(depend_root, edepend["DEPEND"],
-+			(depend_root, "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._frozen_config._running_root.root, "HDEPEND",
- 				self._priority(buildtime=True,
- 				optional=(pkg.built or ignore_hdepend_deps),
- 				ignored=ignore_hdepend_deps)),
--			(myroot, edepend["RDEPEND"],
-+			(myroot, "RDEPEND",
- 				self._priority(runtime=True)),
--			(myroot, edepend["PDEPEND"],
-+			(myroot, "PDEPEND",
- 				self._priority(runtime_post=True))
- 		)
- 
- 		debug = "--debug" in self._frozen_config.myopts
- 
--		for dep_root, dep_string, dep_priority in deps:
-+		for dep_root, dep_type, dep_priority in deps:
-+				dep_string = edepend[dep_type]
- 				if not dep_string:
- 					continue
- 				if debug:
-@@ -2797,7 +2798,7 @@
- 
- 				try:
- 					dep_string = list(self._queue_disjunctive_deps(
--						pkg, dep_root, dep_priority, dep_string))
-+						pkg, dep_root, dep_priority, dep_string, dep_type))
- 				except portage.exception.InvalidDependString as e:
- 					if pkg.installed:
- 						self._dynamic_config._masked_installed.add(pkg)
-@@ -2812,14 +2813,14 @@
- 
- 				if not self._add_pkg_dep_string(
- 					pkg, dep_root, dep_priority, dep_string,
--					allow_unsatisfied):
-+					allow_unsatisfied, dep_type):
- 					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):
-+		allow_unsatisfied, dep_type=None):
- 		_autounmask_backup = self._dynamic_config._autounmask
- 		if dep_priority.optional or dep_priority.ignored:
- 			# Temporarily disable autounmask for deps that
-@@ -2828,7 +2829,7 @@
- 		try:
- 			return self._wrapped_add_pkg_dep_string(
- 				pkg, dep_root, dep_priority, dep_string,
--				allow_unsatisfied)
-+				allow_unsatisfied, dep_type)
- 		finally:
- 			self._dynamic_config._autounmask = _autounmask_backup
- 
-@@ -2864,7 +2865,7 @@
- 			not slot_operator_rebuild
- 
- 	def _wrapped_add_pkg_dep_string(self, pkg, dep_root, dep_priority,
--		dep_string, allow_unsatisfied):
-+		dep_string, allow_unsatisfied, dep_type=None):
- 		if isinstance(pkg.depth, int):
- 			depth = pkg.depth + 1
- 		else:
-@@ -2888,7 +2889,7 @@
- 		try:
- 			selected_atoms = self._select_atoms(dep_root,
- 				dep_string, myuse=self._pkg_use_enabled(pkg), parent=pkg,
--				strict=strict, priority=dep_priority)
-+				strict=strict, priority=dep_priority, dep_type=dep_type)
- 		except portage.exception.InvalidDependString:
- 			if pkg.installed:
- 				self._dynamic_config._masked_installed.add(pkg)
-@@ -3186,7 +3187,7 @@
- 					child_pkgs.sort()
- 				yield (atom, child_pkgs[-1])
- 
--	def _queue_disjunctive_deps(self, pkg, dep_root, dep_priority, dep_struct):
-+	def _queue_disjunctive_deps(self, pkg, dep_root, dep_priority, dep_struct, dep_type=None):
- 		"""
- 		Queue disjunctive (virtual and ||) deps in self._dynamic_config._dep_disjunctive_stack.
- 		Yields non-disjunctive deps. Raises InvalidDependString when
-@@ -3195,33 +3196,33 @@
- 		for x in dep_struct:
- 			if isinstance(x, list):
- 				if x and x[0] == "||":
--					self._queue_disjunction(pkg, dep_root, dep_priority, [x])
-+					self._queue_disjunction(pkg, dep_root, dep_priority, [x], dep_type)
- 				else:
- 					for y in self._queue_disjunctive_deps(
--						pkg, dep_root, dep_priority, x):
-+						pkg, dep_root, dep_priority, x, dep_type):
- 						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])
-+					self._queue_disjunction(pkg, dep_root, dep_priority, [x], dep_type)
- 				else:
- 					yield x
- 
--	def _queue_disjunction(self, pkg, dep_root, dep_priority, dep_struct):
-+	def _queue_disjunction(self, pkg, dep_root, dep_priority, dep_struct, dep_type=None):
- 		self._dynamic_config._dep_disjunctive_stack.append(
--			(pkg, dep_root, dep_priority, dep_struct))
-+			(pkg, dep_root, dep_priority, dep_struct, dep_type))
- 
- 	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 = \
-+		pkg, dep_root, dep_priority, dep_struct, dep_type = \
- 			self._dynamic_config._dep_disjunctive_stack.pop()
- 		if not self._add_pkg_dep_string(
--			pkg, dep_root, dep_priority, dep_struct, allow_unsatisfied):
-+			pkg, dep_root, dep_priority, dep_struct, allow_unsatisfied, dep_type):
- 			return 0
- 		return 1
- 
-@@ -4030,7 +4031,7 @@
- 			**portage._native_kwargs(kwargs))
- 
- 	def _select_atoms_highest_available(self, root, depstring,
--		myuse=None, parent=None, strict=True, trees=None, priority=None):
-+		myuse=None, parent=None, strict=True, trees=None, priority=None, dep_type=None):
- 		"""This will raise InvalidDependString if necessary. If trees is
- 		None then self._dynamic_config._filtered_trees is used."""
- 
-@@ -4053,6 +4054,13 @@
- 		pkgsettings = self._frozen_config.pkgsettings[root]
- 		if trees is None:
- 			trees = self._dynamic_config._filtered_trees
-+
-+		# this one is needed to guarantee good readonly root
-+		# resolution display in the merge list. required since
-+		# parent (below) can be None
-+		trees[root]["disp_parent"] = parent
-+
-+
- 		mytrees = trees[root]
- 		atom_graph = digraph()
- 		if True:
-@@ -4081,7 +4089,7 @@
- 
- 				mycheck = portage.dep_check(depstring, None,
- 					pkgsettings, myuse=myuse,
--					myroot=root, trees=trees)
-+					myroot=root, trees=trees, dep_type=dep_type)
- 			finally:
- 				# restore state
- 				self._dynamic_config._autounmask = _autounmask_backup
-@@ -4152,6 +4160,7 @@
- 							continue
- 						node_stack.append((child_node, node, child_atom))
- 
-+		trees[root].pop("disp_parent")
- 		return selected_atoms
- 
- 	def _expand_virt_from_graph(self, root, atom):
-diff -ru prefix-portage-2.2.14.orig/pym/_emerge/resolver/output.py prefix-portage-2.2.14/pym/_emerge/resolver/output.py
---- prefix-portage-2.2.14.orig/pym/_emerge/resolver/output.py	2014-05-06 21:32:08.000000000 +0200
-+++ prefix-portage-2.2.14/pym/_emerge/resolver/output.py	2015-06-17 10:24:28.920497614 +0200
-@@ -22,11 +22,12 @@
- from portage.package.ebuild.config import _get_feature_flags
- from portage.package.ebuild._spawn_nofetch import spawn_nofetch
- from portage.output import ( blue, colorize, create_color_func,
--	darkblue, darkgreen, green, nc_len, teal)
-+	darkblue, darkgreen, green, nc_len, teal, yellow, turquoise)
- bad = create_color_func("BAD")
- from portage._sets.base import InternalPackageSet
- from portage.util import writemsg_stdout
- from portage.versions import best, cpv_getversion
-+from portage.dep.dep_check import ro_selected
- 
- from _emerge.Blocker import Blocker
- from _emerge.create_world_atom import create_world_atom
-@@ -556,6 +557,42 @@
- 			writemsg_stdout("%s\n" % (pkg,), noiselevel=-1)
- 		return
- 
-+	def print_readonly_prefix(self):
-+		"""Performs the actual output printing for the readonly prefix
-+		information stuff
-+		"""
-+		out = sys.stdout
-+
-+        # print readonly selected packages
-+		if len(ro_selected) > 0:
-+			out.write("\n%s\n\n" % (darkgreen("Packages resolved from readonly installations:")))
-+
-+		ro_mismatch_warning = False
-+		ro_dupcheck = []
-+		for x in ro_selected:
-+			tmp_type = x["type"].replace("END","")
-+			while len(tmp_type) < 4:
-+				tmp_type += " "
-+			if x["parent"] and str(x["atom"]) not in ro_dupcheck:
-+				out.write("[%s %s] %s %s %s (%s by %s)" % (teal("readonly"),
-+					green(tmp_type), green(str(x["matches"][0])), yellow("from"),
-+					blue(x["ro_root"]), turquoise(str(x["atom"])), green(x["parent"].cpv)))
-+
-+				ro_dupcheck.append(str(x["atom"]))
-+
-+				if x["host_mismatch"]:
-+					ro_mismatch_warning = True
-+					out.write(" %s\n" % (red("**")))
-+				else:
-+					out.write("\n")
-+
-+		if ro_mismatch_warning:
-+			out.write("\n%s:" % (red("**")))
-+			out.write(yellow(" WARNING: packages marked with ** have been resolved as a\n"))
-+			out.write(yellow("    runtime dependency, but the CHOST variable for the parent\n"))
-+			out.write(yellow("    and dependency package don't match. This could cause link\n"))
-+			out.write(yellow("    errors. It is recommended to use RDEPEND READONLY_EPREFIX's\n"))
-+			out.write(yellow("    only with matching CHOST portage instances.\n"))
- 
- 	def print_verbose(self, show_repos):
- 		"""Prints the verbose output to std_out
-@@ -907,6 +944,7 @@
- 		# now finally print out the messages
- 		self.print_messages(show_repos)
- 		self.print_blockers()
-+		self.print_readonly_prefix()
- 		if self.conf.verbosity == 3:
- 			self.print_verbose(show_repos)
- 		for pkg, pkg_info in self.restrict_fetch_list.items():
-diff -ru prefix-portage-2.2.14.orig/pym/portage/const.py prefix-portage-2.2.14/pym/portage/const.py
---- prefix-portage-2.2.14.orig/pym/portage/const.py	2014-11-12 18:26:12.000000000 +0100
-+++ prefix-portage-2.2.14/pym/portage/const.py	2015-06-17 10:24:28.963830910 +0200
-@@ -187,6 +187,7 @@
- 	"notitles",
- 	"parallel-fetch",
- 	"parallel-install",
-+	"prefix-chaining",
- 	"prelink-checksums",
- 	"preserve-libs",
- 	"protect-owned",
-@@ -265,6 +266,11 @@
- #EPREFIX = ""
- # END PREFIX LOCAL
- 
-+BPREFIX = EPREFIX
-+
-+# --prefix commandline arg always rules, ends up in os.environ["EPREFIX"]
-+if "EPREFIX" in os.environ:
-+    os.environ["PORTAGE_OVERRIDE_EPREFIX"] = os.environ["EPREFIX"]
- # pick up EPREFIX from the environment if set
- if "PORTAGE_OVERRIDE_EPREFIX" in os.environ:
- 	EPREFIX = os.environ["PORTAGE_OVERRIDE_EPREFIX"]
-Only in prefix-portage-2.2.14/pym/portage: const.py.orig
-diff -ru prefix-portage-2.2.14.orig/pym/portage/dbapi/vartree.py prefix-portage-2.2.14/pym/portage/dbapi/vartree.py
---- prefix-portage-2.2.14.orig/pym/portage/dbapi/vartree.py	2014-11-12 18:28:33.000000000 +0100
-+++ prefix-portage-2.2.14/pym/portage/dbapi/vartree.py	2015-06-17 10:24:28.973830901 +0200
-@@ -184,8 +184,19 @@
- 		self._counter_path = os.path.join(self._eroot,
- 			CACHE_PATH, "counter")
- 
--		self._plib_registry = PreservedLibsRegistry(settings["ROOT"],
--			os.path.join(self._eroot, PRIVATE_PATH, "preserved_libs_registry"))
-+		plibreg_path = os.path.join(self._eroot, PRIVATE_PATH, "preserved_libs_registry")
-+
-+		if vartree:
-+			self._kill_eprefix = vartree._kill_eprefix
-+		else:
-+			self._kill_eprefix = False
-+
-+		if self._kill_eprefix:
-+			self._aux_cache_filename = self._aux_cache_filename.replace(EPREFIX, "")
-+			self._counter_path = self._counter_path.replace(EPREFIX, "")
-+			plibreg_path = plibreg_path.replace(EPREFIX, "")
-+
-+		self._plib_registry = PreservedLibsRegistry(settings["ROOT"], plibreg_path)
- 		self._linkmap = LinkageMap(self)
- 		chost = self.settings.get('CHOST')
- 		if not chost:
-@@ -215,6 +226,9 @@
- 		# This is an optimized hotspot, so don't use unicode-wrapped
- 		# os module and don't use os.path.join().
- 		rValue = self._eroot + VDB_PATH + _os.sep + mykey
-+		if self._kill_eprefix:
-+			rValue = rValue.replace(EPREFIX, "")
-+
- 		if filename is not None:
- 			# If filename is always relative, we can do just
- 			# rValue += _os.sep + filename
-@@ -440,6 +454,9 @@
- 		returnme = []
- 		basepath = os.path.join(self._eroot, VDB_PATH) + os.path.sep
- 
-+		if self._kill_eprefix:
-+			basepath = os.path.join(self.root, basepath.replace(EPREFIX, ""))
-+
- 		if use_cache:
- 			from portage import listdir
- 		else:
-@@ -530,11 +547,17 @@
- 				del self.matchcache[mycat]
- 			return list(self._iter_match(mydep,
- 				self.cp_list(mydep.cp, use_cache=use_cache)))
-+
-+		_tmp_path = os.path.join(self._eroot, VDB_PATH, mycat)
-+
-+		if self._kill_eprefix:
-+			_tmp_path = _tmp_path.replace(EPREFIX, "")
-+
- 		try:
- 			if sys.hexversion >= 0x3030000:
--				curmtime = os.stat(os.path.join(self._eroot, VDB_PATH, mycat)).st_mtime_ns
-+				curmtime = os.stat(_tmp_path).st_mtime_ns
- 			else:
--				curmtime = os.stat(os.path.join(self._eroot, VDB_PATH, mycat)).st_mtime
-+				curmtime = os.stat(_tmp_path).st_mtime
- 		except (IOError, OSError):
- 			curmtime=0
- 
-@@ -1339,7 +1362,7 @@
- class vartree(object):
- 	"this tree will scan a var/db/pkg database located at root (passed to init)"
- 	def __init__(self, root=None, virtual=DeprecationWarning, categories=None,
--		settings=None):
-+		settings=None, kill_eprefix=None):
- 
- 		if settings is None:
- 			settings = portage.settings
-@@ -1357,6 +1380,7 @@
- 				" constructor is unused",
- 				DeprecationWarning, stacklevel=2)
- 
-+		self._kill_eprefix = kill_eprefix
- 		self.settings = settings
- 		self.dbapi = vardbapi(settings=settings, vartree=self)
- 		self.populated = 1
-Only in prefix-portage-2.2.14/pym/portage/dbapi: vartree.py.orig
-diff -ru prefix-portage-2.2.14.orig/pym/portage/dep/dep_check.py prefix-portage-2.2.14/pym/portage/dep/dep_check.py
---- prefix-portage-2.2.14.orig/pym/portage/dep/dep_check.py	2014-09-28 19:12:31.000000000 +0200
-+++ prefix-portage-2.2.14/pym/portage/dep/dep_check.py	2015-06-17 10:24:28.973830901 +0200
-@@ -247,6 +247,95 @@
- 	__slots__ = ('atoms', 'slot_map', 'cp_map', 'all_available',
- 		'all_installed_slots')
- 
-+ro_trees={}
-+ro_vartrees={}
-+ro_selected=[]
-+
-+def dep_match_readonly_roots(settings, atom, dep_type, parent=None):
-+   if len(ro_trees) < len(settings.readonly_prefixes):
-+       # MDUFT: create additional vartrees for every readonly root here.
-+       # the ro_vartrees instances are created below as they are needed to
-+       # avoid reading vartrees of portage instances which aren't required
-+       # while resolving this dependencies.
-+       for type in ("DEPEND","RDEPEND", "PDEPEND"):
-+           ro_trees[type] = []
-+
-+           for ro_root, ro_dep_types in settings.readonly_prefixes.items():
-+               if type in ro_dep_types:
-+                   ro_trees[type].append(ro_root)
-+
-+   if len(ro_trees) == 0:
-+       return []
-+
-+   matches = []
-+
-+   for ro_root in ro_trees[dep_type]:
-+       if not ro_vartrees.has_key(ro_root):
-+           # target_root=ro_root ok? or should it be the real target_root?
-+           _tmp_settings = portage.config(config_root=ro_root, target_root=ro_root,
-+               config_incrementals=portage.const.INCREMENTALS)
-+
-+           ro_vartrees[ro_root] = portage.vartree(root=ro_root,
-+               categories=_tmp_settings.categories,
-+               settings=_tmp_settings, kill_eprefix=True)
-+
-+       ro_matches = ro_vartrees[ro_root].dbapi.match(atom)
-+
-+       if ro_matches:
-+           ro_host_mismatch = False
-+           if dep_type is "RDEPEND":
-+               # we need to assure binary compatability, so it needs to be
-+               # the same CHOST! But how? for now i cannot do anything...
-+               if parent and parent.metadata["CHOST"] != ro_vartrees[ro_root].settings.get("CHOST", ""):
-+                   # provocate a big fat warning in the list of external packages.
-+                   ro_host_mismatch = True
-+               pass
-+
-+           matches.append({ "ro_root": ro_root, "atom": atom, "matches": ro_matches,
-+               "type": dep_type, "parent": parent, "host_mismatch": ro_host_mismatch })
-+
-+   return matches
-+
-+def dep_wordreduce_readonly(reduced, unreduced, settings, dep_type, parent):
-+   for mypos, token in enumerate(unreduced):
-+       # recurse if it's a list.
-+       if isinstance(reduced[mypos], list):
-+           reduced[mypos] = dep_wordreduce_readonly(reduced[mypos],
-+               unreduced[mypos], settings, dep_type, parent)
-+
-+       # do nothing if it's satisfied already.
-+       elif not reduced[mypos]:
-+           ro_matches = dep_match_readonly_roots(settings, unreduced[mypos], dep_type, parent)
-+
-+           if ro_matches:
-+               # TODO: select a match if there are more than one?
-+               # for now, the first match is taken...
-+               ro_selected.append(ro_matches[0])
-+               reduced[mypos] = True
-+
-+   return reduced
-+
-+# this may be better placed somewhere else, but i put it here for now, to
-+# keep all functions in the patch on one big heap.
-+def readonly_pathmatch_any(settings, path):
-+   path = path.lstrip('/')
-+   # first try locally, and match that if it exists.
-+   if os.path.exists(os.path.join(EPREFIX,path)):
-+       return os.path.join(EPREFIX,path)
-+
-+   # after that try all readonly roots where DEPEND is allowed. this makes
-+   # sure that executing binaries is possible from there.
-+   for ro_root, ro_deps in settings.readonly_roots.items():
-+       if "DEPEND" in ro_deps:
-+           print(" --- checking %s --- " % (os.path.join(ro_root,path)))
-+           if os.path.exists(os.path.join(ro_root,path)):
-+               return os.path.join(ro_root,path)
-+           break
-+
-+   # as a fallback make the string the same as it was originally.
-+   # even though this path doesn't exist.
-+   return os.path.join(EPREFIX,path)
-+
- def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None):
- 	"""
- 	Takes an unreduced and reduced deplist and removes satisfied dependencies.
-@@ -567,7 +656,7 @@
- 	assert(False) # This point should not be reachable
- 
- def dep_check(depstring, mydbapi, mysettings, use="yes", mode=None, myuse=None,
--	use_cache=1, use_binaries=0, myroot=None, trees=None):
-+	use_cache=1, use_binaries=0, myroot=None, trees=None, dep_type=None):
- 	"""
- 	Takes a depend string, parses it, and selects atoms.
- 	The myroot parameter is unused (use mysettings['EROOT'] instead).
-@@ -663,6 +752,14 @@
- 	writemsg("mysplit:  %s\n" % (mysplit), 1)
- 	writemsg("mysplit2: %s\n" % (mysplit2), 1)
- 
-+	if dep_type is not None:
-+		mysplit2=dep_wordreduce_readonly(unreduced=mysplit[:],
-+				reduced=mysplit2, settings=mysettings,
-+				dep_type=dep_type, parent=trees[myroot].get("disp_parent"))
-+
-+		writemsg("\n", 1)
-+		writemsg("mysplit2 after readonly reduce: %s\n" % (mysplit2), 1)
-+
- 	selected_atoms = dep_zapdeps(mysplit, mysplit2, myroot,
- 		use_binaries=use_binaries, trees=trees)
- 
-Only in prefix-portage-2.2.14/pym/portage/dep: dep_check.py.orig
-diff -ru prefix-portage-2.2.14.orig/pym/portage/package/ebuild/_config/LocationsManager.py prefix-portage-2.2.14/pym/portage/package/ebuild/_config/LocationsManager.py
---- prefix-portage-2.2.14.orig/pym/portage/package/ebuild/_config/LocationsManager.py	2014-02-06 21:49:32.000000000 +0100
-+++ prefix-portage-2.2.14/pym/portage/package/ebuild/_config/LocationsManager.py	2015-06-17 10:24:28.983830892 +0200
-@@ -285,6 +285,9 @@
- 		if portage.const.EPREFIX:
- 			self.global_config_path = os.path.join(portage.const.EPREFIX,
- 				GLOBAL_CONFIG_PATH.lstrip(os.sep))
-+			if not exists_raise_eaccess(self.global_config_path) and portage.const.BPREFIX:
-+				self.global_config_path = os.path.join(portage.const.BPREFIX,
-+					GLOBAL_CONFIG_PATH.lstrip(os.sep))
- 
- 	def set_port_dirs(self, portdir, portdir_overlay):
- 		self.portdir = portdir
-diff -ru prefix-portage-2.2.14.orig/pym/portage/package/ebuild/config.py prefix-portage-2.2.14/pym/portage/package/ebuild/config.py
---- prefix-portage-2.2.14.orig/pym/portage/package/ebuild/config.py	2014-09-28 19:12:31.000000000 +0200
-+++ prefix-portage-2.2.14/pym/portage/package/ebuild/config.py	2015-06-17 10:24:28.983830892 +0200
-@@ -298,6 +298,7 @@
- 			self.features = features_set(self)
- 			self.features._features = copy.deepcopy(clone.features._features)
- 			self._features_overrides = copy.deepcopy(clone._features_overrides)
-+			self.readonly_prefixes = copy.deepcopy(clone.readonly_prefixes)
- 
- 			#Strictly speaking _license_manager is not immutable. Users need to ensure that
- 			#extract_global_changes() is called right after __init__ (if at all).
-@@ -894,6 +895,63 @@
- 
- 			self._validate_commands()
- 
-+			# expand READONLY_EPREFIX to a list of all readonly portage instances
-+			# all the way down to the last one. beware that ATM a deeper instance
-+			# in the chain can provide more than the toplevel! this means that
-+			# if you only inherit DEPENDS from one instance, that instance may
-+			# inherit RDEPENDs from another one, making the top-level instance
-+			# inherit RDEPENDs from there too - even if the intermediate prefix
-+			# does not do this.
-+			self.readonly_prefixes = {}
-+			ro_cfg_root = config_root
-+			ro_widest_depset = set(['DEPEND', 'RDEPEND', 'PDEPEND'])
-+
-+			while ro_cfg_root:
-+				ro_make_conf_paths = [
-+					os.path.join(ro_cfg_root, 'etc', 'make.conf'),
-+					os.path.join(ro_cfg_root, MAKE_CONF_FILE)
-+				]
-+				try:
-+					if os.path.samefile(*ro_make_conf_paths):
-+						ro_make_conf_paths.pop()
-+				except OSError:
-+					pass
-+
-+				ro_cfg_root = None
-+				for ro_make_conf in ro_make_conf_paths:
-+					if not os.path.exists(ro_make_conf):
-+						continue
-+
-+					ro_cfg = getconfig(ro_make_conf, tolerant=True, allow_sourcing=True)
-+					if not ro_cfg.has_key("READONLY_EPREFIX"):
-+						continue
-+
-+					if not ro_cfg["READONLY_EPREFIX"].find(":"):
-+						raise portage.exception.InvalidReadonlyERoot("ERROR: malformed READONLY_EPREFIX in %s" % (ro_make_conf))
-+
-+					if ro_cfg_root is not None:
-+						raise portage.exception.InvalidReadonlyERoot("ERROR: duplicate READONLY_EPREFIX in %s and %s" % tuple(ro_make_conf_paths))
-+
-+					(ro_cfg_root,ro_cfg_root_deps) = ro_cfg["READONLY_EPREFIX"].rsplit(":",1)
-+
-+					if not os.path.exists(ro_cfg_root):
-+						raise portage.exception.InvalidReadonlyERoot("ERROR: malformed READONLY_EPREFIX in %s: %s does not exist!" % (ro_make_conf, ro_cfg_root))
-+
-+					if os.path.samefile(ro_cfg_root, config_root):
-+						raise portage.exception.InvalidReadonlyERoot("ERROR: cannot add this instance (%s) as READONLY_EPREFIX in %s." % (ro_cfg_root, ro_make_conf))
-+
-+					if self.readonly_prefixes.has_key(ro_cfg_root):
-+						raise portage.exception.InvalidReadonlyERoot("ERROR: circular READONLY_EPREFIX's in %s. %s already checked for %s" % (ro_make_conf, ro_cfg_root, self.readonly_prefixes[ro_cfg_root])) 
-+
-+					# intersect the widest depset with the current one to strip down
-+					# the allowed dependency resolution to not be wider than the
-+					# next higher one. this way we can prevent for a given prefix
-+					# to resolve RDEPENDs from a prefix with a different CHOST that
-+					# is a few levels deeper in the chain.
-+					ro_widest_depset = set(ro_cfg_root_deps.split(",")) & ro_widest_depset
-+					self.readonly_prefixes[ro_cfg_root] = ro_widest_depset
-+				pass
-+
- 			for k in self._case_insensitive_vars:
- 				if k in self:
- 					self[k] = self[k].lower()
-@@ -2671,6 +2729,10 @@
- 		if not eapi_exports_merge_type(eapi):
- 			mydict.pop("MERGE_TYPE", None)
- 
-+		# populate with PORTAGE_READONLY_EPREFIXES
-+		if self.readonly_prefixes and len(self.readonly_prefixes) > 0:
-+			mydict["PORTAGE_READONLY_EPREFIXES"] = ':'.join(self.readonly_prefixes)
-+
- 		# Prefix variables are supported beginning with EAPI 3, or when
- 		# force-prefix is in FEATURES, since older EAPIs would otherwise be
- 		# useless with prefix configurations. This brings compatibility with
-Only in prefix-portage-2.2.14/pym/portage/package/ebuild: config.py.orig
-diff -ru prefix-portage-2.2.14.orig/pym/portage/package/ebuild/doebuild.py prefix-portage-2.2.14/pym/portage/package/ebuild/doebuild.py
---- prefix-portage-2.2.14.orig/pym/portage/package/ebuild/doebuild.py	2014-09-28 19:25:39.000000000 +0200
-+++ prefix-portage-2.2.14/pym/portage/package/ebuild/doebuild.py	2015-06-17 10:23:25.703886164 +0200
-@@ -46,6 +46,7 @@
- 	unmerge, _encodings, _os_merge, \
- 	_shell_quote, _unicode_decode, _unicode_encode
- from portage.const import EBUILD_SH_ENV_FILE, EBUILD_SH_ENV_DIR, \
-+    GLOBAL_CONFIG_PATH, \
- 	EBUILD_SH_BINARY, INVALID_ENV_FILE, MISC_SH_BINARY, PORTAGE_PYM_PACKAGES, EPREFIX, MACOSSANDBOX_PROFILE
- from portage.data import portage_gid, portage_uid, secpass, \
- 	uid, userpriv_groups
-@@ -66,7 +67,8 @@
- from portage.package.ebuild.prepare_build_dirs import prepare_build_dirs
- from portage.util import apply_recursive_permissions, \
- 	apply_secpass_permissions, noiselimit, normalize_path, \
--	writemsg, writemsg_stdout, write_atomic
-+	writemsg, writemsg_stdout, write_atomic, getconfig
-+from portage.util._path import exists_raise_eaccess
- from portage.util.lafilefixer import rewrite_lafile	
- from portage.versions import _pkgsplit
- from _emerge.BinpkgEnvExtractor import BinpkgEnvExtractor
-@@ -212,8 +214,27 @@
- 		path.append(os.path.join(portage_bin_path, "ebuild-helpers", "bsd"))
- 
- 	path.append(os.path.join(portage_bin_path, "ebuild-helpers"))
-+
-+	# PREFIX CHAINING: append default path for all prefixes involved
-+	pfxs = [ eprefix ]
-+	pfxs.extend(settings.readonly_prefixes)
-+	for prefix in pfxs:
-+		global_config_path = os.path.join(prefix, GLOBAL_CONFIG_PATH.lstrip(os.sep))
-+		make_globals_path = os.path.join(global_config_path, "make.globals")
-+		if exists_raise_eaccess(make_globals_path):
-+			expand_map = { "EPREFIX": prefix }
-+			pxcfg = getconfig(make_globals_path, True, expand_map)
-+			pxdefp = [x for x in pxcfg.get("DEFAULT_PATH", "").split(":") if x]
-+			for x in pxdefp:
-+				if x.startswith(prefix) and not x in path:
-+					path.append(x)
-+		else:
-+			pxdefs = [prefix + "/usr/sbin", prefix + "/usr/bin", prefix + "/sbin", prefix + "/bin"]
-+			path.extend(pxdefs)
-+	# END PREFIX CHAINING
-+
- 	path.extend(prerootpath)
--	path.extend(defaultpath)
-+	# path.extend(defaultpath) # PREFIX CHAINING appends the default path for involved prefixes above
- 	path.extend(rootpath)
- 	path.extend(extrapath)
- 	# END PREFIX LOCAL
-diff -ru prefix-portage-2.2.14.orig/pym/portage/package/ebuild/fetch.py prefix-portage-2.2.14/pym/portage/package/ebuild/fetch.py
---- prefix-portage-2.2.14.orig/pym/portage/package/ebuild/fetch.py	2014-04-22 21:50:06.000000000 +0200
-+++ prefix-portage-2.2.14/pym/portage/package/ebuild/fetch.py	2015-06-17 10:24:28.983830892 +0200
-@@ -43,6 +43,7 @@
- from portage.util import apply_recursive_permissions, \
- 	apply_secpass_permissions, ensure_dirs, grabdict, shlex_split, \
- 	varexpand, writemsg, writemsg_level, writemsg_stdout
-+from portage.util._path import exists_raise_eaccess
- from portage.process import spawn
- 
- _userpriv_spawn_kwargs = (
-@@ -869,6 +870,9 @@
- 				global_config_path = GLOBAL_CONFIG_PATH
- 				if portage.const.EPREFIX:
- 					global_config_path = os.path.join(portage.const.EPREFIX,
-+						GLOBAL_CONFIG_PATH.lstrip(os.sep))
-+					if not exists_raise_eaccess(global_config_path) and portage.const.BPREFIX:
-+						global_config_path = os.path.join(portage.const.BPREFIX,
- 							GLOBAL_CONFIG_PATH.lstrip(os.sep))
- 
- 				missing_file_param = False
-diff -ru prefix-portage-2.2.14.orig/pym/portage/_sets/__init__.py prefix-portage-2.2.14/pym/portage/_sets/__init__.py
---- prefix-portage-2.2.14.orig/pym/portage/_sets/__init__.py	2014-01-06 10:44:16.000000000 +0100
-+++ prefix-portage-2.2.14/pym/portage/_sets/__init__.py	2015-06-17 10:24:28.983830892 +0200
-@@ -28,6 +28,7 @@
- from portage.exception import PackageSetNotFound
- from portage.localization import _
- from portage.util import writemsg_level
-+from portage.util._path import exists_raise_eaccess
- 
- SETPREFIX = "@"
- 
-@@ -299,6 +300,10 @@
- 	if portage.const.EPREFIX:
- 		global_config_path = os.path.join(portage.const.EPREFIX,
- 			GLOBAL_CONFIG_PATH.lstrip(os.sep))
-+		if not exists_raise_eaccess(global_config_path) and portage.const.BPREFIX:
-+			global_config_path = os.path.join(portage.const.BPREFIX,
-+				GLOBAL_CONFIG_PATH.lstrip(os.sep))
-+
- 	def _getfiles():
- 		for path, dirs, files in os.walk(os.path.join(global_config_path, "sets")):
- 			for f in files:
-diff -ru prefix-portage-2.2.14.orig/pym/portage/util/_dyn_libs/LinkageMapELF.py prefix-portage-2.2.14/pym/portage/util/_dyn_libs/LinkageMapELF.py
---- prefix-portage-2.2.14.orig/pym/portage/util/_dyn_libs/LinkageMapELF.py	2013-05-04 18:36:19.000000000 +0200
-+++ prefix-portage-2.2.14/pym/portage/util/_dyn_libs/LinkageMapELF.py	2015-06-17 10:24:28.987164223 +0200
-@@ -17,7 +17,7 @@
- from portage.util import grabfile
- from portage.util import normalize_path
- from portage.util import writemsg_level
--from portage.const import EPREFIX
-+from portage.const import BPREFIX
- 
- class LinkageMapELF(object):
- 
-@@ -235,7 +235,7 @@
- 					continue
- 				plibs.update((x, cpv) for x in items)
- 		if plibs:
--			args = [EPREFIX + "/usr/bin/scanelf", "-qF", "%a;%F;%S;%r;%n"]
-+			args = [BPREFIX + "/usr/bin/scanelf", "-qF", "%a;%F;%S;%r;%n"]
- 			args.extend(os.path.join(root, x.lstrip("." + os.sep)) \
- 				for x in plibs)
- 			try:

diff --git a/sys-apps/portage/files/portage-2.3.18-prefix-chaining.patch b/sys-apps/portage/files/portage-2.3.18-prefix-chaining.patch
deleted file mode 100644
index 728b3261ba..0000000000
--- a/sys-apps/portage/files/portage-2.3.18-prefix-chaining.patch
+++ /dev/null
@@ -1,927 +0,0 @@
-From 2ce322b10b0f1971b174067ca9dac373322e4035 Mon Sep 17 00:00:00 2001
-From: Michael Haubenwallner <haubi@gentoo.org>
-Date: Thu, 23 Mar 2017 13:52:32 +0100
-Subject: [PATCH] add prefix-chaining support
-
----
- bin/install-qa-check.d/05prefix                    | 30 ++++++-
- bin/phase-helpers.sh                               | 28 ++++++
- pym/_emerge/actions.py                             |  6 +-
- pym/_emerge/depgraph.py                            | 51 ++++++-----
- pym/_emerge/resolver/output.py                     | 40 ++++++++-
- pym/portage/_sets/__init__.py                      |  5 ++
- pym/portage/const.py                               |  6 ++
- pym/portage/dbapi/vartree.py                       | 34 ++++++--
- pym/portage/dep/dep_check.py                       | 99 +++++++++++++++++++++-
- .../package/ebuild/_config/LocationsManager.py     |  3 +
- pym/portage/package/ebuild/config.py               | 62 ++++++++++++++
- pym/portage/package/ebuild/doebuild.py             | 24 +++++-
- pym/portage/package/ebuild/fetch.py                |  4 +
- pym/portage/sync/controller.py                     | 27 +++---
- pym/portage/util/_dyn_libs/LinkageMapELF.py        |  4 +-
- 15 files changed, 376 insertions(+), 47 deletions(-)
-
-diff --git a/bin/install-qa-check.d/05prefix b/bin/install-qa-check.d/05prefix
-index 32561e263..0c1147367 100644
---- a/bin/install-qa-check.d/05prefix
-+++ b/bin/install-qa-check.d/05prefix
-@@ -79,16 +79,42 @@ install_qa_check_prefix() {
- 		# unprefixed shebang, is the script directly in $PATH or an init
- 		# script?
- 		if [[ ":${PATH}:${EPREFIX}/etc/init.d:" == *":${fp}:"* ]] ; then
--			if [[ -e ${EROOT}${line[0]} || -e ${ED}${line[0]} ]] ; then
-+			all_epfs="$PORTAGE_READONLY_EPREFIXES:$EPREFIX:$EROOT:$ED"
-+			save_IFS=$IFS
-+			IFS=:
-+			epfs=( $all_epfs )
-+			IFS=$save_IFS
-+
-+			found=
-+			for x in "${epfs[@]}"; do
-+				[[ -z "${x}" ]] && continue
-+				check="${x}${line[0]}"
-+
-+				# might already contain a prefix
-+				if [[ "${line[0]}" == "${x}"* ]]; then
-+					check="${line[0]}"
-+				fi
-+
-+				if [[ -e ${check} ]]; then
-+					found="${check}"
-+				fi
-+			done
-+
-+			if [[ -n ${found} ]] ; then
- 				# is it unprefixed, but we can just fix it because a
- 				# prefixed variant exists
- 				eqawarn "prefixing shebang of ${fn#${D}}"
-+
-+				if [[ ${found} == "${ED}"* || ${found} == "${EROOT}"* ]]; then
-+					found="${EPREFIX}${line[0]}"
-+				fi
-+
- 				# statement is made idempotent on purpose, because
- 				# symlinks may point to the same target, and hence the
- 				# same real file may be sedded multiple times since we
- 				# read the shebangs in one go upfront for performance
- 				# reasons
--				sed -i -e '1s:^#! \?'"${line[0]}"':#!'"${EPREFIX}"${line[0]}':' "${rf}"
-+				sed -i -e '1s:^#! \?'"${line[0]}"':#!'"${found}"':' "${rf}"
- 				continue
- 			else
- 				# this is definitely wrong: script in $PATH and invalid shebang
-diff --git a/bin/phase-helpers.sh b/bin/phase-helpers.sh
-index 2cac6f426..b7b5c8ce6 100644
---- a/bin/phase-helpers.sh
-+++ b/bin/phase-helpers.sh
-@@ -868,6 +868,10 @@ has_version() {
- 		"${PORTAGE_BIN_PATH}/ebuild-helpers/portageq" has_version "${eroot}" "${atom}"
- 	fi
- 	local retval=$?
-+	if [[ ${retval} -eq 1 && -n ${READONLY_EPREFIX} ]]; then
-+		${SHELL} -c "EPREFIX='${READONLY_EPREFIX%:*}' EPYTHON= '${PORTAGE_BIN_PATH}/ebuild-helpers/portageq' has_version '${READONLY_EPREFIX%:*}' '${atom}'"
-+		retval=$?
-+	fi
- 	case "${retval}" in
- 		0|1)
- 			return ${retval}
-@@ -927,6 +931,10 @@ best_version() {
- 		"${PORTAGE_BIN_PATH}/ebuild-helpers/portageq" best_version "${eroot}" "${atom}"
- 	fi
- 	local retval=$?
-+	if [[ ${retval} -eq 1 && -n ${READONLY_EPREFIX} ]]; then
-+		${SHELL} -c "EPREFIX='${READONLY_EPREFIX%:*}' EPYTHON= '${PORTAGE_BIN_PATH}/ebuild-helpers/portageq' best_version '${READONLY_EPREFIX%:*}' '${atom}'"
-+		retval=$?
-+	fi
- 	case "${retval}" in
- 		0|1)
- 			return ${retval}
-@@ -1167,6 +1175,10 @@ if ___eapi_has_master_repositories; then
- 			output=$("${PORTAGE_BIN_PATH}/ebuild-helpers/portageq" master_repositories "${EROOT}" "${repository}")
- 		fi
- 		retval=$?
-+		if [[ ${retval} -eq 1 && -n ${READONLY_EPREFIX} ]]; then
-+			output=$(${SHELL} -c "EPREFIX='${READONLY_EPREFIX%:*}' EPYTHON= '${PORTAGE_BIN_PATH}/ebuild-helpers/portageq' master_repositories '${READONLY_EPREFIX%:*}' '${repository}'")
-+			retval=$?
-+		fi
- 		[[ -n ${output} ]] && echo "${output}"
- 		case "${retval}" in
- 			0|1)
-@@ -1198,6 +1210,10 @@ if ___eapi_has_repository_path; then
- 			output=$("${PORTAGE_BIN_PATH}/ebuild-helpers/portageq" get_repo_path "${EROOT}" "${repository}")
- 		fi
- 		retval=$?
-+		if [[ ${retval} -eq 1 && -n ${READONLY_EPREFIX} ]]; then
-+			output=$(${SHELL} -c "EPREFIX='${READONLY_EPREFIX%:*}' EPYTHON= '${PORTAGE_BIN_PATH}/ebuild-helpers/portageq' repository_path '${READONLY_EPREFIX%:*}' '${repository}'")
-+			retval=$?
-+		fi
- 		[[ -n ${output} ]] && echo "${output}"
- 		case "${retval}" in
- 			0|1)
-@@ -1228,6 +1244,10 @@ if ___eapi_has_available_eclasses; then
- 			output=$("${PORTAGE_BIN_PATH}/ebuild-helpers/portageq" available_eclasses "${EROOT}" "${repository}")
- 		fi
- 		retval=$?
-+		if [[ ${retval} -eq 1 && -n ${READONLY_EPREFIX} ]]; then
-+			output=$(${SHELL} -c "EPREFIX='${READONLY_EPREFIX%:*}' EPYTHON= '${PORTAGE_BIN_PATH}/ebuild-helpers/portageq' available_eclasses '${READONLY_EPREFIX%:*}' '${repository}'")
-+			retval=$?
-+		fi
- 		[[ -n ${output} ]] && echo "${output}"
- 		case "${retval}" in
- 			0|1)
-@@ -1258,6 +1278,10 @@ if ___eapi_has_eclass_path; then
- 		else
- 			output=$("${PORTAGE_BIN_PATH}/ebuild-helpers/portageq" eclass_path "${EROOT}" "${repository}" "${eclass}")
- 		fi
-+		if [[ ${retval} -eq 1 && -n ${READONLY_EPREFIX} ]]; then
-+			output=$(${SHELL} -c "EPREFIX='${READONLY_EPREFIX%:*}' EPYTHON= '${PORTAGE_BIN_PATH}/ebuild-helpers/portageq' eclass_path '${READONLY_EPREFIX%:*}' '${repository}' '${eclass}'")
-+			retval=$?
-+		fi
- 		retval=$?
- 		[[ -n ${output} ]] && echo "${output}"
- 		case "${retval}" in
-@@ -1289,6 +1313,10 @@ if ___eapi_has_license_path; then
- 		else
- 			output=$("${PORTAGE_BIN_PATH}/ebuild-helpers/portageq" license_path "${EROOT}" "${repository}" "${license}")
- 		fi
-+		if [[ ${retval} -eq 1 && -n ${READONLY_EPREFIX} ]]; then
-+			output=(${SHELL} -c "EPREFIX='${READONLY_EPREFIX%:*}' EPYTHON= '${PORTAGE_BIN_PATH}/ebuild-helpers/portageq' license_path '${READONLY_EPREFIX%:*}' '${repository}' '${license}'")
-+			retval=$?
-+		fi
- 		retval=$?
- 		[[ -n ${output} ]] && echo "${output}"
- 		case "${retval}" in
-diff --git a/pym/_emerge/actions.py b/pym/_emerge/actions.py
-index 1d37d0ece..2b185ef73 100644
---- a/pym/_emerge/actions.py
-+++ b/pym/_emerge/actions.py
-@@ -39,7 +39,7 @@ from portage import os
- from portage import shutil
- from portage import eapi_is_supported, _encodings, _unicode_decode
- from portage.cache.cache_errors import CacheError
--from portage.const import EPREFIX
-+from portage.const import EPREFIX, BPREFIX
- from portage.const import GLOBAL_CONFIG_PATH, VCS_DIRS, _DEPCLEAN_LIB_CHECK_DEFAULT
- from portage.const import SUPPORTED_BINPKG_FORMATS, TIMESTAMP_FORMAT
- from portage.dbapi.dep_expand import dep_expand
-@@ -65,6 +65,7 @@ from portage.util.SlotObject import SlotObject
- from portage.util._async.run_main_scheduler import run_main_scheduler
- from portage.util._async.SchedulerInterface import SchedulerInterface
- from portage.util._eventloop.global_event_loop import global_event_loop
-+from portage.util._path import exists_raise_eaccess
- from portage._global_updates import _global_updates
- from portage.sync.old_tree_timestamp import old_tree_timestamp_warn
- from portage.localization import _
-@@ -2659,6 +2660,9 @@ def missing_sets_warning(root_config, missing_sets):
- 	if portage.const.EPREFIX:
- 		global_config_path = os.path.join(portage.const.EPREFIX,
- 				portage.const.GLOBAL_CONFIG_PATH.lstrip(os.sep))
-+		if not exists_raise_eaccess(global_config_path) and portage.const.BPREFIX:
-+			global_config_path = os.path.join(portage.const.BPREFIX,
-+                    portage.const.GLOBAL_CONFIG_PATH.lstrip(os.sep))
- 	msg.append("        This usually means that '%s'" % \
- 		(os.path.join(global_config_path, "sets/portage.conf"),))
- 	msg.append("        is missing or corrupt.")
-diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py
-index 8d00f93df..fe317f119 100644
---- a/pym/_emerge/depgraph.py
-+++ b/pym/_emerge/depgraph.py
-@@ -3239,15 +3239,15 @@ class depgraph(object):
- 		# _dep_disjunctive_stack first, so that choices for build-time
- 		# deps influence choices for run-time deps (bug 639346).
- 		deps = (
--			(myroot, edepend["RDEPEND"],
-+			(myroot, "RDEPEND",
- 				self._priority(runtime=True)),
--			(myroot, edepend["PDEPEND"],
-+			(myroot, "PDEPEND",
- 				self._priority(runtime_post=True)),
--			(depend_root, edepend["DEPEND"],
-+			(depend_root, "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._frozen_config._running_root.root, "HDEPEND",
- 				self._priority(buildtime=True,
- 				optional=(pkg.built or ignore_hdepend_deps),
- 				ignored=ignore_hdepend_deps)),
-@@ -3255,7 +3255,8 @@ class depgraph(object):
- 
- 		debug = "--debug" in self._frozen_config.myopts
- 
--		for dep_root, dep_string, dep_priority in deps:
-+		for dep_root, dep_type, dep_priority in deps:
-+				dep_string = edepend[dep_type]
- 				if not dep_string:
- 					continue
- 				if debug:
-@@ -3293,7 +3294,7 @@ class depgraph(object):
- 
- 				try:
- 					dep_string = list(self._queue_disjunctive_deps(
--						pkg, dep_root, dep_priority, dep_string))
-+						pkg, dep_root, dep_priority, dep_string, dep_type))
- 				except portage.exception.InvalidDependString as e:
- 					if pkg.installed:
- 						self._dynamic_config._masked_installed.add(pkg)
-@@ -3308,14 +3309,14 @@ class depgraph(object):
- 
- 				if not self._add_pkg_dep_string(
- 					pkg, dep_root, dep_priority, dep_string,
--					allow_unsatisfied):
-+					allow_unsatisfied, dep_type):
- 					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):
-+		allow_unsatisfied, dep_type=None):
- 		_autounmask_backup = self._dynamic_config._autounmask
- 		if dep_priority.optional or dep_priority.ignored:
- 			# Temporarily disable autounmask for deps that
-@@ -3324,7 +3325,7 @@ class depgraph(object):
- 		try:
- 			return self._wrapped_add_pkg_dep_string(
- 				pkg, dep_root, dep_priority, dep_string,
--				allow_unsatisfied)
-+				allow_unsatisfied, dep_type)
- 		finally:
- 			self._dynamic_config._autounmask = _autounmask_backup
- 
-@@ -3360,7 +3361,7 @@ class depgraph(object):
- 			not slot_operator_rebuild
- 
- 	def _wrapped_add_pkg_dep_string(self, pkg, dep_root, dep_priority,
--		dep_string, allow_unsatisfied):
-+		dep_string, allow_unsatisfied, dep_type=None):
- 		if isinstance(pkg.depth, int):
- 			depth = pkg.depth + 1
- 		else:
-@@ -3384,7 +3385,7 @@ class depgraph(object):
- 		try:
- 			selected_atoms = self._select_atoms(dep_root,
- 				dep_string, myuse=self._pkg_use_enabled(pkg), parent=pkg,
--				strict=strict, priority=dep_priority)
-+				strict=strict, priority=dep_priority, dep_type=dep_type)
- 		except portage.exception.InvalidDependString:
- 			if pkg.installed:
- 				self._dynamic_config._masked_installed.add(pkg)
-@@ -3691,7 +3692,7 @@ class depgraph(object):
- 					child_pkgs.sort()
- 				yield (atom, child_pkgs[-1])
- 
--	def _queue_disjunctive_deps(self, pkg, dep_root, dep_priority, dep_struct):
-+	def _queue_disjunctive_deps(self, pkg, dep_root, dep_priority, dep_struct, dep_type=None):
- 		"""
- 		Queue disjunctive (virtual and ||) deps in self._dynamic_config._dep_disjunctive_stack.
- 		Yields non-disjunctive deps. Raises InvalidDependString when
-@@ -3700,33 +3701,33 @@ class depgraph(object):
- 		for x in dep_struct:
- 			if isinstance(x, list):
- 				if x and x[0] == "||":
--					self._queue_disjunction(pkg, dep_root, dep_priority, [x])
-+					self._queue_disjunction(pkg, dep_root, dep_priority, [x], dep_type)
- 				else:
- 					for y in self._queue_disjunctive_deps(
--						pkg, dep_root, dep_priority, x):
-+						pkg, dep_root, dep_priority, x, dep_type):
- 						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])
-+					self._queue_disjunction(pkg, dep_root, dep_priority, [x], dep_type)
- 				else:
- 					yield x
- 
--	def _queue_disjunction(self, pkg, dep_root, dep_priority, dep_struct):
-+	def _queue_disjunction(self, pkg, dep_root, dep_priority, dep_struct, dep_type=None):
- 		self._dynamic_config._dep_disjunctive_stack.append(
--			(pkg, dep_root, dep_priority, dep_struct))
-+			(pkg, dep_root, dep_priority, dep_struct, dep_type))
- 
- 	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 = \
-+		pkg, dep_root, dep_priority, dep_struct, dep_type = \
- 			self._dynamic_config._dep_disjunctive_stack.pop()
- 		if not self._add_pkg_dep_string(
--			pkg, dep_root, dep_priority, dep_struct, allow_unsatisfied):
-+			pkg, dep_root, dep_priority, dep_struct, allow_unsatisfied, dep_type):
- 			return 0
- 		return 1
- 
-@@ -4579,7 +4580,7 @@ class depgraph(object):
- 		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):
-+		myuse=None, parent=None, strict=True, trees=None, priority=None, dep_type=None):
- 		"""This will raise InvalidDependString if necessary. If trees is
- 		None then self._dynamic_config._filtered_trees is used."""
- 
-@@ -4602,6 +4603,13 @@ class depgraph(object):
- 		pkgsettings = self._frozen_config.pkgsettings[root]
- 		if trees is None:
- 			trees = self._dynamic_config._filtered_trees
-+
-+		# this one is needed to guarantee good readonly root
-+		# resolution display in the merge list. required since
-+		# parent (below) can be None
-+		trees[root]["disp_parent"] = parent
-+
-+
- 		mytrees = trees[root]
- 		atom_graph = digraph()
- 		if True:
-@@ -4633,7 +4641,7 @@ class depgraph(object):
- 
- 				mycheck = portage.dep_check(depstring, None,
- 					pkgsettings, myuse=myuse,
--					myroot=root, trees=trees)
-+					myroot=root, trees=trees, dep_type=dep_type)
- 			finally:
- 				# restore state
- 				self._dynamic_config._autounmask = _autounmask_backup
-@@ -4709,6 +4717,7 @@ class depgraph(object):
- 							continue
- 						node_stack.append((child_node, node, child_atom))
- 
-+		trees[root].pop("disp_parent")
- 		return selected_atoms
- 
- 	def _expand_virt_from_graph(self, root, atom):
-diff --git a/pym/_emerge/resolver/output.py b/pym/_emerge/resolver/output.py
-index e993ce17d..32a942c73 100644
---- a/pym/_emerge/resolver/output.py
-+++ b/pym/_emerge/resolver/output.py
-@@ -22,11 +22,12 @@ from portage.localization import localized_size
- from portage.package.ebuild.config import _get_feature_flags
- from portage.package.ebuild._spawn_nofetch import spawn_nofetch
- from portage.output import ( blue, colorize, create_color_func,
--	darkblue, darkgreen, green, nc_len, teal)
-+	darkblue, darkgreen, green, nc_len, teal, yellow, turquoise)
- bad = create_color_func("BAD")
- from portage._sets.base import InternalPackageSet
- from portage.util import writemsg_stdout
- from portage.versions import best, cpv_getversion
-+from portage.dep.dep_check import ro_selected
- 
- from _emerge.Blocker import Blocker
- from _emerge.create_world_atom import create_world_atom
-@@ -563,6 +564,42 @@ class Display(object):
- 			writemsg_stdout("%s\n" % (pkg,), noiselevel=-1)
- 		return
- 
-+	def print_readonly_prefix(self):
-+		"""Performs the actual output printing for the readonly prefix
-+		information stuff
-+		"""
-+		out = sys.stdout
-+
-+        # print readonly selected packages
-+		if len(ro_selected) > 0:
-+			out.write("\n%s\n\n" % (darkgreen("Packages resolved from readonly installations:")))
-+
-+		ro_mismatch_warning = False
-+		ro_dupcheck = []
-+		for x in ro_selected:
-+			tmp_type = x["type"].replace("END","")
-+			while len(tmp_type) < 4:
-+				tmp_type += " "
-+			if x["parent"] and str(x["atom"]) not in ro_dupcheck:
-+				out.write("[%s %s] %s %s %s (%s by %s)" % (teal("readonly"),
-+					green(tmp_type), green(str(x["matches"][0])), yellow("from"),
-+					blue(x["ro_root"]), turquoise(str(x["atom"])), green(x["parent"].cpv)))
-+
-+				ro_dupcheck.append(str(x["atom"]))
-+
-+				if x["host_mismatch"]:
-+					ro_mismatch_warning = True
-+					out.write(" %s\n" % (red("**")))
-+				else:
-+					out.write("\n")
-+
-+		if ro_mismatch_warning:
-+			out.write("\n%s:" % (red("**")))
-+			out.write(yellow(" WARNING: packages marked with ** have been resolved as a\n"))
-+			out.write(yellow("    runtime dependency, but the CHOST variable for the parent\n"))
-+			out.write(yellow("    and dependency package don't match. This could cause link\n"))
-+			out.write(yellow("    errors. It is recommended to use RDEPEND READONLY_EPREFIX's\n"))
-+			out.write(yellow("    only with matching CHOST portage instances.\n"))
- 
- 	def print_verbose(self, show_repos):
- 		"""Prints the verbose output to std_out
-@@ -913,6 +950,7 @@ class Display(object):
- 		show_repos = self.quiet_repo_display and repoadd_set and repoadd_set != set(["0"])
- 
- 		# now finally print out the messages
-+		self.print_readonly_prefix()
- 		self.print_messages(show_repos)
- 		self.print_blockers()
- 		if self.conf.verbosity == 3:
-diff --git a/pym/portage/_sets/__init__.py b/pym/portage/_sets/__init__.py
-index 2c9bf9715..6a2784207 100644
---- a/pym/portage/_sets/__init__.py
-+++ b/pym/portage/_sets/__init__.py
-@@ -21,6 +21,7 @@ from portage.const import _ENABLE_SET_CONFIG
- from portage.exception import PackageSetNotFound
- from portage.localization import _
- from portage.util import writemsg_level
-+from portage.util._path import exists_raise_eaccess
- from portage.util.configparser import (SafeConfigParser,
- 	NoOptionError, ParsingError, read_configs)
- 
-@@ -281,6 +282,10 @@ def load_default_config(settings, trees):
- 	if portage.const.EPREFIX:
- 		global_config_path = os.path.join(portage.const.EPREFIX,
- 			GLOBAL_CONFIG_PATH.lstrip(os.sep))
-+		if not exists_raise_eaccess(global_config_path) and portage.const.BPREFIX:
-+			global_config_path = os.path.join(portage.const.BPREFIX,
-+				GLOBAL_CONFIG_PATH.lstrip(os.sep))
-+
- 	vcs_dirs = [_unicode_encode(x, encoding=_encodings['fs']) for x in VCS_DIRS]
- 	def _getfiles():
- 		for path, dirs, files in os.walk(os.path.join(global_config_path, "sets")):
-diff --git a/pym/portage/const.py b/pym/portage/const.py
-index dd4657835..6be443082 100644
---- a/pym/portage/const.py
-+++ b/pym/portage/const.py
-@@ -189,6 +189,7 @@ SUPPORTED_FEATURES       = frozenset([
- 	"notitles",
- 	"parallel-fetch",
- 	"parallel-install",
-+	"prefix-chaining",
- 	"prelink-checksums",
- 	"preserve-libs",
- 	"protect-owned",
-@@ -239,6 +240,11 @@ MANIFEST2_IDENTIFIERS    = ("AUX", "MISC", "DIST", "EBUILD")
- #EPREFIX = ""
- # END PREFIX LOCAL
- 
-+BPREFIX = EPREFIX
-+
-+# --prefix commandline arg always rules, ends up in os.environ["EPREFIX"]
-+if "EPREFIX" in os.environ:
-+    os.environ["PORTAGE_OVERRIDE_EPREFIX"] = os.environ["EPREFIX"]
- # pick up EPREFIX from the environment if set
- if "PORTAGE_OVERRIDE_EPREFIX" in os.environ:
- 	EPREFIX = os.environ["PORTAGE_OVERRIDE_EPREFIX"]
-diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py
-index d2c35f9e3..79d612b2d 100644
---- a/pym/portage/dbapi/vartree.py
-+++ b/pym/portage/dbapi/vartree.py
-@@ -195,8 +195,19 @@ class vardbapi(dbapi):
- 		self._counter_path = os.path.join(self._eroot,
- 			CACHE_PATH, "counter")
- 
--		self._plib_registry = PreservedLibsRegistry(settings["ROOT"],
--			os.path.join(self._eroot, PRIVATE_PATH, "preserved_libs_registry"))
-+		plibreg_path = os.path.join(self._eroot, PRIVATE_PATH, "preserved_libs_registry")
-+
-+		if vartree:
-+			self._kill_eprefix = vartree._kill_eprefix
-+		else:
-+			self._kill_eprefix = False
-+
-+		if self._kill_eprefix:
-+			self._aux_cache_filename = self._aux_cache_filename.replace(EPREFIX, "")
-+			self._counter_path = self._counter_path.replace(EPREFIX, "")
-+			plibreg_path = plibreg_path.replace(EPREFIX, "")
-+
-+		self._plib_registry = PreservedLibsRegistry(settings["ROOT"], plibreg_path)
- 		self._linkmap = LinkageMap(self)
- 		chost = self.settings.get('CHOST')
- 		if not chost:
-@@ -237,6 +248,9 @@ class vardbapi(dbapi):
- 		# This is an optimized hotspot, so don't use unicode-wrapped
- 		# os module and don't use os.path.join().
- 		rValue = self._eroot + VDB_PATH + _os.sep + mykey
-+		if self._kill_eprefix:
-+			rValue = rValue.replace(EPREFIX, "")
-+
- 		if filename is not None:
- 			# If filename is always relative, we can do just
- 			# rValue += _os.sep + filename
-@@ -500,6 +514,9 @@ class vardbapi(dbapi):
- 		returnme = []
- 		basepath = os.path.join(self._eroot, VDB_PATH) + os.path.sep
- 
-+		if self._kill_eprefix:
-+			basepath = os.path.join(self.root, basepath.replace(EPREFIX, ""))
-+
- 		if use_cache:
- 			from portage import listdir
- 		else:
-@@ -596,11 +613,17 @@ class vardbapi(dbapi):
- 				del self.matchcache[mycat]
- 			return list(self._iter_match(mydep,
- 				self.cp_list(mydep.cp, use_cache=use_cache)))
-+
-+		_tmp_path = os.path.join(self._eroot, VDB_PATH, mycat)
-+
-+		if self._kill_eprefix:
-+			_tmp_path = _tmp_path.replace(EPREFIX, "")
-+
- 		try:
- 			if sys.hexversion >= 0x3030000:
--				curmtime = os.stat(os.path.join(self._eroot, VDB_PATH, mycat)).st_mtime_ns
-+				curmtime = os.stat(_tmp_path).st_mtime_ns
- 			else:
--				curmtime = os.stat(os.path.join(self._eroot, VDB_PATH, mycat)).st_mtime
-+				curmtime = os.stat(_tmp_path).st_mtime
- 		except (IOError, OSError):
- 			curmtime=0
- 
-@@ -1448,7 +1471,7 @@ class vardbapi(dbapi):
- class vartree(object):
- 	"this tree will scan a var/db/pkg database located at root (passed to init)"
- 	def __init__(self, root=None, virtual=DeprecationWarning, categories=None,
--		settings=None):
-+		settings=None, kill_eprefix=None):
- 
- 		if settings is None:
- 			settings = portage.settings
-@@ -1466,6 +1489,7 @@ class vartree(object):
- 				" constructor is unused",
- 				DeprecationWarning, stacklevel=2)
- 
-+		self._kill_eprefix = kill_eprefix
- 		self.settings = settings
- 		self.dbapi = vardbapi(settings=settings, vartree=self)
- 		self.populated = 1
-diff --git a/pym/portage/dep/dep_check.py b/pym/portage/dep/dep_check.py
-index 2bb9dc339..cc017a2a7 100644
---- a/pym/portage/dep/dep_check.py
-+++ b/pym/portage/dep/dep_check.py
-@@ -298,6 +298,95 @@ class _dep_choice(SlotObject):
- 	__slots__ = ('atoms', 'slot_map', 'cp_map', 'all_available',
- 		'all_installed_slots')
- 
-+ro_trees={}
-+ro_vartrees={}
-+ro_selected=[]
-+
-+def dep_match_readonly_roots(settings, atom, dep_type, parent=None):
-+   if len(ro_trees) < len(settings.readonly_prefixes):
-+       # MDUFT: create additional vartrees for every readonly root here.
-+       # the ro_vartrees instances are created below as they are needed to
-+       # avoid reading vartrees of portage instances which aren't required
-+       # while resolving this dependencies.
-+       for type in ("DEPEND","RDEPEND", "PDEPEND"):
-+           ro_trees[type] = []
-+
-+           for ro_root, ro_dep_types in settings.readonly_prefixes.items():
-+               if type in ro_dep_types:
-+                   ro_trees[type].append(ro_root)
-+
-+   if len(ro_trees) == 0:
-+       return []
-+
-+   matches = []
-+
-+   for ro_root in ro_trees[dep_type]:
-+       if not ro_root in ro_vartrees:
-+           # target_root=ro_root ok? or should it be the real target_root?
-+           _tmp_settings = portage.config(config_root=ro_root, target_root=ro_root,
-+               config_incrementals=portage.const.INCREMENTALS)
-+
-+           ro_vartrees[ro_root] = portage.vartree(root=ro_root,
-+               categories=_tmp_settings.categories,
-+               settings=_tmp_settings, kill_eprefix=True)
-+
-+       ro_matches = ro_vartrees[ro_root].dbapi.match(atom)
-+
-+       if ro_matches:
-+           ro_host_mismatch = False
-+           if dep_type is "RDEPEND":
-+               # we need to assure binary compatability, so it needs to be
-+               # the same CHOST! But how? for now i cannot do anything...
-+               if parent and parent.metadata["CHOST"] != ro_vartrees[ro_root].settings.get("CHOST", ""):
-+                   # provocate a big fat warning in the list of external packages.
-+                   ro_host_mismatch = True
-+               pass
-+
-+           matches.append({ "ro_root": ro_root, "atom": atom, "matches": ro_matches,
-+               "type": dep_type, "parent": parent, "host_mismatch": ro_host_mismatch })
-+
-+   return matches
-+
-+def dep_wordreduce_readonly(reduced, unreduced, settings, dep_type, parent):
-+   for mypos, token in enumerate(unreduced):
-+       # recurse if it's a list.
-+       if isinstance(reduced[mypos], list):
-+           reduced[mypos] = dep_wordreduce_readonly(reduced[mypos],
-+               unreduced[mypos], settings, dep_type, parent)
-+
-+       # do nothing if it's satisfied already.
-+       elif not reduced[mypos]:
-+           ro_matches = dep_match_readonly_roots(settings, unreduced[mypos], dep_type, parent)
-+
-+           if ro_matches:
-+               # TODO: select a match if there are more than one?
-+               # for now, the first match is taken...
-+               ro_selected.append(ro_matches[0])
-+               reduced[mypos] = True
-+
-+   return reduced
-+
-+# this may be better placed somewhere else, but i put it here for now, to
-+# keep all functions in the patch on one big heap.
-+def readonly_pathmatch_any(settings, path):
-+   path = path.lstrip('/')
-+   # first try locally, and match that if it exists.
-+   if os.path.exists(os.path.join(EPREFIX,path)):
-+       return os.path.join(EPREFIX,path)
-+
-+   # after that try all readonly roots where DEPEND is allowed. this makes
-+   # sure that executing binaries is possible from there.
-+   for ro_root, ro_deps in settings.readonly_roots.items():
-+       if "DEPEND" in ro_deps:
-+           print(" --- checking %s --- " % (os.path.join(ro_root,path)))
-+           if os.path.exists(os.path.join(ro_root,path)):
-+               return os.path.join(ro_root,path)
-+           break
-+
-+   # as a fallback make the string the same as it was originally.
-+   # even though this path doesn't exist.
-+   return os.path.join(EPREFIX,path)
-+
- def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None):
- 	"""
- 	Takes an unreduced and reduced deplist and removes satisfied dependencies.
-@@ -695,7 +784,7 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None):
- 	assert(False) # This point should not be reachable
- 
- def dep_check(depstring, mydbapi, mysettings, use="yes", mode=None, myuse=None,
--	use_cache=1, use_binaries=0, myroot=None, trees=None):
-+	use_cache=1, use_binaries=0, myroot=None, trees=None, dep_type=None):
- 	"""
- 	Takes a depend string, parses it, and selects atoms.
- 	The myroot parameter is unused (use mysettings['EROOT'] instead).
-@@ -796,6 +885,14 @@ def dep_check(depstring, mydbapi, mysettings, use="yes", mode=None, myuse=None,
- 	writemsg("mysplit:  %s\n" % (mysplit), 1)
- 	writemsg("mysplit2: %s\n" % (mysplit2), 1)
- 
-+	if dep_type is not None:
-+		mysplit2=dep_wordreduce_readonly(unreduced=mysplit[:],
-+				reduced=mysplit2, settings=mysettings,
-+				dep_type=dep_type, parent=trees[myroot].get("disp_parent"))
-+
-+		writemsg("\n", 1)
-+		writemsg("mysplit2 after readonly reduce: %s\n" % (mysplit2), 1)
-+
- 	selected_atoms = dep_zapdeps(mysplit, mysplit2, myroot,
- 		use_binaries=use_binaries, trees=trees)
- 
-diff --git a/pym/portage/package/ebuild/_config/LocationsManager.py b/pym/portage/package/ebuild/_config/LocationsManager.py
-index 55b8c089a..32e969ed7 100644
---- a/pym/portage/package/ebuild/_config/LocationsManager.py
-+++ b/pym/portage/package/ebuild/_config/LocationsManager.py
-@@ -307,6 +307,9 @@ class LocationsManager(object):
- 		if portage.const.EPREFIX:
- 			self.global_config_path = os.path.join(portage.const.EPREFIX,
- 				GLOBAL_CONFIG_PATH.lstrip(os.sep))
-+			if not exists_raise_eaccess(self.global_config_path) and portage.const.BPREFIX:
-+				self.global_config_path = os.path.join(portage.const.BPREFIX,
-+					GLOBAL_CONFIG_PATH.lstrip(os.sep))
- 
- 	def set_port_dirs(self, portdir, portdir_overlay):
- 		self.portdir = portdir
-diff --git a/pym/portage/package/ebuild/config.py b/pym/portage/package/ebuild/config.py
-index d013b0d5c..fdb1552e9 100644
---- a/pym/portage/package/ebuild/config.py
-+++ b/pym/portage/package/ebuild/config.py
-@@ -306,6 +306,7 @@ class config(object):
- 			self.features = features_set(self)
- 			self.features._features = copy.deepcopy(clone.features._features)
- 			self._features_overrides = copy.deepcopy(clone._features_overrides)
-+			self.readonly_prefixes = copy.deepcopy(clone.readonly_prefixes)
- 
- 			#Strictly speaking _license_manager is not immutable. Users need to ensure that
- 			#extract_global_changes() is called right after __init__ (if at all).
-@@ -945,6 +946,63 @@ class config(object):
- 
- 			self._validate_commands()
- 
-+			# expand READONLY_EPREFIX to a list of all readonly portage instances
-+			# all the way down to the last one. beware that ATM a deeper instance
-+			# in the chain can provide more than the toplevel! this means that
-+			# if you only inherit DEPENDS from one instance, that instance may
-+			# inherit RDEPENDs from another one, making the top-level instance
-+			# inherit RDEPENDs from there too - even if the intermediate prefix
-+			# does not do this.
-+			self.readonly_prefixes = {}
-+			ro_cfg_root = config_root
-+			ro_widest_depset = set(['DEPEND', 'RDEPEND', 'PDEPEND'])
-+
-+			while ro_cfg_root:
-+				ro_make_conf_paths = [
-+					os.path.join(ro_cfg_root, 'etc', 'make.conf'),
-+					os.path.join(ro_cfg_root, MAKE_CONF_FILE)
-+				]
-+				try:
-+					if os.path.samefile(*ro_make_conf_paths):
-+						ro_make_conf_paths.pop()
-+				except OSError:
-+					pass
-+
-+				ro_cfg_root = None
-+				for ro_make_conf in ro_make_conf_paths:
-+					if not os.path.exists(ro_make_conf):
-+						continue
-+
-+					ro_cfg = getconfig(ro_make_conf, tolerant=True, allow_sourcing=True)
-+					if not "READONLY_EPREFIX" in ro_cfg:
-+						continue
-+
-+					if not ro_cfg["READONLY_EPREFIX"].find(":"):
-+						raise portage.exception.InvalidReadonlyERoot("ERROR: malformed READONLY_EPREFIX in %s" % (ro_make_conf))
-+
-+					if ro_cfg_root is not None:
-+						raise portage.exception.InvalidReadonlyERoot("ERROR: duplicate READONLY_EPREFIX in %s and %s" % tuple(ro_make_conf_paths))
-+
-+					(ro_cfg_root,ro_cfg_root_deps) = ro_cfg["READONLY_EPREFIX"].rsplit(":",1)
-+
-+					if not os.path.exists(ro_cfg_root):
-+						raise portage.exception.InvalidReadonlyERoot("ERROR: malformed READONLY_EPREFIX in %s: %s does not exist!" % (ro_make_conf, ro_cfg_root))
-+
-+					if os.path.samefile(ro_cfg_root, config_root):
-+						raise portage.exception.InvalidReadonlyERoot("ERROR: cannot add this instance (%s) as READONLY_EPREFIX in %s." % (ro_cfg_root, ro_make_conf))
-+
-+					if ro_cfg_root in self.readonly_prefixes:
-+						raise portage.exception.InvalidReadonlyERoot("ERROR: circular READONLY_EPREFIX's in %s. %s already checked for %s" % (ro_make_conf, ro_cfg_root, self.readonly_prefixes[ro_cfg_root])) 
-+
-+					# intersect the widest depset with the current one to strip down
-+					# the allowed dependency resolution to not be wider than the
-+					# next higher one. this way we can prevent for a given prefix
-+					# to resolve RDEPENDs from a prefix with a different CHOST that
-+					# is a few levels deeper in the chain.
-+					ro_widest_depset = set(ro_cfg_root_deps.split(",")) & ro_widest_depset
-+					self.readonly_prefixes[ro_cfg_root] = ro_widest_depset
-+				pass
-+
- 			for k in self._case_insensitive_vars:
- 				if k in self:
- 					self[k] = self[k].lower()
-@@ -2813,6 +2871,10 @@ class config(object):
- 		if not eapi_exports_merge_type(eapi):
- 			mydict.pop("MERGE_TYPE", None)
- 
-+		# populate with PORTAGE_READONLY_EPREFIXES
-+		if self.readonly_prefixes and len(self.readonly_prefixes) > 0:
-+			mydict["PORTAGE_READONLY_EPREFIXES"] = ':'.join(self.readonly_prefixes)
-+
- 		# Prefix variables are supported beginning with EAPI 3, or when
- 		# force-prefix is in FEATURES, since older EAPIs would otherwise be
- 		# useless with prefix configurations. This brings compatibility with
-diff --git a/pym/portage/package/ebuild/doebuild.py b/pym/portage/package/ebuild/doebuild.py
-index a24f8fec8..82fcba9e2 100644
---- a/pym/portage/package/ebuild/doebuild.py
-+++ b/pym/portage/package/ebuild/doebuild.py
-@@ -51,6 +51,7 @@ from portage import bsd_chflags, \
- 	unmerge, _encodings, _os_merge, \
- 	_shell_quote, _unicode_decode, _unicode_encode
- from portage.const import EBUILD_SH_ENV_FILE, EBUILD_SH_ENV_DIR, \
-+    GLOBAL_CONFIG_PATH, \
- 	EBUILD_SH_BINARY, INVALID_ENV_FILE, MISC_SH_BINARY, PORTAGE_PYM_PACKAGES, EPREFIX, MACOSSANDBOX_PROFILE
- from portage.data import portage_gid, portage_uid, secpass, \
- 	uid, userpriv_groups
-@@ -72,6 +73,7 @@ from portage.package.ebuild.prepare_build_dirs import prepare_build_dirs
- from portage.process import find_binary
- from portage.util import ( apply_recursive_permissions,
- 	apply_secpass_permissions,
-+	getconfig,
- 	noiselimit,
- 	shlex_split,
- 	varexpand,
-@@ -79,6 +81,7 @@ from portage.util import ( apply_recursive_permissions,
- 	writemsg_stdout,
- 	write_atomic
- 	)
-+from portage.util._path import exists_raise_eaccess
- from portage.util.cpuinfo import get_cpu_count
- from portage.util.lafilefixer import rewrite_lafile
- from portage.util.compression_probe import _compressors
-@@ -241,8 +244,27 @@ def _doebuild_path(settings, eapi=None):
- 
- 	for x in portage_bin_path:
- 		path.append(os.path.join(x, "ebuild-helpers"))
-+
-+	# PREFIX CHAINING: append default path for all prefixes involved
-+	pfxs = [ eprefix ]
-+	pfxs.extend(settings.readonly_prefixes)
-+	for prefix in pfxs:
-+		global_config_path = os.path.join(prefix, GLOBAL_CONFIG_PATH.lstrip(os.sep))
-+		make_globals_path = os.path.join(global_config_path, "make.globals")
-+		if exists_raise_eaccess(make_globals_path):
-+			expand_map = { "EPREFIX": prefix }
-+			pxcfg = getconfig(make_globals_path, True, expand_map)
-+			pxdefp = [x for x in pxcfg.get("DEFAULT_PATH", "").split(":") if x]
-+			for x in pxdefp:
-+				if x.startswith(prefix) and not x in path:
-+					path.append(x)
-+		else:
-+			pxdefs = [prefix + "/usr/sbin", prefix + "/usr/bin", prefix + "/sbin", prefix + "/bin"]
-+			path.extend(pxdefs)
-+	# END PREFIX CHAINING
-+
- 	path.extend(prerootpath)
--	path.extend(defaultpath)
-+	# path.extend(defaultpath) # PREFIX CHAINING appends the default path for involved prefixes above
- 	path.extend(rootpath)
- 	path.extend(extrapath)
- 	# END PREFIX LOCAL
-diff --git a/pym/portage/package/ebuild/fetch.py b/pym/portage/package/ebuild/fetch.py
-index 265d0c9fc..2ec6ff472 100644
---- a/pym/portage/package/ebuild/fetch.py
-+++ b/pym/portage/package/ebuild/fetch.py
-@@ -43,6 +43,7 @@ from portage.output import colorize, EOutput
- from portage.util import apply_recursive_permissions, \
- 	apply_secpass_permissions, ensure_dirs, grabdict, shlex_split, \
- 	varexpand, writemsg, writemsg_level, writemsg_stdout
-+from portage.util._path import exists_raise_eaccess
- from portage.process import spawn
- 
- _userpriv_spawn_kwargs = (
-@@ -874,6 +875,9 @@ def fetch(myuris, mysettings, listonly=0, fetchonly=0,
- 				global_config_path = GLOBAL_CONFIG_PATH
- 				if portage.const.EPREFIX:
- 					global_config_path = os.path.join(portage.const.EPREFIX,
-+						GLOBAL_CONFIG_PATH.lstrip(os.sep))
-+					if not exists_raise_eaccess(global_config_path) and portage.const.BPREFIX:
-+						global_config_path = os.path.join(portage.const.BPREFIX,
- 							GLOBAL_CONFIG_PATH.lstrip(os.sep))
- 
- 				missing_file_param = False
-diff --git a/pym/portage/sync/controller.py b/pym/portage/sync/controller.py
-index 3bccf6f74..cacd63797 100644
---- a/pym/portage/sync/controller.py
-+++ b/pym/portage/sync/controller.py
-@@ -94,19 +94,20 @@ class SyncManager(object):
- 		self.module_controller = portage.sync.module_controller
- 		self.module_names = self.module_controller.module_names
- 		self.hooks = {}
--		for _dir in ["repo.postsync.d", "postsync.d"]:
--			postsync_dir = os.path.join(self.settings["PORTAGE_CONFIGROOT"],
--				portage.USER_CONFIG_PATH, _dir)
--			hooks = OrderedDict()
--			for filepath in util._recursive_file_list(postsync_dir):
--				name = filepath.split(postsync_dir)[1].lstrip(os.sep)
--				if os.access(filepath, os.X_OK):
--					hooks[filepath] = name
--				else:
--					writemsg_level(" %s %s hook: '%s' is not executable\n"
--						% (warn("*"), _dir, _unicode_decode(name),),
--						level=logging.WARN, noiselevel=2)
--			self.hooks[_dir] = hooks
-+		for _confroot in [self.settings["PORTAGE_CONFIGROOT"], portage.const.BPREFIX]:
-+			for _dir in ["repo.postsync.d", "postsync.d"]:
-+					postsync_dir = os.path.join(_confroot,
-+						portage.USER_CONFIG_PATH, _dir)
-+					hooks = OrderedDict()
-+					for filepath in util._recursive_file_list(postsync_dir):
-+						name = filepath.split(postsync_dir)[1].lstrip(os.sep)
-+						if os.access(filepath, os.X_OK):
-+							hooks[filepath] = name
-+						else:
-+							writemsg_level(" %s %s hook: '%s' is not executable\n"
-+								% (warn("*"), _dir, _unicode_decode(name),),
-+								level=logging.WARN, noiselevel=2)
-+					self.hooks[_dir] = hooks
- 
- 	def __getattr__(self, name):
- 		if name == 'async':
-diff --git a/pym/portage/util/_dyn_libs/LinkageMapELF.py b/pym/portage/util/_dyn_libs/LinkageMapELF.py
-index a063621c1..968fbd339 100644
---- a/pym/portage/util/_dyn_libs/LinkageMapELF.py
-+++ b/pym/portage/util/_dyn_libs/LinkageMapELF.py
-@@ -12,7 +12,7 @@ from portage import _os_merge
- from portage import _unicode_decode
- from portage import _unicode_encode
- from portage.cache.mappings import slot_dict_class
--from portage.const import EPREFIX
-+from portage.const import BPREFIX
- from portage.dep.soname.multilib_category import compute_multilib_category
- from portage.exception import CommandNotFound, InvalidData
- from portage.localization import _
-@@ -268,7 +268,7 @@ class LinkageMapELF(object):
- 					continue
- 				plibs.update((x, cpv) for x in items)
- 		if plibs:
--			args = [os.path.join(EPREFIX or "/", "usr/bin/scanelf"), "-qF", "%a;%F;%S;%r;%n"]
-+			args = [os.path.join(BPREFIX or "/", "usr/bin/scanelf"), "-qF", "%a;%F;%S;%r;%n"]
- 			args.extend(os.path.join(root, x.lstrip("." + os.sep)) \
- 				for x in plibs)
- 			try:
--- 
-2.13.6
-

diff --git a/sys-apps/portage/files/portage-2.3.40-prefix-chaining.patch b/sys-apps/portage/files/portage-2.3.40-prefix-chaining.patch
deleted file mode 100644
index 8e0864990d..0000000000
--- a/sys-apps/portage/files/portage-2.3.40-prefix-chaining.patch
+++ /dev/null
@@ -1,921 +0,0 @@
-From 9c991762d6becb779925d59289eb0324f269ad18 Mon Sep 17 00:00:00 2001
-From: Michael Haubenwallner <haubi@gentoo.org>
-Date: Thu, 23 Mar 2017 13:52:32 +0100
-Subject: [PATCH 2/2] add prefix-chaining support
-
----
- bin/install-qa-check.d/05prefix                    | 30 ++++++-
- bin/phase-helpers.sh                               | 24 ++++++
- pym/_emerge/actions.py                             |  6 +-
- pym/_emerge/depgraph.py                            | 53 +++++++-----
- pym/_emerge/resolver/output.py                     | 40 ++++++++-
- pym/portage/_sets/__init__.py                      |  5 ++
- pym/portage/const.py                               |  6 ++
- pym/portage/dbapi/vartree.py                       | 34 ++++++--
- pym/portage/dep/dep_check.py                       | 99 +++++++++++++++++++++-
- .../package/ebuild/_config/LocationsManager.py     |  3 +
- pym/portage/package/ebuild/config.py               | 62 ++++++++++++++
- pym/portage/package/ebuild/doebuild.py             | 24 +++++-
- pym/portage/package/ebuild/fetch.py                |  4 +
- pym/portage/sync/controller.py                     | 27 +++---
- pym/portage/util/_dyn_libs/LinkageMapELF.py        |  4 +-
- 15 files changed, 373 insertions(+), 48 deletions(-)
-
-diff --git a/bin/install-qa-check.d/05prefix b/bin/install-qa-check.d/05prefix
-index 32561e263..0c1147367 100644
---- a/bin/install-qa-check.d/05prefix
-+++ b/bin/install-qa-check.d/05prefix
-@@ -79,16 +79,42 @@ install_qa_check_prefix() {
- 		# unprefixed shebang, is the script directly in $PATH or an init
- 		# script?
- 		if [[ ":${PATH}:${EPREFIX}/etc/init.d:" == *":${fp}:"* ]] ; then
--			if [[ -e ${EROOT}${line[0]} || -e ${ED}${line[0]} ]] ; then
-+			all_epfs="$PORTAGE_READONLY_EPREFIXES:$EPREFIX:$EROOT:$ED"
-+			save_IFS=$IFS
-+			IFS=:
-+			epfs=( $all_epfs )
-+			IFS=$save_IFS
-+
-+			found=
-+			for x in "${epfs[@]}"; do
-+				[[ -z "${x}" ]] && continue
-+				check="${x}${line[0]}"
-+
-+				# might already contain a prefix
-+				if [[ "${line[0]}" == "${x}"* ]]; then
-+					check="${line[0]}"
-+				fi
-+
-+				if [[ -e ${check} ]]; then
-+					found="${check}"
-+				fi
-+			done
-+
-+			if [[ -n ${found} ]] ; then
- 				# is it unprefixed, but we can just fix it because a
- 				# prefixed variant exists
- 				eqawarn "prefixing shebang of ${fn#${D}}"
-+
-+				if [[ ${found} == "${ED}"* || ${found} == "${EROOT}"* ]]; then
-+					found="${EPREFIX}${line[0]}"
-+				fi
-+
- 				# statement is made idempotent on purpose, because
- 				# symlinks may point to the same target, and hence the
- 				# same real file may be sedded multiple times since we
- 				# read the shebangs in one go upfront for performance
- 				# reasons
--				sed -i -e '1s:^#! \?'"${line[0]}"':#!'"${EPREFIX}"${line[0]}':' "${rf}"
-+				sed -i -e '1s:^#! \?'"${line[0]}"':#!'"${found}"':' "${rf}"
- 				continue
- 			else
- 				# this is definitely wrong: script in $PATH and invalid shebang
-diff --git a/bin/phase-helpers.sh b/bin/phase-helpers.sh
-index 75d92b407..c32533fb3 100644
---- a/bin/phase-helpers.sh
-+++ b/bin/phase-helpers.sh
-@@ -934,6 +934,10 @@ ___best_version_and_has_version_common() {
- 	fi
- 	"${cmd[@]}"
- 	local retval=$?
-+	if [[ ${retval} -eq 1 && -n ${READONLY_EPREFIX} ]]; then
-+		${SHELL} -c "EPREFIX='${READONLY_EPREFIX%:*}' EPYTHON= '${PORTAGE_BIN_PATH}/ebuild-helpers/portageq' '${FUNCNAME[1]}' '${READONLY_EPREFIX%:*}' '${atom}'"
-+		retval=$?
-+	fi
- 	case "${retval}" in
- 		0|1)
- 			return ${retval}
-@@ -1194,6 +1198,10 @@ if ___eapi_has_master_repositories; then
- 			output=$("${PORTAGE_BIN_PATH}/ebuild-helpers/portageq" master_repositories "${EROOT}" "${repository}")
- 		fi
- 		retval=$?
-+		if [[ ${retval} -eq 1 && -n ${READONLY_EPREFIX} ]]; then
-+			output=$(${SHELL} -c "EPREFIX='${READONLY_EPREFIX%:*}' EPYTHON= '${PORTAGE_BIN_PATH}/ebuild-helpers/portageq' master_repositories '${READONLY_EPREFIX%:*}' '${repository}'")
-+			retval=$?
-+		fi
- 		[[ -n ${output} ]] && echo "${output}"
- 		case "${retval}" in
- 			0|1)
-@@ -1225,6 +1233,10 @@ if ___eapi_has_repository_path; then
- 			output=$("${PORTAGE_BIN_PATH}/ebuild-helpers/portageq" get_repo_path "${EROOT}" "${repository}")
- 		fi
- 		retval=$?
-+		if [[ ${retval} -eq 1 && -n ${READONLY_EPREFIX} ]]; then
-+			output=$(${SHELL} -c "EPREFIX='${READONLY_EPREFIX%:*}' EPYTHON= '${PORTAGE_BIN_PATH}/ebuild-helpers/portageq' get_repo_path '${READONLY_EPREFIX%:*}' '${repository}'")
-+			retval=$?
-+		fi
- 		[[ -n ${output} ]] && echo "${output}"
- 		case "${retval}" in
- 			0|1)
-@@ -1255,6 +1267,10 @@ if ___eapi_has_available_eclasses; then
- 			output=$("${PORTAGE_BIN_PATH}/ebuild-helpers/portageq" available_eclasses "${EROOT}" "${repository}")
- 		fi
- 		retval=$?
-+		if [[ ${retval} -eq 1 && -n ${READONLY_EPREFIX} ]]; then
-+			output=$(${SHELL} -c "EPREFIX='${READONLY_EPREFIX%:*}' EPYTHON= '${PORTAGE_BIN_PATH}/ebuild-helpers/portageq' available_eclasses '${READONLY_EPREFIX%:*}' '${repository}'")
-+			retval=$?
-+		fi
- 		[[ -n ${output} ]] && echo "${output}"
- 		case "${retval}" in
- 			0|1)
-@@ -1285,6 +1301,10 @@ if ___eapi_has_eclass_path; then
- 		else
- 			output=$("${PORTAGE_BIN_PATH}/ebuild-helpers/portageq" eclass_path "${EROOT}" "${repository}" "${eclass}")
- 		fi
-+		if [[ ${retval} -eq 1 && -n ${READONLY_EPREFIX} ]]; then
-+			output=$(${SHELL} -c "EPREFIX='${READONLY_EPREFIX%:*}' EPYTHON= '${PORTAGE_BIN_PATH}/ebuild-helpers/portageq' eclass_path '${READONLY_EPREFIX%:*}' '${repository}' '${eclass}'")
-+			retval=$?
-+		fi
- 		retval=$?
- 		[[ -n ${output} ]] && echo "${output}"
- 		case "${retval}" in
-@@ -1316,6 +1336,10 @@ if ___eapi_has_license_path; then
- 		else
- 			output=$("${PORTAGE_BIN_PATH}/ebuild-helpers/portageq" license_path "${EROOT}" "${repository}" "${license}")
- 		fi
-+		if [[ ${retval} -eq 1 && -n ${READONLY_EPREFIX} ]]; then
-+			output=(${SHELL} -c "EPREFIX='${READONLY_EPREFIX%:*}' EPYTHON= '${PORTAGE_BIN_PATH}/ebuild-helpers/portageq' license_path '${READONLY_EPREFIX%:*}' '${repository}' '${license}'")
-+			retval=$?
-+		fi
- 		retval=$?
- 		[[ -n ${output} ]] && echo "${output}"
- 		case "${retval}" in
-diff --git a/pym/_emerge/actions.py b/pym/_emerge/actions.py
-index 432fc57e3..764462fc5 100644
---- a/pym/_emerge/actions.py
-+++ b/pym/_emerge/actions.py
-@@ -39,7 +39,7 @@ from portage import os
- from portage import shutil
- from portage import eapi_is_supported, _encodings, _unicode_decode
- from portage.cache.cache_errors import CacheError
--from portage.const import EPREFIX
-+from portage.const import EPREFIX, BPREFIX
- from portage.const import GLOBAL_CONFIG_PATH, VCS_DIRS, _DEPCLEAN_LIB_CHECK_DEFAULT
- from portage.const import SUPPORTED_BINPKG_FORMATS, TIMESTAMP_FORMAT
- from portage.dbapi.dep_expand import dep_expand
-@@ -65,6 +65,7 @@ from portage.util.SlotObject import SlotObject
- from portage.util._async.run_main_scheduler import run_main_scheduler
- from portage.util._async.SchedulerInterface import SchedulerInterface
- from portage.util._eventloop.global_event_loop import global_event_loop
-+from portage.util._path import exists_raise_eaccess
- from portage._global_updates import _global_updates
- from portage.sync.old_tree_timestamp import old_tree_timestamp_warn
- from portage.localization import _
-@@ -2672,6 +2673,9 @@ def missing_sets_warning(root_config, missing_sets):
- 	if portage.const.EPREFIX:
- 		global_config_path = os.path.join(portage.const.EPREFIX,
- 				portage.const.GLOBAL_CONFIG_PATH.lstrip(os.sep))
-+		if not exists_raise_eaccess(global_config_path) and portage.const.BPREFIX:
-+			global_config_path = os.path.join(portage.const.BPREFIX,
-+                    portage.const.GLOBAL_CONFIG_PATH.lstrip(os.sep))
- 	msg.append("        This usually means that '%s'" % \
- 		(os.path.join(global_config_path, "sets/portage.conf"),))
- 	msg.append("        is missing or corrupt.")
-diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py
-index f7bac69f9..a6eb0d3d4 100644
---- a/pym/_emerge/depgraph.py
-+++ b/pym/_emerge/depgraph.py
-@@ -3355,19 +3355,19 @@ class depgraph(object):
- 		# _dep_disjunctive_stack first, so that choices for build-time
- 		# deps influence choices for run-time deps (bug 639346).
- 		deps = (
--			(myroot, edepend["RDEPEND"],
-+			(myroot, "RDEPEND",
- 				self._priority(runtime=True)),
--			(myroot, edepend["PDEPEND"],
-+			(myroot, "PDEPEND",
- 				self._priority(runtime_post=True)),
--			(depend_root, edepend["DEPEND"],
-+			(depend_root, "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._frozen_config._running_root.root, "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._frozen_config._running_root.root, "BDEPEND",
- 				self._priority(buildtime=True,
- 				optional=(pkg.built or ignore_bdepend_deps),
- 				ignored=ignore_bdepend_deps)),
-@@ -3375,7 +3375,8 @@ class depgraph(object):
- 
- 		debug = "--debug" in self._frozen_config.myopts
- 
--		for dep_root, dep_string, dep_priority in deps:
-+		for dep_root, dep_type, dep_priority in deps:
-+				dep_string = edepend[dep_type]
- 				if not dep_string:
- 					continue
- 				if debug:
-@@ -3413,7 +3414,7 @@ class depgraph(object):
- 
- 				try:
- 					dep_string = list(self._queue_disjunctive_deps(
--						pkg, dep_root, dep_priority, dep_string))
-+						pkg, dep_root, dep_priority, dep_string, dep_type))
- 				except portage.exception.InvalidDependString as e:
- 					if pkg.installed:
- 						self._dynamic_config._masked_installed.add(pkg)
-@@ -3428,14 +3429,14 @@ class depgraph(object):
- 
- 				if not self._add_pkg_dep_string(
- 					pkg, dep_root, dep_priority, dep_string,
--					allow_unsatisfied):
-+					allow_unsatisfied, dep_type):
- 					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):
-+		allow_unsatisfied, dep_type=None):
- 		_autounmask_backup = self._dynamic_config._autounmask
- 		if dep_priority.optional or dep_priority.ignored:
- 			# Temporarily disable autounmask for deps that
-@@ -3444,7 +3445,7 @@ class depgraph(object):
- 		try:
- 			return self._wrapped_add_pkg_dep_string(
- 				pkg, dep_root, dep_priority, dep_string,
--				allow_unsatisfied)
-+				allow_unsatisfied, dep_type)
- 		finally:
- 			self._dynamic_config._autounmask = _autounmask_backup
- 
-@@ -3480,7 +3481,7 @@ class depgraph(object):
- 			not slot_operator_rebuild
- 
- 	def _wrapped_add_pkg_dep_string(self, pkg, dep_root, dep_priority,
--		dep_string, allow_unsatisfied):
-+		dep_string, allow_unsatisfied, dep_type=None):
- 		if isinstance(pkg.depth, int):
- 			depth = pkg.depth + 1
- 		else:
-@@ -3504,7 +3505,7 @@ class depgraph(object):
- 		try:
- 			selected_atoms = self._select_atoms(dep_root,
- 				dep_string, myuse=self._pkg_use_enabled(pkg), parent=pkg,
--				strict=strict, priority=dep_priority)
-+				strict=strict, priority=dep_priority, dep_type=dep_type)
- 		except portage.exception.InvalidDependString:
- 			if pkg.installed:
- 				self._dynamic_config._masked_installed.add(pkg)
-@@ -3811,7 +3812,7 @@ class depgraph(object):
- 					child_pkgs.sort()
- 				yield (atom, child_pkgs[-1])
- 
--	def _queue_disjunctive_deps(self, pkg, dep_root, dep_priority, dep_struct):
-+	def _queue_disjunctive_deps(self, pkg, dep_root, dep_priority, dep_struct, dep_type=None):
- 		"""
- 		Queue disjunctive (virtual and ||) deps in self._dynamic_config._dep_disjunctive_stack.
- 		Yields non-disjunctive deps. Raises InvalidDependString when
-@@ -3820,33 +3821,33 @@ class depgraph(object):
- 		for x in dep_struct:
- 			if isinstance(x, list):
- 				if x and x[0] == "||":
--					self._queue_disjunction(pkg, dep_root, dep_priority, [x])
-+					self._queue_disjunction(pkg, dep_root, dep_priority, [x], dep_type)
- 				else:
- 					for y in self._queue_disjunctive_deps(
--						pkg, dep_root, dep_priority, x):
-+						pkg, dep_root, dep_priority, x, dep_type):
- 						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])
-+					self._queue_disjunction(pkg, dep_root, dep_priority, [x], dep_type)
- 				else:
- 					yield x
- 
--	def _queue_disjunction(self, pkg, dep_root, dep_priority, dep_struct):
-+	def _queue_disjunction(self, pkg, dep_root, dep_priority, dep_struct, dep_type=None):
- 		self._dynamic_config._dep_disjunctive_stack.append(
--			(pkg, dep_root, dep_priority, dep_struct))
-+			(pkg, dep_root, dep_priority, dep_struct, dep_type))
- 
- 	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 = \
-+		pkg, dep_root, dep_priority, dep_struct, dep_type = \
- 			self._dynamic_config._dep_disjunctive_stack.pop()
- 		if not self._add_pkg_dep_string(
--			pkg, dep_root, dep_priority, dep_struct, allow_unsatisfied):
-+			pkg, dep_root, dep_priority, dep_struct, allow_unsatisfied, dep_type):
- 			return 0
- 		return 1
- 
-@@ -4699,7 +4700,7 @@ class depgraph(object):
- 		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):
-+		myuse=None, parent=None, strict=True, trees=None, priority=None, dep_type=None):
- 		"""This will raise InvalidDependString if necessary. If trees is
- 		None then self._dynamic_config._filtered_trees is used."""
- 
-@@ -4722,6 +4723,13 @@ class depgraph(object):
- 		pkgsettings = self._frozen_config.pkgsettings[root]
- 		if trees is None:
- 			trees = self._dynamic_config._filtered_trees
-+
-+		# this one is needed to guarantee good readonly root
-+		# resolution display in the merge list. required since
-+		# parent (below) can be None
-+		trees[root]["disp_parent"] = parent
-+
-+
- 		mytrees = trees[root]
- 		atom_graph = digraph()
- 		if True:
-@@ -4753,7 +4761,7 @@ class depgraph(object):
- 
- 				mycheck = portage.dep_check(depstring, None,
- 					pkgsettings, myuse=myuse,
--					myroot=root, trees=trees)
-+					myroot=root, trees=trees, dep_type=dep_type)
- 			finally:
- 				# restore state
- 				self._dynamic_config._autounmask = _autounmask_backup
-@@ -4829,6 +4837,7 @@ class depgraph(object):
- 							continue
- 						node_stack.append((child_node, node, child_atom))
- 
-+		trees[root].pop("disp_parent")
- 		return selected_atoms
- 
- 	def _expand_virt_from_graph(self, root, atom):
-diff --git a/pym/_emerge/resolver/output.py b/pym/_emerge/resolver/output.py
-index 24340576c..4a1741f3a 100644
---- a/pym/_emerge/resolver/output.py
-+++ b/pym/_emerge/resolver/output.py
-@@ -22,11 +22,12 @@ from portage.localization import localized_size
- from portage.package.ebuild.config import _get_feature_flags
- from portage.package.ebuild._spawn_nofetch import spawn_nofetch
- from portage.output import ( blue, colorize, create_color_func,
--	darkblue, darkgreen, green, nc_len, teal)
-+	darkblue, darkgreen, green, nc_len, teal, yellow, turquoise)
- bad = create_color_func("BAD")
- from portage._sets.base import InternalPackageSet
- from portage.util import writemsg_stdout
- from portage.versions import best, cpv_getversion
-+from portage.dep.dep_check import ro_selected
- 
- from _emerge.Blocker import Blocker
- from _emerge.create_world_atom import create_world_atom
-@@ -563,6 +564,42 @@ class Display(object):
- 			writemsg_stdout("%s\n" % (pkg,), noiselevel=-1)
- 		return
- 
-+	def print_readonly_prefix(self):
-+		"""Performs the actual output printing for the readonly prefix
-+		information stuff
-+		"""
-+		out = sys.stdout
-+
-+        # print readonly selected packages
-+		if len(ro_selected) > 0:
-+			out.write("\n%s\n\n" % (darkgreen("Packages resolved from readonly installations:")))
-+
-+		ro_mismatch_warning = False
-+		ro_dupcheck = []
-+		for x in ro_selected:
-+			tmp_type = x["type"].replace("END","")
-+			while len(tmp_type) < 4:
-+				tmp_type += " "
-+			if x["parent"] and str(x["atom"]) not in ro_dupcheck:
-+				out.write("[%s %s] %s %s %s (%s by %s)" % (teal("readonly"),
-+					green(tmp_type), green(str(x["matches"][0])), yellow("from"),
-+					blue(x["ro_root"]), turquoise(str(x["atom"])), green(x["parent"].cpv)))
-+
-+				ro_dupcheck.append(str(x["atom"]))
-+
-+				if x["host_mismatch"]:
-+					ro_mismatch_warning = True
-+					out.write(" %s\n" % (red("**")))
-+				else:
-+					out.write("\n")
-+
-+		if ro_mismatch_warning:
-+			out.write("\n%s:" % (red("**")))
-+			out.write(yellow(" WARNING: packages marked with ** have been resolved as a\n"))
-+			out.write(yellow("    runtime dependency, but the CHOST variable for the parent\n"))
-+			out.write(yellow("    and dependency package don't match. This could cause link\n"))
-+			out.write(yellow("    errors. It is recommended to use RDEPEND READONLY_EPREFIX's\n"))
-+			out.write(yellow("    only with matching CHOST portage instances.\n"))
- 
- 	def print_verbose(self, show_repos):
- 		"""Prints the verbose output to std_out
-@@ -913,6 +950,7 @@ class Display(object):
- 		show_repos = self.quiet_repo_display and repoadd_set and repoadd_set != set(["0"])
- 
- 		# now finally print out the messages
-+		self.print_readonly_prefix()
- 		self.print_messages(show_repos)
- 		self.print_blockers()
- 		if self.conf.verbosity == 3:
-diff --git a/pym/portage/_sets/__init__.py b/pym/portage/_sets/__init__.py
-index 2c9bf9715..6a2784207 100644
---- a/pym/portage/_sets/__init__.py
-+++ b/pym/portage/_sets/__init__.py
-@@ -21,6 +21,7 @@ from portage.const import _ENABLE_SET_CONFIG
- from portage.exception import PackageSetNotFound
- from portage.localization import _
- from portage.util import writemsg_level
-+from portage.util._path import exists_raise_eaccess
- from portage.util.configparser import (SafeConfigParser,
- 	NoOptionError, ParsingError, read_configs)
- 
-@@ -281,6 +282,10 @@ def load_default_config(settings, trees):
- 	if portage.const.EPREFIX:
- 		global_config_path = os.path.join(portage.const.EPREFIX,
- 			GLOBAL_CONFIG_PATH.lstrip(os.sep))
-+		if not exists_raise_eaccess(global_config_path) and portage.const.BPREFIX:
-+			global_config_path = os.path.join(portage.const.BPREFIX,
-+				GLOBAL_CONFIG_PATH.lstrip(os.sep))
-+
- 	vcs_dirs = [_unicode_encode(x, encoding=_encodings['fs']) for x in VCS_DIRS]
- 	def _getfiles():
- 		for path, dirs, files in os.walk(os.path.join(global_config_path, "sets")):
-diff --git a/pym/portage/const.py b/pym/portage/const.py
-index d9c57f300..a3d927c3b 100644
---- a/pym/portage/const.py
-+++ b/pym/portage/const.py
-@@ -190,6 +190,7 @@ SUPPORTED_FEATURES       = frozenset([
- 	"notitles",
- 	"parallel-fetch",
- 	"parallel-install",
-+	"prefix-chaining",
- 	"prelink-checksums",
- 	"preserve-libs",
- 	"protect-owned",
-@@ -241,6 +242,11 @@ MANIFEST2_IDENTIFIERS    = ("AUX", "MISC", "DIST", "EBUILD")
- #EPREFIX = ""
- # END PREFIX LOCAL
- 
-+BPREFIX = EPREFIX
-+
-+# --prefix commandline arg always rules, ends up in os.environ["EPREFIX"]
-+if "EPREFIX" in os.environ:
-+    os.environ["PORTAGE_OVERRIDE_EPREFIX"] = os.environ["EPREFIX"]
- # pick up EPREFIX from the environment if set
- if "PORTAGE_OVERRIDE_EPREFIX" in os.environ:
- 	EPREFIX = os.environ["PORTAGE_OVERRIDE_EPREFIX"]
-diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py
-index 77a72b5b1..f20c6763e 100644
---- a/pym/portage/dbapi/vartree.py
-+++ b/pym/portage/dbapi/vartree.py
-@@ -196,8 +196,19 @@ class vardbapi(dbapi):
- 		self._counter_path = os.path.join(self._eroot,
- 			CACHE_PATH, "counter")
- 
--		self._plib_registry = PreservedLibsRegistry(settings["ROOT"],
--			os.path.join(self._eroot, PRIVATE_PATH, "preserved_libs_registry"))
-+		plibreg_path = os.path.join(self._eroot, PRIVATE_PATH, "preserved_libs_registry")
-+
-+		if vartree:
-+			self._kill_eprefix = vartree._kill_eprefix
-+		else:
-+			self._kill_eprefix = False
-+
-+		if self._kill_eprefix:
-+			self._aux_cache_filename = self._aux_cache_filename.replace(EPREFIX, "")
-+			self._counter_path = self._counter_path.replace(EPREFIX, "")
-+			plibreg_path = plibreg_path.replace(EPREFIX, "")
-+
-+		self._plib_registry = PreservedLibsRegistry(settings["ROOT"], plibreg_path)
- 		self._linkmap = LinkageMap(self)
- 		chost = self.settings.get('CHOST')
- 		if not chost:
-@@ -238,6 +249,9 @@ class vardbapi(dbapi):
- 		# This is an optimized hotspot, so don't use unicode-wrapped
- 		# os module and don't use os.path.join().
- 		rValue = self._eroot + VDB_PATH + _os.sep + mykey
-+		if self._kill_eprefix:
-+			rValue = rValue.replace(EPREFIX, "")
-+
- 		if filename is not None:
- 			# If filename is always relative, we can do just
- 			# rValue += _os.sep + filename
-@@ -502,6 +516,9 @@ class vardbapi(dbapi):
- 		returnme = []
- 		basepath = os.path.join(self._eroot, VDB_PATH) + os.path.sep
- 
-+		if self._kill_eprefix:
-+			basepath = os.path.join(self.root, basepath.replace(EPREFIX, ""))
-+
- 		if use_cache:
- 			from portage import listdir
- 		else:
-@@ -598,11 +615,17 @@ class vardbapi(dbapi):
- 				del self.matchcache[mycat]
- 			return list(self._iter_match(mydep,
- 				self.cp_list(mydep.cp, use_cache=use_cache)))
-+
-+		_tmp_path = os.path.join(self._eroot, VDB_PATH, mycat)
-+
-+		if self._kill_eprefix:
-+			_tmp_path = _tmp_path.replace(EPREFIX, "")
-+
- 		try:
- 			if sys.hexversion >= 0x3030000:
--				curmtime = os.stat(os.path.join(self._eroot, VDB_PATH, mycat)).st_mtime_ns
-+				curmtime = os.stat(_tmp_path).st_mtime_ns
- 			else:
--				curmtime = os.stat(os.path.join(self._eroot, VDB_PATH, mycat)).st_mtime
-+				curmtime = os.stat(_tmp_path).st_mtime
- 		except (IOError, OSError):
- 			curmtime=0
- 
-@@ -1450,7 +1473,7 @@ class vardbapi(dbapi):
- class vartree(object):
- 	"this tree will scan a var/db/pkg database located at root (passed to init)"
- 	def __init__(self, root=None, virtual=DeprecationWarning, categories=None,
--		settings=None):
-+		settings=None, kill_eprefix=None):
- 
- 		if settings is None:
- 			settings = portage.settings
-@@ -1468,6 +1491,7 @@ class vartree(object):
- 				" constructor is unused",
- 				DeprecationWarning, stacklevel=2)
- 
-+		self._kill_eprefix = kill_eprefix
- 		self.settings = settings
- 		self.dbapi = vardbapi(settings=settings, vartree=self)
- 		self.populated = 1
-diff --git a/pym/portage/dep/dep_check.py b/pym/portage/dep/dep_check.py
-index 2896e2389..c700a3651 100644
---- a/pym/portage/dep/dep_check.py
-+++ b/pym/portage/dep/dep_check.py
-@@ -298,6 +298,95 @@ class _dep_choice(SlotObject):
- 	__slots__ = ('atoms', 'slot_map', 'cp_map', 'all_available',
- 		'all_installed_slots', 'new_slot_count')
- 
-+ro_trees={}
-+ro_vartrees={}
-+ro_selected=[]
-+
-+def dep_match_readonly_roots(settings, atom, dep_type, parent=None):
-+   if len(ro_trees) < len(settings.readonly_prefixes):
-+       # MDUFT: create additional vartrees for every readonly root here.
-+       # the ro_vartrees instances are created below as they are needed to
-+       # avoid reading vartrees of portage instances which aren't required
-+       # while resolving this dependencies.
-+       for type in ("DEPEND","RDEPEND", "PDEPEND"):
-+           ro_trees[type] = []
-+
-+           for ro_root, ro_dep_types in settings.readonly_prefixes.items():
-+               if type in ro_dep_types:
-+                   ro_trees[type].append(ro_root)
-+
-+   if len(ro_trees) == 0:
-+       return []
-+
-+   matches = []
-+
-+   for ro_root in ro_trees[dep_type]:
-+       if not ro_root in ro_vartrees:
-+           # target_root=ro_root ok? or should it be the real target_root?
-+           _tmp_settings = portage.config(config_root=ro_root, target_root=ro_root,
-+               config_incrementals=portage.const.INCREMENTALS)
-+
-+           ro_vartrees[ro_root] = portage.vartree(root=ro_root,
-+               categories=_tmp_settings.categories,
-+               settings=_tmp_settings, kill_eprefix=True)
-+
-+       ro_matches = ro_vartrees[ro_root].dbapi.match(atom)
-+
-+       if ro_matches:
-+           ro_host_mismatch = False
-+           if dep_type is "RDEPEND":
-+               # we need to assure binary compatability, so it needs to be
-+               # the same CHOST! But how? for now i cannot do anything...
-+               if parent and parent.metadata["CHOST"] != ro_vartrees[ro_root].settings.get("CHOST", ""):
-+                   # provocate a big fat warning in the list of external packages.
-+                   ro_host_mismatch = True
-+               pass
-+
-+           matches.append({ "ro_root": ro_root, "atom": atom, "matches": ro_matches,
-+               "type": dep_type, "parent": parent, "host_mismatch": ro_host_mismatch })
-+
-+   return matches
-+
-+def dep_wordreduce_readonly(reduced, unreduced, settings, dep_type, parent):
-+   for mypos, token in enumerate(unreduced):
-+       # recurse if it's a list.
-+       if isinstance(reduced[mypos], list):
-+           reduced[mypos] = dep_wordreduce_readonly(reduced[mypos],
-+               unreduced[mypos], settings, dep_type, parent)
-+
-+       # do nothing if it's satisfied already.
-+       elif not reduced[mypos]:
-+           ro_matches = dep_match_readonly_roots(settings, unreduced[mypos], dep_type, parent)
-+
-+           if ro_matches:
-+               # TODO: select a match if there are more than one?
-+               # for now, the first match is taken...
-+               ro_selected.append(ro_matches[0])
-+               reduced[mypos] = True
-+
-+   return reduced
-+
-+# this may be better placed somewhere else, but i put it here for now, to
-+# keep all functions in the patch on one big heap.
-+def readonly_pathmatch_any(settings, path):
-+   path = path.lstrip('/')
-+   # first try locally, and match that if it exists.
-+   if os.path.exists(os.path.join(EPREFIX,path)):
-+       return os.path.join(EPREFIX,path)
-+
-+   # after that try all readonly roots where DEPEND is allowed. this makes
-+   # sure that executing binaries is possible from there.
-+   for ro_root, ro_deps in settings.readonly_roots.items():
-+       if "DEPEND" in ro_deps:
-+           print(" --- checking %s --- " % (os.path.join(ro_root,path)))
-+           if os.path.exists(os.path.join(ro_root,path)):
-+               return os.path.join(ro_root,path)
-+           break
-+
-+   # as a fallback make the string the same as it was originally.
-+   # even though this path doesn't exist.
-+   return os.path.join(EPREFIX,path)
-+
- def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None,
- 	minimize_slots=False):
- 	"""
-@@ -725,7 +814,7 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None,
- 	assert(False) # This point should not be reachable
- 
- def dep_check(depstring, mydbapi, mysettings, use="yes", mode=None, myuse=None,
--	use_cache=1, use_binaries=0, myroot=None, trees=None):
-+	use_cache=1, use_binaries=0, myroot=None, trees=None, dep_type=None):
- 	"""
- 	Takes a depend string, parses it, and selects atoms.
- 	The myroot parameter is unused (use mysettings['EROOT'] instead).
-@@ -829,6 +918,14 @@ def dep_check(depstring, mydbapi, mysettings, use="yes", mode=None, myuse=None,
- 	writemsg("mysplit:  %s\n" % (mysplit), 1)
- 	writemsg("mysplit2: %s\n" % (mysplit2), 1)
- 
-+	if dep_type is not None:
-+		mysplit2=dep_wordreduce_readonly(unreduced=mysplit[:],
-+				reduced=mysplit2, settings=mysettings,
-+				dep_type=dep_type, parent=trees[myroot].get("disp_parent"))
-+
-+		writemsg("\n", 1)
-+		writemsg("mysplit2 after readonly reduce: %s\n" % (mysplit2), 1)
-+
- 	selected_atoms = dep_zapdeps(mysplit, mysplit2, myroot,
- 		use_binaries=use_binaries, trees=trees, minimize_slots=dnf)
- 
-diff --git a/pym/portage/package/ebuild/_config/LocationsManager.py b/pym/portage/package/ebuild/_config/LocationsManager.py
-index f7d7209ff..e37e5b1a9 100644
---- a/pym/portage/package/ebuild/_config/LocationsManager.py
-+++ b/pym/portage/package/ebuild/_config/LocationsManager.py
-@@ -326,6 +326,9 @@ class LocationsManager(object):
- 		if portage.const.EPREFIX:
- 			self.global_config_path = os.path.join(portage.const.EPREFIX,
- 				GLOBAL_CONFIG_PATH.lstrip(os.sep))
-+			if not exists_raise_eaccess(self.global_config_path) and portage.const.BPREFIX:
-+				self.global_config_path = os.path.join(portage.const.BPREFIX,
-+					GLOBAL_CONFIG_PATH.lstrip(os.sep))
- 
- 	def set_port_dirs(self, portdir, portdir_overlay):
- 		self.portdir = portdir
-diff --git a/pym/portage/package/ebuild/config.py b/pym/portage/package/ebuild/config.py
-index 059aa83ce..3bf6049e8 100644
---- a/pym/portage/package/ebuild/config.py
-+++ b/pym/portage/package/ebuild/config.py
-@@ -309,6 +309,7 @@ class config(object):
- 			self.features = features_set(self)
- 			self.features._features = copy.deepcopy(clone.features._features)
- 			self._features_overrides = copy.deepcopy(clone._features_overrides)
-+			self.readonly_prefixes = copy.deepcopy(clone.readonly_prefixes)
- 
- 			#Strictly speaking _license_manager is not immutable. Users need to ensure that
- 			#extract_global_changes() is called right after __init__ (if at all).
-@@ -969,6 +970,63 @@ class config(object):
- 
- 			self._validate_commands()
- 
-+			# expand READONLY_EPREFIX to a list of all readonly portage instances
-+			# all the way down to the last one. beware that ATM a deeper instance
-+			# in the chain can provide more than the toplevel! this means that
-+			# if you only inherit DEPENDS from one instance, that instance may
-+			# inherit RDEPENDs from another one, making the top-level instance
-+			# inherit RDEPENDs from there too - even if the intermediate prefix
-+			# does not do this.
-+			self.readonly_prefixes = {}
-+			ro_cfg_root = config_root
-+			ro_widest_depset = set(['DEPEND', 'RDEPEND', 'PDEPEND'])
-+
-+			while ro_cfg_root:
-+				ro_make_conf_paths = [
-+					os.path.join(ro_cfg_root, 'etc', 'make.conf'),
-+					os.path.join(ro_cfg_root, MAKE_CONF_FILE)
-+				]
-+				try:
-+					if os.path.samefile(*ro_make_conf_paths):
-+						ro_make_conf_paths.pop()
-+				except OSError:
-+					pass
-+
-+				ro_cfg_root = None
-+				for ro_make_conf in ro_make_conf_paths:
-+					if not os.path.exists(ro_make_conf):
-+						continue
-+
-+					ro_cfg = getconfig(ro_make_conf, tolerant=True, allow_sourcing=True)
-+					if not "READONLY_EPREFIX" in ro_cfg:
-+						continue
-+
-+					if not ro_cfg["READONLY_EPREFIX"].find(":"):
-+						raise portage.exception.InvalidReadonlyERoot("ERROR: malformed READONLY_EPREFIX in %s" % (ro_make_conf))
-+
-+					if ro_cfg_root is not None:
-+						raise portage.exception.InvalidReadonlyERoot("ERROR: duplicate READONLY_EPREFIX in %s and %s" % tuple(ro_make_conf_paths))
-+
-+					(ro_cfg_root,ro_cfg_root_deps) = ro_cfg["READONLY_EPREFIX"].rsplit(":",1)
-+
-+					if not os.path.exists(ro_cfg_root):
-+						raise portage.exception.InvalidReadonlyERoot("ERROR: malformed READONLY_EPREFIX in %s: %s does not exist!" % (ro_make_conf, ro_cfg_root))
-+
-+					if os.path.samefile(ro_cfg_root, config_root):
-+						raise portage.exception.InvalidReadonlyERoot("ERROR: cannot add this instance (%s) as READONLY_EPREFIX in %s." % (ro_cfg_root, ro_make_conf))
-+
-+					if ro_cfg_root in self.readonly_prefixes:
-+						raise portage.exception.InvalidReadonlyERoot("ERROR: circular READONLY_EPREFIX's in %s. %s already checked for %s" % (ro_make_conf, ro_cfg_root, self.readonly_prefixes[ro_cfg_root]))
-+
-+					# intersect the widest depset with the current one to strip down
-+					# the allowed dependency resolution to not be wider than the
-+					# next higher one. this way we can prevent for a given prefix
-+					# to resolve RDEPENDs from a prefix with a different CHOST that
-+					# is a few levels deeper in the chain.
-+					ro_widest_depset = set(ro_cfg_root_deps.split(",")) & ro_widest_depset
-+					self.readonly_prefixes[ro_cfg_root] = ro_widest_depset
-+				pass
-+
- 			for k in self._case_insensitive_vars:
- 				if k in self:
- 					self[k] = self[k].lower()
-@@ -2771,6 +2829,10 @@ class config(object):
- 		if not (src_phase and eapi_attrs.broot):
- 			mydict.pop("BROOT", None)
- 
-+		# populate with PORTAGE_READONLY_EPREFIXES
-+		if self.readonly_prefixes and len(self.readonly_prefixes) > 0:
-+			mydict["PORTAGE_READONLY_EPREFIXES"] = ':'.join(self.readonly_prefixes)
-+
- 		# Prefix variables are supported beginning with EAPI 3, or when
- 		# force-prefix is in FEATURES, since older EAPIs would otherwise be
- 		# useless with prefix configurations. This brings compatibility with
-diff --git a/pym/portage/package/ebuild/doebuild.py b/pym/portage/package/ebuild/doebuild.py
-index f8b784d6b..a6548a43b 100644
---- a/pym/portage/package/ebuild/doebuild.py
-+++ b/pym/portage/package/ebuild/doebuild.py
-@@ -52,6 +52,7 @@ from portage import bsd_chflags, \
- 	unmerge, _encodings, _os_merge, \
- 	_shell_quote, _unicode_decode, _unicode_encode
- from portage.const import EBUILD_SH_ENV_FILE, EBUILD_SH_ENV_DIR, \
-+    GLOBAL_CONFIG_PATH, \
- 	EBUILD_SH_BINARY, INVALID_ENV_FILE, MISC_SH_BINARY, PORTAGE_PYM_PACKAGES, EPREFIX, MACOSSANDBOX_PROFILE
- from portage.data import portage_gid, portage_uid, secpass, \
- 	uid, userpriv_groups
-@@ -73,6 +74,7 @@ from portage.package.ebuild.prepare_build_dirs import prepare_build_dirs
- from portage.process import find_binary
- from portage.util import ( apply_recursive_permissions,
- 	apply_secpass_permissions,
-+	getconfig,
- 	noiselimit,
- 	shlex_split,
- 	varexpand,
-@@ -80,6 +82,7 @@ from portage.util import ( apply_recursive_permissions,
- 	writemsg_stdout,
- 	write_atomic
- 	)
-+from portage.util._path import exists_raise_eaccess
- from portage.util.cpuinfo import get_cpu_count
- from portage.util.lafilefixer import rewrite_lafile
- from portage.util.compression_probe import _compressors
-@@ -243,8 +246,27 @@ def _doebuild_path(settings, eapi=None):
- 
- 	for x in portage_bin_path:
- 		path.append(os.path.join(x, "ebuild-helpers"))
-+
-+	# PREFIX CHAINING: append default path for all prefixes involved
-+	pfxs = [ eprefix ]
-+	pfxs.extend(settings.readonly_prefixes)
-+	for prefix in pfxs:
-+		global_config_path = os.path.join(prefix, GLOBAL_CONFIG_PATH.lstrip(os.sep))
-+		make_globals_path = os.path.join(global_config_path, "make.globals")
-+		if exists_raise_eaccess(make_globals_path):
-+			expand_map = { "EPREFIX": prefix }
-+			pxcfg = getconfig(make_globals_path, True, expand_map)
-+			pxdefp = [x for x in pxcfg.get("DEFAULT_PATH", "").split(":") if x]
-+			for x in pxdefp:
-+				if x.startswith(prefix) and not x in path:
-+					path.append(x)
-+		else:
-+			pxdefs = [prefix + "/usr/sbin", prefix + "/usr/bin", prefix + "/sbin", prefix + "/bin"]
-+			path.extend(pxdefs)
-+	# END PREFIX CHAINING
-+
- 	path.extend(prerootpath)
--	path.extend(defaultpath)
-+	# path.extend(defaultpath) # PREFIX CHAINING appends the default path for involved prefixes above
- 	path.extend(rootpath)
- 	path.extend(extrapath)
- 	# END PREFIX LOCAL
-diff --git a/pym/portage/package/ebuild/fetch.py b/pym/portage/package/ebuild/fetch.py
-index 265d0c9fc..2ec6ff472 100644
---- a/pym/portage/package/ebuild/fetch.py
-+++ b/pym/portage/package/ebuild/fetch.py
-@@ -43,6 +43,7 @@ from portage.output import colorize, EOutput
- from portage.util import apply_recursive_permissions, \
- 	apply_secpass_permissions, ensure_dirs, grabdict, shlex_split, \
- 	varexpand, writemsg, writemsg_level, writemsg_stdout
-+from portage.util._path import exists_raise_eaccess
- from portage.process import spawn
- 
- _userpriv_spawn_kwargs = (
-@@ -874,6 +875,9 @@ def fetch(myuris, mysettings, listonly=0, fetchonly=0,
- 				global_config_path = GLOBAL_CONFIG_PATH
- 				if portage.const.EPREFIX:
- 					global_config_path = os.path.join(portage.const.EPREFIX,
-+						GLOBAL_CONFIG_PATH.lstrip(os.sep))
-+					if not exists_raise_eaccess(global_config_path) and portage.const.BPREFIX:
-+						global_config_path = os.path.join(portage.const.BPREFIX,
- 							GLOBAL_CONFIG_PATH.lstrip(os.sep))
- 
- 				missing_file_param = False
-diff --git a/pym/portage/sync/controller.py b/pym/portage/sync/controller.py
-index 3bccf6f74..cacd63797 100644
---- a/pym/portage/sync/controller.py
-+++ b/pym/portage/sync/controller.py
-@@ -94,19 +94,20 @@ class SyncManager(object):
- 		self.module_controller = portage.sync.module_controller
- 		self.module_names = self.module_controller.module_names
- 		self.hooks = {}
--		for _dir in ["repo.postsync.d", "postsync.d"]:
--			postsync_dir = os.path.join(self.settings["PORTAGE_CONFIGROOT"],
--				portage.USER_CONFIG_PATH, _dir)
--			hooks = OrderedDict()
--			for filepath in util._recursive_file_list(postsync_dir):
--				name = filepath.split(postsync_dir)[1].lstrip(os.sep)
--				if os.access(filepath, os.X_OK):
--					hooks[filepath] = name
--				else:
--					writemsg_level(" %s %s hook: '%s' is not executable\n"
--						% (warn("*"), _dir, _unicode_decode(name),),
--						level=logging.WARN, noiselevel=2)
--			self.hooks[_dir] = hooks
-+		for _confroot in [self.settings["PORTAGE_CONFIGROOT"], portage.const.BPREFIX]:
-+			for _dir in ["repo.postsync.d", "postsync.d"]:
-+					postsync_dir = os.path.join(_confroot,
-+						portage.USER_CONFIG_PATH, _dir)
-+					hooks = OrderedDict()
-+					for filepath in util._recursive_file_list(postsync_dir):
-+						name = filepath.split(postsync_dir)[1].lstrip(os.sep)
-+						if os.access(filepath, os.X_OK):
-+							hooks[filepath] = name
-+						else:
-+							writemsg_level(" %s %s hook: '%s' is not executable\n"
-+								% (warn("*"), _dir, _unicode_decode(name),),
-+								level=logging.WARN, noiselevel=2)
-+					self.hooks[_dir] = hooks
- 
- 	def __getattr__(self, name):
- 		if name == 'async':
-diff --git a/pym/portage/util/_dyn_libs/LinkageMapELF.py b/pym/portage/util/_dyn_libs/LinkageMapELF.py
-index a063621c1..968fbd339 100644
---- a/pym/portage/util/_dyn_libs/LinkageMapELF.py
-+++ b/pym/portage/util/_dyn_libs/LinkageMapELF.py
-@@ -12,7 +12,7 @@ from portage import _os_merge
- from portage import _unicode_decode
- from portage import _unicode_encode
- from portage.cache.mappings import slot_dict_class
--from portage.const import EPREFIX
-+from portage.const import BPREFIX
- from portage.dep.soname.multilib_category import compute_multilib_category
- from portage.exception import CommandNotFound, InvalidData
- from portage.localization import _
-@@ -268,7 +268,7 @@ class LinkageMapELF(object):
- 					continue
- 				plibs.update((x, cpv) for x in items)
- 		if plibs:
--			args = [os.path.join(EPREFIX or "/", "usr/bin/scanelf"), "-qF", "%a;%F;%S;%r;%n"]
-+			args = [os.path.join(BPREFIX or "/", "usr/bin/scanelf"), "-qF", "%a;%F;%S;%r;%n"]
- 			args.extend(os.path.join(root, x.lstrip("." + os.sep)) \
- 				for x in plibs)
- 			try:
--- 
-2.16.1
-

diff --git a/sys-apps/portage/files/portage-2.3.62-prefix-stack.patch b/sys-apps/portage/files/portage-2.3.62-prefix-stack.patch
new file mode 100644
index 0000000000..b0bdf2a20e
--- /dev/null
+++ b/sys-apps/portage/files/portage-2.3.62-prefix-stack.patch
@@ -0,0 +1,80 @@
+From 1fe30e79c368ce71e024d70c3ec07a6aed3ef262 Mon Sep 17 00:00:00 2001
+From: Michael Haubenwallner <haubi@gentoo.org>
+Date: Fri, 22 Mar 2019 17:52:05 +0100
+Subject: [PATCH] from FEATURES=stacked-prefix to USE=prefix-stack
+
+Rather than telling the base prefix' portage to support stacked prefix,
+be explicit in the stacked prefix about to USE that feature.
+Bug: https://bugs.gentoo.org/658572
+---
+ bin/install-qa-check.d/05prefix | 10 +++-------
+ bin/phase-helpers.sh            | 12 ++++--------
+ lib/portage/const.py            |  1 -
+ 3 files changed, 7 insertions(+), 16 deletions(-)
+
+diff --git a/bin/install-qa-check.d/05prefix b/bin/install-qa-check.d/05prefix
+index 03da3bbce..4f48e4216 100644
+--- a/bin/install-qa-check.d/05prefix
++++ b/bin/install-qa-check.d/05prefix
+@@ -36,16 +36,12 @@ install_qa_check_prefix() {
+ 	local WHITELIST=" /usr/bin/env "
+ 	# shebang can be an absolutised path, bug #342929
+ 	local eprefix=$(canonicalize ${EPREFIX})
+-	# Without the stacked-prefix feature, tests using BPREFIX
+-	# are redundant to EPREFIX, but run only if we will fail.
++	# Without USE=prefix-stack, tests using BPREFIX are
++	# redundant to EPREFIX, but run only if we will fail.
+ 	# Otherways, BPREFIX really is BROOT (the EAPI 7 one).
+ 	local BPREFIX=${EPREFIX}
+ 	local bprefix=${eprefix}
+-	if has stacked-prefix ${FEATURES} &&
+-	   [[ -z ${ROOT%/} ]]             &&
+-	   [[ ${CBUILD} == ${CHOST} ]]    &&
+-	   [[ ${EPREFIX} != ${BROOT-${PORTAGE_OVERRIDE_EPREFIX}} ]] &&
+-	:; then
++	if has prefix-stack ${USE} ; then
+ 		BPREFIX=${BROOT-${PORTAGE_OVERRIDE_EPREFIX}}
+ 		bprefix=$(canonicalize ${BPREFIX})
+ 	fi
+diff --git a/bin/phase-helpers.sh b/bin/phase-helpers.sh
+index 606b1cdfd..c64f1106b 100644
+--- a/bin/phase-helpers.sh
++++ b/bin/phase-helpers.sh
+@@ -932,18 +932,14 @@ ___best_version_and_has_version_common() {
+ 			fi ;;
+ 	esac
+ 
+-	# PREFIX LOCAL: stacked-prefix feature
++	# PREFIX LOCAL: prefix-stack feature
+ 	if ___eapi_has_prefix_variables         &&
+ 	   has "${root_arg}" '--host-root' '-b' &&
+-	   has stacked-prefix ${FEATURES}       &&
++	   has prefix-stack ${USE}              &&
+ 	   [[ -z ${ROOT%/} ]]                   &&
+-	   [[ ${CBUILD} == ${CHOST} ]]          &&
+-	   [[ ${EPREFIX} != ${BROOT-${PORTAGE_OVERRIDE_EPREFIX}} ]] &&
+ 	:; then
+-		# When we merge into another EPREFIX, but not into some ROOT,
+-		# and CHOST is equal to CBUILD, build tools found in EPREFIX
+-		# perfectly work for the current build environment.
+-		# In a "stacked prefix" we explicitly utilize this situation.
++		# When we merge into "stacked" EPREFIX, but not into some ROOT, build
++		# tools found in EPREFIX perfectly work for current build environment.
+ 		"${FUNCNAME[1]}" "${atom}" && return 0
+ 	fi
+ 	# END PREFIX LOCAL
+diff --git a/lib/portage/const.py b/lib/portage/const.py
+index eddce377d..db02cbc56 100644
+--- a/lib/portage/const.py
++++ b/lib/portage/const.py
+@@ -207,7 +207,6 @@ SUPPORTED_FEATURES       = frozenset([
+ 	"splitdebug",
+ 	"split-elog",
+ 	"split-log",
+-	"stacked-prefix",  # PREFIX LOCAL
+ 	"strict",
+ 	"strict-keepdir",
+ 	"stricter",
+-- 
+2.19.2
+

diff --git a/sys-apps/portage/files/portage-2.3.8-prefix-chaining.patch b/sys-apps/portage/files/portage-2.3.8-prefix-chaining.patch
deleted file mode 100644
index 036d022191..0000000000
--- a/sys-apps/portage/files/portage-2.3.8-prefix-chaining.patch
+++ /dev/null
@@ -1,927 +0,0 @@
-From 448d210bb312ed0930763376d5182ebfbed1abd8 Mon Sep 17 00:00:00 2001
-From: Michael Haubenwallner <haubi@gentoo.org>
-Date: Thu, 23 Mar 2017 13:52:32 +0100
-Subject: [PATCH] add prefix-chaining support
-
----
- bin/install-qa-check.d/05prefix                    | 30 ++++++-
- bin/phase-helpers.sh                               | 28 ++++++
- pym/_emerge/actions.py                             |  6 +-
- pym/_emerge/depgraph.py                            | 51 ++++++-----
- pym/_emerge/resolver/output.py                     | 40 ++++++++-
- pym/portage/_sets/__init__.py                      |  5 ++
- pym/portage/const.py                               |  6 ++
- pym/portage/dbapi/vartree.py                       | 34 ++++++--
- pym/portage/dep/dep_check.py                       | 99 +++++++++++++++++++++-
- .../package/ebuild/_config/LocationsManager.py     |  3 +
- pym/portage/package/ebuild/config.py               | 62 ++++++++++++++
- pym/portage/package/ebuild/doebuild.py             | 24 +++++-
- pym/portage/package/ebuild/fetch.py                |  4 +
- pym/portage/sync/controller.py                     | 27 +++---
- pym/portage/util/_dyn_libs/LinkageMapELF.py        |  4 +-
- 15 files changed, 376 insertions(+), 47 deletions(-)
-
-diff --git a/bin/install-qa-check.d/05prefix b/bin/install-qa-check.d/05prefix
-index 32561e2..0c11473 100644
---- a/bin/install-qa-check.d/05prefix
-+++ b/bin/install-qa-check.d/05prefix
-@@ -79,16 +79,42 @@ install_qa_check_prefix() {
- 		# unprefixed shebang, is the script directly in $PATH or an init
- 		# script?
- 		if [[ ":${PATH}:${EPREFIX}/etc/init.d:" == *":${fp}:"* ]] ; then
--			if [[ -e ${EROOT}${line[0]} || -e ${ED}${line[0]} ]] ; then
-+			all_epfs="$PORTAGE_READONLY_EPREFIXES:$EPREFIX:$EROOT:$ED"
-+			save_IFS=$IFS
-+			IFS=:
-+			epfs=( $all_epfs )
-+			IFS=$save_IFS
-+
-+			found=
-+			for x in "${epfs[@]}"; do
-+				[[ -z "${x}" ]] && continue
-+				check="${x}${line[0]}"
-+
-+				# might already contain a prefix
-+				if [[ "${line[0]}" == "${x}"* ]]; then
-+					check="${line[0]}"
-+				fi
-+
-+				if [[ -e ${check} ]]; then
-+					found="${check}"
-+				fi
-+			done
-+
-+			if [[ -n ${found} ]] ; then
- 				# is it unprefixed, but we can just fix it because a
- 				# prefixed variant exists
- 				eqawarn "prefixing shebang of ${fn#${D}}"
-+
-+				if [[ ${found} == "${ED}"* || ${found} == "${EROOT}"* ]]; then
-+					found="${EPREFIX}${line[0]}"
-+				fi
-+
- 				# statement is made idempotent on purpose, because
- 				# symlinks may point to the same target, and hence the
- 				# same real file may be sedded multiple times since we
- 				# read the shebangs in one go upfront for performance
- 				# reasons
--				sed -i -e '1s:^#! \?'"${line[0]}"':#!'"${EPREFIX}"${line[0]}':' "${rf}"
-+				sed -i -e '1s:^#! \?'"${line[0]}"':#!'"${found}"':' "${rf}"
- 				continue
- 			else
- 				# this is definitely wrong: script in $PATH and invalid shebang
-diff --git a/bin/phase-helpers.sh b/bin/phase-helpers.sh
-index b28fd92..dcfd263 100644
---- a/bin/phase-helpers.sh
-+++ b/bin/phase-helpers.sh
-@@ -867,6 +867,10 @@ has_version() {
- 		"${PORTAGE_BIN_PATH}/ebuild-helpers/portageq" has_version "${eroot}" "${atom}"
- 	fi
- 	local retval=$?
-+	if [[ ${retval} -eq 1 && -n ${READONLY_EPREFIX} ]]; then
-+		${SHELL} -c "EPREFIX='${READONLY_EPREFIX%:*}' EPYTHON= '${PORTAGE_BIN_PATH}/ebuild-helpers/portageq' has_version '${READONLY_EPREFIX%:*}' '${atom}'"
-+		retval=$?
-+	fi
- 	case "${retval}" in
- 		0|1)
- 			return ${retval}
-@@ -926,6 +930,10 @@ best_version() {
- 		"${PORTAGE_BIN_PATH}/ebuild-helpers/portageq" best_version "${eroot}" "${atom}"
- 	fi
- 	local retval=$?
-+	if [[ ${retval} -eq 1 && -n ${READONLY_EPREFIX} ]]; then
-+		${SHELL} -c "EPREFIX='${READONLY_EPREFIX%:*}' EPYTHON= '${PORTAGE_BIN_PATH}/ebuild-helpers/portageq' best_version '${READONLY_EPREFIX%:*}' '${atom}'"
-+		retval=$?
-+	fi
- 	case "${retval}" in
- 		0|1)
- 			return ${retval}
-@@ -1166,6 +1174,10 @@ if ___eapi_has_master_repositories; then
- 			output=$("${PORTAGE_BIN_PATH}/ebuild-helpers/portageq" master_repositories "${EROOT}" "${repository}")
- 		fi
- 		retval=$?
-+		if [[ ${retval} -eq 1 && -n ${READONLY_EPREFIX} ]]; then
-+			output=$(${SHELL} -c "EPREFIX='${READONLY_EPREFIX%:*}' EPYTHON= '${PORTAGE_BIN_PATH}/ebuild-helpers/portageq' master_repositories '${READONLY_EPREFIX%:*}' '${repository}'")
-+			retval=$?
-+		fi
- 		[[ -n ${output} ]] && echo "${output}"
- 		case "${retval}" in
- 			0|1)
-@@ -1197,6 +1209,10 @@ if ___eapi_has_repository_path; then
- 			output=$("${PORTAGE_BIN_PATH}/ebuild-helpers/portageq" get_repo_path "${EROOT}" "${repository}")
- 		fi
- 		retval=$?
-+		if [[ ${retval} -eq 1 && -n ${READONLY_EPREFIX} ]]; then
-+			output=$(${SHELL} -c "EPREFIX='${READONLY_EPREFIX%:*}' EPYTHON= '${PORTAGE_BIN_PATH}/ebuild-helpers/portageq' repository_path '${READONLY_EPREFIX%:*}' '${repository}'")
-+			retval=$?
-+		fi
- 		[[ -n ${output} ]] && echo "${output}"
- 		case "${retval}" in
- 			0|1)
-@@ -1227,6 +1243,10 @@ if ___eapi_has_available_eclasses; then
- 			output=$("${PORTAGE_BIN_PATH}/ebuild-helpers/portageq" available_eclasses "${EROOT}" "${repository}")
- 		fi
- 		retval=$?
-+		if [[ ${retval} -eq 1 && -n ${READONLY_EPREFIX} ]]; then
-+			output=$(${SHELL} -c "EPREFIX='${READONLY_EPREFIX%:*}' EPYTHON= '${PORTAGE_BIN_PATH}/ebuild-helpers/portageq' available_eclasses '${READONLY_EPREFIX%:*}' '${repository}'")
-+			retval=$?
-+		fi
- 		[[ -n ${output} ]] && echo "${output}"
- 		case "${retval}" in
- 			0|1)
-@@ -1257,6 +1277,10 @@ if ___eapi_has_eclass_path; then
- 		else
- 			output=$("${PORTAGE_BIN_PATH}/ebuild-helpers/portageq" eclass_path "${EROOT}" "${repository}" "${eclass}")
- 		fi
-+		if [[ ${retval} -eq 1 && -n ${READONLY_EPREFIX} ]]; then
-+			output=$(${SHELL} -c "EPREFIX='${READONLY_EPREFIX%:*}' EPYTHON= '${PORTAGE_BIN_PATH}/ebuild-helpers/portageq' eclass_path '${READONLY_EPREFIX%:*}' '${repository}' '${eclass}'")
-+			retval=$?
-+		fi
- 		retval=$?
- 		[[ -n ${output} ]] && echo "${output}"
- 		case "${retval}" in
-@@ -1288,6 +1312,10 @@ if ___eapi_has_license_path; then
- 		else
- 			output=$("${PORTAGE_BIN_PATH}/ebuild-helpers/portageq" license_path "${EROOT}" "${repository}" "${license}")
- 		fi
-+		if [[ ${retval} -eq 1 && -n ${READONLY_EPREFIX} ]]; then
-+			output=(${SHELL} -c "EPREFIX='${READONLY_EPREFIX%:*}' EPYTHON= '${PORTAGE_BIN_PATH}/ebuild-helpers/portageq' license_path '${READONLY_EPREFIX%:*}' '${repository}' '${license}'")
-+			retval=$?
-+		fi
- 		retval=$?
- 		[[ -n ${output} ]] && echo "${output}"
- 		case "${retval}" in
-diff --git a/pym/_emerge/actions.py b/pym/_emerge/actions.py
-index 1d37d0e..2b185ef 100644
---- a/pym/_emerge/actions.py
-+++ b/pym/_emerge/actions.py
-@@ -39,7 +39,7 @@ from portage import os
- from portage import shutil
- from portage import eapi_is_supported, _encodings, _unicode_decode
- from portage.cache.cache_errors import CacheError
--from portage.const import EPREFIX
-+from portage.const import EPREFIX, BPREFIX
- from portage.const import GLOBAL_CONFIG_PATH, VCS_DIRS, _DEPCLEAN_LIB_CHECK_DEFAULT
- from portage.const import SUPPORTED_BINPKG_FORMATS, TIMESTAMP_FORMAT
- from portage.dbapi.dep_expand import dep_expand
-@@ -65,6 +65,7 @@ from portage.util.SlotObject import SlotObject
- from portage.util._async.run_main_scheduler import run_main_scheduler
- from portage.util._async.SchedulerInterface import SchedulerInterface
- from portage.util._eventloop.global_event_loop import global_event_loop
-+from portage.util._path import exists_raise_eaccess
- from portage._global_updates import _global_updates
- from portage.sync.old_tree_timestamp import old_tree_timestamp_warn
- from portage.localization import _
-@@ -2659,6 +2660,9 @@ def missing_sets_warning(root_config, missing_sets):
- 	if portage.const.EPREFIX:
- 		global_config_path = os.path.join(portage.const.EPREFIX,
- 				portage.const.GLOBAL_CONFIG_PATH.lstrip(os.sep))
-+		if not exists_raise_eaccess(global_config_path) and portage.const.BPREFIX:
-+			global_config_path = os.path.join(portage.const.BPREFIX,
-+                    portage.const.GLOBAL_CONFIG_PATH.lstrip(os.sep))
- 	msg.append("        This usually means that '%s'" % \
- 		(os.path.join(global_config_path, "sets/portage.conf"),))
- 	msg.append("        is missing or corrupt.")
-diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py
-index 76f1370..8f681d6 100644
---- a/pym/_emerge/depgraph.py
-+++ b/pym/_emerge/depgraph.py
-@@ -3180,23 +3180,24 @@ class depgraph(object):
- 				edepend["HDEPEND"] = ""
- 
- 		deps = (
--			(depend_root, edepend["DEPEND"],
-+			(depend_root, "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._frozen_config._running_root.root, "HDEPEND",
- 				self._priority(buildtime=True,
- 				optional=(pkg.built or ignore_hdepend_deps),
- 				ignored=ignore_hdepend_deps)),
--			(myroot, edepend["RDEPEND"],
-+			(myroot, "RDEPEND",
- 				self._priority(runtime=True)),
--			(myroot, edepend["PDEPEND"],
-+			(myroot, "PDEPEND",
- 				self._priority(runtime_post=True))
- 		)
- 
- 		debug = "--debug" in self._frozen_config.myopts
- 
--		for dep_root, dep_string, dep_priority in deps:
-+		for dep_root, dep_type, dep_priority in deps:
-+				dep_string = edepend[dep_type]
- 				if not dep_string:
- 					continue
- 				if debug:
-@@ -3234,7 +3235,7 @@ class depgraph(object):
- 
- 				try:
- 					dep_string = list(self._queue_disjunctive_deps(
--						pkg, dep_root, dep_priority, dep_string))
-+						pkg, dep_root, dep_priority, dep_string, dep_type))
- 				except portage.exception.InvalidDependString as e:
- 					if pkg.installed:
- 						self._dynamic_config._masked_installed.add(pkg)
-@@ -3249,14 +3250,14 @@ class depgraph(object):
- 
- 				if not self._add_pkg_dep_string(
- 					pkg, dep_root, dep_priority, dep_string,
--					allow_unsatisfied):
-+					allow_unsatisfied, dep_type):
- 					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):
-+		allow_unsatisfied, dep_type=None):
- 		_autounmask_backup = self._dynamic_config._autounmask
- 		if dep_priority.optional or dep_priority.ignored:
- 			# Temporarily disable autounmask for deps that
-@@ -3265,7 +3266,7 @@ class depgraph(object):
- 		try:
- 			return self._wrapped_add_pkg_dep_string(
- 				pkg, dep_root, dep_priority, dep_string,
--				allow_unsatisfied)
-+				allow_unsatisfied, dep_type)
- 		finally:
- 			self._dynamic_config._autounmask = _autounmask_backup
- 
-@@ -3301,7 +3302,7 @@ class depgraph(object):
- 			not slot_operator_rebuild
- 
- 	def _wrapped_add_pkg_dep_string(self, pkg, dep_root, dep_priority,
--		dep_string, allow_unsatisfied):
-+		dep_string, allow_unsatisfied, dep_type=None):
- 		if isinstance(pkg.depth, int):
- 			depth = pkg.depth + 1
- 		else:
-@@ -3325,7 +3326,7 @@ class depgraph(object):
- 		try:
- 			selected_atoms = self._select_atoms(dep_root,
- 				dep_string, myuse=self._pkg_use_enabled(pkg), parent=pkg,
--				strict=strict, priority=dep_priority)
-+				strict=strict, priority=dep_priority, dep_type=dep_type)
- 		except portage.exception.InvalidDependString:
- 			if pkg.installed:
- 				self._dynamic_config._masked_installed.add(pkg)
-@@ -3623,7 +3624,7 @@ class depgraph(object):
- 					child_pkgs.sort()
- 				yield (atom, child_pkgs[-1])
- 
--	def _queue_disjunctive_deps(self, pkg, dep_root, dep_priority, dep_struct):
-+	def _queue_disjunctive_deps(self, pkg, dep_root, dep_priority, dep_struct, dep_type=None):
- 		"""
- 		Queue disjunctive (virtual and ||) deps in self._dynamic_config._dep_disjunctive_stack.
- 		Yields non-disjunctive deps. Raises InvalidDependString when
-@@ -3632,33 +3633,33 @@ class depgraph(object):
- 		for x in dep_struct:
- 			if isinstance(x, list):
- 				if x and x[0] == "||":
--					self._queue_disjunction(pkg, dep_root, dep_priority, [x])
-+					self._queue_disjunction(pkg, dep_root, dep_priority, [x], dep_type)
- 				else:
- 					for y in self._queue_disjunctive_deps(
--						pkg, dep_root, dep_priority, x):
-+						pkg, dep_root, dep_priority, x, dep_type):
- 						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])
-+					self._queue_disjunction(pkg, dep_root, dep_priority, [x], dep_type)
- 				else:
- 					yield x
- 
--	def _queue_disjunction(self, pkg, dep_root, dep_priority, dep_struct):
-+	def _queue_disjunction(self, pkg, dep_root, dep_priority, dep_struct, dep_type=None):
- 		self._dynamic_config._dep_disjunctive_stack.append(
--			(pkg, dep_root, dep_priority, dep_struct))
-+			(pkg, dep_root, dep_priority, dep_struct, dep_type))
- 
- 	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 = \
-+		pkg, dep_root, dep_priority, dep_struct, dep_type = \
- 			self._dynamic_config._dep_disjunctive_stack.pop()
- 		if not self._add_pkg_dep_string(
--			pkg, dep_root, dep_priority, dep_struct, allow_unsatisfied):
-+			pkg, dep_root, dep_priority, dep_struct, allow_unsatisfied, dep_type):
- 			return 0
- 		return 1
- 
-@@ -4511,7 +4512,7 @@ class depgraph(object):
- 		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):
-+		myuse=None, parent=None, strict=True, trees=None, priority=None, dep_type=None):
- 		"""This will raise InvalidDependString if necessary. If trees is
- 		None then self._dynamic_config._filtered_trees is used."""
- 
-@@ -4534,6 +4535,13 @@ class depgraph(object):
- 		pkgsettings = self._frozen_config.pkgsettings[root]
- 		if trees is None:
- 			trees = self._dynamic_config._filtered_trees
-+
-+		# this one is needed to guarantee good readonly root
-+		# resolution display in the merge list. required since
-+		# parent (below) can be None
-+		trees[root]["disp_parent"] = parent
-+
-+
- 		mytrees = trees[root]
- 		atom_graph = digraph()
- 		if True:
-@@ -4565,7 +4573,7 @@ class depgraph(object):
- 
- 				mycheck = portage.dep_check(depstring, None,
- 					pkgsettings, myuse=myuse,
--					myroot=root, trees=trees)
-+					myroot=root, trees=trees, dep_type=dep_type)
- 			finally:
- 				# restore state
- 				self._dynamic_config._autounmask = _autounmask_backup
-@@ -4641,6 +4649,7 @@ class depgraph(object):
- 							continue
- 						node_stack.append((child_node, node, child_atom))
- 
-+		trees[root].pop("disp_parent")
- 		return selected_atoms
- 
- 	def _expand_virt_from_graph(self, root, atom):
-diff --git a/pym/_emerge/resolver/output.py b/pym/_emerge/resolver/output.py
-index e993ce1..32a942c 100644
---- a/pym/_emerge/resolver/output.py
-+++ b/pym/_emerge/resolver/output.py
-@@ -22,11 +22,12 @@ from portage.localization import localized_size
- from portage.package.ebuild.config import _get_feature_flags
- from portage.package.ebuild._spawn_nofetch import spawn_nofetch
- from portage.output import ( blue, colorize, create_color_func,
--	darkblue, darkgreen, green, nc_len, teal)
-+	darkblue, darkgreen, green, nc_len, teal, yellow, turquoise)
- bad = create_color_func("BAD")
- from portage._sets.base import InternalPackageSet
- from portage.util import writemsg_stdout
- from portage.versions import best, cpv_getversion
-+from portage.dep.dep_check import ro_selected
- 
- from _emerge.Blocker import Blocker
- from _emerge.create_world_atom import create_world_atom
-@@ -563,6 +564,42 @@ class Display(object):
- 			writemsg_stdout("%s\n" % (pkg,), noiselevel=-1)
- 		return
- 
-+	def print_readonly_prefix(self):
-+		"""Performs the actual output printing for the readonly prefix
-+		information stuff
-+		"""
-+		out = sys.stdout
-+
-+        # print readonly selected packages
-+		if len(ro_selected) > 0:
-+			out.write("\n%s\n\n" % (darkgreen("Packages resolved from readonly installations:")))
-+
-+		ro_mismatch_warning = False
-+		ro_dupcheck = []
-+		for x in ro_selected:
-+			tmp_type = x["type"].replace("END","")
-+			while len(tmp_type) < 4:
-+				tmp_type += " "
-+			if x["parent"] and str(x["atom"]) not in ro_dupcheck:
-+				out.write("[%s %s] %s %s %s (%s by %s)" % (teal("readonly"),
-+					green(tmp_type), green(str(x["matches"][0])), yellow("from"),
-+					blue(x["ro_root"]), turquoise(str(x["atom"])), green(x["parent"].cpv)))
-+
-+				ro_dupcheck.append(str(x["atom"]))
-+
-+				if x["host_mismatch"]:
-+					ro_mismatch_warning = True
-+					out.write(" %s\n" % (red("**")))
-+				else:
-+					out.write("\n")
-+
-+		if ro_mismatch_warning:
-+			out.write("\n%s:" % (red("**")))
-+			out.write(yellow(" WARNING: packages marked with ** have been resolved as a\n"))
-+			out.write(yellow("    runtime dependency, but the CHOST variable for the parent\n"))
-+			out.write(yellow("    and dependency package don't match. This could cause link\n"))
-+			out.write(yellow("    errors. It is recommended to use RDEPEND READONLY_EPREFIX's\n"))
-+			out.write(yellow("    only with matching CHOST portage instances.\n"))
- 
- 	def print_verbose(self, show_repos):
- 		"""Prints the verbose output to std_out
-@@ -913,6 +950,7 @@ class Display(object):
- 		show_repos = self.quiet_repo_display and repoadd_set and repoadd_set != set(["0"])
- 
- 		# now finally print out the messages
-+		self.print_readonly_prefix()
- 		self.print_messages(show_repos)
- 		self.print_blockers()
- 		if self.conf.verbosity == 3:
-diff --git a/pym/portage/_sets/__init__.py b/pym/portage/_sets/__init__.py
-index 2c9bf97..6a27842 100644
---- a/pym/portage/_sets/__init__.py
-+++ b/pym/portage/_sets/__init__.py
-@@ -21,6 +21,7 @@ from portage.const import _ENABLE_SET_CONFIG
- from portage.exception import PackageSetNotFound
- from portage.localization import _
- from portage.util import writemsg_level
-+from portage.util._path import exists_raise_eaccess
- from portage.util.configparser import (SafeConfigParser,
- 	NoOptionError, ParsingError, read_configs)
- 
-@@ -281,6 +282,10 @@ def load_default_config(settings, trees):
- 	if portage.const.EPREFIX:
- 		global_config_path = os.path.join(portage.const.EPREFIX,
- 			GLOBAL_CONFIG_PATH.lstrip(os.sep))
-+		if not exists_raise_eaccess(global_config_path) and portage.const.BPREFIX:
-+			global_config_path = os.path.join(portage.const.BPREFIX,
-+				GLOBAL_CONFIG_PATH.lstrip(os.sep))
-+
- 	vcs_dirs = [_unicode_encode(x, encoding=_encodings['fs']) for x in VCS_DIRS]
- 	def _getfiles():
- 		for path, dirs, files in os.walk(os.path.join(global_config_path, "sets")):
-diff --git a/pym/portage/const.py b/pym/portage/const.py
-index a0ad1f9..4f14bc8 100644
---- a/pym/portage/const.py
-+++ b/pym/portage/const.py
-@@ -189,6 +189,7 @@ SUPPORTED_FEATURES       = frozenset([
- 	"notitles",
- 	"parallel-fetch",
- 	"parallel-install",
-+	"prefix-chaining",
- 	"prelink-checksums",
- 	"preserve-libs",
- 	"protect-owned",
-@@ -266,6 +267,11 @@ MANIFEST2_IDENTIFIERS    = ("AUX", "MISC", "DIST", "EBUILD")
- #EPREFIX = ""
- # END PREFIX LOCAL
- 
-+BPREFIX = EPREFIX
-+
-+# --prefix commandline arg always rules, ends up in os.environ["EPREFIX"]
-+if "EPREFIX" in os.environ:
-+    os.environ["PORTAGE_OVERRIDE_EPREFIX"] = os.environ["EPREFIX"]
- # pick up EPREFIX from the environment if set
- if "PORTAGE_OVERRIDE_EPREFIX" in os.environ:
- 	EPREFIX = os.environ["PORTAGE_OVERRIDE_EPREFIX"]
-diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py
-index 0006bc5..2ea5f16 100644
---- a/pym/portage/dbapi/vartree.py
-+++ b/pym/portage/dbapi/vartree.py
-@@ -194,8 +194,19 @@ class vardbapi(dbapi):
- 		self._counter_path = os.path.join(self._eroot,
- 			CACHE_PATH, "counter")
- 
--		self._plib_registry = PreservedLibsRegistry(settings["ROOT"],
--			os.path.join(self._eroot, PRIVATE_PATH, "preserved_libs_registry"))
-+		plibreg_path = os.path.join(self._eroot, PRIVATE_PATH, "preserved_libs_registry")
-+
-+		if vartree:
-+			self._kill_eprefix = vartree._kill_eprefix
-+		else:
-+			self._kill_eprefix = False
-+
-+		if self._kill_eprefix:
-+			self._aux_cache_filename = self._aux_cache_filename.replace(EPREFIX, "")
-+			self._counter_path = self._counter_path.replace(EPREFIX, "")
-+			plibreg_path = plibreg_path.replace(EPREFIX, "")
-+
-+		self._plib_registry = PreservedLibsRegistry(settings["ROOT"], plibreg_path)
- 		self._linkmap = LinkageMap(self)
- 		chost = self.settings.get('CHOST')
- 		if not chost:
-@@ -236,6 +247,9 @@ class vardbapi(dbapi):
- 		# This is an optimized hotspot, so don't use unicode-wrapped
- 		# os module and don't use os.path.join().
- 		rValue = self._eroot + VDB_PATH + _os.sep + mykey
-+		if self._kill_eprefix:
-+			rValue = rValue.replace(EPREFIX, "")
-+
- 		if filename is not None:
- 			# If filename is always relative, we can do just
- 			# rValue += _os.sep + filename
-@@ -499,6 +513,9 @@ class vardbapi(dbapi):
- 		returnme = []
- 		basepath = os.path.join(self._eroot, VDB_PATH) + os.path.sep
- 
-+		if self._kill_eprefix:
-+			basepath = os.path.join(self.root, basepath.replace(EPREFIX, ""))
-+
- 		if use_cache:
- 			from portage import listdir
- 		else:
-@@ -595,11 +612,17 @@ class vardbapi(dbapi):
- 				del self.matchcache[mycat]
- 			return list(self._iter_match(mydep,
- 				self.cp_list(mydep.cp, use_cache=use_cache)))
-+
-+		_tmp_path = os.path.join(self._eroot, VDB_PATH, mycat)
-+
-+		if self._kill_eprefix:
-+			_tmp_path = _tmp_path.replace(EPREFIX, "")
-+
- 		try:
- 			if sys.hexversion >= 0x3030000:
--				curmtime = os.stat(os.path.join(self._eroot, VDB_PATH, mycat)).st_mtime_ns
-+				curmtime = os.stat(_tmp_path).st_mtime_ns
- 			else:
--				curmtime = os.stat(os.path.join(self._eroot, VDB_PATH, mycat)).st_mtime
-+				curmtime = os.stat(_tmp_path).st_mtime
- 		except (IOError, OSError):
- 			curmtime=0
- 
-@@ -1410,7 +1433,7 @@ class vardbapi(dbapi):
- class vartree(object):
- 	"this tree will scan a var/db/pkg database located at root (passed to init)"
- 	def __init__(self, root=None, virtual=DeprecationWarning, categories=None,
--		settings=None):
-+		settings=None, kill_eprefix=None):
- 
- 		if settings is None:
- 			settings = portage.settings
-@@ -1428,6 +1451,7 @@ class vartree(object):
- 				" constructor is unused",
- 				DeprecationWarning, stacklevel=2)
- 
-+		self._kill_eprefix = kill_eprefix
- 		self.settings = settings
- 		self.dbapi = vardbapi(settings=settings, vartree=self)
- 		self.populated = 1
-diff --git a/pym/portage/dep/dep_check.py b/pym/portage/dep/dep_check.py
-index 35caecc..f0dca8a 100644
---- a/pym/portage/dep/dep_check.py
-+++ b/pym/portage/dep/dep_check.py
-@@ -255,6 +255,95 @@ class _dep_choice(SlotObject):
- 	__slots__ = ('atoms', 'slot_map', 'cp_map', 'all_available',
- 		'all_installed_slots')
- 
-+ro_trees={}
-+ro_vartrees={}
-+ro_selected=[]
-+
-+def dep_match_readonly_roots(settings, atom, dep_type, parent=None):
-+   if len(ro_trees) < len(settings.readonly_prefixes):
-+       # MDUFT: create additional vartrees for every readonly root here.
-+       # the ro_vartrees instances are created below as they are needed to
-+       # avoid reading vartrees of portage instances which aren't required
-+       # while resolving this dependencies.
-+       for type in ("DEPEND","RDEPEND", "PDEPEND"):
-+           ro_trees[type] = []
-+
-+           for ro_root, ro_dep_types in settings.readonly_prefixes.items():
-+               if type in ro_dep_types:
-+                   ro_trees[type].append(ro_root)
-+
-+   if len(ro_trees) == 0:
-+       return []
-+
-+   matches = []
-+
-+   for ro_root in ro_trees[dep_type]:
-+       if not ro_root in ro_vartrees:
-+           # target_root=ro_root ok? or should it be the real target_root?
-+           _tmp_settings = portage.config(config_root=ro_root, target_root=ro_root,
-+               config_incrementals=portage.const.INCREMENTALS)
-+
-+           ro_vartrees[ro_root] = portage.vartree(root=ro_root,
-+               categories=_tmp_settings.categories,
-+               settings=_tmp_settings, kill_eprefix=True)
-+
-+       ro_matches = ro_vartrees[ro_root].dbapi.match(atom)
-+
-+       if ro_matches:
-+           ro_host_mismatch = False
-+           if dep_type is "RDEPEND":
-+               # we need to assure binary compatability, so it needs to be
-+               # the same CHOST! But how? for now i cannot do anything...
-+               if parent and parent.metadata["CHOST"] != ro_vartrees[ro_root].settings.get("CHOST", ""):
-+                   # provocate a big fat warning in the list of external packages.
-+                   ro_host_mismatch = True
-+               pass
-+
-+           matches.append({ "ro_root": ro_root, "atom": atom, "matches": ro_matches,
-+               "type": dep_type, "parent": parent, "host_mismatch": ro_host_mismatch })
-+
-+   return matches
-+
-+def dep_wordreduce_readonly(reduced, unreduced, settings, dep_type, parent):
-+   for mypos, token in enumerate(unreduced):
-+       # recurse if it's a list.
-+       if isinstance(reduced[mypos], list):
-+           reduced[mypos] = dep_wordreduce_readonly(reduced[mypos],
-+               unreduced[mypos], settings, dep_type, parent)
-+
-+       # do nothing if it's satisfied already.
-+       elif not reduced[mypos]:
-+           ro_matches = dep_match_readonly_roots(settings, unreduced[mypos], dep_type, parent)
-+
-+           if ro_matches:
-+               # TODO: select a match if there are more than one?
-+               # for now, the first match is taken...
-+               ro_selected.append(ro_matches[0])
-+               reduced[mypos] = True
-+
-+   return reduced
-+
-+# this may be better placed somewhere else, but i put it here for now, to
-+# keep all functions in the patch on one big heap.
-+def readonly_pathmatch_any(settings, path):
-+   path = path.lstrip('/')
-+   # first try locally, and match that if it exists.
-+   if os.path.exists(os.path.join(EPREFIX,path)):
-+       return os.path.join(EPREFIX,path)
-+
-+   # after that try all readonly roots where DEPEND is allowed. this makes
-+   # sure that executing binaries is possible from there.
-+   for ro_root, ro_deps in settings.readonly_roots.items():
-+       if "DEPEND" in ro_deps:
-+           print(" --- checking %s --- " % (os.path.join(ro_root,path)))
-+           if os.path.exists(os.path.join(ro_root,path)):
-+               return os.path.join(ro_root,path)
-+           break
-+
-+   # as a fallback make the string the same as it was originally.
-+   # even though this path doesn't exist.
-+   return os.path.join(EPREFIX,path)
-+
- def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None):
- 	"""
- 	Takes an unreduced and reduced deplist and removes satisfied dependencies.
-@@ -643,7 +732,7 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None):
- 	assert(False) # This point should not be reachable
- 
- def dep_check(depstring, mydbapi, mysettings, use="yes", mode=None, myuse=None,
--	use_cache=1, use_binaries=0, myroot=None, trees=None):
-+	use_cache=1, use_binaries=0, myroot=None, trees=None, dep_type=None):
- 	"""
- 	Takes a depend string, parses it, and selects atoms.
- 	The myroot parameter is unused (use mysettings['EROOT'] instead).
-@@ -741,6 +830,14 @@ def dep_check(depstring, mydbapi, mysettings, use="yes", mode=None, myuse=None,
- 	writemsg("mysplit:  %s\n" % (mysplit), 1)
- 	writemsg("mysplit2: %s\n" % (mysplit2), 1)
- 
-+	if dep_type is not None:
-+		mysplit2=dep_wordreduce_readonly(unreduced=mysplit[:],
-+				reduced=mysplit2, settings=mysettings,
-+				dep_type=dep_type, parent=trees[myroot].get("disp_parent"))
-+
-+		writemsg("\n", 1)
-+		writemsg("mysplit2 after readonly reduce: %s\n" % (mysplit2), 1)
-+
- 	selected_atoms = dep_zapdeps(mysplit, mysplit2, myroot,
- 		use_binaries=use_binaries, trees=trees)
- 
-diff --git a/pym/portage/package/ebuild/_config/LocationsManager.py b/pym/portage/package/ebuild/_config/LocationsManager.py
-index 55b8c08..32e969e 100644
---- a/pym/portage/package/ebuild/_config/LocationsManager.py
-+++ b/pym/portage/package/ebuild/_config/LocationsManager.py
-@@ -307,6 +307,9 @@ class LocationsManager(object):
- 		if portage.const.EPREFIX:
- 			self.global_config_path = os.path.join(portage.const.EPREFIX,
- 				GLOBAL_CONFIG_PATH.lstrip(os.sep))
-+			if not exists_raise_eaccess(self.global_config_path) and portage.const.BPREFIX:
-+				self.global_config_path = os.path.join(portage.const.BPREFIX,
-+					GLOBAL_CONFIG_PATH.lstrip(os.sep))
- 
- 	def set_port_dirs(self, portdir, portdir_overlay):
- 		self.portdir = portdir
-diff --git a/pym/portage/package/ebuild/config.py b/pym/portage/package/ebuild/config.py
-index b5fb42e..8cac700 100644
---- a/pym/portage/package/ebuild/config.py
-+++ b/pym/portage/package/ebuild/config.py
-@@ -306,6 +306,7 @@ class config(object):
- 			self.features = features_set(self)
- 			self.features._features = copy.deepcopy(clone.features._features)
- 			self._features_overrides = copy.deepcopy(clone._features_overrides)
-+			self.readonly_prefixes = copy.deepcopy(clone.readonly_prefixes)
- 
- 			#Strictly speaking _license_manager is not immutable. Users need to ensure that
- 			#extract_global_changes() is called right after __init__ (if at all).
-@@ -945,6 +946,63 @@ class config(object):
- 
- 			self._validate_commands()
- 
-+			# expand READONLY_EPREFIX to a list of all readonly portage instances
-+			# all the way down to the last one. beware that ATM a deeper instance
-+			# in the chain can provide more than the toplevel! this means that
-+			# if you only inherit DEPENDS from one instance, that instance may
-+			# inherit RDEPENDs from another one, making the top-level instance
-+			# inherit RDEPENDs from there too - even if the intermediate prefix
-+			# does not do this.
-+			self.readonly_prefixes = {}
-+			ro_cfg_root = config_root
-+			ro_widest_depset = set(['DEPEND', 'RDEPEND', 'PDEPEND'])
-+
-+			while ro_cfg_root:
-+				ro_make_conf_paths = [
-+					os.path.join(ro_cfg_root, 'etc', 'make.conf'),
-+					os.path.join(ro_cfg_root, MAKE_CONF_FILE)
-+				]
-+				try:
-+					if os.path.samefile(*ro_make_conf_paths):
-+						ro_make_conf_paths.pop()
-+				except OSError:
-+					pass
-+
-+				ro_cfg_root = None
-+				for ro_make_conf in ro_make_conf_paths:
-+					if not os.path.exists(ro_make_conf):
-+						continue
-+
-+					ro_cfg = getconfig(ro_make_conf, tolerant=True, allow_sourcing=True)
-+					if not "READONLY_EPREFIX" in ro_cfg:
-+						continue
-+
-+					if not ro_cfg["READONLY_EPREFIX"].find(":"):
-+						raise portage.exception.InvalidReadonlyERoot("ERROR: malformed READONLY_EPREFIX in %s" % (ro_make_conf))
-+
-+					if ro_cfg_root is not None:
-+						raise portage.exception.InvalidReadonlyERoot("ERROR: duplicate READONLY_EPREFIX in %s and %s" % tuple(ro_make_conf_paths))
-+
-+					(ro_cfg_root,ro_cfg_root_deps) = ro_cfg["READONLY_EPREFIX"].rsplit(":",1)
-+
-+					if not os.path.exists(ro_cfg_root):
-+						raise portage.exception.InvalidReadonlyERoot("ERROR: malformed READONLY_EPREFIX in %s: %s does not exist!" % (ro_make_conf, ro_cfg_root))
-+
-+					if os.path.samefile(ro_cfg_root, config_root):
-+						raise portage.exception.InvalidReadonlyERoot("ERROR: cannot add this instance (%s) as READONLY_EPREFIX in %s." % (ro_cfg_root, ro_make_conf))
-+
-+					if ro_cfg_root in self.readonly_prefixes:
-+						raise portage.exception.InvalidReadonlyERoot("ERROR: circular READONLY_EPREFIX's in %s. %s already checked for %s" % (ro_make_conf, ro_cfg_root, self.readonly_prefixes[ro_cfg_root])) 
-+
-+					# intersect the widest depset with the current one to strip down
-+					# the allowed dependency resolution to not be wider than the
-+					# next higher one. this way we can prevent for a given prefix
-+					# to resolve RDEPENDs from a prefix with a different CHOST that
-+					# is a few levels deeper in the chain.
-+					ro_widest_depset = set(ro_cfg_root_deps.split(",")) & ro_widest_depset
-+					self.readonly_prefixes[ro_cfg_root] = ro_widest_depset
-+				pass
-+
- 			for k in self._case_insensitive_vars:
- 				if k in self:
- 					self[k] = self[k].lower()
-@@ -2805,6 +2863,10 @@ class config(object):
- 		if not eapi_exports_merge_type(eapi):
- 			mydict.pop("MERGE_TYPE", None)
- 
-+		# populate with PORTAGE_READONLY_EPREFIXES
-+		if self.readonly_prefixes and len(self.readonly_prefixes) > 0:
-+			mydict["PORTAGE_READONLY_EPREFIXES"] = ':'.join(self.readonly_prefixes)
-+
- 		# Prefix variables are supported beginning with EAPI 3, or when
- 		# force-prefix is in FEATURES, since older EAPIs would otherwise be
- 		# useless with prefix configurations. This brings compatibility with
-diff --git a/pym/portage/package/ebuild/doebuild.py b/pym/portage/package/ebuild/doebuild.py
-index c6d6133..f914091 100644
---- a/pym/portage/package/ebuild/doebuild.py
-+++ b/pym/portage/package/ebuild/doebuild.py
-@@ -51,6 +51,7 @@ from portage import bsd_chflags, \
- 	unmerge, _encodings, _os_merge, \
- 	_shell_quote, _unicode_decode, _unicode_encode
- from portage.const import EBUILD_SH_ENV_FILE, EBUILD_SH_ENV_DIR, \
-+    GLOBAL_CONFIG_PATH, \
- 	EBUILD_SH_BINARY, INVALID_ENV_FILE, MISC_SH_BINARY, PORTAGE_PYM_PACKAGES, EPREFIX, MACOSSANDBOX_PROFILE
- from portage.data import portage_gid, portage_uid, secpass, \
- 	uid, userpriv_groups
-@@ -72,6 +73,7 @@ from portage.package.ebuild.prepare_build_dirs import prepare_build_dirs
- from portage.process import find_binary
- from portage.util import ( apply_recursive_permissions,
- 	apply_secpass_permissions,
-+	getconfig,
- 	noiselimit,
- 	shlex_split,
- 	varexpand,
-@@ -79,6 +81,7 @@ from portage.util import ( apply_recursive_permissions,
- 	writemsg_stdout,
- 	write_atomic
- 	)
-+from portage.util._path import exists_raise_eaccess
- from portage.util.cpuinfo import get_cpu_count
- from portage.util.lafilefixer import rewrite_lafile
- from portage.util.compression_probe import _compressors
-@@ -241,8 +244,27 @@ def _doebuild_path(settings, eapi=None):
- 
- 	for x in portage_bin_path:
- 		path.append(os.path.join(x, "ebuild-helpers"))
-+
-+	# PREFIX CHAINING: append default path for all prefixes involved
-+	pfxs = [ eprefix ]
-+	pfxs.extend(settings.readonly_prefixes)
-+	for prefix in pfxs:
-+		global_config_path = os.path.join(prefix, GLOBAL_CONFIG_PATH.lstrip(os.sep))
-+		make_globals_path = os.path.join(global_config_path, "make.globals")
-+		if exists_raise_eaccess(make_globals_path):
-+			expand_map = { "EPREFIX": prefix }
-+			pxcfg = getconfig(make_globals_path, True, expand_map)
-+			pxdefp = [x for x in pxcfg.get("DEFAULT_PATH", "").split(":") if x]
-+			for x in pxdefp:
-+				if x.startswith(prefix) and not x in path:
-+					path.append(x)
-+		else:
-+			pxdefs = [prefix + "/usr/sbin", prefix + "/usr/bin", prefix + "/sbin", prefix + "/bin"]
-+			path.extend(pxdefs)
-+	# END PREFIX CHAINING
-+
- 	path.extend(prerootpath)
--	path.extend(defaultpath)
-+	# path.extend(defaultpath) # PREFIX CHAINING appends the default path for involved prefixes above
- 	path.extend(rootpath)
- 	path.extend(extrapath)
- 	# END PREFIX LOCAL
-diff --git a/pym/portage/package/ebuild/fetch.py b/pym/portage/package/ebuild/fetch.py
-index 265d0c9..2ec6ff4 100644
---- a/pym/portage/package/ebuild/fetch.py
-+++ b/pym/portage/package/ebuild/fetch.py
-@@ -43,6 +43,7 @@ from portage.output import colorize, EOutput
- from portage.util import apply_recursive_permissions, \
- 	apply_secpass_permissions, ensure_dirs, grabdict, shlex_split, \
- 	varexpand, writemsg, writemsg_level, writemsg_stdout
-+from portage.util._path import exists_raise_eaccess
- from portage.process import spawn
- 
- _userpriv_spawn_kwargs = (
-@@ -874,6 +875,9 @@ def fetch(myuris, mysettings, listonly=0, fetchonly=0,
- 				global_config_path = GLOBAL_CONFIG_PATH
- 				if portage.const.EPREFIX:
- 					global_config_path = os.path.join(portage.const.EPREFIX,
-+						GLOBAL_CONFIG_PATH.lstrip(os.sep))
-+					if not exists_raise_eaccess(global_config_path) and portage.const.BPREFIX:
-+						global_config_path = os.path.join(portage.const.BPREFIX,
- 							GLOBAL_CONFIG_PATH.lstrip(os.sep))
- 
- 				missing_file_param = False
-diff --git a/pym/portage/sync/controller.py b/pym/portage/sync/controller.py
-index 3bccf6f..cacd637 100644
---- a/pym/portage/sync/controller.py
-+++ b/pym/portage/sync/controller.py
-@@ -94,19 +94,20 @@ class SyncManager(object):
- 		self.module_controller = portage.sync.module_controller
- 		self.module_names = self.module_controller.module_names
- 		self.hooks = {}
--		for _dir in ["repo.postsync.d", "postsync.d"]:
--			postsync_dir = os.path.join(self.settings["PORTAGE_CONFIGROOT"],
--				portage.USER_CONFIG_PATH, _dir)
--			hooks = OrderedDict()
--			for filepath in util._recursive_file_list(postsync_dir):
--				name = filepath.split(postsync_dir)[1].lstrip(os.sep)
--				if os.access(filepath, os.X_OK):
--					hooks[filepath] = name
--				else:
--					writemsg_level(" %s %s hook: '%s' is not executable\n"
--						% (warn("*"), _dir, _unicode_decode(name),),
--						level=logging.WARN, noiselevel=2)
--			self.hooks[_dir] = hooks
-+		for _confroot in [self.settings["PORTAGE_CONFIGROOT"], portage.const.BPREFIX]:
-+			for _dir in ["repo.postsync.d", "postsync.d"]:
-+					postsync_dir = os.path.join(_confroot,
-+						portage.USER_CONFIG_PATH, _dir)
-+					hooks = OrderedDict()
-+					for filepath in util._recursive_file_list(postsync_dir):
-+						name = filepath.split(postsync_dir)[1].lstrip(os.sep)
-+						if os.access(filepath, os.X_OK):
-+							hooks[filepath] = name
-+						else:
-+							writemsg_level(" %s %s hook: '%s' is not executable\n"
-+								% (warn("*"), _dir, _unicode_decode(name),),
-+								level=logging.WARN, noiselevel=2)
-+					self.hooks[_dir] = hooks
- 
- 	def __getattr__(self, name):
- 		if name == 'async':
-diff --git a/pym/portage/util/_dyn_libs/LinkageMapELF.py b/pym/portage/util/_dyn_libs/LinkageMapELF.py
-index a063621..968fbd3 100644
---- a/pym/portage/util/_dyn_libs/LinkageMapELF.py
-+++ b/pym/portage/util/_dyn_libs/LinkageMapELF.py
-@@ -12,7 +12,7 @@ from portage import _os_merge
- from portage import _unicode_decode
- from portage import _unicode_encode
- from portage.cache.mappings import slot_dict_class
--from portage.const import EPREFIX
-+from portage.const import BPREFIX
- from portage.dep.soname.multilib_category import compute_multilib_category
- from portage.exception import CommandNotFound, InvalidData
- from portage.localization import _
-@@ -268,7 +268,7 @@ class LinkageMapELF(object):
- 					continue
- 				plibs.update((x, cpv) for x in items)
- 		if plibs:
--			args = [os.path.join(EPREFIX or "/", "usr/bin/scanelf"), "-qF", "%a;%F;%S;%r;%n"]
-+			args = [os.path.join(BPREFIX or "/", "usr/bin/scanelf"), "-qF", "%a;%F;%S;%r;%n"]
- 			args.extend(os.path.join(root, x.lstrip("." + os.sep)) \
- 				for x in plibs)
- 			try:
--- 
-2.10.2
-

diff --git a/sys-apps/portage/metadata.xml b/sys-apps/portage/metadata.xml
index 1e859c1071..c66241962c 100644
--- a/sys-apps/portage/metadata.xml
+++ b/sys-apps/portage/metadata.xml
@@ -23,6 +23,5 @@
     <flag name="xattr">Preserve extended attributes (filesystem-stored metadata)
         when installing files. Usually only required for hardened systems.
     </flag>
-    <flag name="prefix-chaining">mduft's experimental prefix chaining facilities</flag>
   </use>
 </pkgmetadata>

diff --git a/sys-apps/portage/portage-2.3.52.2.ebuild b/sys-apps/portage/portage-2.3.52.2.ebuild
index 9797e183cd..e2ca476f68 100644
--- a/sys-apps/portage/portage-2.3.52.2.ebuild
+++ b/sys-apps/portage/portage-2.3.52.2.ebuild
@@ -1,4 +1,4 @@
-# Copyright 1999-2018 Gentoo Authors
+# Copyright 1999-2019 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 EAPI=5
@@ -17,7 +17,7 @@ HOMEPAGE="https://wiki.gentoo.org/wiki/Project:Portage"
 LICENSE="GPL-2"
 KEYWORDS="~ppc-aix ~x64-cygwin ~amd64-linux ~x86-linux ~ppc-macos ~x64-macos ~x86-macos ~m68k-mint ~sparc-solaris ~sparc64-solaris ~x64-solaris ~x86-solaris"
 SLOT="0"
-IUSE="build doc epydoc +ipc +native-extensions selinux xattr prefix-chaining"
+IUSE="build doc epydoc +ipc +native-extensions selinux xattr"
 
 DEPEND="!build? ( $(python_gen_impl_dep 'ssl(+)') )
 	>=app-arch/tar-1.27
@@ -92,8 +92,6 @@ python_prepare_all() {
 	distutils-r1_python_prepare_all
 
 	epatch "${FILESDIR}"/${PN}-2.3.45-ebuildshell.patch # 155161
-	use prefix-chaining && # maybe useful even with stacked-prefix
-		epatch "${FILESDIR}"/${PN}-2.3.40-prefix-chaining.patch
 
 	if use native-extensions; then
 		printf "[build_ext]\nportage-ext-modules=true\n" >> \

diff --git a/sys-apps/portage/portage-2.3.55.1.ebuild b/sys-apps/portage/portage-2.3.55.1.ebuild
index 9528084055..e2ca476f68 100644
--- a/sys-apps/portage/portage-2.3.55.1.ebuild
+++ b/sys-apps/portage/portage-2.3.55.1.ebuild
@@ -17,7 +17,7 @@ HOMEPAGE="https://wiki.gentoo.org/wiki/Project:Portage"
 LICENSE="GPL-2"
 KEYWORDS="~ppc-aix ~x64-cygwin ~amd64-linux ~x86-linux ~ppc-macos ~x64-macos ~x86-macos ~m68k-mint ~sparc-solaris ~sparc64-solaris ~x64-solaris ~x86-solaris"
 SLOT="0"
-IUSE="build doc epydoc +ipc +native-extensions selinux xattr prefix-chaining"
+IUSE="build doc epydoc +ipc +native-extensions selinux xattr"
 
 DEPEND="!build? ( $(python_gen_impl_dep 'ssl(+)') )
 	>=app-arch/tar-1.27
@@ -92,8 +92,6 @@ python_prepare_all() {
 	distutils-r1_python_prepare_all
 
 	epatch "${FILESDIR}"/${PN}-2.3.45-ebuildshell.patch # 155161
-	use prefix-chaining && # maybe useful even with stacked-prefix
-		epatch "${FILESDIR}"/${PN}-2.3.40-prefix-chaining.patch
 
 	if use native-extensions; then
 		printf "[build_ext]\nportage-ext-modules=true\n" >> \

diff --git a/sys-apps/portage/portage-2.3.55.1.ebuild b/sys-apps/portage/portage-2.3.62-r00.1.ebuild
similarity index 97%
copy from sys-apps/portage/portage-2.3.55.1.ebuild
copy to sys-apps/portage/portage-2.3.62-r00.1.ebuild
index 9528084055..8dab4da44e 100644
--- a/sys-apps/portage/portage-2.3.55.1.ebuild
+++ b/sys-apps/portage/portage-2.3.62-r00.1.ebuild
@@ -17,7 +17,7 @@ HOMEPAGE="https://wiki.gentoo.org/wiki/Project:Portage"
 LICENSE="GPL-2"
 KEYWORDS="~ppc-aix ~x64-cygwin ~amd64-linux ~x86-linux ~ppc-macos ~x64-macos ~x86-macos ~m68k-mint ~sparc-solaris ~sparc64-solaris ~x64-solaris ~x86-solaris"
 SLOT="0"
-IUSE="build doc epydoc +ipc +native-extensions selinux xattr prefix-chaining"
+IUSE="build doc epydoc +ipc +native-extensions selinux xattr"
 
 DEPEND="!build? ( $(python_gen_impl_dep 'ssl(+)') )
 	>=app-arch/tar-1.27
@@ -91,9 +91,8 @@ pkg_setup() {
 python_prepare_all() {
 	distutils-r1_python_prepare_all
 
+	epatch "${FILESDIR}"/${PN}-2.3.62-prefix-stack.patch # 658572
 	epatch "${FILESDIR}"/${PN}-2.3.45-ebuildshell.patch # 155161
-	use prefix-chaining && # maybe useful even with stacked-prefix
-		epatch "${FILESDIR}"/${PN}-2.3.40-prefix-chaining.patch
 
 	if use native-extensions; then
 		printf "[build_ext]\nportage-ext-modules=true\n" >> \

diff --git a/sys-apps/portage/portage-2.3.62.ebuild b/sys-apps/portage/portage-2.3.62.ebuild
index 9528084055..e2ca476f68 100644
--- a/sys-apps/portage/portage-2.3.62.ebuild
+++ b/sys-apps/portage/portage-2.3.62.ebuild
@@ -17,7 +17,7 @@ HOMEPAGE="https://wiki.gentoo.org/wiki/Project:Portage"
 LICENSE="GPL-2"
 KEYWORDS="~ppc-aix ~x64-cygwin ~amd64-linux ~x86-linux ~ppc-macos ~x64-macos ~x86-macos ~m68k-mint ~sparc-solaris ~sparc64-solaris ~x64-solaris ~x86-solaris"
 SLOT="0"
-IUSE="build doc epydoc +ipc +native-extensions selinux xattr prefix-chaining"
+IUSE="build doc epydoc +ipc +native-extensions selinux xattr"
 
 DEPEND="!build? ( $(python_gen_impl_dep 'ssl(+)') )
 	>=app-arch/tar-1.27
@@ -92,8 +92,6 @@ python_prepare_all() {
 	distutils-r1_python_prepare_all
 
 	epatch "${FILESDIR}"/${PN}-2.3.45-ebuildshell.patch # 155161
-	use prefix-chaining && # maybe useful even with stacked-prefix
-		epatch "${FILESDIR}"/${PN}-2.3.40-prefix-chaining.patch
 
 	if use native-extensions; then
 		printf "[build_ext]\nportage-ext-modules=true\n" >> \


             reply	other threads:[~2019-03-25 14:20 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-03-25 14:20 Michael Haubenwallner [this message]
  -- strict thread matches above, loose matches on Subject: below --
2024-02-22  7:55 [gentoo-commits] repo/proj/prefix:master commit in: sys-apps/portage/, sys-apps/portage/files/ Fabian Groffen
2022-01-26  7:22 Fabian Groffen
2022-01-14 12:28 Fabian Groffen
2020-12-07 17:39 Fabian Groffen
2020-12-04 10:38 Fabian Groffen
2018-12-06 13:49 Fabian Groffen
2016-04-27 13:10 Michael Haubenwallner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1553515292.beae731778eee1216ad4d94d52935617598320ae.haubi@gentoo \
    --to=haubi@gentoo.org \
    --cc=gentoo-commits@lists.gentoo.org \
    --cc=gentoo-dev@lists.gentoo.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox