bundler 2.7.0 → 4.0.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 (152) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1058 -896
  3. data/README.md +4 -4
  4. data/bundler.gemspec +3 -3
  5. data/lib/bundler/build_metadata.rb +2 -2
  6. data/lib/bundler/capistrano.rb +1 -19
  7. data/lib/bundler/checksum.rb +6 -0
  8. data/lib/bundler/cli/cache.rb +1 -12
  9. data/lib/bundler/cli/common.rb +21 -4
  10. data/lib/bundler/cli/config.rb +1 -2
  11. data/lib/bundler/cli/console.rb +5 -0
  12. data/lib/bundler/cli/exec.rb +29 -4
  13. data/lib/bundler/cli/gem.rb +19 -33
  14. data/lib/bundler/cli/install.rb +10 -85
  15. data/lib/bundler/cli/issue.rb +2 -2
  16. data/lib/bundler/cli/list.rb +33 -2
  17. data/lib/bundler/cli/lock.rb +5 -5
  18. data/lib/bundler/cli/plugin.rb +5 -1
  19. data/lib/bundler/cli/show.rb +3 -7
  20. data/lib/bundler/cli/update.rb +4 -4
  21. data/lib/bundler/cli.rb +157 -122
  22. data/lib/bundler/compact_index_client.rb +0 -1
  23. data/lib/bundler/current_ruby.rb +3 -15
  24. data/lib/bundler/definition.rb +143 -95
  25. data/lib/bundler/deployment.rb +1 -64
  26. data/lib/bundler/digest.rb +1 -1
  27. data/lib/bundler/dsl.rb +27 -37
  28. data/lib/bundler/environment_preserver.rb +1 -0
  29. data/lib/bundler/errors.rb +1 -5
  30. data/lib/bundler/feature_flag.rb +0 -33
  31. data/lib/bundler/fetcher/compact_index.rb +1 -1
  32. data/lib/bundler/fetcher/gem_remote_fetcher.rb +6 -0
  33. data/lib/bundler/friendly_errors.rb +2 -2
  34. data/lib/bundler/index.rb +0 -7
  35. data/lib/bundler/inline.rb +9 -1
  36. data/lib/bundler/installer/gem_installer.rb +0 -11
  37. data/lib/bundler/installer.rb +0 -6
  38. data/lib/bundler/lockfile_generator.rb +1 -1
  39. data/lib/bundler/lockfile_parser.rb +2 -12
  40. data/lib/bundler/man/bundle-add.1 +1 -1
  41. data/lib/bundler/man/bundle-binstubs.1 +3 -6
  42. data/lib/bundler/man/bundle-binstubs.1.ronn +4 -6
  43. data/lib/bundler/man/bundle-cache.1 +2 -14
  44. data/lib/bundler/man/bundle-cache.1.ronn +1 -14
  45. data/lib/bundler/man/bundle-check.1 +2 -5
  46. data/lib/bundler/man/bundle-check.1.ronn +0 -5
  47. data/lib/bundler/man/bundle-clean.1 +1 -1
  48. data/lib/bundler/man/bundle-config.1 +39 -46
  49. data/lib/bundler/man/bundle-config.1.ronn +73 -75
  50. data/lib/bundler/man/bundle-console.1 +1 -1
  51. data/lib/bundler/man/bundle-doctor.1 +4 -4
  52. data/lib/bundler/man/bundle-doctor.1.ronn +4 -4
  53. data/lib/bundler/man/bundle-env.1 +1 -1
  54. data/lib/bundler/man/bundle-exec.1 +2 -5
  55. data/lib/bundler/man/bundle-exec.1.ronn +1 -5
  56. data/lib/bundler/man/bundle-fund.1 +1 -1
  57. data/lib/bundler/man/bundle-gem.1 +3 -6
  58. data/lib/bundler/man/bundle-gem.1.ronn +2 -5
  59. data/lib/bundler/man/bundle-help.1 +1 -1
  60. data/lib/bundler/man/bundle-info.1 +1 -1
  61. data/lib/bundler/man/bundle-init.1 +1 -1
  62. data/lib/bundler/man/bundle-install.1 +16 -59
  63. data/lib/bundler/man/bundle-install.1.ronn +27 -108
  64. data/lib/bundler/man/bundle-issue.1 +1 -1
  65. data/lib/bundler/man/bundle-licenses.1 +1 -1
  66. data/lib/bundler/man/bundle-list.1 +6 -1
  67. data/lib/bundler/man/bundle-list.1.ronn +5 -0
  68. data/lib/bundler/man/bundle-lock.1 +1 -1
  69. data/lib/bundler/man/bundle-open.1 +1 -1
  70. data/lib/bundler/man/bundle-outdated.1 +1 -1
  71. data/lib/bundler/man/bundle-platform.1 +1 -1
  72. data/lib/bundler/man/bundle-plugin.1 +33 -15
  73. data/lib/bundler/man/bundle-plugin.1.ronn +36 -15
  74. data/lib/bundler/man/bundle-pristine.1 +1 -1
  75. data/lib/bundler/man/bundle-remove.1 +2 -8
  76. data/lib/bundler/man/bundle-remove.1.ronn +1 -8
  77. data/lib/bundler/man/bundle-show.1 +2 -5
  78. data/lib/bundler/man/bundle-show.1.ronn +0 -4
  79. data/lib/bundler/man/bundle-update.1 +5 -5
  80. data/lib/bundler/man/bundle-update.1.ronn +4 -4
  81. data/lib/bundler/man/bundle-version.1 +1 -1
  82. data/lib/bundler/man/bundle.1 +1 -10
  83. data/lib/bundler/man/bundle.1.ronn +0 -9
  84. data/lib/bundler/man/gemfile.5 +32 -1
  85. data/lib/bundler/man/gemfile.5.ronn +28 -0
  86. data/lib/bundler/man/index.txt +0 -2
  87. data/lib/bundler/materialization.rb +1 -1
  88. data/lib/bundler/plugin/installer.rb +0 -10
  89. data/lib/bundler/plugin/source_list.rb +1 -1
  90. data/lib/bundler/plugin.rb +1 -1
  91. data/lib/bundler/resolver/package.rb +1 -0
  92. data/lib/bundler/resolver.rb +1 -1
  93. data/lib/bundler/ruby_dsl.rb +2 -0
  94. data/lib/bundler/ruby_version.rb +1 -3
  95. data/lib/bundler/rubygems_ext.rb +1 -1
  96. data/lib/bundler/rubygems_gem_installer.rb +1 -1
  97. data/lib/bundler/rubygems_integration.rb +1 -5
  98. data/lib/bundler/runtime.rb +5 -1
  99. data/lib/bundler/self_manager.rb +1 -1
  100. data/lib/bundler/settings.rb +9 -27
  101. data/lib/bundler/shared_helpers.rb +12 -20
  102. data/lib/bundler/source/gemspec.rb +4 -0
  103. data/lib/bundler/source/git/git_proxy.rb +3 -11
  104. data/lib/bundler/source/git.rb +2 -3
  105. data/lib/bundler/source/path.rb +5 -7
  106. data/lib/bundler/source/rubygems.rb +11 -17
  107. data/lib/bundler/source.rb +1 -1
  108. data/lib/bundler/source_list.rb +4 -45
  109. data/lib/bundler/source_map.rb +2 -5
  110. data/lib/bundler/spec_set.rb +6 -15
  111. data/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt +7 -129
  112. data/lib/bundler/templates/newgem/Rakefile.tt +5 -0
  113. data/lib/bundler/templates/newgem/circleci/config.yml.tt +12 -0
  114. data/lib/bundler/templates/newgem/ext/newgem/Cargo.toml.tt +1 -1
  115. data/lib/bundler/templates/newgem/ext/newgem/extconf-go.rb.tt +11 -0
  116. data/lib/bundler/templates/newgem/ext/newgem/go.mod.tt +5 -0
  117. data/lib/bundler/templates/newgem/ext/newgem/newgem-go.c.tt +2 -0
  118. data/lib/bundler/templates/newgem/ext/newgem/newgem.go.tt +31 -0
  119. data/lib/bundler/templates/newgem/github/workflows/main.yml.tt +6 -0
  120. data/lib/bundler/templates/newgem/gitlab-ci.yml.tt +9 -0
  121. data/lib/bundler/templates/newgem/lib/newgem.rb.tt +1 -1
  122. data/lib/bundler/templates/newgem/newgem.gemspec.tt +7 -4
  123. data/lib/bundler/ui/shell.rb +10 -6
  124. data/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +26 -23
  125. data/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +1 -1
  126. data/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +50 -6
  127. data/lib/bundler/vendor/fileutils/lib/fileutils.rb +57 -52
  128. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +5 -2
  129. data/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +42 -6
  130. data/lib/bundler/vendor/thor/lib/thor/parser/options.rb +1 -1
  131. data/lib/bundler/vendor/thor/lib/thor/runner.rb +2 -2
  132. data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +3 -7
  133. data/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
  134. data/lib/bundler/vendor/thor/lib/thor.rb +1 -1
  135. data/lib/bundler/vendor/uri/lib/uri/common.rb +57 -15
  136. data/lib/bundler/vendor/uri/lib/uri/file.rb +1 -1
  137. data/lib/bundler/vendor/uri/lib/uri/generic.rb +34 -21
  138. data/lib/bundler/vendor/uri/lib/uri/http.rb +12 -0
  139. data/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb +9 -8
  140. data/lib/bundler/vendor/uri/lib/uri/version.rb +2 -2
  141. data/lib/bundler/version.rb +1 -1
  142. data/lib/bundler/vlad.rb +1 -14
  143. data/lib/bundler.rb +6 -28
  144. metadata +9 -13
  145. data/lib/bundler/cli/inject.rb +0 -60
  146. data/lib/bundler/cli/viz.rb +0 -31
  147. data/lib/bundler/graph.rb +0 -152
  148. data/lib/bundler/man/bundle-inject.1 +0 -31
  149. data/lib/bundler/man/bundle-inject.1.ronn +0 -32
  150. data/lib/bundler/man/bundle-viz.1 +0 -30
  151. data/lib/bundler/man/bundle-viz.1.ronn +0 -36
  152. data/lib/bundler/similarity_detector.rb +0 -63
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "lockfile_parser"
4
+ require_relative "worker"
4
5
 
