bundler 2.6.9 → 4.0.10

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 (190) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +2212 -1879
  3. data/README.md +11 -11
  4. data/bundler.gemspec +5 -5
  5. data/lib/bundler/build_metadata.rb +10 -11
  6. data/lib/bundler/capistrano.rb +1 -19
  7. data/lib/bundler/checksum.rb +6 -0
  8. data/lib/bundler/cli/add.rb +10 -0
  9. data/lib/bundler/cli/cache.rb +1 -12
  10. data/lib/bundler/cli/common.rb +21 -4
  11. data/lib/bundler/cli/config.rb +1 -2
  12. data/lib/bundler/cli/console.rb +5 -0
  13. data/lib/bundler/cli/exec.rb +29 -4
  14. data/lib/bundler/cli/gem.rb +89 -63
  15. data/lib/bundler/cli/install.rb +15 -90
  16. data/lib/bundler/cli/issue.rb +2 -2
  17. data/lib/bundler/cli/list.rb +33 -2
  18. data/lib/bundler/cli/lock.rb +5 -5
  19. data/lib/bundler/cli/outdated.rb +1 -1
  20. data/lib/bundler/cli/plugin.rb +5 -1
  21. data/lib/bundler/cli/pristine.rb +5 -1
  22. data/lib/bundler/cli/show.rb +3 -7
  23. data/lib/bundler/cli/update.rb +5 -5
  24. data/lib/bundler/cli.rb +162 -127
  25. data/lib/bundler/compact_index_client.rb +1 -6
  26. data/lib/bundler/current_ruby.rb +17 -5
  27. data/lib/bundler/definition.rb +199 -117
  28. data/lib/bundler/dependency.rb +1 -1
  29. data/lib/bundler/deployment.rb +1 -64
  30. data/lib/bundler/digest.rb +1 -1
  31. data/lib/bundler/dsl.rb +48 -48
  32. data/lib/bundler/environment_preserver.rb +1 -0
  33. data/lib/bundler/errors.rb +1 -5
  34. data/lib/bundler/feature_flag.rb +5 -35
  35. data/lib/bundler/fetcher/compact_index.rb +1 -1
  36. data/lib/bundler/fetcher/dependency.rb +9 -2
  37. data/lib/bundler/fetcher/downloader.rb +33 -8
  38. data/lib/bundler/fetcher/gem_remote_fetcher.rb +6 -0
  39. data/lib/bundler/fetcher.rb +49 -19
  40. data/lib/bundler/friendly_errors.rb +4 -3
  41. data/lib/bundler/index.rb +7 -9
  42. data/lib/bundler/injector.rb +1 -2
  43. data/lib/bundler/inline.rb +9 -1
  44. data/lib/bundler/installer/gem_installer.rb +14 -11
  45. data/lib/bundler/installer/parallel_installer.rb +63 -17
  46. data/lib/bundler/installer.rb +6 -19
  47. data/lib/bundler/lazy_specification.rb +47 -20
  48. data/lib/bundler/lockfile_generator.rb +1 -1
  49. data/lib/bundler/lockfile_parser.rb +11 -5
  50. data/lib/bundler/man/bundle-add.1 +1 -1
  51. data/lib/bundler/man/bundle-binstubs.1 +3 -6
  52. data/lib/bundler/man/bundle-binstubs.1.ronn +4 -6
  53. data/lib/bundler/man/bundle-cache.1 +2 -14
  54. data/lib/bundler/man/bundle-cache.1.ronn +1 -14
  55. data/lib/bundler/man/bundle-check.1 +2 -5
  56. data/lib/bundler/man/bundle-check.1.ronn +0 -5
  57. data/lib/bundler/man/bundle-clean.1 +1 -1
  58. data/lib/bundler/man/bundle-config.1 +206 -148
  59. data/lib/bundler/man/bundle-config.1.ronn +135 -118
  60. data/lib/bundler/man/bundle-console.1 +1 -1
  61. data/lib/bundler/man/bundle-doctor.1 +43 -4
  62. data/lib/bundler/man/bundle-doctor.1.ronn +48 -4
  63. data/lib/bundler/man/bundle-env.1 +1 -1
  64. data/lib/bundler/man/bundle-exec.1 +2 -5
  65. data/lib/bundler/man/bundle-exec.1.ronn +1 -5
  66. data/lib/bundler/man/bundle-fund.1 +1 -1
  67. data/lib/bundler/man/bundle-gem.1 +64 -44
  68. data/lib/bundler/man/bundle-gem.1.ronn +10 -9
  69. data/lib/bundler/man/bundle-help.1 +1 -1
  70. data/lib/bundler/man/bundle-info.1 +1 -1
  71. data/lib/bundler/man/bundle-init.1 +1 -1
  72. data/lib/bundler/man/bundle-install.1 +16 -59
  73. data/lib/bundler/man/bundle-install.1.ronn +27 -108
  74. data/lib/bundler/man/bundle-issue.1 +1 -1
  75. data/lib/bundler/man/bundle-licenses.1 +1 -1
  76. data/lib/bundler/man/bundle-list.1 +6 -1
  77. data/lib/bundler/man/bundle-list.1.ronn +5 -0
  78. data/lib/bundler/man/bundle-lock.1 +1 -1
  79. data/lib/bundler/man/bundle-open.1 +1 -1
  80. data/lib/bundler/man/bundle-outdated.1 +1 -1
  81. data/lib/bundler/man/bundle-platform.1 +1 -1
  82. data/lib/bundler/man/bundle-plugin.1 +33 -15
  83. data/lib/bundler/man/bundle-plugin.1.ronn +36 -15
  84. data/lib/bundler/man/bundle-pristine.1 +1 -1
  85. data/lib/bundler/man/bundle-remove.1 +2 -8
  86. data/lib/bundler/man/bundle-remove.1.ronn +1 -8
  87. data/lib/bundler/man/bundle-show.1 +2 -5
  88. data/lib/bundler/man/bundle-show.1.ronn +0 -4
  89. data/lib/bundler/man/bundle-update.1 +5 -5
  90. data/lib/bundler/man/bundle-update.1.ronn +4 -4
  91. data/lib/bundler/man/bundle-version.1 +1 -1
  92. data/lib/bundler/man/bundle.1 +1 -10
  93. data/lib/bundler/man/bundle.1.ronn +0 -9
  94. data/lib/bundler/man/gemfile.5 +32 -1
  95. data/lib/bundler/man/gemfile.5.ronn +28 -0
  96. data/lib/bundler/man/index.txt +0 -2
  97. data/lib/bundler/match_platform.rb +31 -12
  98. data/lib/bundler/materialization.rb +3 -3
  99. data/lib/bundler/plugin/api/source.rb +8 -0
  100. data/lib/bundler/plugin/index.rb +6 -0
  101. data/lib/bundler/plugin/installer.rb +2 -11
  102. data/lib/bundler/plugin/source_list.rb +1 -1
  103. data/lib/bundler/plugin.rb +7 -4
  104. data/lib/bundler/resolver/package.rb +2 -1
  105. data/lib/bundler/resolver/strategy.rb +6 -3
  106. data/lib/bundler/resolver.rb +20 -4
  107. data/lib/bundler/retry.rb +30 -4
  108. data/lib/bundler/ruby_dsl.rb +17 -12
  109. data/lib/bundler/ruby_version.rb +1 -3
  110. data/lib/bundler/rubygems_ext.rb +117 -121
  111. data/lib/bundler/rubygems_gem_installer.rb +5 -4
  112. data/lib/bundler/rubygems_integration.rb +13 -12
  113. data/lib/bundler/runtime.rb +14 -3
  114. data/lib/bundler/self_manager.rb +34 -43
  115. data/lib/bundler/settings/validator.rb +5 -21
  116. data/lib/bundler/settings.rb +17 -32
  117. data/lib/bundler/shared_helpers.rb +12 -18
  118. data/lib/bundler/source/gemspec.rb +4 -0
  119. data/lib/bundler/source/git/git_proxy.rb +55 -29
  120. data/lib/bundler/source/git.rb +2 -3
  121. data/lib/bundler/source/path.rb +12 -7
  122. data/lib/bundler/source/rubygems.rb +59 -43
  123. data/lib/bundler/source/rubygems_aggregate.rb +4 -1
  124. data/lib/bundler/source.rb +3 -1
  125. data/lib/bundler/source_list.rb +5 -50
  126. data/lib/bundler/source_map.rb +8 -7
  127. data/lib/bundler/spec_set.rb +9 -14
  128. data/lib/bundler/stub_specification.rb +1 -0
  129. data/lib/bundler/templates/Executable +0 -11
  130. data/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt +7 -129
  131. data/lib/bundler/templates/newgem/Cargo.toml.tt +6 -0
  132. data/lib/bundler/templates/newgem/Rakefile.tt +5 -0
  133. data/lib/bundler/templates/newgem/circleci/config.yml.tt +12 -0
  134. data/lib/bundler/templates/newgem/ext/newgem/Cargo.toml.tt +8 -1
  135. data/lib/bundler/templates/newgem/ext/newgem/build.rs.tt +5 -0
  136. data/lib/bundler/templates/newgem/ext/newgem/extconf-go.rb.tt +11 -0
  137. data/lib/bundler/templates/newgem/ext/newgem/go.mod.tt +5 -0
  138. data/lib/bundler/templates/newgem/ext/newgem/newgem-go.c.tt +2 -0
  139. data/lib/bundler/templates/newgem/ext/newgem/newgem.go.tt +31 -0
  140. data/lib/bundler/templates/newgem/ext/newgem/src/lib.rs.tt +13 -2
  141. data/lib/bundler/templates/newgem/github/workflows/build-gems.yml.tt +69 -0
  142. data/lib/bundler/templates/newgem/github/workflows/main.yml.tt +12 -1
  143. data/lib/bundler/templates/newgem/gitlab-ci.yml.tt +9 -0
  144. data/lib/bundler/templates/newgem/lib/newgem.rb.tt +1 -1
  145. data/lib/bundler/templates/newgem/newgem.gemspec.tt +10 -10
  146. data/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt +8 -0
  147. data/lib/bundler/templates/newgem/test/minitest/test_newgem.rb.tt +6 -0
  148. data/lib/bundler/ui/shell.rb +12 -8
  149. data/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +26 -23
  150. data/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +1 -1
  151. data/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +50 -6
  152. data/lib/bundler/vendor/fileutils/lib/fileutils.rb +57 -52
  153. data/lib/bundler/vendor/net-http-persistent/README.rdoc +1 -1
  154. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/timed_stack_multi.rb +2 -1
  155. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +84 -42
  156. data/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +42 -6
  157. data/lib/bundler/vendor/thor/lib/thor/parser/options.rb +1 -1
  158. data/lib/bundler/vendor/thor/lib/thor/runner.rb +2 -2
  159. data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +3 -7
  160. data/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
  161. data/lib/bundler/vendor/thor/lib/thor.rb +1 -1
  162. data/lib/bundler/vendor/uri/lib/uri/common.rb +57 -15
  163. data/lib/bundler/vendor/uri/lib/uri/file.rb +1 -1
  164. data/lib/bundler/vendor/uri/lib/uri/generic.rb +34 -21
  165. data/lib/bundler/vendor/uri/lib/uri/http.rb +12 -0
  166. data/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb +9 -8
  167. data/lib/bundler/vendor/uri/lib/uri/version.rb +2 -2
  168. data/lib/bundler/version.rb +10 -2
  169. data/lib/bundler/vlad.rb +1 -14
  170. data/lib/bundler/worker.rb +12 -4
  171. data/lib/bundler.rb +20 -40
  172. metadata +13 -25
  173. data/lib/bundler/cli/inject.rb +0 -60
  174. data/lib/bundler/cli/viz.rb +0 -31
  175. data/lib/bundler/gem_helpers.rb +0 -144
  176. data/lib/bundler/graph.rb +0 -152
  177. data/lib/bundler/man/bundle-inject.1 +0 -31
  178. data/lib/bundler/man/bundle-inject.1.ronn +0 -32
  179. data/lib/bundler/man/bundle-viz.1 +0 -30
  180. data/lib/bundler/man/bundle-viz.1.ronn +0 -36
  181. data/lib/bundler/similarity_detector.rb +0 -63
  182. data/lib/bundler/templates/Executable.bundler +0 -109
  183. data/lib/bundler/vendor/connection_pool/.document +0 -1
  184. data/lib/bundler/vendor/fileutils/.document +0 -1
  185. data/lib/bundler/vendor/net-http-persistent/.document +0 -1
  186. data/lib/bundler/vendor/pub_grub/.document +0 -1
  187. data/lib/bundler/vendor/securerandom/.document +0 -1
  188. data/lib/bundler/vendor/thor/.document +0 -1
  189. data/lib/bundler/vendor/tsort/.document +0 -1
  190. data/lib/bundler/vendor/uri/.document +0 -1
