bundler 2.2.28 → 2.2.32

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bundler might be problematic. Click here for more details.

Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +58 -1
  3. data/README.md +1 -1
  4. data/lib/bundler/build_metadata.rb +2 -2
  5. data/lib/bundler/cli/gem.rb +86 -8
  6. data/lib/bundler/cli/info.rb +11 -4
  7. data/lib/bundler/cli/issue.rb +4 -3
  8. data/lib/bundler/cli.rb +3 -1
  9. data/lib/bundler/compact_index_client.rb +2 -2
  10. data/lib/bundler/definition.rb +49 -78
  11. data/lib/bundler/digest.rb +71 -0
  12. data/lib/bundler/errors.rb +18 -2
  13. data/lib/bundler/fetcher.rb +2 -1
  14. data/lib/bundler/friendly_errors.rb +5 -30
  15. data/lib/bundler/gem_helper.rb +6 -17
  16. data/lib/bundler/lockfile_parser.rb +1 -0
  17. data/lib/bundler/man/bundle-add.1 +1 -1
  18. data/lib/bundler/man/bundle-binstubs.1 +1 -1
  19. data/lib/bundler/man/bundle-cache.1 +1 -1
  20. data/lib/bundler/man/bundle-check.1 +1 -1
  21. data/lib/bundler/man/bundle-clean.1 +1 -1
  22. data/lib/bundler/man/bundle-config.1 +3 -3
  23. data/lib/bundler/man/bundle-config.1.ronn +2 -2
  24. data/lib/bundler/man/bundle-doctor.1 +1 -1
  25. data/lib/bundler/man/bundle-exec.1 +1 -1
  26. data/lib/bundler/man/bundle-gem.1 +14 -1
  27. data/lib/bundler/man/bundle-gem.1.ronn +16 -0
  28. data/lib/bundler/man/bundle-info.1 +1 -1
  29. data/lib/bundler/man/bundle-init.1 +1 -1
  30. data/lib/bundler/man/bundle-inject.1 +1 -1
  31. data/lib/bundler/man/bundle-install.1 +1 -1
  32. data/lib/bundler/man/bundle-list.1 +1 -1
  33. data/lib/bundler/man/bundle-lock.1 +1 -1
  34. data/lib/bundler/man/bundle-open.1 +1 -1
  35. data/lib/bundler/man/bundle-outdated.1 +1 -1
  36. data/lib/bundler/man/bundle-platform.1 +1 -1
  37. data/lib/bundler/man/bundle-pristine.1 +1 -1
  38. data/lib/bundler/man/bundle-remove.1 +1 -1
  39. data/lib/bundler/man/bundle-show.1 +1 -1
  40. data/lib/bundler/man/bundle-update.1 +1 -1
  41. data/lib/bundler/man/bundle-viz.1 +1 -1
  42. data/lib/bundler/man/bundle.1 +1 -1
  43. data/lib/bundler/man/gemfile.5 +1 -1
  44. data/lib/bundler/rubygems_ext.rb +4 -0
  45. data/lib/bundler/rubygems_gem_installer.rb +20 -4
  46. data/lib/bundler/rubygems_integration.rb +26 -9
  47. data/lib/bundler/runtime.rb +2 -2
  48. data/lib/bundler/source/git/git_proxy.rb +5 -2
  49. data/lib/bundler/source/git.rb +22 -4
  50. data/lib/bundler/source/rubygems.rb +36 -72
  51. data/lib/bundler/spec_set.rb +1 -1
  52. data/lib/bundler/templates/newgem/Gemfile.tt +5 -2
  53. data/lib/bundler/templates/newgem/Rakefile.tt +5 -1
  54. data/lib/bundler/templates/newgem/newgem.gemspec.tt +12 -12
  55. data/lib/bundler/templates/newgem/standard.yml.tt +2 -0
  56. data/lib/bundler/vendor/connection_pool/LICENSE +20 -0
  57. data/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +19 -21
  58. data/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +1 -1
  59. data/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb +57 -0
  60. data/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +39 -74
  61. data/lib/bundler/vendor/fileutils/LICENSE.txt +22 -0
  62. data/lib/bundler/vendor/molinillo/LICENSE +9 -0
  63. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +2 -2
  64. data/lib/bundler/vendor/net-http-persistent/README.rdoc +82 -0
  65. data/lib/bundler/vendor/thor/LICENSE.md +20 -0
  66. data/lib/bundler/vendor/tsort/LICENSE.txt +22 -0
  67. data/lib/bundler/vendor/tsort/lib/tsort.rb +453 -0
  68. data/lib/bundler/vendor/uri/LICENSE.txt +22 -0
  69. data/lib/bundler/vendored_tsort.rb +4 -0
  70. data/lib/bundler/version.rb +1 -1
  71. data/lib/bundler/worker.rb +2 -2
  72. data/lib/bundler.rb +2 -1
  73. metadata +18 -7
  74. data/lib/bundler/vendor/connection_pool/lib/connection_pool/monotonic_time.rb +0 -66
