diff options
author | The Bundler Bot <bot@bundler.io> | 2018-09-13 12:43:47 +0000 |
---|---|---|
committer | The Bundler Bot <bot@bundler.io> | 2018-09-13 12:43:47 +0000 |
commit | 8c31a61037e2d526affb13d4fe07035e18266947 (patch) | |
tree | 38247e5d2ed3a6ac2d95b3eafb9b62243e950ba6 | |
parent | cb543fb07c08ec0bc79f61c35a00dc645367f7a1 (diff) | |
parent | 0676955f6d951e3af70e4efecbe6ef8fa8397d75 (diff) | |
download | bundler-8c31a61037e2d526affb13d4fe07035e18266947.tar.gz |
Auto merge of #6689 - bundler:colby/fix-bundler-load-error, r=colby-swandale
Fix loadError occurring in nested bundle exec calls
### What was the end-user problem that led to this PR?
There is a LoadError occurring in Bundler when an application has its Gemfile installed with `--path`, and the user has a recent version of RubyGems that installs a version of Bundler as a default gem.
If the user has some code that they're running with `bundle exec` (like a test suite) that is shelling out and executing `bundle exec` again, the user will receive an error saying that Bundler could not be loaded.
/home/travis/.rvm/gems/ruby-2.5.1/bin/bundle:23:in `load': cannot load such file -- /home/travis/.rvm/rubies/ruby-2.5.1/lib/ruby/gems/2.5.0/gems/bundler-1.16.3/exe/bundle (LoadError)
The problem that's happening is that when we run `bundle exec`, Bundler will set the Ruby environment to add the path of the current version of Bundler into the `LOAD_PATH` and also require `bundler/setup`.
RUBYOPT=-rbundler/setup
RUBYLIB=/usr/local/bundle/gems/bundler-1.16.4/lib
This will have Ruby load the lib directory of the version of Bundler the user installed, but it's been loaded with the Gemspec from the default gem version of Bundler that RubyGems installed.
This gemspec is being loaded because RubyGems has a copy of the Bundler gemspec sitting in the default gems. And because we changed `GEM_HOME` when the user ran Bundler with `bundle install --path`, RubyGems just figures that seeing this is only Bundler gemspec it can find, then it should activate it but then `RUBYLIB` comes into play and just overrules RubyGems to load the newer Bundler src.
This is ultimately what's giving us the weird load path that doesn't exist.
![mind blown](https://thumbs.gfycat.com/BlankScarceAfricanporcupine-size_restricted.gif)
### What was your diagnosis of the problem?
See #6537 and #6629
### What is your fix for the problem, implemented in this PR?
When we set the `BUNDLE_BIN_PATH` env var inside bundler, check that the file exists. If it doesn't, we will just set it to the bundle executable file.
### Why did you choose this fix out of the possible options?
This seems to be the solution that patches the LoadError issue without having to heavily refactor code or make the existing code more complicated.
-rw-r--r-- | lib/bundler/shared_helpers.rb | 7 | ||||
-rw-r--r-- | spec/bundler/shared_helpers_spec.rb | 10 |
2 files changed, 16 insertions, 1 deletions
diff --git a/lib/bundler/shared_helpers.rb b/lib/bundler/shared_helpers.rb index 7ff391ab60..dca17885dd 100644 --- a/lib/bundler/shared_helpers.rb +++ b/lib/bundler/shared_helpers.rb @@ -300,7 +300,12 @@ module Bundler def set_bundle_variables begin - Bundler::SharedHelpers.set_env "BUNDLE_BIN_PATH", Bundler.rubygems.bin_path("bundler", "bundle", VERSION) + exe_file = Bundler.rubygems.bin_path("bundler", "bundle", VERSION) + unless File.exist?(exe_file) + exe_file = File.expand_path("../../../exe/bundle", __FILE__) + end + + Bundler::SharedHelpers.set_env "BUNDLE_BIN_PATH", exe_file rescue Gem::GemNotFoundException Bundler::SharedHelpers.set_env "BUNDLE_BIN_PATH", File.expand_path("../../../exe/bundle", __FILE__) end diff --git a/spec/bundler/shared_helpers_spec.rb b/spec/bundler/shared_helpers_spec.rb index b8f099d5ba..72b1c2a51f 100644 --- a/spec/bundler/shared_helpers_spec.rb +++ b/spec/bundler/shared_helpers_spec.rb @@ -378,6 +378,16 @@ RSpec.describe Bundler::SharedHelpers do it_behaves_like "ENV['RUBYLIB'] gets set correctly" end + context "bundle executable in ENV['BUNDLE_BIN_PATH'] does not exist" do + before { ENV["BUNDLE_BIN_PATH"] = "/does/not/exist" } + before { Bundler.rubygems.replace_bin_path [], [] } + + it "sets BUNDLE_BIN_PATH to the bundle executable file" do + subject.set_bundle_environment + expect(ENV["BUNDLE_BIN_PATH"]).to eq(File.expand_path("../../../exe/bundle", __FILE__)) + end + end + context "ENV['RUBYLIB'] already contains the bundler's ruby version lib path" do let(:ruby_lib_path) { "stubbed_ruby_lib_dir" } |