bundler 2.5.23 → 2.6.0

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 (148) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +59 -0
  3. data/bundler.gemspec +2 -2
  4. data/lib/bundler/build_metadata.rb +2 -2
  5. data/lib/bundler/cli/console.rb +0 -4
  6. data/lib/bundler/cli/doctor.rb +4 -4
  7. data/lib/bundler/cli/exec.rb +1 -0
  8. data/lib/bundler/cli/gem.rb +1 -1
  9. data/lib/bundler/cli/info.rb +2 -2
  10. data/lib/bundler/cli/inject.rb +1 -1
  11. data/lib/bundler/cli/install.rb +4 -0
  12. data/lib/bundler/cli/lock.rb +20 -1
  13. data/lib/bundler/cli/pristine.rb +1 -1
  14. data/lib/bundler/cli/show.rb +2 -2
  15. data/lib/bundler/cli.rb +22 -53
  16. data/lib/bundler/compact_index_client/cache_file.rb +0 -5
  17. data/lib/bundler/compact_index_client/updater.rb +0 -11
  18. data/lib/bundler/definition.rb +134 -61
  19. data/lib/bundler/dependency.rb +1 -1
  20. data/lib/bundler/dsl.rb +2 -13
  21. data/lib/bundler/endpoint_specification.rb +10 -1
  22. data/lib/bundler/errors.rb +10 -0
  23. data/lib/bundler/feature_flag.rb +1 -0
  24. data/lib/bundler/fetcher/compact_index.rb +1 -1
  25. data/lib/bundler/fetcher.rb +10 -3
  26. data/lib/bundler/gem_helpers.rb +21 -5
  27. data/lib/bundler/injector.rb +2 -2
  28. data/lib/bundler/installer/standalone.rb +2 -2
  29. data/lib/bundler/installer.rb +4 -38
  30. data/lib/bundler/lazy_specification.rb +65 -24
  31. data/lib/bundler/lockfile_parser.rb +9 -1
  32. data/lib/bundler/man/bundle-add.1 +13 -10
  33. data/lib/bundler/man/bundle-add.1.ronn +12 -9
  34. data/lib/bundler/man/bundle-binstubs.1 +7 -4
  35. data/lib/bundler/man/bundle-binstubs.1.ronn +6 -3
  36. data/lib/bundler/man/bundle-cache.1 +30 -2
  37. data/lib/bundler/man/bundle-cache.1.ronn +31 -2
  38. data/lib/bundler/man/bundle-check.1 +3 -3
  39. data/lib/bundler/man/bundle-check.1.ronn +4 -2
  40. data/lib/bundler/man/bundle-clean.1 +1 -1
  41. data/lib/bundler/man/bundle-config.1 +3 -1
  42. data/lib/bundler/man/bundle-config.1.ronn +2 -0
  43. data/lib/bundler/man/bundle-console.1 +2 -4
  44. data/lib/bundler/man/bundle-console.1.ronn +2 -7
  45. data/lib/bundler/man/bundle-doctor.1 +2 -2
  46. data/lib/bundler/man/bundle-doctor.1.ronn +1 -1
  47. data/lib/bundler/man/bundle-env.1 +9 -0
  48. data/lib/bundler/man/bundle-env.1.ronn +10 -0
  49. data/lib/bundler/man/bundle-exec.1 +5 -2
  50. data/lib/bundler/man/bundle-exec.1.ronn +4 -1
  51. data/lib/bundler/man/bundle-fund.1 +22 -0
  52. data/lib/bundler/man/bundle-fund.1.ronn +25 -0
  53. data/lib/bundler/man/bundle-gem.1 +17 -5
  54. data/lib/bundler/man/bundle-gem.1.ronn +27 -6
  55. data/lib/bundler/man/bundle-help.1 +1 -1
  56. data/lib/bundler/man/bundle-info.1 +5 -2
  57. data/lib/bundler/man/bundle-info.1.ronn +6 -2
  58. data/lib/bundler/man/bundle-init.1 +3 -3
  59. data/lib/bundler/man/bundle-init.1.ronn +3 -2
  60. data/lib/bundler/man/bundle-inject.1 +10 -2
  61. data/lib/bundler/man/bundle-inject.1.ronn +9 -1
  62. data/lib/bundler/man/bundle-install.1 +14 -11
  63. data/lib/bundler/man/bundle-install.1.ronn +21 -16
  64. data/lib/bundler/man/bundle-issue.1 +45 -0
  65. data/lib/bundler/man/bundle-issue.1.ronn +37 -0
  66. data/lib/bundler/man/bundle-licenses.1 +9 -0
  67. data/lib/bundler/man/bundle-licenses.1.ronn +10 -0
  68. data/lib/bundler/man/bundle-list.1 +1 -1
  69. data/lib/bundler/man/bundle-list.1.ronn +4 -1
  70. data/lib/bundler/man/bundle-lock.1 +21 -6
  71. data/lib/bundler/man/bundle-lock.1.ronn +25 -4
  72. data/lib/bundler/man/bundle-open.1 +2 -2
  73. data/lib/bundler/man/bundle-open.1.ronn +2 -1
  74. data/lib/bundler/man/bundle-outdated.1 +8 -5
  75. data/lib/bundler/man/bundle-outdated.1.ronn +8 -4
  76. data/lib/bundler/man/bundle-platform.1 +1 -1
  77. data/lib/bundler/man/bundle-plugin.1 +1 -1
  78. data/lib/bundler/man/bundle-pristine.1 +1 -1
  79. data/lib/bundler/man/bundle-pristine.1.ronn +1 -1
  80. data/lib/bundler/man/bundle-remove.1 +1 -1
  81. data/lib/bundler/man/bundle-remove.1.ronn +1 -1
  82. data/lib/bundler/man/bundle-show.1 +5 -2
  83. data/lib/bundler/man/bundle-show.1.ronn +4 -0
  84. data/lib/bundler/man/bundle-update.1 +13 -7
  85. data/lib/bundler/man/bundle-update.1.ronn +14 -6
  86. data/lib/bundler/man/bundle-version.1 +1 -1
  87. data/lib/bundler/man/bundle-viz.1 +4 -4
  88. data/lib/bundler/man/bundle-viz.1.ronn +7 -3
  89. data/lib/bundler/man/bundle.1 +1 -1
  90. data/lib/bundler/man/gemfile.5 +1 -1
  91. data/lib/bundler/man/index.txt +4 -0
  92. data/lib/bundler/materialization.rb +59 -0
  93. data/lib/bundler/plugin/events.rb +24 -0
  94. data/lib/bundler/plugin/installer.rb +1 -1
  95. data/lib/bundler/process_lock.rb +1 -1
  96. data/lib/bundler/remote_specification.rb +6 -1
  97. data/lib/bundler/resolver/base.rb +2 -6
  98. data/lib/bundler/resolver/candidate.rb +2 -2
  99. data/lib/bundler/resolver/spec_group.rb +4 -3
  100. data/lib/bundler/resolver.rb +5 -5
  101. data/lib/bundler/rubygems_ext.rb +17 -28
  102. data/lib/bundler/rubygems_gem_installer.rb +0 -1
  103. data/lib/bundler/rubygems_integration.rb +21 -11
  104. data/lib/bundler/runtime.rb +27 -7
  105. data/lib/bundler/self_manager.rb +2 -3
  106. data/lib/bundler/settings.rb +1 -0
  107. data/lib/bundler/shared_helpers.rb +2 -2
  108. data/lib/bundler/source/git/git_proxy.rb +0 -6
  109. data/lib/bundler/source/git.rb +56 -31
  110. data/lib/bundler/source/path.rb +2 -2
  111. data/lib/bundler/source_list.rb +1 -1
  112. data/lib/bundler/spec_set.rb +81 -56
  113. data/lib/bundler/stub_specification.rb +8 -0
  114. data/lib/bundler/templates/newgem/README.md.tt +1 -1
  115. data/lib/bundler/uri_credentials_filter.rb +1 -1
  116. data/lib/bundler/vendor/fileutils/COPYING +56 -0
  117. data/lib/bundler/vendor/fileutils/lib/fileutils.rb +15 -13
  118. data/lib/bundler/vendor/securerandom/COPYING +56 -0
  119. data/lib/bundler/vendor/securerandom/lib/securerandom.rb +5 -5
  120. data/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +3 -5
  121. data/lib/bundler/vendor/thor/lib/thor/group.rb +11 -0
  122. data/lib/bundler/vendor/thor/lib/thor/parser/argument.rb +1 -4
  123. data/lib/bundler/vendor/thor/lib/thor/parser/option.rb +2 -2
  124. data/lib/bundler/vendor/thor/lib/thor/parser/options.rb +2 -1
  125. data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +9 -9
  126. data/lib/bundler/vendor/thor/lib/thor/shell/html.rb +1 -1
  127. data/lib/bundler/vendor/thor/lib/thor/shell/table_printer.rb +5 -21
  128. data/lib/bundler/vendor/thor/lib/thor/util.rb +1 -1
  129. data/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
  130. data/lib/bundler/vendor/thor/lib/thor.rb +11 -0
  131. data/lib/bundler/vendor/uri/COPYING +56 -0
  132. data/lib/bundler/vendor/uri/lib/uri/common.rb +37 -16
  133. data/lib/bundler/vendor/uri/lib/uri/file.rb +3 -3
  134. data/lib/bundler/vendor/uri/lib/uri/ftp.rb +1 -1
  135. data/lib/bundler/vendor/uri/lib/uri/generic.rb +16 -26
  136. data/lib/bundler/vendor/uri/lib/uri/http.rb +2 -2
  137. data/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb +10 -3
  138. data/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb +26 -3
  139. data/lib/bundler/vendor/uri/lib/uri/version.rb +1 -1
  140. data/lib/bundler/vendor/uri/lib/uri.rb +9 -9
  141. data/lib/bundler/vendored_securerandom.rb +0 -2
  142. data/lib/bundler/version.rb +1 -1
  143. data/lib/bundler.rb +37 -13
  144. metadata +18 -12
  145. data/lib/bundler/vendor/fileutils/LICENSE.txt +0 -22
  146. data/lib/bundler/vendor/securerandom/LICENSE.txt +0 -22
  147. data/lib/bundler/vendor/securerandom/lib/random/formatter.rb +0 -373
  148. data/lib/bundler/vendor/uri/LICENSE.txt +0 -22
