bundler 2.6.5 → 2.7.1

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.
Files changed (136) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1172 -1024
  3. data/README.md +7 -7
  4. data/bundler.gemspec +2 -2
  5. data/lib/bundler/build_metadata.rb +10 -11
  6. data/lib/bundler/checksum.rb +22 -12
  7. data/lib/bundler/cli/common.rb +1 -1
  8. data/lib/bundler/cli/config.rb +2 -2
  9. data/lib/bundler/cli/doctor/diagnose.rb +167 -0
  10. data/lib/bundler/cli/doctor/ssl.rb +249 -0
  11. data/lib/bundler/cli/doctor.rb +27 -155
  12. data/lib/bundler/cli/gem.rb +62 -30
  13. data/lib/bundler/cli/inject.rb +2 -2
  14. data/lib/bundler/cli/install.rb +5 -5
  15. data/lib/bundler/cli/issue.rb +2 -2
  16. data/lib/bundler/cli/lock.rb +2 -1
  17. data/lib/bundler/cli/outdated.rb +1 -1
  18. data/lib/bundler/cli/update.rb +3 -3
  19. data/lib/bundler/cli.rb +26 -49
  20. data/lib/bundler/compact_index_client/cache.rb +1 -1
  21. data/lib/bundler/compact_index_client/parser.rb +1 -1
  22. data/lib/bundler/compact_index_client/updater.rb +2 -1
  23. data/lib/bundler/compact_index_client.rb +1 -5
  24. data/lib/bundler/current_ruby.rb +27 -3
  25. data/lib/bundler/definition.rb +184 -151
  26. data/lib/bundler/dependency.rb +1 -1
  27. data/lib/bundler/dsl.rb +35 -26
  28. data/lib/bundler/errors.rb +18 -0
  29. data/lib/bundler/feature_flag.rb +15 -12
  30. data/lib/bundler/fetcher/dependency.rb +2 -1
  31. data/lib/bundler/fetcher/downloader.rb +33 -7
  32. data/lib/bundler/fetcher.rb +49 -19
  33. data/lib/bundler/friendly_errors.rb +3 -2
  34. data/lib/bundler/index.rb +7 -2
  35. data/lib/bundler/injector.rb +9 -9
  36. data/lib/bundler/installer.rb +6 -5
  37. data/lib/bundler/lazy_specification.rb +38 -19
  38. data/lib/bundler/lockfile_parser.rb +29 -10
  39. data/lib/bundler/man/bundle-add.1 +1 -1
  40. data/lib/bundler/man/bundle-binstubs.1 +1 -1
  41. data/lib/bundler/man/bundle-cache.1 +1 -1
  42. data/lib/bundler/man/bundle-check.1 +1 -1
  43. data/lib/bundler/man/bundle-clean.1 +1 -1
  44. data/lib/bundler/man/bundle-config.1 +175 -129
  45. data/lib/bundler/man/bundle-config.1.ronn +93 -88
  46. data/lib/bundler/man/bundle-console.1 +1 -1
  47. data/lib/bundler/man/bundle-doctor.1 +43 -4
  48. data/lib/bundler/man/bundle-doctor.1.ronn +48 -4
  49. data/lib/bundler/man/bundle-env.1 +1 -1
  50. data/lib/bundler/man/bundle-exec.1 +3 -3
  51. data/lib/bundler/man/bundle-exec.1.ronn +2 -2
  52. data/lib/bundler/man/bundle-fund.1 +1 -1
  53. data/lib/bundler/man/bundle-gem.1 +67 -44
  54. data/lib/bundler/man/bundle-gem.1.ronn +8 -4
  55. data/lib/bundler/man/bundle-help.1 +1 -1
  56. data/lib/bundler/man/bundle-info.1 +1 -1
  57. data/lib/bundler/man/bundle-init.1 +1 -1
  58. data/lib/bundler/man/bundle-inject.1 +2 -2
  59. data/lib/bundler/man/bundle-inject.1.ronn +1 -1
  60. data/lib/bundler/man/bundle-install.1 +4 -4
  61. data/lib/bundler/man/bundle-install.1.ronn +3 -4
  62. data/lib/bundler/man/bundle-issue.1 +1 -1
  63. data/lib/bundler/man/bundle-licenses.1 +1 -1
  64. data/lib/bundler/man/bundle-list.1 +1 -1
  65. data/lib/bundler/man/bundle-lock.1 +1 -1
  66. data/lib/bundler/man/bundle-open.1 +1 -1
  67. data/lib/bundler/man/bundle-outdated.1 +1 -1
  68. data/lib/bundler/man/bundle-platform.1 +1 -1
  69. data/lib/bundler/man/bundle-plugin.1 +1 -1
  70. data/lib/bundler/man/bundle-pristine.1 +1 -1
  71. data/lib/bundler/man/bundle-remove.1 +1 -1
  72. data/lib/bundler/man/bundle-show.1 +1 -1
  73. data/lib/bundler/man/bundle-update.1 +5 -5
  74. data/lib/bundler/man/bundle-update.1.ronn +4 -4
  75. data/lib/bundler/man/bundle-version.1 +1 -1
  76. data/lib/bundler/man/bundle-viz.1 +1 -1
  77. data/lib/bundler/man/bundle.1 +1 -1
  78. data/lib/bundler/man/gemfile.5 +1 -1
  79. data/lib/bundler/match_platform.rb +31 -12
  80. data/lib/bundler/materialization.rb +2 -2
  81. data/lib/bundler/plugin/api/source.rb +1 -1
  82. data/lib/bundler/plugin/index.rb +1 -1
  83. data/lib/bundler/plugin/installer/path.rb +8 -0
  84. data/lib/bundler/plugin.rb +1 -1
  85. data/lib/bundler/resolver/candidate.rb +12 -9
  86. data/lib/bundler/resolver/package.rb +1 -1
  87. data/lib/bundler/resolver/strategy.rb +40 -0
  88. data/lib/bundler/resolver.rb +18 -27
  89. data/lib/bundler/rubygems_ext.rb +131 -120
  90. data/lib/bundler/rubygems_integration.rb +11 -6
  91. data/lib/bundler/runtime.rb +9 -6
  92. data/lib/bundler/self_manager.rb +32 -42
  93. data/lib/bundler/settings/validator.rb +0 -23
  94. data/lib/bundler/settings.rb +4 -6
  95. data/lib/bundler/shared_helpers.rb +10 -4
  96. data/lib/bundler/source/gemspec.rb +1 -4
  97. data/lib/bundler/source/git/git_proxy.rb +17 -6
  98. data/lib/bundler/source/git.rb +5 -1
  99. data/lib/bundler/source/path.rb +9 -2
  100. data/lib/bundler/source/rubygems/remote.rb +11 -3
  101. data/lib/bundler/source_list.rb +30 -16
  102. data/lib/bundler/source_map.rb +1 -1
  103. data/lib/bundler/spec_set.rb +55 -16
  104. data/lib/bundler/templates/Executable +0 -11
  105. data/lib/bundler/templates/newgem/github/workflows/main.yml.tt +2 -0
  106. data/lib/bundler/templates/newgem/newgem.gemspec.tt +6 -5
  107. data/lib/bundler/ui/shell.rb +2 -2
  108. data/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +53 -3
  109. data/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +1 -1
  110. data/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +11 -0
  111. data/lib/bundler/vendor/net-http-persistent/README.rdoc +1 -1
  112. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/timed_stack_multi.rb +2 -1
  113. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +81 -42
  114. data/lib/bundler/vendor/pub_grub/lib/pub_grub/basic_package_source.rb +4 -24
  115. data/lib/bundler/vendor/pub_grub/lib/pub_grub/strategy.rb +42 -0
  116. data/lib/bundler/vendor/pub_grub/lib/pub_grub/version_range.rb +20 -8
  117. data/lib/bundler/vendor/pub_grub/lib/pub_grub/version_solver.rb +17 -29
  118. data/lib/bundler/vendor/uri/lib/uri/common.rb +7 -3
  119. data/lib/bundler/vendor/uri/lib/uri/generic.rb +12 -11
  120. data/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb +6 -6
  121. data/lib/bundler/vendor/uri/lib/uri/version.rb +1 -1
  122. data/lib/bundler/version.rb +10 -2
  123. data/lib/bundler/worker.rb +1 -1
  124. data/lib/bundler.rb +14 -12
  125. metadata +9 -16
  126. data/lib/bundler/compact_index_client/gem_parser.rb +0 -32
  127. data/lib/bundler/gem_helpers.rb +0 -144
  128. data/lib/bundler/templates/Executable.bundler +0 -109
  129. data/lib/bundler/vendor/connection_pool/.document +0 -1
  130. data/lib/bundler/vendor/fileutils/.document +0 -1
  131. data/lib/bundler/vendor/net-http-persistent/.document +0 -1
  132. data/lib/bundler/vendor/pub_grub/.document +0 -1
  133. data/lib/bundler/vendor/securerandom/.document +0 -1
  134. data/lib/bundler/vendor/thor/.document +0 -1
  135. data/lib/bundler/vendor/tsort/.document +0 -1
  136. data/lib/bundler/vendor/uri/.document +0 -1
