diff --git a/lib/bundler/man/bundle-lock.1 b/lib/bundler/man/bundle-lock.1 index ce783b3bb371f3..97290708a82b94 100644 --- a/lib/bundler/man/bundle-lock.1 +++ b/lib/bundler/man/bundle-lock.1 @@ -4,7 +4,7 @@ .SH "NAME" \fBbundle\-lock\fR \- Creates / Updates a lockfile without installing .SH "SYNOPSIS" -\fBbundle lock\fR [\-\-update] [\-\-bundler[=BUNDLER]] [\-\-local] [\-\-print] [\-\-lockfile=PATH] [\-\-full\-index] [\-\-gemfile=GEMFILE] [\-\-add\-checkums] [\-\-add\-platform] [\-\-remove\-platform] [\-\-normalize\-platforms] [\-\-patch] [\-\-minor] [\-\-major] [\-\-pre] [\-\-strict] [\-\-conservative] +\fBbundle lock\fR [\-\-update] [\-\-bundler[=BUNDLER]] [\-\-local] [\-\-print] [\-\-lockfile=PATH] [\-\-full\-index] [\-\-gemfile=GEMFILE] [\-\-add\-checksums] [\-\-add\-platform] [\-\-remove\-platform] [\-\-normalize\-platforms] [\-\-patch] [\-\-minor] [\-\-major] [\-\-pre] [\-\-strict] [\-\-conservative] .SH "DESCRIPTION" Lock the gems specified in Gemfile\. .SH "OPTIONS" diff --git a/lib/bundler/man/bundle-lock.1.ronn b/lib/bundler/man/bundle-lock.1.ronn index 6927d9b6c4cdf6..6d3e63c982c500 100644 --- a/lib/bundler/man/bundle-lock.1.ronn +++ b/lib/bundler/man/bundle-lock.1.ronn @@ -10,7 +10,7 @@ bundle-lock(1) -- Creates / Updates a lockfile without installing [--lockfile=PATH] [--full-index] [--gemfile=GEMFILE] - [--add-checkums] + [--add-checksums] [--add-platform] [--remove-platform] [--normalize-platforms] diff --git a/lib/bundler/self_manager.rb b/lib/bundler/self_manager.rb index b88faf75898cfe..2aeac6be52d243 100644 --- a/lib/bundler/self_manager.rb +++ b/lib/bundler/self_manager.rb @@ -84,8 +84,9 @@ def restart_with(version) require "shellwords" cmd = [*Shellwords.shellsplit(bundler_spec_original_cmd), *ARGV] else - cmd = [Process.argv0, *ARGV] - cmd.unshift(Gem.ruby) unless File.executable?(Process.argv0) + argv0 = File.exist?($PROGRAM_NAME) ? $PROGRAM_NAME : Process.argv0 + cmd = [argv0, *ARGV] + cmd.unshift(Gem.ruby) unless File.executable?(argv0) end Bundler.with_original_env do diff --git a/lib/bundler/version.rb b/lib/bundler/version.rb index baca95db67ee9a..a73b900d961265 100644 --- a/lib/bundler/version.rb +++ b/lib/bundler/version.rb @@ -1,7 +1,7 @@ # frozen_string_literal: false module Bundler - VERSION = "2.6.1".freeze + VERSION = "2.6.2".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 a2bba9bf0d8c1d..55e3661844789a 100644 --- a/lib/rubygems.rb +++ b/lib/rubygems.rb @@ -9,7 +9,7 @@ require "rbconfig" module Gem - VERSION = "3.6.1" + VERSION = "3.6.2" end # Must be first since it unloads the prelude from 1.9.2 diff --git a/lib/rubygems/rdoc.rb b/lib/rubygems/rdoc.rb index 907dcd94311346..977a51da01b147 100644 --- a/lib/rubygems/rdoc.rb +++ b/lib/rubygems/rdoc.rb @@ -6,8 +6,17 @@ require "rdoc/rubygems_hook" module Gem RDoc = ::RDoc::RubygemsHook + + ## + # Returns whether RDoc defines its own install hooks through a RubyGems + # plugin. This and whatever is guarded by it can be removed once no + # supported Ruby ships with RDoc older than 6.9.0. + + def self.rdoc_hooks_defined_via_plugin? + Gem::Version.new(::RDoc::VERSION) >= Gem::Version.new("6.9.0") + end end - Gem.done_installing(&Gem::RDoc.method(:generation_hook)) + Gem.done_installing(&Gem::RDoc.method(:generation_hook)) unless Gem.rdoc_hooks_defined_via_plugin? rescue LoadError end diff --git a/lib/rubygems/requirement.rb b/lib/rubygems/requirement.rb index d9796c4208a0dc..4bbfbfd7c412bb 100644 --- a/lib/rubygems/requirement.rb +++ b/lib/rubygems/requirement.rb @@ -22,7 +22,7 @@ class Gem::Requirement SOURCE_SET_REQUIREMENT = Struct.new(:for_lockfile).new "!" # :nodoc: - quoted = OPS.keys.map {|k| Regexp.quote k }.join "|" + quoted = Regexp.union(OPS.keys) PATTERN_RAW = "\\s*(#{quoted})?\\s*(#{Gem::Version::VERSION_PATTERN})\\s*".freeze # :nodoc: ## @@ -201,7 +201,8 @@ def marshal_dump # :nodoc: def marshal_load(array) # :nodoc: @requirements = array[0] - raise TypeError, "wrong @requirements" unless Array === @requirements + raise TypeError, "wrong @requirements" unless Array === @requirements && + @requirements.all? {|r| r.size == 2 && (r.first.is_a?(String) || r[0] = "=") && r.last.is_a?(Gem::Version) } end def yaml_initialize(tag, vals) # :nodoc: @@ -238,7 +239,7 @@ def pretty_print(q) # :nodoc: def satisfied_by?(version) raise ArgumentError, "Need a Gem::Version: #{version.inspect}" unless Gem::Version === version - requirements.all? {|op, rv| OPS[op].call version, rv } + requirements.all? {|op, rv| OPS.fetch(op).call version, rv } end alias_method :===, :satisfied_by? diff --git a/lib/rubygems/safe_marshal/reader.rb b/lib/rubygems/safe_marshal/reader.rb index 740be113e5a217..4362d65fd681a3 100644 --- a/lib/rubygems/safe_marshal/reader.rb +++ b/lib/rubygems/safe_marshal/reader.rb @@ -20,6 +20,12 @@ class NotImplementedError < Error class EOFError < Error end + class DataTooShortError < Error + end + + class NegativeLengthError < Error + end + def initialize(io) @io = io end @@ -27,7 +33,7 @@ def initialize(io) def read! read_header root = read_element - raise UnconsumedBytesError unless @io.eof? + raise UnconsumedBytesError, "expected EOF, got #{@io.read(10).inspect}... after top-level element #{root.class}" unless @io.eof? root end @@ -41,8 +47,16 @@ def read_header raise UnsupportedVersionError, "Unsupported marshal version #{v.bytes.map(&:ord).join(".")}, expected #{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}" unless v == MARSHAL_VERSION end + def read_bytes(n) + raise NegativeLengthError if n < 0 + str = @io.read(n) + raise EOFError, "expected #{n} bytes, got EOF" if str.nil? + raise DataTooShortError, "expected #{n} bytes, got #{str.inspect}" unless str.bytesize == n + str + end + def read_byte - @io.getbyte + @io.getbyte || raise(EOFError, "Unexpected EOF") end def read_integer @@ -67,8 +81,6 @@ def read_integer read_byte | (read_byte << 8) | -0x10000 when 0xFF read_byte | -0x100 - when nil - raise EOFError, "Unexpected EOF" else signed = (b ^ 128) - 128 if b >= 128 @@ -107,8 +119,6 @@ def read_element when 47 then read_regexp # ?/ when 83 then read_struct # ?S when 67 then read_user_class # ?C - when nil - raise EOFError, "Unexpected EOF" else raise Error, "Unknown marshal type discriminator #{type.chr.inspect} (#{type})" end @@ -127,7 +137,7 @@ def read_symbol Elements::Symbol.new(byte.chr) end else - name = -@io.read(len) + name = read_bytes(len) Elements::Symbol.new(name) end end @@ -138,7 +148,7 @@ def read_symbol def read_string length = read_integer return EMPTY_STRING if length == 0 - str = @io.read(length) + str = read_bytes(length) Elements::String.new(str) end @@ -152,7 +162,7 @@ def read_false def read_user_defined name = read_element - binary_string = @io.read(read_integer) + binary_string = read_bytes(read_integer) Elements::UserDefined.new(name, binary_string) end @@ -162,6 +172,7 @@ def read_user_defined def read_array length = read_integer return EMPTY_ARRAY if length == 0 + raise NegativeLengthError if length < 0 elements = Array.new(length) do read_element end @@ -170,7 +181,9 @@ def read_array def read_object_with_ivars object = read_element - ivars = Array.new(read_integer) do + length = read_integer + raise NegativeLengthError if length < 0 + ivars = Array.new(length) do [read_element, read_element] end Elements::WithIvars.new(object, ivars) @@ -239,7 +252,9 @@ def read_hash end def read_hash_with_default_value - pairs = Array.new(read_integer) do + length = read_integer + raise NegativeLengthError if length < 0 + pairs = Array.new(length) do [read_element, read_element] end default = read_element @@ -249,7 +264,9 @@ def read_hash_with_default_value def read_object name = read_element object = Elements::Object.new(name) - ivars = Array.new(read_integer) do + length = read_integer + raise NegativeLengthError if length < 0 + ivars = Array.new(length) do [read_element, read_element] end Elements::WithIvars.new(object, ivars) @@ -260,13 +277,13 @@ def read_nil end def read_float - string = @io.read(read_integer) + string = read_bytes(read_integer) Elements::Float.new(string) end def read_bignum sign = read_byte - data = @io.read(read_integer * 2) + data = read_bytes(read_integer * 2) Elements::Bignum.new(sign, data) end diff --git a/lib/rubygems/safe_marshal/visitors/to_ruby.rb b/lib/rubygems/safe_marshal/visitors/to_ruby.rb index a9f1d048d492b8..a1f94817760e43 100644 --- a/lib/rubygems/safe_marshal/visitors/to_ruby.rb +++ b/lib/rubygems/safe_marshal/visitors/to_ruby.rb @@ -45,7 +45,7 @@ def visit_Gem_SafeMarshal_Elements_Array(a) idx = 0 # not idiomatic, but there's a huge number of IMEMOs allocated here, so we avoid the block # because this is such a hot path when doing a bundle install with the full index - until idx == size + while idx < size push_stack idx array << visit(elements[idx]) idx += 1 @@ -98,16 +98,21 @@ def visit_Gem_SafeMarshal_Elements_WithIvars(e) end s = e.object.binary_string + # 122 is the largest integer that can be represented in marshal in a single byte + raise TimeTooLargeError.new("binary string too large", stack: formatted_stack) if s.bytesize > 122 marshal_string = "\x04\bIu:\tTime".b - marshal_string.concat(s.size + 5) + marshal_string.concat(s.bytesize + 5) marshal_string << s + # internal is limited to 5, so no overflow is possible marshal_string.concat(internal.size + 5) internal.each do |k, v| + k = k.name + # ivar name can't be too large because only known ivars are in the internal ivars list marshal_string.concat(":") - marshal_string.concat(k.size + 5) - marshal_string.concat(k.to_s) + marshal_string.concat(k.bytesize + 5) + marshal_string.concat(k) dumped = Marshal.dump(v) dumped[0, 2] = "" marshal_string.concat(dumped) @@ -171,11 +176,11 @@ def visit_Gem_SafeMarshal_Elements_Object(o) end def visit_Gem_SafeMarshal_Elements_ObjectLink(o) - @objects[o.offset] + @objects.fetch(o.offset) end def visit_Gem_SafeMarshal_Elements_SymbolLink(o) - @symbols[o.offset] + @symbols.fetch(o.offset) end def visit_Gem_SafeMarshal_Elements_UserDefined(o) @@ -219,16 +224,18 @@ def visit_Gem_SafeMarshal_Elements_String(s) end def visit_Gem_SafeMarshal_Elements_Float(f) - case f.string - when "inf" - ::Float::INFINITY - when "-inf" - -::Float::INFINITY - when "nan" - ::Float::NAN - else - f.string.to_f - end + register_object( + case f.string + when "inf" + ::Float::INFINITY + when "-inf" + -::Float::INFINITY + when "nan" + ::Float::NAN + else + f.string.to_f + end + ) end def visit_Gem_SafeMarshal_Elements_Bignum(b) @@ -374,6 +381,12 @@ def formatted_stack class Error < StandardError end + class TimeTooLargeError < Error + def initialize(message, stack:) + super "#{message} @ #{stack.join "."}" + end + end + class UnpermittedSymbolError < Error def initialize(symbol:, stack:) @symbol = symbol diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb index 5f1cb92e02acd7..8f353aeddacf9a 100644 --- a/lib/rubygems/specification.rb +++ b/lib/rubygems/specification.rb @@ -1817,16 +1817,8 @@ def doc_dir(type = nil) def encode_with(coder) # :nodoc: coder.add "name", @name coder.add "version", @version - platform = case @new_platform - when nil, "" then - "ruby" - when String then - @new_platform - else - @new_platform.to_s - end - coder.add "platform", platform - coder.add "original_platform", @original_platform.to_s if platform != @original_platform.to_s + coder.add "platform", platform.to_s + coder.add "original_platform", original_platform.to_s if platform.to_s != original_platform.to_s attributes = @@attributes.map(&:to_s) - %w[name version platform] attributes.each do |name| diff --git a/lib/rubygems/uninstaller.rb b/lib/rubygems/uninstaller.rb index 471c29b6e45ce4..991bc6fb95d038 100644 --- a/lib/rubygems/uninstaller.rb +++ b/lib/rubygems/uninstaller.rb @@ -10,7 +10,6 @@ require_relative "../rubygems" require_relative "installer_uninstaller_utils" require_relative "dependency_list" -require_relative "rdoc" require_relative "user_interaction" ## diff --git a/lib/rubygems/vendor/net-http/lib/net/http.rb b/lib/rubygems/vendor/net-http/lib/net/http.rb index e32067e49fe34d..ad3e646ccae474 100644 --- a/lib/rubygems/vendor/net-http/lib/net/http.rb +++ b/lib/rubygems/vendor/net-http/lib/net/http.rb @@ -460,7 +460,7 @@ class HTTPHeaderSyntaxError < StandardError; end # # First, what's elsewhere. Class Gem::Net::HTTP: # - # - Inherits from {class Object}[https://docs.ruby-lang.org/en/master/Object.html#class-Object-label-What-27s+Here]. + # - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here]. # # This is a categorized summary of methods and attributes. # diff --git a/lib/rubygems/version.rb b/lib/rubygems/version.rb index d9cd91bffa86aa..3ac3676d0a8972 100644 --- a/lib/rubygems/version.rb +++ b/lib/rubygems/version.rb @@ -288,7 +288,10 @@ def marshal_dump # 1.3.5 and earlier) compatibility. def marshal_load(array) - initialize array[0] + string = array[0] + raise TypeError, "wrong version string" unless string.is_a?(String) + + initialize string end def yaml_initialize(tag, map) # :nodoc: diff --git a/spec/bundler/runtime/self_management_spec.rb b/spec/bundler/runtime/self_management_spec.rb index 7804f5991f99de..a0b2d83d0e583c 100644 --- a/spec/bundler/runtime/self_management_spec.rb +++ b/spec/bundler/runtime/self_management_spec.rb @@ -194,7 +194,7 @@ expect(out).to include("Using bundler #{Bundler::VERSION}") end - it "uses the right original script when re-execing, even if `$0` has been changed", :ruby_repo do + it "uses the right original script when re-execing, if `$0` has been changed to something that's not a script", :ruby_repo do bundle "config path vendor/bundle" system_gems "bundler-9.9.9", path: vendored_gems @@ -213,6 +213,29 @@ expect(err).not_to include("this is the program name") end + it "uses modified $0 when re-execing, if `$0` has been changed to a script", :ruby_repo do + bundle "config path vendor/bundle" + + system_gems "bundler-9.9.9", path: vendored_gems + + runner = bundled_app("runner.rb") + + create_file runner, <<~RUBY + $0 = ARGV.shift + load $0 + RUBY + + script = bundled_app("script.rb") + create_file script, <<~RUBY + require "bundler/setup" + RUBY + + lockfile_bundled_with("9.9.9") + + sys_exec "#{Gem.ruby} #{runner} #{script}", artifice: nil, raise_on_error: false + expect(err).to include("Could not find myrack-1.0.0") + end + private def lockfile_bundled_with(version) diff --git a/test/rubygems/test_gem_commands_install_command.rb b/test/rubygems/test_gem_commands_install_command.rb index 1bd96600f33983..c7fbca196be921 100644 --- a/test/rubygems/test_gem_commands_install_command.rb +++ b/test/rubygems/test_gem_commands_install_command.rb @@ -16,8 +16,6 @@ def setup @cmd.options[:document] = [] @gemdeps = "tmp_install_gemdeps" - - common_installer_setup end def teardown @@ -667,7 +665,7 @@ def test_execute_rdoc assert_path_exist File.join(a2.doc_dir, "ri") assert_path_exist File.join(a2.doc_dir, "rdoc") - end if defined?(Gem::RDoc) + end unless Gem.rdoc_hooks_defined_via_plugin? def test_execute_rdoc_with_path specs = spec_fetcher do |fetcher| @@ -703,7 +701,7 @@ def test_execute_rdoc_with_path wait_for_child_process_to_exit assert_path_exist "whatever/doc/a-2", "documentation not installed" - end if defined?(Gem::RDoc) + end unless Gem.rdoc_hooks_defined_via_plugin? def test_execute_saves_build_args specs = spec_fetcher do |fetcher| diff --git a/test/rubygems/test_gem_commands_update_command.rb b/test/rubygems/test_gem_commands_update_command.rb index 642a62a3736643..24e24f97f64339 100644 --- a/test/rubygems/test_gem_commands_update_command.rb +++ b/test/rubygems/test_gem_commands_update_command.rb @@ -506,7 +506,7 @@ def test_execute_rdoc a2 = @specs["a-2"] assert_path_exist File.join(a2.doc_dir, "rdoc") - end if defined?(Gem::RDoc) + end unless Gem.rdoc_hooks_defined_via_plugin? def test_execute_named spec_fetcher do |fetcher| diff --git a/test/rubygems/test_gem_safe_marshal.rb b/test/rubygems/test_gem_safe_marshal.rb index b33028c17b38ed..3cfa66fb2743b7 100644 --- a/test/rubygems/test_gem_safe_marshal.rb +++ b/test/rubygems/test_gem_safe_marshal.rb @@ -233,6 +233,14 @@ def test_floats end end + def test_link_after_float + pend "Marshal.load of links and floats is broken on truffleruby, see https://github.com/oracle/truffleruby/issues/3747" if RUBY_ENGINE == "truffleruby" + + a = [] + a << a + assert_safe_load_as [0.0, a, 1.0, a] + end + def test_hash_with_ivar h = { runtime: :development } h.instance_variable_set :@type, [] @@ -257,6 +265,31 @@ def test_hash_with_compare_by_identity end end + class UserMarshal + def marshal_load(*) + throw "#{self.class}#marshal_load called" + end + + def marshal_dump + end + end + + def test_time_user_marshal + payload = [ + Marshal::MAJOR_VERSION.chr, Marshal::MINOR_VERSION.chr, + "I", # TYPE_IVAR + "u", # TYPE_USERDEF + Marshal.dump(:Time)[2..-1], + Marshal.dump(0xfb - 5)[3..-1], + Marshal.dump(1)[3..-1], + Marshal.dump(:zone)[2..-1], + Marshal.dump(UserMarshal.new)[2..-1], + ("\x00" * (236 - UserMarshal.name.bytesize)) + ].join + + assert_raise(Gem::SafeMarshal::Visitors::ToRuby::TimeTooLargeError, TypeError) { Gem::SafeMarshal.safe_load(payload) } + end + class StringSubclass < ::String end @@ -323,6 +356,22 @@ def test_gem_spec_unmarshall_license assert_equal ["MIT"], unmarshalled_spec.license end + def test_gem_spec_unmarshall_required_ruby_rubygems_version + spec = Gem::Specification.new do |s| + s.name = "hi" + s.version = "1.2.3" + s.license = "MIT" + end + + assert_safe_load_marshal spec._dump(0), inspect: false, to_s: false + assert_safe_load_marshal Marshal.dump(spec), inspect: false, additional_methods: [:to_ruby, :required_ruby_version, :required_rubygems_version] + + unmarshalled_spec = Gem::SafeMarshal.safe_load(Marshal.dump(spec)) + + assert_equal Gem::Requirement.new(">= 0"), unmarshalled_spec.required_ruby_version + assert_equal Gem::Requirement.new(">= 0"), unmarshalled_spec.required_rubygems_version + end + def test_gem_spec_disallowed_symbol e = assert_raise(Gem::SafeMarshal::Visitors::ToRuby::UnpermittedSymbolError) do spec = Gem::Specification.new do |s| @@ -366,17 +415,52 @@ def test_unexpected_eof Gem::SafeMarshal.safe_load("\x04\x08[\x06") end assert_equal e.message, "Unexpected EOF" + + e = assert_raise(Gem::SafeMarshal::Reader::EOFError) do + Gem::SafeMarshal.safe_load("\004\010:\012") + end + assert_equal e.message, "expected 5 bytes, got EOF" + + e = assert_raise(Gem::SafeMarshal::Reader::EOFError) do + Gem::SafeMarshal.safe_load("\x04\x08i\x01") + end + assert_equal e.message, "Unexpected EOF" + e = assert_raise(Gem::SafeMarshal::Reader::EOFError) do + Gem::SafeMarshal.safe_load("\x04\x08\"\x06") + end + assert_equal e.message, "expected 1 bytes, got EOF" + end + + def test_negative_length + assert_raise(Gem::SafeMarshal::Reader::NegativeLengthError) do + Gem::SafeMarshal.safe_load("\004\010}\325") + end + assert_raise(Gem::SafeMarshal::Reader::NegativeLengthError) do + Gem::SafeMarshal.safe_load("\004\010:\325") + end + assert_raise(Gem::SafeMarshal::Reader::NegativeLengthError) do + Gem::SafeMarshal.safe_load("\004\010\"\325") + end + assert_raise(IndexError) do + Gem::SafeMarshal.safe_load("\004\010;\325") + end + assert_raise(Gem::SafeMarshal::Reader::EOFError) do + Gem::SafeMarshal.safe_load("\004\010@\377") + end end - def assert_safe_load_marshal(dumped, additional_methods: [], permitted_ivars: nil, equality: true, marshal_dump_equality: true) + def assert_safe_load_marshal(dumped, additional_methods: [], permitted_ivars: nil, equality: true, marshal_dump_equality: true, + inspect: true, to_s: true) loaded = Marshal.load(dumped) safe_loaded = - if permitted_ivars - with_const(Gem::SafeMarshal, :PERMITTED_IVARS, permitted_ivars) do + assert_nothing_raised("dumped: #{dumped.b.inspect} loaded: #{loaded.inspect}") do + if permitted_ivars + with_const(Gem::SafeMarshal, :PERMITTED_IVARS, permitted_ivars) do + Gem::SafeMarshal.safe_load(dumped) + end + else Gem::SafeMarshal.safe_load(dumped) end - else - Gem::SafeMarshal.safe_load(dumped) end # NaN != NaN, for example @@ -384,8 +468,8 @@ def assert_safe_load_marshal(dumped, additional_methods: [], permitted_ivars: ni assert_equal loaded, safe_loaded, "should equal what Marshal.load returns" end - assert_equal loaded.to_s, safe_loaded.to_s, "should have equal to_s" - assert_equal loaded.inspect, safe_loaded.inspect, "should have equal inspect" + assert_equal loaded.to_s, safe_loaded.to_s, "should have equal to_s" if to_s + assert_equal loaded.inspect, safe_loaded.inspect, "should have equal inspect" if inspect additional_methods.each do |m| if m.is_a?(Proc) call = m diff --git a/test/rubygems/test_gem_specification.rb b/test/rubygems/test_gem_specification.rb index 56f06742b39792..43b649b9eaeb9c 100644 --- a/test/rubygems/test_gem_specification.rb +++ b/test/rubygems/test_gem_specification.rb @@ -2492,7 +2492,31 @@ def test_to_yaml_fancy assert_equal @a1, same_spec end - def test_to_yaml_platform_empty_string + def test_to_yaml_platform + yaml_str = @a1.to_yaml + + assert_match(/^platform: ruby$/, yaml_str) + refute_match(/^original_platform: /, yaml_str) + end + + def test_to_yaml_platform_no_specific_platform + a = Gem::Specification.new do |s| + s.name = "a" + s.version = "1.0" + s.author = "A User" + s.email = "example@example.com" + s.homepage = "http://example.com" + s.summary = "this is a summary" + s.description = "This is a test description" + end + + yaml_str = a.to_yaml + + assert_match(/^platform: ruby$/, yaml_str) + refute_match(/^original_platform: /, yaml_str) + end + + def test_to_yaml_platform_original_platform_empty_string @a1.instance_variable_set :@original_platform, "" assert_match(/^platform: ruby$/, @a1.to_yaml) @@ -2510,7 +2534,7 @@ def test_to_yaml_platform_legacy assert_equal "powerpc-darwin7.9.0", same_spec.original_platform end - def test_to_yaml_platform_nil + def test_to_yaml_platform_original_platform_nil @a1.instance_variable_set :@original_platform, nil assert_match(/^platform: ruby$/, @a1.to_yaml) @@ -3630,6 +3654,8 @@ def test_version_change_reset_cache_file end def test__load_fixes_Date_objects + pend "Marshal.load of links and floats is broken on truffleruby, see https://github.com/oracle/truffleruby/issues/3747" if RUBY_ENGINE == "truffleruby" + spec = util_spec "a", 1 spec.instance_variable_set :@date, Date.today