@@ -13,13 +13,13 @@ module Bundler
13
13
 
14
14
  attr_reader(
15
15
  :dependencies,
16
+ :locked_checksums,
16
17
  :locked_deps,
17
18
  :locked_gems,
18
19
  :platforms,
19
20
  :ruby_version,
20
21
  :lockfile,
21
22
  :gemfiles,
22
- :locked_checksums,
23
23
  :sources
24
24
  )
25
25
 
@@ -89,6 +89,7 @@ module Bundler
89
89
  @lockfile_contents = Bundler.read_file(lockfile)
90
90
  @locked_gems = LockfileParser.new(@lockfile_contents)
91
91
  @locked_platforms = @locked_gems.platforms
92
+ @most_specific_locked_platform = @locked_gems.most_specific_locked_platform
92
93
  @platforms = @locked_platforms.dup
93
94
  @locked_bundler_version = @locked_gems.bundler_version
94
95
  @locked_ruby_version = @locked_gems.ruby_version
@@ -108,15 +109,16 @@ module Bundler
108
109
  end
109
110
  else
110
111
  @unlock = {}
111
- @platforms = []
112
112
  @locked_gems = nil
113
+ @locked_platforms = []
114
+ @most_specific_locked_platform = nil
115
+ @platforms = []
113
116
  @locked_deps = {}
