Skip to content
Open
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
5 changes: 4 additions & 1 deletion .github/instructions/bash.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,10 @@ set -uo pipefail;
word-splitting
3. **Double-quoted traps:** `trap "rm ${var}" EXIT` expands at definition time.
Use functions or single quotes.
4. **`$@` in for-loops:** Always quote: `for arg in "$@"`
4. **`$@` in for-loops:** Use `for arg; do`, which iterates `"$@"` without
expanding it. Unquoted `$@` word-splits, and quoted `"$@"` is an unbound
variable under `set -u` on Bash 3.2 (macOS `/bin/bash`) when there are
no arguments.
5. **Regex anchoring:** `^1.1` matches `1.10.x` because `.` is a regex
wildcard. Use `^1\.1\.` for exact prefix matching.

Expand Down
5 changes: 4 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,10 @@ These are the most frequent sources of bugs. Check for them in every change:
conditions, and assignments. Unquoted variables cause word-splitting.
3. **Double-quoted traps:** `trap "rm ${var}" EXIT` expands at definition
time and is vulnerable to word-splitting. Use functions or single quotes.
4. **`$@` in for-loops:** Always quote: `for arg in "$@"`.
4. **`$@` in for-loops:** Use `for arg; do`, which iterates `"$@"` without
expanding it. Unquoted `$@` word-splits, and quoted `"$@"` is an unbound
variable under `set -u` on Bash 3.2 (macOS `/bin/bash`) when there are
no arguments.
5. **Regex anchoring:** `^1.1` matches `1.10.x` because `.` is a regex
wildcard. Use `^1\.1\.` for exact prefix matching.
6. **Cross-platform differences:** macOS uses BSD `sed`/`grep`/`readlink`.
Expand Down
5 changes: 4 additions & 1 deletion lib/tfenv-exec.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ function realpath-relative-to() {
export -f realpath-relative-to;

function tfenv-exec() {
for _arg in "${@}"; do
# `for _arg; do` iterates "$@" without expanding it. Bash 3.2 (macOS /bin/bash)
# treats "$@" as unbound under `set -u` when there are no arguments, and
# zsh's bashcompinit runs `complete -C` commands with no arguments (#532).
for _arg; do
if [[ "${_arg}" == -chdir=* ]]; then
chdir="${_arg#-chdir=}";
log 'debug' "Found -chdir arg: ${chdir}";
Expand Down
50 changes: 50 additions & 0 deletions test/test_exec.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#!/usr/bin/env bash

# Source common test setup
source "$(dirname "${0}")/test_common.sh";

#####################
# Begin Script Body #
#####################

declare -a errors=();

log 'info' '### Test Suite: terraform shim (tfenv-exec)';

cleanup || log 'error' 'Cleanup failed?!';
tfenv install 1.6.1 || early_death 'Failed to install 1.6.1 for shim tests';
tfenv use 1.6.1 || early_death 'Failed to use 1.6.1 for shim tests';

# zsh's bashcompinit runs `complete -C` commands with no arguments, and Bash 3.2
# (macOS /bin/bash) treats "$@" as unbound under `set -u` when it is empty (#532).
# Run the shim under each available bash so the system bash is exercised on macOS
# even when a newer bash is first on PATH.
for shell in bash /bin/bash; do
command -v "${shell}" >/dev/null 2>&1 || continue;
log 'info' "## terraform (no args) under ${shell}: passes through to terraform usage";
(
declare output;
output="$("${shell}" "${TFENV_ROOT}/bin/terraform" 2>&1 || true)";
echo "${output}" | grep -q 'unbound variable' && exit 1;
echo "${output}" | grep -q 'Usage: terraform' || exit 1;
) && log 'info' "## terraform (no args) under ${shell}: passed" \
|| error_and_proceed "terraform with no args under ${shell} did not reach terraform usage";
done;

log 'info' '## terraform -chdir with a space in the path: argument is not word-split';
cleanup || log 'error' 'Cleanup failed?!';
(
echo '1.6.1' > .terraform-version;
mkdir -p 'chdir-dir/with space';
echo '1.6.0' > 'chdir-dir/with space/.terraform-version';
declare output;
output="$(terraform '-chdir=chdir-dir/with space' version 2>&1)" || exit 1;
echo "${output}" | grep -q 'Terraform v1.6.0' || exit 1;
) && log 'info' '## terraform -chdir with a space in the path: passed' \
|| error_and_proceed 'terraform -chdir with a space in the path did not resolve the version from that directory';

cleanup || log 'error' 'Cleanup failed?!';

finish_tests 'exec';

exit 0;