@@ -51,7 +51,22 @@ function common::parse_cmdline {
5151 case $argv in
5252 -a | --args)
5353 shift
54- ARGS+=(" $1 " )
54+ # `argv` is an string from array with content like:
55+ # ('provider aws' '--version "> 0.14"' '--ignore-path "some/path"')
56+ # where each element is the value of each `--args` from hook config.
57+ # `echo` prints contents of `argv` as an expanded string
58+ # `xargs` passes expanded string to `printf`
59+ # `printf` which splits it into NUL-separated elements,
60+ # NUL-separated elements read by `read` using empty separator
61+ # (`-d ''` or `-d $'\0'`)
62+ # into an `ARGS` array
63+
64+ # This allows to "rebuild" initial `args` array of sort of grouped elements
65+ # into a proper array, where each element is a standalone array slice
66+ # with quoted elements being treated as a standalone slice of array as well.
67+ while read -r -d ' ' ARG; do
68+ ARGS+=(" $ARG " )
69+ done < <( echo " $1 " | xargs printf ' %s\0' )
5570 shift
5671 ;;
5772 -h | --hook-config)
@@ -129,7 +144,7 @@ function common::parse_and_export_env_vars {
129144# ######################################################################
130145function common::is_hook_run_on_whole_repo {
131146 local -r hook_id=" $1 "
132- shift 1
147+ shift
133148 local -a -r files=(" $@ " )
134149 # get directory containing `.pre-commit-hooks.yaml` file
135150 local -r root_config_dir=" $( dirname " $( cd " $( dirname " ${BASH_SOURCE[0]} " ) " && pwd -P) " ) "
@@ -163,21 +178,31 @@ function common::is_hook_run_on_whole_repo {
163178# 2.1. If at least 1 check failed - change exit code to non-zero
164179# 3. Complete hook execution and return exit code
165180# Arguments:
166- # args (string with array) arguments that configure wrapped tool behavior
167181# hook_id (string) hook ID, see `- id` for details in .pre-commit-hooks.yaml file
182+ # args_array_length (integer) Count of arguments in args array.
183+ # args (array) arguments that configure wrapped tool behavior
168184# files (array) filenames to check
169185# ######################################################################
170186function common::per_dir_hook {
171- local -r args =" $1 "
172- local -r hook_id= " $2 "
187+ local -r hook_id =" $1 "
188+ local -i args_array_length= $2
173189 shift 2
190+ local -a args=()
191+ # Expand args to a true array.
192+ # Based on https://stackoverflow.com/a/10953834
193+ while (( args_array_length-- > 0 )) ; do
194+ args+=(" $1 " )
195+ shift
196+ done
197+ # assign rest of function's positional ARGS into `files` array,
198+ # despite there's only one positional ARG left
174199 local -a -r files=(" $@ " )
175200
176201 # check is (optional) function defined
177202 if [ " $( type -t run_hook_on_whole_repo) " == function ] &&
178203 # check is hook run via `pre-commit run --all`
179204 common::is_hook_run_on_whole_repo " $hook_id " " ${files[@]} " ; then
180- run_hook_on_whole_repo " $args "
205+ run_hook_on_whole_repo " ${ args[@]} "
181206 exit 0
182207 fi
183208
@@ -203,7 +228,7 @@ function common::per_dir_hook {
203228 dir_path=" ${dir_path// __REPLACED__SPACE__/ } "
204229 pushd " $dir_path " > /dev/null || continue
205230
206- per_dir_hook_unique_part " $args " " $dir_path "
231+ per_dir_hook_unique_part " $dir_path " " ${args[@]} "
207232
208233 local exit_code=$?
209234 if [ $exit_code -ne 0 ]; then
0 commit comments