114
117
  @locked_specs = SpecSet.new([])
115
118
  @originally_locked_deps = {}
116
119
  @originally_locked_specs = @locked_specs
117
120
  @locked_sources = []
118
- @locked_platforms = []
119
- @locked_checksums = Bundler.feature_flag.bundler_3_mode?
121
+ @locked_checksums = Bundler.feature_flag.lockfile_checksums?
120
122
  end
121
123
 
122
124
  locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
@@ -150,7 +152,7 @@ module Bundler
150
152
  @gems_to_unlock = @explicit_unlocks.any? ? @explicit_unlocks : @dependencies.map(&:name)
151
153
  else
152
154
  eager_unlock = @explicit_unlocks.map {|name| Dependency.new(name, ">= 0") }
153
- @gems_to_unlock = @locked_specs.for(eager_unlock, false, platforms).map(&:name).uniq
155
+ @gems_to_unlock = @locked_specs.for(eager_unlock, platforms).map(&:name).uniq
154
156
  end
155
157
 
156
158
  @dependency_changes = converge_dependencies
@@ -175,16 +177,45 @@ module Bundler
175
177
  resolve
176
178
  end
177
179
 
180
+ #
181
+ # Setup sources according to the given options and the state of the
182
+ # definition.
183
+ #
184
+ # @return [Boolean] Whether fetching remote information will be necessary or not
185
+ #
186
+ def setup_domain!(options = {})
187
+ prefer_local! if options[:"prefer-local"]
188
+
189
+ if options[:local] || no_install_needed?
190
+ Bundler.settings.set_command_option(:jobs, 1) if no_install_needed? # to avoid the overhead of Bundler::Worker
191
+ with_cache!
192
+ false
193
+ else
194
+ remotely!
195
+ true
196
+ end
197
+ end
198
+
178
199
  def resolve_with_cache!
200
+ with_cache!
201
+
202
+ resolve
203
+ end
204
+
205
+ def with_cache!
179
206
  sources.local!
180
207
  sources.cached!
181
- resolve
182
208
  end
183
209
 
184
210
  def resolve_remotely!
211
+ remotely!
212
+
213
+ resolve
214
+ end
215
+
216
+ def remotely!
185
217
  sources.cached!
186
218
  sources.remote!
187
- resolve
188
219
  end
189
220
 
190
221
  def prefer_local!
@@ -210,7 +241,7 @@ module Bundler
210
241
  end
211
242
 
212
243
  def missing_specs
213
- resolve.materialize(requested_dependencies).missing_specs
244
+ resolve.missing_specs_for(requested_dependencies)
214
245
  end