@@ -42,7 +42,7 @@ module Bundler
42
42
  %w[ref branch tag submodules].each do |opt|
43
43
  out << " #{opt}: #{options[opt]}\n" if options[opt]
44
44
  end
45
- out << " glob: #{@glob}\n" unless @glob == DEFAULT_GLOB
45
+ out << " glob: #{@glob}\n" unless default_glob?
46
46
  out << " specs:\n"
47
47
  end
48
48
 
@@ -75,12 +75,20 @@ module Bundler
75
75
  git_proxy.branch
76
76
  end
77
77
 
78
- rev = " (at #{at}@#{shortref_for_display(revision)})"
78
+ rev = "at #{at}@#{shortref_for_display(revision)}"
79
79
  rescue GitError
80
80
  ""
81
81
  end
82
82
 
83
- "#{@safe_uri}#{rev}"
83
+ specifiers = [rev, glob_for_display].compact
84
+ suffix =
85
+ if specifiers.any?
86
+ " (#{specifiers.join(", ")})"
87
+ else
88
+ ""
89
+ end
90
+
91
+ "#{@safe_uri}#{suffix}"
84
92
  end
85
93
 
86
94
  def name
@@ -282,6 +290,14 @@ module Bundler
282
290
  ref[0..11]
283
291
  end
284
292
 
293
+ def glob_for_display
294
+ default_glob? ? nil : "glob: #{@glob}"
295
+ end
296
+
297
+ def default_glob?
298
+ @glob == DEFAULT_GLOB
299
+ end
300
+
285
301
  def uri_hash