5
6
  module Bundler
6
7
  class Definition
@@ -9,6 +10,8 @@ module Bundler
9
10
  attr_accessor :no_lock
10
11
  end
11
12
 
13
+ attr_writer :lockfile
14
+
12
15
  attr_reader(
13
16
  :dependencies,
14
17
  :locked_checksums,
@@ -107,6 +110,7 @@ module Bundler
107
110
  @locked_ruby_version = @locked_gems.ruby_version
108
111
  @locked_deps = @locked_gems.dependencies
109
112
  @originally_locked_specs = SpecSet.new(@locked_gems.specs)
113
+ @originally_locked_sources = @locked_gems.sources
110
114
  @locked_checksums = @locked_gems.checksums
111
115
 
112
116
  if @unlocking_all
@@ -114,7 +118,16 @@ module Bundler
114
118
  @locked_sources = []
115
119
  else
116
120
  @locked_specs = @originally_locked_specs
117
- @locked_sources = @locked_gems.sources
121
+ @locked_sources = @originally_locked_sources
122
+ end
123
+
124
+ locked_gem_sources = @originally_locked_sources.select {|s| s.is_a?(Source::Rubygems) }
125
+ multisource_lockfile = locked_gem_sources.size == 1 && locked_gem_sources.first.multiple_remotes?
126
+
127
+ if multisource_lockfile
128
+ msg = "Your lockfile contains a single rubygems source section with multiple remotes, which is insecure. Make sure you run `bundle install` in non frozen mode and commit the result to make your lockfile secure."
129
+
130
+ Bundler::SharedHelpers.feature_removed! msg
118
131
  end
119
132
  else
120
133
  @locked_gems = nil
@@ -123,22 +136,10 @@ module Bundler
123
136
  @platforms = []
124
137
  @locked_deps = {}
125
138
  @locked_specs = SpecSet.new([])
126
- @originally_locked_specs = @locked_specs
127
139
  @locked_sources = []
128
- @locked_checksums = Bundler.feature_flag.lockfile_checksums?
129
- end
130
-
131
- locked_gem_sources = @locked_sources.select {|s| s.is_a?(Source::Rubygems) }
132
- @multisource_allowed = locked_gem_sources.size == 1 && locked_gem_sources.first.multiple_remotes? && Bundler.frozen_bundle?
133
-
134
- if @multisource_allowed
135
- unless sources.aggregate_global_source?
136
- msg = "Your lockfile contains a single rubygems source section with multiple remotes, which is insecure. Make sure you run `bundle install` in non frozen mode and commit the result to make your lockfile secure."
137
-
138
- Bundler::SharedHelpers.major_deprecation 2, msg
139
- end
140
-
141
- @sources.merged_gem_lockfile_sections!(locked_gem_sources.first)
140
+ @originally_locked_specs = @locked_specs
141
+ @originally_locked_sources = @locked_sources
142
+ @locked_checksums = Bundler.settings[:lockfile_checksums]
142
143
  end
143
144
 
144
145
  @unlocking_ruby ||= if @ruby_version && locked_ruby_version_object
@@ -189,12 +190,14 @@ module Bundler
189
190
  def setup_domain!(options = {})
190
191
  prefer_local! if options[:"prefer-local"]
191
192
 
193
+ sources.cached!
194
+
192
195
  if options[:add_checksums] || (!options[:local] && install_needed?)
193
- remotely!
196
+ sources.remote!
194
197
  true
195
198
  else
196
199
  Bundler.settings.set_command_option(:jobs, 1) unless install_needed? # to avoid the overhead of Bundler::Worker
197
- with_cache!
200
+ sources.local!
198
201
  false
199
202
  end
200
203
  end
@@ -282,12 +285,17 @@ module Bundler
282
285
  end
283
286
 
284
287
  def filter_relevant(dependencies)
285
- platforms_array = [Bundler.generic_local_platform].freeze
286
288
  dependencies.select do |d|
287
- d.should_include? && !d.gem_platforms(platforms_array).empty?
289
+ relevant_deps?(d)
288
290
  end
289
291
  end
290
292
 
293
+ def relevant_deps?(dep)
294
+ platforms_array = [Bundler.generic_local_platform].freeze
295
+
296
+ dep.should_include? && !dep.gem_platforms(platforms_array).empty?
297
+ end
298
+
291
299
  def locked_dependencies
292
300
  @locked_deps.values
293
301
  end
@@ -367,12 +375,50 @@ module Bundler
367
375
 
368
376
  msg = "`Definition#lock` was passed a target file argument. #{suggestion}"
369
377
 
370
- Bundler::SharedHelpers.major_deprecation 2, msg
378
+ Bundler::SharedHelpers.feature_removed! msg
371
379
  end
372
380
 
373
381
  write_lock(target_lockfile, preserve_unknown_sections)
374
382
  end
375
383
 
384
+ def write_lock(file, preserve_unknown_sections)
385
+ return if Definition.no_lock || !lockfile || file.nil?
386
+
387
+ contents = to_lock
388
+
389
+ # Convert to \r\n if the existing lock has them
390
+ # i.e., Windows with `git config core.autocrlf=true`
391
+ contents.gsub!(/\n/, "\r\n") if @lockfile_contents.match?("\r\n")
392
+
393
+ if @locked_bundler_version
394
+ locked_major = @locked_bundler_version.segments.first
395
+ current_major = bundler_version_to_lock.segments.first
396
+
397
+ updating_major = locked_major < current_major
398
+ end
399
+
400
+ preserve_unknown_sections ||= !updating_major && (Bundler.frozen_bundle? || !(unlocking? || @unlocking_bundler))
401
+
402
+ if File.exist?(file) && lockfiles_equal?(@lockfile_contents, contents, preserve_unknown_sections)
403
+ return if Bundler.frozen_bundle?
404
+ SharedHelpers.filesystem_access(file) { FileUtils.touch(file) }
405
+ return
406
+ end
407
+
408
+ if Bundler.frozen_bundle?
409
+ Bundler.ui.error "Cannot write a changed lockfile while frozen."
410
+ return
411
+ end
412
+
413
+ begin
414
+ SharedHelpers.filesystem_access(file) do |p|
415
+ File.open(p, "wb") {|f| f.puts(contents) }
416
+ end
417
+ rescue ReadOnlyFileSystemError
418
+ raise ProductionError, lockfile_changes_summary("file system is read-only")
419
+ end
420
+ end
421
+
376
422
  def locked_ruby_version
377
423
  return unless ruby_version
378
424
  if @unlocking_ruby || !@locked_ruby_version
@@ -492,14 +538,25 @@ module Bundler
492
538
  @unlocking
493
539
  end
494
540
 
495
- attr_writer :source_requirements
496
-
497
541
  def add_checksums
542
+ require "rubygems/package"
543
+
498
544
  @locked_checksums = true
499
545
 
500
546
  setup_domain!(add_checksums: true)
501
547
 
502
- specs # force materialization to real specifications, so that checksums are fetched
548
+ # force materialization to real specifications, so that checksums are fetched
549
+ specs.each do |spec|
550
+ next unless spec.source.is_a?(Bundler::Source::Rubygems)
551
+ # Checksum was fetched from the compact index API.
552
+ next if !spec.source.checksum_store.missing?(spec) && !spec.source.checksum_store.empty?(spec)
553
+ # The gem isn't installed, can't compute the checksum.
554
+ next unless spec.loaded_from
555
+
556
+ package = Gem::Package.new(spec.source.cached_built_in_gem(spec))
557
+ checksum = Checksum.from_gem_package(package)
558
+ spec.source.checksum_store.register(spec, checksum)
559
+ end
503
560
  end
504
561
 
505
562
  private
@@ -533,7 +590,7 @@ module Bundler
533
590
 
534
591
  return unless added.any? || deleted.any? || changed.any? || resolve_needed?
535
592
 
536
- msg = String.new("#{change_reason.capitalize.strip}, but ")
593
+ msg = String.new("#{change_reason[0].upcase}#{change_reason[1..-1].strip}, but ")
537
594
  msg << "the lockfile " unless msg.start_with?("Your lockfile")
538
595
  msg << "can't be updated because #{update_refused_reason}"
539
596
  msg << "\n\nYou have added to the Gemfile:\n" << added.join("\n") if added.any?
@@ -559,6 +616,7 @@ module Bundler
559
616
  @missing_lockfile_dep ||
560
617
  @unlocking_bundler ||
561
618
  @locked_spec_with_missing_checksums ||
619
+ @locked_spec_with_empty_checksums ||
562
620
  @locked_spec_with_missing_deps ||
563
621
  @locked_spec_with_invalid_deps
564
622
  end
@@ -575,46 +633,8 @@ module Bundler
575
633
  lockfile && File.exist?(lockfile)
576
634
  end
577
635
 
578
- def write_lock(file, preserve_unknown_sections)
579
- return if Definition.no_lock || file.nil?
580
-
581
- contents = to_lock
582
-
583
- # Convert to \r\n if the existing lock has them
584
- # i.e., Windows with `git config core.autocrlf=true`
585
- contents.gsub!(/\n/, "\r\n") if @lockfile_contents.match?("\r\n")
586
-
587
- if @locked_bundler_version
588
- locked_major = @locked_bundler_version.segments.first
589
- current_major = bundler_version_to_lock.segments.first
590
-
591
- updating_major = locked_major < current_major
592
- end
593
-
594
- preserve_unknown_sections ||= !updating_major && (Bundler.frozen_bundle? || !(unlocking? || @unlocking_bundler))
595
-
596
- if File.exist?(file) && lockfiles_equal?(@lockfile_contents, contents, preserve_unknown_sections)
597
- return if Bundler.frozen_bundle?
598
- SharedHelpers.filesystem_access(file) { FileUtils.touch(file) }
599
- return
600
- end
601
-
602
- if Bundler.frozen_bundle?
603
- Bundler.ui.error "Cannot write a changed lockfile while frozen."
604
- return
605
- end
606
-
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")
613
- end
614
- end
615
-
616
636
  def resolver
617
- @resolver ||= Resolver.new(resolution_base, gem_version_promoter, @most_specific_locked_platform)
637
+ @resolver ||= new_resolver(resolution_base)
618
638
  end
619
639
 
620
640
  def expanded_dependencies
@@ -632,8 +652,7 @@ module Bundler
632
652
  @resolution_base ||= begin
633
653
  last_resolve = converge_locked_specs
634
654
  remove_invalid_platforms!
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)
655
+ base = new_resolution_base(last_resolve: last_resolve, unlock: @unlocking_all || @gems_to_unlock)
637
656
  base = additional_base_requirements_to_prevent_downgrades(base)