215
246
 
216
247
  def missing_specs?
@@ -274,11 +305,7 @@ module Bundler
274
305
  groups.map!(&:to_sym)
275
306
  deps = current_dependencies # always returns a new array
276
307
  deps.select! do |d|
277
- if RUBY_VERSION >= "3.1"
278
- d.groups.intersect?(groups)
279
- else
280
- !(d.groups & groups).empty?
281
- end
308
+ d.groups.intersect?(groups)
282
309
  end
283
310
  deps
284
311
  end
@@ -316,11 +343,11 @@ module Bundler
316
343
  end
317
344
 
318
345
  def spec_git_paths
319
- sources.git_sources.map {|s| File.realpath(s.path) if File.exist?(s.path) }.compact
346
+ sources.git_sources.filter_map {|s| File.realpath(s.path) if File.exist?(s.path) }
320
347
  end
321
348
 
322
349
  def groups
323
- dependencies.map(&:groups).flatten.uniq
350
+ dependencies.flat_map(&:groups).uniq
324
351
  end
325
352
 
326
353
  def lock(file_or_preserve_unknown_sections = false, preserve_unknown_sections_or_unused = false)
@@ -465,6 +492,12 @@ module Bundler
465
492
  "Add the current platform to the lockfile with\n`bundle lock --add-platform #{local_platform}` and try again."
466
493
  end
467
494
 
495
+ def normalize_platforms
496
+ @platforms = resolve.normalize_platforms!(current_dependencies, platforms)
497
+
498
+ @resolve = SpecSet.new(resolve.for(current_dependencies, @platforms))
499
+ end
500
+
468
501
  def add_platform(platform)
469
502
  return if @platforms.include?(platform)
470
503
 
@@ -479,12 +512,6 @@ module Bundler
479
512
  raise InvalidOption, "Unable to remove the platform `#{platform}` since the only platforms are #{@platforms.join ", "}"
480
513
  end
481
514
 
482
- def most_specific_locked_platform
483
- @platforms.min_by do |bundle_platform|
484
- platform_specificity_match(bundle_platform, local_platform)
485
- end
486
- end
487
-
488
515
  def nothing_changed?
489
516
  return false unless lockfile_exists?
490
517
 
@@ -500,6 +527,10 @@ module Bundler
500
527
  !@locked_spec_with_invalid_deps
501
528
  end
502
529
 
530
+ def no_install_needed?
531
+ no_resolve_needed? && !missing_specs?
532
+ end
533
+
503
534
  def no_resolve_needed?
504
535
  !unlocking? && nothing_changed?
505
536
  end
@@ -510,6 +541,14 @@ module Bundler
510
541
 
511
542
  attr_writer :source_requirements
512
543
 
544
+ def add_checksums
545
+ @locked_checksums = true
546
+
547
+ setup_domain!
548
+
549
+ specs # force materialization to real specifications, so that checksums are fetched
550
+ end
551
+
513
552
  private
514
553
 
515
554
  def should_add_extra_platforms?
@@ -555,7 +594,7 @@ module Bundler
555
594
  end
556
595
 
557
596
  def resolver
558
- @resolver ||= Resolver.new(resolution_packages, gem_version_promoter)
597
+ @resolver ||= Resolver.new(resolution_packages, gem_version_promoter, @most_specific_locked_platform)
559
598
  end
560
599
 
561
600
  def expanded_dependencies
@@ -564,7 +603,7 @@ module Bundler
564
603
 
565
604
  def dependencies_with_bundler
566
605
  return dependencies unless @unlocking_bundler
567
- return dependencies if dependencies.map(&:name).include?("bundler")
606
+ return dependencies if dependencies.any? {|d| d.name == "bundler" }
568
607
 
569
608
  [Dependency.new("bundler", @unlocking_bundler)] + dependencies
570
609
  end
@@ -580,22 +619,46 @@ module Bundler
580
619
  end
581
620
  end
582
621
 
583
- def filter_specs(specs, deps)
584
- SpecSet.new(specs).for(deps, false, platforms)
622
+ def filter_specs(specs, deps, skips: [])
623
+ SpecSet.new(specs).for(deps, platforms, skips: skips)
585
624
  end
586
625
 
587
626
  def materialize(dependencies)
588
- specs = resolve.materialize(dependencies)
589
- missing_specs = specs.missing_specs
627
+ # Tracks potential endless loops trying to re-resolve.
628
+ # TODO: Remove as dead code if not reports are received in a while
629
+ incorrect_spec = nil
630
+
631
+ specs = begin
632
+ resolve.materialize(dependencies)
633
+ rescue IncorrectLockfileDependencies => e
634
+ spec = e.spec
635
+ raise "Infinite loop while fixing lockfile dependencies" if incorrect_spec == spec
636
+
637
+ incorrect_spec = spec
638
+ reresolve_without([spec])
639
+ retry
640
+ end
641
+
642
+ missing_specs = resolve.missing_specs
590
643
 