@@ -4,8 +4,6 @@ require_relative "lockfile_parser"
4
4
 
5
5
  module Bundler
6
6
  class Definition
7
- include GemHelpers
8
-
9
7
  class << self
10
8
  # Do not create or modify a lockfile (Makes #lock a noop)
11
9
  attr_accessor :no_lock
@@ -62,6 +60,7 @@ module Bundler
62
60
 
63
61
  if unlock == true
64
62
  @unlocking_all = true
63
+ strict = false
65
64
  @unlocking_bundler = false
66
65
  @unlocking = unlock
67
66
  @sources_to_unlock = []
@@ -70,6 +69,7 @@ module Bundler
70
69
  conservative = false
71
70
  else
72
71
  @unlocking_all = false
72
+ strict = unlock.delete(:strict)
73
73
  @unlocking_bundler = unlock.delete(:bundler)
74
74
  @unlocking = unlock.any? {|_k, v| !Array(v).empty? }
75
75
  @sources_to_unlock = unlock.delete(:sources) || []
@@ -94,11 +94,12 @@ module Bundler
94
94
 
95
95
  @locked_ruby_version = nil
96
96
  @new_platforms = []
97
- @removed_platform = nil
97
+ @removed_platforms = []
98
+ @originally_invalid_platforms = []
98
99
 
