Skip to content

Commit

Permalink
Report all function errors as JSON (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
tesujimath authored Oct 27, 2024
1 parent 83fbfc9 commit da44b38
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 24 deletions.
65 changes: 41 additions & 24 deletions bash-env-json
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,9 @@ function eval_or_source() {
_path="$1"

_error_file=$(mktemp -u)
# tell ShellCheck I really do want to expand this now and not at the point of exit
# shellcheck disable=SC2064
trap "rm -f $_error_file" EXIT
touch "$_error_file"
exec 3<"$_error_file" 4>"$_error_file"
rm -f "$_error_file"

if test -n "$_path"; then
# source from file if specified
Expand All @@ -142,19 +142,35 @@ function eval_or_source() {

# ShellCheck can't cope with sourcing from an unknown path
# shellcheck disable=SC1090
if ! source "$_path" >/dev/null 2>"$_error_file"; then
emit_error_exit "$(head -1 "$_error_file")"
if ! source "$_path" >/dev/null 2>&4; then
exec 4>&-
emit_error_exit "$(head -1 <&3)"
fi
else
# otherwise eval from stdin
_source=$(</dev/stdin)
if ! eval "$_source" >/dev/null 2>"$_error_file"; then
if ! eval "$_source" >/dev/null 2>&4; then
exec 4>&-
# discard error location, because it is this file not the one sourced
emit_error_exit "$(sed -e 's/^.*line\s*[0-9]*:\s*//' "$_error_file")"
emit_error_exit "$(sed -e 's/^.*line\s*[0-9]*:\s*//' <&3)"
fi
fi
}

function invoke_safely() {
local _fn="$1"

_error_file=$(mktemp -u)
touch "$_error_file"
exec 3<"$_error_file" 4>"$_error_file"
rm -f "$_error_file"

"$_fn" >/dev/null 2>&4 || {
exec 4>&-
emit_error_exit "$(head -1 <&3)"
}
}

function get_args() {
local -n _opt_path="$1"
local -n _opt_shellfn_names="$2"
Expand Down Expand Up @@ -203,39 +219,40 @@ function main() {
eval_or_source "$_path"
capture _env_current _shellvars_current

# validate all the functions we will invoke before committing to the happy path
for _fn in "${_shellfn_names[@]}"; do
test "$(type -t "$_fn")" == "function" || {
emit_error_exit "no such function: $_fn"
}
done
# accumulate result in a file until we know we are error-free
_result_file=$(mktemp -u)
touch "$_result_file"
exec 5<"$_result_file" 6>"$_result_file"
rm -f "$_result_file"

emit "{" env _env_previous _env_current
emit "," shellvars _shellvars_previous _shellvars_current
emit "{" env _env_previous _env_current >&6
emit "," shellvars _shellvars_previous _shellvars_current >&6

test "${#_shellfn_names[@]}" -gt 0 && {
echo ",\"fn\":{"
echo ",\"fn\":{" >&6
}

local _fn_comma=""
for _fn in "${_shellfn_names[@]}"; do
capture _env_previous _shellvars_previous
# execute the function
"$_fn"
invoke_safely "$_fn"
capture _env_current _shellvars_current

echo "$_fn_comma\"$_fn\":"
emit "{" env _env_previous _env_current
emit "," shellvars _shellvars_previous _shellvars_current
echo "}"
echo "$_fn_comma\"$_fn\":" >&6
emit "{" env _env_previous _env_current >&6
emit "," shellvars _shellvars_previous _shellvars_current >&6
echo "}" >&6
_fn_comma=","
done

test "${#_shellfn_names[@]}" -gt 0 && {
echo "}"
echo "}" >&6
}

echo "}"
echo "}" >&6
exec 6>&-

cat <&5
}

function bad_usage() {
Expand Down
3 changes: 3 additions & 0 deletions tests/shell-function-error.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
function f() {
whacky-doodle-doo
}

0 comments on commit da44b38

Please sign in to comment.