1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

[rubygems/rubygems] Fix bundle install crash due to an incorrectly incomplete resolve

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.

https://github.com/rubygems/rubygems/commit/708afdd789
This commit is contained in:
David Rodríguez 2021-09-29 21:11:23 +02:00 committed by git
parent d1e6f2226b
commit 853004e04d
2 changed files with 97 additions and 2 deletions

View file

@ -78,7 +78,6 @@ module Bundler
@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)
@ -144,6 +143,8 @@ module Bundler
@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
@ -762,7 +763,6 @@ module Bundler
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

View file

@ -775,6 +775,101 @@ RSpec.describe "bundle install with gem sources" do
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