638
657
  base = additional_base_requirements_to_force_updates(base)
639
658
  base
@@ -645,20 +664,12 @@ module Bundler
645
664
  end
646
665
 
647
666
  def materialize(dependencies)
648
- # Tracks potential endless loops trying to re-resolve.
649
- # TODO: Remove as dead code if not reports are received in a while
650
- incorrect_spec = nil
651
-
652
667
  specs = begin
653
668
  resolve.materialize(dependencies)
654
669
  rescue IncorrectLockfileDependencies => e
655
670
  raise if Bundler.frozen_bundle?
656
671
 
657
- spec = e.spec
658
- raise "Infinite loop while fixing lockfile dependencies" if incorrect_spec == spec
659
-
660
- incorrect_spec = spec
661
- reresolve_without([spec])
672
+ reresolve_without([e.spec])
662
673
  retry
663
674
  end
664
675
 
@@ -740,7 +751,6 @@ module Bundler
740
751
  def start_resolution
741
752
  local_platform_needed_for_resolvability = @most_specific_non_local_locked_platform && !@platforms.include?(Bundler.local_platform)
742
753
  @platforms << Bundler.local_platform if local_platform_needed_for_resolvability
743
- add_platform(Gem::Platform::RUBY) if RUBY_ENGINE == "truffleruby"
744
754
 