591
644
  if missing_specs.any?
592
645
  missing_specs.each do |s|
593
646
  locked_gem = @locked_specs[s.name].last
594
647
  next if locked_gem.nil? || locked_gem.version != s.version || sources.local_mode?
595
- raise GemNotFound, "Your bundle is locked to #{locked_gem} from #{locked_gem.source}, but that version can " \
596
- "no longer be found in that source. That means the author of #{locked_gem} has removed it. " \
597
- "You'll need to update your bundle to a version other than #{locked_gem} that hasn't been " \
598
- "removed in order to install."
648
+
649
+ message = if sources.implicit_global_source?
650
+ "Because your Gemfile specifies no global remote source, your bundle is locked to " \
651
+ "#{locked_gem} from #{locked_gem.source}. However, #{locked_gem} is not installed. You'll " \
652
+ "need to either add a global remote source to your Gemfile or make sure #{locked_gem} is " \
653
+ "available locally before rerunning Bundler."
654
+ else
655
+ "Your bundle is locked to #{locked_gem} from #{locked_gem.source}, but that version can " \
656
+ "no longer be found in that source. That means the author of #{locked_gem} has removed it. " \
657
+ "You'll need to update your bundle to a version other than #{locked_gem} that hasn't been " \
658
+ "removed in order to install."
659
+ end
660
+
661
+ raise GemNotFound, message
599
662
  end
600
663
 
601
664
  missing_specs_list = missing_specs.group_by(&:source).map do |source, missing_specs_for_source|
@@ -605,17 +668,24 @@ module Bundler
605
668
  raise GemNotFound, "Could not find #{missing_specs_list.join(" nor ")}"
606
669
  end
607
670
 
608
- incomplete_specs = specs.incomplete_specs
671
+ partially_missing_specs = resolve.partially_missing_specs
672
+
673
+ if partially_missing_specs.any? && !sources.local_mode?
674
+ Bundler.ui.warn "Some locked specs have possibly been yanked (#{partially_missing_specs.map(&:full_name).join(", ")}). Ignoring them..."
675
+
676
+ resolve.delete(partially_missing_specs)
677
+ end
678
+
679
+ incomplete_specs = resolve.incomplete_specs
609
680
  loop do
610
681
  break if incomplete_specs.empty?
611
682
 
612
683
  Bundler.ui.debug("The lockfile does not have all gems needed for the current platform though, Bundler will still re-resolve dependencies")
613
684
  sources.remote!
614
- resolution_packages.delete(incomplete_specs)
615
- @resolve = start_resolution
685
+ reresolve_without(incomplete_specs)
616
686
  specs = resolve.materialize(dependencies)
617
687
 
618
- still_incomplete_specs = specs.incomplete_specs
688
+ still_incomplete_specs = resolve.incomplete_specs
619
689
 
620
690
  if still_incomplete_specs == incomplete_specs
621
691
  package = resolution_packages.get_package(incomplete_specs.first.name)
@@ -625,12 +695,26 @@ module Bundler
625
695
  incomplete_specs = still_incomplete_specs
626
696
  end
627
697
 
698
+ insecurely_materialized_specs = resolve.insecurely_materialized_specs
699
+
700
+ if insecurely_materialized_specs.any?
701
+ Bundler.ui.warn "The following platform specific gems are getting installed, yet the lockfile includes only their generic ruby version:\n" \
702
+ " * #{insecurely_materialized_specs.map(&:full_name).join("\n * ")}\n" \
703
+ "Please run `bundle lock --normalize-platforms` and commit the resulting lockfile.\n" \
704
+ "Alternatively, you may run `bundle lock --add-platform <list-of-platforms-that-you-want-to-support>`"
705
+ end
706
+
628
707
  bundler = sources.metadata_source.specs.search(["bundler", Bundler.gem_version]).last
629
708
  specs["bundler"] = bundler
630
709
 
631
710
  specs
632
711
  end
633
712
 
713
+ def reresolve_without(incomplete_specs)
714
+ resolution_packages.delete(incomplete_specs)
715
+ @resolve = start_resolution
716
+ end
717
+
634
718
  def start_resolution
635
719
  local_platform_needed_for_resolvability = @most_specific_non_local_locked_ruby_platform && !@platforms.include?(local_platform)
636
720
  @platforms << local_platform if local_platform_needed_for_resolvability
@@ -650,7 +734,7 @@ module Bundler
650
734
 
651
735
  @platforms = result.add_extra_platforms!(platforms) if should_add_extra_platforms?
652
736
 
