rubygems-update 3.6.6 → 3.6.8
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +26 -0
- data/Manifest.txt +2 -1
- data/README.md +1 -1
- data/bundler/CHANGELOG.md +37 -6
- data/bundler/lib/bundler/build_metadata.rb +2 -2
- data/bundler/lib/bundler/checksum.rb +21 -11
- data/bundler/lib/bundler/compact_index_client/cache.rb +1 -1
- data/bundler/lib/bundler/compact_index_client/parser.rb +1 -1
- data/bundler/lib/bundler/definition.rb +90 -65
- data/bundler/lib/bundler/dsl.rb +2 -3
- data/bundler/lib/bundler/friendly_errors.rb +1 -1
- data/bundler/lib/bundler/installer.rb +1 -1
- data/bundler/lib/bundler/lazy_specification.rb +9 -1
- data/bundler/lib/bundler/lockfile_parser.rb +8 -5
- data/bundler/lib/bundler/plugin/api/source.rb +1 -1
- data/bundler/lib/bundler/plugin/installer/path.rb +8 -0
- data/bundler/lib/bundler/plugin.rb +1 -1
- data/bundler/lib/bundler/resolver/candidate.rb +1 -1
- data/bundler/lib/bundler/resolver/strategy.rb +40 -0
- data/bundler/lib/bundler/resolver.rb +11 -22
- data/bundler/lib/bundler/rubygems_ext.rb +15 -0
- data/bundler/lib/bundler/runtime.rb +8 -5
- data/bundler/lib/bundler/source/gemspec.rb +1 -4
- data/bundler/lib/bundler/source/git/git_proxy.rb +8 -3
- data/bundler/lib/bundler/source/path.rb +2 -2
- data/bundler/lib/bundler/source_list.rb +29 -11
- data/bundler/lib/bundler/spec_set.rb +27 -10
- data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +53 -3
- data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +1 -1
- data/bundler/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +11 -0
- data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/basic_package_source.rb +4 -24
- data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/strategy.rb +42 -0
- data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version_range.rb +20 -8
- data/bundler/lib/bundler/vendor/pub_grub/lib/pub_grub/version_solver.rb +17 -29
- data/bundler/lib/bundler/version.rb +1 -1
- data/doc/rubygems/CONTRIBUTING.md +0 -4
- data/lib/rubygems/commands/exec_command.rb +15 -6
- data/lib/rubygems/defaults.rb +1 -1
- data/lib/rubygems/resolver/api_set/gem_parser.rb +2 -5
- data/lib/rubygems/specification.rb +5 -5
- data/lib/rubygems/version.rb +22 -4
- data/lib/rubygems.rb +10 -7
- data/rubygems-update.gemspec +1 -1
- metadata +11 -10
- data/bundler/lib/bundler/compact_index_client/gem_parser.rb +0 -32
@@ -195,7 +195,7 @@ module Bundler
|
|
195
195
|
@sources[name]
|
196
196
|
end
|
197
197
|
|
198
|
-
# @param [Hash] The options that are present in the
|
198
|
+
# @param [Hash] The options that are present in the lockfile
|
199
199
|
# @return [API::Source] the instance of the class that handles the source
|
200
200
|
# type passed in locked_opts
|
201
201
|
def from_lock(locked_opts)
|
@@ -17,7 +17,7 @@ module Bundler
|
|
17
17
|
# Some candidates may also keep some information explicitly about the
|
18
18
|
# package they refer to. These candidates are referred to as "canonical" and
|
19
19
|
# are used when materializing resolution results back into RubyGems
|
20
|
-
# specifications that can be installed, written to
|
20
|
+
# specifications that can be installed, written to lockfiles, and so on.
|
21
21
|
#
|
22
22
|
class Candidate
|
23
23
|
include Comparable
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bundler
|
4
|
+
class Resolver
|
5
|
+
class Strategy
|
6
|
+
def initialize(source)
|
7
|
+
@source = source
|
8
|
+
end
|
9
|
+
|
10
|
+
def next_package_and_version(unsatisfied)
|
11
|
+
package, range = next_term_to_try_from(unsatisfied)
|
12
|
+
|
13
|
+
[package, most_preferred_version_of(package, range).first]
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def next_term_to_try_from(unsatisfied)
|
19
|
+
unsatisfied.min_by do |package, range|
|
20
|
+
matching_versions = @source.versions_for(package, range)
|
21
|
+
higher_versions = @source.versions_for(package, range.upper_invert)
|
22
|
+
|
23
|
+
[matching_versions.count <= 1 ? 0 : 1, higher_versions.count]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def most_preferred_version_of(package, range)
|
28
|
+
versions = @source.versions_for(package, range)
|
29
|
+
|
30
|
+
# Conditional avoids (among other things) calling
|
31
|
+
# sort_versions_by_preferred with the root package
|
32
|
+
if versions.size > 1
|
33
|
+
@source.sort_versions_by_preferred(package, versions)
|
34
|
+
else
|
35
|
+
versions
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -12,6 +12,7 @@ module Bundler
|
|
12
12
|
require_relative "resolver/candidate"
|
13
13
|
require_relative "resolver/incompatibility"
|
14
14
|
require_relative "resolver/root"
|
15
|
+
require_relative "resolver/strategy"
|
15
16
|
|
16
17
|
include GemHelpers
|
17
18
|
|
@@ -78,7 +79,7 @@ module Bundler
|
|
78
79
|
end
|
79
80
|
|
80
81
|
def solve_versions(root:, logger:)
|
81
|
-
solver = PubGrub::VersionSolver.new(source: self, root: root, logger: logger)
|
82
|
+
solver = PubGrub::VersionSolver.new(source: self, root: root, strategy: Strategy.new(self), logger: logger)
|
82
83
|
result = solver.solve
|
83
84
|
resolved_specs = result.flat_map {|package, version| version.to_specs(package, @most_specific_locked_platform) }
|
84
85
|
SpecSet.new(resolved_specs).specs_with_additional_variants_from(@base.locked_specs)
|
@@ -167,15 +168,7 @@ module Bundler
|
|
167
168
|
end
|
168
169
|
|
169
170
|
def versions_for(package, range=VersionRange.any)
|
170
|
-
|
171
|
-
|
172
|
-
# Conditional avoids (among other things) calling
|
173
|
-
# sort_versions_by_preferred with the root package
|
174
|
-
if versions.size > 1
|
175
|
-
sort_versions_by_preferred(package, versions)
|
176
|
-
else
|
177
|
-
versions
|
178
|
-
end
|
171
|
+
range.select_versions(@sorted_versions[package])
|
179
172
|
end
|
180
173
|
|
181
174
|
def no_versions_incompatibility_for(package, unsatisfied_term)
|
@@ -284,8 +277,8 @@ module Bundler
|
|
284
277
|
ruby_group = Resolver::SpecGroup.new(ruby_specs)
|
285
278
|
|
286
279
|
unless ruby_group.empty?
|
287
|
-
platform_specs.each do |
|
288
|
-
ruby_group.merge(Resolver::SpecGroup.new(
|
280
|
+
platform_specs.each do |s|
|
281
|
+
ruby_group.merge(Resolver::SpecGroup.new(s))
|
289
282
|
end
|
290
283
|
|
291
284
|
groups << Resolver::Candidate.new(version, group: ruby_group, priority: -1)
|
@@ -355,6 +348,10 @@ module Bundler
|
|
355
348
|
raise GemNotFound, message
|
356
349
|
end
|
357
350
|
|
351
|
+
def sort_versions_by_preferred(package, versions)
|
352
|
+
@gem_version_promoter.sort_versions(package, versions)
|
353
|
+
end
|
354
|
+
|
358
355
|
private
|
359
356
|
|
360
357
|
def filtered_versions_for(package)
|
@@ -414,10 +411,6 @@ module Bundler
|
|
414
411
|
requirement.satisfied_by?(spec.version) || spec.source.is_a?(Source::Gemspec)
|
415
412
|
end
|
416
413
|
|
417
|
-
def sort_versions_by_preferred(package, versions)
|
418
|
-
@gem_version_promoter.sort_versions(package, versions)
|
419
|
-
end
|
420
|
-
|
421
414
|
def repository_for(package)
|
422
415
|
source_for(package.name)
|
423
416
|
end
|
@@ -433,7 +426,7 @@ module Bundler
|
|
433
426
|
next [dep_package, dep_constraint] if name == "bundler"
|
434
427
|
|
435
428
|
dep_range = dep_constraint.range
|
436
|
-
versions =
|
429
|
+
versions = versions_for(dep_package, dep_range)
|
437
430
|
if versions.empty?
|
438
431
|
if dep_package.ignores_prereleases? || dep_package.prefer_local?
|
439
432
|
@all_versions.delete(dep_package)
|
@@ -441,7 +434,7 @@ module Bundler
|
|
441
434
|
end
|
442
435
|
dep_package.consider_prereleases! if dep_package.ignores_prereleases?
|
443
436
|
dep_package.consider_remote_versions! if dep_package.prefer_local?
|
444
|
-
versions =
|
437
|
+
versions = versions_for(dep_package, dep_range)
|
445
438
|
end
|
446
439
|
|
447
440
|
if versions.empty? && select_all_versions(dep_package, dep_range).any?
|
@@ -456,10 +449,6 @@ module Bundler
|
|
456
449
|
end.to_h
|
457
450
|
end
|
458
451
|
|
459
|
-
def select_sorted_versions(package, range)
|
460
|
-
range.select_versions(@sorted_versions[package])
|
461
|
-
end
|
462
|
-
|
463
452
|
def select_all_versions(package, range)
|
464
453
|
range.select_versions(@all_versions[package])
|
465
454
|
end
|
@@ -262,6 +262,10 @@ module Gem
|
|
262
262
|
!default_gem? && !File.directory?(full_gem_path)
|
263
263
|
end
|
264
264
|
|
265
|
+
def lock_name
|
266
|
+
@lock_name ||= name_tuple.lock_name
|
267
|
+
end
|
268
|
+
|
265
269
|
unless VALIDATES_FOR_RESOLUTION
|
266
270
|
def validate_for_resolution
|
267
271
|
SpecificationPolicy.new(self).validate_for_resolution
|
@@ -443,6 +447,17 @@ module Gem
|
|
443
447
|
end
|
444
448
|
end
|
445
449
|
|
450
|
+
unless Gem.rubygems_version >= Gem::Version.new("3.6.7")
|
451
|
+
module UnfreezeCompactIndexParsedResponse
|
452
|
+
def parse(line)
|
453
|
+
version, platform, dependencies, requirements = super
|
454
|
+
[version, platform, dependencies.frozen? ? dependencies.dup : dependencies, requirements.frozen? ? requirements.dup : requirements]
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
458
|
+
Resolver::APISet::GemParser.prepend(UnfreezeCompactIndexParsedResponse)
|
459
|
+
end
|
460
|
+
|
446
461
|
if Gem.rubygems_version < Gem::Version.new("3.6.0")
|
447
462
|
class Package; end
|
448
463
|
require "rubygems/package/tar_reader"
|
@@ -130,11 +130,14 @@ module Bundler
|
|
130
130
|
|
131
131
|
specs_to_cache.each do |spec|
|
132
132
|
next if spec.name == "bundler"
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
133
|
+
|
134
|
+
source = spec.source
|
135
|
+
next if source.is_a?(Source::Gemspec)
|
136
|
+
|
137
|
+
if source.respond_to?(:migrate_cache)
|
138
|
+
source.migrate_cache(custom_path, local: local)
|
139
|
+
elsif source.respond_to?(:cache)
|
140
|
+
source.cache(spec, custom_path)
|
138
141
|
end
|
139
142
|
end
|
140
143
|
|
@@ -4,15 +4,12 @@ module Bundler
|
|
4
4
|
class Source
|
5
5
|
class Gemspec < Path
|
6
6
|
attr_reader :gemspec
|
7
|
+
attr_writer :checksum_store
|
7
8
|
|
8
9
|
def initialize(options)
|
9
10
|
super
|
10
11
|
@gemspec = options["gemspec"]
|
11
12
|
end
|
12
|
-
|
13
|
-
def as_path_source
|
14
|
-
Path.new(options)
|
15
|
-
end
|
16
13
|
end
|
17
14
|
end
|
18
15
|
end
|
@@ -185,7 +185,8 @@ module Bundler
|
|
185
185
|
_, err, status = capture(command, nil)
|
186
186
|
return extra_ref if status.success?
|
187
187
|
|
188
|
-
if err.include?("Could not find remote branch")
|
188
|
+
if err.include?("Could not find remote branch") || # git up to 2.49
|
189
|
+
err.include?("Remote branch #{branch_option} not found") # git 2.49 or higher
|
189
190
|
raise MissingGitRevisionError.new(command_with_no_credentials, nil, explicit_ref, credential_filtered_uri)
|
190
191
|
else
|
191
192
|
idx = command.index("--depth")
|
@@ -262,7 +263,7 @@ module Bundler
|
|
262
263
|
end
|
263
264
|
|
264
265
|
def not_pinned?
|
265
|
-
|
266
|
+
branch_option || ref.nil?
|
266
267
|
end
|
267
268
|
|
268
269
|
def pinned_to_full_sha?
|
@@ -426,7 +427,7 @@ module Bundler
|
|
426
427
|
# anyways.
|
427
428
|
return args if @revision
|
428
429
|
|
429
|
-
args += ["--branch",
|
430
|
+
args += ["--branch", branch_option] if branch_option
|
430
431
|
args
|
431
432
|
end
|
432
433
|
|
@@ -442,6 +443,10 @@ module Bundler
|
|
442
443
|
extra_args
|
443
444
|
end
|
444
445
|
|
446
|
+
def branch_option
|
447
|
+
branch || tag
|
448
|
+
end
|
449
|
+
|
445
450
|
def full_clone?
|
446
451
|
depth.nil?
|
447
452
|
end
|
@@ -60,8 +60,8 @@ module Bundler
|
|
60
60
|
end
|
61
61
|
|
62
62
|
def eql?(other)
|
63
|
-
|
64
|
-
|
63
|
+
[Gemspec, Path].include?(other.class) &&
|
64
|
+
expanded_original_path == other.expanded_original_path &&
|
65
65
|
version == other.version
|
66
66
|
end
|
67
67
|
|
@@ -173,39 +173,57 @@ module Bundler
|
|
173
173
|
|
174
174
|
def map_sources(replacement_sources)
|
175
175
|
rubygems = @rubygems_sources.map do |source|
|
176
|
-
replace_rubygems_source(replacement_sources, source)
|
176
|
+
replace_rubygems_source(replacement_sources, source)
|
177
177
|
end
|
178
178
|
|
179
179
|
git, plugin = [@git_sources, @plugin_sources].map do |sources|
|
180
180
|
sources.map do |source|
|
181
|
-
replacement_sources
|
181
|
+
replace_source(replacement_sources, source)
|
182
182
|
end
|
183
183
|
end
|
184
184
|
|
185
185
|
path = @path_sources.map do |source|
|
186
|
-
replacement_sources
|
186
|
+
replace_path_source(replacement_sources, source)
|
187
187
|
end
|
188
188
|
|
189
189
|
[rubygems, path, git, plugin]
|
190
190
|
end
|
191
191
|
|
192
192
|
def global_replacement_source(replacement_sources)
|
193
|
-
|
194
|
-
return global_rubygems_source unless replacement_source
|
195
|
-
|
196
|
-
replacement_source.local!
|
197
|
-
replacement_source
|
193
|
+
replace_rubygems_source(replacement_sources, global_rubygems_source, &:local!)
|
198
194
|
end
|
199
195
|
|
200
196
|
def replace_rubygems_source(replacement_sources, gemfile_source)
|
197
|
+
replace_source(replacement_sources, gemfile_source) do |replacement_source|
|
198
|
+
# locked sources never include credentials so always prefer remotes from the gemfile
|
199
|
+
replacement_source.remotes = gemfile_source.remotes
|
200
|
+
|
201
|
+
yield replacement_source if block_given?
|
202
|
+
|
203
|
+
replacement_source
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def replace_source(replacement_sources, gemfile_source)
|
201
208
|
replacement_source = replacement_sources.find {|s| s == gemfile_source }
|
202
|
-
return unless replacement_source
|
209
|
+
return gemfile_source unless replacement_source
|
210
|
+
|
211
|
+
replacement_source = yield(replacement_source) if block_given?
|
203
212
|
|
204
|
-
# locked sources never include credentials so always prefer remotes from the gemfile
|
205
|
-
replacement_source.remotes = gemfile_source.remotes
|
206
213
|
replacement_source
|
207
214
|
end
|
208
215
|
|
216
|
+
def replace_path_source(replacement_sources, gemfile_source)
|
217
|
+
replace_source(replacement_sources, gemfile_source) do |replacement_source|
|
218
|
+
if gemfile_source.is_a?(Source::Gemspec)
|
219
|
+
gemfile_source.checksum_store = replacement_source.checksum_store
|
220
|
+
gemfile_source
|
221
|
+
else
|
222
|
+
replacement_source
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
209
227
|
def different_sources?(lock_sources, replacement_sources)
|
210
228
|
!equivalent_sources?(lock_sources, replacement_sources)
|
211
229
|
end
|
@@ -29,9 +29,9 @@ module Bundler
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def normalize_platforms!(deps, platforms)
|
32
|
-
|
32
|
+
add_extra_platforms!(platforms)
|
33
33
|
|
34
|
-
|
34
|
+
platforms.map! do |platform|
|
35
35
|
next platform if platform == Gem::Platform::RUBY
|
36
36
|
|
37
37
|
begin
|
@@ -44,11 +44,20 @@ module Bundler
|
|
44
44
|
next platform if incomplete_for_platform?(deps, less_specific_platform)
|
45
45
|
|
46
46
|
less_specific_platform
|
47
|
-
end.uniq
|
47
|
+
end.uniq!
|
48
|
+
end
|
49
|
+
|
50
|
+
def add_originally_invalid_platforms!(platforms, originally_invalid_platforms)
|
51
|
+
originally_invalid_platforms.each do |originally_invalid_platform|
|
52
|
+
platforms << originally_invalid_platform if complete_platform(originally_invalid_platform)
|
53
|
+
end
|
48
54
|
end
|
49
55
|
|
50
56
|
def add_extra_platforms!(platforms)
|
51
|
-
|
57
|
+
if @specs.empty?
|
58
|
+
platforms.concat([Gem::Platform::RUBY]).uniq
|
59
|
+
return
|
60
|
+
end
|
52
61
|
|
53
62
|
new_platforms = all_platforms.select do |platform|
|
54
63
|
next if platforms.include?(platform)
|
@@ -56,14 +65,13 @@ module Bundler
|
|
56
65
|
|
57
66
|
complete_platform(platform)
|
58
67
|
end
|
59
|
-
return
|
68
|
+
return if new_platforms.empty?
|
60
69
|
|
61
70
|
platforms.concat(new_platforms)
|
71
|
+
return if new_platforms.include?(Bundler.local_platform)
|
62
72
|
|
63
73
|
less_specific_platform = new_platforms.find {|platform| platform != Gem::Platform::RUBY && Bundler.local_platform === platform && platform === Bundler.local_platform }
|
64
74
|
platforms.delete(Bundler.local_platform) if less_specific_platform
|
65
|
-
|
66
|
-
platforms
|
67
75
|
end
|
68
76
|
|
69
77
|
def validate_deps(s)
|
@@ -173,7 +181,7 @@ module Bundler
|
|
173
181
|
end
|
174
182
|
|
175
183
|
def version_for(name)
|
176
|
-
|
184
|
+
exemplary_spec(name)&.version
|
177
185
|
end
|
178
186
|
|
179
187
|
def what_required(spec)
|
@@ -278,8 +286,13 @@ module Bundler
|
|
278
286
|
end
|
279
287
|
|
280
288
|
def additional_variants_from(other)
|
281
|
-
other.select do |
|
282
|
-
|
289
|
+
other.select do |other_spec|
|
290
|
+
spec = exemplary_spec(other_spec.name)
|
291
|
+
next unless spec
|
292
|
+
|
293
|
+
selected = spec.version == other_spec.version && valid_dependencies?(other_spec)
|
294
|
+
other_spec.source = spec.source if selected
|
295
|
+
selected
|
283
296
|
end
|
284
297
|
end
|
285
298
|
|
@@ -356,5 +369,9 @@ module Bundler
|
|
356
369
|
hash[key] ||= []
|
357
370
|
hash[key] << value
|
358
371
|
end
|
372
|
+
|
373
|
+
def exemplary_spec(name)
|
374
|
+
self[name].first
|
375
|
+
end
|
359
376
|
end
|
360
377
|
end
|
@@ -41,6 +41,7 @@ class Bundler::ConnectionPool::TimedStack
|
|
41
41
|
def push(obj, options = {})
|
42
42
|
@mutex.synchronize do
|
43
43
|
if @shutdown_block
|
44
|
+
@created -= 1 unless @created == 0
|
44
45
|
@shutdown_block.call(obj)
|
45
46
|
else
|
46
47
|
store_connection obj, options
|
@@ -98,6 +99,26 @@ class Bundler::ConnectionPool::TimedStack
|
|
98
99
|
end
|
99
100
|
end
|
100
101
|
|
102
|
+
##
|
103
|
+
# Reaps connections that were checked in more than +idle_seconds+ ago.
|
104
|
+
def reap(idle_seconds, &block)
|
105
|
+
raise ArgumentError, "reap must receive a block" unless block
|
106
|
+
raise ArgumentError, "idle_seconds must be a number" unless idle_seconds.is_a?(Numeric)
|
107
|
+
raise Bundler::ConnectionPool::PoolShuttingDownError if @shutdown_block
|
108
|
+
|
109
|
+
idle.times do
|
110
|
+
conn =
|
111
|
+
@mutex.synchronize do
|
112
|
+
raise Bundler::ConnectionPool::PoolShuttingDownError if @shutdown_block
|
113
|
+
|
114
|
+
reserve_idle_connection(idle_seconds)
|
115
|
+
end
|
116
|
+
break unless conn
|
117
|
+
|
118
|
+
block.call(conn)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
101
122
|
##
|
102
123
|
# Returns +true+ if there are no available connections.
|
103
124
|
|
@@ -112,6 +133,12 @@ class Bundler::ConnectionPool::TimedStack
|
|
112
133
|
@max - @created + @que.length
|
113
134
|
end
|
114
135
|
|
136
|
+
##
|
137
|
+
# The number of connections created and available on the stack.
|
138
|
+
def idle
|
139
|
+
@que.length
|
140
|
+
end
|
141
|
+
|
115
142
|
private
|
116
143
|
|
117
144
|
def current_time
|
@@ -133,7 +160,7 @@ class Bundler::ConnectionPool::TimedStack
|
|
133
160
|
# This method must return a connection from the stack.
|
134
161
|
|
135
162
|
def fetch_connection(options = nil)
|
136
|
-
@que.pop
|
163
|
+
@que.pop&.first
|
137
164
|
end
|
138
165
|
|
139
166
|
##
|
@@ -144,9 +171,32 @@ class Bundler::ConnectionPool::TimedStack
|
|
144
171
|
def shutdown_connections(options = nil)
|
145
172
|
while connection_stored?(options)
|
146
173
|
conn = fetch_connection(options)
|
174
|
+
@created -= 1 unless @created == 0
|
147
175
|
@shutdown_block.call(conn)
|
148
176
|
end
|
149
|
-
|
177
|
+
end
|
178
|
+
|
179
|
+
##
|
180
|
+
# This is an extension point for TimedStack and is called with a mutex.
|
181
|
+
#
|
182
|
+
# This method returns the oldest idle connection if it has been idle for more than idle_seconds.
|
183
|
+
# This requires that the stack is kept in order of checked in time (oldest first).
|
184
|
+
|
185
|
+
def reserve_idle_connection(idle_seconds)
|
186
|
+
return unless idle_connections?(idle_seconds)
|
187
|
+
|
188
|
+
@created -= 1 unless @created == 0
|
189
|
+
|
190
|
+
@que.shift.first
|
191
|
+
end
|
192
|
+
|
193
|
+
##
|
194
|
+
# This is an extension point for TimedStack and is called with a mutex.
|
195
|
+
#
|
196
|
+
# Returns true if the first connection in the stack has been idle for more than idle_seconds
|
197
|
+
|
198
|
+
def idle_connections?(idle_seconds)
|
199
|
+
connection_stored? && (current_time - @que.first.last > idle_seconds)
|
150
200
|
end
|
151
201
|
|
152
202
|
##
|
@@ -155,7 +205,7 @@ class Bundler::ConnectionPool::TimedStack
|
|
155
205
|
# This method must return +obj+ to the stack.
|
156
206
|
|
157
207
|
def store_connection(obj, options = nil)
|
158
|
-
@que.push obj
|
208
|
+
@que.push [obj, current_time]
|
159
209
|
end
|
160
210
|
|
161
211
|
##
|
@@ -160,6 +160,12 @@ class Bundler::ConnectionPool
|
|
160
160
|
@available.shutdown(reload: true, &block)
|
161
161
|
end
|
162
162
|
|
163
|
+
## Reaps idle connections that have been idle for over +idle_seconds+.
|
164
|
+
# +idle_seconds+ defaults to 60.
|
165
|
+
def reap(idle_seconds = 60, &block)
|
166
|
+
@available.reap(idle_seconds, &block)
|
167
|
+
end
|
168
|
+
|
163
169
|
# Size of this connection pool
|
164
170
|
attr_reader :size
|
165
171
|
# Automatically drop all connections after fork
|
@@ -169,6 +175,11 @@ class Bundler::ConnectionPool
|
|
169
175
|
def available
|
170
176
|
@available.length
|
171
177
|
end
|
178
|
+
|
179
|
+
# Number of pool entries created and idle in the pool.
|
180
|
+
def idle
|
181
|
+
@available.idle
|
182
|
+
end
|
172
183
|
end
|
173
184
|
|
174
185
|
require_relative "connection_pool/timed_stack"
|
@@ -79,29 +79,17 @@ module Bundler::PubGrub
|
|
79
79
|
dependencies_for(@root_package, @root_version)
|
80
80
|
end
|
81
81
|
|
82
|
-
# Override me (maybe)
|
83
|
-
#
|
84
|
-
# If not overridden, the order returned by all_versions_for will be used
|
85
|
-
#
|
86
|
-
# Returns: Array of versions in preferred order
|
87
|
-
def sort_versions_by_preferred(package, sorted_versions)
|
88
|
-
indexes = @version_indexes[package]
|
89
|
-
sorted_versions.sort_by { |version| indexes[version] }
|
90
|
-
end
|
91
|
-
|
92
82
|
def initialize
|
93
83
|
@root_package = Package.root
|
94
84
|
@root_version = Package.root_version
|
95
85
|
|
96
|
-
@
|
86
|
+
@sorted_versions = Hash.new do |h,k|
|
97
87
|
if k == @root_package
|
98
88
|
h[k] = [@root_version]
|
99
89
|
else
|
100
|
-
h[k] = all_versions_for(k)
|
90
|
+
h[k] = all_versions_for(k).sort
|
101
91
|
end
|
102
92
|
end
|
103
|
-
@sorted_versions = Hash.new { |h,k| h[k] = @cached_versions[k].sort }
|
104
|
-
@version_indexes = Hash.new { |h,k| h[k] = @cached_versions[k].each.with_index.to_h }
|
105
93
|
|
106
94
|
@cached_dependencies = Hash.new do |packages, package|
|
107
95
|
if package == @root_package
|
@@ -117,15 +105,7 @@ module Bundler::PubGrub
|
|
117
105
|
end
|
118
106
|
|
119
107
|
def versions_for(package, range=VersionRange.any)
|
120
|
-
|
121
|
-
|
122
|
-
# Conditional avoids (among other things) calling
|
123
|
-
# sort_versions_by_preferred with the root package
|
124
|
-
if versions.size > 1
|
125
|
-
sort_versions_by_preferred(package, versions)
|
126
|
-
else
|
127
|
-
versions
|
128
|
-
end
|
108
|
+
range.select_versions(@sorted_versions[package])
|
129
109
|
end
|
130
110
|
|
131
111
|
def no_versions_incompatibility_for(_package, unsatisfied_term)
|
@@ -164,7 +144,7 @@ module Bundler::PubGrub
|
|
164
144
|
sorted_versions[high]
|
165
145
|
end
|
166
146
|
|
167
|
-
range = VersionRange.new(min: low, max: high, include_min:
|
147
|
+
range = VersionRange.new(min: low, max: high, include_min: !low.nil?)
|
168
148
|
|
169
149
|
self_constraint = VersionConstraint.new(package, range: range)
|
170
150
|
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Bundler::PubGrub
|
2
|
+
class Strategy
|
3
|
+
def initialize(source)
|
4
|
+
@source = source
|
5
|
+
|
6
|
+
@root_package = Package.root
|
7
|
+
@root_version = Package.root_version
|
8
|
+
|
9
|
+
@version_indexes = Hash.new do |h,k|
|
10
|
+
if k == @root_package
|
11
|
+
h[k] = { @root_version => 0 }
|
12
|
+
else
|
13
|
+
h[k] = @source.all_versions_for(k).each.with_index.to_h
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def next_package_and_version(unsatisfied)
|
19
|
+
package, range = next_term_to_try_from(unsatisfied)
|
20
|
+
|
21
|
+
[package, most_preferred_version_of(package, range)]
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def most_preferred_version_of(package, range)
|
27
|
+
versions = @source.versions_for(package, range)
|
28
|
+
|
29
|
+
indexes = @version_indexes[package]
|
30
|
+
versions.min_by { |version| indexes[version] }
|
31
|
+
end
|
32
|
+
|
33
|
+
def next_term_to_try_from(unsatisfied)
|
34
|
+
unsatisfied.min_by do |package, range|
|
35
|
+
matching_versions = @source.versions_for(package, range)
|
36
|
+
higher_versions = @source.versions_for(package, range.upper_invert)
|
37
|
+
|
38
|
+
[matching_versions.count <= 1 ? 0 : 1, higher_versions.count]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|