@@ -113,7 +113,7 @@ module Bundler
113
113
 
114
114
  return if definition.dependencies.empty?
115
115
 
116
- plugins = definition.dependencies.map(&:name).reject {|p| index.installed? p }
116
+ plugins = definition.dependencies.map(&:name)
117
117
  installed_specs = Installer.new.install_definition(definition)
118
118
 
119
119
  save_plugins plugins, installed_specs, builder.inferred_plugins
@@ -220,7 +220,7 @@ module Bundler
220
220
  #
221
221
  # @param [String] event
222
222
  def hook(event, *args, &arg_blk)
223
- return unless Bundler.feature_flag.plugins?
223
+ return unless Bundler.settings[:plugins]
224
224
  unless Events.defined_event?(event)
225
225
  raise ArgumentError, "Event '#{event}' not defined in Bundler::Plugin::Events"
226
226
  end
@@ -253,10 +253,13 @@ module Bundler
253
253
  # @param [Array<String>] names of inferred source plugins that can be ignored
254
254
  def save_plugins(plugins, specs, optional_plugins = [])
255
255
  plugins.each do |name|
256
- next if index.installed?(name)
257
-
258
256
  spec = specs[name]
259
257
 
258
+ # It's possible that the `plugin` found in the Gemfile don't appear in the specs. For instance when
259
+ # calling `BUNDLE_WITHOUT=default bundle install`, the plugins will not get installed.
260
+ next if spec.nil?
261
+ next if index.up_to_date?(spec)
262
+
260
263
  save_plugin(name, spec, optional_plugins.include?(name))
