bundler 2.2.26 → 2.3.7

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 (149) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +206 -1
  3. data/README.md +1 -1
  4. data/exe/bundle +7 -8
  5. data/lib/bundler/.document +1 -0
  6. data/lib/bundler/build_metadata.rb +2 -2
  7. data/lib/bundler/cli/check.rb +1 -1
  8. data/lib/bundler/cli/config.rb +10 -1
  9. data/lib/bundler/cli/doctor.rb +12 -3
  10. data/lib/bundler/cli/gem.rb +98 -9
  11. data/lib/bundler/cli/info.rb +26 -5
  12. data/lib/bundler/cli/install.rb +8 -28
  13. data/lib/bundler/cli/issue.rb +4 -3
  14. data/lib/bundler/cli/platform.rb +1 -1
  15. data/lib/bundler/cli/remove.rb +1 -2
  16. data/lib/bundler/cli/update.rb +8 -4
  17. data/lib/bundler/cli.rb +13 -11
  18. data/lib/bundler/compact_index_client/cache.rb +0 -9
  19. data/lib/bundler/compact_index_client/updater.rb +0 -5
  20. data/lib/bundler/compact_index_client.rb +2 -8
  21. data/lib/bundler/definition.rb +79 -133
  22. data/lib/bundler/dependency.rb +5 -7
  23. data/lib/bundler/digest.rb +71 -0
  24. data/lib/bundler/dsl.rb +18 -30
  25. data/lib/bundler/endpoint_specification.rb +21 -11
  26. data/lib/bundler/env.rb +1 -1
  27. data/lib/bundler/environment_preserver.rb +4 -1
  28. data/lib/bundler/errors.rb +18 -2
  29. data/lib/bundler/fetcher/compact_index.rb +9 -14
  30. data/lib/bundler/fetcher/index.rb +0 -26
  31. data/lib/bundler/fetcher.rb +13 -20
  32. data/lib/bundler/friendly_errors.rb +5 -30
  33. data/lib/bundler/gem_helper.rb +7 -18
  34. data/lib/bundler/injector.rb +10 -1
  35. data/lib/bundler/installer/gem_installer.rb +1 -6
  36. data/lib/bundler/installer.rb +1 -5
  37. data/lib/bundler/lazy_specification.rb +19 -3
  38. data/lib/bundler/lockfile_generator.rb +1 -1
  39. data/lib/bundler/lockfile_parser.rb +10 -12
  40. data/lib/bundler/man/bundle-add.1 +10 -2
  41. data/lib/bundler/man/bundle-add.1.ronn +7 -1
  42. data/lib/bundler/man/bundle-binstubs.1 +1 -1
  43. data/lib/bundler/man/bundle-cache.1 +1 -1
  44. data/lib/bundler/man/bundle-check.1 +1 -1
  45. data/lib/bundler/man/bundle-clean.1 +1 -1
  46. data/lib/bundler/man/bundle-config.1 +5 -5
  47. data/lib/bundler/man/bundle-config.1.ronn +5 -5
  48. data/lib/bundler/man/bundle-doctor.1 +1 -1
  49. data/lib/bundler/man/bundle-exec.1 +1 -1
  50. data/lib/bundler/man/bundle-gem.1 +14 -1
  51. data/lib/bundler/man/bundle-gem.1.ronn +16 -0
  52. data/lib/bundler/man/bundle-info.1 +1 -1
  53. data/lib/bundler/man/bundle-init.1 +1 -1
  54. data/lib/bundler/man/bundle-inject.1 +1 -1
  55. data/lib/bundler/man/bundle-install.1 +2 -2
  56. data/lib/bundler/man/bundle-install.1.ronn +2 -2
  57. data/lib/bundler/man/bundle-list.1 +1 -1
  58. data/lib/bundler/man/bundle-lock.1 +1 -1
  59. data/lib/bundler/man/bundle-open.1 +1 -1
  60. data/lib/bundler/man/bundle-outdated.1 +1 -1
  61. data/lib/bundler/man/bundle-platform.1 +1 -1
  62. data/lib/bundler/man/bundle-pristine.1 +1 -1
  63. data/lib/bundler/man/bundle-remove.1 +1 -1
  64. data/lib/bundler/man/bundle-show.1 +1 -1
  65. data/lib/bundler/man/bundle-update.1 +2 -2
  66. data/lib/bundler/man/bundle-update.1.ronn +2 -1
  67. data/lib/bundler/man/bundle-viz.1 +1 -1
  68. data/lib/bundler/man/bundle.1 +1 -1
  69. data/lib/bundler/man/gemfile.5 +28 -2
  70. data/lib/bundler/man/gemfile.5.ronn +9 -1
  71. data/lib/bundler/plugin/api/source.rb +1 -0
  72. data/lib/bundler/plugin/installer.rb +3 -1
  73. data/lib/bundler/plugin.rb +23 -6
  74. data/lib/bundler/process_lock.rb +1 -1
  75. data/lib/bundler/remote_specification.rb +7 -0
  76. data/lib/bundler/resolver/spec_group.rb +1 -1
  77. data/lib/bundler/resolver.rb +38 -40
  78. data/lib/bundler/ruby_version.rb +1 -1
  79. data/lib/bundler/rubygems_ext.rb +19 -10
  80. data/lib/bundler/rubygems_gem_installer.rb +21 -5
  81. data/lib/bundler/rubygems_integration.rb +40 -70
  82. data/lib/bundler/runtime.rb +2 -2
  83. data/lib/bundler/self_manager.rb +168 -0
  84. data/lib/bundler/settings.rb +11 -2
  85. data/lib/bundler/shared_helpers.rb +4 -12
  86. data/lib/bundler/source/git/git_proxy.rb +7 -4
  87. data/lib/bundler/source/git.rb +22 -4
  88. data/lib/bundler/source/metadata.rb +1 -1
  89. data/lib/bundler/source/rubygems.rb +60 -85
  90. data/lib/bundler/source/rubygems_aggregate.rb +1 -1
  91. data/lib/bundler/source.rb +3 -1
  92. data/lib/bundler/source_list.rb +11 -29
  93. data/lib/bundler/spec_set.rb +2 -2
  94. data/lib/bundler/templates/Executable.bundler +1 -1
  95. data/lib/bundler/templates/Gemfile +0 -2
  96. data/lib/bundler/templates/gems.rb +0 -3
  97. data/lib/bundler/templates/newgem/Gemfile.tt +5 -2
  98. data/lib/bundler/templates/newgem/Rakefile.tt +15 -2
  99. data/lib/bundler/templates/newgem/github/workflows/main.yml.tt +4 -3
  100. data/lib/bundler/templates/newgem/newgem.gemspec.tt +15 -15
  101. data/lib/bundler/templates/newgem/sig/newgem.rbs.tt +8 -0
  102. data/lib/bundler/templates/newgem/standard.yml.tt +3 -0
  103. data/lib/bundler/templates/newgem/test/minitest/{newgem_test.rb.tt → test_newgem.rb.tt} +1 -1
  104. data/lib/bundler/ui/shell.rb +1 -1
  105. data/lib/bundler/vendor/.document +1 -0
  106. data/lib/bundler/vendor/connection_pool/LICENSE +20 -0
  107. data/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +19 -21
  108. data/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +1 -1
  109. data/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb +57 -0
  110. data/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +39 -74
  111. data/lib/bundler/vendor/fileutils/LICENSE.txt +22 -0
  112. data/lib/bundler/vendor/molinillo/LICENSE +9 -0
  113. data/lib/bundler/vendor/molinillo/lib/molinillo/dependency_graph.rb +2 -2
  114. data/lib/bundler/vendor/net-http-persistent/README.rdoc +82 -0
  115. data/lib/bundler/vendor/thor/LICENSE.md +20 -0
  116. data/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +6 -6
  117. data/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +1 -2
  118. data/lib/bundler/vendor/thor/lib/thor/actions.rb +6 -2
  119. data/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +6 -0
  120. data/lib/bundler/vendor/thor/lib/thor/error.rb +9 -4
  121. data/lib/bundler/vendor/thor/lib/thor/parser/options.rb +19 -1
  122. data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +22 -4
  123. data/lib/bundler/vendor/thor/lib/thor/shell.rb +1 -1
  124. data/lib/bundler/vendor/thor/lib/thor/util.rb +1 -1
  125. data/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
  126. data/lib/bundler/vendor/tsort/LICENSE.txt +22 -0
  127. data/lib/bundler/vendor/tsort/lib/tsort.rb +453 -0
  128. data/lib/bundler/vendor/uri/LICENSE.txt +22 -0
  129. data/lib/bundler/vendor/uri/lib/uri/common.rb +17 -80
  130. data/lib/bundler/vendor/uri/lib/uri/ftp.rb +0 -1
  131. data/lib/bundler/vendor/uri/lib/uri/generic.rb +5 -6
  132. data/lib/bundler/vendor/uri/lib/uri/http.rb +0 -1
  133. data/lib/bundler/vendor/uri/lib/uri/https.rb +0 -1
  134. data/lib/bundler/vendor/uri/lib/uri/ldap.rb +1 -1
  135. data/lib/bundler/vendor/uri/lib/uri/mailto.rb +0 -1
  136. data/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb +1 -14
  137. data/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb +1 -12
  138. data/lib/bundler/vendor/uri/lib/uri/version.rb +1 -1
  139. data/lib/bundler/vendor/uri/lib/uri/ws.rb +84 -0
  140. data/lib/bundler/vendor/uri/lib/uri/wss.rb +22 -0
  141. data/lib/bundler/vendor/uri/lib/uri.rb +0 -1
  142. data/lib/bundler/vendored_tsort.rb +4 -0
  143. data/lib/bundler/version.rb +1 -1
  144. data/lib/bundler/worker.rb +2 -2
  145. data/lib/bundler.rb +23 -22
  146. metadata +25 -10
  147. data/lib/bundler/gemdeps.rb +0 -29
  148. data/lib/bundler/psyched_yaml.rb +0 -22
  149. data/lib/bundler/vendor/connection_pool/lib/connection_pool/monotonic_time.rb +0 -66