745
755
  result = SpecSet.new(resolver.start)
746
756
 
@@ -772,7 +782,7 @@ module Bundler
772
782
  end
773
783
 
774
784
  def precompute_source_requirements_for_indirect_dependencies?
775
- sources.non_global_rubygems_sources.all?(&:dependency_api_available?) && !sources.aggregate_global_source?
785
+ sources.non_global_rubygems_sources.all?(&:dependency_api_available?)
776
786
  end
777
787
 
778
788
  def current_platform_locked?
@@ -848,6 +858,7 @@ module Bundler
848
858
  [@missing_lockfile_dep, "your lockfile is missing \"#{@missing_lockfile_dep}\""],
849
859
  [@unlocking_bundler, "an update to the version of Bundler itself was requested"],
850
860
  [@locked_spec_with_missing_checksums, "your lockfile is missing a CHECKSUMS entry for \"#{@locked_spec_with_missing_checksums}\""],
861
+ [@locked_spec_with_empty_checksums, "your lockfile has an empty CHECKSUMS entry for \"#{@locked_spec_with_empty_checksums}\""],
851
862
  [@locked_spec_with_missing_deps, "your lockfile includes \"#{@locked_spec_with_missing_deps}\" but not some of its dependencies"],
852
863
  [@locked_spec_with_invalid_deps, "your lockfile does not satisfy dependencies of \"#{@locked_spec_with_invalid_deps}\""],
