Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Replace mapfile to support Bash 3.2.57 pre-installed in macOS #627

Merged
merged 8 commits into from
Feb 19, 2024
4 changes: 3 additions & 1 deletion hooks/_common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,9 @@ function common::per_dir_hook {

local pids=()

mapfile -t dir_paths_unique < <(echo "${dir_paths[@]}" | tr ' ' '\n' | sort -u)
while IFS= read -r _line; do
dir_paths_unique+=("$_line")
done < <(printf '%s\n' "${dir_paths[@]}" | sort -u)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well it was replaced to mapfile from https://www.shellcheck.net/wiki/SC2207

Maybe we'd prefer a more readable variant than all this read IFS ololo done <<< | )?

  # shellcheck disable=SC2207 # Most readable variant
  local dir_paths_unique=( $(echo "${dir_paths[@]}" | tr ' ' '\n' | sort -u) )

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we'd prefer a more readable variant than all this read IFS ololo done <<< | )?

The link that you refer to has this at the very top =)
изображение

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, and I don't think that it is problematic, as paths must be split by spaces, just by tr ' ' '\n'

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have no spaces in paths which can be split accidentally

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. The suggested ("problematic") code will split a path with spaces in it into different elements of array.
  2. For the consistency sake I'd stay with while read approach. Else we need to replace other while read bits with the "other" solution.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're confusing your inexperience of process substitution and array manipulation with "hard to understand".

That's a good shout out. But... but if between three of us one says "canonical" is less readable, while var=($(command)) is, then I reckon we have to provide readability and clarity for that one of us who prefers specific solution over other solution unless that preferred solution breaks for someone else (when we stumble upon someone with newlines in dir/file names 🤪).

Copy link
Collaborator Author

@yermulnik yermulnik Feb 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unless that preferred solution breaks for someone else (when we stumble upon someone with newlines in dir/file names 🤪).

And even then we will just need to use a proper separator of \0, though this may require us to deal with diffs between BSD and GNU sort.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And now code from #629

➜ docker run -ti bash:3.2.57  
bash-3.2# 
bash-3.2# eee() {
>   local -a dir_paths_unique
>   IFS=$'\n' dir_paths_unique=($(sort -u <<< "${dir_paths[*]}"))
>   unset IFS
>   printf '%s\n' "${dir_paths_unique[@]}"
> }
bash-3.2# 
bash-3.2# eee 11 44 11 "55 55"

bash-3.2# 
bash-3.2# 
bash-3.2# eee() {
>   local -a dir_paths_unique
>   IFS=$'\n' dir_paths_unique=($(sort -u <<< "${dir_paths[*]}"))
>   unset IFS
>   echo "${dir_paths_unique[@]}"
> }
bash-3.2# eee 11 44 11 "55 55"

I don't get it

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I got it. This is about IFS and *.
Ok, #629 works.
Apologies for the confusion.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect you're seeing differences because you're passing the params to a function, which means they're passing through an extra layer of quoting.

This code works for me on MacOS, with both v3 and v5:

set -euo pipefail

dir_paths=(
  11
  44
  11
  "55 55"
)

IFS=$'\n' dir_paths_unique=($(sort -u <<< "${dir_paths[*]}"))
printf '%s\n' "${dir_paths_unique[@]}"
$ /bin/bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin23)
Copyright (C) 2007 Free Software Foundation, Inc.

$ /bin/bash test.sh
11
44
55 55
$ bash --version
GNU bash, version 5.2.26(1)-release (x86_64-apple-darwin23.2.0)
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

$ bash test.sh
11
44
55 55

local length=${#dir_paths_unique[@]}
local last_index=$((${#dir_paths_unique[@]} - 1))

Expand Down
Loading