99
100
  if lockfile_exists?
100
101
  @lockfile_contents = Bundler.read_file(lockfile)
101
- @locked_gems = LockfileParser.new(@lockfile_contents)
102
+ @locked_gems = LockfileParser.new(@lockfile_contents, strict: strict)
102
103
  @locked_platforms = @locked_gems.platforms
103
104
  @most_specific_locked_platform = @locked_gems.most_specific_locked_platform
104
105
  @platforms = @locked_platforms.dup
@@ -147,9 +148,8 @@ module Bundler
147
148
 
148
149
  @current_platform_missing = add_current_platform unless Bundler.frozen_bundle?
149
150
 
150
- converge_path_sources_to_gemspec_sources
151
- @path_changes = converge_paths
152
151
  @source_changes = converge_sources
152
+ @path_changes = converge_paths
153
153
 
154
154
  if conservative
155
155
  @gems_to_unlock = @explicit_unlocks.any? ? @explicit_unlocks : @dependencies.map(&:name)
@@ -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
 
@@ -282,7 +282,7 @@ module Bundler
282
282
  end
283
283
 
284
284
  def filter_relevant(dependencies)
285
- platforms_array = [generic_local_platform].freeze
285
+ platforms_array = [Bundler.generic_local_platform].freeze
286
286
  dependencies.select do |d|
287
287
  d.should_include? && !d.gem_platforms(platforms_array).empty?
288
288
  end
@@ -330,18 +330,14 @@ module Bundler
330
330
  SpecSet.new(filter_specs(@locked_specs, @dependencies - deleted_deps))
331
331
  else
332
332
  Bundler.ui.debug "Found no changes, using resolution from the lockfile"
333
- if @removed_platform || @locked_gems.may_include_redundant_platform_specific_gems?
333
+ if @removed_platforms.any? || @locked_gems.may_include_redundant_platform_specific_gems?
334
334
  SpecSet.new(filter_specs(@locked_specs, @dependencies))
335
335
  else
336
336
  @locked_specs
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
@@ -412,41 +408,8 @@ module Bundler
412
408
 
413
409
  raise ProductionError, "Frozen mode is set, but there's no lockfile" unless lockfile_exists?
414
410
 
415
- added = []
416
- deleted = []
417
- changed = []
418
-
419
- new_platforms = @platforms - @locked_platforms
420
- deleted_platforms = @locked_platforms - @platforms
421
- added.concat new_platforms.map {|p| "* platform: #{p}" }
422
- deleted.concat deleted_platforms.map {|p| "* platform: #{p}" }
423
-
424
- added.concat new_deps.map {|d| "* #{pretty_dep(d)}" } if new_deps.any?
425
- deleted.concat deleted_deps.map {|d| "* #{pretty_dep(d)}" } if deleted_deps.any?
426
-
427
- both_sources = Hash.new {|h, k| h[k] = [] }
428
- current_dependencies.each {|d| both_sources[d.name][0] = d }
429
- current_locked_dependencies.each {|d| both_sources[d.name][1] = d }
430
-
431
- both_sources.each do |name, (dep, lock_dep)|
432
- next if dep.nil? || lock_dep.nil?
433
-
434
- gemfile_source = dep.source || default_source
435
- lock_source = lock_dep.source || default_source
436
- next if lock_source.include?(gemfile_source)
437
-
438
- gemfile_source_name = dep.source ? gemfile_source.to_gemfile : "no specified source"
439
- lockfile_source_name = lock_dep.source ? lock_source.to_gemfile : "no specified source"
440
- changed << "* #{name} from `#{lockfile_source_name}` to `#{gemfile_source_name}`"
441
- end
442
-
443
- reason = resolve_needed? ? change_reason : "some dependencies were deleted from your gemfile"
444
- msg = String.new
445
- msg << "#{reason.capitalize.strip}, but the lockfile can't be updated because frozen mode is set"
446
- msg << "\n\nYou have added to the Gemfile:\n" << added.join("\n") if added.any?
447
- msg << "\n\nYou have deleted from the Gemfile:\n" << deleted.join("\n") if deleted.any?
448
- msg << "\n\nYou have changed in the Gemfile:\n" << changed.join("\n") if changed.any?
449
- msg << "\n\nRun `bundle install` elsewhere and add the updated #{SharedHelpers.relative_gemfile_path} to version control.\n" unless unlocking?
411
+ msg = lockfile_changes_summary("frozen mode is set")
412
+ return unless msg
450
413
 
