bundler 2.6.7 → 2.6.9
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 +25 -0
- data/lib/bundler/build_metadata.rb +1 -1
- data/lib/bundler/cli/doctor/diagnose.rb +167 -0
- data/lib/bundler/cli/doctor/ssl.rb +249 -0
- data/lib/bundler/cli/doctor.rb +27 -155
- data/lib/bundler/cli/issue.rb +2 -2
- data/lib/bundler/cli.rb +2 -11
- data/lib/bundler/definition.rb +73 -56
- data/lib/bundler/friendly_errors.rb +1 -1
- data/lib/bundler/installer.rb +1 -1
- data/lib/bundler/lazy_specification.rb +22 -13
- data/lib/bundler/resolver.rb +10 -6
- data/lib/bundler/spec_set.rb +37 -9
- data/lib/bundler/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 855ce06e8526e58b49de6b5872997ade47beb38288f5cf783ad551417accfa2c
|
4
|
+
data.tar.gz: bfa8b4371917aa0b993a31d9452196c00239de57803b0a233795040be5e158f0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bdf0dab626499ae76ef5fae750d9354c8c064fc19cb4b357de8e11bb1036246d8b0aed7fe12d2dbec3a81745db31b6268c4c4fec14111c5b224c96217834f8d9
|
7
|
+
data.tar.gz: c297223566644f831412d15723e0cd96a1f9d7c9d6d2985596716dd1a00d7b3f386014402403fbefb0fa0805e36662de35268bd3b2ab7168ce08f1ee34a31f29
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,28 @@
|
|
1
|
+
# 2.6.9 (May 13, 2025)
|
2
|
+
|
3
|
+
## Enhancements:
|
4
|
+
|
5
|
+
- Fix doctor command parsing of otool output [#8665](https://github.com/rubygems/rubygems/pull/8665)
|
6
|
+
- Add SSL troubleshooting to `bundle doctor` [#8624](https://github.com/rubygems/rubygems/pull/8624)
|
7
|
+
- Let `bundle lock --normalize-platforms` remove invalid platforms [#8631](https://github.com/rubygems/rubygems/pull/8631)
|
8
|
+
|
9
|
+
## Bug fixes:
|
10
|
+
|
11
|
+
- Fix `bundle lock` sometimes allowing invalid platforms into the lockfile [#8630](https://github.com/rubygems/rubygems/pull/8630)
|
12
|
+
- Fix false positive warning about insecure materialization in frozen mode [#8629](https://github.com/rubygems/rubygems/pull/8629)
|
13
|
+
|
14
|
+
# 2.6.8 (April 13, 2025)
|
15
|
+
|
16
|
+
## Enhancements:
|
17
|
+
|
18
|
+
- Refine `bundle update --verbose` logs [#8627](https://github.com/rubygems/rubygems/pull/8627)
|
19
|
+
- Improve bug report instructions [#8607](https://github.com/rubygems/rubygems/pull/8607)
|
20
|
+
|
21
|
+
## Bug fixes:
|
22
|
+
|
23
|
+
- Fix `bundle update` crash in an edge case [#8626](https://github.com/rubygems/rubygems/pull/8626)
|
24
|
+
- Fix `bundle lock --normalize-platforms` regression [#8620](https://github.com/rubygems/rubygems/pull/8620)
|
25
|
+
|
1
26
|
# 2.6.7 (April 3, 2025)
|
2
27
|
|
3
28
|
## Enhancements:
|
@@ -0,0 +1,167 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rbconfig"
|
4
|
+
require "shellwords"
|
5
|
+
|
6
|
+
module Bundler
|
7
|
+
class CLI::Doctor::Diagnose
|
8
|
+
DARWIN_REGEX = /\s+(.+) \(compatibility /
|
9
|
+
LDD_REGEX = /\t\S+ => (\S+) \(\S+\)/
|
10
|
+
|
11
|
+
attr_reader :options
|
12
|
+
|
13
|
+
def initialize(options)
|
14
|
+
@options = options
|
15
|
+
end
|
16
|
+
|
17
|
+
def otool_available?
|
18
|
+
Bundler.which("otool")
|
19
|
+
end
|
20
|
+
|
21
|
+
def ldd_available?
|
22
|
+
Bundler.which("ldd")
|
23
|
+
end
|
24
|
+
|
25
|
+
def dylibs_darwin(path)
|
26
|
+
output = `/usr/bin/otool -L #{path.shellescape}`.chomp
|
27
|
+
dylibs = output.split("\n")[1..-1].filter_map {|l| l.match(DARWIN_REGEX)&.match(1) }.uniq
|
28
|
+
# ignore @rpath and friends
|
29
|
+
dylibs.reject {|dylib| dylib.start_with? "@" }
|
30
|
+
end
|
31
|
+
|
32
|
+
def dylibs_ldd(path)
|
33
|
+
output = `/usr/bin/ldd #{path.shellescape}`.chomp
|
34
|
+
output.split("\n").filter_map do |l|
|
35
|
+
match = l.match(LDD_REGEX)
|
36
|
+
next if match.nil?
|
37
|
+
match.captures[0]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def dylibs(path)
|
42
|
+
case RbConfig::CONFIG["host_os"]
|
43
|
+
when /darwin/
|
44
|
+
return [] unless otool_available?
|
45
|
+
dylibs_darwin(path)
|
46
|
+
when /(linux|solaris|bsd)/
|
47
|
+
return [] unless ldd_available?
|
48
|
+
dylibs_ldd(path)
|
49
|
+
else # Windows, etc.
|
50
|
+
Bundler.ui.warn("Dynamic library check not supported on this platform.")
|
51
|
+
[]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def bundles_for_gem(spec)
|
56
|
+
Dir.glob("#{spec.full_gem_path}/**/*.bundle")
|
57
|
+
end
|
58
|
+
|
59
|
+
def lookup_with_fiddle(path)
|
60
|
+
require "fiddle"
|
61
|
+
Fiddle.dlopen(path)
|
62
|
+
false
|
63
|
+
rescue Fiddle::DLError
|
64
|
+
true
|
65
|
+
end
|
66
|
+
|
67
|
+
def check!
|
68
|
+
require_relative "../check"
|
69
|
+
Bundler::CLI::Check.new({}).run
|
70
|
+
end
|
71
|
+
|
72
|
+
def diagnose_ssl
|
73
|
+
require_relative "ssl"
|
74
|
+
Bundler::CLI::Doctor::SSL.new({}).run
|
75
|
+
end
|
76
|
+
|
77
|
+
def run
|
78
|
+
Bundler.ui.level = "warn" if options[:quiet]
|
79
|
+
Bundler.settings.validate!
|
80
|
+
check!
|
81
|
+
diagnose_ssl if options[:ssl]
|
82
|
+
|
83
|
+
definition = Bundler.definition
|
84
|
+
broken_links = {}
|
85
|
+
|
86
|
+
definition.specs.each do |spec|
|
87
|
+
bundles_for_gem(spec).each do |bundle|
|
88
|
+
bad_paths = dylibs(bundle).select do |f|
|
89
|
+
lookup_with_fiddle(f)
|
90
|
+
end
|
91
|
+
if bad_paths.any?
|
92
|
+
broken_links[spec] ||= []
|
93
|
+
broken_links[spec].concat(bad_paths)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
permissions_valid = check_home_permissions
|
99
|
+
|
100
|
+
if broken_links.any?
|
101
|
+
message = "The following gems are missing OS dependencies:"
|
102
|
+
broken_links.flat_map do |spec, paths|
|
103
|
+
paths.uniq.map do |path|
|
104
|
+
"\n * #{spec.name}: #{path}"
|
105
|
+
end
|
106
|
+
end.sort.each {|m| message += m }
|
107
|
+
raise ProductionError, message
|
108
|
+
elsif permissions_valid
|
109
|
+
Bundler.ui.info "No issues found with the installed bundle"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
|
115
|
+
def check_home_permissions
|
116
|
+
require "find"
|
117
|
+
files_not_readable = []
|
118
|
+
files_not_readable_and_owned_by_different_user = []
|
119
|
+
files_not_owned_by_current_user_but_still_readable = []
|
120
|
+
broken_symlinks = []
|
121
|
+
Find.find(Bundler.bundle_path.to_s).each do |f|
|
122
|
+
if !File.exist?(f)
|
123
|
+
broken_symlinks << f
|
124
|
+
elsif !File.readable?(f)
|
125
|
+
if File.stat(f).uid != Process.uid
|
126
|
+
files_not_readable_and_owned_by_different_user << f
|
127
|
+
else
|
128
|
+
files_not_readable << f
|
129
|
+
end
|
130
|
+
elsif File.stat(f).uid != Process.uid
|
131
|
+
files_not_owned_by_current_user_but_still_readable << f
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
ok = true
|
136
|
+
|
137
|
+
if broken_symlinks.any?
|
138
|
+
Bundler.ui.warn "Broken links exist in the Bundler home. Please report them to the offending gem's upstream repo. These files are:\n - #{broken_symlinks.join("\n - ")}"
|
139
|
+
|
140
|
+
ok = false
|
141
|
+
end
|
142
|
+
|
143
|
+
if files_not_owned_by_current_user_but_still_readable.any?
|
144
|
+
Bundler.ui.warn "Files exist in the Bundler home that are owned by another " \
|
145
|
+
"user, but are still readable. These files are:\n - #{files_not_owned_by_current_user_but_still_readable.join("\n - ")}"
|
146
|
+
|
147
|
+
ok = false
|
148
|
+
end
|
149
|
+
|
150
|
+
if files_not_readable_and_owned_by_different_user.any?
|
151
|
+
Bundler.ui.warn "Files exist in the Bundler home that are owned by another " \
|
152
|
+
"user, and are not readable. These files are:\n - #{files_not_readable_and_owned_by_different_user.join("\n - ")}"
|
153
|
+
|
154
|
+
ok = false
|
155
|
+
end
|
156
|
+
|
157
|
+
if files_not_readable.any?
|
158
|
+
Bundler.ui.warn "Files exist in the Bundler home that are not " \
|
159
|
+
"readable by the current user. These files are:\n - #{files_not_readable.join("\n - ")}"
|
160
|
+
|
161
|
+
ok = false
|
162
|
+
end
|
163
|
+
|
164
|
+
ok
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
@@ -0,0 +1,249 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rubygems/remote_fetcher"
|
4
|
+
require "uri"
|
5
|
+
|
6
|
+
module Bundler
|
7
|
+
class CLI::Doctor::SSL
|
8
|
+
attr_reader :options
|
9
|
+
|
10
|
+
def initialize(options)
|
11
|
+
@options = options
|
12
|
+
end
|
13
|
+
|
14
|
+
def run
|
15
|
+
return unless openssl_installed?
|
16
|
+
|
17
|
+
output_ssl_environment
|
18
|
+
bundler_success = bundler_connection_successful?
|
19
|
+
rubygem_success = rubygem_connection_successful?
|
20
|
+
|
21
|
+
return unless net_http_connection_successful?
|
22
|
+
|
23
|
+
Explanation.summarize(bundler_success, rubygem_success, host)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def host
|
29
|
+
@options[:host] || "rubygems.org"
|
30
|
+
end
|
31
|
+
|
32
|
+
def tls_version
|
33
|
+
@options[:"tls-version"].then do |version|
|
34
|
+
"TLS#{version.sub(".", "_")}".to_sym if version
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def verify_mode
|
39
|
+
mode = @options[:"verify-mode"] || :peer
|
40
|
+
|
41
|
+
@verify_mode ||= mode.then {|mod| OpenSSL::SSL.const_get("verify_#{mod}".upcase) }
|
42
|
+
end
|
43
|
+
|
44
|
+
def uri
|
45
|
+
@uri ||= URI("https://#{host}")
|
46
|
+
end
|
47
|
+
|
48
|
+
def openssl_installed?
|
49
|
+
require "openssl"
|
50
|
+
|
51
|
+
true
|
52
|
+
rescue LoadError
|
53
|
+
Bundler.ui.warn(<<~MSG)
|
54
|
+
Oh no! Your Ruby doesn't have OpenSSL, so it can't connect to #{host}.
|
55
|
+
You'll need to recompile or reinstall Ruby with OpenSSL support and try again.
|
56
|
+
MSG
|
57
|
+
|
58
|
+
false
|
59
|
+
end
|
60
|
+
|
61
|
+
def output_ssl_environment
|
62
|
+
Bundler.ui.info(<<~MESSAGE)
|
63
|
+
Here's your OpenSSL environment:
|
64
|
+
|
65
|
+
OpenSSL: #{OpenSSL::VERSION}
|
66
|
+
Compiled with: #{OpenSSL::OPENSSL_VERSION}
|
67
|
+
Loaded with: #{OpenSSL::OPENSSL_LIBRARY_VERSION}
|
68
|
+
MESSAGE
|
69
|
+
end
|
70
|
+
|
71
|
+
def bundler_connection_successful?
|
72
|
+
Bundler.ui.info("\nTrying connections to #{uri}:\n")
|
73
|
+
|
74
|
+
bundler_uri = Gem::URI(uri.to_s)
|
75
|
+
Bundler::Fetcher.new(
|
76
|
+
Bundler::Source::Rubygems::Remote.new(bundler_uri)
|
77
|
+
).send(:connection).request(bundler_uri)
|
78
|
+
|
79
|
+
Bundler.ui.info("Bundler: success")
|
80
|
+
|
81
|
+
true
|
82
|
+
rescue StandardError => error
|
83
|
+
Bundler.ui.warn("Bundler: failed (#{Explanation.explain_bundler_or_rubygems_error(error)})")
|
84
|
+
|
85
|
+
false
|
86
|
+
end
|
87
|
+
|
88
|
+
def rubygem_connection_successful?
|
89
|
+
Gem::RemoteFetcher.fetcher.fetch_path(uri)
|
90
|
+
Bundler.ui.info("RubyGems: success")
|
91
|
+
|
92
|
+
true
|
93
|
+
rescue StandardError => error
|
94
|
+
Bundler.ui.warn("RubyGems: failed (#{Explanation.explain_bundler_or_rubygems_error(error)})")
|
95
|
+
|
96
|
+
false
|
97
|
+
end
|
98
|
+
|
99
|
+
def net_http_connection_successful?
|
100
|
+
::Gem::Net::HTTP.new(uri.host, uri.port).tap do |http|
|
101
|
+
http.use_ssl = true
|
102
|
+
http.min_version = tls_version
|
103
|
+
http.max_version = tls_version
|
104
|
+
http.verify_mode = verify_mode
|
105
|
+
end.start
|
106
|
+
|
107
|
+
Bundler.ui.info("Ruby net/http: success")
|
108
|
+
warn_on_unsupported_tls12
|
109
|
+
|
110
|
+
true
|
111
|
+
rescue StandardError => error
|
112
|
+
Bundler.ui.warn(<<~MSG)
|
113
|
+
Ruby net/http: failed
|
114
|
+
|
115
|
+
Unfortunately, this Ruby can't connect to #{host}.
|
116
|
+
|
117
|
+
#{Explanation.explain_net_http_error(error, host, tls_version)}
|
118
|
+
MSG
|
119
|
+
|
120
|
+
false
|
121
|
+
end
|
122
|
+
|
123
|
+
def warn_on_unsupported_tls12
|
124
|
+
ctx = OpenSSL::SSL::SSLContext.new
|
125
|
+
supported = true
|
126
|
+
|
127
|
+
if ctx.respond_to?(:min_version=)
|
128
|
+
begin
|
129
|
+
ctx.min_version = ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION
|
130
|
+
rescue OpenSSL::SSL::SSLError, NameError
|
131
|
+
supported = false
|
132
|
+
end
|
133
|
+
else
|
134
|
+
supported = OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1_2) # rubocop:disable Naming/VariableNumber
|
135
|
+
end
|
136
|
+
|
137
|
+
Bundler.ui.warn(<<~EOM) unless supported
|
138
|
+
|
139
|
+
WARNING: Although your Ruby can connect to #{host} today, your OpenSSL is very old!
|
140
|
+
WARNING: You will need to upgrade OpenSSL to use #{host}.
|
141
|
+
|
142
|
+
EOM
|
143
|
+
end
|
144
|
+
|
145
|
+
module Explanation
|
146
|
+
extend self
|
147
|
+
|
148
|
+
def explain_bundler_or_rubygems_error(error)
|
149
|
+
case error.message
|
150
|
+
when /certificate verify failed/
|
151
|
+
"certificate verification"
|
152
|
+
when /read server hello A/
|
153
|
+
"SSL/TLS protocol version mismatch"
|
154
|
+
when /tlsv1 alert protocol version/
|
155
|
+
"requested TLS version is too old"
|
156
|
+
else
|
157
|
+
error.message
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def explain_net_http_error(error, host, tls_version)
|
162
|
+
case error.message
|
163
|
+
# Check for certificate errors
|
164
|
+
when /certificate verify failed/
|
165
|
+
<<~MSG
|
166
|
+
#{show_ssl_certs}
|
167
|
+
Your Ruby can't connect to #{host} because you are missing the certificate files OpenSSL needs to verify you are connecting to the genuine #{host} servers.
|
168
|
+
MSG
|
169
|
+
# Check for TLS version errors
|
170
|
+
when /read server hello A/, /tlsv1 alert protocol version/
|
171
|
+
if tls_version.to_s == "TLS1_3"
|
172
|
+
"Your Ruby can't connect to #{host} because #{tls_version} isn't supported yet.\n"
|
173
|
+
else
|
174
|
+
<<~MSG
|
175
|
+
Your Ruby can't connect to #{host} because your version of OpenSSL is too old.
|
176
|
+
You'll need to upgrade your OpenSSL install and/or recompile Ruby to use a newer OpenSSL.
|
177
|
+
MSG
|
178
|
+
end
|
179
|
+
# OpenSSL doesn't support TLS version specified by argument
|
180
|
+
when /unknown SSL method/
|
181
|
+
"Your Ruby can't connect because #{tls_version} isn't supported by your version of OpenSSL."
|
182
|
+
else
|
183
|
+
<<~MSG
|
184
|
+
Even worse, we're not sure why.
|
185
|
+
|
186
|
+
Here's the full error information:
|
187
|
+
#{error.class}: #{error.message}
|
188
|
+
#{error.backtrace.join("\n ")}
|
189
|
+
|
190
|
+
You might have more luck using Mislav's SSL doctor.rb script. You can get it here:
|
191
|
+
https://github.com/mislav/ssl-tools/blob/8b3dec4/doctor.rb
|
192
|
+
|
193
|
+
Read more about the script and how to use it in this blog post:
|
194
|
+
https://mislav.net/2013/07/ruby-openssl/
|
195
|
+
MSG
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def summarize(bundler_success, rubygems_success, host)
|
200
|
+
guide_url = "http://ruby.to/ssl-check-failed"
|
201
|
+
|
202
|
+
message = if bundler_success && rubygems_success
|
203
|
+
<<~MSG
|
204
|
+
Hooray! This Ruby can connect to #{host}.
|
205
|
+
You are all set to use Bundler and RubyGems.
|
206
|
+
|
207
|
+
MSG
|
208
|
+
elsif !bundler_success && !rubygems_success
|
209
|
+
<<~MSG
|
210
|
+
For some reason, your Ruby installation can connect to #{host}, but neither RubyGems nor Bundler can.
|
211
|
+
The most likely fix is to manually upgrade RubyGems by following the instructions at #{guide_url}.
|
212
|
+
After you've done that, run `gem install bundler` to upgrade Bundler, and then run this script again to make sure everything worked. ❣
|
213
|
+
|
214
|
+
MSG
|
215
|
+
elsif !bundler_success
|
216
|
+
<<~MSG
|
217
|
+
Although your Ruby installation and RubyGems can both connect to #{host}, Bundler is having trouble.
|
218
|
+
The most likely way to fix this is to upgrade Bundler by running `gem install bundler`.
|
219
|
+
Run this script again after doing that to make sure everything is all set.
|
220
|
+
If you're still having trouble, check out the troubleshooting guide at #{guide_url}.
|
221
|
+
|
222
|
+
MSG
|
223
|
+
else
|
224
|
+
<<~MSG
|
225
|
+
It looks like Ruby and Bundler can connect to #{host}, but RubyGems itself cannot.
|
226
|
+
You can likely solve this by manually downloading and installing a RubyGems update.
|
227
|
+
Visit #{guide_url} for instructions on how to manually upgrade RubyGems.
|
228
|
+
|
229
|
+
MSG
|
230
|
+
end
|
231
|
+
|
232
|
+
Bundler.ui.info("\n#{message}")
|
233
|
+
end
|
234
|
+
|
235
|
+
private
|
236
|
+
|
237
|
+
def show_ssl_certs
|
238
|
+
ssl_cert_file = ENV["SSL_CERT_FILE"] || OpenSSL::X509::DEFAULT_CERT_FILE
|
239
|
+
ssl_cert_dir = ENV["SSL_CERT_DIR"] || OpenSSL::X509::DEFAULT_CERT_DIR
|
240
|
+
|
241
|
+
<<~MSG
|
242
|
+
Below affect only Ruby net/http connections:
|
243
|
+
SSL_CERT_FILE: #{File.exist?(ssl_cert_file) ? "exists #{ssl_cert_file}" : "is missing #{ssl_cert_file}"}
|
244
|
+
SSL_CERT_DIR: #{Dir.exist?(ssl_cert_dir) ? "exists #{ssl_cert_dir}" : "is missing #{ssl_cert_dir}"}
|
245
|
+
MSG
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
data/lib/bundler/cli/doctor.rb
CHANGED
@@ -1,161 +1,33 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "rbconfig"
|
4
|
-
require "shellwords"
|
5
|
-
|
6
3
|
module Bundler
|
7
|
-
class CLI::Doctor
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
output.split("\n").filter_map do |l|
|
35
|
-
match = l.match(LDD_REGEX)
|
36
|
-
next if match.nil?
|
37
|
-
match.captures[0]
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def dylibs(path)
|
42
|
-
case RbConfig::CONFIG["host_os"]
|
43
|
-
when /darwin/
|
44
|
-
return [] unless otool_available?
|
45
|
-
dylibs_darwin(path)
|
46
|
-
when /(linux|solaris|bsd)/
|
47
|
-
return [] unless ldd_available?
|
48
|
-
dylibs_ldd(path)
|
49
|
-
else # Windows, etc.
|
50
|
-
Bundler.ui.warn("Dynamic library check not supported on this platform.")
|
51
|
-
[]
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def bundles_for_gem(spec)
|
56
|
-
Dir.glob("#{spec.full_gem_path}/**/*.bundle")
|
57
|
-
end
|
58
|
-
|
59
|
-
def lookup_with_fiddle(path)
|
60
|
-
require "fiddle"
|
61
|
-
Fiddle.dlopen(path)
|
62
|
-
false
|
63
|
-
rescue Fiddle::DLError
|
64
|
-
true
|
65
|
-
end
|
66
|
-
|
67
|
-
def check!
|
68
|
-
require_relative "check"
|
69
|
-
Bundler::CLI::Check.new({}).run
|
70
|
-
end
|
71
|
-
|
72
|
-
def run
|
73
|
-
Bundler.ui.level = "warn" if options[:quiet]
|
74
|
-
Bundler.settings.validate!
|
75
|
-
check!
|
76
|
-
|
77
|
-
definition = Bundler.definition
|
78
|
-
broken_links = {}
|
79
|
-
|
80
|
-
definition.specs.each do |spec|
|
81
|
-
bundles_for_gem(spec).each do |bundle|
|
82
|
-
bad_paths = dylibs(bundle).select do |f|
|
83
|
-
lookup_with_fiddle(f)
|
84
|
-
end
|
85
|
-
if bad_paths.any?
|
86
|
-
broken_links[spec] ||= []
|
87
|
-
broken_links[spec].concat(bad_paths)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
permissions_valid = check_home_permissions
|
93
|
-
|
94
|
-
if broken_links.any?
|
95
|
-
message = "The following gems are missing OS dependencies:"
|
96
|
-
broken_links.flat_map do |spec, paths|
|
97
|
-
paths.uniq.map do |path|
|
98
|
-
"\n * #{spec.name}: #{path}"
|
99
|
-
end
|
100
|
-
end.sort.each {|m| message += m }
|
101
|
-
raise ProductionError, message
|
102
|
-
elsif permissions_valid
|
103
|
-
Bundler.ui.info "No issues found with the installed bundle"
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
private
|
108
|
-
|
109
|
-
def check_home_permissions
|
110
|
-
require "find"
|
111
|
-
files_not_readable = []
|
112
|
-
files_not_readable_and_owned_by_different_user = []
|
113
|
-
files_not_owned_by_current_user_but_still_readable = []
|
114
|
-
broken_symlinks = []
|
115
|
-
Find.find(Bundler.bundle_path.to_s).each do |f|
|
116
|
-
if !File.exist?(f)
|
117
|
-
broken_symlinks << f
|
118
|
-
elsif !File.readable?(f)
|
119
|
-
if File.stat(f).uid != Process.uid
|
120
|
-
files_not_readable_and_owned_by_different_user << f
|
121
|
-
else
|
122
|
-
files_not_readable << f
|
123
|
-
end
|
124
|
-
elsif File.stat(f).uid != Process.uid
|
125
|
-
files_not_owned_by_current_user_but_still_readable << f
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
|
-
ok = true
|
130
|
-
|
131
|
-
if broken_symlinks.any?
|
132
|
-
Bundler.ui.warn "Broken links exist in the Bundler home. Please report them to the offending gem's upstream repo. These files are:\n - #{broken_symlinks.join("\n - ")}"
|
133
|
-
|
134
|
-
ok = false
|
135
|
-
end
|
136
|
-
|
137
|
-
if files_not_owned_by_current_user_but_still_readable.any?
|
138
|
-
Bundler.ui.warn "Files exist in the Bundler home that are owned by another " \
|
139
|
-
"user, but are still readable. These files are:\n - #{files_not_owned_by_current_user_but_still_readable.join("\n - ")}"
|
140
|
-
|
141
|
-
ok = false
|
142
|
-
end
|
143
|
-
|
144
|
-
if files_not_readable_and_owned_by_different_user.any?
|
145
|
-
Bundler.ui.warn "Files exist in the Bundler home that are owned by another " \
|
146
|
-
"user, and are not readable. These files are:\n - #{files_not_readable_and_owned_by_different_user.join("\n - ")}"
|
147
|
-
|
148
|
-
ok = false
|
149
|
-
end
|
150
|
-
|
151
|
-
if files_not_readable.any?
|
152
|
-
Bundler.ui.warn "Files exist in the Bundler home that are not " \
|
153
|
-
"readable by the current user. These files are:\n - #{files_not_readable.join("\n - ")}"
|
154
|
-
|
155
|
-
ok = false
|
156
|
-
end
|
157
|
-
|
158
|
-
ok
|
4
|
+
class CLI::Doctor < Thor
|
5
|
+
default_command(:diagnose)
|
6
|
+
|
7
|
+
desc "diagnose [OPTIONS]", "Checks the bundle for common problems"
|
8
|
+
long_desc <<-D
|
9
|
+
Doctor scans the OS dependencies of each of the gems requested in the Gemfile. If
|
10
|
+
missing dependencies are detected, Bundler prints them and exits status 1.
|
11
|
+
Otherwise, Bundler prints a success message and exits with a status of 0.
|
12
|
+
D
|
13
|
+
method_option "gemfile", type: :string, banner: "Use the specified gemfile instead of Gemfile"
|
14
|
+
method_option "quiet", type: :boolean, banner: "Only output warnings and errors."
|
15
|
+
method_option "ssl", type: :boolean, default: false, banner: "Diagnose SSL problems."
|
16
|
+
def diagnose
|
17
|
+
require_relative "doctor/diagnose"
|
18
|
+
Diagnose.new(options).run
|
19
|
+
end
|
20
|
+
|
21
|
+
desc "ssl [OPTIONS]", "Diagnose SSL problems"
|
22
|
+
long_desc <<-D
|
23
|
+
Diagnose SSL problems, especially related to certificates or TLS version while connecting to https://rubygems.org.
|
24
|
+
D
|
25
|
+
method_option "host", type: :string, banner: "The host to diagnose."
|
26
|
+
method_option "tls-version", type: :string, banner: "Specify the SSL/TLS version when running the diagnostic. Accepts either <1.1> or <1.2>"
|
27
|
+
method_option "verify-mode", type: :string, banner: "Specify the mode used for certification verification. Accepts either <peer> or <none>"
|
28
|
+
def ssl
|
29
|
+
require_relative "doctor/ssl"
|
30
|
+
SSL.new(options).run
|
159
31
|
end
|
160
32
|
end
|
161
33
|
end
|
data/lib/bundler/cli/issue.rb
CHANGED
data/lib/bundler/cli.rb
CHANGED
@@ -610,17 +610,8 @@ module Bundler
|
|
610
610
|
end
|
611
611
|
|
612
612
|
desc "doctor [OPTIONS]", "Checks the bundle for common problems"
|
613
|
-
|
614
|
-
|
615
|
-
missing dependencies are detected, Bundler prints them and exits status 1.
|
616
|
-
Otherwise, Bundler prints a success message and exits with a status of 0.
|
617
|
-
D
|
618
|
-
method_option "gemfile", type: :string, banner: "Use the specified gemfile instead of Gemfile"
|
619
|
-
method_option "quiet", type: :boolean, banner: "Only output warnings and errors."
|
620
|
-
def doctor
|
621
|
-
require_relative "cli/doctor"
|
622
|
-
Doctor.new(options).run
|
623
|
-
end
|
613
|
+
require_relative "cli/doctor"
|
614
|
+
subcommand("doctor", Doctor)
|
624
615
|
|
625
616
|
desc "issue", "Learn how to report an issue in Bundler"
|
626
617
|
def issue
|
data/lib/bundler/definition.rb
CHANGED
@@ -257,7 +257,7 @@ module Bundler
|
|
257
257
|
rescue BundlerError => e
|
258
258
|
@resolve = nil
|
259
259
|
@resolver = nil
|
260
|
-
@
|
260
|
+
@resolution_base = nil
|
261
261
|
@source_requirements = nil
|
262
262
|
@specs = nil
|
263
263
|
|
@@ -337,11 +337,7 @@ module Bundler
|
|
337
337
|
end
|
338
338
|
end
|
339
339
|
else
|
340
|
-
|
341
|
-
Bundler.ui.debug "Found changes from the lockfile, re-resolving dependencies because #{change_reason}"
|
342
|
-
else
|
343
|
-
Bundler.ui.debug "Resolving dependencies because there's no lockfile"
|
344
|
-
end
|
340
|
+
Bundler.ui.debug resolve_needed_reason
|
345
341
|
|
346
342
|
start_resolution
|
347
343
|
end
|
@@ -465,7 +461,7 @@ module Bundler
|
|
465
461
|
end
|
466
462
|
|
467
463
|
def normalize_platforms
|
468
|
-
|
464
|
+
resolve.normalize_platforms!(current_dependencies, platforms)
|
469
465
|
|
470
466
|
@resolve = SpecSet.new(resolve.for(current_dependencies, @platforms))
|
471
467
|
end
|
@@ -537,9 +533,7 @@ module Bundler
|
|
537
533
|
|
538
534
|
return unless added.any? || deleted.any? || changed.any? || resolve_needed?
|
539
535
|
|
540
|
-
|
541
|
-
|
542
|
-
msg = String.new("#{reason.capitalize.strip}, but ")
|
536
|
+
msg = String.new("#{change_reason.capitalize.strip}, but ")
|
543
537
|
msg << "the lockfile " unless msg.start_with?("Your lockfile")
|
544
538
|
msg << "can't be updated because #{update_refused_reason}"
|
545
539
|
msg << "\n\nYou have added to the Gemfile:\n" << added.join("\n") if added.any?
|
@@ -620,7 +614,7 @@ module Bundler
|
|
620
614
|
end
|
621
615
|
|
622
616
|
def resolver
|
623
|
-
@resolver ||= Resolver.new(
|
617
|
+
@resolver ||= Resolver.new(resolution_base, gem_version_promoter, @most_specific_locked_platform)
|
624
618
|
end
|
625
619
|
|
626
620
|
def expanded_dependencies
|
@@ -634,15 +628,15 @@ module Bundler
|
|
634
628
|
[Dependency.new("bundler", @unlocking_bundler)] + dependencies
|
635
629
|
end
|
636
630
|
|
637
|
-
def
|
638
|
-
@
|
631
|
+
def resolution_base
|
632
|
+
@resolution_base ||= begin
|
639
633
|
last_resolve = converge_locked_specs
|
640
634
|
remove_invalid_platforms!
|
641
635
|
new_resolution_platforms = @current_platform_missing ? @new_platforms + [local_platform] : @new_platforms
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
636
|
+
base = Resolver::Base.new(source_requirements, expanded_dependencies, last_resolve, @platforms, locked_specs: @originally_locked_specs, unlock: @unlocking_all || @gems_to_unlock, prerelease: gem_version_promoter.pre?, prefer_local: @prefer_local, new_platforms: new_resolution_platforms)
|
637
|
+
base = additional_base_requirements_to_prevent_downgrades(base)
|
638
|
+
base = additional_base_requirements_to_force_updates(base)
|
639
|
+
base
|
646
640
|
end
|
647
641
|
end
|
648
642
|
|
@@ -717,8 +711,7 @@ module Bundler
|
|
717
711
|
still_incomplete_specs = resolve.incomplete_specs
|
718
712
|
|
719
713
|
if still_incomplete_specs == incomplete_specs
|
720
|
-
|
721
|
-
resolver.raise_not_found! package
|
714
|
+
resolver.raise_incomplete! incomplete_specs
|
722
715
|
end
|
723
716
|
|
724
717
|
incomplete_specs = still_incomplete_specs
|
@@ -740,7 +733,7 @@ module Bundler
|
|
740
733
|
end
|
741
734
|
|
742
735
|
def reresolve_without(incomplete_specs)
|
743
|
-
|
736
|
+
resolution_base.delete(incomplete_specs)
|
744
737
|
@resolve = start_resolution
|
745
738
|
end
|
746
739
|
|
@@ -753,8 +746,16 @@ module Bundler
|
|
753
746
|
|
754
747
|
@resolved_bundler_version = result.find {|spec| spec.name == "bundler" }&.version
|
755
748
|
|
749
|
+
@new_platforms.each do |platform|
|
750
|
+
incomplete_specs = result.incomplete_specs_for_platform(current_dependencies, platform)
|
751
|
+
|
752
|
+
if incomplete_specs.any?
|
753
|
+
resolver.raise_incomplete! incomplete_specs
|
754
|
+
end
|
755
|
+
end
|
756
|
+
|
756
757
|
if @most_specific_non_local_locked_platform
|
757
|
-
if
|
758
|
+
if result.incomplete_for_platform?(current_dependencies, @most_specific_non_local_locked_platform)
|
758
759
|
@platforms.delete(@most_specific_non_local_locked_platform)
|
759
760
|
elsif local_platform_needed_for_resolvability
|
760
761
|
@platforms.delete(local_platform)
|
@@ -796,22 +797,47 @@ module Bundler
|
|
796
797
|
@most_specific_locked_platform
|
797
798
|
end
|
798
799
|
|
799
|
-
def
|
800
|
-
if
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
800
|
+
def resolve_needed_reason
|
801
|
+
if lockfile_exists?
|
802
|
+
if unlocking?
|
803
|
+
"Re-resolving dependencies because #{unlocking_reason}"
|
804
|
+
else
|
805
|
+
"Found changes from the lockfile, re-resolving dependencies because #{lockfile_changed_reason}"
|
805
806
|
end
|
807
|
+
else
|
808
|
+
"Resolving dependencies because there's no lockfile"
|
809
|
+
end
|
810
|
+
end
|
806
811
|
|
807
|
-
|
808
|
-
|
812
|
+
def change_reason
|
813
|
+
if resolve_needed?
|
814
|
+
if unlocking?
|
815
|
+
unlocking_reason
|
809
816
|
else
|
810
|
-
|
817
|
+
lockfile_changed_reason
|
811
818
|
end
|
819
|
+
else
|
820
|
+
"some dependencies were deleted from your gemfile"
|
821
|
+
end
|
822
|
+
end
|
812
823
|
|
813
|
-
|
824
|
+
def unlocking_reason
|
825
|
+
unlock_targets = if @gems_to_unlock.any?
|
826
|
+
["gems", @gems_to_unlock]
|
827
|
+
elsif @sources_to_unlock.any?
|
828
|
+
["sources", @sources_to_unlock]
|
814
829
|
end
|
830
|
+
|
831
|
+
unlock_reason = if unlock_targets
|
832
|
+
"#{unlock_targets.first}: (#{unlock_targets.last.join(", ")})"
|
833
|
+
else
|
834
|
+
@unlocking_ruby ? "ruby" : ""
|
835
|
+
end
|
836
|
+
|
837
|
+
"bundler is unlocking #{unlock_reason}"
|
838
|
+
end
|
839
|
+
|
840
|
+
def lockfile_changed_reason
|
815
841
|
[
|
816
842
|
[@source_changes, "the list of sources changed"],
|
817
843
|
[@dependency_changes, "the dependencies in your gemfile changed"],
|
@@ -1105,27 +1131,27 @@ module Bundler
|
|
1105
1131
|
current == proposed
|
1106
1132
|
end
|
1107
1133
|
|
1108
|
-
def additional_base_requirements_to_prevent_downgrades(
|
1109
|
-
return
|
1134
|
+
def additional_base_requirements_to_prevent_downgrades(resolution_base)
|
1135
|
+
return resolution_base unless @locked_gems && !sources.expired_sources?(@locked_gems.sources)
|
1110
1136
|
@originally_locked_specs.each do |locked_spec|
|
1111
1137
|
next if locked_spec.source.is_a?(Source::Path)
|
1112
1138
|
|
1113
1139
|
name = locked_spec.name
|
1114
1140
|
next if @changed_dependencies.include?(name)
|
1115
1141
|
|
1116
|
-
|
1142
|
+
resolution_base.base_requirements[name] = Gem::Requirement.new(">= #{locked_spec.version}")
|
1117
1143
|
end
|
1118
|
-
|
1144
|
+
resolution_base
|
1119
1145
|
end
|
1120
1146
|
|
1121
|
-
def additional_base_requirements_to_force_updates(
|
1122
|
-
return
|
1147
|
+
def additional_base_requirements_to_force_updates(resolution_base)
|
1148
|
+
return resolution_base if @explicit_unlocks.empty?
|
1123
1149
|
full_update = dup_for_full_unlock.resolve
|
1124
1150
|
@explicit_unlocks.each do |name|
|
1125
1151
|
version = full_update.version_for(name)
|
1126
|
-
|
1152
|
+
resolution_base.base_requirements[name] = Gem::Requirement.new("= #{version}") if version
|
1127
1153
|
end
|
1128
|
-
|
1154
|
+
resolution_base
|
1129
1155
|
end
|
1130
1156
|
|
1131
1157
|
def dup_for_full_unlock
|
@@ -1142,25 +1168,16 @@ module Bundler
|
|
1142
1168
|
def remove_invalid_platforms!
|
1143
1169
|
return if Bundler.frozen_bundle?
|
1144
1170
|
|
1145
|
-
|
1146
|
-
next if local_platform == platform ||
|
1147
|
-
@new_platforms.include?(platform)
|
1148
|
-
|
1149
|
-
# We should probably avoid removing non-ruby platforms, since that means
|
1150
|
-
# lockfile will no longer install on those platforms, so a error to give
|
1151
|
-
# heads up to the user may be better. However, we have tests expecting
|
1152
|
-
# non ruby platform autoremoval to work, so leaving that in place for
|
1153
|
-
# now.
|
1154
|
-
next if @dependency_changes && platform != Gem::Platform::RUBY
|
1171
|
+
skips = (@new_platforms + [local_platform]).uniq
|
1155
1172
|
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1159
|
-
|
1160
|
-
|
1173
|
+
# We should probably avoid removing non-ruby platforms, since that means
|
1174
|
+
# lockfile will no longer install on those platforms, so a error to give
|
1175
|
+
# heads up to the user may be better. However, we have tests expecting
|
1176
|
+
# non ruby platform autoremoval to work, so leaving that in place for
|
1177
|
+
# now.
|
1178
|
+
skips |= platforms - [Gem::Platform::RUBY] if @dependency_changes
|
1161
1179
|
|
1162
|
-
|
1163
|
-
spec_set.incomplete_for_platform?(current_dependencies, platform)
|
1180
|
+
@originally_invalid_platforms = @originally_locked_specs.remove_invalid_platforms!(current_dependencies, platforms, skips: skips)
|
1164
1181
|
end
|
1165
1182
|
|
1166
1183
|
def source_map
|
@@ -80,7 +80,7 @@ module Bundler
|
|
80
80
|
First, try this link to see if there are any existing issue reports for this error:
|
81
81
|
#{issues_url(e)}
|
82
82
|
|
83
|
-
If there aren't any reports for this error yet, please fill in the new issue form located at #{new_issue_url}
|
83
|
+
If there aren't any reports for this error yet, please fill in the new issue form located at #{new_issue_url}. Make sure to copy and paste the full output of this command under the "What happened instead?" section.
|
84
84
|
EOS
|
85
85
|
end
|
86
86
|
|
data/lib/bundler/installer.rb
CHANGED
@@ -212,7 +212,7 @@ module Bundler
|
|
212
212
|
def load_plugins
|
213
213
|
Gem.load_plugins
|
214
214
|
|
215
|
-
requested_path_gems = @definition.
|
215
|
+
requested_path_gems = @definition.specs.select {|s| s.source.is_a?(Source::Path) }
|
216
216
|
path_plugin_files = requested_path_gems.flat_map do |spec|
|
217
217
|
spec.matches_for_glob("rubygems_plugin#{Bundler.rubygems.suffix_pattern}")
|
218
218
|
rescue TypeError
|
@@ -213,22 +213,31 @@ module Bundler
|
|
213
213
|
end
|
214
214
|
if search.nil? && fallback_to_non_installable
|
215
215
|
search = candidates.last
|
216
|
-
|
217
|
-
# We don't validate locally installed dependencies but accept what's in
|
218
|
-
# the lockfile instead for performance, since loading locally installed
|
219
|
-
# dependencies would mean evaluating all gemspecs, which would affect
|
220
|
-
# `bundler/setup` performance
|
221
|
-
if search.is_a?(StubSpecification)
|
222
|
-
search.dependencies = dependencies
|
223
|
-
else
|
224
|
-
if !source.is_a?(Source::Path) && search.runtime_dependencies.sort != dependencies.sort
|
225
|
-
raise IncorrectLockfileDependencies.new(self)
|
226
|
-
end
|
216
|
+
end
|
227
217
|
|
228
|
-
|
229
|
-
|
218
|
+
if search
|
219
|
+
validate_dependencies(search) if search.platform == platform
|
220
|
+
|
221
|
+
search.locked_platform = platform if search.instance_of?(RemoteSpecification) || search.instance_of?(EndpointSpecification)
|
230
222
|
end
|
231
223
|
search
|
232
224
|
end
|
225
|
+
|
226
|
+
# Validate dependencies of this locked spec are consistent with dependencies
|
227
|
+
# of the actual spec that was materialized.
|
228
|
+
#
|
229
|
+
# Note that we don't validate dependencies of locally installed gems but
|
230
|
+
# accept what's in the lockfile instead for performance, since loading
|
231
|
+
# dependencies of locally installed gems would mean evaluating all gemspecs,
|
232
|
+
# which would affect `bundler/setup` performance.
|
233
|
+
def validate_dependencies(spec)
|
234
|
+
if spec.is_a?(StubSpecification)
|
235
|
+
spec.dependencies = dependencies
|
236
|
+
else
|
237
|
+
if !source.is_a?(Source::Path) && spec.runtime_dependencies.sort != dependencies.sort
|
238
|
+
raise IncorrectLockfileDependencies.new(self)
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
233
242
|
end
|
234
243
|
end
|
data/lib/bundler/resolver.rb
CHANGED
@@ -312,6 +312,16 @@ module Bundler
|
|
312
312
|
"Gemfile"
|
313
313
|
end
|
314
314
|
|
315
|
+
def raise_incomplete!(incomplete_specs)
|
316
|
+
raise_not_found!(@base.get_package(incomplete_specs.first.name))
|
317
|
+
end
|
318
|
+
|
319
|
+
def sort_versions_by_preferred(package, versions)
|
320
|
+
@gem_version_promoter.sort_versions(package, versions)
|
321
|
+
end
|
322
|
+
|
323
|
+
private
|
324
|
+
|
315
325
|
def raise_not_found!(package)
|
316
326
|
name = package.name
|
317
327
|
source = source_for(name)
|
@@ -348,12 +358,6 @@ module Bundler
|
|
348
358
|
raise GemNotFound, message
|
349
359
|
end
|
350
360
|
|
351
|
-
def sort_versions_by_preferred(package, versions)
|
352
|
-
@gem_version_promoter.sort_versions(package, versions)
|
353
|
-
end
|
354
|
-
|
355
|
-
private
|
356
|
-
|
357
361
|
def filtered_versions_for(package)
|
358
362
|
@gem_version_promoter.filter_versions(package, @all_versions[package])
|
359
363
|
end
|
data/lib/bundler/spec_set.rb
CHANGED
@@ -29,9 +29,10 @@ module Bundler
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def normalize_platforms!(deps, platforms)
|
32
|
-
|
32
|
+
remove_invalid_platforms!(deps, platforms)
|
33
|
+
add_extra_platforms!(platforms)
|
33
34
|
|
34
|
-
|
35
|
+
platforms.map! do |platform|
|
35
36
|
next platform if platform == Gem::Platform::RUBY
|
36
37
|
|
37
38
|
begin
|
@@ -44,7 +45,7 @@ module Bundler
|
|
44
45
|
next platform if incomplete_for_platform?(deps, less_specific_platform)
|
45
46
|
|
46
47
|
less_specific_platform
|
47
|
-
end.uniq
|
48
|
+
end.uniq!
|
48
49
|
end
|
49
50
|
|
50
51
|
def add_originally_invalid_platforms!(platforms, originally_invalid_platforms)
|
@@ -53,6 +54,20 @@ module Bundler
|
|
53
54
|
end
|
54
55
|
end
|
55
56
|
|
57
|
+
def remove_invalid_platforms!(deps, platforms, skips: [])
|
58
|
+
invalid_platforms = []
|
59
|
+
|
60
|
+
platforms.reject! do |platform|
|
61
|
+
next false if skips.include?(platform)
|
62
|
+
|
63
|
+
invalid = incomplete_for_platform?(deps, platform)
|
64
|
+
invalid_platforms << platform if invalid
|
65
|
+
invalid
|
66
|
+
end
|
67
|
+
|
68
|
+
invalid_platforms
|
69
|
+
end
|
70
|
+
|
56
71
|
def add_extra_platforms!(platforms)
|
57
72
|
if @specs.empty?
|
58
73
|
platforms.concat([Gem::Platform::RUBY]).uniq
|
@@ -68,6 +83,7 @@ module Bundler
|
|
68
83
|
return if new_platforms.empty?
|
69
84
|
|
70
85
|
platforms.concat(new_platforms)
|
86
|
+
return if new_platforms.include?(Bundler.local_platform)
|
71
87
|
|
72
88
|
less_specific_platform = new_platforms.find {|platform| platform != Gem::Platform::RUBY && Bundler.local_platform === platform && platform === Bundler.local_platform }
|
73
89
|
platforms.delete(Bundler.local_platform) if less_specific_platform
|
@@ -129,12 +145,15 @@ module Bundler
|
|
129
145
|
end
|
130
146
|
|
131
147
|
def incomplete_for_platform?(deps, platform)
|
132
|
-
|
148
|
+
incomplete_specs_for_platform(deps, platform).any?
|
149
|
+
end
|
150
|
+
|
151
|
+
def incomplete_specs_for_platform(deps, platform)
|
152
|
+
return [] if @specs.empty?
|
133
153
|
|
134
154
|
validation_set = self.class.new(@specs)
|
135
155
|
validation_set.for(deps, [platform])
|
136
|
-
|
137
|
-
validation_set.incomplete_specs.any?
|
156
|
+
validation_set.incomplete_specs
|
138
157
|
end
|
139
158
|
|
140
159
|
def missing_specs_for(deps)
|
@@ -180,7 +199,7 @@ module Bundler
|
|
180
199
|
end
|
181
200
|
|
182
201
|
def version_for(name)
|
183
|
-
|
202
|
+
exemplary_spec(name)&.version
|
184
203
|
end
|
185
204
|
|
186
205
|
def what_required(spec)
|
@@ -285,8 +304,13 @@ module Bundler
|
|
285
304
|
end
|
286
305
|
|
287
306
|
def additional_variants_from(other)
|
288
|
-
other.select do |
|
289
|
-
|
307
|
+
other.select do |other_spec|
|
308
|
+
spec = exemplary_spec(other_spec.name)
|
309
|
+
next unless spec
|
310
|
+
|
311
|
+
selected = spec.version == other_spec.version && valid_dependencies?(other_spec)
|
312
|
+
other_spec.source = spec.source if selected
|
313
|
+
selected
|
290
314
|
end
|
291
315
|
end
|
292
316
|
|
@@ -363,5 +387,9 @@ module Bundler
|
|
363
387
|
hash[key] ||= []
|
364
388
|
hash[key] << value
|
365
389
|
end
|
390
|
+
|
391
|
+
def exemplary_spec(name)
|
392
|
+
self[name].first
|
393
|
+
end
|
366
394
|
end
|
367
395
|
end
|
data/lib/bundler/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bundler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.6.
|
4
|
+
version: 2.6.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- André Arko
|
@@ -55,6 +55,8 @@ files:
|
|
55
55
|
- lib/bundler/cli/config.rb
|
56
56
|
- lib/bundler/cli/console.rb
|
57
57
|
- lib/bundler/cli/doctor.rb
|
58
|
+
- lib/bundler/cli/doctor/diagnose.rb
|
59
|
+
- lib/bundler/cli/doctor/ssl.rb
|
58
60
|
- lib/bundler/cli/exec.rb
|
59
61
|
- lib/bundler/cli/fund.rb
|
60
62
|
- lib/bundler/cli/gem.rb
|
@@ -412,7 +414,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
412
414
|
- !ruby/object:Gem::Version
|
413
415
|
version: 3.3.3
|
414
416
|
requirements: []
|
415
|
-
rubygems_version: 3.6.
|
417
|
+
rubygems_version: 3.6.9
|
416
418
|
specification_version: 4
|
417
419
|
summary: The best way to manage your application's dependencies
|
418
420
|
test_files: []
|