Skip to content
This repository has been archived by the owner on Apr 14, 2021. It is now read-only.

Could not find 'bundler' #4592

Closed
guxiaobai opened this issue May 19, 2016 · 9 comments · Fixed by #4701 or #4992
Closed

Could not find 'bundler' #4592

guxiaobai opened this issue May 19, 2016 · 9 comments · Fixed by #4701 or #4992

Comments

@guxiaobai
Copy link

guxiaobai commented May 19, 2016

Software

  • osx 10.11.4
  • rbenv 1.0.0
  • ruby 2.2.3p173 (2015-08-18 revision 51636) [x86_64-darwin15]
  • Rails 4.2.6

bundle exec gem list|grep guard

guard (2.13.0)
guard-compat (1.2.1)
guard-rspec (4.6.5)

bundle exec guard -d

RubyDep: WARNING: Your Ruby has security vulnerabilities! (To disable warnings, set RUBY_DEP_GEM_SILENCE_WARNINGS=1)
RubyDep: WARNING: Your Ruby is: 2.2.3 (insecure). Recommendation: install 2.2.5 or 2.3.1. (Or, at least to 2.2.4 or 2.3.0)
00:54:56 - DEBUG - Notiffany: gntp not available (Please add "gem 'ruby_gntp'" to your Gemfile and run your app with "bundle exec".).
00:54:56 - DEBUG - Notiffany: growl not available (Please add "gem 'growl'" to your Gemfile and run your app with "bundle exec".).
00:54:56 - DEBUG - Notiffany: terminal_notifier not available (Please add "gem 'terminal-notifier-guard'" to your Gemfile and run your app with "bundle exec".).
00:54:56 - DEBUG - Notiffany: libnotify not available (Unsupported platform "darwin15.4.0").
00:54:56 - DEBUG - Notiffany: notifysend not available (Unsupported platform "darwin15.4.0").
00:54:56 - DEBUG - Notiffany: notifu not available (Unsupported platform "darwin15.4.0").
00:54:56 - DEBUG - Command execution: {"ALTERNATE_EDITOR"=>"false"} emacsclient --eval '1'
00:54:56 - DEBUG - Notiffany: emacs not available (Emacs client failed).
00:54:56 - DEBUG - Notiffany: tmux not available (:tmux notifier is only available inside a TMux session.).
00:54:56 - DEBUG - Notiffany: file not available (No :path option given).
00:54:56 - DEBUG - Notiffany is using TerminalTitle to send notifications.
00:54:56 - DEBUG - Command execution: hash stty
00:54:56 - DEBUG - Guard starts all plugins
00:54:56 - DEBUG - Hook :start_begin executed for Guard::RSpec
00:54:56 - INFO - Guard::RSpec is running
00:54:56 - DEBUG - Hook :start_end executed for Guard::RSpec
00:54:56 - INFO - Guard is now watching at '/Users/lemon/Documents/chavis'
00:54:56 - DEBUG - Start interactor
00:54:56 - DEBUG - Command execution: stty -g 2>/dev/null
[1] guard(main)>
00:54:58 - DEBUG - Interactor was stopped or killed
00:54:58 - DEBUG - Command execution: stty  2>/dev/null
00:54:58 - INFO - Run all
00:54:58 - DEBUG - Hook :run_all_begin executed for Guard::RSpec
00:54:58 - INFO - Running all specs
/Users/lemon/.rbenv/versions/2.2.3/lib/ruby/2.2.0/rubygems/dependency.rb:315:in `to_specs': Could not find 'bundler' (>= 0) among 98 total gem(s) (Gem::LoadError)
Checked in 'GEM_PATH=/Users/lemon/Documents/chavis/vendor/bundle/ruby/2.2.0', execute `gem env` for more information
    from /Users/lemon/.rbenv/versions/2.2.3/lib/ruby/2.2.0/rubygems/dependency.rb:324:in `to_spec'
    from /Users/lemon/.rbenv/versions/2.2.3/lib/ruby/2.2.0/rubygems/core_ext/kernel_gem.rb:64:in `gem'
    from /Users/lemon/.rbenv/versions/2.2.3/bin/bundle:22:in `<main>'