451
414
  unless explicit_flag
452
415
  suggested_command = unless Bundler.settings.locations("frozen").keys.include?(:env)
@@ -456,7 +419,7 @@ module Bundler
456
419
  "freeze by running `#{suggested_command}`." if suggested_command
457
420
  end
458
421
 
459
- raise ProductionError, msg if added.any? || deleted.any? || changed.any? || resolve_needed?
422
+ raise ProductionError, msg
460
423
  end
461
424
 
462
425
  def validate_runtime!
@@ -493,12 +456,12 @@ module Bundler
493
456
  return if current_platform_locked? || @platforms.include?(Gem::Platform::RUBY)
494
457
 
495
458
  raise ProductionError, "Your bundle only supports platforms #{@platforms.map(&:to_s)} " \
496
- "but your local platform is #{local_platform}. " \
497
- "Add the current platform to the lockfile with\n`bundle lock --add-platform #{local_platform}` and try again."
459
+ "but your local platform is #{Bundler.local_platform}. " \
460
+ "Add the current platform to the lockfile with\n`bundle lock --add-platform #{Bundler.local_platform}` and try again."
498
461
  end
499
462
 
500
463
  def normalize_platforms
501
- @platforms = resolve.normalize_platforms!(current_dependencies, platforms)
464
+ resolve.normalize_platforms!(current_dependencies, platforms)
502
465
 
503
466
  @resolve = SpecSet.new(resolve.for(current_dependencies, @platforms))
504
467
  end
@@ -511,10 +474,10 @@ module Bundler
511
474
  end
512
475
 
513
476
  def remove_platform(platform)
514
- removed_platform = @platforms.delete(Gem::Platform.new(platform))
515
- @removed_platform ||= removed_platform
516
- return if removed_platform
517
- raise InvalidOption, "Unable to remove the platform `#{platform}` since the only platforms are #{@platforms.join ", "}"
477
+ raise InvalidOption, "Unable to remove the platform `#{platform}` since the only platforms are #{@platforms.join ", "}" unless @platforms.include?(platform)
478
+
479
+ @removed_platforms << platform
480
+ @platforms.delete(platform)
518
481
  end
519
482
 
520
483
  def nothing_changed?
@@ -541,6 +504,45 @@ module Bundler
541
504
 
542
505
  private
543
506
 
507
+ def lockfile_changes_summary(update_refused_reason)
508
+ added = []
509
+ deleted = []
510
+ changed = []
511
+
512
+ added.concat @new_platforms.map {|p| "* platform: #{p}" }
513
+ deleted.concat @removed_platforms.map {|p| "* platform: #{p}" }
514
+
515
+ added.concat new_deps.map {|d| "* #{pretty_dep(d)}" } if new_deps.any?
516
+ deleted.concat deleted_deps.map {|d| "* #{pretty_dep(d)}" } if deleted_deps.any?
517
+
518
+ both_sources = Hash.new {|h, k| h[k] = [] }
519
+ current_dependencies.each {|d| both_sources[d.name][0] = d }
520
+ current_locked_dependencies.each {|d| both_sources[d.name][1] = d }
521
+
522
+ both_sources.each do |name, (dep, lock_dep)|
523
+ next if dep.nil? || lock_dep.nil?
524
+
525
+ gemfile_source = dep.source || default_source
526
+ lock_source = lock_dep.source || default_source
527
+ next if lock_source.include?(gemfile_source)
528
+
529
+ gemfile_source_name = dep.source ? gemfile_source.to_gemfile : "no specified source"
530
+ lockfile_source_name = lock_dep.source ? lock_source.to_gemfile : "no specified source"
531
+ changed << "* #{name} from `#{lockfile_source_name}` to `#{gemfile_source_name}`"
532
+ end
533
+
534
+ return unless added.any? || deleted.any? || changed.any? || resolve_needed?
535
+
536
+ msg = String.new("#{change_reason.capitalize.strip}, but ")
537
+ msg << "the lockfile " unless msg.start_with?("Your lockfile")
538
+ msg << "can't be updated because #{update_refused_reason}"
539
+ msg << "\n\nYou have added to the Gemfile:\n" << added.join("\n") if added.any?
540
+ msg << "\n\nYou have deleted from the Gemfile:\n" << deleted.join("\n") if deleted.any?
541
+ msg << "\n\nYou have changed in the Gemfile:\n" << changed.join("\n") if changed.any?
542
+ msg << "\n\nRun `bundle install` elsewhere and add the updated #{SharedHelpers.relative_lockfile_path} to version control.\n" unless unlocking?
543
+ msg
544
+ end
545
+
544
546
  def install_needed?