286
302
  if uri =~ %r{^\w+://(\w+@)?}
287
303
  # Downcase the domain component of the URI
@@ -291,7 +307,9 @@ module Bundler
291
307
  # If there is no URI scheme, assume it is an ssh/git URI
292
308
  input = uri
293
309
  end
294
- SharedHelpers.digest(:SHA1).hexdigest(input)
310
+ # We use SHA1 here for historical reason and to preserve backward compatibility.
311
+ # But a transition to a simpler mangling algorithm would be welcome.
312
+ Bundler::Digest.sha1(input)
295
313
  end
296
314
 
297
315
  def cached_revision
@@ -135,7 +135,7 @@ module Bundler
135
135
  force = opts[:force]
136
136
  ensure_builtin_gems_cached = opts[:ensure_builtin_gems_cached]
137
137
 
138
- if ensure_builtin_gems_cached && builtin_gem?(spec)
138
+ if ensure_builtin_gems_cached && spec.default_gem?
139
139
  if !cached_path(spec)
140
140
  cached_built_in_gem(spec) unless spec.remote
141
141
  force = true
@@ -162,7 +162,7 @@ module Bundler
162
162
  begin
163
163
  s = Bundler.rubygems.spec_from_gem(path, Bundler.settings["trust-policy"])
164
164
  spec.__swap__(s)
165
- rescue StandardError
165
+ rescue Gem::Package::FormatError
166
166
  Bundler.rm_rf(path)
167
167
  raise
168
168
  end
@@ -174,6 +174,7 @@ module Bundler
174
174
  Bundler.ui.confirm message
175
175
 
176
176
  path = cached_gem(spec)
177
+ raise GemNotFound, "Could not find #{spec.file_name} for installation" unless path
177
178
  if requires_sudo?
178
179
  install_path = Bundler.tmp(spec.full_name)
179
180
  bin_path = install_path.join("bin")
@@ -233,12 +234,8 @@ module Bundler
233
234
  end
234
235
 
235
236
  def cache(spec, custom_path = nil)
236
- if builtin_gem?(spec)
237
- cached_path = cached_built_in_gem(spec)
238
- else
239
- cached_path = cached_gem(spec)
240
- end
241
- raise GemNotFound, "Missing gem file '#{spec.full_name}.gem'." unless cached_path
237
+ cached_path = cached_gem(spec)
238
+ raise GemNotFound, "Missing gem file '#{spec.file_name}'." unless cached_path
242
239
  return if File.dirname(cached_path) == Bundler.app_cache.to_s
243
240
  Bundler.ui.info " * #{File.basename(cached_path)}"
244
241
  FileUtils.cp(cached_path, Bundler.app_cache(custom_path))
@@ -352,14 +349,17 @@ module Bundler
352
349
  end
353
350
 
354
351
  def cached_gem(spec)
355
- cached_gem = cached_path(spec)
356
- unless cached_gem
357
- raise Bundler::GemNotFound, "Could not find #{spec.file_name} for installation"
352
+ if spec.default_gem?
353
+ cached_built_in_gem(spec)
354
+ else
355
+ cached_path(spec)
358
356
  end
359
- cached_gem
360
357
  end
361
358
 
362
359
  def cached_path(spec)
360
+ global_cache_path = download_cache_path(spec)
361
+ @caches << global_cache_path if global_cache_path
362
+
363
363
  possibilities = @caches.map {|p| "#{p}/#{spec.file_name}" }
364
364
  possibilities.find {|p| File.exist?(p) }
365
365
  end
@@ -459,19 +459,26 @@ module Bundler
459
459
 
460
460
  spec.fetch_platform
461
461
 
462
- download_path = requires_sudo? ? Bundler.tmp(spec.full_name) : rubygems_dir
463
- gem_path = "#{rubygems_dir}/cache/#{spec.full_name}.gem"
462
+ cache_path = download_cache_path(spec) || default_cache_path_for(rubygems_dir)
463
+ gem_path = "#{cache_path}/#{spec.file_name}"
464
+
465
+ if requires_sudo?
466
+ download_path = Bundler.tmp(spec.full_name)
467
+ download_cache_path = default_cache_path_for(download_path)
468
+ else
469
+ download_cache_path = cache_path
470
+ end
464
471
 
465
- SharedHelpers.filesystem_access("#{download_path}/cache") do |p|
472
+ SharedHelpers.filesystem_access(download_cache_path) do |p|
466
473
  FileUtils.mkdir_p(p)
467
474
  end
468
- download_gem(spec, download_path)
475
+ download_gem(spec, download_cache_path)
469
476
 
470
477
  if requires_sudo?
471
- SharedHelpers.filesystem_access("#{rubygems_dir}/cache") do |p|
478
+ SharedHelpers.filesystem_access(cache_path) do |p|
472
479
  Bundler.mkdir_p(p)
473
480
  end
474
- Bundler.sudo "mv #{download_path}/cache/#{spec.full_name}.gem #{gem_path}"
481
+ Bundler.sudo "mv #{download_cache_path}/#{spec.file_name} #{gem_path}"
475
482
  end
476
483
 
477
484
  gem_path
@@ -479,16 +486,8 @@ module Bundler
479
486
  Bundler.rm_rf(download_path) if requires_sudo?
480
487
  end
481
488
 
482
- def builtin_gem?(spec)
483
- # Ruby 2.1, where all included gems have this summary
484
- return true if spec.summary =~ /is bundled with Ruby/
485
-
486
- # Ruby 2.0, where gemspecs are stored in specifications/default/
487
- spec.loaded_from && spec.loaded_from.include?("specifications/default/")
488
- end
489
-
490
489
  def installed?(spec)
491
- installed_specs[spec].any?
490
+ installed_specs[spec].any? && !spec.deleted_gem?
492
491
  end
493
492
 
494
493
  def requires_sudo?
@@ -499,6 +498,10 @@ module Bundler
499
498
  Bundler.rubygems.gem_dir
500
499
  end
501
500
 
501
+ def default_cache_path_for(dir)
502
+ "#{dir}/cache"
503
+ end
504
+
502
505
  def cache_path
503
506
  Bundler.app_cache
504
507
  end
@@ -511,52 +514,13 @@ module Bundler
511
514
  # @param [Specification] spec
512
515
  # the spec we want to download or retrieve from the cache.
513
516
  #
514
- # @param [String] download_path
517
+ # @param [String] download_cache_path
515
518
  # the local directory the .gem will end up in.
516
519
  #
517
- def download_gem(spec, download_path)
518
- local_path = File.join(download_path, "cache/#{spec.full_name}.gem")
519
-
520
- if (cache_path = download_cache_path(spec)) && cache_path.file?
521
- SharedHelpers.filesystem_access(local_path) do
522
- FileUtils.cp(cache_path, local_path)
523
- end
524
- else
525
- uri = spec.remote.uri
526
- Bundler.ui.confirm("Fetching #{version_message(spec)}")
527
- rubygems_local_path = Bundler.rubygems.download_gem(spec, uri, download_path)
528
-
529
- # older rubygems return varying file:// variants depending on version
530
- rubygems_local_path = rubygems_local_path.gsub(/\Afile:/, "") unless Bundler.rubygems.provides?(">= 3.2.0.rc.2")
531
- rubygems_local_path = rubygems_local_path.gsub(%r{\A//}, "") if Bundler.rubygems.provides?("< 3.1.0")
532
-
533
- if rubygems_local_path != local_path
534
- SharedHelpers.filesystem_access(local_path) do
535
- FileUtils.mv(rubygems_local_path, local_path)
536
- end
537
- end
538
- cache_globally(spec, local_path)
539
- end
540
- end
541
-
542
- # Checks if the requested spec exists in the global cache. If it does
543
- # not, we create the relevant global cache subdirectory if it does not
544
- # exist and copy the spec from the local cache to the global cache.
545
- #
546
- # @param [Specification] spec
547
- # the spec we want to copy to the global cache.
548
- #
549
- # @param [String] local_cache_path
550
- # the local directory from which we want to copy the .gem.
551
- #
552
- def cache_globally(spec, local_cache_path)
553
- return unless cache_path = download_cache_path(spec)
554
- return if cache_path.exist?
555
-
556
- SharedHelpers.filesystem_access(cache_path.dirname, &:mkpath)
557
- SharedHelpers.filesystem_access(cache_path) do
558
- FileUtils.cp(local_cache_path, cache_path)
559
- end
520
+ def download_gem(spec, download_cache_path)
521
+ uri = spec.remote.uri
522
+ Bundler.ui.confirm("Fetching #{version_message(spec)}")
523
+ Bundler.rubygems.download_gem(spec, uri, download_cache_path)
560
524
  end
561
525
 
562
526
  # Returns the global cache path of the calling Rubygems::Source object.
@@ -575,7 +539,7 @@ module Bundler
575
539
  return unless remote = spec.remote
576
540
  return unless cache_slug = remote.cache_slug
577
541
 
578
- Bundler.user_cache.join("gems", cache_slug, spec.file_name)
542
+ Bundler.user_cache.join("gems", cache_slug)
579
543
  end
580
544
 
581
545
  def extension_cache_slug(spec)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "tsort"
3
+ require_relative "vendored_tsort"
4
4
 
5
5
  module Bundler
6
6
  class SpecSet
@@ -14,7 +14,10 @@ gem "rake-compiler"
14
14
 
15
15
  gem "<%= config[:test] %>", "~> <%= config[:test_framework_version] %>"
16
16
  <%- end -%>
17
- <%- if config[:rubocop] -%>
17
+ <%- if config[:linter] == "rubocop" -%>
18
18
 
19
- gem "rubocop", "~> <%= config[:rubocop_version] %>"
19
+ gem "rubocop", "~> <%= config[:linter_version] %>"
20
+ <%- elsif config[:linter] == "standard" -%>
21
+
22
+ gem "standard", "~> <%= config[:linter_version] %>"
20
23
  <%- end -%>
@@ -18,12 +18,16 @@ require "rspec/core/rake_task"
18
18
  RSpec::Core::RakeTask.new(:spec)
19
19
 
20
20
  <% end -%>
21
- <% if config[:rubocop] -%>
21
+ <% if config[:linter] == "rubocop" -%>
22
22
  <% default_task_names << :rubocop -%>
23
23
  require "rubocop/rake_task"
24
24
 
25
25
  RuboCop::RakeTask.new
26
26
 
27
+ <% elsif config[:linter] == "standard" -%>
28
+ <% default_task_names << :standard -%>
29
+ require "standard/rake"
30
+
27
31
  <% end -%>
28
32
  <% if config[:ext] -%>
29
33
  <% default_task_names.unshift(:clobber, :compile) -%>
@@ -3,16 +3,16 @@
3
3
  require_relative "lib/<%=config[:namespaced_path]%>/version"
4
4
 
5
5
  Gem::Specification.new do |spec|
6
- spec.name = <%= config[:name].inspect %>
7
- spec.version = <%= config[:constant_name] %>::VERSION
8
- spec.authors = [<%= config[:author].inspect %>]
9
- spec.email = [<%= config[:email].inspect %>]
10
-
11
- spec.summary = "TODO: Write a short summary, because RubyGems requires one."
12
- spec.description = "TODO: Write a longer description or delete this line."
13
- spec.homepage = "TODO: Put your gem's website or public repo URL here."
6
+ spec.name = <%= config[:name].inspect %>
7
+ spec.version = <%= config[:constant_name] %>::VERSION
8
+ spec.authors = [<%= config[:author].inspect %>]
9
+ spec.email = [<%= config[:email].inspect %>]
10
+
11
+ spec.summary = "TODO: Write a short summary, because RubyGems requires one."
12
+ spec.description = "TODO: Write a longer description or delete this line."
13
+ spec.homepage = "TODO: Put your gem's website or public repo URL here."
14
14
  <%- if config[:mit] -%>
15
- spec.license = "MIT"
15
+ spec.license = "MIT"
16
16
  <%- end -%>
17
17
  spec.required_ruby_version = ">= <%= config[:required_ruby_version] %>"
18
18
 
@@ -29,11 +29,11 @@ Gem::Specification.new do |spec|
29
29
  (f == __FILE__) || f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
30
30
  end
31
31
  end
32
- spec.bindir = "exe"
33
- spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
32
+ spec.bindir = "exe"
33
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
34
34
  spec.require_paths = ["lib"]
35
35
  <%- if config[:ext] -%>
36
- spec.extensions = ["ext/<%= config[:underscored_name] %>/extconf.rb"]
36
+ spec.extensions = ["ext/<%= config[:underscored_name] %>/extconf.rb"]
37
37
  <%- end -%>
38
38
 
39
39
  # Uncomment to register a new dependency of your gem
@@ -0,0 +1,2 @@
1
+ # For available configuration options, see:
2
+ # https://github.com/testdouble/standard
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Mike Perham
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,13 +1,3 @@
1
- require 'thread'
2
- require 'timeout'
3
- require_relative 'monotonic_time'
4
-
5
- ##
6
- # Raised when you attempt to retrieve a connection from a pool that has been
7
- # shut down.
8
-
9
- class Bundler::ConnectionPool::PoolShuttingDownError < RuntimeError; end
10
-
11
1
  ##
12
2
  # The TimedStack manages a pool of homogeneous connections (or any resource
13
3
  # you wish to manage). Connections are created lazily up to a given maximum
@@ -25,7 +15,7 @@ class Bundler::ConnectionPool::PoolShuttingDownError < RuntimeError; end
25
15
  #
26
16
  # conn = ts.pop
27
17
  # ts.pop timeout: 5
28
- # #=> raises Timeout::Error after 5 seconds
18
+ # #=> raises Bundler::ConnectionPool::TimeoutError after 5 seconds
29
19
 
30
20
  class Bundler::ConnectionPool::TimedStack
31
21
  attr_reader :max
@@ -39,8 +29,8 @@ class Bundler::ConnectionPool::TimedStack
39
29
  @created = 0
40
30
  @que = []
41
31
  @max = size
42
- @mutex = Mutex.new
43
- @resource = ConditionVariable.new
32
+ @mutex = Thread::Mutex.new
33
+ @resource = Thread::ConditionVariable.new
44
34
  @shutdown_block = nil
45
35
  end
46
36
 
@@ -59,12 +49,12 @@ class Bundler::ConnectionPool::TimedStack
59
49
  @resource.broadcast
60
50
  end
61
51
  end
62
- alias_method :<<, :push
52
+ alias << push
63
53
 
64
54
  ##
65
55
  # Retrieves a connection from the stack. If a connection is available it is
66
56
  # immediately returned. If no connection is available within the given
67
- # timeout a Timeout::Error is raised.
57
+ # timeout a Bundler::ConnectionPool::TimeoutError is raised.
68
58
  #
69
59
  # +:timeout+ is the only checked entry in +options+ and is preferred over
70
60
  # the +timeout+ argument (which will be removed in a future release). Other
@@ -74,7 +64,7 @@ class Bundler::ConnectionPool::TimedStack
74
64
  options, timeout = timeout, 0.5 if Hash === timeout
75
65
  timeout = options.fetch :timeout, timeout
76
66
 
77
- deadline = Bundler::ConnectionPool.monotonic_time + timeout
67
+ deadline = current_time + timeout
78
68
  @mutex.synchronize do
79
69
  loop do
80
70
  raise Bundler::ConnectionPool::PoolShuttingDownError if @shutdown_block
@@ -83,18 +73,20 @@ class Bundler::ConnectionPool::TimedStack
83
73
  connection = try_create(options)
84
74
  return connection if connection
85
75
 
86
- to_wait = deadline - Bundler::ConnectionPool.monotonic_time
87
- raise Timeout::Error, "Waited #{timeout} sec" if to_wait <= 0
76
+ to_wait = deadline - current_time
77
+ raise Bundler::ConnectionPool::TimeoutError, "Waited #{timeout} sec" if to_wait <= 0
88
78
  @resource.wait(@mutex, to_wait)
89
79
  end
90
80
  end
91
81
  end
92
82
 
93
83
  ##
94
- # Shuts down the TimedStack which prevents connections from being checked
95
- # out. The +block+ is called once for each connection on the stack.
84
+ # Shuts down the TimedStack by passing each connection to +block+ and then
85
+ # removing it from the pool. Attempting to checkout a connection after
86
+ # shutdown will raise +Bundler::ConnectionPool::PoolShuttingDownError+ unless
87
+ # +:reload+ is +true+.
96
88
 
97
- def shutdown(&block)
89
+ def shutdown(reload: false, &block)
98
90
  raise ArgumentError, "shutdown must receive a block" unless block_given?
99
91
 
100
92
  @mutex.synchronize do
@@ -102,6 +94,7 @@ class Bundler::ConnectionPool::TimedStack
102
94
  @resource.broadcast
103
95
 
104
96
  shutdown_connections
97
+ @shutdown_block = nil if reload
105
98
  end
106
99
  end
107
100
 
@@ -121,6 +114,10 @@ class Bundler::ConnectionPool::TimedStack
121
114
 
122
115
  private
123
116
 
117
+ def current_time
118
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
119
+ end
120
+
124
121
  ##
125
122
  # This is an extension point for TimedStack and is called with a mutex.
126
123
  #
@@ -149,6 +146,7 @@ class Bundler::ConnectionPool::TimedStack
149
146
  conn = fetch_connection(options)
150
147
  @shutdown_block.call(conn)
151
148
  end
149
+ @created = 0
152
150
  end
153
151
 
154
152
  ##
@@ -1,3 +1,3 @@
1
1
  class Bundler::ConnectionPool
2
- VERSION = "2.2.2"
2
+ VERSION = "2.3.0"
3
3
  end
@@ -0,0 +1,57 @@
1
+ class Bundler::ConnectionPool
2
+ class Wrapper < ::BasicObject
3
+ METHODS = [:with, :pool_shutdown, :wrapped_pool]
4
+
5
+ def initialize(options = {}, &block)
6
+ @pool = options.fetch(:pool) { ::Bundler::ConnectionPool.new(options, &block) }
7
+ end
8
+
9
+ def wrapped_pool
10
+ @pool
11
+ end
12
+
13
+ def with(&block)
14
+ @pool.with(&block)
15
+ end
16
+
17
+ def pool_shutdown(&block)
18
+ @pool.shutdown(&block)
19
+ end
20
+
21
+ def pool_size
22
+ @pool.size
23
+ end
24
+
25
+ def pool_available
26
+ @pool.available
27
+ end
28
+
29
+ def respond_to?(id, *args)
30
+ METHODS.include?(id) || with { |c| c.respond_to?(id, *args) }
31
+ end
32
+
33
+ # rubocop:disable Style/MethodMissingSuper
34
+ # rubocop:disable Style/MissingRespondToMissing
35
+ if ::RUBY_VERSION >= "3.0.0"
36
+ def method_missing(name, *args, **kwargs, &block)
37
+ with do |connection|
38
+ connection.send(name, *args, **kwargs, &block)
39
+ end
40
+ end
41
+ elsif ::RUBY_VERSION >= "2.7.0"
42
+ ruby2_keywords def method_missing(name, *args, &block)
43
+ with do |connection|
44
+ connection.send(name, *args, &block)
45
+ end
46
+ end
47
+ else
48
+ def method_missing(name, *args, &block)
49
+ with do |connection|
50
+ connection.send(name, *args, &block)
51
+ end
52
+ end
53
+ end
54
+ # rubocop:enable Style/MethodMissingSuper
55
+ # rubocop:enable Style/MissingRespondToMissing
56
+ end
57
+ end