00:54:58 - ERROR - Failed: "bundle exec rspec -f progress -r /Users/lemon/Documents/chavis/vendor/bundle/ruby/2.2.0/gems/guard-rspec-4.6.5/lib/guard/rspec_formatter.rb -f Guard::RSpecFormatter --failure-exit-code 2  spec" (exit code: 1)

00:54:58 - DEBUG - Start interactor
00:54:58 - DEBUG - Command execution: stty -g 2>/dev/null

gem env

RubyGems Environment:
  - RUBYGEMS VERSION: 2.4.5.1
  - RUBY VERSION: 2.2.3 (2015-08-18 patchlevel 173) [x86_64-darwin15]
  - INSTALLATION DIRECTORY: /Users/lemon/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0
  - RUBY EXECUTABLE: /Users/lemon/.rbenv/versions/2.2.3/bin/ruby
  - EXECUTABLE DIRECTORY: /Users/lemon/.rbenv/versions/2.2.3/bin
  - SPEC CACHE DIRECTORY: /Users/lemon/.gem/specs
  - SYSTEM CONFIGURATION DIRECTORY: /Users/lemon/.rbenv/versions/2.2.3/etc
  - RUBYGEMS PLATFORMS:
    - ruby
    - x86_64-darwin-15
  - GEM PATHS:
     - /Users/lemon/.rbenv/versions/2.2.3/lib/ruby/gems/2.2.0
     - /Users/lemon/.gem/ruby/2.2.0
  - GEM CONFIGURATION:
     - :update_sources => true
     - :verbose => true
     - :backtrace => false
     - :bulk_threshold => 1000
     - :sources => ["https://gems.ruby-china.org/"]
  - REMOTE SOURCES:
     - https://gems.ruby-china.org/
  - SHELL PATH:
     - /Users/lemon/.rbenv/versions/2.2.3/bin
     - /usr/local/Cellar/rbenv/1.0.0/libexec
     - /Users/lemon/.rbenv/shims
     - /usr/local/bin
     - /usr/bin
     - /bin
     - /usr/sbin
     - /sbin

guard/guard-rspec#369

@RochesterinNYC
Copy link
Contributor

What is the output of bundle env?

@biinari
Copy link

biinari commented May 20, 2016

I have the same issue on arch-linux with the following:

  • bundler 1.12.0.pre.2 to 1.12.4 inclusive
  • rbenv 1.0.0
  • ruby 2.0.0-p247, 2.3.1
  • rubygems 2.5.1

ruby versions tested:

ruby 2.0.0p247 (2013-06-27 revision 41674) [x86_64-linux]
ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-linux]

Bundler versions 1.12.0.pre.1 and earlier did not exhibit this problem for me.

gem env:

RubyGems Environment:
  - RUBYGEMS VERSION: 2.5.1
  - RUBY VERSION: 2.3.1 (2016-04-26 patchlevel 112) [x86_64-linux]
  - INSTALLATION DIRECTORY: /home/bill/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0
  - USER INSTALLATION DIRECTORY: /home/bill/.gem/ruby/2.3.0
  - RUBY EXECUTABLE: /home/bill/.rbenv/versions/2.3.1/bin/ruby
  - EXECUTABLE DIRECTORY: /home/bill/.rbenv/versions/2.3.1/bin
  - SPEC CACHE DIRECTORY: /home/bill/.gem/specs
  - SYSTEM CONFIGURATION DIRECTORY: /home/bill/.rbenv/versions/2.3.1/etc
  - RUBYGEMS PLATFORMS:
    - ruby
    - x86_64-linux
  - GEM PATHS:
     - /home/bill/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0
     - /home/bill/.gem/ruby/2.3.0
  - GEM CONFIGURATION:
     - :update_sources => true
     - :verbose => true
     - :backtrace => false
     - :bulk_threshold => 1000
     - "gem" => "--no-user-install --no-ri --no-rdoc"
  - REMOTE SOURCES:
     - https://rubygems.org/
  - SHELL PATH:
     - /home/bill/.rbenv/versions/2.3.1/bin
     - /usr/lib/rbenv/libexec
     - /home/bill/.rbenv/plugins/rbenv-binstubs/bin
     - /home/bill/.rbenv/shims
     - /usr/local/sbin
     - /usr/local/bin
     - /usr/bin
     - /opt/cuda/bin
     - /usr/lib/jvm/default/bin
     - /usr/bin/site_perl
     - /usr/bin/vendor_perl
     - /usr/bin/core_perl
     - /usr/local/jdk/bin
     - /home/bill/.gem/ruby/2.1.0/bin

