diff options
author | Hiroshi SHIBATA <hsbt@ruby-lang.org> | 2019-06-01 12:45:11 +0300 |
---|---|---|
committer | Hiroshi SHIBATA <hsbt@ruby-lang.org> | 2019-06-01 13:50:41 +0300 |
commit | 56660de3c6df7a4ff8667ef4047d30d0de169935 (patch) | |
tree | dd1e526075687b4b24e089cee50eabc21a6143cc /lib | |
parent | 560cd5b1f04f30542a294b3d77527d3b12f7cc15 (diff) |
Merge rubygems master from upstream.
I picked the commit from 3c469e0da538428a0ddd94f99aa73c32da22e8ba
Diffstat (limited to 'lib')
-rw-r--r-- | lib/rubygems.rb | 24 | ||||
-rw-r--r-- | lib/rubygems/commands/pristine_command.rb | 2 | ||||
-rw-r--r-- | lib/rubygems/commands/query_command.rb | 170 | ||||
-rw-r--r-- | lib/rubygems/commands/setup_command.rb | 2 | ||||
-rw-r--r-- | lib/rubygems/commands/update_command.rb | 4 | ||||
-rw-r--r-- | lib/rubygems/core_ext/kernel_gem.rb | 3 | ||||
-rw-r--r-- | lib/rubygems/defaults.rb | 7 | ||||
-rw-r--r-- | lib/rubygems/ext/rake_builder.rb | 2 | ||||
-rw-r--r-- | lib/rubygems/installer_test_case.rb | 116 | ||||
-rw-r--r-- | lib/rubygems/package/tar_header.rb | 13 | ||||
-rw-r--r-- | lib/rubygems/remote_fetcher.rb | 12 | ||||
-rw-r--r-- | lib/rubygems/request/connection_pools.rb | 4 | ||||
-rw-r--r-- | lib/rubygems/resolver.rb | 2 | ||||
-rw-r--r-- | lib/rubygems/resolver/activation_request.rb | 49 | ||||
-rw-r--r-- | lib/rubygems/specification.rb | 18 | ||||
-rw-r--r-- | lib/rubygems/test_case.rb | 243 | ||||
-rw-r--r-- | lib/rubygems/test_utilities.rb | 7 | ||||
-rw-r--r-- | lib/rubygems/util.rb | 54 |
18 files changed, 290 insertions, 442 deletions
diff --git a/lib/rubygems.rb b/lib/rubygems.rb index 193e8d3539..c013e4b8ed 100644 --- a/lib/rubygems.rb +++ b/lib/rubygems.rb @@ -670,6 +670,21 @@ An Array (#{env.inspect}) was passed in from #{caller[3]} index end + ## + # Add a list of paths to the $LOAD_PATH at the proper place. + + def self.add_to_load_path(*paths) + insert_index = load_path_insert_index + + if insert_index + # gem directories must come after -I and ENV['RUBYLIB'] + $LOAD_PATH.insert(insert_index, *paths) + else + # we are probably testing in core, -I and RUBYLIB don't apply + $LOAD_PATH.unshift(*paths) + end + end + @yaml_loaded = false ## @@ -1084,6 +1099,13 @@ An Array (#{env.inspect}) was passed in from #{caller[3]} end ## + # Is this a java platform? + + def self.java_platform? + RUBY_PLATFORM == "java" + end + + ## # Load +plugins+ as Ruby files def self.load_plugin_files(plugins) # :nodoc: @@ -1243,7 +1265,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]} # def register_default_spec(spec) - new_format = Gem.default_gems_use_full_paths? || spec.require_paths.any? {|path| spec.files.any? {|f| f.start_with? path } } + new_format = spec.require_paths.any? {|path| spec.files.any? {|f| f.start_with? path } } if new_format prefix_group = spec.require_paths.map {|f| f + "/"}.join("|") diff --git a/lib/rubygems/commands/pristine_command.rb b/lib/rubygems/commands/pristine_command.rb index a25b690afc..e4628bdd40 100644 --- a/lib/rubygems/commands/pristine_command.rb +++ b/lib/rubygems/commands/pristine_command.rb @@ -104,7 +104,7 @@ extensions will be restored. end.flatten end - specs = specs.select{|spec| RUBY_ENGINE == spec.platform || Gem::Platform.local === spec.platform } + specs = specs.select{|spec| RUBY_ENGINE == spec.platform || Gem::Platform.local === spec.platform || spec.platform == Gem::Platform::RUBY } if specs.to_a.empty? raise Gem::Exception, diff --git a/lib/rubygems/commands/query_command.rb b/lib/rubygems/commands/query_command.rb index 5a42d45249..4fb23bc6c1 100644 --- a/lib/rubygems/commands/query_command.rb +++ b/lib/rubygems/commands/query_command.rb @@ -78,46 +78,58 @@ is too hard to use. end def execute + gem_names = Array(options[:name]) + + if !args.empty? + gem_names = options[:exact] ? args.map{|arg| /\A#{Regexp.escape(arg)}\Z/ } : args.map{|arg| /#{arg}/i } + end + + terminate_interaction(check_installed_gems(gem_names)) if check_installed_gems? + + gem_names.each { |n| show_gems(n) } + end + + private + + def check_installed_gems(gem_names) exit_code = 0 - if options[:args].to_a.empty? and options[:name].source.empty? - name = options[:name] - no_name = true - elsif !options[:name].source.empty? - name = Array(options[:name]) + + if args.empty? && !gem_name? + alert_error "You must specify a gem name" + exit_code = 4 + elsif gem_names.count > 1 + alert_error "You must specify only ONE gem!" + exit_code = 4 else - args = options[:args].to_a - name = options[:exact] ? args.map{|arg| /\A#{Regexp.escape(arg)}\Z/ } : args.map{|arg| /#{arg}/i } + installed = installed?(gem_names.first, options[:version]) + installed = !installed unless options[:installed] + + say(installed) + exit_code = 1 if !installed end - prerelease = options[:prerelease] + exit_code + end - unless options[:installed].nil? - if no_name - alert_error "You must specify a gem name" - exit_code |= 4 - elsif name.count > 1 - alert_error "You must specify only ONE gem!" - exit_code |= 4 - else - installed = installed? name.first, options[:version] - installed = !installed unless options[:installed] + def check_installed_gems? + !options[:installed].nil? + end - if installed - say "true" - else - say "false" - exit_code |= 1 - end - end + def gem_name? + !options[:name].source.empty? + end - terminate_interaction exit_code - end + def prerelease + options[:prerelease] + end - names = Array(name) - names.each { |n| show_gems n, prerelease } + def show_prereleases? + prerelease.nil? || prerelease end - private + def args + options[:args].to_a + end def display_header(type) if (ui.outs.tty? and Gem.configuration.verbose) or both? @@ -128,56 +140,57 @@ is too hard to use. end #Guts of original execute - def show_gems(name, prerelease) - req = Gem::Requirement.default - # TODO: deprecate for real + def show_gems(name) + show_local_gems(name) if local? + show_remote_gems(name) if remote? + end + + def show_local_gems(name, req = Gem::Requirement.default) + display_header("LOCAL") + + specs = Gem::Specification.find_all do |s| + s.name =~ name and req =~ s.version + end + dep = Gem::Deprecate.skip_during { Gem::Dependency.new name, req } - dep.prerelease = prerelease + specs.select! do |s| + dep.match?(s.name, s.version, show_prereleases?) + end - if local? - if prerelease and not both? - alert_warning "prereleases are always shown locally" - end + spec_tuples = specs.map do |spec| + [spec.name_tuple, spec] + end + + output_query_results(spec_tuples) + end - display_header 'LOCAL' + def show_remote_gems(name) + display_header("REMOTE") - specs = Gem::Specification.find_all do |s| - s.name =~ name and req =~ s.version - end + fetcher = Gem::SpecFetcher.fetcher - spec_tuples = specs.map do |spec| - [spec.name_tuple, spec] - end + spec_tuples = if name.respond_to?(:source) && name.source.empty? + fetcher.detect(specs_type) { true } + else + fetcher.detect(specs_type) do |name_tuple| + name === name_tuple.name + end + end - output_query_results spec_tuples - end + output_query_results(spec_tuples) + end - if remote? - display_header 'REMOTE' - - fetcher = Gem::SpecFetcher.fetcher - - type = if options[:all] - if options[:prerelease] - :complete - else - :released - end - elsif options[:prerelease] - :prerelease - else - :latest - end - - if name.respond_to?(:source) && name.source.empty? - spec_tuples = fetcher.detect(type) { true } + def specs_type + if options[:all] + if options[:prerelease] + :complete else - spec_tuples = fetcher.detect(type) do |name_tuple| - name === name_tuple.name - end + :released end - - output_query_results spec_tuples + elsif options[:prerelease] + :prerelease + else + :latest end end @@ -235,7 +248,7 @@ is too hard to use. name_tuple, spec = detail_tuple - spec = spec.fetch_spec name_tuple if spec.respond_to? :fetch_spec + spec = spec.fetch_spec(name_tuple)if spec.respond_to?(:fetch_spec) entry << "\n" @@ -285,8 +298,8 @@ is too hard to use. entry = [name_tuples.first.name] - entry_versions entry, name_tuples, platforms, specs - entry_details entry, detail_tuple, specs, platforms + entry_versions(entry, name_tuples, platforms, specs) + entry_details(entry, detail_tuple, specs, platforms) entry.join end @@ -337,12 +350,13 @@ is too hard to use. if platforms.length == 1 title = platforms.values.length == 1 ? 'Platform' : 'Platforms' - entry << " #{title}: #{platforms.values.sort.join ', '}\n" + entry << " #{title}: #{platforms.values.sort.join(', ')}\n" else entry << " Platforms:\n" - platforms.sort_by do |version,| - version - end.each do |version, pls| + + sorted_platforms = platforms.sort_by { |version,| version } + + sorted_platforms.each do |version, pls| label = " #{version}: " data = format_text pls.sort.join(', '), 68, label.length data[0, label.length] = label diff --git a/lib/rubygems/commands/setup_command.rb b/lib/rubygems/commands/setup_command.rb index f5e5236a06..1754630c8c 100644 --- a/lib/rubygems/commands/setup_command.rb +++ b/lib/rubygems/commands/setup_command.rb @@ -429,7 +429,7 @@ By default, this RubyGems will install gem as: Dir.chdir("bundler") do built_gem = Gem::Package.build(bundler_spec) begin - installer = Gem::Installer.at(built_gem, env_shebang: options[:env_shebang], install_as_default: true, bin_dir: bin_dir, wrappers: true) + installer = Gem::Installer.at(built_gem, env_shebang: options[:env_shebang], format_executable: options[:format_executable], install_as_default: true, bin_dir: bin_dir, wrappers: true) installer.install ensure FileUtils.rm_f built_gem diff --git a/lib/rubygems/commands/update_command.rb b/lib/rubygems/commands/update_command.rb index 4b182396f3..e8031a259d 100644 --- a/lib/rubygems/commands/update_command.rb +++ b/lib/rubygems/commands/update_command.rb @@ -254,9 +254,7 @@ command to remove old versions. def update_rubygems_arguments # :nodoc: args = [] args << '--prefix' << Gem.prefix if Gem.prefix - # TODO use --document for >= 1.9 , --no-rdoc --no-ri < 1.9 - args << '--no-rdoc' unless options[:document].include? 'rdoc' - args << '--no-ri' unless options[:document].include? 'ri' + args << '--no-document' unless options[:document].include?('rdoc') || options[:document].include?('ri') args << '--no-format-executable' if options[:no_format_executable] args << '--previous-version' << Gem::VERSION if options[:system] == true or diff --git a/lib/rubygems/core_ext/kernel_gem.rb b/lib/rubygems/core_ext/kernel_gem.rb index 39b00387ea..fb3053fd83 100644 --- a/lib/rubygems/core_ext/kernel_gem.rb +++ b/lib/rubygems/core_ext/kernel_gem.rb @@ -7,9 +7,6 @@ module Kernel - # REFACTOR: This should be pulled out into some kind of hacks file. - remove_method :gem if 'method' == defined? gem # from gem_prelude.rb on 1.9 - ## # Use Kernel#gem to activate a specific version of +gem_name+. # diff --git a/lib/rubygems/defaults.rb b/lib/rubygems/defaults.rb index 7aa0480b80..33b6ab3f3e 100644 --- a/lib/rubygems/defaults.rb +++ b/lib/rubygems/defaults.rb @@ -148,13 +148,6 @@ module Gem end ## - # Whether to expect full paths in default gems - true for non-MRI - # ruby implementations - def self.default_gems_use_full_paths? - ruby_engine != 'ruby' - end - - ## # Install extensions into lib as well as into the extension directory. def self.install_extension_in_lib # :nodoc: diff --git a/lib/rubygems/ext/rake_builder.rb b/lib/rubygems/ext/rake_builder.rb index 52041a2713..077f080c07 100644 --- a/lib/rubygems/ext/rake_builder.rb +++ b/lib/rubygems/ext/rake_builder.rb @@ -20,7 +20,7 @@ class Gem::Ext::RakeBuilder < Gem::Ext::Builder rake = rake.shellsplit else begin - rake = [Gem.ruby, "-rrubygems", Gem.bin_path('rake', 'rake')] + rake = [Gem.ruby, "-I#{File.expand_path("..", __dir__)}", "-rrubygems", Gem.bin_path('rake', 'rake')] rescue Gem::Exception rake = [Gem.default_exec_format % 'rake'] end diff --git a/lib/rubygems/installer_test_case.rb b/lib/rubygems/installer_test_case.rb index 1c16959f5f..f48466d3ea 100644 --- a/lib/rubygems/installer_test_case.rb +++ b/lib/rubygems/installer_test_case.rb @@ -66,44 +66,9 @@ end class Gem::InstallerTestCase < Gem::TestCase - ## - # Creates the following instance variables: - # - # @spec:: - # a spec named 'a', intended for regular installs - # @user_spec:: - # a spec named 'b', intended for user installs - # - # @gem:: - # the path to a built gem from @spec - # @user_spec:: - # the path to a built gem from @user_spec - # - # @installer:: - # a Gem::Installer for the @spec that installs into @gemhome - # @user_installer:: - # a Gem::Installer for the @user_spec that installs into Gem.user_dir - def setup super - @spec = quick_gem 'a' do |spec| - util_make_exec spec - end - - @user_spec = quick_gem 'b' do |spec| - util_make_exec spec - end - - util_build_gem @spec - util_build_gem @user_spec - - @gem = @spec.cache_file - @user_gem = @user_spec.cache_file - - @installer = util_installer @spec, @gemhome - @user_installer = util_installer @user_spec, Gem.user_dir, :user - Gem::Installer.path_warning = false end @@ -136,6 +101,83 @@ class Gem::InstallerTestCase < Gem::TestCase end ## + # Creates the following instance variables: + # + # @spec:: + # a spec named 'a', intended for regular installs + # + # @gem:: + # the path to a built gem from @spec + # + # And returns a Gem::Installer for the @spec that installs into @gemhome + + def setup_base_installer + @gem = setup_base_gem + util_installer @spec, @gemhome + end + + ## + # Creates the following instance variables: + # + # @spec:: + # a spec named 'a', intended for regular installs + # + # And returns a gem built for the @spec + + def setup_base_gem + @spec = setup_base_spec + util_build_gem @spec + @spec.cache_file + end + + ## + # Sets up a generic specification for testing the rubygems installer + # + # And returns it + + def setup_base_spec + quick_gem 'a' do |spec| + util_make_exec spec + end + end + + ## + # Creates the following instance variables: + # + # @spec:: + # a spec named 'a', intended for regular installs + # @user_spec:: + # a spec named 'b', intended for user installs + # + # @gem:: + # the path to a built gem from @spec + # @user_gem:: + # the path to a built gem from @user_spec + # + # And returns a Gem::Installer for the @user_spec that installs into Gem.user_dir + + def setup_base_user_installer + @user_spec = quick_gem 'b' do |spec| + util_make_exec spec + end + + util_build_gem @user_spec + + @user_gem = @user_spec.cache_file + + util_installer @user_spec, Gem.user_dir, :user + end + + ## + # Sets up the base @gem, builds it and returns an installer for it. + # + def util_setup_installer + @gem = setup_base_gem + + util_setup_gem + end + + ## # Builds the @spec gem and returns an installer for it. The built gem # includes: # @@ -143,7 +185,7 @@ class Gem::InstallerTestCase < Gem::TestCase # lib/code.rb # ext/a/mkrf_conf.rb - def util_setup_gem(ui = @ui) # HACK fix use_ui to make this automatic + def util_setup_gem(ui = @ui) @spec.files << File.join('lib', 'code.rb') @spec.extensions << File.join('ext', 'a', 'mkrf_conf.rb') @@ -175,7 +217,7 @@ class Gem::InstallerTestCase < Gem::TestCase end end - @installer = Gem::Installer.at @gem + Gem::Installer.at @gem end ## diff --git a/lib/rubygems/package/tar_header.rb b/lib/rubygems/package/tar_header.rb index c7b5f88dbd..c37612772a 100644 --- a/lib/rubygems/package/tar_header.rb +++ b/lib/rubygems/package/tar_header.rb @@ -107,8 +107,8 @@ class Gem::Package::TarHeader new :name => fields.shift, :mode => strict_oct(fields.shift), - :uid => strict_oct(fields.shift), - :gid => strict_oct(fields.shift), + :uid => oct_or_256based(fields.shift), + :gid => oct_or_256based(fields.shift), :size => strict_oct(fields.shift), :mtime => strict_oct(fields.shift), :checksum => strict_oct(fields.shift), @@ -130,6 +130,15 @@ class Gem::Package::TarHeader raise ArgumentError, "#{str.inspect} is not an octal string" end + def self.oct_or_256based(str) + # \x80 flags a positive 256-based number + # \ff flags a negative 256-based number + # In case we have a match, parse it as a signed binary value + # in big-endian order, except that the high-order bit is ignored. + return str.unpack('N2').last if str =~ /\A[\x80\xff]/n + strict_oct(str) + end + ## # Creates a new TarHeader using +vals+ diff --git a/lib/rubygems/remote_fetcher.rb b/lib/rubygems/remote_fetcher.rb index 32c65eada8..a40ee55273 100644 --- a/lib/rubygems/remote_fetcher.rb +++ b/lib/rubygems/remote_fetcher.rb @@ -173,7 +173,7 @@ class Gem::RemoteFetcher path = source_uri.path path = File.dirname(path) if File.extname(path) == '.gem' - remote_gem_path = correct_for_windows_path(File.join(path, 'gems', gem_file_name)) + remote_gem_path = Gem::Util.correct_for_windows_path(File.join(path, 'gems', gem_file_name)) FileUtils.cp(remote_gem_path, local_gem_path) rescue Errno::EACCES @@ -210,7 +210,7 @@ class Gem::RemoteFetcher # File Fetcher. Dispatched by +fetch_path+. Use it instead. def fetch_file(uri, *_) - Gem.read_binary correct_for_windows_path uri.path + Gem.read_binary Gem::Util.correct_for_windows_path uri.path end ## @@ -317,14 +317,6 @@ class Gem::RemoteFetcher response['content-length'].to_i end - def correct_for_windows_path(path) - if path[0].chr == '/' && path[1].chr =~ /[a-z]/i && path[2].chr == ':' - path[1..-1] - else - path - end - end - ## # Performs a Net::HTTP request of type +request_class+ on +uri+ returning # a Net::HTTP response object. request maintains a table of persistent diff --git a/lib/rubygems/request/connection_pools.rb b/lib/rubygems/request/connection_pools.rb index 7c273d5465..9444239b2c 100644 --- a/lib/rubygems/request/connection_pools.rb +++ b/lib/rubygems/request/connection_pools.rb @@ -76,9 +76,7 @@ class Gem::Request::ConnectionPools # :nodoc: end def net_http_args(uri, proxy_uri) - # URI::Generic#hostname was added in ruby 1.9.3, use it if exists, otherwise - # don't support IPv6 literals and use host. - hostname = uri.respond_to?(:hostname) ? uri.hostname : uri.host + hostname = uri.hostname net_http_args = [hostname, uri.port] no_proxy = get_no_proxy_from_env diff --git a/lib/rubygems/resolver.rb b/lib/rubygems/resolver.rb index d308f68f21..f74995713b 100644 --- a/lib/rubygems/resolver.rb +++ b/lib/rubygems/resolver.rb @@ -246,7 +246,7 @@ class Gem::Resolver sources.each do |source| groups[source]. sort_by { |spec| [spec.version, Gem::Platform.local =~ spec.platform ? 1 : 0] }. - map { |spec| ActivationRequest.new spec, dependency, [] }. + map { |spec| ActivationRequest.new spec, dependency }. each { |activation_request| activation_requests << activation_request } end diff --git a/lib/rubygems/resolver/activation_request.rb b/lib/rubygems/resolver/activation_request.rb index 7fbabbff50..2a8d6032f8 100644 --- a/lib/rubygems/resolver/activation_request.rb +++ b/lib/rubygems/resolver/activation_request.rb @@ -18,14 +18,10 @@ class Gem::Resolver::ActivationRequest ## # Creates a new ActivationRequest that will activate +spec+. The parent # +request+ is used to provide diagnostics in case of conflicts. - # - # +others_possible+ indicates that other specifications may also match this - # activation request. - def initialize(spec, request, others_possible = true) + def initialize(spec, request) @spec = spec @request = request - @others_possible = others_possible end def ==(other) # :nodoc: @@ -90,21 +86,8 @@ class Gem::Resolver::ActivationRequest end def inspect # :nodoc: - others = - case @others_possible - when true then # TODO remove at RubyGems 3 - ' (others possible)' - when false then # TODO remove at RubyGems 3 - nil - else - unless @others_possible.empty? - others = @others_possible.map { |s| s.full_name } - " (others possible: #{others.join ', '})" - end - end - - '#<%s for %p from %s%s>' % [ - self.class, @spec, @request, others + '#<%s for %p from %s>' % [ + self.class, @spec, @request ] end @@ -132,19 +115,6 @@ class Gem::Resolver::ActivationRequest end ## - # Indicate if this activation is one of a set of possible - # requests for the same Dependency request. - - def others_possible? - case @others_possible - when true, false then - @others_possible - else - not @others_possible.empty? - end - end - - ## # Return the ActivationRequest that contained the dependency # that we were activated for. @@ -160,19 +130,6 @@ class Gem::Resolver::ActivationRequest q.breakable q.text ' for ' q.pp @request - - case @others_possible - when false then - when true then - q.breakable - q.text 'others possible' - else - unless @others_possible.empty? - q.breakable - q.text 'others ' - q.pp @others_possible.map { |s| s.full_name } - end - end end end diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb index 942e49bf84..c1286369be 100644 --- a/lib/rubygems/specification.rb +++ b/lib/rubygems/specification.rb @@ -743,9 +743,6 @@ class Gem::Specification < Gem::BasicSpecification def self._all # :nodoc: unless defined?(@@all) && @@all @@all = stubs.map(&:to_spec) - if @@all.any?(&:nil?) # TODO: remove once we're happy - raise "pid: #{$$} nil spec! included in #{stubs.inspect}" - end # After a reset, make sure already loaded specs # are still marked as activated. @@ -896,7 +893,6 @@ class Gem::Specification < Gem::BasicSpecification # -- wilsonb def self.all=(specs) - raise "nil spec!" if specs.any?(&:nil?) # TODO: remove once we're happy @@stubs_by_name = specs.group_by(&:name) @@all = @@stubs = specs end @@ -1498,16 +1494,7 @@ class Gem::Specification < Gem::BasicSpecification paths = full_require_paths - # gem directories must come after -I and ENV['RUBYLIB'] - insert_index = Gem.load_path_insert_index - - if insert_index - # gem directories must come after -I and ENV['RUBYLIB'] - $LOAD_PATH.insert(insert_index, *paths) - else - # we are probably testing in core, -I and RUBYLIB don't apply - $LOAD_PATH.unshift(*paths) - end + Gem.add_to_load_path(*paths) end ## @@ -1927,8 +1914,7 @@ class Gem::Specification < Gem::BasicSpecification end def gems_dir - # TODO: this logic seems terribly broken, but tests fail if just base_dir - @gems_dir ||= File.join(loaded_from && base_dir || Gem.dir, "gems") + @gems_dir ||= File.join(base_dir, "gems") end ## diff --git a/lib/rubygems/test_case.rb b/lib/rubygems/test_case.rb index 8e909e4afe..b466e7a4e0 100644 --- a/lib/rubygems/test_case.rb +++ b/lib/rubygems/test_case.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -# TODO: $SAFE = 1 require 'rubygems' @@ -27,13 +26,6 @@ begin rescue LoadError end -# We have to load these up front because otherwise we'll try to load -# them while we're testing rubygems, and thus we can't actually load them. -unless Gem::Dependency.new('rdoc', '>= 3.10').matching_specs.empty? - gem 'rdoc' - gem 'json' -end - require 'bundler' require 'minitest/autorun' @@ -91,8 +83,6 @@ end # gem-related behavior in a sandbox. Through RubyGemTestCase you can install # and uninstall gems, fetch remote gems through a stub fetcher and be assured # your normal set of gems is not affected. -# -# Tests are always run at a safe level of 1. class Gem::TestCase < (defined?(Minitest::Test) ? Minitest::Test : MiniTest::Unit::TestCase) @@ -152,6 +142,28 @@ class Gem::TestCase < (defined?(Minitest::Test) ? Minitest::Test : MiniTest::Uni end end + ## + # Sets the vendordir entry in RbConfig::CONFIG to +value+ and restores the + # original value when the block ends + # + def vendordir(value) + vendordir = RbConfig::CONFIG['vendordir'] + + if value + RbConfig::CONFIG['vendordir'] = value + else + RbConfig::CONFIG.delete 'vendordir' + end + + yield + ensure + if vendordir + RbConfig::CONFIG['vendordir'] = vendordir + else + RbConfig::CONFIG.delete 'vendordir' + end + end + # TODO: move to minitest def refute_path_exists(path, msg = nil) msg = message(msg) { "Expected path '#{path}' to not exist" } @@ -222,8 +234,6 @@ class Gem::TestCase < (defined?(Minitest::Test) ? Minitest::Test : MiniTest::Uni @@project_dir = Dir.pwd.untaint unless defined?(@@project_dir) - @@initial_reset = false - ## # #setup prepares a sandboxed location to install gems. All installs are # directed to a temporary directory. All install plugins are removed. @@ -231,24 +241,11 @@ class Gem::TestCase < (defined?(Minitest::Test) ? Minitest::Test : MiniTest::Uni # If the +RUBY+ environment variable is set the given path is used for # Gem::ruby. The local platform is set to <tt>i386-mswin32</tt> for Windows # or <tt>i686-darwin8.10.1</tt> otherwise. - # - # If the +KEEP_FILES+ environment variable is set the files will not be - # removed from <tt>/tmp/test_rubygems_#{$$}.#{Time.now.to_i}</tt>. def setup super - @orig_gem_home = ENV['GEM_HOME'] - @orig_gem_path = ENV['GEM_PATH'] - @orig_gem_vendor = ENV['GEM_VENDOR'] - @orig_gem_spec_cache = ENV['GEM_SPEC_CACHE'] - @orig_rubygems_gemdeps = ENV['RUBYGEMS_GEMDEPS'] - @orig_bundle_gemfile = ENV['BUNDLE_GEMFILE'] - @orig_rubygems_host = ENV['RUBYGEMS_HOST'] - ENV.keys.find_all { |k| k.start_with?('GEM_REQUIREMENT_') }.each do |k| - ENV.delete k - end - @orig_gem_env_requirements = ENV.to_hash + @orig_env = ENV.to_hash ENV['GEM_VENDOR'] = nil ENV['SOURCE_DATE_EPOCH'] = nil @@ -256,36 +253,20 @@ class Gem::TestCase < (defined?(Minitest::Test) ? Minitest::Test : MiniTest::Uni @current_dir = Dir.pwd @fetcher = nil - Bundler.ui = Bundler::UI::Silent.new - @back_ui = Gem::DefaultUserInteraction.ui @ui = Gem::MockGemUi.new # This needs to be a new instance since we call use_ui(@ui) when we want to # capture output Gem::DefaultUserInteraction.ui = Gem::MockGemUi.new - tmpdir = File.expand_path Dir.tmpdir + tmpdir = File.realpath Dir.tmpdir tmpdir.untaint - if ENV['KEEP_FILES'] - @tempdir = File.join(tmpdir, "test_rubygems_#{$$}.#{Time.now.to_i}") - else - @tempdir = File.join(tmpdir, "test_rubygems_#{$$}") - end + @tempdir = File.join(tmpdir, "test_rubygems_#{$$}") @tempdir.untaint FileUtils.mkdir_p @tempdir - # This makes the tempdir consistent on OS X. - # File.expand_path Dir.tmpdir #=> "/var/..." - # Dir.chdir Dir.tmpdir do File.expand_path '.' end #=> "/private/var/..." - # TODO use File#realpath above instead of #expand_path once 1.8 support is - # dropped. - Dir.chdir @tempdir do - @tempdir = File.expand_path '.' - @tempdir.untaint - end - # This makes the tempdir consistent on Windows. # Dir.tmpdir may return short path name, but Dir[Dir.tmpdir] returns long # path name. https://bugs.ruby-lang.org/issues/10819 @@ -343,25 +324,21 @@ class Gem::TestCase < (defined?(Minitest::Test) ? Minitest::Test : MiniTest::Uni @default_dir = File.join @tempdir, 'default' @default_spec_dir = File.join @default_dir, "specifications", "default" - Gem.instance_variable_set :@default_dir, @default_dir - FileUtils.mkdir_p @default_spec_dir - - # We use Gem::Specification.reset the first time only so that if there - # are unresolved deps that leak into the whole test suite, they're at least - # reported once. - if @@initial_reset - Gem::Specification.unresolved_deps.clear # done to avoid cross-test warnings + if Gem.java_platform? + @orig_default_gem_home = RbConfig::CONFIG['default_gem_home'] + RbConfig::CONFIG['default_gem_home'] = @default_dir else - @@initial_reset = true - Gem::Specification.reset + Gem.instance_variable_set(:@default_dir, @default_dir) end + FileUtils.mkdir_p @default_spec_dir + + Gem::Specification.unresolved_deps.clear Gem.use_paths(@gemhome) Gem::Security.reset Gem.loaded_specs.clear Gem.clear_default_specs - Gem::Specification.unresolved_deps.clear Bundler.reset! Gem.configuration.verbose = true @@ -395,7 +372,7 @@ class Gem::TestCase < (defined?(Minitest::Test) ? Minitest::Test : MiniTest::Uni ## # #teardown restores the process to its original state and removes the - # tempdir unless the +KEEP_FILES+ environment variable was set. + # tempdir def teardown $LOAD_PATH.replace @orig_LOAD_PATH if @orig_LOAD_PATH @@ -420,33 +397,18 @@ class Gem::TestCase < (defined?(Minitest::Test) ? Minitest::Test : MiniTest::Uni Dir.chdir @current_dir - FileUtils.rm_rf @tempdir unless ENV['KEEP_FILES'] + FileUtils.rm_rf @tempdir - ENV.clear - @orig_gem_env_requirements.each do |k,v| - ENV[k] = v - end - - ENV['GEM_HOME'] = @orig_gem_home - ENV['GEM_PATH'] = @orig_gem_path - ENV['GEM_VENDOR'] = @orig_gem_vendor - ENV['GEM_SPEC_CACHE'] = @orig_gem_spec_cache - ENV['RUBYGEMS_GEMDEPS'] = @orig_rubygems_gemdeps - ENV['BUNDLE_GEMFILE'] = @orig_bundle_gemfile - ENV['RUBYGEMS_HOST'] = @orig_rubygems_host + ENV.replace(@orig_env) Gem.ruby = @orig_ruby if @orig_ruby - if @orig_ENV_HOME - ENV['HOME'] = @orig_ENV_HOME + if Gem.java_platform? + RbConfig::CONFIG['default_gem_home'] = @orig_default_gem_home else - ENV.delete 'HOME' + Gem.instance_variable_set :@default_dir, nil end - Gem.instance_variable_set :@default_dir, nil - - ENV['GEM_PRIVATE_KEY_PASSPHRASE'] = @orig_gem_private_key_passphrase - Gem::Specification._clear_load_cache Gem::Specification.unresolved_deps.clear Gem::refresh @@ -594,22 +556,6 @@ class Gem::TestCase < (defined?(Minitest::Test) ? Minitest::Test : MiniTest::Uni end ## - # creates a temporary directory with hax - # TODO: deprecate and remove - - def create_tmpdir - tmpdir = nil - - Dir.chdir Dir.tmpdir do - tmpdir = Dir.pwd - end # HACK OSX /private/tmp - - tmpdir = File.join tmpdir, "test_rubygems_#{$$}" - FileUtils.mkdir_p tmpdir - return tmpdir - end - - ## # Enables pretty-print for all tests def mu_pp(obj) @@ -686,7 +632,7 @@ class Gem::TestCase < (defined?(Minitest::Test) ? Minitest::Test : MiniTest::Uni io.write spec.to_ruby_for_cache end - spec.loaded_from = spec.loaded_from = written_path + spec.loaded_from = written_path Gem::Specification.reset @@ -694,14 +640,6 @@ class Gem::TestCase < (defined?(Minitest::Test) ? Minitest::Test : MiniTest::Uni end ## - # TODO: remove in RubyGems 4.0 - - def quick_spec(name, version = '2') # :nodoc: - util_spec name, version - end - deprecate :quick_spec, :util_spec, 2018, 12 - - ## # Builds a gem from +spec+ and places it in <tt>File.join @gemhome, # 'cache'</tt>. Automatically creates files based on +spec.files+ @@ -744,11 +682,6 @@ class Gem::TestCase < (defined?(Minitest::Test) ? Minitest::Test : MiniTest::Uni Gem::Specification.reset end - def util_clear_default_gems - FileUtils.rm_rf @default_spec_dir - FileUtils.mkdir @default_spec_dir - end - ## # Install the provided specs @@ -802,52 +735,6 @@ class Gem::TestCase < (defined?(Minitest::Test) ? Minitest::Test : MiniTest::Uni $LOADED_FEATURES.replace old_loaded_features end - ## - # new_spec is deprecated as it is never used. - # - # TODO: remove in RubyGems 4.0 - - def new_spec(name, version, deps = nil, *files) # :nodoc: - require 'rubygems/specification' - - spec = Gem::Specification.new do |s| - s.platform = Gem::Platform::RUBY - s.name = name - s.version = version - 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" - - Array(deps).each do |n, req| - s.add_dependency n, (req || '>= 0') - end - - s.files.push(*files) unless files.empty? - - yield s if block_given? - end - - spec.loaded_from = spec.spec_file - - unless files.empty? - write_file spec.spec_file do |io| - io.write spec.to_ruby_for_cache - end - - util_build_gem spec - - cache_file = File.join @tempdir, 'gems', "#{spec.full_name}.gem" - FileUtils.mkdir_p File.dirname cache_file - FileUtils.mv spec.cache_file, cache_file - FileUtils.rm spec.spec_file - end - - spec - end - deprecate :new_spec, :none, 2018, 12 - def new_default_spec(name, version, deps = nil, *files) spec = util_spec name, version, deps @@ -910,8 +797,6 @@ class Gem::TestCase < (defined?(Minitest::Test) ? Minitest::Test : MiniTest::Uni FileUtils.rm spec.spec_file end - Gem::Specification.reset - return spec end @@ -1061,31 +946,6 @@ Also, a list: end ## - # Sets up a fake fetcher using the gems from #util_make_gems. Optionally - # additional +prerelease+ gems may be included. - # - # Gems created by this method may be fetched using Gem::RemoteFetcher. - - def util_setup_fake_fetcher(prerelease = false) - require 'zlib' - require 'socket' - require 'rubygems/remote_fetcher' - - @fetcher = Gem::FakeFetcher.new - - util_make_gems(prerelease) - Gem::Specification.reset - - @all_gems = [@a1, @a2, @a3a, @a_evil9, @b2, @c1_2].sort - @all_gem_names = @all_gems.map { |gem| gem.full_name } - - gem_names = [@a1.full_name, @a2.full_name, @a3a.full_name, @b2.full_name] - @gem_names = gem_names.sort.join("\n") - - Gem::RemoteFetcher.fetcher = @fetcher - end - - ## # Add +spec+ to +@fetcher+ serving the data in the file +path+. # +repo+ indicates which repo to make +spec+ appear to be in. @@ -1096,7 +956,6 @@ Also, a list: ## # Sets up Gem::SpecFetcher to return information from the gems in +specs+. - # Best used with +@all_gems+ from #util_setup_fake_fetcher. def util_setup_spec_fetcher(*specs) all_specs = Gem::Specification.to_a + specs @@ -1163,8 +1022,7 @@ Also, a list: end def util_set_RUBY_VERSION(version, patchlevel = nil, revision = nil, description = nil, engine = "ruby", engine_version = nil) - if Gem.instance_variables.include? :@ruby_version or - Gem.instance_variables.include? '@ruby_version' + if Gem.instance_variables.include? :@ruby_version Gem.send :remove_instance_variable, :@ruby_version end @@ -1224,6 +1082,20 @@ Also, a list: end ## + # Is this test being run on a Java platform? + + def self.java_platform? + Gem.java_platform? + end + + ## + # Is this test being run on a Java platform? + + def java_platform? + Gem.java_platform? + end + + ## # Returns whether or not we're on a version of Ruby built with VC++ (or # Borland) versus Cygwin, Mingw, etc. @@ -1623,10 +1495,3 @@ rescue LoadError, Gem::LoadError end require 'rubygems/test_utilities' -tmpdirs = [] -tmpdirs << (ENV['GEM_HOME'] = Dir.mktmpdir("home")) -tmpdirs << (ENV['GEM_PATH'] = Dir.mktmpdir("path")) -pid = $$ -END {tmpdirs.each {|dir| Dir.rmdir(dir)} if $$ == pid} -Gem.clear_paths -Gem.loaded_specs.clear diff --git a/lib/rubygems/test_utilities.rb b/lib/rubygems/test_utilities.rb index 5d02b04897..69ff05370e 100644 --- a/lib/rubygems/test_utilities.rb +++ b/lib/rubygems/test_utilities.rb @@ -241,21 +241,22 @@ class Gem::TestCase::SpecFetcherSetup def execute_operations # :nodoc: @operations.each do |operation, *arguments| + block = arguments.pop case operation when :gem then - spec, gem = @test.util_gem(*arguments, &arguments.pop) + spec, gem = @test.util_gem(*arguments, &block) write_spec spec @gems[spec] = gem @installed << spec when :download then - spec, gem = @test.util_gem(*arguments, &arguments.pop) + spec, gem = @test.util_gem(*arguments, &block) @gems[spec] = gem @downloaded << spec when :spec then - spec = @test.util_spec(*arguments, &arguments.pop) + spec = @test.util_spec(*arguments, &block) write_spec spec diff --git a/lib/rubygems/util.rb b/lib/rubygems/util.rb index 401e5609f7..b5f1408401 100644 --- a/lib/rubygems/util.rb +++ b/lib/rubygems/util.rb @@ -44,29 +44,10 @@ module Gem::Util end ## - # This calls IO.popen where it accepts an array for a +command+ (Ruby 1.9+) - # and implements an IO.popen-like behavior where it does not accept an array - # for a command. + # This calls IO.popen and reads the result def self.popen(*command) IO.popen command, &:read - rescue TypeError # ruby 1.8 only supports string command - r, w = IO.pipe - - pid = fork do - STDIN.close - STDOUT.reopen w - - exec(*command) - end - - w.close - - begin - return r.read - ensure - Process.wait pid - end end ## @@ -80,26 +61,7 @@ module Gem::Util else cmds = command.dup end - return system(*(cmds << opt)) - rescue TypeError - @silent_mutex ||= Mutex.new - - @silent_mutex.synchronize do - begin - stdout = STDOUT.dup - stderr = STDERR.dup - - STDOUT.reopen IO::NULL, 'w' - STDERR.reopen IO::NULL, 'w' - - return system(*command) - ensure - STDOUT.reopen stdout - STDERR.reopen stderr - stdout.close - stderr.close - end - end + system(*(cmds << opt)) end ## @@ -130,4 +92,16 @@ module Gem::Util end end + ## + # Corrects +path+ (usually returned by `URI.parse().path` on Windows), that + # comes with a leading slash. + + def self.correct_for_windows_path(path) + if path[0].chr == '/' && path[1].chr =~ /[a-z]/i && path[2].chr == ':' + path[1..-1] + else + path + end + end + end |