bundler 2.4.19 → 2.4.22

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +83 -2
  3. data/README.md +1 -2
  4. data/lib/bundler/build_metadata.rb +3 -3
  5. data/lib/bundler/cli/check.rb +1 -1
  6. data/lib/bundler/cli/gem.rb +4 -3
  7. data/lib/bundler/cli/info.rb +1 -1
  8. data/lib/bundler/cli/install.rb +2 -2
  9. data/lib/bundler/cli/lock.rb +26 -23
  10. data/lib/bundler/cli/open.rb +5 -7
  11. data/lib/bundler/cli/update.rb +1 -0
  12. data/lib/bundler/definition.rb +43 -26
  13. data/lib/bundler/endpoint_specification.rb +1 -1
  14. data/lib/bundler/env.rb +2 -2
  15. data/lib/bundler/errors.rb +15 -0
  16. data/lib/bundler/fetcher/base.rb +2 -2
  17. data/lib/bundler/fetcher/compact_index.rb +1 -5
  18. data/lib/bundler/fetcher/dependency.rb +1 -1
  19. data/lib/bundler/fetcher.rb +31 -30
  20. data/lib/bundler/gem_helpers.rb +7 -0
  21. data/lib/bundler/gem_version_promoter.rb +2 -2
  22. data/lib/bundler/index.rb +62 -31
  23. data/lib/bundler/injector.rb +1 -1
  24. data/lib/bundler/installer/gem_installer.rb +5 -5
  25. data/lib/bundler/installer/parallel_installer.rb +0 -26
  26. data/lib/bundler/installer/standalone.rb +15 -1
  27. data/lib/bundler/lazy_specification.rb +4 -0
  28. data/lib/bundler/lockfile_parser.rb +32 -39
  29. data/lib/bundler/man/bundle-add.1 +1 -1
  30. data/lib/bundler/man/bundle-binstubs.1 +1 -1
  31. data/lib/bundler/man/bundle-cache.1 +1 -1
  32. data/lib/bundler/man/bundle-check.1 +1 -1
  33. data/lib/bundler/man/bundle-clean.1 +1 -1
  34. data/lib/bundler/man/bundle-config.1 +1 -1
  35. data/lib/bundler/man/bundle-console.1 +1 -1
  36. data/lib/bundler/man/bundle-doctor.1 +1 -1
  37. data/lib/bundler/man/bundle-exec.1 +2 -2
  38. data/lib/bundler/man/bundle-exec.1.ronn +2 -3
  39. data/lib/bundler/man/bundle-gem.1 +1 -1
  40. data/lib/bundler/man/bundle-help.1 +1 -1
  41. data/lib/bundler/man/bundle-info.1 +1 -1
  42. data/lib/bundler/man/bundle-init.1 +1 -1
  43. data/lib/bundler/man/bundle-inject.1 +1 -1
  44. data/lib/bundler/man/bundle-install.1 +1 -1
  45. data/lib/bundler/man/bundle-list.1 +1 -1
  46. data/lib/bundler/man/bundle-lock.1 +1 -1
  47. data/lib/bundler/man/bundle-open.1 +1 -1
  48. data/lib/bundler/man/bundle-outdated.1 +1 -1
  49. data/lib/bundler/man/bundle-platform.1 +1 -1
  50. data/lib/bundler/man/bundle-plugin.1 +17 -17
  51. data/lib/bundler/man/bundle-plugin.1.ronn +5 -5
  52. data/lib/bundler/man/bundle-pristine.1 +1 -1
  53. data/lib/bundler/man/bundle-remove.1 +1 -1
  54. data/lib/bundler/man/bundle-show.1 +1 -1
  55. data/lib/bundler/man/bundle-update.1 +1 -1
  56. data/lib/bundler/man/bundle-version.1 +1 -1
  57. data/lib/bundler/man/bundle-viz.1 +1 -1
  58. data/lib/bundler/man/bundle.1 +1 -1
  59. data/lib/bundler/man/gemfile.5 +12 -1
  60. data/lib/bundler/man/gemfile.5.ronn +5 -0
  61. data/lib/bundler/plugin/index.rb +8 -0
  62. data/lib/bundler/plugin.rb +10 -3
  63. data/lib/bundler/resolver/package.rb +5 -0
  64. data/lib/bundler/resolver.rb +45 -10
  65. data/lib/bundler/retry.rb +1 -1
  66. data/lib/bundler/ruby_dsl.rb +23 -2
  67. data/lib/bundler/ruby_version.rb +8 -1
  68. data/lib/bundler/rubygems_ext.rb +3 -4
  69. data/lib/bundler/rubygems_gem_installer.rb +23 -8
  70. data/lib/bundler/self_manager.rb +2 -0
  71. data/lib/bundler/settings.rb +86 -25
  72. data/lib/bundler/shared_helpers.rb +16 -1
  73. data/lib/bundler/source/git/git_proxy.rb +35 -6
  74. data/lib/bundler/source/metadata.rb +1 -1
  75. data/lib/bundler/source/rubygems.rb +22 -25
  76. data/lib/bundler/spec_set.rb +7 -4
  77. data/lib/bundler/stub_specification.rb +4 -2
  78. data/lib/bundler/templates/newgem/Rakefile.tt +6 -2
  79. data/lib/bundler/templates/newgem/github/workflows/main.yml.tt +1 -1
  80. data/lib/bundler/templates/newgem/newgem.gemspec.tt +1 -1
  81. data/lib/bundler/ui/shell.rb +1 -1
  82. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/connection.rb +1 -0
  83. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/pool.rb +21 -9
  84. data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +1 -1
  85. data/lib/bundler/vendor/thor/lib/thor/actions/create_file.rb +3 -2
  86. data/lib/bundler/vendor/thor/lib/thor/actions/directory.rb +1 -1
  87. data/lib/bundler/vendor/thor/lib/thor/actions/empty_directory.rb +1 -1
  88. data/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +8 -10
  89. data/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +15 -4
  90. data/lib/bundler/vendor/thor/lib/thor/actions.rb +15 -15
  91. data/lib/bundler/vendor/thor/lib/thor/base.rb +140 -14
  92. data/lib/bundler/vendor/thor/lib/thor/command.rb +13 -4
  93. data/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +4 -0
  94. data/lib/bundler/vendor/thor/lib/thor/error.rb +16 -25
  95. data/lib/bundler/vendor/thor/lib/thor/group.rb +1 -1
  96. data/lib/bundler/vendor/thor/lib/thor/invocation.rb +1 -1
  97. data/lib/bundler/vendor/thor/lib/thor/nested_context.rb +2 -2
  98. data/lib/bundler/vendor/thor/lib/thor/parser/argument.rb +20 -1
  99. data/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb +33 -17
  100. data/lib/bundler/vendor/thor/lib/thor/parser/option.rb +27 -8
  101. data/lib/bundler/vendor/thor/lib/thor/parser/options.rb +44 -6
  102. data/lib/bundler/vendor/thor/lib/thor/rake_compat.rb +2 -2
  103. data/lib/bundler/vendor/thor/lib/thor/runner.rb +40 -30
  104. data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +26 -150
  105. data/lib/bundler/vendor/thor/lib/thor/shell/color.rb +4 -46
  106. data/lib/bundler/vendor/thor/lib/thor/shell/column_printer.rb +29 -0
  107. data/lib/bundler/vendor/thor/lib/thor/shell/html.rb +3 -45
  108. data/lib/bundler/vendor/thor/lib/thor/shell/lcs_diff.rb +49 -0
  109. data/lib/bundler/vendor/thor/lib/thor/shell/table_printer.rb +134 -0
  110. data/lib/bundler/vendor/thor/lib/thor/shell/terminal.rb +42 -0
  111. data/lib/bundler/vendor/thor/lib/thor/shell/wrapped_printer.rb +38 -0
  112. data/lib/bundler/vendor/thor/lib/thor/shell.rb +1 -1
  113. data/lib/bundler/vendor/thor/lib/thor/util.rb +8 -7
  114. data/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
  115. data/lib/bundler/vendor/thor/lib/thor.rb +155 -8
  116. data/lib/bundler/version.rb +1 -1
  117. data/lib/bundler/yaml_serializer.rb +12 -8
  118. data/lib/bundler.rb +0 -8
  119. metadata +8 -3
