initial archbuilder version

This commit is contained in:
Matthias Fulz 2021-06-29 20:01:25 +02:00
commit 06344291fa
7 changed files with 662 additions and 0 deletions

28
Makefile Normal file
View File

@ -0,0 +1,28 @@
PROGNM ?= archbuilder
PREFIX ?= /usr
SHRDIR ?= $(PREFIX)/share
BINDIR ?= $(PREFIX)/bin
LIBDIR ?= $(PREFIX)/lib
CNFDIR ?= $(PREFIX)/etc
ARCHBUILDER_LIB_DIR ?= $(LIBDIR)/$(PROGNM)
ARCHBUILDER_CONF_DIR ?= $(CNFDIR)/$(PROGNM)
ARCHBUILDER_VERSION ?= 0.9.0
.PHONY: install build archbuilder
build: archbuilder
archbuilder: archbuilder.in
sed -e 's|ARCHBUILDER_LIB_DIR|$(ARCHBUILDER_LIB_DIR)|' \
-e 's|ARCHBUILDER_CONF_DIR|$(ARCHBUILDER_CONF_DIR)|' \
-e 's|ARCHBUILDER_VERSION|$(ARCHBUILDER_VERSION)|' $< >$@
install-archbuilder: archbuilder
@install -Dm755 archbuilder -t '$(DESTDIR)$(BINDIR)'
install: install-archbuilder
@install -Dm644 lib/archbuilder.inc.sh -t '$(DESTDIR)$(LIBDIR)/$(PROGNM)'
@install -Dm644 lib/buildah.inc.sh -t '$(DESTDIR)$(LIBDIR)/$(PROGNM)'
@install -Dm644 lib/ext/slog.sh -t '$(DESTDIR)$(LIBDIR)/$(PROGNM)/ext'
@install -Dm644 lib/ext/bash_log_internals.inc.sh -t '$(DESTDIR)$(LIBDIR)/$(PROGNM)/ext'
@install -Dm644 archbuilder.env -t '$(DESTDIR)$(CNFDIR)/$(PROGNM)'

11
archbuilder.env Normal file
View File

@ -0,0 +1,11 @@
#!/bin/bash
ARCHBUILDER_BASE_DIR="${HOME}/.archbuilder"
ARCHBUILDER_IMAGE_NAME="archbuilder"
ARCHBUILDER_CACHE_REPO="${ARCHBUILDER_BASE_DIR}/crepo"
ARCHBUILDER_LOG_PATH="${ARCHBUILDER_BASE_DIR}/logs"
ARCHBUILDER_LOG_TO_FILE=1
LOG_LEVEL_STDOUT="INFO"
LOG_LEVEL_LOG="INFO"

145
archbuilder.in Normal file
View File

