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