653
- SpecSet.new(result.for(dependencies, false, @platforms))
737
+ SpecSet.new(result.for(dependencies, @platforms))
654
738
  end
655
739
 
656
740
  def precompute_source_requirements_for_indirect_dependencies?
@@ -676,7 +760,7 @@ module Bundler
676
760
  def find_most_specific_locked_ruby_platform
677
761
  return unless generic_local_platform_is_ruby? && current_platform_locked?
678
762
 
679
- most_specific_locked_platform
763
+ @most_specific_locked_platform
680
764
  end
681
765
 
682
766
  def change_reason
@@ -877,7 +961,7 @@ module Bundler
877
961
  def converge_locked_specs
878
962
  converged = converge_specs(@locked_specs)
879
963
 
880
- resolve = SpecSet.new(converged.reject {|s| @gems_to_unlock.include?(s.name) })
964
+ resolve = SpecSet.new(converged)
881
965
 
882
966
  diff = nil
883
967
 
@@ -906,8 +990,7 @@ module Bundler
906
990
  if dep
907
991
  gemfile_source = dep.source || default_source
908
992
 
909
- deps << dep if !dep.source || lockfile_source.include?(dep.source)
910
- @gems_to_unlock << name if lockfile_source.include?(dep.source) && lockfile_source != gemfile_source
993
+ deps << dep if !dep.source || lockfile_source.include?(dep.source) || new_deps.include?(dep)
911
994
 
912
995
  # Replace the locked dependency's source with the equivalent source from the Gemfile
913
996
  s.source = gemfile_source
@@ -916,25 +999,14 @@ module Bundler
916
999
  s.source = default_source unless sources.get(lockfile_source)
917
1000
  end
918
1001
 
919
- next if @sources_to_unlock.include?(s.source.name)
1002
+ source = s.source
1003
+ next if @sources_to_unlock.include?(source.name)
920
1004
 
921
1005
  # Path sources have special logic
922
- if s.source.instance_of?(Source::Path) || s.source.instance_of?(Source::Gemspec)
923
- new_specs = begin
924
- s.source.specs
925
- rescue PathError
926
- # if we won't need the source (according to the lockfile),
927
- # don't error if the path source isn't available
928
- next if specs.
929
- for(requested_dependencies, false).
930
- none? {|locked_spec| locked_spec.source == s.source }
931
-
932
- raise
933
- end
934
-
935
- new_spec = new_specs[s].first
1006
+ if source.instance_of?(Source::Path) || source.instance_of?(Source::Gemspec) || (source.instance_of?(Source::Git) && !@gems_to_unlock.include?(name) && deps.include?(dep))
1007
+ new_spec = source.specs[s].first
936
1008
  if new_spec
937
- s.dependencies.replace(new_spec.dependencies)
1009
+ s.runtime_dependencies.replace(new_spec.runtime_dependencies)
938
1010
  else
939
1011
  # If the spec is no longer in the path source, unlock it. This
940
1012
  # commonly happens if the version changed in the gemspec
@@ -942,14 +1014,15 @@ module Bundler
942
1014
  end
943
1015
  end
944
1016
 
945
- if dep.nil? && requested_dependencies.find {|d| name == d.name }
946
- @gems_to_unlock << s.name
947
- else
948
- converged << s
1017
+ if dep.nil? && requested_dep = requested_dependencies.find {|d| name == d.name }
1018
+ @gems_to_unlock << name
1019
+ deps << requested_dep
949
1020
  end
1021
+
1022
+ converged << s
950
1023
  end
951
1024
 
952
- filter_specs(converged, deps)
1025
+ filter_specs(converged, deps, skips: @gems_to_unlock)
953
1026
  end
954
1027
 
955
1028
  def metadata_dependencies
@@ -62,7 +62,7 @@ module Bundler
62
62
  end
63
63
 
64
64
  def expanded_platforms
65
- @expanded_platforms ||= @platforms.map {|pl| PLATFORM_MAP[pl] }.compact.flatten.uniq
65
+ @expanded_platforms ||= @platforms.filter_map {|pl| PLATFORM_MAP[pl] }.flatten.uniq
66
66
  end
67
67
 
68
68
  def should_include?
data/lib/bundler/dsl.rb CHANGED
@@ -66,7 +66,7 @@ module Bundler
66
66
  development_group = opts[:development_group] || :development
67
67
  expanded_path = gemfile_root.join(path)
68
68
 
69
- gemspecs = Gem::Util.glob_files_in_dir("{,*}.gemspec", expanded_path).map {|g| Bundler.load_gemspec(g) }.compact
69
+ gemspecs = Gem::Util.glob_files_in_dir("{,*}.gemspec", expanded_path).filter_map {|g| Bundler.load_gemspec(g) }
70
70
  gemspecs.reject! {|s| s.name != name } if name
71
71
  specs_by_name_and_version = gemspecs.group_by {|s| [s.name, s.version] }
