Skip to content

Commit

Permalink
Merge pull request #8 from mbland/cmd-name-argv
Browse files Browse the repository at this point in the history
Export _GO_CMD_{NAME,ARGV}, add Bash test
  • Loading branch information
mbland committed Nov 11, 2016
2 parents d674191 + 202b17c commit 87ce40a
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 9 deletions.
27 changes: 24 additions & 3 deletions go-core.bash
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,19 @@ declare -r -x _GO_SCRIPT="$_GO_ROOTDIR/${0##*/}"
# The name of either the ./go script itself or the shell function invoking it.
declare -r -x _GO_CMD="${_GO_CMD:=$0}"

# The array of command line arguments comprising the ./go command name after
# _GO_CMD.
#
# When exported to scripts not written in bash, the array is converted to a
# string with the components delimited by the ASCII NUL character ($'\0').
declare -x _GO_CMD_NAME=

# The array of command line arguments for the ./go command after _GO_CMD_NAME.
#
# When exported to scripts not written in bash, the array is converted to a
# string with the arguments delimited by the ASCII NUL character ($'\0').
declare -x _GO_CMD_ARGV=

# The URL of the framework's original source repository.
declare -r -x _GO_CORE_URL='https://github.com/mbland/go-script-bash'

Expand Down Expand Up @@ -162,6 +175,7 @@ declare -r -x _GO_CORE_URL='https://github.com/mbland/go-script-bash'

. "$_GO_CORE_DIR/lib/internal/path"
local __go_cmd_path
local __go_cmd_name
local __go_argv

if ! _@go.set_command_path_and_argv "$cmd" "$@"; then
Expand Down Expand Up @@ -197,12 +211,19 @@ _@go.run_command_script() {
interpreter="${interpreter%% *}"

if [[ "$interpreter" == 'bash' || "$interpreter" == 'sh' ]]; then
_GO_CMD_NAME=("${__go_cmd_name[@]}")
_GO_CMD_ARGV=("$@")
. "$cmd_path" "$@"
elif [[ -n "$interpreter" ]]; then
"$interpreter" "$cmd_path" "$@"
else
elif [[ -z "$interpreter" ]]; then
@go.printf "Could not parse interpreter from first line of $cmd_path.\n" >&2
return 1
else
local origIFS="$IFS"
local IFS=$'\0'
_GO_CMD_NAME="${__go_cmd_name[*]}"
_GO_CMD_ARGV="$*"
IFS="$origIFS"
"$interpreter" "$cmd_path" "$@"
fi
}