545
547
  resolve_needed? || missing_specs?
546
548
  end
@@ -556,6 +558,7 @@ module Bundler
556
558
  @local_changes ||
557
559
  @missing_lockfile_dep ||
558
560
  @unlocking_bundler ||
561
+ @locked_spec_with_missing_checksums ||
559
562
  @locked_spec_with_missing_deps ||
560
563
  @locked_spec_with_invalid_deps
561
564
  end
@@ -565,7 +568,7 @@ module Bundler
565
568
  end
566
569
 
567
570
  def should_add_extra_platforms?
568
- !lockfile_exists? && generic_local_platform_is_ruby? && !Bundler.settings[:force_ruby_platform]
571
+ !lockfile_exists? && Bundler::MatchPlatform.generic_local_platform_is_ruby? && !Bundler.settings[:force_ruby_platform]
569
572
  end
570
573
 
571
574
  def lockfile_exists?
@@ -601,13 +604,17 @@ module Bundler
601
604
  return
602
605
  end
603
606
 
604
- SharedHelpers.filesystem_access(file) do |p|
605
- File.open(p, "wb") {|f| f.puts(contents) }
607
+ begin
608
+ SharedHelpers.filesystem_access(file) do |p|
609
+ File.open(p, "wb") {|f| f.puts(contents) }
610
+ end
611
+ rescue ReadOnlyFileSystemError
612
+ raise ProductionError, lockfile_changes_summary("file system is read-only")
606
613
  end
607
614
  end
608
615
 
609
616
  def resolver
610
- @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)
611
618
  end
612
619
 
613
620
  def expanded_dependencies
@@ -621,14 +628,15 @@ module Bundler
621
628
  [Dependency.new("bundler", @unlocking_bundler)] + dependencies
622
629
  end
623
630
 
624
- def resolution_packages
625
- @resolution_packages ||= begin
631
+ def resolution_base
632
+ @resolution_base ||= begin
626
633
  last_resolve = converge_locked_specs
627
634
  remove_invalid_platforms!
628
- 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_platforms)
629
- packages = additional_base_requirements_to_prevent_downgrades(packages)
630
- packages = additional_base_requirements_to_force_updates(packages)
631
- packages
635
+ new_resolution_platforms = @current_platform_missing ? @new_platforms + [Bundler.local_platform] : @new_platforms
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
632
640
  end
633
641
  end
634
642
 
@@ -703,8 +711,7 @@ module Bundler
703
711
  still_incomplete_specs = resolve.incomplete_specs
704
712
 
705
713
  if still_incomplete_specs == incomplete_specs
706
- package = resolution_packages.get_package(incomplete_specs.first.name)
707
- resolver.raise_not_found! package
714
+ resolver.raise_incomplete! incomplete_specs
708
715
  end
709
716
 
710
717
  incomplete_specs = still_incomplete_specs
@@ -726,28 +733,40 @@ module Bundler
726
733
  end
727
734
 
728
735
  def reresolve_without(incomplete_specs)
729
- resolution_packages.delete(incomplete_specs)
736
+ resolution_base.delete(incomplete_specs)
730
737
  @resolve = start_resolution
731
738
  end
732
739
 
733
740
  def start_resolution
734
- local_platform_needed_for_resolvability = @most_specific_non_local_locked_platform && !@platforms.include?(local_platform)
735
- @platforms << local_platform if local_platform_needed_for_resolvability
741
+ local_platform_needed_for_resolvability = @most_specific_non_local_locked_platform && !@platforms.include?(Bundler.local_platform)
742
+ @platforms << Bundler.local_platform if local_platform_needed_for_resolvability
736
743
  add_platform(Gem::Platform::RUBY) if RUBY_ENGINE == "truffleruby"
737
744
 
738
745
  result = SpecSet.new(resolver.start)
739
746
 
740
747
  @resolved_bundler_version = result.find {|spec| spec.name == "bundler" }&.version
741
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
+
742
757
  if @most_specific_non_local_locked_platform
