From 76e64ff2ea3cc5298a143cf38a4c839da883adb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Wed, 29 Sep 2021 17:50:03 +0200 Subject: [PATCH] Have shims survive symlinked rbenv updates a la Homebrew Homebrew places the rbenv executable in a location such as `/usr/local/bin/rbenv`, which is in PATH. However, that is a symlink to `/usr/local/Cellar/rbenv//bin/rbenv`, which is itself a symlink to `/usr/local/Cellar/rbenv//libexec/rbenv`. Upon executing, rbenv will add its own directory to PATH so that it can easily invoke its subcommands. When generating shims during `rbenv rehash`, rbenv will try to put the absolute path to itself inside each shim so that shims would work even if rbenv itself isn't in PATH. Under Homebrew, rbenv's directory will be the versioned directory in Homebrew's Cellar. However, due to Homebrew's auto-cleanup functionality, shims generated this way will be broken after upgrading rbenv because of the versioned Cellar path. This changes how rbenv discovers itself in PATH: it will look at the original PATH, not in the one modified by rbenv, with the intention of excluding results under rbenv's own `libexec/`. If rbenv wasn't found in PATH, return the absolute path to rbenv's own `bin/rbenv`. --- libexec/rbenv | 1 + libexec/rbenv-rehash | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/libexec/rbenv b/libexec/rbenv index 2e45496..8a295e9 100755 --- a/libexec/rbenv +++ b/libexec/rbenv @@ -68,6 +68,7 @@ else fi export RBENV_DIR +[ -n "$RBENV_ORIG_PATH" ] || export RBENV_ORIG_PATH="$PATH" shopt -s nullglob diff --git a/libexec/rbenv-rehash b/libexec/rbenv-rehash index 30f362e..c5f8d55 100755 --- a/libexec/rbenv-rehash +++ b/libexec/rbenv-rehash @@ -34,6 +34,22 @@ remove_prototype_shim() { rm -f "$PROTOTYPE_SHIM_PATH" } +# Locates rbenv as found in the user's PATH. Otherwise, returns an +# absolute path to the rbenv executable itself. +rbenv_path() { + local found + found="$(PATH="$RBENV_ORIG_PATH" command -v rbenv)" + if [[ $found == /* ]]; then + echo "$found" + elif [[ -n "$found" ]]; then + echo "$PWD/${found#./}" + else + # Assume rbenv isn't in PATH. + local here="${BASH_SOURCE%/*}" + echo "${here%/*}/bin/rbenv" + fi +} + # The prototype shim file is a script that re-execs itself, passing # its filename and any arguments to `rbenv exec`. This file is # hard-linked for every executable and then removed. The linking @@ -61,7 +77,7 @@ if [ "\$program" = "ruby" ]; then fi export RBENV_ROOT="$RBENV_ROOT" -exec "$(command -v rbenv)" exec "\$program" "\$@" +exec "$(rbenv_path)" exec "\$program" "\$@" SH chmod +x "$PROTOTYPE_SHIM_PATH" }