@@ -88,14 +88,26 @@ module Bundler
88
88
  def initialize(root = nil)
89
89
  @root = root
90
90
  @local_config = load_config(local_config_file)
91
- @env_config = ENV.to_h.select {|key, _value| key =~ /\ABUNDLE_.+/ }
91
+
92
+ @env_config = ENV.to_h
93
+ @env_config.select! {|key, _value| key.start_with?("BUNDLE_") }
94
+ @env_config.delete("BUNDLE_")
95
+
92
96
  @global_config = load_config(global_config_file)
93
97
  @temporary = {}
98
+
99
+ @key_cache = {}
94
100
  end
95
101
 
96
102
  def [](name)
97
103
  key = key_for(name)
98
- value = configs.values.map {|config| config[key] }.compact.first
104
+
105
+ value = nil
106
+ configs.each do |_, config|
107
+ value = config[key]
108
+ next if value.nil?
109
+ break
110
+ end
99
111
 
100
112
  converted_value(value, name)
101
113
  end
@@ -138,17 +150,22 @@ module Bundler
138
150
  end
139
151
 
140
152
  def all
141
- keys = @temporary.keys | @global_config.keys | @local_config.keys | @env_config.keys
153
+ keys = @temporary.keys.union(@global_config.keys, @local_config.keys, @env_config.keys)
142
154
 