743
- 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)
744
759
  @platforms.delete(@most_specific_non_local_locked_platform)
745
760
  elsif local_platform_needed_for_resolvability
746
- @platforms.delete(local_platform)
761
+ @platforms.delete(Bundler.local_platform)
747
762
  end
748
763
  end
749
764
 
750
- @platforms = result.add_extra_platforms!(platforms) if should_add_extra_platforms?
765
+ if should_add_extra_platforms?
766
+ result.add_extra_platforms!(platforms)
767
+ elsif @originally_invalid_platforms.any?
768
+ result.add_originally_invalid_platforms!(platforms, @originally_invalid_platforms)
769
+ end
751
770
 
752
771
  SpecSet.new(result.for(dependencies, @platforms | [Gem::Platform::RUBY]))
753
772
  end
@@ -758,18 +777,17 @@ module Bundler
758
777
 
759
778
  def current_platform_locked?
760
779
  @platforms.any? do |bundle_platform|
761
- generic_local_platform == bundle_platform || local_platform === bundle_platform
780
+ Bundler.generic_local_platform == bundle_platform || Bundler.local_platform === bundle_platform
762
781
  end
763
782
  end
764
783
 
765
784
  def add_current_platform
766
- return if @platforms.include?(local_platform)
785
+ return if @platforms.include?(Bundler.local_platform)
767
786
 
768
787
  @most_specific_non_local_locked_platform = find_most_specific_locked_platform
769
788
  return if @most_specific_non_local_locked_platform
770
789
 
771
- @new_platforms << local_platform
772
- @platforms << local_platform
790
+ @platforms << Bundler.local_platform
773
791
  true
774
792
  end
775
793
 
@@ -779,32 +797,58 @@ module Bundler
779
797
  @most_specific_locked_platform
780
798
  end
781
799
 
782
- def change_reason
783
- if unlocking?
784
- unlock_targets = if @gems_to_unlock.any?
785
- ["gems", @gems_to_unlock]
786
- elsif @sources_to_unlock.any?
787
- ["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}"
788
806
  end
807
+ else
808
+ "Resolving dependencies because there's no lockfile"
809
+ end
810
+ end
789
811
 
790
- unlock_reason = if unlock_targets
791
- "#{unlock_targets.first}: (#{unlock_targets.last.join(", ")})"
812
+ def change_reason
813
+ if resolve_needed?
814
+ if unlocking?
815
+ unlocking_reason
792
816
  else
793
- @unlocking_ruby ? "ruby" : ""
817
+ lockfile_changed_reason
794
818
  end
819
+ else
820
+ "some dependencies were deleted from your gemfile"
821
+ end
822
+ end
795
823
 
796
- 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]
829
+ end
830
+
831
+ unlock_reason = if unlock_targets
832
+ "#{unlock_targets.first}: (#{unlock_targets.last.join(", ")})"
833
+ else
834
+ @unlocking_ruby ? "ruby" : ""
797
835
  end
836
+
837
+ "bundler is unlocking #{unlock_reason}"
838
+ end
839
+
840
+ def lockfile_changed_reason
798
841
  [
799
842
  [@source_changes, "the list of sources changed"],
800
843
  [@dependency_changes, "the dependencies in your gemfile changed"],
801
- [@current_platform_missing, "your lockfile does not include the current platform"],
802
- [@new_platforms.any?, "you added a new platform to your gemfile"],
844
+ [@current_platform_missing, "your lockfile is missing the current platform"],
845
+ [@new_platforms.any?, "you are adding a new platform to your lockfile"],
803
846
  [@path_changes, "the gemspecs for path gems changed"],
804
847
  [@local_changes, "the gemspecs for git local gems changed"],
805
- [@missing_lockfile_dep, "your lock file is missing \"#{@missing_lockfile_dep}\""],
848
+ [@missing_lockfile_dep, "your lockfile is missing \"#{@missing_lockfile_dep}\""],
806
849
  [@unlocking_bundler, "an update to the version of Bundler itself was requested"],
807
- [@locked_spec_with_missing_deps, "your lock file includes \"#{@locked_spec_with_missing_deps}\" but not some of its dependencies"],
850
+ [@locked_spec_with_missing_checksums, "your lockfile is missing a CHECKSUMS entry for \"#{@locked_spec_with_missing_checksums}\""],
851
+ [@locked_spec_with_missing_deps, "your lockfile includes \"#{@locked_spec_with_missing_deps}\" but not some of its dependencies"],
808
852
  [@locked_spec_with_invalid_deps, "your lockfile does not satisfy dependencies of \"#{@locked_spec_with_invalid_deps}\""],
809
853
  ].select(&:first).map(&:last).join(", ")
810
854
  end
