scrut 0.4.3

A simple and powerful test framework for CLI applications
Documentation
# vim:set ft=bash

# Copyright (c) Meta Platforms, Inc. and affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

__SCRUT_TEMP_STATE_PATH="{state_directory}"

# persist the whole state / context of the execution in a file `state`, so that
# it can be recovered in a subsequent execution using `source state`.
function __scrut_persist_state {
    local code=$?

    # do not persist this trap
    unset -f __scrut_persist_state

    # ensure the state directory exists
    mkdir -p "$__SCRUT_TEMP_STATE_PATH"

    # for bash (<4): "declare -p" returns expressions of the form "VARNAME=VARVALUE" as opposed to
    # the longer form "declare -x VARNAME=VARVALUE". Re-importing these statements works, but the
    # variables are not exported to the environment, which changes the behavior of Scrut. The
    # following ensures the "declare -x"-form export of variables and aligns the behavior accross
    # bash versions.
    __SCRUT_DECLARE_VARS_CMD="declare -p"
    if ! declare -p | grep -q "^declare "; then
        __SCRUT_DECLARE_VARS_CMD="declare -p | sed -re 's/^([A-Za-z0-9_]+)=/declare -x \1=/'"
    fi

    (
        # store all settings (sh)
        set +o

        # store all settings (bash)
        shopt -p

        # store all aliases
        alias -p

        # store all functions
        declare -f

        # store all shell and environment variables
        eval "$__SCRUT_DECLARE_VARS_CMD" | \
            grep -Ev "^declare -.?r" | \
            grep -Ev "^declare -[a-zA-Z-]* ({excluded_variables}|[^=]*[^a-zA-Z0-9_=][^=]*)(=|\$)"

        # ensure directory stack starts at same position
        printf "cd %q 2>/dev/null\n" "${DIRSTACK[${#DIRSTACK[@]} - 1]}"

        # store the current directory stack (pushd / popd)
        printf "pushd %q >/dev/null 2>/dev/null\n" "${DIRSTACK[@]}" | sed '1!G;h;$!d' | tail -n +2
    ) > "$__SCRUT_TEMP_STATE_PATH/state"

    exit $code
}

# load the state from the previous execution, if it exists
shopt -s expand_aliases
[ -f "$__SCRUT_TEMP_STATE_PATH/state" ] && source "$__SCRUT_TEMP_STATE_PATH/state"

# ensure the state of this execution will be persisted for the next execution
[ {persist_state} -eq 1 ] && trap __scrut_persist_state EXIT

# execute the shell expression
{shell_expression}