72
72
 
@@ -503,18 +503,7 @@ module Bundler
503
503
  end
504
504
 
505
505
  def check_rubygems_source_safety
506
- if @sources.implicit_global_source?
507
- implicit_global_source_warning
508
- elsif @sources.aggregate_global_source?
509
- multiple_global_source_warning
510
- end
511
- end
512
-
513
- def implicit_global_source_warning
514
- Bundler::SharedHelpers.major_deprecation 2, "This Gemfile does not include an explicit global source. " \
515
- "Not using an explicit global source may result in a different lockfile being generated depending on " \
516
- "the gems you have installed locally before bundler is run. " \
517
- "Instead, define a global source in your Gemfile like this: source \"https://rubygems.org\"."
506
+ multiple_global_source_warning if @sources.aggregate_global_source?
518
507
  end
519
508
 
520
509
  def multiple_global_source_warning
@@ -6,7 +6,7 @@ module Bundler
6
6
  include MatchRemoteMetadata
7
7
 
8
8
  attr_reader :name, :version, :platform, :checksum
9
- attr_accessor :source, :remote, :dependencies
9
+ attr_accessor :remote, :dependencies, :locked_platform
10
10
 
11
11
  def initialize(name, version, platform, spec_fetcher, dependencies, metadata = nil)
12
12
  super()
@@ -18,10 +18,15 @@ module Bundler
18
18
 
19
19
  @loaded_from = nil
20
20
  @remote_specification = nil
21
+ @locked_platform = nil
21
22
 
22
23
  parse_metadata(metadata)
23
24
  end
24
25
 
26
+ def insecurely_materialized?
27
+ @locked_platform.to_s != @platform.to_s
28
+ end
29
+
25
30
  def fetch_platform
26
31
  @platform
27
32
  end
@@ -115,6 +120,10 @@ module Bundler
115
120
  @remote_specification = spec
116
121
  end
117
122
 
123
+ def inspect
124
+ "#<#{self.class} @name=\"#{name}\" (#{full_name.delete_prefix("#{name}-")})>"
125
+ end
126
+
118
127
  private
119
128
 
120
129
  def _remote_specification
@@ -246,4 +246,14 @@ module Bundler
246
246
  end
247
247
 
248
248
  class InvalidArgumentError < BundlerError; status_code(40); end
249
+
250
+ class IncorrectLockfileDependencies < BundlerError
251
+ attr_reader :spec
252
+
253
+ def initialize(spec)
254
+ @spec = spec
255
+ end
256
+
257
+ status_code(41)
258
+ end
249
259
  end
@@ -33,6 +33,7 @@ module Bundler
33
33
  settings_flag(:default_install_uses_path) { bundler_3_mode? }
34
34
  settings_flag(:forget_cli_options) { bundler_3_mode? }
35
35
  settings_flag(:global_gem_cache) { bundler_3_mode? }
36
+ settings_flag(:lockfile_checksums) { bundler_3_mode? }
36
37
  settings_flag(:path_relative_to_cwd) { bundler_3_mode? }
37
38
  settings_flag(:plugins) { @bundler_version >= Gem::Version.new("1.14") }
38
39
  settings_flag(:print_only_version_number) { bundler_3_mode? }
@@ -10,7 +10,7 @@ module Bundler
10
10
  method = instance_method(method_name)
11
11
  undef_method(method_name)
12
12
  define_method(method_name) do |*args, &blk|
13
- method.bind(self).call(*args, &blk)
13
+ method.bind_call(self, *args, &blk)
14
14
  rescue NetworkDownError, CompactIndexClient::Updater::MismatchedChecksumError => e
15
15
  raise HTTPError, e.message
16
16
  rescue AuthenticationRequiredError, BadAuthenticationError
@@ -37,8 +37,9 @@ module Bundler
37
37
  # This is the error raised when a source is HTTPS and OpenSSL didn't load
38
38
  class SSLError < HTTPError
39
39
  def initialize(msg = nil)
40
- super msg || "Could not load OpenSSL.\n" \
41
- "You must recompile Ruby with OpenSSL support."
40
+ super "Could not load OpenSSL.\n" \
41
+ "You must recompile Ruby with OpenSSL support.\n" \
42
+ "original error: #{msg}\n"
42
43
  end
43
44
  end
44
45
 
@@ -251,7 +252,13 @@ module Bundler
251
252
  needs_ssl = remote_uri.scheme == "https" ||
252
253
  Bundler.settings[:ssl_verify_mode] ||
253
254
  Bundler.settings[:ssl_client_cert]
254
- raise SSLError if needs_ssl && !defined?(OpenSSL::SSL)
255
+ if needs_ssl
256
+ begin
257
+ require "openssl"
258
+ rescue StandardError, LoadError => e
259
+ raise SSLError.new(e.message)
260
+ end
261
+ end
255
262
 