853
864
  ].select(&:first).map(&:last).join(", ")
@@ -907,13 +918,23 @@ module Bundler
907
918
  @locked_spec_with_invalid_deps = nil
908
919
  @locked_spec_with_missing_deps = nil
909
920
  @locked_spec_with_missing_checksums = nil
921
+ @locked_spec_with_empty_checksums = nil
910
922
 
911
923
  missing_deps = []
912
924
  missing_checksums = []
925
+ empty_checksums = []
913
926
  invalid = []
914
927
 
915
928
  @locked_specs.each do |s|
916
- missing_checksums << s if @locked_checksums && s.source.checksum_store.missing?(s)
929
+ if @locked_checksums
930
+ checksum_store = s.source.checksum_store
931
+
932
+ if checksum_store.missing?(s)
933
+ missing_checksums << s
934
+ elsif checksum_store.empty?(s)
935
+ empty_checksums << s
936
+ end
937
+ end
917
938
 
918
939
  validation = @locked_specs.validate_deps(s)
919
940
 
@@ -922,6 +943,7 @@ module Bundler
922
943
  end
923
944
 
924
945
  @locked_spec_with_missing_checksums = missing_checksums.first.name if missing_checksums.any?
946
+ @locked_spec_with_empty_checksums = empty_checksums.first.name if empty_checksums.any?
925
947
 
926
948
  if missing_deps.any?
927
949
  @locked_specs.delete(missing_deps)
@@ -951,7 +973,7 @@ module Bundler
951
973
  sources.all_sources.each do |source|
952
974
  # has to be done separately, because we want to keep the locked checksum
953
975
  # store for a source, even when doing a full update
954
- if @locked_checksums && @locked_gems && locked_source = @locked_gems.sources.find {|s| s == source && !s.equal?(source) }
976
+ if @locked_checksums && @locked_gems && locked_source = @originally_locked_sources.find {|s| s == source && !s.equal?(source) }
955
977
  source.checksum_store.merge!(locked_source.checksum_store)
956
978
  end
957
979
  # If the source is unlockable and the current command allows an unlock of
@@ -972,10 +994,11 @@ module Bundler
972
994
  @missing_lockfile_dep = nil
973
995
  @changed_dependencies = []
974
996
 
975
- current_dependencies.each do |dep|
997
+ @dependencies.each do |dep|
976
998
  if dep.source
977
999
  dep.source = sources.get(dep.source)
978
1000
  end
1001
+ next unless relevant_deps?(dep)
979
1002
 
980
1003
  name = dep.name
981
1004
 
@@ -1033,6 +1056,8 @@ module Bundler
1033
1056
 
1034
1057
  specs.each do |s|
1035
1058
  name = s.name
1059
+ next if @gems_to_unlock.include?(name)
1060
+
1036
1061
  dep = @dependencies.find {|d| s.satisfies?(d) }
1037
1062
  lockfile_source = s.source
1038
1063
 
