postmodern / chruby

Changes the current Ruby
MIT License
2.87k stars 190 forks source link

chruby setting wrong gem bin path? #411

Open webframp opened 5 years ago

webframp commented 5 years ago

This is likely something very easy that I have missed or mistaken, so please point me at old issues or docs somewhere else if so.

I currently use a combination of chruby and direnv to manage rubies alongside the embedded ruby from my installed chef workstation package. It all seems a bit convoluted to me to try and track down what's happening so I'll try to explain clearly.

On macOS I have done ruby-install ruby-2.6.1 and brew cask install chef/chef/chef-workstation

This gives me ruby 2.6.1 at .rubies/ruby-2.6.1 and the embedded chef ruby at /opt/chef-workstation/embedded which is currently ruby 2.5.3

as a result my $RUBIES var looks like:

$ echo $RUBIES
/Users/sme/.rubies/ruby-2.6.1 /opt/chef-workstation/embedded

using chruby ruby-2.6.1 or chruby embedded sets the wrong value for $PATH with this setup.

$ chruby system
$ echo $PATH
/Users/sme/.cargo/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/share/dotnet:~/.dotnet/tools:/Users/sme/.cargo/bin
$ chruby ruby-2.6.1
$ env |grep GEM
GEM_ROOT=/Users/sme/.rubies/ruby-2.6.1/lib/ruby/gems/2.6.0
GEM_HOME=/Users/sme/.gem/ruby/2.6.1
GEM_PATH=/Users/sme/.gem/ruby/2.6.1:/Users/sme/.rubies/ruby-2.6.1/lib/ruby/gems/2.6.0
$ echo $PATH
/Users/sme/.gem/ruby/2.6.1/bin:/Users/sme/.rubies/ruby-2.6.1/lib/ruby/gems/2.6.0/bin:/Users/sme/.rubies/ruby-2.6.1/bin:/Users/sme/.cargo/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/share/dotnet:~/.dotnet/tools:/Users/sme/.cargo/bin

Here I believe the correct bin path should be ~/.gem/ruby/2.6.0/bin not ~/.gem/ruby/2.6.1/bin

$ chruby embedded
$ env |grep GEM
GEM_ROOT=/opt/chef-workstation/embedded/lib/ruby/gems/2.5.0
GEM_HOME=/Users/sme/.gem/ruby/2.5.3
GEM_PATH=/Users/sme/.gem/ruby/2.5.3:/opt/chef-workstation/embedded/lib/ruby/gems/2.5.0
$ echo $PATH
/Users/sme/.gem/ruby/2.5.3/bin:/opt/chef-workstation/embedded/lib/ruby/gems/2.5.0/bin:/opt/chef-workstation/embedded/bin:/Users/sme/.cargo/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/share/dotnet:~/.dotnet/tools:/Users/sme/.cargo/bin

Again here I believe the correct bin path should be ~/.gem/ruby/2.5.0/bin not ~/.gem/ruby/2.5.3/bin

Where direnv comes into the picture is that I have defined a custom layout for the embedded chef ruby which behaves slightly differently than chruby and it seems to work consistently.

In my ~/.direnvrc I have added:

use_chefdk() {
    # use chefdk
    EXPANDED_HOME=$(expand_path ~)

    # Override the GEM environment

    log_status "Overriding default Ruby environment to use Chef Workstation"

    RUBY_ABI_VERSION=$(ls /opt/chef-workstation/embedded/lib/ruby/gems/)
    export GEM_ROOT="/opt/chef-workstation/embedded/lib/ruby/gems/$RUBY_ABI_VERSION"
    export GEM_HOME="$EXPANDED_HOME/.chefdk/gem/ruby/$RUBY_ABI_VERSION"
    export GEM_PATH="$EXPANDED_HOME/.chefdk/gem/ruby/$RUBY_ABI_VERSION:/opt/chef-workstation/embedded/lib/ruby/gems/$RUBY_ABI_VERSION"

    # Ensure ChefDK embedded tools are first in the PATH

    log_status "Ensuring Chef Workstation and it's embedded tools are first in the PATH"

    PATH_add "$EXPANDED_HOME/.chefdk/gem/ruby/$RUBY_ABI_VERSION/bin/"
    PATH_add /opt/chef-workstation/embedded/bin
    PATH_add /opt/chef-workstation/bin
}

Which allows me to just add a use chefdk statement in any .envrc file and it sets the correct local ruby gem bin path for that working directory.

However with this in my .direnvrc:

use_ruby() {
    # use ruby <ver>
    source /usr/local/opt/chruby/share/chruby/chruby.sh

    local ver=$1
    if [[ -z $ver ]] && [[ -f .ruby-version ]]; then
        ver=$(cat .ruby-version)
    fi
    if [[ -z $ver ]]; then
        echo Unknown ruby version: need to declare a version in .ruby-version or in .envrc
        exit 1
    fi

    # switch to the desired ruby
    chruby "$ver"

    layout ruby
}

I do not get the same behavior but get an invalid gem bin path in my $PATH variable, the same as described about with just using chruby.

Thanks for reviewing!

havenwood commented 5 years ago

Currently, chruby does use ~/.gem/$ruby/X.Y.Z instead of the ABI version. This issue has some discussion about how the RubyGems default is currently --no-env-shebang, so gem executable shebangs are hardcoded to a specific Ruby version.

This RubyGems issue looks at changing the default to --env-shebang, so Ruby version switchers like chruby could use the ABI version for gem locations.