Considerations:
- `./libexec/rbenv` executable is the entrypoint to the program;
- BASH_SOURCE might be the path to a symlink that has activated `./libexec/rbenv`;
- We must resolve the symlink to learn where rbenv's libexec directory is;
- It's not guaranteed that rbenv commands will always remain directly under their own "libexec" directory, since a package maintainer can change that, e.g. rbenv commands are sometimes placed into `/usr/libexec/rbenv/*`;
- Resolving symlinks might fail and in that case we just assume rbenv project layout.
The rehash process will now discover executables in additional locations:
- `~/.gem/ruby/<version>/bin/*`
- `$GEM_HOME/bin`
The `rbenv which` (and thus `rbenv exec`) command will also search these locations when looking up a command. This enables shims to dispatch calls to executables added by `gem install --user-install`.
Note that this support is limited:
- It will only work with C Ruby, as it's difficult to guess the `~/.gem/<engine>/<version>` directory for other Rubies without actually loading Ruby;
- It will only work for RBENV_VERSION values in the format `X.Y.Z` and not "system".
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/<VERSION>/bin/rbenv`, which is itself a symlink to
`/usr/local/Cellar/rbenv/<VERSION>/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`.
This speeds up subsequent `rbenv init -` executions for the user who
followed these instructions because the shell will no longer have to be
detected each time.
Since fish 3.10 at least, the current way of loading rbenv in `fish` is misbehaving, at least in some environments:
```
source: Error encountered while sourcing file '/var/folders/pj/jn249gcn7ddfrjzj2_9mxjhw0000gp/T//.psub.f0iJSWRByB':
source: No such file or directory
```
This changes the initialization to the method recommended by a `fish` developer here: https://github.com/fish-shell/fish-shell/issues/6613#issuecomment-586679958
Sometimes the command fails with a 'type: write error: Broken pipe'.
This is because 'head -1' only reads the first line, then exits.
If 'type' writes the second line after 'head -1' has already exited,
then the aforementioned error is triggered.
We fix this by buffering the entire output of 'type' before
invoking 'head -1'.
A malicious `.ruby-version` file in the current directory could inject
`../../../` into the version string and trigger execution of binaries
outside of `RBENV_ROOT/versions/`.
Fixes#977 OVE-20170303-0004
This suppressed any output when using RBENV_DEBUG=1 and does not really
hurt to have in the unlikely case that it should fail; you would get
two error messages now:
rbenv: ruby: command not found
rbenv: system version not found in PATH
Command `rbenv version-name > .ruby-version` will create an empty `.ruby-version` file
before running `rbenv-version-file`. This causes `rbenv-version-file` to return empty
string which in turn causes `rbenv-version-name` to return `system`.
Ensure size of `.ruby-version` is non-zero as a workaround.
Shell integration is not enabled by default. This means that, from all the
commands from `rbenv commands`, only "shell" won't work right away.
Replace "no such command" with a more descriptive message that points to
`rbenv init` instead.