Skip to content

Commit

Permalink
Fix bundle install crash due to an incorrectly incomplete resolve
Browse files Browse the repository at this point in the history
In case we have a corrupted lockfile that claims to support a platform, but
it's missing platform specific gems for it, bundler has a check that
detects the situation and forces a re-resolve. The result of this check
is kept under the `@locked_specs_incomplete_for_platformn` instance
variable in `Definition`.

The installer, however, calls `Definition#nothing_changed?` before this
instance variable has been filled, so the result of it is actually
incorrect here since it will claim that nothing has changed, but
something has changed (locked specs are incomplete for the current
platform).

The consequence of this incorrect result is that the installer thinks it
can go on without re-resolving, resulting in the incomplete resolution
from the lockfile being used, and in a crash being triggered due to
that.

The solution is to make sure the `@locked_specs_incomplete_for_platform`
instance variable is filled before `nothing_changed?` gets called.
Moving it to `initialize` makes the most sense, not because it's the
best place for it (we can refactor this later), but because all of the
other "outdated definition" checks are already set there.
  • Loading branch information
deivid-rodriguez committed Oct 13, 2021
1 parent d6c6d04 commit 708afdd
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 2 deletions.
4 changes: 2 additions & 2 deletions bundler/lib/bundler/definition.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ def initialize(lockfile, dependencies, sources, unlock, ruby_version = nil, opti
@lockfile_contents = String.new
@locked_bundler_version = nil
@locked_ruby_version = nil
@locked_specs_incomplete_for_platform = false
@new_platform = nil

if lockfile && File.exist?(lockfile)
Expand Down Expand Up @@ -144,6 +143,8 @@ def initialize(lockfile, dependencies, sources, unlock, ruby_version = nil, opti
@dependency_changes = converge_dependencies
@local_changes = converge_locals

@locked_specs_incomplete_for_platform = !@locked_specs.for(expand_dependencies(requested_dependencies & locked_dependencies), true, true)

@requires = compute_requires
end

Expand Down Expand Up @@ -762,7 +763,6 @@ def converge_locked_specs
end

resolve = SpecSet.new(converged)
@locked_specs_incomplete_for_platform = !@locked_specs.for(expand_dependencies(requested_dependencies & locked_dependencies), true, true)
resolve = SpecSet.new(resolve.for(expand_dependencies(deps, true), false, false).reject{|s| @unlock[:gems].include?(s.name) })
diff = nil

Expand Down
95 changes: 95 additions & 0 deletions bundler/spec/commands/install_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,101 @@ def run
end
end

context "with missing platform specific gems in lockfile" do
before do
build_repo4 do
build_gem "racc", "1.5.2"

build_gem "nokogiri", "1.12.4" do |s|
s.platform = "x86_64-darwin"
s.add_runtime_dependency "racc", "~> 1.4"
end

build_gem "nokogiri", "1.12.4" do |s|
s.platform = "x86_64-linux"
s.add_runtime_dependency "racc", "~> 1.4"
end

build_gem "crass", "1.0.6"

build_gem "loofah", "2.12.0" do |s|
s.add_runtime_dependency "crass", "~> 1.0.2"
s.add_runtime_dependency "nokogiri", ">= 1.5.9"
end
end

gemfile <<-G
source "https://gem.repo4"
ruby "#{RUBY_VERSION}"
gem "loofah", "~> 2.12.0"
G

lockfile <<-L
GEM
remote: https://gem.repo4/
specs:
crass (1.0.6)
loofah (2.12.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
nokogiri (1.12.4-x86_64-darwin)
racc (~> 1.4)
racc (1.5.2)
PLATFORMS
x86_64-darwin-20
x86_64-linux
DEPENDENCIES
loofah (~> 2.12.0)
RUBY VERSION
#{Bundler::RubyVersion.system}
BUNDLED WITH
#{Bundler::VERSION}
L
end

it "automatically fixes the lockfile" do
bundle "config set --local path vendor/bundle"

simulate_platform "x86_64-linux" do
bundle "install", :artifice => "compact_index"
end

expect(lockfile).to eq <<~L
GEM
remote: https://gem.repo4/
specs:
crass (1.0.6)
loofah (2.12.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
nokogiri (1.12.4-x86_64-darwin)
racc (~> 1.4)
nokogiri (1.12.4-x86_64-linux)
racc (~> 1.4)
racc (1.5.2)
PLATFORMS
x86_64-darwin-20
x86_64-linux
DEPENDENCIES
loofah (~> 2.12.0)
RUBY VERSION
#{Bundler::RubyVersion.system}
BUNDLED WITH
#{Bundler::VERSION}
L
end
end

context "with --local flag" do
before do
system_gems "rack-1.0.0", :path => default_bundle_path
Expand Down

0 comments on commit 708afdd

Please sign in to comment.