261
264
  end
262
265
  end
@@ -21,6 +21,7 @@ module Bundler
21
21
  @locked_version = locked_specs.version_for(name)
22
22
  @unlock = unlock
23
23
  @dependency = dependency || Dependency.new(name, @locked_version)
24
+ @platforms |= [Gem::Platform::RUBY] if @dependency.default_force_ruby_platform
24
25
  @top_level = !dependency.nil?
25
26
  @prerelease = @dependency.prerelease? || @locked_version&.prerelease? || prerelease ? :consider_first : :ignore
26
27
  @prefer_local = prefer_local
@@ -30,7 +31,7 @@ module Bundler
30
31
  def platform_specs(specs)
31
32
  platforms.map do |platform|
32
33
  prefer_locked = @new_platforms.include?(platform) ? false : !unlock?
33
- GemHelpers.select_best_platform_match(specs, platform, prefer_locked: prefer_locked)
34
+ MatchPlatform.select_best_platform_match(specs, platform, prefer_locked: prefer_locked)
34
35
  end
35
36
  end
36
37
 
@@ -5,6 +5,7 @@ module Bundler
5
5
  class Strategy
6
6
  def initialize(source)
7
7
  @source = source
8
+ @package_priority_cache = {}
8
9
  end
9
10
 
10
11
  def next_package_and_version(unsatisfied)
