Add the updated check-reqs eclass as per gentoo-dev discussion.
authorTomas Chvatal <scarabeus@gentoo.org>
Mon, 5 Sep 2011 08:22:31 +0000 (08:22 +0000)
committerTomas Chvatal <scarabeus@gentoo.org>
Mon, 5 Sep 2011 08:22:31 +0000 (08:22 +0000)
eclass/check-reqs.eclass

index a63a687045d0ce2dce493757b84e00f6e0404ce7..b3d920e4993bc176c02d4680a88431e71a592345 100644 (file)
@@ -1,11 +1,12 @@
 # Copyright 1999-2011 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
-# $Header: /var/cvsroot/gentoo-x86/eclass/check-reqs.eclass,v 1.8 2011/08/22 04:46:31 vapier Exp $
+# $Header: /var/cvsroot/gentoo-x86/eclass/check-reqs.eclass,v 1.9 2011/09/05 08:22:31 scarabeus Exp $
 
 # @ECLASS: check-reqs.eclass
 # @MAINTAINER:
-# Bo Ørsted Andresen <zlin@gentoo.org>
+# QA Team <qa@gentoo.org>
 # @AUTHOR:
+# Bo Ørsted Andresen <zlin@gentoo.org>
 # Original Author: Ciaran McCreesh <ciaranm@gentoo.org>
 # @BLURB: Provides a uniform way of handling ebuild which have very high build requirements
 # @DESCRIPTION:
 # 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
-#
-#     # need this much memory (does *not* check swap)
-#     CHECKREQS_MEMORY="256"
+# # need this much memory (does *not* check swap)
+# CHECKREQS_MEMORY="256M"
 #
-#     # need this much temporary build space
-#     CHECKREQS_DISK_BUILD="2048"
+# # need this much temporary build space
+# CHECKREQS_DISK_BUILD="2G"
 #
-#     # install will need this much space in /usr
-#     CHECKREQS_DISK_USR="1024"
+# # install will need this much space in /usr
+# CHECKREQS_DISK_USR="1G"
 #
-#     # install will need this much space in /var
-#     CHECKREQS_DISK_VAR="1024"
+# # install will need this much space in /var
+# CHECKREQS_DISK_VAR="1024M"
 #
-#     # go!
-#     check_reqs
-# }
 # @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.
 #
 inherit eutils
 
 # @ECLASS-VARIABLE: CHECKREQS_MEMORY
+# @DEFAULT_UNSET
 # @DESCRIPTION:
-# How much RAM is needed in MB?
+# How much RAM is needed? Eg.: CHECKREQS_MEMORY=15M
 
 # @ECLASS-VARIABLE:  CHECKREQS_DISK_BUILD
+# @DEFAULT_UNSET
 # @DESCRIPTION:
-# How much diskspace is needed to build the package? In MB
+# How much diskspace is needed to build the package? Eg.: CHECKREQS_DISK_BUILD=2T
 
 # @ECLASS-VARIABLE: CHECKREQS_DISK_USR
+# @DEFAULT_UNSET
 # @DESCRIPTION:
-# How much space in /usr is needed to install the package? In MB
+# How much space in /usr is needed to install the package? Eg.: CHECKREQS_DISK_USR=15G
 
 # @ECLASS-VARIABLE: CHECKREQS_DISK_VAR
+# @DEFAULT_UNSET
 # @DESCRIPTION:
-# How much space is needed in /var? In MB
+# How much space is needed in /var? Eg.: CHECKREQS_DISK_VAR=3000M
+
+EXPORT_FUNCTIONS pkg_setup
+case "${EAPI:-0}" in
+       0|1|2|3) ;;
+       4) EXPORT_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"
-
-       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}"
-       fi
+       debug-print-function ${FUNCNAME} "$@"
 
-       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
-       fi
+       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 "$@"
+}
+
+# @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 "$@"
+}
 
-       if [[ -n "${CHECKREQS_NEED_DIE}" ]] ; then
-               eerror "Bailing out as specified by CHECKREQS_ACTION"
-               die "Build requirements not met"
+# @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 file a bug against the package."
+               die "${FUNCNAME}: check-reqs eclass called but not actualy used!"
        fi
 }
 
