You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
142 lines
3.6 KiB
142 lines
3.6 KiB
#!/usr/bin/env bash
|
|
|
|
# constants
|
|
|
|
MIAOU_BASH_ERROR=$(mktemp -t "$(basename "$0").XXXXXXXX" --tmpdir="/run/user/$(id -u)")
|
|
MIAOU_DEBUG=${MIAOU_DEBUG:-false}
|
|
readonly MIAOU_BASH_ERROR MIAOU_DEBUG
|
|
|
|
## functions
|
|
|
|
function is_true {
|
|
[[ "${1:-}" == 'true' ]]
|
|
}
|
|
|
|
# FIXME: define an alias to bypass ARG evaluation when unnecessary!
|
|
# example:
|
|
# alias toto="bash -c \"[[ \\\$MIAOU_DEBUG == 'true' ]] && echo yes \\\$* || echo nope\""
|
|
function miaou_debug {
|
|
is_true "${MIAOU_DEBUG}" && >/dev/tty builtin echo -e "\e[90mDEBUG <==> \e[33m$*\e[0m" || true
|
|
}
|
|
|
|
function tty_ansi {
|
|
fg="${1:-}"
|
|
[[ -n $fg ]] && >/dev/tty echo -ne "\e[${fg}m" || true
|
|
}
|
|
|
|
function on_error {
|
|
local code
|
|
code="${1:-100}"
|
|
>/dev/tty printf '\r' # force carriage return explicitly
|
|
|
|
miaou_debug "on_error: $code ($$ -- $BASHPID)"
|
|
|
|
if [[ $$ == "$BASHPID" ]]; then
|
|
>&2 echo "${BASH_SOURCE[1]}: line ${BASH_LINENO[0]}: command_error: ${code}"
|
|
failure_type="COMMAND_ERROR"
|
|
error_source=("${BASH_SOURCE[@]}")
|
|
error_lineno=("${BASH_LINENO[@]}")
|
|
error_funcname=("${FUNCNAME[@]}")
|
|
unset 'error_source[-1]' 'error_lineno[-1]' 'error_funcname[-1]'
|
|
unset 'error_source[0]' 'error_lineno[-1]' 'error_funcname[0]'
|
|
error_funcname[-1]='<main>'
|
|
error_source=("${error_source[@]}")
|
|
error_lineno=("${error_lineno[@]}")
|
|
error_funcname=("${error_funcname[@]}")
|
|
|
|
exit "$code"
|
|
else
|
|
>&2 echo "${BASH_SOURCE[1]}: line ${BASH_LINENO[0]}: subshell_error: ${code}"
|
|
kill -PIPE $$
|
|
fi
|
|
}
|
|
|
|
function dump_stderr {
|
|
miaou_debug --stderr--
|
|
mapfile -t tmp_error <"$MIAOU_BASH_ERROR"
|
|
tty_ansi 94
|
|
for i in "${tmp_error[@]}"; do echo "$i"; done
|
|
tty_ansi 0
|
|
miaou_debug --end of stderr--
|
|
}
|
|
|
|
function dump_failure {
|
|
miaou_debug --error box--
|
|
tty_ansi 94
|
|
echo -n "FAILURE TYPE = "
|
|
tty_ansi 95
|
|
echo "$failure_type"
|
|
tty_ansi 0
|
|
miaou_debug --end of error box--
|
|
}
|
|
|
|
function dump_stacktrace {
|
|
miaou_debug --stacktrace ${#error_source[@]}--
|
|
tty_ansi 94
|
|
local i source lineno funcname
|
|
for i in "${!error_source[@]}"; do
|
|
source="${error_source[$i]}"
|
|
lineno="${error_lineno[$i]}"
|
|
funcname="${error_funcname[$i]}"
|
|
printf "%40s:%.4s \t%s\n" "$source" "$lineno" "$funcname"
|
|
done
|
|
tty_ansi 0
|
|
miaou_debug --end of stacktrace--
|
|
}
|
|
|
|
function on_exit {
|
|
code="${1:-0}"
|
|
failure_type="${failure_type:-UNDEFINED}"
|
|
|
|
2>&3 >&3 dump_stderr
|
|
2>&3 >&3 dump_failure
|
|
2>&3 >&3 dump_stacktrace
|
|
|
|
miaou_debug "on_exit $code $failure_type"
|
|
}
|
|
|
|
function on_pipe {
|
|
local code tmp_error regex
|
|
|
|
error_source=("${BASH_SOURCE[@]}")
|
|
error_lineno=("${BASH_LINENO[@]}")
|
|
error_funcname=("${FUNCNAME[@]}")
|
|
unset 'error_source[0]' 'error_lineno[0]' 'error_funcname[0]'
|
|
unset 'error_source[-1]' 'error_lineno[-1]' 'error_funcname[-1]'
|
|
unset 'error_source[-1]' 'error_lineno[-1]' 'error_funcname[-1]'
|
|
|
|
mapfile -t tmp_error <"$MIAOU_BASH_ERROR"
|
|
last_error="${tmp_error[-1]}"
|
|
regex='(.*): line ([0-9]+): subshell_error: ([0-9]+)'
|
|
if [[ $last_error =~ $regex ]]; then
|
|
source=${BASH_REMATCH[1]}
|
|
lineno=${BASH_REMATCH[2]}
|
|
code=${BASH_REMATCH[3]}
|
|
failure_type="SUBSHELL_ERROR"
|
|
error_source=("$source" "${error_source[@]}")
|
|
error_lineno=("$lineno" "${error_lineno[@]}")
|
|
error_funcname=("${error_funcname[@]}" '<main>')
|
|
else
|
|
code=141
|
|
failure_type="PIPE_ERROR"
|
|
fi
|
|
|
|
# miaou_debug on_pipe: "${code}"
|
|
exit "$code"
|
|
}
|
|
|
|
## main
|
|
|
|
set -euo pipefail
|
|
set -E # HALT on subshell error
|
|
# set -T # DEBUG RETURN
|
|
|
|
trap 'on_error $?' ERR
|
|
trap 'on_exit $?' EXIT
|
|
trap 'on_pipe' PIPE
|
|
|
|
echo "--SOURCE scenario ${BASHPID}"
|
|
exec 3>/dev/stderr
|
|
2>"$MIAOU_BASH_ERROR" source ./test/stub/scenario.bash subshell_term
|
|
exec 3>-
|
|
echo "--SUCCESS scenario"
|