@@ -821,8 +865,8 @@ module Bundler
821
865
  !locked || dependencies_for_source_changed?(source, locked) || specs_for_source_changed?(source)
822
866
  end
823
867
 
824
- def dependencies_for_source_changed?(source, locked_source = source)
825
- deps_for_source = @dependencies.select {|s| s.source == source }
868
+ def dependencies_for_source_changed?(source, locked_source)
869
+ deps_for_source = @dependencies.select {|dep| dep.source == source }
826
870
  locked_deps_for_source = locked_dependencies.select {|dep| dep.source == locked_source }
827
871
 
828
872
  deps_for_source.uniq.sort != locked_deps_for_source.sort
@@ -830,7 +874,7 @@ module Bundler
830
874
 
831
875
  def specs_for_source_changed?(source)
832
876
  locked_index = Index.new
833
- locked_index.use(@locked_specs.select {|s| source.can_lock?(s) })
877
+ locked_index.use(@locked_specs.select {|s| s.replace_source_with!(source) })
834
878
 
835
879
  !locked_index.subset?(source.specs)
836
880
  rescue PathError, GitError => e
@@ -862,21 +906,27 @@ module Bundler
862
906
  def check_lockfile
863
907
  @locked_spec_with_invalid_deps = nil
864
908
  @locked_spec_with_missing_deps = nil
909
+ @locked_spec_with_missing_checksums = nil
865
910
 
866
- missing = []
911
+ missing_deps = []
912
+ missing_checksums = []
867
913
  invalid = []
868
914
 
869
915
  @locked_specs.each do |s|
916
+ missing_checksums << s if @locked_checksums && s.source.checksum_store.missing?(s)
917
+
870
918
  validation = @locked_specs.validate_deps(s)
871
919
 
872
- missing << s if validation == :missing
920
+ missing_deps << s if validation == :missing
873
921
  invalid << s if validation == :invalid
874
922
  end
875
923
 
876
- if missing.any?
877
- @locked_specs.delete(missing)
924
+ @locked_spec_with_missing_checksums = missing_checksums.first.name if missing_checksums.any?
925
+
926
+ if missing_deps.any?
927
+ @locked_specs.delete(missing_deps)
878
928
 
879
- @locked_spec_with_missing_deps = missing.first.name
929
+ @locked_spec_with_missing_deps = missing_deps.first.name
880
930
  end
881
931
 
882
932
  if invalid.any?
@@ -892,24 +942,6 @@ module Bundler
892
942
  end
893
943
  end
894
944
 
895
- def converge_path_source_to_gemspec_source(source)
896
- return source unless source.instance_of?(Source::Path)
897
- gemspec_source = sources.path_sources.find {|s| s.is_a?(Source::Gemspec) && s.as_path_source == source }
898
- gemspec_source || source
899
- end
900
-
901
- def converge_path_sources_to_gemspec_sources
902
- @locked_sources.map! do |source|
903
- converge_path_source_to_gemspec_source(source)
904
- end
905
- @locked_specs.each do |spec|
906
- spec.source &&= converge_path_source_to_gemspec_source(spec.source)
907
- end
908
- @locked_deps.each do |_, dep|
909
- dep.source &&= converge_path_source_to_gemspec_source(dep.source)
910
- end
911
- end
912
-
913
945
  def converge_sources
914
946
  # Replace the sources from the Gemfile with the sources from the Gemfile.lock,
915
947
  # if they exist in the Gemfile.lock and are `==`. If you can't find an equivalent
@@ -952,11 +984,17 @@ module Bundler
952
984
  unless name == "bundler"
953
985
  locked_specs = @originally_locked_specs[name]
954
986
 
955
- if locked_specs.any? && !dep.matches_spec?(locked_specs.first)
956
- @gems_to_unlock << name
957
- dep_changed = true
958
- elsif locked_specs.empty? && dep_changed == false
959
- @missing_lockfile_dep = name
987
+ if locked_specs.empty?
988
+ @missing_lockfile_dep = name if dep_changed == false
989
+ else
990
+ if locked_specs.map(&:source).uniq.size > 1
991
+ @locked_specs.delete(locked_specs.select {|s| s.source != dep.source })
992
+ end
993
+
994
+ unless dep.matches_spec?(locked_specs.first)
995
+ @gems_to_unlock << name
996
+ dep_changed = true
997
+ end
960
998
  end
961
999
  end
962
1000
 
@@ -999,17 +1037,16 @@ module Bundler
999
1037
  lockfile_source = s.source
1000
1038
 
1001
1039
  if dep
1002
- gemfile_source = dep.source || default_source
1003
-
1004
- deps << dep if !dep.source || lockfile_source.include?(dep.source) || new_deps.include?(dep)
1040
+ replacement_source = dep.source
1005
1041
 