I've narrowed down point where the issue is introduced to #4298. Whether the problem is with bundler or with the way guard uses it I'm not yet sure.

@biinari
Copy link

biinari commented May 23, 2016

I have created a minimal repo that demonstrates when the issue occurs for me: https://github.com/biinari/bundler-rbenv-guard-issue

Included outputs from bundle env, gem env, bundle exec guard.

@chrismo
Copy link
Contributor

chrismo commented Jun 22, 2016

I think I've diagnosed this. It's a lot, so I may be missing stuff.

In 1.12.5 (and prior 1.12 versions), bundle exec calls a new method, kernel_load if the cmd to execute (guard in this case) has a ruby shebang in it. => https://github.com/bundler/bundler/blob/a65a2db118ed714586ac4c56a0584c97bf0305df/lib/bundler/cli/exec.rb#L24

Inside kernel_load - "bundler/setup" is required. => https://github.com/bundler/bundler/blob/a65a2db118ed714586ac4c56a0584c97bf0305df/lib/bundler/cli/exec.rb#L62

That drills down into this call stack:

/Users/chrismo/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler.rb:413:in `configure_gem_home_and_path'
/Users/chrismo/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler.rb:60:in `configure'
/Users/chrismo/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler.rb:121:in `definition'
/Users/chrismo/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler.rb:91:in `setup'
/Users/chrismo/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/setup.rb:19:in `<top (required)>'
/Users/chrismo/.rbenv/versions/2.3.1/lib/ruby/site_ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
/Users/chrismo/.rbenv/versions/2.3.1/lib/ruby/site_ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
/Users/chrismo/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/cli/exec.rb:62:in `kernel_load'

...ending at this bit of code:

    def configure_gem_home_and_path
      blank_home = ENV["GEM_HOME"].nil? || ENV["GEM_HOME"].empty?
      if settings[:disable_shared_gems]
        ENV["GEM_PATH"] = ""
      elsif blank_home || Bundler.rubygems.gem_dir != bundle_path.to_s
        possibles = [Bundler.rubygems.gem_dir, Bundler.rubygems.gem_path]
        paths = possibles.flatten.compact.uniq.reject(&:empty?)
        ENV["GEM_PATH"] = paths.join(File::PATH_SEPARATOR)
      end

      configure_gem_home
      bundle_path
    end

Since --path vendor was used, :disable_shared_gems is true, so ENV['GEM_PATH'] isn't set to nil (like it would be in 1.11.2 which doesn't involve any of this setup) but set to empty string.

Once we jump over to the new process, we hit this initial code load Gem.activate_bin_path('bundler', 'bundle', version) which leads into this call stack:

/Users/chrismo/.rbenv/versions/2.3.1/lib/ruby/site_ruby/2.3.0/rubygems/dependency.rb:279:in `matching_specs'
/Users/chrismo/.rbenv/versions/2.3.1/lib/ruby/site_ruby/2.3.0/rubygems.rb:248:in `find_spec_for_exe'
/Users/chrismo/.rbenv/versions/2.3.1/lib/ruby/site_ruby/2.3.0/rubygems.rb:278:in `activate_bin_path'
/Users/chrismo/.rbenv/versions/2.3.1/bin/bundle:22:in `<main>'

and no matching specs are found, because when Gem.path is setup in path_support.rb:

    @path = split_gem_path env["GEM_PATH"], @home
  def split_gem_path gpaths, home
    # FIX: it should be [home, *path], not [*path, home]

    gem_path = []

    if gpaths
      gem_path = gpaths.split(Gem.path_separator)
      # Handle the path_separator being set to a regexp, which will cause
      # end_with? to error
      if gpaths =~ /#{Gem.path_separator}\z/
        gem_path += default_path
      end

      if File::ALT_SEPARATOR then
        gem_path.map! do |this_path|
          this_path.gsub File::ALT_SEPARATOR, File::SEPARATOR
        end
      end

      gem_path << home
    else
      gem_path = default_path
    end

    gem_path.uniq
  end

=> https://github.com/rubygems/rubygems/blob/9c1101160d1b7394a4acc96f0e183334d7346dfe/lib/rubygems/path_support.rb#L65 (2.6.4)