@@ -1046,12 +1071,13 @@ module Bundler
1046
1071
 
1047
1072
  # Replace the locked dependency's source with the equivalent source from the Gemfile
1048
1073
  s.source = replacement_source || default_source
1074
+ next if s.source_changed?
1049
1075
 
1050
1076
  source = s.source
1051
1077
  next if @sources_to_unlock.include?(source.name)
1052
1078
 
1053
1079
  # Path sources have special logic
1054
- if source.instance_of?(Source::Path) || source.instance_of?(Source::Gemspec) || (source.instance_of?(Source::Git) && !@gems_to_unlock.include?(name) && deps.include?(dep))
1080
+ if source.is_a?(Source::Path)
1055
1081
  new_spec = source.specs[s].first
1056
1082
  if new_spec
1057
1083
  s.runtime_dependencies.replace(new_spec.runtime_dependencies)
@@ -1079,7 +1105,23 @@ module Bundler
1079
1105
  @source_requirements ||= find_source_requirements
1080
1106
  end
1081
1107
 
1108
+ def preload_git_source_worker
1109
+ @preload_git_source_worker ||= Bundler::Worker.new(5, "Git source preloading", ->(source, _) { source.specs })
1110
+ end
1111
+
1112
+ def preload_git_sources
1113
+ sources.git_sources.each {|source| preload_git_source_worker.enq(source) }
1114
+ ensure
1115
+ preload_git_source_worker.stop
1116
+ end
1117
+
1082
1118
  def find_source_requirements
1119
+ if Gem.ruby_version >= Gem::Version.new("3.3")
1120
+ # Ruby 3.2 has a bug that incorrectly triggers a circular dependency warning. This version will continue to
1121
+ # fetch git repositories one by one.
1122
+ preload_git_sources
1123
+ end
1124
+
1083
1125
  # Record the specs available in each gem's source, so that those
1084
1126
  # specs will be available later when the resolver knows where to
1085
1127
  # look for that gemspec (or its dependencies)
@@ -1131,9 +1173,9 @@ module Bundler
1131
1173
  end
1132
1174
 
1133
1175
  def additional_base_requirements_to_prevent_downgrades(resolution_base)
1134
- return resolution_base unless @locked_gems && !sources.expired_sources?(@locked_gems.sources)
1176
+ return resolution_base unless @locked_gems
1135
1177
  @originally_locked_specs.each do |locked_spec|
1136
- next if locked_spec.source.is_a?(Source::Path)
1178
+ next if locked_spec.source.is_a?(Source::Path) || locked_spec.source_changed?
1137
1179
 
1138
1180
  name = locked_spec.name
1139
1181
  next if @changed_dependencies.include?(name)
@@ -1145,7 +1187,7 @@ module Bundler
1145
1187
 
1146
1188
  def additional_base_requirements_to_force_updates(resolution_base)
1147
1189
  return resolution_base if @explicit_unlocks.empty?
1148
- full_update = dup_for_full_unlock.resolve
1190
+ full_update = SpecSet.new(new_resolver_for_full_update.start)
1149
1191
  @explicit_unlocks.each do |name|
1150
1192
  version = full_update.version_for(name)
1151
1193
  resolution_base.base_requirements[name] = Gem::Requirement.new("= #{version}") if version
@@ -1153,17 +1195,6 @@ module Bundler
1153
1195
  resolution_base
1154
1196
  end
1155
1197
 
1156
- def dup_for_full_unlock
1157
- unlocked_definition = self.class.new(@lockfile, @dependencies, @sources, true, @ruby_version, @optional_groups, @gemfiles)
1158
- unlocked_definition.source_requirements = source_requirements
1159
- unlocked_definition.gem_version_promoter.tap do |gvp|
1160
- gvp.level = gem_version_promoter.level
1161
- gvp.strict = gem_version_promoter.strict
1162
- gvp.pre = gem_version_promoter.pre
1163
- end
1164
- unlocked_definition
1165
- end
1166
-
1167
1198
  def remove_invalid_platforms!
1168
1199
  return if Bundler.frozen_bundle?
1169
1200
 
@@ -1182,5 +1213,22 @@ module Bundler
1182
1213
  def source_map
1183
1214
  @source_map ||= SourceMap.new(sources, dependencies, @locked_specs)
1184
1215
  end
1216
+
1217
+ def new_resolver_for_full_update
1218
+ new_resolver(unlocked_resolution_base)
1219
+ end
1220
+
1221
+ def unlocked_resolution_base
1222
+ new_resolution_base(last_resolve: SpecSet.new([]), unlock: true)
1223
+ end
1224
+
1225
+ def new_resolution_base(last_resolve:, unlock:)
1226
+ new_resolution_platforms = @current_platform_missing ? @new_platforms + [Bundler.local_platform] : @new_platforms
1227
+ Resolver::Base.new(source_requirements, expanded_dependencies, last_resolve, @platforms, locked_specs: @originally_locked_specs, unlock: unlock, prerelease: gem_version_promoter.pre?, prefer_local: @prefer_local, new_platforms: new_resolution_platforms)
1228
+ end
1229
+
1230
+ def new_resolver(base)
1231
+ Resolver.new(base, gem_version_promoter, @most_specific_locked_platform)
1232
+ end
1185
1233
  end
1186
1234
  end