@@ -17,10 +18,12 @@ module Bundler
17
18
 
18
19
  def next_term_to_try_from(unsatisfied)
19
20
  unsatisfied.min_by do |package, range|
20
- matching_versions = @source.versions_for(package, range)
21
- higher_versions = @source.versions_for(package, range.upper_invert)
21
+ @package_priority_cache[[package, range]] ||= begin
22
+ matching_versions = @source.versions_for(package, range)
23
+ higher_versions = @source.versions_for(package, range.upper_invert)
22
24
 
23
- [matching_versions.count <= 1 ? 0 : 1, higher_versions.count]
25
+ [matching_versions.count <= 1 ? 0 : 1, higher_versions.count]
26
+ end
24
27
  end
25
28
  end
26
29
 
@@ -14,8 +14,6 @@ module Bundler
14
14
  require_relative "resolver/root"
15
15
  require_relative "resolver/strategy"
16
16
 
17
- include GemHelpers
18
-
19
17
  def initialize(base, gem_version_promoter, most_specific_locked_platform = nil)
20
18
  @source_requirements = base.source_requirements
21
19
  @base = base
@@ -167,7 +165,7 @@ module Bundler
167
165
  PubGrub::VersionConstraint.new(package, range: range)
168
166
  end
169
167
 
170
- def versions_for(package, range=VersionRange.any)
168
+ def versions_for(package, range = VersionRange.any)
171
169
  range.select_versions(@sorted_versions[package])
172
170
  end
173
171
 
@@ -273,7 +271,7 @@ module Bundler
273
271
  next groups if platform_specs.all?(&:empty?)
274
272
  end
275
273
 
276
- ruby_specs = select_best_platform_match(specs, Gem::Platform::RUBY)
274
+ ruby_specs = MatchPlatform.select_best_platform_match(specs, Gem::Platform::RUBY)
277
275
  ruby_group = Resolver::SpecGroup.new(ruby_specs)
278
276
 
279
277
  unless ruby_group.empty?
@@ -355,9 +353,27 @@ module Bundler
355
353
  message << "\n#{other_specs_matching_message(specs, matching_part)}"
356
354
  end
357
355
 
356
+ if specs_matching_requirement.any? && (hint = platform_mismatch_hint)
357
+ message << "\n\n#{hint}"
358
+ end
359
+
358
360
  raise GemNotFound, message
359
361
  end
360
362
 
363
+ def platform_mismatch_hint
364
+ locked_platforms = Bundler.locked_gems&.platforms
365
+ return unless locked_platforms
366
+
367
+ local_platform = Bundler.local_platform
368
+ return if locked_platforms.include?(local_platform)
369
+ return if locked_platforms.any? {|p| p == Gem::Platform::RUBY }
370
+
371
+ "Your current platform (#{local_platform}) is not included in the lockfile's platforms (#{locked_platforms.join(", ")}). " \
372
+ "Add the current platform to the lockfile with\n`bundle lock --add-platform #{local_platform}` and try again."
373
+ rescue GemfileNotFound
374
+ nil
375
+ end
376
+
361
377
  def filtered_versions_for(package)
362
378
  @gem_version_promoter.filter_versions(package, @all_versions[package])
363
379
  end
data/lib/bundler/retry.rb CHANGED
@@ -6,6 +6,8 @@ module Bundler
6
6
  attr_accessor :name, :total_runs, :current_run
7
7
 
8
8
  class << self
9
+ attr_accessor :default_base_delay
10
+
9
11
  def default_attempts
10
12
  default_retries + 1
11
13
  end
@@ -16,11 +18,17 @@ module Bundler
16
18
  end
17
19
  end
18
20
 
19
- def initialize(name, exceptions = nil, retries = self.class.default_retries)
21
+ # Set default base delay for exponential backoff
22
+ self.default_base_delay = 1.0
23
+
24
+ def initialize(name, exceptions = nil, retries = self.class.default_retries, opts = {})
20
25
  @name = name
21
26
  @retries = retries
22
27
  @exceptions = Array(exceptions) || []
23
28
  @total_runs = @retries + 1 # will run once, then upto attempts.times
29
+ @base_delay = opts[:base_delay] || self.class.default_base_delay
30
+ @max_delay = opts[:max_delay] || 60.0
31
+ @jitter = opts[:jitter] || 0.5
24
32
  end
25
33
 
26
34
  def attempt(&block)
@@ -48,9 +56,27 @@ module Bundler
48
56
  Bundler.ui.info "" unless Bundler.ui.debug?
49
57
  raise e
50
58
  end
