From 260c91dbec198926607d48a1a9a131fdb67a7400 Mon Sep 17 00:00:00 2001 From: Yusuf Kandemir Date: Tue, 19 May 2026 23:17:16 +0300 Subject: [PATCH] fix: preserve argv boundaries in spin run and spin exec filter_out_spin_arguments returned its result via echo (space-joined, unquoted) and the caller word-split it back on IFS, destroying any argument containing whitespace. `spin run --quiet php php -r 'echo "hi";'` reached PHP as `echo` + `"hi";` (two tokens), causing parse errors. --- AGENTS.md | 15 +++++++++------ lib/actions/exec.sh | 2 +- lib/actions/run.sh | 3 ++- lib/functions.sh | 20 ++++++++++++-------- 4 files changed, 24 insertions(+), 16 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index ad0730a5..0aebedd0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -176,9 +176,10 @@ docker run --rm \ # lib/actions/example.sh #!/usr/bin/env bash action_example() { - local args=($(filter_out_spin_arguments "$@")) - - # Implementation here + filter_out_spin_arguments "$@" + local args=("${SPIN_FILTERED_ARGS[@]}") + + # Implementation here, using "${args[@]}" for the filtered arguments echo "Running example command" } ``` @@ -238,9 +239,11 @@ SPIN_ENV=production spin deploy production ### Argument Filtering ```bash -# Remove Spin-specific arguments before passing to Docker -local args=($(filter_out_spin_arguments "$@")) -$COMPOSE_CMD up ${args[@]} +# Remove Spin-specific arguments before passing to Docker. The filtered +# args are returned via the SPIN_FILTERED_ARGS global. +filter_out_spin_arguments "$@" +local args=("${SPIN_FILTERED_ARGS[@]}") +$COMPOSE_CMD up "${args[@]}" ``` ### Cache Management diff --git a/lib/actions/exec.sh b/lib/actions/exec.sh index 6b2d72c2..ef1e2291 100755 --- a/lib/actions/exec.sh +++ b/lib/actions/exec.sh @@ -1,4 +1,4 @@ #!/usr/bin/env bash action_exec(){ - $COMPOSE_CMD exec $@ + $COMPOSE_CMD exec "$@" } \ No newline at end of file diff --git a/lib/actions/run.sh b/lib/actions/run.sh index 02c60975..7d99cd89 100755 --- a/lib/actions/run.sh +++ b/lib/actions/run.sh @@ -2,7 +2,8 @@ action_run(){ docker_pull_check "$@" - local args=($(filter_out_spin_arguments "$@")) + filter_out_spin_arguments "$@" + local args=("${SPIN_FILTERED_ARGS[@]}") # Run Docker Compose without dependencies. Ensure automations and S6 logging are disabled $COMPOSE_CMD run -e "S6_VERBOSITY=0" -e "SHOW_WELCOME_MESSAGE=false" --remove-orphans --no-deps --rm \ diff --git a/lib/functions.sh b/lib/functions.sh index bcc7f1b1..a7ff802d 100755 --- a/lib/functions.sh +++ b/lib/functions.sh @@ -459,15 +459,22 @@ export_compose_file_variable(){ fi } +# Filters spin-only flags out of "$@". Returns the remaining arguments via +# the SPIN_FILTERED_ARGS global. bash can't return arrays through stdout +# without IFS word-splitting destroying argument boundaries at the call site. +# +# Example usage: +# filter_out_spin_arguments "$@" +# local args=("${SPIN_FILTERED_ARGS[@]}") +# $COMPOSE_CMD run ... "${args[@]}" filter_out_spin_arguments() { - non_docker_args=( + SPIN_FILTERED_ARGS=() + + local non_docker_args=( "--skip-pull" "--force-pull" ) - # Declare an array to hold the filtered arguments - local filtered_args=() - # Loop through all passed arguments for arg in "$@"; do local is_non_docker_arg=false @@ -479,12 +486,9 @@ filter_out_spin_arguments() { done if ! $is_non_docker_arg; then - filtered_args+=("$arg") + SPIN_FILTERED_ARGS+=("$arg") fi done - - # Return the filtered arguments as an array - echo "${filtered_args[@]}" } get_ansible_variable(){