@@ -1,69 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "shared_helpers"
4
- Bundler::SharedHelpers.major_deprecation 2, "Bundler no longer integrates with " \
4
+ Bundler::SharedHelpers.feature_removed! "Bundler no longer integrates with " \
5
5
  "Capistrano, but Capistrano provides its own integration with " \
6
6
  "Bundler via the capistrano-bundler gem. Use it instead."
7
-
8
- module Bundler
9
- class Deployment
10
- def self.define_task(context, task_method = :task, opts = {})
11
- if defined?(Capistrano) && context.is_a?(Capistrano::Configuration)
12
- context_name = "capistrano"
13
- role_default = "{:except => {:no_release => true}}"
14
- error_type = ::Capistrano::CommandError
15
- else
16
- context_name = "vlad"
17
- role_default = "[:app]"
18
- error_type = ::Rake::CommandFailedError
19
- end
20
-
21
- roles = context.fetch(:bundle_roles, false)
22
- opts[:roles] = roles if roles
23
-
24
- context.send :namespace, :bundle do
25
- send :desc, <<-DESC
26
- Install the current Bundler environment. By default, gems will be \
27
- installed to the shared/bundle path. Gems in the development and \
28
- test group will not be installed. The install command is executed \
29
- with the --deployment and --quiet flags. If the bundle cmd cannot \
30
- be found then you can override the bundle_cmd variable to specify \
31
- which one it should use. The base path to the app is fetched from \
32
- the :latest_release variable. Set it for custom deploy layouts.
33
-
34
- You can override any of these defaults by setting the variables shown below.
35
-
36
- N.B. bundle_roles must be defined before you require 'bundler/#{context_name}' \
37
- in your deploy.rb file.
38
-
39
- set :bundle_gemfile, "Gemfile"
40
- set :bundle_dir, File.join(fetch(:shared_path), 'bundle')
41
- set :bundle_flags, "--deployment --quiet"
42
- set :bundle_without, [:development, :test]
43
- set :bundle_with, [:mysql]
44
- set :bundle_cmd, "bundle" # e.g. "/opt/ruby/bin/bundle"
45
- set :bundle_roles, #{role_default} # e.g. [:app, :batch]
46
- DESC
47
- send task_method, :install, opts do
48
- bundle_cmd = context.fetch(:bundle_cmd, "bundle")
49
- bundle_flags = context.fetch(:bundle_flags, "--deployment --quiet")
50
- bundle_dir = context.fetch(:bundle_dir, File.join(context.fetch(:shared_path), "bundle"))
51
- bundle_gemfile = context.fetch(:bundle_gemfile, "Gemfile")
52
- bundle_without = [*context.fetch(:bundle_without, [:development, :test])].compact
53
- bundle_with = [*context.fetch(:bundle_with, [])].compact
54
- app_path = context.fetch(:latest_release)
55
- if app_path.to_s.empty?
56
- raise error_type.new("Cannot detect current release path - make sure you have deployed at least once.")
57
- end
58
- args = ["--gemfile #{File.join(app_path, bundle_gemfile)}"]
59
- args << "--path #{bundle_dir}" unless bundle_dir.to_s.empty?
60
- args << bundle_flags.to_s
61
- args << "--without #{bundle_without.join(" ")}" unless bundle_without.empty?
62
- args << "--with #{bundle_with.join(" ")}" unless bundle_with.empty?
63
-
64
- run "cd #{app_path} && #{bundle_cmd} install #{args.join(" ")}"
65
- end
66
- end
67
- end
68
- end
69
- end
@@ -26,7 +26,7 @@ module Bundler
26
26
  end
27
27
  a, b, c, d, e = *words
28
28
  (16..79).each do |i|
29
- w[i] = SHA1_MASK & rotate((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]), 1)
29
+ w[i] = SHA1_MASK & rotate(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1)
30
30
  end
31
31
  0.upto(79) do |i|
32
32
  case i
data/lib/bundler/dsl.rb CHANGED
@@ -9,8 +9,9 @@ module Bundler
9
9
 
10
10
  def self.evaluate(gemfile, lockfile, unlock)
11
11
  builder = new
12
+ builder.lockfile(lockfile)
12
13
  builder.eval_gemfile(gemfile)
13
- builder.to_definition(lockfile, unlock)
14
+ builder.to_definition(builder.lockfile_path, unlock)
14
15
  end
15
16
 
16
17
  VALID_PLATFORMS = Bundler::CurrentRuby::PLATFORM_MAP.keys.freeze
@@ -38,6 +39,7 @@ module Bundler
38
39
  @gemspecs = []
39
40
  @gemfile = nil
40
41
  @gemfiles = []
42
+ @lockfile = nil
41
43
  add_git_sources
42
44
  end
43
45
 
@@ -101,6 +103,15 @@ module Bundler
101
103
  add_dependency(name, version, options)
102
104
  end
103
105
 
106
+ # For usage in Dsl.evaluate, since lockfile is used as part of the Gemfile.
107
+ def lockfile_path
108
+ @lockfile
109
+ end
110
+
111
+ def lockfile(file)
112
+ @lockfile = file
113
+ end
114
+
104
115
  def source(source, *args, &blk)
105
116
  options = args.last.is_a?(Hash) ? args.pop.dup : {}
106
117
  options = normalize_hash(options)
@@ -175,6 +186,7 @@ module Bundler
175
186
 
176
187
  def to_definition(lockfile, unlock)
177
188
  check_primary_source_safety
