Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions go-core.bash
Original file line number Diff line number Diff line change
Expand Up @@ -248,9 +248,6 @@ declare _GO_INJECT_MODULE_PATH="$_GO_INJECT_MODULE_PATH"
@go.search_plugins() {
local __gsp_plugins_dir="$_GO_SCRIPTS_DIR/plugins"

# Set `_GO_PLUGINS_DIR` if called from a top-level `./go` script before `@go`.
_GO_PLUGINS_DIR="${_GO_PLUGINS_DIR:-$_GO_SCRIPTS_DIR/plugins}"

while true; do
if "$1" "$__gsp_plugins_dir"; then
return
Expand Down Expand Up @@ -412,3 +409,4 @@ elif [[ -z "$COLUMNS" ]]; then
fi
export COLUMNS="${COLUMNS:-80}"
fi
_GO_PLUGINS_DIR="$_GO_SCRIPTS_DIR/plugins"
2 changes: 1 addition & 1 deletion lib/bats-main
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export _GO_COVERALLS_URL="${_GO_COVERALLS_URL}"

# Collect coverage on Travis. Doesn't seem to slow anything down substantially.
if [[ -n "$_GO_COVERALLS_URL" && "$TRAVIS_OS_NAME" == 'linux' ]]; then
declare _GO_COLLECT_BATS_COVERAGE='true'
_GO_COLLECT_BATS_COVERAGE='true'
fi

# Array of `./go glob` arguments to select Bats test files in `_GO_TEST_DIR`
Expand Down
34 changes: 1 addition & 33 deletions lib/internal/path
Original file line number Diff line number Diff line change
@@ -1,38 +1,6 @@
#! /bin/bash

_@go.set_search_paths_add_plugin_paths() {
local plugin_paths=("$1"/*/bin)
if [[ "${plugin_paths[0]}" != "$1/*/bin" ]]; then
_GO_PLUGINS_PATHS+=("${plugin_paths[@]}")
fi
return 1
}

_@go.set_search_paths() {
local plugin_path

if [[ -n "$_GO_INJECT_SEARCH_PATH" ]]; then
_GO_SEARCH_PATHS+=("$_GO_INJECT_SEARCH_PATH")
fi
_GO_SEARCH_PATHS+=("$_GO_CORE_DIR/libexec" "$_GO_SCRIPTS_DIR")

# A plugin's own local plugin paths will appear before inherited ones. If
# there is a version incompatibility issue with other installed plugins, this
# allows a plugin's preferred version to take precedence.
@go.search_plugins '_@go.set_search_paths_add_plugin_paths'

# Ensure a plugin's _GO_SCRIPTS_DIR isn't duplicated in _GO_SEARCH_PATHS.
for plugin_path in "${_GO_PLUGINS_PATHS[@]}"; do
if [[ "$plugin_path" != "$_GO_SCRIPTS_DIR" ]]; then
_GO_SEARCH_PATHS+=("$plugin_path")
fi
done
}

if [[ "${#_GO_SEARCH_PATHS[@]}" -eq 0 ]]; then
_GO_PLUGINS_DIR="$_GO_SCRIPTS_DIR/plugins"
_@go.set_search_paths
fi
. "$_GO_CORE_DIR/lib/internal/set-search-paths"

_@go.list_available_commands() {
. "$_GO_CORE_DIR/lib/internal/commands"
Expand Down
35 changes: 35 additions & 0 deletions lib/internal/set-search-paths
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#! /bin/bash

_@go.set_search_paths_add_plugin_paths() {
local plugin_paths=("$1"/*/bin)
local plugin_path

if [[ "${plugin_paths[0]}" != "$1/*/bin" ]]; then
# Ensure a plugin's _GO_SCRIPTS_DIR isn't duplicated in _GO_PLUGINS_PATHS.
for plugin_path in "${plugin_paths[@]}"; do
if [[ "$plugin_path" != "$_GO_SCRIPTS_DIR" ]]; then
_GO_PLUGINS_PATHS+=("$plugin_path")
fi
done
fi
return 1
}

_@go.set_search_paths() {
local plugin_path

if [[ -n "$_GO_INJECT_SEARCH_PATH" ]]; then
_GO_SEARCH_PATHS+=("$_GO_INJECT_SEARCH_PATH")
fi
_GO_SEARCH_PATHS+=("$_GO_CORE_DIR/libexec" "$_GO_SCRIPTS_DIR")

# A plugin's own local plugin paths will appear before inherited ones. If
# there is a version incompatibility issue with other installed plugins, this
# allows a plugin's preferred version to take precedence.
@go.search_plugins '_@go.set_search_paths_add_plugin_paths'
_GO_SEARCH_PATHS+=("${_GO_PLUGINS_PATHS[@]}")
}

if [[ "${#_GO_SEARCH_PATHS[@]}" -eq 0 ]]; then
_@go.set_search_paths
fi
169 changes: 80 additions & 89 deletions lib/internal/use
Original file line number Diff line number Diff line change
Expand Up @@ -73,115 +73,106 @@
# for modules imported within a Bash command script or function:
# @go modules --imported

declare __go_module_name
declare __go_module_file
declare __go_loaded_module
declare __go_loaded_file
declare __go_module_index
declare __go_use_caller
declare __go_use_prev_caller

# Wrapper function necessary due to BASH_SOURCE and FUNCNAME bug in Bash <4.3.
_@go.set_use_caller() {
__go_use_caller="${BASH_SOURCE[2]}:${BASH_LINENO[1]} ${FUNCNAME[2]}"
}

_@go.find_plugin_module() {
[[ -f "$1/$__go_module_file" ]] && __go_module_file="$1/$__go_module_file"
}

_@go.find_module() {
# If a script imports a plugin module, and that module (`__go_use_caller`)
# tries to import another module from the same plugin, this block will adjust
# the search parameters accordingly.
if [[ -n "$_GO_PLUGINS_DIR" &&
"$__go_use_caller" =~ ^$_GO_PLUGINS_DIR/.*/lib/ ]]; then
local _GO_SCRIPTS_DIR="${__go_use_caller%/lib/*}/bin"
local _GO_ROOTDIR="${_GO_SCRIPTS_DIR%/bin}"
if [[ -n "$_GO_INJECT_MODULE_PATH" ]]; then
__go_module_file="$_GO_INJECT_MODULE_PATH/$__go_module_name"
if [[ -f "$__go_module_file" ]]; then
return
fi
fi
__go_module_file="$_GO_SCRIPTS_DIR/lib/$__go_module_name"
__go_module_file="$_GO_CORE_DIR/lib/$__go_module_name"

if [[ ! -f "$__go_module_file" ]]; then
__go_module_file="$_GO_ROOTDIR/lib/$__go_module_name"
__go_module_file="$_GO_SCRIPTS_DIR/lib/$__go_module_name"

if [[ ! -f "$__go_module_file" ]]; then
# Convert <plugin>/<module> to plugins/<plugin>/lib/<module>
__go_module_file="${__go_module_name/\///lib/}"
@go.search_plugins '_@go.find_plugin_module'
__go_module_file="$_GO_ROOTDIR/lib/$__go_module_name"

if [[ ! -f "$__go_module_file" ]]; then
# Convert <plugin>/<module> to plugins/<plugin>/lib/<module>
__go_module_file="${__go_module_name/\///lib/}"
@go.search_plugins '_@go.find_plugin_module'
fi
fi
fi
}

for __go_module_name in "$@"; do
# Since every import is in the same scope, setting the caller each time is
# necessary in case any imported modules import other modules.
_@go.set_use_caller
__go_module_file="$_GO_CORE_DIR/lib/$__go_module_name"

if [[ -n "$_GO_INJECT_MODULE_PATH" ]]; then
__go_module_file="$_GO_INJECT_MODULE_PATH/$__go_module_name"
if [[ ! -f "$__go_module_file" ]]; then
__go_module_file="$_GO_CORE_DIR/lib/$__go_module_name"
fi
_@go.import_module() {
if [[ "${__go_module_file#$_GO_SCRIPTS_DIR}" =~ /plugins/[^/]+/lib/ ]]; then
local _GO_SCRIPTS_DIR="${__go_module_file%/lib/*}/bin"
local _GO_ROOTDIR="${_GO_SCRIPTS_DIR%/bin}"
local _GO_PLUGINS_PATHS=()
local _GO_SEARCH_PATHS=()
fi

if [[ ! -f "$__go_module_file" ]] && ! _@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
fi
# Prevent self- and circular importing by registering info before sourcing.
_GO_IMPORTED_MODULES+=("$__go_module_name")
_GO_IMPORTED_MODULE_FILES+=("$__go_module_file")
_GO_IMPORTED_MODULE_CALLERS+=("$current_caller")
. "$__go_module_file"
}

# If we found the module in our project, but we're installed as a plugin,
# change the loaded module name to reflect that.
#
# Using `##` to trim the string instead of `#` flattens the module name
# namespace. We could use `#` to keep it hierarchical, but since the Bash
# namespace itself is flat, this might lead to hard-to-debug collisions if
# functions and variables get redefined. Keeping a flat module name namespace
# allows us to detect such potential collisions and issue a warning below.
if [[ -n "$_GO_PLUGINS_DIR" &&
"$__go_module_file" =~ ^$_GO_PLUGINS_DIR ]]; then
__go_module_name="${__go_module_file##*/plugins/}"
__go_module_name="${__go_module_name/\/bin\///}"
__go_module_name="${__go_module_name/\/lib\///}"
fi
_@go.use_modules() {
local __go_module_name
local __go_module_file
local loaded_module
local loaded_file
local module_index
local current_caller="${BASH_SOURCE[2]}:${BASH_LINENO[1]} ${FUNCNAME[2]}"
local prev_caller

__go_module_index=0
for __go_loaded_module in "${_GO_IMPORTED_MODULES[@]}"; do
if [[ "$__go_module_name" == "$__go_loaded_module" ]]; then
__go_loaded_file="${_GO_IMPORTED_MODULE_FILES[$__go_module_index]}"
__go_use_prev_caller="${_GO_IMPORTED_MODULE_CALLERS[$__go_module_index]}"
for __go_module_name in "$@"; do
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
fi

# This may happen if a plugin appears more than once in a project tree.
if [[ "$__go_module_file" != "$__go_loaded_file" ]]; then
@go.printf '%s\n' "WARNING: Module: $__go_module_name" \
"imported at: $__go_use_caller" \
"from file: $__go_module_file" \
"previously imported at: $__go_use_prev_caller" \
"from file: $__go_loaded_file" >&2
fi
continue 2
# If we found the module in our project, but we're installed as a plugin,
# change the loaded module name to reflect that.
#
# Using `##` to trim the string instead of `#` flattens the module name
# namespace. We could use `#` to keep it hierarchical, but since the Bash
# namespace itself is flat, this might lead to hard-to-debug collisions if
# functions and variables get redefined. Keeping a flat module name
# namespace allows us to detect such potential collisions and issue a
# warning below.
if [[ "$__go_module_file" =~ ^$_GO_PLUGINS_DIR/ ]]; then
__go_module_name="${__go_module_file##*/plugins/}"
__go_module_name="${__go_module_name/\/bin\///}"
__go_module_name="${__go_module_name/\/lib\///}"
fi
((++__go_module_index))
done

# Prevent self- and circular importing by registering info before sourcing.
_GO_IMPORTED_MODULES+=("$__go_module_name")
_GO_IMPORTED_MODULE_FILES+=("$__go_module_file")
_GO_IMPORTED_MODULE_CALLERS+=("$__go_use_caller")
module_index=0
for loaded_module in "${_GO_IMPORTED_MODULES[@]}"; do
if [[ "$__go_module_name" == "$loaded_module" ]]; then
loaded_file="${_GO_IMPORTED_MODULE_FILES[$module_index]}"
prev_caller="${_GO_IMPORTED_MODULE_CALLERS[$module_index]}"

if ! . "$__go_module_file"; then
@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
fi
done
# This may happen if a plugin appears more than once in a project tree.
if [[ "$__go_module_file" != "$loaded_file" ]]; then
@go.printf '%s\n' "WARNING: Module: $__go_module_name" \
"imported at: $current_caller" \
"from file: $__go_module_file" \
"previously imported at: $prev_caller" \
"from file: $loaded_file" >&2
fi
continue 2
fi
((++module_index))
done

if ! _@go.import_module; then
@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
fi
done
}

unset __go_use_prev_caller
unset __go_use_caller
unset __go_module_index
unset __go_loaded_file
unset __go_loaded_module
unset __go_module_file
unset __go_module_name
_@go.use_modules "$@"
3 changes: 2 additions & 1 deletion lib/kcov-ubuntu
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
# This may eventually be extracted into a plugin library of its own, which is
# why its exported functions don't contain a `@go.` prefix.

readonly __KCOV_DEV_PACKAGES=(
__KCOV_DEV_PACKAGES=(
'binutils-dev'
'cmake'
'libcurl4-openssl-dev'
Expand All @@ -18,6 +18,7 @@ readonly __KCOV_DEV_PACKAGES=(
'libiberty-dev'
'zlib1g-dev'
)
readonly __KCOV_DEV_PACKAGES
readonly __KCOV_URL='https://github.com/SimonKagstrom/kcov'
readonly __KCOV_VERSION='master'

Expand Down
5 changes: 0 additions & 5 deletions tests/core/plugin-scope-variable-values.bats
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ assert_scope_values_equal() {
'_GO_SCRIPTS_DIR:' \
"$TEST_GO_PLUGINS_DIR/first/bin" \
'_GO_PLUGINS_PATHS:' \
"$TEST_GO_PLUGINS_DIR/first/bin" \
"$TEST_GO_PLUGINS_DIR/second/bin" \
'_GO_SEARCH_PATHS:' \
"$_GO_CORE_DIR/libexec" \
Expand All @@ -131,7 +130,6 @@ assert_scope_values_equal() {
'_GO_SCRIPTS_DIR:' \
"$TEST_GO_PLUGINS_DIR/second/bin/plugins/third/bin" \
'_GO_PLUGINS_PATHS:' \
"$TEST_GO_PLUGINS_DIR/second/bin/plugins/third/bin" \
"$TEST_GO_PLUGINS_DIR/first/bin" \
"$TEST_GO_PLUGINS_DIR/second/bin" \
'_GO_SEARCH_PATHS:' \
Expand All @@ -151,7 +149,6 @@ assert_scope_values_equal() {
'_GO_PLUGINS_PATHS:' \
"$TEST_GO_PLUGINS_DIR/second/bin/plugins/third/bin" \
"$TEST_GO_PLUGINS_DIR/first/bin" \
"$TEST_GO_PLUGINS_DIR/second/bin" \
'_GO_SEARCH_PATHS:' \
"$_GO_CORE_DIR/libexec" \
"$TEST_GO_PLUGINS_DIR/second/bin" \
Expand All @@ -173,7 +170,6 @@ assert_scope_values_equal() {
'_GO_SCRIPTS_DIR:' \
"$TEST_GO_PLUGINS_DIR/first/bin" \
'_GO_PLUGINS_PATHS:' \
"$TEST_GO_PLUGINS_DIR/first/bin" \
"$TEST_GO_PLUGINS_DIR/second/bin" \
'_GO_SEARCH_PATHS:' \
"$_GO_CORE_DIR/libexec" \
Expand All @@ -189,7 +185,6 @@ assert_scope_values_equal() {
'_GO_PLUGINS_PATHS:' \
"$TEST_GO_PLUGINS_DIR/second/bin/plugins/third/bin" \
"$TEST_GO_PLUGINS_DIR/first/bin" \
"$TEST_GO_PLUGINS_DIR/second/bin" \
'_GO_SEARCH_PATHS:' \
"$_GO_CORE_DIR/libexec" \
"$TEST_GO_PLUGINS_DIR/second/bin" \
Expand Down
Loading