From 470239bb7d923d3e012c7ed5563d9d53c596a997 Mon Sep 17 00:00:00 2001 From: Nikolaos Kakouros Date: Thu, 18 Jan 2018 00:25:29 +0100 Subject: [PATCH 01/16] Adds custom error codes to go-core.bash --- go-core.bash | 59 ++++++++++++++++++++++++------------------- lib/internal/sysexits | 18 +++++++++++++ 2 files changed, 51 insertions(+), 26 deletions(-) create mode 100644 lib/internal/sysexits diff --git a/go-core.bash b/go-core.bash index 61cf511..450ba89 100755 --- a/go-core.bash +++ b/go-core.bash @@ -26,11 +26,14 @@ # https://mike-bland.com/ # https://github.com/mbland +_GO_EC_GENERR="${_GO_EC_GENERR:-70}" +_GO_EC_DEPMISS="${_GO_EC_DEPMISS:-72}" + if [[ "${BASH_VERSINFO[0]}" -lt '3' || ( "${BASH_VERSINFO[0]}" -eq '3' && "${BASH_VERSINFO[1]}" -lt '2' ) ]]; then printf "This module requires bash version 3.2 or greater:\n %s %s\n" \ "$BASH" "$BASH_VERSION" - exit 1 + exit "$_GO_EXIT_DEPMISS" fi # The version of the framework @@ -46,7 +49,7 @@ declare -r -x _GO_CORE_VERSION='v1.7.0' declare -r -x _GO_CORE_URL='https://github.com/mbland/go-script-bash' declare __go_orig_dir="$PWD" -cd "${0%/*}" || exit 1 +cd "${0%/*}" || exit "$_GO_EC_GENERR" # Path to the project's root directory # @@ -58,19 +61,21 @@ declare -x _GO_ROOTDIR="$PWD" if [[ "${BASH_SOURCE[0]:0:1}" != '/' ]]; then cd "$__go_orig_dir/${BASH_SOURCE[0]%/*}" || exit 1 else - cd "${BASH_SOURCE[0]%/*}" || exit 1 + cd "${BASH_SOURCE[0]%/*}" || exit "$_GO_EC_GENERR" fi # Path to the ./go script framework's directory declare -r -x _GO_CORE_DIR="$PWD" +. "$_GO_CORE_DIR/lib/internal/sysexits" + # Set _GO_STANDALONE if your script is a standalone program. # # See the "Standalone mode" section of README.md for more information. if [[ -z "$_GO_STANDALONE" ]]; then - cd "$_GO_ROOTDIR" || exit 1 + cd "$_GO_ROOTDIR" || exit "$_GO_EC_GENERR" else - cd "$__go_orig_dir" || exit 1 + cd "$__go_orig_dir" || exit "$_GO_EC_GENERR" fi unset __go_orig_dir @@ -205,17 +210,17 @@ declare _GO_INJECT_MODULE_PATH="$_GO_INJECT_MODULE_PATH" # skip_callers: The number of callers to skip over when printing the stack @go.print_stack_trace() { local skip_callers="$1" - local result=0 + local result="$_GO_EC_OK" local i if [[ -n "$skip_callers" && ! "$skip_callers" =~ ^[1-9][0-9]*$ ]]; then printf '%s argument %s not a positive integer; printing full stack\n' \ "$FUNCNAME" "'$skip_callers'" >&2 - result=1 + result="$_GO_EC_GENERR" elif [[ "$skip_callers" -ge "${#FUNCNAME[@]}" ]]; then printf '%s argument %d exceeds stack size %d; printing full stack\n' \ "$FUNCNAME" "$skip_callers" "$((${#FUNCNAME[@]} - 1))" >&2 - result=1 + result="$_GO_EC_GENERR" fi if [[ "$result" -ne '0' ]]; then @@ -269,9 +274,9 @@ declare _GO_INJECT_MODULE_PATH="$_GO_INJECT_MODULE_PATH" while true; do if "$1" "$__gsp_plugins_dir"; then - return + return "$_GO_EC_OK" elif [[ "$__gsp_plugins_dir" == "$_GO_PLUGINS_DIR" ]]; then - return 1 + return "$_GO_EC_GENERR" fi __gsp_plugins_dir="${__gsp_plugins_dir%/plugins/*}/plugins" done @@ -289,7 +294,7 @@ declare _GO_INJECT_MODULE_PATH="$_GO_INJECT_MODULE_PATH" case "$cmd" in '') _@go.source_builtin 'help' 1>&2 - return 1 + return "$_GO_EC_USAGE" ;; -h|-help|--help) cmd='help' @@ -297,30 +302,30 @@ declare _GO_INJECT_MODULE_PATH="$_GO_INJECT_MODULE_PATH" -*) @go.printf "Unknown flag: $cmd\n\n" _@go.source_builtin 'help' 1>&2 - return 1 + return "$_GO_EC_USAGE" ;; edit) if [[ -z "$EDITOR" ]]; then echo "Cannot edit $@: \$EDITOR not defined." - return 1 + return "$_GO_EC_SYSERR" fi "$EDITOR" "$@" - return + return "$_GO_EC_OK" ;; run) "$@" - return + return "$_GO_EC_OK" ;; cd|pushd|unenv) @go.printf "$cmd is only available after using \"$_GO_CMD env\" %s\n" \ "to set up your shell environment." >&2 - return 1 + return "$_GO_EC_USAGE" ;; esac if _@go.source_builtin 'aliases' --exists "$cmd"; then "$cmd" "$@" - return + return "$_GO_EC_OK" fi . "$_GO_CORE_DIR/lib/internal/path" @@ -329,7 +334,7 @@ declare _GO_INJECT_MODULE_PATH="$_GO_INJECT_MODULE_PATH" local __go_argv if ! _@go.set_command_path_and_argv "$cmd" "$@"; then - return 1 + return "$_GO_EC_GENERR" fi if [[ "${__go_cmd_path#$_GO_SCRIPTS_DIR}" =~ /plugins/[^/]+/bin/ ]]; then @@ -366,7 +371,7 @@ _@go.run_command_script() { @go.printf \ "The first line of %s does not contain #!/path/to/interpreter.\n" \ "$cmd_path" >&2 - return 1 + return "$_GO_EC_BADFRMT" fi interpreter="${interpreter%$'\r'}" @@ -383,7 +388,7 @@ _@go.run_command_script() { . "$cmd_path" "$@" elif [[ -z "$interpreter" ]]; then @go.printf "Could not parse interpreter from first line of $cmd_path.\n" >&2 - return 1 + return "$_GO_EC_BADFRMT" else if [[ -z "$_GO_CMD_NAME" ]]; then local origIFS="$IFS" @@ -401,23 +406,25 @@ _@go.set_scripts_dir() { if [[ "$#" -ne '1' ]]; then echo "ERROR: there should be exactly one command script dir specified" >&2 - return 1 + return "$_GO_EC_CONFIG" elif [[ ! -e "$scripts_dir" ]]; then echo "ERROR: command script directory $scripts_dir does not exist" >&2 - return 1 + return "$_GO_EC_CONFIG" elif [[ ! -d "$scripts_dir" ]]; then echo "ERROR: $scripts_dir is not a directory" >&2 - return 1 + return "$_GO_EC_CONFIG" elif [[ ! -r "$scripts_dir" || ! -x "$scripts_dir" ]]; then echo "ERROR: you do not have permission to access the $scripts_dir" \ "directory" >&2 - return 1 + return "$_GO_EC_NOPERM" fi _GO_SCRIPTS_DIR="$scripts_dir" } -if ! _@go.set_scripts_dir "$@"; then - exit 1 +_@go.set_scripts_dir "$@" && rc=0 || rc="$?" + +if [[ "$rc" -ne 0 ]]; then + exit "$rc" elif [[ -z "$COLUMNS" ]]; then # On Travis, $TERM is set to 'dumb', but `tput cols` still fails. if command -v tput >/dev/null && tput cols >/dev/null 2>&1; then diff --git a/lib/internal/sysexits b/lib/internal/sysexits new file mode 100644 index 0000000..c2cbb24 --- /dev/null +++ b/lib/internal/sysexits @@ -0,0 +1,18 @@ +#! /bin/bash + +declare -r -x _GO_EC_OK=0 +declare -r -x _GO_EC_USAGE=64 +declare -r -x _GO_EC_DATAERR=65 +declare -r -x _GO_EC_NOINPUT=66 +declare -r -x _GO_EC_BADFRMT=67 +declare -r -x _GO_EC_NOHOST=68 +declare -r -x _GO_EC_UNAVAILABLE=69 +declare -r -x _GO_EC_GENERR=70 +declare -r -x _GO_EC_SYSERR=71 +declare -r -x _GO_EC_DEPMISS=72 +declare -r -x _GO_EC_CANTCREAT=73 +declare -r -x _GO_EC_IOERR=74 +declare -r -x _GO_EC_ +declare -r -x _GO_EC_ +declare -r -x _GO_EC_NOPERM=77 +declare -r -x _GO_EC_CONFIG=78 From 74c09b110f41159bb0d3c1f2c1640f37ec0957f0 Mon Sep 17 00:00:00 2001 From: Nikolaos Kakouros Date: Thu, 18 Jan 2018 08:43:04 +0100 Subject: [PATCH 02/16] Adds offset and boundaries to exit codes --- lib/internal/sysexits | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/lib/internal/sysexits b/lib/internal/sysexits index c2cbb24..369c900 100644 --- a/lib/internal/sysexits +++ b/lib/internal/sysexits @@ -1,18 +1,21 @@ #! /bin/bash -declare -r -x _GO_EC_OK=0 -declare -r -x _GO_EC_USAGE=64 -declare -r -x _GO_EC_DATAERR=65 -declare -r -x _GO_EC_NOINPUT=66 -declare -r -x _GO_EC_BADFRMT=67 -declare -r -x _GO_EC_NOHOST=68 -declare -r -x _GO_EC_UNAVAILABLE=69 -declare -r -x _GO_EC_GENERR=70 -declare -r -x _GO_EC_SYSERR=71 -declare -r -x _GO_EC_DEPMISS=72 -declare -r -x _GO_EC_CANTCREAT=73 -declare -r -x _GO_EC_IOERR=74 -declare -r -x _GO_EC_ -declare -r -x _GO_EC_ -declare -r -x _GO_EC_NOPERM=77 -declare -r -x _GO_EC_CONFIG=78 +declare -r -x -i _GO_EC_OFFSET=0 +declare -r -x -i _GO_EC_OK=0 +declare -r -x -i _GO_EC_BASE=_GO_EC_OFFSET+64 +declare -r -x -i _GO_EC_USAGE=_GO_EC_OFFSET+64 +declare -r -x -i _GO_EC_DATAERR=_GO_EC_OFFSET+65 +declare -r -x -i _GO_EC_NOINPUT=_GO_EC_OFFSET+66 +declare -r -x -i _GO_EC_BADFRMT=_GO_EC_OFFSET+67 +declare -r -x -i _GO_EC_NOHOST=_GO_EC_OFFSET+68 +declare -r -x -i _GO_EC_UNAVAILABLE=_GO_EC_OFFSET+69 +declare -r -x -i _GO_EC_GENERR=_GO_EC_OFFSET+70 +declare -r -x -i _GO_EC_SYSERR=_GO_EC_OFFSET+71 +declare -r -x -i _GO_EC_DEPMISS=_GO_EC_OFFSET+72 +declare -r -x -i _GO_EC_CANTCREAT=_GO_EC_OFFSET+73 +declare -r -x -i _GO_EC_IOERR=_GO_EC_OFFSET+74 +declare -r -x -i _GO_EC_ +declare -r -x -i _GO_EC_ +declare -r -x -i _GO_EC_NOPERM=_GO_EC_OFFSET+77 +declare -r -x -i _GO_EC_CONFIG=_GO_EC_OFFSET+78 +declare -r -x -i _GO_EC_MAX=_GO_EC_OFFSET+78 From a4f549a48bfd16467c0eea2ecb06d87332db4ec5 Mon Sep 17 00:00:00 2001 From: Nikolaos Kakouros Date: Fri, 19 Jan 2018 13:59:48 +0100 Subject: [PATCH 03/16] Adds custom return codes to more places --- go-core.bash | 15 +++++++++++++-- go-template | 16 ++++++++-------- lib/existence | 28 ++++++++++++++++++++-------- lib/internal/sysexits | 2 +- scripts/changes | 8 ++++---- 5 files changed, 46 insertions(+), 23 deletions(-) diff --git a/go-core.bash b/go-core.bash index 450ba89..6defdd8 100755 --- a/go-core.bash +++ b/go-core.bash @@ -198,6 +198,8 @@ declare _GO_INJECT_MODULE_PATH="$_GO_INJECT_MODULE_PATH" done printf '%s' "$line" done <<<"${result//$'\n'/$'\n\x1f'}"$'\x1f' + + return "$_GO_EC_OK" } # Prints the stack trace at the point of the call. @@ -268,7 +270,7 @@ declare _GO_INJECT_MODULE_PATH="$_GO_INJECT_MODULE_PATH" # search_func: Helper function implementing the search operation # # Returns: -# Zero if `search_func` ever returns zero, nonzero otherwise +# _GO_EC_OK if `search_func` ever returns zero, _GO_EC_GENERR otherwise @go.search_plugins() { local __gsp_plugins_dir="$_GO_SCRIPTS_DIR/plugins" @@ -307,7 +309,7 @@ declare _GO_INJECT_MODULE_PATH="$_GO_INJECT_MODULE_PATH" edit) if [[ -z "$EDITOR" ]]; then echo "Cannot edit $@: \$EDITOR not defined." - return "$_GO_EC_SYSERR" + return "$_GO_EC_CONFIG" fi "$EDITOR" "$@" return "$_GO_EC_OK" @@ -342,12 +344,16 @@ declare _GO_INJECT_MODULE_PATH="$_GO_INJECT_MODULE_PATH" else _@go.run_command_script "$__go_cmd_path" "${__go_argv[@]}" fi + + return "$_GO_EC_OK" } _@go.source_builtin() { local c="$1" shift . "$_GO_CORE_DIR/libexec/$c" + + return "$_GO_EC_OK" } _@go.run_plugin_command_script() { @@ -358,6 +364,8 @@ _@go.run_plugin_command_script() { _@go.set_search_paths _@go.run_command_script "$__go_cmd_path" "${__go_argv[@]}" + + return "$_GO_EC_OK" } _@go.run_command_script() { @@ -399,6 +407,8 @@ _@go.run_command_script() { fi "$interpreter" "$cmd_path" "$@" fi + + return "$_GO_EC_OK" } _@go.set_scripts_dir() { @@ -419,6 +429,7 @@ _@go.set_scripts_dir() { return "$_GO_EC_NOPERM" fi _GO_SCRIPTS_DIR="$scripts_dir" + return "$_GO_EC_OK" } _@go.set_scripts_dir "$@" && rc=0 || rc="$?" diff --git a/go-template b/go-template index fe51f57..2e54f3c 100755 --- a/go-template +++ b/go-template @@ -57,7 +57,7 @@ download_go_script_bash_tarball() { if [[ "$protocol" == "$url" ]]; then printf 'GO_SCRIPT_BASH_DOWNLOAD_URL has no protocol: %s\n' "$url" >&2 - return 1 + return "$_GO_EC_CONFIG" elif [[ "$(git --version)" =~ windows && "$protocol" == 'file' ]]; then url="file://$(cygpath -m "${url#file://}")" fi @@ -74,28 +74,28 @@ download_go_script_bash_tarball() { download_cmd=(wget -O - "$url") else printf "Failed to find cURL, wget, or fetch\n" >&2 - return 1 + return "$_GO_EC_DEPMISS" fi if ! command -v tar >/dev/null; then printf "Failed to find tar\n" >&2 - return 1 + return "$_GO_EC_DEPMISS" fi printf "Downloading framework from '%s'...\n" "$url" if ! "${download_cmd[@]}" | tar -xzf - || [[ "${PIPESTATUS[0]}" -ne '0' ]]; then printf "Failed to download from '%s'.\n" "$url" >&2 - return 1 + return "$_GO_EC_NOTFND" elif [[ ! -d "$core_dir_parent" ]] && ! mkdir -p "$core_dir_parent" ; then printf "Failed to create scripts dir '%s'\n" "$core_dir_parent" >&2 rm -rf "$unpacked_dir" - return 1 + return "$_GO_EC_CANTCREAT" elif ! mv "$unpacked_dir" "$GO_SCRIPT_BASH_CORE_DIR"; then printf "Failed to install downloaded directory in '%s'\n" \ "$GO_SCRIPT_BASH_CORE_DIR" >&2 rm -rf "$unpacked_dir" - return 1 + return "$_GO_EC_CANTCREAT" fi printf "Download of '%s' successful.\n\n" "$url" } @@ -106,7 +106,7 @@ git_clone_go_script_bash() { -b "$GO_SCRIPT_BASH_VERSION" "$GO_SCRIPT_BASH_REPO_URL" \ "$GO_SCRIPT_BASH_CORE_DIR"; then printf "Failed to clone '%s'; aborting.\n" "$GO_SCRIPT_BASH_REPO_URL" >&2 - return 1 + return "$_GO_EC_GENERR" fi printf "Clone of '%s' successful.\n\n" "$GO_SCRIPT_BASH_REPO_URL" } @@ -115,7 +115,7 @@ if [[ ! -e "$GO_SCRIPT_BASH_CORE_DIR/go-core.bash" ]]; then if ! download_go_script_bash_tarball; then printf "Using git clone as fallback\n" if ! git_clone_go_script_bash; then - exit 1 + exit "$_GO_EC_GENERR" fi fi fi diff --git a/lib/existence b/lib/existence index 80d4366..f183681 100644 --- a/lib/existence +++ b/lib/existence @@ -25,10 +25,15 @@ # Arguments: # label: Label describing the type of file # file_path: Path to the file to check +# +# Returns: +# _GO_EC_OK if file exists, _GO_EC_NOTFND otherwise @go.check_file_exists() { if [[ ! -e "$2" ]]; then @go.printf "%s doesn't exist: %s\n" "$1" "$2" >&2 - return 1 + return "$_GO_EC_NOTFND" + else + return "$_GO_EC_OK" fi } @@ -37,10 +42,15 @@ # Arguments: # label: Label describing the type of file # file_path: Path to the file to check +# +# Returns: +# _GO_EC_OK if file exists and is readable, _GO_EC_GENERR otherwise @go.check_file_readable() { if [[ ! -r "$2" ]]; then @go.printf "%s doesn't exist or isn't readable: %s\n" "$1" "$2" >&2 - return 1 + return "$_GO_EC_GENERR" + else + return "$_GO_EC_OK" fi } @@ -54,18 +64,18 @@ # ...: List of commands from which to select the first available # # Returns: -# Zero if any of the commands are installed, nonzero otherwise +# _GO_EC_OK if any of the commands are installed, _GO_EC_NOTFND otherwise @go.pick_command() { local __go_pick_cmd for __go_pick_cmd in "${@:2}"; do if command -v "$__go_pick_cmd" >/dev/null; then printf -v "$1" -- '%s' "$__go_pick_cmd" - return + return "$_GO_EC_OK" fi done @go.printf 'None of the following commands were found on the system:\n' >&2 printf ' %s\n' "${@:2}" >&2 - return 1 + return "$_GO_EC_NOTFND" } # Checks whether a required command is installed on the system. @@ -78,11 +88,13 @@ # err_msg: Name of the command or other info to use in the error message # # Returns: -# Zero if the command is installed, nonzero otherwise +# _GO_EC_OK if the command is installed, _GO_EC_DEPMISS otherwise @go.check_command_installed() { - if ! command -v "$1" >/dev/null; then + if command -v "$1" >/dev/null; then + return "$_GO_EC_OK" + else @go.printf 'Please install %s on your system and try again.\n' \ "${2:-$1}" >&2 - return 1 + return "$_GO_EC_DEPMISS" fi } diff --git a/lib/internal/sysexits b/lib/internal/sysexits index 369c900..009363d 100644 --- a/lib/internal/sysexits +++ b/lib/internal/sysexits @@ -7,7 +7,7 @@ declare -r -x -i _GO_EC_USAGE=_GO_EC_OFFSET+64 declare -r -x -i _GO_EC_DATAERR=_GO_EC_OFFSET+65 declare -r -x -i _GO_EC_NOINPUT=_GO_EC_OFFSET+66 declare -r -x -i _GO_EC_BADFRMT=_GO_EC_OFFSET+67 -declare -r -x -i _GO_EC_NOHOST=_GO_EC_OFFSET+68 +declare -r -x -i _GO_EC_NOTFND=_GO_EC_OFFSET+68 declare -r -x -i _GO_EC_UNAVAILABLE=_GO_EC_OFFSET+69 declare -r -x -i _GO_EC_GENERR=_GO_EC_OFFSET+70 declare -r -x -i _GO_EC_SYSERR=_GO_EC_OFFSET+71 diff --git a/scripts/changes b/scripts/changes index f08d04e..d888a80 100755 --- a/scripts/changes +++ b/scripts/changes @@ -17,10 +17,10 @@ _changes() { # Tab completions local word_index="$2" if [[ "$word_index" -gt 1 ]]; then - return 1 + return "$_GO_EC_GENERR" fi git tag - return + return "$_GO_EC_OK" fi local start_ref="$1" @@ -28,10 +28,10 @@ _changes() { if [[ -z "$start_ref" ]]; then echo "Start ref not specified." >&2 - return 1 + return "$_GO_EC_USAGE" elif [[ -z "$end_ref" ]]; then echo "End ref not specified." >&2 - return 1 + return "$_GO_EC_USAGE" fi git log '--pretty=format:%h %an <%ae>%n %s%n' \ From c95b6a31018a82c8aaff0dddf4f8b968eb59fab7 Mon Sep 17 00:00:00 2001 From: Nikolaos Kakouros Date: Fri, 19 Jan 2018 14:22:49 +0100 Subject: [PATCH 04/16] Comments out unused lines --- lib/internal/sysexits | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/internal/sysexits b/lib/internal/sysexits index 009363d..7c1a4dc 100644 --- a/lib/internal/sysexits +++ b/lib/internal/sysexits @@ -14,8 +14,8 @@ declare -r -x -i _GO_EC_SYSERR=_GO_EC_OFFSET+71 declare -r -x -i _GO_EC_DEPMISS=_GO_EC_OFFSET+72 declare -r -x -i _GO_EC_CANTCREAT=_GO_EC_OFFSET+73 declare -r -x -i _GO_EC_IOERR=_GO_EC_OFFSET+74 -declare -r -x -i _GO_EC_ -declare -r -x -i _GO_EC_ +#declare -r -x -i _GO_EC_ +#declare -r -x -i _GO_EC_ declare -r -x -i _GO_EC_NOPERM=_GO_EC_OFFSET+77 declare -r -x -i _GO_EC_CONFIG=_GO_EC_OFFSET+78 declare -r -x -i _GO_EC_MAX=_GO_EC_OFFSET+78 From fbfc8bee13fe630a63b5efa489c530bb441cfb1a Mon Sep 17 00:00:00 2001 From: Nikolaos Kakouros Date: Fri, 19 Jan 2018 16:05:33 +0100 Subject: [PATCH 05/16] Removes some overzealous returns and converts some more --- go-core.bash | 6 ------ lib/complete | 9 ++++++++- lib/internal/argv | 14 ++++++++++---- libexec/aliases | 16 ++++++++-------- libexec/complete | 10 +++++----- 5 files changed, 31 insertions(+), 24 deletions(-) diff --git a/go-core.bash b/go-core.bash index 6defdd8..28d2ab5 100755 --- a/go-core.bash +++ b/go-core.bash @@ -352,8 +352,6 @@ _@go.source_builtin() { local c="$1" shift . "$_GO_CORE_DIR/libexec/$c" - - return "$_GO_EC_OK" } _@go.run_plugin_command_script() { @@ -364,8 +362,6 @@ _@go.run_plugin_command_script() { _@go.set_search_paths _@go.run_command_script "$__go_cmd_path" "${__go_argv[@]}" - - return "$_GO_EC_OK" } _@go.run_command_script() { @@ -407,8 +403,6 @@ _@go.run_command_script() { fi "$interpreter" "$cmd_path" "$@" fi - - return "$_GO_EC_OK" } _@go.set_scripts_dir() { diff --git a/lib/complete b/lib/complete index 50f492a..6414a38 100644 --- a/lib/complete +++ b/lib/complete @@ -28,7 +28,12 @@ compgen_exit_index="$((${#compreply[@]} - 1))" - if [[ "${compreply[$compgen_exit_index]}" -ne '0' ]]; then + if [[ "${compreply[$compgen_exit_index]}" -eq '1' ]]; then + return "$_GO_EC_NOTFND" + elif [[ "${compreply[$compgen_exit_index]}" -eq '2' ]]; then + return "$_GO_EC_USAGE" + elif [[ "${compreply[$compgen_exit_index]}" -ne '0' ]]; then + # probably never occurs return "${compreply[$compgen_exit_index]}" fi unset "compreply[$compgen_exit_index]" @@ -77,4 +82,6 @@ fi done done + + return "$_GO_EC_OK" } diff --git a/lib/internal/argv b/lib/internal/argv index 296ad20..64684bd 100644 --- a/lib/internal/argv +++ b/lib/internal/argv @@ -6,8 +6,10 @@ _@go.check_flag_has_no_arguments() { if [[ "$#" -ne 0 ]]; then echo "ERROR: $flag takes no arguments" >&2 - return 1 + return "$_GO_EC_USAGE" fi + + return "$_GO_EC_OK" } _@go.check_flag_has_one_argument() { @@ -16,16 +18,20 @@ _@go.check_flag_has_one_argument() { if [[ "$#" -eq 0 ]]; then echo "ERROR: no argument given after $flag" >&2 - return 1 + return "$_GO_EC_USAGE" elif [[ "$#" -ne 1 ]]; then echo "ERROR: only one argument should follow $flag" >&2 - return 1 + return "$_GO_EC_USAGE" fi + + return "$_GO_EC_OK" } _@go.check_argv_empty_if_no_flags() { if [[ "$#" -ne '0' ]]; then echo 'ERROR: with no flag specified, the argument list should be empty' >&2 - return 1 + return "$_GO_EC_USAGE" fi + + return "$_GO_EC_OK" } diff --git a/libexec/aliases b/libexec/aliases index ecfbbcd..2836527 100755 --- a/libexec/aliases +++ b/libexec/aliases @@ -31,14 +31,14 @@ _@go.aliases() { for c in "${_GO_ALIAS_CMDS[@]}"; do echo "$c" done - return + return "$_GO_EC_OK" elif [[ "$1" == '--complete' ]]; then # Tab completions local word_index="$2" if [[ "$word_index" -eq 0 ]]; then echo "--exists" fi - return + return "$_GO_EC_OK" fi . "$_GO_CORE_DIR/lib/internal/argv" @@ -49,17 +49,17 @@ _@go.aliases() { flag="${1#--}" shift if ! _@go.check_flag_has_one_argument "--$flag" "$@"; then - return 1 + return "$_GO_EC_USAGE" fi ;; -*) @go.printf "ERROR: unknown flag: $1\n" >&2 - return 1 + return "$_GO_EC_USAGE" ;; esac if [[ -z "$flag" ]] && ! _@go.check_argv_empty_if_no_flags "$@"; then - return 1 + return "$_GO_EC_USAGE" fi # Help filter @@ -67,7 +67,7 @@ _@go.aliases() { local pattern='{{_GO_ALIAS_CMDS}}' local replacement="${_GO_ALIAS_CMDS[@]}" echo "${1//$pattern/$replacement}" - return + return "$_GO_EC_OK" fi for c in "${_GO_ALIAS_CMDS[@]}"; do @@ -84,10 +84,10 @@ _@go.aliases() { "\"$_GO_CMD env\" to set up your shell environment." fi fi - return + return "$_GO_EC_OK" done - return 1 + return "$_GO_EC_NOTFND" } _@go.aliases "$@" diff --git a/libexec/complete b/libexec/complete index 9de742b..a80c4aa 100755 --- a/libexec/complete +++ b/libexec/complete @@ -87,29 +87,29 @@ _@go.complete_args() { @go.compgen -W "$(_@go.complete_top_level_commands)" -- "$cmd_name" ;; esac - return + return "$_GO_EC_OK" fi case "$cmd_name" in cd|pushd) @go.compgen -d -- "$word" - return + return "$_GO_EC_OK" ;; edit|run) @go.compgen -f -- "$word" - return + return "$_GO_EC_OK" ;; -h|-help|--help) cmd_name='help' ;; -*|unenv) - return 1 + return "$_GO_EC_GENERR" ;; esac if _@go.source_builtin 'aliases' --exists "$cmd_name"; then @go.compgen -f -- "$word" - return + return "$_GO_EC_OK" fi unset 'args[0]' From 0053a91c02218e153d434e2f5dbe98ef542fcaaa Mon Sep 17 00:00:00 2001 From: Nikolaos Kakouros Date: Fri, 19 Jan 2018 16:41:10 +0100 Subject: [PATCH 06/16] Removes more overzealous returns and converts some more --- go-core.bash | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/go-core.bash b/go-core.bash index 28d2ab5..ca88360 100755 --- a/go-core.bash +++ b/go-core.bash @@ -344,8 +344,6 @@ declare _GO_INJECT_MODULE_PATH="$_GO_INJECT_MODULE_PATH" else _@go.run_command_script "$__go_cmd_path" "${__go_argv[@]}" fi - - return "$_GO_EC_OK" } _@go.source_builtin() { @@ -427,8 +425,12 @@ _@go.set_scripts_dir() { } _@go.set_scripts_dir "$@" && rc=0 || rc="$?" +<<<<<<< Updated upstream if [[ "$rc" -ne 0 ]]; then +======= +if [[ "$rc" -ne "$_GO_EC_OK" ]]; then +>>>>>>> Stashed changes exit "$rc" elif [[ -z "$COLUMNS" ]]; then # On Travis, $TERM is set to 'dumb', but `tput cols` still fails. From 603fd1e8ef0b3ddb8f7964523a50f8f44cce22be Mon Sep 17 00:00:00 2001 From: Nikolaos Kakouros Date: Fri, 19 Jan 2018 21:28:37 +0100 Subject: [PATCH 07/16] More places --- lib/subcommands | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/subcommands b/lib/subcommands index 5b731ef..68f34d4 100644 --- a/lib/subcommands +++ b/lib/subcommands @@ -19,14 +19,14 @@ # Returns: # zero on success, nonzero on error (when `_GO_CMD_ARGV` is not empty) @go.show_subcommands() { - local result='0' + local result="$_GO_EC_OK" local out_fd='1' local cmd_name="${_GO_CMD_NAME[*]}" if [[ "${#_GO_CMD_ARGV[@]}" -ne 0 ]]; then @go.printf '"%s" is not an available subcommand of "%s".\n\n' \ "${_GO_CMD_ARGV[0]}" "$cmd_name" >&2 - result='1' + result="$_GO_EC_USAGE" out_fd='2' fi From 7e8da46c037115287be7db588daf76fe895501ab Mon Sep 17 00:00:00 2001 From: Nikolaos Kakouros Date: Fri, 19 Jan 2018 21:39:58 +0100 Subject: [PATCH 08/16] Resolves conflict --- go-core.bash | 4 ---- 1 file changed, 4 deletions(-) diff --git a/go-core.bash b/go-core.bash index ca88360..b8e5d50 100755 --- a/go-core.bash +++ b/go-core.bash @@ -425,12 +425,8 @@ _@go.set_scripts_dir() { } _@go.set_scripts_dir "$@" && rc=0 || rc="$?" -<<<<<<< Updated upstream -if [[ "$rc" -ne 0 ]]; then -======= if [[ "$rc" -ne "$_GO_EC_OK" ]]; then ->>>>>>> Stashed changes exit "$rc" elif [[ -z "$COLUMNS" ]]; then # On Travis, $TERM is set to 'dumb', but `tput cols` still fails. From 5b43b3037b579311e0b36da54600942588dc2f19 Mon Sep 17 00:00:00 2001 From: Nikolaos Kakouros Date: Sat, 20 Jan 2018 23:58:14 +0100 Subject: [PATCH 09/16] Adds custom return codes to lib/bats-helpers --- lib/bats/helpers | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/bats/helpers b/lib/bats/helpers index 76a281a..c0d7f85 100644 --- a/lib/bats/helpers +++ b/lib/bats/helpers @@ -208,7 +208,7 @@ skip_if_none_present_on_system() { test_join() { if [[ ! "$2" =~ ^[[:alpha:]_][[:alnum:]_]*$ ]]; then printf '"%s" is not a valid variable identifier.\n' "$2" >&2 - return 1 + return "$_GO_EC_GENERR" fi local IFS="$1" @@ -268,7 +268,7 @@ test_break_after_num_iterations() { printf 'The argument to %s must be a positive integer at:\n' "$FUNCNAME" >&2 __tbani_do_exit='true' elif [[ -z "$TEST_DEBUG" ]]; then - return + return "$_GO_EC_OK" else printf -v "$__tbani_var" -- '%d' "$((${!__tbani_var} + 1))" if [[ "${!__tbani_var}" -eq "$__tbani_num_iterations" ]]; then @@ -287,7 +287,7 @@ test_break_after_num_iterations() { for __tbani_caller_var in "${@:2}"; do printf -- '%s: %s\n' "$__tbani_caller_var" "${!__tbani_caller_var}" >&2 done - exit 1 + exit "$_GO_EC_GENERR" fi } export -f test_break_after_num_iterations @@ -551,7 +551,7 @@ __create_bats_test_script() { if [[ -z "$script_path" ]]; then echo "No test script name or path specified" >&2 - exit 1 + exit "$_GO_EC_USAGE" elif [[ "$script_dir" == "$script_path" ]]; then script_dir='' fi From 3bd06b4017287e04210dfd0bfa7bc6fcfc0b7b5a Mon Sep 17 00:00:00 2001 From: Nikolaos Kakouros Date: Sun, 21 Jan 2018 03:27:32 +0100 Subject: [PATCH 10/16] A whole bunch of custom return codes --- go-core.bash | 2 +- lib/bats-main | 4 +- lib/diff | 4 +- lib/file | 22 +++++------ lib/fileutil | 13 +++++-- lib/internal/command_descriptions | 22 ++++++----- lib/internal/commands | 2 +- lib/internal/complete | 8 ++-- lib/internal/path | 10 ++--- lib/internal/set-search-paths | 2 +- lib/internal/sysexits | 61 +++++++++++++++++++++++++++++-- lib/internal/use | 6 +-- lib/kcov-ubuntu | 16 ++++---- lib/log | 38 ++++++++++++------- lib/path | 10 ++--- lib/platform | 4 +- lib/prompt | 15 ++++---- lib/testing/log | 6 +-- lib/testing/stack-trace | 16 ++++---- lib/validation | 16 ++++++-- libexec/builtins | 28 +++++++------- libexec/commands | 30 ++++++++------- libexec/env | 12 +++--- libexec/get.d/file | 18 ++++----- libexec/glob | 40 ++++++++++---------- libexec/help | 11 +++--- libexec/modules | 40 +++++++++++--------- libexec/new | 54 ++++++++++++++------------- tests/modules/use.bats | 2 +- 29 files changed, 302 insertions(+), 210 deletions(-) diff --git a/go-core.bash b/go-core.bash index b8e5d50..06e52d0 100755 --- a/go-core.bash +++ b/go-core.bash @@ -59,7 +59,7 @@ cd "${0%/*}" || exit "$_GO_EC_GENERR" declare -x _GO_ROOTDIR="$PWD" if [[ "${BASH_SOURCE[0]:0:1}" != '/' ]]; then - cd "$__go_orig_dir/${BASH_SOURCE[0]%/*}" || exit 1 + cd "$__go_orig_dir/${BASH_SOURCE[0]%/*}" || exit "$_GO_EC_GENERR" else cd "${BASH_SOURCE[0]%/*}" || exit "$_GO_EC_GENERR" fi diff --git a/lib/bats-main b/lib/bats-main index 74ec0b1..86526e1 100644 --- a/lib/bats-main +++ b/lib/bats-main @@ -120,7 +120,7 @@ fi if [[ "$1" == '--complete' ]]; then shift @go.bats_tab_completion "$@" - return + return "$_GO_EC_OK" fi @go.bats_clone @@ -180,7 +180,7 @@ fi if [[ "$word_index" -eq '0' ]]; then echo '--coverage' '--edit' '--list' if [[ "${1:0:1}" == '-' ]]; then - return + return "$_GO_EC_OK" fi fi @go 'glob' '--complete' "$test_word_index" "${_GO_BATS_GLOB_ARGS[@]}" "$@" diff --git a/lib/diff b/lib/diff index c6f3271..7de34c9 100644 --- a/lib/diff +++ b/lib/diff @@ -61,9 +61,9 @@ export _GO_DIFF_EDITOR="${_GO_DIFF_EDITOR:-vimdiff}" "$_GO_DIFF_EDITOR" "$lhs" "$rhs" fi else - return '0' + return "$_GO_EC_OK" fi - return '1' + return "$_GO_EC_SIGN1" } # Log differences between two directory structures diff --git a/lib/file b/lib/file index a0fc50d..e94c0de 100644 --- a/lib/file +++ b/lib/file @@ -27,7 +27,7 @@ if [[ ! "$_GO_MAX_FILE_DESCRIPTORS" =~ $__GO_FILE_DESCRIPTOR_PATTERN || printf "_GO_MAX_FILE_DESCRIPTORS is %s, must be a number greater than %d.\n" \ "\"$_GO_MAX_FILE_DESCRIPTORS\"" "$__GO_START_FD" >&2 @go.print_stack_trace '2' >&2 - exit 1 + exit "$_GO_EC_CONFIG" fi . "$_GO_USE_MODULES" 'strings' 'validation' @@ -80,7 +80,7 @@ fi *) echo "Unknown mode: $mode" >&2 @go.print_stack_trace '1' >&2 - exit 1 + exit "$_GO_EC_GENERR" ;; esac @@ -89,16 +89,16 @@ fi if ! eval "exec ${i}${bash_mode}${file_path_or_fd}"; then echo "Failed to open fd $i for $file_path_or_fd in mode '$mode' at:" >&2 @go.print_stack_trace '1' >&2 - exit 1 + exit "$_GO_EC_ARGERR" fi printf -v "$fd_var_reference" -- '%s' "$i" - return + return "$_GO_EC_OK" fi done echo "No file descriptors < $_GO_MAX_FILE_DESCRIPTORS available; failed at:" \ >&2 @go.print_stack_trace '1' >&2 - exit 1 + exit "$_GO_EC_NOTFND" } # Calls `printf` on its arguments for each of a list of file descriptors. @@ -117,7 +117,7 @@ fi # ...: Arguments to pass to the `printf` builtin @go.fds_printf() { local output_fds=() - local result=0 + local result="$_GO_EC_OK" @go.split ',' "$1" 'output_fds' shift @@ -126,7 +126,7 @@ fi if [[ ! "$output_fd" =~ $__GO_FILE_DESCRIPTOR_PATTERN ]]; then echo "Invalid file descriptor value \"$output_fd\" for $FUNCNAME at:" >&2 @go.print_stack_trace '1' >&2 - exit 1 + exit "$_GO_EC_NOTFND" fi done @@ -134,7 +134,7 @@ fi if ! printf "$@" >&"$output_fd"; then echo "Failed to print to fd $output_fd at:" >&2 @go.print_stack_trace '1' >&2 - result=1 + result="$_GO_EC_IOERR" fi done return "$result" @@ -151,20 +151,20 @@ fi if [[ "$#" -eq 0 ]]; then echo "No file descriptors to close specified at:" >&2 @go.print_stack_trace '1' >&2 - return 1 + return "$_GO_EC_USAGE" fi for fd in "$@"; do if [[ ! "$fd" =~ $__GO_FILE_DESCRIPTOR_PATTERN ]]; then echo "Bad file descriptor \"$fd\" at:" >&2 @go.print_stack_trace '1' >&2 - return 1 + return "$_GO_EC_BADFRMT" elif ! eval "exec $fd>&-"; then # Believe it or not, this case seems impossible to trigger given the $fd # check above. Keeping it despite not being able to cover it with a test. echo "Failed to close file descriptor \"$fd\" at:" >&2 @go.print_stack_trace '1' >&2 - return 1 + return "$_GO_EC_GENERR" fi done } diff --git a/lib/fileutil b/lib/fileutil index 54c9b2f..a18612c 100644 --- a/lib/fileutil +++ b/lib/fileutil @@ -113,7 +113,7 @@ local __go_source_file_errors=() local src local dest - local result='0' + local result="$_GO_EC_OK" _@go.parse_copy_files_safely_args "$@" @@ -223,7 +223,7 @@ _@go.find_missing_parent_path() { __go_missing_parent="$1" if [[ ! -d "$1" ]]; then - return 1 + return "$_GO_EC_NOTFND" fi } @@ -314,7 +314,7 @@ _@go.set_source_files_for_copy_files_safely() { if [[ -n "$__go_src_dir" && "$#" -eq '0' ]]; then @go.collect_file_paths "$__go_src_dir" __go_src_files=("${__go_collected_file_paths[@]#$__go_src_dir/}") - return + return "$_GO_EC_OK" fi __go_src_dir="${__go_src_dir:-$PWD}" __go_src_files=() @@ -337,5 +337,10 @@ _@go.set_source_files_for_copy_files_safely() { __go_src_files+=("$canonical_src") fi done - return "${#__go_source_file_errors[@]}" + + if [[ "${#__go_source_file_errors[@]}" -gt 0 ]]; then + return "$_GO_EC_GENERR" + else + return "$_GO_EC_OK" + fi } diff --git a/lib/internal/command_descriptions b/lib/internal/command_descriptions index 11961c8..5266b19 100644 --- a/lib/internal/command_descriptions +++ b/lib/internal/command_descriptions @@ -20,7 +20,7 @@ _@go.format_summary() { if [[ "${#summary}" -le "$COLUMNS" ]]; then printf "$summary" - return + return "$_GO_EC_OK" fi # Pad 4 spaces from first format string, plus 2 more to indent wrapped lines. @@ -30,7 +30,7 @@ _@go.format_summary() { if [[ "$padding_size" -ge "$((COLUMNS/2))" ]]; then printf "$summary" - return + return "$_GO_EC_OK" fi printf -v padding "%-${padding_size}s" '' @@ -71,8 +71,9 @@ _@go.command_summary() { local __go_cmd_name __go_cmd_desc='' - if ! _@go.check_command_path_and_parse_command_name "$cmd_path"; then - return 1 + _@go.check_command_path_and_parse_command_name "$cmd_path" && ec=0 || ec="$?" + if [[ "$ec" -ne 0 ]]; then + return "$ec" fi local line @@ -92,7 +93,7 @@ _@go.command_summary() { if [[ "$?" -ne '0' ]]; then echo "ERROR: problem reading $cmd_path" >&2 - return 1 + return "$_GO_EC_GENERR" elif [[ -z "$__go_cmd_desc" ]]; then __go_cmd_desc='No description available' fi @@ -105,8 +106,9 @@ _@go.command_description() { local __go_cmd_name __go_cmd_desc='' - if ! _@go.check_command_path_and_parse_command_name "$cmd_path"; then - return 1 + _@go.check_command_path_and_parse_command_name "$cmd_path" && ec=0 || ec="$?" + if [[ "$ec" -ne 0 ]] ; then + return "$ec" fi local line @@ -156,7 +158,7 @@ _@go.command_description() { if [[ "$?" -ne '0' ]]; then echo "ERROR: problem reading $cmd_path" >&2 - return 1 + return "$_GO_EC_GENERR" elif [[ -z "$__go_cmd_desc" ]]; then __go_cmd_desc='No description available' else @@ -176,10 +178,10 @@ _@go.check_command_path_and_parse_command_name() { if [[ -z "$cmd_path" ]]; then echo "ERROR: no command script specified" >&2 - return 1 + return "$_GO_EC_ARGERR" elif [[ ! -e "$cmd_path" ]]; then echo "ERROR: command script \"$cmd_path\" does not exist" >&2 - return 1 + return "$_GO_EC_NOTFND" elif [[ "$cmd_path" =~ $subcommand_pattern ]]; then __go_cmd_name="${BASH_REMATCH[1]//.d\// }" else diff --git a/lib/internal/commands b/lib/internal/commands index 46f088f..b72f2f1 100644 --- a/lib/internal/commands +++ b/lib/internal/commands @@ -60,7 +60,7 @@ _@go.find_commands() { done if [[ "${#__go_command_scripts[@]}" -eq '0' ]]; then - return 1 + return "$_GO_EC_NOTFND" elif [[ -z "$_GO_STANDALONE" ]]; then __go_command_scripts=("${__go_command_scripts[@]#$_GO_ROOTDIR/}") else diff --git a/lib/internal/complete b/lib/internal/complete index a187dd3..64ac1e9 100644 --- a/lib/internal/complete +++ b/lib/internal/complete @@ -22,7 +22,7 @@ _@go.complete_top_level_commands() { # return status. _@go.complete_command_path() { if [[ "$#" -eq 0 ]]; then - return 1 + return "$_GO_EC_SIGN1" fi __go_complete_word_index="$1" @@ -31,16 +31,16 @@ _@go.complete_command_path() { if [[ "$#" -le 1 || "$__go_complete_word_index" -eq '0' ]]; then _@go.complete_top_level_commands - return 1 + return "$_GO_EC_SIGN1" elif ! _@go.set_command_path_and_argv "$@"; then - return 1 + return "$_GO_EC_SIGN1" fi (( __go_complete_word_index -= ($# - ${#__go_argv[@]}) )) if [[ "$__go_complete_word_index" -lt '0' ]]; then # This (sub)command itself is the completion target. echo "${__go_cmd_path##*/}" - return 1 + return "$_GO_EC_SIGN1" elif [[ "$__go_complete_word_index" -eq '0' ]]; then # Complete subcommand scripts. diff --git a/lib/internal/path b/lib/internal/path index e9a5075..063401f 100644 --- a/lib/internal/path +++ b/lib/internal/path @@ -10,7 +10,7 @@ _@go.list_available_commands() { echo "ERROR: No commands available in:" >&2 local IFS=$'\n' echo "${@/#/ }" >&2 - return 1 + return "$_GO_EC_NOTFND" fi echo "Available commands are:" @@ -20,7 +20,7 @@ _@go.list_available_commands() { _@go.set_command_path_and_argv() { if [[ "$#" -eq '0' || -z "$*" ]]; then - return 1 + return "$_GO_EC_ARGERR" fi local cmd_args=("$@") @@ -38,14 +38,14 @@ _@go.set_command_path_and_argv() { break elif [[ -e "$try_path" ]]; then @go.printf "$try_path is not an executable script\n" >&2 - return 1 + return "$_GO_EC_CONFIG" fi done if [[ -z "$cmd_path" ]]; then printf "Unknown command: ${cmd_name}\n\n" >&2 _@go.list_available_commands "${_GO_SEARCH_PATHS[@]}" >&2 - return 1 + return "$_GO_EC_USAGE" fi local cmd_arg_index=1 @@ -63,7 +63,7 @@ _@go.set_command_path_and_argv() { break elif [[ ! (-f "$try_path" && -x "$try_path") ]]; then @go.printf "$try_path is not an executable script\n" >&2 - return 1 + return "$_GO_EC_CONFIG" fi __go_cmd_name+=("$arg") diff --git a/lib/internal/set-search-paths b/lib/internal/set-search-paths index b540b39..8b61fec 100644 --- a/lib/internal/set-search-paths +++ b/lib/internal/set-search-paths @@ -12,7 +12,7 @@ _@go.set_search_paths_add_plugin_paths() { fi done fi - return 1 + return "$_GO_EC_SIGN1" } _@go.set_search_paths() { diff --git a/lib/internal/sysexits b/lib/internal/sysexits index 7c1a4dc..39b9264 100644 --- a/lib/internal/sysexits +++ b/lib/internal/sysexits @@ -1,21 +1,74 @@ #! /bin/bash declare -r -x -i _GO_EC_OFFSET=0 +# This is useful in case go-script-bash is used together with other frameworks +# or commands that overlap in their exit codes and the user wants to +# distinguish among them. + declare -r -x -i _GO_EC_OK=0 -declare -r -x -i _GO_EC_BASE=_GO_EC_OFFSET+64 + declare -r -x -i _GO_EC_USAGE=_GO_EC_OFFSET+64 +# The application was called with an invalid option, parameter, command, etc. +# This error refers to end-user supplied input to the application, not wrong +# function arguments, etc. + declare -r -x -i _GO_EC_DATAERR=_GO_EC_OFFSET+65 +# ??? + declare -r -x -i _GO_EC_NOINPUT=_GO_EC_OFFSET+66 +# Some input was expected but none was given. This refers to either expected +# input from the user (eg via a prompt) or command/function input that is +# empty (eg an empty file). + declare -r -x -i _GO_EC_BADFRMT=_GO_EC_OFFSET+67 +# An argument or a file is not in the format expected. This is used in +# validation errors or wrongly formatted files (eg scipts missing the shebang). +# For bad arguments to functions, _GO_EC_ARGERR should be used. + declare -r -x -i _GO_EC_NOTFND=_GO_EC_OFFSET+68 +# A resource was not found. "Resource" might refer to some file/folder on the +# filesystem. This return code should also be used by functions that perform a +# search for the case that no result was found. + declare -r -x -i _GO_EC_UNAVAILABLE=_GO_EC_OFFSET+69 +# ??? + declare -r -x -i _GO_EC_GENERR=_GO_EC_OFFSET+70 -declare -r -x -i _GO_EC_SYSERR=_GO_EC_OFFSET+71 +# A general error that is not covered by the other exit codes. + +declare -r -x -i _GO_EC_ARGERR=_GO_EC_OFFSET+71 +# A function was passed an argument that is invalid. See also _GO_EC_BADFRMT. + declare -r -x -i _GO_EC_DEPMISS=_GO_EC_OFFSET+72 +# A required program is missing. + declare -r -x -i _GO_EC_CANTCREAT=_GO_EC_OFFSET+73 +# An operation failed to create a target. It can be used in filesystem +# operations like `mv` and `tar x` or in network requests. + declare -r -x -i _GO_EC_IOERR=_GO_EC_OFFSET+74 -#declare -r -x -i _GO_EC_ -#declare -r -x -i _GO_EC_ +# An input/output operation failed. Here, IO is defined loosely. Eg writing to +# the console failed. + +declare -r -x -i _GO_EC_SIGN1=_GO_EC_OFFSET+75 +declare -r -x -i _GO_EC_SIGN2=_GO_EC_OFFSET+76 +# These should not be used as error codes. If a function should return two or +# three different return values to signal two or three different cases, these +# _GO_EC_OK should be used to signal the first, most common or expected one and +# these two signals the rest. Eg, `@go.file_diff` returns _GO_EC_OK if the +# supplied files are the same or _GO_EC_SIGN1 if not (in both cases, there is no +# actual error). + declare -r -x -i _GO_EC_NOPERM=_GO_EC_OFFSET+77 +# The user running the script does not have permission to perform an operation, +# either locally or over the network. + declare -r -x -i _GO_EC_CONFIG=_GO_EC_OFFSET+78 +# There is an issue with the configuration of either the system, go-script or a +# network resource. Eg, an environment variable is missing, a set parameter +# exceeds a maximum value, etc. + +declare -r -x -i _GO_EC_BASE=_GO_EC_OFFSET+64 declare -r -x -i _GO_EC_MAX=_GO_EC_OFFSET+78 +# These are useful in checking whether an exit code belongs to go-script's +# exit codes. diff --git a/lib/internal/use b/lib/internal/use index a5ee0a9..a8a2615 100644 --- a/lib/internal/use +++ b/lib/internal/use @@ -87,7 +87,7 @@ _@go.find_module() { if [[ -n "$_GO_INJECT_MODULE_PATH" ]]; then __go_module_file="$_GO_INJECT_MODULE_PATH/$__go_module_name" if [[ -f "$__go_module_file" ]]; then - return + return "$_GO_EC_OK" fi fi __go_module_file="$_GO_CORE_DIR/lib/$__go_module_name" @@ -135,7 +135,7 @@ _@go.use_modules() { if ! _@go.find_module; then @go.printf 'ERROR: Module %s not found at:\n' "$__go_module_name" >&2 @go.print_stack_trace 1 >&2 - exit 1 + exit "$_GO_EC_NOTFND" fi # If we found the module in our project, but we're installed as a plugin, @@ -176,7 +176,7 @@ _@go.use_modules() { @go.printf 'ERROR: Failed to import %s module from %s at:\n' \ "$__go_module_name" "$__go_module_file" >&2 @go.print_stack_trace 1 >&2 - exit 1 + exit "$_GO_EC_IOERR" fi done } diff --git a/lib/kcov-ubuntu b/lib/kcov-ubuntu index fcd79a7..f8b453c 100644 --- a/lib/kcov-ubuntu +++ b/lib/kcov-ubuntu @@ -54,13 +54,13 @@ run_kcov() { if ! command -v apt-get >/dev/null; then @go.printf 'Coverage is only available on Linux platforms %s.\n' \ 'with apt-get' >&2 - return 1 + return "$_GO_EC_UNAVAILABLE" elif [[ -d "$coverage_dir" ]]; then @go.printf '%s %s\n' "The $coverage_dir directory already exists." \ 'Please move or remove this directory first.' >&2 - return 1 + return "$_GO_EC_GENERR" elif ! ( [[ -f "$kcov_path" ]] || __clone_and_build_kcov "$kcov_dir" ); then - return 1 + return "$_GO_EC_CANTCREAT" fi local kcov_flags=("--include-pattern=$include_pattern" @@ -86,7 +86,7 @@ run_kcov() { fi else @go.printf 'kcov exited with errors.\n' - return 1 + return "$_GO_EC_GENERR" fi } @@ -105,7 +105,7 @@ __clone_and_build_kcov() { @go.printf 'Cloning kcov repository from %s...\n' "$__KCOV_URL" if ! @go get git-repo "$__KCOV_URL" "$__KCOV_VERSION" "$kcov_dir"; then - return 1 + return "$_GO_EC_GENERR" fi fi @@ -116,17 +116,17 @@ __clone_and_build_kcov() { if ! sudo apt-get install -y "${__KCOV_DEV_PACKAGES[@]}"; then @go.printf "Failed to install dev packages needed to build kcov." >&2 - return 1 + return "$_GO_EC_GENERR" fi fi @go.printf 'Building kcov...\n' if cd "$kcov_dir" >/dev/null && cmake . && make && cd - >/dev/null; then - return + return "$_GO_EC_OK" fi @go.printf 'Failed to build kcov.\n' >&2 - return 1 + return "$_GO_EC_GENERR" } __check_kcov_dev_packages_installed() { diff --git a/lib/log b/lib/log index 793a9a0..f1a04ee 100644 --- a/lib/log +++ b/lib/log @@ -223,7 +223,7 @@ readonly __GO_LOG_COMMAND_EXIT_PATTERN='^@go.log_command (exit|fatal):([0-9]+)$' @go.log() { local args=("$@") local log_level="${args[0]^^}" - local exit_status=0 + local exit_status="$_GO_EC_OK" local log_msg local stripped_log_msg local level_fd @@ -235,7 +235,7 @@ readonly __GO_LOG_COMMAND_EXIT_PATTERN='^@go.log_command (exit|fatal):([0-9]+)$' if ! _@go.log_level_index "$log_level"; then @go.log ERROR "Unknown log level $log_level; defaulting to WARN" @go.log WARN "${args[@]}" - return 1 + return "$_GO_EC_GENERR" fi if [[ "$log_level" =~ ERROR|QUIT|FATAL ]]; then @@ -305,17 +305,27 @@ readonly __GO_LOG_COMMAND_EXIT_PATTERN='^@go.log_command (exit|fatal):([0-9]+)$' @go.log_timestamp() { _@go.log_init + local ec + ec=0 + case "$__GO_LOG_TIMESTAMP_IMPL" in printf) - printf -v __go_log_timestamp "%($_GO_LOG_TIMESTAMP_FORMAT)T" - return "$?" + printf -v __go_log_timestamp "%($_GO_LOG_TIMESTAMP_FORMAT)T" && ec=0 || ec="$?" ;; date) - __go_log_timestamp="$(date "+$_GO_LOG_TIMESTAMP_FORMAT")" - return "$?" + __go_log_timestamp="$(date "+$_GO_LOG_TIMESTAMP_FORMAT")" && ec=0 || ec="$?" ;; + *) + ec=127 esac - return 1 + + if [[ "$ec" -eq 0 ]];then + return "$_GO_EC_OK" + elif [[ "$ec" -eq 127 ]]; then + return "$_GO_EC_DEPMISS" + else + return "$_GO_EC_GENERR" + fi } # Adds a new log level or updates an existing one. @@ -430,7 +440,7 @@ readonly __GO_LOG_COMMAND_EXIT_PATTERN='^@go.log_command (exit|fatal):([0-9]+)$' @go.critical_section_end() { if [[ "$__GO_LOG_CRITICAL_SECTION" -ne '0' ]]; then ((--__GO_LOG_CRITICAL_SECTION)) - return 0 + return "$_GO_EC_OK" fi } @@ -471,7 +481,7 @@ readonly __GO_LOG_COMMAND_EXIT_PATTERN='^@go.log_command (exit|fatal):([0-9]+)$' @go.log RUN "$cmd_string" if [[ -n "$_GO_DRY_RUN" ]]; then - return + return "$_GO_EC_OK" fi local __go_log_level_file_descriptors=('1') @@ -607,7 +617,7 @@ _@go.log_init() { local run_fd if [[ -n "$__GO_LOG_INIT" ]]; then - return + return "$_GO_EC_OK" fi readonly __GO_LOG_INIT='done' @@ -701,10 +711,10 @@ _@go.log_level_index() { for ((i=0; i != "${#_GO_LOG_LEVELS[@]}"; ++i)); do if [[ "${_GO_LOG_LEVELS[$i]}" == "$1" ]]; then __go_log_level_index="$i" - return + return "$_GO_EC_OK" fi done - return 1 + return "$_GO_EC_NOTFND" } # Checks whether the log message is of sufficient priority to emit @@ -752,11 +762,11 @@ _@go.log_load() { if [[ "${#__GO_LOG_LEVELS_FORMAT_CODES[@]}" != "$num_levels" ]]; then echo "Should have $num_levels log level format codes," \ "only have ${#__GO_LOG_LEVELS_FORMAT_CODES[@]}" >&2 - exit 1 + exit "$_GO_EC_CONFIG" elif [[ "${#__GO_LOG_LEVELS_FILE_DESCRIPTORS[@]}" != "$num_levels" ]]; then echo "Should have $num_levels log level file descriptors," \ "only have ${#__GO_LOG_LEVELS_FILE_DESCRIPTORS[@]}" >&2 - exit 1 + exit "$_GO_EC_CONFIG" fi } diff --git a/lib/path b/lib/path index a63a7dd..260b643 100644 --- a/lib/path +++ b/lib/path @@ -145,19 +145,19 @@ for current in "${@:2}"; do if [[ -e "$current" ]] && ! "$operation" "$current"; then - return 1 + return "$_GO_EC_GENERR" elif [[ -d "$current" ]]; then if [[ -n "$do_bfs" ]]; then bfs_queue+=("$current") elif ! @go.walk_file_system "$operation" "$current"/*; then - return 1 + return "$_GO_EC_GENERR" fi fi done for current in "${bfs_queue[@]}"; do if ! @go.walk_file_system '--bfs' "$operation" "$current"/*; then - return 1 + return "$_GO_EC_GENERR" fi done } @@ -191,7 +191,7 @@ for component in "${components[@]}"; do current_path+="${component:-/}" if ! "$operation" "$current_path"; then - return 1 + return "$_GO_EC_GENERR" elif [[ -n "$component" ]]; then current_path+='/' fi @@ -257,7 +257,7 @@ # path: Current path passed in by @go.walk_path_forward _@go.realpath_impl() { if ! cd -P "$1" >/dev/null 2>&1; then - return 1 + return "$_GO_EC_GENERR" fi printf -v '__grpi_real_prefix' '%s' "$1" printf -v '__grpi_real_dir' '%s' "$PWD" diff --git a/lib/platform b/lib/platform index e749d9f..8dbc952 100644 --- a/lib/platform +++ b/lib/platform @@ -22,7 +22,7 @@ _@go.platform_os_release() { local value if [[ ! -f "$__GO_ETC_OS_RELEASE" ]]; then - return 1 + return "$_GO_EC_NOTFND" fi while read -r line; do @@ -65,7 +65,7 @@ _@go.platform_ostype() { _@go.platform() { if [[ -n "$_GO_PLATFORM_ID" ]]; then - return + return "$_GO_EC_OK" elif ! _@go.platform_os_release; then _@go.platform_ostype fi diff --git a/lib/prompt b/lib/prompt index 393a9f4..fba1ab1 100644 --- a/lib/prompt +++ b/lib/prompt @@ -60,7 +60,7 @@ if [[ -z "${!1}" && -n "$4" ]]; then @go.printf '%s\n' "$4" >&2 - return 1 + return "$_GO_EC_NOINPUT" fi } @@ -89,14 +89,15 @@ fi @go.validate_identifier_or_die 'Input prompt response variable name' "$1" - if ! @go.prompt_for_input "$@"; then - return 1 + @go.prompt_for_input "$@" && ec=0 || ec="$?" + if [[ "$ec" -ne 0 ]]; then + return "$ec" elif [[ "$or_die" == 'true' ]]; then @go.validate_input_or_die "$description" "${!1}" elif ! @go.validate_input "${!1}"; then @go.printf '"%s" is an invalid response, as it contains %s.\n' \ "${!1}" 'unescaped shell metacharacters or control operators' >&2 - return 1 + return "$_GO_EC_BADFRMT" fi } @@ -127,7 +128,7 @@ @go.printf 'Invalid `default` parameter "%s" for %s at:\n' \ "$default" "$FUNCNAME" >&2 @go.print_stack_trace '1' >&2 - exit 1 + exit "$_GO_EC_BADFRMT" ;; esac @@ -135,9 +136,9 @@ @go.read_prompt_response 'response' "$default" if [[ "$response" =~ ^[Yy]([Ee][Ss])?$ ]]; then - return 0 + return "$_GO_EC_OK" elif [[ "$response" =~ ^[Nn]([Oo])?$ ]]; then - return 1 + return "$_GO_EC_SIGN1" else if [[ -n "$response" ]]; then @go.printf '\n"%s" is an invalid response.\n' "$response" >&2 diff --git a/lib/testing/log b/lib/testing/log index e0a7ac9..432f082 100644 --- a/lib/testing/log +++ b/lib/testing/log @@ -54,7 +54,7 @@ export _GO_LOG_TIMESTAMP_FORMAT= local __go_log_level_index=0 if ! _@go.log_level_index "$label"; then printf 'Unknown log level label: %s\n' "$label" >&2 - exit 1 + exit "$_GO_EC_NOTFND" fi printf '%s' "${__GO_LOG_LEVELS_FORMATTED[$__go_log_level_index]}" restore_bats_shell_options "$?" @@ -174,7 +174,7 @@ __@go.assert_log_equals() { if ! shift 2; then printf 'ERROR: Wrong number of arguments for log line %d.\n' "$i" >&2 - return 1 + return "$_GO_EC_ARGERR" fi else expected+=("$1") @@ -205,7 +205,7 @@ __@go.parse_log_level_label() { fi if ! _@go.log_level_index "$try_level"; then - return 1 + return "$_GO_EC_NOTFND" elif [[ "$level_label" != "$try_level" ]]; then __log_level_label="$level_label" else diff --git a/lib/testing/stack-trace b/lib/testing/stack-trace index dfec99f..c9a391d 100644 --- a/lib/testing/stack-trace +++ b/lib/testing/stack-trace @@ -104,11 +104,11 @@ __@go.stack_trace_item() { if [[ -z "$function_name" ]]; then printf 'No function name specified for `%s`.\n' "${FUNCNAME[1]}" >&2 - exit 1 + exit "$_GO_EC_ARGERR" elif [[ "$function_name" =~ ^(main|source)$ && -z "$target_line" ]]; then printf 'No target line from `%s` specified for `%s`.\n' \ "$function_name" "${FUNCNAME[1]}" >&2 - exit 1 + exit "$_GO_EC_ARGERR" fi if [[ "$function_name" == 'main' || "$function_name" == 'source' ]]; then @@ -164,7 +164,7 @@ __@go.stack_trace_item() { case "$state" in SUCCESS) printf ' %s:%d %s\n' "$filepath" "$lineno" "$function_name" - return + return "$_GO_EC_OK" ;; MAIN|FOUND_FUNCTION) printf 'Line not found in `%s` from "%s": "%s"\n' \ @@ -174,7 +174,7 @@ __@go.stack_trace_item() { printf 'Function `%s` not found in "%s".\n' "$function_name" "$filepath" >&2 ;; esac - return '1' + return "$_GO_EC_NOTFND" } # Implementation for `@go.set_go_core_stack_trace_components` @@ -199,7 +199,7 @@ __@go.set_go_core_stack_trace_components() { if [[ "$stack_item" =~ $go_core_file ]]; then GO_CORE_STACK_TRACE_COMPONENTS+=("$stack_item") elif [[ "${#_GO_CORE_STACK_TRACE_COMPONENTS[@]}" -ne '0' ]]; then - return + return "$_GO_EC_OK" fi done rm "$script" "$TEST_GO_SCRIPTS_DIR/print-stack-trace" @@ -220,7 +220,7 @@ __@go.count_lines() { if [[ -z "$result_name" ]]; then printf 'No result variable specified for `%s`.\n' "${FUNCNAME[1]}" >&2 - exit 1 + exit "$_GO_EC_ARGERR" fi while read line; do @@ -238,9 +238,9 @@ __@go.count_lines() { __@go.check_file_path_specified_and_present() { if [[ -z "$1" ]]; then printf 'No file specified for `%s`.\n' "${FUNCNAME[1]}" >&2 - exit 1 + exit "$_GO_EC_ARGERR" elif [[ ! -e "$1" ]]; then printf 'Create "%s" before calling `%s`.\n' "$1" "${FUNCNAME[1]}" >&2 - exit 1 + exit "$_GO_EC_GENERR" fi } diff --git a/lib/validation b/lib/validation index 9be7e9d..61bd913 100644 --- a/lib/validation +++ b/lib/validation @@ -36,7 +36,11 @@ readonly __GO_VALID_IDENTIFIER_PATTERN='^[[:alpha:]_][[:alnum:]_]*$' # Returns: # 0 on success; nonzero on failure @go.validate_input() { - [[ ! "$1" =~ $__GO_VALIDATE_INPUT_PATTERN ]] + if [[ "$1" =~ $__GO_VALIDATE_INPUT_PATTERN ]]; then + return "$_GO_EC_BADFRMT" + else + return "$_GO_EC_OK" + fi } # Wraps `@go.validate_input` to print an error and exit on failure @@ -56,7 +60,7 @@ readonly __GO_VALID_IDENTIFIER_PATTERN='^[[:alpha:]_][[:alnum:]_]*$' "$description" "$value" "${FUNCNAME[$((skip_callers - 1))]}" \ 'unescaped shell metacharacters or control operators' >&2 @go.print_stack_trace "$skip_callers" >&2 - exit 1 + exit "$_GO_EC_BADFRMT" fi } @@ -70,7 +74,11 @@ readonly __GO_VALID_IDENTIFIER_PATTERN='^[[:alpha:]_][[:alnum:]_]*$' # Returns: # 0 on success; nonzero on failure @go.validate_identifier() { - [[ "$1" =~ $__GO_VALID_IDENTIFIER_PATTERN ]] + if [[ "$1" =~ $__GO_VALID_IDENTIFIER_PATTERN ]]; then + return "$_GO_EC_OK" + else + return "$_GO_EC_BADFRMT" + fi } # Wraps `@go.validate_identifier` to print an error and exit on failure @@ -98,6 +106,6 @@ readonly __GO_VALID_IDENTIFIER_PATTERN='^[[:alpha:]_][[:alnum:]_]*$' printf '%s "%s" for %s %s at:\n' \ "$description" "$value" "$called_func" "$err_msg" >&2 @go.print_stack_trace "$skip_callers" >&2 - exit 1 + exit "$_GO_EC_BADFRMT" fi } diff --git a/libexec/builtins b/libexec/builtins index 8cb485d..1e024bd 100755 --- a/libexec/builtins +++ b/libexec/builtins @@ -59,8 +59,10 @@ _@go.builtin_summaries() { local __go_cmd_desc for cmd_name in "${_GO_BUILTIN_CMDS[@]}"; do - if ! _@go.command_summary "$_GO_CORE_DIR/libexec/$cmd_name"; then - return 1 + + _@go.command_summary "$_GO_CORE_DIR/libexec/$cmd_name" && ec=0 || ec="$?" + if [[ "$ec" -ne 0 ]] ; then + return "$ec" fi _@go.format_summary "$cmd_name" "$__go_cmd_desc" $longest_name_len done @@ -70,14 +72,14 @@ _@go.builtins() { if [[ "$#" -eq '0' ]]; then local IFS=$'\n' echo "${_GO_BUILTIN_CMDS[*]}" - return + return "$_GO_EC_OK" elif [[ "$1" == '--complete' ]]; then # Tab completions local word_index="$2" if [[ "$word_index" -eq '0' ]]; then echo '--exists' '--summaries' fi - return + return "$_GO_EC_OK" fi . "$_GO_CORE_DIR/lib/internal/argv" @@ -88,44 +90,44 @@ _@go.builtins() { flag="$1" shift if ! _@go.check_flag_has_no_arguments "$flag" "$@"; then - return 1 + return "$_GO_EC_USAGE" fi _@go.builtin_summaries - return + return "$_GO_EC_OK" ;; --exists) flag="$1" shift if ! _@go.check_flag_has_one_argument "$flag" "$@"; then - return 1 + return "$_GO_EC_USAGE" fi for cmd_name in "${_GO_BUILTIN_CMDS[@]}"; do if [[ "$cmd_name" == "$1" ]]; then - return + return "$_GO_EC_OK" fi done - return 1 + return "$_GO_EC_NOTFND" ;; --help-filter) flag="$1" shift # Help filter if ! _@go.check_flag_has_one_argument "$flag" "$@"; then - return 1 + return "$_GO_EC_USAGE" fi local pattern='{{_GO_BUILTIN_SUMMARIES}}' local replacement="$(_@go.builtin_summaries)" echo "${1//$pattern/$replacement}" - return + return "$_GO_EC_OK" ;; -*) echo "ERROR: unknown flag: $1" - return 1 + return "$_GO_EC_USAGE" ;; esac if ! _@go.check_argv_empty_if_no_flags "$@"; then - return 1 + return "$_GO_EC_USAGE" fi } diff --git a/libexec/commands b/libexec/commands index ad65a5d..bfbf311 100755 --- a/libexec/commands +++ b/libexec/commands @@ -64,7 +64,7 @@ _@go.commands_parse_search_paths() { for search_path in "${__go_commands_search_paths[@]}"; do if [[ ! -d "$search_path" ]]; then @go.printf "Command search path %s does not exist.\n" "$search_path" >&2 - return 1 + return "$_GO_EC_NOTFND" fi done } @@ -77,7 +77,7 @@ _@go.commands_parse_argv() { ;; -*) echo "Unknown option: $1" - return 1 + return "$_GO_EC_USAGE" ;; esac @@ -86,19 +86,20 @@ _@go.commands_parse_argv() { elif [[ "$1" =~ : || -d "$1" ]]; then if [[ "$#" -ne 1 ]]; then @go.printf 'Cannot specify any arguments after search paths.\n' >&2 - return 1 + return "$_GO_EC_USAGE" elif ! _@go.commands_parse_search_paths "$1"; then - return 1 + return "$_GO_EC_NOTFND" fi else if _@go.source_builtin 'aliases' --exists "$1"; then @go.printf '%s is a shell alias.\n' "$1" >&2 - return 1 + return "$_GO_EC_GENERR" fi local __go_cmd_path - if ! _@go.set_command_path_and_argv "$@"; then - return 1 + _@go.set_command_path_and_argv "$@" && ec=0 || ec="$?" + if [[ "$ec" -ne 0 ]]; then + return "$?" fi __go_commands_search_paths=("${__go_cmd_path}.d") fi @@ -111,7 +112,7 @@ _@go.commands_tab_completions() { if [[ "$word_index" -eq '0' ]]; then echo '--paths' '--summaries' if [[ "${1:0:1}" == '-' || "$#" -gt 1 ]]; then - return + return "$_GO_EC_OK" fi fi @@ -119,13 +120,13 @@ _@go.commands_tab_completions() { shift ((--word_index)) elif [[ "$1" =~ : || -d "$1" ]]; then - return 1 + return "$_GO_EC_SIGN1" fi local args=("$@") local last_arg_index="$((${#args[@]} - 1))" if [[ "$word_index" -lt "$last_arg_index" ]]; then - return 1 + return "$_GO_EC_SIGN1" fi _@go.commands "${args[@]:0:$word_index}" } @@ -135,14 +136,15 @@ _@go.commands() { if [[ "$1" == '--complete' ]]; then shift _@go.commands_tab_completions "$@" - return + return "$_GO_EC_OK" fi local __go_commands_action="list" local __go_commands_search_paths=() - if ! _@go.commands_parse_argv "$@"; then - return 1 + _@go.commands_parse_argv "$@" && ec=0 || ec="$?" + if [[ "$ec" -ne 0 ]] ; then + return "$ec" fi . "$_GO_CORE_DIR/lib/internal/commands" @@ -152,7 +154,7 @@ _@go.commands() { local __go_longest_name_len if ! _@go.find_commands "${__go_commands_search_paths[@]}"; then - return 1 + return "$_GO_EC_NOTFND" fi case "$__go_commands_action" in diff --git a/libexec/env b/libexec/env index 22e52b4..9dc1506 100755 --- a/libexec/env +++ b/libexec/env @@ -26,7 +26,7 @@ _@go.env() { if [[ "$word_index" -eq '0' ]]; then echo '-' fi - return + return "$_GO_EC_OK" fi local go_func="$1" @@ -39,7 +39,7 @@ _@go.env() { @go.printf "%s%s\n" \ "Check $_GO_CORE_URL/tree/master/lib/env to see if an implementation " \ "has been added, or feel free to send a pull request to add it." >&2 - return 1 + return "$_GO_EC_GENERR" fi local spaces_error=('ERROR: %s must not contain spaces in order' @@ -47,7 +47,7 @@ _@go.env() { if _@go.has_spaces "$default_name"; then @go.printf "${spaces_error[*]}" "the \"$default_name\" script" >&2 - return 1 + return "$_GO_EC_CONFIG" fi if [[ -z "$go_func" ]]; then @@ -67,7 +67,7 @@ _@go.env() { @go.printf 'ERROR: %s must contain a line of the form "%s" %s%s\n' \ "$shell_impl" "$eval_pattern" "illustrating the command used to " \ "evaluate the generated shell commands." >&2 - return 1 + return "$_GO_EC_BADFRMT" fi read -r -d '' help_msg <&2 - return 1 + return "$_GO_EC_CONFIG" fi read -r -d '' env_script < "$shell_impl" diff --git a/libexec/get.d/file b/libexec/get.d/file index f6fc7a6..915d41a 100755 --- a/libexec/get.d/file +++ b/libexec/get.d/file @@ -98,7 +98,7 @@ _@go.get_file_download_command() { fi @go.printf 'Please install curl or wget before running "%s".\n' \ "${_GO_CMD_NAME[*]}" >&2 - return 1 + return "$_GO_EC_DEPMISS" ;; esac } @@ -116,27 +116,27 @@ _@go.get_file_impl() { local download_dir="$1" local filename="$2" local url="$3" - local result='0' + local result="$_GO_EC_OK" local errfile="${url##*/}.get-error" local errmsg local __go_get_file_download_cmd=() if ! _@go.get_file_download_command "$filename"; then - return 1 + return "$_GO_EC_DEPMISS" fi if [[ -n "$filename" ]]; then if [[ -f "$filename" ]]; then @go.printf 'File already exists; not overwriting: %s\n' "$filename" >&2 - return 1 + return "$_GO_EC_CANTCREAT" elif [[ ! -d "$download_dir" ]] && ! mkdir -p "$download_dir"; then @go.printf "Download dir doesn't exist and can't be created: %s\n" \ "$download_dir" >&2 - return 1 + return "$_GO_EC_CANTCREAT" elif [[ ! -w "$download_dir" ]]; then @go.printf "You don't have permission to write to download dir: %s\n" \ "$download_dir" >&2 - return 1 + return "$_GO_EC_NOPERM" fi errfile="${filename}.get-error" fi @@ -154,7 +154,7 @@ _@go.get_file_impl() { if [[ -f "$filename" ]]; then rm "$filename" fi - result='1' + result="$_GO_EC_GENERR" elif [[ -n "$filename" ]]; then @go.printf 'Downloaded "%s" as: %s\n' "$url" "$filename" @@ -177,7 +177,7 @@ _@go.get_file() { --complete) # Tab completions _@go.get_file_tab_completions "${@:2}" - return + return "$_GO_EC_OK" ;; -f) filename="$2" @@ -186,7 +186,7 @@ _@go.get_file() { if [[ "$#" -ne '1' ]]; then @go help "${_GO_CMD_NAME[@]}" >&2 - return 1 + return "$_GO_EC_USAGE" fi url="$1" diff --git a/libexec/glob b/libexec/glob index 94217f7..e9a2db8 100755 --- a/libexec/glob +++ b/libexec/glob @@ -52,7 +52,7 @@ _@go.glob_impl() { # directory (preferring the file if they share the same name). if [[ -f "$pattern$__go_glob_suffix" ]]; then __go_glob_matches+=("$pattern$__go_glob_suffix") - return + return "$_GO_EC_OK" elif [[ -d "$pattern" ]]; then pattern="${pattern%/}/*" fi @@ -63,7 +63,7 @@ _@go.glob_impl() { _@go.glob_impl_helper "$pattern" if [[ "${#__go_glob_impl_matches[@]}" -eq '0' ]]; then - return 1 + return "$_GO_EC_SIGN1" fi __go_glob_matches+=("${__go_glob_impl_matches[@]}") } @@ -119,7 +119,7 @@ _@go.glob_tab_completion_parse_argv() { if [[ "$word_index" -eq "$((i+1))" ]]; then # No completion for the GLOBIGNORE spec. - return 1 + return "$_GO_EC_SIGN1" elif [[ "${__go_glob_ignore_spec:0:1}" =~ $shell_quote ]]; then # The shell won't expand arguments or remove quotes during completion. local spec_len="${#__go_glob_ignore_spec}" @@ -130,17 +130,17 @@ _@go.glob_tab_completion_parse_argv() { if [[ "$word_index" -lt "$i" ]]; then __go_glob_complete_flags_only='true' - return + return "$_GO_EC_OK" elif [[ -d "$arg" ]]; then if [[ "$word_index" -eq "$((i+1))" ]]; then # No completion for the file suffix. - return 1 + return "$_GO_EC_SIGN1" elif [[ "$word_index" -ne "$i" ]]; then # Don't set rootdir if rootdir is the completion target argument. __go_glob_rootdir="${arg%/}" __go_glob_suffix="${args[$((i+1))]}" fi - return + return "$_GO_EC_OK" fi done } @@ -178,15 +178,15 @@ _@go.glob_tab_completion() { local __go_glob_complete_flags_only if ! _@go.glob_tab_completion_parse_argv "$@"; then - return 1 + return "$_GO_EC_SIGN1" elif [[ "$__go_glob_complete_flags_only" == 'true' ]]; then echo "${__go_glob_flags[@]}" - return + return "$_GO_EC_OK" elif [[ -z "$__go_glob_rootdir" ]]; then echo "${__go_glob_flags[@]}" . "$_GO_USE_MODULES" 'complete' @go.compgen -d -- "$__go_glob_complete_word" - return + return "$_GO_EC_OK" fi local __go_glob_matches=() @@ -195,7 +195,7 @@ _@go.glob_tab_completion() { _@go.glob_trim_matches if [[ "${#__go_glob_matches[@]}" -eq '0' ]]; then - return 1 + return "$_GO_EC_SIGN1" elif [[ "${#__go_glob_matches[@]}" -eq '1' ]]; then echo "${__go_glob_matches[0]}" else @@ -209,10 +209,10 @@ _@go.glob_set_globignore() { if [[ -z "$rootdir" ]]; then echo "ERROR: root dir not set before setting GLOBIGNORE" >&2 - return 1 + return "$_GO_EC_CONFIG" elif [[ ! -d "$rootdir" ]]; then echo "ERROR: root dir not valid when setting GLOBIGNORE: $rootdir " >&2 - return 1 + return "$_GO_EC_CONFIG" fi if [[ -n "$globignore_spec" ]]; then @@ -239,7 +239,7 @@ _@go.glob_parse_argv() { ;; *) @go.printf "Unknown flag: $1" >&2 - return 1 + return "$_GO_EC_USAGE" ;; esac done @@ -249,11 +249,11 @@ _@go.glob_parse_argv() { if [[ -z "$__go_glob_rootdir" ]]; then @go.printf "Root directory argument not specified.\n" >&2 - return 1 + return "$_GO_EC_ARGERR" elif [[ ! -d "$__go_glob_rootdir" ]]; then @go.printf "Root directory argument %s is not a directory.\n" \ "$__go_glob_rootdir" >&2 - return 1 + return "$_GO_EC_ARGERR" fi __go_glob_suffix="$1" @@ -261,11 +261,11 @@ _@go.glob_parse_argv() { if [[ -z "$__go_glob_suffix" ]]; then @go.printf "File suffix argument not specified.\n" >&2 - return 1 + return "$_GO_EC_ARGERR" fi if ! _@go.glob_set_globignore "$globignore" "$__go_glob_rootdir"; then - return 1 + return "$_GO_EC_SIGN1" fi __go_glob_patterns=("${@:-*}") } @@ -275,7 +275,7 @@ _@go.glob() { if [[ "$1" == '--complete' ]]; then shift _@go.glob_tab_completion "$@" - return + return "$_GO_EC_OK" fi local __go_glob_trim @@ -284,7 +284,7 @@ _@go.glob() { local __go_glob_patterns if ! _@go.glob_parse_argv "$@"; then - return 1 + return "$_GO_EC_SIGN1" fi local pattern @@ -294,7 +294,7 @@ _@go.glob() { if ! _@go.glob_impl "$__go_glob_rootdir/$pattern"; then @go.printf "\"$pattern\" does not match any %s files in %s.\n" \ "$__go_glob_suffix" "$__go_glob_rootdir" >&2 - return 1 + return "$_GO_EC_NOTFND" fi done diff --git a/libexec/help b/libexec/help index 7c3d207..fc9f30b 100755 --- a/libexec/help +++ b/libexec/help @@ -90,14 +90,15 @@ _@go.usage() { _@go.help_message_for_command() { if _@go.source_builtin 'aliases' --help "$1"; then - return + return "$_GO_EC_OK" fi local __go_cmd_path local __go_argv - if ! _@go.set_command_path_and_argv "$@"; then - return 1 + _@go.set_command_path_and_argv "$@" && ec=0 || ec="$?" + if [[ "$ec" -ne 0 ]] ; then + return "$ec" fi local cmd_name="${__go_cmd_path//.d\// }" @@ -111,7 +112,7 @@ _@go.help_message_for_command() { # _shouldn't_ ever happen. @go.printf "ERROR: failed to parse description from %s\n" \ "$__go_cmd_path" >&2 - return 1 + return "$_GO_EC_BADFRMT" fi local filter_pattern='# [Hh]elp [Ff]ilter['$'\n\r'']' @@ -134,7 +135,7 @@ _@go.help() { shift . "$_GO_CORE_DIR/lib/internal/complete" _@go.complete_command_path "$@" - return + return "$_GO_EC_OK" fi if [[ "$#" -eq '0' ]]; then diff --git a/libexec/modules b/libexec/modules index 3afe2af..b2d2ebb 100755 --- a/libexec/modules +++ b/libexec/modules @@ -63,10 +63,10 @@ _@go.modules_help() { __go_module_file="$_GO_USE_MODULES" elif [[ "$#" -ne '1' ]]; then @go.printf "Please specify only one module name.\n" >&2 - return 1 + return "$_GO_EC_ARGERR" elif ! _@go.find_module; then @go.printf "Unknown module: $1\n" >&2 - return 1 + return "$_GO_EC_NOTFND" fi local __go_cmd_desc @@ -76,7 +76,7 @@ _@go.modules_help() { if ! _@go.command_description "$__go_module_file"; then @go.printf "ERROR: failed to parse description from %s\n" \ "$__go_module_file" >&2 - return 1 + return "$_GO_EC_BADFRMT" fi @go.printf "$__go_module_name - $__go_cmd_desc\n" } @@ -102,7 +102,7 @@ _@go.modules_summaries() { for module_path in "${__go_modules[@]}"; do if ! _@go.command_summary "$module_path"; then @go.printf "ERROR: failed to parse summary from %s\n" "$module_path" >&2 - return 1 + return "$_GO_EC_BADFRMT" fi __go_modules_summaries+=("$__go_cmd_desc") done @@ -134,7 +134,7 @@ _@go.modules_produce_listing() { if [[ -z "$action" ]]; then __go_modules_listing=("${modules[@]}") - return + return "$_GO_EC_OK" fi . "$_GO_USE_MODULES" 'format' @@ -148,7 +148,7 @@ _@go.modules_produce_listing() { summaries) local __go_modules_summaries=() if ! _@go.modules_summaries; then - return 1 + return "$_GO_EC_BADFRMT" fi @go.zip_items modules __go_modules_summaries ' ' modules ;; @@ -156,7 +156,7 @@ _@go.modules_produce_listing() { # Should only happen if _@go.modules is updated and this case statement # isn't. @go.printf 'ERROR: Unknown action: %s\n' "$action" >&2 - return 1 + return "$_GO_EC_USAGE" esac __go_modules_listing=("${modules[@]}") } @@ -241,22 +241,24 @@ _@go.modules_list() { if [[ "$__go_module_name" == '*' ]]; then if [[ "${#module_specs[@]}" -ne 1 ]]; then @go.printf "Do not specify other patterns when '*' is present.\n" >&2 - return 1 + return "$_GO_EC_USAGE" fi _@go.modules_search elif [[ "$__go_module_name" =~ \*|/$ ]]; then _@go.modules_search "$__go_module_name" elif ! _@go.find_module; then @go.printf "Unknown module: $__go_module_name\n" >&2 - return 1 + return "$_GO_EC_NOTFND" else __go_modules+=("$__go_module_file") fi done local __go_modules_listing=() - if ! _@go.modules_produce_listing "$action"; then - return 1 + + _@go.modules_produce_listing "$action" && ec=0 || ec="$?" + if [[ "$ec" -ne 0]] ; then + return "$ec" fi printf '%s\n' "${__go_modules_listing[@]}" } @@ -268,7 +270,7 @@ _@go.modules_tab_completion_plugins() { if [[ "$glob" =~ / ]]; then plugin="${glob%/*}" _@go.modules_find_all_in_dir "$1/$plugin" "${glob#*/}*" - return + return "$_GO_EC_OK" fi # Otherwise collect all plugin modules and the names of the plugins to @@ -310,9 +312,9 @@ _@go.modules_tab_completion() { if [[ ( "$word_index" -ne '0' && "${first:0:1}" == '-' ) && ( ! "$first" =~ $flags_pattern || "$first" == '--imported' ) ]]; then - return 1 + return "$_GO_EC_SIGN1" elif [[ "$first" =~ ^(-h|-help|--help)$ && "$word_index" -gt '1' ]]; then - return 1 + return "$_GO_EC_SIGN1" fi if [[ "$#" -eq '0' || "$word_index" -eq '0' ]]; then @@ -343,9 +345,11 @@ _@go.modules_tab_completion() { fi local __go_modules_listing=() - if ! _@go.modules_produce_listing; then + + _@go.modules_produce_listing && ec=0 || ec="$?" + if [[ "$ec" -ne 0 ]] ; then # Shouldn't happen, since modules_produce_listing isn't parsing summaries. - return 1 + return "$ec" fi completions+=("${__go_modules_listing[@]}") @go.complete_remove_completions_already_present \ @@ -356,7 +360,7 @@ _@go.modules_tab_completion() { _@go.modules_list_imported() { if [[ "$#" -ne 0 ]]; then @go.printf 'The --imported option takes no other arguments.\n' >&2 - return 1 + return "$_GO_EC_USAGE" fi # Collect imported module info before _GO_USE_MODULES imports possibly more. @@ -399,7 +403,7 @@ _@go.modules() { ;; -*) @go.printf "Unknown option: $action\n" >&2 - return 1 + return "$_GO_EC_USAGE" ;; *) # Here we treat $action as a potential glob pattern. diff --git a/libexec/new b/libexec/new index 276f750..56a3725 100755 --- a/libexec/new +++ b/libexec/new @@ -48,7 +48,7 @@ _@go.new_tab_completions() { if [[ "$word_index" -eq '0' ]]; then printf -- '--command --internal --public --test --type' - return + return "$_GO_EC_OK" fi ((--word_index)) @@ -60,31 +60,31 @@ _@go.new_tab_completions() { . "$_GO_CORE_DIR/lib/internal/complete" _@go.complete_command_path "$word_index" "$@" fi - return + return "$_GO_EC_OK" ;; --internal) if [[ "$word_index" -ne '0' ]] || ! cd "$_GO_SCRIPTS_DIR/lib"; then - return 1 + return "$_GO_EC_GENERR" fi ;; --public) if [[ "$word_index" -ne '0' ]] || ! cd "$_GO_ROOTDIR/lib"; then - return 1 + return "$_GO_EC_GENERR" fi ;; --test) if [[ "$word_index" -ne '0' ]] || ! cd "$_GO_ROOTDIR/$_GO_TEST_DIR"; then - return 1 + return "$_GO_EC_GENERR" fi ;; --type) if [[ "$word_index" -ne '1' ]]; then - return 1 + return "$_GO_EC_GENERR" fi shift ;; *) - return 1 + return "$_GO_EC_USAGE" ;; esac @go.compgen -f -- "$1" @@ -114,25 +114,25 @@ _@go.new_file() { if [[ -z "$file_path" ]]; then @go.printf 'No %sfile path specified.\n' "$file_type" >&2 - return 1 + return "$_GO_EC_ARGERR" elif [[ ! "$permissions" =~ $permissions_pattern ]]; then @go.printf 'Invalid permissions specification "%s" for %sfile: %s\n' \ "$permissions" "$file_type" "$relpath" >&2 - return 1 + return "$_GO_EC_ARGERR" elif [[ ! -d "$parent_dir" ]] && ! mkdir -p "$parent_dir"; then @go.printf "Couldn't create parent directory for new %sfile: %s\n" \ "$file_type" "$relpath" >&2 - return 1 + return "$_GO_EC_CANTCREAT" elif [[ -f "$file_path" ]]; then @go.printf '%sfile already exists: %s\n' "$file_type" "$relpath" >&2 - return 1 + return "$_GO_EC_GENERR" elif ! printf -- '%s\n' "$@" >"$file_path"; then @go.printf 'Failed to create new %sfile: %s\n' "$file_type" "$relpath" >&2 - return 1 + return "$_GO_EC_CANTCREAT" elif ! chmod "$permissions" "$file_path"; then @go.printf 'Failed to set permissions for new %sfile to "%s": %s\n' \ "$file_type" "$permissions" "$relpath" >&2 - return 1 + return "$_GO_EC_NOPERM" fi } @@ -168,7 +168,7 @@ _@go.new_command_scripts() { if [[ "$#" -eq '0' ]]; then printf 'No command script name specified.\n' >&2 - return 1 + return "$_GO_EC_ARGERR" fi for cmd in "$@"; do @@ -182,8 +182,9 @@ _@go.new_command_scripts() { fi new_scripts+=("$cmd_path") - if ! _@go.new_command_script "$cmd" "$cmd_path" "$is_last_cmd"; then - return 1 + _@go.new_command_script "$cmd" "$cmd_path" "$is_last_cmd" && ec=0 || ec="$?" + if [[ "$ec" -ne 0 ]] ; then + return "$ec" fi done @@ -213,8 +214,9 @@ _@go.new_module() { ;; esac - if ! _@go.new_file "$module_type" "$module_path" '644' "${impl[@]}"; then - return 1 + _@go.new_file "$module_type" "$module_path" '644' "${impl[@]}" && ec=0 || ec="$?" + if [[ "$ec" -ne 0 ]] ; then + return "$ec" elif command -v "$EDITOR" >/dev/null; then "$EDITOR" "$module_path" fi @@ -248,8 +250,9 @@ _@go.new_test() { '@test "$SUITE: short description of your first test case" {' '}') - if ! _@go.new_file "Bats test" "$test_path" '644' "${impl[@]}"; then - return 1 + _@go.new_file "Bats test" "$test_path" '644' "${impl[@]}" && ec=0 || ec="$?" + if [[ "$ec" -ne 0 ]] ; then + return "$ec" elif command -v "$EDITOR" >/dev/null; then "$EDITOR" "$test_path" fi @@ -260,7 +263,7 @@ _@go.new() { if [[ "$#" -eq '0' ]]; then @go 'help' "${_GO_CMD_NAME[@]}" >&2 - return 1 + return "$_GO_EC_USAGE" fi shift @@ -268,7 +271,7 @@ _@go.new() { --complete) # Tab completions _@go.new_tab_completions "$@" - return + return "$_GO_EC_OK" ;; --command) _@go.new_command_scripts "$@" @@ -283,8 +286,9 @@ _@go.new() { _@go.new_test "$_GO_ROOTDIR/$_GO_TEST_DIR/$1" ;; --type) - if ! _@go.new_file "$1" "$2" "${@:3}"; then - return 1 + _@go.new_file "$1" "$2" "${@:3}" && ec=0 || ec="$?" + if [[ "$ec" -ne 0 ]]; then + return "$ec" elif [[ "$#" -le '3' ]] && command -v "$EDITOR" >/dev/null; then "$EDITOR" "$2" fi @@ -292,7 +296,7 @@ _@go.new() { *) printf 'The first argument is "%s", but must be one of:\n %s\n' \ "$mode" '--command --internal --public --test --type' >&2 - return 1 + return "$_GO_EC_USAGE" esac } diff --git a/tests/modules/use.bats b/tests/modules/use.bats index 395512d..d9c5bae 100644 --- a/tests/modules/use.bats +++ b/tests/modules/use.bats @@ -61,7 +61,7 @@ do_setup() { for core_test_module in 'builtin-test' 'go-use-modules-test'; do if [[ -e "$_GO_CORE_DIR/lib/$core_test_module" ]]; then printf 'ERROR: "%s" exists, aborting.\n' "$core_test_module" >&2 - return 1 + return "$_GO_EC_GENERR" fi done From a9865436f5efcb16fdca6f56030e0ff4b898426f Mon Sep 17 00:00:00 2001 From: Nikolaos Kakouros Date: Mon, 22 Jan 2018 08:00:52 +0100 Subject: [PATCH 11/16] More --- lib/bats/background-process | 6 +++--- lib/log | 2 +- lib/testing/environment | 2 +- libexec/demo-core.d/log | 2 +- libexec/demo-core.d/prompt | 4 ++-- libexec/demo-core.d/select-option | 4 ++-- libexec/fullpath | 2 +- libexec/get.d/git-repo | 10 +++++----- libexec/path | 9 +++++---- libexec/plugins | 2 +- 10 files changed, 22 insertions(+), 21 deletions(-) diff --git a/lib/bats/background-process b/lib/bats/background-process index e39241c..948856b 100644 --- a/lib/bats/background-process +++ b/lib/bats/background-process @@ -109,11 +109,11 @@ wait_for_background_output() { if [[ -z "$BATS_BACKGROUND_RUN_OUTPUT" ]]; then printf 'run_in_background not called\n' >&2 restore_bats_shell_options '1' - return + return "$_GO_EC_OK" elif [[ -z "$pattern" ]]; then printf 'pattern not specified\n' >&2 restore_bats_shell_options '1' - return + return "$_GO_EC_OK" fi # Since `tail -f` will block forever, even if the background process died, we @@ -126,7 +126,7 @@ wait_for_background_output() { # Kill the sleep so `pkill -f 'tail -f'` will run sooner. pkill -P "$kill_input_pid" sleep restore_bats_shell_options - return + return "$_GO_EC_OK" fi done < <("${input_cmd[@]}") diff --git a/lib/log b/lib/log index f1a04ee..7186652 100644 --- a/lib/log +++ b/lib/log @@ -361,7 +361,7 @@ readonly __GO_LOG_COMMAND_EXIT_PATTERN='^@go.log_command (exit|fatal):([0-9]+)$' _GO_LOG_LEVELS+=("$log_level") __GO_LOG_LEVELS_FORMAT_CODES+=("$format_code") __GO_LOG_LEVELS_FILE_DESCRIPTORS+=("$level_fd") - return + return "$_GO_EC_OK" fi _GO_LOG_LEVELS[$__go_log_level_index]="$log_level" diff --git a/lib/testing/environment b/lib/testing/environment index 250b0ad..47a985d 100644 --- a/lib/testing/environment +++ b/lib/testing/environment @@ -130,7 +130,7 @@ test-go() { printf -v 'err_args' ' "%s"' "${@:2}" printf 'compgen failed or results were empty:%s\n' "$err_args" >&2 restore_bats_shell_options '1' - return + return "$_GO_EC_OK" fi @go.split $'\n' "$completions" "$1" restore_bats_shell_options "$?" diff --git a/libexec/demo-core.d/log b/libexec/demo-core.d/log index 2b049b3..19fa5db 100755 --- a/libexec/demo-core.d/log +++ b/libexec/demo-core.d/log @@ -68,7 +68,7 @@ log_demo() { if [[ "$2" -eq 0 ]]; then echo "-v --verbose" fi - return + return "$_GO_EC_OK" fi . "$_GO_USE_MODULES" 'log' diff --git a/libexec/demo-core.d/prompt b/libexec/demo-core.d/prompt index 6b4e2c9..544dc4d 100755 --- a/libexec/demo-core.d/prompt +++ b/libexec/demo-core.d/prompt @@ -18,7 +18,7 @@ _@go.prompt_demo() { # No default value; returns error on no input. if ! @go.prompt_for_input 'name' $'What is your name?\n' '' \ 'Run away, Sir or Madam Not Appearing in this Film! Run away!'; then - return 1 + return "$_GO_EC_NOINPUT" fi @go.printf 'Nice to meet you, %s!\n' "$name" @@ -28,7 +28,7 @@ _@go.prompt_demo() { @go.prompt_for_input 'quest' $'What is your quest?\n' "$quest" elif ! @go.prompt_for_yes_or_no "Might I suggest: $quest" 'yes'; then @go.printf 'OK, no quest. Suit yourself!\n' - return 1 + return "$_GO_EC_SIGN1" fi @go.printf 'Your quest is: %s\n' "$quest" } diff --git a/libexec/demo-core.d/select-option b/libexec/demo-core.d/select-option index b55789e..dffe210 100755 --- a/libexec/demo-core.d/select-option +++ b/libexec/demo-core.d/select-option @@ -27,7 +27,7 @@ select_option_demo() { if ! @go.select_option 'selected' "${options[@]}"; then @go.printf 'You declined to select an option. Exiting...\n\n' - return 1 + return "$_GO_EC_NOINPUT" else @go.printf 'You selected: "%s"\n\n' "$selected" fi @@ -35,7 +35,7 @@ select_option_demo() { if ! @go.prompt_for_yes_or_no 'Would you like to select another option?' \ 'yes'; then @go.printf 'Exiting...\n' - return 0 + return "$_GO_EC_OK" fi done } diff --git a/libexec/fullpath b/libexec/fullpath index d532f91..9b2d628 100755 --- a/libexec/fullpath +++ b/libexec/fullpath @@ -26,7 +26,7 @@ _@go.fullpath() { if [[ "$1" == '--complete' ]]; then shift _@go.fullpath_tab_completion "$@" - return + return "$_GO_EC_OK" fi local existing_only diff --git a/libexec/get.d/git-repo b/libexec/get.d/git-repo index 9064aa8..d85e6bb 100755 --- a/libexec/get.d/git-repo +++ b/libexec/get.d/git-repo @@ -32,13 +32,13 @@ _@go.get_git_repo_impl() { if ! command -v git >/dev/null; then @go.printf 'Please install git before running "%s".\n' \ "${_GO_CMD_NAME[*]}" >&2 - return 1 + return "$_GO_EC_DEPMISS" elif [[ -e "$clone_dir" ]]; then @go.printf '"%s" already exists; not updating.\n' "$clone_dir" - return 1 + return "$_GO_EC_GENERR" elif ! "${git_clone[@]}" -b "$git_ref" "$repo_url" "$clone_dir"; then @go.printf 'Failed to clone %s.\n' "$repo_msg" >&2 - return 1 + return "$_GO_EC_IOERR" fi @go.printf 'Successfully cloned %s.\n' "$repo_msg" } @@ -57,12 +57,12 @@ _@go.get_git_repo() { . "$_GO_USE_MODULES" 'complete' @go.compgen -f -- "$3" fi - return + return "$_GO_EC_OK" fi if [[ "$#" -ne '3' ]]; then @go help "${_GO_CMD_NAME[@]}" >&2 - return 1 + return "$_GO_EC_USAGE" fi if [[ -e "$repo_url" ]]; then diff --git a/libexec/path b/libexec/path index 0921ec2..517030e 100755 --- a/libexec/path +++ b/libexec/path @@ -15,23 +15,24 @@ _@go.path() { shift . "$_GO_CORE_DIR/lib/internal/complete" _@go.complete_command_path "$@" - return + return "$_GO_EC_OK" fi if [[ "$#" -ne '0' ]]; then if _@go.source_builtin 'aliases' --exists "$1"; then echo '[alias]' - return + return "$_GO_EC_OK" elif _@go.source_builtin 'builtins' --exists "$1"; then echo -n '[builtin] ' fi local __go_cmd_path - if _@go.set_command_path_and_argv "$@"; then + _@go.set_command_path_and_argv "$@" && ec=0 || ec="$?" + if [[ "$ec" -eq 0 ]]; then echo "${__go_cmd_path#$_GO_ROOTDIR/}" else - return 1 + return "$ec" fi fi } diff --git a/libexec/plugins b/libexec/plugins index fe09450..d805c3a 100755 --- a/libexec/plugins +++ b/libexec/plugins @@ -55,7 +55,7 @@ _@go.plugins() { # Tab completions _@go.source_builtin 'commands' "$@" "$__go_plugins_pathspec" else - return 1 + return "$_GO_EC_NOTFND" fi } From 2d904597837c2c17952c3fb8b097031129ceba83 Mon Sep 17 00:00:00 2001 From: Nikolaos Kakouros Date: Mon, 22 Jan 2018 08:22:04 +0100 Subject: [PATCH 12/16] Reverts changes in bats related files --- lib/bats/background-process | 6 +++--- lib/bats/helpers | 4 ++-- tests/modules/use.bats | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/bats/background-process b/lib/bats/background-process index 948856b..e39241c 100644 --- a/lib/bats/background-process +++ b/lib/bats/background-process @@ -109,11 +109,11 @@ wait_for_background_output() { if [[ -z "$BATS_BACKGROUND_RUN_OUTPUT" ]]; then printf 'run_in_background not called\n' >&2 restore_bats_shell_options '1' - return "$_GO_EC_OK" + return elif [[ -z "$pattern" ]]; then printf 'pattern not specified\n' >&2 restore_bats_shell_options '1' - return "$_GO_EC_OK" + return fi # Since `tail -f` will block forever, even if the background process died, we @@ -126,7 +126,7 @@ wait_for_background_output() { # Kill the sleep so `pkill -f 'tail -f'` will run sooner. pkill -P "$kill_input_pid" sleep restore_bats_shell_options - return "$_GO_EC_OK" + return fi done < <("${input_cmd[@]}") diff --git a/lib/bats/helpers b/lib/bats/helpers index c0d7f85..c4619a7 100644 --- a/lib/bats/helpers +++ b/lib/bats/helpers @@ -208,7 +208,7 @@ skip_if_none_present_on_system() { test_join() { if [[ ! "$2" =~ ^[[:alpha:]_][[:alnum:]_]*$ ]]; then printf '"%s" is not a valid variable identifier.\n' "$2" >&2 - return "$_GO_EC_GENERR" + return 1 fi local IFS="$1" @@ -268,7 +268,7 @@ test_break_after_num_iterations() { printf 'The argument to %s must be a positive integer at:\n' "$FUNCNAME" >&2 __tbani_do_exit='true' elif [[ -z "$TEST_DEBUG" ]]; then - return "$_GO_EC_OK" + return else printf -v "$__tbani_var" -- '%d' "$((${!__tbani_var} + 1))" if [[ "${!__tbani_var}" -eq "$__tbani_num_iterations" ]]; then diff --git a/tests/modules/use.bats b/tests/modules/use.bats index d9c5bae..395512d 100644 --- a/tests/modules/use.bats +++ b/tests/modules/use.bats @@ -61,7 +61,7 @@ do_setup() { for core_test_module in 'builtin-test' 'go-use-modules-test'; do if [[ -e "$_GO_CORE_DIR/lib/$core_test_module" ]]; then printf 'ERROR: "%s" exists, aborting.\n' "$core_test_module" >&2 - return "$_GO_EC_GENERR" + return 1 fi done From 885a34f3ec9879e13416cdc77fb6302c5222c5a2 Mon Sep 17 00:00:00 2001 From: Nikolaos Kakouros Date: Mon, 22 Jan 2018 11:28:04 +0100 Subject: [PATCH 13/16] Fixes some returns --- lib/log | 5 ++--- lib/testing/environment | 2 +- libexec/complete | 25 ++++++++++++++++++------- libexec/modules | 2 +- 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/lib/log b/lib/log index 7186652..8e4a880 100644 --- a/lib/log +++ b/lib/log @@ -305,8 +305,7 @@ readonly __GO_LOG_COMMAND_EXIT_PATTERN='^@go.log_command (exit|fatal):([0-9]+)$' @go.log_timestamp() { _@go.log_init - local ec - ec=0 + local ec=0 case "$__GO_LOG_TIMESTAMP_IMPL" in printf) @@ -361,7 +360,7 @@ readonly __GO_LOG_COMMAND_EXIT_PATTERN='^@go.log_command (exit|fatal):([0-9]+)$' _GO_LOG_LEVELS+=("$log_level") __GO_LOG_LEVELS_FORMAT_CODES+=("$format_code") __GO_LOG_LEVELS_FILE_DESCRIPTORS+=("$level_fd") - return "$_GO_EC_OK" + return fi _GO_LOG_LEVELS[$__go_log_level_index]="$log_level" diff --git a/lib/testing/environment b/lib/testing/environment index 47a985d..250b0ad 100644 --- a/lib/testing/environment +++ b/lib/testing/environment @@ -130,7 +130,7 @@ test-go() { printf -v 'err_args' ' "%s"' "${@:2}" printf 'compgen failed or results were empty:%s\n' "$err_args" >&2 restore_bats_shell_options '1' - return "$_GO_EC_OK" + return fi @go.split $'\n' "$completions" "$1" restore_bats_shell_options "$?" diff --git a/libexec/complete b/libexec/complete index a80c4aa..19608bc 100755 --- a/libexec/complete +++ b/libexec/complete @@ -69,6 +69,7 @@ _@go.complete_args() { local args=("$@") local cmd_name="${args[0]}" local word="${args[$word_index]}" + local ec=0 . "$_GO_CORE_DIR/lib/internal/complete" @@ -84,31 +85,41 @@ _@go.complete_args() { printf -- '--help \n' ;; *) - @go.compgen -W "$(_@go.complete_top_level_commands)" -- "$cmd_name" + @go.compgen -W "$(_@go.complete_top_level_commands)" -- "$cmd_name" && ec=0 || ec="$?" ;; esac + if [[ "${ec-0}" -ne 0 ]]; then + return "$ec" + fi return "$_GO_EC_OK" fi + ec="unset" case "$cmd_name" in cd|pushd) - @go.compgen -d -- "$word" - return "$_GO_EC_OK" + @go.compgen -d -- "$word" && ec=0 || ec="$?" ;; edit|run) - @go.compgen -f -- "$word" - return "$_GO_EC_OK" + @go.compgen -f -- "$word" && ec=0 || ec="$?" ;; -h|-help|--help) cmd_name='help' ;; -*|unenv) - return "$_GO_EC_GENERR" + ec=1 ;; esac + if [[ "$ec" == '0' ]]; then + return "$_GO_EC_OK" + elif [[ "$ec" != "unset" ]]; then + return "$ec" + fi if _@go.source_builtin 'aliases' --exists "$cmd_name"; then - @go.compgen -f -- "$word" + @go.compgen -f -- "$word" && ec=0 || ec="$?" + if [[ "$ec" -ne 0 ]]; then + return "$ec" + fi return "$_GO_EC_OK" fi diff --git a/libexec/modules b/libexec/modules index b2d2ebb..ccf7204 100755 --- a/libexec/modules +++ b/libexec/modules @@ -257,7 +257,7 @@ _@go.modules_list() { local __go_modules_listing=() _@go.modules_produce_listing "$action" && ec=0 || ec="$?" - if [[ "$ec" -ne 0]] ; then + if [[ "$ec" -ne 0 ]] ; then return "$ec" fi printf '%s\n' "${__go_modules_listing[@]}" From 624e7498c84050bb5bccb47cabe4fe5d445c91ad Mon Sep 17 00:00:00 2001 From: Nikolaos Kakouros Date: Mon, 22 Jan 2018 11:28:17 +0100 Subject: [PATCH 14/16] Fixes tests --- tests/vars.bats | 57 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/tests/vars.bats b/tests/vars.bats index 9eedb0c..5ae0d61 100644 --- a/tests/vars.bats +++ b/tests/vars.bats @@ -44,6 +44,25 @@ quotify_expected() { "declare -rx _GO_CORE_URL=\"$_GO_CORE_URL\"" "declare -rx _GO_CORE_VERSION=\"$_GO_CORE_VERSION\"" "declare -x _GO_COVERALLS_URL=\"$_GO_COVERALLS_URL\"" + 'declare -irx _GO_EC_ARGERR="71"' + 'declare -irx _GO_EC_BADFRMT="67"' + 'declare -irx _GO_EC_BASE="64"' + 'declare -irx _GO_EC_CANTCREAT="73"' + 'declare -irx _GO_EC_CONFIG="78"' + 'declare -irx _GO_EC_DATAERR="65"' + 'declare -irx _GO_EC_DEPMISS="72"' + 'declare -irx _GO_EC_GENERR="70"' + 'declare -irx _GO_EC_IOERR="74"' + 'declare -irx _GO_EC_MAX="78"' + 'declare -irx _GO_EC_NOINPUT="66"' + 'declare -irx _GO_EC_NOPERM="77"' + 'declare -irx _GO_EC_NOTFND="68"' + 'declare -irx _GO_EC_OFFSET="0"' + 'declare -irx _GO_EC_OK="0"' + 'declare -irx _GO_EC_SIGN1="75"' + 'declare -irx _GO_EC_SIGN2="76"' + 'declare -irx _GO_EC_UNAVAILABLE="69"' + 'declare -irx _GO_EC_USAGE="64"' 'declare -a _GO_IMPORTED_MODULES=()' 'declare -a _GO_IMPORTED_MODULE_CALLERS=()' 'declare -a _GO_IMPORTED_MODULE_FILES=()' @@ -118,6 +137,25 @@ quotify_expected() { "declare -rx _GO_CORE_URL=\"$_GO_CORE_URL\"" "declare -rx _GO_CORE_VERSION=\"$_GO_CORE_VERSION\"" "declare -x _GO_COVERALLS_URL=\"$_GO_COVERALLS_URL\"" + "declare -irx _GO_EC_ARGERR=\"71\"" + "declare -irx _GO_EC_BADFRMT=\"67\"" + "declare -irx _GO_EC_BASE=\"64\"" + "declare -irx _GO_EC_CANTCREAT=\"73\"" + "declare -irx _GO_EC_CONFIG=\"78\"" + "declare -irx _GO_EC_DATAERR=\"65\"" + "declare -irx _GO_EC_DEPMISS=\"72\"" + "declare -irx _GO_EC_GENERR=\"70\"" + "declare -irx _GO_EC_IOERR=\"74\"" + "declare -irx _GO_EC_MAX=\"78\"" + "declare -irx _GO_EC_NOINPUT=\"66\"" + "declare -irx _GO_EC_NOPERM=\"77\"" + "declare -irx _GO_EC_NOTFND=\"68\"" + "declare -irx _GO_EC_OFFSET=\"0\"" + "declare -irx _GO_EC_OK=\"0\"" + "declare -irx _GO_EC_SIGN1=\"75\"" + "declare -irx _GO_EC_SIGN2=\"76\"" + "declare -irx _GO_EC_UNAVAILABLE=\"69\"" + "declare -irx _GO_EC_USAGE=\"64\"" "declare -a _GO_IMPORTED_MODULES=(${expected_modules[*]})" "declare -a _GO_IMPORTED_MODULE_CALLERS=(${expected_module_callers[*]})" "declare -a _GO_IMPORTED_MODULE_FILES=(${expected_module_files[*]})" @@ -168,6 +206,25 @@ quotify_expected() { "_GO_CORE_URL: $_GO_CORE_URL" \ "_GO_CORE_VERSION: $_GO_CORE_VERSION" \ "_GO_COVERALLS_URL: $_GO_COVERALLS_URL" \ + "_GO_EC_ARGERR: $_GO_EC_ARGERR" \ + "_GO_EC_BADFRMT: $_GO_EC_BADFRMT" \ + "_GO_EC_BASE: $_GO_EC_BASE" \ + "_GO_EC_CANTCREAT: $_GO_EC_CANTCREAT" \ + "_GO_EC_CONFIG: $_GO_EC_CONFIG" \ + "_GO_EC_DATAERR: $_GO_EC_DATAERR" \ + "_GO_EC_DEPMISS: $_GO_EC_DEPMISS" \ + "_GO_EC_GENERR: $_GO_EC_GENERR" \ + "_GO_EC_IOERR: $_GO_EC_IOERR" \ + "_GO_EC_MAX: $_GO_EC_MAX" \ + "_GO_EC_NOINPUT: $_GO_EC_NOINPUT" \ + "_GO_EC_NOPERM: $_GO_EC_NOPERM" \ + "_GO_EC_NOTFND: $_GO_EC_NOTFND" \ + "_GO_EC_OFFSET: $_GO_EC_OK" \ + "_GO_EC_OK: $_GO_EC_OK" \ + "_GO_EC_SIGN1: $_GO_EC_SIGN1" \ + "_GO_EC_SIGN2: $_GO_EC_SIGN2" \ + "_GO_EC_UNAVAILABLE: $_GO_EC_UNAVAILABLE" \ + "_GO_EC_USAGE: $_GO_EC_USAGE" \ "_GO_KCOV_DIR: $_GO_KCOV_DIR" \ "_GO_ROOTDIR: $TEST_GO_ROOTDIR" \ "_GO_SCRIPT: $TEST_GO_SCRIPT" \ From 500cb99ddffe58a902435aea32593e32dd0e0917 Mon Sep 17 00:00:00 2001 From: Nikolaos Kakouros Date: Mon, 22 Jan 2018 14:27:02 +0100 Subject: [PATCH 15/16] Removes overzealous OKs, adds _GO_EC_EXT1,2, some more --- go-core.bash | 12 ++++++------ lib/bats-main | 2 +- lib/existence | 11 +++++++---- lib/file | 8 ++++++-- lib/fileutil | 3 +-- lib/internal/command_descriptions | 5 ++++- lib/internal/sysexits | 26 ++++++++++++------------- lib/kcov-ubuntu | 2 +- lib/testing/stack-trace | 5 ++++- libexec/builtins | 2 +- libexec/commands | 2 +- libexec/complete | 25 ++++++++---------------- libexec/demo-core.d/select-option | 2 +- libexec/env | 2 +- libexec/fullpath | 2 +- libexec/get.d/file | 2 +- libexec/get.d/git-repo | 2 +- libexec/glob | 2 +- libexec/help | 2 +- libexec/modules | 2 +- libexec/new | 4 ++-- libexec/path | 2 +- scripts/changes | 5 ++++- tests/vars.bats | 32 +++++++++++++++---------------- 24 files changed, 84 insertions(+), 78 deletions(-) diff --git a/go-core.bash b/go-core.bash index 06e52d0..ae66fdc 100755 --- a/go-core.bash +++ b/go-core.bash @@ -312,11 +312,11 @@ declare _GO_INJECT_MODULE_PATH="$_GO_INJECT_MODULE_PATH" return "$_GO_EC_CONFIG" fi "$EDITOR" "$@" - return "$_GO_EC_OK" + return ;; run) "$@" - return "$_GO_EC_OK" + return ;; cd|pushd|unenv) @go.printf "$cmd is only available after using \"$_GO_CMD env\" %s\n" \ @@ -327,7 +327,7 @@ declare _GO_INJECT_MODULE_PATH="$_GO_INJECT_MODULE_PATH" if _@go.source_builtin 'aliases' --exists "$cmd"; then "$cmd" "$@" - return "$_GO_EC_OK" + return fi . "$_GO_CORE_DIR/lib/internal/path" @@ -424,10 +424,10 @@ _@go.set_scripts_dir() { return "$_GO_EC_OK" } -_@go.set_scripts_dir "$@" && rc=0 || rc="$?" +_@go.set_scripts_dir "$@" && ec=0 || ec="$?" -if [[ "$rc" -ne "$_GO_EC_OK" ]]; then - exit "$rc" +if [[ "$ec" -ne "$_GO_EC_OK" ]]; then + exit "$ec" elif [[ -z "$COLUMNS" ]]; then # On Travis, $TERM is set to 'dumb', but `tput cols` still fails. if command -v tput >/dev/null && tput cols >/dev/null 2>&1; then diff --git a/lib/bats-main b/lib/bats-main index 86526e1..f977b50 100644 --- a/lib/bats-main +++ b/lib/bats-main @@ -120,7 +120,7 @@ fi if [[ "$1" == '--complete' ]]; then shift @go.bats_tab_completion "$@" - return "$_GO_EC_OK" + return fi @go.bats_clone diff --git a/lib/existence b/lib/existence index f183681..b18180a 100644 --- a/lib/existence +++ b/lib/existence @@ -49,9 +49,8 @@ if [[ ! -r "$2" ]]; then @go.printf "%s doesn't exist or isn't readable: %s\n" "$1" "$2" >&2 return "$_GO_EC_GENERR" - else - return "$_GO_EC_OK" fi + return "$_GO_EC_OK" } # Selects the first installed command from a list of possible commands/names. @@ -69,8 +68,12 @@ local __go_pick_cmd for __go_pick_cmd in "${@:2}"; do if command -v "$__go_pick_cmd" >/dev/null; then - printf -v "$1" -- '%s' "$__go_pick_cmd" - return "$_GO_EC_OK" + printf -v "$1" -- '%s' "$__go_pick_cmd" && ec=0 || ec="$?" + if [[ "$ec" -ne 0 ]]; then + return $((_GO_EC_GENERR+ec)) + else + return "$_GO_EC_OK" + fi fi done @go.printf 'None of the following commands were found on the system:\n' >&2 diff --git a/lib/file b/lib/file index e94c0de..026b334 100644 --- a/lib/file +++ b/lib/file @@ -91,8 +91,12 @@ fi @go.print_stack_trace '1' >&2 exit "$_GO_EC_ARGERR" fi - printf -v "$fd_var_reference" -- '%s' "$i" - return "$_GO_EC_OK" + printf -v "$fd_var_reference" -- '%s' "$i" && ec=0 || ec="$?" + if [[ "$ec" -ne 0 ]]; then + return $((_GO_EC_GENERR+ec)) + else + return "$_GO_EC_OK" + fi fi done echo "No file descriptors < $_GO_MAX_FILE_DESCRIPTORS available; failed at:" \ diff --git a/lib/fileutil b/lib/fileutil index a18612c..61ad798 100644 --- a/lib/fileutil +++ b/lib/fileutil @@ -340,7 +340,6 @@ _@go.set_source_files_for_copy_files_safely() { if [[ "${#__go_source_file_errors[@]}" -gt 0 ]]; then return "$_GO_EC_GENERR" - else - return "$_GO_EC_OK" fi + return "$_GO_EC_OK" } diff --git a/lib/internal/command_descriptions b/lib/internal/command_descriptions index 5266b19..247715a 100644 --- a/lib/internal/command_descriptions +++ b/lib/internal/command_descriptions @@ -19,7 +19,10 @@ _@go.format_summary() { printf -v summary " %-${longest_name_len}s %s\n" "$cmd_name" "$summary" if [[ "${#summary}" -le "$COLUMNS" ]]; then - printf "$summary" + printf "$summary" && ec=0 || ec="$?" + if [[ "$ec" -ne 0 ]]; then + return $((_GO_EC_GENERR+ec)) + fi return "$_GO_EC_OK" fi diff --git a/lib/internal/sysexits b/lib/internal/sysexits index 39b9264..eb6cd12 100644 --- a/lib/internal/sysexits +++ b/lib/internal/sysexits @@ -7,35 +7,35 @@ declare -r -x -i _GO_EC_OFFSET=0 declare -r -x -i _GO_EC_OK=0 -declare -r -x -i _GO_EC_USAGE=_GO_EC_OFFSET+64 +declare -r -x -i _GO_EC_GENERR=_GO_EC_OFFSET+64 +# A general error that is not covered by the other exit codes. + +declare -r -x -i _GO_EC_EXT1=_GO_EC_OFFSET+65 +# ??? + +declare -r -x -i _GO_EC_EXT2=_GO_EC_OFFSET+66 +# ??? + +declare -r -x -i _GO_EC_USAGE=_GO_EC_OFFSET+67 # The application was called with an invalid option, parameter, command, etc. # This error refers to end-user supplied input to the application, not wrong # function arguments, etc. -declare -r -x -i _GO_EC_DATAERR=_GO_EC_OFFSET+65 -# ??? - -declare -r -x -i _GO_EC_NOINPUT=_GO_EC_OFFSET+66 +declare -r -x -i _GO_EC_NOINPUT=_GO_EC_OFFSET+68 # Some input was expected but none was given. This refers to either expected # input from the user (eg via a prompt) or command/function input that is # empty (eg an empty file). -declare -r -x -i _GO_EC_BADFRMT=_GO_EC_OFFSET+67 +declare -r -x -i _GO_EC_BADFRMT=_GO_EC_OFFSET+69 # An argument or a file is not in the format expected. This is used in # validation errors or wrongly formatted files (eg scipts missing the shebang). # For bad arguments to functions, _GO_EC_ARGERR should be used. -declare -r -x -i _GO_EC_NOTFND=_GO_EC_OFFSET+68 +declare -r -x -i _GO_EC_NOTFND=_GO_EC_OFFSET+70 # A resource was not found. "Resource" might refer to some file/folder on the # filesystem. This return code should also be used by functions that perform a # search for the case that no result was found. -declare -r -x -i _GO_EC_UNAVAILABLE=_GO_EC_OFFSET+69 -# ??? - -declare -r -x -i _GO_EC_GENERR=_GO_EC_OFFSET+70 -# A general error that is not covered by the other exit codes. - declare -r -x -i _GO_EC_ARGERR=_GO_EC_OFFSET+71 # A function was passed an argument that is invalid. See also _GO_EC_BADFRMT. diff --git a/lib/kcov-ubuntu b/lib/kcov-ubuntu index f8b453c..ada0598 100644 --- a/lib/kcov-ubuntu +++ b/lib/kcov-ubuntu @@ -54,7 +54,7 @@ run_kcov() { if ! command -v apt-get >/dev/null; then @go.printf 'Coverage is only available on Linux platforms %s.\n' \ 'with apt-get' >&2 - return "$_GO_EC_UNAVAILABLE" + return "$_GO_EC_GENERR" elif [[ -d "$coverage_dir" ]]; then @go.printf '%s %s\n' "The $coverage_dir directory already exists." \ 'Please move or remove this directory first.' >&2 diff --git a/lib/testing/stack-trace b/lib/testing/stack-trace index c9a391d..5c84257 100644 --- a/lib/testing/stack-trace +++ b/lib/testing/stack-trace @@ -163,7 +163,10 @@ __@go.stack_trace_item() { case "$state" in SUCCESS) - printf ' %s:%d %s\n' "$filepath" "$lineno" "$function_name" + printf ' %s:%d %s\n' "$filepath" "$lineno" "$function_name" && ec=0 || ec="$?" + if [[ "$ec" -ne 0 ]]; then + return $((_GO_EC_GENERR+ec)) + fi return "$_GO_EC_OK" ;; MAIN|FOUND_FUNCTION) diff --git a/libexec/builtins b/libexec/builtins index 1e024bd..a99e14e 100755 --- a/libexec/builtins +++ b/libexec/builtins @@ -93,7 +93,7 @@ _@go.builtins() { return "$_GO_EC_USAGE" fi _@go.builtin_summaries - return "$_GO_EC_OK" + return ;; --exists) flag="$1" diff --git a/libexec/commands b/libexec/commands index bfbf311..6ea3ebb 100755 --- a/libexec/commands +++ b/libexec/commands @@ -136,7 +136,7 @@ _@go.commands() { if [[ "$1" == '--complete' ]]; then shift _@go.commands_tab_completions "$@" - return "$_GO_EC_OK" + return fi local __go_commands_action="list" diff --git a/libexec/complete b/libexec/complete index 19608bc..c31e5c0 100755 --- a/libexec/complete +++ b/libexec/complete @@ -85,42 +85,33 @@ _@go.complete_args() { printf -- '--help \n' ;; *) - @go.compgen -W "$(_@go.complete_top_level_commands)" -- "$cmd_name" && ec=0 || ec="$?" + @go.compgen -W "$(_@go.complete_top_level_commands)" -- "$cmd_name" ;; esac - if [[ "${ec-0}" -ne 0 ]]; then - return "$ec" - fi - return "$_GO_EC_OK" + return fi ec="unset" case "$cmd_name" in cd|pushd) - @go.compgen -d -- "$word" && ec=0 || ec="$?" + @go.compgen -d -- "$word" + return ;; edit|run) - @go.compgen -f -- "$word" && ec=0 || ec="$?" + @go.compgen -f -- "$word" + return ;; -h|-help|--help) cmd_name='help' ;; -*|unenv) - ec=1 + return "$_GO_EC_GENERR" ;; esac - if [[ "$ec" == '0' ]]; then - return "$_GO_EC_OK" - elif [[ "$ec" != "unset" ]]; then - return "$ec" - fi if _@go.source_builtin 'aliases' --exists "$cmd_name"; then @go.compgen -f -- "$word" && ec=0 || ec="$?" - if [[ "$ec" -ne 0 ]]; then - return "$ec" - fi - return "$_GO_EC_OK" + return fi unset 'args[0]' diff --git a/libexec/demo-core.d/select-option b/libexec/demo-core.d/select-option index dffe210..7f83a1f 100755 --- a/libexec/demo-core.d/select-option +++ b/libexec/demo-core.d/select-option @@ -35,7 +35,7 @@ select_option_demo() { if ! @go.prompt_for_yes_or_no 'Would you like to select another option?' \ 'yes'; then @go.printf 'Exiting...\n' - return "$_GO_EC_OK" + return fi done } diff --git a/libexec/env b/libexec/env index 9dc1506..cf93054 100755 --- a/libexec/env +++ b/libexec/env @@ -77,7 +77,7 @@ _@go.env() { ${eval_cmd//%s/$0} END_OF_HELP @go.printf "$help_msg\n" - return "$_GO_EC_OK" + return elif [[ "$go_func" == '-' ]]; then go_func="$default_name" fi diff --git a/libexec/fullpath b/libexec/fullpath index 9b2d628..d532f91 100755 --- a/libexec/fullpath +++ b/libexec/fullpath @@ -26,7 +26,7 @@ _@go.fullpath() { if [[ "$1" == '--complete' ]]; then shift _@go.fullpath_tab_completion "$@" - return "$_GO_EC_OK" + return fi local existing_only diff --git a/libexec/get.d/file b/libexec/get.d/file index 915d41a..dca7351 100755 --- a/libexec/get.d/file +++ b/libexec/get.d/file @@ -177,7 +177,7 @@ _@go.get_file() { --complete) # Tab completions _@go.get_file_tab_completions "${@:2}" - return "$_GO_EC_OK" + return ;; -f) filename="$2" diff --git a/libexec/get.d/git-repo b/libexec/get.d/git-repo index d85e6bb..acb6252 100755 --- a/libexec/get.d/git-repo +++ b/libexec/get.d/git-repo @@ -57,7 +57,7 @@ _@go.get_git_repo() { . "$_GO_USE_MODULES" 'complete' @go.compgen -f -- "$3" fi - return "$_GO_EC_OK" + return fi if [[ "$#" -ne '3' ]]; then diff --git a/libexec/glob b/libexec/glob index e9a2db8..0d8dd2c 100755 --- a/libexec/glob +++ b/libexec/glob @@ -186,7 +186,7 @@ _@go.glob_tab_completion() { echo "${__go_glob_flags[@]}" . "$_GO_USE_MODULES" 'complete' @go.compgen -d -- "$__go_glob_complete_word" - return "$_GO_EC_OK" + return fi local __go_glob_matches=() diff --git a/libexec/help b/libexec/help index fc9f30b..8611adc 100755 --- a/libexec/help +++ b/libexec/help @@ -135,7 +135,7 @@ _@go.help() { shift . "$_GO_CORE_DIR/lib/internal/complete" _@go.complete_command_path "$@" - return "$_GO_EC_OK" + return fi if [[ "$#" -eq '0' ]]; then diff --git a/libexec/modules b/libexec/modules index ccf7204..e174ea0 100755 --- a/libexec/modules +++ b/libexec/modules @@ -270,7 +270,7 @@ _@go.modules_tab_completion_plugins() { if [[ "$glob" =~ / ]]; then plugin="${glob%/*}" _@go.modules_find_all_in_dir "$1/$plugin" "${glob#*/}*" - return "$_GO_EC_OK" + return fi # Otherwise collect all plugin modules and the names of the plugins to diff --git a/libexec/new b/libexec/new index 56a3725..88d519d 100755 --- a/libexec/new +++ b/libexec/new @@ -60,7 +60,7 @@ _@go.new_tab_completions() { . "$_GO_CORE_DIR/lib/internal/complete" _@go.complete_command_path "$word_index" "$@" fi - return "$_GO_EC_OK" + return ;; --internal) if [[ "$word_index" -ne '0' ]] || ! cd "$_GO_SCRIPTS_DIR/lib"; then @@ -271,7 +271,7 @@ _@go.new() { --complete) # Tab completions _@go.new_tab_completions "$@" - return "$_GO_EC_OK" + return ;; --command) _@go.new_command_scripts "$@" diff --git a/libexec/path b/libexec/path index 517030e..5ba962c 100755 --- a/libexec/path +++ b/libexec/path @@ -15,7 +15,7 @@ _@go.path() { shift . "$_GO_CORE_DIR/lib/internal/complete" _@go.complete_command_path "$@" - return "$_GO_EC_OK" + return fi if [[ "$#" -ne '0' ]]; then diff --git a/scripts/changes b/scripts/changes index d888a80..cb149ff 100755 --- a/scripts/changes +++ b/scripts/changes @@ -19,7 +19,10 @@ _changes() { if [[ "$word_index" -gt 1 ]]; then return "$_GO_EC_GENERR" fi - git tag + git tag && ec=0 || ec="$?" + if [[ "$ec" -ne 0 ]]; then + return "$ec" + fi return "$_GO_EC_OK" fi diff --git a/tests/vars.bats b/tests/vars.bats index 5ae0d61..3bb3064 100644 --- a/tests/vars.bats +++ b/tests/vars.bats @@ -45,24 +45,24 @@ quotify_expected() { "declare -rx _GO_CORE_VERSION=\"$_GO_CORE_VERSION\"" "declare -x _GO_COVERALLS_URL=\"$_GO_COVERALLS_URL\"" 'declare -irx _GO_EC_ARGERR="71"' - 'declare -irx _GO_EC_BADFRMT="67"' + 'declare -irx _GO_EC_BADFRMT="69"' 'declare -irx _GO_EC_BASE="64"' 'declare -irx _GO_EC_CANTCREAT="73"' 'declare -irx _GO_EC_CONFIG="78"' - 'declare -irx _GO_EC_DATAERR="65"' 'declare -irx _GO_EC_DEPMISS="72"' - 'declare -irx _GO_EC_GENERR="70"' + 'declare -irx _GO_EC_EXT1="65"' + 'declare -irx _GO_EC_EXT2="66"' + 'declare -irx _GO_EC_GENERR="64"' 'declare -irx _GO_EC_IOERR="74"' 'declare -irx _GO_EC_MAX="78"' - 'declare -irx _GO_EC_NOINPUT="66"' + 'declare -irx _GO_EC_NOINPUT="68"' 'declare -irx _GO_EC_NOPERM="77"' - 'declare -irx _GO_EC_NOTFND="68"' + 'declare -irx _GO_EC_NOTFND="70"' 'declare -irx _GO_EC_OFFSET="0"' 'declare -irx _GO_EC_OK="0"' 'declare -irx _GO_EC_SIGN1="75"' 'declare -irx _GO_EC_SIGN2="76"' - 'declare -irx _GO_EC_UNAVAILABLE="69"' - 'declare -irx _GO_EC_USAGE="64"' + 'declare -irx _GO_EC_USAGE="67"' 'declare -a _GO_IMPORTED_MODULES=()' 'declare -a _GO_IMPORTED_MODULE_CALLERS=()' 'declare -a _GO_IMPORTED_MODULE_FILES=()' @@ -138,24 +138,24 @@ quotify_expected() { "declare -rx _GO_CORE_VERSION=\"$_GO_CORE_VERSION\"" "declare -x _GO_COVERALLS_URL=\"$_GO_COVERALLS_URL\"" "declare -irx _GO_EC_ARGERR=\"71\"" - "declare -irx _GO_EC_BADFRMT=\"67\"" + "declare -irx _GO_EC_BADFRMT=\"69\"" "declare -irx _GO_EC_BASE=\"64\"" "declare -irx _GO_EC_CANTCREAT=\"73\"" "declare -irx _GO_EC_CONFIG=\"78\"" - "declare -irx _GO_EC_DATAERR=\"65\"" "declare -irx _GO_EC_DEPMISS=\"72\"" - "declare -irx _GO_EC_GENERR=\"70\"" + "declare -irx _GO_EC_EXT1=\"65\"" + "declare -irx _GO_EC_EXT2=\"66\"" + "declare -irx _GO_EC_GENERR=\"64\"" "declare -irx _GO_EC_IOERR=\"74\"" "declare -irx _GO_EC_MAX=\"78\"" - "declare -irx _GO_EC_NOINPUT=\"66\"" + "declare -irx _GO_EC_NOINPUT=\"68\"" "declare -irx _GO_EC_NOPERM=\"77\"" - "declare -irx _GO_EC_NOTFND=\"68\"" + "declare -irx _GO_EC_NOTFND=\"70\"" "declare -irx _GO_EC_OFFSET=\"0\"" "declare -irx _GO_EC_OK=\"0\"" "declare -irx _GO_EC_SIGN1=\"75\"" "declare -irx _GO_EC_SIGN2=\"76\"" - "declare -irx _GO_EC_UNAVAILABLE=\"69\"" - "declare -irx _GO_EC_USAGE=\"64\"" + "declare -irx _GO_EC_USAGE=\"67\"" "declare -a _GO_IMPORTED_MODULES=(${expected_modules[*]})" "declare -a _GO_IMPORTED_MODULE_CALLERS=(${expected_module_callers[*]})" "declare -a _GO_IMPORTED_MODULE_FILES=(${expected_module_files[*]})" @@ -211,8 +211,9 @@ quotify_expected() { "_GO_EC_BASE: $_GO_EC_BASE" \ "_GO_EC_CANTCREAT: $_GO_EC_CANTCREAT" \ "_GO_EC_CONFIG: $_GO_EC_CONFIG" \ - "_GO_EC_DATAERR: $_GO_EC_DATAERR" \ "_GO_EC_DEPMISS: $_GO_EC_DEPMISS" \ + "_GO_EC_EXT1: $_GO_EC_EXT1" \ + "_GO_EC_EXT2: $_GO_EC_EXT2" \ "_GO_EC_GENERR: $_GO_EC_GENERR" \ "_GO_EC_IOERR: $_GO_EC_IOERR" \ "_GO_EC_MAX: $_GO_EC_MAX" \ @@ -223,7 +224,6 @@ quotify_expected() { "_GO_EC_OK: $_GO_EC_OK" \ "_GO_EC_SIGN1: $_GO_EC_SIGN1" \ "_GO_EC_SIGN2: $_GO_EC_SIGN2" \ - "_GO_EC_UNAVAILABLE: $_GO_EC_UNAVAILABLE" \ "_GO_EC_USAGE: $_GO_EC_USAGE" \ "_GO_KCOV_DIR: $_GO_KCOV_DIR" \ "_GO_ROOTDIR: $TEST_GO_ROOTDIR" \ From 769ee6bdc8cf00505ed9bd7059e0894fd39a5d6c Mon Sep 17 00:00:00 2001 From: Nikolaos Kakouros Date: Mon, 22 Jan 2018 14:30:40 +0100 Subject: [PATCH 16/16] Adds doc for new exti codes --- lib/internal/sysexits | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/internal/sysexits b/lib/internal/sysexits index eb6cd12..1a36761 100644 --- a/lib/internal/sysexits +++ b/lib/internal/sysexits @@ -11,10 +11,11 @@ declare -r -x -i _GO_EC_GENERR=_GO_EC_OFFSET+64 # A general error that is not covered by the other exit codes. declare -r -x -i _GO_EC_EXT1=_GO_EC_OFFSET+65 -# ??? - declare -r -x -i _GO_EC_EXT2=_GO_EC_OFFSET+66 -# ??? +# These should be used to return error codes from external commands. Eg when +# calling `compgen` or `printf`. Most of these commands exit with `1` on general +# error and `2` on usage error. Their return code should be captured in a +# a variable, eg `ec`, and returned as `return $((_GO_EC_GENERR+ec)). declare -r -x -i _GO_EC_USAGE=_GO_EC_OFFSET+67 # The application was called with an invalid option, parameter, command, etc.