If gpaths is "" or nil it matters. When nil (1.11.2 behavior), then Gem.path gets GEM_HOME included, which is where bundler exists. In this case in 1.12.5, it doesn't, and bundler itself isn't installed in only the vendor path ... therefore - kerblooie.

Since kernel_load hits up bundler/setup and there's a ton of stuff in there, I don't know of a potential patch - bypassing all of that seems suspect. (cc @segiddins).

@chrismo
Copy link
Contributor

chrismo commented Jun 22, 2016

changing that code to be nil makes this pass - but that code is ooooold ... so no idea how risky that is otherwise.

      if settings[:disable_shared_gems]
        ENV["GEM_PATH"] = nil   # <= ...

@segiddins
Copy link
Member

@chrismo a PR changing to to nil would be great :D

@chrismo
Copy link
Contributor

chrismo commented Jun 22, 2016

I ran it locally, and got mixed results on specs, but then again I don't think I've run the whole suite locally recently, so I'll push up a PR in a bit.

chrismo added a commit to chrismo/bundler that referenced this issue Jun 22, 2016
Pushing this to get a good build against it to see what side-effects
this may cause. It appears to fix rubygems#4592, but the line of code in
question goes back to 2010.

Issue rubygems#4592 has full write-up on the diagnosis of the problem - if this
passes the build, then it should get a spec on it, etc. and a better
commit message perhaps.
chrismo added a commit to chrismo/bundler that referenced this issue Jun 23, 2016
This should fix rubygems#4592, the tests all pass, but the line of code in
question goes back to 2010, so this sorta seems slightly dangerous, but
it's probable the circumstances of hitting this line in conjunction with
`bundle exec` is a combination that didn't exist prior to 1.12.x.

Issue rubygems#4592 has a full diagnosis, but the gist of it is this: if an
empty string is passed as the `GEM_PATH` to the subsequent process
launched by `bundle exec`, then if the `cmd` portion of `bundle exec` is
a ruby shebanged file, then if the current bundle install uses a local
path (`disable_shared_gems` is true) then it won't be able to find the
bundler gem at all because Bundler doesn't install itself into its own
Bundle, it's only installed in the system gems for the Ruby.

`nil` must be passed because the RubyGems code that sets up the
`GEM_PATH` does a conditional on the current `GEM_PATH` and empty string
evaluates to true, whereas `nil` evaluates to false. In the false case
the `GEM_PATH` is internally populated with the system gems path such
that the bundler gem can be found.
@chrismo
Copy link
Contributor

chrismo commented Jun 23, 2016

First shot tests passing, just pushed up a legit commit with a small method extract and a spec to match. We'll check on it mañana.

homu added a commit that referenced this issue Jun 23, 2016
…iddins

Unset GEM_PATH with nil not empty string.

This should fix #4592, the tests all pass, but the line of code in
question goes back to 2010, so this sorta seems slightly dangerous, but
it's probable the circumstances of hitting this line in conjunction with
`bundle exec` is a combination that didn't exist prior to 1.12.x.

Issue #4592 has a full diagnosis, but the gist of it is this: if an
empty string is passed as the `GEM_PATH` to the subsequent process
launched by `bundle exec`, then if the `cmd` portion of `bundle exec` is
a ruby shebanged file, then if the current bundle install uses a local
path (`disable_shared_gems` is true) then it won't be able to find the
bundler gem at all because Bundler doesn't install itself into its own
Bundle, it's only installed in the system gems for the Ruby.

`nil` must be passed because the RubyGems code that sets up the
`GEM_PATH` does a conditional on the current `GEM_PATH` and empty string
evaluates to true, whereas `nil` evaluates to false. In the false case
the `GEM_PATH` is internally populated with the system gems path such
that the bundler gem can be found.
segiddins pushed a commit that referenced this issue Jun 27, 2016
…iddins

Unset GEM_PATH with nil not empty string.

This should fix #4592, the tests all pass, but the line of code in
question goes back to 2010, so this sorta seems slightly dangerous, but
it's probable the circumstances of hitting this line in conjunction with
`bundle exec` is a combination that didn't exist prior to 1.12.x.