1006
- # Replace the locked dependency's source with the equivalent source from the Gemfile
1007
- s.source = gemfile_source
1042
+ deps << dep if !replacement_source || lockfile_source.include?(replacement_source) || new_deps.include?(dep)
1008
1043
  else
1009
- # Replace the locked dependency's source with the default source, if the locked source is no longer in the Gemfile
1010
- s.source = default_source unless sources.get(lockfile_source)
1044
+ replacement_source = sources.get(lockfile_source)
1011
1045
  end
1012
1046
 
1047
+ # Replace the locked dependency's source with the equivalent source from the Gemfile
1048
+ s.source = replacement_source || default_source
1049
+
1013
1050
  source = s.source
1014
1051
  next if @sources_to_unlock.include?(source.name)
1015
1052
 
@@ -1093,27 +1130,27 @@ module Bundler
1093
1130
  current == proposed
1094
1131
  end
1095
1132
 
1096
- def additional_base_requirements_to_prevent_downgrades(resolution_packages)
1097
- return resolution_packages unless @locked_gems && !sources.expired_sources?(@locked_gems.sources)
1133
+ def additional_base_requirements_to_prevent_downgrades(resolution_base)
1134
+ return resolution_base unless @locked_gems && !sources.expired_sources?(@locked_gems.sources)
1098
1135
  @originally_locked_specs.each do |locked_spec|
1099
1136
  next if locked_spec.source.is_a?(Source::Path)
1100
1137
 
1101
1138
  name = locked_spec.name
1102
1139
  next if @changed_dependencies.include?(name)
1103
1140
 
1104
- resolution_packages.base_requirements[name] = Gem::Requirement.new(">= #{locked_spec.version}")
1141
+ resolution_base.base_requirements[name] = Gem::Requirement.new(">= #{locked_spec.version}")
1105
1142
  end
1106
- resolution_packages
1143
+ resolution_base
1107
1144
  end
1108
1145
 
1109
- def additional_base_requirements_to_force_updates(resolution_packages)
1110
- return resolution_packages if @explicit_unlocks.empty?
1146
+ def additional_base_requirements_to_force_updates(resolution_base)
1147
+ return resolution_base if @explicit_unlocks.empty?
1111
1148
  full_update = dup_for_full_unlock.resolve
1112
1149
  @explicit_unlocks.each do |name|
1113
1150
  version = full_update.version_for(name)
1114
- resolution_packages.base_requirements[name] = Gem::Requirement.new("= #{version}") if version
1151
+ resolution_base.base_requirements[name] = Gem::Requirement.new("= #{version}") if version
1115
1152
  end
1116
- resolution_packages
1153
+ resolution_base
1117
1154
  end
1118
1155
 
1119
1156
  def dup_for_full_unlock
@@ -1130,20 +1167,16 @@ module Bundler
1130
1167
  def remove_invalid_platforms!
1131
1168
  return if Bundler.frozen_bundle?
1132
1169
 
1133
- platforms.reverse_each do |platform|
1134
- next if local_platform == platform ||
1135
- @new_platforms.include?(platform) ||
1136
- @path_changes ||
1137
- @dependency_changes ||
1138
- @locked_spec_with_invalid_deps ||
1139
- !spec_set_incomplete_for_platform?(@originally_locked_specs, platform)
1170
+ skips = (@new_platforms + [Bundler.local_platform]).uniq
1140
1171
 
1141
- remove_platform(platform)
1142
- end
1143
- end
1172
+ # We should probably avoid removing non-ruby platforms, since that means
1173
+ # lockfile will no longer install on those platforms, so a error to give
1174
+ # heads up to the user may be better. However, we have tests expecting
1175
+ # non ruby platform autoremoval to work, so leaving that in place for
1176
+ # now.
1177
+ skips |= platforms - [Gem::Platform::RUBY] if @dependency_changes
1144
1178
 
1145
- def spec_set_incomplete_for_platform?(spec_set, platform)
1146
- spec_set.incomplete_for_platform?(current_dependencies, platform)
1179
+ @originally_invalid_platforms = @originally_locked_specs.remove_invalid_platforms!(current_dependencies, platforms, skips: skips)
1147
1180
  end
1148
1181
 
1149
1182
  def source_map
@@ -99,7 +99,7 @@ module Bundler
99
99
  return RUBY_PLATFORM_ARRAY if force_ruby_platform
100
100
  return valid_platforms if platforms.empty?
101
101
 
102
- valid_platforms.select {|p| expanded_platforms.include?(GemHelpers.generic(p)) }
102
+ valid_platforms.select {|p| expanded_platforms.include?(Gem::Platform.generic(p)) }
103
103
  end
104
104
 
105
105
  def expanded_platforms