@@ -98,7 +98,7 @@ module Bundler
98
98
  end
99
99
 
100
100
  def get(source)
101
- source_list_for(source).find {|s| equal_source?(source, s) || equivalent_source?(source, s) }
101
+ source_list_for(source).find {|s| equivalent_source?(source, s) }
102
102
  end
103
103
 
104
104
  def lock_sources
@@ -106,14 +106,14 @@ module Bundler
106
106
  end
107
107
 
108
108
  def lock_other_sources
109
- (path_sources + git_sources + plugin_sources).sort_by(&:to_s)
109
+ (path_sources + git_sources + plugin_sources).sort_by(&:identifier)
110
110
  end
111
111
 
112
112
  def lock_rubygems_sources
113
113
  if merged_gem_lockfile_sections?
114
114
  [combine_rubygems_sources]
115
115
  else
116
- rubygems_sources.sort_by(&:to_s)
116
+ rubygems_sources.sort_by(&:identifier)
117
117
  end
118
118
  end
119
119
 
@@ -136,6 +136,10 @@ module Bundler
136
136
  different_sources?(lock_sources, replacement_sources)
137
137
  end
138
138
 
139
+ def local_only!
140
+ all_sources.each(&:local_only!)
141
+ end
142
+
139
143
  def cached!
140
144
  all_sources.each(&:cached!)