@ -0,0 +1,145 @@
#!/bin/bash
readonly archbuilder_version='ARCHBUILDER_VERSION'
readonly lib_dir='ARCHBUILDER_LIB_DIR'
readonly conf_dir='ARCHBUILDER_CONF_DIR'
. "${lib_dir}/ext/slog.sh"
. "${lib_dir}/ext/bash_log_internals.inc.sh"
. "${conf_dir}/archbuilder.env"
. "${lib_dir}/archbuilder.inc.sh"
. "${lib_dir}/buildah.inc.sh"
# internal params
unset _FLAG_KEEP
unset _FLAG_SILENT
_OPT_MODE="build"
_OPT_DEPS=()
_OPT_KEYS=()
_OPT_CON_BUILD_USER="archbuilder"
_OPT_CON_COPTIONS=""
# actions to initialize runtime
unset _ACT_CREATE_IMAGE
unset _ACT_CREATE_BASE_DIR
unset _ACT_CREATE_CACHE_REPO_PATH
unset _ACT_CREATE_LOG_PATH
function usage() {
echo "archbuilder is a makepkg wrapper that uses buildah for the build process."
echo "That will lead to a very clean build, where the PKGBUILD and the dependencies,"
echo "have to be 100% correct and nothing will pollute the host system."
echo
echo "Usage:"
echo " archbuilder [options] -- <coptions>"
echo
echo "Options:"
echo -e " -h, --help\t\t\t\t\tPrint this help"
echo -e " -k, --keep\t\t\t\t\tKeep the working container that is used for the build"
echo -e " -n, --name <string>\t\t\t\tImage name that is used to spin up the container (default: ${INAME})"
echo -e " -m, --mode <create | update | build>\t\tRun mode: (default: ${MODE})"
echo -e " \t\tcreate will setup the base image"
echo -e " \t\tupdate will update the base image"
echo -e " \t\tbuild will build the PKGBUILD"
echo -e " -d, --dep <string>\t\t\t\tPath to pacman package file that is needed as dependency for the build. (Can be added multiple times)"
echo -e " -e, --key <string>\t\t\t\tPublic signing keys that should be trusted by for the build. (Can be added multiple times)"
echo -e " -r, --repo <string>\t\t\t\tHost path to use as repository inside the container. This can be used to avoid"
echo -e " \t\t\t\thanding over dependencies via command line arguments as they will be added to this repo"
echo -e " -s, --silent <string>\t\t\t\tMake container silent: No output from container commands will be send to shell."
echo -e " --version <string>\t\t\t\tPrint version information."
echo
echo "coptions:"
echo -e " These options will be handed over directly to makepkg inside the buildah container to build the package."
echo -e " coptions has to be added ater the double dash -- to work."
}
options=$(getopt \
-o hkn:m:p:d:r:e:s \
-l "help" \
-l keep \
-l name: \
-l mode: \
-l dep: \
-l repo: \
-l silent: \
-l version \
-l key: -- "$@" 2>/dev/null)
eval set -- "${options}"
while true; do
case "${1}" in
-k|--keep)
_FLAG_KEEP=1
;;
-n|--name)
shift
ARCHBUILDER_IMAGE_NAME=${1}
;;
-m|--mode)
shift
_OPT_MODE="${1}"
;;
-d|--dep)
shift
_OPT_DEPS[${#_OPT_DEPS[*]}]="${1}"
;;
-e|--key)
shift
_OPT_KEYS[${#_OPT_KEYS[*]}]="${1}"
;;
-r|--repo)
shift
ARCHBUILDER_CACHE_REPO="${1}"
;;
-s|--silent)
_FLAG_SILENT=1
;;
--version)
echo -e "archbuilder v${archbuilder_version}"
exit 0
;;
--)
shift
break
;;
-h|--help|*)
usage
exit 0
;;
esac
shift
done
_OPT_CON_COPTIONS=$@
set_env
init_env
buildah_prepare_params
function exit_trap() {
buildah_exit
}
trap exit_trap EXIT
buildah_create
case "${_OPT_MODE}" in
"create")
buildah_create
;;
"update")
buildah_update
;;
"build")
buildah_build
;;
esac
exit 0

106
lib/archbuilder.inc.sh Normal file
View File