51
- return true unless name
52
- Bundler.ui.info "" unless Bundler.ui.debug? # Add new line in case dots preceded this
53
- Bundler.ui.warn "Retrying #{name} due to error (#{current_run.next}/#{total_runs}): #{e.class} #{e.message}", true
59
+ if name
60
+ Bundler.ui.info "" unless Bundler.ui.debug? # Add new line in case dots preceded this
61
+ Bundler.ui.warn "Retrying #{name} due to error (#{current_run.next}/#{total_runs}): #{e.class} #{e.message}", true
62
+ end
63
+ backoff_sleep if @base_delay > 0
64
+ true
65
+ end
66
+
67
+ def backoff_sleep
68
+ # Exponential backoff: delay = base_delay * 2^(attempt - 1)
69
+ # Add jitter to prevent thundering herd: random value between 0 and jitter seconds
70
+ delay = @base_delay * (2**(@current_run - 1))
71
+ delay = [@max_delay, delay].min
72
+ jitter_amount = rand * @jitter
73
+ total_delay = delay + jitter_amount
74
+ Bundler.ui.debug "Sleeping for #{total_delay.round(2)} seconds before retry"
75
+ sleep(total_delay)
76
+ end
77
+
78
+ def sleep(duration)
79
+ Kernel.sleep(duration)
54
80
  end
55
81
 
56
82
  def keep_trying?
@@ -42,21 +42,26 @@ module Bundler
42
42
  # Loads the file relative to the dirname of the Gemfile itself.
43
43
  def normalize_ruby_file(filename)
44
44
  file_content = Bundler.read_file(gemfile.dirname.join(filename))
