#!/bin/bash # Copyright 2010-2012, Asio Software Technologies # Distributed under the terms of the GNU General Public License v3 #------------------------------------------------------------------------------- # Checks if system running EzBuild meets its requirements #------------------------------------------------------------------------------- function checkPrerequisites() { if [ "$(uname -s)" != "Linux" ]; then printError "You are trying to launch ${EZNAME} on non-Linux system!" return 1 fi if [ "${EUID}" != "0" ] && [ "${USER}" != "root" ]; then printError "The ${EZNAME} needs to be launched from root account!" return 1 fi if [ ! -e /dev/null ]; then printError "The /dev directory seems to be not mounted!" return 1 fi if [ ! -e /proc/mounts ]; then printError "The /proc directory seems to be not mounted!" return 1 fi ping -c 1 google.com &> /dev/null if [ ${?} -ne 0 ]; then printError "There seems to be no Internet conectivity!" return 1 fi return 0 } #------------------------------------------------------------------------------- # Tests for a minimum version level by comparing version numbers # Parameters: %min_version% %test_version% #------------------------------------------------------------------------------- function checkVersion() { local BEST REF TST REF=$(echo "${1}" | \ sed -u -e "s/-r/_z/g" -e "s/_p/_z/g" -e "s/_zre/_pre/" -e "s/$/_z0/") TST=$(echo "${2}" | \ sed -u -e "s/-r/_z/g" -e "s/_p/_z/g" -e "s/_zre/_pre/" -e "s/$/_z0/") BEST=$(echo -e "${REF}\n${TST}" | sed "/^$/d" | sort -Vr | head -1) [[ "${BEST}" = "${TST}" ]] && return 0 return 1 } #------------------------------------------------------------------------------- # Outputs formatted error message and aborts script execution with given status # Parameters: %message% [%status%] #------------------------------------------------------------------------------- function die() { local STATUS=${2:-1} notify ${STATUS} "${1}" printError "${1}" echo -ne "\n" exit ${STATUS} } #------------------------------------------------------------------------------- # Failure handler; outputs warning or error depending on user settings # Parameters: %message% [%status%] #------------------------------------------------------------------------------- function fail() { local STATUS=${2:-1} if isEnabled ${FATALERRORS}; then die "${1}" ${STATUS} else pushNotification ${STATUS} "${1}" printWarn "${1}" fi } #------------------------------------------------------------------------------- # Checks if the given function has been defined # Parameters: %function% #------------------------------------------------------------------------------- function functionExists() { type ${1} 2>/dev/null | grep -q "is a function" return ${?} } #------------------------------------------------------------------------------- # Checks whether a defined variable contain specified element or not # Parameters: %element% %variable% #------------------------------------------------------------------------------- function hasElement() { local NEEDLE=${1} shift local X for X in "${@}"; do [ "${X}" = "${NEEDLE}" ] && return 0 done return 1 } #------------------------------------------------------------------------------- # Checks whether a supplied variable is defined or not # Parameters: %variable% #------------------------------------------------------------------------------- function isDefined() { [[ ${!1-X} == ${!1-Y} ]] } #------------------------------------------------------------------------------- # Checks whether a supplied variable is enabled or not # Parameters: %variable% #------------------------------------------------------------------------------- function isEnabled() { case "${1}" in [Ee][Nn][Aa][Bb][Ll][Ee][Dd]) return 0 ;; [Tt][Rr][Uu][Ee]) return 0 ;; [Yy][Ee][Ss]) return 0 ;; 1) return 0 ;; esac return 1 } #------------------------------------------------------------------------------- # Checks whether a variable is defined and if value's length > 0 # Parameters: %variable% #------------------------------------------------------------------------------- function isSet() { if isDefined ${1}; then if [[ -n ${!1} ]]; then return 0 fi fi return 1 } #------------------------------------------------------------------------------- # Prints a list of available built-in modules #------------------------------------------------------------------------------- function listModules() { local MODULE echo -e "Modules can be used to enhance EzBuild functionality by handling" echo -e "triggered events. They can be easily enabled and/or disabled in" echo -e "configuration files. Every event has its own list of modules." echo -e "List of built-in modules available for ${EZNAME}:\n" for MODULE in ${EZROOT}/modules/*.ezmod; do source ${MODULE} &> /dev/null if [ ${?} -ne 0 ] || ! hasElement ${EZNAME} ${EZMOD_COMPATIBILITY}; then unloadModule continue fi MODULE=$(basename "${MODULE}" .ezmod) EZMOD_AUTHOR=${EZMOD_AUTHOR:-Unknown} EZMOD_DESCRIPTION=${EZMOD_DESCRIPTION:-No description provided} EZMOD_VERSION=${EZMOD_VERSION:-N/A} echo -e "${COLOR_CYAN}${COLOR_BOLD} ${MODULE}${COLOR_NORMAL}" echo -e "\t${COLOR_RED}Description:\t${COLOR_CYAN}${EZMOD_DESCRIPTION}" echo -e "\t${COLOR_RED}Version:\t${COLOR_CYAN}${EZMOD_VERSION}" echo -e "\t${COLOR_RED}Author:\t\t${COLOR_CYAN}${EZMOD_AUTHOR}\n" unloadModule done echo -e "${COLOR_WHITE}" exit 0 } #------------------------------------------------------------------------------- # Loads EzBuild configuration #------------------------------------------------------------------------------- function loadConfiguration() { source ${EZROOT}/config/common.conf &> /dev/null || panic source ${EZROOT}/config/${EZNAME}.conf &> /dev/null || panic source ${EZROOT}/config/layout.conf &> /dev/null || panic source /etc/ezbuild/common.conf &> /dev/null || panic source /etc/ezbuild/${EZNAME}.conf &> /dev/null || panic source /etc/ezbuild/layout.conf &> /dev/null || panic } #------------------------------------------------------------------------------- # Loads all EzBuild Libraries #------------------------------------------------------------------------------- function loadLibraries() { source ${EZROOT}/libraries/constants &> /dev/null || panic source ${EZROOT}/libraries/filesystem &> /dev/null || panic source ${EZROOT}/libraries/repositories &> /dev/null || panic } #------------------------------------------------------------------------------- # Loads and executes given EzBuild module # Parameters: %module% %step% #------------------------------------------------------------------------------- function loadModule() { local MODULE="${1}" local FUNCTION="${EZNAME}_${2}" if [ -e ${MODULESCUSTOMDIR}/${MODULE}.ezmod ]; then source ${MODULESCUSTOMDIR}/${MODULE}.ezmod &> /dev/null else source ${EZROOT}/modules/${MODULE}.ezmod &> /dev/null fi if [ ${?} -eq 0 ] && hasElement ${EZNAME} ${EZMOD_COMPATIBILITY}; then if [ -e ${MODULESCUSTOMDIR}/${MODULE}.conf ]; then source ${EZROOT}/config/modules/${MODULE}.conf &> /dev/null source ${MODULESCUSTOMDIR}/${MODULE}.conf &> /dev/null elif [ -e /etc/ezbuild/modules/${MODULE}.conf ]; then source ${EZROOT}/config/modules/${MODULE}.conf &> /dev/null source /etc/ezbuild/modules/${MODULE}.conf &> /dev/null fi if [ ${?} -eq 0 ]; then if functionExists ${FUNCTION}; then eval ${FUNCTION} return ${?} else return 255 fi fi fi return 1 } #------------------------------------------------------------------------------- # Saves specified message into a log file # Parameters: %message% [%level%] #------------------------------------------------------------------------------- function logMessage() { local DATE MESSAGE TYPE if isEnabled ${LOGGING}; then MESSAGE="${1}" TYPE="${2}" DATE=$(date +"${LOGDATEFORMAT}") if [ -z ${TYPE} ]; then TYPE=" - " fi { echo -e "[${DATE}][${TYPE}] ${MESSAGE}" >> ${LOGFILE}; } 2> /dev/null fi } #------------------------------------------------------------------------------- # Saves executed command multiline output into a log file # Parameters: %command_output% #------------------------------------------------------------------------------- function logOutput() { if isEnabled ${LOGGING}; then if [ -z "${@}" ]; then echo -e " )> (NO OUTPUT)" >> ${LOGFILE} else echo -e "${@}" | awk '{ print " )> ", $0; }' >> ${LOGFILE} fi fi } #------------------------------------------------------------------------------- # Sends an e-mail notification about occured error # Parameters: %status% %message% #------------------------------------------------------------------------------- function notify() { if isEnabled ${LOGGING} && isSet NOTIFY && isEnabled ${EZNOTIFY}; then local MESG="" local SEND=0 if [ ${1} -ne 0 ]; then MESG="The ${EZNAME} has failed with code: ${1} and message: ${2}" SEND=1 if [ ${#NOTIFICATIONS[@]} -ne 0 ]; then MESG="${MESG}\nThere were also some non-fatal errors that has \ been treated as warnings:" fi elif [ ${#NOTIFICATIONS[@]} -ne 0 ]; then MESG="The ${EZNAME} process has ended its job without any fatal \ error, but there still were some non-fatal errors that has \ been treated as warnings:" SEND=1 fi MESG=$(echo -e "${MESG}" | awk -v OFS=" " '$1=$1') if [ ${SEND} -eq 1 ]; then if [ ${#NOTIFICATIONS[@]} -ne 0 ]; then for NOTIFICATION in "${NOTIFICATIONS[@]}"; do MESG="${MESG}\n * ${NOTIFICATION}" done fi local LOGS="Full output from log file:\n\n$(cat ${LOGFILE})" local TOPIC="The ${EZNAME} process has produced an error!" echo -e "${MESG}\n\n\n${LOGS}" | mailx -s "${TOPIC}" "${NOTIFY}" fi fi } #------------------------------------------------------------------------------- # Outputs error message and aborts program execution #------------------------------------------------------------------------------- function panic() { echo -e "FATAL ERROR: Unable to load necessary files!" echo -e "Your EzBuild installation seems to be broken..." exit 1 } #------------------------------------------------------------------------------- # Outputs formatted error message to both display and log file # Parameters: %message% #------------------------------------------------------------------------------- function printError() { logMessage "${1}" "ERROR" echo -e " ${MESSAGE_ERROR} ${@}" } #------------------------------------------------------------------------------- # Outputs formatted information to both display and log file # Parameters: %message% #------------------------------------------------------------------------------- function printInfo() { logMessage "${1}" "INFO" echo -e " ${MESSAGE_INFO} ${@}" } #------------------------------------------------------------------------------- # Outputs formatted information about EzBuild version and copyrights #------------------------------------------------------------------------------- function printNotice() { echo -e "\n${COLOR_BOLD}EzBuild v${EZVERSION} (${EZNAME} launched)" echo -e "${EZCOPYRIGHT}${COLOR_NORMAL}" echo -e "${BORDER_STAR}\n" } #------------------------------------------------------------------------------- # Outputs formatted warning to both display and log file # Parameters: %message% #------------------------------------------------------------------------------- function printWarn() { logMessage "${1}" "WARN" echo -e " ${MESSAGE_WARN} ${@}" } #------------------------------------------------------------------------------- # Adds new non-fatal error notification message to the queue # Parameters: %status% %message% #------------------------------------------------------------------------------- function pushNotification() { local NUM=${#NOTIFICATIONS[@]} NOTIFICATIONS[${NUM}]="Code: ${1} Message: ${2}" } #------------------------------------------------------------------------------- # Optionally sends all notifications from queue and aborts program execution #------------------------------------------------------------------------------- function quit() { notify 0 echo -e "${COLOR_BOLD}ALL DONE!\n${COLOR_NORMAL}" exit 0 } #------------------------------------------------------------------------------- # Restores original Internal Field Separator (IFS) #------------------------------------------------------------------------------- function restoreIFS() { if [ "${ORGIFS:-unset}" != "unset" ]; then IFS="${ORGIFS}" unset ORGIFS else unset IFS fi } #------------------------------------------------------------------------------- # Silently executes given command and saves its output to log file if enabled # Parameters: %command% #------------------------------------------------------------------------------- function run() { local COMMAND OUTPUT RESULT COMMAND="${@}" logMessage "Executing: \"${COMMAND}\"" "DEBUG" OUTPUT=$(eval ${COMMAND} 2>&1) RESULT=${?} logOutput "${OUTPUT}" return ${RESULT} } #------------------------------------------------------------------------------- # Saves original Internal Field Separator (IFS) and optionally sets new value # Parameters: %new_ifs% #------------------------------------------------------------------------------- function saveIFS() { local NEWIFS if [ "${IFS:-unset}" != "unset" ]; then ORGIFS="${IFS}" fi NEWIFS="${1}" if isSet NEWIFS; then IFS="${NEWIFS}" fi } #------------------------------------------------------------------------------- # Prints EzSync usage information #------------------------------------------------------------------------------- function showEzsyncUsage() { echo -e "\tEzSync is a part of EzBuild release building metatool used by" echo -e "\treGen2 Linux for synchronizing Portage Tree with mainline.\n" echo -e "USAGE: ezsync [parameters]" echo -e " -c\t--cleanlog\tclears log file; not working with -p and -P" echo -e " -h\t--help\t\tdisplays this screen and exits immediately" echo -e " -l\t--listmods\tshows the list of available built-in modules" echo -e " -n\t--nosync\tspecifies the ebuilds source that will be omitted" echo -e " -N\t--nopush\tavoids automatic commits into repositories" echo -e " -p\t--purge\t\tclears temporary folder" echo -e " -P\t--purgeonly\tclears temporary folder and exits" echo -e " -s\t--syscheck\tperforms prerequisites check only" echo -e "\nEXAMPLES:" echo -e " ezsync -c -n mainline" echo -e " ezsync -n mainline -n my_repo1" echo -e "\n" exit 0 } #------------------------------------------------------------------------------- # Returns a UNIX timestamp #------------------------------------------------------------------------------- function timestamp() { echo $(date +%s) } #------------------------------------------------------------------------------- # Returns lowercase string # Parameters: %string% #------------------------------------------------------------------------------- function toLower() { echo "${@}" | tr '[:upper:]' '[:lower:]' } #------------------------------------------------------------------------------- # Returns uppercase string # Parameters: %string% #------------------------------------------------------------------------------- function toUpper() { echo "${@}" | tr '[:lower:]' '[:upper:]' } #------------------------------------------------------------------------------- # Returns only the first part of a string, delimited by tabs or spaces # Parameters: %string% #------------------------------------------------------------------------------- function trim() { echo ${1} } #------------------------------------------------------------------------------- # Silently unloads any previously loaded module #------------------------------------------------------------------------------- function unloadModule() { unset EZMOD_AUTHOR unset EZMOD_COMPATIBILITY unset EZMOD_DESCRIPTION unset EZMOD_VERSION unset ezsync_precommit unset ezsync_presync unset ezsync_postcommit unset ezsync_postsync }