Browse Source

almost done with command_not_found

main
pvincent 2 weeks ago
parent
commit
75be83eb94
  1. 69
      poc
  2. 6
      test/poc.test.bash

69
poc

@ -49,20 +49,23 @@ function is_true {
# example: alias toto="bash -c \"[[ \\\$MIAOU_DEBUG == 'true' ]] && echo yes \\\$* || echo nope\"" # example: alias toto="bash -c \"[[ \\\$MIAOU_DEBUG == 'true' ]] && echo yes \\\$* || echo nope\""
function miaou_debug { function miaou_debug {
if is_true "${MIAOU_DEBUG}"; then if is_true "${MIAOU_DEBUG}"; then
local i message="$*" padding=''
local compute_hierarchy=true local compute_hierarchy=true
[[ ! -v miaou_debug_hierarchy ]] && miaou_debug_hierarchy=0 [[ ! -v miaou_debug_hierarchy ]] && miaou_debug_hierarchy=0
local i message="$*" padding=''
regex='^</' # starts with </ regex='^</' # starts with </
[[ $miaou_debug_hierarchy -gt 0 ]] && [[ $miaou_debug_hierarchy -gt 0 ]] &&
[[ "${message}" =~ $regex ]] && [[ "${message}" =~ $regex ]] &&
((--miaou_debug_hierarchy)) &&
miaou_debug_hierarchy=$((miaou_debug_hierarchy - 1)) &&
compute_hierarchy=false compute_hierarchy=false
for ((i = 0; i < miaou_debug_hierarchy; i++)); do padding+=' '; done for ((i = 0; i < miaou_debug_hierarchy; i++)); do padding+=' '; done
>&4 builtin echo -e "\e[90m <== DEBUG ==> ${padding}\e[33m${message}\e[0m" >&4 builtin echo -e "\e[90m <== DEBUG ==> ${padding}\e[33m${message}\e[0m"
regex='[^/]>$' # does NOT end with /> regex='[^/]>$' # does NOT end with />
is_true $compute_hierarchy && is_true $compute_hierarchy &&
[[ "${message}" =~ $regex ]] && [[ "${message}" =~ $regex ]] &&
((++miaou_debug_hierarchy)) ||
miaou_debug_hierarchy=$((miaou_debug_hierarchy + 1)) ||
true true
fi fi
} }
@ -117,7 +120,15 @@ function print_miaou_error {
local message local message
message="${source}: line ${line}: miaou_error: ${type} ${code}" message="${source}: line ${line}: miaou_error: ${type} ${code}"
[[ -n "$payload" ]] && message+=" payload: ${payload}" [[ -n "$payload" ]] && message+=" payload: ${payload}"
[[ -v tmp_error ]] && miaou_debug "tmp_error=${#tmp_error[@]}" && tmp_error+=("$message") || >&2 echo "$message"
>&2 echo "$message"
}
function add_miaou_error {
local source="$1" line="$2" code="$3" type="$4" payload="${5:-}"
local message
message="${source}: line ${line}: miaou_error: ${type} ${code}"
[[ -n "$payload" ]] && message+=" payload: ${payload}"
tmp_error+=("$message")
} }
function on_error { function on_error {
@ -131,11 +142,28 @@ function on_error {
if [[ ! -v failure_type ]]; then if [[ ! -v failure_type ]]; then
if [[ ${BASH_COMMAND} == 'false' ]]; then if [[ ${BASH_COMMAND} == 'false' ]]; then
failure_type="FALSE" failure_type="FALSE"
print_miaou_error "${BASH_SOURCE[1]}" "${BASH_LINENO[0]}" "${failure_code}" "${failure_type}"
else else
failure_type="COMMAND_ERROR" failure_type="COMMAND_ERROR"
failure_payload="${BASH_COMMAND}" failure_payload="${BASH_COMMAND}"
print_miaou_error "${BASH_SOURCE[1]}" "${BASH_LINENO[0]}" "${failure_code}" "${failure_type}" "${failure_payload}"
miaou_debug "<investigate_tmp_error pid=${BASHPID}>"
load_tmp_error # cannot print_miaou_error after investigation
if [[ ${#tmp_error[@]} -gt 1 ]]; then
local last_error regex
last_error="${tmp_error[-2]}" # the second latest cause previous print_miaou_error above
regex='^(.*): line ([0-9]+): (.*): command not found$'
if [[ $failure_code == 127 && "$last_error" =~ $regex ]]; then
failure_type='COMMAND_NOT_FOUND'
failure_payload="${BASH_REMATCH[3]}"
miaou_debug "<command_not_found payload=${failure_payload}/>"
fi
fi
miaou_debug '</investigate_tmp_error>'
fi fi
print_miaou_error "${BASH_SOURCE[1]}" "${BASH_LINENO[0]}" "${failure_code}" "${failure_type}"
fi fi
error_source=("${BASH_SOURCE[@]}") error_source=("${BASH_SOURCE[@]}")
@ -153,11 +181,10 @@ function on_error {
else else
miaou_debug "</on_error exit=$failure_code type=${failure_type}>" miaou_debug "</on_error exit=$failure_code type=${failure_type}>"
fi fi
builtin exit "$failure_code" builtin exit "$failure_code"
else else
miaou_debug "</on_error pipe=$failure_code sub_pid=$BASHPID pid=$$ command={${BASH_COMMAND}}>"
print_miaou_error "${BASH_SOURCE[1]}" "${BASH_LINENO[0]}" "${failure_code}" 'SUBSHELL_ERROR' "${BASH_COMMAND}" print_miaou_error "${BASH_SOURCE[1]}" "${BASH_LINENO[0]}" "${failure_code}" 'SUBSHELL_ERROR' "${BASH_COMMAND}"
miaou_debug "</on_error pipe=$failure_code sub_pid=$BASHPID pid=$$ command={${BASH_COMMAND}}>"
kill -PIPE $$ kill -PIPE $$
fi fi
} }
@ -174,7 +201,7 @@ function on_pipe {
unset 'error_source[-1]' 'error_lineno[-1]' 'error_funcname[-1]' unset 'error_source[-1]' 'error_lineno[-1]' 'error_funcname[-1]'
unset 'error_source[-1]' 'error_lineno[-1]' 'error_funcname[-1]' unset 'error_source[-1]' 'error_lineno[-1]' 'error_funcname[-1]'
miaou_debug '<load_tmp_error/>' && mapfile -t tmp_error <"$MIAOU_BASH_ERROR"
load_tmp_error
last_error="${tmp_error[-1]}" last_error="${tmp_error[-1]}"
regex='^(.*): line ([0-9]+): miaou_error: SUBSHELL_ERROR ([0-9]+) payload: (.*)$' regex='^(.*): line ([0-9]+): miaou_error: SUBSHELL_ERROR ([0-9]+) payload: (.*)$'
@ -247,15 +274,24 @@ function dump_stacktrace {
miaou_debug '</stacktrace>' miaou_debug '</stacktrace>'
} }
function load_tmp_error {
[[ -v tmp_error ]] && return 0
mapfile -t tmp_error <"$MIAOU_BASH_ERROR"
local count=${#tmp_error[@]}
if [[ $count == 0 ]]; then
miaou_debug "<tmp_error empty/>"
else
miaou_debug "<tmp_error count=${count}/>"
fi
}
function on_exit { function on_exit {
trap - RETURN trap - RETURN
local code="${1:-0}" last_error regex local code="${1:-0}" last_error regex
miaou_debug "<on_exit code=$code>" miaou_debug "<on_exit code=$code>"
[[ ! -v tmp_error ]] &&
miaou_debug '<load_tmp_error/>' &&
mapfile -t tmp_error <"$MIAOU_BASH_ERROR"
load_tmp_error
if [[ -v failure_type && "$failure_type" == 'RETURN' ]]; then if [[ -v failure_type && "$failure_type" == 'RETURN' ]]; then
last_error="${tmp_error[-1]}" last_error="${tmp_error[-1]}"
@ -272,7 +308,7 @@ function on_exit {
miaou_debug "<return type=unexpected/>" miaou_debug "<return type=unexpected/>"
fi fi
else
elif [[ ! -v failure_type ]]; then
if [[ $code -gt 0 && ${#tmp_error[@]} -gt 0 ]]; then if [[ $code -gt 0 && ${#tmp_error[@]} -gt 0 ]]; then
last_error="${tmp_error[-1]}" last_error="${tmp_error[-1]}"
miaou_debug "<investigate_tmp_error last={$last_error}>" miaou_debug "<investigate_tmp_error last={$last_error}>"
@ -298,9 +334,10 @@ function on_exit {
failure_type='UNBOUND_VARIABLE' failure_type='UNBOUND_VARIABLE'
failure_payload=$payload failure_payload=$payload
print_miaou_error "${BASH_SOURCE[1]}" "${BASH_LINENO[0]}" "${failure_code}" "${failure_type}" "${failure_payload}"
unset 'tmp_error[-2]' # replace previous last_error
add_miaou_error "${BASH_SOURCE[1]}" "${BASH_LINENO[0]}" "${failure_code}" "${failure_type}" "${failure_payload}"
miaou_debug "<unbound_variable source=${source} line=${line} payload={${failure_payload}}/>" miaou_debug "<unbound_variable source=${source} line=${line} payload={${failure_payload}}/>"
else
failure_type='UNKNOWN ERROR'
fi fi
miaou_debug "</investigate_tmp_error>" miaou_debug "</investigate_tmp_error>"
fi fi
@ -332,6 +369,8 @@ trap 'on_exit $?' EXIT
trap 'on_pipe' PIPE trap 'on_pipe' PIPE
trap 'on_return' RETURN trap 'on_return' RETURN
declare -a tmp_error # to prevent loading multiple times
if [[ -e /proc/$$/fd/3 ]]; then exec 4>&3 3>&-; else exec 4>/dev/tty; fi # swap fd 3 4 when fd 3 sent off if [[ -e /proc/$$/fd/3 ]]; then exec 4>&3 3>&-; else exec 4>/dev/tty; fi # swap fd 3 4 when fd 3 sent off
exec 3>/dev/stderr 2>"$MIAOU_BASH_ERROR" exec 3>/dev/stderr 2>"$MIAOU_BASH_ERROR"

6
test/poc.test.bash

@ -24,7 +24,7 @@ function fail_type {
mapfile -t stderr <<<"$(./poc ./test/stub/scenario.bash "$1" 2>&1 >/dev/null 3>/dev/null)" mapfile -t stderr <<<"$(./poc ./test/stub/scenario.bash "$1" 2>&1 >/dev/null 3>/dev/null)"
last_error="${stderr[-1]}" last_error="${stderr[-1]}"
regex="^(.*): line ([0-9]+): miaou_error: $2 ([0-9]+) payload: (.*)\$"
regex="^(.*): line ([0-9]+): miaou_error: $2 ([0-9]+)"
[[ "${last_error}" =~ $regex ]] && success=true [[ "${last_error}" =~ $regex ]] && success=true
# if [[ $success == true && -n "${hint_message}" ]]; then # if [[ $success == true && -n "${hint_message}" ]]; then
@ -60,13 +60,13 @@ fail_type command_not_found COMMAND_NOT_FOUND
# fail_type subshell_error COMMAND_NOT_FOUND '(hint: prefer source than subshell)' # fail_type subshell_error COMMAND_NOT_FOUND '(hint: prefer source than subshell)'
# fail_type command_error COMMAND_ERROR # fail_type command_error COMMAND_ERROR
failed=$((test_count - ${#failures[@]}))
failed=${#failures[@]}
success=$((test_count - failed)) success=$((test_count - failed))
echo echo
if [[ $failed -gt 0 ]]; then if [[ $failed -gt 0 ]]; then
ratio=$((100 * success / test_count)) ratio=$((100 * success / test_count))
echo "${ratio}% passed, $success succeeded, $failed failed!"
echo "${ratio}% passed, ${test_count} tests, ${failed} failed!"
echo failures: echo failures:
for failure in "${failures[@]}"; do for failure in "${failures[@]}"; do
echo -e "\t- $failure" echo -e "\t- $failure"

Loading…
Cancel
Save