bundler 4.0.19 → 4.1.0.beta1
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/{lib/bundler/vendor/connection_pool/LICENSE → MIT.txt} +8 -6
- data/bundler.gemspec +24 -7
- data/lib/bundler/build_metadata.rb +2 -2
- data/lib/bundler/checksum.rb +40 -25
- data/lib/bundler/ci_detector.rb +1 -1
- data/lib/bundler/cli/add.rb +3 -4
- data/lib/bundler/cli/cache.rb +4 -0
- data/lib/bundler/cli/clean.rb +5 -0
- data/lib/bundler/cli/common.rb +37 -1
- data/lib/bundler/cli/config.rb +4 -2
- data/lib/bundler/cli/doctor/diagnose.rb +1 -1
- data/lib/bundler/cli/exec.rb +15 -1
- data/lib/bundler/cli/gem.rb +0 -17
- data/lib/bundler/cli/init.rb +4 -0
- data/lib/bundler/cli/install.rb +4 -5
- data/lib/bundler/cli/lock.rb +1 -2
- data/lib/bundler/cli/outdated.rb +45 -10
- data/lib/bundler/cli/pristine.rb +2 -1
- data/lib/bundler/cli/update.rb +20 -11
- data/lib/bundler/cli.rb +12 -9
- data/lib/bundler/definition.rb +60 -13
- data/lib/bundler/dependency.rb +4 -0
- data/lib/bundler/dsl.rb +78 -12
- data/lib/bundler/endpoint_specification.rb +51 -14
- data/lib/bundler/env.rb +7 -24
- data/lib/bundler/errors.rb +34 -5
- data/lib/bundler/fetcher/compact_index.rb +14 -5
- data/lib/bundler/fetcher/connection_pools.rb +150 -0
- data/lib/bundler/fetcher/downloader.rb +40 -16
- data/lib/bundler/fetcher.rb +8 -47
- data/lib/bundler/gem_helper.rb +2 -2
- data/lib/bundler/injector.rb +3 -3
- data/lib/bundler/inline.rb +44 -4
- data/lib/bundler/installer/parallel_installer.rb +25 -30
- data/lib/bundler/installer.rb +20 -6
- data/lib/bundler/lazy_specification.rb +44 -17
- data/lib/bundler/lockfile_generator.rb +24 -2
- data/lib/bundler/lockfile_parser.rb +43 -5
- data/lib/bundler/man/bundle-add.1 +7 -4
- data/lib/bundler/man/bundle-add.1.ronn +8 -4
- data/lib/bundler/man/bundle-binstubs.1 +1 -1
- data/lib/bundler/man/bundle-cache.1 +2 -2
- data/lib/bundler/man/bundle-cache.1.ronn +2 -2
- data/lib/bundler/man/bundle-check.1 +1 -1
- data/lib/bundler/man/bundle-clean.1 +1 -1
- data/lib/bundler/man/bundle-config.1 +38 -6
- data/lib/bundler/man/bundle-config.1.ronn +143 -10
- data/lib/bundler/man/bundle-console.1 +1 -1
- data/lib/bundler/man/bundle-doctor.1 +1 -1
- data/lib/bundler/man/bundle-env.1 +1 -1
- data/lib/bundler/man/bundle-exec.1 +1 -1
- data/lib/bundler/man/bundle-fund.1 +1 -1
- data/lib/bundler/man/bundle-gem.1 +1 -1
- data/lib/bundler/man/bundle-help.1 +1 -1
- data/lib/bundler/man/bundle-info.1 +1 -1
- data/lib/bundler/man/bundle-init.1 +1 -1
- data/lib/bundler/man/bundle-install.1 +2 -2
- data/lib/bundler/man/bundle-install.1.ronn +4 -4
- data/lib/bundler/man/bundle-issue.1 +1 -1
- data/lib/bundler/man/bundle-licenses.1 +1 -1
- data/lib/bundler/man/bundle-list.1 +1 -1
- data/lib/bundler/man/bundle-lock.1 +2 -2
- data/lib/bundler/man/bundle-lock.1.ronn +3 -2
- data/lib/bundler/man/bundle-open.1 +1 -1
- data/lib/bundler/man/bundle-outdated.1 +2 -2
- data/lib/bundler/man/bundle-outdated.1.ronn +7 -1
- data/lib/bundler/man/bundle-platform.1 +5 -1
- data/lib/bundler/man/bundle-platform.1.ronn +4 -0
- data/lib/bundler/man/bundle-plugin.1 +1 -1
- data/lib/bundler/man/bundle-pristine.1 +1 -1
- data/lib/bundler/man/bundle-remove.1 +1 -1
- data/lib/bundler/man/bundle-show.1 +1 -1
- data/lib/bundler/man/bundle-update.1 +2 -2
- data/lib/bundler/man/bundle-update.1.ronn +2 -2
- data/lib/bundler/man/bundle-version.1 +1 -1
- data/lib/bundler/man/bundle.1 +1 -1
- data/lib/bundler/man/gemfile.5 +46 -2
- data/lib/bundler/man/gemfile.5.ronn +56 -1
- data/lib/bundler/match_metadata.rb +20 -0
- data/lib/bundler/match_platform.rb +25 -2
- data/lib/bundler/match_remote_metadata.rb +21 -6
- data/lib/bundler/materialization.rb +2 -1
- data/lib/bundler/override.rb +69 -0
- data/lib/bundler/plugin/dsl.rb +3 -5
- data/lib/bundler/plugin/events.rb +55 -13
- data/lib/bundler/plugin/index.rb +87 -11
- data/lib/bundler/plugin/installer/path.rb +1 -1
- data/lib/bundler/plugin/installer.rb +13 -5
- data/lib/bundler/plugin.rb +58 -30
- data/lib/bundler/remote_specification.rb +6 -3
- data/lib/bundler/resolver/base.rb +2 -1
- data/lib/bundler/resolver/incompatibility.rb +1 -1
- data/lib/bundler/resolver.rb +73 -23
- data/lib/bundler/ruby_version.rb +0 -2
- data/lib/bundler/rubygems_ext.rb +71 -1
- data/lib/bundler/rubygems_gem_installer.rb +41 -2
- data/lib/bundler/rubygems_integration.rb +7 -2
- data/lib/bundler/runtime.rb +79 -12
- data/lib/bundler/settings.rb +373 -30
- data/lib/bundler/shared_helpers.rb +17 -1
- data/lib/bundler/source/git/git_proxy.rb +65 -4
- data/lib/bundler/source/git.rb +25 -14
- data/lib/bundler/source/path/installer.rb +1 -1
- data/lib/bundler/source/path.rb +1 -1
- data/lib/bundler/source/rubygems/remote.rb +10 -5
- data/lib/bundler/source/rubygems.rb +49 -13
- data/lib/bundler/spec_set.rb +16 -4
- data/lib/bundler/stub_specification.rb +5 -2
- data/lib/bundler/templates/newgem/Gemfile.tt +4 -4
- data/lib/bundler/templates/newgem/newgem.gemspec.tt +3 -3
- data/lib/bundler/templates/newgem/spec/newgem_spec.rb.tt +1 -1
- data/lib/bundler/templates/newgem/test/minitest/test_newgem.rb.tt +1 -1
- data/lib/bundler/ui/shell.rb +0 -4
- data/lib/bundler/ui/silent.rb +0 -4
- data/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +35 -2
- data/lib/bundler/vendor/thor/lib/thor/base.rb +2 -1
- data/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +14 -6
- data/lib/bundler/vendor/thor/lib/thor/shell/color.rb +2 -0
- data/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
- data/lib/bundler/vendor/thor/lib/thor.rb +34 -1
- data/lib/bundler/vendored_pub_grub.rb +5 -2
- data/lib/bundler/vendored_securerandom.rb +11 -8
- data/lib/bundler/vendored_uri.rb +14 -14
- data/lib/bundler/version.rb +1 -1
- data/lib/bundler/worker.rb +3 -2
- data/lib/bundler.rb +16 -6
- data/lib/rubygems/compact_index_client/cache.rb +122 -0
- data/lib/rubygems/compact_index_client/cache_file.rb +147 -0
- data/lib/rubygems/compact_index_client/http_fetcher.rb +88 -0
- data/lib/rubygems/compact_index_client/parser.rb +90 -0
- data/lib/rubygems/compact_index_client/updater.rb +113 -0
- data/lib/rubygems/compact_index_client.rb +111 -0
- data/lib/rubygems/cooldown_settings.rb +57 -0
- data/lib/rubygems/credential_store/native/linux.rb +97 -0
- data/lib/rubygems/credential_store/native/macos.rb +88 -0
- data/lib/rubygems/credential_store/native/windows.rb +130 -0
- data/lib/rubygems/credential_store.rb +332 -0
- data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/assignment.rb +1 -1
- data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/basic_package_source.rb +7 -7
- data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/failure_writer.rb +1 -1
- data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/incompatibility.rb +4 -4
- data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/package.rb +1 -1
- data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/partial_solution.rb +1 -1
- data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/rubygems.rb +3 -3
- data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/solve_failure.rb +1 -1
- data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/static_package_source.rb +3 -3
- data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/strategy.rb +2 -2
- data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/term.rb +1 -1
- data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/version.rb +1 -1
- data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/version_constraint.rb +3 -3
- data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/version_range.rb +1 -1
- data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/version_solver.rb +2 -2
- data/lib/{bundler → rubygems}/vendor/pub_grub/lib/pub_grub/version_union.rb +1 -1
- data/lib/rubygems/vendor/pub_grub/lib/pub_grub.rb +57 -0
- data/lib/{bundler → rubygems}/vendor/securerandom/lib/securerandom.rb +10 -6
- data/lib/{bundler → rubygems}/vendor/uri/lib/uri/common.rb +119 -119
- data/lib/{bundler → rubygems}/vendor/uri/lib/uri/file.rb +13 -13
- data/lib/{bundler → rubygems}/vendor/uri/lib/uri/ftp.rb +24 -24
- data/lib/{bundler → rubygems}/vendor/uri/lib/uri/generic.rb +132 -132
- data/lib/{bundler → rubygems}/vendor/uri/lib/uri/http.rb +18 -18
- data/lib/{bundler → rubygems}/vendor/uri/lib/uri/https.rb +4 -4
- data/lib/{bundler → rubygems}/vendor/uri/lib/uri/ldap.rb +14 -14
- data/lib/{bundler → rubygems}/vendor/uri/lib/uri/ldaps.rb +4 -4
- data/lib/{bundler → rubygems}/vendor/uri/lib/uri/mailto.rb +21 -21
- data/lib/{bundler → rubygems}/vendor/uri/lib/uri/rfc2396_parser.rb +39 -39
- data/lib/{bundler → rubygems}/vendor/uri/lib/uri/rfc3986_parser.rb +14 -14
- data/lib/{bundler → rubygems}/vendor/uri/lib/uri/version.rb +1 -1
- data/lib/{bundler → rubygems}/vendor/uri/lib/uri/ws.rb +12 -12
- data/lib/{bundler → rubygems}/vendor/uri/lib/uri/wss.rb +4 -4
- data/lib/{bundler → rubygems}/vendor/uri/lib/uri.rb +35 -31
- data/lib/rubygems/yaml_serializer.rb +880 -0
- metadata +79 -70
- data/CHANGELOG.md +0 -5749
- data/LICENSE.md +0 -22
- data/README.md +0 -58
- data/lib/bundler/compact_index_client/cache.rb +0 -107
- data/lib/bundler/compact_index_client/cache_file.rb +0 -148
- data/lib/bundler/compact_index_client/parser.rb +0 -87
- data/lib/bundler/compact_index_client/updater.rb +0 -105
- data/lib/bundler/compact_index_client.rb +0 -92
- data/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb +0 -227
- data/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb +0 -3
- data/lib/bundler/vendor/connection_pool/lib/connection_pool/wrapper.rb +0 -56
- data/lib/bundler/vendor/connection_pool/lib/connection_pool.rb +0 -230
- data/lib/bundler/vendor/net-http-persistent/README.rdoc +0 -82
- data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/connection.rb +0 -41
- data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/pool.rb +0 -65
- data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/timed_stack_multi.rb +0 -80
- data/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +0 -1153
- data/lib/bundler/vendor/pub_grub/lib/pub_grub.rb +0 -31
- data/lib/bundler/vendored_persistent.rb +0 -11
- data/lib/bundler/yaml_serializer.rb +0 -98
- /data/lib/{bundler → rubygems}/vendor/pub_grub/LICENSE.txt +0 -0
- /data/lib/{bundler → rubygems}/vendor/securerandom/COPYING +0 -0
- /data/lib/{bundler → rubygems}/vendor/uri/COPYING +0 -0
data/lib/bundler/errors.rb
CHANGED
|
@@ -131,7 +131,8 @@ module Bundler
|
|
|
131
131
|
attr_reader :orig_exception
|
|
132
132
|
|
|
133
133
|
def initialize(orig_exception, msg)
|
|
134
|
-
full_message = msg + "\nGem Load Error is:
|
|
134
|
+
full_message = msg + "\nGem Load Error is:
|
|
135
|
+
#{orig_exception.full_message(highlight: false)}\n"\
|
|
135
136
|
"Backtrace for gem load error is:\n"\
|
|
136
137
|
"#{orig_exception.backtrace.join("\n")}\n"\
|
|
137
138
|
"Bundler Error Backtrace:\n"
|
|
@@ -221,7 +222,9 @@ module Bundler
|
|
|
221
222
|
class DirectoryRemovalError < BundlerError
|
|
222
223
|
def initialize(orig_exception, msg)
|
|
223
224
|
full_message = "#{msg}.\n" \
|
|
224
|
-
"The underlying error was #{orig_exception.class}:
|
|
225
|
+
"The underlying error was #{orig_exception.class}:
|
|
226
|
+
#{orig_exception.full_message(highlight: false)},
|
|
227
|
+
with backtrace:\n" \
|
|
225
228
|
" #{orig_exception.backtrace.join("\n ")}\n\n" \
|
|
226
229
|
"Bundler Error Backtrace:"
|
|
227
230
|
super(full_message)
|
|
@@ -262,14 +265,40 @@ module Bundler
|
|
|
262
265
|
class InvalidArgumentError < BundlerError; status_code(40); end
|
|
263
266
|
|
|
264
267
|
class IncorrectLockfileDependencies < BundlerError
|
|
265
|
-
attr_reader :spec
|
|
268
|
+
attr_reader :spec, :actual_dependencies, :lockfile_dependencies
|
|
266
269
|
|
|
267
|
-
def initialize(spec)
|
|
270
|
+
def initialize(spec, actual_dependencies = nil, lockfile_dependencies = nil)
|
|
268
271
|
@spec = spec
|
|
272
|
+
@actual_dependencies = actual_dependencies
|
|
273
|
+
@lockfile_dependencies = lockfile_dependencies
|
|
269
274
|
end
|
|
270
275
|
|
|
271
276
|
def message
|
|
272
|
-
"Bundler found incorrect dependencies in the lockfile for #{spec.full_name}"
|
|
277
|
+
lines = ["Bundler found incorrect dependencies in the lockfile for #{spec.full_name}", ""]
|
|
278
|
+
|
|
279
|
+
if @actual_dependencies && @lockfile_dependencies
|
|
280
|
+
actual_by_name = @actual_dependencies.each_with_object({}) {|d, h| h[d.name] = d }
|
|
281
|
+
lockfile_by_name = @lockfile_dependencies.each_with_object({}) {|d, h| h[d.name] = d }
|
|
282
|
+
|
|
283
|
+
(actual_by_name.keys | lockfile_by_name.keys).sort.each do |name|
|
|
284
|
+
actual = actual_by_name[name]
|
|
285
|
+
lockfile = lockfile_by_name[name]
|
|
286
|
+
next if actual && lockfile && actual.requirement == lockfile.requirement
|
|
287
|
+
|
|
288
|
+
if actual && lockfile
|
|
289
|
+
lines << " #{name}: gemspec specifies #{actual.requirement}, lockfile has #{lockfile.requirement}"
|
|
290
|
+
elsif actual
|
|
291
|
+
lines << " #{name}: gemspec specifies #{actual.requirement}, not in lockfile"
|
|
292
|
+
else
|
|
293
|
+
lines << " #{name}: not in gemspec, lockfile has #{lockfile.requirement}"
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
lines << ""
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
lines << "Please run `bundle install` to regenerate the lockfile."
|
|
301
|
+
lines.join("\n")
|
|
273
302
|
end
|
|
274
303
|
|
|
275
304
|
status_code(41)
|
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative "base"
|
|
4
4
|
require_relative "../worker"
|
|
5
|
+
require "rubygems/compact_index_client"
|
|
6
|
+
|
|
7
|
+
# Route the client's filesystem access through Bundler's helper so
|
|
8
|
+
# permission problems raise friendly Bundler errors. The respond_to?
|
|
9
|
+
# check covers a host RubyGems that already loaded its own copy of the
|
|
10
|
+
# client from before the hook existed.
|
|
11
|
+
if Gem::CompactIndexClient.respond_to?(:filesystem_access=)
|
|
12
|
+
Gem::CompactIndexClient.filesystem_access = Bundler::SharedHelpers.method(:filesystem_access)
|
|
13
|
+
end
|
|
5
14
|
|
|
6
15
|
module Bundler
|
|
7
16
|
class Fetcher
|
|
@@ -11,12 +20,12 @@ module Bundler
|
|
|
11
20
|
undef_method(method_name)
|
|
12
21
|
define_method(method_name) do |*args, &blk|
|
|
13
22
|
method.bind_call(self, *args, &blk)
|
|
14
|
-
rescue NetworkDownError, CompactIndexClient::Updater::MismatchedChecksumError => e
|
|
23
|
+
rescue NetworkDownError, Gem::CompactIndexClient::Updater::MismatchedChecksumError => e
|
|
15
24
|
raise HTTPError, e.message
|
|
16
25
|
rescue AuthenticationRequiredError, BadAuthenticationError
|
|
17
26
|
# Fail since we got a 401 from the server.
|
|
18
27
|
raise
|
|
19
|
-
rescue HTTPError => e
|
|
28
|
+
rescue HTTPError, Gem::CompactIndexClient::Error => e
|
|
20
29
|
Bundler.ui.trace(e)
|
|
21
30
|
nil
|
|
22
31
|
end
|
|
@@ -35,7 +44,7 @@ module Bundler
|
|
|
35
44
|
until remaining_gems.empty?
|
|
36
45
|
log_specs { "Looking up gems #{remaining_gems.inspect}" }
|
|
37
46
|
deps = fetch_gem_infos(remaining_gems).flatten(1)
|
|
38
|
-
next_gems = deps.flat_map {|d| d[CompactIndexClient::INFO_DEPS].flat_map(&:first) }.uniq
|
|
47
|
+
next_gems = deps.flat_map {|d| d[Gem::CompactIndexClient::INFO_DEPS].flat_map(&:first) }.uniq
|
|
39
48
|
deps.each {|dep| gem_info << dep }
|
|
40
49
|
complete_gems.concat(deps.map(&:first)).uniq!
|
|
41
50
|
remaining_gems = next_gems - complete_gems
|
|
@@ -53,7 +62,7 @@ module Bundler
|
|
|
53
62
|
end
|
|
54
63
|
# Read info file checksums out of /versions, so we can know if gems are up to date
|
|
55
64
|
compact_index_client.available?
|
|
56
|
-
rescue CompactIndexClient::Updater::MismatchedChecksumError => e
|
|
65
|
+
rescue Gem::CompactIndexClient::Updater::MismatchedChecksumError => e
|
|
57
66
|
Bundler.ui.debug(e.message)
|
|
58
67
|
nil
|
|
59
68
|
end
|
|
@@ -75,7 +84,7 @@ module Bundler
|
|
|
75
84
|
def compact_index_client
|
|
76
85
|
@compact_index_client ||=
|
|
77
86
|
SharedHelpers.filesystem_access(cache_path) do
|
|
78
|
-
CompactIndexClient.new(cache_path, client_fetcher)
|
|
87
|
+
Gem::CompactIndexClient.new(cache_path, client_fetcher)
|
|
79
88
|
end
|
|
80
89
|
end
|
|
81
90
|
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rubygems/request"
|
|
4
|
+
require "rubygems/remote_fetcher"
|
|
5
|
+
|
|
6
|
+
module Bundler
|
|
7
|
+
class Fetcher
|
|
8
|
+
# Hands out pools of configured Gem::Net::HTTP connections, compatible
|
|
9
|
+
# with the checkout/checkin interface that Gem::Request expects.
|
|
10
|
+
# Connection policy (proxy, SSL, timeouts) follows Bundler settings
|
|
11
|
+
# first, falling back to RubyGems configuration.
|
|
12
|
+
class ConnectionPools
|
|
13
|
+
# A fixed-size pool of connections to a single host, sharing the
|
|
14
|
+
# interface of Gem::Request::HTTPPool.
|
|
15
|
+
class Pool
|
|
16
|
+
attr_reader :cert_files, :proxy_uri
|
|
17
|
+
|
|
18
|
+
def initialize(connections, uri, proxy_uri, size)
|
|
19
|
+
@connections = connections
|
|
20
|
+
@uri = uri
|
|
21
|
+
@proxy_uri = proxy_uri
|
|
22
|
+
@cert_files = connections.cert_files
|
|
23
|
+
@queue = Thread::SizedQueue.new(size)
|
|
24
|
+
size.times { @queue.push(nil) }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def checkout
|
|
28
|
+
@queue.pop || @connections.build_connection(@uri, @proxy_uri)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def checkin(connection)
|
|
32
|
+
@queue.push(connection)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
attr_reader :override_headers, :cert_files
|
|
37
|
+
|
|
38
|
+
def initialize(size:, timeout:)
|
|
39
|
+
@size = size
|
|
40
|
+
@timeout = timeout
|
|
41
|
+
@override_headers = {}
|
|
42
|
+
@cert_files = Gem::Request.get_cert_files
|
|
43
|
+
@pools = {}
|
|
44
|
+
@pool_mutex = Thread::Mutex.new
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Performs a GET request through Gem::Request, which handles resetting
|
|
48
|
+
# and retrying stale connections, and returns the raw response.
|
|
49
|
+
def request(uri, headers = nil)
|
|
50
|
+
Gem::Request.new(uri, Gem::Net::HTTP::Get, nil, pool_for(uri)).fetch do |request|
|
|
51
|
+
@override_headers.each {|key, value| request[key] = value }
|
|
52
|
+
headers&.each {|key, value| request[key] = value }
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def pool_for(uri)
|
|
57
|
+
key = [uri.scheme, uri.hostname, uri.port]
|
|
58
|
+
@pool_mutex.synchronize do
|
|
59
|
+
@pools[key] ||= Pool.new(self, uri, proxy_for(uri), @size)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# The proxy that will be used for +uri+, or nil. RubyGems configuration
|
|
64
|
+
# takes precedence over the environment, like Gem::RemoteFetcher.
|
|
65
|
+
# Unlike Gem::Request, an https URI falls back to `http_proxy` when no
|
|
66
|
+
# https-specific proxy is set, which is what the previous
|
|
67
|
+
# net-http-persistent based transport did.
|
|
68
|
+
def proxy_for(uri)
|
|
69
|
+
proxy = if config_proxy = Gem.configuration[:http_proxy]
|
|
70
|
+
Gem::Request.proxy_uri(config_proxy)
|
|
71
|
+
else
|
|
72
|
+
env_proxy_for(uri)
|
|
73
|
+
end
|
|
74
|
+
return unless proxy
|
|
75
|
+
# NO_PROXY="*" bypasses the proxy for every host, which
|
|
76
|
+
# Gem::URI::Generic.use_proxy? does not understand.
|
|
77
|
+
return if no_proxy_env.strip == "*"
|
|
78
|
+
return unless Gem::URI::Generic.use_proxy?(uri.hostname, nil, uri.port, no_proxy_env)
|
|
79
|
+
proxy
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def build_connection(uri, proxy_uri) # :nodoc:
|
|
83
|
+
args = [uri.hostname, uri.port]
|
|
84
|
+
args += if proxy_uri
|
|
85
|
+
[proxy_uri.hostname, proxy_uri.port,
|
|
86
|
+
Gem::UriFormatter.new(proxy_uri.user).unescape,
|
|
87
|
+
Gem::UriFormatter.new(proxy_uri.password).unescape]
|
|
88
|
+
else
|
|
89
|
+
[nil, nil]
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
connection = Gem::Request::ConnectionPools.client.new(*args)
|
|
93
|
+
configure_ssl(connection) if uri.scheme == "https"
|
|
94
|
+
connection.open_timeout = @timeout
|
|
95
|
+
connection.read_timeout = @timeout
|
|
96
|
+
# Stale connections are already resent by Gem::Request#perform_request,
|
|
97
|
+
# and Bundler::Retry retries whole requests, so the Gem::Net::HTTP
|
|
98
|
+
# level retry would only multiply the time spent on a timing out host.
|
|
99
|
+
connection.max_retries = 0
|
|
100
|
+
connection.start
|
|
101
|
+
connection
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
private
|
|
105
|
+
|
|
106
|
+
def env_proxy_for(uri)
|
|
107
|
+
proxy = Gem::Request.get_proxy_from_env(uri.scheme)
|
|
108
|
+
proxy = Gem::Request.get_proxy_from_env("http") if proxy == :no_proxy && uri.scheme == "https"
|
|
109
|
+
proxy == :no_proxy ? nil : proxy
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def no_proxy_env
|
|
113
|
+
ENV["no_proxy"] || ENV["NO_PROXY"] || ""
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def configure_ssl(connection)
|
|
117
|
+
connection.use_ssl = true
|
|
118
|
+
connection.verify_mode = Bundler.settings[:ssl_verify_mode] || OpenSSL::SSL::VERIFY_PEER
|
|
119
|
+
connection.cert_store = bundler_cert_store
|
|
120
|
+
|
|
121
|
+
ssl_client_cert = Bundler.settings[:ssl_client_cert] ||
|
|
122
|
+
(Gem.configuration.ssl_client_cert if
|
|
123
|
+
Gem.configuration.respond_to?(:ssl_client_cert))
|
|
124
|
+
return unless ssl_client_cert
|
|
125
|
+
|
|
126
|
+
pem = File.read(ssl_client_cert)
|
|
127
|
+
connection.cert = OpenSSL::X509::Certificate.new(pem)
|
|
128
|
+
connection.key = OpenSSL::PKey.read(pem)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def bundler_cert_store
|
|
132
|
+
store = OpenSSL::X509::Store.new
|
|
133
|
+
ssl_ca_cert = Bundler.settings[:ssl_ca_cert] ||
|
|
134
|
+
(Gem.configuration.ssl_ca_cert if
|
|
135
|
+
Gem.configuration.respond_to?(:ssl_ca_cert))
|
|
136
|
+
if ssl_ca_cert
|
|
137
|
+
if File.directory? ssl_ca_cert
|
|
138
|
+
store.add_path ssl_ca_cert
|
|
139
|
+
else
|
|
140
|
+
store.add_file ssl_ca_cert
|
|
141
|
+
end
|
|
142
|
+
else
|
|
143
|
+
store.set_default_paths
|
|
144
|
+
cert_files.each {|c| store.add_file c }
|
|
145
|
+
end
|
|
146
|
+
store
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
@@ -6,14 +6,19 @@ module Bundler
|
|
|
6
6
|
HTTP_NON_RETRYABLE_ERRORS = [
|
|
7
7
|
SocketError,
|
|
8
8
|
Errno::EADDRNOTAVAIL,
|
|
9
|
+
Errno::ECONNREFUSED,
|
|
10
|
+
Errno::EHOSTDOWN,
|
|
11
|
+
Errno::EHOSTUNREACH,
|
|
9
12
|
Errno::ENETDOWN,
|
|
10
13
|
Errno::ENETUNREACH,
|
|
11
|
-
Gem::Net::HTTP::Persistent::Error,
|
|
12
|
-
Errno::EHOSTUNREACH,
|
|
13
14
|
].freeze
|
|
14
15
|
|
|
16
|
+
# The vendored net-http raises Gem::Timeout::Error, but when Gem::Net is
|
|
17
|
+
# the real Net (hosts without a vendored net-http), timeouts are plain
|
|
18
|
+
# Timeout::Error subclasses instead.
|
|
15
19
|
HTTP_RETRYABLE_ERRORS = [
|
|
16
20
|
Gem::Timeout::Error,
|
|
21
|
+
*(::Timeout::Error if defined?(::Timeout::Error)),
|
|
17
22
|
EOFError,
|
|
18
23
|
Errno::EINVAL,
|
|
19
24
|
Errno::ECONNRESET,
|
|
@@ -25,11 +30,11 @@ module Bundler
|
|
|
25
30
|
Zlib::BufError,
|
|
26
31
|
].freeze
|
|
27
32
|
|
|
28
|
-
attr_reader :
|
|
33
|
+
attr_reader :connections
|
|
29
34
|
attr_reader :redirect_limit
|
|
30
35
|
|
|
31
|
-
def initialize(
|
|
32
|
-
@
|
|
36
|
+
def initialize(connections, redirect_limit)
|
|
37
|
+
@connections = connections
|
|
33
38
|
@redirect_limit = redirect_limit
|
|
34
39
|
end
|
|
35
40
|
|
|
@@ -46,6 +51,11 @@ module Bundler
|
|
|
46
51
|
response
|
|
47
52
|
when Gem::Net::HTTPRedirection
|
|
48
53
|
new_uri = Gem::URI.parse(response["location"])
|
|
54
|
+
# Following a downgrade would put the credentials this request carries
|
|
55
|
+
# on a plaintext connection, so refuse it like Gem::RemoteFetcher does.
|
|
56
|
+
if https?(uri) && !https?(new_uri)
|
|
57
|
+
raise HTTPError, "Redirecting to a non-https URI is not allowed: #{URICredentialsFilter.credential_filtered_uri(new_uri)}"
|
|
58
|
+
end
|
|
49
59
|
if new_uri.host == uri.host
|
|
50
60
|
new_uri.user = uri.user
|
|
51
61
|
new_uri.password = uri.password
|
|
@@ -79,23 +89,25 @@ module Bundler
|
|
|
79
89
|
filtered_uri = URICredentialsFilter.credential_filtered_uri(uri)
|
|
80
90
|
|
|
81
91
|
Bundler.ui.debug "HTTP GET #{filtered_uri}"
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
92
|
+
connections.request(uri, headers)
|
|
93
|
+
rescue Gem::RemoteFetcher::FetchError => e
|
|
94
|
+
Bundler.ui.trace e
|
|
95
|
+
|
|
96
|
+
case e.message
|
|
97
|
+
when /certificate verify failed/
|
|
98
|
+
raise CertificateFailureError.new(uri)
|
|
99
|
+
when /host is down|host down/i
|
|
100
|
+
raise network_down_error(uri, filtered_uri)
|
|
101
|
+
else
|
|
102
|
+
raise HTTPError, "Network error while fetching #{filtered_uri}" \
|
|
103
|
+
" (#{e})"
|
|
87
104
|
end
|
|
88
|
-
connection.request(uri, req)
|
|
89
105
|
rescue OpenSSL::SSL::SSLError
|
|
90
106
|
raise CertificateFailureError.new(uri)
|
|
91
107
|
rescue *HTTP_NON_RETRYABLE_ERRORS => e
|
|
92
108
|
Bundler.ui.trace e
|
|
93
109
|
|
|
94
|
-
|
|
95
|
-
host_port = "#{host}:#{uri.port}"
|
|
96
|
-
host = host_port if filtered_uri.to_s.include?(host_port)
|
|
97
|
-
raise NetworkDownError, "Could not reach host #{host}. Check your network " \
|
|
98
|
-
"connection and try again."
|
|
110
|
+
raise network_down_error(uri, filtered_uri)
|
|
99
111
|
rescue *HTTP_RETRYABLE_ERRORS => e
|
|
100
112
|
Bundler.ui.trace e
|
|
101
113
|
|
|
@@ -105,6 +117,18 @@ module Bundler
|
|
|
105
117
|
|
|
106
118
|
private
|
|
107
119
|
|
|
120
|
+
def network_down_error(uri, filtered_uri)
|
|
121
|
+
host = uri.host
|
|
122
|
+
host_port = "#{host}:#{uri.port}"
|
|
123
|
+
host = host_port if filtered_uri.to_s.include?(host_port)
|
|
124
|
+
NetworkDownError.new("Could not reach host #{host}. Check your network " \
|
|
125
|
+
"connection and try again.")
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def https?(uri)
|
|
129
|
+
uri.scheme&.casecmp("https")&.zero?
|
|
130
|
+
end
|
|
131
|
+
|
|
108
132
|
def validate_uri_scheme!(uri)
|
|
109
133
|
return if /\Ahttps?\z/.match?(uri.scheme)
|
|
110
134
|
raise InvalidOption,
|
data/lib/bundler/fetcher.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative "
|
|
3
|
+
require_relative "vendored_net_http"
|
|
4
4
|
require_relative "vendored_timeout"
|
|
5
5
|
require_relative "vendored_securerandom"
|
|
6
6
|
require "zlib"
|
|
@@ -10,6 +10,7 @@ module Bundler
|
|
|
10
10
|
class Fetcher
|
|
11
11
|
autoload :Base, File.expand_path("fetcher/base", __dir__)
|
|
12
12
|
autoload :CompactIndex, File.expand_path("fetcher/compact_index", __dir__)
|
|
13
|
+
autoload :ConnectionPools, File.expand_path("fetcher/connection_pools", __dir__)
|
|
13
14
|
autoload :Downloader, File.expand_path("fetcher/downloader", __dir__)
|
|
14
15
|
autoload :Dependency, File.expand_path("fetcher/dependency", __dir__)
|
|
15
16
|
autoload :Index, File.expand_path("fetcher/index", __dir__)
|
|
@@ -137,7 +138,7 @@ module Bundler
|
|
|
137
138
|
@remote = remote
|
|
138
139
|
|
|
139
140
|
Socket.do_not_reverse_lookup = true
|
|
140
|
-
connection #
|
|
141
|
+
connection # set up the connection pools eagerly so SSL support is checked upfront
|
|
141
142
|
end
|
|
142
143
|
|
|
143
144
|
def uri
|
|
@@ -176,13 +177,13 @@ module Bundler
|
|
|
176
177
|
def specs(gem_names, source)
|
|
177
178
|
index = Bundler::Index.new
|
|
178
179
|
|
|
179
|
-
fetch_specs(gem_names).each do |name, version,
|
|
180
|
+
fetch_specs(gem_names).each do |name, version, suffix, dependencies, metadata|
|
|
180
181
|
spec = if dependencies
|
|
181
|
-
EndpointSpecification.new(name, version,
|
|
182
|
+
EndpointSpecification.new(name, version, suffix, self, dependencies, metadata).tap do |es|
|
|
182
183
|
source.checksum_store.replace(es, es.checksum)
|
|
183
184
|
end
|
|
184
185
|
else
|
|
185
|
-
RemoteSpecification.new(name, version,
|
|
186
|
+
RemoteSpecification.new(name, version, suffix, self)
|
|
186
187
|
end
|
|
187
188
|
spec.source = source
|
|
188
189
|
spec.remote = @remote
|
|
@@ -237,7 +238,7 @@ module Bundler
|
|
|
237
238
|
end
|
|
238
239
|
|
|
239
240
|
def http_proxy
|
|
240
|
-
return unless uri = connection.
|
|
241
|
+
return unless uri = connection.proxy_for(remote_uri)
|
|
241
242
|
uri.to_s
|
|
242
243
|
end
|
|
243
244
|
|
|
@@ -307,28 +308,7 @@ module Bundler
|
|
|
307
308
|
end
|
|
308
309
|
end
|
|
309
310
|
|
|
310
|
-
con =
|
|
311
|
-
if gem_proxy = Gem.configuration[:http_proxy]
|
|
312
|
-
con.proxy = Gem::URI.parse(gem_proxy) if gem_proxy != :no_proxy
|
|
313
|
-
end
|
|
314
|
-
|
|
315
|
-
if remote_uri.scheme == "https"
|
|
316
|
-
con.verify_mode = (Bundler.settings[:ssl_verify_mode] ||
|
|
317
|
-
OpenSSL::SSL::VERIFY_PEER)
|
|
318
|
-
con.cert_store = bundler_cert_store
|
|
319
|
-
end
|
|
320
|
-
|
|
321
|
-
ssl_client_cert = Bundler.settings[:ssl_client_cert] ||
|
|
322
|
-
(Gem.configuration.ssl_client_cert if
|
|
323
|
-
Gem.configuration.respond_to?(:ssl_client_cert))
|
|
324
|
-
if ssl_client_cert
|
|
325
|
-
pem = File.read(ssl_client_cert)
|
|
326
|
-
con.cert = OpenSSL::X509::Certificate.new(pem)
|
|
327
|
-
con.key = OpenSSL::PKey.read(pem)
|
|
328
|
-
end
|
|
329
|
-
|
|
330
|
-
con.read_timeout = Fetcher.api_timeout
|
|
331
|
-
con.open_timeout = Fetcher.api_timeout
|
|
311
|
+
con = ConnectionPools.new(size: Bundler.settings.processor_count, timeout: Fetcher.api_timeout)
|
|
332
312
|
con.override_headers["User-Agent"] = user_agent
|
|
333
313
|
con.override_headers["X-Gemfile-Source"] = @remote.original_uri.to_s if @remote.original_uri
|
|
334
314
|
con
|
|
@@ -341,25 +321,6 @@ module Bundler
|
|
|
341
321
|
paths.find {|path| File.file? path }
|
|
342
322
|
end
|
|
343
323
|
|
|
344
|
-
def bundler_cert_store
|
|
345
|
-
store = OpenSSL::X509::Store.new
|
|
346
|
-
ssl_ca_cert = Bundler.settings[:ssl_ca_cert] ||
|
|
347
|
-
(Gem.configuration.ssl_ca_cert if
|
|
348
|
-
Gem.configuration.respond_to?(:ssl_ca_cert))
|
|
349
|
-
if ssl_ca_cert
|
|
350
|
-
if File.directory? ssl_ca_cert
|
|
351
|
-
store.add_path ssl_ca_cert
|
|
352
|
-
else
|
|
353
|
-
store.add_file ssl_ca_cert
|
|
354
|
-
end
|
|
355
|
-
else
|
|
356
|
-
store.set_default_paths
|
|
357
|
-
require "rubygems/request"
|
|
358
|
-
Gem::Request.get_cert_files.each {|c| store.add_file c }
|
|
359
|
-
end
|
|
360
|
-
store
|
|
361
|
-
end
|
|
362
|
-
|
|
363
324
|
def remote_uri
|
|
364
325
|
@remote.uri
|
|
365
326
|
end
|
data/lib/bundler/gem_helper.rb
CHANGED
|
@@ -32,7 +32,7 @@ module Bundler
|
|
|
32
32
|
|
|
33
33
|
def initialize(base = nil, name = nil)
|
|
34
34
|
@base = File.expand_path(base || SharedHelpers.pwd)
|
|
35
|
-
gemspecs = name ? [File.join(@base, "#{name}.gemspec")] :
|
|
35
|
+
gemspecs = name ? [File.join(@base, "#{name}.gemspec")] : SharedHelpers.glob_files_in_dir("{,*}.gemspec", @base)
|
|
36
36
|
raise "Unable to determine name from existing gemspec. Use :name => 'gemname' in #install_tasks to manually set it." unless gemspecs.size == 1
|
|
37
37
|
@spec_path = gemspecs.first
|
|
38
38
|
@gemspec = Bundler.load_gemspec(@spec_path)
|
|
@@ -124,7 +124,7 @@ module Bundler
|
|
|
124
124
|
end
|
|
125
125
|
|
|
126
126
|
def built_gem_path
|
|
127
|
-
|
|
127
|
+
SharedHelpers.glob_files_in_dir("#{name}-*.gem", base).sort_by {|f| File.mtime(f) }.last
|
|
128
128
|
end
|
|
129
129
|
|
|
130
130
|
def git_push(remote = nil)
|
data/lib/bundler/injector.rb
CHANGED
data/lib/bundler/inline.rb
CHANGED
|
@@ -62,13 +62,52 @@ def gemfile(force_latest_compatible = false, options = {}, &gemfile)
|
|
|
62
62
|
definition.validate_runtime!
|
|
63
63
|
|
|
64
64
|
if force_latest_compatible || definition.missing_specs?
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
do_install = -> do
|
|
66
|
+
Bundler.settings.temporary(inline: true, no_install: false) do
|
|
67
|
+
installer = Bundler::Installer.install(Bundler.root, definition, system: true)
|
|
68
|
+
installer.post_install_messages.each do |name, message|
|
|
69
|
+
Bundler.ui.info "Post-install message from #{name}:\n#{message}"
|
|
70
|
+
end
|
|
69
71
|
end
|
|
70
72
|
end
|
|
73
|
+
|
|
74
|
+
# When possible we do the install in a subprocess because to install
|
|
75
|
+
# gems we need to require some default gems like `securerandom` etc
|
|
76
|
+
# which may later conflict with the Gemfile requirements.
|
|
77
|
+
installed_in_fork = false
|
|
78
|
+
if Process.respond_to?(:fork)
|
|
79
|
+
Gem.load_yaml # Avoid NameError on Ruby 3.2's safe_yaml.rb after Gem::Specification.reset
|
|
80
|
+
_, status = Process.waitpid2(Process.fork do
|
|
81
|
+
$VERBOSE = nil
|
|
82
|
+
do_install.call end)
|
|
83
|
+
exit(status.exitstatus || status.to_i) unless status.success?
|
|
84
|
+
|
|
85
|
+
installed_in_fork = true
|
|
86
|
+
|
|
87
|
+
Bundler.reset!
|
|
88
|
+
Gem::Specification.reset
|
|
89
|
+
Bundler.instance_variable_set(:@bundle_path, Pathname.new(Gem.dir))
|
|
90
|
+
|
|
91
|
+
builder = Bundler::Dsl.new
|
|
92
|
+
builder.instance_eval(&gemfile)
|
|
93
|
+
builder.check_primary_source_safety
|
|
94
|
+
|
|
95
|
+
definition = builder.to_definition(nil, true)
|
|
96
|
+
definition.validate_runtime!
|
|
97
|
+
else
|
|
98
|
+
do_install.call
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
configure_forked_definition = ->(d) do
|
|
103
|
+
d.sources.rubygems_sources.each(&:remote!)
|
|
104
|
+
d.sources.git_sources.each do |source|
|
|
105
|
+
source.cached!
|
|
106
|
+
source.instance_variable_set(:@copied, true)
|
|
107
|
+
end
|
|
108
|
+
def d.lock(*); end
|
|
71
109
|
end
|
|
110
|
+
configure_forked_definition.call(definition) if installed_in_fork
|
|
72
111
|
|
|
73
112
|
begin
|
|
74
113
|
runtime = Bundler::Runtime.new(nil, definition).setup
|
|
@@ -84,6 +123,7 @@ def gemfile(force_latest_compatible = false, options = {}, &gemfile)
|
|
|
84
123
|
builder.dependencies.delete_if {|d| d.name == name }
|
|
85
124
|
builder.instance_eval { gem name, activated_version }
|
|
86
125
|
definition = builder.to_definition(nil, true)
|
|
126
|
+
configure_forked_definition.call(definition) if installed_in_fork
|
|
87
127
|
|
|
88
128
|
retry
|
|
89
129
|
end
|
|
@@ -20,10 +20,6 @@ module Bundler
|
|
|
20
20
|
state == :installed
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
def enqueued?
|
|
24
|
-
state == :enqueued
|
|
25
|
-
end
|
|
26
|
-
|
|
27
23
|
def enqueue_with_priority?
|
|
28
24
|
state == :installable && spec.extensions.any?
|
|
29
25
|
end
|
|
@@ -100,7 +96,8 @@ module Bundler
|
|
|
100
96
|
handle_error if failed_specs.any?
|
|
101
97
|
@specs
|
|
102
98
|
ensure
|
|
103
|
-
worker_pool&.stop
|
|
99
|
+
@worker_pool&.stop
|
|
100
|
+
@download_worker_pool&.stop
|
|
104
101
|
end
|
|
105
102
|
|
|
106
103
|
private
|
|
@@ -170,17 +167,18 @@ module Bundler
|
|
|
170
167
|
end
|
|
171
168
|
end
|
|
172
169
|
|
|
170
|
+
def download_worker_pool
|
|
171
|
+
@download_worker_pool ||= Bundler::Worker.new(@size, "Gem Downloader",
|
|
172
|
+
->(spec_install, worker_num) { do_download(spec_install, worker_num) }, response_queue: response_queue)
|
|
173
|
+
end
|
|
174
|
+
|
|
173
175
|
def worker_pool
|
|
174
|
-
@worker_pool ||= Bundler::Worker.new
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
else
|
|
181
|
-
spec_install
|
|
182
|
-
end
|
|
183
|
-
}
|
|
176
|
+
@worker_pool ||= Bundler::Worker.new(@size, "Parallel Installer",
|
|
177
|
+
->(spec_install, worker_num) { do_install(spec_install, worker_num) }, response_queue: response_queue)
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def response_queue
|
|
181
|
+
@response_queue ||= Thread::Queue.new
|
|
184
182
|
end
|
|
185
183
|
|
|
186
184
|
def do_download(spec_install, worker_num)
|
|
@@ -218,24 +216,24 @@ module Bundler
|
|
|
218
216
|
spec_install
|
|
219
217
|
end
|
|
220
218
|
|
|
221
|
-
#
|
|
222
|
-
#
|
|
223
|
-
#
|
|
224
|
-
# processed so the call to `enqueue_specs` is important after every
|
|
225
|
-
# dequeue.
|
|
219
|
+
# Process one completed download or installation. Downloads can finish
|
|
220
|
+
# before their dependencies are installed, so check all downloaded specs
|
|
221
|
+
# after each completion and enqueue any that are now installable.
|
|
226
222
|
def process_specs(installed_specs)
|
|
227
223
|
spec = worker_pool.deq
|
|
228
224
|
|
|
229
225
|
if spec.installed?
|
|
230
226
|
installed_specs[spec.name] = true
|
|
231
|
-
return
|
|
232
227
|
elsif spec.failed?
|
|
233
228
|
return
|
|
234
|
-
elsif spec.ready_to_install?(installed_specs)
|
|
235
|
-
spec.state = :installable
|
|
236
229
|
end
|
|
237
230
|
|
|
238
|
-
|
|
231
|
+
@specs.each do |candidate|
|
|
232
|
+
next unless candidate.ready_to_install?(installed_specs)
|
|
233
|
+
|
|
234
|
+
candidate.state = :installable
|
|
235
|
+
worker_pool.enq(candidate, priority: candidate.enqueue_with_priority?)
|
|
236
|
+
end
|
|
239
237
|
end
|
|
240
238
|
|
|
241
239
|
def finished_installing?
|
|
@@ -274,11 +272,8 @@ module Bundler
|
|
|
274
272
|
t
|
|
275
273
|
end
|
|
276
274
|
|
|
277
|
-
#
|
|
278
|
-
#
|
|
279
|
-
# Later we call this lambda again to install specs that depended on
|
|
280
|
-
# previously installed specifications. We continue until all specs
|
|
281
|
-
# are installed.
|
|
275
|
+
# Queue every missing spec for download. `process_specs` schedules each
|
|
276
|
+
# downloaded spec for installation once its dependencies are installed.
|
|
282
277
|
def enqueue_specs(installed_specs)
|
|
283
278
|
@specs.each do |spec|
|
|
284
279
|
if spec.installed?
|
|
@@ -287,7 +282,7 @@ module Bundler
|
|
|
287
282
|
end
|
|
288
283
|
|
|
289
284
|
spec.state = :enqueued
|
|
290
|
-
|
|
285
|
+
download_worker_pool.enq spec
|
|
291
286
|
end
|
|
292
287
|
end
|
|
293
288
|
end
|