143
- keys.map do |key|
144
- key.sub(/^BUNDLE_/, "").gsub(/___/, "-").gsub(/__/, ".").downcase
145
- end.sort
155
+ keys.map! do |key|
156
+ key = key.delete_prefix("BUNDLE_")
157
+ key.gsub!("___", "-")
158
+ key.gsub!("__", ".")
159
+ key.downcase!
160
+ key
161
+ end.sort!
162
+ keys
146
163
  end
147
164
 
148
165
  def local_overrides
149
166
  repos = {}
150
167
  all.each do |k|
151
- repos[$'] = self[k] if k =~ /^local\./
168
+ repos[k.delete_prefix("local.")] = self[k] if k.start_with?("local.")
152
169
  end
153
170
  repos
154
171
  end
@@ -295,13 +312,13 @@ module Bundler
295
312
  end
296
313
 
297
314
  def key_for(key)
298
- self.class.key_for(key)
315
+ @key_cache[key] ||= self.class.key_for(key)
299
316
  end
300
317
 
301
318
  private
302
319
 
303
320
  def configs
304
- {
321
+ @configs ||= {
305
322
  :temporary => @temporary,
306
323
  :local => @local_config,
307
324
  :env => @env_config,
@@ -327,16 +344,20 @@ module Bundler
327
344
  end
328
345
 
329
346
  def is_bool(name)
330
- BOOL_KEYS.include?(name.to_s) || BOOL_KEYS.include?(parent_setting_for(name.to_s))
347
+ name = self.class.key_to_s(name)
348
+ BOOL_KEYS.include?(name) || BOOL_KEYS.include?(parent_setting_for(name))
331
349
  end
332
350
 
333
351
  def is_string(name)
334
- STRING_KEYS.include?(name.to_s) || name.to_s.start_with?("local.") || name.to_s.start_with?("mirror.") || name.to_s.start_with?("build.")
352
+ name = self.class.key_to_s(name)
353
+ STRING_KEYS.include?(name) || name.start_with?("local.") || name.start_with?("mirror.") || name.start_with?("build.")
335
354
  end
336
355
 
337
356
  def to_bool(value)
338
357
  case value
339
- when nil, /\A(false|f|no|n|0|)\z/i, false
358
+ when String
359
+ value.match?(/\A(false|f|no|n|0|)\z/i) ? false : true
360
+ when nil, false
340
361
  false
341
362
  else
342
363
  true
@@ -344,11 +365,11 @@ module Bundler
344
365
  end
345
366
 
346
367
  def is_num(key)
347
- NUMBER_KEYS.include?(key.to_s)
368
+ NUMBER_KEYS.include?(self.class.key_to_s(key))
348
369
  end
349
370
 
350
371
  def is_array(key)
351
- ARRAY_KEYS.include?(key.to_s)
372
+ ARRAY_KEYS.include?(self.class.key_to_s(key))
352
373
  end
353
374
 
354
375
  def is_credential(key)
@@ -371,7 +392,7 @@ module Bundler
371
392
  end
372
393
 
373
394
  def set_key(raw_key, value, hash, file)
374
- raw_key = raw_key.to_s
395
+ raw_key = self.class.key_to_s(raw_key)
375
396
  value = array_to_s(value) if is_array(raw_key)
376
397
 
377
398
  key = key_for(raw_key)
@@ -386,12 +407,13 @@ module Bundler
386
407
  return unless file
387
408
  SharedHelpers.filesystem_access(file) do |p|
388
409
  FileUtils.mkdir_p(p.dirname)
389
- require_relative "yaml_serializer"
390
- p.open("w") {|f| f.write(YAMLSerializer.dump(hash)) }
410
+ p.open("w") {|f| f.write(serializer_class.dump(hash)) }
391
411
  end
392
412
  end
393
413
 
394
414
  def converted_value(value, key)
415
+ key = self.class.key_to_s(key)
416
+
395
417
  if is_array(key)
396
418
  to_array(value)
397
419
  elsif value.nil?
@@ -449,24 +471,31 @@ module Bundler
449
471
  SharedHelpers.filesystem_access(config_file, :read) do |file|
450
472
  valid_file = file.exist? && !file.size.zero?
451
473
  return {} unless valid_file
452
- require_relative "yaml_serializer"
453
- YAMLSerializer.load(file.read).inject({}) do |config, (k, v)|
454
- new_k = k
455
-
474
+ serializer_class.load(file.read).inject({}) do |config, (k, v)|
456
475
  if k.include?("-")
457
476
  Bundler.ui.warn "Your #{file} config includes `#{k}`, which contains the dash character (`-`).\n" \
458
477
  "This is deprecated, because configuration through `ENV` should be possible, but `ENV` keys cannot include dashes.\n" \
459
478
  "Please edit #{file} and replace any dashes in configuration keys with a triple underscore (`___`)."
460
479
 
461
- new_k = k.gsub("-", "___")
480
+ # string hash keys are frozen
481
+ k = k.gsub("-", "___")
462
482
  end
463
483
 
464
- config[new_k] = v
484
+ config[k] = v
465
485
  config
466
486
  end
467
487
  end
468
488
  end
469
489
 
490
+ def serializer_class
491
+ require "rubygems/yaml_serializer"
492
+ Gem::YAMLSerializer
493
+ rescue LoadError
494
+ # TODO: Remove this when RubyGems 3.4 is EOL
495
+ require_relative "yaml_serializer"
496
+ YAMLSerializer
497
+ end
498
+
470
499
  PER_URI_OPTIONS = %w[
471
500
  fallback_timeout
472
501
  ].freeze
@@ -482,8 +511,11 @@ module Bundler
482
511
 
483
512
  def self.key_for(key)
484
513
  key = normalize_uri(key).to_s if key.is_a?(String) && key.start_with?("http", "mirror.http")
485
- key = key.to_s.gsub(".", "__").gsub("-", "___").upcase
486
- "BUNDLE_#{key}"
514
+ key = key_to_s(key).gsub(".", "__")
515
+ key.gsub!("-", "___")
516
+ key.upcase!
517
+
518
+ key.prepend("BUNDLE_")
487
519
  end
488
520
 
489
521
  # TODO: duplicates Rubygems#normalize_uri
@@ -503,5 +535,34 @@ module Bundler
503
535
  end
504
536
  "#{prefix}#{uri}#{suffix}"
505
537
  end
538
+
539
+ # This is a hot method, so avoid respond_to? checks on every invocation
540
+ if :read.respond_to?(:name)
541
+ def self.key_to_s(key)
542
+ case key
543
+ when String
544
+ key
545
+ when Symbol
546
+ key.name
547
+ when Bundler::URI::HTTP
548
+ key.to_s
549
+ else
550
+ raise ArgumentError, "Invalid key: #{key.inspect}"
551
+ end
552
+ end
553
+ else
554
+ def self.key_to_s(key)
555
+ case key
556
+ when String
557
+ key
558
+ when Symbol
559
+ key.to_s
560
+ when Bundler::URI::HTTP
561
+ key.to_s
562
+ else
563
+ raise ArgumentError, "Invalid key: #{key.inspect}"
564
+ end
565
+ end
566
+ end
506
567
  end
507
568
  end
@@ -197,6 +197,21 @@ module Bundler
197
197
  filesystem_access(gemfile_path) {|g| File.open(g, "w") {|file| file.puts contents } }
198
198
  end
199
199
 
200
+ def relative_gemfile_path
201
+ relative_path_to(Bundler.default_gemfile)
202
+ end
203
+
204
+ def relative_lockfile_path
205
+ relative_path_to(Bundler.default_lockfile)
206
+ end
207
+
208
+ def relative_path_to(destination, from: pwd)
209
+ Pathname.new(destination).relative_path_from(from).to_s
210
+ rescue ArgumentError
211
+ # on Windows, if source and destination are on different drivers, there's no relative path from one to the other
212
+ destination
213
+ end
214
+
200
215
  private
201
216
 
202
217
  def validate_bundle_path
@@ -297,7 +312,7 @@ module Bundler
297
312
  def set_rubyopt
298
313
  rubyopt = [ENV["RUBYOPT"]].compact
299
314
  setup_require = "-r#{File.expand_path("setup", __dir__)}"
300
- return if !rubyopt.empty? && rubyopt.first =~ /#{setup_require}/
315
+ return if !rubyopt.empty? && rubyopt.first =~ /#{Regexp.escape(setup_require)}/
301
316
  rubyopt.unshift setup_require
302
317
  Bundler::SharedHelpers.set_env "RUBYOPT", rubyopt.join(" ")
303
318
  end
@@ -43,6 +43,13 @@ module Bundler
43
43
  end
44
44
  end
45
45
 
46
+ class AmbiguousGitReference < GitError
47
+ def initialize(options)
48
+ msg = "Specification of branch or ref with tag is ambiguous. You specified #{options.inspect}"
49
+ super msg
50
+ end
51
+ end
52
+
46
53
  # The GitProxy is responsible to interact with git repositories.
47
54
  # All actions required by the Git source is encapsulated in this
48
55
  # object.
@@ -53,10 +60,15 @@ module Bundler
53
60
  def initialize(path, uri, options = {}, revision = nil, git = nil)
54
61
  @path = path
55
62
  @uri = uri
56
- @branch = options["branch"]
57
63
  @tag = options["tag"]
64
+ @branch = options["branch"]
58
65
  @ref = options["ref"]
59
- @explicit_ref = branch || tag || ref
66
+ if @tag
67
+ raise AmbiguousGitReference.new(options) if @branch || @ref
68
+ @explicit_ref = @tag
69
+ else
70
+ @explicit_ref = @ref || @branch
71
+ end
60
72
  @revision = revision
61
73
  @git = git
62
74
  @commit_ref = nil
@@ -118,7 +130,12 @@ module Bundler
118
130
  end
119
131
  end
120
132
 
121
- git "fetch", "--force", "--quiet", *extra_fetch_args, :dir => destination if @commit_ref
133
+ ref = @commit_ref || (locked_to_full_sha? && @revision)
134
+ if ref
135
+ git "config", "uploadpack.allowAnySHA1InWant", "true", :dir => path.to_s if @commit_ref.nil? && needs_allow_any_sha1_in_want?
136
+
137
+ git "fetch", "--force", "--quiet", *extra_fetch_args(ref), :dir => destination
138
+ end
122
139
 
123
140
  git "reset", "--hard", @revision, :dir => destination
124
141
 
@@ -235,7 +252,15 @@ module Bundler
235
252
  end
236
253
 
237
254
  def pinned_to_full_sha?
238
- ref =~ /\A\h{40}\z/
255
+ full_sha_revision?(ref)
256
+ end
257
+
258
+ def locked_to_full_sha?
259
+ full_sha_revision?(@revision)
260
+ end
261
+
262
+ def full_sha_revision?(ref)
263
+ ref&.match?(/\A\h{40}\z/)
239
264
  end
240
265
 
241
266
  def git_null(*command, dir: nil)
@@ -399,9 +424,9 @@ module Bundler
399
424
  ["--depth", depth.to_s]
400
425
  end
401
426
 
402
- def extra_fetch_args
427
+ def extra_fetch_args(ref)
403
428
  extra_args = [path.to_s, *depth_args]
404
- extra_args.push(@commit_ref)
429
+ extra_args.push(ref)
405
430
  extra_args
406
431
  end
407
432
 
@@ -413,6 +438,10 @@ module Bundler
413
438
  @supports_minus_c ||= Gem::Version.new(version) >= Gem::Version.new("1.8.5")
414
439
  end
415
440
 
441
+ def needs_allow_any_sha1_in_want?
442
+ @needs_allow_any_sha1_in_want ||= Gem::Version.new(version) <= Gem::Version.new("2.13.7")
443
+ end
444
+
416
445
  def supports_fetching_unreachable_refs?
417
446
  @supports_fetching_unreachable_refs ||= Gem::Version.new(version) >= Gem::Version.new("2.5.0")
418
447
  end
@@ -5,7 +5,7 @@ module Bundler
5
5
  class Metadata < Source
6
6
  def specs
7
7
  @specs ||= Index.build do |idx|
8
- idx << Gem::Specification.new("Ruby\0", Gem.ruby_version)
8
+ idx << Gem::Specification.new("Ruby\0", Bundler::RubyVersion.system.gem_version)
9
9
  idx << Gem::Specification.new("RubyGems\0", Gem::VERSION) do |s|
10
10
  s.required_rubygems_version = Gem::Requirement.default
11
11
  end
@@ -88,6 +88,7 @@ module Bundler
88
88
  end
89
89
 
90
90
  def self.from_lock(options)
91
+ options["remotes"] = Array(options.delete("remote")).reverse
91
92
  new(options)
92
93
  end
93
94
 
@@ -128,12 +129,12 @@ module Bundler
128
129
  def specs
129
130
  @specs ||= begin
130
131
  # remote_specs usually generates a way larger Index than the other
131
- # sources, and large_idx.use small_idx is way faster than
132
- # small_idx.use large_idx.
133
- idx = @allow_remote ? remote_specs.dup : Index.new
134
- idx.use(cached_specs, :override_dupes) if @allow_cached || @allow_remote
135
- idx.use(installed_specs, :override_dupes) if @allow_local
136
- idx
132
+ # sources, and large_idx.merge! small_idx is way faster than
133
+ # small_idx.merge! large_idx.
134
+ index = @allow_remote ? remote_specs.dup : Index.new
135
+ index.merge!(cached_specs) if @allow_cached || @allow_remote
136
+ index.merge!(installed_specs) if @allow_local
137
+ index
137
138
  end
138
139
  end
139
140
 
@@ -237,7 +238,7 @@ module Bundler
237
238
  end
238
239
 
239
240
  def spec_names
240
- if @allow_remote && dependency_api_available?
241
+ if dependency_api_available?
241
242
  remote_specs.spec_names
242
243
  else
243
244
  []
@@ -245,7 +246,7 @@ module Bundler
245
246
  end
246
247
 
247
248
  def unmet_deps
248
- if @allow_remote && dependency_api_available?
249
+ if dependency_api_available?
249
250
  remote_specs.unmet_dependency_names
250
251
  else
251
252
  []
@@ -260,7 +261,6 @@ module Bundler
260
261
  end
261
262
 
262
263
  def double_check_for(unmet_dependency_names)
263
- return unless @allow_remote
264
264
  return unless dependency_api_available?
265
265
 
266
266
  unmet_dependency_names = unmet_dependency_names.call
@@ -275,7 +275,9 @@ module Bundler
275
275
 
276
276
  Bundler.ui.debug "Double checking for #{unmet_dependency_names || "all specs (due to the size of the request)"} in #{self}"
277
277
 
278
- fetch_names(api_fetchers, unmet_dependency_names, specs, false)
278
+ fetch_names(api_fetchers, unmet_dependency_names, remote_specs)
279
+
280
+ specs.use remote_specs
279
281
  end
280
282
 
281
283
  def dependency_names_to_double_check
@@ -379,7 +381,7 @@ module Bundler
379
381
 
380
382
  def cached_specs
381
383
  @cached_specs ||= begin
382
- idx = @allow_local ? installed_specs.dup : Index.new
384
+ idx = Index.new
383
385
 
384
386
  Dir["#{cache_path}/*.gem"].each do |gemfile|
385
387
  s ||= Bundler.rubygems.spec_from_gem(gemfile)
@@ -392,35 +394,30 @@ module Bundler
392
394
  end
393
395
 
394
396
  def api_fetchers
395
- fetchers.select {|f| f.use_api && f.fetchers.first.api_fetcher? }
397
+ fetchers.select(&:api_fetcher?)
396
398
  end
397
399
 
398
400
  def remote_specs
399
401
  @remote_specs ||= Index.build do |idx|
400
402
  index_fetchers = fetchers - api_fetchers
401
403
 
402
- # gather lists from non-api sites
403
- fetch_names(index_fetchers, nil, idx, false)
404
-
405
- # legacy multi-remote sources need special logic to figure out
406
- # dependency names and that logic can be very costly if one remote
407
- # uses the dependency API but others don't. So use full indexes
408
- # consistently in that particular case.
409
- allow_api = !multiple_remotes?
410
-
411
- fetch_names(api_fetchers, allow_api && dependency_names, idx, false)
404
+ if index_fetchers.empty?
405
+ fetch_names(api_fetchers, dependency_names, idx)
406
+ else
407
+ fetch_names(fetchers, nil, idx)
408
+ end
412
409
  end
413
410
  end
414
411
 
415
- def fetch_names(fetchers, dependency_names, index, override_dupes)
412
+ def fetch_names(fetchers, dependency_names, index)
416
413
  fetchers.each do |f|
417
414
  if dependency_names
418
415
  Bundler.ui.info "Fetching gem metadata from #{URICredentialsFilter.credential_filtered_uri(f.uri)}", Bundler.ui.debug?
419
- index.use f.specs_with_retry(dependency_names, self), override_dupes
416
+ index.use f.specs_with_retry(dependency_names, self)
420
417
  Bundler.ui.info "" unless Bundler.ui.debug? # new line now that the dots are over
421
418
  else
422
419
  Bundler.ui.info "Fetching source index from #{URICredentialsFilter.credential_filtered_uri(f.uri)}"
423
- index.use f.specs_with_retry(nil, self), override_dupes
420
+ index.use f.specs_with_retry(nil, self)
424
421
  end
425
422
  end
426
423
  end
@@ -100,12 +100,12 @@ module Bundler
100
100
  end
101
101
  end
102
102
 
103
- def incomplete_ruby_specs?(deps)
103
+ def incomplete_for_platform?(deps, platform)
104
104
  return false if @specs.empty?
105
105
 
106
106
  @incomplete_specs = []
107
107
 
108
- self.for(deps, true, [Gem::Platform::RUBY])
108
+ self.for(deps, true, [platform])
109
109
 
110
110
  @incomplete_specs.any?
111
111
  end
@@ -200,8 +200,11 @@ module Bundler
200
200
 
201
201
  def specs_for_dependency(dep, platform)
202
202
  specs_for_name = lookup[dep.name]
203
- target_platform = dep.force_ruby_platform ? Gem::Platform::RUBY : (platform || Bundler.local_platform)
204
- matching_specs = GemHelpers.select_best_platform_match(specs_for_name, target_platform)
203
+ matching_specs = if dep.force_ruby_platform
204
+ GemHelpers.force_ruby_platform(specs_for_name)
205
+ else
206
+ GemHelpers.select_best_platform_match(specs_for_name, platform || Bundler.local_platform)
207
+ end
205
208
  matching_specs.map!(&:materialize_for_installation).compact! if platform.nil?
206
209
  matching_specs
207
210
  end
@@ -16,7 +16,8 @@ module Bundler
16
16
  # Stub has no concept of source, which means that extension_dir may be wrong
17
17
  # This is the case for git-based gems. So, instead manually assign the extension dir
18
18
  return unless source.respond_to?(:extension_dir_name)
19
- path = File.join(stub.extensions_dir, source.extension_dir_name)
19
+ unique_extension_dir = [source.extension_dir_name, File.basename(full_gem_path)].uniq.join("-")
20
+ path = File.join(stub.extensions_dir, unique_extension_dir)
20
21
  stub.extension_dir = File.expand_path(path)
21
22
  end
22
23
 
@@ -56,7 +57,7 @@ module Bundler
56
57
  end
57
58
 
58
59
  def gem_build_complete_path
59
- File.join(extension_dir, "gem.build_complete")
60
+ stub.gem_build_complete_path
60
61
  end
61
62
 
62
63
  def default_gem?
@@ -108,6 +109,7 @@ module Bundler
108
109
  end
109
110
 
110
111
  rs.source = source
112
+ rs.base_dir = stub.base_dir
111
113
 
112
114
  rs
113
115
  end
@@ -46,7 +46,9 @@ require "rb_sys/extensiontask"
46
46
 
47
47
  task build: :compile
48
48
 
49
- RbSys::ExtensionTask.new(<%= config[:name].inspect %>) do |ext|
49
+ GEMSPEC = Gem::Specification.load("<%= config[:underscored_name] %>.gemspec")
50
+
51
+ RbSys::ExtensionTask.new(<%= config[:name].inspect %>, GEMSPEC) do |ext|
50
52
  ext.lib_dir = "lib/<%= config[:namespaced_path] %>"
51
53
  end
52
54
  <% else -%>
@@ -54,7 +56,9 @@ require "rake/extensiontask"
54
56
 
55
57
  task build: :compile
56
58
 
57
- Rake::ExtensionTask.new("<%= config[:underscored_name] %>") do |ext|
59
+ GEMSPEC = Gem::Specification.load("<%= config[:underscored_name] %>.gemspec")
60
+
61
+ Rake::ExtensionTask.new("<%= config[:underscored_name] %>", GEMSPEC) do |ext|
58
62
  ext.lib_dir = "lib/<%= config[:namespaced_path] %>"
59
63
  end
60
64
  <% end -%>
@@ -17,7 +17,7 @@ jobs:
17
17
  - '<%= RUBY_VERSION %>'
18
18
 
19
19
  steps:
20
- - uses: actions/checkout@v3
20
+ - uses: actions/checkout@v4
21
21
  <%- if config[:ext] == 'rust' -%>
22
22
  - name: Set up Ruby & Rust
23
23
  uses: oxidize-rb/actions/setup-ruby-and-rust@v1
@@ -30,7 +30,7 @@ Gem::Specification.new do |spec|
30
30
  spec.files = Dir.chdir(__dir__) do
31
31
  `git ls-files -z`.split("\x0").reject do |f|
32
32
  (File.expand_path(f) == __FILE__) ||
33
- f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor Gemfile])
33
+ f.start_with?(*%w[bin/ test/ spec/ features/ .git <%= config[:ci_config_path] %>appveyor Gemfile])
34
34
  end
35
35
  end
36
36
  spec.bindir = "exe"
@@ -147,7 +147,7 @@ module Bundler
147
147
  spaces ? text.gsub(/#{spaces}/, "") : text
148
148
  end
149
149
 
150
- def word_wrap(text, line_width = @shell.terminal_width)
150
+ def word_wrap(text, line_width = Thor::Terminal.terminal_width)
151
151
  strip_leading_spaces(text).split("\n").collect do |line|
152
152
  line.length > line_width ? line.gsub(/(.{1,#{line_width}})(\s+|$)/, "\\1\n").strip : line
153
153
  end * "\n"
@@ -25,6 +25,7 @@ class Bundler::Persistent::Net::HTTP::Persistent::Connection # :nodoc:
25
25
  ensure
26
26
  reset
27
27
  end
28
+ alias_method :close, :finish
28
29
 
29
30
  def reset
30
31
  @last_use = Bundler::Persistent::Net::HTTP::Persistent::EPOCH
@@ -11,20 +11,32 @@ class Bundler::Persistent::Net::HTTP::Persistent::Pool < Bundler::ConnectionPool
11
11
  end
12
12
 
13
13
  def checkin net_http_args
14
- stack = Thread.current[@key][net_http_args] ||= []
14
+ if net_http_args.is_a?(Hash) && net_http_args.size == 1 && net_http_args[:force]
15
+ # Bundler::ConnectionPool 2.4+ calls `checkin(force: true)` after fork.
16
+ # When this happens, we should remove all connections from Thread.current
17
+ if stacks = Thread.current[@key]
18
+ stacks.each do |http_args, connections|
19
+ connections.each do |conn|
20
+ @available.push conn, connection_args: http_args
21
+ end
22
+ connections.clear
23
+ end
24
+ end
25
+ else
26
+ stack = Thread.current[@key][net_http_args] ||= []
15
27
 
16
- raise Bundler::ConnectionPool::Error, 'no connections are checked out' if
17
- stack.empty?
28
+ raise Bundler::ConnectionPool::Error, 'no connections are checked out' if
29
+ stack.empty?
18
30
 
19
- conn = stack.pop
31
+ conn = stack.pop
20
32
 
21
- if stack.empty?
22
- @available.push conn, connection_args: net_http_args
33
+ if stack.empty?
34
+ @available.push conn, connection_args: net_http_args
23
35
 
24
- Thread.current[@key].delete(net_http_args)
25
- Thread.current[@key] = nil if Thread.current[@key].empty?
36
+ Thread.current[@key].delete(net_http_args)
37
+ Thread.current[@key] = nil if Thread.current[@key].empty?
38
+ end
26
39
  end
27
-
28
40
  nil
29
41
  end
30
42
 
@@ -174,7 +174,7 @@ class Bundler::Persistent::Net::HTTP::Persistent
174
174
  ##
175
175
  # The version of Bundler::Persistent::Net::HTTP::Persistent you are using
176
176
 
177
- VERSION = '4.0.1'
177
+ VERSION = '4.0.2'
178
178
 
179
179
  ##
180
180
  # Error class for errors raised by Bundler::Persistent::Net::HTTP::Persistent. Various
@@ -43,7 +43,8 @@ class Bundler::Thor
43
43
  # Boolean:: true if it is identical, false otherwise.
44
44
  #
45
45
  def identical?
46
- exists? && File.binread(destination) == render
46
+ # binread uses ASCII-8BIT, so to avoid false negatives, the string must use the same
47
+ exists? && File.binread(destination) == String.new(render).force_encoding("ASCII-8BIT")
47
48
  end
48
49
 
49
50
  # Holds the content to be added to the file.
@@ -60,7 +61,7 @@ class Bundler::Thor
60
61
  invoke_with_conflict_check do
61
62
  require "fileutils"
62
63
  FileUtils.mkdir_p(File.dirname(destination))
63
- File.open(destination, "wb") { |f| f.write render }
64
+ File.open(destination, "wb", config[:perm]) { |f| f.write render }
64
65
  end
65
66
  given_destination
66
67
  end
@@ -58,7 +58,7 @@ class Bundler::Thor
58
58
  def initialize(base, source, destination = nil, config = {}, &block)
59
59
  @source = File.expand_path(Dir[Util.escape_globs(base.find_in_source_paths(source.to_s))].first)
60
60
  @block = block
61
- super(base, destination, {:recursive => true}.merge(config))
61
+ super(base, destination, {recursive: true}.merge(config))
62
62
  end
63
63
 
64
64
  def invoke!
@@ -33,7 +33,7 @@ class Bundler::Thor
33
33
  #
34
34
  def initialize(base, destination, config = {})
35
35
  @base = base
36
- @config = {:verbose => true}.merge(config)
36
+ @config = {verbose: true}.merge(config)
37
37
  self.destination = destination
38
38
  end
39
39