Skip to content

Commit 10d74a3

Browse files
Merge pull request #7307 from rubygems/fix-incorrect-lockfile
Fix incorrect lockfiles being generated in some situations
2 parents b82eca1 + b558baa commit 10d74a3

File tree

7 files changed

+88
-15
lines changed

7 files changed

+88
-15
lines changed

bundler/lib/bundler/definition.rb

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -722,17 +722,14 @@ def check_lockfile
722722
@locked_spec_with_invalid_deps = nil
723723
@locked_spec_with_missing_deps = nil
724724

725-
locked_names = @locked_specs.map(&:name)
726725
missing = []
727726
invalid = []
728727

729728
@locked_specs.each do |s|
730-
s.dependencies.each do |dep|
731-
next if dep.name == "bundler"
729+
validation = @locked_specs.validate_deps(s)
732730

733-
missing << s unless locked_names.include?(dep.name)
734-
invalid << s if @locked_specs.none? {|spec| dep.matches_spec?(spec) }
735-
end
731+
missing << s if validation == :missing
732+
invalid << s if validation == :invalid
736733
end
737734

738735
if missing.any?

bundler/lib/bundler/lazy_specification.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ class LazySpecification
1010
attr_reader :name, :version, :platform
1111
attr_accessor :source, :remote, :force_ruby_platform, :dependencies, :required_ruby_version, :required_rubygems_version
1212

13+
alias_method :runtime_dependencies, :dependencies
14+
1315
def self.from_spec(s)
1416
lazy_spec = new(s.name, s.version, s.platform, s.source)
1517
lazy_spec.dependencies = s.dependencies

bundler/lib/bundler/remote_specification.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ def dependencies
8888
end
8989
end
9090

91+
def runtime_dependencies
92+
dependencies.select(&:runtime?)
93+
end
94+
9195
def git_version
9296
return unless loaded_from && source.is_a?(Bundler::Source::Git)
9397
" #{source.revision[0..6]}"

bundler/lib/bundler/spec_set.rb

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,15 @@ def for(dependencies, check = false, platforms = [nil])
3737

3838
specs_for_dep.first.dependencies.each do |d|
3939
next if d.type == :development
40-
incomplete = true if d.name != "bundler" && lookup[d.name].empty?
40+
incomplete = true if d.name != "bundler" && lookup[d.name].nil?
4141
deps << [d, dep[1]]
4242
end
4343
else
4444
incomplete = true
4545
end
4646

4747
if incomplete && check
48-
@incomplete_specs += lookup[name].any? ? lookup[name] : [LazySpecification.new(name, nil, nil)]
48+
@incomplete_specs += lookup[name] || [LazySpecification.new(name, nil, nil)]
4949
end
5050
end
5151

@@ -64,7 +64,9 @@ def complete_platforms!(platforms)
6464
valid_platform = lookup.all? do |_, specs|
6565
spec = specs.first
6666
matching_specs = spec.source.specs.search([spec.name, spec.version])
67-
platform_spec = GemHelpers.select_best_platform_match(matching_specs, platform).find(&:matches_current_metadata?)
67+
platform_spec = GemHelpers.select_best_platform_match(matching_specs, platform).find do |s|
68+
s.matches_current_metadata? && valid_dependencies?(s)
69+
end
6870

6971
if platform_spec
7072
new_specs << LazySpecification.from_spec(platform_spec)
@@ -90,9 +92,20 @@ def complete_platforms!(platforms)
9092
platforms
9193
end
9294

95+
def validate_deps(s)
96+
s.runtime_dependencies.each do |dep|
97+
next if dep.name == "bundler"
98+
99+
return :missing unless names.include?(dep.name)
100+
return :invalid if none? {|spec| dep.matches_spec?(spec) }
101+
end
102+
103+
:valid
104+
end
105+
93106
def [](key)
94107
key = key.name if key.respond_to?(:name)
95-
lookup[key].reverse
108+
lookup[key]&.reverse || []
96109
end
97110

98111
def []=(key, value)
@@ -167,7 +180,7 @@ def delete_by_name(name)
167180
end
168181

169182
def what_required(spec)
170-
unless req = find {|s| s.dependencies.any? {|d| d.type == :runtime && d.name == spec.name } }
183+
unless req = find {|s| s.runtime_dependencies.any? {|d| d.name == spec.name } }
171184
return [spec]
172185
end
173186
what_required(req) << spec
@@ -193,8 +206,16 @@ def each(&b)
193206
sorted.each(&b)
194207
end
195208