256
263
  con = Gem::Net::HTTP::Persistent.new name: "bundler", proxy: :ENV
257
264
  if gem_proxy = Gem.configuration[:http_proxy]
@@ -46,7 +46,7 @@ module Bundler
46
46
  end
47
47
  module_function :platform_specificity_match
48
48
 
49
- def select_best_platform_match(specs, platform, force_ruby: false, prefer_locked: false)
49
+ def select_all_platform_match(specs, platform, force_ruby: false, prefer_locked: false)
50
50
  matching = if force_ruby
51
51
  specs.select {|spec| spec.match_platform(Gem::Platform::RUBY) && spec.force_ruby_platform! }
52
52
  else
@@ -58,24 +58,40 @@ module Bundler
58
58
  return locked_originally if locked_originally.any?
59
59
  end
60
60
 
61
- sort_best_platform_match(matching, platform)
61
+ matching
62
+ end
63
+ module_function :select_all_platform_match
64
+
65
+ def select_best_platform_match(specs, platform, force_ruby: false, prefer_locked: false)
66
+ matching = select_all_platform_match(specs, platform, force_ruby: force_ruby, prefer_locked: prefer_locked)
67
+
68
+ sort_and_filter_best_platform_match(matching, platform)
62
69
  end
63
70
  module_function :select_best_platform_match
64
71
 
65
72
  def select_best_local_platform_match(specs, force_ruby: false)
66
- select_best_platform_match(specs, local_platform, force_ruby: force_ruby).map(&:materialize_for_installation).compact
73
+ matching = select_all_platform_match(specs, local_platform, force_ruby: force_ruby).filter_map(&:materialized_for_installation)
74
+
75
+ sort_best_platform_match(matching, local_platform)
67
76
  end
68
77
  module_function :select_best_local_platform_match
69
78
 
70
- def sort_best_platform_match(matching, platform)
79
+ def sort_and_filter_best_platform_match(matching, platform)
80
+ return matching if matching.one?
81
+
71
82
  exact = matching.select {|spec| spec.platform == platform }
72
83
  return exact if exact.any?
73
84
 
74
- sorted_matching = matching.sort_by {|spec| platform_specificity_match(spec.platform, platform) }
85
+ sorted_matching = sort_best_platform_match(matching, platform)
75
86
  exemplary_spec = sorted_matching.first
76
87
 
77
88
  sorted_matching.take_while {|spec| same_specificity(platform, spec, exemplary_spec) && same_deps(spec, exemplary_spec) }
78
89
  end
90
+ module_function :sort_and_filter_best_platform_match
91
+
92
+ def sort_best_platform_match(matching, platform)
93
+ matching.sort_by {|spec| platform_specificity_match(spec.platform, platform) }
94
+ end
79
95
  module_function :sort_best_platform_match
80
96
 
81
97
  class PlatformMatch
@@ -41,7 +41,7 @@ module Bundler
41
41
 
42
42
  # resolve to see if the new deps broke anything
43
43
  @definition = builder.to_definition(lockfile_path, {})
44
- @definition.resolve_remotely!
44
+ @definition.remotely!
45
45
 
46
46
  # since nothing broke, we can add those gems to the gemfile
47
47
  append_to(gemfile_path, build_gem_lines(@options[:conservative_versioning])) if @deps.any?
@@ -184,7 +184,7 @@ module Bundler
184
184
  # @param [Array] gems Array of names of gems to be removed.
185
185
  # @param [Pathname] gemfile_path The Gemfile from which to remove dependencies.
186
186
  def remove_gems_from_gemfile(gems, gemfile_path)
187
- patterns = /gem\s+(['"])#{Regexp.union(gems)}\1|gem\s*\((['"])#{Regexp.union(gems)}\2\)/
187
+ patterns = /gem\s+(['"])#{Regexp.union(gems)}\1|gem\s*\((['"])#{Regexp.union(gems)}\2.*\)/
188
188
  new_gemfile = []
189
189
  multiline_removal = false
190
190
  File.readlines(gemfile_path).each do |line|
@@ -28,7 +28,7 @@ module Bundler
28
28
  private
29
29
 
30
30
  def paths
31
- @specs.map do |spec|
31
+ @specs.flat_map do |spec|
32
32
  next if spec.name == "bundler"
33
33
  Array(spec.require_paths).map do |path|
34
34
  gem_path(path, spec).
@@ -36,7 +36,7 @@ module Bundler
36
36
  sub(extensions_dir, 'extensions/\k<platform>/#{Gem.extension_api_version}')
37
37
  # This is a static string intentionally. It's interpolated at a later time.
38
38
  end
39
- end.flatten.compact
39
+ end.compact
40
40
  end
41
41
 
42
42
  def version_dir