-# @FUNCTION: check_reqs_conditional
-# @RETURN: True if requirements check passed, else False
-# @DESCRIPTION:
-# Checks the requirements given in the specific variables
-check_reqs_conditional() {
-       [[ -n "${1}" ]] && die "Usage: check_reqs"
-
-       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_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_mebibytes
+# @DESCRIPTION:
+# Internal function that returns number in mebibytes.
+# Converts from 1G=1024 or 1T=1048576
+check-reqs_get_mebibytes() {
+       debug-print-function ${FUNCNAME} "$@"
+
+       [[ -z ${1} ]] && die "Usage: ${FUNCNAME} [size]"
+
+       local unit=${1:(-1)}
+       local size=${1%[GMT]}
+
+       case ${unit} in
+               G) echo $((1024 * size)) ;;
+               [M0-9]) echo ${size} ;;
+               T) echo $((1024 * 1024 * size)) ;;
+               *)
+                       die "${FUNCNAME}: Unknown unit: ${unit}"
+               ;;
+       esac
+}
+
+# @FUNCTION: check-reqs_get_number
+# @DESCRIPTION:
+# Internal function that returns number without the unit.
+# Converts from 1G=1 or 150T=150.
+check-reqs_get_number() {
+       debug-print-function ${FUNCNAME} "$@"
+
+       [[ -z ${1} ]] && die "Usage: ${FUNCNAME} [size]"
+
+       local unit=${1:(-1)}
+       local size=${1%[GMT]}
+
+       # Check for unset units and warn about them.
+       # Backcompat.
+       if [[ ${size} == ${1} ]]; then
+               ewarn "QA: Package does not specify unit for the size check"
+               ewarn "QA: Assuming mebibytes."
+               ewarn "QA: File bug against the package. It should specify the unit."
        fi
 
-       [[ -z "${CHECKREQS_NEED_SLEEP}" && -z "${CHECKREQS_NEED_DIE}" ]]
+       echo ${size}
+}
+
+# @FUNCTION: check-reqs_get_unit
+# @DESCRIPTION:
+# Internal function that returns number without the unit.
+# Converts from 1G=1 or 150T=150.
+check-reqs_get_unit() {
+       debug-print-function ${FUNCNAME} "$@"
+
+       [[ -z ${1} ]] && die "Usage: ${FUNCNAME} [size]"
+
+       local unit=${1:(-1)}
+
+       case ${unit} in
+               G) echo "gibibytes" ;;
+               [M0-9]) echo "mebibytes" ;;
+               T) echo "tebibytes" ;;
+               *)
+                       die "${FUNCNAME}: Unknown unit: ${unit}"
+               ;;
+       esac
 }
 
-# internal use only!
-check_build_memory() {
-       [[ -n "${1}" ]] && die "Usage: check_build_memory"
-       check_build_msg_begin "${CHECKREQS_MEMORY}" "MBytes" "RAM"
+# @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
+}
+
+# @FUNCTION: check-reqs_memory
+# @DESCRIPTION:
+# Internal function that checks size of RAM.
+check-reqs_memory() {
+       debug-print-function ${FUNCNAME} "$@"
+
+       [[ -z ${1} ]] && die "Usage: ${FUNCNAME} [size]"
+
+       local size=${1}
+       local actual_memory
+
+       check-reqs_start_phase \
+               ${size} \
+               "RAM"
+
        if [[ -r /proc/meminfo ]] ; then
-               actual_memory=$(sed -n -e '/MemTotal:/s/^[^:]*: *\([0-9]\+\) kB/\1/p' \
-                       /proc/meminfo)
+               actual_memory=$(awk '/MemTotal/ { print $2 }' /proc/meminfo)
        else
                actual_memory=$(sysctl hw.physmem 2>/dev/null )
                [[ "$?" == "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_mebibytes ${size}))) ]] ; then
                        eend 1
-                       check_build_msg_ick "${CHECKREQS_MEMORY}" "MBytes" "RAM"
+                       check-reqs_unsatisfied \
+                               ${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 \
+               ${size} \
+               "disk space at \"${path}\""
+
+       space_megs=$(df -Pm "${1}" 2>/dev/null | awk 'FNR == 2 {print $4}')
+
+       if [[ $? == 0 && -n ${space_megs} ]] ; then
+               if [[ ${space_megs} -lt $(check-reqs_get_mebibytes ${size}) ]] ; then
                        eend 1
-                       check_build_msg_ick "${2}" "MBytes" \
-                                       "disk space at ${1}"
+                       check-reqs_unsatisfied \
+                               ${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 ${2} ]] && die "Usage: ${FUNCNAME} [size] [location]"
+
+       local size=${1}
+       local location=${2}
+       local sizeunit="$(check-reqs_get_number ${size}) $(check-reqs_get_unit ${size})"
+
+       ebegin "Checking for at least ${sizeunit} ${location}"
 }
 
-# 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_unsatisfied
+# @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_unsatisfied() {
+       debug-print-function ${FUNCNAME} "$@"
+
+       [[ -z ${2} ]] && die "Usage: ${FUNCNAME} [size] [location]"
+
+       local msg="ewarn"
+       local size=${1}
+       local location=${2}
+       local sizeunit="$(check-reqs_get_number ${size}) $(check-reqs_get_unit ${size})"
+
+       [[ ${EBUILD_PHASE} == "pretend" && -z ${I_KNOW_WHAT_I_AM_DOING} ]] && msg="eerror"
+       ${msg} "Don't have at least ${sizeunit} ${location}"
+
+       # @ECLASS-VARIABLE: CHECKREQS_FAILED
+       # @DESCRIPTION:
+       # @INTERNAL
+       # If set the checks failed and eclass should abort the build.
+       # Internal, do not set yourself.
+       CHECKREQS_FAILED="true"
 }