@ -0,0 +1,106 @@
#!/bin/bash
function exit_error() {
log_error "${1}"
exit ${2}
}
function check_mode() {
log_debug "set_mode for val '${1}' called"
if [ -z "${1}" ]
then
err="Mode not given"
return 1
fi
case "$1" in
"update")
log_debug "Mode 'update' selected"
return 0
;;
"create")
log_debug "Mode 'create' selected"
return 0
;;
"build")
log_debug "Mode 'build' selected"
return 0
;;
*)
err="Mode '${1}' invalid"
return 1
;;
esac
}
function check_flag() {
if [ -z "${2}" ]
then
log_debug "Flag '${1}' unset"
else
log_debug "Flag '${1}' set"
fi
}
function set_env() {
log_info "Checking environment and params"
log_debug "Verifying mode '${_OPT_MODE}'"
check_mode "${_OPT_MODE}" \
|| exit_error "${err}" 1
check_flag "KEEP" "${_FLAG_KEEP}"
check_flag "SILENT" "${_FLAG_SILENT}"
test_exists "${ARCHBUILDER_BASE_DIR}" || _ACT_CREATE_BASE_DIR=1
check_flag "_ACT_CREATE_BASE_DIR" "${_ACT_CREATE_BASE_DIR}"
test_exists "${ARCHBUILDER_CACHE_REPO}" || _ACT_CREATE_CACHE_REPO_PATH=1
check_flag "_ACT_CREATE_CACHE_REPO_PATH" "${_ACT_CREATE_CACHE_REPO_PATH}"
test_exists "${ARCHBUILDER_LOG_PATH}" || _ACT_CREATE_LOG_PATH=1
check_flag "_ACT_CREATE_LOG_PATH" "${_ACT_CREATE_LOG_PATH}"
buildah_exists "${ARCHBUILDER_IMAGE_NAME}" || _ACT_CREATE_IMAGE=1
check_flag "_ACT_CREATE_IMAGE" "${_ACT_CREATE_IMAGE}"
test_null "ARCHBUILDER_IMAGE_NAME" "${ARCHBUILDER_IMAGE_NAME}" \
&& exit_error "Image name cannot be empty" 1
return 0
}
function init_env() {
log_info "Initializing environment"
test_null "_ACT_CREATE_BASE_DIR" "${_ACT_CREATE_BASE_DIR}" \
|| log_info "Creating directory '${ARCHBUILDER_BASE_DIR}'"; {
err="$(mkdir -p "${ARCHBUILDER_BASE_DIR}" 1>/dev/null)" \
|| exit_error "Failed to create directory '${ARCHBUILDER_BASE_DIR}': '${err}'" 1
}
test_dir "${ARCHBUILDER_BASE_DIR}" \
|| exit_error "Not a directory '${ARCHBUILDER_BASE_DIR}'" 1
test_null "_ACT_CREATE_CACHE_REPO_PATH" "${_ACT_CREATE_CACHE_REPO_PATH}" \
|| log_info "Creating directory '${ARCHBUILDER_CACHE_REPO}'"; {
err="$(mkdir -p "${ARCHBUILDER_CACHE_REPO}" 1>/dev/null)" \
|| exit_error "Failed to create directory '${ARCHBUILDER_CACHE_REPO}': '${err}'" 1
}
test_dir "${ARCHBUILDER_CACHE_REPO}" \
|| exit_error "Not a directory '${ARCHBUILDER_CACHE_REPO}'" 1
test_null "_ACT_CREATE_LOG_PATH" "${_ACT_CREATE_LOG_PATH}" \
|| log_info "Creating directory '${ARCHBUILDER_LOG_PATH}'"; {
err="$(mkdir -p "${ARCHBUILDER_LOG_PATH}" 1>/dev/null)" \
|| exit_error "Failed to create directory '${ARCHBUILDER_LOG_PATH}': '${err}'" 1
}
test_dir "${ARCHBUILDER_LOG_PATH}" \
|| exit_error "Not a directory '${ARCHBUILDER_LOG_PATH}'" 1
test_null "ARCHBUILDER_LOG_TO_FILE" "${ARCHBUILDER_LOG_TO_FILE}" \
|| {
LOG_PATH="${ARCHBUILDER_LOG_PATH}/$(date +"%F-%H_%M_%S").log"
log_info "Logfile: '${LOG_PATH}'"
}
log_info "Environment ready"
}

181
lib/buildah.inc.sh Normal file
View File

