зеркало из https://github.com/github/ruby.git
[rubygems/rubygems] Fix activation conflicts when circularly requiring a gem
If a gem is required circular, and there are unresolved specs depending on it, we may end up in an activation conflict. The solution is to not try to activate unresolved gems when requiring a default gem, regardless of it having already been activated or not. https://github.com/rubygems/rubygems/commit/3b2b8f4e3e
This commit is contained in:
Родитель
f1f5f22d22
Коммит
db44088c2a
|
@ -1216,6 +1216,13 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
|
|||
##
|
||||
# Find a Gem::Specification of default gem from +path+
|
||||
|
||||
def find_default_spec(path)
|
||||
@path_to_default_spec_map[path]
|
||||
end
|
||||
|
||||
##
|
||||
# Find an unresolved Gem::Specification of default gem from +path+
|
||||
|
||||
def find_unresolved_default_spec(path)
|
||||
default_spec = @path_to_default_spec_map[path]
|
||||
default_spec if default_spec && loaded_specs[default_spec.name] != default_spec
|
||||
|
|
|
@ -42,7 +42,11 @@ module Kernel
|
|||
# If +path+ belongs to a default gem, we activate it and then go straight
|
||||
# to normal require
|
||||
|
||||
if spec = Gem.find_unresolved_default_spec(path)
|
||||
if spec = Gem.find_default_spec(path)
|
||||
name = spec.name
|
||||
|
||||
next if Gem.loaded_specs[name]
|
||||
|
||||
# Ensure -I beats a default gem
|
||||
resolved_path = begin
|
||||
rp = nil
|
||||
|
@ -60,7 +64,7 @@ module Kernel
|
|||
rp
|
||||
end
|
||||
|
||||
Kernel.send(:gem, spec.name, Gem::Requirement.default_prerelease) unless
|
||||
Kernel.send(:gem, name, Gem::Requirement.default_prerelease) unless
|
||||
resolved_path
|
||||
|
||||
next
|
||||
|
|
|
@ -560,6 +560,45 @@ class TestGemRequire < Gem::TestCase
|
|||
assert_require "net/http"
|
||||
end
|
||||
|
||||
def test_default_gem_required_circulary_with_unresolved_gems_depending_on_it
|
||||
net_http_old = util_spec "net-http", "0.1.1", nil, "lib/net/http.rb"
|
||||
install_gem net_http_old
|
||||
|
||||
net_http_default = new_default_spec "net-http", "0.3.0", nil, "net/http.rb"
|
||||
net_http_default_path = File.join(@tempdir, "default_gems", "lib", "net/http.rb")
|
||||
install_default_gems net_http_default
|
||||
File.write(net_http_default_path, 'require "net/http"')
|
||||
|
||||
faraday_1 = util_spec "faraday", "1", { "net-http" => ">= 0" }
|
||||
install_gem faraday_1
|
||||
|
||||
faraday_2 = util_spec "faraday", "2", { "net-http" => ">= 0" }
|
||||
install_gem faraday_2
|
||||
|
||||
chef = util_spec "chef", "1", { "faraday" => [">= 1", "< 3"] }, "lib/chef.rb"
|
||||
install_gem chef
|
||||
|
||||
assert_require "chef"
|
||||
|
||||
out, err = capture_output do
|
||||
assert_require "net/http"
|
||||
end
|
||||
|
||||
assert_empty out
|
||||
|
||||
circular_require_warning = false
|
||||
|
||||
err_lines = err.split("\n").reject do |line|
|
||||
if line.include?("circular require")
|
||||
circular_require_warning = true
|
||||
elsif circular_require_warning # ignore backtrace lines for circular require warning
|
||||
circular_require_warning = line.start_with?(/[\s]/)
|
||||
end
|
||||
end
|
||||
|
||||
assert_empty err_lines
|
||||
end
|
||||
|
||||
def loaded_spec_names
|
||||
Gem.loaded_specs.values.map(&:full_name).sort
|
||||
end
|
||||
|
|
Загрузка…
Ссылка в новой задаче