diff options
Diffstat (limited to 'sys-apps/portage/files/portage-2.3.40-prefix-chaining.patch')
-rw-r--r-- | sys-apps/portage/files/portage-2.3.40-prefix-chaining.patch | 921 |
1 files changed, 0 insertions, 921 deletions
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 - |