fix(gnu-utils): reassign GNU utils on preexec (#10535)

The previous version rebound the `hash` and `rehash` builtins to
reassing GNU utils when they were called. This didn't take into
account that when `$PATH` changes, the commands are rehashed as
well.

This version adds a preexec hook to reassign the GNU utilities
before running any command, if and only if they aren't already
reassigned. This is checked by looking at the `whoami` command.

Fixes #10535
This commit is contained in:
Marc Cornellà 2021-12-27 17:34:06 +01:00
parent 0f1de08713
commit 8cb53ba692
No known key found for this signature in database
GPG key ID: 0314585E776A9C1B

View file

@ -11,11 +11,8 @@ if [[ ! -x "${commands[gwhoami]}" ]]; then
fi fi
__gnu_utils() { __gnu_utils() {
emulate -L zsh local -a gcmds
local gcmds
local gcmd local gcmd
local cmd
local prefix
# coreutils # coreutils
gcmds=('g[' 'gbase64' 'gbasename' 'gcat' 'gchcon' 'gchgrp' 'gchmod' gcmds=('g[' 'gbase64' 'gbasename' 'gcat' 'gchcon' 'gchgrp' 'gchmod'
@ -43,36 +40,21 @@ __gnu_utils() {
(( ${+commands[$gcmd]} )) || continue (( ${+commands[$gcmd]} )) || continue
# This method allows for builtin commands to be primary but it's # This method allows for builtin commands to be primary but it's
# lost if hash -r or rehash -f is executed. Thus, those two # lost if hash -r or rehash is executed, or if $PATH is updated.
# functions have to be wrapped. # Thus, a preexec hook is needed, which will only run if whoami
# is not already rehashed.
# #
hash ${gcmd[2,-1]}=${commands[$gcmd]} hash ${gcmd[2,-1]}=${commands[$gcmd]}
# This method generates wrapper functions.
# It will override shell builtins.
#
# eval "function $gcmd[2,-1]() { \"${prefix}/${gcmd//"["/"\\["}\" \"\$@\"; }"
# This method is inflexible since the aliases are at risk of being
# overridden resulting in the BSD coreutils being called.
#
# alias "$gcmd[2,-1]"="${prefix}/${gcmd//"["/"\\["}"
done done
return 0 return 0
} }
__gnu_utils
function hash() { __gnu_utils_preexec() {
if [[ "$*" =~ "-(r|f)" ]]; then # Run __gnu_utils when the whoami command is not already rehashed.
builtin hash "$@" # This acts as a sign that we need to rehash all GNU utils.
__gnu_utils [[ "${commands[whoami]}" = "${commands[gwhoami]}" ]] || __gnu_utils
else
builtin hash "$@"
fi
} }
function rehash() { autoload -Uz add-zsh-hook
builtin rehash "$@" add-zsh-hook preexec __gnu_utils_preexec
__gnu_utils
}