diff options
| author | Paul Buetow <paul@buetow.org> | 2026-06-24 10:14:27 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-06-24 10:14:27 +0300 |
| commit | 7f7ae1bef10bcf186e21a3e923b9756a50ecf52b (patch) | |
| tree | 2aab70a937ced49d0a1198544b1d8e4985f2b940 /tests | |
| parent | 6b5281c14393290726442a7ddbfe7576ea203cfc (diff) | |
Fix: shell-quote rewritten TEMPLATE_DIR so spaced source paths source cleanly
init_config rewrote the TEMPLATE_DIR line via awk as a bare, unquoted literal
when running --init from a source checkout. A source-root path containing a
space (or any shell metacharacter) produced a config that aborts on source
under "set -euo pipefail": the value was word-split, truncating the path and
running its tail as a command (exit 127), leaving TEMPLATE_DIR empty and
breaking every subsequent action.
Emit the rewritten value as a single-quoted assignment, escaping any embedded
single quote as '\'', so the generated shuriken.conf round-trips through
sourcing regardless of spaces or single quotes. The non-rewrite path (installed
/etc/default/shuriken) is unchanged. Regenerated bin/shuriken via just build.
Tests: test_init and test_init_with_hash_in_source_path now assert the SOURCED
TEMPLATE_DIR (the real contract) instead of the literal line, and a new
test_init_with_space_in_source_path covers the spaced-path regression.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Diffstat (limited to 'tests')
| -rwxr-xr-x | tests/cli.sh | 51 |
1 files changed, 39 insertions, 12 deletions
diff --git a/tests/cli.sh b/tests/cli.sh index 2c784bc..320ab7e 100755 --- a/tests/cli.sh +++ b/tests/cli.sh @@ -166,8 +166,24 @@ test_version() { test::assert_contains 'This is Shuriken Version' "$output" } +# Sources a generated config under "set -euo pipefail" in an isolated subshell +# and prints the resulting TEMPLATE_DIR. This mirrors how load_configured_action +# consumes the config, so it both proves the file sources cleanly (the subshell +# would abort otherwise) and reports the value that actually takes effect after +# the shell parses any quoting. +test::sourced_template_dir() { + local -r config_file="$1"; shift + + ( + set -euo pipefail + # shellcheck disable=SC1090 + source "$config_file" + printf '%s\n' "$TEMPLATE_DIR" + ) +} + test_init() { - local config + local template_dir test::setup ( @@ -176,20 +192,22 @@ test_init() { "$TEST_SHURIKEN" --init >/dev/null test::assert_file_exists shuriken.conf ) - config=$(<"$TEST_TMPDIR/shuriken.conf") - test::assert_contains \ - "TEMPLATE_DIR=$TEST_REPO_ROOT/share/templates/default" \ - "$config" + template_dir=$(test::sourced_template_dir "$TEST_TMPDIR/shuriken.conf") + test "$template_dir" = "$TEST_REPO_ROOT/share/templates/default" test::teardown } -test_init_with_hash_in_source_path() { - local config +# Runs --init from a copy of the repo whose root path contains "marker", then +# asserts the generated config sources cleanly and that TEMPLATE_DIR resolves to +# the expected path with the marker preserved. Shared by the # and space cases. +test::assert_init_rewrites_template_dir() { + local -r marker="$1"; shift local output_dir local repo_dir + local template_dir test::setup - repo_dir="$TEST_TMPDIR/repo#with-hash" + repo_dir="$TEST_TMPDIR/repo$marker" output_dir="$TEST_TMPDIR/output" mkdir -p "$repo_dir" "$output_dir" cp -R \ @@ -204,13 +222,19 @@ test_init_with_hash_in_source_path() { "$repo_dir/bin/shuriken" --init >/dev/null test::assert_file_exists shuriken.conf ) - config=$(<"$output_dir/shuriken.conf") - test::assert_contains \ - "TEMPLATE_DIR=$repo_dir/share/templates/default" \ - "$config" + template_dir=$(test::sourced_template_dir "$output_dir/shuriken.conf") + test "$template_dir" = "$repo_dir/share/templates/default" test::teardown } +test_init_with_hash_in_source_path() { + test::assert_init_rewrites_template_dir '#with-hash' +} + +test_init_with_space_in_source_path() { + test::assert_init_rewrites_template_dir ' with space' +} + test_init_existing_config_fails_without_overwrite() { local output @@ -6407,6 +6431,9 @@ main() { '--init succeeds when source path contains #' \ test_init_with_hash_in_source_path test::run_case \ + '--init succeeds when source path contains a space' \ + test_init_with_space_in_source_path + test::run_case \ '--init refuses existing config without overwrite' \ test_init_existing_config_fails_without_overwrite test::run_case \ |