141
145
  end
@@ -169,7 +173,7 @@ module Bundler
169
173
  end
170
174
 
171
175
  def different_sources?(lock_sources, replacement_sources)
172
- !equal_sources?(lock_sources, replacement_sources) && !equivalent_sources?(lock_sources, replacement_sources)
176
+ !equivalent_sources?(lock_sources, replacement_sources)
173
177
  end
174
178
 
175
179
  def rubygems_aggregate_class
@@ -206,34 +210,12 @@ module Bundler
206
210
  end
207
211
  end
208
212
 
209
- def equal_sources?(lock_sources, replacement_sources)
210
- lock_sources.sort_by(&:to_s) == replacement_sources.sort_by(&:to_s)
211
- end
212
-
213
- def equal_source?(source, other_source)
214
- return source.include?(other_source) if source.is_a?(Source::Rubygems) && other_source.is_a?(Source::Rubygems)
215
-
216
- source == other_source
217
- end
218
-
219
- def equivalent_source?(source, other_source)
220
- return false unless Bundler.settings[:allow_deployment_source_credential_changes] && source.is_a?(Source::Rubygems)
221
-
222
- equivalent_rubygems_sources?([source], [other_source])
223
- end
224
-
225
213
  def equivalent_sources?(lock_sources, replacement_sources)
