Second patch containing only the ebuild.sh change.
Answers to suggestions inline.

On Thu, Sep 11, 2014 at 12:49 PM, Zac Medico <zmed...@gentoo.org> wrote:

> On 09/11/2014 04:18 AM, Bertrand Simonnet wrote:
> > Hi guys,
> >
> > I have been working on a patch to make package.env (and env/ files)
> > stackable with the profiles.
> > The main goal would be to have a mechanism to be able to define a
> > per-package, per-profile environment in a simple way.
> >
> > We can currently do this with profile.bashrc but we have to add some
> > logic there to decide which package are relevant which already exist in
> > ebuild.sh and pym/*.
> >
> > I attached my current patch which contain two main modifications:
> > - ebuild.sh walk the profile and source all scripts with path:
> > ${profile_path}/env/${category}/${PN}
> > - config.py imports package.env from all profiles and then from
> > /etc/portage/package.env
>
> It seems like duplication of work, to load the per-package env in
> _grab_pkg_env on the python side, and to source it again on the bash
> side. Why load the environments in both places? Note that the python
> getconfig function only supports variable settings (no executable code),
> which is very limited to what can be done when sourcing the files in bash.
>
> Right.
The python part was mostly useful from a reuse point of view (write few
scripts
and enable them for some packages only. As the python mechanism is less
powerful
than I thought, I removed it.


> > Note:
> > * I gated the env/$CATEGORY/$PN scripts with a new feature:
> per-profile-env.
> >    I couldn't do this with package.env as the scripts are parsed before
> > we initialize self.features.
> > * I am not particularly attach to both package.env and
> > env/$CATEGORY/$PN. It might make more sense to have only
> > env/$CATEGORY/$PN, especially considering the problem with package.env.
> >
> > Do you have any suggestions on this patch ?
>
> 1) If you want both the python-side env loading and the bash-side env
> loading, I would make those into separate features, since sourcing the
> files in bash supports full bash syntax while the python-side getconfig
> function does not.
>
Fixed: removed the python part completly

2) When adding new global functions in ebuild.sh, please unset them
> inside bin/save-ebuild-env.sh, when internal functions are stripped from
> the environment.
>
Done.


> 3) You might want to look into using the repository's
> metadata/layout.conf profile-formats setting, as an alternative to using
> FEATURES to control profile-related behavior.

I replaced the FEATURES gate by a profile-formats option.
I added some logic to find layout.conf for a given profile path. (find the
first
parent dir named profiles then check ../metadata/layout.conf)
Is there a corner case that I missed?

> Would you be willing to accept this patch once the few problems are
> > sorted out ?
>
> I can't speak for everyone, but I'm pretty sure we can work something out.
> --
> Thanks,
> Zac
>
>
Thanks,
Bertrand
From 8a7e493d343bd986fa14e3c7148e76012e6f98d6 Mon Sep 17 00:00:00 2001
From: Bertrand SIMONNET <bsimon...@chromium.org>
Date: Fri, 12 Sep 2014 05:07:20 -0700
Subject: [PATCH] Make env/ bash scripts profile specific

This generalize the /etc/portage/env mechanism to be stackable with profiles.
ebuild.sh will walk the profiles and sources scripts in env/ following the same
matching rules as for /etc/portage/env.

Change-Id: I16bcd75790213d2204f83d4aa6e8b910f8829b6e
---
 bin/ebuild.sh                    | 78 ++++++++++++++++++++++++----------------
 bin/isolated-functions.sh        | 23 ++++++++++++
 bin/save-ebuild-env.sh           |  1 +
 pym/portage/repository/config.py |  2 +-
 4 files changed, 73 insertions(+), 31 deletions(-)

diff --git a/bin/ebuild.sh b/bin/ebuild.sh
index be044e0..87e44f4 100755
--- a/bin/ebuild.sh
+++ b/bin/ebuild.sh
@@ -67,11 +67,11 @@ unset BASH_ENV
 # earlier portage versions do not detect a version change in this case
 # (9999 to 9999) and therefore they try execute an incompatible version of
 # ebuild.sh during the upgrade.
-export PORTAGE_BZIP2_COMMAND=${PORTAGE_BZIP2_COMMAND:-bzip2} 
+export PORTAGE_BZIP2_COMMAND=${PORTAGE_BZIP2_COMMAND:-bzip2}
 
 # These two functions wrap sourcing and calling respectively.  At present they
 # perform a qa check to make sure eclasses and ebuilds and profiles don't mess
-# with shell opts (shopts).  Ebuilds/eclasses changing shopts should reset them 
+# with shell opts (shopts).  Ebuilds/eclasses changing shopts should reset them
 # when they are done.
 
 __qa_source() {
@@ -275,7 +275,7 @@ inherit() {
 		set +f
 
 		__qa_source "$location" || die "died sourcing $location in inherit()"
-		
+
 		#turn off glob expansion
 		set -f
 
@@ -290,7 +290,7 @@ inherit() {
 
 		[ "${B_IUSE+set}"     = set ] && IUSE="${B_IUSE}"
 		[ "${B_IUSE+set}"     = set ] || unset IUSE
-		
+
 		[ "${B_REQUIRED_USE+set}"     = set ] && REQUIRED_USE="${B_REQUIRED_USE}"
 		[ "${B_REQUIRED_USE+set}"     = set ] || unset REQUIRED_USE
 
@@ -372,42 +372,60 @@ __source_all_bashrcs() {
 		restore_IFS
 		for x in "${path_array[@]}" ; do
 			[ -f "$x/profile.bashrc" ] && __qa_source "$x/profile.bashrc"
+			__profile_env_enabled "${x}" && \
+				__source_env_files "$x/env"
 		done
 	fi
 
-	if [ -r "${PORTAGE_BASHRC}" ] ; then
-		if [ "$PORTAGE_DEBUG" != "1" ] || [ "${-/x/}" != "$-" ]; then
-			source "${PORTAGE_BASHRC}"
-		else
-			set -x
-			source "${PORTAGE_BASHRC}"
-			set +x
-		fi
-	fi
+	# The user's bashrc is the ONLY non-portage bit of code
+	# that can change shopts without a QA violation.
+	__try_source "${PORTAGE_BASHRC}" "no_qa"
 
 	if [[ $EBUILD_PHASE != depend ]] ; then
-		# The user's bashrc is the ONLY non-portage bit of code that can
-		# change shopts without a QA violation.
-		for x in "${PM_EBUILD_HOOK_DIR}"/${CATEGORY}/{${PN},${PN}:${SLOT%/*},${P},${PF}}; do
-			if [ -r "${x}" ]; then
-				# If $- contains x, then tracing has already been enabled
-				# elsewhere for some reason. We preserve it's state so as
-				# not to interfere.
-				if [ "$PORTAGE_DEBUG" != "1" ] || [ "${-/x/}" != "$-" ]; then
-					source "${x}"
-				else
-					set -x
-					source "${x}"
-					set +x
-				fi
-			fi
-		done
+		__source_env_files "${PM_EBUILD_HOOK_DIR}" "no_qa"
 	fi
 
 	[ ! -z "${OCC}" ] && export CC="${OCC}"
 	[ ! -z "${OCXX}" ] && export CXX="${OCXX}"
 }
 
+# @FUNCTION: __source_env_files
+# @DESCRIPTION:
+# Source the files relevant to the current package from the given path.
+# If $2 is not 'no_qa', all the scripts are sourced with __qa_source.
+__source_env_files() {
+	for x in "${1}"/${CATEGORY}/{${PN},${PN}:${SLOT%/*},${P},${PF}}; do
+		__try_source "${x}" "${2}"
+	done
+}
+
+# @FUNCTION: __try_source
+# @DESCRIPTION:
+# If the path given as argument exists, source the file while preserving
+# $-.
+# If $2 is not 'no_qa', the file is sourced with __qa_source.
+__try_source() {
+	if [[ -r "$1" ]]; then
+		# If $- contains x, then tracing has already been enabled
+		# elsewhere for some reason. We preserve it's state so as
+		# not to interfere.
+		if [[ "$PORTAGE_DEBUG" != "1" ]] || [[ "${-/x/}" != "$-" ]]; then
+			if [[ "${2}" == "no_qa" ]]; then
+				source "${x}"
+			else
+				__qa_source "${x}"
+			fi
+		else
+			set -x
+			if [[ "${2}" == "no_qa" ]]; then
+				source "${x}"
+			else
+				__qa_source "${x}"
+			fi
+			set +x
+		fi
+	fi
+}
 # === === === === === === === === === === === === === === === === === ===
 # === === === === === functions end, main part begins === === === === ===
 # === === === === === === === === === === === === === === === === === ===
@@ -572,7 +590,7 @@ if ! has "$EBUILD_PHASE" clean cleanrm ; then
 		PDEPEND+="${PDEPEND:+ }${E_PDEPEND}"
 		HDEPEND+="${HDEPEND:+ }${E_HDEPEND}"
 		REQUIRED_USE+="${REQUIRED_USE:+ }${E_REQUIRED_USE}"
-		
+
 		unset ECLASS E_IUSE E_REQUIRED_USE E_DEPEND E_RDEPEND E_PDEPEND E_HDEPEND \
 			__INHERITED_QA_CACHE
 
diff --git a/bin/isolated-functions.sh b/bin/isolated-functions.sh
index a22af57..17a4c61 100644
--- a/bin/isolated-functions.sh
+++ b/bin/isolated-functions.sh
@@ -482,4 +482,27 @@ __repo_attr() {
 	return ${exit_status}
 }
 
+# @FUNCTION: __profile_env_enabled
+# @DESCRIPTION:
+# Return "yes" if the layout.conf file of a given profile $1 has profile-env
+# enabled.
+__profile_env_enabled() {
+	local current_dir="$1"
+	while ! [[ "$(basename "${current_dir}")" == "profiles" ]]; do
+		if [[ "${current_dir}" == "/" ]]; then
+			return 1
+		fi
+		current_dir="$(dirname "${current_dir}")"
+	done
+	local layout="$(dirname "${current_dir}")/metadata/layout.conf"
+	if [[ -f "${layout}" ]]; then
+		while read line; do
+			if [[ "${line}" =~ ^profile-format.*profile-env ]]; then
+				return 0
+			fi
+		done < "${layout}"
+	fi
+	return 1
+}
+
 true
diff --git a/bin/save-ebuild-env.sh b/bin/save-ebuild-env.sh
index 98cff83..8e0cac5 100644
--- a/bin/save-ebuild-env.sh
+++ b/bin/save-ebuild-env.sh
@@ -75,6 +75,7 @@ __save_ebuild_env() {
 		__ebuild_main __ebuild_phase __ebuild_phase_with_hooks \
 		__ebuild_arg_to_phase __ebuild_phase_funcs default \
 		__unpack_tar __unset_colors \
+		__profile_env_enabled __source_env_files __try_source \
 		${QA_INTERCEPTORS}
 
 	___eapi_has_usex && unset -f usex
diff --git a/pym/portage/repository/config.py b/pym/portage/repository/config.py
index 5e0d055..ef8054e 100644
--- a/pym/portage/repository/config.py
+++ b/pym/portage/repository/config.py
@@ -40,7 +40,7 @@ if sys.hexversion >= 0x3000000:
 _invalid_path_char_re = re.compile(r'[^a-zA-Z0-9._\-+:/]')
 
 _valid_profile_formats = frozenset(
-	['pms', 'portage-1', 'portage-2'])
+	['pms', 'portage-1', 'portage-2', 'profile-env'])
 
 _portage1_profiles_allow_directories = frozenset(
 	["portage-1-compat", "portage-1", 'portage-2'])
-- 
2.1.0.rc2.206.gedb03e5

Reply via email to