189
+ lockfile = @lockfile unless @lockfile.nil?
178
190
  Definition.new(lockfile, @dependencies, @sources, unlock, @ruby_version, @optional_groups, @gemfiles)
179
191
  end
180
192
 
@@ -290,7 +302,7 @@ module Bundler
290
302
  @dependencies.delete(current)
291
303
  elsif dep.gemspec_dev_dep?
292
304
  return
293
- elsif current.source != dep.source
305
+ elsif current.source.to_s != dep.source.to_s
294
306
  raise GemfileError, "You cannot specify the same gem twice coming from different sources.\n" \
295
307
  "You specified that #{name} (#{dep.requirement}) should come from " \
296
308
  "#{current.source || "an unspecified source"} and #{dep.source}\n"
@@ -411,7 +423,13 @@ module Bundler
411
423
  next if VALID_PLATFORMS.include?(p)
412
424
  raise GemfileError, "`#{p}` is not a valid platform. The available options are: #{VALID_PLATFORMS.inspect}"
413
425
  end
414
- deprecate_legacy_windows_platforms(platforms)
426
+
427
+ windows_platforms = platforms.select {|pl| pl.to_s.match?(/mingw|mswin/) }
428
+ if windows_platforms.any?
429
+ windows_platforms = windows_platforms.map! {|pl| ":#{pl}" }.join(", ")
430
+ deprecated_message = "Platform #{windows_platforms} will be removed in the future. Please use platform :windows instead."
431
+ Bundler::SharedHelpers.feature_deprecated! deprecated_message
432
+ end
415
433
 
416
434
  # Save sources passed in a key
417
435
  if opts.key?("source")
@@ -477,14 +495,10 @@ module Bundler
477
495
  def normalize_source(source)
478
496
  case source
479
497
  when :gemcutter, :rubygems, :rubyforge
480
- message =
481
- "The source :#{source} is deprecated because HTTP requests are insecure.\n" \
482
- "Please change your source to 'https://rubygems.org' if possible, or 'http://rubygems.org' if not."
483
498
  removed_message =
484
499
  "The source :#{source} is disallowed because HTTP requests are insecure.\n" \
485
500
  "Please change your source to 'https://rubygems.org' if possible, or 'http://rubygems.org' if not."
486
- Bundler::SharedHelpers.major_deprecation 2, message, removed_message: removed_message
487
- "http://rubygems.org"
501
+ Bundler::SharedHelpers.feature_removed! removed_message
488
502
  when String
489
503
  source
490
504
  else
@@ -492,16 +506,6 @@ module Bundler
492
506
  end
493
507
  end
494
508
 
495
- def deprecate_legacy_windows_platforms(platforms)
496
- windows_platforms = platforms.select {|pl| pl.to_s.match?(/mingw|mswin/) }
497
- return if windows_platforms.empty?
498
-
499
- windows_platforms = windows_platforms.map! {|pl| ":#{pl}" }.join(", ")
500
- message = "Platform #{windows_platforms} is deprecated. Please use platform :windows instead."
501
- removed_message = "Platform #{windows_platforms} has been removed. Please use platform :windows instead."
502
- Bundler::SharedHelpers.major_deprecation 2, message, removed_message: removed_message
503
- end
504
-
505
509
  def check_path_source_safety
506
510
  return if @sources.global_path_source.nil?
507
511
 
@@ -513,7 +517,7 @@ module Bundler
513
517
  " gem 'rails'\n" \
514
518
  " end\n\n"
515
519
 
516
- SharedHelpers.major_deprecation(2, msg.strip)
520
+ SharedHelpers.feature_removed! msg.strip
517
521
  end
518
522
 
519
523
  def check_rubygems_source_safety
@@ -521,24 +525,10 @@ module Bundler
521
525
  end
522
526
 
523
527
  def multiple_global_source_warning
524
- if Bundler.feature_flag.bundler_4_mode?
525
- msg = "This Gemfile contains multiple global sources. " \
526
- "Each source after the first must include a block to indicate which gems " \
527
- "should come from that source"
528
- raise GemfileEvalError, msg
529
- else
530
- message =
531
- "Your Gemfile contains multiple global sources. " \
532
- "Using `source` more than once without a block is a security risk, and " \
533
- "may result in installing unexpected gems. To resolve this warning, use " \
534
- "a block to indicate which gems should come from the secondary source."
535
- removed_message =
536
- "Your Gemfile contains multiple global sources. " \
537
- "Using `source` more than once without a block is a security risk, and " \
538
- "may result in installing unexpected gems. To resolve this error, use " \
539
- "a block to indicate which gems should come from the secondary source."
540
- Bundler::SharedHelpers.major_deprecation 2, message, removed_message: removed_message
541
- end
528
+ msg = "This Gemfile contains multiple global sources. " \
529
+ "Each source after the first must include a block to indicate which gems " \
530
+ "should come from that source"
531
+ raise GemfileEvalError, msg
542
532
  end
543
533
 
544
534
  class DSLError < GemfileError
@@ -6,6 +6,7 @@ module Bundler
6
6
  BUNDLER_KEYS = %w[
7
7
  BUNDLE_BIN_PATH
8
8
  BUNDLE_GEMFILE
9
+ BUNDLE_LOCKFILE
9
10
  BUNDLER_VERSION
10
11
  BUNDLER_SETUP
11
12
  GEM_HOME