209+
def names
210+
lookup.keys
211+
end
212+
196213
private
197214

215+
def valid_dependencies?(s)
216+
validate_deps(s) == :valid
217+
end
218+
198219
def sorted
199220
rake = @specs.find {|s| s.name == "rake" }
200221
begin
@@ -213,8 +234,9 @@ def extract_circular_gems(error)
213234

214235
def lookup
215236
@lookup ||= begin
216-
lookup = Hash.new {|h, k| h[k] = [] }
237+
lookup = {}
217238
@specs.each do |s|
239+
lookup[s.name] ||= []
218240
lookup[s.name] << s
219241
end
220242
lookup
@@ -228,6 +250,8 @@ def tsort_each_node
228250

229251
def specs_for_dependency(dep, platform)
230252
specs_for_name = lookup[dep.name]
253+
return [] unless specs_for_name
254+
231255
matching_specs = if dep.force_ruby_platform
232256
GemHelpers.force_ruby_platform(specs_for_name)
233257
else
@@ -240,7 +264,11 @@ def specs_for_dependency(dep, platform)
240264
def tsort_each_child(s)
241265
s.dependencies.sort_by(&:name).each do |d|
242266
next if d.type == :development
243-
lookup[d.name].each {|s2| yield s2 }
267+
268+
specs_for_name = lookup[d.name]
269+
next unless specs_for_name
270+
271+
specs_for_name.each {|s2| yield s2 }
244272
end
245273
end
246274
end

bundler/spec/install/gemfile/specific_platform_spec.rb

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,6 +1220,48 @@
12201220
end
12211221
end
12221222

1223+
it "does not add ruby platform gem if it brings extra dependencies not resolved originally" do
1224+
build_repo4 do
1225+
build_gem "nokogiri", "1.15.5" do |s|
1226+
s.add_dependency "mini_portile2", "~> 2.8.2"
1227+
end
1228+
1229+
build_gem "nokogiri", "1.15.5" do |s|
1230+
s.platform = "x86_64-linux"
1231+
end
1232+
end
1233+
1234+
gemfile <<~G
1235+
source "#{file_uri_for(gem_repo4)}"
1236+
1237+
gem "nokogiri"
1238+
G
1239+
1240+
checksums = checksums_section_when_existing do |c|
1241+
c.checksum gem_repo4, "nokogiri", "1.15.5", "x86_64-linux"
1242+
end
1243+
1244+
simulate_platform "x86_64-linux" do
1245+
bundle "install --verbose", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
1246+
1247+
expect(lockfile).to eq(<<~L)
1248+
GEM
1249+
remote: #{file_uri_for(gem_repo4)}/
1250+
specs:
1251+
nokogiri (1.15.5-x86_64-linux)
1252+
1253+
PLATFORMS
1254+
x86_64-linux
1255+
1256+
DEPENDENCIES
1257+
nokogiri
1258+
#{checksums}
1259+
BUNDLED WITH
1260+
#{Bundler::VERSION}
1261+
L
1262+
end
1263+
end
1264+
12231265
private
12241266

12251267
def setup_multiplatform_gem

bundler/spec/support/artifice/helpers/compact_index.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ def gems(gem_repo = default_gem_repo)
7777

7878
specs.group_by(&:name).map do |name, versions|
7979
gem_versions = versions.map do |spec|
80-
deps = spec.dependencies.select {|d| d.type == :runtime }.map do |d|
80+
deps = spec.runtime_dependencies.map do |d|
8181
reqs = d.requirement.requirements.map {|r| r.join(" ") }.join(", ")
8282
CompactIndex::Dependency.new(d.name, reqs)
8383
end

bundler/spec/support/artifice/helpers/endpoint.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ def dependencies_for(gem_names, gem_repo = default_gem_repo)
7272
name: spec.name,
7373
number: spec.version.version,
7474
platform: spec.platform.to_s,
75-
dependencies: spec.dependencies.select {|dep| dep.type == :runtime }.map do |dep|
75+
dependencies: spec.runtime_dependencies.map do |dep|
7676
[dep.name, dep.requirement.requirements.map {|a| a.join(" ") }.join(", ")]
7777
end,
7878
}

0 commit comments

Comments
 (0)