Expand Down
2 changes: 2 additions & 0 deletions lib/internal/path
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ _@go.set_command_path_and_argv() {
fi

local cmd_arg_index=1
__go_cmd_name=("$cmd_name")

for arg in "${cmd_args[@]}"; do
# This is most likely to happen during argument completion.
Expand All @@ -76,6 +77,7 @@ _@go.set_command_path_and_argv() {
return 1
fi

__go_cmd_name+=("$arg")
cmd_path="$try_path"
unset "cmd_args[$((cmd_arg_index++))]"
done
Expand Down
37 changes: 36 additions & 1 deletion tests/core/run-command-script.bats
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,39 @@ teardown() {
assert_success 'Can use @go.printf'
}

@test "$SUITE: _GO_* variables are set" {
local script=(
'. "$_GO_USE_MODULES" "complete" "format"'
'local array_decl_pattern="declare -a"'
'for go_var in "${!_GO_@}"; do'
' # Tip from https://stackoverflow.com/questions/14525296/#27254437'
' if [[ "$(declare -p "$go_var")" =~ $array_decl_pattern ]]; then'
' local arr_ref="$go_var[*]"'
' local IFS=,'
' echo "$go_var: ${!arr_ref}"'
' else'
' echo "$go_var: ${!go_var}"'
' fi'
'done')

local expected=("_GO_CMD: $TEST_GO_SCRIPT"
"_GO_CMD_ARGV: foo,bar,baz quux,xyzzy"
"_GO_CMD_NAME: test-command"
"_GO_CORE_DIR: $_GO_CORE_DIR"
"_GO_CORE_URL: $_GO_CORE_URL"
"_GO_IMPORTED_MODULES: complete,format"
"_GO_ROOTDIR: $TEST_GO_ROOTDIR"
"_GO_SCRIPT: $TEST_GO_SCRIPT"
"_GO_SCRIPTS_DIR: $TEST_GO_SCRIPTS_DIR"
"_GO_SEARCH_PATHS: $_GO_CORE_DIR/libexec,$TEST_GO_SCRIPTS_DIR"
"_GO_USE_MODULES: $_GO_CORE_DIR/lib/internal/use")

create_test_command_script 'test-command' "${script[@]}"
run "$TEST_GO_SCRIPT" test-command foo bar 'baz quux' xyzzy
local IFS=$'\n'
assert_success "${expected[*]}"
}

# Since Bash scripts are sourced, and have access to these variables regardless,
# we use Perl to ensure they are are exported to new processes that run command
# scripts in languages other than Bash.
Expand All @@ -50,14 +83,16 @@ teardown() {
'}')

local expected=("_GO_CMD: $TEST_GO_SCRIPT"
"_GO_CMD_ARGV: foo"$'\0'"bar"$'\0'"baz quux"$'\0'"xyzzy"
"_GO_CMD_NAME: test-command"
"_GO_CORE_DIR: $_GO_CORE_DIR"
"_GO_CORE_URL: $_GO_CORE_URL"
"_GO_ROOTDIR: $TEST_GO_ROOTDIR"
"_GO_SCRIPT: $TEST_GO_SCRIPT"
"_GO_SCRIPTS_DIR: $TEST_GO_SCRIPTS_DIR")

create_test_command_script 'test-command' "${script[@]}"
run "$TEST_GO_SCRIPT" test-command
run "$TEST_GO_SCRIPT" test-command foo bar 'baz quux' xyzzy
local IFS=$'\n'
assert_success "${expected[*]}"
}
Expand Down
15 changes: 10 additions & 5 deletions tests/path/set-path-and-argv.bats
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ setup() {
' exit 1' \
'fi' \
'echo "PATH: $__go_cmd_path"' \
'echo "ARGV: ${__go_argv[@]}"'
'echo "NAME: ${__go_cmd_name[*]}"' \
'echo "ARGV: ${__go_argv[*]}"'
}

teardown() {
Expand All @@ -33,7 +34,8 @@ teardown() {
run "$TEST_GO_SCRIPT" "${builtin_cmd##*/}" '--exists' 'ls'
assert_success
assert_line_equals 0 "PATH: $builtin_cmd"
assert_line_equals 1 'ARGV: --exists ls'
assert_line_equals 1 "NAME: ${builtin_cmd##*/}"
assert_line_equals 2 'ARGV: --exists ls'
}

@test "$SUITE: list available commands if command not found" {
Expand All @@ -53,7 +55,8 @@ teardown() {
run "$TEST_GO_SCRIPT" 'foobar' 'baz' 'quux'
assert_success
assert_line_equals 0 "PATH: $TEST_GO_SCRIPTS_DIR/foobar"
assert_line_equals 1 'ARGV: baz quux'
assert_line_equals 1 'NAME: foobar'
assert_line_equals 2 'ARGV: baz quux'
}

@test "$SUITE: empty string argument is not an error" {
Expand All @@ -64,7 +67,8 @@ teardown() {
run "$TEST_GO_SCRIPT" 'foobar' '' 'baz' 'quux'
assert_success
assert_line_equals 0 "PATH: $TEST_GO_SCRIPTS_DIR/foobar"
assert_line_equals 1 'ARGV: baz quux'
assert_line_equals 1 'NAME: foobar'
assert_line_equals 2 'ARGV: baz quux'
}

@test "$SUITE: error if top-level command name is a directory" {
Expand Down Expand Up @@ -95,7 +99,8 @@ teardown() {
run "$TEST_GO_SCRIPT" 'foobar' 'baz' 'quux'
assert_success
assert_line_equals 0 "PATH: $TEST_GO_SCRIPTS_DIR/foobar.d/baz"
assert_line_equals 1 'ARGV: quux'
assert_line_equals 1 'NAME: foobar baz'
assert_line_equals 2 'ARGV: quux'
}

@test "$SUITE: error if subcommand name is a directory" {
Expand Down

0 comments on commit 87ce40a

Please sign in to comment.