45
- # match "ruby-3.2.2", ruby = "3.2.2" or "ruby 3.2.2" capturing version string up to the first space or comment
46
- if /^ # Start of line
47
- ruby # Literal "ruby"
48
- [\s-]* # Optional whitespace or hyphens (for "ruby-3.2.2" format)
49
- (?:=\s*)? # Optional equals sign with whitespace (for ruby = "3.2.2" format)
50
- "? # Optional opening quote
51
- ( # Start capturing group
52
- [^\s#"]+ # One or more chars that aren't spaces, #, or quotes
53
- ) # End capturing group
54
- "? # Optional closing quote
55
- /x.match(file_content)
56
- $1
45
+ # match "ruby-3.2.2", ruby = "3.2.2", ruby = '3.2.2' or "ruby 3.2.2" capturing version string up to the first space or comment
46
+ version_match = /^ # Start of line
47
+ ruby # Literal "ruby"
48
+ [\s-]* # Optional whitespace or hyphens (for "ruby-3.2.2" format)
49
+ (?:=\s*)? # Optional equals sign with whitespace (for ruby = "3.2.2" format)
50
+ (?:
51
+ "([^"]+)" # Double quoted version
52
+ |
53
+ '([^']+)' # Single quoted version
54
+ |
55
+ ([^\s#"']+) # Unquoted version
56
+ )
57
+ /x.match(file_content)
58
+ if version_match
59
+ version_match[1] || version_match[2] || version_match[3]
57
60
  else
58
61
  file_content.strip
59
62
  end
63
+ rescue Errno::ENOENT
64
+ raise GemfileError, "Could not find version file #{filename}"
60
65
  end
61
66
  end
62
67
  end
@@ -43,7 +43,6 @@ module Bundler
43
43
 
44
44
  def to_s(versions = self.versions)
45
45
  output = String.new("ruby #{versions_string(versions)}")
46
- output << "p#{patchlevel}" if patchlevel && patchlevel != "-1"
47
46
  output << " (#{engine} #{versions_string(engine_versions)})" unless engine == "ruby"
48
47
 
49
48
  output
@@ -72,8 +71,7 @@ module Bundler
72
71
  def ==(other)
73
72
  versions == other.versions &&
74
73
  engine == other.engine &&
75
- engine_versions == other.engine_versions &&
76
- patchlevel == other.patchlevel
74
+ engine_versions == other.engine_versions
77
75
  end
78
76
 
79
77
  def host
@@ -13,15 +13,6 @@ require "rubygems" unless defined?(Gem)
13
13
  # `Gem::Source` from the redefined `Gem::Specification#source`.
14
14
  require "rubygems/source"
15
15
 
16
- # Cherry-pick fixes to `Gem.ruby_version` to be useful for modern Bundler
17
- # versions and ignore patchlevels
18
- # (https://github.com/rubygems/rubygems/pull/5472,
19
- # https://github.com/rubygems/rubygems/pull/5486). May be removed once RubyGems
20
- # 3.3.12 support is dropped.
21
- unless Gem.ruby_version.to_s == RUBY_VERSION || RUBY_PATCHLEVEL == -1
22
- Gem.instance_variable_set(:@ruby_version, Gem::Version.new(RUBY_VERSION))
23
- end
24
-
25
16
  module Gem
26
17
  # Can be removed once RubyGems 3.5.11 support is dropped
27
18
  unless Gem.respond_to?(:freebsd_platform?)
@@ -61,81 +52,122 @@ module Gem
61
52
  require "rubygems/platform"
62
53
 
63
54
  class Platform
64
- JAVA = Gem::Platform.new("java")
65
- MSWIN = Gem::Platform.new("mswin32")
66
- MSWIN64 = Gem::Platform.new("mswin64")
67
- MINGW = Gem::Platform.new("x86-mingw32")
68
- X64_MINGW = [Gem::Platform.new("x64-mingw32"),
69
- Gem::Platform.new("x64-mingw-ucrt")].freeze
70
- UNIVERSAL_MINGW = Gem::Platform.new("universal-mingw")
71
- WINDOWS = [MSWIN, MSWIN64, UNIVERSAL_MINGW].flatten.freeze
72
- X64_LINUX = Gem::Platform.new("x86_64-linux")
73
- X64_LINUX_MUSL = Gem::Platform.new("x86_64-linux-musl")
74
-
75
- if X64_LINUX === X64_LINUX_MUSL
76
- remove_method :===
77
-
78
- def ===(other)
79
- return nil unless Gem::Platform === other
80
-
81
- # universal-mingw32 matches x64-mingw-ucrt
82
- return true if (@cpu == "universal" || other.cpu == "universal") &&
83
- @os.start_with?("mingw") && other.os.start_with?("mingw")
84
-
85
- # cpu
86
- ([nil,"universal"].include?(@cpu) || [nil, "universal"].include?(other.cpu) || @cpu == other.cpu ||
87
- (@cpu == "arm" && other.cpu.start_with?("armv"))) &&
88
-
89
- # os
90
- @os == other.os &&
91
-
92
- # version
93
- (
94
- (@os != "linux" && (@version.nil? || other.version.nil?)) ||
95
- (@os == "linux" && (normalized_linux_version_ext == other.normalized_linux_version_ext || ["musl#{@version}", "musleabi#{@version}", "musleabihf#{@version}"].include?(other.version))) ||
96
- @version == other.version
97
- )
98
- end
55
+ # Can be removed once RubyGems 3.6.9 support is dropped
56
+ unless respond_to?(:generic)
57
+ JAVA = Gem::Platform.new("java") # :nodoc:
58
+ MSWIN = Gem::Platform.new("mswin32") # :nodoc:
59
+ MSWIN64 = Gem::Platform.new("mswin64") # :nodoc:
60
+ MINGW = Gem::Platform.new("x86-mingw32") # :nodoc:
61
+ X64_MINGW_LEGACY = Gem::Platform.new("x64-mingw32") # :nodoc:
62
+ X64_MINGW = Gem::Platform.new("x64-mingw-ucrt") # :nodoc:
63
+ UNIVERSAL_MINGW = Gem::Platform.new("universal-mingw") # :nodoc:
64
+ WINDOWS = [MSWIN, MSWIN64, UNIVERSAL_MINGW].freeze # :nodoc:
65
+ X64_LINUX = Gem::Platform.new("x86_64-linux") # :nodoc:
66
+ X64_LINUX_MUSL = Gem::Platform.new("x86_64-linux-musl") # :nodoc:
67
+
68
+ GENERICS = [JAVA, *WINDOWS].freeze # :nodoc:
69
+ private_constant :GENERICS
70
+
71
+ GENERIC_CACHE = GENERICS.each_with_object({}) {|g, h| h[g] = g } # :nodoc:
72
+ private_constant :GENERIC_CACHE
99
73
 
100
- # This is a copy of RubyGems 3.3.23 or higher `normalized_linux_method`.
101
- # Once only 3.3.23 is supported, we can use the method in RubyGems.
102
- def normalized_linux_version_ext
103
- return nil unless @version
74
+ class << self
75
+ ##
76
+ # Returns the generic platform for the given platform.
104
77
 
105
- without_gnu_nor_abi_modifiers = @version.sub(/\Agnu/, "").sub(/eabi(hf)?\Z/, "")
106
- return nil if without_gnu_nor_abi_modifiers.empty?
78
+ def generic(platform)
79
+ return Gem::Platform::RUBY if platform.nil? || platform == Gem::Platform::RUBY
107
80
 
108
- without_gnu_nor_abi_modifiers
109
- end
110
- end
111
- end
81
+ GENERIC_CACHE[platform] ||= begin
82
+ found = GENERICS.find do |match|
83
+ platform === match
84
+ end
85
+ found || Gem::Platform::RUBY
86
+ end
87
+ end
112
88
 
113
- Platform.singleton_class.module_eval do
114
- unless Platform.singleton_methods.include?(:match_spec?)
115
- def match_spec?(spec)
116
- match_gem?(spec.platform, spec.name)
117
- end
89
+ ##
90
+ # Returns the platform specificity match for the given spec platform and user platform.
118
91
 
119
- def match_gem?(platform, gem_name)
120
- match_platforms?(platform, Gem.platforms)
121
- end
122
- end
92
+ def platform_specificity_match(spec_platform, user_platform)
93
+ return -1 if spec_platform == user_platform
94
+ return 1_000_000 if spec_platform.nil? || spec_platform == Gem::Platform::RUBY || user_platform == Gem::Platform::RUBY
95
+
96
+ os_match(spec_platform, user_platform) +
97
+ cpu_match(spec_platform, user_platform) * 10 +
98
+ version_match(spec_platform, user_platform) * 100
99
+ end
100
+
101
+ ##
102
+ # Sorts and filters the best platform match for the given matching specs and platform.
123
103
 
124
- match_platforms_defined = Gem::Platform.respond_to?(:match_platforms?, true)
104
+ def sort_and_filter_best_platform_match(matching, platform)
105
+ return matching if matching.one?
125
106
 
126
- if !match_platforms_defined || Gem::Platform.send(:match_platforms?, Gem::Platform::X64_LINUX_MUSL, [Gem::Platform::X64_LINUX])
107
+ exact = matching.select {|spec| spec.platform == platform }
108
+ return exact if exact.any?
127
109
 
128
- private
110
+ sorted_matching = sort_best_platform_match(matching, platform)
111
+ exemplary_spec = sorted_matching.first
129
112
 
130
- remove_method :match_platforms? if match_platforms_defined
113
+ sorted_matching.take_while {|spec| same_specificity?(platform, spec, exemplary_spec) && same_deps?(spec, exemplary_spec) }
114
+ end
115
+
116
+ ##
117
+ # Sorts the best platform match for the given matching specs and platform.
118
+
119
+ def sort_best_platform_match(matching, platform)
120
+ matching.sort_by.with_index do |spec, i|
121
+ [
122
+ platform_specificity_match(spec.platform, platform),
123
+ i, # for stable sort
124
+ ]
125
+ end
126
+ end
127
+
128
+ private
129
+
130
+ def same_specificity?(platform, spec, exemplary_spec)
131
+ platform_specificity_match(spec.platform, platform) == platform_specificity_match(exemplary_spec.platform, platform)
132
+ end
131
133
 
132
- def match_platforms?(platform, platforms)
133
- platforms.any? do |local_platform|
134
- platform.nil? ||
135
- local_platform == platform ||
136
- (local_platform != Gem::Platform::RUBY && platform =~ local_platform)
134
+ def same_deps?(spec, exemplary_spec)
135
+ spec.required_ruby_version == exemplary_spec.required_ruby_version &&
136
+ spec.required_rubygems_version == exemplary_spec.required_rubygems_version &&
137
+ spec.dependencies.sort == exemplary_spec.dependencies.sort
138
+ end
139
+
140
+ def os_match(spec_platform, user_platform)
141
+ if spec_platform.os == user_platform.os
142
+ 0
143
+ else
144
+ 1
145
+ end
146
+ end
147
+
148
+ def cpu_match(spec_platform, user_platform)
149
+ if spec_platform.cpu == user_platform.cpu
150
+ 0
151
+ elsif spec_platform.cpu == "arm" && user_platform.cpu.to_s.start_with?("arm")
152
+ 0
153
+ elsif spec_platform.cpu.nil? || spec_platform.cpu == "universal"
154
+ 1
155
+ else
156
+ 2
157
+ end
158
+ end
159
+
160
+ def version_match(spec_platform, user_platform)
161
+ if spec_platform.version == user_platform.version
162
+ 0
163
+ elsif spec_platform.version.nil?
164
+ 1
165
+ else
166
+ 2
167
+ end
137
168
  end
138
169
  end
170
+
139
171
  end
140
172
  end
141
173
 
@@ -144,9 +176,6 @@ module Gem
144
176
  # Can be removed once RubyGems 3.5.14 support is dropped
145
177
  VALIDATES_FOR_RESOLUTION = Specification.new.respond_to?(:validate_for_resolution).freeze
146
178
 
147
- # Can be removed once RubyGems 3.3.15 support is dropped
148
- FLATTENS_REQUIRED_PATHS = Specification.new.respond_to?(:flatten_require_paths).freeze
149
-
150
179
  class Specification
151
180
  # Can be removed once RubyGems 3.5.15 support is dropped
152
181
  correct_array_attributes = @@default_value.select {|_k,v| v.is_a?(Array) }.keys
@@ -158,7 +187,6 @@ module Gem
158
187
  require_relative "match_platform"
159
188
 
160
189
  include ::Bundler::MatchMetadata
161
- include ::Bundler::MatchPlatform
162
190
 
163
191
  attr_accessor :remote, :relative_loaded_from
164
192
 
@@ -214,23 +242,6 @@ module Gem
214
242
  full_gem_path
215
243
  end
216
244
 
217
- unless const_defined?(:LATEST_RUBY_WITHOUT_PATCH_VERSIONS)
218
- LATEST_RUBY_WITHOUT_PATCH_VERSIONS = Gem::Version.new("2.1")
219
-
220
- alias_method :rg_required_ruby_version=, :required_ruby_version=
221
- def required_ruby_version=(req)
222
- self.rg_required_ruby_version = req
223
-
224
- @required_ruby_version.requirements.map! do |op, v|
225
- if v >= LATEST_RUBY_WITHOUT_PATCH_VERSIONS && v.release.segments.size == 4
226
- [op == "~>" ? "=" : op, Gem::Version.new(v.segments.tap {|s| s.delete_at(3) }.join("."))]
227
- else
228
- [op, v]
229
- end
230
- end
231
- end
232
- end
233
-
234
245
  def insecurely_materialized?
235
246
  false
236
247
  end
@@ -272,25 +283,16 @@ module Gem
272
283
  end
273
284
  end
274
285
 
275
- unless FLATTENS_REQUIRED_PATHS
276
- def flatten_require_paths
277
- return unless raw_require_paths.first.is_a?(Array)
278
-
279
- warn "#{name} #{version} includes a gemspec with `require_paths` set to an array of arrays. Newer versions of this gem might've already fixed this"
280
- raw_require_paths.flatten!
281
- end
286
+ if Gem.rubygems_version < Gem::Version.new("3.5.22")
287
+ module FixPathSourceMissingExtensions
288
+ def missing_extensions?
289
+ return false if %w[Bundler::Source::Path Bundler::Source::Gemspec].include?(source.class.name)
282
290
 
283
- class << self
284
- module RequirePathFlattener
285
- def from_yaml(input)
286
- spec = super(input)
287
- spec.flatten_require_paths
288
- spec
289
- end
291
+ super
290
292
  end
291
-
292
- prepend RequirePathFlattener
293
293
  end
294
+
295
+ prepend FixPathSourceMissingExtensions
294
296
  end
295
297
 
296
298
  private
@@ -401,6 +403,11 @@ module Gem
401
403
  @ignored = missing_extensions?
402
404
  end
403
405
  end
406
+
407
+ # Can be removed once RubyGems 3.6.9 support is dropped
408
+ unless new.respond_to?(:installable_on_platform?)
409
+ include(::Bundler::MatchPlatform)
410
+ end
404
411
  end
405
412
 
406
413
  require "rubygems/name_tuple"
@@ -410,7 +417,7 @@ module Gem
410
417
  unless Gem::NameTuple.new("a", Gem::Version.new("1"), Gem::Platform.new("x86_64-linux")).platform.is_a?(String)
411
418
  alias_method :initialize_with_platform, :initialize
412
419
 
413
- def initialize(name, version, platform=Gem::Platform::RUBY)
420
+ def initialize(name, version, platform = Gem::Platform::RUBY)
414
421
  if Gem::Platform === platform
415
422
  initialize_with_platform(name, version, platform.to_s)
416
423
  else
@@ -471,15 +478,4 @@ module Gem
471
478
 
472
479
  Package::TarReader::Entry.prepend(FixFullNameEncoding)
473
480
  end
474
-
475
- require "rubygems/uri"
476
-
477
- # Can be removed once RubyGems 3.3.15 support is dropped
478
- unless Gem::Uri.respond_to?(:redact)
479
- class Uri
480
- def self.redact(uri)
481
- new(uri).redacted
482
- end
483
- end
484
- end
485
481
  end
@@ -69,10 +69,7 @@ module Bundler
69
69
  end
70
70
 
71
71
  def generate_plugins
72
- return unless Gem::Installer.instance_methods(false).include?(:generate_plugins)
73
-
74
- latest = Gem::Specification.stubs_for(spec.name).first
75
- return if latest && latest.version > spec.version
72
+ return unless Gem::Installer.method_defined?(:generate_plugins, false)
76
73
 
77
74
  ensure_writable_dir @plugins_dir
78
75
 
@@ -103,6 +100,10 @@ module Bundler
103
100
  end
104
101
  end
105
102
 
103
+ def build_jobs
104
+ Bundler.settings[:jobs] || super
105
+ end
106
+
106
107
  def build_extensions
107
108
  extension_cache_path = options[:bundler_extension_cache_path]
108
109
  extension_dir = spec.extension_dir
@@ -214,16 +214,11 @@ module Bundler
214
214
  e.requirement = dep.requirement
215
215
  raise e
216
216
  end
217
-
218
- # backwards compatibility shim, see https://github.com/rubygems/bundler/issues/5102
219
- kernel_class.send(:public, :gem) if Bundler.feature_flag.setup_makes_kernel_gem_public?
220
217
  end
221
218
  end
222
219
 
223
220
  # Used to give better error messages when activating specs outside of the current bundle
224
221
  def replace_bin_path(specs_by_name)
225
- gem_class = (class << Gem; self; end)
226
-
227
222
  redefine_method(gem_class, :find_spec_for_exe) do |gem_name, *args|
228
223
  exec_name = args.first
229
224
  raise ArgumentError, "you must supply exec_name" unless exec_name
@@ -345,9 +340,13 @@ module Bundler
345
340
  Gem::Specification.all = specs
346
341
  end
347
342
 
348
- redefine_method((class << Gem; self; end), :finish_resolve) do |*|
343
+ redefine_method(gem_class, :finish_resolve) do |*|
349
344
  []
350
345
  end
346
+
347
+ redefine_method(gem_class, :load_plugins) do |*|
348
+ load_plugin_files specs.flat_map(&:plugins)
349
+ end
351
350
  end
352
351
 
353
352
  def plain_specs
@@ -417,11 +416,7 @@ module Bundler
417
416
  end
418
417
 
419
418
  def all_specs
420
- SharedHelpers.major_deprecation 2, "Bundler.rubygems.all_specs has been removed in favor of Bundler.rubygems.installed_specs"
421
-
422
- Gem::Specification.stubs.map do |stub|
423
- StubSpecification.from_stub(stub)
424
- end
419
+ SharedHelpers.feature_removed! "Bundler.rubygems.all_specs has been removed in favor of Bundler.rubygems.installed_specs"
425
420
  end
426
421
 
427
422
  def installed_specs
@@ -437,7 +432,7 @@ module Bundler
437
432
  end
438
433
 
439
434
  def find_bundler(version)
440
- find_name("bundler").find {|s| s.version.to_s == version }
435
+ find_name("bundler").find {|s| s.version.to_s == version.to_s }
441
436
  end
442
437
 
443
438
  def find_name(name)
@@ -447,6 +442,12 @@ module Bundler
447
442
  def default_stubs
448
443
  Gem::Specification.default_stubs("*.gemspec")
449
444
  end
445
+
446
+ private
447
+
448
+ def gem_class
449
+ class << Gem; self; end
450
+ end
450
451
  end
451
452
 
452
453
  def self.rubygems