diff options
author | Hiroshi SHIBATA <hsbt@ruby-lang.org> | 2020-06-30 21:23:37 +0900 |
---|---|---|
committer | nagachika <nagachika@ruby-lang.org> | 2020-09-15 20:55:40 +0900 |
commit | 7d76314885be3532999684356657ce36da84d04e (patch) | |
tree | aae23ff9ce30ff03c1f0867c0bc46ea968e8e324 | |
parent | 3590f082442afc4506250f5274a7877371a112de (diff) | |
download | ruby-7d76314885be3532999684356657ce36da84d04e.tar.gz |
Merge RubyGems 3.1.4
26 files changed, 372 insertions, 119 deletions
diff --git a/lib/rubygems.rb b/lib/rubygems.rb index 57cb70cc2b..94242a1310 100644 --- a/lib/rubygems.rb +++ b/lib/rubygems.rb @@ -9,7 +9,7 @@ require 'rbconfig' module Gem - VERSION = "3.1.2".freeze + VERSION = "3.1.4".freeze end # Must be first since it unloads the prelude from 1.9.2 @@ -26,19 +26,19 @@ require 'rubygems/errors' # For user documentation, see: # # * <tt>gem help</tt> and <tt>gem help [command]</tt> -# * {RubyGems User Guide}[http://guides.rubygems.org/] -# * {Frequently Asked Questions}[http://guides.rubygems.org/faqs] +# * {RubyGems User Guide}[https://guides.rubygems.org/] +# * {Frequently Asked Questions}[https://guides.rubygems.org/faqs] # # For gem developer documentation see: # -# * {Creating Gems}[http://guides.rubygems.org/make-your-own-gem] +# * {Creating Gems}[https://guides.rubygems.org/make-your-own-gem] # * Gem::Specification # * Gem::Version for version dependency notes # # Further RubyGems documentation can be found at: # -# * {RubyGems Guides}[http://guides.rubygems.org] -# * {RubyGems API}[http://www.rubydoc.info/github/rubygems/rubygems] (also available from +# * {RubyGems Guides}[https://guides.rubygems.org] +# * {RubyGems API}[https://www.rubydoc.info/github/rubygems/rubygems] (also available from # <tt>gem server</tt>) # # == RubyGems Plugins @@ -189,6 +189,8 @@ module Gem @pre_reset_hooks ||= [] @post_reset_hooks ||= [] + @default_source_date_epoch = nil + ## # Try to activate a gem containing +path+. Returns true if # activation succeeded or wasn't needed because it was already @@ -1236,20 +1238,43 @@ An Array (#{env.inspect}) was passed in from #{caller[3]} end ## - # The SOURCE_DATE_EPOCH environment variable (or, if that's not set, the current time), converted to Time object. - # This is used throughout RubyGems for enabling reproducible builds. + # If the SOURCE_DATE_EPOCH environment variable is set, returns it's value. + # Otherwise, returns the time that `Gem.source_date_epoch_string` was + # first called in the same format as SOURCE_DATE_EPOCH. # - # If it is not set as an environment variable already, this also sets it. + # NOTE(@duckinator): The implementation is a tad weird because we want to: + # 1. Make builds reproducible by default, by having this function always + # return the same result during a given run. + # 2. Allow changing ENV['SOURCE_DATE_EPOCH'] at runtime, since multiple + # tests that set this variable will be run in a single process. + # + # If you simplify this function and a lot of tests fail, that is likely + # due to #2 above. # # Details on SOURCE_DATE_EPOCH: # https://reproducible-builds.org/specs/source-date-epoch/ - def self.source_date_epoch - if ENV["SOURCE_DATE_EPOCH"].nil? || ENV["SOURCE_DATE_EPOCH"].empty? - ENV["SOURCE_DATE_EPOCH"] = Time.now.to_i.to_s - end + def self.source_date_epoch_string + # The value used if $SOURCE_DATE_EPOCH is not set. + @default_source_date_epoch ||= Time.now.to_i.to_s + + specified_epoch = ENV["SOURCE_DATE_EPOCH"] + + # If it's empty or just whitespace, treat it like it wasn't set at all. + specified_epoch = nil if !specified_epoch.nil? && specified_epoch.strip.empty? + + epoch = specified_epoch || @default_source_date_epoch - Time.at(ENV["SOURCE_DATE_EPOCH"].to_i).utc.freeze + epoch.strip + end + + ## + # Returns the value of Gem.source_date_epoch_string, as a Time object. + # + # This is used throughout RubyGems for enabling reproducible builds. + + def self.source_date_epoch + Time.at(self.source_date_epoch_string.to_i).utc.freeze end # FIX: Almost everywhere else we use the `def self.` way of defining class @@ -1281,10 +1306,11 @@ An Array (#{env.inspect}) was passed in from #{caller[3]} # def register_default_spec(spec) - new_format = spec.require_paths.any? {|path| spec.files.any? {|f| f.start_with? path } } + extended_require_paths = spec.require_paths.map {|f| f + "/"} + new_format = extended_require_paths.any? {|path| spec.files.any? {|f| f.start_with? path } } if new_format - prefix_group = spec.require_paths.map {|f| f + "/"}.join("|") + prefix_group = extended_require_paths.join("|") prefix_pattern = /^(#{prefix_group})/ end @@ -1366,23 +1392,24 @@ An Array (#{env.inspect}) was passed in from #{caller[3]} MARSHAL_SPEC_DIR = "quick/Marshal.#{Gem.marshal_version}/".freeze - autoload :BundlerVersionFinder, 'rubygems/bundler_version_finder' - autoload :ConfigFile, 'rubygems/config_file' - autoload :Dependency, 'rubygems/dependency' - autoload :DependencyList, 'rubygems/dependency_list' - autoload :Installer, 'rubygems/installer' - autoload :Licenses, 'rubygems/util/licenses' - autoload :PathSupport, 'rubygems/path_support' - autoload :Platform, 'rubygems/platform' - autoload :RequestSet, 'rubygems/request_set' - autoload :Requirement, 'rubygems/requirement' - autoload :Resolver, 'rubygems/resolver' - autoload :Source, 'rubygems/source' - autoload :SourceList, 'rubygems/source_list' - autoload :SpecFetcher, 'rubygems/spec_fetcher' - autoload :Specification, 'rubygems/specification' - autoload :Util, 'rubygems/util' - autoload :Version, 'rubygems/version' + autoload :BundlerVersionFinder, File.expand_path('rubygems/bundler_version_finder', __dir__) + autoload :ConfigFile, File.expand_path('rubygems/config_file', __dir__) + autoload :Dependency, File.expand_path('rubygems/dependency', __dir__) + autoload :DependencyList, File.expand_path('rubygems/dependency_list', __dir__) + autoload :Installer, File.expand_path('rubygems/installer', __dir__) + autoload :Licenses, File.expand_path('rubygems/util/licenses', __dir__) + autoload :NameTuple, File.expand_path('rubygems/name_tuple', __dir__) + autoload :PathSupport, File.expand_path('rubygems/path_support', __dir__) + autoload :Platform, File.expand_path('rubygems/platform', __dir__) + autoload :RequestSet, File.expand_path('rubygems/request_set', __dir__) + autoload :Requirement, File.expand_path('rubygems/requirement', __dir__) + autoload :Resolver, File.expand_path('rubygems/resolver', __dir__) + autoload :Source, File.expand_path('rubygems/source', __dir__) + autoload :SourceList, File.expand_path('rubygems/source_list', __dir__) + autoload :SpecFetcher, File.expand_path('rubygems/spec_fetcher', __dir__) + autoload :Specification, File.expand_path('rubygems/specification', __dir__) + autoload :Util, File.expand_path('rubygems/util', __dir__) + autoload :Version, File.expand_path('rubygems/version', __dir__) require "rubygems/specification" end diff --git a/lib/rubygems/basic_specification.rb b/lib/rubygems/basic_specification.rb index c6d63ac473..339953eb29 100644 --- a/lib/rubygems/basic_specification.rb +++ b/lib/rubygems/basic_specification.rb @@ -78,7 +78,7 @@ class Gem::BasicSpecification elsif missing_extensions? @ignored = true - if RUBY_ENGINE == platform || Gem::Platform.local === platform + if Gem::Platform::RUBY == platform || Gem::Platform.local === platform warn "Ignoring #{full_name} because its extensions are not built. " + "Try: gem pristine #{name} --version #{version}" end diff --git a/lib/rubygems/command.rb b/lib/rubygems/command.rb index c1e5e13c5a..32ec0f8ba6 100644 --- a/lib/rubygems/command.rb +++ b/lib/rubygems/command.rb @@ -646,7 +646,7 @@ basic help message containing pointers to more information. http://localhost:8808/ with info about installed gems Further information: - http://guides.rubygems.org + https://guides.rubygems.org HELP # :startdoc: diff --git a/lib/rubygems/commands/help_command.rb b/lib/rubygems/commands/help_command.rb index 9f14e22f90..259e8b5622 100644 --- a/lib/rubygems/commands/help_command.rb +++ b/lib/rubygems/commands/help_command.rb @@ -38,7 +38,7 @@ Some examples of 'gem' usage. * Create a gem: - See http://guides.rubygems.org/make-your-own-gem/ + See https://guides.rubygems.org/make-your-own-gem/ * See information about RubyGems: diff --git a/lib/rubygems/commands/sources_command.rb b/lib/rubygems/commands/sources_command.rb index feab23237d..ca9d425232 100644 --- a/lib/rubygems/commands/sources_command.rb +++ b/lib/rubygems/commands/sources_command.rb @@ -136,7 +136,7 @@ RubyGems has been configured to serve gems via the following URLs through its history: * http://gems.rubyforge.org (RubyGems 1.3.6 and earlier) -* http://rubygems.org (RubyGems 1.3.7 through 1.8.25) +* https://rubygems.org/ (RubyGems 1.3.7 through 1.8.25) * https://rubygems.org (RubyGems 2.0.1 and newer) Since all of these sources point to the same set of gems you only need one @@ -153,8 +153,8 @@ before it is added. To remove a source use the --remove argument: - $ gem sources --remove http://rubygems.org - http://rubygems.org removed from sources + $ gem sources --remove https://rubygems.org/ + https://rubygems.org/ removed from sources EOF end diff --git a/lib/rubygems/commands/uninstall_command.rb b/lib/rubygems/commands/uninstall_command.rb index 68e048c010..c1a9dbba32 100644 --- a/lib/rubygems/commands/uninstall_command.rb +++ b/lib/rubygems/commands/uninstall_command.rb @@ -143,7 +143,7 @@ that is a dependency of an existing gem. You can use the uninstall_gem spec.name end - alert "Uninstalled all gems in #{options[:install_dir]}" + alert "Uninstalled all gems in #{options[:install_dir] || Gem.dir}" end def uninstall_specific diff --git a/lib/rubygems/ext/builder.rb b/lib/rubygems/ext/builder.rb index 2fc1074d92..a8bd4c8d1b 100644 --- a/lib/rubygems/ext/builder.rb +++ b/lib/rubygems/ext/builder.rb @@ -68,7 +68,9 @@ class Gem::Ext::Builder results << (command.respond_to?(:shelljoin) ? command.shelljoin : command) require "open3" - output, status = Open3.capture2e(*command) + # Set $SOURCE_DATE_EPOCH for the subprocess. + env = {'SOURCE_DATE_EPOCH' => Gem.source_date_epoch_string} + output, status = Open3.capture2e(env, *command) if verbose puts output else diff --git a/lib/rubygems/request_set/gem_dependency_api.rb b/lib/rubygems/request_set/gem_dependency_api.rb index b7a8ee6f4f..ef3f302ea8 100644 --- a/lib/rubygems/request_set/gem_dependency_api.rb +++ b/lib/rubygems/request_set/gem_dependency_api.rb @@ -235,7 +235,7 @@ class Gem::RequestSet::GemDependencyAPI return unless (groups & @without_groups).empty? dependencies.each do |dep| - @set.gem dep.name, *dep.requirement + @set.gem dep.name, *dep.requirement.as_list end end diff --git a/lib/rubygems/resolver/api_set.rb b/lib/rubygems/resolver/api_set.rb index 6fd91e3b73..135f1b08aa 100644 --- a/lib/rubygems/resolver/api_set.rb +++ b/lib/rubygems/resolver/api_set.rb @@ -23,7 +23,7 @@ class Gem::Resolver::APISet < Gem::Resolver::Set ## # Creates a new APISet that will retrieve gems from +uri+ using the RubyGems # API URL +dep_uri+ which is described at - # http://guides.rubygems.org/rubygems-org-api + # https://guides.rubygems.org/rubygems-org-api def initialize(dep_uri = 'https://rubygems.org/api/v1/dependencies') super() diff --git a/lib/rubygems/resolver/api_specification.rb b/lib/rubygems/resolver/api_specification.rb index 9bbc095788..4052846e99 100644 --- a/lib/rubygems/resolver/api_specification.rb +++ b/lib/rubygems/resolver/api_specification.rb @@ -11,7 +11,7 @@ class Gem::Resolver::APISpecification < Gem::Resolver::Specification # Creates an APISpecification for the given +set+ from the rubygems.org # +api_data+. # - # See http://guides.rubygems.org/rubygems-org-api/#misc_methods for the + # See https://guides.rubygems.org/rubygems-org-api/#misc_methods for the # format of the +api_data+. def initialize(set, api_data) diff --git a/lib/rubygems/server.rb b/lib/rubygems/server.rb index 97923ef698..83d7cf5abc 100644 --- a/lib/rubygems/server.rb +++ b/lib/rubygems/server.rb @@ -661,7 +661,7 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; } "only_one_executable" => true, "full_name" => "rubygems-#{Gem::VERSION}", "has_deps" => false, - "homepage" => "http://guides.rubygems.org/", + "homepage" => "https://guides.rubygems.org/", "name" => 'rubygems', "ri_installed" => true, "summary" => "RubyGems itself", diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb index 5321edfcc3..f925480f88 100644 --- a/lib/rubygems/specification.rb +++ b/lib/rubygems/specification.rb @@ -193,6 +193,12 @@ class Gem::Specification < Gem::BasicSpecification @@spec_with_requirable_file = {} @@active_stub_with_requirable_file = {} + # Tracking removed method calls to warn users during build time. + REMOVED_METHODS = [:rubyforge_project=].freeze # :nodoc: + def removed_method_calls + @removed_method_calls ||= [] + end + ###################################################################### # :section: Required gemspec attributes @@ -727,14 +733,6 @@ class Gem::Specification < Gem::BasicSpecification attr_writer :original_platform # :nodoc: ## - # Deprecated and ignored. - # - # Formerly used to set rubyforge project. - - attr_writer :rubyforge_project - deprecate :rubyforge_project=, :none, 2019, 12 - - ## # The Gem::Specification version of this gemspec. # # Do not set this, it is set automatically when the gem is packaged. @@ -2107,9 +2105,15 @@ class Gem::Specification < Gem::BasicSpecification end ## + # Track removed method calls to warn about during build time. # Warn about unknown attributes while loading a spec. def method_missing(sym, *a, &b) # :nodoc: + if REMOVED_METHODS.include?(sym) + removed_method_calls << sym + return + end + if @specification_version > CURRENT_SPECIFICATION_VERSION and sym.to_s =~ /=$/ warn "ignoring #{sym} loading #{full_name}" if $DEBUG diff --git a/lib/rubygems/specification_policy.rb b/lib/rubygems/specification_policy.rb index c3c496db9b..b7fb2cfa1a 100644 --- a/lib/rubygems/specification_policy.rb +++ b/lib/rubygems/specification_policy.rb @@ -75,6 +75,8 @@ class Gem::SpecificationPolicy validate_dependencies + validate_removed_attributes + if @warnings > 0 if strict error "specification has warnings" @@ -408,6 +410,12 @@ http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard li warning "#{executable_path} is missing #! line" end + def validate_removed_attributes # :nodoc: + @specification.removed_method_calls.each do |attr| + warning("#{attr} is deprecated and ignored. Please remove this from your gemspec to ensure that your gem continues to build in the future.") + end + end + def warning(statement) # :nodoc: @warnings += 1 @@ -421,7 +429,7 @@ http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard li end def help_text # :nodoc: - "See http://guides.rubygems.org/specification-reference/ for help" + "See https://guides.rubygems.org/specification-reference/ for help" end end diff --git a/lib/rubygems/test_case.rb b/lib/rubygems/test_case.rb index 206497c651..89403206f9 100644 --- a/lib/rubygems/test_case.rb +++ b/lib/rubygems/test_case.rb @@ -96,6 +96,8 @@ class Gem::TestCase < (defined?(Minitest::Test) ? Minitest::Test : MiniTest::Uni TEST_PATH = ENV.fetch('RUBYGEMS_TEST_PATH', File.expand_path('../../../test/rubygems', __FILE__)) + SPECIFICATIONS = File.expand_path(File.join(TEST_PATH, "specifications"), __FILE__) + def assert_activate(expected, *specs) specs.each do |spec| case spec @@ -169,20 +171,24 @@ class Gem::TestCase < (defined?(Minitest::Test) ? Minitest::Test : MiniTest::Uni # original value when the block ends # def bindir(value) - bindir = RbConfig::CONFIG['bindir'] + with_clean_path_to_ruby do + bindir = RbConfig::CONFIG['bindir'] - if value - RbConfig::CONFIG['bindir'] = value - else - RbConfig::CONFIG.delete 'bindir' - end + if value + RbConfig::CONFIG['bindir'] = value + else + RbConfig::CONFIG.delete 'bindir' + end - yield - ensure - if bindir - RbConfig::CONFIG['bindir'] = bindir - else - RbConfig::CONFIG.delete 'bindir' + begin + yield + ensure + if bindir + RbConfig::CONFIG['bindir'] = bindir + else + RbConfig::CONFIG.delete 'bindir' + end + end end end @@ -1247,6 +1253,16 @@ Also, a list: end end + def with_clean_path_to_ruby + orig_ruby = Gem.ruby + + Gem.instance_variable_set :@ruby, nil + + yield + ensure + Gem.instance_variable_set :@ruby, orig_ruby + end + class << self # :nodoc: diff --git a/lib/rubygems/util.rb b/lib/rubygems/util.rb index b5f1408401..7fc239af9a 100644 --- a/lib/rubygems/util.rb +++ b/lib/rubygems/util.rb @@ -14,7 +14,13 @@ module Gem::Util require 'stringio' data = StringIO.new(data, 'r') - unzipped = Zlib::GzipReader.new(data).read + gzip_reader = begin + Zlib::GzipReader.new(data) + rescue Zlib::GzipFile::Error => e + raise e.class, e.inspect, e.backtrace + end + + unzipped = gzip_reader.read unzipped.force_encoding Encoding::BINARY unzipped end diff --git a/lib/rubygems/version.rb b/lib/rubygems/version.rb index 6524faf5c8..b1faedcda2 100644 --- a/lib/rubygems/version.rb +++ b/lib/rubygems/version.rb @@ -151,7 +151,7 @@ class Gem::Version - autoload :Requirement, 'rubygems/requirement' + autoload :Requirement, File.expand_path('requirement', __dir__) include Comparable diff --git a/test/rubygems/specifications/rubyforge-0.0.1.gemspec b/test/rubygems/specifications/rubyforge-0.0.1.gemspec new file mode 100644 index 0000000000..0df2c4c379 --- /dev/null +++ b/test/rubygems/specifications/rubyforge-0.0.1.gemspec @@ -0,0 +1,14 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = "rubyforge" + s.version = "0.0.1" + s.platform = "ruby" + s.require_paths = ["lib"] + s.summary = "A very bar gem" + s.authors = ["unknown"] + s.license = 'MIT' + s.homepage = 'http://example.com' + s.files = ['README.md'] + s.rubyforge_project = 'abc' +end diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 6d223b7d69..b5d399f972 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -161,10 +161,8 @@ class TestGem < Gem::TestCase def test_self_install_permissions_with_format_executable_and_non_standard_ruby_install_name Gem::Installer.exec_format = nil - with_clean_path_to_ruby do - ruby_install_name 'ruby27' do - assert_self_install_permissions(format_executable: true) - end + ruby_install_name 'ruby27' do + assert_self_install_permissions(format_executable: true) end ensure Gem::Installer.exec_format = nil @@ -310,6 +308,21 @@ class TestGem < Gem::TestCase assert_equal %w(a-1 b-2 c-1), loaded_spec_names end + def test_activate_bin_path_in_debug_mode + a1 = util_spec 'a', '1' do |s| + s.executables = ['exec'] + end + + install_specs a1 + + output, status = Open3.capture2e( + { "GEM_HOME" => Gem.paths.home, "DEBUG_RESOLVER" => "1" }, + Gem.ruby, "-I", File.expand_path("../../lib", __dir__), "-e", "\"Gem.activate_bin_path('a', 'exec', '>= 0')\"" + ) + + assert status.success?, output + end + def test_activate_bin_path_gives_proper_error_for_bundler bundler = util_spec 'bundler', '2' do |s| s.executables = ['bundle'] @@ -1024,21 +1037,17 @@ class TestGem < Gem::TestCase end def test_self_ruby_escaping_spaces_in_path - with_clean_path_to_ruby do - with_bindir_and_exeext("C:/Ruby 1.8/bin", ".exe") do - ruby_install_name "ruby" do - assert_equal "\"C:/Ruby 1.8/bin/ruby.exe\"", Gem.ruby - end + with_bindir_and_exeext("C:/Ruby 1.8/bin", ".exe") do + ruby_install_name "ruby" do + assert_equal "\"C:/Ruby 1.8/bin/ruby.exe\"", Gem.ruby end end end def test_self_ruby_path_without_spaces - with_clean_path_to_ruby do - with_bindir_and_exeext("C:/Ruby18/bin", ".exe") do - ruby_install_name "ruby" do - assert_equal "C:/Ruby18/bin/ruby.exe", Gem.ruby - end + with_bindir_and_exeext("C:/Ruby18/bin", ".exe") do + ruby_install_name "ruby" do + assert_equal "C:/Ruby18/bin/ruby.exe", Gem.ruby end end end @@ -1090,7 +1099,7 @@ class TestGem < Gem::TestCase util_restore_RUBY_VERSION end - def test_self_ruby_version_with_prerelease + def test_self_ruby_version_with_svn_prerelease util_set_RUBY_VERSION '2.6.0', -1, 63539, 'ruby 2.6.0preview2 (2018-05-31 trunk 63539) [x86_64-linux]' assert_equal Gem::Version.new('2.6.0.preview2'), Gem.ruby_version @@ -1098,6 +1107,14 @@ class TestGem < Gem::TestCase util_restore_RUBY_VERSION end + def test_self_ruby_version_with_git_prerelease + util_set_RUBY_VERSION '2.7.0', -1, 'b563439274a402e33541f5695b1bfd4ac1085638', 'ruby 2.7.0preview3 (2019-11-23 master b563439274) [x86_64-linux]' + + assert_equal Gem::Version.new('2.7.0.preview3'), Gem.ruby_version + ensure + util_restore_RUBY_VERSION + end + def test_self_ruby_version_with_non_mri_implementations_with_mri_prerelase_compatibility util_set_RUBY_VERSION '2.6.0', -1, 63539, 'weirdjruby 9.2.0.0 (2.6.0preview2) 2018-05-24 81156a8 OpenJDK 64-Bit Server VM 25.171-b11 on 1.8.0_171-8u171-b11-0ubuntu0.16.04.1-b11 [linux-x86_64]', 'weirdjruby', '9.2.0.0' @@ -1106,7 +1123,7 @@ class TestGem < Gem::TestCase util_restore_RUBY_VERSION end - def test_self_ruby_version_with_trunk + def test_self_ruby_version_with_svn_trunk util_set_RUBY_VERSION '1.9.2', -1, 23493, 'ruby 1.9.2dev (2009-05-20 trunk 23493) [x86_64-linux]' assert_equal Gem::Version.new('1.9.2.dev'), Gem.ruby_version @@ -1114,6 +1131,14 @@ class TestGem < Gem::TestCase util_restore_RUBY_VERSION end + def test_self_ruby_version_with_git_master + util_set_RUBY_VERSION '2.7.0', -1, '5de284ec78220e75643f89b454ce999da0c1c195', 'ruby 2.7.0dev (2019-12-23T01:37:30Z master 5de284ec78) [x86_64-linux]' + + assert_equal Gem::Version.new('2.7.0.dev'), Gem.ruby_version + ensure + util_restore_RUBY_VERSION + end + def test_self_rubygems_version assert_equal Gem::Version.new(Gem::VERSION), Gem.rubygems_version end @@ -1731,6 +1756,18 @@ class TestGem < Gem::TestCase assert_nil Gem.find_unresolved_default_spec("README") end + def test_register_default_spec_old_style_with_folder_starting_with_lib + Gem.clear_default_specs + + old_style = Gem::Specification.new do |spec| + spec.files = ["libexec/bundle", "foo.rb", "bar.rb"] + end + + Gem.register_default_spec old_style + + assert_equal old_style, Gem.find_unresolved_default_spec("foo.rb") + end + def test_use_gemdeps gem_deps_file = 'gem.deps.rb'.tap(&Gem::UNTAINT) spec = util_spec 'a', 1 @@ -1903,16 +1940,38 @@ You may need to `gem install -g` to install missing gems assert platform_defaults.is_a? Hash end - def ruby_install_name(name) - orig_RUBY_INSTALL_NAME = RbConfig::CONFIG['ruby_install_name'] - RbConfig::CONFIG['ruby_install_name'] = name + # Ensure that `Gem.source_date_epoch` is consistent even if + # $SOURCE_DATE_EPOCH has not been set. + def test_default_source_date_epoch_doesnt_change + old_epoch = ENV['SOURCE_DATE_EPOCH'] + ENV['SOURCE_DATE_EPOCH'] = nil - yield + # Unfortunately, there is no real way to test this aside from waiting + # enough for `Time.now.to_i` to change -- which is a whole second. + # + # Fortunately, we only need to do this once. + a = Gem.source_date_epoch + sleep 1 + b = Gem.source_date_epoch + assert_equal a, b ensure - if orig_RUBY_INSTALL_NAME - RbConfig::CONFIG['ruby_install_name'] = orig_RUBY_INSTALL_NAME - else - RbConfig::CONFIG.delete 'ruby_install_name' + ENV['SOURCE_DATE_EPOCH'] = old_epoch + end + + def ruby_install_name(name) + with_clean_path_to_ruby do + orig_RUBY_INSTALL_NAME = RbConfig::CONFIG['ruby_install_name'] + RbConfig::CONFIG['ruby_install_name'] = name + + begin + yield + ensure + if orig_RUBY_INSTALL_NAME + RbConfig::CONFIG['ruby_install_name'] = orig_RUBY_INSTALL_NAME + else + RbConfig::CONFIG.delete 'ruby_install_name' + end + end end end @@ -1924,16 +1983,6 @@ You may need to `gem install -g` to install missing gems end end - def with_clean_path_to_ruby - orig_ruby = Gem.ruby - - Gem.instance_variable_set :@ruby, nil - - yield - ensure - Gem.instance_variable_set :@ruby, orig_ruby - end - def with_plugin(path) test_plugin_path = File.expand_path("test/rubygems/plugin/#{path}", PROJECT_DIR) diff --git a/test/rubygems/test_gem_commands_build_command.rb b/test/rubygems/test_gem_commands_build_command.rb index 50c447e2eb..309e15f859 100644 --- a/test/rubygems/test_gem_commands_build_command.rb +++ b/test/rubygems/test_gem_commands_build_command.rb @@ -122,6 +122,23 @@ class TestGemCommandsBuildCommand < Gem::TestCase util_test_build_gem @gem end + def test_execute_rubyforge_project_warning + rubyforge_gemspec = File.join SPECIFICATIONS, "rubyforge-0.0.1.gemspec" + + @cmd.options[:args] = [rubyforge_gemspec] + + use_ui @ui do + Dir.chdir @tempdir do + @cmd.execute + end + end + + error = @ui.error.split("\n") + assert_equal "WARNING: rubyforge_project= is deprecated and ignored. Please remove this from your gemspec to ensure that your gem continues to build in the future.", error.shift + assert_equal "WARNING: See https://guides.rubygems.org/specification-reference/ for help", error.shift + assert_equal [], error + end + def test_execute_strict_with_warnings bad_gem = util_spec 'some_bad_gem' do |s| s.files = ['README.md'] @@ -147,7 +164,7 @@ class TestGemCommandsBuildCommand < Gem::TestCase error = @ui.error.split "\n" assert_equal "WARNING: licenses is empty, but is recommended. Use a license identifier from", error.shift assert_equal "http://spdx.org/licenses or 'Nonstandard' for a nonstandard license.", error.shift - assert_equal "WARNING: See http://guides.rubygems.org/specification-reference/ for help", error.shift + assert_equal "WARNING: See https://guides.rubygems.org/specification-reference/ for help", error.shift assert_equal [], error gem_file = File.join @tempdir, File.basename(@gem.cache_file) diff --git a/test/rubygems/test_gem_commands_sources_command.rb b/test/rubygems/test_gem_commands_sources_command.rb index b63fbce81f..3a0899245b 100644 --- a/test/rubygems/test_gem_commands_sources_command.rb +++ b/test/rubygems/test_gem_commands_sources_command.rb @@ -247,7 +247,7 @@ source http://gems.example.com/ already present in the cache end def test_execute_add_http_rubygems_org - http_rubygems_org = 'http://rubygems.org' + http_rubygems_org = 'http://rubygems.org/' spec_fetcher do |fetcher| fetcher.spec 'a', 1 @@ -284,6 +284,44 @@ source http://gems.example.com/ already present in the cache assert_empty @ui.error end + def test_execute_add_https_rubygems_org + https_rubygems_org = 'https://rubygems.org/' + + spec_fetcher do |fetcher| + fetcher.spec 'a', 1 + end + + specs = Gem::Specification.map do |spec| + [spec.name, spec.version, spec.original_platform] + end + + specs_dump_gz = StringIO.new + Zlib::GzipWriter.wrap specs_dump_gz do |io| + Marshal.dump specs, io + end + + @fetcher.data["#{https_rubygems_org}/specs.#{@marshal_version}.gz"] = + specs_dump_gz.string + + @cmd.handle_options %W[--add #{https_rubygems_org}] + + ui = Gem::MockGemUi.new "n" + + use_ui ui do + assert_raises Gem::MockGemUi::TermError do + @cmd.execute + end + end + + assert_equal [@gem_repo], Gem.sources + + expected = <<-EXPECTED + EXPECTED + + assert_equal expected, @ui.output + assert_empty @ui.error + end + def test_execute_add_bad_uri @cmd.handle_options %w[--add beta-gems.example.com] diff --git a/test/rubygems/test_gem_commands_uninstall_command.rb b/test/rubygems/test_gem_commands_uninstall_command.rb index 927a241203..c3582390f9 100644 --- a/test/rubygems/test_gem_commands_uninstall_command.rb +++ b/test/rubygems/test_gem_commands_uninstall_command.rb @@ -361,6 +361,7 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase end assert_equal %w[default-1], Gem::Specification.all_names.sort + assert_equal "INFO: Uninstalled all gems in #{@gemhome}", @ui.output.split("\n").last end def test_execute_outside_gem_home diff --git a/test/rubygems/test_gem_package.rb b/test/rubygems/test_gem_package.rb index 5da247e141..64ceda39b2 100644 --- a/test/rubygems/test_gem_package.rb +++ b/test/rubygems/test_gem_package.rb @@ -106,7 +106,7 @@ class TestGemPackage < Gem::Package::TarTestCase assert_equal expected, YAML.load(checksums) end - def test_build_time_source_date_epoch + def test_build_time_uses_source_date_epoch epoch = ENV["SOURCE_DATE_EPOCH"] ENV["SOURCE_DATE_EPOCH"] = "123456789" @@ -124,12 +124,10 @@ class TestGemPackage < Gem::Package::TarTestCase ENV["SOURCE_DATE_EPOCH"] = epoch end - def test_build_time_source_date_epoch_automatically_set + def test_build_time_without_source_date_epoch epoch = ENV["SOURCE_DATE_EPOCH"] ENV["SOURCE_DATE_EPOCH"] = nil - start_time = Time.now.utc.to_i - spec = Gem::Specification.new 'build', '1' spec.summary = 'build' spec.authors = 'build' @@ -138,14 +136,11 @@ class TestGemPackage < Gem::Package::TarTestCase package = Gem::Package.new spec.file_name - end_time = Time.now.utc.to_i - assert_kind_of Time, package.build_time build_time = package.build_time.to_i - assert_operator(start_time, :<=, build_time) - assert_operator(build_time, :<=, end_time) + assert_equal Gem.source_date_epoch.to_i, build_time ensure ENV["SOURCE_DATE_EPOCH"] = epoch end diff --git a/test/rubygems/test_gem_package_tar_writer.rb b/test/rubygems/test_gem_package_tar_writer.rb index 81661da45a..903d681c7e 100644 --- a/test/rubygems/test_gem_package_tar_writer.rb +++ b/test/rubygems/test_gem_package_tar_writer.rb @@ -8,6 +8,11 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase def setup super + # Setting `@default_source_date_epoch` to `nil` effectively resets the + # value used for `Gem.source_date_epoch` whenever `$SOURCE_DATE_EPOCH` + # is not set. + Gem.instance_variable_set(:'@default_source_date_epoch', nil) + @data = 'abcde12345' @io = TempIO.new @tar_writer = Gem::Package::TarWriter.new @io diff --git a/test/rubygems/test_gem_request_set.rb b/test/rubygems/test_gem_request_set.rb index ac344015e7..fb71829471 100644 --- a/test/rubygems/test_gem_request_set.rb +++ b/test/rubygems/test_gem_request_set.rb @@ -183,6 +183,58 @@ DEPENDENCIES assert_path_exists File.join @gemhome, 'specifications', 'b-1.gemspec' end + def test_install_from_gemdeps_complex_dependencies + quick_gem("z", 1) + quick_gem("z", "1.0.1") + quick_gem("z", "1.0.2") + quick_gem("z", "1.0.3") + quick_gem("z", 2) + + spec_fetcher do |fetcher| + fetcher.download "z", 1 + end + + rs = Gem::RequestSet.new + installed = [] + + File.open 'Gemfile.lock', 'w' do |io| + io.puts <<-LOCKFILE +GEM + remote: #{@gem_repo} + specs: + z (1) + +PLATFORMS + #{Gem::Platform::RUBY} + +DEPENDENCIES + z (~> 1.0, >= 1.0.1) + LOCKFILE + end + + File.open 'testo.gemspec', 'w' do |io| + io.puts <<-LOCKFILE +Gem::Specification.new do |spec| + spec.name = 'testo' + spec.version = '1.0.0' + spec.add_dependency('z', '~> 1.0', '>= 1.0.1') +end + LOCKFILE + end + + File.open 'Gemfile', 'w' do |io| + io.puts("gemspec") + end + + rs.install_from_gemdeps :gemdeps => 'Gemfile' do |req, installer| + installed << req.full_name + end + + assert_includes installed, 'z-1.0.3' + + assert_path_exists File.join @gemhome, 'specifications', 'z-1.0.3.gemspec' + end + def test_install_from_gemdeps_version_mismatch spec_fetcher do |fetcher| fetcher.gem 'a', 2 diff --git a/test/rubygems/test_gem_specification.rb b/test/rubygems/test_gem_specification.rb index dbd45a31fd..39a483378a 100644 --- a/test/rubygems/test_gem_specification.rb +++ b/test/rubygems/test_gem_specification.rb @@ -83,6 +83,11 @@ end def setup super + # Setting `@default_source_date_epoch` to `nil` effectively resets the + # value used for `Gem.source_date_epoch` whenever `$SOURCE_DATE_EPOCH` + # is not set. + Gem.instance_variable_set(:'@default_source_date_epoch', nil) + @a1 = util_spec 'a', '1' do |s| s.executable = 'exec' s.test_file = 'test/suite.rb' @@ -939,7 +944,7 @@ dependencies: [] assert_equal File.join(@tempdir, 'a-2.gemspec'), spec.loaded_from end - if RUBY_VERSION < '2.7' + if RUBY_ENGINE == 'ruby' and RUBY_VERSION < '2.7' def test_self_load_tainted full_path = @a2.spec_file write_file full_path do |io| @@ -2784,7 +2789,7 @@ end add_runtime_dependency 'l', '~> 1.2', '> 1.2.3' #{w}: open-ended dependency on o (>= 0) is not recommended use a bounded requirement, such as '~> x.y' -#{w}: See http://guides.rubygems.org/specification-reference/ for help +#{w}: See https://guides.rubygems.org/specification-reference/ for help EXPECTED assert_equal expected, @ui.error, 'warning' @@ -2816,7 +2821,7 @@ duplicate dependency on c (>= 1.2.3, development), (~> 1.2) use: end assert_equal <<-EXPECTED, @ui.error -#{w}: See http://guides.rubygems.org/specification-reference/ for help +#{w}: See https://guides.rubygems.org/specification-reference/ for help EXPECTED end end @@ -2927,7 +2932,7 @@ duplicate dependency on c (>= 1.2.3, development), (~> 1.2) use: end end - assert_match 'See http://guides.rubygems.org/specification-reference/ for help', @ui.error + assert_match 'See https://guides.rubygems.org/specification-reference/ for help', @ui.error end def test_validate_executables @@ -3100,7 +3105,7 @@ Please report a bug if this causes problems. assert_equal '"ftp://rubygems.org" is not a valid HTTP URI', e.message - @a1.homepage = 'http://rubygems.org' + @a1.homepage = 'https://rubygems.org/' assert_equal true, @a1.validate @a1.homepage = 'https://rubygems.org' @@ -3123,6 +3128,21 @@ http://spdx.org/licenses or 'Nonstandard' for a nonstandard license. warning end + def test_removed_methods + assert_equal Gem::Specification::REMOVED_METHODS, [:rubyforge_project=] + end + + def test_validate_removed_rubyforge_project + util_setup_validate + + use_ui @ui do + @a1.rubyforge_project = 'invalid-attribute' + @a1.validate + end + + assert_match "rubyforge_project= is deprecated", @ui.error + end + def test_validate_license_values util_setup_validate @@ -3430,7 +3450,7 @@ Did you mean 'Ruby'? @a1.validate end - assert_match 'See http://guides.rubygems.org/specification-reference/ for help', @ui.error + assert_match 'See https://guides.rubygems.org/specification-reference/ for help', @ui.error end def test_version diff --git a/test/rubygems/test_gem_stub_specification.rb b/test/rubygems/test_gem_stub_specification.rb index 8553194c44..91a46d7842 100644 --- a/test/rubygems/test_gem_stub_specification.rb +++ b/test/rubygems/test_gem_stub_specification.rb @@ -4,7 +4,6 @@ require "rubygems/stub_specification" class TestStubSpecification < Gem::TestCase - SPECIFICATIONS = File.expand_path(File.join("..", "specifications"), __FILE__) FOO = File.join SPECIFICATIONS, "foo-0.0.1-x86-mswin32.gemspec" BAR = File.join SPECIFICATIONS, "bar-0.0.2.gemspec" |