avoids bugs and confusion that happen occasionally when phases are accidentally left around but not exported so they don't do anything. This is also the first step if we want to make the exporting automatic in the future to make sure that doesn't suddenly activate previously unexported phases. Change-Id: I4f7c5de4974e547c2596d138839dd41738d61e68
308 lines
11 KiB
Bash
308 lines
11 KiB
Bash
#!/usr/bin/env bash
|
|
# vim: set sw=4 sts=4 et :
|
|
|
|
# Copyright (c) 2007, 2008, 2009, 2010 Ciaran McCreesh
|
|
# Copyright (c) 2009 Bo Ørsted Andresen
|
|
#
|
|
# This file is part of the Paludis package manager. Paludis is free software;
|
|
# you can redistribute it and/or modify it under the terms of the GNU General
|
|
# Public License, version 2, as published by the Free Software Foundation.
|
|
#
|
|
# Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
# details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License along with
|
|
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|
# Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
export_exlib_phases()
|
|
{
|
|
[[ -z "${CURRENT_EXLIB}" ]] && die "export_exlib_phases called but CURRENT_EXLIB undefined"
|
|
|
|
local e
|
|
for e in "$@" ; do
|
|
if [[ "${e}" == builtin_* ]] || ! has "${e}" ${PALUDIS_EBUILD_FUNCTIONS}; then
|
|
die "$e should not be in export_exlib_phases for ${CURRENT_EXLIB}"
|
|
fi
|
|
eval "${e}() { type -t ${CURRENT_EXLIB}_${e} >/dev/null || \
|
|
die \"exported phase function ${CURRENT_EXLIB}_${e} does not exist\" ; ${CURRENT_EXLIB}_${e} \"\$@\" ; }"
|
|
PALUDIS_CHECK_EXPORTED_PHASES+=" ${CURRENT_EXLIB}_${e}"
|
|
done
|
|
}
|
|
|
|
exparam()
|
|
{
|
|
die "exparam is banned outside exlibs"
|
|
}
|
|
|
|
exparam_var_name()
|
|
{
|
|
local var=EXPARAMVAR_${1//-/__dash__}
|
|
var=${var//./__dot__}
|
|
var=${var//+/__plus__}
|
|
echo ${var}
|
|
}
|
|
|
|
exparam_print()
|
|
{
|
|
case "${1}" in
|
|
-a) eval "${2}=( \"\${${3}}\" )" ;;
|
|
-v) eval "${2}=\"\${${3}}\"" ;;
|
|
*) eval "echo \"\${${1}}\"" ;;
|
|
esac
|
|
}
|
|
|
|
exparam_internal()
|
|
{
|
|
local i e=${1} a to_var v a_v=$(exparam_var_name ${1})__ALLDECLS__ b_v=$(exparam_var_name ${1})__BOOLEANS__
|
|
shift
|
|
|
|
if [[ ${1} == -b ]]; then
|
|
[[ ${#} -eq 2 ]] || die "exparam ${1} requires exactly two arguments"
|
|
shift
|
|
has "${1}" ${!b_v} || die "${e}.exlib has no ${1} boolean"
|
|
v=$(exparam_var_name ${e})_${1}
|
|
if ${!v}; then
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
if [[ ${1} == -v ]]; then
|
|
[[ ${#} -eq 3 ]] || die "exparam ${1} requires exactly three arguments"
|
|
a=${1}
|
|
to_var=${2}
|
|
shift 2
|
|
else
|
|
[[ ${#} -eq 1 ]] || die "exparam requires exactly one argument"
|
|
fi
|
|
|
|
v=$(exparam_var_name ${e})_${1%\[*}
|
|
if [[ ${1} == *\[*\] ]]; then
|
|
has "${1%\[*}[]" ${!a_v} || die "${e}.exlib has no ${1%\[*} array"
|
|
i=${1#*\[}
|
|
i=${i%\]}
|
|
case "${i}" in
|
|
"#") exparam_print ${to_var:+-v "${to_var}"} "#${v}[*]" ;;
|
|
"*"|"@") exparam_print ${to_var:+-a "${to_var}"} "${v}[${i}]" ;;
|
|
+([[:digit:]])) exparam_print ${to_var:+-v "${to_var}"} "${v}[${i}]" ;;
|
|
*) die "Invalid index in exparam ${1}" ;;
|
|
esac
|
|
else
|
|
has "${1}" ${!a_v%\[\]} || die "${e}.exlib has no ${1} parameter"
|
|
exparam_print ${to_var:+-v "${to_var}"} "${v}"
|
|
fi
|
|
}
|
|
|
|
myexparam()
|
|
{
|
|
[[ -z "${CURRENT_EXLIB}" ]] && die "myexparam called but CURRENT_EXLIB undefined"
|
|
|
|
local bool=false
|
|
if [[ ${1} == -b ]]; then
|
|
bool=true
|
|
shift
|
|
fi
|
|
|
|
local v=${1%%=*} a_v="$(exparam_var_name ${CURRENT_EXLIB})__ALLDECLS__"
|
|
[[ ${1} == *=\[ && ${#} -gt 1 ]] && v+="[]"
|
|
printf -v "${a_v}" "%s %s" "${!a_v}" "${v}"
|
|
if ${bool}; then
|
|
local b_v="$(exparam_var_name ${CURRENT_EXLIB})__BOOLEANS__"
|
|
printf -v "${b_v}" "%s %s" "${!b_v}" "${v}"
|
|
fi
|
|
|
|
v=$(exparam_var_name ${CURRENT_EXLIB})_${v%\[\]}
|
|
if ! declare -p ${v} &>/dev/null && [[ ${1} == *=* ]]; then
|
|
if [[ ${1} == *=\[ && ${#} -gt 1 ]]; then
|
|
shift
|
|
local i a=()
|
|
while [[ ${#} -gt 1 ]]; do
|
|
a+=( "${1}" )
|
|
shift
|
|
done
|
|
[[ ${1} == \] ]] || die "Array encountered with no closing ]"
|
|
eval "${v}=( \"\${a[@]}\" )"
|
|
else
|
|
printf -v "${v}" "%s" "${1#*=}"
|
|
fi
|
|
fi
|
|
|
|
if ${bool} && ! has "${!v}" true false; then
|
|
die "exparam ${1%%=*} for ${CURRENT_EXLIB}.exlib must be 'true' or 'false'"
|
|
fi
|
|
}
|
|
|
|
require()
|
|
{
|
|
ebuild_notice "debug" "Command 'require ${@}', using EXLIBSDIRS '${EXLIBSDIRS}'"
|
|
local exlibs e ee p a=() location v a_v v_qa
|
|
# parse exlib parameters
|
|
while [[ -n $@ ]]; do
|
|
if [[ ${1} == +('[') ]]; then
|
|
[[ -z ${e} ]] && die "\"${1}\" encountered with no preceding exlib"
|
|
p=${1}
|
|
shift
|
|
while [[ -n ${1} && ${1} != ${p//\[/\]} ]]; do
|
|
v="${1%%=*}"
|
|
if [[ ${1#*=} == ${p} ]]; then
|
|
v+="[]"
|
|
a=()
|
|
shift
|
|
while [[ -n ${1} && ${1} != ${p//\[/\]} ]]; do
|
|
a+=( "${1}" )
|
|
shift
|
|
done
|
|
[[ ${1} == ${p//\[/\]} ]] || die "\"${p}\" encountered with no closing \"${p//[/]}\" for array ${v}"
|
|
eval "$(exparam_var_name ${e})_${v%\[\]}=( \"\${a[@]}\" )"
|
|
else
|
|
printf -v "$(exparam_var_name ${e})_${1%%=*}" "%s" "${1#*=}"
|
|
fi
|
|
a_v="$(exparam_var_name ${e})__ALL__"
|
|
printf -v "${a_v}" "%s %s" "${!a_v}" "${v}"
|
|
shift
|
|
done
|
|
[[ ${1} == ${p//\[/\]} ]] || die "\"${p}\" encountered with no closing \"${p//[/]}\""
|
|
else
|
|
e=${1}
|
|
exlibs+=" ${e}"
|
|
fi
|
|
shift
|
|
done
|
|
# source exlibs
|
|
for e in ${exlibs}; do
|
|
location=
|
|
for ee in ${EXLIBSDIRS} ; do
|
|
[[ -f "${ee}/${e}.exlib" ]] && location="${ee}/${e}.exlib"
|
|
done
|
|
local old_CURRENT_EXLIB="${CURRENT_EXLIB}"
|
|
export CURRENT_EXLIB="${e}"
|
|
local old_PALUDIS_CHECK_EXPORTED_PHASES="${PALUDIS_CHECK_EXPORTED_PHASES}"
|
|
export PALUDIS_CHECK_EXPORTED_PHASES=
|
|
alias exparam="exparam_internal ${CURRENT_EXLIB}"
|
|
|
|
for v in ${PALUDIS_SOURCE_MERGED_VARIABLES} ${PALUDIS_BRACKET_MERGED_VARIABLES} ; do
|
|
local c_v="current_${v}" u_v="unset_${v}"
|
|
local ${c_v}="${!v}"
|
|
local ${u_v}="${!v-unset}"
|
|
unset ${v}
|
|
done
|
|
|
|
for v_qa in ${PALUDIS_ECLASS_MUST_NOT_SET_VARIABLES} ; do
|
|
local v=${v_qa#qa:}
|
|
local c_v="current_${v}" u_v="unset_${v}"
|
|
export -n ${c_v}="${!v}"
|
|
export -n ${u_v}="${!v-unset}"
|
|
done
|
|
|
|
[[ -z "${location}" ]] && die "Error finding exlib ${e} in ${EXLIBSDIRS}"
|
|
source "${location}" || die "Error sourcing exlib ${e}"
|
|
hasq "${CURRENT_EXLIB}" ${INHERITED} || export INHERITED="${INHERITED} ${CURRENT_EXLIB}"
|
|
|
|
local f e_f
|
|
for f in ${PALUDIS_EBUILD_FUNCTIONS} ; do
|
|
[[ ${f} == builtin_* ]] && continue
|
|
[[ $(type -t ${CURRENT_EXLIB}_${f}) == function ]] || continue
|
|
e_f=$(declare -f ${CURRENT_EXLIB}_${f})
|
|
eval "${e_f/{/{ verify_not_called_cross_phase ${f}}"
|
|
done
|
|
|
|
for v in ${PALUDIS_SOURCE_MERGED_VARIABLES} ; do
|
|
local e_v="E_${v}"
|
|
export -n ${e_v}="${!e_v} ${!v}"
|
|
done
|
|
|
|
for v in ${PALUDIS_BRACKET_MERGED_VARIABLES} ; do
|
|
local e_v="E_${v}"
|
|
if [[ -z "${!v}" ]] ; then
|
|
export -n ${e_v}="${!e_v}"
|
|
elif has "${v}" ${PALUDIS_BRACKET_MERGED_VARIABLES_ANNOTATABLE} ; then
|
|
export -n ${e_v}="${!e_v} ( ${!v} ) [[ ${PALUDIS_BRACKET_MERGED_VARIABLES_ANNOTATION} =
|
|
[ ${CURRENT_EXLIB}.exlib ] ]]"
|
|
else
|
|
export -n ${e_v}="${!e_v} ( ${!v} )"
|
|
fi
|
|
done
|
|
|
|
for v in ${PALUDIS_SOURCE_MERGED_VARIABLES} ${PALUDIS_BRACKET_MERGED_VARIABLES} ; do
|
|
local c_v="current_${v}" u_v="unset_${v}"
|
|
[[ "unset" == ${!u_v} ]] && unset ${v} || export ${v}="${!c_v}"
|
|
done
|
|
|
|
for v_qa in ${PALUDIS_ECLASS_MUST_NOT_SET_VARIABLES} ; do
|
|
local v=${v_qa#qa:}
|
|
local c_v="current_${v}" u_v="unset_${v}"
|
|
if [[ ${!c_v} != ${!v} || ${!u_v} != ${!v-unset} ]]; then
|
|
if [[ ${v} == ${v_qa} ]] ; then
|
|
die "Variable '${v}' illegally set by ${location}"
|
|
else
|
|
ebuild_notice "qa" "Variable '${v}' should not be set by ${location}"
|
|
export -n ${c_v}="${!v}"
|
|
export -n ${u_v}="${!v-unset}"
|
|
fi
|
|
fi
|
|
done
|
|
|
|
# die on required exlib parameters that haven't been supplied
|
|
local c_v v
|
|
a_v=$(exparam_var_name ${CURRENT_EXLIB})__ALLDECLS__
|
|
for v in ${!a_v}; do
|
|
c_v=$(exparam_var_name ${CURRENT_EXLIB})_${v%\[\]}
|
|
if [[ $(eval "declare -p ${c_v}") == declare\ -a\ ${c_v}=* ]]; then
|
|
[[ ${v} == *\[\] ]] || die "${CURRENT_EXLIB}.exlib requires a scalar ${v} parameter but got an array"
|
|
elif [[ -n ${!c_v+set} ]]; then
|
|
[[ ${v} != *\[\] ]] || die "${CURRENT_EXLIB}.exlib requires an array ${v} but got a scalar"
|
|
else
|
|
die "${CURRENT_EXLIB}.exlib requires a ${v} parameter"
|
|
fi
|
|
done
|
|
|
|
# die on supplied exlib parameters which haven't been declared
|
|
v=$(exparam_var_name ${CURRENT_EXLIB})__ALL__
|
|
for v in ${!v}; do
|
|
has ${v} ${!a_v} || die "${CURRENT_EXLIB}.exlib takes no ${v} parameter"
|
|
done
|
|
|
|
for v in ${PALUDIS_EBUILD_FUNCTIONS} ; do
|
|
c_v=${CURRENT_EXLIB}_${v}
|
|
if has ${c_v} ${PALUDIS_CHECK_EXPORTED_PHASES}; then
|
|
type -t ${c_v} >/dev/null || die "exported phase function ${v} does not exist"
|
|
else
|
|
type -t ${c_v} >/dev/null && die "phase function ${c_v} exists but was not exported"
|
|
fi
|
|
done
|
|
export PALUDIS_CHECK_EXPORTED_PHASES="${old_PALUDIS_CHECK_EXPORTED_PHASES}"
|
|
|
|
export CURRENT_EXLIB="${old_CURRENT_EXLIB}"
|
|
if [[ -n ${CURRENT_EXLIB} ]]; then
|
|
alias exparam="exparam_internal ${CURRENT_EXLIB}"
|
|
else
|
|
unalias exparam
|
|
fi
|
|
done
|
|
}
|
|
|
|
default()
|
|
{
|
|
[[ $(type -t "default_$(paludis_phase_to_function_name "${!PALUDIS_EBUILD_PHASE_VAR}")" ) == "function" ]] || \
|
|
die "default_$(paludis_phase_to_function_name "${!PALUDIS_EBUILD_PHASE_VAR}") is not a function"
|
|
default_$(paludis_phase_to_function_name "${!PALUDIS_EBUILD_PHASE_VAR}") "$@"
|
|
}
|
|
|
|
illegal_in_global_scope()
|
|
{
|
|
[[ "${!PALUDIS_EBUILD_PHASE_VAR}" == "metadata" ]] \
|
|
&& die "Exheres bug: ${FUNCNAME[1]} must not be called in global scope"
|
|
}
|
|
|
|
verify_not_called_cross_phase() {
|
|
if [[ ${1:-${FUNCNAME[1]}} != $(paludis_phase_to_function_name "${!PALUDIS_EBUILD_PHASE_VAR}") ]] ; then
|
|
local correct_phase=${1:-${FUNCNAME[1]}#src_}; correct_phase=${correct_phase#pkg_}; correct_phase=${correct_phase#builtin_}
|
|
die "Exheres bug: ${FUNCNAME[1]} must only be called in the ${corect_phase} phase, was called in ${!PALUDIS_EBUILD_PHASE_VAR}"
|
|
fi
|
|
}
|
|
|