Issue #4592 has a full diagnosis, but the gist of it is this: if an
empty string is passed as the `GEM_PATH` to the subsequent process
launched by `bundle exec`, then if the `cmd` portion of `bundle exec` is
a ruby shebanged file, then if the current bundle install uses a local
path (`disable_shared_gems` is true) then it won't be able to find the
bundler gem at all because Bundler doesn't install itself into its own
Bundle, it's only installed in the system gems for the Ruby.

`nil` must be passed because the RubyGems code that sets up the
`GEM_PATH` does a conditional on the current `GEM_PATH` and empty string
evaluates to true, whereas `nil` evaluates to false. In the false case
the `GEM_PATH` is internally populated with the system gems path such
that the bundler gem can be found.

(cherry picked from commit 37064b3)
@miros
Copy link

miros commented Sep 13, 2016

@chrismo Can you please look into #4974. This fix might have changed bundler install --deployment behaviour.

chrismo added a commit to chrismo/bundler that referenced this issue Sep 27, 2016
tl;dr `--deployment` will copy _all_ gems to the `--path` now and a
proper fix is in place for nested bundle execs when `--path` is set and
RubyGems >=2.6.2 is being used.

Fixes rubygems#4974.

There's two problems blended in here. Let's trace the events here from
the beginning, shall we?

First off, from probably the first versions of Bundler, when
`disable_shared_gems` is true, the `GEM_PATH` gets internally overridden
and initialized to an empty string. This is done to make sure that later
in the `Bundler.setup` process it's expanded to ONLY the Bundler `--path`
setting, otherwise it expands to include the system path.

In 1.12, `bundle exec` was changed to use `Kernel.load` in some cases,
and that new code path calls `require "bundler/setup"`.

