diff options
Diffstat (limited to 'eclass')
-rw-r--r-- | eclass/estack.eclass | 217 | ||||
-rw-r--r-- | eclass/eutils.eclass | 210 | ||||
-rwxr-xr-x | eclass/tests/estack_eshopts.sh (renamed from eclass/tests/eutils_eshopts.sh) | 4 | ||||
-rwxr-xr-x | eclass/tests/estack_estack.sh (renamed from eclass/tests/eutils_estack.sh) | 4 | ||||
-rwxr-xr-x | eclass/tests/estack_evar.sh (renamed from eclass/tests/eutils_evar.sh) | 4 |
5 files changed, 230 insertions, 209 deletions
diff --git a/eclass/estack.eclass b/eclass/estack.eclass new file mode 100644 index 000000000000..19c388f3d8d2 --- /dev/null +++ b/eclass/estack.eclass @@ -0,0 +1,217 @@ +# Copyright 1999-2017 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +# @ECLASS: estack.eclass +# @MAINTAINER: +# base-system@gentoo.org +# @BLURB: stack-like value storage support +# @DESCRIPTION: +# Support for storing values on stack-like variables. + +if [[ -z ${_ESTACK_ECLASS} ]]; then + +# @FUNCTION: estack_push +# @USAGE: <stack> [items to push] +# @DESCRIPTION: +# Push any number of items onto the specified stack. Pick a name that +# is a valid variable (i.e. stick to alphanumerics), and push as many +# items as you like onto the stack at once. +# +# The following code snippet will echo 5, then 4, then 3, then ... +# @CODE +# estack_push mystack 1 2 3 4 5 +# while estack_pop mystack i ; do +# echo "${i}" +# done +# @CODE +estack_push() { + [[ $# -eq 0 ]] && die "estack_push: incorrect # of arguments" + local stack_name="_ESTACK_$1_" ; shift + eval ${stack_name}+=\( \"\$@\" \) +} + +# @FUNCTION: estack_pop +# @USAGE: <stack> [variable] +# @DESCRIPTION: +# Pop a single item off the specified stack. If a variable is specified, +# the popped item is stored there. If no more items are available, return +# 1, else return 0. See estack_push for more info. +estack_pop() { + [[ $# -eq 0 || $# -gt 2 ]] && die "estack_pop: incorrect # of arguments" + + # We use the fugly _estack_xxx var names to avoid collision with + # passing back the return value. If we used "local i" and the + # caller ran `estack_pop ... i`, we'd end up setting the local + # copy of "i" rather than the caller's copy. The _estack_xxx + # garbage is preferable to using $1/$2 everywhere as that is a + # bit harder to read. + local _estack_name="_ESTACK_$1_" ; shift + local _estack_retvar=$1 ; shift + eval local _estack_i=\${#${_estack_name}\[@\]} + # Don't warn -- let the caller interpret this as a failure + # or as normal behavior (akin to `shift`) + [[ $(( --_estack_i )) -eq -1 ]] && return 1 + + if [[ -n ${_estack_retvar} ]] ; then + eval ${_estack_retvar}=\"\${${_estack_name}\[${_estack_i}\]}\" + fi + eval unset \"${_estack_name}\[${_estack_i}\]\" +} + +# @FUNCTION: evar_push +# @USAGE: <variable to save> [more vars to save] +# @DESCRIPTION: +# This let's you temporarily modify a variable and then restore it (including +# set vs unset semantics). Arrays are not supported at this time. +# +# This is meant for variables where using `local` does not work (such as +# exported variables, or only temporarily changing things in a func). +# +# For example: +# @CODE +# evar_push LC_ALL +# export LC_ALL=C +# ... do some stuff that needs LC_ALL=C set ... +# evar_pop +# +# # You can also save/restore more than one var at a time +# evar_push BUTTERFLY IN THE SKY +# ... do stuff with the vars ... +# evar_pop # This restores just one var, SKY +# ... do more stuff ... +# evar_pop 3 # This pops the remaining 3 vars +# @CODE +evar_push() { + local var val + for var ; do + [[ ${!var+set} == "set" ]] \ + && val=${!var} \ + || val="unset_76fc3c462065bb4ca959f939e6793f94" + estack_push evar "${var}" "${val}" + done +} + +# @FUNCTION: evar_push_set +# @USAGE: <variable to save> [new value to store] +# @DESCRIPTION: +# This is a handy shortcut to save and temporarily set a variable. If a value +# is not specified, the var will be unset. +evar_push_set() { + local var=$1 + evar_push ${var} + case $# in + 1) unset ${var} ;; + 2) printf -v "${var}" '%s' "$2" ;; + *) die "${FUNCNAME}: incorrect # of args: $*" ;; + esac +} + +# @FUNCTION: evar_pop +# @USAGE: [number of vars to restore] +# @DESCRIPTION: +# Restore the variables to the state saved with the corresponding +# evar_push call. See that function for more details. +evar_pop() { + local cnt=${1:-bad} + case $# in + 0) cnt=1 ;; + 1) isdigit "${cnt}" || die "${FUNCNAME}: first arg must be a number: $*" ;; + *) die "${FUNCNAME}: only accepts one arg: $*" ;; + esac + + local var val + while (( cnt-- )) ; do + estack_pop evar val || die "${FUNCNAME}: unbalanced push" + estack_pop evar var || die "${FUNCNAME}: unbalanced push" + [[ ${val} == "unset_76fc3c462065bb4ca959f939e6793f94" ]] \ + && unset ${var} \ + || printf -v "${var}" '%s' "${val}" + done +} + +# @FUNCTION: eshopts_push +# @USAGE: [options to `set` or `shopt`] +# @DESCRIPTION: +# Often times code will want to enable a shell option to change code behavior. +# Since changing shell options can easily break other pieces of code (which +# assume the default state), eshopts_push is used to (1) push the current shell +# options onto a stack and (2) pass the specified arguments to set. +# +# If the first argument is '-s' or '-u', we assume you want to call `shopt` +# rather than `set` as there are some options only available via that. +# +# A common example is to disable shell globbing so that special meaning/care +# may be used with variables/arguments to custom functions. That would be: +# @CODE +# eshopts_push -o noglob +# for x in ${foo} ; do +# if ...some check... ; then +# eshopts_pop +# return 0 +# fi +# done +# eshopts_pop +# @CODE +eshopts_push() { + if [[ $1 == -[su] ]] ; then + estack_push eshopts "$(shopt -p)" + [[ $# -eq 0 ]] && return 0 + shopt "$@" || die "${FUNCNAME}: bad options to shopt: $*" + else + estack_push eshopts $- + [[ $# -eq 0 ]] && return 0 + set "$@" || die "${FUNCNAME}: bad options to set: $*" + fi +} + +# @FUNCTION: eshopts_pop +# @USAGE: +# @DESCRIPTION: +# Restore the shell options to the state saved with the corresponding +# eshopts_push call. See that function for more details. +eshopts_pop() { + local s + estack_pop eshopts s || die "${FUNCNAME}: unbalanced push" + if [[ ${s} == "shopt -"* ]] ; then + eval "${s}" || die "${FUNCNAME}: sanity: invalid shopt options: ${s}" + else + set +$- || die "${FUNCNAME}: sanity: invalid shell settings: $-" + set -${s} || die "${FUNCNAME}: sanity: unable to restore saved shell settings: ${s}" + fi +} + +# @FUNCTION: eumask_push +# @USAGE: <new umask> +# @DESCRIPTION: +# Set the umask to the new value specified while saving the previous +# value onto a stack. Useful for temporarily changing the umask. +eumask_push() { + estack_push eumask "$(umask)" + umask "$@" || die "${FUNCNAME}: bad options to umask: $*" +} + +# @FUNCTION: eumask_pop +# @USAGE: +# @DESCRIPTION: +# Restore the previous umask state. +eumask_pop() { + [[ $# -eq 0 ]] || die "${FUNCNAME}: we take no options" + local s + estack_pop eumask s || die "${FUNCNAME}: unbalanced push" + umask ${s} || die "${FUNCNAME}: sanity: could not restore umask: ${s}" +} + +# @FUNCTION: isdigit +# @USAGE: <number> [more numbers] +# @DESCRIPTION: +# Return true if all arguments are numbers. +isdigit() { + local d + for d ; do + [[ ${d:-bad} == *[!0-9]* ]] && return 1 + done + return 0 +} + +_ESTACK_ECLASS=1 +fi #_ESTACK_ECLASS diff --git a/eclass/eutils.eclass b/eclass/eutils.eclass index ac6a4854d17b..79ec00042a3f 100644 --- a/eclass/eutils.eclass +++ b/eclass/eutils.eclass @@ -19,6 +19,13 @@ _EUTILS_ECLASS=1 inherit multilib toolchain-funcs +# implicitly inherited (now split) eclasses +case ${EAPI:-0} in +0|1|2|3|4|5|6) + inherit estack + ;; +esac + # @FUNCTION: eqawarn # @USAGE: [message] # @DESCRIPTION: @@ -63,209 +70,6 @@ egit_clean() { find "$@" -type d -name '.git*' -prune -print0 | xargs -0 rm -rf } -# @FUNCTION: estack_push -# @USAGE: <stack> [items to push] -# @DESCRIPTION: -# Push any number of items onto the specified stack. Pick a name that -# is a valid variable (i.e. stick to alphanumerics), and push as many -# items as you like onto the stack at once. -# -# The following code snippet will echo 5, then 4, then 3, then ... -# @CODE -# estack_push mystack 1 2 3 4 5 -# while estack_pop mystack i ; do -# echo "${i}" -# done -# @CODE -estack_push() { - [[ $# -eq 0 ]] && die "estack_push: incorrect # of arguments" - local stack_name="_ESTACK_$1_" ; shift - eval ${stack_name}+=\( \"\$@\" \) -} - -# @FUNCTION: estack_pop -# @USAGE: <stack> [variable] -# @DESCRIPTION: -# Pop a single item off the specified stack. If a variable is specified, -# the popped item is stored there. If no more items are available, return -# 1, else return 0. See estack_push for more info. -estack_pop() { - [[ $# -eq 0 || $# -gt 2 ]] && die "estack_pop: incorrect # of arguments" - - # We use the fugly _estack_xxx var names to avoid collision with - # passing back the return value. If we used "local i" and the - # caller ran `estack_pop ... i`, we'd end up setting the local - # copy of "i" rather than the caller's copy. The _estack_xxx - # garbage is preferable to using $1/$2 everywhere as that is a - # bit harder to read. - local _estack_name="_ESTACK_$1_" ; shift - local _estack_retvar=$1 ; shift - eval local _estack_i=\${#${_estack_name}\[@\]} - # Don't warn -- let the caller interpret this as a failure - # or as normal behavior (akin to `shift`) - [[ $(( --_estack_i )) -eq -1 ]] && return 1 - - if [[ -n ${_estack_retvar} ]] ; then - eval ${_estack_retvar}=\"\${${_estack_name}\[${_estack_i}\]}\" - fi - eval unset \"${_estack_name}\[${_estack_i}\]\" -} - -# @FUNCTION: evar_push -# @USAGE: <variable to save> [more vars to save] -# @DESCRIPTION: -# This let's you temporarily modify a variable and then restore it (including -# set vs unset semantics). Arrays are not supported at this time. -# -# This is meant for variables where using `local` does not work (such as -# exported variables, or only temporarily changing things in a func). -# -# For example: -# @CODE -# evar_push LC_ALL -# export LC_ALL=C -# ... do some stuff that needs LC_ALL=C set ... -# evar_pop -# -# # You can also save/restore more than one var at a time -# evar_push BUTTERFLY IN THE SKY -# ... do stuff with the vars ... -# evar_pop # This restores just one var, SKY -# ... do more stuff ... -# evar_pop 3 # This pops the remaining 3 vars -# @CODE -evar_push() { - local var val - for var ; do - [[ ${!var+set} == "set" ]] \ - && val=${!var} \ - || val="unset_76fc3c462065bb4ca959f939e6793f94" - estack_push evar "${var}" "${val}" - done -} - -# @FUNCTION: evar_push_set -# @USAGE: <variable to save> [new value to store] -# @DESCRIPTION: -# This is a handy shortcut to save and temporarily set a variable. If a value -# is not specified, the var will be unset. -evar_push_set() { - local var=$1 - evar_push ${var} - case $# in - 1) unset ${var} ;; - 2) printf -v "${var}" '%s' "$2" ;; - *) die "${FUNCNAME}: incorrect # of args: $*" ;; - esac -} - -# @FUNCTION: evar_pop -# @USAGE: [number of vars to restore] -# @DESCRIPTION: -# Restore the variables to the state saved with the corresponding -# evar_push call. See that function for more details. -evar_pop() { - local cnt=${1:-bad} - case $# in - 0) cnt=1 ;; - 1) isdigit "${cnt}" || die "${FUNCNAME}: first arg must be a number: $*" ;; - *) die "${FUNCNAME}: only accepts one arg: $*" ;; - esac - - local var val - while (( cnt-- )) ; do - estack_pop evar val || die "${FUNCNAME}: unbalanced push" - estack_pop evar var || die "${FUNCNAME}: unbalanced push" - [[ ${val} == "unset_76fc3c462065bb4ca959f939e6793f94" ]] \ - && unset ${var} \ - || printf -v "${var}" '%s' "${val}" - done -} - -# @FUNCTION: eshopts_push -# @USAGE: [options to `set` or `shopt`] -# @DESCRIPTION: -# Often times code will want to enable a shell option to change code behavior. -# Since changing shell options can easily break other pieces of code (which -# assume the default state), eshopts_push is used to (1) push the current shell -# options onto a stack and (2) pass the specified arguments to set. -# -# If the first argument is '-s' or '-u', we assume you want to call `shopt` -# rather than `set` as there are some options only available via that. -# -# A common example is to disable shell globbing so that special meaning/care -# may be used with variables/arguments to custom functions. That would be: -# @CODE -# eshopts_push -o noglob -# for x in ${foo} ; do -# if ...some check... ; then -# eshopts_pop -# return 0 -# fi -# done -# eshopts_pop -# @CODE -eshopts_push() { - if [[ $1 == -[su] ]] ; then - estack_push eshopts "$(shopt -p)" - [[ $# -eq 0 ]] && return 0 - shopt "$@" || die "${FUNCNAME}: bad options to shopt: $*" - else - estack_push eshopts $- - [[ $# -eq 0 ]] && return 0 - set "$@" || die "${FUNCNAME}: bad options to set: $*" - fi -} - -# @FUNCTION: eshopts_pop -# @USAGE: -# @DESCRIPTION: -# Restore the shell options to the state saved with the corresponding -# eshopts_push call. See that function for more details. -eshopts_pop() { - local s - estack_pop eshopts s || die "${FUNCNAME}: unbalanced push" - if [[ ${s} == "shopt -"* ]] ; then - eval "${s}" || die "${FUNCNAME}: sanity: invalid shopt options: ${s}" - else - set +$- || die "${FUNCNAME}: sanity: invalid shell settings: $-" - set -${s} || die "${FUNCNAME}: sanity: unable to restore saved shell settings: ${s}" - fi -} - -# @FUNCTION: eumask_push -# @USAGE: <new umask> -# @DESCRIPTION: -# Set the umask to the new value specified while saving the previous -# value onto a stack. Useful for temporarily changing the umask. -eumask_push() { - estack_push eumask "$(umask)" - umask "$@" || die "${FUNCNAME}: bad options to umask: $*" -} - -# @FUNCTION: eumask_pop -# @USAGE: -# @DESCRIPTION: -# Restore the previous umask state. -eumask_pop() { - [[ $# -eq 0 ]] || die "${FUNCNAME}: we take no options" - local s - estack_pop eumask s || die "${FUNCNAME}: unbalanced push" - umask ${s} || die "${FUNCNAME}: sanity: could not restore umask: ${s}" -} - -# @FUNCTION: isdigit -# @USAGE: <number> [more numbers] -# @DESCRIPTION: -# Return true if all arguments are numbers. -isdigit() { - local d - for d ; do - [[ ${d:-bad} == *[!0-9]* ]] && return 1 - done - return 0 -} - # @VARIABLE: EPATCH_SOURCE # @DESCRIPTION: # Default directory to search for patches. diff --git a/eclass/tests/eutils_eshopts.sh b/eclass/tests/estack_eshopts.sh index 2e9bbb6d4612..606a17cfb053 100755 --- a/eclass/tests/eutils_eshopts.sh +++ b/eclass/tests/estack_eshopts.sh @@ -1,10 +1,10 @@ #!/bin/bash -# Copyright 1999-2015 Gentoo Foundation +# Copyright 1999-2017 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 source tests-common.sh -inherit eutils +inherit estack test-it() { local s0 s1 s2 diff --git a/eclass/tests/eutils_estack.sh b/eclass/tests/estack_estack.sh index c1fecf323133..4845243d3ae4 100755 --- a/eclass/tests/eutils_estack.sh +++ b/eclass/tests/estack_estack.sh @@ -1,10 +1,10 @@ #!/bin/bash -# Copyright 1999-2015 Gentoo Foundation +# Copyright 1999-2017 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 source tests-common.sh -inherit eutils +inherit estack tbegin "initial stack state" estack_pop teststack diff --git a/eclass/tests/eutils_evar.sh b/eclass/tests/estack_evar.sh index f8db340f723d..29badba0079e 100755 --- a/eclass/tests/eutils_evar.sh +++ b/eclass/tests/estack_evar.sh @@ -1,10 +1,10 @@ #!/bin/bash -# Copyright 1999-2015 Gentoo Foundation +# Copyright 1999-2017 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 source tests-common.sh -inherit eutils +inherit estack tbegin "simple push/pop" VAR=1 |