diff --git a/libexec/rbenv-rehash b/libexec/rbenv-rehash index cb7713ef..67a14b3b 100755 --- a/libexec/rbenv-rehash +++ b/libexec/rbenv-rehash @@ -43,26 +43,93 @@ SH chmod +x "$PROTOTYPE_SHIM_PATH" } -# Make shims by iterating over every filename argument and creating a -# hard link from the prototype shim to a file of the same name in the -# shims directory, if one does not already exist. +# The basename of each argument passed to `make_shims` will be +# registered for installation as a shim. In this way, plugins may call +# `make_shims` with a glob to register many shims at once. make_shims() { - local glob="$@" + local shims="$@" - for file in $glob; do + for file in $shims; do local shim="${file##*/}" + register_shim "$shim" + done +} + +# Create an empty array for the list of registered shims. +registered_shims=() + +# We will keep track of shims registered for installation with the +# global `reigstered_shims` array and with a global variable for each +# shim. The array will let us iterate over all registered shims. The +# global variables will let us quickly check whether a shim with the +# given name has been registered or not. +register_shim() { + local shim="$@" + local var="$(shim_variable_name "$shim")" + + if [ -z "${!var}" ]; then + registered_shims[${#registered_shims[*]}]="$shim" + eval "${var}=1" + fi +} + +# To compute the global variable name for a given shim we must first +# escape any non-alphanumeric characters. If the shim name is +# alphanumeric (including a hyphen or underscore) we can take a +# shorter path. Otherwise, we must iterate over each character and +# escape the non-alphanumeric ones using `printf`. +shim_variable_name() { + local shim="$1" + local result="_shim_" + + if [[ ! "$shim" =~ [^[:alnum:]_-] ]]; then + shim="${shim//_/_5f}" + shim="${shim//-/_2d}" + result+="$shim" + else + local length="${#shim}" + local char i + + for ((i=0; i