226
- return false unless Bundler.settings[:allow_deployment_source_credential_changes]
227
-
228
- lock_rubygems_sources, lock_other_sources = lock_sources.partition {|s| s.is_a?(Source::Rubygems) }
229
- replacement_rubygems_sources, replacement_other_sources = replacement_sources.partition {|s| s.is_a?(Source::Rubygems) }
230
-
231
- equivalent_rubygems_sources?(lock_rubygems_sources, replacement_rubygems_sources) && equal_sources?(lock_other_sources, replacement_other_sources)
214
+ lock_sources.sort_by(&:identifier) == replacement_sources.sort_by(&:identifier)
232
215
  end
233
216
 
234
- def equivalent_rubygems_sources?(lock_sources, replacement_sources)
235
- actual_remotes = replacement_sources.map(&:remotes).flatten.uniq
236
- lock_sources.all? {|s| s.equivalent_remotes?(actual_remotes) }
217
+ def equivalent_source?(source, other_source)
218
+ source == other_source
237
219
  end
238
220
  end
239
221
  end
@@ -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
@@ -24,7 +24,7 @@ module Bundler
24
24
 
25
25
  specs_for_dep = spec_for_dependency(dep, match_current_platform)
26
26
  if specs_for_dep.any?
27
- specs += specs_for_dep
27
+ match_current_platform ? specs += specs_for_dep : specs |= specs_for_dep
28
28
 
29
29
  specs_for_dep.first.dependencies.each do |d|
30
30
  next if d.type == :development
@@ -73,7 +73,7 @@ m = Module.new do
73
73
 
74
74
  requirement = bundler_gem_version.approximate_recommendation
75
75
 
76
- return requirement unless Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.7.0")
76
+ return requirement unless Gem.rubygems_version < Gem::Version.new("2.7.0")
77
77
 
78
78
  requirement += ".a" if bundler_gem_version.prerelease?
79
79
 
@@ -2,6 +2,4 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
-
7
5
  # gem "rails"
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # A sample gems.rb
4
3
  source "https://rubygems.org"
5
4
 
6
- git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
7
-
8
5
  # gem "rails"
@@ -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 -%>
@@ -3,7 +3,16 @@
3
3
  require "bundler/gem_tasks"
4
4
  <% default_task_names = [config[:test_task]].compact -%>
5
5
  <% case config[:test] -%>
6
- <% when "minitest", "test-unit" -%>
6
+ <% when "minitest" -%>
7
+ require "rake/testtask"
8
+
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << "test"
11
+ t.libs << "lib"
12
+ t.test_files = FileList["test/**/test_*.rb"]
13
+ end
14
+
15
+ <% when "test-unit" -%>
7
16
  require "rake/testtask"
8
17
 
9
18
  Rake::TestTask.new(:test) do |t|
@@ -18,12 +27,16 @@ require "rspec/core/rake_task"
18
27
  RSpec::Core::RakeTask.new(:spec)
19
28
 
20
29
  <% end -%>
21
- <% if config[:rubocop] -%>
30
+ <% if config[:linter] == "rubocop" -%>
22
31
  <% default_task_names << :rubocop -%>
23
32
  require "rubocop/rake_task"
24
33
 
25
34
  RuboCop::RakeTask.new
26
35
 
36
+ <% elsif config[:linter] == "standard" -%>
37
+ <% default_task_names << :standard -%>
38
+ require "standard/rake"
39
+
27
40
  <% end -%>
28
41
  <% if config[:ext] -%>
29
42
  <% default_task_names.unshift(:clobber, :compile) -%>
@@ -2,18 +2,19 @@ name: Ruby
2
2
 
3
3
  on:
4
4
  push:
5
- - <%= config[:git_default_branch] %>
5
+ branches:
6
+ - <%= config[:git_default_branch] %>
6
7
 
7
8
  pull_request:
8
9
 
9
10
  jobs:
10
11
  build:
11
12
  runs-on: ubuntu-latest
12
-
13
+ name: Ruby ${{ matrix.ruby }}
13
14
  strategy:
14
15
  matrix:
15
16
  ruby:
16
- - <%= RUBY_VERSION %>
17
+ - '<%= RUBY_VERSION %>'
17
18
 
18
19
  steps:
19
20
  - uses: actions/checkout@v2
@@ -3,20 +3,20 @@
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
 
19
- spec.metadata["allowed_push_host"] = "TODO: Set to 'https://mygemserver.com'"
19
+ spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'"
20
20
 
