rubygems-update 3.6.7 → 3.6.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,161 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "rbconfig"
4
- require "shellwords"
5
-
6
3
  module Bundler
7
- class CLI::Doctor
8
- DARWIN_REGEX = /\s+(.+) \(compatibility /
9
- LDD_REGEX = /\t\S+ => (\S+) \(\S+\)/
10
-
11
- attr_reader :options
12
-
13
- def initialize(options)
14
- @options = options
15
- end
16
-
17
- def otool_available?
18
- Bundler.which("otool")
19
- end
20
-
21
- def ldd_available?
22
- Bundler.which("ldd")
23
- end
24
-
25
- def dylibs_darwin(path)
26
- output = `/usr/bin/otool -L #{path.shellescape}`.chomp
27
- dylibs = output.split("\n")[1..-1].map {|l| l.match(DARWIN_REGEX).captures[0] }.uniq
28
- # ignore @rpath and friends
29
- dylibs.reject {|dylib| dylib.start_with? "@" }
30
- end
31
-
32
- def dylibs_ldd(path)
33
- output = `/usr/bin/ldd #{path.shellescape}`.chomp
34
- output.split("\n").filter_map do |l|
35
- match = l.match(LDD_REGEX)
36
- next if match.nil?
37
- match.captures[0]
38
- end
39
- end
40
-
41
- def dylibs(path)
42
- case RbConfig::CONFIG["host_os"]
43
- when /darwin/
44
- return [] unless otool_available?
45
- dylibs_darwin(path)
46
- when /(linux|solaris|bsd)/
47
- return [] unless ldd_available?
48
- dylibs_ldd(path)
49
- else # Windows, etc.
50
- Bundler.ui.warn("Dynamic library check not supported on this platform.")
51
- []
52
- end
53
- end
54
-
55
- def bundles_for_gem(spec)
56
- Dir.glob("#{spec.full_gem_path}/**/*.bundle")
57
- end
58
-
59
- def lookup_with_fiddle(path)
60
- require "fiddle"
61
- Fiddle.dlopen(path)
62
- false
63
- rescue Fiddle::DLError
64
- true
65
- end
66
-
67
- def check!
68
- require_relative "check"
69
- Bundler::CLI::Check.new({}).run
70
- end
71
-
72
- def run
73
- Bundler.ui.level = "warn" if options[:quiet]
74
- Bundler.settings.validate!
75
- check!
76
-
77
- definition = Bundler.definition
78
- broken_links = {}
79
-
80
- definition.specs.each do |spec|
81
- bundles_for_gem(spec).each do |bundle|
82
- bad_paths = dylibs(bundle).select do |f|
83
- lookup_with_fiddle(f)
84
- end
85
- if bad_paths.any?
86
- broken_links[spec] ||= []
87
- broken_links[spec].concat(bad_paths)
88
- end
89
- end
90
- end
91
-
92
- permissions_valid = check_home_permissions
93
-
94
- if broken_links.any?
95
- message = "The following gems are missing OS dependencies:"
96
- broken_links.flat_map do |spec, paths|
97
- paths.uniq.map do |path|
98
- "\n * #{spec.name}: #{path}"
99
- end
100
- end.sort.each {|m| message += m }
101
- raise ProductionError, message
102
- elsif permissions_valid
103
- Bundler.ui.info "No issues found with the installed bundle"
104
- end
105
- end
106
-
107
- private
108
-
109
- def check_home_permissions
110
- require "find"
111
- files_not_readable = []
112
- files_not_readable_and_owned_by_different_user = []
113
- files_not_owned_by_current_user_but_still_readable = []
114
- broken_symlinks = []
115
- Find.find(Bundler.bundle_path.to_s).each do |f|
116
- if !File.exist?(f)
117
- broken_symlinks << f
118
- elsif !File.readable?(f)
119
- if File.stat(f).uid != Process.uid
120
- files_not_readable_and_owned_by_different_user << f
121
- else
122
- files_not_readable << f
123
- end
124
- elsif File.stat(f).uid != Process.uid
125
- files_not_owned_by_current_user_but_still_readable << f
126
- end
127
- end
128
-
129
- ok = true
130
-
131
- if broken_symlinks.any?
132
- Bundler.ui.warn "Broken links exist in the Bundler home. Please report them to the offending gem's upstream repo. These files are:\n - #{broken_symlinks.join("\n - ")}"
133
-
134
- ok = false
135
- end
136
-
137
- if files_not_owned_by_current_user_but_still_readable.any?
138
- Bundler.ui.warn "Files exist in the Bundler home that are owned by another " \
139
- "user, but are still readable. These files are:\n - #{files_not_owned_by_current_user_but_still_readable.join("\n - ")}"
140
-
141
- ok = false
142
- end
143
-
144
- if files_not_readable_and_owned_by_different_user.any?
145
- Bundler.ui.warn "Files exist in the Bundler home that are owned by another " \
146
- "user, and are not readable. These files are:\n - #{files_not_readable_and_owned_by_different_user.join("\n - ")}"
147
-
148
- ok = false
149
- end
150
-
151
- if files_not_readable.any?
152
- Bundler.ui.warn "Files exist in the Bundler home that are not " \
153
- "readable by the current user. These files are:\n - #{files_not_readable.join("\n - ")}"
154
-
155
- ok = false
156
- end
157
-
158
- ok
4
+ class CLI::Doctor < Thor
5
+ default_command(:diagnose)
6
+
7
+ desc "diagnose [OPTIONS]", "Checks the bundle for common problems"
8
+ long_desc <<-D
9
+ Doctor scans the OS dependencies of each of the gems requested in the Gemfile. If
10
+ missing dependencies are detected, Bundler prints them and exits status 1.
11
+ Otherwise, Bundler prints a success message and exits with a status of 0.
12
+ D
13
+ method_option "gemfile", type: :string, banner: "Use the specified gemfile instead of Gemfile"
14
+ method_option "quiet", type: :boolean, banner: "Only output warnings and errors."
15
+ method_option "ssl", type: :boolean, default: false, banner: "Diagnose SSL problems."
16
+ def diagnose
17
+ require_relative "doctor/diagnose"
18
+ Diagnose.new(options).run
19
+ end
20
+
21
+ desc "ssl [OPTIONS]", "Diagnose SSL problems"
22
+ long_desc <<-D
23
+ Diagnose SSL problems, especially related to certificates or TLS version while connecting to https://rubygems.org.
24
+ D
25
+ method_option "host", type: :string, banner: "The host to diagnose."
26
+ method_option "tls-version", type: :string, banner: "Specify the SSL/TLS version when running the diagnostic. Accepts either <1.1> or <1.2>"
27
+ method_option "verify-mode", type: :string, banner: "Specify the mode used for certification verification. Accepts either <peer> or <none>"
28
+ def ssl
29
+ require_relative "doctor/ssl"
30
+ SSL.new(options).run
159
31
  end
160
32
  end
161
33
  end
@@ -34,8 +34,8 @@ module Bundler
34
34
  end
35
35
 
36
36
  def doctor
37
- require_relative "doctor"
38
- Bundler::CLI::Doctor.new({}).run
37
+ require_relative "doctor/diagnose"
38
+ Bundler::CLI::Doctor::Diagnose.new({}).run
39
39
  end
40
40
  end
41
41
  end
@@ -610,17 +610,8 @@ module Bundler
610
610
  end
611
611
 
612
612
  desc "doctor [OPTIONS]", "Checks the bundle for common problems"
613
- long_desc <<-D
614
- Doctor scans the OS dependencies of each of the gems requested in the Gemfile. If
615
- missing dependencies are detected, Bundler prints them and exits status 1.
616
- Otherwise, Bundler prints a success message and exits with a status of 0.
617
- D
618
- method_option "gemfile", type: :string, banner: "Use the specified gemfile instead of Gemfile"
619
- method_option "quiet", type: :boolean, banner: "Only output warnings and errors."
620
- def doctor
621
- require_relative "cli/doctor"
622
- Doctor.new(options).run
623
- end
613
+ require_relative "cli/doctor"
614
+ subcommand("doctor", Doctor)
624
615
 
625
616
  desc "issue", "Learn how to report an issue in Bundler"
626
617
  def issue
@@ -257,7 +257,7 @@ module Bundler
257
257
  rescue BundlerError => e
258
258
  @resolve = nil
259
259
  @resolver = nil
260
- @resolution_packages = nil
260
+ @resolution_base = nil
261
261
  @source_requirements = nil
262
262
  @specs = nil
263
263
 
@@ -337,11 +337,7 @@ module Bundler
337
337
  end
338
338
  end
339
339
  else
340
- if lockfile_exists?
341
- Bundler.ui.debug "Found changes from the lockfile, re-resolving dependencies because #{change_reason}"
342
- else
343
- Bundler.ui.debug "Resolving dependencies because there's no lockfile"
344
- end
340
+ Bundler.ui.debug resolve_needed_reason
345
341
 
346
342
  start_resolution
347
343
  end
@@ -465,7 +461,7 @@ module Bundler
465
461
  end
466
462
 
467
463
  def normalize_platforms
468
- @platforms = resolve.normalize_platforms!(current_dependencies, platforms)
464
+ resolve.normalize_platforms!(current_dependencies, platforms)
469
465
 
470
466
  @resolve = SpecSet.new(resolve.for(current_dependencies, @platforms))
471
467
  end
@@ -537,9 +533,7 @@ module Bundler
537
533
 
538
534
  return unless added.any? || deleted.any? || changed.any? || resolve_needed?
539
535
 
540
- reason = resolve_needed? ? change_reason : "some dependencies were deleted from your gemfile"
541
-
542
- msg = String.new("#{reason.capitalize.strip}, but ")
536
+ msg = String.new("#{change_reason.capitalize.strip}, but ")
543
537
  msg << "the lockfile " unless msg.start_with?("Your lockfile")
544
538
  msg << "can't be updated because #{update_refused_reason}"
545
539
  msg << "\n\nYou have added to the Gemfile:\n" << added.join("\n") if added.any?
@@ -620,7 +614,7 @@ module Bundler
620
614
  end
621
615
 
622
616
  def resolver
623
- @resolver ||= Resolver.new(resolution_packages, gem_version_promoter, @most_specific_locked_platform)
617
+ @resolver ||= Resolver.new(resolution_base, gem_version_promoter, @most_specific_locked_platform)
624
618
  end
625
619
 
626
620
  def expanded_dependencies
@@ -634,15 +628,15 @@ module Bundler
634
628
  [Dependency.new("bundler", @unlocking_bundler)] + dependencies
635
629
  end
636
630
 
637
- def resolution_packages
638
- @resolution_packages ||= begin
631
+ def resolution_base
632
+ @resolution_base ||= begin
639
633
  last_resolve = converge_locked_specs
640
634
  remove_invalid_platforms!
641
635
  new_resolution_platforms = @current_platform_missing ? @new_platforms + [local_platform] : @new_platforms
642
- packages = Resolver::Base.new(source_requirements, expanded_dependencies, last_resolve, @platforms, locked_specs: @originally_locked_specs, unlock: @unlocking_all || @gems_to_unlock, prerelease: gem_version_promoter.pre?, prefer_local: @prefer_local, new_platforms: new_resolution_platforms)
643
- packages = additional_base_requirements_to_prevent_downgrades(packages)
644
- packages = additional_base_requirements_to_force_updates(packages)
645
- packages
636
+ base = Resolver::Base.new(source_requirements, expanded_dependencies, last_resolve, @platforms, locked_specs: @originally_locked_specs, unlock: @unlocking_all || @gems_to_unlock, prerelease: gem_version_promoter.pre?, prefer_local: @prefer_local, new_platforms: new_resolution_platforms)
637
+ base = additional_base_requirements_to_prevent_downgrades(base)
638
+ base = additional_base_requirements_to_force_updates(base)
639
+ base
646
640
  end
647
641
  end
648
642
 
@@ -717,8 +711,7 @@ module Bundler
717
711
  still_incomplete_specs = resolve.incomplete_specs
718
712
 
719
713
  if still_incomplete_specs == incomplete_specs
720
- package = resolution_packages.get_package(incomplete_specs.first.name)
721
- resolver.raise_not_found! package
714
+ resolver.raise_incomplete! incomplete_specs
722
715
  end
723
716
 
724
717
  incomplete_specs = still_incomplete_specs
@@ -740,7 +733,7 @@ module Bundler
740
733
  end
741
734
 
742
735
  def reresolve_without(incomplete_specs)
743
- resolution_packages.delete(incomplete_specs)
736
+ resolution_base.delete(incomplete_specs)
744
737
  @resolve = start_resolution
745
738
  end
746
739
 
@@ -753,8 +746,16 @@ module Bundler
753
746
 
754
747
  @resolved_bundler_version = result.find {|spec| spec.name == "bundler" }&.version
755
748
 
749
+ @new_platforms.each do |platform|
750
+ incomplete_specs = result.incomplete_specs_for_platform(current_dependencies, platform)
751
+
752
+ if incomplete_specs.any?
753
+ resolver.raise_incomplete! incomplete_specs
754
+ end
755
+ end
756
+
756
757
  if @most_specific_non_local_locked_platform
757
- if spec_set_incomplete_for_platform?(result, @most_specific_non_local_locked_platform)
758
+ if result.incomplete_for_platform?(current_dependencies, @most_specific_non_local_locked_platform)
758
759
  @platforms.delete(@most_specific_non_local_locked_platform)
759
760
  elsif local_platform_needed_for_resolvability
760
761
  @platforms.delete(local_platform)
@@ -796,22 +797,47 @@ module Bundler
796
797
  @most_specific_locked_platform
797
798
  end
798
799
 
799
- def change_reason
800
- if unlocking?
801
- unlock_targets = if @gems_to_unlock.any?
802
- ["gems", @gems_to_unlock]
803
- elsif @sources_to_unlock.any?
804
- ["sources", @sources_to_unlock]
800
+ def resolve_needed_reason
801
+ if lockfile_exists?
802
+ if unlocking?
803
+ "Re-resolving dependencies because #{unlocking_reason}"
804
+ else
805
+ "Found changes from the lockfile, re-resolving dependencies because #{lockfile_changed_reason}"
805
806
  end
807
+ else
808
+ "Resolving dependencies because there's no lockfile"
809
+ end
810
+ end
806
811
 
807
- unlock_reason = if unlock_targets
808
- "#{unlock_targets.first}: (#{unlock_targets.last.join(", ")})"
812
+ def change_reason
813
+ if resolve_needed?
814
+ if unlocking?
815
+ unlocking_reason
809
816
  else
810
- @unlocking_ruby ? "ruby" : ""
817
+ lockfile_changed_reason
811
818
  end
819
+ else
820
+ "some dependencies were deleted from your gemfile"
821
+ end
822
+ end
812
823
 
813
- return "bundler is unlocking #{unlock_reason}"
824
+ def unlocking_reason
825
+ unlock_targets = if @gems_to_unlock.any?
826
+ ["gems", @gems_to_unlock]
827
+ elsif @sources_to_unlock.any?
828
+ ["sources", @sources_to_unlock]
814
829
  end
830
+
831
+ unlock_reason = if unlock_targets
832
+ "#{unlock_targets.first}: (#{unlock_targets.last.join(", ")})"
833
+ else
834
+ @unlocking_ruby ? "ruby" : ""
835
+ end
836
+
837
+ "bundler is unlocking #{unlock_reason}"
838
+ end
839
+
840
+ def lockfile_changed_reason
815
841
  [
816
842
  [@source_changes, "the list of sources changed"],
817
843
  [@dependency_changes, "the dependencies in your gemfile changed"],
@@ -1105,27 +1131,27 @@ module Bundler
1105
1131
  current == proposed
1106
1132
  end
1107
1133
 
1108
- def additional_base_requirements_to_prevent_downgrades(resolution_packages)
1109
- return resolution_packages unless @locked_gems && !sources.expired_sources?(@locked_gems.sources)
1134
+ def additional_base_requirements_to_prevent_downgrades(resolution_base)
1135
+ return resolution_base unless @locked_gems && !sources.expired_sources?(@locked_gems.sources)
1110
1136
  @originally_locked_specs.each do |locked_spec|
1111
1137
  next if locked_spec.source.is_a?(Source::Path)
1112
1138
 
1113
1139
  name = locked_spec.name
1114
1140
  next if @changed_dependencies.include?(name)
1115
1141
 
1116
- resolution_packages.base_requirements[name] = Gem::Requirement.new(">= #{locked_spec.version}")
1142
+ resolution_base.base_requirements[name] = Gem::Requirement.new(">= #{locked_spec.version}")
1117
1143
  end
1118
- resolution_packages
1144
+ resolution_base
1119
1145
  end
1120
1146
 
1121
- def additional_base_requirements_to_force_updates(resolution_packages)
1122
- return resolution_packages if @explicit_unlocks.empty?
1147
+ def additional_base_requirements_to_force_updates(resolution_base)
1148
+ return resolution_base if @explicit_unlocks.empty?
1123
1149
  full_update = dup_for_full_unlock.resolve
1124
1150
  @explicit_unlocks.each do |name|
1125
1151
  version = full_update.version_for(name)
1126
- resolution_packages.base_requirements[name] = Gem::Requirement.new("= #{version}") if version
1152
+ resolution_base.base_requirements[name] = Gem::Requirement.new("= #{version}") if version
1127
1153
  end
1128
- resolution_packages
1154
+ resolution_base
1129
1155
  end
1130
1156
 
1131
1157
  def dup_for_full_unlock
@@ -1142,25 +1168,16 @@ module Bundler
1142
1168
  def remove_invalid_platforms!
1143
1169
  return if Bundler.frozen_bundle?
1144
1170
 
1145
- @originally_invalid_platforms = platforms.select do |platform|
1146
- next if local_platform == platform ||
1147
- @new_platforms.include?(platform)
1148
-
1149
- # We should probably avoid removing non-ruby platforms, since that means
1150
- # lockfile will no longer install on those platforms, so a error to give
1151
- # heads up to the user may be better. However, we have tests expecting
1152
- # non ruby platform autoremoval to work, so leaving that in place for
1153
- # now.
1154
- next if @dependency_changes && platform != Gem::Platform::RUBY
1171
+ skips = (@new_platforms + [local_platform]).uniq
1155
1172
 
1156
- spec_set_incomplete_for_platform?(@originally_locked_specs, platform)
1157
- end
1158
-
1159
- @platforms -= @originally_invalid_platforms
1160
- end
1173
+ # We should probably avoid removing non-ruby platforms, since that means
1174
+ # lockfile will no longer install on those platforms, so a error to give
1175
+ # heads up to the user may be better. However, we have tests expecting
1176
+ # non ruby platform autoremoval to work, so leaving that in place for
1177
+ # now.
1178
+ skips |= platforms - [Gem::Platform::RUBY] if @dependency_changes
1161
1179
 
1162
- def spec_set_incomplete_for_platform?(spec_set, platform)
1163
- spec_set.incomplete_for_platform?(current_dependencies, platform)
1180
+ @originally_invalid_platforms = @originally_locked_specs.remove_invalid_platforms!(current_dependencies, platforms, skips: skips)
1164
1181
  end
1165
1182
 
1166
1183
  def source_map
@@ -80,7 +80,7 @@ module Bundler
80
80
  First, try this link to see if there are any existing issue reports for this error:
81
81
  #{issues_url(e)}
82
82
 
83
- If there aren't any reports for this error yet, please fill in the new issue form located at #{new_issue_url}, and copy and paste the report template above in there.
83
+ If there aren't any reports for this error yet, please fill in the new issue form located at #{new_issue_url}. Make sure to copy and paste the full output of this command under the "What happened instead?" section.
84
84
  EOS
85
85
  end
86
86
 
@@ -212,7 +212,7 @@ module Bundler
212
212
  def load_plugins
213
213
  Gem.load_plugins
214
214
 
215
- requested_path_gems = @definition.requested_specs.select {|s| s.source.is_a?(Source::Path) }
215
+ requested_path_gems = @definition.specs.select {|s| s.source.is_a?(Source::Path) }
216
216
  path_plugin_files = requested_path_gems.flat_map do |spec|
217
217
  spec.matches_for_glob("rubygems_plugin#{Bundler.rubygems.suffix_pattern}")
218
218
  rescue TypeError
@@ -213,22 +213,31 @@ module Bundler
213
213
  end
214
214
  if search.nil? && fallback_to_non_installable
215
215
  search = candidates.last
216
- elsif search && search.full_name == full_name
217
- # We don't validate locally installed dependencies but accept what's in
218
- # the lockfile instead for performance, since loading locally installed
219
- # dependencies would mean evaluating all gemspecs, which would affect
220
- # `bundler/setup` performance
221
- if search.is_a?(StubSpecification)
222
- search.dependencies = dependencies
223
- else
224
- if !source.is_a?(Source::Path) && search.runtime_dependencies.sort != dependencies.sort
225
- raise IncorrectLockfileDependencies.new(self)
226
- end
216
+ end
227
217
 
228
- search.locked_platform = platform if search.instance_of?(RemoteSpecification) || search.instance_of?(EndpointSpecification)
229
- end
218
+ if search
219
+ validate_dependencies(search) if search.platform == platform
220
+
221
+ search.locked_platform = platform if search.instance_of?(RemoteSpecification) || search.instance_of?(EndpointSpecification)
230
222
  end
231
223
  search
232
224
  end
225
+
226
+ # Validate dependencies of this locked spec are consistent with dependencies
227
+ # of the actual spec that was materialized.
228
+ #
229
+ # Note that we don't validate dependencies of locally installed gems but
230
+ # accept what's in the lockfile instead for performance, since loading
231
+ # dependencies of locally installed gems would mean evaluating all gemspecs,
232
+ # which would affect `bundler/setup` performance.
233
+ def validate_dependencies(spec)
234
+ if spec.is_a?(StubSpecification)
235
+ spec.dependencies = dependencies
236
+ else
237
+ if !source.is_a?(Source::Path) && spec.runtime_dependencies.sort != dependencies.sort
238
+ raise IncorrectLockfileDependencies.new(self)
239
+ end
240
+ end
241
+ end
233
242
  end
234
243
  end
@@ -312,6 +312,16 @@ module Bundler
312
312
  "Gemfile"
313
313
  end
314
314
 
315
+ def raise_incomplete!(incomplete_specs)
316
+ raise_not_found!(@base.get_package(incomplete_specs.first.name))
317
+ end
318
+
319
+ def sort_versions_by_preferred(package, versions)
320
+ @gem_version_promoter.sort_versions(package, versions)
321
+ end
322
+
323
+ private
324
+
315
325
  def raise_not_found!(package)
316
326
  name = package.name
317
327
  source = source_for(name)
@@ -348,12 +358,6 @@ module Bundler
348
358
  raise GemNotFound, message
349
359
  end
350
360
 
351
- def sort_versions_by_preferred(package, versions)
352
- @gem_version_promoter.sort_versions(package, versions)
353
- end
354
-
355
- private
356
-
357
361
  def filtered_versions_for(package)
358
362
  @gem_version_promoter.filter_versions(package, @all_versions[package])
359
363
  end
@@ -29,9 +29,10 @@ module Bundler
29
29
  end
30
30
 
31
31
  def normalize_platforms!(deps, platforms)
32
- complete_platforms = add_extra_platforms!(platforms)
32
+ remove_invalid_platforms!(deps, platforms)
33
+ add_extra_platforms!(platforms)
33
34
 
34
- complete_platforms.map do |platform|
35
+ platforms.map! do |platform|
35
36
  next platform if platform == Gem::Platform::RUBY
36
37
 
37
38
  begin
@@ -44,7 +45,7 @@ module Bundler
44
45
  next platform if incomplete_for_platform?(deps, less_specific_platform)
45
46
 
46
47
  less_specific_platform
47
- end.uniq
48
+ end.uniq!
48
49
  end
49
50
 
50
51
  def add_originally_invalid_platforms!(platforms, originally_invalid_platforms)
@@ -53,6 +54,20 @@ module Bundler
53
54
  end
54
55
  end
55
56
 
57
+ def remove_invalid_platforms!(deps, platforms, skips: [])
58
+ invalid_platforms = []
59
+
60
+ platforms.reject! do |platform|
61
+ next false if skips.include?(platform)
62
+
63
+ invalid = incomplete_for_platform?(deps, platform)
64
+ invalid_platforms << platform if invalid
65
+ invalid
66
+ end
67
+
68
+ invalid_platforms
69
+ end
70
+
56
71
  def add_extra_platforms!(platforms)
57
72
  if @specs.empty?
58
73
  platforms.concat([Gem::Platform::RUBY]).uniq
@@ -68,6 +83,7 @@ module Bundler
68
83
  return if new_platforms.empty?
69
84
 
70
85
  platforms.concat(new_platforms)
86
+ return if new_platforms.include?(Bundler.local_platform)
71
87
 
72
88
  less_specific_platform = new_platforms.find {|platform| platform != Gem::Platform::RUBY && Bundler.local_platform === platform && platform === Bundler.local_platform }
73
89
  platforms.delete(Bundler.local_platform) if less_specific_platform
@@ -129,12 +145,15 @@ module Bundler
129
145
  end
130
146
 
131
147
  def incomplete_for_platform?(deps, platform)
132
- return false if @specs.empty?
148
+ incomplete_specs_for_platform(deps, platform).any?
149
+ end
150
+
151
+ def incomplete_specs_for_platform(deps, platform)
152
+ return [] if @specs.empty?
133
153
 
134
154
  validation_set = self.class.new(@specs)
135
155
  validation_set.for(deps, [platform])
136
-
137
- validation_set.incomplete_specs.any?
156
+ validation_set.incomplete_specs
138
157
  end
139
158
 
140
159
  def missing_specs_for(deps)
@@ -180,7 +199,7 @@ module Bundler
180
199
  end
181
200
 
182
201
  def version_for(name)
183
- self[name].first&.version
202
+ exemplary_spec(name)&.version
184
203
  end
185
204
 
186
205
  def what_required(spec)
@@ -285,8 +304,13 @@ module Bundler
285
304
  end
286
305
 
287
306
  def additional_variants_from(other)
288
- other.select do |spec|
289
- version_for(spec.name) == spec.version && valid_dependencies?(spec)
307
+ other.select do |other_spec|
308
+ spec = exemplary_spec(other_spec.name)
309
+ next unless spec
310
+
311
+ selected = spec.version == other_spec.version && valid_dependencies?(other_spec)
312
+ other_spec.source = spec.source if selected
313
+ selected
290
314
  end
291
315
  end
292
316
 
@@ -363,5 +387,9 @@ module Bundler
363
387
  hash[key] ||= []
364
388
  hash[key] << value
365
389
  end
390
+
391
+ def exemplary_spec(name)
392
+ self[name].first
393
+ end
366
394
  end
367
395
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: false
2
2
 
3
3
  module Bundler
4
- VERSION = "2.6.7".freeze
4
+ VERSION = "2.6.9".freeze
5
5
 
6
6
  def self.bundler_major_version
7
7
  @bundler_major_version ||= VERSION.split(".").first.to_i
@@ -70,10 +70,6 @@ And to run an individual test method named `test_default` within a test file, yo
70
70
 
71
71
  ### Running bundler tests
72
72
 
73
- To setup bundler tests:
74
-
75
- bin/rake spec:parallel_deps
76
-
77
73
  To run the entire bundler test suite in parallel (it takes a while), run the following from the `bundler/` subfolder:
78
74
 
79
75
  bin/parallel_rspec