[rubygems/rubygems] Fix yanked gems being unintentionally update when other gems are unlocked

This is a regression from a change intended to raise errors when user
puts a gem under an incorrect source in the Gemfile by mistake. To fix
the issue, we revert the change that caused it and implement it in a
different way that restores the resolver independency from real
specifications. Now it deals only with names and versions and does not
try to materialize anything into real specifications before resolving.

https://github.com/rubygems/rubygems/commit/d2bf1b86eb
This commit is contained in:
David Rodríguez 2022-08-03 19:03:50 +02:00 коммит произвёл git
Родитель 8dd63b89d9
Коммит 466a760e18
6 изменённых файлов: 81 добавлений и 20 удалений

Просмотреть файл

@ -739,11 +739,22 @@ module Bundler
specs[dep].any? {|s| s.satisfies?(dep) && (!dep.source || s.source.include?(dep.source)) }
end
@specs_that_changed_sources = []
specs.each do |s|
dep = @dependencies.find {|d| s.satisfies?(d) }
# Replace the locked dependency's source with the equivalent source from the Gemfile
s.source = (dep && dep.source) || sources.get_with_fallback(s.source)
s.source = if dep && dep.source
gemfile_source = dep.source
lockfile_source = s.source
@specs_that_changed_sources << s if gemfile_source != lockfile_source
gemfile_source
else
sources.get_with_fallback(s.source)
end
next if @unlock[:sources].include?(s.source.name)
@ -821,9 +832,18 @@ module Bundler
end
source_requirements[:default_bundler] = source_requirements["bundler"] || sources.default_source
source_requirements["bundler"] = sources.metadata_source # needs to come last to override
verify_changed_sources!
source_requirements
end
def verify_changed_sources!
@specs_that_changed_sources.each do |s|
if s.source.specs.search(s.name).empty?
raise GemNotFound, "Could not find gem '#{s.name}' in #{s.source}"
end
end
end
def requested_groups
values = groups - Bundler.settings[:without] - @optional_groups + Bundler.settings[:with]
values &= Bundler.settings[:only] unless Bundler.settings[:only].empty?

Просмотреть файл

@ -93,14 +93,6 @@ module Bundler
__materialize__(candidates)
end
def materialize_for_resolution
return self unless Gem::Platform.match_spec?(self)
candidates = source.specs.search(self)
__materialize__(candidates)
end
def __materialize__(candidates)
@specification = begin
search = candidates.reverse.find do |spec|

Просмотреть файл

@ -28,10 +28,11 @@ module Bundler
def initialize(source_requirements, base, gem_version_promoter, additional_base_requirements, platforms, metadata_requirements)
@source_requirements = source_requirements
@metadata_requirements = metadata_requirements
@base = base
@resolver = Molinillo::Resolver.new(self, self)
@search_for = {}
@base_dg = Molinillo::DependencyGraph.new
@base = base.materialized_for_resolution do |ls|
base.each do |ls|
dep = Dependency.new(ls.name, ls.version)
@base_dg.add_vertex(ls.name, DepProxy.get_proxy(dep, ls.platform), true)
end

Просмотреть файл

@ -82,15 +82,6 @@ module Bundler
end
end
def materialized_for_resolution
materialized = @specs.map do |s|
spec = s.materialize_for_resolution
yield spec if spec
spec
end.compact
SpecSet.new(materialized)
end
def incomplete_ruby_specs?(deps)
self.class.new(self.for(deps, true, [Gem::Platform::RUBY])).incomplete_specs.any?
end

Просмотреть файл

@ -43,6 +43,63 @@ RSpec.context "when installing a bundle that includes yanked gems" do
end
end
RSpec.context "when resolving a bundle that includes yanked gems, but unlocking an unrelated gem" do
before(:each) do
build_repo4 do
build_gem "foo", "10.0.0"
build_gem "bar", "1.0.0"
build_gem "bar", "2.0.0"
end
lockfile <<-L
GEM
remote: #{file_uri_for(gem_repo4)}
specs:
foo (9.0.0)
bar (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
foo
bar
BUNDLED WITH
#{Bundler::VERSION}
L
gemfile <<-G
source "#{file_uri_for(gem_repo4)}"
gem "foo"
gem "bar"
G
end
it "does not update the yanked gem" do
bundle "lock --update bar"
expect(lockfile).to eq <<~L
GEM
remote: #{file_uri_for(gem_repo4)}/
specs:
bar (2.0.0)
foo (9.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
bar
foo
BUNDLED WITH
#{Bundler::VERSION}
L
end
end
RSpec.context "when using gem before installing" do
it "does not suggest the author has yanked the gem" do
gemfile <<-G

Просмотреть файл

@ -233,7 +233,7 @@ Bundler could not find compatible versions for gem "a":
it "resolves foo only to latest patch - changing dependency declared case" do
# bar is locked AND a declared dependency in the Gemfile, so it will not move, and therefore
# foo can only move up to 1.4.4.
@base << Bundler::LazySpecification.new("bar", "2.0.3", nil)
@base << build_spec("bar", "2.0.3").first
should_conservative_resolve_and_include :patch, ["foo"], %w[foo-1.4.4 bar-2.0.3]
end