[ruby/rubygems] Undeprecate Gem::Version.new(nil)

It seems like we were trying to deprecate passing `nil` to
Gem::Version.new.  This breaks existing code, and I don't think there is
a good reason to deprecate this usage.

I believe what we want to prevent is the following code:

```ruby
Gem::Specification.new do |spec|
  spec.version = nil
  # suddenly the spec version is 0!
  p spec.version
end
```

This commit allows people to manually construct `Gem::Version.new(nil)`,
but when someone assigns `nil` as the Gem specification version, it sets
the spec version to `nil` (making the specification invalid).  People
who manually construct `Gem::Version` objects and use nil should be
allowed to do it, and `Gem::Version.new(nil) == Gem::Version.new("0")`,
but people who assign `nil` in a gemspec will get an invalid gemspec.

I think deprecation started
[here](https://github.com/ruby/rubygems/pull/2203) but there doesn't
seem to be a reason to do it.

Fixes https://github.com/ruby/rubygems/pull/9052

https://github.com/ruby/rubygems/commit/ded5e909c2
This commit is contained in:
Aaron Patterson 2025-11-16 15:53:00 -08:00 committed by git
parent b5d0aac900
commit 5ccaeee2e8
5 changed files with 43 additions and 55 deletions

View File

@ -2517,7 +2517,7 @@ class Gem::Specification < Gem::BasicSpecification
# Set the version to +version+.
def version=(version)
@version = Gem::Version.create(version)
@version = version.nil? ? version : Gem::Version.create(version)
end
def stubbed?

View File

@ -171,9 +171,7 @@ class Gem::Version
# True if the +version+ string matches RubyGems' requirements.
def self.correct?(version)
nil_versions_are_discouraged! if version.nil?
ANCHORED_VERSION_PATTERN.match?(version.to_s)
version.nil? || ANCHORED_VERSION_PATTERN.match?(version.to_s)
end
##
@ -182,15 +180,10 @@ class Gem::Version
#
# ver1 = Version.create('1.3.17') # -> (Version object)
# ver2 = Version.create(ver1) # -> (ver1)
# ver3 = Version.create(nil) # -> nil
def self.create(input)
if self === input # check yourself before you wreck yourself
input
elsif input.nil?
nil_versions_are_discouraged!
nil
else
new input
end
@ -206,14 +199,6 @@ class Gem::Version
@@all[version] ||= super
end
def self.nil_versions_are_discouraged!
unless Gem::Deprecate.skip
warn "nil versions are discouraged and will be deprecated in Rubygems 4"
end
end
private_class_method :nil_versions_are_discouraged!
##
# Constructs a Version from the +version+ string. A version string is a
# series of digits or ASCII letters separated by dots.
@ -224,7 +209,7 @@ class Gem::Version
end
# If version is an empty string convert it to 0
version = 0 if version.is_a?(String) && /\A\s*\Z/.match?(version)
version = 0 if version.nil? || (version.is_a?(String) && /\A\s*\Z/.match?(version))
@version = version.to_s

View File

@ -137,11 +137,7 @@ class TestGemRequirement < Gem::TestCase
refute_satisfied_by "1.2", r
assert_satisfied_by "1.3", r
assert_raise ArgumentError do
Gem::Deprecate.skip_during do
assert_satisfied_by nil, r
end
end
assert_satisfied_by nil, r
end
def test_satisfied_by_eh_blank
@ -151,11 +147,7 @@ class TestGemRequirement < Gem::TestCase
assert_satisfied_by "1.2", r
refute_satisfied_by "1.3", r
assert_raise ArgumentError do
Gem::Deprecate.skip_during do
assert_satisfied_by nil, r
end
end
refute_satisfied_by nil, r
end
def test_satisfied_by_eh_equal
@ -165,11 +157,7 @@ class TestGemRequirement < Gem::TestCase
assert_satisfied_by "1.2", r
refute_satisfied_by "1.3", r
assert_raise ArgumentError do
Gem::Deprecate.skip_during do
assert_satisfied_by nil, r
end
end
refute_satisfied_by nil, r
end
def test_satisfied_by_eh_gt
@ -179,9 +167,7 @@ class TestGemRequirement < Gem::TestCase
refute_satisfied_by "1.2", r
assert_satisfied_by "1.3", r
assert_raise ArgumentError do
r.satisfied_by? nil
end
refute_satisfied_by nil, r
end
def test_satisfied_by_eh_gte

View File

@ -1247,12 +1247,37 @@ dependencies: []
end
def test_initialize_nil_version
expected = "nil versions are discouraged and will be deprecated in Rubygems 4\n"
actual_stdout, actual_stderr = capture_output do
Gem::Specification.new.version = nil
spec = Gem::Specification.new
spec.name = "test-name"
assert_nil spec.version
spec.version = nil
assert_nil spec.version
spec.summary = "test gem"
spec.authors = ["test author"]
e = assert_raise Gem::InvalidSpecificationException do
spec.validate
end
assert_empty actual_stdout
assert_equal(expected, actual_stderr)
assert_match("missing value for attribute version", e.message)
end
def test_set_version_to_nil_after_setting_version
spec = Gem::Specification.new
spec.name = "test-name"
assert_nil spec.version
spec.version = "1.0.0"
assert_equal "1.0.0", spec.version.to_s
spec.version = nil
assert_nil spec.version
spec.summary = "test gem"
spec.authors = ["test author"]
e = assert_raise Gem::InvalidSpecificationException do
spec.validate
end
assert_match("missing value for attribute version", e.message)
end
def test__dump

View File

@ -7,6 +7,11 @@ class TestGemVersion < Gem::TestCase
class V < ::Gem::Version
end
def test_nil_is_zero
zero = Gem::Version.create nil
assert_equal Gem::Version.create(0), zero
end
def test_bump
assert_bumped_version_equal "5.3", "5.2.4"
end
@ -35,13 +40,6 @@ class TestGemVersion < Gem::TestCase
assert_same real, Gem::Version.create(real)
expected = "nil versions are discouraged and will be deprecated in Rubygems 4\n"
actual_stdout, actual_stderr = capture_output do
assert_nil Gem::Version.create(nil)
end
assert_empty actual_stdout
assert_equal(expected, actual_stderr)
assert_equal v("5.1"), Gem::Version.create("5.1")
ver = "1.1"
@ -51,13 +49,7 @@ class TestGemVersion < Gem::TestCase
def test_class_correct
assert_equal true, Gem::Version.correct?("5.1")
assert_equal false, Gem::Version.correct?("an incorrect version")
expected = "nil versions are discouraged and will be deprecated in Rubygems 4\n"
actual_stdout, actual_stderr = capture_output do
Gem::Version.correct?(nil)
end
assert_empty actual_stdout
assert_equal(expected, actual_stderr)
assert_equal true, Gem::Version.correct?(nil)
end
def test_class_new_subclass