bundler 4.0.21 → 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 +23 -6
- 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/gem.rb +0 -17
- data/lib/bundler/cli/install.rb +4 -5
- data/lib/bundler/cli/lock.rb +1 -2
- data/lib/bundler/cli/outdated.rb +8 -3
- data/lib/bundler/cli/pristine.rb +2 -1
- data/lib/bundler/cli/update.rb +21 -12
- data/lib/bundler/cli.rb +14 -11
- data/lib/bundler/definition.rb +61 -24
- data/lib/bundler/dependency.rb +4 -0
- data/lib/bundler/dsl.rb +77 -11
- 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 +31 -16
- data/lib/bundler/fetcher.rb +8 -47
- 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 +3 -3
- data/lib/bundler/man/bundle-lock.1.ronn +5 -5
- data/lib/bundler/man/bundle-open.1 +1 -1
- data/lib/bundler/man/bundle-outdated.1 +1 -1
- data/lib/bundler/man/bundle-platform.1 +1 -1
- 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 +3 -3
- data/lib/bundler/man/bundle-update.1.ronn +3 -5
- data/lib/bundler/man/bundle-version.1 +1 -1
- data/lib/bundler/man/bundle.1 +1 -1
- data/lib/bundler/man/gemfile.5 +45 -1
- data/lib/bundler/man/gemfile.5.ronn +53 -0
- 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 +69 -2
- data/lib/bundler/self_manager.rb +9 -15
- data/lib/bundler/settings.rb +373 -30
- data/lib/bundler/shared_helpers.rb +2 -1
- data/lib/bundler/source/git/git_proxy.rb +2 -10
- data/lib/bundler/source/git.rb +15 -6
- data/lib/bundler/source/path/installer.rb +1 -1
- data/lib/bundler/source/rubygems/remote.rb +10 -5
- data/lib/bundler/source/rubygems.rb +48 -12
- data/lib/bundler/spec_set.rb +16 -4
- data/lib/bundler/stub_specification.rb +2 -1
- 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 +1 -1
- 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 +77 -68
- data/CHANGELOG.md +0 -5784
- 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
|
@@ -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
|
|
|
@@ -84,23 +89,25 @@ module Bundler
|
|
|
84
89
|
filtered_uri = URICredentialsFilter.credential_filtered_uri(uri)
|
|
85
90
|
|
|
86
91
|
Bundler.ui.debug "HTTP GET #{filtered_uri}"
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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})"
|
|
92
104
|
end
|
|
93
|
-
connection.request(uri, req)
|
|
94
105
|
rescue OpenSSL::SSL::SSLError
|
|
95
106
|
raise CertificateFailureError.new(uri)
|
|
96
107
|
rescue *HTTP_NON_RETRYABLE_ERRORS => e
|
|
97
108
|
Bundler.ui.trace e
|
|
98
109
|
|
|
99
|
-
|
|
100
|
-
host_port = "#{host}:#{uri.port}"
|
|
101
|
-
host = host_port if filtered_uri.to_s.include?(host_port)
|
|
102
|
-
raise NetworkDownError, "Could not reach host #{host}. Check your network " \
|
|
103
|
-
"connection and try again."
|
|
110
|
+
raise network_down_error(uri, filtered_uri)
|
|
104
111
|
rescue *HTTP_RETRYABLE_ERRORS => e
|
|
105
112
|
Bundler.ui.trace e
|
|
106
113
|
|
|
@@ -110,6 +117,14 @@ module Bundler
|
|
|
110
117
|
|
|
111
118
|
private
|
|
112
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
|
+
|
|
113
128
|
def https?(uri)
|
|
114
129
|
uri.scheme&.casecmp("https")&.zero?
|
|
115
130
|
end
|
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/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
|
data/lib/bundler/installer.rb
CHANGED
|
@@ -228,18 +228,32 @@ module Bundler
|
|
|
228
228
|
end
|
|
229
229
|
|
|
230
230
|
def ensure_specs_are_compatible!
|
|
231
|
+
overrides = @definition.overrides
|
|
231
232
|
@definition.specs.each do |spec|
|
|
232
|
-
unless spec.
|
|
233
|
-
raise InstallError,
|
|
234
|
-
"which is incompatible with the current version, #{Gem.ruby_version}"
|
|
233
|
+
unless spec.matches_current_ruby_with_overrides?(overrides)
|
|
234
|
+
raise InstallError, incompatibility_message(spec, "requires ruby version #{spec.required_ruby_version}, " \
|
|
235
|
+
"which is incompatible with the current version, #{Gem.ruby_version}")
|
|
235
236
|
end
|
|
236
|
-
unless spec.
|
|
237
|
-
raise InstallError,
|
|
238
|
-
"which is incompatible with the current version, #{Gem.rubygems_version}"
|
|
237
|
+
unless spec.matches_current_rubygems_with_overrides?(overrides)
|
|
238
|
+
raise InstallError, incompatibility_message(spec, "requires rubygems version #{spec.required_rubygems_version}, " \
|
|
239
|
+
"which is incompatible with the current version, #{Gem.rubygems_version}")
|
|
239
240
|
end
|
|
240
241
|
end
|
|
241
242
|
end
|
|
242
243
|
|
|
244
|
+
# Build the error raised when a locked spec can't run on the current Ruby or
|
|
245
|
+
# RubyGems. When the offending spec is a platform-specific variant locked in
|
|
246
|
+
# frozen mode, point users at the fix: re-resolving outside frozen mode adds
|
|
247
|
+
# the Ruby (non platform-specific) fallback variant to the lockfile.
|
|
248
|
+
def incompatibility_message(spec, reason)
|
|
249
|
+
message = "#{spec.full_name} #{reason}"
|
|
250
|
+
return message unless Bundler.frozen_bundle? && spec.platform != Gem::Platform::RUBY
|
|
251
|
+
|
|
252
|
+
message + "\n\nThe lockfile only includes the #{spec.platform} variant of #{spec.name}. " \
|
|
253
|
+
"If a compatible Ruby variant is available, run `bundle install` outside of frozen/deployment mode " \
|
|
254
|
+
"to add it to the lockfile as a fallback, then commit the updated #{SharedHelpers.relative_lockfile_path}."
|
|
255
|
+
end
|
|
256
|
+
|
|
243
257
|
def lock
|
|
244
258
|
@definition.lock
|
|
245
259
|
end
|