Index: check-reqs.eclass =================================================================== RCS file: /var/cvsroot/gentoo-x86/eclass/check-reqs.eclass,v retrieving revision 1.8 diff -u -b -B -r1.8 check-reqs.eclass --- check-reqs.eclass 22 Aug 2011 04:46:31 -0000 1.8 +++ check-reqs.eclass 26 Aug 2011 21:50:11 -0000 @@ -4,8 +4,9 @@ # @ECLASS: check-reqs.eclass # @MAINTAINER: -# Bo Ørsted Andresen +# QA Team # @AUTHOR: +# Bo Ørsted Andresen # Original Author: Ciaran McCreesh # @BLURB: Provides a uniform way of handling ebuild which have very high build requirements # @DESCRIPTION: @@ -13,49 +14,36 @@ # build requirements in terms of memory or disk space. It provides a function # which should usually be called during pkg_setup(). # -# From a user perspective, the variable CHECKREQS_ACTION can be set to: -# * "warn" (default), which will display a warning and wait for 15s -# * "error", which will make the ebuild error out -# * "ignore", which will not take any action -# # The chosen action only happens when the system's resources are detected # correctly and only if they are below the threshold specified by the package. # -# For ebuild authors: only use this eclass if you reaaalllllly have stupidly -# high build requirements. At an absolute minimum, you shouldn't be using this -# unless the ebuild needs >256MBytes RAM or >1GByte temporary or install space. -# The code should look something like: -# # @CODE -# pkg_setup() { -# # values in MBytes +# # values in MBytes or suffixed by the metric "2G" # # # need this much memory (does *not* check swap) -# CHECKREQS_MEMORY="256" +# CHECKREQS_MEMORY="256M" # # # need this much temporary build space -# CHECKREQS_DISK_BUILD="2048" +# CHECKREQS_DISK_BUILD="2G" # # # install will need this much space in /usr -# CHECKREQS_DISK_USR="1024" +# CHECKREQS_DISK_USR="1G" # # # install will need this much space in /var -# CHECKREQS_DISK_VAR="1024" +# CHECKREQS_DISK_VAR="1024M" # # # go! -# check_reqs +# pkg_pretend() { +# check-reqs_pkg_pretend +# } +# +# # Run once again to ensure that environment didn't +# # change since the pretend phase. +# pkg_setup() { +# check-reqs_pkg_setup # } # @CODE # -# Alternatively, the check_reqs_conditional function can be used to carry out -# alternate actions (e.g. using a much slower but far less memory intensive -# build option that gives the same end result). -# -# You should *not* override the user's CHECKREQS_ACTION setting, nor should you -# attempt to provide a value if it is unset. Note that the environment variables -# are used rather than parameters for a few reasons: -# * easier to do if use blah ; then things -# * we might add in additional requirements things later # If you don't specify a value for, say, CHECKREQS_MEMORY, then the test is not # carried out. # @@ -66,80 +54,240 @@ # @ECLASS-VARIABLE: CHECKREQS_MEMORY # @DESCRIPTION: -# How much RAM is needed in MB? +# @DEAULT_UNSET +# How much RAM is needed? # @ECLASS-VARIABLE: CHECKREQS_DISK_BUILD # @DESCRIPTION: -# How much diskspace is needed to build the package? In MB +# @DEAULT_UNSET +# How much diskspace is needed to build the package? # @ECLASS-VARIABLE: CHECKREQS_DISK_USR # @DESCRIPTION: -# How much space in /usr is needed to install the package? In MB +# @DEAULT_UNSET +# How much space in /usr is needed to install the package? # @ECLASS-VARIABLE: CHECKREQS_DISK_VAR # @DESCRIPTION: -# How much space is needed in /var? In MB +# @DEAULT_UNSET +# How much space is needed in /var? + +# @ECLASS-VARIABLE: CHECKREQS_IGNORE +# @DESCRIPTION: +# @DEAULT_UNSET +# User set value in environment allowing proceeding without +# sufficient resources. + +CHECKREQS_EXPORTED_FUNCTIONS="pkg_setup" +case "${EAPI:-0}" in + 0|1|2|3) ;; + 4) CHECKREQS_EXPORTED_FUNCTIONS="${EXPORTED_FUNCTIONS} pkg_pretend" ;; + *) die "EAPI=${EAPI} is not supported" ;; +esac # @FUNCTION: check_reqs # @DESCRIPTION: -# Checks the requirements given in the specific variables. If not reached, -# either prints a warning or dies. +# Obsolete function executing all the checks and priting out results check_reqs() { - [[ -n "${1}" ]] && die "Usage: check_reqs" + debug-print-function ${FUNCNAME} "$@" + + echo + ewarn "QA: Package calling old ${FUNCNAME} function." + ewarn "QA: Please file a bug against the package." + ewarn "QA: It should call check-reqs_pkg_pretend and check-reqs_pkg_setup" + ewarn "QA: and possibly use EAPI=4 or later." + echo + + check-reqs_pkg_setup "$@" +} - export CHECKREQS_NEED_SLEEP="" CHECKREQS_NEED_DIE="" - if [[ "$CHECKREQS_ACTION" != "ignore" ]] ; then - [[ -n "$CHECKREQS_MEMORY" ]] && check_build_memory - [[ -n "$CHECKREQS_DISK_BUILD" ]] && check_build_disk \ - "${T}" "${CHECKREQS_DISK_BUILD}" - [[ -n "$CHECKREQS_DISK_USR" ]] && check_build_disk \ - "${ROOT}/usr" "${CHECKREQS_DISK_USR}" - [[ -n "$CHECKREQS_DISK_VAR" ]] && check_build_disk \ - "${ROOT}/var" "${CHECKREQS_DISK_VAR}" +# @FUNCTION: check-reqs_pkg_setup +# @DESCRIPTION: +# Exported function running the resources checks in pkg_setup phase. +# It should be run in both phases to ensure condition changes between +# pkg_pretend and pkg_setup won't affect the build. +check-reqs_pkg_setup() { + debug-print-function ${FUNCNAME} "$@" + + check-reqs_prepare + check-reqs_run + check-reqs_output +} + +# @FUNCTION: check-reqs_pkg_pretend +# @DESCRIPTION: +# Exported function running the resources checks in pkg_pretend phase. +check-reqs_pkg_pretend() { + debug-print-function ${FUNCNAME} "$@" + + check-reqs_pkg_setup "$@" +} + +# @FUNCTION: check-reqs_prepare +# @DESCRIPTION: +# Internal function that checks the variables that should be defined. +check-reqs_prepare() { + debug-print-function ${FUNCNAME} "$@" + + if [[ -z ${CHECKREQS_MEMORY} && + -z ${CHECKREQS_DISK_BUILD} && + -z ${CHECKREQS_DISK_USR} && + -z ${CHECKREQS_DISK_VAR} ]]; then + eerror "Set some check-reqs eclass variables if you want to use it." + eerror "If you are user and see this message fill a bug against the package." + die "${FUNCNAME}: check-reqs eclass called but not actualy used!" fi +} - if [[ -n "${CHECKREQS_NEED_SLEEP}" ]] ; then - echo - ewarn "Bad things may happen! You may abort the build by pressing ctrl+c in" - ewarn "the next 15 seconds." - ewarn " " - einfo "To make this kind of warning a fatal error, add a line to /etc/make.conf" - einfo "setting CHECKREQS_ACTION=\"error\". To skip build requirements checking," - einfo "set CHECKREQS_ACTION=\"ignore\"." - epause 15 +# @FUNCTION: check-reqs_run +# @DESCRIPTION: +# Internal function that runs the check based on variable settings. +check-reqs_run() { + debug-print-function ${FUNCNAME} "$@" + + # some people are *censored* + unset CHECKREQS_FAILED + + [[ -n ${CHECKREQS_MEMORY} ]] && \ + check-reqs_memory \ + ${CHECKREQS_MEMORY} + + [[ -n ${CHECKREQS_DISK_BUILD} ]] && \ + check-reqs_disk \ + "${T}" \ + "${CHECKREQS_DISK_BUILD}" + + [[ -n ${CHECKREQS_DISK_USR} ]] && \ + check-reqs_disk \ + "${EROOT}/usr" \ + "${CHECKREQS_DISK_USR}" + + [[ -n ${CHECKREQS_DISK_VAR} ]] && \ + check-reqs_disk \ + "${EROOT}/var" \ + "${CHECKREQS_DISK_VAR}" +} + +# @FUNCTION: check-reqs_get_mesg +# @DESCRIPTION: +# Internal function that returns number in megabites. +# Converts from 1G=1024 or 1T=1048576 +check-reqs_get_megs() { + debug-print-function ${FUNCNAME} "$@" + + [[ -z ${1} ]] && die "Usage: ${FUNCNAME} [size]" + + local unit=${1//[[:digit:]]/} + local size=${1//[[:alpha:]]/} + + if [[ ${unit//[[:alpha:]]/} != "" ]]; then + die "${FUNCNAME}: Failed to determine units, garbage in variables" + else + # temporary workaround for empty units + unit="M" + fi + + case ${unit} in + [gG]) echo $((1024 * ${size})) ;; + [mM]) echo ${size} ;; + [tT]) echo $((1024 * 1024 * ${size})) ;; + *) + die "${FUNCNAME}: Unknown unit size: ${unit}" + ;; + esac +} + +# @FUNCTION: check-reqs_get_numbers +# @DESCRIPTION: +# Internal function that returns number without the unit. +# Converts from 1G=1 or 150T=150. +check-reqs_get_numbers() { + debug-print-function ${FUNCNAME} "$@" + + [[ -z ${1} ]] && die "Usage: ${FUNCNAME} [size]" + + local size=${1//[[:alpha:]]/} + + # warn about un-united variables + if [[ ${size} == ${1//[[:alpha:]]/} ]]; then + ewarn "QA: Package does not specify unit for the size check" + ewarn "QA: Assuming Megabytes." + ewarn "QA: File bug against the package. It should specify it." fi - if [[ -n "${CHECKREQS_NEED_DIE}" ]] ; then - eerror "Bailing out as specified by CHECKREQS_ACTION" - die "Build requirements not met" + if [[ ${size//[[:digit:]]/} == "" ]]; then + echo ${size} + else + die "${FUNCNAME}: Failed to determine size, garbage in variables." fi } -# @FUNCTION: check_reqs_conditional -# @RETURN: True if requirements check passed, else False +# @FUNCTION: check-reqs_get_unit # @DESCRIPTION: -# Checks the requirements given in the specific variables -check_reqs_conditional() { - [[ -n "${1}" ]] && die "Usage: check_reqs" +# Internal function that returns number without the unit. +# Converts from 1G=1 or 150T=150. +check-reqs_get_unit() { + debug-print-function ${FUNCNAME} "$@" - export CHECKREQS_NEED_SLEEP="" CHECKREQS_NEED_DIE="" - if [[ "$CHECKREQS_ACTION" != "ignore" ]] ; then - [[ -n "$CHECKREQS_MEMORY" ]] && check_build_memory - [[ -n "$CHECKREQS_DISK_BUILD" ]] && check_build_disk \ - "${T}" "${CHECKREQS_DISK_BUILD}" - [[ -n "$CHECKREQS_DISK_USR" ]] && check_build_disk \ - "${ROOT}/usr" "${CHECKREQS_DISK_USR}" - [[ -n "$CHECKREQS_DISK_VAR" ]] && check_build_disk \ - "${ROOT}/var" "${CHECKREQS_DISK_VAR}" + [[ -z ${1} ]] && die "Usage: ${FUNCNAME} [size]" + + local unit=${1//[[:digit:]]/} + + if [[ ${unit//[[:alpha:]]/} != "" ]]; then + die "${FUNCNAME}: Failed to determine units, garbage in variables." + else + # temporary workaround for empty units + unit="M" fi - [[ -z "${CHECKREQS_NEED_SLEEP}" && -z "${CHECKREQS_NEED_DIE}" ]] + case ${unit} in + [gG]) echo "Gigabytes" ;; + [mM]) echo "Megabytes" ;; + [tT]) echo "Terabytes" ;; + *) + die "${FUNCNAME}: Unknown unit size: ${unit}" + ;; + esac +} + +# @FUNCTION: check-reqs_output +# @DESCRIPTION: +# Internal function that prints the warning and dies if required based on +# the test results. +check-reqs_output() { + debug-print-function ${FUNCNAME} "$@" + + local msg="ewarn" + + [[ ${EBUILD_PHASE} == "pretend" && -z ${I_KNOW_WHAT_I_AM_DOING} ]] && msg="eerror" + if [[ -n ${CHECKREQS_FAILED} ]]; then + ${msg} + ${msg} "Space constrains set in the ebuild were not met!" + ${msg} "The build will most probably fail, you should enhance the space" + ${msg} "as per failed tests." + ${msg} + + [[ ${EBUILD_PHASE} == "pretend" && -z ${I_KNOW_WHAT_I_AM_DOING} ]] && \ + die "Build requirements not met!" + fi } -# internal use only! -check_build_memory() { - [[ -n "${1}" ]] && die "Usage: check_build_memory" - check_build_msg_begin "${CHECKREQS_MEMORY}" "MBytes" "RAM" +# @FUNCTION: check-reqs_memory +# @DESCRIPTION: +# Internal function that checks space on the RAM. +check-reqs_memory() { + debug-print-function ${FUNCNAME} "$@" + + [[ -z ${1} ]] && die "Usage: ${FUNCNAME} [size]" + + local size=${1} + local actual_memory + + check-reqs_start_phase \ + $(check-reqs_get_numbers ${size}) \ + $(check-reqs_get_unit ${size}) \ + "RAM" + if [[ -r /proc/meminfo ]] ; then actual_memory=$(sed -n -e '/MemTotal:/s/^[^:]*: *\([0-9]\+\) kB/\1/p' \ /proc/meminfo) @@ -148,60 +296,89 @@ [[ "$?" == "0" ]] && actual_memory=$(echo $actual_memory | sed -e 's/^[^:=]*[:=]//' ) fi - if [[ -n "${actual_memory}" ]] ; then - if [[ ${actual_memory} -lt $((1024 * ${CHECKREQS_MEMORY})) ]] ; then + if [[ -n ${actual_memory} ]] ; then + if [[ ${actual_memory} -lt $((1024 * $(check-reqs_get_megs ${size}))) ]] ; then eend 1 - check_build_msg_ick "${CHECKREQS_MEMORY}" "MBytes" "RAM" + check-reqs_unsattisfied \ + $(check-reqs_get_numbers ${size}) \ + $(check-reqs_get_unit ${size}) \ + "RAM" else eend 0 fi else eend 1 - ewarn "Couldn't determine amount of memory, skipping ..." + ewarn "Couldn't determine amount of memory, skipping..." fi } -# internal use only! -check_build_disk() { - [[ -z "${2}" ]] && die "Usage: check_build_disk where name needed" - check_build_msg_begin "${2}" "MBytes" \ - "disk space at ${1}" - actual_space=$(df -Pm ${1} 2>/dev/null | sed -n \ - '$s/\(\S\+\s\+\)\{3\}\([0-9]\+\).*/\2/p' 2>/dev/null ) - if [[ "$?" == "0" && -n "${actual_space}" ]] ; then - if [[ ${actual_space} -lt ${2} ]] ; then +# @FUNCTION: check-reqs_disk +# @DESCRIPTION: +# Internal function that checks space on the harddrive. +check-reqs_disk() { + debug-print-function ${FUNCNAME} "$@" + + [[ -z ${2} ]] && die "Usage: ${FUNCNAME} [path] [size]" + + local path=${1} + local size=${2} + local space_megs + + check-reqs_start_phase \ + $(check-reqs_get_numbers ${size}) \ + $(check-reqs_get_unit ${size}) \ + "disk space at \"${path}\"" + + space_megs=$(df -Pm ${1} 2>/dev/null | sed -n \ + '$s/\(\S\+\s\+\)\{3\}\([0-9]\+\).*/\2/p' 2>/dev/null) + + if [[ $? == 0 && -n ${space_megs} ]] ; then + if [[ ${space_megs} -lt $(check-reqs_get_megs ${size}) ]] ; then eend 1 - check_build_msg_ick "${2}" "MBytes" \ - "disk space at ${1}" + check-reqs_unsattisfied \ + $(check-reqs_get_numbers ${size}) \ + $(check-reqs_get_unit ${size}) \ + "disk space at \"${path}\"" else eend 0 fi else eend 1 - ewarn "Couldn't figure out disk space, skipping ..." + ewarn "Couldn't determine disk space, skipping..." fi } -# internal use only! -check_build_msg_begin() { - ebegin "Checking for at least ${1}${2} ${3}" -} +# @FUNCTION: check-reqs_start_phase +# @DESCRIPTION: +# Internal function that inform about started check +check-reqs_start_phase() { + debug-print-function ${FUNCNAME} "$@" -# internal use only! -check_build_msg_skip() { - ewarn "Skipping check for at least ${1}${2} ${3}" + [[ -z ${3} ]] && die "Usage: ${FUNCNAME} [size] [unit] [location]" + + ebegin "Checking for at least ${1}${2} ${3}" } -# internal use only! -check_build_msg_ick() { - if [[ "${CHECKREQS_ACTION}" == "error" ]] ; then - eerror "Don't have at least ${1}${2} ${3}" - echo - export CHECKREQS_NEED_DIE="yes" - else - ewarn "Don't have at least ${1}${2} ${3}" - echo - export CHECKREQS_NEED_SLEEP="yes" - fi +# @FUNCTION: check-reqs_unsattisfied +# @DESCRIPTION: +# Internal function that inform about check result. +# It has different output between pretend and setup phase, +# where in pretend phase it is fatal. +check-reqs_unsattisfied() { + debug-print-function ${FUNCNAME} "$@" + + [[ -z ${3} ]] && die "Usage: ${FUNCNAME} [size] [unit] [location]" + + local msg="ewarn" + + [[ ${EBUILD_PHASE} == "pretend" && -z ${I_KNOW_WHAT_I_AM_DOING} ]] && msg="eerror" + ${msg} "Don't have at least ${1}${2} ${3}" + + # @ECLASS-VARIABLE: CHECKREQS_FAILED + # @DESCRIPTION: + # @DEAULT_UNSET + # If set the checks failed and eclass should abort the build. + # Internal, do not set yourself. + CHECKREQS_FAILED="true" }