@ -0,0 +1,181 @@
#!/bin/bash
_BUILDAH_CONT=""
_BUILDAH_BASE_IMAGE="archlinux"
_BUILDAH_BASE_PATH="/home/archbuilder"
_BUILDAH_DEP_PATH="${_BUILDAH_BASE_PATH}/deps"
_BUILDAH_MKPKG_PATH="${_BUILDAH_BASE_PATH}/mkpgs"
_BUILDAH_PKGDEST_PATH="${_BUILDAH_BASE_PATH}/pkgdest"
_BUILDAH_CACHE_REPO_NAME="archbuilder_cache_repo"
_BUILDAH_CACHE_REPO_PATH="${_BUILDAH_BASE_PATH}/crepo"
_BUILDAH_CACHE_REPO="${_BUILDAH_CACHE_REPO_PATH}/${_BUILDAH_CACHE_REPO_NAME}.db.tar.gz"
_BUILDAH_MOUNTS=()
_BUILDAH_PARAMS=""
_BUILDAH_MAKEPKG_ENV=""
_BUILDAH_MAKEPKG_FLAGS=" --noconfirm" # always noconfirm to avoid hanging
function buildah_exists() {
log_debug "Checking if buildah image '${1}' exists"
if buildah inspect "${1}" > /dev/null 2>&1
then
log_debug "Buildah image '${1}' exists"
return 0
fi
log_debug "Buildah image '${1}' does not exist"
return 1
}
function buildah_prepare_params() {
_BUILDAH_PARAMS="${_BUILDAH_PARAMS} -v ${ARCHBUILDER_CACHE_REPO}:${_BUILDAH_CACHE_REPO_PATH}:rw,U"
# adding working directory to container
_BUILDAH_PARAMS="${_BUILDAH_PARAMS} -v $(pwd):${_BUILDAH_MKPKG_PATH}:rw,U"
log_info "Preparing makepkg environment"
test_null "PKGDEST" "${PKGDEST}" || {
_BUILDAH_PARAMS="${_BUILDAH_PARAMS} -v ${PKGDEST}:${_BUILDAH_PKGDEST_PATH}:rw,U"
_BUILDAH_MAKEPKG_ENV="${_BUILDAH_MAKEPKG_ENV} PKGDEST=${_BUILDAH_PKGDEST_PATH}"
}
log_debug "Final _BUILDAH_PARAMS '${_BUILDAH_PARAMS}'"
}
function buildah_exit() {
# fix permissions in any case
log_info "Cleaning up buildah stuff"
test_null "_BUILDAH_CONT" "${_BUILDAH_CONT}" || {
exec_cmd buildah run ${_BUILDAH_PARAMS} "${_BUILDAH_CONT}" bash -c "exit 0"
test_null "_FLAG_KEEP" "${_FLAG_KEEP}" && {
log_info "Deleting working container '${_BUILDAH_CONT}'"
exec_cmd buildah rm "${_BUILDAH_CONT}"
}
unset _BUILDAH_CONT
}
}
function buildah_create() {
# checking if base image is existing
buildah_exists "${_BUILDAH_BASE_IMAGE}" || {
log_info "Trying to fetch base image '${_BUILDAH_BASE_IMAGE}'"
exec_cmd buildah pull "${_BUILDAH_BASE_IMAGE}"
}
test_null "_ACT_CREATE_IMAGE" "${_ACT_CREATE_IMAGE}" \
&& return 0
log_info "Creating working container '${ARCHBUILDER_IMAGE_NAME}' from '${_BUILDAH_BASE_IMAGE}'"
_BUILDAH_CONT=$(buildah from --name "${ARCHBUILDER_IMAGE_NAME}" "${_BUILDAH_BASE_IMAGE}")
log_info "Updating working container '${ARCHBUILDER_IMAGE_NAME}'"
exec_cmd buildah run "${_BUILDAH_CONT}" pacman --noconfirm -Syu
log_info "Installing devel packages"
exec_cmd buildah run "${_BUILDAH_CONT}" pacman --noconfirm -S base-devel sudo vim git
log_info "Creating user '${_OPT_CON_BUILD_USER}'"
exec_cmd buildah run "${_BUILDAH_CONT}" useradd -m -s /bin/bash -U -u 1000 "${_OPT_CON_BUILD_USER}"
log_info "Setting up sudo for user '${_OPT_CON_BUILD_USER}'"
exec_cmd buildah run "${_BUILDAH_CONT}" bash -c "echo '${_OPT_CON_BUILD_USER} ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/${_OPT_CON_BUILD_USER}"
log_info "Creating container folder '${_BUILDAH_DEP_PATH}'"
exec_cmd buildah run --user "${_OPT_CON_BUILD_USER}" "${_BUILDAH_CONT}" mkdir "${_BUILDAH_DEP_PATH}"
log_info "Creating container folder '${_BUILDAH_MKPKG_PATH}'"
exec_cmd buildah run --user "${_OPT_CON_BUILD_USER}" "${_BUILDAH_CONT}" mkdir "${_BUILDAH_MKPKG_PATH}"
log_info "Creating container folder '${_BUILDAH_PKGDEST_PATH}'"
exec_cmd buildah run --user "${_OPT_CON_BUILD_USER}" "${_BUILDAH_CONT}" mkdir "${_BUILDAH_PKGDEST_PATH}"
log_info "Creating container folder '${_BUILDAH_CACHE_REPO_PATH}'"
exec_cmd buildah run --user "${_OPT_CON_BUILD_USER}" "${_BUILDAH_CONT}" mkdir "${_BUILDAH_CACHE_REPO_PATH}"
log_info "Adding repository '${_BUILDAH_CACHE_REPO} 'to container"
exec_cmd buildah run --user "${_OPT_CON_BUILD_USER}" ${_BUILDAH_PARAMS} "${_BUILDAH_CONT}" repo-add "${_BUILDAH_CACHE_REPO}"
exec_cmd buildah run "${_BUILDAH_CONT}" bash -c "echo -e \"\n\" >> /etc/pacman.conf"
exec_cmd buildah run "${_BUILDAH_CONT}" bash -c "echo -e \"[${_BUILDAH_CACHE_REPO_NAME}]\" >> /etc/pacman.conf"
exec_cmd buildah run "${_BUILDAH_CONT}" bash -c "echo -e \"SigLevel = Optional TrustAll\" >> /etc/pacman.conf"
exec_cmd buildah run "${_BUILDAH_CONT}" bash -c "echo -e \"Server = file://${_BUILDAH_CACHE_REPO_PATH}\" >> /etc/pacman.conf"
log_info "Copying host makepkg.conf to container"
exec_cmd buildah copy --chown root:root "${_BUILDAH_CONT}" "/etc/makepkg.conf" "/etc/makepkg.conf"
log_info "Finalizing image '${ARCHBUILDER_IMAGE_NAME}'"
exec_cmd buildah commit "${_BUILDAH_CONT}" "${ARCHBUILDER_IMAGE_NAME}"
buildah_exit
}
function buildah_update() {
buildah_exists "${ARCHBUILDER_IMAGE_NAME}" \
|| exit_error "Build image '${ARCHBUILDER_IMAGE_NAME}' does not exist" 1
log_info "Creating working container '${ARCHBUILDER_IMAGE_NAME}' from '${ARCHBUILDER_IMAGE_NAME}'"
_BUILDAH_CONT=$(buildah from --name "${ARCHBUILDER_IMAGE_NAME}" "${ARCHBUILDER_IMAGE_NAME}")
log_info "Copying host makepkg.conf to container"
exec_cmd buildah copy --chown root:root "${_BUILDAH_CONT}" "/etc/makepkg.conf" "/etc/makepkg.conf"
log_info "Updating container system"
exec_cmd buildah run --user ${_OPT_CON_BUILD_USER} ${_BUILDAH_PARAMS} "${_BUILDAH_CONT}" sudo pacman --noconfirm -Syu
log_info "Finalizing image '${ARCHBUILDER_IMAGE_NAME}'"
buildah commit "${_BUILDAH_CONT}" "${ARCHBUILDER_IMAGE_NAME}"
buildah_exit
}
function buildah_prepare_build() {
buildah_exists "${ARCHBUILDER_IMAGE_NAME}" \
|| exit_error "Build image '${ARCHBUILDER_IMAGE_NAME}' does not exist" 1
log_info "Creating working container '${ARCHBUILDER_IMAGE_NAME}' from '${ARCHBUILDER_IMAGE_NAME}'"
_BUILDAH_CONT=$(buildah from --name "${ARCHBUILDER_IMAGE_NAME}" "${ARCHBUILDER_IMAGE_NAME}")
log_info "Copying host makepkg.conf to container"
exec_cmd buildah copy --chown root:root "${_BUILDAH_CONT}" "/etc/makepkg.conf" "/etc/makepkg.conf"
log_info "Updating container system"
exec_cmd buildah run --user ${_OPT_CON_BUILD_USER} ${_BUILDAH_PARAMS} "${_BUILDAH_CONT}" sudo pacman --noconfirm -Syu
return 0
for d in "${DEPS[@]}"
do
buildah copy --chown "${_BUILD_USER}" "${CONT}" "${d}" "${_DEP_PATH}/"
f=$(basename "${d}")
buildah run "${CONT}" pacman --noconfirm -U "${_DEP_PATH}/${f}"
done
for k in "${KEYS[@]}"
do
buildah run --user "${_BUILD_USER}" "${CONT}" gpg --receive-keys "${k}"
done
}
function buildah_build() {
buildah_prepare_build
arrExt=$(grep PKGEXT /etc/makepkg.conf)
arrExt=(${arrExt//=/ })
ext=$(echo "${arrExt[1]}" | cut -d "'" -f 2)
exec_cmd buildah run --user "${_OPT_CON_BUILD_USER}" ${_BUILDAH_PARAMS} "${_BUILDAH_CONT}" \
bash -c "cd ${_BUILDAH_MKPKG_PATH} && ${_BUILDAH_MAKEPKG_ENV} makepkg ${_BUILDAH_MAKEPKG_FLAGS} ${_OPT_CON_COPTIONS}"
test_null "PKGDEST" "${PKGDEST}" && {
exec_cmd buildah run --user "${_OPT_CON_BUILD_USER}" ${_BUILDAH_PARAMS} "${_BUILDAH_CONT}" bash -c "cp ${_BUILDAH_MKPKG_PATH}/*${ext} ${_BUILDAH_CACHE_REPO_PATH}"
} || {
exec_cmd buildah run --user "${_OPT_CON_BUILD_USER}" ${_BUILDAH_PARAMS} "${_BUILDAH_CONT}" bash -c "cp ${_BUILDAH_PKGDEST_PATH}/*${ext} ${_BUILDAH_CACHE_REPO_PATH}"
}
exec_cmd buildah run --user "${_OPT_CON_BUILD_USER}" ${_BUILDAH_PARAMS} "${_BUILDAH_CONT}" bash -c "repo-add -n ${_BUILDAH_CACHE_REPO} ${_BUILDAH_CACHE_REPO_PATH}/*${ext}"
buildah_exit
}

View File

@ -0,0 +1,68 @@
#!/bin/bash
function test_dir() {
log_debug "Testing directory '${1}'"
if [ -d "${1}" ]
then
log_debug "'${1}' is a directory"
return 0
fi
log_debug "'${1}' is not a directory"
return 1
}
function test_file() {
log_debug "Testing file '${1}'"
if [ -f "${1}" ]
then
log_debug "'${1}' is a file"
return 0
fi
log_debug "'${1}' is not a file"
return 1
}
function test_exists() {
log_debug "Testing exists '${1}'"
if [ -e "${1}" ]
then
log_debug "'${1}' exists"
return 0
fi
log_debug "'${1}' does not exist"
return 1
}
function test_null() {
log_debug "Testing null for '${1}'"
if [ -z "${2}" ]
then
log_debug "'${1}' is null"
return 0
fi
log_debug "'${1}' is not null"
return 1
}
function test_not_empty() {
log_debug "Testing not empty for '${1}'"
if [ -n "${2}" ]
then
log_debug "'${1}' is not empty"
return 0
fi
log_debug "'${1}' is empty"
return 1
}
function exec_cmd() {
log_debug "Running cmd '${*}'"
exec 3>&2
test_null "_FLAG_SILENT" "${_FLAG_SILENT}" && {
{ err="$( { "$@"; } 2>&1 1>&3 3>&- )"; } 3>&1 \
|| exit_error "${err}" 1;
return 0
}
{ err="$( { "$@"; } 2>&1 1>/dev/null 3>&- )"; } 3>&1 \
|| exit_error "${err}" 1
}

123
lib/ext/slog.sh Normal file
View File

@ -0,0 +1,123 @@
#!/bin/sh
#--------------------------------------------------------------------------------------------------
# slog - Makes logging in POSIX shell scripting suck less
# Copyright (c) Fred Palmer
# POSIX version Copyright Joe Cooper
# Licensed under the MIT license
# http://github.com/swelljoe/slog
#--------------------------------------------------------------------------------------------------
set -e # Fail on first error
# LOG_PATH - Define $LOG_PATH in your script to log to a file, otherwise
# just writes to STDOUT.
# LOG_LEVEL_STDOUT - Define to determine above which level goes to STDOUT.
# By default, all log levels will be written to STDOUT.
LOG_LEVEL_STDOUT="INFO"
# LOG_LEVEL_LOG - Define to determine which level goes to LOG_PATH.
# By default all log levels will be written to LOG_PATH.
LOG_LEVEL_LOG="INFO"
# Useful global variables that users may wish to reference
SCRIPT_ARGS="$@"
SCRIPT_NAME="$0"
SCRIPT_NAME="${SCRIPT_NAME#\./}"
SCRIPT_NAME="${SCRIPT_NAME##/*/}"
# Determines if we print colors or not
if [ $(tty -s) ]; then
readonly INTERACTIVE_MODE="off"
else
readonly INTERACTIVE_MODE="on"
fi
#--------------------------------------------------------------------------------------------------
# Begin Logging Section
if [ "${INTERACTIVE_MODE}" = "off" ]
then
# Then we don't care about log colors
LOG_DEFAULT_COLOR=""
LOG_ERROR_COLOR=""
LOG_INFO_COLOR=""
LOG_SUCCESS_COLOR=""
LOG_WARN_COLOR=""
LOG_DEBUG_COLOR=""
else
LOG_DEFAULT_COLOR=$(tput sgr0)
LOG_ERROR_COLOR=$(tput setaf 1)
LOG_INFO_COLOR=$(tput sgr 0)
LOG_SUCCESS_COLOR=$(tput setaf 2)
LOG_WARN_COLOR=$(tput setaf 3)
LOG_DEBUG_COLOR=$(tput setaf 4)
fi
# This function scrubs the output of any control characters used in colorized output
# It's designed to be piped through with text that needs scrubbing. The scrubbed
# text will come out the other side!
prepare_log_for_nonterminal() {
# Essentially this strips all the control characters for log colors
sed "s/[[:cntrl:]]\[[0-9;]*m//g"
}
log() {
local log_text="$1"
local log_level="$2"
local log_color="$3"
# Levels for comparing against LOG_LEVEL_STDOUT and LOG_LEVEL_LOG
local LOG_LEVEL_DEBUG=0
local LOG_LEVEL_INFO=1
local LOG_LEVEL_SUCCESS=2
local LOG_LEVEL_WARNING=3
local LOG_LEVEL_ERROR=4
# Default level to "info"
[ -z ${log_level} ] && log_level="INFO";
[ -z ${log_color} ] && log_color="${LOG_INFO_COLOR}";
# Validate LOG_LEVEL_STDOUT and LOG_LEVEL_LOG since they'll be eval-ed.
case $LOG_LEVEL_STDOUT in
DEBUG|INFO|SUCCESS|WARNING|ERROR)
;;
*)
LOG_LEVEL_STDOUT=INFO
;;
esac
case $LOG_LEVEL_LOG in
DEBUG|INFO|SUCCESS|WARNING|ERROR)
;;
*)
LOG_LEVEL_LOG=INFO
;;
esac
# Check LOG_LEVEL_STDOUT to see if this level of entry goes to STDOUT.
# XXX This is the horror that happens when your language doesn't have a hash data struct.
eval log_level_int="\$LOG_LEVEL_${log_level}";
eval log_level_stdout="\$LOG_LEVEL_${LOG_LEVEL_STDOUT}"
if [ $log_level_stdout -le $log_level_int ]; then
# STDOUT
printf "${log_color}[$(date +"%Y-%m-%d %H:%M:%S %Z")] [${log_level}] ${log_text} ${LOG_DEFAULT_COLOR}\n";
fi
eval log_level_log="\$LOG_LEVEL_${LOG_LEVEL_LOG}"
# Check LOG_LEVEL_LOG to see if this level of entry goes to LOG_PATH
if [ $log_level_log -le $log_level_int ]; then
# LOG_PATH minus fancypants colors
if [ ! -z $LOG_PATH ]; then
printf "[$(date +"%Y-%m-%d %H:%M:%S %Z")] [${log_level}] ${log_text}\n" >> $LOG_PATH;
fi
fi
return 0;
}
log_info() { log "$@"; }
log_success() { log "$1" "SUCCESS" "${LOG_SUCCESS_COLOR}"; }
log_error() { log "$1" "ERROR" "${LOG_ERROR_COLOR}"; }
log_warning() { log "$1" "WARNING" "${LOG_WARN_COLOR}"; }
log_debug() { log "$1" "DEBUG" "${LOG_DEBUG_COLOR}"; }
# End Logging Section
#--------------------------------------------------------------------------------------------------