Later, issue rubygems#4592 was filed, showing that in cases like `--deployment`
where `disable_shared_gems` is true, Bundler couldn't find itself,
because Bundler never lives in the `--path` but only in system gems. And
as it would later be discovered, was not a problem with RubyGems 2.6.1,
but was a problem with >=2.6.2 (and older RubyGems it would seem, though
those weren't as thoroughly investigated).

We fixed rubygems#4592 (see PR rubygems#4701) in 1.13.0 by changing the oooold code
initializing `GEM_PATH` to be initialized to `nil` instead of empty
string in all `disable_shared_gems` cases. But it created another bug,
filed as rubygems#4974, wherein system gems were no longer copied to the
`--path` when `disable_shared_gems` is true. In this commit here (rubygems#4992)
we've reverted the change so that `GEM_PATH` is now back to being
initialized to an empty string instead of `nil`.

That fixes rubygems#4974, but regresses rubygems#4592, and we needed a new way to fix
it.

After a few tortured attempts at this, I ran across issue rubygems#4602, a
similar report of nested bundle execs being broken, rubygems#4602 itself an
extension of rubygems#4381 reporting the same problem. It brought to light the
role the Rubygems version played in the problem.

When the `bundler` gem is installed and the wrapper is generated for any
gem executables, the contents of this wrapper are determined by the
Rubygems version. Up until RubyGems 2.6.1 the last line of this wrapper
calls `Gem.bin_path`. Bundler replaces the Rubygems implementation of
`Gem.bin_path` with its own, and has for a long time made a special
exception for the Bundler gem itself, short-circuiting with the contents
of a special ENV variable called `BUNDLE_BIN_PATH`.

In Rubygems 2.6.2, `bin_path` was superseded by a new
`Gem.activate_bin_path` method which did what `bin_path` did but also
activated the gem. Bundler 1.13 added support for this, but it didn't
include the same short-circuit for bundler itself. (Alert user @taoza
even noticed this here
rubygems@fcaab35#r56665282).

This commit also includes that short circuit for Rubygems >=2.6.2 now
and nested bundle exec should continue to work.

Thx to @miros for filing rubygems#4974 and isolating the problem in 1.12,
@segiddins for many contributions and better ideas, and everyone else
for their patience :)
chrismo added a commit to chrismo/bundler that referenced this issue Sep 27, 2016
tl;dr `--deployment` will copy _all_ gems to the `--path` now and a
proper fix is in place for nested bundle execs when `--path` is set and
RubyGems >=2.6.2 is being used.

Fixes rubygems#4974.

There's two problems blended in here. Let's trace the events here from
the beginning, shall we?

First off, from probably the first versions of Bundler, when
`disable_shared_gems` is true, the `GEM_PATH` gets internally overridden
and initialized to an empty string. This is done to make sure that later
in the `Bundler.setup` process it's expanded to ONLY the Bundler `--path`
setting, otherwise it expands to include the system gems path.

In 1.12, `bundle exec` was changed to use `Kernel.load` in some cases,
and that new code path calls `require "bundler/setup"`.

Later, issue rubygems#4592 was filed, showing that in cases like `--deployment`
where `disable_shared_gems` is true, Bundler couldn't find itself,
because Bundler never lives in the `--path` but only in system gems. And
as it would later be discovered, was not a problem with RubyGems 2.6.1,
but was a problem with >=2.6.2 (and older RubyGems it would seem, though
those weren't as thoroughly investigated).

We fixed rubygems#4592 (see PR rubygems#4701) in 1.13.0 by changing the oooold code
initializing `GEM_PATH` to be initialized to `nil` instead of empty
string in all `disable_shared_gems` cases. But it created another bug,
filed as rubygems#4974, wherein system gems were no longer copied to the
`--path` when `disable_shared_gems` was true. In this commit here (rubygems#4992)
we've reverted the change so that `GEM_PATH` is now back to being
initialized to an empty string instead of `nil`.

That fixes rubygems#4974, but regresses rubygems#4592, and we needed a new way to fix
it.

After a few tortured attempts at this, I ran across issue rubygems#4602, a
similar report of nested bundle execs being broken, rubygems#4602 itself an
extension of rubygems#4381 reporting the same problem. It brought to light the
role the Rubygems version played in the problem.

When the `bundler` gem is installed and the wrapper is generated for any
gem executables, the contents of this wrapper are determined by the
Rubygems version. Up until RubyGems 2.6.1 the last line of this wrapper
calls `Gem.bin_path`. Bundler replaces the Rubygems implementation of
`Gem.bin_path` with its own, and has for a long time made a special
exception for the Bundler gem itself, short-circuiting with the contents
of a special ENV variable called `BUNDLE_BIN_PATH`.

In Rubygems 2.6.2, `bin_path` was superseded by a new
`Gem.activate_bin_path` method which did what `bin_path` did but also
activated the gem. Bundler 1.13 added support for this, but it didn't
include the same short-circuit for bundler itself. (Alert user @taoza
even noticed this here rubygems@fcaab35#r56665282).

This commit also includes that short circuit for Rubygems >=2.6.2 now
and nested bundle exec should continue to work.

Thx to @miros for filing rubygems#4974 and isolating the problem in 1.12,
@segiddins for many contributions and better ideas, and everyone else
for their bug reports and patience :)
homu added a commit that referenced this issue Sep 27, 2016
…ismo

Fix GEM_PATH regression in 1.13.

_nth time is a charm ... here's the latest latest latest commit message_:

Fix disable_shared_gems bug & keep nested exec
tl;dr `--deployment` will copy _all_ gems to the `--path` now and a
proper fix is in place for nested bundle execs when `--path` is set and
RubyGems >=2.6.2 is being used.

Fixes #4974.

There's two problems blended in here. Let's trace the events here from
the beginning, shall we?

First off, from probably the first versions of Bundler, when
`disable_shared_gems` is true, the `GEM_PATH` gets internally overridden
and initialized to an empty string. This is done to make sure that later
in the `Bundler.setup` process it's expanded to ONLY the Bundler `--path`
setting, otherwise it expands to include the system path.

In 1.12, `bundle exec` was changed to use `Kernel.load` in some cases,
and that new code path calls `require "bundler/setup"`.

Later, issue #4592 was filed, showing that in cases like `--deployment`
where `disable_shared_gems` is true, Bundler couldn't find itself,
because Bundler never lives in the `--path` but only in system gems. And
as it would later be discovered, was not a problem with RubyGems 2.6.1,
but was a problem with >=2.6.2 (and older RubyGems it would seem, though
those weren't as thoroughly investigated).

We fixed #4592 (see PR #4701) in 1.13.0 by changing the oooold code
initializing `GEM_PATH` to be initialized to `nil` instead of empty
string in all `disable_shared_gems` cases. But it created another bug,
filed as #4974, wherein system gems were no longer copied to the
`--path` when `disable_shared_gems` is true. In this commit here (#4992)
we've reverted the change so that `GEM_PATH` is now back to being
initialized to an empty string instead of `nil`.

That fixes #4974, but regresses #4592, and we needed a new way to fix
it.

After a few tortured attempts at this, I ran across issue #4602, a
similar report of nested bundle execs being broken, #4602 itself an
extension of #4381 reporting the same problem. It brought to light the
role the Rubygems version played in the problem.

When the `bundler` gem is installed and the wrapper is generated for any
gem executables, the contents of this wrapper are determined by the
Rubygems version. Up until RubyGems 2.6.1 the last line of this wrapper
calls `Gem.bin_path`. Bundler replaces the Rubygems implementation of
`Gem.bin_path` with its own, and has for a long time made a special
exception for the Bundler gem itself, short-circuiting with the contents
of a special ENV variable called `BUNDLE_BIN_PATH`.

In Rubygems 2.6.2, `bin_path` was superseded by a new
`Gem.activate_bin_path` method which did what `bin_path` did but also
activated the gem. Bundler 1.13 added support for this, but it didn't
include the same short-circuit for bundler itself. (Alert user @taoza
even noticed this here
fcaab35#r56665282).

This commit also includes that short circuit for Rubygems >=2.6.2 now
and nested bundle exec should continue to work.
segiddins pushed a commit that referenced this issue Sep 30, 2016
…ismo

Fix GEM_PATH regression in 1.13.

_nth time is a charm ... here's the latest latest latest commit message_:

Fix disable_shared_gems bug & keep nested exec
tl;dr `--deployment` will copy _all_ gems to the `--path` now and a
proper fix is in place for nested bundle execs when `--path` is set and
RubyGems >=2.6.2 is being used.

Fixes #4974.

There's two problems blended in here. Let's trace the events here from
the beginning, shall we?

First off, from probably the first versions of Bundler, when
`disable_shared_gems` is true, the `GEM_PATH` gets internally overridden
and initialized to an empty string. This is done to make sure that later
in the `Bundler.setup` process it's expanded to ONLY the Bundler `--path`
setting, otherwise it expands to include the system path.

In 1.12, `bundle exec` was changed to use `Kernel.load` in some cases,
and that new code path calls `require "bundler/setup"`.

Later, issue #4592 was filed, showing that in cases like `--deployment`
where `disable_shared_gems` is true, Bundler couldn't find itself,
because Bundler never lives in the `--path` but only in system gems. And
as it would later be discovered, was not a problem with RubyGems 2.6.1,
but was a problem with >=2.6.2 (and older RubyGems it would seem, though
those weren't as thoroughly investigated).

We fixed #4592 (see PR #4701) in 1.13.0 by changing the oooold code
initializing `GEM_PATH` to be initialized to `nil` instead of empty
string in all `disable_shared_gems` cases. But it created another bug,
filed as #4974, wherein system gems were no longer copied to the
`--path` when `disable_shared_gems` is true. In this commit here (#4992)
we've reverted the change so that `GEM_PATH` is now back to being
initialized to an empty string instead of `nil`.

That fixes #4974, but regresses #4592, and we needed a new way to fix
it.

After a few tortured attempts at this, I ran across issue #4602, a
similar report of nested bundle execs being broken, #4602 itself an
extension of #4381 reporting the same problem. It brought to light the
role the Rubygems version played in the problem.

When the `bundler` gem is installed and the wrapper is generated for any
gem executables, the contents of this wrapper are determined by the
Rubygems version. Up until RubyGems 2.6.1 the last line of this wrapper
calls `Gem.bin_path`. Bundler replaces the Rubygems implementation of
`Gem.bin_path` with its own, and has for a long time made a special
exception for the Bundler gem itself, short-circuiting with the contents
of a special ENV variable called `BUNDLE_BIN_PATH`.

In Rubygems 2.6.2, `bin_path` was superseded by a new
`Gem.activate_bin_path` method which did what `bin_path` did but also
activated the gem. Bundler 1.13 added support for this, but it didn't
include the same short-circuit for bundler itself. (Alert user @taoza
even noticed this here
fcaab35#r56665282).

This commit also includes that short circuit for Rubygems >=2.6.2 now
and nested bundle exec should continue to work.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
7 participants