21
21
  spec.metadata["homepage_uri"] = spec.homepage
22
22
  spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
@@ -26,19 +26,19 @@ Gem::Specification.new do |spec|
26
26
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
27
27
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
28
28
  `git ls-files -z`.split("\x0").reject do |f|
29
- (f == __FILE__) || f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
29
+ (f == __FILE__) || f.match(%r{\A(?:(?:bin|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
40
40
  # spec.add_dependency "example-gem", "~> 1.0"
41
41
 
42
- # For more information and examples about making a new gem, checkout our
42
+ # For more information and examples about making a new gem, check out our
43
43
  # guide at: https://bundler.io/guides/creating_gem.html
44
44
  end
@@ -0,0 +1,8 @@
1
+ <%- config[:constant_array].each_with_index do |c, i| -%>
2
+ <%= " " * i %>module <%= c %>
3
+ <%- end -%>
4
+ <%= " " * config[:constant_array].size %>VERSION: String
5
+ <%= " " * config[:constant_array].size %># See the writing guide of rbs: https://github.com/ruby/rbs#guides
6
+ <%- (config[:constant_array].size-1).downto(0) do |i| -%>
7
+ <%= " " * i %>end
8
+ <%- end -%>
@@ -0,0 +1,3 @@
1
+ # For available configuration options, see:
2
+ # https://github.com/testdouble/standard
3
+ ruby_version: <%= ::Gem::Version.new(config[:required_ruby_version]).segments[0..1].join(".") %>
@@ -2,7 +2,7 @@
2
2
 
3
3
  require "test_helper"
4
4
 
5
- class <%= config[:constant_name] %>Test < Minitest::Test
5
+ class <%= config[:minitest_constant_name] %> < Minitest::Test
6
6
  def test_that_it_has_a_version_number
7
7
  refute_nil ::<%= config[:constant_name] %>::VERSION
8
8
  end
@@ -81,7 +81,7 @@ module Bundler
81
81
  def trace(e, newline = nil, force = false)
82
82
  return unless debug? || force
83
83
  msg = "#{e.class}: #{e.message}\n#{e.backtrace.join("\n ")}"
84
- tell_me(msg, nil, newline)
84
+ tell_err(msg, nil, newline)
85
85
  end
86
86
 
87
87
  def silence(&blk)
@@ -0,0 +1 @@
1
+ # Vendored files do not need to be documented
@@ -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
@@ -1,14 +1,18 @@
1
- require_relative 'connection_pool/version'
2
- require_relative 'connection_pool/timed_stack'
1
+ require "timeout"
2
+ require_relative "connection_pool/version"
3
3
 
4
+ class Bundler::ConnectionPool
5
+ class Error < ::RuntimeError; end
6
+ class PoolShuttingDownError < ::Bundler::ConnectionPool::Error; end
7
+ class TimeoutError < ::Timeout::Error; end
8
+ end
4
9
 
5
- # Generic connection pool class for e.g. sharing a limited number of network connections
6
- # among many threads. Note: Connections are lazily created.
10
+ # Generic connection pool class for sharing a limited number of objects or network connections
11
+ # among many threads. Note: pool elements are lazily created.
7
12
  #
8
13
  # Example usage with block (faster):
9
14
  #
10
15
  # @pool = Bundler::ConnectionPool.new { Redis.new }
11
- #
12
16
  # @pool.with do |redis|
13
17
  # redis.lpop('my-list') if redis.llen('my-list') > 0
14
18
  # end
@@ -34,29 +38,23 @@ require_relative 'connection_pool/timed_stack'
34
38
  class Bundler::ConnectionPool
35
39
  DEFAULTS = {size: 5, timeout: 5}
36
40
 
37
- class Error < RuntimeError
38
- end
39
-
40
41
  def self.wrap(options, &block)
41
42
  Wrapper.new(options, &block)
42
43
  end
43
44
 
44
45
  def initialize(options = {}, &block)
45
- raise ArgumentError, 'Connection pool requires a block' unless block
46
+ raise ArgumentError, "Connection pool requires a block" unless block
46
47
 
47
48
  options = DEFAULTS.merge(options)
48
49
 
49
- @size = options.fetch(:size)
50
+ @size = Integer(options.fetch(:size))
50
51
  @timeout = options.fetch(:timeout)
51
52
 
52
53
  @available = TimedStack.new(@size, &block)
53
- @key = :"current-#{@available.object_id}"
54
- @key_count = :"current-#{@available.object_id}-count"
54
+ @key = :"pool-#{@available.object_id}"
55
+ @key_count = :"pool-#{@available.object_id}-count"
55
56
  end
56
57
 
57
- if Thread.respond_to?(:handle_interrupt)
58
-
59
- # MRI
60
58
  def with(options = {})
61
59
  Thread.handle_interrupt(Exception => :never) do
62
60
  conn = checkout(options)
@@ -69,28 +67,15 @@ if Thread.respond_to?(:handle_interrupt)
69
67
  end
70
68
  end
71
69
  end
72
-
73
- else
74
-
75
- # jruby 1.7.x
76
- def with(options = {})
77
- conn = checkout(options)
78
- begin
79
- yield conn
80
- ensure
81
- checkin
82
- end
83
- end
84
-
85
- end
70
+ alias then with
86
71
 
87
72
  def checkout(options = {})
88
73
  if ::Thread.current[@key]
89
- ::Thread.current[@key_count]+= 1
74
+ ::Thread.current[@key_count] += 1
90
75
  ::Thread.current[@key]
91
76
  else
92
- ::Thread.current[@key_count]= 1
93
- ::Thread.current[@key]= @available.pop(options[:timeout] || @timeout)
77
+ ::Thread.current[@key_count] = 1
78
+ ::Thread.current[@key] = @available.pop(options[:timeout] || @timeout)
94
79
  end
95
80
  end
96
81
 
@@ -98,64 +83,44 @@ end
98
83
  if ::Thread.current[@key]
99
84
  if ::Thread.current[@key_count] == 1
100
85
  @available.push(::Thread.current[@key])
101
- ::Thread.current[@key]= nil
86
+ ::Thread.current[@key] = nil
87
+ ::Thread.current[@key_count] = nil
102
88
  else
103
- ::Thread.current[@key_count]-= 1
89
+ ::Thread.current[@key_count] -= 1
104
90
  end
105
91
  else
106
- raise Bundler::ConnectionPool::Error, 'no connections are checked out'
92
+ raise Bundler::ConnectionPool::Error, "no connections are checked out"
107
93
  end
108
94
 
109
95
  nil
110
96
  end
111
97
 
98
+ ##
99
+ # Shuts down the Bundler::ConnectionPool by passing each connection to +block+ and
100
+ # then removing it from the pool. Attempting to checkout a connection after
101
+ # shutdown will raise +Bundler::ConnectionPool::PoolShuttingDownError+.
102
+
112
103
  def shutdown(&block)
113
104
  @available.shutdown(&block)
114
105
  end
115
106
 
116
- # Size of this connection pool
117
- def size
118
- @size
107
+ ##
108
+ # Reloads the Bundler::ConnectionPool by passing each connection to +block+ and then
109
+ # removing it the pool. Subsequent checkouts will create new connections as
110
+ # needed.
111
+
112
+ def reload(&block)
113
+ @available.shutdown(reload: true, &block)
119
114
  end
120
115
 
116
+ # Size of this connection pool
117
+ attr_reader :size
118
+
121
119
  # Number of pool entries available for checkout at this instant.
122
120
  def available
123
121
  @available.length
124
122
  end
125
-
126
- private
127
-
128
- class Wrapper < ::BasicObject
129
- METHODS = [:with, :pool_shutdown]
130
-
131
- def initialize(options = {}, &block)
132
- @pool = options.fetch(:pool) { ::Bundler::ConnectionPool.new(options, &block) }
133
- end
134
-
135
- def with(&block)
136
- @pool.with(&block)
137
- end
138
-
139
- def pool_shutdown(&block)
140
- @pool.shutdown(&block)
141
- end
142
-
143
- def pool_size
144
- @pool.size
145
- end
146
-
147
- def pool_available
148
- @pool.available
149
- end
150
-
151
- def respond_to?(id, *args)
152
- METHODS.include?(id) || with { |c| c.respond_to?(id, *args) }
153
- end
154
-
155
- def method_missing(name, *args, &block)
156
- with do |connection|
157
- connection.send(name, *args, &block)
158
- end
159
- end
160
- end
161
123
  end
124
+
125
+ require_relative "connection_pool/timed_stack"
126
+ require_relative "connection_pool/wrapper"