summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorHiroshi SHIBATA <hsbt@ruby-lang.org>2021-12-23 09:21:36 +0900
committerHiroshi SHIBATA <hsbt@ruby-lang.org>2021-12-23 09:44:45 +0900
commitfb1ab27f535833f1ba1648d7cdce4cc893e36d07 (patch)
treefab2ac1a60ba75a8e897d6077c8234af2fd77900 /lib
parentfeaf4fbc3fa16382fbd07158c448c7b5bdae78b5 (diff)
Merge RubyGems-3.3.1 and Bundler-2.3.1
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/5325
Diffstat (limited to 'lib')
-rw-r--r--lib/bundler/rubygems_gem_installer.rb2
-rw-r--r--lib/bundler/self_manager.rb5
-rw-r--r--lib/bundler/vendor/thor/lib/thor/actions.rb8
-rw-r--r--lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb12
-rw-r--r--lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb8
-rw-r--r--lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb6
-rw-r--r--lib/bundler/vendor/thor/lib/thor/error.rb13
-rw-r--r--lib/bundler/vendor/thor/lib/thor/parser/options.rb20
-rw-r--r--lib/bundler/vendor/thor/lib/thor/shell.rb2
-rw-r--r--lib/bundler/vendor/thor/lib/thor/shell/basic.rb26
-rw-r--r--lib/bundler/vendor/thor/lib/thor/util.rb2
-rw-r--r--lib/bundler/version.rb2
-rw-r--r--lib/rubygems.rb5
-rw-r--r--lib/rubygems/bundler_version_finder.rb52
-rw-r--r--lib/rubygems/dependency.rb14
-rw-r--r--lib/rubygems/errors.rb3
-rw-r--r--lib/rubygems/security.rb14
-rw-r--r--lib/rubygems/security/policy.rb4
-rw-r--r--lib/rubygems/specification.rb2
19 files changed, 110 insertions, 90 deletions
diff --git a/lib/bundler/rubygems_gem_installer.rb b/lib/bundler/rubygems_gem_installer.rb
index bb9f1cb3f5..452583617b 100644
--- a/lib/bundler/rubygems_gem_installer.rb
+++ b/lib/bundler/rubygems_gem_installer.rb
@@ -67,7 +67,7 @@ module Bundler
def build_extensions
extension_cache_path = options[:bundler_extension_cache_path]
unless extension_cache_path && extension_dir = spec.extension_dir
- require "shellwords" # compensate missing require in rubygems before version 3.2.25
+ require "shellwords" unless Bundler.rubygems.provides?(">= 3.2.25")
return super
end
diff --git a/lib/bundler/self_manager.rb b/lib/bundler/self_manager.rb
index bda2eb51f3..d62ef6ca12 100644
--- a/lib/bundler/self_manager.rb
+++ b/lib/bundler/self_manager.rb
@@ -39,10 +39,13 @@ module Bundler
configured_gem_home = ENV["GEM_HOME"]
configured_gem_path = ENV["GEM_PATH"]
+ cmd = [$PROGRAM_NAME, *ARGV]
+ cmd.unshift(Gem.ruby) unless File.executable?($PROGRAM_NAME)
+
Bundler.with_original_env do
Kernel.exec(
{ "GEM_HOME" => configured_gem_home, "GEM_PATH" => configured_gem_path, "BUNDLER_VERSION" => lockfile_version },
- $PROGRAM_NAME, *ARGV
+ *cmd
)
end
end
diff --git a/lib/bundler/vendor/thor/lib/thor/actions.rb b/lib/bundler/vendor/thor/lib/thor/actions.rb
index de9323b2db..de9b3b4c86 100644
--- a/lib/bundler/vendor/thor/lib/thor/actions.rb
+++ b/lib/bundler/vendor/thor/lib/thor/actions.rb
@@ -161,6 +161,8 @@ class Bundler::Thor
# to the block you provide. The path is set back to the previous path when
# the method exits.
#
+ # Returns the value yielded by the block.
+ #
# ==== Parameters
# dir<String>:: the directory to move to.
# config<Hash>:: give :verbose => true to log and use padding.
@@ -179,16 +181,18 @@ class Bundler::Thor
FileUtils.mkdir_p(destination_root)
end
+ result = nil
if pretend
# In pretend mode, just yield down to the block
- block.arity == 1 ? yield(destination_root) : yield
+ result = block.arity == 1 ? yield(destination_root) : yield
else
require "fileutils"
- FileUtils.cd(destination_root) { block.arity == 1 ? yield(destination_root) : yield }
+ FileUtils.cd(destination_root) { result = block.arity == 1 ? yield(destination_root) : yield }
end
@destination_stack.pop
shell.padding -= 1 if verbose
+ result
end
# Goes to the root and execute the given block.
diff --git a/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb b/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb
index 90a8d2e847..bf2a737c84 100644
--- a/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb
+++ b/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb
@@ -210,9 +210,9 @@ class Bundler::Thor
#
# ==== Examples
#
- # inject_into_class "app/controllers/application_controller.rb", ApplicationController, " filter_parameter :password\n"
+ # inject_into_class "app/controllers/application_controller.rb", "ApplicationController", " filter_parameter :password\n"
#
- # inject_into_class "app/controllers/application_controller.rb", ApplicationController do
+ # inject_into_class "app/controllers/application_controller.rb", "ApplicationController" do
# " filter_parameter :password\n"
# end
#
@@ -233,9 +233,9 @@ class Bundler::Thor
#
# ==== Examples
#
- # inject_into_module "app/helpers/application_helper.rb", ApplicationHelper, " def help; 'help'; end\n"
+ # inject_into_module "app/helpers/application_helper.rb", "ApplicationHelper", " def help; 'help'; end\n"
#
- # inject_into_module "app/helpers/application_helper.rb", ApplicationHelper do
+ # inject_into_module "app/helpers/application_helper.rb", "ApplicationHelper" do
# " def help; 'help'; end\n"
# end
#
@@ -252,7 +252,7 @@ class Bundler::Thor
# flag<Regexp|String>:: the regexp or string to be replaced
# replacement<String>:: the replacement, can be also given as a block
# config<Hash>:: give :verbose => false to not log the status, and
- # :force => true, to force the replacement regardless of runner behavior.
+ # :force => true, to force the replacement regardles of runner behavior.
#
# ==== Example
#
@@ -331,7 +331,7 @@ class Bundler::Thor
path = File.expand_path(path, destination_root)
say_status :remove, relative_to_original_destination_root(path), config.fetch(:verbose, true)
- if !options[:pretend] && File.exist?(path)
+ if !options[:pretend] && (File.exist?(path) || File.symlink?(path))
require "fileutils"
::FileUtils.rm_rf(path)
end
diff --git a/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb b/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb
index 09ce0864f0..f52ced2bcd 100644
--- a/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb
+++ b/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb
@@ -106,12 +106,14 @@ class Bundler::Thor
# Adds the content to the file.
#
def replace!(regexp, string, force)
- return if pretend?
content = File.read(destination)
- if force || !content.include?(replacement)
+ before, after = content.split(regexp, 2)
+ snippet = (behavior == :after ? after : before).to_s
+
+ if force || !snippet.include?(replacement)
success = content.gsub!(regexp, string)
- File.open(destination, "wb") { |file| file.write(content) }
+ File.open(destination, "wb") { |file| file.write(content) } unless pretend?
success
end
end
diff --git a/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb b/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb
index c167aa33b8..3c4483e5dd 100644
--- a/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb
+++ b/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb
@@ -28,6 +28,12 @@ class Bundler::Thor
super(convert_key(key))
end
+ def except(*keys)
+ dup.tap do |hash|
+ keys.each { |key| hash.delete(convert_key(key)) }
+ end
+ end
+
def fetch(key, *args)
super(convert_key(key), *args)
end
diff --git a/lib/bundler/vendor/thor/lib/thor/error.rb b/lib/bundler/vendor/thor/lib/thor/error.rb
index 7d57129b83..03f2ce85bb 100644
--- a/lib/bundler/vendor/thor/lib/thor/error.rb
+++ b/lib/bundler/vendor/thor/lib/thor/error.rb
@@ -102,9 +102,14 @@ class Bundler::Thor
end
if Correctable
- DidYouMean::SPELL_CHECKERS.merge!(
- 'Bundler::Thor::UndefinedCommandError' => UndefinedCommandError::SpellChecker,
- 'Bundler::Thor::UnknownArgumentError' => UnknownArgumentError::SpellChecker
- )
+ if DidYouMean.respond_to?(:correct_error)
+ DidYouMean.correct_error(Bundler::Thor::UndefinedCommandError, UndefinedCommandError::SpellChecker)
+ DidYouMean.correct_error(Bundler::Thor::UnknownArgumentError, UnknownArgumentError::SpellChecker)
+ else
+ DidYouMean::SPELL_CHECKERS.merge!(
+ 'Bundler::Thor::UndefinedCommandError' => UndefinedCommandError::SpellChecker,
+ 'Bundler::Thor::UnknownArgumentError' => UnknownArgumentError::SpellChecker
+ )
+ end
end
end
diff --git a/lib/bundler/vendor/thor/lib/thor/parser/options.rb b/lib/bundler/vendor/thor/lib/thor/parser/options.rb
index 3a8927d09c..5bd97aba6f 100644
--- a/lib/bundler/vendor/thor/lib/thor/parser/options.rb
+++ b/lib/bundler/vendor/thor/lib/thor/parser/options.rb
@@ -45,6 +45,7 @@ class Bundler::Thor
@switches = {}
@extra = []
@stopped_parsing_after_extra_index = nil
+ @is_treated_as_value = false
options.each do |option|
@switches[option.switch_name] = option
@@ -74,8 +75,19 @@ class Bundler::Thor
end
end
+ def shift
+ @is_treated_as_value = false
+ super
+ end
+
+ def unshift(arg, is_value: false)
+ @is_treated_as_value = is_value
+ super(arg)
+ end
+
def parse(args) # rubocop:disable MethodLength
@pile = args.dup
+ @is_treated_as_value = false
@parsing_options = true
while peek
@@ -88,7 +100,10 @@ class Bundler::Thor
when SHORT_SQ_RE
unshift($1.split("").map { |f| "-#{f}" })
next
- when EQ_RE, SHORT_NUM
+ when EQ_RE
+ unshift($2, is_value: true)
+ switch = $1
+ when SHORT_NUM
unshift($2)
switch = $1
when LONG_RE, SHORT_RE
@@ -148,6 +163,7 @@ class Bundler::Thor
# Two booleans are returned. The first is true if the current value
# starts with a hyphen; the second is true if it is a registered switch.
def current_is_switch?
+ return [false, false] if @is_treated_as_value
case peek
when LONG_RE, SHORT_RE, EQ_RE, SHORT_NUM
[true, switch?($1)]
@@ -159,6 +175,7 @@ class Bundler::Thor
end
def current_is_switch_formatted?
+ return false if @is_treated_as_value
case peek
when LONG_RE, SHORT_RE, EQ_RE, SHORT_NUM, SHORT_SQ_RE
true
@@ -168,6 +185,7 @@ class Bundler::Thor
end
def current_is_value?
+ return true if @is_treated_as_value
peek && (!parsing_options? || super)
end
diff --git a/lib/bundler/vendor/thor/lib/thor/shell.rb b/lib/bundler/vendor/thor/lib/thor/shell.rb
index e36fa472d6..a4137d1bde 100644
--- a/lib/bundler/vendor/thor/lib/thor/shell.rb
+++ b/lib/bundler/vendor/thor/lib/thor/shell.rb
@@ -21,7 +21,7 @@ class Bundler::Thor
end
module Shell
- SHELL_DELEGATED_METHODS = [:ask, :error, :set_color, :yes?, :no?, :say, :say_status, :print_in_columns, :print_table, :print_wrapped, :file_collision, :terminal_width]
+ SHELL_DELEGATED_METHODS = [:ask, :error, :set_color, :yes?, :no?, :say, :say_error, :say_status, :print_in_columns, :print_table, :print_wrapped, :file_collision, :terminal_width]
attr_writer :shell
autoload :Basic, File.expand_path("shell/basic", __dir__)
diff --git a/lib/bundler/vendor/thor/lib/thor/shell/basic.rb b/lib/bundler/vendor/thor/lib/thor/shell/basic.rb
index 2dddd4a53a..8eff00bf3d 100644
--- a/lib/bundler/vendor/thor/lib/thor/shell/basic.rb
+++ b/lib/bundler/vendor/thor/lib/thor/shell/basic.rb
@@ -103,6 +103,23 @@ class Bundler::Thor
stdout.flush
end
+ # Say (print) an error to the user. If the sentence ends with a whitespace
+ # or tab character, a new line is not appended (print + flush). Otherwise
+ # are passed straight to puts (behavior got from Highline).
+ #
+ # ==== Example
+ # say_error("error: something went wrong")
+ #
+ def say_error(message = "", color = nil, force_new_line = (message.to_s !~ /( |\t)\Z/))
+ return if quiet?
+
+ buffer = prepare_message(message, *color)
+ buffer << "\n" if force_new_line && !message.to_s.end_with?("\n")
+
+ stderr.print(buffer)
+ stderr.flush
+ end
+
# Say a status with the given color and appends the message. Since this
# method is used frequently by actions, it allows nil or false to be given
# in log_status, avoiding the message from being shown. If a Symbol is
@@ -111,13 +128,14 @@ class Bundler::Thor
def say_status(status, message, log_status = true)
return if quiet? || log_status == false
spaces = " " * (padding + 1)
- color = log_status.is_a?(Symbol) ? log_status : :green
-
status = status.to_s.rjust(12)
+ margin = " " * status.length + spaces
+
+ color = log_status.is_a?(Symbol) ? log_status : :green
status = set_color status, color, true if color
- buffer = "#{status}#{spaces}#{message}"
- buffer = "#{buffer}\n" unless buffer.end_with?("\n")
+ message = message.to_s.chomp.gsub(/(?<!\A)^/, margin)
+ buffer = "#{status}#{spaces}#{message}\n"
stdout.print(buffer)
stdout.flush
diff --git a/lib/bundler/vendor/thor/lib/thor/util.rb b/lib/bundler/vendor/thor/lib/thor/util.rb
index ddf4d21b90..d2572a4249 100644
--- a/lib/bundler/vendor/thor/lib/thor/util.rb
+++ b/lib/bundler/vendor/thor/lib/thor/util.rb
@@ -211,7 +211,7 @@ class Bundler::Thor
#
def globs_for(path)
path = escape_globs(path)
- ["#{path}/Thorfile", "#{path}/*.thor", "#{path}/tasks/*.thor", "#{path}/lib/tasks/*.thor"]
+ ["#{path}/Thorfile", "#{path}/*.thor", "#{path}/tasks/*.thor", "#{path}/lib/tasks/**/*.thor"]
end
# Return the path to the ruby interpreter taking into account multiple
diff --git a/lib/bundler/version.rb b/lib/bundler/version.rb
index d987722f78..bfe7ae7f7c 100644
--- a/lib/bundler/version.rb
+++ b/lib/bundler/version.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: false
module Bundler
- VERSION = "2.3.0".freeze
+ VERSION = "2.3.1".freeze
def self.bundler_major_version
@bundler_major_version ||= VERSION.split(".").first.to_i
diff --git a/lib/rubygems.rb b/lib/rubygems.rb
index a956e06bdb..2e13c589b3 100644
--- a/lib/rubygems.rb
+++ b/lib/rubygems.rb
@@ -8,7 +8,7 @@
require 'rbconfig'
module Gem
- VERSION = "3.3.0".freeze
+ VERSION = "3.3.1".freeze
end
# Must be first since it unloads the prelude from 1.9.2
@@ -272,9 +272,6 @@ module Gem
unless spec = specs.first
msg = "can't find gem #{dep} with executable #{exec_name}"
- if dep.filters_bundler? && bundler_message = Gem::BundlerVersionFinder.missing_version_message
- msg = bundler_message
- end
raise Gem::GemNotFoundException, msg
end
diff --git a/lib/rubygems/bundler_version_finder.rb b/lib/rubygems/bundler_version_finder.rb
index 9ce0a2378e..14179aebf3 100644
--- a/lib/rubygems/bundler_version_finder.rb
+++ b/lib/rubygems/bundler_version_finder.rb
@@ -2,48 +2,18 @@
module Gem::BundlerVersionFinder
def self.bundler_version
- version, _ = bundler_version_with_reason
+ v = ENV["BUNDLER_VERSION"]
- return unless version
+ v ||= bundle_update_bundler_version
+ return if v == true
- Gem::Version.new(version)
- end
-
- def self.bundler_version_with_reason
- if v = ENV["BUNDLER_VERSION"]
- return [v, "`$BUNDLER_VERSION`"]
- end
- if v = bundle_update_bundler_version
- return if v == true
- return [v, "`bundle update --bundler`"]
- end
- v, lockfile = lockfile_version
- if v
- return [v, "your #{lockfile}"]
- end
- end
+ v ||= lockfile_version
+ return unless v
- def self.missing_version_message
- return unless vr = bundler_version_with_reason
- <<-EOS
-Could not find 'bundler' (#{vr.first}) required by #{vr.last}.
-To update to the latest version installed on your system, run `bundle update --bundler`.
-To install the missing version, run `gem install bundler:#{vr.first}`
- EOS
+ Gem::Version.new(v)
end
- def self.compatible?(spec)
- return true unless spec.name == "bundler".freeze
- return true unless bundler_version = self.bundler_version
-
- spec.version.segments.first == bundler_version.segments.first
- end
-
- def self.filter!(specs)
- return unless bundler_version = self.bundler_version
-
- specs.reject! {|spec| spec.version.segments.first != bundler_version.segments.first }
-
+ def self.prioritize!(specs)
exact_match_index = specs.find_index {|spec| spec.version == bundler_version }
return unless exact_match_index
@@ -68,12 +38,10 @@ To install the missing version, run `gem install bundler:#{vr.first}`
private_class_method :bundle_update_bundler_version
def self.lockfile_version
- return unless lockfile = lockfile_contents
- lockfile, contents = lockfile
- lockfile ||= "lockfile"
+ return unless contents = lockfile_contents
regexp = /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
return unless contents =~ regexp
- [$1, lockfile]
+ $1
end
private_class_method :lockfile_version
@@ -103,7 +71,7 @@ To install the missing version, run `gem install bundler:#{vr.first}`
return unless File.file?(lockfile)
- [lockfile, File.read(lockfile)]
+ File.read(lockfile)
end
private_class_method :lockfile_contents
end
diff --git a/lib/rubygems/dependency.rb b/lib/rubygems/dependency.rb
index 3721204ab2..3640362364 100644
--- a/lib/rubygems/dependency.rb
+++ b/lib/rubygems/dependency.rb
@@ -277,7 +277,7 @@ class Gem::Dependency
requirement.satisfied_by?(spec.version) && env_req.satisfied_by?(spec.version)
end.map(&:to_spec)
- Gem::BundlerVersionFinder.filter!(matches) if filters_bundler?
+ Gem::BundlerVersionFinder.prioritize!(matches) if prioritizes_bundler?
if platform_only
matches.reject! do |spec|
@@ -295,7 +295,7 @@ class Gem::Dependency
@requirement.specific?
end
- def filters_bundler?
+ def prioritizes_bundler?
name == "bundler".freeze && !specific?
end
@@ -325,11 +325,11 @@ class Gem::Dependency
active = matches.find {|spec| spec.activated? }
return active if active
- return matches.first if prerelease?
-
- # Move prereleases to the end of the list for >= 0 requirements
- pre, matches = matches.partition {|spec| spec.version.prerelease? }
- matches += pre if requirement == Gem::Requirement.default
+ unless prerelease?
+ # Move prereleases to the end of the list for >= 0 requirements
+ pre, matches = matches.partition {|spec| spec.version.prerelease? }
+ matches += pre if requirement == Gem::Requirement.default
+ end
matches.first
end
diff --git a/lib/rubygems/errors.rb b/lib/rubygems/errors.rb
index 86f0d1da14..f115ce23d0 100644
--- a/lib/rubygems/errors.rb
+++ b/lib/rubygems/errors.rb
@@ -59,9 +59,6 @@ module Gem
private
def build_message
- if name == "bundler" && message = Gem::BundlerVersionFinder.missing_version_message
- return message
- end
names = specs.map(&:full_name)
"Could not find '#{name}' (#{requirement}) - did find: [#{names.join ','}]\n"
end
diff --git a/lib/rubygems/security.rb b/lib/rubygems/security.rb
index 2275997207..f21c175642 100644
--- a/lib/rubygems/security.rb
+++ b/lib/rubygems/security.rb
@@ -424,6 +424,8 @@ module Gem::Security
# Gets the right public key from a PKey instance
def self.get_public_key(key)
+ # Ruby 3.0 (Ruby/OpenSSL 2.2) or later
+ return OpenSSL::PKey.read(key.public_to_der) if key.respond_to?(:public_to_der)
return key.public_key unless key.is_a?(OpenSSL::PKey::EC)
ec_key = OpenSSL::PKey::EC.new(key.group.curve_name)
@@ -490,9 +492,13 @@ module Gem::Security
when 'rsa'
OpenSSL::PKey::RSA.new(RSA_DSA_KEY_LENGTH)
when 'ec'
- domain_key = OpenSSL::PKey::EC.new(EC_NAME)
- domain_key.generate_key
- domain_key
+ if RUBY_VERSION >= "2.4.0"
+ OpenSSL::PKey::EC.generate(EC_NAME)
+ else
+ domain_key = OpenSSL::PKey::EC.new(EC_NAME)
+ domain_key.generate_key
+ domain_key
+ end
else
raise Gem::Security::Exception,
"#{algorithm} algorithm not found. RSA, DSA, and EC algorithms are supported."
@@ -527,7 +533,7 @@ module Gem::Security
raise Gem::Security::Exception,
"incorrect signing key for re-signing " +
"#{expired_certificate.subject}" unless
- expired_certificate.public_key.to_pem == get_public_key(private_key).to_pem
+ expired_certificate.check_private_key(private_key)
unless expired_certificate.subject.to_s ==
expired_certificate.issuer.to_s
diff --git a/lib/rubygems/security/policy.rb b/lib/rubygems/security/policy.rb
index 3c3cb647ee..06eae073f4 100644
--- a/lib/rubygems/security/policy.rb
+++ b/lib/rubygems/security/policy.rb
@@ -115,11 +115,9 @@ class Gem::Security::Policy
raise Gem::Security::Exception, 'missing key or signature'
end
- public_key = Gem::Security.get_public_key(key)
-
raise Gem::Security::Exception,
"certificate #{signer.subject} does not match the signing key" unless
- signer.public_key.to_pem == public_key.to_pem
+ signer.check_private_key(key)
true
end
diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb
index dc5e5ba013..f162eb4a84 100644
--- a/lib/rubygems/specification.rb
+++ b/lib/rubygems/specification.rb
@@ -995,7 +995,6 @@ class Gem::Specification < Gem::BasicSpecification
def self.find_by_path(path)
path = path.dup.freeze
spec = @@spec_with_requirable_file[path] ||= (stubs.find do |s|
- next unless Gem::BundlerVersionFinder.compatible?(s)
s.contains_requirable_file? path
end || NOT_FOUND)
spec.to_spec
@@ -1008,7 +1007,6 @@ class Gem::Specification < Gem::BasicSpecification
def self.find_inactive_by_path(path)
stub = stubs.find do |s|
next if s.activated?
- next unless Gem::BundlerVersionFinder.compatible?(s)
s.contains_requirable_file? path
end
stub && stub.to_spec