[rubygems/rubygems] Ensure that loading multiple gemspecs with legacy YAML class references does not warn
Before this, you would get constant redefinition warnings on Psych::DefaultKey Additionally, ensure the retries wont continue infinitely in the case of the ArgumentError not being caused by Marshal trying to load the undefined classes https://github.com/rubygems/rubygems/commit/919e8c2de4
This commit is contained in:
parent
f69f775f24
commit
1935433f5f
@ -1302,10 +1302,20 @@ class Gem::Specification < Gem::BasicSpecification
|
|||||||
Gem.load_yaml
|
Gem.load_yaml
|
||||||
|
|
||||||
yaml_set = false
|
yaml_set = false
|
||||||
|
retry_count = 0
|
||||||
|
|
||||||
array = begin
|
array = begin
|
||||||
Marshal.load str
|
Marshal.load str
|
||||||
rescue ArgumentError => e
|
rescue ArgumentError => e
|
||||||
|
# Avoid an infinite retry loop when the argument error has nothing to do
|
||||||
|
# with the classes not being defined.
|
||||||
|
# 1 retry each allowed in case all 3 of
|
||||||
|
# - YAML
|
||||||
|
# - YAML::Syck::DefaultKey
|
||||||
|
# - YAML::Private type
|
||||||
|
# need to be defined
|
||||||
|
raise if retry_count >= 3
|
||||||
|
|
||||||
#
|
#
|
||||||
# Some very old marshaled specs included references to `YAML::PrivateType`
|
# Some very old marshaled specs included references to `YAML::PrivateType`
|
||||||
# and `YAML::Syck::DefaultKey` constants due to bugs in the old emitter
|
# and `YAML::Syck::DefaultKey` constants due to bugs in the old emitter
|
||||||
@ -1323,11 +1333,12 @@ class Gem::Specification < Gem::BasicSpecification
|
|||||||
if message.include?("YAML::Syck::")
|
if message.include?("YAML::Syck::")
|
||||||
YAML.const_set "Syck", YAML unless YAML.const_defined?(:Syck)
|
YAML.const_set "Syck", YAML unless YAML.const_defined?(:Syck)
|
||||||
|
|
||||||
YAML::Syck.const_set "DefaultKey", Class.new if message.include?("YAML::Syck::DefaultKey")
|
YAML::Syck.const_set "DefaultKey", Class.new if message.include?("YAML::Syck::DefaultKey") && !YAML::Syck.const_defined?(:DefaultKey)
|
||||||
elsif message.include?("YAML::PrivateType")
|
elsif message.include?("YAML::PrivateType") && !YAML.const_defined?(:PrivateType)
|
||||||
YAML.const_set "PrivateType", Class.new
|
YAML.const_set "PrivateType", Class.new
|
||||||
end
|
end
|
||||||
|
|
||||||
|
retry_count += 1
|
||||||
retry
|
retry
|
||||||
ensure
|
ensure
|
||||||
Object.__send__(:remove_const, "YAML") if yaml_set
|
Object.__send__(:remove_const, "YAML") if yaml_set
|
||||||
|
@ -1094,6 +1094,25 @@ dependencies: []
|
|||||||
assert_equal(yaml_defined, Object.const_defined?("YAML"))
|
assert_equal(yaml_defined, Object.const_defined?("YAML"))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_handles_dependencies_with_other_syck_requirements_argument_error
|
||||||
|
yaml_defined = Object.const_defined?("YAML")
|
||||||
|
|
||||||
|
data = Marshal.dump(Gem::Specification.new do |s|
|
||||||
|
v = Gem::Version.allocate
|
||||||
|
v.instance_variable_set :@version, "YAML::Syck::DefaultKey"
|
||||||
|
s.instance_variable_set :@version, v
|
||||||
|
end)
|
||||||
|
|
||||||
|
assert_raises(ArgumentError) { Marshal.load(data) }
|
||||||
|
out, err = capture_output do
|
||||||
|
assert_raises(ArgumentError) { Marshal.load(data) }
|
||||||
|
end
|
||||||
|
assert_empty out
|
||||||
|
assert_empty err
|
||||||
|
|
||||||
|
assert_equal(yaml_defined, Object.const_defined?("YAML"))
|
||||||
|
end
|
||||||
|
|
||||||
def test_initialize
|
def test_initialize
|
||||||
spec = Gem::Specification.new do |s|
|
spec = Gem::Specification.new do |s|
|
||||||
s.name = "blah"
|
s.name = "blah"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user