From 5ccaeee2e89310d52d15469719c98d02f103b5aa Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Sun, 16 Nov 2025 15:53:00 -0800 Subject: [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 --- lib/rubygems/specification.rb | 2 +- lib/rubygems/version.rb | 19 ++---------------- test/rubygems/test_gem_requirement.rb | 22 ++++----------------- test/rubygems/test_gem_specification.rb | 35 ++++++++++++++++++++++++++++----- test/rubygems/test_gem_version.rb | 20 ++++++------------- 5 files changed, 43 insertions(+), 55 deletions(-) diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb index 4c5ecb8f79..a9ec6aa3a3 100644 --- a/lib/rubygems/specification.rb +++ b/lib/rubygems/specification.rb @@ -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? diff --git a/lib/rubygems/version.rb b/lib/rubygems/version.rb index 25c412be4b..c9fffc1cb7 100644 --- a/lib/rubygems/version.rb +++ b/lib/rubygems/version.rb @@ -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 diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index de0d11ec00..00634dc7f4 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -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 diff --git a/test/rubygems/test_gem_specification.rb b/test/rubygems/test_gem_specification.rb index 05138e570e..e8c2c0eb47 100644 --- a/test/rubygems/test_gem_specification.rb +++ b/test/rubygems/test_gem_specification.rb @@ -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 diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index cf771bc5a1..1d963daa65 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -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 -- cgit v1.2.3