diff --git a/lib/rubygems.rb b/lib/rubygems.rb index 830c16b7d7..d263f29dd2 100644 --- a/lib/rubygems.rb +++ b/lib/rubygems.rb @@ -10,7 +10,7 @@ require 'rbconfig' require 'thread' module Gem - VERSION = "2.7.7" + VERSION = "3.0.0.beta1" end # Must be first since it unloads the prelude from 1.9.2 @@ -247,7 +247,7 @@ module Gem ## # Find the full path to the executable for gem +name+. If the +exec_name+ - # is not given, the gem's default_executable is chosen, otherwise the + # is not given, an exception will be raised, otherwise the # specified executable's path is returned. +requirements+ allows # you to specify specific gem versions. @@ -295,7 +295,7 @@ module Gem ## # Find the full path to the executable for gem +name+. If the +exec_name+ - # is not given, the gem's default_executable is chosen, otherwise the + # is not given, an exception will be raised, otherwise the # specified executable's path is returned. +requirements+ allows # you to specify specific gem versions. # @@ -373,11 +373,6 @@ module Gem spec.datadir end - class << self - extend Gem::Deprecate - deprecate :datadir, "spec.datadir", 2016, 10 - end - ## # A Zlib::Deflate.deflate wrapper @@ -582,20 +577,9 @@ An Array (#{env.inspect}) was passed in from #{caller[3]} #++ def self.find_home - windows = File::ALT_SEPARATOR - if not windows or RUBY_VERSION >= '1.9' then - File.expand_path "~" - else - ['HOME', 'USERPROFILE'].each do |key| - return File.expand_path ENV[key] if ENV[key] - end - - if ENV['HOMEDRIVE'] && ENV['HOMEPATH'] then - File.expand_path "#{ENV['HOMEDRIVE']}#{ENV['HOMEPATH']}" - end - end + Dir.home rescue - if windows then + if Gem.win_platform? then File.expand_path File.join(ENV['HOMEDRIVE'] || ENV['SystemDrive'], '/') else File.expand_path "/" @@ -696,45 +680,32 @@ An Array (#{env.inspect}) was passed in from #{caller[3]} return if @yaml_loaded return unless defined?(gem) - test_syck = ENV['TEST_SYCK'] + begin + gem 'psych', '>= 2.0.0' + rescue Gem::LoadError + # It's OK if the user does not have the psych gem installed. We will + # attempt to require the stdlib version + end - # Only Ruby 1.8 and 1.9 have syck - test_syck = false unless /^1\./ =~ RUBY_VERSION - - unless test_syck - begin - gem 'psych', '>= 2.0.0' - rescue Gem::LoadError - # It's OK if the user does not have the psych gem installed. We will - # attempt to require the stdlib version + begin + # Try requiring the gem version *or* stdlib version of psych. + require 'psych' + rescue ::LoadError + # If we can't load psych, thats fine, go on. + else + # If 'yaml' has already been required, then we have to + # be sure to switch it over to the newly loaded psych. + if defined?(YAML::ENGINE) && YAML::ENGINE.yamler != "psych" + YAML::ENGINE.yamler = "psych" end - begin - # Try requiring the gem version *or* stdlib version of psych. - require 'psych' - rescue ::LoadError - # If we can't load psych, thats fine, go on. - else - # If 'yaml' has already been required, then we have to - # be sure to switch it over to the newly loaded psych. - if defined?(YAML::ENGINE) && YAML::ENGINE.yamler != "psych" - YAML::ENGINE.yamler = "psych" - end - - require 'rubygems/psych_additions' - require 'rubygems/psych_tree' - end + require 'rubygems/psych_additions' + require 'rubygems/psych_tree' end require 'yaml' require 'rubygems/safe_yaml' - # If we're supposed to be using syck, then we may have to force - # activate it via the YAML::ENGINE API. - if test_syck and defined?(YAML::ENGINE) - YAML::ENGINE.yamler = "syck" unless YAML::ENGINE.syck? - end - # Now that we're sure some kind of yaml library is loaded, pull # in our hack to deal with Syck's DefaultKey ugliness. require 'rubygems/syck_hack' @@ -1376,7 +1347,6 @@ An Array (#{env.inspect}) was passed in from #{caller[3]} autoload :ConfigFile, 'rubygems/config_file' autoload :Dependency, 'rubygems/dependency' autoload :DependencyList, 'rubygems/dependency_list' - autoload :DependencyResolver, 'rubygems/resolver' autoload :Installer, 'rubygems/installer' autoload :Licenses, 'rubygems/util/licenses' autoload :PathSupport, 'rubygems/path_support' @@ -1397,25 +1367,22 @@ end require 'rubygems/exceptions' # REFACTOR: This should be pulled out into some kind of hacks file. -gem_preluded = Gem::GEM_PRELUDE_SUCKAGE and defined? Gem -unless gem_preluded then # TODO: remove guard after 1.9.2 dropped +begin + ## + # Defaults the operating system (or packager) wants to provide for RubyGems. + + require 'rubygems/defaults/operating_system' +rescue LoadError +end + +if defined?(RUBY_ENGINE) then begin ## - # Defaults the operating system (or packager) wants to provide for RubyGems. + # Defaults the Ruby implementation wants to provide for RubyGems - require 'rubygems/defaults/operating_system' + require "rubygems/defaults/#{RUBY_ENGINE}" rescue LoadError end - - if defined?(RUBY_ENGINE) then - begin - ## - # Defaults the Ruby implementation wants to provide for RubyGems - - require "rubygems/defaults/#{RUBY_ENGINE}" - rescue LoadError - end - end end ## diff --git a/lib/rubygems/command.rb b/lib/rubygems/command.rb index a7ec212e51..71199c59b4 100644 --- a/lib/rubygems/command.rb +++ b/lib/rubygems/command.rb @@ -152,15 +152,23 @@ class Gem::Command #-- # TODO: replace +domain+ with a parameter to suppress suggestions - def show_lookup_failure(gem_name, version, errors, domain) + def show_lookup_failure(gem_name, version, errors, domain, required_by = nil) + gem = "'#{gem_name}' (#{version})" + msg = String.new "Could not find a valid gem #{gem}" + if errors and !errors.empty? - msg = "Could not find a valid gem '#{gem_name}' (#{version}), here is why:\n".dup + msg << ", here is why:\n" errors.each { |x| msg << " #{x.wordy}\n" } - alert_error msg else - alert_error "Could not find a valid gem '#{gem_name}' (#{version}) in any repository" + if required_by and gem != required_by then + msg << " (required by #{required_by}) in any repository" + else + msg << " in any repository" + end end + alert_error msg + unless domain == :local then # HACK suggestions = Gem::SpecFetcher.fetcher.suggest_gems_from_name gem_name diff --git a/lib/rubygems/command_manager.rb b/lib/rubygems/command_manager.rb index 887272378e..e22dc5deb3 100644 --- a/lib/rubygems/command_manager.rb +++ b/lib/rubygems/command_manager.rb @@ -45,6 +45,7 @@ class Gem::CommandManager :fetch, :generate_index, :help, + :info, :install, :list, :lock, diff --git a/lib/rubygems/commands/build_command.rb b/lib/rubygems/commands/build_command.rb index 38c45e46f0..0ba24e5ea3 100644 --- a/lib/rubygems/commands/build_command.rb +++ b/lib/rubygems/commands/build_command.rb @@ -47,13 +47,15 @@ with gem spec: end if File.exist? gemspec then - spec = Gem::Specification.load gemspec + Dir.chdir(File.dirname(gemspec)) do + spec = Gem::Specification.load File.basename(gemspec) - if spec then - Gem::Package.build spec, options[:force] - else - alert_error "Error loading gemspec. Aborting." - terminate_interaction 1 + if spec then + Gem::Package.build spec, options[:force] + else + alert_error "Error loading gemspec. Aborting." + terminate_interaction 1 + end end else alert_error "Gemspec file not found: #{gemspec}" diff --git a/lib/rubygems/commands/environment_command.rb b/lib/rubygems/commands/environment_command.rb index e825c761ad..29c9d4d38f 100644 --- a/lib/rubygems/commands/environment_command.rb +++ b/lib/rubygems/commands/environment_command.rb @@ -120,6 +120,8 @@ lib/rubygems/defaults/operating_system.rb out << " - RUBY EXECUTABLE: #{Gem.ruby}\n" + out << " - GIT EXECUTABLE: #{git_path}\n" + out << " - EXECUTABLE DIRECTORY: #{Gem.bindir}\n" out << " - SPEC CACHE DIRECTORY: #{Gem.spec_cache_dir}\n" @@ -157,4 +159,21 @@ lib/rubygems/defaults/operating_system.rb out end + private + + ## + # Git binary path + + def git_path + exts = ENV["PATHEXT"] ? ENV["PATHEXT"].split(";") : [""] + ENV["PATH"].split(File::PATH_SEPARATOR).each do |path| + exts.each do |ext| + exe = File.join(path, "git#{ext}") + return exe if File.executable?(exe) && !File.directory?(exe) + end + end + + return nil + end + end diff --git a/lib/rubygems/commands/info_command.rb b/lib/rubygems/commands/info_command.rb new file mode 100644 index 0000000000..8d9611a957 --- /dev/null +++ b/lib/rubygems/commands/info_command.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require 'rubygems/command' +require 'rubygems/commands/query_command' + +class Gem::Commands::InfoCommand < Gem::Commands::QueryCommand + def initialize + super "info", "Show information for the given gem" + + remove_option('--name-matches') + remove_option('-d') + + defaults[:details] = true + defaults[:exact] = true + end + + def description # :nodoc: + "Info prints information about the gem such as name,"\ + " description, website, license and installed paths" + end + + def usage # :nodoc: + "#{program_name} GEMNAME" + end + + def arguments # :nodoc: + "GEMNAME name of the gem to print information about" + end + + def defaults_str + "--local" + end +end diff --git a/lib/rubygems/commands/install_command.rb b/lib/rubygems/commands/install_command.rb index 3a7d50517f..c6abf9cd7c 100644 --- a/lib/rubygems/commands/install_command.rb +++ b/lib/rubygems/commands/install_command.rb @@ -134,7 +134,8 @@ to write the specification by hand. For example: def check_version # :nodoc: if options[:version] != Gem::Requirement.default and get_all_gem_names.size > 1 then - alert_error "Can't use --version w/ multiple gems. Use name:ver instead." + alert_error "Can't use --version with multiple gems. You can specify multiple gems with" \ + " version requirments using `gem install 'my_gem:1.0.0' 'my_other_gem:~>2.0.0'`" terminate_interaction 1 end end @@ -148,7 +149,7 @@ to write the specification by hand. For example: @installed_specs = [] - ENV.delete 'GEM_PATH' if options[:install_dir].nil? and RUBY_VERSION > '1.9' + ENV.delete 'GEM_PATH' if options[:install_dir].nil? check_install_dir check_version @@ -250,17 +251,22 @@ to write the specification by hand. For example: get_all_gem_names_and_versions.each do |gem_name, gem_version| gem_version ||= options[:version] + domain = options[:domain] + domain = :local unless options[:suggest_alternate] begin install_gem gem_name, gem_version rescue Gem::InstallError => e alert_error "Error installing #{gem_name}:\n\t#{e.message}" exit_code |= 1 - rescue Gem::GemNotFoundException, Gem::UnsatisfiableDependencyError => e - domain = options[:domain] - domain = :local unless options[:suggest_alternate] + rescue Gem::GemNotFoundException => e show_lookup_failure e.name, e.version, e.errors, domain + exit_code |= 2 + rescue Gem::UnsatisfiableDependencyError => e + show_lookup_failure e.name, e.version, e.errors, domain, + "'#{gem_name}' (#{gem_version})" + exit_code |= 2 end end @@ -300,4 +306,3 @@ to write the specification by hand. For example: end end - diff --git a/lib/rubygems/commands/pristine_command.rb b/lib/rubygems/commands/pristine_command.rb index fafe35bec1..817e752266 100644 --- a/lib/rubygems/commands/pristine_command.rb +++ b/lib/rubygems/commands/pristine_command.rb @@ -24,7 +24,8 @@ class Gem::Commands::PristineCommand < Gem::Command add_option('--skip=gem_name', 'used on --all, skip if name == gem_name') do |value, options| - options[:skip] = value + options[:skip] ||= [] + options[:skip] << value end add_option('--[no-]extensions', @@ -115,9 +116,11 @@ extensions will be restored. next end - if spec.name == options[:skip] - say "Skipped #{spec.full_name}, it was given through options" - next + if options.has_key? :skip + if options[:skip].include? spec.name + say "Skipped #{spec.full_name}, it was given through options" + next + end end if spec.bundled_gem_in_old_ruby? diff --git a/lib/rubygems/commands/setup_command.rb b/lib/rubygems/commands/setup_command.rb index b6690c9d54..fc87063fe3 100644 --- a/lib/rubygems/commands/setup_command.rb +++ b/lib/rubygems/commands/setup_command.rb @@ -6,8 +6,10 @@ require 'rubygems/command' # RubyGems checkout or tarball. class Gem::Commands::SetupCommand < Gem::Command - HISTORY_HEADER = /^===\s*[\d.]+\s*\/\s*\d{4}-\d{2}-\d{2}\s*$/ - VERSION_MATCHER = /^===\s*([\d.]+)\s*\/\s*\d{4}-\d{2}-\d{2}\s*$/ + HISTORY_HEADER = /^===\s*[\d.a-zA-Z]+\s*\/\s*\d{4}-\d{2}-\d{2}\s*$/ + VERSION_MATCHER = /^===\s*([\d.a-zA-Z]+)\s*\/\s*\d{4}-\d{2}-\d{2}\s*$/ + + ENV_PATHS = %w[/usr/bin/env /bin/env] def initialize require 'tmpdir' @@ -85,6 +87,12 @@ class Gem::Commands::SetupCommand < Gem::Command options[:regenerate_binstubs] = value end + add_option('-E', '--[no-]env-shebang', + 'Rewrite executables with a shebang', + 'of /usr/bin/env') do |value, options| + options[:env_shebang] = value + end + @verbose = nil end @@ -119,6 +127,13 @@ By default, this RubyGems will install gem as: EOF end + module MakeDirs + def mkdir_p(path, *opts) + super + (@mkdirs ||= []) << path + end + end + def execute @verbose = Gem.configuration.really_verbose @@ -137,6 +152,7 @@ By default, this RubyGems will install gem as: else extend FileUtils end + extend MakeDirs lib_dir, bin_dir = make_destination_dirs install_destdir @@ -150,6 +166,11 @@ By default, this RubyGems will install gem as: install_default_bundler_gem + if mode = options[:dir_mode] + @mkdirs.uniq! + File.chmod(mode, @mkdirs) + end + say "RubyGems #{Gem::VERSION} installed" regenerate_binstubs if options[:regenerate_binstubs] @@ -216,6 +237,8 @@ By default, this RubyGems will install gem as: def install_executables(bin_dir) @bin_file_names = [] + prog_mode = options[:prog_mode] || 0755 + executables = { 'gem' => 'bin' } executables['bundler'] = 'bundler/exe' if Gem::USE_BUNDLER_FOR_GEMDEPS executables.each do |tool, path| @@ -238,13 +261,13 @@ By default, this RubyGems will install gem as: begin bin = File.readlines bin_file - bin[0] = "#!#{Gem.ruby}\n" + bin[0] = shebang File.open bin_tmp_file, 'w' do |fp| fp.puts bin.join end - install bin_tmp_file, dest_file, :mode => 0755 + install bin_tmp_file, dest_file, :mode => prog_mode @bin_file_names << dest_file ensure rm bin_tmp_file @@ -266,7 +289,7 @@ By default, this RubyGems will install gem as: TEXT end - install bin_cmd_file, "#{dest_file}.bat", :mode => 0755 + install bin_cmd_file, "#{dest_file}.bat", :mode => prog_mode ensure rm bin_cmd_file end @@ -275,12 +298,24 @@ By default, this RubyGems will install gem as: end end + def shebang + if options[:env_shebang] + ruby_name = RbConfig::CONFIG['ruby_install_name'] + @env_path ||= ENV_PATHS.find {|env_path| File.executable? env_path } + "#!#{@env_path} #{ruby_name}\n" + else + "#!#{Gem.ruby}\n" + end + end + def install_file file, dest_dir dest_file = File.join dest_dir, file dest_dir = File.dirname dest_file - mkdir_p dest_dir unless File.directory? dest_dir + unless File.directory? dest_dir + mkdir_p dest_dir, :mode => 0700 + end - install file, dest_file, :mode => 0644 + install file, dest_file, :mode => options[:data_mode] || 0644 end def install_lib(lib_dir) @@ -352,7 +387,7 @@ By default, this RubyGems will install gem as: specs_dir = Gem::Specification.default_specifications_dir specs_dir = File.join(options[:destdir], specs_dir) unless Gem.win_platform? - mkdir_p specs_dir + mkdir_p specs_dir, :mode => 0700 # Workaround for non-git environment. gemspec = File.open('bundler/bundler.gemspec', 'rb'){|f| f.read.gsub(/`git ls-files -z`/, "''") } @@ -387,7 +422,7 @@ By default, this RubyGems will install gem as: bundler_bin_dir = bundler_spec.bin_dir bundler_bin_dir = File.join(options[:destdir], bundler_bin_dir) unless Gem.win_platform? - mkdir_p bundler_bin_dir + mkdir_p bundler_bin_dir, :mode => 0700 bundler_spec.executables.each do |e| cp File.join("bundler", bundler_spec.bindir, e), File.join(bundler_bin_dir, e) end @@ -411,8 +446,8 @@ By default, this RubyGems will install gem as: lib_dir, bin_dir = generate_default_dirs(install_destdir) end - mkdir_p lib_dir - mkdir_p bin_dir + mkdir_p lib_dir, :mode => 0700 + mkdir_p bin_dir, :mode => 0700 return lib_dir, bin_dir end @@ -543,8 +578,7 @@ abort "#{deprecation_message}" if File.exist? release_notes then history = File.read release_notes - history.force_encoding Encoding::UTF_8 if - Object.const_defined? :Encoding + history.force_encoding Encoding::UTF_8 history = history.sub(/^# coding:.*?(?=^=)/m, '') @@ -582,8 +616,14 @@ abort "#{deprecation_message}" def regenerate_binstubs require "rubygems/commands/pristine_command" say "Regenerating binstubs" + + args = %w[--all --only-executables --silent] + if options[:env_shebang] + args << "--env-shebang" + end + command = Gem::Commands::PristineCommand.new - command.invoke(*%w[--all --only-executables --silent]) + command.invoke(*args) end end diff --git a/lib/rubygems/commands/uninstall_command.rb b/lib/rubygems/commands/uninstall_command.rb index 20b3a7a1e4..55a052284a 100644 --- a/lib/rubygems/commands/uninstall_command.rb +++ b/lib/rubygems/commands/uninstall_command.rb @@ -129,11 +129,7 @@ that is a dependency of an existing gem. You can use the specs.each do |spec| options[:version] = spec.version - - begin - Gem::Uninstaller.new(spec.name, options).uninstall - rescue Gem::InstallError - end + uninstall_gem spec.name end alert "Uninstalled all gems in #{options[:install_dir]}" @@ -153,14 +149,27 @@ that is a dependency of an existing gem. You can use the deps = deplist.strongly_connected_components.flatten.reverse deps.map(&:name).uniq.each do |gem_name| - begin - Gem::Uninstaller.new(gem_name, options).uninstall - rescue Gem::GemNotInHomeException => e - spec = e.spec - alert("In order to remove #{spec.name}, please execute:\n" + - "\tgem uninstall #{spec.name} --install-dir=#{spec.installation_path}") - end + uninstall_gem(gem_name) end end + def uninstall_gem(gem_name) + uninstall(gem_name) + rescue Gem::InstallError + nil + rescue Gem::GemNotInHomeException => e + spec = e.spec + alert("In order to remove #{spec.name}, please execute:\n" + + "\tgem uninstall #{spec.name} --install-dir=#{spec.installation_path}") + rescue Gem::UninstallError => e + spec = e.spec + alert_error("Error: unable to successfully uninstall '#{spec.name}' which is " + + "located at '#{spec.full_gem_path}'. This is most likely because" + + "the current user does not have the appropriate permissions") + terminate_interaction 1 + end + + def uninstall(gem_name) + Gem::Uninstaller.new(gem_name, options).uninstall + end end diff --git a/lib/rubygems/commands/unpack_command.rb b/lib/rubygems/commands/unpack_command.rb index bdcfd524f1..b2edf7d349 100644 --- a/lib/rubygems/commands/unpack_command.rb +++ b/lib/rubygems/commands/unpack_command.rb @@ -94,7 +94,17 @@ command help for an example. spec_file = File.basename spec.spec_file - File.open spec_file, 'w' do |io| + FileUtils.mkdir_p @options[:target] if @options[:target] + + destination = begin + if @options[:target] + File.join @options[:target], spec_file + else + spec_file + end + end + + File.open destination, 'w' do |io| io.write metadata end else diff --git a/lib/rubygems/commands/update_command.rb b/lib/rubygems/commands/update_command.rb index 93ee60e1ab..1c86ba6753 100644 --- a/lib/rubygems/commands/update_command.rb +++ b/lib/rubygems/commands/update_command.rb @@ -85,18 +85,27 @@ command to remove old versions. end def execute - if options[:system] then update_rubygems return end - say "Updating installed gems" - hig = highest_installed_gems gems_to_update = which_to_update hig, options[:args].uniq + if options[:explain] + say "Gems to update:" + + gems_to_update.each do |(name, version)| + say " #{name}-#{version}" + end + + return + end + + say "Updating installed gems" + updated = update_gems gems_to_update updated_names = updated.map { |spec| spec.name } diff --git a/lib/rubygems/compatibility.rb b/lib/rubygems/compatibility.rb index 2056b5b53a..24c741e99b 100644 --- a/lib/rubygems/compatibility.rb +++ b/lib/rubygems/compatibility.rb @@ -9,26 +9,6 @@ # Ruby 1.9.x has introduced some things that are awkward, and we need to # support them, so we define some constants to use later. #++ -module Gem - # Only MRI 1.9.2 has the custom prelude. - GEM_PRELUDE_SUCKAGE = RUBY_VERSION =~ /^1\.9\.2/ and RUBY_ENGINE == "ruby" -end - -# Gem::QuickLoader exists in the gem prelude code in ruby 1.9.2 itself. -# We gotta get rid of it if it's there, before we do anything else. -if Gem::GEM_PRELUDE_SUCKAGE and defined?(Gem::QuickLoader) then - Gem::QuickLoader.remove - - $LOADED_FEATURES.delete Gem::QuickLoader.path_to_full_rubygems_library - - if path = $LOADED_FEATURES.find {|n| n.end_with? '/rubygems.rb'} then - raise LoadError, "another rubygems is already loaded from #{path}" - end - - class << Gem - remove_method :try_activate if Gem.respond_to?(:try_activate, true) - end -end module Gem RubyGemsVersion = VERSION diff --git a/lib/rubygems/config_file.rb b/lib/rubygems/config_file.rb index c0d19dbfc2..c0fe3d8964 100644 --- a/lib/rubygems/config_file.rb +++ b/lib/rubygems/config_file.rb @@ -48,7 +48,7 @@ class Gem::ConfigFile # For Ruby packagers to set configuration defaults. Set in # rubygems/defaults/operating_system.rb - OPERATING_SYSTEM_DEFAULTS = {} + OPERATING_SYSTEM_DEFAULTS = Gem.operating_system_defaults ## # For Ruby implementers to set configuration defaults. Set in @@ -63,26 +63,7 @@ class Gem::ConfigFile require "etc" Etc.sysconfdir rescue LoadError, NoMethodError - begin - # TODO: remove after we drop 1.8.7 and 1.9.1 - require 'Win32API' - - CSIDL_COMMON_APPDATA = 0x0023 - path = 0.chr * 260 - if RUBY_VERSION > '1.9' then - SHGetFolderPath = Win32API.new 'shell32', 'SHGetFolderPath', 'PLPLP', - 'L', :stdcall - SHGetFolderPath.call nil, CSIDL_COMMON_APPDATA, nil, 1, path - else - SHGetFolderPath = Win32API.new 'shell32', 'SHGetFolderPath', 'LLLLP', - 'L' - SHGetFolderPath.call 0, CSIDL_COMMON_APPDATA, 0, 1, path - end - - path.strip - rescue LoadError - RbConfig::CONFIG["sysconfdir"] || "/etc" - end + RbConfig::CONFIG["sysconfdir"] || "/etc" end # :startdoc: diff --git a/lib/rubygems/core_ext/kernel_require.rb b/lib/rubygems/core_ext/kernel_require.rb index d3df9d85f9..e93cd7c728 100755 --- a/lib/rubygems/core_ext/kernel_require.rb +++ b/lib/rubygems/core_ext/kernel_require.rb @@ -11,13 +11,8 @@ module Kernel RUBYGEMS_ACTIVATION_MONITOR = Monitor.new # :nodoc: - if defined?(gem_original_require) then - # Ruby ships with a custom_require, override its require - remove_method :require - else - ## - # The Kernel#require from before RubyGems was loaded. - + # Make sure we have a reference to Ruby's original Kernel#require + unless defined?(gem_original_require) alias gem_original_require require private :gem_original_require end diff --git a/lib/rubygems/defaults.rb b/lib/rubygems/defaults.rb index 43d57fc808..b8222877ae 100644 --- a/lib/rubygems/defaults.rb +++ b/lib/rubygems/defaults.rb @@ -176,7 +176,26 @@ module Gem end ## - # Default options for gem commands. + # Default options for gem commands for Ruby packagers. + # + # The options here should be structured as an array of string "gem" + # command names as keys and a string of the default options as values. + # + # Example: + # + # def self.operating_system_defaults + # { + # 'install' => '--no-rdoc --no-ri --env-shebang', + # 'update' => '--no-rdoc --no-ri --env-shebang' + # } + # end + + def self.operating_system_defaults + {} + end + + ## + # Default options for gem commands for Ruby implementers. # # The options here should be structured as an array of string "gem" # command names as keys and a string of the default options as values. diff --git a/lib/rubygems/dependency_installer.rb b/lib/rubygems/dependency_installer.rb index 879e085359..4b474e1d19 100644 --- a/lib/rubygems/dependency_installer.rb +++ b/lib/rubygems/dependency_installer.rb @@ -15,6 +15,7 @@ require 'rubygems/deprecate' class Gem::DependencyInstaller include Gem::UserInteraction + extend Gem::Deprecate DEFAULT_OPTIONS = { # :nodoc: :env_shebang => false, @@ -41,15 +42,6 @@ class Gem::DependencyInstaller attr_reader :errors - ## - #-- - # TODO remove, no longer used - - attr_reader :gems_to_install # :nodoc: - - extend Gem::Deprecate - deprecate :gems_to_install, :none, 2016, 10 - ## # List of gems installed by #install in alphabetic order @@ -97,6 +89,9 @@ class Gem::DependencyInstaller @build_args = options[:build_args] @build_docs_in_background = options[:build_docs_in_background] @install_as_default = options[:install_as_default] + @dir_mode = options[:dir_mode] + @data_mode = options[:data_mode] + @prog_mode = options[:prog_mode] # Indicates that we should not try to update any deps unless # we absolutely must. @@ -404,7 +399,10 @@ class Gem::DependencyInstaller :user_install => @user_install, :wrappers => @wrappers, :build_root => @build_root, - :install_as_default => @install_as_default + :install_as_default => @install_as_default, + :dir_mode => @dir_mode, + :data_mode => @data_mode, + :prog_mode => @prog_mode, } options[:install_dir] = @install_dir if @only_install_dir diff --git a/lib/rubygems/exceptions.rb b/lib/rubygems/exceptions.rb index 328bd5f476..5999bc2a0d 100644 --- a/lib/rubygems/exceptions.rb +++ b/lib/rubygems/exceptions.rb @@ -56,6 +56,13 @@ class Gem::GemNotInHomeException < Gem::Exception attr_accessor :spec end +### +# Raised when removing a gem with the uninstall command fails + +class Gem::UninstallError < Gem::Exception + attr_accessor :spec +end + class Gem::DocumentError < Gem::Exception; end ## diff --git a/lib/rubygems/ext/builder.rb b/lib/rubygems/ext/builder.rb index eb9db199d5..805ef02422 100644 --- a/lib/rubygems/ext/builder.rb +++ b/lib/rubygems/ext/builder.rb @@ -39,7 +39,7 @@ class Gem::Ext::Builder make_program = (/mswin/ =~ RUBY_PLATFORM) ? 'nmake' : 'make' end - destdir = '"DESTDIR=%s"' % ENV['DESTDIR'] if RUBY_VERSION > '2.0' + destdir = '"DESTDIR=%s"' % ENV['DESTDIR'] ['clean', '', 'install'].each do |target| # Pass DESTDIR via command line to override what's in MAKEFLAGS @@ -160,11 +160,19 @@ EOF FileUtils.mkdir_p dest_path CHDIR_MUTEX.synchronize do - Dir.chdir extension_dir do - results = builder.build(extension, @gem_dir, dest_path, + pwd = Dir.getwd + Dir.chdir extension_dir + begin + results = builder.build(extension, dest_path, results, @build_args, lib_dir) verbose { results.join("\n") } + ensure + begin + Dir.chdir pwd + rescue SystemCallError + Dir.chdir dest_path + end end end @@ -218,4 +226,3 @@ EOF end end - diff --git a/lib/rubygems/ext/cmake_builder.rb b/lib/rubygems/ext/cmake_builder.rb index efa3bd1d88..cfcc83c9a7 100644 --- a/lib/rubygems/ext/cmake_builder.rb +++ b/lib/rubygems/ext/cmake_builder.rb @@ -2,7 +2,7 @@ require 'rubygems/command' class Gem::Ext::CmakeBuilder < Gem::Ext::Builder - def self.build(extension, directory, dest_path, results, args=[], lib_dir=nil) + def self.build(extension, dest_path, results, args=[], lib_dir=nil) unless File.exist?('Makefile') then cmd = "cmake . -DCMAKE_INSTALL_PREFIX=#{dest_path}" cmd << " #{Gem::Command.build_args.join ' '}" unless Gem::Command.build_args.empty? diff --git a/lib/rubygems/ext/configure_builder.rb b/lib/rubygems/ext/configure_builder.rb index 8b42bf7ee9..1b9e374075 100644 --- a/lib/rubygems/ext/configure_builder.rb +++ b/lib/rubygems/ext/configure_builder.rb @@ -7,7 +7,7 @@ class Gem::Ext::ConfigureBuilder < Gem::Ext::Builder - def self.build(extension, directory, dest_path, results, args=[], lib_dir=nil) + def self.build(extension, dest_path, results, args=[], lib_dir=nil) unless File.exist?('Makefile') then cmd = "sh ./configure --prefix=#{dest_path}" cmd << " #{args.join ' '}" unless args.empty? @@ -21,4 +21,3 @@ class Gem::Ext::ConfigureBuilder < Gem::Ext::Builder end end - diff --git a/lib/rubygems/ext/ext_conf_builder.rb b/lib/rubygems/ext/ext_conf_builder.rb index 965b728278..a17881a890 100644 --- a/lib/rubygems/ext/ext_conf_builder.rb +++ b/lib/rubygems/ext/ext_conf_builder.rb @@ -11,7 +11,7 @@ require 'tempfile' class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder FileEntry = FileUtils::Entry_ # :nodoc: - def self.build(extension, directory, dest_path, results, args=[], lib_dir=nil) + def self.build(extension, dest_path, results, args=[], lib_dir=nil) tmp_dest = Dir.mktmpdir(".gem.", ".") # Some versions of `mktmpdir` return absolute paths, which will break make @@ -23,9 +23,7 @@ class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder # spaces do not work. # # Details: https://github.com/rubygems/rubygems/issues/977#issuecomment-171544940 - # - # TODO: Make this unconditional when rubygems no longer supports Ruby 1.9.x. - tmp_dest = get_relative_path(tmp_dest) unless Gem.win_platform? && RUBY_VERSION <= '2.0' + tmp_dest = get_relative_path(tmp_dest) Tempfile.open %w"siteconf .rb", "." do |siteconf| siteconf.puts "require 'rbconfig'" diff --git a/lib/rubygems/ext/rake_builder.rb b/lib/rubygems/ext/rake_builder.rb index 4b3534bf35..7a5a48c6cc 100644 --- a/lib/rubygems/ext/rake_builder.rb +++ b/lib/rubygems/ext/rake_builder.rb @@ -7,7 +7,7 @@ class Gem::Ext::RakeBuilder < Gem::Ext::Builder - def self.build(extension, directory, dest_path, results, args=[], lib_dir=nil) + def self.build(extension, dest_path, results, args=[], lib_dir=nil) if File.basename(extension) =~ /mkrf_conf/i then cmd = "#{Gem.ruby} #{File.basename extension}".dup cmd << " #{args.join " "}" unless args.empty? @@ -34,4 +34,3 @@ class Gem::Ext::RakeBuilder < Gem::Ext::Builder end end - diff --git a/lib/rubygems/installer.rb b/lib/rubygems/installer.rb index 0c58c29ac9..b142454c09 100644 --- a/lib/rubygems/installer.rb +++ b/lib/rubygems/installer.rb @@ -110,6 +110,10 @@ class Gem::Installer class FakePackage attr_accessor :spec + attr_accessor :dir_mode + attr_accessor :prog_mode + attr_accessor :data_mode + def initialize(spec) @spec = spec end @@ -179,6 +183,10 @@ class Gem::Installer process_options + @package.dir_mode = options[:dir_mode] + @package.prog_mode = options[:prog_mode] + @package.data_mode = options[:data_mode] + if options[:user_install] and not options[:unpack] then @gem_home = Gem.user_dir @bin_dir = Gem.bindir gem_home unless options[:bin_dir] @@ -298,7 +306,8 @@ class Gem::Installer FileUtils.rm_rf gem_dir FileUtils.rm_rf spec.extension_dir - FileUtils.mkdir_p gem_dir + dir_mode = options[:dir_mode] + FileUtils.mkdir_p gem_dir, :mode => dir_mode && 0700 if @options[:install_as_default] then extract_bin @@ -315,6 +324,8 @@ class Gem::Installer write_cache_file end + File.chmod(dir_mode, gem_dir) if dir_mode + say spec.post_install_message if options[:post_install_message] && !spec.post_install_message.nil? Gem::Installer.install_lock.synchronize { Gem::Specification.reset } @@ -468,7 +479,7 @@ class Gem::Installer return if spec.executables.nil? or spec.executables.empty? begin - Dir.mkdir @bin_dir + Dir.mkdir @bin_dir, *[options[:dir_mode] && 0700].compact rescue SystemCallError raise unless File.directory? @bin_dir end @@ -486,7 +497,8 @@ class Gem::Installer end mode = File.stat(bin_path).mode - FileUtils.chmod mode | 0111, bin_path unless (mode | 0111) == mode + dir_mode = options[:prog_mode] || (mode | 0111) + FileUtils.chmod dir_mode, bin_path unless dir_mode == mode check_executable_overwrite filename @@ -511,8 +523,9 @@ class Gem::Installer FileUtils.rm_f bin_script_path # prior install may have been --no-wrappers - File.open bin_script_path, 'wb', 0755 do |file| + File.open bin_script_path, 'wb', 0700 do |file| file.print app_script_text(filename) + file.chmod(options[:prog_mode] || 0755) end verbose bin_script_path @@ -705,7 +718,7 @@ class Gem::Installer end def verify_gem_home(unpack = false) # :nodoc: - FileUtils.mkdir_p gem_home + FileUtils.mkdir_p gem_home, :mode => options[:dir_mode] && 0700 raise Gem::FilePermissionError, gem_home unless unpack or File.writable?(gem_home) end @@ -736,7 +749,7 @@ version = "#{Gem::Requirement.default}.a" if ARGV.first str = ARGV.first - str = str.dup.force_encoding("BINARY") if str.respond_to? :force_encoding + str = str.dup.force_encoding("BINARY") if str =~ /\\A_(.*)_\\z/ and Gem::Version.correct?($1) then version = $1 ARGV.shift @@ -868,7 +881,8 @@ TEXT build_info_dir = File.join gem_home, 'build_info' - FileUtils.mkdir_p build_info_dir + dir_mode = options[:dir_mode] + FileUtils.mkdir_p build_info_dir, :mode => dir_mode && 0700 build_info_file = File.join build_info_dir, "#{spec.full_name}.info" @@ -877,6 +891,8 @@ TEXT io.puts arg end end + + File.chmod(dir_mode, build_info_dir) if dir_mode end ## diff --git a/lib/rubygems/installer_test_case.rb b/lib/rubygems/installer_test_case.rb index 4cec5da3f4..943c6c1256 100644 --- a/lib/rubygems/installer_test_case.rb +++ b/lib/rubygems/installer_test_case.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'rubygems/test_case' require 'rubygems/installer' -require 'rubygems/deprecate' class Gem::Installer @@ -107,18 +106,6 @@ class Gem::InstallerTestCase < Gem::TestCase Gem::Installer.path_warning = false end - def util_gem_bindir spec = @spec # :nodoc: - spec.bin_dir - end - - def util_gem_dir spec = @spec # :nodoc: - spec.gem_dir - end - - extend Gem::Deprecate - deprecate :util_gem_bindir, "@spec.bin_dir", 2016, 10 - deprecate :util_gem_dir, "@spec.gem_dir", 2016, 10 - ## # The path where installed executables live diff --git a/lib/rubygems/local_remote_options.rb b/lib/rubygems/local_remote_options.rb index 597b87ea03..fe09e34e54 100644 --- a/lib/rubygems/local_remote_options.rb +++ b/lib/rubygems/local_remote_options.rb @@ -24,8 +24,10 @@ module Gem::LocalRemoteOptions raise OptionParser::InvalidArgument, value end - unless ['http', 'https', 'file', 's3'].include?(uri.scheme) - raise OptionParser::InvalidArgument, value + valid_uri_schemes = ["http", "https", "file", "s3"] + unless valid_uri_schemes.include?(uri.scheme) + msg = "Invalid uri scheme for #{value}\nPreface URLs with one of #{valid_uri_schemes.map{|s| "#{s}://"}}" + raise ArgumentError, msg end value diff --git a/lib/rubygems/package.rb b/lib/rubygems/package.rb index 729bbd6f79..b20334c8ca 100644 --- a/lib/rubygems/package.rb +++ b/lib/rubygems/package.rb @@ -107,6 +107,18 @@ class Gem::Package attr_writer :spec + ## + # Permission for directories + attr_accessor :dir_mode + + ## + # Permission for program files + attr_accessor :prog_mode + + ## + # Permission for other files + attr_accessor :data_mode + def self.build spec, skip_validation=false gem_file = spec.file_name @@ -148,7 +160,7 @@ class Gem::Package def initialize gem, security_policy # :notnew: @gem = gem - @build_time = Time.now + @build_time = ENV["SOURCE_DATE_EPOCH"] ? Time.at(ENV["SOURCE_DATE_EPOCH"].to_i).utc : Time.now @checksums = {} @contents = nil @digests = Hash.new { |h, algorithm| h[algorithm] = {} } @@ -334,7 +346,7 @@ EOM def extract_files destination_dir, pattern = "*" verify unless @spec - FileUtils.mkdir_p destination_dir + FileUtils.mkdir_p destination_dir, :mode => dir_mode && 0700 @gem.with_read_io do |io| reader = Gem::Package::TarReader.new io @@ -361,6 +373,7 @@ EOM # extracted. def extract_tar_gz io, destination_dir, pattern = "*" # :nodoc: + directories = [] if dir_mode open_tar_gz io do |tar| tar.each do |entry| next unless File.fnmatch pattern, entry.full_name, File::FNM_DOTMATCH @@ -370,19 +383,20 @@ EOM FileUtils.rm_rf destination mkdir_options = {} - mkdir_options[:mode] = entry.header.mode if entry.directory? + mkdir_options[:mode] = dir_mode ? 0700 : (entry.header.mode if entry.directory?) mkdir = if entry.directory? then destination else File.dirname destination end + directories << mkdir if directories mkdir_p_safe mkdir, mkdir_options, destination_dir, entry.full_name File.open destination, 'wb' do |out| out.write entry.read - FileUtils.chmod entry.header.mode, destination + FileUtils.chmod file_mode(entry.header.mode), destination end if entry.file? File.symlink(entry.header.linkname, destination) if entry.symlink? @@ -390,6 +404,15 @@ EOM verbose destination end end + + if directories + directories.uniq! + File.chmod(dir_mode, *directories) + end + end + + def file_mode(mode) # :nodoc: + ((mode & 0111).zero? ? data_mode : prog_mode) || mode end ## @@ -416,11 +439,8 @@ EOM raise Gem::Package::PathError.new(filename, destination_dir) if filename.start_with? '/' - destination_dir = realpath destination_dir - destination_dir = File.expand_path destination_dir - - destination = File.join destination_dir, filename - destination = File.expand_path destination + destination_dir = File.expand_path(File.realpath(destination_dir)) + destination = File.expand_path(File.join(destination_dir, filename)) raise Gem::Package::PathError.new(destination, destination_dir) unless destination.start_with? destination_dir + '/' @@ -438,10 +458,10 @@ EOM end def mkdir_p_safe mkdir, mkdir_options, destination_dir, file_name - destination_dir = realpath File.expand_path(destination_dir) + destination_dir = File.realpath(File.expand_path(destination_dir)) parts = mkdir.split(File::SEPARATOR) parts.reduce do |path, basename| - path = realpath path unless path == "" + path = File.realpath(path) unless path == "" path = File.expand_path(path + File::SEPARATOR + basename) lstat = File.lstat path rescue nil if !lstat || !lstat.directory? @@ -463,8 +483,7 @@ EOM when 'metadata.gz' then args = [entry] args << { :external_encoding => Encoding::UTF_8 } if - Object.const_defined?(:Encoding) && - Zlib::GzipReader.method(:wrap).arity != 1 + Zlib::GzipReader.method(:wrap).arity != 1 Zlib::GzipReader.wrap(*args) do |gzio| @spec = Gem::Specification.from_yaml gzio.read @@ -643,16 +662,6 @@ EOM raise Gem::Package::FormatError.new(e.message, entry.full_name) end - if File.respond_to? :realpath - def realpath file - File.realpath file - end - else - def realpath file - file - end - end - end require 'rubygems/package/digest_io' diff --git a/lib/rubygems/package/old.rb b/lib/rubygems/package/old.rb index 322d682ca8..a8457948ff 100644 --- a/lib/rubygems/package/old.rb +++ b/lib/rubygems/package/old.rb @@ -78,9 +78,9 @@ class Gem::Package::Old < Gem::Package FileUtils.rm_rf destination - FileUtils.mkdir_p File.dirname destination + FileUtils.mkdir_p File.dirname(destination), :mode => dir_mode && 0700 - File.open destination, 'wb', entry['mode'] do |out| + File.open destination, 'wb', file_mode(entry['mode']) do |out| out.write file_data end @@ -144,17 +144,9 @@ class Gem::Package::Old < Gem::Package end end - yaml_error = if RUBY_VERSION < '1.9' then - YAML::ParseError - elsif YAML.const_defined?(:ENGINE) && YAML::ENGINE.yamler == 'syck' then - YAML::ParseError - else - YAML::SyntaxError - end - begin @spec = Gem::Specification.from_yaml yaml - rescue yaml_error + rescue YAML::SyntaxError raise Gem::Exception, "Failed to parse gem specification out of gem file" end rescue ArgumentError diff --git a/lib/rubygems/package/tar_header.rb b/lib/rubygems/package/tar_header.rb index d557357114..fa1f5b6e46 100644 --- a/lib/rubygems/package/tar_header.rb +++ b/lib/rubygems/package/tar_header.rb @@ -94,12 +94,14 @@ class Gem::Package::TarHeader attr_reader(*FIELDS) + EMPTY_HEADER = ("\0" * 512).freeze # :nodoc: + ## # Creates a tar header from IO +stream+ def self.from(stream) header = stream.read 512 - empty = (header == "\0" * 512) + empty = (EMPTY_HEADER == header) fields = header.unpack UNPACK_FORMAT diff --git a/lib/rubygems/package/tar_reader.rb b/lib/rubygems/package/tar_reader.rb index 1098336e36..d00f89e7f6 100644 --- a/lib/rubygems/package/tar_reader.rb +++ b/lib/rubygems/package/tar_reader.rb @@ -93,10 +93,8 @@ class Gem::Package::TarReader def rewind if @init_pos == 0 then - raise Gem::Package::NonSeekableIO unless @io.respond_to? :rewind @io.rewind else - raise Gem::Package::NonSeekableIO unless @io.respond_to? :pos= @io.pos = @init_pos end end diff --git a/lib/rubygems/package/tar_reader/entry.rb b/lib/rubygems/package/tar_reader/entry.rb index 5f958edc2f..b6fb8c3a3a 100644 --- a/lib/rubygems/package/tar_reader/entry.rb +++ b/lib/rubygems/package/tar_reader/entry.rb @@ -145,8 +145,6 @@ class Gem::Package::TarReader::Entry def rewind check_closed - raise Gem::Package::NonSeekableIO unless @io.respond_to? :pos= - @io.pos = @orig_pos @read = 0 end diff --git a/lib/rubygems/package/tar_test_case.rb b/lib/rubygems/package/tar_test_case.rb index 46ac949587..381a5d0f43 100644 --- a/lib/rubygems/package/tar_test_case.rb +++ b/lib/rubygems/package/tar_test_case.rb @@ -94,13 +94,7 @@ class Gem::Package::TarTestCase < Gem::TestCase ASCIIZ(dname, 155) # char prefix[155]; ASCII + (Z unless filled) ] - format = "C100C8C8C8C12C12C8CC100C6C2C32C32C8C8C155" - h = if RUBY_VERSION >= "1.9" then - arr.join - else - arr = arr.join("").split(//).map{|x| x[0]} - arr.pack format - end + h = arr.join ret = h + "\0" * (512 - h.size) assert_equal(512, ret.size) ret diff --git a/lib/rubygems/package/tar_writer.rb b/lib/rubygems/package/tar_writer.rb index 390f7851a3..a2dbab9f2f 100644 --- a/lib/rubygems/package/tar_writer.rb +++ b/lib/rubygems/package/tar_writer.rb @@ -106,12 +106,10 @@ class Gem::Package::TarWriter def add_file(name, mode) # :yields: io check_closed - raise Gem::Package::NonSeekableIO unless @io.respond_to? :pos= - name, prefix = split_name name init_pos = @io.pos - @io.write "\0" * 512 # placeholder for the header + @io.write Gem::Package::TarHeader::EMPTY_HEADER # placeholder for the header yield RestrictedStream.new(@io) if block_given? @@ -125,7 +123,7 @@ class Gem::Package::TarWriter header = Gem::Package::TarHeader.new :name => name, :mode => mode, :size => size, :prefix => prefix, - :mtime => Time.now + :mtime => ENV["SOURCE_DATE_EPOCH"] ? Time.at(ENV["SOURCE_DATE_EPOCH"].to_i).utc : Time.now @io.write header @io.pos = final_pos @@ -220,7 +218,7 @@ class Gem::Package::TarWriter header = Gem::Package::TarHeader.new(:name => name, :mode => mode, :size => size, :prefix => prefix, - :mtime => Time.now).to_s + :mtime => ENV["SOURCE_DATE_EPOCH"] ? Time.at(ENV["SOURCE_DATE_EPOCH"].to_i).utc : Time.now).to_s @io.write header os = BoundedStream.new @io, size @@ -248,7 +246,7 @@ class Gem::Package::TarWriter :size => 0, :typeflag => "2", :linkname => target, :prefix => prefix, - :mtime => Time.now).to_s + :mtime => ENV["SOURCE_DATE_EPOCH"] ? Time.at(ENV["SOURCE_DATE_EPOCH"].to_i).utc : Time.now).to_s @io.write header @@ -301,7 +299,7 @@ class Gem::Package::TarWriter header = Gem::Package::TarHeader.new :name => name, :mode => mode, :typeflag => "5", :size => 0, :prefix => prefix, - :mtime => Time.now + :mtime => ENV["SOURCE_DATE_EPOCH"] ? Time.at(ENV["SOURCE_DATE_EPOCH"].to_i).utc : Time.now @io.write header diff --git a/lib/rubygems/rdoc.rb b/lib/rubygems/rdoc.rb index 7043bd2a31..dfaf7c55bf 100644 --- a/lib/rubygems/rdoc.rb +++ b/lib/rubygems/rdoc.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true require 'rubygems' -require 'rubygems/user_interaction' -require 'fileutils' begin gem 'rdoc' @@ -15,321 +13,12 @@ else Gem.finish_resolve end -loaded_hook = false - begin require 'rdoc/rubygems_hook' - loaded_hook = true module Gem RDoc = ::RDoc::RubygemsHook end rescue LoadError end -## -# Gem::RDoc provides methods to generate RDoc and ri data for installed gems. -# It works for RDoc 1.0.1 (in Ruby 1.8) up to RDoc 3.6. -# -# This implementation is considered obsolete. The RDoc project is the -# appropriate location to find this functionality. This file provides the -# hooks to load RDoc generation code from the "rdoc" gem and a fallback in -# case the installed version of RDoc does not have them. - -class Gem::RDoc # :nodoc: all - - include Gem::UserInteraction - extend Gem::UserInteraction - - @rdoc_version = nil - @specs = [] - - ## - # Force installation of documentation? - - attr_accessor :force - - ## - # Generate rdoc? - - attr_accessor :generate_rdoc - - ## - # Generate ri data? - - attr_accessor :generate_ri - - class << self - - ## - # Loaded version of RDoc. Set by ::load_rdoc - - attr_reader :rdoc_version - - end - - ## - # Post installs hook that generates documentation for each specification in - # +specs+ - - def self.generation_hook installer, specs - start = Time.now - types = installer.document - - generate_rdoc = types.include? 'rdoc' - generate_ri = types.include? 'ri' - - specs.each do |spec| - new(spec, generate_rdoc, generate_ri).generate - end - - return unless generate_rdoc or generate_ri - - duration = (Time.now - start).to_i - names = specs.map(&:name).join ', ' - - say "Done installing documentation for #{names} after #{duration} seconds" - end - - ## - # Loads the RDoc generator - - def self.load_rdoc - return if @rdoc_version - - require 'rdoc/rdoc' - - @rdoc_version = if ::RDoc.const_defined? :VERSION then - Gem::Version.new ::RDoc::VERSION - else - Gem::Version.new '1.0.1' - end - - rescue LoadError => e - raise Gem::DocumentError, "RDoc is not installed: #{e}" - end - - ## - # Creates a new documentation generator for +spec+. RDoc and ri data - # generation can be enabled or disabled through +generate_rdoc+ and - # +generate_ri+ respectively. - # - # Only +generate_ri+ is enabled by default. - - def initialize spec, generate_rdoc = true, generate_ri = true - @doc_dir = spec.doc_dir - @file_info = nil - @force = false - @rdoc = nil - @spec = spec - - @generate_rdoc = generate_rdoc - @generate_ri = generate_ri - - @rdoc_dir = spec.doc_dir 'rdoc' - @ri_dir = spec.doc_dir 'ri' - end - - ## - # Removes legacy rdoc arguments from +args+ - #-- - # TODO move to RDoc::Options - - def delete_legacy_args args - args.delete '--inline-source' - args.delete '--promiscuous' - args.delete '-p' - args.delete '--one-file' - end - - ## - # Generates documentation using the named +generator+ ("darkfish" or "ri") - # and following the given +options+. - # - # Documentation will be generated into +destination+ - - def document generator, options, destination - generator_name = generator - - options = options.dup - options.exclude ||= [] # TODO maybe move to RDoc::Options#finish - options.setup_generator generator - options.op_dir = destination - options.finish - - generator = options.generator.new @rdoc.store, options - - @rdoc.options = options - @rdoc.generator = generator - - say "Installing #{generator_name} documentation for #{@spec.full_name}" - - FileUtils.mkdir_p options.op_dir - - Dir.chdir options.op_dir do - begin - @rdoc.class.current = @rdoc - @rdoc.generator.generate @file_info - ensure - @rdoc.class.current = nil - end - end - end - - ## - # Generates RDoc and ri data - - def generate - return unless @generate_ri or @generate_rdoc - - setup - - options = nil - - if Gem::Requirement.new('< 3').satisfied_by? self.class.rdoc_version then - generate_legacy - return - end - - ::RDoc::TopLevel.reset # TODO ::RDoc::RDoc.reset - ::RDoc::Parser::C.reset - - args = @spec.rdoc_options - args.concat @spec.source_paths - args.concat @spec.extra_rdoc_files - - case config_args = Gem.configuration[:rdoc] - when String then - args = args.concat config_args.split - when Array then - args = args.concat config_args - end - - delete_legacy_args args - - Dir.chdir @spec.full_gem_path do - options = ::RDoc::Options.new - options.default_title = "#{@spec.full_name} Documentation" - options.parse args - end - - options.quiet = !Gem.configuration.really_verbose - - @rdoc = new_rdoc - @rdoc.options = options - - say "Parsing documentation for #{@spec.full_name}" - - Dir.chdir @spec.full_gem_path do - @file_info = @rdoc.parse_files options.files - end - - document 'ri', options, @ri_dir if - @generate_ri and (@force or not File.exist? @ri_dir) - - document 'darkfish', options, @rdoc_dir if - @generate_rdoc and (@force or not File.exist? @rdoc_dir) - end - - ## - # Generates RDoc and ri data for legacy RDoc versions. This method will not - # exist in future versions. - - def generate_legacy - if @generate_rdoc then - FileUtils.rm_rf @rdoc_dir - say "Installing RDoc documentation for #{@spec.full_name}" - legacy_rdoc '--op', @rdoc_dir - end - - if @generate_ri then - FileUtils.rm_rf @ri_dir - say "Installing ri documentation for #{@spec.full_name}" - legacy_rdoc '--ri', '--op', @ri_dir - end - end - - ## - # Generates RDoc using a legacy version of RDoc from the ARGV-like +args+. - # This method will not exist in future versions. - - def legacy_rdoc *args - args << @spec.rdoc_options - args << '--quiet' - args << @spec.require_paths.clone - args << @spec.extra_rdoc_files - args << '--title' << "#{@spec.full_name} Documentation" - args = args.flatten.map do |arg| arg.to_s end - - delete_legacy_args args if - Gem::Requirement.new('>= 2.4.0') =~ self.class.rdoc_version - - r = new_rdoc - verbose { "rdoc #{args.join ' '}" } - - Dir.chdir @spec.full_gem_path do - begin - r.document args - rescue Errno::EACCES => e - dirname = File.dirname e.message.split("-")[1].strip - raise Gem::FilePermissionError, dirname - rescue Interrupt => e - raise e - rescue Exception => ex - alert_error "While generating documentation for #{@spec.full_name}" - ui.errs.puts "... MESSAGE: #{ex}" - ui.errs.puts "... RDOC args: #{args.join(' ')}" - ui.backtrace ex - ui.errs.puts "(continuing with the rest of the installation)" - end - end - end - - ## - # #new_rdoc creates a new RDoc instance. This method is provided only to - # make testing easier. - - def new_rdoc # :nodoc: - ::RDoc::RDoc.new - end - - ## - # Is rdoc documentation installed? - - def rdoc_installed? - File.exist? @rdoc_dir - end - - ## - # Removes generated RDoc and ri data - - def remove - base_dir = @spec.base_dir - - raise Gem::FilePermissionError, base_dir unless File.writable? base_dir - - FileUtils.rm_rf @rdoc_dir - FileUtils.rm_rf @ri_dir - end - - ## - # Is ri data installed? - - def ri_installed? - File.exist? @ri_dir - end - - ## - # Prepares the spec for documentation generation - - def setup - self.class.load_rdoc - - raise Gem::FilePermissionError, @doc_dir if - File.exist?(@doc_dir) and not File.writable?(@doc_dir) - - FileUtils.mkdir_p @doc_dir unless File.exist? @doc_dir - end - -end unless loaded_hook - Gem.done_installing(&Gem::RDoc.method(:generation_hook)) diff --git a/lib/rubygems/remote_fetcher.rb b/lib/rubygems/remote_fetcher.rb index 80fb1aaaa5..a829268f39 100644 --- a/lib/rubygems/remote_fetcher.rb +++ b/lib/rubygems/remote_fetcher.rb @@ -164,9 +164,7 @@ class Gem::RemoteFetcher begin source_uri = URI.parse(source_uri) rescue - source_uri = URI.parse(URI.const_defined?(:DEFAULT_PARSER) ? - URI::DEFAULT_PARSER.escape(source_uri.to_s) : - URI.escape(source_uri.to_s)) + source_uri = URI.parse(URI::DEFAULT_PARSER.escape(source_uri.to_s)) end end diff --git a/lib/rubygems/request/connection_pools.rb b/lib/rubygems/request/connection_pools.rb index 31fc609800..d70dea785a 100644 --- a/lib/rubygems/request/connection_pools.rb +++ b/lib/rubygems/request/connection_pools.rb @@ -54,10 +54,23 @@ class Gem::Request::ConnectionPools # :nodoc: host = host.downcase env_no_proxy.any? do |pattern| - pattern = pattern.downcase + env_no_proxy_pattern = pattern.downcase.dup - host[-pattern.length, pattern.length] == pattern or - (pattern.start_with? '.' and pattern[1..-1] == host) + # Remove dot in front of pattern for wildcard matching + env_no_proxy_pattern[0] = "" if env_no_proxy_pattern[0] == "." + + host_tokens = host.split(".") + pattern_tokens = env_no_proxy_pattern.split(".") + + intersection = (host_tokens - pattern_tokens) | (pattern_tokens - host_tokens) + + # When we do the split into tokens we miss a dot character, so add it back if we need it + missing_dot = intersection.length > 0 ? 1 : 0 + start = intersection.join(".").size + missing_dot + + no_proxy_host = host[start..-1] + + env_no_proxy_pattern == no_proxy_host end end diff --git a/lib/rubygems/request_set.rb b/lib/rubygems/request_set.rb index e54a7b8818..89f47616ec 100644 --- a/lib/rubygems/request_set.rb +++ b/lib/rubygems/request_set.rb @@ -191,22 +191,7 @@ class Gem::RequestSet return requests if options[:gemdeps] - specs = requests.map do |request| - case request - when Gem::Resolver::ActivationRequest then - request.spec.spec - else - request - end - end - - require 'rubygems/dependency_installer' - inst = Gem::DependencyInstaller.new options - inst.installed_gems.replace specs - - Gem.done_installing_hooks.each do |hook| - hook.call inst, specs - end unless Gem.done_installing_hooks.empty? + install_hooks requests, options requests end @@ -283,11 +268,35 @@ class Gem::RequestSet installed << request end + install_hooks installed, options + installed ensure ENV['GEM_HOME'] = gem_home end + ## + # Call hooks on installed gems + + def install_hooks requests, options + specs = requests.map do |request| + case request + when Gem::Resolver::ActivationRequest then + request.spec.spec + else + request + end + end + + require "rubygems/dependency_installer" + inst = Gem::DependencyInstaller.new options + inst.installed_gems.replace specs + + Gem.done_installing_hooks.each do |hook| + hook.call inst, specs + end unless Gem.done_installing_hooks.empty? + end + ## # Load a dependency management file. diff --git a/lib/rubygems/request_set/gem_dependency_api.rb b/lib/rubygems/request_set/gem_dependency_api.rb index 867086cc0e..a26e8b90a3 100644 --- a/lib/rubygems/request_set/gem_dependency_api.rb +++ b/lib/rubygems/request_set/gem_dependency_api.rb @@ -842,8 +842,4 @@ Gem dependencies file #{@path} includes git reference for both ref/branch and ta Gem.sources << url end - # TODO: remove this typo name at RubyGems 3.0 - - Gem::RequestSet::GemDepedencyAPI = self # :nodoc: - end diff --git a/lib/rubygems/request_set/lockfile/parser.rb b/lib/rubygems/request_set/lockfile/parser.rb index ebea940188..368b56e6e6 100644 --- a/lib/rubygems/request_set/lockfile/parser.rb +++ b/lib/rubygems/request_set/lockfile/parser.rb @@ -325,24 +325,13 @@ class Gem::RequestSet::Lockfile::Parser @tokens.peek end - if [].respond_to? :flat_map - def pinned_requirement name # :nodoc: - requirement = Gem::Dependency.new name - specification = @set.sets.flat_map { |set| - set.find_all(requirement) - }.compact.first + def pinned_requirement name # :nodoc: + requirement = Gem::Dependency.new name + specification = @set.sets.flat_map { |set| + set.find_all(requirement) + }.compact.first - specification && specification.version - end - else # FIXME: remove when 1.8 is dropped - def pinned_requirement name # :nodoc: - requirement = Gem::Dependency.new name - specification = @set.sets.map { |set| - set.find_all(requirement) - }.flatten(1).compact.first - - specification && specification.version - end + specification && specification.version end ## diff --git a/lib/rubygems/requirement.rb b/lib/rubygems/requirement.rb index 2a60c86e69..430f351280 100644 --- a/lib/rubygems/requirement.rb +++ b/lib/rubygems/requirement.rb @@ -133,6 +133,7 @@ class Gem::Requirement @requirements = [DefaultRequirement] else @requirements = requirements.map! { |r| self.class.parse r } + sort_requirements! end end @@ -146,6 +147,7 @@ class Gem::Requirement new = new.map { |r| self.class.parse r } @requirements.concat new + sort_requirements! end ## @@ -183,11 +185,11 @@ class Gem::Requirement end def as_list # :nodoc: - requirements.map { |op, version| "#{op} #{version}" }.sort + requirements.map { |op, version| "#{op} #{version}" } end def hash # :nodoc: - requirements.sort.hash + requirements.hash end def marshal_dump # :nodoc: @@ -264,7 +266,8 @@ class Gem::Requirement end def == other # :nodoc: - Gem::Requirement === other and to_s == other.to_s + return unless Gem::Requirement === other + requirements == other.requirements end private @@ -279,6 +282,14 @@ class Gem::Requirement end end end + + def sort_requirements! # :nodoc: + @requirements.sort! do |l, r| + comp = l.last <=> r.last # first, sort by the requirement's version + next comp unless comp == 0 + l.first <=> r.first # then, sort by the operator (for stability) + end + end end class Gem::Version diff --git a/lib/rubygems/resolver.rb b/lib/rubygems/resolver.rb index 13ee035e4c..866998dc59 100644 --- a/lib/rubygems/resolver.rb +++ b/lib/rubygems/resolver.rb @@ -171,7 +171,7 @@ class Gem::Resolver include Molinillo::UI def output - @output ||= debug? ? $stdout : File.open(Gem::Util::NULL_DEVICE, 'w') + @output ||= debug? ? $stdout : File.open(IO::NULL, 'w') end def debug? @@ -314,11 +314,6 @@ class Gem::Resolver end -## -# TODO remove in RubyGems 3 - -Gem::DependencyResolver = Gem::Resolver # :nodoc: - require 'rubygems/resolver/activation_request' require 'rubygems/resolver/conflict' require 'rubygems/resolver/dependency_request' diff --git a/lib/rubygems/resolver/api_specification.rb b/lib/rubygems/resolver/api_specification.rb index 1e22dd0b6f..c4e8a7cb54 100644 --- a/lib/rubygems/resolver/api_specification.rb +++ b/lib/rubygems/resolver/api_specification.rb @@ -21,6 +21,7 @@ class Gem::Resolver::APISpecification < Gem::Resolver::Specification @name = api_data[:name] @version = Gem::Version.new api_data[:number] @platform = Gem::Platform.new api_data[:platform] + @original_platform = api_data[:platform] @dependencies = api_data[:dependencies].map do |name, ver| Gem::Dependency.new name, ver.split(/\s*,\s*/) end @@ -73,7 +74,11 @@ class Gem::Resolver::APISpecification < Gem::Resolver::Specification @spec ||= begin tuple = Gem::NameTuple.new @name, @version, @platform + source.fetch_spec tuple + rescue Gem::RemoteFetcher::FetchError + raise if @original_platform == @platform + tuple = Gem::NameTuple.new @name, @version, @original_platform source.fetch_spec tuple end end diff --git a/lib/rubygems/security/trust_dir.rb b/lib/rubygems/security/trust_dir.rb index 849cf3cd3e..62dbe29e4e 100644 --- a/lib/rubygems/security/trust_dir.rb +++ b/lib/rubygems/security/trust_dir.rb @@ -93,8 +93,9 @@ class Gem::Security::TrustDir destination = cert_path certificate - File.open destination, 'wb', @permissions[:trusted_cert] do |io| + File.open destination, 'wb', 0600 do |io| io.write certificate.to_pem + io.chmod(@permissions[:trusted_cert]) end end diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb index 49cd50794f..2fe315f4f6 100644 --- a/lib/rubygems/specification.rb +++ b/lib/rubygems/specification.rb @@ -13,9 +13,9 @@ require 'rubygems/platform' require 'rubygems/deprecate' require 'rubygems/basic_specification' require 'rubygems/stub_specification' +require 'rubygems/specification_policy' require 'rubygems/util/list' require 'stringio' -require 'uri' ## # The Specification class contains the information for a Gem. Typically @@ -135,7 +135,7 @@ class Gem::Specification < Gem::BasicSpecification :autorequire => nil, :bindir => 'bin', :cert_chain => [], - :date => TODAY, + :date => nil, :dependencies => [], :description => nil, :email => nil, @@ -788,52 +788,22 @@ class Gem::Specification < Gem::BasicSpecification end private_class_method :installed_stubs - if [].respond_to? :flat_map - def self.map_stubs(dirs, pattern) # :nodoc: - dirs.flat_map { |dir| - base_dir = File.dirname dir - gems_dir = File.join base_dir, "gems" - gemspec_stubs_in(dir, pattern) { |path| yield path, base_dir, gems_dir } - } - end - else # FIXME: remove when 1.8 is dropped - def self.map_stubs(dirs, pattern) # :nodoc: - dirs.map { |dir| - base_dir = File.dirname dir - gems_dir = File.join base_dir, "gems" - gemspec_stubs_in(dir, pattern) { |path| yield path, base_dir, gems_dir } - }.flatten 1 - end + def self.map_stubs(dirs, pattern) # :nodoc: + dirs.flat_map { |dir| + base_dir = File.dirname dir + gems_dir = File.join base_dir, "gems" + gemspec_stubs_in(dir, pattern) { |path| yield path, base_dir, gems_dir } + } end private_class_method :map_stubs - uniq_takes_a_block = false - [1,2].uniq { uniq_takes_a_block = true } - - if uniq_takes_a_block - def self.uniq_by(list, &block) # :nodoc: - list.uniq(&block) - end - else # FIXME: remove when 1.8 is dropped - def self.uniq_by(list) # :nodoc: - values = {} - list.each { |item| - value = yield item - values[value] ||= item - } - values.values - end + def self.uniq_by(list, &block) # :nodoc: + list.uniq(&block) end private_class_method :uniq_by - if [].respond_to? :sort_by! - def self.sort_by! list, &block - list.sort_by!(&block) - end - else # FIXME: remove when 1.8 is dropped - def self.sort_by! list, &block - list.replace list.sort_by(&block) - end + def self.sort_by! list, &block + list.sort_by!(&block) end private_class_method :sort_by! @@ -1185,11 +1155,7 @@ class Gem::Specification < Gem::BasicSpecification file = file.dup.untaint return unless File.file?(file) - code = if defined? Encoding - File.read file, :mode => 'r:UTF-8:-' - else - File.read file - end + code = File.read file, :mode => 'r:UTF-8:-' code.untaint @@ -1747,13 +1713,16 @@ class Gem::Specification < Gem::BasicSpecification } end - ## - # The date this gem was created. Lazily defaults to the current UTC date. + # The date this gem was created. # - # There is no need to set this in your gem specification. + # If SOURCE_DATE_EPOCH is set as an environment variable, use that to support + # reproducible builds; otherwise, default to the current UTC date. + # + # Details on SOURCE_DATE_EPOCH: + # https://reproducible-builds.org/specs/source-date-epoch/ def date - @date ||= TODAY + @date ||= ENV["SOURCE_DATE_EPOCH"] ? Time.utc(*Time.at(ENV["SOURCE_DATE_EPOCH"].to_i).utc.to_a[3..5].reverse) : TODAY end DateLike = Object.new # :nodoc: @@ -2620,32 +2589,23 @@ class Gem::Specification < Gem::BasicSpecification end def to_yaml(opts = {}) # :nodoc: - if (YAML.const_defined?(:ENGINE) && !YAML::ENGINE.syck?) || - (defined?(Psych) && YAML == Psych) then - # Because the user can switch the YAML engine behind our - # back, we have to check again here to make sure that our - # psych code was properly loaded, and load it if not. - unless Gem.const_defined?(:NoAliasYAMLTree) - require 'rubygems/psych_tree' - end - - builder = Gem::NoAliasYAMLTree.create - builder << self - ast = builder.tree - - io = StringIO.new - io.set_encoding Encoding::UTF_8 if Object.const_defined? :Encoding - - Psych::Visitors::Emitter.new(io).accept(ast) - - io.string.gsub(/ !!null \n/, " \n") - else - YAML.quick_emit object_id, opts do |out| - out.map taguri, to_yaml_style do |map| - encode_with map - end - end + # Because the user can switch the YAML engine behind our + # back, we have to check again here to make sure that our + # psych code was properly loaded, and load it if not. + unless Gem.const_defined?(:NoAliasYAMLTree) + require 'rubygems/psych_tree' end + + builder = Gem::NoAliasYAMLTree.create + builder << self + ast = builder.tree + + io = StringIO.new + io.set_encoding Encoding::UTF_8 + + Psych::Visitors::Emitter.new(io).accept(ast) + + io.string.gsub(/ !!null \n/, " \n") end ## @@ -2691,330 +2651,39 @@ class Gem::Specification < Gem::BasicSpecification extend Gem::UserInteraction normalize - nil_attributes = self.class.non_nil_attributes.find_all do |attrname| - instance_variable_get("@#{attrname}").nil? - end - - unless nil_attributes.empty? then - raise Gem::InvalidSpecificationException, - "#{nil_attributes.join ', '} must not be nil" - end - - if packaging and rubygems_version != Gem::VERSION then - raise Gem::InvalidSpecificationException, - "expected RubyGems version #{Gem::VERSION}, was #{rubygems_version}" - end - - @@required_attributes.each do |symbol| - unless self.send symbol then - raise Gem::InvalidSpecificationException, - "missing value for attribute #{symbol}" - end - end - - if !name.is_a?(String) then - raise Gem::InvalidSpecificationException, - "invalid value for attribute name: \"#{name.inspect}\" must be a string" - elsif name !~ /[a-zA-Z]/ then - raise Gem::InvalidSpecificationException, - "invalid value for attribute name: #{name.dump} must include at least one letter" - elsif name !~ VALID_NAME_PATTERN then - raise Gem::InvalidSpecificationException, - "invalid value for attribute name: #{name.dump} can only include letters, numbers, dashes, and underscores" - end - - if raw_require_paths.empty? then - raise Gem::InvalidSpecificationException, - 'specification must have at least one require_path' - end - - @files.delete_if { |x| File.directory?(x) && !File.symlink?(x) } - @test_files.delete_if { |x| File.directory?(x) && !File.symlink?(x) } - @executables.delete_if { |x| File.directory?(File.join(@bindir, x)) } - @extra_rdoc_files.delete_if { |x| File.directory?(x) && !File.symlink?(x) } - @extensions.delete_if { |x| File.directory?(x) && !File.symlink?(x) } - - non_files = files.reject { |x| File.file?(x) || File.symlink?(x) } - - unless not packaging or non_files.empty? then - raise Gem::InvalidSpecificationException, - "[\"#{non_files.join "\", \""}\"] are not files" - end - - if files.include? file_name then - raise Gem::InvalidSpecificationException, - "#{full_name} contains itself (#{file_name}), check your files list" - end - - unless specification_version.is_a?(Integer) - raise Gem::InvalidSpecificationException, - 'specification_version must be an Integer (did you mean version?)' - end - - case platform - when Gem::Platform, Gem::Platform::RUBY then # ok - else - raise Gem::InvalidSpecificationException, - "invalid platform #{platform.inspect}, see Gem::Platform" - end - - self.class.array_attributes.each do |field| - val = self.send field - klass = case field - when :dependencies - Gem::Dependency - else - String - end - - unless Array === val and val.all? { |x| x.kind_of?(klass) } then - raise(Gem::InvalidSpecificationException, - "#{field} must be an Array of #{klass}") - end - end - - [:authors].each do |field| - val = self.send field - raise Gem::InvalidSpecificationException, "#{field} may not be empty" if - val.empty? - end - - unless Hash === metadata - raise Gem::InvalidSpecificationException, - 'metadata must be a hash' - end - - validate_metadata - - licenses.each { |license| - if license.length > 64 - raise Gem::InvalidSpecificationException, - "each license must be 64 characters or less" - end - - if !Gem::Licenses.match?(license) - suggestions = Gem::Licenses.suggestions(license) - message = <<-warning -license value '#{license}' is invalid. Use a license identifier from -http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard license. - warning - message += "Did you mean #{suggestions.map { |s| "'#{s}'"}.join(', ')}?\n" unless suggestions.nil? - warning(message) - end - } - - warning <<-warning if licenses.empty? -licenses is empty, but is recommended. Use a license identifier from -http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard license. - warning - - validate_permissions - - # reject lazy developers: - - lazy = '"FIxxxXME" or "TOxxxDO"'.gsub(/xxx/, '') - - unless authors.grep(/FI XME|TO DO/x).empty? then - raise Gem::InvalidSpecificationException, "#{lazy} is not an author" - end - - unless Array(email).grep(/FI XME|TO DO/x).empty? then - raise Gem::InvalidSpecificationException, "#{lazy} is not an email" - end - - if description =~ /FI XME|TO DO/x then - raise Gem::InvalidSpecificationException, "#{lazy} is not a description" - end - - if summary =~ /FI XME|TO DO/x then - raise Gem::InvalidSpecificationException, "#{lazy} is not a summary" - end - - # Make sure a homepage is valid HTTP/HTTPS URI - if homepage and not homepage.empty? - begin - homepage_uri = URI.parse(homepage) - unless [URI::HTTP, URI::HTTPS].member? homepage_uri.class - raise Gem::InvalidSpecificationException, "\"#{homepage}\" is not a valid HTTP URI" - end - rescue URI::InvalidURIError - raise Gem::InvalidSpecificationException, "\"#{homepage}\" is not a valid HTTP URI" - end - end - - # Warnings - - %w[author homepage summary files].each do |attribute| - value = self.send attribute - warning "no #{attribute} specified" if value.nil? or value.empty? - end - - if description == summary then - warning 'description and summary are identical' - end - - # TODO: raise at some given date - warning "deprecated autorequire specified" if autorequire - - executables.each do |executable| - executable_path = File.join(bindir, executable) - shebang = File.read(executable_path, 2) == '#!' - - warning "#{executable_path} is missing #! line" unless shebang - end - - files.each do |file| - next unless File.symlink?(file) - warning "#{file} is a symlink, which is not supported on all platforms" - end - - validate_dependencies - - true + validation_policy = Gem::SpecificationPolicy.new(self) + validation_policy.packaging = packaging + validation_policy.validate ensure if $! or @warnings > 0 then alert_warning "See http://guides.rubygems.org/specification-reference/ for help" end end + def keep_only_files_and_directories + @executables.delete_if { |x| File.directory?(File.join(@bindir, x)) } + @extensions.delete_if { |x| File.directory?(x) && !File.symlink?(x) } + @extra_rdoc_files.delete_if { |x| File.directory?(x) && !File.symlink?(x) } + @files.delete_if { |x| File.directory?(x) && !File.symlink?(x) } + @test_files.delete_if { |x| File.directory?(x) && !File.symlink?(x) } + end + def validate_metadata - url_validation_regex = %r{\Ahttps?:\/\/([^\s:@]+:[^\s:@]*@)?[A-Za-z\d\-]+(\.[A-Za-z\d\-]+)+\.?(:\d{1,5})?([\/?]\S*)?\z} - link_keys = %w( - bug_tracker_uri - changelog_uri - documentation_uri - homepage_uri - mailing_list_uri - source_code_uri - wiki_uri - ) - - metadata.each do|key, value| - if !key.kind_of?(String) - raise Gem::InvalidSpecificationException, - "metadata keys must be a String" - end - - if key.size > 128 - raise Gem::InvalidSpecificationException, - "metadata key too large (#{key.size} > 128)" - end - - if !value.kind_of?(String) - raise Gem::InvalidSpecificationException, - "metadata values must be a String" - end - - if value.size > 1024 - raise Gem::InvalidSpecificationException, - "metadata value too large (#{value.size} > 1024)" - end - - if link_keys.include? key - if value !~ url_validation_regex - raise Gem::InvalidSpecificationException, - "metadata['#{key}'] has invalid link: #{value.inspect}" - end - end - end + Gem::SpecificationPolicy.new(self).validate_metadata end ## # Checks that dependencies use requirements as we recommend. Warnings are # issued when dependencies are open-ended or overly strict for semantic # versioning. - - def validate_dependencies # :nodoc: - # NOTE: see REFACTOR note in Gem::Dependency about types - this might be brittle - seen = Gem::Dependency::TYPES.inject({}) { |types, type| types.merge({ type => {}}) } - - error_messages = [] - warning_messages = [] - dependencies.each do |dep| - if prev = seen[dep.type][dep.name] then - error_messages << <<-MESSAGE -duplicate dependency on #{dep}, (#{prev.requirement}) use: - add_#{dep.type}_dependency '#{dep.name}', '#{dep.requirement}', '#{prev.requirement}' - MESSAGE - end - - seen[dep.type][dep.name] = dep - - prerelease_dep = dep.requirements_list.any? do |req| - Gem::Requirement.new(req).prerelease? - end - - warning_messages << "prerelease dependency on #{dep} is not recommended" if - prerelease_dep && !version.prerelease? - - overly_strict = dep.requirement.requirements.length == 1 && - dep.requirement.requirements.any? do |op, version| - op == '~>' and - not version.prerelease? and - version.segments.length > 2 and - version.segments.first != 0 - end - - if overly_strict then - _, dep_version = dep.requirement.requirements.first - - base = dep_version.segments.first 2 - - warning_messages << <<-WARNING -pessimistic dependency on #{dep} may be overly strict - if #{dep.name} is semantically versioned, use: - add_#{dep.type}_dependency '#{dep.name}', '~> #{base.join '.'}', '>= #{dep_version}' - WARNING - end - - open_ended = dep.requirement.requirements.all? do |op, version| - not version.prerelease? and (op == '>' or op == '>=') - end - - if open_ended then - op, dep_version = dep.requirement.requirements.first - - base = dep_version.segments.first 2 - - bugfix = if op == '>' then - ", '> #{dep_version}'" - elsif op == '>=' and base != dep_version.segments then - ", '>= #{dep_version}'" - end - - warning_messages << <<-WARNING -open-ended dependency on #{dep} is not recommended - if #{dep.name} is semantically versioned, use: - add_#{dep.type}_dependency '#{dep.name}', '~> #{base.join '.'}'#{bugfix} - WARNING - end - end - if error_messages.any? - raise Gem::InvalidSpecificationException, error_messages.join - end - if warning_messages.any? - warning_messages.each { |warning_message| warning warning_message } - end + def validate_dependencies + Gem::SpecificationPolicy.new(self).validate_dependencies end ## # Checks to see if the files to be packaged are world-readable. - def validate_permissions - return if Gem.win_platform? - - files.each do |file| - next unless File.file?(file) - next if File.stat(file).mode & 0444 == 0444 - warning "#{file} is not world-readable" - end - - executables.each do |name| - exec = File.join @bindir, name - next unless File.file?(exec) - next if File.stat(exec).executable? - warning "#{exec} is not executable" - end + Gem::SpecificationPolicy.new(self).validate_permissions end ## @@ -3024,7 +2693,11 @@ open-ended dependency on #{dep} is not recommended def version= version @version = Gem::Version.create(version) - self.required_rubygems_version = '> 1.3.1' if @version.prerelease? + # skip to set required_ruby_version when pre-released rubygems. + # It caused to raise CircularDependencyError + if @version.prerelease? && @name.strip != "rubygems" + self.required_rubygems_version = '> 1.3.1' + end invalidate_memoized_attributes return @version diff --git a/lib/rubygems/specification_policy.rb b/lib/rubygems/specification_policy.rb new file mode 100644 index 0000000000..a05edcd5c9 --- /dev/null +++ b/lib/rubygems/specification_policy.rb @@ -0,0 +1,410 @@ +require 'delegate' +require 'uri' + +class Gem::SpecificationPolicy < SimpleDelegator + VALID_NAME_PATTERN = /\A[a-zA-Z0-9\.\-\_]+\z/ # :nodoc: + + VALID_URI_PATTERN = %r{\Ahttps?:\/\/([^\s:@]+:[^\s:@]*@)?[A-Za-z\d\-]+(\.[A-Za-z\d\-]+)+\.?(:\d{1,5})?([\/?]\S*)?\z} # :nodoc: + + METADATA_LINK_KEYS = %w[ + bug_tracker_uri + changelog_uri + documentation_uri + homepage_uri + mailing_list_uri + source_code_uri + wiki_uri + ] # :nodoc: + + ## + # If set to true, run packaging-specific checks, as well. + + attr_accessor :packaging + + ## + # Checks that the specification contains all required fields, and does a + # very basic sanity check. + # + # Raises InvalidSpecificationException if the spec does not pass the + # checks. + + def validate + validate_nil_attributes + + validate_rubygems_version + + validate_required_attributes + + validate_name + + validate_require_paths + + keep_only_files_and_directories + + validate_non_files + + validate_self_inclusion_in_files_list + + validate_specification_version + + validate_platform + + validate_array_attributes + + validate_authors_field + + validate_metadata + + validate_licenses + + validate_permissions + + validate_lazy_metadata + + validate_values + + validate_dependencies + true + end + + ## + # Implementation for Specification#validate_metadata + + def validate_metadata + unless Hash === metadata then + raise Gem::InvalidSpecificationException, + 'metadata must be a hash' + end + + metadata.each do |key, value| + if !key.kind_of?(String) then + raise Gem::InvalidSpecificationException, + "metadata keys must be a String" + end + + if key.size > 128 then + raise Gem::InvalidSpecificationException, + "metadata key too large (#{key.size} > 128)" + end + + if !value.kind_of?(String) then + raise Gem::InvalidSpecificationException, + "metadata values must be a String" + end + + if value.size > 1024 then + raise Gem::InvalidSpecificationException, + "metadata value too large (#{value.size} > 1024)" + end + + if METADATA_LINK_KEYS.include? key then + if value !~ VALID_URI_PATTERN then + raise Gem::InvalidSpecificationException, + "metadata['#{key}'] has invalid link: #{value.inspect}" + end + end + end + end + + ## + # Implementation for Specification#validate_dependencies + + def validate_dependencies # :nodoc: + # NOTE: see REFACTOR note in Gem::Dependency about types - this might be brittle + seen = Gem::Dependency::TYPES.inject({}) { |types, type| types.merge({ type => {}}) } + + error_messages = [] + warning_messages = [] + dependencies.each do |dep| + if prev = seen[dep.type][dep.name] then + error_messages << <<-MESSAGE +duplicate dependency on #{dep}, (#{prev.requirement}) use: + add_#{dep.type}_dependency '#{dep.name}', '#{dep.requirement}', '#{prev.requirement}' + MESSAGE + end + + seen[dep.type][dep.name] = dep + + prerelease_dep = dep.requirements_list.any? do |req| + Gem::Requirement.new(req).prerelease? + end + + warning_messages << "prerelease dependency on #{dep} is not recommended" if + prerelease_dep && !version.prerelease? + + overly_strict = dep.requirement.requirements.length == 1 && + dep.requirement.requirements.any? do |op, version| + op == '~>' and + not version.prerelease? and + version.segments.length > 2 and + version.segments.first != 0 + end + + if overly_strict then + _, dep_version = dep.requirement.requirements.first + + base = dep_version.segments.first 2 + upper_bound = dep_version.segments.first(dep_version.segments.length - 1) + upper_bound[-1] += 1 + + warning_messages << <<-WARNING +pessimistic dependency on #{dep} may be overly strict + if #{dep.name} is semantically versioned, use: + add_#{dep.type}_dependency '#{dep.name}', '~> #{base.join '.'}', '>= #{dep_version}' + if #{dep.name} is not semantically versioned, you can bypass this warning with: + add_#{dep.type}_dependency '#{dep.name}', '>= #{dep_version}', '< #{upper_bound.join '.'}.a' + WARNING + end + + open_ended = dep.requirement.requirements.all? do |op, version| + not version.prerelease? and (op == '>' or op == '>=') + end + + if open_ended then + op, dep_version = dep.requirement.requirements.first + + base = dep_version.segments.first 2 + + bugfix = if op == '>' then + ", '> #{dep_version}'" + elsif op == '>=' and base != dep_version.segments then + ", '>= #{dep_version}'" + end + + warning_messages << <<-WARNING +open-ended dependency on #{dep} is not recommended + if #{dep.name} is semantically versioned, use: + add_#{dep.type}_dependency '#{dep.name}', '~> #{base.join '.'}'#{bugfix} + WARNING + end + end + if error_messages.any? then + raise Gem::InvalidSpecificationException, error_messages.join + end + if warning_messages.any? then + warning_messages.each { |warning_message| warning warning_message } + end + end + + ## + # Issues a warning for each file to be packaged which is world-readable. + # + # Implementation for Specification#validate_permissions + + def validate_permissions + return if Gem.win_platform? + + files.each do |file| + next unless File.file?(file) + next if File.stat(file).mode & 0444 == 0444 + warning "#{file} is not world-readable" + end + + executables.each do |name| + exec = File.join bindir, name + next unless File.file?(exec) + next if File.stat(exec).executable? + warning "#{exec} is not executable" + end + end + + private + + def validate_nil_attributes + nil_attributes = Gem::Specification.non_nil_attributes.select do |attrname| + __getobj__.instance_variable_get("@#{attrname}").nil? + end + return if nil_attributes.empty? + raise Gem::InvalidSpecificationException, + "#{nil_attributes.join ', '} must not be nil" + end + + def validate_rubygems_version + return unless packaging + return if rubygems_version == Gem::VERSION + + raise Gem::InvalidSpecificationException, + "expected RubyGems version #{Gem::VERSION}, was #{rubygems_version}" + end + + def validate_required_attributes + Gem::Specification.required_attributes.each do |symbol| + unless send symbol then + raise Gem::InvalidSpecificationException, + "missing value for attribute #{symbol}" + end + end + end + + def validate_name + if !name.is_a?(String) then + raise Gem::InvalidSpecificationException, + "invalid value for attribute name: \"#{name.inspect}\" must be a string" + elsif name !~ /[a-zA-Z]/ then + raise Gem::InvalidSpecificationException, + "invalid value for attribute name: #{name.dump} must include at least one letter" + elsif name !~ VALID_NAME_PATTERN then + raise Gem::InvalidSpecificationException, + "invalid value for attribute name: #{name.dump} can only include letters, numbers, dashes, and underscores" + end + end + + def validate_require_paths + return unless raw_require_paths.empty? + + raise Gem::InvalidSpecificationException, + 'specification must have at least one require_path' + end + + def validate_non_files + return unless packaging + non_files = files.reject {|x| File.file?(x) || File.symlink?(x)} + + unless non_files.empty? then + raise Gem::InvalidSpecificationException, + "[\"#{non_files.join "\", \""}\"] are not files" + end + end + + def validate_self_inclusion_in_files_list + return unless files.include?(file_name) + + raise Gem::InvalidSpecificationException, + "#{full_name} contains itself (#{file_name}), check your files list" + end + + def validate_specification_version + return if specification_version.is_a?(Integer) + + raise Gem::InvalidSpecificationException, + 'specification_version must be an Integer (did you mean version?)' + end + + def validate_platform + case platform + when Gem::Platform, Gem::Platform::RUBY then # ok + else + raise Gem::InvalidSpecificationException, + "invalid platform #{platform.inspect}, see Gem::Platform" + end + end + + def validate_array_attributes + Gem::Specification.array_attributes.each do |field| + validate_array_attribute(field) + end + end + + def validate_array_attribute(field) + val = self.send(field) + klass = case field + when :dependencies then + Gem::Dependency + else + String + end + + unless Array === val and val.all? {|x| x.kind_of?(klass)} then + raise(Gem::InvalidSpecificationException, + "#{field} must be an Array of #{klass}") + end + end + + def validate_authors_field + return unless authors.empty? + + raise Gem::InvalidSpecificationException, + "authors may not be empty" + end + + def validate_licenses + licenses.each { |license| + if license.length > 64 then + raise Gem::InvalidSpecificationException, + "each license must be 64 characters or less" + end + + if !Gem::Licenses.match?(license) then + suggestions = Gem::Licenses.suggestions(license) + message = <<-warning +license value '#{license}' is invalid. Use a license identifier from +http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard license. + warning + message += "Did you mean #{suggestions.map { |s| "'#{s}'"}.join(', ')}?\n" unless suggestions.nil? + warning(message) + end + } + + warning <<-warning if licenses.empty? +licenses is empty, but is recommended. Use a license identifier from +http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard license. + warning + end + + LAZY = '"FIxxxXME" or "TOxxxDO"'.gsub(/xxx/, '') + LAZY_PATTERN = /FI XME|TO DO/x + HOMEPAGE_URI_PATTERN = /\A[a-z][a-z\d+.-]*:/i + + def validate_lazy_metadata + unless authors.grep(LAZY_PATTERN).empty? then + raise Gem::InvalidSpecificationException, "#{LAZY} is not an author" + end + + unless Array(email).grep(LAZY_PATTERN).empty? then + raise Gem::InvalidSpecificationException, "#{LAZY} is not an email" + end + + if description =~ LAZY_PATTERN then + raise Gem::InvalidSpecificationException, "#{LAZY} is not a description" + end + + if summary =~ LAZY_PATTERN then + raise Gem::InvalidSpecificationException, "#{LAZY} is not a summary" + end + + # Make sure a homepage is valid HTTP/HTTPS URI + if homepage and not homepage.empty? + begin + homepage_uri = URI.parse(homepage) + unless [URI::HTTP, URI::HTTPS].member? homepage_uri.class + raise Gem::InvalidSpecificationException, "\"#{homepage}\" is not a valid HTTP URI" + end + rescue URI::InvalidURIError + raise Gem::InvalidSpecificationException, "\"#{homepage}\" is not a valid HTTP URI" + end + end + end + + def validate_values + %w[author homepage summary files].each do |attribute| + validate_attribute_present(attribute) + end + + if description == summary then + warning "description and summary are identical" + end + + # TODO: raise at some given date + warning "deprecated autorequire specified" if autorequire + + executables.each do |executable| + validate_shebang_line_in(executable) + end + + files.select { |f| File.symlink?(f) }.each do |file| + warning "#{file} is a symlink, which is not supported on all platforms" + end + end + + def validate_attribute_present(attribute) + value = self.send attribute + warning("no #{attribute} specified") if value.nil? || value.empty? + end + + def validate_shebang_line_in(executable) + executable_path = File.join(bindir, executable) + return if File.read(executable_path, 2) == '#!' + + warning "#{executable_path} is missing #! line" + end +end diff --git a/lib/rubygems/stub_specification.rb b/lib/rubygems/stub_specification.rb index ae2effbc84..62689c21f9 100644 --- a/lib/rubygems/stub_specification.rb +++ b/lib/rubygems/stub_specification.rb @@ -8,12 +8,8 @@ class Gem::StubSpecification < Gem::BasicSpecification # :nodoc: PREFIX = "# stub: " - OPEN_MODE = # :nodoc: - if Object.const_defined? :Encoding then - 'r:UTF-8:-' - else - 'r' - end + # :nodoc: + OPEN_MODE = 'r:UTF-8:-' class StubLine # :nodoc: all attr_reader :name, :version, :platform, :require_paths, :extensions, diff --git a/lib/rubygems/test_case.rb b/lib/rubygems/test_case.rb index f03515cc8f..f1cd3d274c 100644 --- a/lib/rubygems/test_case.rb +++ b/lib/rubygems/test_case.rb @@ -2,7 +2,7 @@ # TODO: $SAFE = 1 begin - gem 'minitest', '~> 4.0' + gem 'minitest', '~> 5.0' rescue NoMethodError, Gem::LoadError # for ruby tests end @@ -18,6 +18,16 @@ begin rescue Gem::LoadError end +begin + require 'simplecov' + SimpleCov.start do + add_filter "/test/" + add_filter "/bundler/" + add_filter "/lib/rubygems/resolver/molinillo" + end +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? @@ -86,7 +96,7 @@ end # # Tests are always run at a safe level of 1. -class Gem::TestCase < MiniTest::Unit::TestCase +class Gem::TestCase < (defined?(Minitest::Test) ? Minitest::Test : MiniTest::Unit::TestCase) extend Gem::Deprecate @@ -595,7 +605,7 @@ class Gem::TestCase < MiniTest::Unit::TestCase def mu_pp(obj) s = String.new s = PP.pp obj, s - s = s.force_encoding(Encoding.default_external) if defined? Encoding + s = s.force_encoding(Encoding.default_external) s.chomp end @@ -819,8 +829,7 @@ class Gem::TestCase < MiniTest::Unit::TestCase spec end - # TODO: mark deprecate after replacing util_spec from new_spec - # deprecate :new_spec, :none, 2018, 12 + deprecate :new_spec, :none, 2018, 12 def new_default_spec(name, version, deps = nil, *files) spec = util_spec name, version, deps @@ -845,7 +854,7 @@ class Gem::TestCase < MiniTest::Unit::TestCase # Creates a spec with +name+, +version+. +deps+ can specify the dependency # or a +block+ can be given for full customization of the specification. - def util_spec name, version = 2, deps = nil # :yields: specification + def util_spec name, version = 2, deps = nil, *files # :yields: specification raise "deps or block, not both" if deps and block_given? spec = Gem::Specification.new do |s| @@ -858,6 +867,8 @@ class Gem::TestCase < MiniTest::Unit::TestCase s.summary = "this is a summary" s.description = "This is a test description" + s.files.push(*files) unless files.empty? + yield s if block_given? end @@ -869,6 +880,19 @@ class Gem::TestCase < MiniTest::Unit::TestCase end end + unless files.empty? then + 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 + Gem::Specification.reset return spec diff --git a/lib/rubygems/uninstaller.rb b/lib/rubygems/uninstaller.rb index 89f47a45fe..3059099373 100644 --- a/lib/rubygems/uninstaller.rb +++ b/lib/rubygems/uninstaller.rb @@ -213,8 +213,8 @@ class Gem::Uninstaller exe_file = File.join bin_dir, exe_name - FileUtils.rm_f exe_file - FileUtils.rm_f "#{exe_file}.bat" + safe_delete { FileUtils.rm exe_file } + safe_delete { FileUtils.rm "#{exe_file}.bat" } end else say "Executables and scripts will remain installed." @@ -250,26 +250,26 @@ class Gem::Uninstaller raise Gem::FilePermissionError, spec.base_dir unless File.writable?(spec.base_dir) - FileUtils.rm_rf spec.full_gem_path - FileUtils.rm_rf spec.extension_dir + safe_delete { FileUtils.rm_r spec.full_gem_path } + safe_delete { FileUtils.rm_r spec.extension_dir } old_platform_name = spec.original_name - gemspec = spec.spec_file - - unless File.exist? gemspec then - gemspec = File.join(File.dirname(gemspec), "#{old_platform_name}.gemspec") - end - - FileUtils.rm_rf gemspec gem = spec.cache_file gem = File.join(spec.cache_dir, "#{old_platform_name}.gem") unless File.exist? gem - FileUtils.rm_rf gem + safe_delete { FileUtils.rm_r gem } Gem::RDoc.new(spec).remove + gemspec = spec.spec_file + + unless File.exist? gemspec then + gemspec = File.join(File.dirname(gemspec), "#{old_platform_name}.gemspec") + end + + safe_delete { FileUtils.rm_r gemspec } say "Successfully uninstalled #{spec.full_name}" Gem::Specification.reset @@ -343,4 +343,15 @@ class Gem::Uninstaller filename end end + + def safe_delete(&block) + block.call + rescue Errno::ENOENT + nil + rescue Errno::EPERM + e = Gem::UninstallError.new + e.spec = @spec + + raise e + end end diff --git a/lib/rubygems/user_interaction.rb b/lib/rubygems/user_interaction.rb index 91236eec15..6a5aecf1b7 100644 --- a/lib/rubygems/user_interaction.rb +++ b/lib/rubygems/user_interaction.rb @@ -205,11 +205,7 @@ class Gem::StreamUI # Returns true if TTY methods should be used on this StreamUI. def tty? - if RUBY_VERSION < '1.9.3' and RUBY_PLATFORM =~ /mingw|mswin/ then - @usetty - else - @usetty && @ins.tty? - end + @usetty && @ins.tty? end ## @@ -324,29 +320,7 @@ class Gem::StreamUI def _gets_noecho require_io_console - if IO.method_defined?(:noecho) then - @ins.noecho {@ins.gets} - elsif Gem.win_platform? - require "Win32API" - password = '' - - while char = Win32API.new("crtdll", "_getch", [ ], "L").Call do - break if char == 10 || char == 13 # received carriage return or newline - if char == 127 || char == 8 # backspace and delete - password.slice!(-1, 1) - else - password << char.chr - end - end - password - else - system "stty -echo" - begin - @ins.gets - ensure - system "stty echo" - end - end + @ins.noecho {@ins.gets} end ## @@ -684,8 +658,8 @@ class Gem::SilentUI < Gem::StreamUI def initialize reader, writer = nil, nil - reader = File.open(Gem::Util::NULL_DEVICE, 'r') - writer = File.open(Gem::Util::NULL_DEVICE, 'w') + reader = File.open(IO::NULL, 'r') + writer = File.open(IO::NULL, 'w') super reader, writer, writer, false end diff --git a/lib/rubygems/util.rb b/lib/rubygems/util.rb index 6c75910004..9f5b9a2239 100644 --- a/lib/rubygems/util.rb +++ b/lib/rubygems/util.rb @@ -15,7 +15,7 @@ module Gem::Util data = StringIO.new(data, 'r') unzipped = Zlib::GzipReader.new(data).read - unzipped.force_encoding Encoding::BINARY if Object.const_defined? :Encoding + unzipped.force_encoding Encoding::BINARY unzipped end @@ -26,7 +26,7 @@ module Gem::Util require 'zlib' require 'stringio' zipped = StringIO.new(String.new, 'w') - zipped.set_encoding Encoding::BINARY if Object.const_defined? :Encoding + zipped.set_encoding Encoding::BINARY Zlib::GzipWriter.wrap zipped do |io| io.write data end @@ -67,13 +67,11 @@ module Gem::Util end end - NULL_DEVICE = defined?(IO::NULL) ? IO::NULL : Gem.win_platform? ? 'NUL' : '/dev/null' - ## # Invokes system, but silences all output. def self.silent_system *command - opt = {:out => NULL_DEVICE, :err => [:child, :out]} + opt = {:out => IO::NULL, :err => [:child, :out]} if Hash === command.last opt.update(command.last) cmds = command[0...-1] @@ -86,15 +84,13 @@ module Gem::Util @silent_mutex ||= Mutex.new - null_device = NULL_DEVICE - @silent_mutex.synchronize do begin stdout = STDOUT.dup stderr = STDERR.dup - STDOUT.reopen null_device, 'w' - STDERR.reopen null_device, 'w' + STDOUT.reopen IO::NULL, 'w' + STDERR.reopen IO::NULL, 'w' return system(*command) ensure diff --git a/lib/rubygems/util/licenses.rb b/lib/rubygems/util/licenses.rb index 96fed282f1..2a536575c0 100644 --- a/lib/rubygems/util/licenses.rb +++ b/lib/rubygems/util/licenses.rb @@ -8,7 +8,7 @@ class Gem::Licenses # Software Package Data Exchange (SPDX) standard open-source software # license identifiers - IDENTIFIERS = %w( + LICENSE_IDENTIFIERS = %w( 0BSD AAL ADSL @@ -19,6 +19,8 @@ class Gem::Licenses AFL-3.0 AGPL-1.0 AGPL-3.0 + AGPL-3.0-only + AGPL-3.0-or-later AMDPLPA AML AMPAS @@ -41,9 +43,11 @@ class Gem::Licenses Artistic-1.0-Perl Artistic-1.0-cl8 Artistic-2.0 + BSD-1-Clause BSD-2-Clause BSD-2-Clause-FreeBSD BSD-2-Clause-NetBSD + BSD-2-Clause-Patent BSD-3-Clause BSD-3-Clause-Attribution BSD-3-Clause-Clear @@ -96,6 +100,8 @@ class Gem::Licenses CC0-1.0 CDDL-1.0 CDDL-1.1 + CDLA-Permissive-1.0 + CDLA-Sharing-1.0 CECILL-1.0 CECILL-1.1 CECILL-2.0 @@ -124,9 +130,11 @@ class Gem::Licenses EFL-1.0 EFL-2.0 EPL-1.0 + EPL-2.0 EUDatagrid EUPL-1.0 EUPL-1.1 + EUPL-1.2 Entessa ErlPL-1.1 Eurosym @@ -138,13 +146,23 @@ class Gem::Licenses Frameworx-1.0 FreeImage GFDL-1.1 + GFDL-1.1-only + GFDL-1.1-or-later GFDL-1.2 + GFDL-1.2-only + GFDL-1.2-or-later GFDL-1.3 + GFDL-1.3-only + GFDL-1.3-or-later GL2PS GPL-1.0 GPL-1.0+ + GPL-1.0-only + GPL-1.0-or-later GPL-2.0 GPL-2.0+ + GPL-2.0-only + GPL-2.0-or-later GPL-2.0-with-GCC-exception GPL-2.0-with-autoconf-exception GPL-2.0-with-bison-exception @@ -152,6 +170,8 @@ class Gem::Licenses GPL-2.0-with-font-exception GPL-3.0 GPL-3.0+ + GPL-3.0-only + GPL-3.0-or-later GPL-3.0-with-GCC-exception GPL-3.0-with-autoconf-exception Giftware @@ -177,10 +197,16 @@ class Gem::Licenses LAL-1.3 LGPL-2.0 LGPL-2.0+ + LGPL-2.0-only + LGPL-2.0-or-later LGPL-2.1 LGPL-2.1+ + LGPL-2.1-only + LGPL-2.1-or-later LGPL-3.0 LGPL-3.0+ + LGPL-3.0-only + LGPL-3.0-or-later LGPLLR LPL-1.0 LPL-1.02 @@ -317,7 +343,6 @@ class Gem::Licenses W3C-19980720 W3C-20150513 WTFPL - WXwindows Watcom-1.0 Wsuipa X11 @@ -349,17 +374,49 @@ class Gem::Licenses mpich2 psfrag psutils + wxWindows xinetd xpp zlib-acknowledgement ).freeze + # exception identifiers + EXCEPTION_IDENTIFIERS = %w( + 389-exception + Autoconf-exception-2.0 + Autoconf-exception-3.0 + Bison-exception-2.2 + Bootloader-exception + CLISP-exception-2.0 + Classpath-exception-2.0 + DigiRule-FOSS-exception + FLTK-exception + Fawkes-Runtime-exception + Font-exception-2.0 + GCC-exception-2.0 + GCC-exception-3.1 + LZMA-exception + Libtool-exception + Linux-syscall-note + Nokia-Qt-exception-1.1 + OCCT-exception-1.0 + Qwt-exception-1.0 + WxWindows-exception-3.1 + eCos-exception-2.0 + freertos-exception-2.0 + gnu-javamail-exception + i2p-gpl-java-exception + mif-exception + openvpn-openssl-exception + u-boot-exception-2.0 + ).freeze + REGEXP = %r{ \A ( - #{Regexp.union(IDENTIFIERS)} + #{Regexp.union(LICENSE_IDENTIFIERS)} \+? - (\s WITH \s .+)? + (\s WITH \s #{Regexp.union(EXCEPTION_IDENTIFIERS)})? | #{NONSTANDARD} ) \Z @@ -370,7 +427,7 @@ class Gem::Licenses end def self.suggestions(license) - by_distance = IDENTIFIERS.group_by do |identifier| + by_distance = LICENSE_IDENTIFIERS.group_by do |identifier| levenshtein_distance(identifier, license) end lowest = by_distance.keys.min diff --git a/test/rubygems/fix_openssl_warnings.rb b/test/rubygems/fix_openssl_warnings.rb deleted file mode 100644 index 1f5b8b5e0a..0000000000 --- a/test/rubygems/fix_openssl_warnings.rb +++ /dev/null @@ -1,13 +0,0 @@ -# frozen_string_literal: true -## -# HACK: this drives me BONKERS - -if defined? OpenSSL then - class OpenSSL::X509::ExtensionFactory - alias :old_create_ext :create_ext - def create_ext(*args) - @config ||= nil - old_create_ext(*args) - end - end -end if RUBY_VERSION < "1.9" diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index a6741e02c0..f383d5af58 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -31,11 +31,11 @@ class TestGem < Gem::TestCase def test_self_finish_resolve save_loaded_features do - a1 = new_spec "a", "1", "b" => "> 0" - b1 = new_spec "b", "1", "c" => ">= 1" - b2 = new_spec "b", "2", "c" => ">= 2" - c1 = new_spec "c", "1" - c2 = new_spec "c", "2" + a1 = util_spec "a", "1", "b" => "> 0" + b1 = util_spec "b", "1", "c" => ">= 1" + b2 = util_spec "b", "2", "c" => ">= 2" + c1 = util_spec "c", "1" + c2 = util_spec "c", "2" install_specs c1, c2, b1, b2, a1 @@ -53,13 +53,13 @@ class TestGem < Gem::TestCase def test_self_finish_resolve_wtf save_loaded_features do - a1 = new_spec "a", "1", "b" => "> 0", "d" => "> 0" # this - b1 = new_spec "b", "1", { "c" => ">= 1" }, "lib/b.rb" # this - b2 = new_spec "b", "2", { "c" => ">= 2" }, "lib/b.rb" - c1 = new_spec "c", "1" # this - c2 = new_spec "c", "2" - d1 = new_spec "d", "1", { "c" => "< 2" }, "lib/d.rb" - d2 = new_spec "d", "2", { "c" => "< 2" }, "lib/d.rb" # this + a1 = util_spec "a", "1", "b" => "> 0", "d" => "> 0" # this + b1 = util_spec "b", "1", { "c" => ">= 1" }, "lib/b.rb" # this + b2 = util_spec "b", "2", { "c" => ">= 2" }, "lib/b.rb" + c1 = util_spec "c", "1" # this + c2 = util_spec "c", "2" + d1 = util_spec "d", "1", { "c" => "< 2" }, "lib/d.rb" + d2 = util_spec "d", "2", { "c" => "< 2" }, "lib/d.rb" # this install_specs c1, c2, b1, b2, d1, d2, a1 @@ -77,11 +77,11 @@ class TestGem < Gem::TestCase def test_self_finish_resolve_respects_loaded_specs save_loaded_features do - a1 = new_spec "a", "1", "b" => "> 0" - b1 = new_spec "b", "1", "c" => ">= 1" - b2 = new_spec "b", "2", "c" => ">= 2" - c1 = new_spec "c", "1" - c2 = new_spec "c", "2" + a1 = util_spec "a", "1", "b" => "> 0" + b1 = util_spec "b", "1", "c" => ">= 1" + b2 = util_spec "b", "2", "c" => ">= 2" + c1 = util_spec "c", "1" + c2 = util_spec "c", "2" install_specs c1, c2, b1, b2, a1 @@ -130,6 +130,75 @@ class TestGem < Gem::TestCase assert_equal %w[a-1], installed.map { |spec| spec.full_name } end + def test_self_install_permissions + assert_self_install_permissions + end + + def test_self_install_permissions_umask_0 + umask = File.umask(0) + assert_self_install_permissions + ensure + File.umask(umask) + end + + def test_self_install_permissions_umask_077 + umask = File.umask(077) + assert_self_install_permissions + ensure + File.umask(umask) + end + + def assert_self_install_permissions + mask = /mingw|mswin/ =~ RUBY_PLATFORM ? 0700 : 0777 + options = { + :dir_mode => 0500, + :prog_mode => 0510, + :data_mode => 0640, + :wrappers => true, + } + Dir.chdir @tempdir do + Dir.mkdir 'bin' + File.open 'bin/foo.cmd', 'w' do |fp| + fp.chmod(0755) + fp.puts 'p' + end + + Dir.mkdir 'data' + File.open 'data/foo.txt', 'w' do |fp| + fp.puts 'blah' + end + + spec_fetcher do |f| + f.gem 'foo', 1 do |s| + s.executables = ['foo.cmd'] + s.files = %w[bin/foo.cmd data/foo.txt] + end + end + Gem.install 'foo', Gem::Requirement.default, options + end + + prog_mode = (options[:prog_mode] & mask).to_s(8) + dir_mode = (options[:dir_mode] & mask).to_s(8) + data_mode = (options[:data_mode] & mask).to_s(8) + expected = { + 'bin/foo.cmd' => prog_mode, + 'gems/foo-1' => dir_mode, + 'gems/foo-1/bin' => dir_mode, + 'gems/foo-1/data' => dir_mode, + 'gems/foo-1/bin/foo.cmd' => prog_mode, + 'gems/foo-1/data/foo.txt' => data_mode, + } + result = {} + Dir.chdir @gemhome do + expected.each_key do |n| + result[n] = (File.stat(n).mode & mask).to_s(8) + end + end + assert_equal(expected, result) + ensure + File.chmod(0700, *Dir.glob(@gemhome+'/gems/**/').map {|path| path.untaint}) + end + def test_require_missing save_loaded_features do assert_raises ::LoadError do @@ -140,7 +209,7 @@ class TestGem < Gem::TestCase def test_require_does_not_glob save_loaded_features do - a1 = new_spec "a", "1", nil, "lib/a1.rb" + a1 = util_spec "a", "1", nil, "lib/a1.rb" install_specs a1 @@ -388,7 +457,6 @@ class TestGem < Gem::TestCase end def test_self_use_gemdeps - skip 'Insecure operation - chdir' if RUBY_VERSION <= "1.8.7" rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-' FileUtils.mkdir_p 'detect/a/b' @@ -542,9 +610,6 @@ class TestGem < Gem::TestCase end def test_self_find_files_with_gemfile - # write_file(File.join Dir.pwd, 'Gemfile') fails on travis 1.8.7 with $SAFE=1 - skip if RUBY_VERSION <= "1.8.7" - cwd = File.expand_path("test/rubygems", @@project_dir) actual_load_path = $LOAD_PATH.unshift(cwd).dup @@ -577,7 +642,7 @@ class TestGem < Gem::TestCase assert_equal expected, Gem.find_files('sff/discover').sort assert_equal expected, Gem.find_files('sff/**.rb').sort, '[ruby-core:31730]' ensure - assert_equal cwd, actual_load_path.shift unless RUBY_VERSION <= "1.8.7" + assert_equal cwd, actual_load_path.shift end def test_self_find_latest_files @@ -793,7 +858,6 @@ class TestGem < Gem::TestCase end def test_self_refresh - skip 'Insecure operation - mkdir' if RUBY_VERSION <= "1.8.7" util_make_gems a1_spec = @a1.spec_file @@ -813,7 +877,6 @@ class TestGem < Gem::TestCase end def test_self_refresh_keeps_loaded_specs_activated - skip 'Insecure operation - mkdir' if RUBY_VERSION <= "1.8.7" util_make_gems a1_spec = @a1.spec_file @@ -1188,13 +1251,12 @@ class TestGem < Gem::TestCase end def test_self_needs_picks_up_unresolved_deps - skip 'loading from unsafe file' if RUBY_VERSION <= "1.8.7" save_loaded_features do util_clear_gems a = util_spec "a", "1" b = util_spec "b", "1", "c" => nil c = util_spec "c", "2" - d = new_spec "d", "1", {'e' => '= 1'}, "lib/d.rb" + d = util_spec "d", "1", {'e' => '= 1'}, "lib/d.rb" e = util_spec "e", "1" install_specs a, c, b, e, d @@ -1217,9 +1279,6 @@ class TestGem < Gem::TestCase output = Gem::Util.gunzip input assert_equal 'hello', output - - return unless Object.const_defined? :Encoding - assert_equal Encoding::BINARY, output.encoding end @@ -1231,55 +1290,9 @@ class TestGem < Gem::TestCase zipped = StringIO.new output assert_equal 'hello', Zlib::GzipReader.new(zipped).read - - return unless Object.const_defined? :Encoding - assert_equal Encoding::BINARY, output.encoding end - if Gem.win_platform? && '1.9' > RUBY_VERSION - # Ruby 1.9 properly handles ~ path expansion, so no need to run such tests. - def test_self_user_home_userprofile - - Gem.clear_paths - - # safe-keep env variables - orig_home, orig_user_profile = ENV['HOME'], ENV['USERPROFILE'] - - # prepare for the test - ENV.delete('HOME') - ENV['USERPROFILE'] = "W:\\Users\\RubyUser" - - assert_equal 'W:/Users/RubyUser', Gem.user_home - - ensure - ENV['HOME'] = orig_home - ENV['USERPROFILE'] = orig_user_profile - end - - def test_self_user_home_user_drive_and_path - Gem.clear_paths - - # safe-keep env variables - orig_home, orig_user_profile = ENV['HOME'], ENV['USERPROFILE'] - orig_home_drive, orig_home_path = ENV['HOMEDRIVE'], ENV['HOMEPATH'] - - # prepare the environment - ENV.delete('HOME') - ENV.delete('USERPROFILE') - ENV['HOMEDRIVE'] = 'Z:' - ENV['HOMEPATH'] = "\\Users\\RubyUser" - - assert_equal 'Z:/Users/RubyUser', Gem.user_home - - ensure - ENV['HOME'] = orig_home - ENV['USERPROFILE'] = orig_user_profile - ENV['HOMEDRIVE'] = orig_home_drive - ENV['HOMEPATH'] = orig_home_path - end - end - def test_self_vendor_dir expected = File.join RbConfig::CONFIG['vendordir'], 'gems', @@ -1305,7 +1318,6 @@ class TestGem < Gem::TestCase end def test_load_plugins - skip 'Insecure operation - chdir' if RUBY_VERSION <= "1.8.7" plugin_path = File.join "lib", "rubygems_plugin.rb" Dir.chdir @tempdir do @@ -1360,8 +1372,8 @@ class TestGem < Gem::TestCase write_file File.join(@tempdir, 'lib', "g.rb") { |fp| fp.puts "" } write_file File.join(@tempdir, 'lib', 'm.rb') { |fp| fp.puts "" } - g = new_spec 'g', '1', nil, "lib/g.rb" - m = new_spec 'm', '1', nil, "lib/m.rb" + g = util_spec 'g', '1', nil, "lib/g.rb" + m = util_spec 'm', '1', nil, "lib/m.rb" install_gem g, :install_dir => Gem.dir m0 = install_gem m, :install_dir => Gem.dir @@ -1416,8 +1428,8 @@ class TestGem < Gem::TestCase write_file File.join(@tempdir, 'lib', "g.rb") { |fp| fp.puts "" } write_file File.join(@tempdir, 'lib', 'm.rb') { |fp| fp.puts "" } - g = new_spec 'g', '1', nil, "lib/g.rb" - m = new_spec 'm', '1', nil, "lib/m.rb" + g = util_spec 'g', '1', nil, "lib/g.rb" + m = util_spec 'm', '1', nil, "lib/m.rb" install_gem g, :install_dir => Gem.dir install_gem m, :install_dir => Gem.dir @@ -1434,9 +1446,9 @@ class TestGem < Gem::TestCase def test_auto_activation_of_specific_gemdeps_file util_clear_gems - a = new_spec "a", "1", nil, "lib/a.rb" - b = new_spec "b", "1", nil, "lib/b.rb" - c = new_spec "c", "1", nil, "lib/c.rb" + a = util_spec "a", "1", nil, "lib/a.rb" + b = util_spec "b", "1", nil, "lib/b.rb" + c = util_spec "c", "1", nil, "lib/c.rb" install_specs a, b, c @@ -1456,12 +1468,11 @@ class TestGem < Gem::TestCase end def test_auto_activation_of_used_gemdeps_file - skip 'Insecure operation - chdir' if RUBY_VERSION <= "1.8.7" util_clear_gems - a = new_spec "a", "1", nil, "lib/a.rb" - b = new_spec "b", "1", nil, "lib/b.rb" - c = new_spec "c", "1", nil, "lib/c.rb" + a = util_spec "a", "1", nil, "lib/a.rb" + b = util_spec "b", "1", nil, "lib/b.rb" + c = util_spec "c", "1", nil, "lib/c.rb" install_specs a, b, c @@ -1496,9 +1507,9 @@ class TestGem < Gem::TestCase def test_looks_for_gemdeps_files_automatically_on_start util_clear_gems - a = new_spec "a", "1", nil, "lib/a.rb" - b = new_spec "b", "1", nil, "lib/b.rb" - c = new_spec "c", "1", nil, "lib/c.rb" + a = util_spec "a", "1", nil, "lib/a.rb" + b = util_spec "b", "1", nil, "lib/b.rb" + c = util_spec "c", "1", nil, "lib/c.rb" install_specs a, b, c @@ -1513,12 +1524,7 @@ class TestGem < Gem::TestCase path = File.join @tempdir, "gem.deps.rb" cmd = [Gem.ruby.dup.untaint, "-I#{LIB_PATH.untaint}", "-I#{BUNDLER_LIB_PATH.untaint}", "-rrubygems"] - if RUBY_VERSION < '1.9' - cmd << "-e 'puts Gem.loaded_specs.values.map(&:full_name).sort'" - cmd = cmd.join(' ') - else - cmd << "-eputs Gem.loaded_specs.values.map(&:full_name).sort" - end + cmd << "-eputs Gem.loaded_specs.values.map(&:full_name).sort" File.open path, "w" do |f| f.puts "gem 'a'" @@ -1537,9 +1543,9 @@ class TestGem < Gem::TestCase def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir util_clear_gems - a = new_spec "a", "1", nil, "lib/a.rb" - b = new_spec "b", "1", nil, "lib/b.rb" - c = new_spec "c", "1", nil, "lib/c.rb" + a = util_spec "a", "1", nil, "lib/a.rb" + b = util_spec "b", "1", nil, "lib/b.rb" + c = util_spec "c", "1", nil, "lib/c.rb" install_specs a, b, c @@ -1556,12 +1562,7 @@ class TestGem < Gem::TestCase path = File.join @tempdir, "gem.deps.rb" cmd = [Gem.ruby.dup.untaint, "-Csub1", "-I#{LIB_PATH.untaint}", "-I#{BUNDLER_LIB_PATH.untaint}", "-rrubygems"] - if RUBY_VERSION < '1.9' - cmd << "-e 'puts Gem.loaded_specs.values.map(&:full_name).sort'" - cmd = cmd.join(' ') - else - cmd << "-eputs Gem.loaded_specs.values.map(&:full_name).sort" - end + cmd << "-eputs Gem.loaded_specs.values.map(&:full_name).sort" File.open path, "w" do |f| f.puts "gem 'a'" @@ -1590,7 +1591,7 @@ class TestGem < Gem::TestCase assert_equal old_style, Gem.find_unresolved_default_spec("foo.rb") assert_equal old_style, Gem.find_unresolved_default_spec("bar.rb") - assert_equal nil, Gem.find_unresolved_default_spec("baz.rb") + assert_nil Gem.find_unresolved_default_spec("baz.rb") Gem.clear_default_specs @@ -1603,8 +1604,8 @@ class TestGem < Gem::TestCase assert_equal new_style, Gem.find_unresolved_default_spec("foo.rb") assert_equal new_style, Gem.find_unresolved_default_spec("bar.rb") - assert_equal nil, Gem.find_unresolved_default_spec("exec") - assert_equal nil, Gem.find_unresolved_default_spec("README") + assert_nil Gem.find_unresolved_default_spec("exec") + assert_nil Gem.find_unresolved_default_spec("README") end def test_default_gems_use_full_paths @@ -1696,7 +1697,6 @@ class TestGem < Gem::TestCase end def test_use_gemdeps_automatic - skip 'Insecure operation - chdir' if RUBY_VERSION <= "1.8.7" rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-' spec = util_spec 'a', 1 @@ -1717,7 +1717,6 @@ class TestGem < Gem::TestCase end def test_use_gemdeps_automatic_missing - skip 'Insecure operation - chdir' if RUBY_VERSION <= "1.8.7" rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-' Gem.use_gemdeps @@ -1746,7 +1745,6 @@ class TestGem < Gem::TestCase end def test_use_gemdeps_missing_gem - skip 'Insecure operation - read' if RUBY_VERSION <= "1.8.7" rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], 'x' File.open 'x', 'w' do |io| @@ -1781,7 +1779,6 @@ You may need to `gem install -g` to install missing gems end if Gem::USE_BUNDLER_FOR_GEMDEPS def test_use_gemdeps_specific - skip 'Insecure operation - read' if RUBY_VERSION <= "1.8.7" rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], 'x' spec = util_spec 'a', 1 @@ -1801,6 +1798,13 @@ You may need to `gem install -g` to install missing gems ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps end + def test_operating_system_defaults + operating_system_defaults = Gem.operating_system_defaults + + assert operating_system_defaults != nil + assert operating_system_defaults.is_a? Hash + end + def test_platform_defaults platform_defaults = Gem.platform_defaults diff --git a/test/rubygems/test_gem_command_manager.rb b/test/rubygems/test_gem_command_manager.rb index 2d2fc7d7a0..c3aa01503a 100644 --- a/test/rubygems/test_gem_command_manager.rb +++ b/test/rubygems/test_gem_command_manager.rb @@ -114,8 +114,8 @@ class TestGemCommandManager < Gem::TestCase assert_equal :both, check_options[:domain] assert_equal true, check_options[:wrappers] assert_equal Gem::Requirement.default, check_options[:version] - assert_equal nil, check_options[:install_dir] - assert_equal nil, check_options[:bin_dir] + assert_nil check_options[:install_dir] + assert_nil check_options[:bin_dir] #check settings check_options = nil diff --git a/test/rubygems/test_gem_commands_build_command.rb b/test/rubygems/test_gem_commands_build_command.rb index 08854f0bf1..6d31949187 100644 --- a/test/rubygems/test_gem_commands_build_command.rb +++ b/test/rubygems/test_gem_commands_build_command.rb @@ -64,6 +64,38 @@ class TestGemCommandsBuildCommand < Gem::TestCase assert_equal "ERROR: Gemspec file not found: some_gem\n", @ui.error end + def test_execute_outside_dir + gemspec_dir = File.join @tempdir, 'build_command_gem' + gemspec_file = File.join gemspec_dir, @gem.spec_name + + FileUtils.mkdir_p gemspec_dir + + File.open gemspec_file, 'w' do |gs| + gs.write @gem.to_ruby + end + + @cmd.options[:args] = [gemspec_file] + + use_ui @ui do + @cmd.execute + end + + output = @ui.output.split "\n" + assert_equal " Successfully built RubyGem", output.shift + assert_equal " Name: some_gem", output.shift + assert_equal " Version: 2", output.shift + assert_equal " File: some_gem-2.gem", output.shift + assert_equal [], output + + gem_file = File.join gemspec_dir, File.basename(@gem.cache_file) + assert File.exist?(gem_file) + + spec = Gem::Package.new(gem_file).spec + + assert_equal "some_gem", spec.name + assert_equal "this is a summary", spec.summary + end + def test_can_find_gemspecs_without_dot_gemspec gemspec_file = File.join(@tempdir, @gem.spec_name) diff --git a/test/rubygems/test_gem_commands_cert_command.rb b/test/rubygems/test_gem_commands_cert_command.rb index 2d38a57bc4..3f67513c3f 100644 --- a/test/rubygems/test_gem_commands_cert_command.rb +++ b/test/rubygems/test_gem_commands_cert_command.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'rubygems/test_case' require 'rubygems/commands/cert_command' -require 'rubygems/fix_openssl_warnings' if RUBY_VERSION < "1.9" unless defined?(OpenSSL::SSL) then warn 'Skipping `gem cert` tests. openssl not found.' diff --git a/test/rubygems/test_gem_commands_dependency_command.rb b/test/rubygems/test_gem_commands_dependency_command.rb index d0389ccf55..7433c33d63 100644 --- a/test/rubygems/test_gem_commands_dependency_command.rb +++ b/test/rubygems/test_gem_commands_dependency_command.rb @@ -6,7 +6,7 @@ class TestGemCommandsDependencyCommand < Gem::TestCase def setup super - + @stub_ui = Gem::MockGemUi.new @cmd = Gem::Commands::DependencyCommand.new @cmd.options[:domain] = :local end @@ -19,17 +19,17 @@ class TestGemCommandsDependencyCommand < Gem::TestCase @cmd.options[:args] = %w[foo] - use_ui @ui do + use_ui @stub_ui do @cmd.execute end assert_equal "Gem foo-2\n bar (> 1)\n baz (> 1)\n\n", - @ui.output - assert_equal '', @ui.error + @stub_ui.output + assert_equal '', @stub_ui.error end def test_execute_no_args - install_specs new_spec 'x', '2' + install_specs util_spec 'x', '2' spec_fetcher do |fetcher| fetcher.spec 'a', 1 @@ -40,7 +40,7 @@ class TestGemCommandsDependencyCommand < Gem::TestCase @cmd.options[:args] = [] - use_ui @ui do + use_ui @stub_ui do @cmd.execute end @@ -58,21 +58,21 @@ Gem x-2 EOF - assert_equal expected, @ui.output - assert_equal '', @ui.error + assert_equal expected, @stub_ui.output + assert_equal '', @stub_ui.error end def test_execute_no_match @cmd.options[:args] = %w[foo] assert_raises Gem::MockGemUi::TermError do - use_ui @ui do + use_ui @stub_ui do @cmd.execute end end - assert_equal "No gems found matching foo (>= 0)\n", @ui.output - assert_equal '', @ui.error + assert_equal "No gems found matching foo (>= 0)\n", @stub_ui.output + assert_equal '', @stub_ui.error end def test_execute_pipe_format @@ -85,12 +85,12 @@ Gem x-2 @cmd.options[:args] = %w[foo] @cmd.options[:pipe_format] = true - use_ui @ui do + use_ui @stub_ui do @cmd.execute end - assert_equal "bar --version '> 1'\n", @ui.output - assert_equal '', @ui.error + assert_equal "bar --version '> 1'\n", @stub_ui.output + assert_equal '', @stub_ui.error end def test_execute_regexp @@ -103,7 +103,7 @@ Gem x-2 @cmd.options[:args] = %w[/[ab]/] - use_ui @ui do + use_ui @stub_ui do @cmd.execute end @@ -118,8 +118,8 @@ Gem b-2 EOF - assert_equal expected, @ui.output - assert_equal '', @ui.error + assert_equal expected, @stub_ui.output + assert_equal '', @stub_ui.error end def test_execute_reverse @@ -135,7 +135,7 @@ Gem b-2 @cmd.options[:args] = %w[foo] @cmd.options[:reverse_dependencies] = true - use_ui @ui do + use_ui @stub_ui do @cmd.execute end @@ -147,8 +147,8 @@ Gem foo-2 EOF - assert_equal expected, @ui.output - assert_equal '', @ui.error + assert_equal expected, @stub_ui.output + assert_equal '', @stub_ui.error end def test_execute_reverse_remote @@ -157,7 +157,7 @@ Gem foo-2 @cmd.options[:domain] = :remote assert_raises Gem::MockGemUi::TermError do - use_ui @ui do + use_ui @stub_ui do @cmd.execute end end @@ -166,12 +166,12 @@ Gem foo-2 ERROR: Only reverse dependencies for local gems are supported. EOF - assert_equal '', @ui.output - assert_equal expected, @ui.error + assert_equal '', @stub_ui.output + assert_equal expected, @stub_ui.error end def test_execute_remote - install_specs new_spec 'bar', '2' + install_specs util_spec 'bar', '2' spec_fetcher do |fetcher| fetcher.spec 'foo', 2, 'bar' => '> 1' @@ -180,12 +180,12 @@ ERROR: Only reverse dependencies for local gems are supported. @cmd.options[:args] = %w[foo] @cmd.options[:domain] = :remote - use_ui @ui do + use_ui @stub_ui do @cmd.execute end - assert_equal "Gem foo-2\n bar (> 1)\n\n", @ui.output - assert_equal '', @ui.error + assert_equal "Gem foo-2\n bar (> 1)\n\n", @stub_ui.output + assert_equal '', @stub_ui.error end def test_execute_remote_version @@ -201,12 +201,12 @@ ERROR: Only reverse dependencies for local gems are supported. @cmd.options[:domain] = :remote @cmd.options[:version] = req '= 1' - use_ui @ui do + use_ui @stub_ui do @cmd.execute end - assert_equal "Gem a-1\n\n", @ui.output - assert_equal '', @ui.error + assert_equal "Gem a-1\n\n", @stub_ui.output + assert_equal '', @stub_ui.error end def test_execute_prerelease @@ -218,12 +218,12 @@ ERROR: Only reverse dependencies for local gems are supported. @cmd.options[:domain] = :remote @cmd.options[:prerelease] = true - use_ui @ui do + use_ui @stub_ui do @cmd.execute end - assert_equal "Gem a-2.a\n\n", @ui.output - assert_equal '', @ui.error + assert_equal "Gem a-2.a\n\n", @stub_ui.output + assert_equal '', @stub_ui.error end end diff --git a/test/rubygems/test_gem_commands_environment_command.rb b/test/rubygems/test_gem_commands_environment_command.rb index 040e5c4c39..1451f03982 100644 --- a/test/rubygems/test_gem_commands_environment_command.rb +++ b/test/rubygems/test_gem_commands_environment_command.rb @@ -29,6 +29,7 @@ class TestGemCommandsEnvironmentCommand < Gem::TestCase assert_match %r|RUBYGEMS PREFIX: |, @ui.output assert_match %r|RUBY EXECUTABLE:.*#{RbConfig::CONFIG['ruby_install_name']}|, @ui.output + assert_match %r|GIT EXECUTABLE: #{@cmd.send(:git_path)}|, @ui.output assert_match %r|SYSTEM CONFIGURATION DIRECTORY:|, @ui.output assert_match %r|EXECUTABLE DIRECTORY:|, @ui.output assert_match %r|RUBYGEMS PLATFORMS:|, @ui.output diff --git a/test/rubygems/test_gem_commands_help_command.rb b/test/rubygems/test_gem_commands_help_command.rb index 986df1a9a5..6542cab599 100644 --- a/test/rubygems/test_gem_commands_help_command.rb +++ b/test/rubygems/test_gem_commands_help_command.rb @@ -7,13 +7,16 @@ require "rubygems/command_manager" require File.expand_path('../rubygems_plugin', __FILE__) class TestGemCommandsHelpCommand < Gem::TestCase + # previously this was calc'd in setup, but 1.8.7 had + # intermittent failures, but no issues with above require + PLUGIN = File.expand_path('../rubygems_plugin.rb', __FILE__) + def setup super @cmd = Gem::Commands::HelpCommand.new - load File.expand_path('../rubygems_plugin.rb', __FILE__) unless - Gem::Commands.const_defined? :InterruptCommand + load PLUGIN unless Gem::Commands.const_defined? :InterruptCommand end def test_gem_help_bad diff --git a/test/rubygems/test_gem_commands_info_command.rb b/test/rubygems/test_gem_commands_info_command.rb new file mode 100644 index 0000000000..83b18c5036 --- /dev/null +++ b/test/rubygems/test_gem_commands_info_command.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true +require 'rubygems/test_case' +require 'rubygems/commands/info_command' + +class TestGemCommandsInfoCommand < Gem::TestCase + + def setup + super + + @cmd = Gem::Commands::InfoCommand.new + end + + def gem(name, version = "1.0") + spec = quick_gem name do |gem| + gem.summary = "test gem" + gem.homepage = "https://github.com/rubygems/rubygems" + gem.files = %W[lib/#{name}.rb Rakefile] + gem.authors = ["Colby", "Jack"] + gem.license = "MIT" + gem.version = version + end + write_file File.join(*%W[gems #{spec.full_name} lib #{name}.rb]) + write_file File.join(*%W[gems #{spec.full_name} Rakefile]) + spec + end + + def test_execute + @gem = gem "foo", "1.0.0" + + @cmd.handle_options %w[foo] + + use_ui @ui do + @cmd.execute + end + + assert_match %r%#{@gem.name} \(#{@gem.version}\)\n%, @ui.output + assert_match %r%Authors: #{@gem.authors.join(', ')}\n%, @ui.output + assert_match %r%Homepage: #{@gem.homepage}\n%, @ui.output + assert_match %r%License: #{@gem.license}\n%, @ui.output + assert_match %r%Installed at: #{@gem.base_dir}\n%, @ui.output + assert_match %r%#{@gem.summary}\n%, @ui.output + assert_match "", @ui.error + end +end diff --git a/test/rubygems/test_gem_commands_install_command.rb b/test/rubygems/test_gem_commands_install_command.rb index 822d40e3f3..8c084a94a6 100644 --- a/test/rubygems/test_gem_commands_install_command.rb +++ b/test/rubygems/test_gem_commands_install_command.rb @@ -201,6 +201,38 @@ class TestGemCommandsInstallCommand < Gem::TestCase assert_match(/ould not find a valid gem 'nonexistent'/, @ui.error) end + def test_execute_dependency_nonexistent + spec_fetcher do |fetcher| + fetcher.spec 'foo', 2, 'bar' => '0.5' + end + + @cmd.options[:args] = ['foo'] + + use_ui @ui do + e = assert_raises Gem::MockGemUi::TermError do + @cmd.execute + end + + assert_equal 2, e.exit_code + end + + expected = <<-EXPECTED +ERROR: Could not find a valid gem 'bar' (= 0.5) (required by 'foo' (>= 0)) in any repository + EXPECTED + + assert_equal expected, @ui.error + end + + def test_execute_http_proxy + use_ui @ui do + e = assert_raises ArgumentError, @ui.error do + @cmd.handle_options %w[-p=foo.bar.com] + end + + assert_match "Invalid uri scheme for =foo.bar.com\nPreface URLs with one of [\"http://\", \"https://\", \"file://\", \"s3://\"]", e.message + end + end + def test_execute_bad_source spec_fetcher @@ -380,7 +412,6 @@ ERROR: Possible alternatives: non_existent_with_hint end def test_execute_rdoc - skip if RUBY_VERSION <= "1.8.7" specs = spec_fetcher do |fetcher| fetcher.gem 'a', 2 end @@ -416,6 +447,42 @@ ERROR: Possible alternatives: non_existent_with_hint assert_path_exists File.join(a2.doc_dir, 'rdoc') end + def test_execute_rdoc_with_path + specs = spec_fetcher do |fetcher| + fetcher.gem 'a', 2 + end + + Gem.done_installing(&Gem::RDoc.method(:generation_hook)) + + @cmd.options[:document] = %w[rdoc ri] + @cmd.options[:domain] = :local + @cmd.options[:install_dir] = 'whatever' + + a2 = specs['a-2'] + FileUtils.mv a2.cache_file, @tempdir + + @cmd.options[:args] = %w[a] + + use_ui @ui do + # Don't use Dir.chdir with a block, it warnings a lot because + # of a downstream Dir.chdir with a block + old = Dir.getwd + + begin + Dir.chdir @tempdir + assert_raises Gem::MockGemUi::SystemExitException, @ui.error do + @cmd.execute + end + ensure + Dir.chdir old + end + end + + wait_for_child_process_to_exit + + assert_path_exists 'whatever/doc/a-2', 'documentation not installed' + end + def test_execute_saves_build_args specs = spec_fetcher do |fetcher| fetcher.gem 'a', 2 @@ -581,7 +648,8 @@ ERROR: Possible alternatives: non_existent_with_hint assert_empty @cmd.installed_specs - msg = "ERROR: Can't use --version w/ multiple gems. Use name:ver instead." + msg = "ERROR: Can't use --version with multiple gems. You can specify multiple gems with" \ + " version requirments using `gem install 'my_gem:1.0.0' 'my_other_gem:~>2.0.0'`" assert_empty @ui.output assert_equal msg, @ui.error.chomp diff --git a/test/rubygems/test_gem_commands_owner_command.rb b/test/rubygems/test_gem_commands_owner_command.rb index 53cac4ce87..3185074d98 100644 --- a/test/rubygems/test_gem_commands_owner_command.rb +++ b/test/rubygems/test_gem_commands_owner_command.rb @@ -8,8 +8,10 @@ class TestGemCommandsOwnerCommand < Gem::TestCase super ENV["RUBYGEMS_HOST"] = nil - @fetcher = Gem::FakeFetcher.new - Gem::RemoteFetcher.fetcher = @fetcher + @stub_ui = Gem::MockGemUi.new + @stub_fetcher = Gem::FakeFetcher.new + Gem::RemoteFetcher.fetcher = @stub_fetcher + Gem.configuration = nil Gem.configuration.rubygems_api_key = "ed244fbf2b1a52e012da8616c512fa47f9aa5250" @cmd = Gem::Commands::OwnerCommand.new @@ -27,20 +29,20 @@ class TestGemCommandsOwnerCommand < Gem::TestCase - id: 4 EOF - @fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, 'OK'] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, 'OK'] - use_ui @ui do + use_ui @stub_ui do @cmd.show_owners("freewill") end - assert_equal Net::HTTP::Get, @fetcher.last_request.class - assert_equal Gem.configuration.rubygems_api_key, @fetcher.last_request["Authorization"] + assert_equal Net::HTTP::Get, @stub_fetcher.last_request.class + assert_equal Gem.configuration.rubygems_api_key, @stub_fetcher.last_request["Authorization"] - assert_match %r{Owners for gem: freewill}, @ui.output - assert_match %r{- user1@example.com}, @ui.output - assert_match %r{- user2@example.com}, @ui.output - assert_match %r{- user3}, @ui.output - assert_match %r{- 4}, @ui.output + assert_match %r{Owners for gem: freewill}, @stub_ui.output + assert_match %r{- user1@example.com}, @stub_ui.output + assert_match %r{- user2@example.com}, @stub_ui.output + assert_match %r{- user3}, @stub_ui.output + assert_match %r{- 4}, @stub_ui.output end def test_show_owners_dont_load_objects @@ -57,7 +59,7 @@ EOF - id: 4 EOF - @fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, 'OK'] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, 'OK'] assert_raises Psych::DisallowedClass do use_ui @ui do @@ -73,14 +75,14 @@ EOF host = "http://rubygems.example" ENV["RUBYGEMS_HOST"] = host - @fetcher.data["#{host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, 'OK'] + @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, 'OK'] - use_ui @ui do + use_ui @stub_ui do @cmd.show_owners("freewill") end - assert_match %r{Owners for gem: freewill}, @ui.output - assert_match %r{- user1@example.com}, @ui.output + assert_match %r{Owners for gem: freewill}, @stub_ui.output + assert_match %r{- user1@example.com}, @stub_ui.output end def test_show_owners_setting_up_host @@ -88,32 +90,32 @@ EOF host = "http://rubygems.example" @cmd.host = host - @fetcher.data["#{host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, 'OK'] + @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, 'OK'] - use_ui @ui do + use_ui @stub_ui do @cmd.show_owners("freewill") end - assert_match %r{Owners for gem: freewill}, @ui.output - assert_match %r{- user1@example.com}, @ui.output + assert_match %r{Owners for gem: freewill}, @stub_ui.output + assert_match %r{- user1@example.com}, @stub_ui.output end def test_show_owners_denied response = "You don't have permission to push to this gem" - @fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = [response, 403, 'Forbidden'] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = [response, 403, 'Forbidden'] assert_raises Gem::MockGemUi::TermError do - use_ui @ui do + use_ui @stub_ui do @cmd.show_owners("freewill") end end - assert_match response, @ui.output + assert_match response, @stub_ui.output end def test_show_owners_key response = "- email: user1@example.com\n" - @fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, 'OK'] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, 'OK'] File.open Gem.configuration.credentials_path, 'a' do |f| f.write ':other: 701229f217cdf23b1344c7b4b54ca97' end @@ -122,56 +124,56 @@ EOF @cmd.handle_options %w(-k other) @cmd.show_owners('freewill') - assert_equal '701229f217cdf23b1344c7b4b54ca97', @fetcher.last_request['Authorization'] + assert_equal '701229f217cdf23b1344c7b4b54ca97', @stub_fetcher.last_request['Authorization'] end def test_add_owners response = "Owner added successfully." - @fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 200, 'OK'] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 200, 'OK'] - use_ui @ui do + use_ui @stub_ui do @cmd.add_owners("freewill", ["user-new1@example.com"]) end - assert_equal Net::HTTP::Post, @fetcher.last_request.class - assert_equal Gem.configuration.rubygems_api_key, @fetcher.last_request["Authorization"] - assert_equal "email=user-new1%40example.com", @fetcher.last_request.body + assert_equal Net::HTTP::Post, @stub_fetcher.last_request.class + assert_equal Gem.configuration.rubygems_api_key, @stub_fetcher.last_request["Authorization"] + assert_equal "email=user-new1%40example.com", @stub_fetcher.last_request.body - assert_match response, @ui.output + assert_match response, @stub_ui.output end def test_add_owners_denied response = "You don't have permission to push to this gem" - @fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 403, 'Forbidden'] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 403, 'Forbidden'] - use_ui @ui do + use_ui @stub_ui do @cmd.add_owners("freewill", ["user-new1@example.com"]) end - assert_match response, @ui.output + assert_match response, @stub_ui.output end def test_add_owner_with_host_option_through_execute host = "http://rubygems.example" add_owner_response = "Owner added successfully." show_owners_response = "- email: user1@example.com\n" - @fetcher.data["#{host}/api/v1/gems/freewill/owners"] = [add_owner_response, 200, 'OK'] - @fetcher.data["#{host}/api/v1/gems/freewill/owners.yaml"] = [show_owners_response, 200, 'OK'] + @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners"] = [add_owner_response, 200, 'OK'] + @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners.yaml"] = [show_owners_response, 200, 'OK'] @cmd.handle_options %W[--host #{host} --add user-new1@example.com freewill] - use_ui @ui do + use_ui @stub_ui do @cmd.execute end - assert_match add_owner_response, @ui.output - assert_match %r{Owners for gem: freewill}, @ui.output - assert_match %r{- user1@example.com}, @ui.output + assert_match add_owner_response, @stub_ui.output + assert_match %r{Owners for gem: freewill}, @stub_ui.output + assert_match %r{- user1@example.com}, @stub_ui.output end def test_add_owners_key response = "Owner added successfully." - @fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 200, 'OK'] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 200, 'OK'] File.open Gem.configuration.credentials_path, 'a' do |f| f.write ':other: 701229f217cdf23b1344c7b4b54ca97' end @@ -180,38 +182,38 @@ EOF @cmd.handle_options %w(-k other) @cmd.add_owners('freewill', ['user-new1@example.com']) - assert_equal '701229f217cdf23b1344c7b4b54ca97', @fetcher.last_request['Authorization'] + assert_equal '701229f217cdf23b1344c7b4b54ca97', @stub_fetcher.last_request['Authorization'] end def test_remove_owners response = "Owner removed successfully." - @fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 200, 'OK'] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 200, 'OK'] - use_ui @ui do + use_ui @stub_ui do @cmd.remove_owners("freewill", ["user-remove1@example.com"]) end - assert_equal Net::HTTP::Delete, @fetcher.last_request.class - assert_equal Gem.configuration.rubygems_api_key, @fetcher.last_request["Authorization"] - assert_equal "email=user-remove1%40example.com", @fetcher.last_request.body + assert_equal Net::HTTP::Delete, @stub_fetcher.last_request.class + assert_equal Gem.configuration.rubygems_api_key, @stub_fetcher.last_request["Authorization"] + assert_equal "email=user-remove1%40example.com", @stub_fetcher.last_request.body - assert_match response, @ui.output + assert_match response, @stub_ui.output end def test_remove_owners_denied response = "You don't have permission to push to this gem" - @fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 403, 'Forbidden'] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 403, 'Forbidden'] - use_ui @ui do + use_ui @stub_ui do @cmd.remove_owners("freewill", ["user-remove1@example.com"]) end - assert_match response, @ui.output + assert_match response, @stub_ui.output end def test_remove_owners_key response = "Owner removed successfully." - @fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 200, 'OK'] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 200, 'OK'] File.open Gem.configuration.credentials_path, 'a' do |f| f.write ':other: 701229f217cdf23b1344c7b4b54ca97' end @@ -220,18 +222,18 @@ EOF @cmd.handle_options %w(-k other) @cmd.remove_owners('freewill', ['user-remove1@example.com']) - assert_equal '701229f217cdf23b1344c7b4b54ca97', @fetcher.last_request['Authorization'] + assert_equal '701229f217cdf23b1344c7b4b54ca97', @stub_fetcher.last_request['Authorization'] end def test_remove_owners_missing response = 'Owner could not be found.' - @fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 404, 'Not Found'] + @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 404, 'Not Found'] - use_ui @ui do + use_ui @stub_ui do @cmd.remove_owners("freewill", ["missing@example"]) end - assert_equal "Removing missing@example: #{response}\n", @ui.output + assert_equal "Removing missing@example: #{response}\n", @stub_ui.output end end diff --git a/test/rubygems/test_gem_commands_pristine_command.rb b/test/rubygems/test_gem_commands_pristine_command.rb index d2f8b10bb8..806ed87007 100644 --- a/test/rubygems/test_gem_commands_pristine_command.rb +++ b/test/rubygems/test_gem_commands_pristine_command.rb @@ -253,6 +253,31 @@ class TestGemCommandsPristineCommand < Gem::TestCase assert_empty out, out.inspect end + def test_skip_many_gems + a = util_spec 'a' + b = util_spec 'b' + c = util_spec 'c' + + install_gem a + install_gem b + install_gem c + + @cmd.options[:args] = %w[a b c] + @cmd.options[:skip] = ['a', 'c'] + + use_ui @ui do + @cmd.execute + end + + out = @ui.output.split "\n" + + assert_equal "Restoring gems to pristine condition...", out.shift + assert_equal "Skipped #{a.full_name}, it was given through options", out.shift + assert_equal "Restored #{b.full_name}", out.shift + assert_equal "Skipped #{c.full_name}, it was given through options", out.shift + assert_empty out, out.inspect + end + def test_execute_many_multi_repo a = util_spec 'a' install_gem a @@ -488,4 +513,3 @@ class TestGemCommandsPristineCommand < Gem::TestCase end end - diff --git a/test/rubygems/test_gem_commands_query_command.rb b/test/rubygems/test_gem_commands_query_command.rb index 5471ecadcc..db6c16e91b 100644 --- a/test/rubygems/test_gem_commands_query_command.rb +++ b/test/rubygems/test_gem_commands_query_command.rb @@ -9,8 +9,10 @@ module TestGemCommandsQueryCommandSetup @cmd = Gem::Commands::QueryCommand.new @specs = add_gems_to_fetcher - - @fetcher.data["#{@gem_repo}Marshal.#{Gem.marshal_version}"] = proc do + @stub_ui = Gem::MockGemUi.new + @stub_fetcher = Gem::FakeFetcher.new + + @stub_fetcher.data["#{@gem_repo}Marshal.#{Gem.marshal_version}"] = proc do raise Gem::RemoteFetcher::FetchError end end @@ -26,7 +28,7 @@ class TestGemCommandsQueryCommandWithInstalledGems < Gem::TestCase @cmd.handle_options %w[-r] - use_ui @ui do + use_ui @stub_ui do @cmd.execute end @@ -38,8 +40,8 @@ a (2) pl (1 i386-linux) EOF - assert_equal expected, @ui.output - assert_equal '', @ui.error + assert_equal expected, @stub_ui.output + assert_equal '', @stub_ui.error end def test_execute_all @@ -49,7 +51,7 @@ pl (1 i386-linux) @cmd.handle_options %w[-r --all] - use_ui @ui do + use_ui @stub_ui do @cmd.execute end @@ -61,8 +63,8 @@ a (2, 1) pl (1 i386-linux) EOF - assert_equal expected, @ui.output - assert_equal '', @ui.error + assert_equal expected, @stub_ui.output + assert_equal '', @stub_ui.error end def test_execute_all_prerelease @@ -72,7 +74,7 @@ pl (1 i386-linux) @cmd.handle_options %w[-r --all --prerelease] - use_ui @ui do + use_ui @stub_ui do @cmd.execute end @@ -84,8 +86,8 @@ a (3.a, 2, 1) pl (1 i386-linux) EOF - assert_equal expected, @ui.output - assert_equal '', @ui.error + assert_equal expected, @stub_ui.output + assert_equal '', @stub_ui.error end def test_execute_details @@ -101,7 +103,7 @@ pl (1 i386-linux) @cmd.handle_options %w[-r -d] - use_ui @ui do + use_ui @stub_ui do @cmd.execute end @@ -124,8 +126,8 @@ pl (1) this is a summary EOF - assert_equal expected, @ui.output - assert_equal '', @ui.error + assert_equal expected, @stub_ui.output + assert_equal '', @stub_ui.error end def test_execute_details_cleans_text @@ -141,7 +143,7 @@ pl (1) @cmd.handle_options %w[-r -d] - use_ui @ui do + use_ui @stub_ui do @cmd.execute end @@ -164,8 +166,8 @@ pl (1) this is a summary EOF - assert_equal expected, @ui.output - assert_equal '', @ui.error + assert_equal expected, @stub_ui.output + assert_equal '', @stub_ui.error end def test_execute_details_truncates_summary @@ -181,7 +183,7 @@ pl (1) @cmd.handle_options %w[-r -d] - use_ui @ui do + use_ui @stub_ui do @cmd.execute end @@ -204,34 +206,34 @@ pl (1) this is a summary EOF - assert_equal expected, @ui.output - assert_equal '', @ui.error + assert_equal expected, @stub_ui.output + assert_equal '', @stub_ui.error end def test_execute_installed @cmd.handle_options %w[-n a --installed] assert_raises Gem::MockGemUi::SystemExitException do - use_ui @ui do + use_ui @stub_ui do @cmd.execute end end - assert_equal "true\n", @ui.output - assert_equal '', @ui.error + assert_equal "true\n", @stub_ui.output + assert_equal '', @stub_ui.error end def test_execute_installed_inverse @cmd.handle_options %w[-n a --no-installed] e = assert_raises Gem::MockGemUi::TermError do - use_ui @ui do + use_ui @stub_ui do @cmd.execute end end - assert_equal "false\n", @ui.output - assert_equal '', @ui.error + assert_equal "false\n", @stub_ui.output + assert_equal '', @stub_ui.error assert_equal 1, e.exit_code end @@ -240,26 +242,26 @@ pl (1) @cmd.handle_options %w[-n not_installed --no-installed] assert_raises Gem::MockGemUi::SystemExitException do - use_ui @ui do + use_ui @stub_ui do @cmd.execute end end - assert_equal "true\n", @ui.output - assert_equal '', @ui.error + assert_equal "true\n", @stub_ui.output + assert_equal '', @stub_ui.error end def test_execute_installed_no_name @cmd.handle_options %w[--installed] e = assert_raises Gem::MockGemUi::TermError do - use_ui @ui do + use_ui @stub_ui do @cmd.execute end end - assert_equal '', @ui.output - assert_equal "ERROR: You must specify a gem name\n", @ui.error + assert_equal '', @stub_ui.output + assert_equal "ERROR: You must specify a gem name\n", @stub_ui.error assert_equal 4, e.exit_code end @@ -268,13 +270,13 @@ pl (1) @cmd.handle_options %w[-n not_installed --installed] e = assert_raises Gem::MockGemUi::TermError do - use_ui @ui do + use_ui @stub_ui do @cmd.execute end end - assert_equal "false\n", @ui.output - assert_equal '', @ui.error + assert_equal "false\n", @stub_ui.output + assert_equal '', @stub_ui.error assert_equal 1, e.exit_code end @@ -283,26 +285,26 @@ pl (1) @cmd.handle_options %w[-n a --installed --version 2] assert_raises Gem::MockGemUi::SystemExitException do - use_ui @ui do + use_ui @stub_ui do @cmd.execute end end - assert_equal "true\n", @ui.output - assert_equal '', @ui.error + assert_equal "true\n", @stub_ui.output + assert_equal '', @stub_ui.error end def test_execute_installed_version_not_installed @cmd.handle_options %w[-n c --installed --version 2] e = assert_raises Gem::MockGemUi::TermError do - use_ui @ui do + use_ui @stub_ui do @cmd.execute end end - assert_equal "false\n", @ui.output - assert_equal '', @ui.error + assert_equal "false\n", @stub_ui.output + assert_equal '', @stub_ui.error assert_equal 1, e.exit_code end @@ -314,7 +316,7 @@ pl (1) @cmd.options[:domain] = :local - use_ui @ui do + use_ui @stub_ui do @cmd.execute end @@ -326,8 +328,8 @@ a (3.a, 2, 1) pl (1 i386-linux) EOF - assert_equal expected, @ui.output - assert_equal '', @ui.error + assert_equal expected, @stub_ui.output + assert_equal '', @stub_ui.error end def test_execute_local_notty @@ -337,9 +339,9 @@ pl (1 i386-linux) @cmd.handle_options %w[] - @ui.outs.tty = false + @stub_ui.outs.tty = false - use_ui @ui do + use_ui @stub_ui do @cmd.execute end @@ -348,8 +350,8 @@ a (3.a, 2, 1) pl (1 i386-linux) EOF - assert_equal expected, @ui.output - assert_equal '', @ui.error + assert_equal expected, @stub_ui.output + assert_equal '', @stub_ui.error end def test_execute_local_quiet @@ -360,7 +362,7 @@ pl (1 i386-linux) @cmd.options[:domain] = :local Gem.configuration.verbose = false - use_ui @ui do + use_ui @stub_ui do @cmd.execute end @@ -369,8 +371,8 @@ a (3.a, 2, 1) pl (1 i386-linux) EOF - assert_equal expected, @ui.output - assert_equal '', @ui.error + assert_equal expected, @stub_ui.output + assert_equal '', @stub_ui.error end def test_execute_no_versions @@ -380,7 +382,7 @@ pl (1 i386-linux) @cmd.handle_options %w[-r --no-versions] - use_ui @ui do + use_ui @stub_ui do @cmd.execute end @@ -392,8 +394,8 @@ a pl EOF - assert_equal expected, @ui.output - assert_equal '', @ui.error + assert_equal expected, @stub_ui.output + assert_equal '', @stub_ui.error end def test_execute_notty @@ -403,9 +405,9 @@ pl @cmd.handle_options %w[-r] - @ui.outs.tty = false + @stub_ui.outs.tty = false - use_ui @ui do + use_ui @stub_ui do @cmd.execute end @@ -414,14 +416,14 @@ a (2) pl (1 i386-linux) EOF - assert_equal expected, @ui.output - assert_equal '', @ui.error + assert_equal expected, @stub_ui.output + assert_equal '', @stub_ui.error end def test_execute_prerelease @cmd.handle_options %w[-r --prerelease] - use_ui @ui do + use_ui @stub_ui do @cmd.execute end @@ -432,8 +434,8 @@ pl (1 i386-linux) a (3.a) EOF - assert_equal expected, @ui.output - assert_equal '', @ui.error + assert_equal expected, @stub_ui.output + assert_equal '', @stub_ui.error end def test_execute_prerelease_local @@ -443,7 +445,7 @@ a (3.a) @cmd.handle_options %w[-l --prerelease] - use_ui @ui do + use_ui @stub_ui do @cmd.execute end @@ -455,8 +457,8 @@ a (3.a, 2, 1) pl (1 i386-linux) EOF - assert_equal expected, @ui.output - assert_equal "WARNING: prereleases are always shown locally\n", @ui.error + assert_equal expected, @stub_ui.output + assert_equal "WARNING: prereleases are always shown locally\n", @stub_ui.error end def test_execute_remote @@ -466,7 +468,7 @@ pl (1 i386-linux) @cmd.options[:domain] = :remote - use_ui @ui do + use_ui @stub_ui do @cmd.execute end @@ -478,8 +480,8 @@ a (2) pl (1 i386-linux) EOF - assert_equal expected, @ui.output - assert_equal '', @ui.error + assert_equal expected, @stub_ui.output + assert_equal '', @stub_ui.error end def test_execute_remote_notty @@ -489,9 +491,9 @@ pl (1 i386-linux) @cmd.handle_options %w[] - @ui.outs.tty = false + @stub_ui.outs.tty = false - use_ui @ui do + use_ui @stub_ui do @cmd.execute end @@ -500,8 +502,8 @@ a (3.a, 2, 1) pl (1 i386-linux) EOF - assert_equal expected, @ui.output - assert_equal '', @ui.error + assert_equal expected, @stub_ui.output + assert_equal '', @stub_ui.error end def test_execute_remote_quiet @@ -512,7 +514,7 @@ pl (1 i386-linux) @cmd.options[:domain] = :remote Gem.configuration.verbose = false - use_ui @ui do + use_ui @stub_ui do @cmd.execute end @@ -521,14 +523,14 @@ a (2) pl (1 i386-linux) EOF - assert_equal expected, @ui.output - assert_equal '', @ui.error + assert_equal expected, @stub_ui.output + assert_equal '', @stub_ui.error end def test_make_entry a_2_name = @specs['a-2'].original_name - @fetcher.data.delete \ + @stub_fetcher.data.delete \ "#{@gem_repo}quick/Marshal.#{Gem.marshal_version}/#{a_2_name}.gemspec.rz" a2 = @specs['a-2'] @@ -552,26 +554,26 @@ pl (1 i386-linux) @cmd.handle_options %w[a pl] - use_ui @ui do + use_ui @stub_ui do @cmd.execute end - assert_match %r%^a %, @ui.output - assert_match %r%^pl %, @ui.output - assert_equal '', @ui.error + assert_match %r%^a %, @stub_ui.output + assert_match %r%^pl %, @stub_ui.output + assert_equal '', @stub_ui.error end def test_show_gems @cmd.options[:name] = // @cmd.options[:domain] = :remote - use_ui @ui do + use_ui @stub_ui do @cmd.send :show_gems, /a/i, false end - assert_match %r%^a %, @ui.output - refute_match %r%^pl %, @ui.output - assert_empty @ui.error + assert_match %r%^a %, @stub_ui.output + refute_match %r%^pl %, @stub_ui.output + assert_empty @stub_ui.error end private @@ -602,7 +604,7 @@ class TestGemCommandsQueryCommandWithoutInstalledGems < Gem::TestCase @cmd.handle_options %w[-r -a] - use_ui @ui do + use_ui @stub_ui do @cmd.execute end @@ -613,8 +615,8 @@ class TestGemCommandsQueryCommandWithoutInstalledGems < Gem::TestCase a (2 universal-darwin, 1 ruby x86-linux) EOF - assert_equal expected, @ui.output - assert_equal '', @ui.error + assert_equal expected, @stub_ui.output + assert_equal '', @stub_ui.error end def test_execute_show_default_gems @@ -623,7 +625,7 @@ a (2 universal-darwin, 1 ruby x86-linux) a1 = new_default_spec 'a', 1 install_default_specs a1 - use_ui @ui do + use_ui @stub_ui do @cmd.execute end @@ -634,7 +636,7 @@ a (2 universal-darwin, 1 ruby x86-linux) a (2, default: 1) EOF - assert_equal expected, @ui.output + assert_equal expected, @stub_ui.output end def test_execute_show_default_gems_with_platform @@ -642,7 +644,7 @@ EOF a1.platform = 'java' install_default_specs a1 - use_ui @ui do + use_ui @stub_ui do @cmd.execute end @@ -653,7 +655,7 @@ EOF a (default: 1 java) EOF - assert_equal expected, @ui.output + assert_equal expected, @stub_ui.output end def test_execute_default_details @@ -666,7 +668,7 @@ EOF @cmd.handle_options %w[-l -d] - use_ui @ui do + use_ui @stub_ui do @cmd.execute end @@ -683,7 +685,7 @@ a (2, 1) this is a summary EOF - assert_equal expected, @ui.output + assert_equal expected, @stub_ui.output end def test_execute_local_details @@ -704,11 +706,11 @@ a (2, 1) @cmd.handle_options %w[-l -d] - use_ui @ui do + use_ui @stub_ui do @cmd.execute end - str = @ui.output + str = @stub_ui.output str.gsub!(/\(\d\): [^\n]*/, "-") str.gsub!(/at: [^\n]*/, "at: -") @@ -738,7 +740,7 @@ pl (1) this is a summary EOF - assert_equal expected, @ui.output + assert_equal expected, @stub_ui.output end def test_execute_exact_remote @@ -750,7 +752,7 @@ pl (1) @cmd.handle_options %w[--remote --exact coolgem] - use_ui @ui do + use_ui @stub_ui do @cmd.execute end @@ -761,7 +763,7 @@ pl (1) coolgem (4.2.1) EOF - assert_equal expected, @ui.output + assert_equal expected, @stub_ui.output end def test_execute_exact_local @@ -773,7 +775,7 @@ coolgem (4.2.1) @cmd.handle_options %w[--exact coolgem] - use_ui @ui do + use_ui @stub_ui do @cmd.execute end @@ -784,7 +786,7 @@ coolgem (4.2.1) coolgem (4.2.1) EOF - assert_equal expected, @ui.output + assert_equal expected, @stub_ui.output end def test_execute_exact_multiple @@ -800,7 +802,7 @@ coolgem (4.2.1) @cmd.handle_options %w[--exact coolgem othergem] - use_ui @ui do + use_ui @stub_ui do @cmd.execute end @@ -815,7 +817,7 @@ coolgem (4.2.1) othergem (1.2.3) EOF - assert_equal expected, @ui.output + assert_equal expected, @stub_ui.output end private diff --git a/test/rubygems/test_gem_commands_setup_command.rb b/test/rubygems/test_gem_commands_setup_command.rb index c4de8c53d5..6d388ab0ee 100644 --- a/test/rubygems/test_gem_commands_setup_command.rb +++ b/test/rubygems/test_gem_commands_setup_command.rb @@ -103,6 +103,32 @@ class TestGemCommandsSetupCommand < Gem::TestCase assert_equal "I changed it!\n", File.read(gem_bin_path) end + def test_env_shebang_flag + gem_bin_path = gem_install 'a' + write_file gem_bin_path do |io| + io.puts 'I changed it!' + end + + @cmd.options[:document] = [] + @cmd.options[:env_shebang] = true + @cmd.execute + + default_gem_bin_path = File.join @install_dir, 'bin', 'gem' + default_bundle_bin_path = File.join @install_dir, 'bin', 'bundle' + + ruby_exec = sprintf Gem.default_exec_format, 'ruby' + + if Gem.win_platform? + assert_match %r%\A#!\s*#{ruby_exec}%, File.read(default_gem_bin_path) + assert_match %r%\A#!\s*#{ruby_exec}%, File.read(default_bundle_bin_path) + assert_match %r%\A#!\s*#{ruby_exec}%, File.read(gem_bin_path) + else + assert_match %r%\A#!/usr/bin/env #{ruby_exec}%, File.read(default_gem_bin_path) + assert_match %r%\A#!/usr/bin/env #{ruby_exec}%, File.read(default_bundle_bin_path) + assert_match %r%\A#!/usr/bin/env #{ruby_exec}%, File.read(gem_bin_path) + end + end + def test_pem_files_in assert_equal %w[rubygems/ssl_certs/rubygems.org/foo.pem], @cmd.pem_files_in('lib').sort @@ -207,11 +233,8 @@ class TestGemCommandsSetupCommand < Gem::TestCase end def test_show_release_notes - @default_external = nil - if Object.const_defined? :Encoding - @default_external = @ui.outs.external_encoding - @ui.outs.set_encoding Encoding::US_ASCII - end + @default_external = @ui.outs.external_encoding + @ui.outs.set_encoding Encoding::US_ASCII @cmd.options[:previous_version] = Gem::Version.new '2.0.2' @@ -256,7 +279,7 @@ class TestGemCommandsSetupCommand < Gem::TestCase EXPECTED output = @ui.output - output.force_encoding Encoding::UTF_8 if Object.const_defined? :Encoding + output.force_encoding Encoding::UTF_8 assert_equal expected, output ensure diff --git a/test/rubygems/test_gem_commands_signin_command.rb b/test/rubygems/test_gem_commands_signin_command.rb index 56eecfc1f8..2cf86edd09 100644 --- a/test/rubygems/test_gem_commands_signin_command.rb +++ b/test/rubygems/test_gem_commands_signin_command.rb @@ -48,7 +48,7 @@ class TestGemCommandsSigninCommand < Gem::TestCase assert_equal credentials[:rubygems_api_key], api_key - assert_equal credentials[host], nil + assert_nil credentials[host] end def test_execute_with_host_supplied diff --git a/test/rubygems/test_gem_commands_specification_command.rb b/test/rubygems/test_gem_commands_specification_command.rb index c3650649ae..72e008b2cb 100644 --- a/test/rubygems/test_gem_commands_specification_command.rb +++ b/test/rubygems/test_gem_commands_specification_command.rb @@ -105,7 +105,7 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase end def test_execute_field - foo = new_spec 'foo', '2' + foo = util_spec 'foo', '2' install_specs foo @@ -137,7 +137,7 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase end def test_execute_marshal - foo = new_spec 'foo', '2' + foo = util_spec 'foo', '2' install_specs foo diff --git a/test/rubygems/test_gem_commands_stale_command.rb b/test/rubygems/test_gem_commands_stale_command.rb index 4d2f5349f0..a8909c6d13 100644 --- a/test/rubygems/test_gem_commands_stale_command.rb +++ b/test/rubygems/test_gem_commands_stale_command.rb @@ -6,6 +6,7 @@ class TestGemCommandsStaleCommand < Gem::TestCase def setup super + @stub_ui = Gem::MockGemUi.new @cmd = Gem::Commands::StaleCommand.new end @@ -31,11 +32,11 @@ class TestGemCommandsStaleCommand < Gem::TestCase FileUtils.touch(filename, :mtime => Time.now - 86400) end - use_ui @ui do + use_ui @stub_ui do @cmd.execute end - lines = @ui.output.split("\n") + lines = @stub_ui.output.split("\n") assert_equal("#{foo_bar.name}-#{foo_bar.version}", lines[0].split.first) assert_equal("#{bar_baz.name}-#{bar_baz.version}", lines[1].split.first) end diff --git a/test/rubygems/test_gem_commands_uninstall_command.rb b/test/rubygems/test_gem_commands_uninstall_command.rb index 2fdff706e7..f23f4c2461 100644 --- a/test/rubygems/test_gem_commands_uninstall_command.rb +++ b/test/rubygems/test_gem_commands_uninstall_command.rb @@ -238,7 +238,7 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase @cmd.handle_options %w[] assert_equal false, @cmd.options[:check_dev] - assert_equal nil, @cmd.options[:install_dir] + assert_nil @cmd.options[:install_dir] assert_equal true, @cmd.options[:user_install] assert_equal Gem::Requirement.default, @cmd.options[:version] assert_equal false, @cmd.options[:vendor] @@ -291,5 +291,31 @@ WARNING: Use your OS package manager to uninstall vendor gems assert_equal output.first, "Gem 'd' is not installed" end + def test_execute_with_gem_uninstall_error + util_make_gems + + @cmd.options[:args] = %w[a] + + uninstall_exception = lambda do |_a| + ex = Gem::UninstallError.new + ex.spec = @spec + + raise ex + end + + e = nil + @cmd.stub :uninstall, uninstall_exception do + use_ui @ui do + e = assert_raises Gem::MockGemUi::TermError do + @cmd.execute + end + end + + assert_equal 1, e.exit_code + end + + assert_empty @ui.output + assert_match %r!Error: unable to successfully uninstall '#{@spec.name}'!, @ui.error + end end diff --git a/test/rubygems/test_gem_commands_unpack_command.rb b/test/rubygems/test_gem_commands_unpack_command.rb index 61f671da7d..4fde83e524 100644 --- a/test/rubygems/test_gem_commands_unpack_command.rb +++ b/test/rubygems/test_gem_commands_unpack_command.rb @@ -134,6 +134,23 @@ class TestGemCommandsUnpackCommand < Gem::TestCase assert File.exist?(File.join(@tempdir, 'b-2.gemspec')) end + def test_execute_spec_target + util_make_gems + + @cmd.options[:args] = %w[a b] + @cmd.options[:target] = 'specs' + @cmd.options[:spec] = true + + use_ui @ui do + Dir.chdir @tempdir do + @cmd.execute + end + end + + assert File.exist?(File.join(@tempdir, 'specs/a-3.a.gemspec')) + assert File.exist?(File.join(@tempdir, 'specs/b-2.gemspec')) + end + def test_execute_sudo skip 'Cannot perform this test on windows (chmod)' if win_platform? diff --git a/test/rubygems/test_gem_commands_update_command.rb b/test/rubygems/test_gem_commands_update_command.rb index fa444fa32f..549e34c218 100644 --- a/test/rubygems/test_gem_commands_update_command.rb +++ b/test/rubygems/test_gem_commands_update_command.rb @@ -217,7 +217,6 @@ class TestGemCommandsUpdateCommand < Gem::TestCase end def test_execute_rdoc - skip if RUBY_VERSION <= "1.8.7" spec_fetcher do |fetcher| fetcher.download 'a', 2 fetcher.spec 'a', 1 @@ -504,5 +503,23 @@ class TestGemCommandsUpdateCommand < Gem::TestCase assert_empty arguments end -end + def test_explain + spec_fetcher do |fetcher| + fetcher.download 'a', 2 + fetcher.spec 'a', 1 + end + @cmd.options[:explain] = true + @cmd.options[:args] = %w[a] + + use_ui @ui do + @cmd.execute + end + + out = @ui.output.split "\n" + + assert_equal "Gems to update:", out.shift + assert_equal " a-2", out.shift + assert_empty out + end +end diff --git a/test/rubygems/test_gem_dependency_installer.rb b/test/rubygems/test_gem_dependency_installer.rb index 3d76291668..51d3b450f7 100644 --- a/test/rubygems/test_gem_dependency_installer.rb +++ b/test/rubygems/test_gem_dependency_installer.rb @@ -431,7 +431,7 @@ class TestGemDependencyInstaller < Gem::TestCase EXTCONF_RB end - e1 = new_spec 'e', '1', nil, 'extconf.rb' do |s| + e1 = util_spec 'e', '1', nil, 'extconf.rb' do |s| s.extensions << 'extconf.rb' end e1_gem = File.join @tempdir, 'gems', "#{e1.full_name}.gem" diff --git a/test/rubygems/test_gem_dependency_list.rb b/test/rubygems/test_gem_dependency_list.rb index d03a8fdfea..0533a5f342 100644 --- a/test/rubygems/test_gem_dependency_list.rb +++ b/test/rubygems/test_gem_dependency_list.rb @@ -11,7 +11,7 @@ class TestGemDependencyList < Gem::TestCase @deplist = Gem::DependencyList.new - # TODO: switch to new_spec + # TODO: switch to util_spec @a1 = util_spec 'a', '1' @a2 = util_spec 'a', '2' @a3 = util_spec 'a', '3' @@ -144,13 +144,13 @@ class TestGemDependencyList < Gem::TestCase end def test_why_not_ok_eh_old_dependency - a = new_spec 'a', '1', + a = util_spec 'a', '1', 'b' => '~> 1.0' - b0 = new_spec 'b', '1.0', + b0 = util_spec 'b', '1.0', 'd' => '>= 0' - b1 = new_spec 'b', '1.1' + b1 = util_spec 'b', '1.1' util_clear_gems diff --git a/test/rubygems/test_gem_ext_builder.rb b/test/rubygems/test_gem_ext_builder.rb index 3dabd3e350..ce04762e84 100644 --- a/test/rubygems/test_gem_ext_builder.rb +++ b/test/rubygems/test_gem_ext_builder.rb @@ -50,15 +50,9 @@ install: results = results.join "\n" - if RUBY_VERSION > '2.0' then - assert_match %r%"DESTDIR=#{ENV['DESTDIR']}" clean$%, results - assert_match %r%"DESTDIR=#{ENV['DESTDIR']}"$%, results - assert_match %r%"DESTDIR=#{ENV['DESTDIR']}" install$%, results - else - refute_match %r%"DESTDIR=#{ENV['DESTDIR']}" clean$%, results - refute_match %r%"DESTDIR=#{ENV['DESTDIR']}"$%, results - refute_match %r%"DESTDIR=#{ENV['DESTDIR']}" install$%, results - end + assert_match %r%"DESTDIR=#{ENV['DESTDIR']}" clean$%, results + assert_match %r%"DESTDIR=#{ENV['DESTDIR']}"$%, results + assert_match %r%"DESTDIR=#{ENV['DESTDIR']}" install$%, results if /nmake/ !~ results assert_match %r%^clean: destination$%, results @@ -87,15 +81,9 @@ install: results = results.join "\n" - if RUBY_VERSION > '2.0' then - assert_match %r%"DESTDIR=#{ENV['DESTDIR']}" clean$%, results - assert_match %r%"DESTDIR=#{ENV['DESTDIR']}"$%, results - assert_match %r%"DESTDIR=#{ENV['DESTDIR']}" install$%, results - else - refute_match %r%"DESTDIR=#{ENV['DESTDIR']}" clean$%, results - refute_match %r%"DESTDIR=#{ENV['DESTDIR']}"$%, results - refute_match %r%"DESTDIR=#{ENV['DESTDIR']}" install$%, results - end + assert_match %r%"DESTDIR=#{ENV['DESTDIR']}" clean$%, results + assert_match %r%"DESTDIR=#{ENV['DESTDIR']}"$%, results + assert_match %r%"DESTDIR=#{ENV['DESTDIR']}" install$%, results end def test_build_extensions @@ -134,11 +122,6 @@ install: end def test_build_extensions_with_gemhome_with_space - # Details: https://github.com/rubygems/rubygems/issues/977#issuecomment-171544940 - if win_platform? && RUBY_VERSION <= '2.0' - skip 'gemhome with spaces does not work with Ruby 1.9.x on Windows' - end - new_gemhome = File.join @tempdir, 'gem home' File.rename(@gemhome, new_gemhome) @gemhome = new_gemhome @@ -227,6 +210,8 @@ install: end def test_build_extensions_extconf_bad + cwd = Dir.pwd + @spec.extensions << 'extconf.rb' FileUtils.mkdir_p @spec.gem_dir @@ -257,6 +242,8 @@ install: assert_match %r%#{Regexp.escape Gem.ruby}: No such file%, File.read(gem_make_out) + + assert_equal cwd, Dir.pwd end def test_build_extensions_unsupported diff --git a/test/rubygems/test_gem_ext_cmake_builder.rb b/test/rubygems/test_gem_ext_cmake_builder.rb index 2093c7da55..76d3cb2afe 100644 --- a/test/rubygems/test_gem_ext_cmake_builder.rb +++ b/test/rubygems/test_gem_ext_cmake_builder.rb @@ -34,7 +34,7 @@ install (FILES test.txt DESTINATION bin) output = [] Dir.chdir @ext do - Gem::Ext::CmakeBuilder.build nil, nil, @dest_path, output + Gem::Ext::CmakeBuilder.build nil, @dest_path, output end output = output.join "\n" @@ -52,7 +52,7 @@ install (FILES test.txt DESTINATION bin) error = assert_raises Gem::InstallError do Dir.chdir @ext do - Gem::Ext::CmakeBuilder.build nil, nil, @dest_path, output + Gem::Ext::CmakeBuilder.build nil, @dest_path, output end end @@ -75,7 +75,7 @@ install (FILES test.txt DESTINATION bin) output = [] Dir.chdir @ext do - Gem::Ext::CmakeBuilder.build nil, nil, @dest_path, output + Gem::Ext::CmakeBuilder.build nil, @dest_path, output end output = output.join "\n" diff --git a/test/rubygems/test_gem_ext_configure_builder.rb b/test/rubygems/test_gem_ext_configure_builder.rb index cf7559d56c..967458170b 100644 --- a/test/rubygems/test_gem_ext_configure_builder.rb +++ b/test/rubygems/test_gem_ext_configure_builder.rb @@ -27,7 +27,7 @@ class TestGemExtConfigureBuilder < Gem::TestCase output = [] Dir.chdir @ext do - Gem::Ext::ConfigureBuilder.build nil, nil, @dest_path, output + Gem::Ext::ConfigureBuilder.build nil, @dest_path, output end assert_match(/^current directory:/, output.shift) @@ -50,7 +50,7 @@ class TestGemExtConfigureBuilder < Gem::TestCase error = assert_raises Gem::InstallError do Dir.chdir @ext do - Gem::Ext::ConfigureBuilder.build nil, nil, @dest_path, output + Gem::Ext::ConfigureBuilder.build nil, @dest_path, output end end @@ -76,7 +76,7 @@ class TestGemExtConfigureBuilder < Gem::TestCase output = [] Dir.chdir @ext do - Gem::Ext::ConfigureBuilder.build nil, nil, @dest_path, output + Gem::Ext::ConfigureBuilder.build nil, @dest_path, output end assert_contains_make_command 'clean', output[1] diff --git a/test/rubygems/test_gem_ext_ext_conf_builder.rb b/test/rubygems/test_gem_ext_ext_conf_builder.rb index b43ebf00d9..8d5135e309 100644 --- a/test/rubygems/test_gem_ext_ext_conf_builder.rb +++ b/test/rubygems/test_gem_ext_ext_conf_builder.rb @@ -29,7 +29,7 @@ class TestGemExtExtConfBuilder < Gem::TestCase Dir.chdir @ext do result = - Gem::Ext::ExtConfBuilder.build 'extconf.rb', nil, @dest_path, output + Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output assert_same result, output end @@ -54,7 +54,7 @@ class TestGemExtExtConfBuilder < Gem::TestCase output = [] Dir.chdir @ext do - Gem::Ext::ExtConfBuilder.build 'extconf.rb', nil, @dest_path, output + Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output end assert_equal "creating Makefile\n", output[2] @@ -77,7 +77,7 @@ class TestGemExtExtConfBuilder < Gem::TestCase assert_raises Gem::InstallError do Dir.chdir @ext do - Gem::Ext::ExtConfBuilder.build 'extconf.rb', nil, @dest_path, output + Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output end end @@ -103,7 +103,7 @@ class TestGemExtExtConfBuilder < Gem::TestCase error = assert_raises Gem::InstallError do Dir.chdir @ext do - Gem::Ext::ExtConfBuilder.build 'extconf.rb', nil, @dest_path, output + Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output end end @@ -130,7 +130,7 @@ class TestGemExtExtConfBuilder < Gem::TestCase output = [] Dir.chdir @ext do - Gem::Ext::ExtConfBuilder.build 'extconf.rb', nil, @dest_path, output + Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output end refute_includes(output, "To see why this extension failed to compile, please check the mkmf.log which can be found here:\n") @@ -172,7 +172,7 @@ end output = [] Dir.chdir @ext do - Gem::Ext::ExtConfBuilder.build 'extconf.rb', nil, @dest_path, output + Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output end assert_contains_make_command 'clean', output[4] @@ -231,4 +231,3 @@ end end end - diff --git a/test/rubygems/test_gem_ext_rake_builder.rb b/test/rubygems/test_gem_ext_rake_builder.rb index 3229982778..6141f9bc59 100644 --- a/test/rubygems/test_gem_ext_rake_builder.rb +++ b/test/rubygems/test_gem_ext_rake_builder.rb @@ -16,12 +16,10 @@ class TestGemExtRakeBuilder < Gem::TestCase def test_class_build create_temp_mkrf_file('task :default') output = [] - realdir = nil # HACK /tmp vs. /private/tmp build_rake_in do |rake| Dir.chdir @ext do - realdir = Dir.pwd - Gem::Ext::RakeBuilder.build 'mkrf_conf.rb', nil, @dest_path, output + Gem::Ext::RakeBuilder.build 'mkrf_conf.rb', @dest_path, output end output = output.join "\n" @@ -38,13 +36,11 @@ class TestGemExtRakeBuilder < Gem::TestCase def test_class_build_with_args create_temp_mkrf_file('task :default') output = [] - realdir = nil # HACK /tmp vs. /private/tmp build_rake_in do |rake| Dir.chdir @ext do - realdir = Dir.pwd non_empty_args_list = [''] - Gem::Ext::RakeBuilder.build 'mkrf_conf.rb', nil, @dest_path, output, non_empty_args_list + Gem::Ext::RakeBuilder.build 'mkrf_conf.rb', @dest_path, output, non_empty_args_list end output = output.join "\n" @@ -62,7 +58,7 @@ class TestGemExtRakeBuilder < Gem::TestCase build_rake_in(false) do |rake| error = assert_raises Gem::InstallError do Dir.chdir @ext do - Gem::Ext::RakeBuilder.build "mkrf_conf.rb", nil, @dest_path, output + Gem::Ext::RakeBuilder.build "mkrf_conf.rb", @dest_path, output end end diff --git a/test/rubygems/test_gem_gemcutter_utilities.rb b/test/rubygems/test_gem_gemcutter_utilities.rb index 286d59a787..7b3e273957 100644 --- a/test/rubygems/test_gem_gemcutter_utilities.rb +++ b/test/rubygems/test_gem_gemcutter_utilities.rb @@ -8,6 +8,8 @@ class TestGemGemcutterUtilities < Gem::TestCase def setup super + # below needed for random testing, class property + Gem.configuration.disable_default_gem_server = nil ENV['RUBYGEMS_HOST'] = nil Gem.configuration.rubygems_api_key = nil diff --git a/test/rubygems/test_gem_installer.rb b/test/rubygems/test_gem_installer.rb index 93b0482407..062d366665 100644 --- a/test/rubygems/test_gem_installer.rb +++ b/test/rubygems/test_gem_installer.rb @@ -21,7 +21,7 @@ class TestGemInstaller < Gem::InstallerTestCase super common_installer_setup - if __name__ =~ /^test_install(_|$)/ then + if (self.class.method_defined?(:__name__) ? __name__ : name) =~ /\Atest_install(_|\Z)/ FileUtils.rm_r @spec.gem_dir FileUtils.rm_r @user_spec.gem_dir end @@ -34,7 +34,7 @@ class TestGemInstaller < Gem::InstallerTestCase super - Gem.configuration = @config + Gem.configuration = instance_variable_defined?(:@config) ? @config : nil end def test_app_script_text @@ -55,7 +55,7 @@ version = \">= 0.a\" if ARGV.first str = ARGV.first - str = str.dup.force_encoding("BINARY") if str.respond_to? :force_encoding + str = str.dup.force_encoding("BINARY") if str =~ /\\A_(.*)_\\z/ and Gem::Version.correct?($1) then version = $1 ARGV.shift @@ -663,7 +663,7 @@ gem 'other', version assert_path_exists installed_exec if symlink_supported? - assert_send([File, :symlink?, installed_exec]) + assert File.symlink?(installed_exec) return end @@ -890,8 +890,6 @@ gem 'other', version end def test_install_creates_binstub_that_dont_trust_encoding - skip unless "".respond_to?(:force_encoding) - Dir.mkdir util_inst_bindir util_setup_gem util_clear_gems @@ -1179,88 +1177,47 @@ gem 'other', version refute_path_exists File.join expected_extension_dir, 'gem_make.out' end - # ruby core repository needs to `depend` file for extension build. - # but 1.9.2 and earlier mkmf.rb does not create TOUCH file like depend. - if RUBY_VERSION < '1.9.3' - def test_find_lib_file_after_install + def test_find_lib_file_after_install + @spec.extensions << "extconf.rb" + write_file File.join(@tempdir, "extconf.rb") do |io| + io.write <<-RUBY + require "mkmf" - @spec.extensions << "extconf.rb" - write_file File.join(@tempdir, "extconf.rb") do |io| - io.write <<-RUBY - require "mkmf" - create_makefile("#{@spec.name}") - RUBY - end + CONFIG['CC'] = '$(TOUCH) $@ ||' + CONFIG['LDSHARED'] = '$(TOUCH) $@ ||' + $ruby = '#{Gem.ruby}' - write_file File.join(@tempdir, "a.c") do |io| - io.write <<-C - #include - void Init_a() { } - C - end - - Dir.mkdir File.join(@tempdir, "lib") - write_file File.join(@tempdir, 'lib', "b.rb") do |io| - io.write "# b.rb" - end - - @spec.files += %w[extconf.rb lib/b.rb a.c] - - use_ui @ui do - path = Gem::Package.build @spec - - installer = Gem::Installer.at path - installer.install - end - - expected = File.join @spec.full_require_paths.find { |path| - File.exist? File.join path, 'b.rb' - }, 'b.rb' - assert_equal expected, @spec.matches_for_glob('b.rb').first + create_makefile("#{@spec.name}") + RUBY end - else - def test_find_lib_file_after_install - @spec.extensions << "extconf.rb" - write_file File.join(@tempdir, "extconf.rb") do |io| - io.write <<-RUBY - require "mkmf" - CONFIG['CC'] = '$(TOUCH) $@ ||' - CONFIG['LDSHARED'] = '$(TOUCH) $@ ||' - $ruby = '#{Gem.ruby}' + write_file File.join(@tempdir, "depend") - create_makefile("#{@spec.name}") - RUBY - end - - write_file File.join(@tempdir, "depend") - - write_file File.join(@tempdir, "a.c") do |io| - io.write <<-C - #include - void Init_a() { } - C - end - - Dir.mkdir File.join(@tempdir, "lib") - write_file File.join(@tempdir, 'lib', "b.rb") do |io| - io.write "# b.rb" - end - - @spec.files += %w[extconf.rb lib/b.rb depend a.c] - - use_ui @ui do - path = Gem::Package.build @spec - - installer = Gem::Installer.at path - installer.install - end - - expected = File.join @spec.full_require_paths.find { |path| - File.exist? File.join path, 'b.rb' - }, 'b.rb' - assert_equal expected, @spec.matches_for_glob('b.rb').first + write_file File.join(@tempdir, "a.c") do |io| + io.write <<-C + #include + void Init_a() { } + C end + + Dir.mkdir File.join(@tempdir, "lib") + write_file File.join(@tempdir, 'lib', "b.rb") do |io| + io.write "# b.rb" + end + + @spec.files += %w[extconf.rb lib/b.rb depend a.c] + + use_ui @ui do + path = Gem::Package.build @spec + + installer = Gem::Installer.at path + installer.install + end + + expected = File.join @spec.full_require_paths.find { |path| + File.exist? File.join path, 'b.rb' + }, 'b.rb' + assert_equal expected, @spec.matches_for_glob('b.rb').first end def test_install_extension_and_script @@ -1302,13 +1259,6 @@ gem 'other', version end def test_install_extension_flat - skip '1.9.2 and earlier mkmf.rb does not create TOUCH' if - RUBY_VERSION < '1.9.3' - - if RUBY_VERSION == "1.9.3" and RUBY_PATCHLEVEL <= 194 - skip "TOUCH was introduced into 1.9.3 after p194" - end - @spec.require_paths = ["."] @spec.extensions << "extconf.rb" diff --git a/test/rubygems/test_gem_local_remote_options.rb b/test/rubygems/test_gem_local_remote_options.rb index 272623be74..a51182b11c 100644 --- a/test/rubygems/test_gem_local_remote_options.rb +++ b/test/rubygems/test_gem_local_remote_options.rb @@ -44,8 +44,9 @@ class TestGemLocalRemoteOptions < Gem::TestCase spec_fetcher @cmd.add_local_remote_options + Gem.configuration.sources = nil @cmd.handle_options %W[--clear-sources] - assert_equal Gem.default_sources, Gem.sources + assert_equal Gem.default_sources, Gem.sources.to_a end def test_local_eh @@ -123,7 +124,7 @@ class TestGemLocalRemoteOptions < Gem::TestCase s1 = 'htp://more-gems.example.com' - assert_raises OptionParser::InvalidArgument do + assert_raises ArgumentError do @cmd.handle_options %W[--source #{s1}] end diff --git a/test/rubygems/test_gem_package.rb b/test/rubygems/test_gem_package.rb index f8eb245f26..09ef27ee22 100644 --- a/test/rubygems/test_gem_package.rb +++ b/test/rubygems/test_gem_package.rb @@ -104,6 +104,22 @@ class TestGemPackage < Gem::Package::TarTestCase assert_equal expected, YAML.load(checksums) end + def test_build_time_source_date_epoch + ENV["SOURCE_DATE_EPOCH"] = "123456789" + + spec = Gem::Specification.new 'build', '1' + spec.summary = 'build' + spec.authors = 'build' + spec.files = ['lib/code.rb'] + spec.date = Time.at 0 + spec.rubygems_version = Gem::Version.new '0' + + + package = Gem::Package.new spec.file_name + + assert_equal Time.at(ENV["SOURCE_DATE_EPOCH"].to_i).utc, package.build_time + end + def test_add_files spec = Gem::Specification.new spec.files = %w[lib/code.rb lib/empty] @@ -579,7 +595,6 @@ class TestGemPackage < Gem::Package::TarTestCase end def test_install_location_extra_slash - skip 'no File.realpath on 1.8' if RUBY_VERSION < '1.9' package = Gem::Package.new @gem file = 'foo//file.rb'.dup @@ -752,7 +767,7 @@ class TestGemPackage < Gem::Package::TarTestCase e.message io end - tf.close! if tf.respond_to? :close! + tf.close! end def test_verify_empty diff --git a/test/rubygems/test_gem_package_tar_header.rb b/test/rubygems/test_gem_package_tar_header.rb index f804b2d808..2dbfffa14c 100644 --- a/test/rubygems/test_gem_package_tar_header.rb +++ b/test/rubygems/test_gem_package_tar_header.rb @@ -160,7 +160,7 @@ group\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000 assert_raises ArgumentError do Gem::Package::TarHeader.from io end - io.close! if io.respond_to? :close! + io.close! end end diff --git a/test/rubygems/test_gem_package_tar_writer.rb b/test/rubygems/test_gem_package_tar_writer.rb index bed1e3b221..2808d87718 100644 --- a/test/rubygems/test_gem_package_tar_writer.rb +++ b/test/rubygems/test_gem_package_tar_writer.rb @@ -31,6 +31,16 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase assert_equal 1024, @io.pos end + def test_add_file_source_date_epoch + ENV["SOURCE_DATE_EPOCH"] = "123456789" + Time.stub :now, Time.at(1458518157) do + @tar_writer.mkdir 'foo', 0644 + + assert_headers_equal tar_dir_header('foo', '', 0644, Time.at(ENV["SOURCE_DATE_EPOCH"].to_i).utc), + @io.string[0, 512] + end + end + def test_add_symlink Time.stub :now, Time.at(1458518157) do @tar_writer.add_symlink 'x', 'y', 0644 @@ -41,6 +51,16 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase assert_equal 512, @io.pos end + def test_add_symlink_source_date_epoch + ENV["SOURCE_DATE_EPOCH"] = "123456789" + Time.stub :now, Time.at(1458518157) do + @tar_writer.add_symlink 'x', 'y', 0644 + + assert_headers_equal(tar_symlink_header('x', '', 0644, Time.at(ENV["SOURCE_DATE_EPOCH"].to_i).utc, 'y'), + @io.string[0, 512]) + end + end + def test_add_file_digest digest_algorithms = Digest::SHA1, Digest::SHA512 @@ -148,6 +168,16 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase assert_equal 1024, @io.pos end + def test_add_file_simple_source_date_epoch + ENV["SOURCE_DATE_EPOCH"] = "123456789" + Time.stub :now, Time.at(1458518157) do + @tar_writer.add_file_simple 'x', 0644, 10 do |io| io.write "a" * 10 end + + assert_headers_equal(tar_file_header('x', '', 0644, 10, Time.at(ENV["SOURCE_DATE_EPOCH"].to_i).utc), + @io.string[0, 512]) + end + end + def test_add_file_simple_padding Time.stub :now, Time.at(1458518157) do @tar_writer.add_file_simple 'x', 0, 100 @@ -175,12 +205,6 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase end end - def test_add_file_unseekable - assert_raises Gem::Package::NonSeekableIO do - Gem::Package::TarWriter.new(Object.new).add_file 'x', 0 - end - end - def test_close @tar_writer.close @@ -223,6 +247,16 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase end end + def test_mkdir_source_date_epoch + ENV["SOURCE_DATE_EPOCH"] = "123456789" + Time.stub :now, Time.at(1458518157) do + @tar_writer.mkdir 'foo', 0644 + + assert_headers_equal tar_dir_header('foo', '', 0644, Time.at(ENV["SOURCE_DATE_EPOCH"].to_i).utc), + @io.string[0, 512] + end + end + def test_split_name assert_equal ['b' * 100, 'a' * 155], @tar_writer.split_name("#{'a' * 155}/#{'b' * 100}") diff --git a/test/rubygems/test_gem_path_support.rb b/test/rubygems/test_gem_path_support.rb index 754c43e893..ccb46d6b8e 100644 --- a/test/rubygems/test_gem_path_support.rb +++ b/test/rubygems/test_gem_path_support.rb @@ -29,7 +29,7 @@ class TestGemPathSupport < Gem::TestCase assert_equal expected, ps.path end - if defined?(File::ALT_SEPARATOR) and File::ALT_SEPARATOR + if File::ALT_SEPARATOR def test_initialize_home_normalize alternate = @tempdir.gsub(File::SEPARATOR, File::ALT_SEPARATOR) ps = Gem::PathSupport.new "GEM_HOME" => alternate diff --git a/test/rubygems/test_gem_remote_fetcher.rb b/test/rubygems/test_gem_remote_fetcher.rb index c48a5f538f..884d26a3c7 100644 --- a/test/rubygems/test_gem_remote_fetcher.rb +++ b/test/rubygems/test_gem_remote_fetcher.rb @@ -118,7 +118,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== @a1.loaded_from = File.join(@gemhome, 'specifications', @a1.full_name) Gem::RemoteFetcher.fetcher = nil - + @stub_ui = Gem::MockGemUi.new @fetcher = Gem::RemoteFetcher.fetcher end @@ -175,7 +175,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== end def test_no_proxy - use_ui @ui do + use_ui @stub_ui do assert_data_from_server @fetcher.fetch_path(@server_uri) assert_equal SERVER_DATA.size, @fetcher.fetch_size(@server_uri) end @@ -267,7 +267,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== fetch = Gem::RemoteFetcher.new nil, dns begin old_verbose, Gem.configuration.verbose = Gem.configuration.verbose, 1 - endpoint = use_ui @ui do + endpoint = use_ui @stub_ui do fetch.api_endpoint(uri) end ensure @@ -276,7 +276,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== assert_equal uri, endpoint - assert_equal "Getting SRV record failed: timeout!\n", @ui.output + assert_equal "Getting SRV record failed: timeout!\n", @stub_ui.output dns.verify end @@ -625,7 +625,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== end def test_implicit_no_proxy - use_ui @ui do + use_ui @stub_ui do ENV['http_proxy'] = 'http://fakeurl:12345' fetcher = Gem::RemoteFetcher.new :no_proxy @fetcher = fetcher @@ -634,7 +634,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== end def test_implicit_proxy - use_ui @ui do + use_ui @stub_ui do ENV['http_proxy'] = @proxy_uri fetcher = Gem::RemoteFetcher.new nil @fetcher = fetcher @@ -643,7 +643,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== end def test_implicit_upper_case_proxy - use_ui @ui do + use_ui @stub_ui do ENV['HTTP_PROXY'] = @proxy_uri fetcher = Gem::RemoteFetcher.new nil @fetcher = fetcher @@ -652,7 +652,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== end def test_implicit_proxy_no_env - use_ui @ui do + use_ui @stub_ui do fetcher = Gem::RemoteFetcher.new nil @fetcher = fetcher assert_data_from_server fetcher.fetch_path(@server_uri) @@ -764,7 +764,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== end def test_observe_no_proxy_env_single_host - use_ui @ui do + use_ui @stub_ui do ENV["http_proxy"] = @proxy_uri ENV["no_proxy"] = URI::parse(@server_uri).host fetcher = Gem::RemoteFetcher.new nil @@ -774,7 +774,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== end def test_observe_no_proxy_env_list - use_ui @ui do + use_ui @stub_ui do ENV["http_proxy"] = @proxy_uri ENV["no_proxy"] = "fakeurl.com, #{URI::parse(@server_uri).host}" fetcher = Gem::RemoteFetcher.new nil @@ -796,7 +796,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg== end def test_yaml_error_on_size - use_ui @ui do + use_ui @stub_ui do self.class.enable_yaml = false fetcher = Gem::RemoteFetcher.new nil @fetcher = fetcher diff --git a/test/rubygems/test_gem_request_connection_pools.rb b/test/rubygems/test_gem_request_connection_pools.rb index a087095a53..ecd1e9861f 100644 --- a/test/rubygems/test_gem_request_connection_pools.rb +++ b/test/rubygems/test_gem_request_connection_pools.rb @@ -25,6 +25,28 @@ class TestGemRequestConnectionPool < Gem::TestCase super end + def test_to_proxy_substring + pools = Gem::Request::ConnectionPools.new nil, [] + + env_no_proxy = %w[ + ems.example + ] + + no_proxy = pools.send :no_proxy?, 'rubygems.example', env_no_proxy + + refute no_proxy, 'mismatch' + end + + def test_to_proxy_empty_string + pools = Gem::Request::ConnectionPools.new nil, [] + + env_no_proxy = [""] + + no_proxy = pools.send :no_proxy?, 'ems.example', env_no_proxy + + refute no_proxy, 'mismatch' + end + def test_checkout_same_connection uri = URI.parse('http://example/some_endpoint') @@ -86,8 +108,7 @@ class TestGemRequestConnectionPool < Gem::TestCase net_http_args = pools.send :net_http_args, URI('http://[::1]'), nil - expected_host = RUBY_VERSION >= "1.9.3" ? "::1" : "[::1]" - assert_equal [expected_host, 80], net_http_args + assert_equal ["::1", 80], net_http_args end def test_net_http_args_proxy diff --git a/test/rubygems/test_gem_request_set.rb b/test/rubygems/test_gem_request_set.rb index 5dc6c1518d..86986f2287 100644 --- a/test/rubygems/test_gem_request_set.rb +++ b/test/rubygems/test_gem_request_set.rb @@ -218,7 +218,7 @@ ruby "0" assert_kind_of Gem::RequestSet::GemDependencyAPI, gem_deps io end - tf.close! if tf.respond_to? :close! + tf.close! assert_equal [dep('a')], rs.dependencies @@ -239,7 +239,7 @@ ruby "0" assert_kind_of Gem::RequestSet::GemDependencyAPI, gem_deps io end - tf.close! if tf.respond_to? :close! + tf.close! assert_equal [dep('a')], rs.dependencies end @@ -254,7 +254,7 @@ ruby "0" rs.load_gemdeps io.path, [:test] io end - tf.close! if tf.respond_to? :close! + tf.close! assert_empty rs.dependencies end @@ -346,7 +346,7 @@ ruby "0" rs.load_gemdeps io.path io end - tf.close! if tf.respond_to? :close! + tf.close! res = rs.resolve assert_equal 1, res.size @@ -410,7 +410,7 @@ ruby "0" rs.load_gemdeps io.path io end - tf.close! if tf.respond_to? :close! + tf.close! res = rs.resolve assert_equal 2, res.size diff --git a/test/rubygems/test_gem_request_set_gem_dependency_api.rb b/test/rubygems/test_gem_request_set_gem_dependency_api.rb index e8bb1d4a6d..71a095b07f 100644 --- a/test/rubygems/test_gem_request_set_gem_dependency_api.rb +++ b/test/rubygems/test_gem_request_set_gem_dependency_api.rb @@ -627,11 +627,7 @@ end assert_equal [dep('a'), dep('b')], @set.dependencies io end - tf.close! if tf.respond_to? :close! - end - - def test_name_typo - assert_same @GDA, Gem::RequestSet::GemDepedencyAPI + tf.close! end def test_pin_gem_source diff --git a/test/rubygems/test_gem_request_set_lockfile_parser.rb b/test/rubygems/test_gem_request_set_lockfile_parser.rb index f3517da43a..296cf5f4a0 100644 --- a/test/rubygems/test_gem_request_set_lockfile_parser.rb +++ b/test/rubygems/test_gem_request_set_lockfile_parser.rb @@ -248,13 +248,8 @@ DEPENDENCIES assert_equal %w[a-2], lockfile_set.specs.map { |s| s.full_name } - if [].respond_to? :flat_map - assert_equal %w[https://gems.example/ https://other.example/], - lockfile_set.specs.flat_map { |s| s.sources.map{ |src| src.uri.to_s } } - else # FIXME: remove when 1.8 is dropped - assert_equal %w[https://gems.example/ https://other.example/], - lockfile_set.specs.map { |s| s.sources.map{ |src| src.uri.to_s } }.flatten(1) - end + assert_equal %w[https://gems.example/ https://other.example/], + lockfile_set.specs.flat_map { |s| s.sources.map{ |src| src.uri.to_s } } end def test_parse_GIT diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index ea354f7b1d..7bca00e58b 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -28,6 +28,8 @@ class TestGemRequirement < Gem::TestCase assert_requirement_equal "= 2", "2" assert_requirement_equal "= 2", ["2"] assert_requirement_equal "= 2", v(2) + assert_requirement_equal "2.0", "2" + assert_requirement_equal ["= 2", ">= 2"], [">= 2", "= 2"] end def test_create @@ -69,6 +71,7 @@ class TestGemRequirement < Gem::TestCase assert_equal ['=', Gem::Version.new(1)], Gem::Requirement.parse('= 1') assert_equal ['>', Gem::Version.new(1)], Gem::Requirement.parse('> 1') assert_equal ['=', Gem::Version.new(1)], Gem::Requirement.parse("=\n1") + assert_equal ['=', Gem::Version.new(1)], Gem::Requirement.parse('1.0') assert_equal ['=', Gem::Version.new(2)], Gem::Requirement.parse(Gem::Version.new('2')) @@ -226,6 +229,8 @@ class TestGemRequirement < Gem::TestCase assert_satisfied_by "0.2.33", "= 0.2.33" assert_satisfied_by "0.2.34", "> 0.2.33" assert_satisfied_by "1.0", "= 1.0" + assert_satisfied_by "1.0.0", "= 1.0" + assert_satisfied_by "1.0", "= 1.0.0" assert_satisfied_by "1.0", "1.0" assert_satisfied_by "1.8.2", "> 1.8.0" assert_satisfied_by "1.112", "> 1.111" @@ -313,6 +318,7 @@ class TestGemRequirement < Gem::TestCase def test_satisfied_by_boxed refute_satisfied_by "1.3", "~> 1.4" assert_satisfied_by "1.4", "~> 1.4" + assert_satisfied_by "1.4.0", "~> 1.4" assert_satisfied_by "1.5", "~> 1.4" refute_satisfied_by "2.0", "~> 1.4" @@ -324,6 +330,20 @@ class TestGemRequirement < Gem::TestCase refute_satisfied_by "2.0", "~> 1.4.4" end + def test_satisfied_by_explicitly_bounded + req = [">= 1.4.4", "< 1.5"] + + assert_satisfied_by "1.4.5", req + assert_satisfied_by "1.5.0.rc1", req + refute_satisfied_by "1.5.0", req + + req = [">= 1.4.4", "< 1.5.a"] + + assert_satisfied_by "1.4.5", req + refute_satisfied_by "1.5.0.rc1", req + refute_satisfied_by "1.5.0", req + end + def test_specific refute req('> 1') .specific? refute req('>= 1').specific? diff --git a/test/rubygems/test_gem_resolver.rb b/test/rubygems/test_gem_resolver.rb index 417f0580f7..b083622da4 100644 --- a/test/rubygems/test_gem_resolver.rb +++ b/test/rubygems/test_gem_resolver.rb @@ -36,10 +36,6 @@ class TestGemResolver < Gem::TestCase flunk e.message end - def test_self_compatibility - assert_same Gem::Resolver, Gem::DependencyResolver - end - def test_self_compose_sets_best_set best_set = @DR::BestSet.new @@ -666,12 +662,12 @@ class TestGemResolver < Gem::TestCase end def test_second_level_backout - b1 = new_spec "b", "1", { "c" => ">= 1" }, "lib/b.rb" - b2 = new_spec "b", "2", { "c" => ">= 2" }, "lib/b.rb" - c1 = new_spec "c", "1" - c2 = new_spec "c", "2" - d1 = new_spec "d", "1", { "c" => "< 2" }, "lib/d.rb" - d2 = new_spec "d", "2", { "c" => "< 2" }, "lib/d.rb" + b1 = util_spec "b", "1", { "c" => ">= 1" }, "lib/b.rb" + b2 = util_spec "b", "2", { "c" => ">= 2" }, "lib/b.rb" + c1 = util_spec "c", "1" + c2 = util_spec "c", "2" + d1 = util_spec "d", "1", { "c" => "< 2" }, "lib/d.rb" + d2 = util_spec "d", "2", { "c" => "< 2" }, "lib/d.rb" s = set(b1, b2, c1, c2, d1, d2) @@ -688,11 +684,11 @@ class TestGemResolver < Gem::TestCase sourceB = Gem::Source.new 'http://example.com/b' sourceC = Gem::Source.new 'http://example.com/c' - spec_A_1 = new_spec 'some-dep', '0.0.1' - spec_A_2 = new_spec 'some-dep', '1.0.0' - spec_B_1 = new_spec 'some-dep', '0.0.1' - spec_B_2 = new_spec 'some-dep', '0.0.2' - spec_C_1 = new_spec 'some-dep', '0.1.0' + spec_A_1 = util_spec 'some-dep', '0.0.1' + spec_A_2 = util_spec 'some-dep', '1.0.0' + spec_B_1 = util_spec 'some-dep', '0.0.1' + spec_B_2 = util_spec 'some-dep', '0.0.2' + spec_C_1 = util_spec 'some-dep', '0.1.0' set = StaticSet.new [ Gem::Resolver::SpecSpecification.new(nil, spec_B_1, sourceB), diff --git a/test/rubygems/test_gem_resolver_api_specification.rb b/test/rubygems/test_gem_resolver_api_specification.rb index 4f198ea395..8c17d42386 100644 --- a/test/rubygems/test_gem_resolver_api_specification.rb +++ b/test/rubygems/test_gem_resolver_api_specification.rb @@ -141,5 +141,29 @@ class TestGemResolverAPISpecification < Gem::TestCase assert_equal 'a-1', spec.full_name end + def test_spec_jruby_platform + spec_fetcher do |fetcher| + fetcher.gem 'j', 1 do |spec| + spec.platform = 'jruby' + end + end + + dep_uri = URI(@gem_repo) + 'api/v1/dependencies' + set = Gem::Resolver::APISet.new dep_uri + data = { + :name => 'j', + :number => '1', + :platform => 'jruby', + :dependencies => [], + } + + api_spec = Gem::Resolver::APISpecification.new set, data + + spec = api_spec.spec + + assert_kind_of Gem::Specification, spec + assert_equal 'j-1-java', spec.full_name + end + end diff --git a/test/rubygems/test_gem_resolver_installer_set.rb b/test/rubygems/test_gem_resolver_installer_set.rb index e8d82d93b7..9644e0a7a9 100644 --- a/test/rubygems/test_gem_resolver_installer_set.rb +++ b/test/rubygems/test_gem_resolver_installer_set.rb @@ -25,8 +25,8 @@ class TestGemResolverInstallerSet < Gem::TestCase end def test_add_always_install_errors - @fetcher = Gem::FakeFetcher.new - Gem::RemoteFetcher.fetcher = @fetcher + @stub_fetcher = Gem::FakeFetcher.new + Gem::RemoteFetcher.fetcher = @stub_fetcher set = Gem::Resolver::InstallerSet.new :both @@ -197,7 +197,7 @@ class TestGemResolverInstallerSet < Gem::TestCase def (set.remote_set).prefetch(_) raise "called" end - assert_equal nil, set.prefetch(nil) + assert_nil set.prefetch(nil) end def test_prerelease_equals diff --git a/test/rubygems/test_gem_security.rb b/test/rubygems/test_gem_security.rb index 47010e088c..962f858b5b 100644 --- a/test/rubygems/test_gem_security.rb +++ b/test/rubygems/test_gem_security.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require 'rubygems/test_case' require 'rubygems/security' -require 'rubygems/fix_openssl_warnings' if RUBY_VERSION < "1.9" unless defined?(OpenSSL::SSL) then warn 'Skipping Gem::Security tests. openssl not found.' diff --git a/test/rubygems/test_gem_server.rb b/test/rubygems/test_gem_server.rb index 8a3e6410ae..6886ec4858 100644 --- a/test/rubygems/test_gem_server.rb +++ b/test/rubygems/test_gem_server.rb @@ -377,9 +377,9 @@ class TestGemServer < Gem::TestCase assert_equal 200, @res.status assert_match 'xsshomepagegem 1', @res.body - # This verifies that the homepage for this spec is not displayed and is set to ".", because it's not a + # This verifies that the homepage for this spec is not displayed and is set to ".", because it's not a # valid HTTP/HTTPS URL and could be unsafe in an HTML context. We would prefer to throw an exception here, - # but spec.homepage is currently free form and not currently required to be a URL, this behavior may be + # but spec.homepage is currently free form and not currently required to be a URL, this behavior may be # validated in future versions of Gem::Specification. # # There are two variant we're checking here, one where rdoc is not present, and one where rdoc is present in the same regex: @@ -432,9 +432,9 @@ class TestGemServer < Gem::TestCase assert_equal 200, @res.status assert_match 'invalidhomepagegem 1', @res.body - # This verifies that the homepage for this spec is not displayed and is set to ".", because it's not a + # This verifies that the homepage for this spec is not displayed and is set to ".", because it's not a # valid HTTP/HTTPS URL and could be unsafe in an HTML context. We would prefer to throw an exception here, - # but spec.homepage is currently free form and not currently required to be a URL, this behavior may be + # but spec.homepage is currently free form and not currently required to be a URL, this behavior may be # validated in future versions of Gem::Specification. # # There are two variant we're checking here, one where rdoc is not present, and one where rdoc is present in the same regex: diff --git a/test/rubygems/test_gem_specification.rb b/test/rubygems/test_gem_specification.rb index 8a488f87d9..845914d33a 100644 --- a/test/rubygems/test_gem_specification.rb +++ b/test/rubygems/test_gem_specification.rb @@ -101,7 +101,7 @@ end end def test_self_find_active_stub_by_path - spec = new_spec('a', '1', nil, 'lib/foo.rb') + spec = util_spec('a', '1', nil, 'lib/foo.rb') spec.activated = true # There used to be a bug (introduced in a9c1aaf) when Gem::Specification @@ -119,11 +119,11 @@ end def test_self_activate_ambiguous_direct save_loaded_features do - a1 = new_spec "a", "1", "b" => "> 0" - b1 = new_spec("b", "1", { "c" => ">= 1" }, "lib/d.rb") - b2 = new_spec("b", "2", { "c" => ">= 2" }, "lib/d.rb") - c1 = new_spec "c", "1" - c2 = new_spec "c", "2" + a1 = util_spec "a", "1", "b" => "> 0" + b1 = util_spec("b", "1", { "c" => ">= 1" }, "lib/d.rb") + b2 = util_spec("b", "2", { "c" => ">= 2" }, "lib/d.rb") + c1 = util_spec "c", "1" + c2 = util_spec "c", "2" Gem::Specification.reset install_specs c1, c2, b1, b2, a1 @@ -148,10 +148,10 @@ end deps = Hash[((pkgi + 1)..num_of_pkg).map { |deppkgi| ["pkg#{deppkgi}", ">= 0"] }] - new_spec "pkg#{pkgi}", pkg_version.to_s, deps + util_spec "pkg#{pkgi}", pkg_version.to_s, deps end end - base = new_spec "pkg_base", "1", {"pkg0" => ">= 0"} + base = util_spec "pkg_base", "1", {"pkg0" => ">= 0"} Gem::Specification.reset install_specs(*packages.flatten.reverse) @@ -167,11 +167,11 @@ end def test_self_activate_ambiguous_indirect save_loaded_features do - a1 = new_spec "a", "1", "b" => "> 0" - b1 = new_spec "b", "1", "c" => ">= 1" - b2 = new_spec "b", "2", "c" => ">= 2" - c1 = new_spec "c", "1", nil, "lib/d.rb" - c2 = new_spec "c", "2", nil, "lib/d.rb" + a1 = util_spec "a", "1", "b" => "> 0" + b1 = util_spec "b", "1", "c" => ">= 1" + b2 = util_spec "b", "2", "c" => ">= 2" + c1 = util_spec "c", "1", nil, "lib/d.rb" + c2 = util_spec "c", "2", nil, "lib/d.rb" install_specs c1, c2, b1, b2, a1 @@ -188,12 +188,12 @@ end def test_self_activate_ambiguous_indirect_conflict save_loaded_features do - a1 = new_spec "a", "1", "b" => "> 0" - a2 = new_spec "a", "2", "b" => "> 0" - b1 = new_spec "b", "1", "c" => ">= 1" - b2 = new_spec "b", "2", "c" => ">= 2" - c1 = new_spec "c", "1", nil, "lib/d.rb" - c2 = new_spec("c", "2", { "a" => "1" }, "lib/d.rb") # conflicts with a-2 + a1 = util_spec "a", "1", "b" => "> 0" + a2 = util_spec "a", "2", "b" => "> 0" + b1 = util_spec "b", "1", "c" => ">= 1" + b2 = util_spec "b", "2", "c" => ">= 2" + c1 = util_spec "c", "1", nil, "lib/d.rb" + c2 = util_spec("c", "2", { "a" => "1" }, "lib/d.rb") # conflicts with a-2 install_specs c1, b1, a1, a2, c2, b2 @@ -210,12 +210,12 @@ end def test_self_activate_ambiguous_unrelated save_loaded_features do - a1 = new_spec "a", "1", "b" => "> 0" - b1 = new_spec "b", "1", "c" => ">= 1" - b2 = new_spec "b", "2", "c" => ">= 2" - c1 = new_spec "c", "1" - c2 = new_spec "c", "2" - d1 = new_spec "d", "1", nil, "lib/d.rb" + a1 = util_spec "a", "1", "b" => "> 0" + b1 = util_spec "b", "1", "c" => ">= 1" + b2 = util_spec "b", "2", "c" => ">= 2" + c1 = util_spec "c", "1" + c2 = util_spec "c", "2" + d1 = util_spec "d", "1", nil, "lib/d.rb" install_specs d1, c1, c2, b1, b2, a1 @@ -232,11 +232,11 @@ end def test_require_should_prefer_latest_gem_level1 save_loaded_features do - a1 = new_spec "a", "1", "b" => "> 0" - b1 = new_spec "b", "1", "c" => ">= 0" # unresolved - b2 = new_spec "b", "2", "c" => ">= 0" - c1 = new_spec "c", "1", nil, "lib/c.rb" # 1st level - c2 = new_spec "c", "2", nil, "lib/c.rb" + a1 = util_spec "a", "1", "b" => "> 0" + b1 = util_spec "b", "1", "c" => ">= 0" # unresolved + b2 = util_spec "b", "2", "c" => ">= 0" + c1 = util_spec "c", "1", nil, "lib/c.rb" # 1st level + c2 = util_spec "c", "2", nil, "lib/c.rb" install_specs c1, c2, b1, b2, a1 @@ -250,13 +250,13 @@ end def test_require_should_prefer_latest_gem_level2 save_loaded_features do - a1 = new_spec "a", "1", "b" => "> 0" - b1 = new_spec "b", "1", "c" => ">= 0" # unresolved - b2 = new_spec "b", "2", "c" => ">= 0" - c1 = new_spec "c", "1", "d" => ">= 0" # 1st level - c2 = new_spec "c", "2", "d" => ">= 0" - d1 = new_spec "d", "1", nil, "lib/d.rb" # 2nd level - d2 = new_spec "d", "2", nil, "lib/d.rb" + a1 = util_spec "a", "1", "b" => "> 0" + b1 = util_spec "b", "1", "c" => ">= 0" # unresolved + b2 = util_spec "b", "2", "c" => ">= 0" + c1 = util_spec "c", "1", "d" => ">= 0" # 1st level + c2 = util_spec "c", "2", "d" => ">= 0" + d1 = util_spec "d", "1", nil, "lib/d.rb" # 2nd level + d2 = util_spec "d", "2", nil, "lib/d.rb" install_specs d1, d2, c1, c2, b1, b2, a1 @@ -270,14 +270,14 @@ end def test_require_finds_in_2nd_level_indirect save_loaded_features do - a1 = new_spec "a", "1", "b" => "> 0" - b1 = new_spec "b", "1", "c" => ">= 0" # unresolved - b2 = new_spec "b", "2", "c" => ">= 0" - c1 = new_spec "c", "1", "d" => "<= 2" # 1st level - c2 = new_spec "c", "2", "d" => "<= 2" - d1 = new_spec "d", "1", nil, "lib/d.rb" # 2nd level - d2 = new_spec "d", "2", nil, "lib/d.rb" - d3 = new_spec "d", "3", nil, "lib/d.rb" + a1 = util_spec "a", "1", "b" => "> 0" + b1 = util_spec "b", "1", "c" => ">= 0" # unresolved + b2 = util_spec "b", "2", "c" => ">= 0" + c1 = util_spec "c", "1", "d" => "<= 2" # 1st level + c2 = util_spec "c", "2", "d" => "<= 2" + d1 = util_spec "d", "1", nil, "lib/d.rb" # 2nd level + d2 = util_spec "d", "2", nil, "lib/d.rb" + d3 = util_spec "d", "3", nil, "lib/d.rb" install_specs d1, d2, d3, c1, c2, b1, b2, a1 @@ -291,15 +291,15 @@ end def test_require_should_prefer_reachable_gems save_loaded_features do - a1 = new_spec "a", "1", "b" => "> 0" - b1 = new_spec "b", "1", "c" => ">= 0" # unresolved - b2 = new_spec "b", "2", "c" => ">= 0" - c1 = new_spec "c", "1", "d" => "<= 2" # 1st level - c2 = new_spec "c", "2", "d" => "<= 2" - d1 = new_spec "d", "1", nil, "lib/d.rb" # 2nd level - d2 = new_spec "d", "2", nil, "lib/d.rb" - d3 = new_spec "d", "3", nil, "lib/d.rb" - e = new_spec "anti_d", "1", nil, "lib/d.rb" + a1 = util_spec "a", "1", "b" => "> 0" + b1 = util_spec "b", "1", "c" => ">= 0" # unresolved + b2 = util_spec "b", "2", "c" => ">= 0" + c1 = util_spec "c", "1", "d" => "<= 2" # 1st level + c2 = util_spec "c", "2", "d" => "<= 2" + d1 = util_spec "d", "1", nil, "lib/d.rb" # 2nd level + d2 = util_spec "d", "2", nil, "lib/d.rb" + d3 = util_spec "d", "3", nil, "lib/d.rb" + e = util_spec "anti_d", "1", nil, "lib/d.rb" install_specs d1, d2, d3, e, c1, c2, b1, b2, a1 @@ -313,14 +313,14 @@ end def test_require_should_not_conflict save_loaded_features do - base = new_spec "0", "1", "A" => ">= 1" - a1 = new_spec "A", "1", {"c" => ">= 2", "b" => "> 0"}, "lib/a.rb" - a2 = new_spec "A", "2", {"c" => ">= 2", "b" => "> 0"}, "lib/a.rb" - b1 = new_spec "b", "1", {"c" => "= 1"}, "lib/d.rb" - b2 = new_spec "b", "2", {"c" => "= 2"}, "lib/d.rb" - c1 = new_spec "c", "1", {}, "lib/c.rb" - c2 = new_spec "c", "2", {}, "lib/c.rb" - c3 = new_spec "c", "3", {}, "lib/c.rb" + base = util_spec "0", "1", "A" => ">= 1" + a1 = util_spec "A", "1", {"c" => ">= 2", "b" => "> 0"}, "lib/a.rb" + a2 = util_spec "A", "2", {"c" => ">= 2", "b" => "> 0"}, "lib/a.rb" + b1 = util_spec "b", "1", {"c" => "= 1"}, "lib/d.rb" + b2 = util_spec "b", "2", {"c" => "= 2"}, "lib/d.rb" + c1 = util_spec "c", "1", {}, "lib/c.rb" + c2 = util_spec "c", "2", {}, "lib/c.rb" + c3 = util_spec "c", "3", {}, "lib/c.rb" install_specs c1, c2, c3, b1, b2, a1, a2, base @@ -337,15 +337,15 @@ end def test_inner_clonflict_in_indirect_gems save_loaded_features do - a1 = new_spec "a", "1", "b" => "> 0" - b1 = new_spec "b", "1", "c" => ">= 1" # unresolved - b2 = new_spec "b", "2", "c" => ">= 1", "d" => "< 3" - c1 = new_spec "c", "1", "d" => "<= 2" # 1st level - c2 = new_spec "c", "2", "d" => "<= 2" - c3 = new_spec "c", "3", "d" => "<= 3" - d1 = new_spec "d", "1", nil, "lib/d.rb" # 2nd level - d2 = new_spec "d", "2", nil, "lib/d.rb" - d3 = new_spec "d", "3", nil, "lib/d.rb" + a1 = util_spec "a", "1", "b" => "> 0" + b1 = util_spec "b", "1", "c" => ">= 1" # unresolved + b2 = util_spec "b", "2", "c" => ">= 1", "d" => "< 3" + c1 = util_spec "c", "1", "d" => "<= 2" # 1st level + c2 = util_spec "c", "2", "d" => "<= 2" + c3 = util_spec "c", "3", "d" => "<= 3" + d1 = util_spec "d", "1", nil, "lib/d.rb" # 2nd level + d2 = util_spec "d", "2", nil, "lib/d.rb" + d3 = util_spec "d", "3", nil, "lib/d.rb" install_specs d1, d2, d3, c1, c2, c3, b1, b2, a1 @@ -359,15 +359,15 @@ end def test_inner_clonflict_in_indirect_gems_reversed save_loaded_features do - a1 = new_spec "a", "1", "b" => "> 0" - b1 = new_spec "b", "1", "xc" => ">= 1" # unresolved - b2 = new_spec "b", "2", "xc" => ">= 1", "d" => "< 3" - c1 = new_spec "xc", "1", "d" => "<= 3" # 1st level - c2 = new_spec "xc", "2", "d" => "<= 2" - c3 = new_spec "xc", "3", "d" => "<= 3" - d1 = new_spec "d", "1", nil, "lib/d.rb" # 2nd level - d2 = new_spec "d", "2", nil, "lib/d.rb" - d3 = new_spec "d", "3", nil, "lib/d.rb" + a1 = util_spec "a", "1", "b" => "> 0" + b1 = util_spec "b", "1", "xc" => ">= 1" # unresolved + b2 = util_spec "b", "2", "xc" => ">= 1", "d" => "< 3" + c1 = util_spec "xc", "1", "d" => "<= 3" # 1st level + c2 = util_spec "xc", "2", "d" => "<= 2" + c3 = util_spec "xc", "3", "d" => "<= 3" + d1 = util_spec "d", "1", nil, "lib/d.rb" # 2nd level + d2 = util_spec "d", "2", nil, "lib/d.rb" + d3 = util_spec "d", "3", nil, "lib/d.rb" install_specs d1, d2, d3, c1, c2, c3, b1, b2, a1 @@ -493,9 +493,9 @@ end end def test_self_activate_via_require - a1 = new_spec "a", "1", "b" => "= 1" - b1 = new_spec "b", "1", nil, "lib/b/c.rb" - b2 = new_spec "b", "2", nil, "lib/b/c.rb" + a1 = util_spec "a", "1", "b" => "= 1" + b1 = util_spec "b", "1", nil, "lib/b/c.rb" + b2 = util_spec "b", "2", nil, "lib/b/c.rb" install_specs b1, b2, a1 @@ -509,13 +509,13 @@ end def test_self_activate_via_require_wtf save_loaded_features do - a1 = new_spec "a", "1", "b" => "> 0", "d" => "> 0" # this - b1 = new_spec "b", "1", { "c" => ">= 1" }, "lib/b.rb" - b2 = new_spec "b", "2", { "c" => ">= 2" }, "lib/b.rb" # this - c1 = new_spec "c", "1" - c2 = new_spec "c", "2" # this - d1 = new_spec "d", "1", { "c" => "< 2" }, "lib/d.rb" - d2 = new_spec "d", "2", { "c" => "< 2" }, "lib/d.rb" # this + a1 = util_spec "a", "1", "b" => "> 0", "d" => "> 0" # this + b1 = util_spec "b", "1", { "c" => ">= 1" }, "lib/b.rb" + b2 = util_spec "b", "2", { "c" => ">= 2" }, "lib/b.rb" # this + c1 = util_spec "c", "1" + c2 = util_spec "c", "2" # this + d1 = util_spec "d", "1", { "c" => "< 2" }, "lib/d.rb" + d2 = util_spec "d", "2", { "c" => "< 2" }, "lib/d.rb" # this install_specs c1, c2, b1, b2, d1, d2, a1 @@ -538,11 +538,11 @@ end end def test_self_activate_deep_unambiguous - a1 = new_spec "a", "1", "b" => "= 1" - b1 = new_spec "b", "1", "c" => "= 1" - b2 = new_spec "b", "2", "c" => "= 2" - c1 = new_spec "c", "1" - c2 = new_spec "c", "2" + a1 = util_spec "a", "1", "b" => "= 1" + b1 = util_spec "b", "1", "c" => "= 1" + b2 = util_spec "b", "2", "c" => "= 2" + c1 = util_spec "c", "1" + c2 = util_spec "c", "2" install_specs c1, c2, b1, b2, a1 @@ -668,7 +668,7 @@ end end def test_self_all_equals - a = new_spec "foo", "1", nil, "lib/foo.rb" + a = util_spec "foo", "1", nil, "lib/foo.rb" install_specs a Gem::Specification.all = [a] @@ -721,11 +721,11 @@ end spec.version = '1' spec.specification_version = @current_version + 1 - new_spec = Marshal.load Marshal.dump(spec) + load_spec = Marshal.load Marshal.dump(spec) - assert_equal 'a', new_spec.name - assert_equal Gem::Version.new(1), new_spec.version - assert_equal @current_version, new_spec.specification_version + assert_equal 'a', load_spec.name + assert_equal Gem::Version.new(1), load_spec.version + assert_equal @current_version, load_spec.specification_version end def test_self_from_yaml @@ -743,12 +743,12 @@ end yaml = @a1.to_yaml yaml.sub!(/^date:.*/, "date: 2011-04-26 00:00:00.000000000Z") - new_spec = with_syck do + spec = with_syck do Gem::Specification.from_yaml yaml end assert_kind_of Time, @a1.date - assert_kind_of Time, new_spec.date + assert_kind_of Time, spec.date end def test_self_from_yaml_syck_default_key_bug @@ -778,14 +778,14 @@ test_files: [] bindir: YAML - new_spec = with_syck do + spec = with_syck do Gem::Specification.from_yaml yaml end - op = new_spec.dependencies.first.requirement.requirements.first.first + op = spec.dependencies.first.requirement.requirements.first.first refute_kind_of YAML::Syck::DefaultKey, op - refute_match %r%DefaultKey%, new_spec.to_ruby + refute_match %r%DefaultKey%, spec.to_ruby end def test_self_from_yaml_cleans_up_defaultkey @@ -814,12 +814,12 @@ test_files: [] bindir: YAML - new_spec = Gem::Specification.from_yaml yaml + spec = Gem::Specification.from_yaml yaml - op = new_spec.dependencies.first.requirement.requirements.first.first + op = spec.dependencies.first.requirement.requirements.first.first refute_kind_of YAML::Syck::DefaultKey, op - refute_match %r%DefaultKey%, new_spec.to_ruby + refute_match %r%DefaultKey%, spec.to_ruby end def test_self_from_yaml_cleans_up_defaultkey_from_newer_192 @@ -848,12 +848,12 @@ test_files: [] bindir: YAML - new_spec = Gem::Specification.from_yaml yaml + spec = Gem::Specification.from_yaml yaml - op = new_spec.dependencies.first.requirement.requirements.first.first + op = spec.dependencies.first.requirement.requirements.first.first refute_kind_of YAML::Syck::DefaultKey, op - refute_match %r%DefaultKey%, new_spec.to_ruby + refute_match %r%DefaultKey%, spec.to_ruby end def test_self_from_yaml_cleans_up_Date_objects @@ -903,9 +903,9 @@ requirements: [] dependencies: [] YAML - new_spec = Gem::Specification.from_yaml yaml + spec = Gem::Specification.from_yaml yaml - assert_kind_of Time, new_spec.date + assert_kind_of Time, spec.date end def test_self_load @@ -1010,7 +1010,6 @@ dependencies: [] assert_equal @a2, spec end - if defined?(Encoding) def test_self_load_utf8_with_ascii_encoding int_enc = Encoding.default_internal silence_warnings { Encoding.default_internal = 'US-ASCII' } @@ -1031,7 +1030,6 @@ dependencies: [] ensure silence_warnings { Encoding.default_internal = int_enc } end - end def test_self_load_legacy_ruby spec = Gem::Deprecate.skip_during do @@ -1135,18 +1133,9 @@ dependencies: [] data = Marshal.load Gem::Util.inflate(Gem.read_binary(path)) - assert_equal nil, data.rubyforge_project + assert_nil data.rubyforge_project end - def test_emits_zulu_timestamps_properly - t = Time.utc(2012, 3, 12) - @a2.date = t - - yaml = with_psych { @a2.to_yaml } - - assert_match %r!date: 2012-03-12 00:00:00\.000000000 Z!, yaml - end if RUBY_VERSION =~ /1\.9\.2/ - def test_initialize spec = Gem::Specification.new do |s| s.name = "blah" @@ -1156,7 +1145,7 @@ dependencies: [] assert_equal "blah", spec.name assert_equal "1.3.5", spec.version.to_s assert_equal Gem::Platform::RUBY, spec.platform - assert_equal nil, spec.summary + assert_nil spec.summary assert_equal [], spec.files assert_equal [], spec.test_files @@ -1204,57 +1193,57 @@ dependencies: [] s.add_dependency 'some_gem' end - new_spec = spec.dup + dup_spec = spec.dup assert_equal "blah", spec.name - assert_same spec.name, new_spec.name + assert_same spec.name, dup_spec.name assert_equal "1.3.5", spec.version.to_s - assert_same spec.version, new_spec.version + assert_same spec.version, dup_spec.version assert_equal Gem::Platform::RUBY, spec.platform - assert_same spec.platform, new_spec.platform + assert_same spec.platform, dup_spec.platform assert_equal 'summary', spec.summary - assert_same spec.summary, new_spec.summary + assert_same spec.summary, dup_spec.summary assert_equal %w[README.txt bin/exec ext/extconf.rb lib/file.rb test/file.rb].sort, spec.files - refute_same spec.files, new_spec.files, 'files' + refute_same spec.files, dup_spec.files, 'files' assert_equal %w[test/file.rb], spec.test_files - refute_same spec.test_files, new_spec.test_files, 'test_files' + refute_same spec.test_files, dup_spec.test_files, 'test_files' assert_equal %w[--foo], spec.rdoc_options - refute_same spec.rdoc_options, new_spec.rdoc_options, 'rdoc_options' + refute_same spec.rdoc_options, dup_spec.rdoc_options, 'rdoc_options' assert_equal %w[README.txt], spec.extra_rdoc_files - refute_same spec.extra_rdoc_files, new_spec.extra_rdoc_files, + refute_same spec.extra_rdoc_files, dup_spec.extra_rdoc_files, 'extra_rdoc_files' assert_equal %w[exec], spec.executables - refute_same spec.executables, new_spec.executables, 'executables' + refute_same spec.executables, dup_spec.executables, 'executables' assert_equal %w[ext/extconf.rb], spec.extensions - refute_same spec.extensions, new_spec.extensions, 'extensions' + refute_same spec.extensions, dup_spec.extensions, 'extensions' assert_equal %w[requirement], spec.requirements - refute_same spec.requirements, new_spec.requirements, 'requirements' + refute_same spec.requirements, dup_spec.requirements, 'requirements' assert_equal [Gem::Dependency.new('some_gem', Gem::Requirement.default)], spec.dependencies - refute_same spec.dependencies, new_spec.dependencies, 'dependencies' + refute_same spec.dependencies, dup_spec.dependencies, 'dependencies' assert_equal 'bin', spec.bindir - assert_same spec.bindir, new_spec.bindir + assert_same spec.bindir, dup_spec.bindir assert_equal '>= 0', spec.required_ruby_version.to_s - assert_same spec.required_ruby_version, new_spec.required_ruby_version + assert_same spec.required_ruby_version, dup_spec.required_ruby_version assert_equal '>= 0', spec.required_rubygems_version.to_s assert_same spec.required_rubygems_version, - new_spec.required_rubygems_version + dup_spec.required_rubygems_version end def test_initialize_copy_broken @@ -1333,31 +1322,31 @@ dependencies: [] @a2.bindir = nil @a2.executable = 'app' - assert_equal nil, @a2.bindir + assert_nil @a2.bindir assert_equal %w[app lib/code.rb].sort, @a2.files end def test_extensions_equals_nil @a2.instance_variable_set(:@extensions, nil) - assert_equal nil, @a2.instance_variable_get(:@extensions) + assert_nil @a2.instance_variable_get(:@extensions) assert_equal %w[lib/code.rb], @a2.files end def test_test_files_equals_nil @a2.instance_variable_set(:@test_files, nil) - assert_equal nil, @a2.instance_variable_get(:@test_files) + assert_nil @a2.instance_variable_get(:@test_files) assert_equal %w[lib/code.rb], @a2.files end def test_executables_equals_nil @a2.instance_variable_set(:@executables, nil) - assert_equal nil, @a2.instance_variable_get(:@executables) + assert_nil @a2.instance_variable_get(:@executables) assert_equal %w[lib/code.rb], @a2.files end def test_extra_rdoc_files_equals_nil @a2.instance_variable_set(:@extra_rdoc_files, nil) - assert_equal nil, @a2.instance_variable_get(:@extra_rdoc_files) + assert_nil @a2.instance_variable_get(:@extra_rdoc_files) assert_equal %w[lib/code.rb], @a2.files end @@ -1641,6 +1630,11 @@ dependencies: [] assert_equal Time.utc(2012,01,12,0,0,0), @a1.date end + def test_date_use_env_source_date_epoch + ENV["SOURCE_DATE_EPOCH"] = "123456789" + assert_equal Time.utc(1973,11,29,0,0,0), @a1.date + end + def test_dependencies util_setup_deps assert_equal [@bonobo, @monkey], @gem.dependencies @@ -1685,8 +1679,8 @@ dependencies: [] end def test_eql_eh - g1 = new_spec 'gem', 1 - g2 = new_spec 'gem', 1 + g1 = util_spec 'gem', 1 + g2 = util_spec 'gem', 1 assert_equal g1, g2 assert_equal g1.hash, g2.hash @@ -2167,7 +2161,7 @@ dependencies: [] def test_require_already_activated save_loaded_features do - a1 = new_spec "a", "1", nil, "lib/d.rb" + a1 = util_spec "a", "1", nil, "lib/d.rb" install_specs a1 # , a2, b1, b2, c1, c2 @@ -2184,12 +2178,12 @@ dependencies: [] def test_require_already_activated_indirect_conflict save_loaded_features do - a1 = new_spec "a", "1", "b" => "> 0" - a2 = new_spec "a", "2", "b" => "> 0" - b1 = new_spec "b", "1", "c" => ">= 1" - b2 = new_spec "b", "2", "c" => ">= 2" - c1 = new_spec "c", "1", nil, "lib/d.rb" - c2 = new_spec("c", "2", { "a" => "1" }, "lib/d.rb") # conflicts with a-2 + a1 = util_spec "a", "1", "b" => "> 0" + a2 = util_spec "a", "2", "b" => "> 0" + b1 = util_spec "b", "1", "c" => ">= 1" + b2 = util_spec "b", "2", "c" => ">= 2" + c1 = util_spec "c", "1", nil, "lib/d.rb" + c2 = util_spec("c", "2", { "a" => "1" }, "lib/d.rb") # conflicts with a-2 install_specs c1, b1, a1, a2, c2, b2 @@ -2210,7 +2204,7 @@ dependencies: [] end def test_allowed_push_host - assert_equal nil, @a1.metadata['allowed_push_host'] + assert_nil @a1.metadata['allowed_push_host'] assert_equal 'https://privategemserver.com', @a3.metadata['allowed_push_host'] end @@ -2227,8 +2221,8 @@ dependencies: [] end def test_spaceship_name - s1 = new_spec 'a', '1' - s2 = new_spec 'b', '1' + s1 = util_spec 'a', '1' + s2 = util_spec 'b', '1' assert_equal(-1, (s1 <=> s2)) assert_equal( 0, (s1 <=> s1)) @@ -2236,8 +2230,8 @@ dependencies: [] end def test_spaceship_platform - s1 = new_spec 'a', '1' - s2 = new_spec 'a', '1' do |s| + s1 = util_spec 'a', '1' + s2 = util_spec 'a', '1' do |s| s.platform = Gem::Platform.new 'x86-my_platform1' end @@ -2247,8 +2241,8 @@ dependencies: [] end def test_spaceship_version - s1 = new_spec 'a', '1' - s2 = new_spec 'a', '2' + s1 = util_spec 'a', '1' + s2 = util_spec 'a', '2' assert_equal( -1, (s1 <=> s2)) assert_equal( 0, (s1 <=> s1)) @@ -2431,16 +2425,16 @@ Gem::Specification.new do |s| if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_runtime_dependency(%q.freeze, [\"> 0.4\"]) s.add_runtime_dependency(%q.freeze, [\"> 0.0.0\"]) - s.add_runtime_dependency(%q.freeze, [\"<= 0.6\", \"> 0.4\"]) + s.add_runtime_dependency(%q.freeze, [\"> 0.4\", \"<= 0.6\"]) else s.add_dependency(%q.freeze, [\"> 0.4\"]) s.add_dependency(%q.freeze, [\"> 0.0.0\"]) - s.add_dependency(%q.freeze, [\"<= 0.6\", \"> 0.4\"]) + s.add_dependency(%q.freeze, [\"> 0.4\", \"<= 0.6\"]) end else s.add_dependency(%q.freeze, [\"> 0.4\"]) s.add_dependency(%q.freeze, [\"> 0.0.0\"]) - s.add_dependency(%q.freeze, [\"<= 0.6\", \"> 0.4\"]) + s.add_dependency(%q.freeze, [\"> 0.4\", \"<= 0.6\"]) end end SPEC @@ -2624,9 +2618,13 @@ end #{w}: pessimistic dependency on d (~> 1.2.3) may be overly strict if d is semantically versioned, use: add_runtime_dependency 'd', '~> 1.2', '>= 1.2.3' + if d is not semantically versioned, you can bypass this warning with: + add_runtime_dependency 'd', '>= 1.2.3', '< 1.3.a' #{w}: pessimistic dependency on e (~> 1.2.3.4) may be overly strict if e is semantically versioned, use: add_runtime_dependency 'e', '~> 1.2', '>= 1.2.3.4' + if e is not semantically versioned, you can bypass this warning with: + add_runtime_dependency 'e', '>= 1.2.3.4', '< 1.2.4.a' #{w}: open-ended dependency on i (>= 1.2) is not recommended if i is semantically versioned, use: add_runtime_dependency 'i', '~> 1.2' @@ -2642,6 +2640,8 @@ end #{w}: pessimistic dependency on m (~> 2.1.0) may be overly strict if m is semantically versioned, use: add_runtime_dependency 'm', '~> 2.1', '>= 2.1.0' + if m is not semantically versioned, you can bypass this warning with: + add_runtime_dependency 'm', '>= 2.1.0', '< 2.2.a' #{w}: See http://guides.rubygems.org/specification-reference/ for help EXPECTED @@ -2944,6 +2944,17 @@ http://spdx.org/licenses or 'Nonstandard' for a nonstandard license. assert_empty @ui.error end + def test_validate_license_values_or_later + util_setup_validate + + use_ui @ui do + @a1.licenses = ['GPL-2.0-or-later'] + @a1.validate + end + + assert_empty @ui.error + end + def test_validate_license_values_with util_setup_validate @@ -2973,6 +2984,20 @@ http://spdx.org/licenses or 'Nonstandard' for a nonstandard license. warning end + def test_validate_license_with_invalid_exception + util_setup_validate + + use_ui @ui do + @a1.licenses = ['GPL-2.0+ WITH Autocofn-exception-2.0'] + @a1.validate + end + + assert_match <<-warning, @ui.error +WARNING: license value 'GPL-2.0+ WITH Autocofn-exception-2.0' is invalid. Use a license identifier from +http://spdx.org/licenses or 'Nonstandard' for a nonstandard license. + warning + end + def test_validate_license_gives_suggestions util_setup_validate @@ -3225,7 +3250,7 @@ Did you mean 'Ruby'? end def test__load_fixes_Date_objects - spec = new_spec "a", 1 + spec = util_spec "a", 1 spec.instance_variable_set :@date, Date.today spec = Marshal.load Marshal.dump(spec) @@ -3537,7 +3562,7 @@ end end def test_find_by_path - a = new_spec "foo", "1", nil, "lib/foo.rb" + a = util_spec "foo", "1", nil, "lib/foo.rb" install_specs a @@ -3547,13 +3572,13 @@ end end def test_find_inactive_by_path - a = new_spec "foo", "1", nil, "lib/foo.rb" + a = util_spec "foo", "1", nil, "lib/foo.rb" install_specs a assert_equal a, Gem::Specification.find_inactive_by_path('foo') a.activate - assert_equal nil, Gem::Specification.find_inactive_by_path('foo') + assert_nil Gem::Specification.find_inactive_by_path('foo') end def test_load_default_gem @@ -3573,7 +3598,7 @@ end def test_detect_bundled_gem_in_old_ruby util_set_RUBY_VERSION '1.9.3', 551 - spec = new_spec 'bigdecimal', '1.1.0' do |s| + spec = util_spec 'bigdecimal', '1.1.0' do |s| s.summary = "This bigdecimal is bundled with Ruby" end diff --git a/test/rubygems/test_gem_stream_ui.rb b/test/rubygems/test_gem_stream_ui.rb index 51fd51c474..56ab1cee5b 100644 --- a/test/rubygems/test_gem_stream_ui.rb +++ b/test/rubygems/test_gem_stream_ui.rb @@ -36,9 +36,6 @@ class TestGemStreamUI < Gem::TestCase end def test_ask - skip 'TTY detection broken on windows' if - Gem.win_platform? && RUBY_VERSION <= '1.9.2' - Timeout.timeout(1) do expected_answer = "Arthur, King of the Britons" @in.string = "#{expected_answer}\n" @@ -48,21 +45,15 @@ class TestGemStreamUI < Gem::TestCase end def test_ask_no_tty - skip 'TTY detection broken on windows' if - Gem.win_platform? && RUBY_VERSION <= '1.9.2' - @in.tty = false Timeout.timeout(0.1) do answer = @sui.ask("what is your favorite color?") - assert_equal nil, answer + assert_nil answer end end def test_ask_for_password - skip 'Always uses $stdin on windows' if - Gem.win_platform? && RUBY_VERSION <= '1.9.2' - Timeout.timeout(1) do expected_answer = "Arthur, King of the Britons" @in.string = "#{expected_answer}\n" @@ -72,21 +63,15 @@ class TestGemStreamUI < Gem::TestCase end def test_ask_for_password_no_tty - skip 'TTY handling is broken on windows' if - Gem.win_platform? && RUBY_VERSION <= '1.9.2' - @in.tty = false Timeout.timeout(0.1) do answer = @sui.ask_for_password("what is the airspeed velocity of an unladen swallow?") - assert_equal nil, answer + assert_nil answer end end def test_ask_yes_no_no_tty_with_default - skip 'TTY handling is broken on windows' if - Gem.win_platform? && RUBY_VERSION <= '1.9.2' - @in.tty = false Timeout.timeout(0.1) do @@ -99,9 +84,6 @@ class TestGemStreamUI < Gem::TestCase end def test_ask_yes_no_no_tty_without_default - skip 'TTY handling is broken on windows' if - Gem.win_platform? && RUBY_VERSION <= '1.9.2' - @in.tty = false Timeout.timeout(0.1) do diff --git a/test/rubygems/test_gem_uninstaller.rb b/test/rubygems/test_gem_uninstaller.rb index d005130895..a53526c0bc 100644 --- a/test/rubygems/test_gem_uninstaller.rb +++ b/test/rubygems/test_gem_uninstaller.rb @@ -177,10 +177,12 @@ class TestGemUninstaller < Gem::InstallerTestCase gem_dir = File.join @gemhome, 'gems', @spec.full_name Gem.pre_uninstall do + sleep(0.1) if win_platform? assert File.exist?(gem_dir), 'gem_dir should exist' end Gem.post_uninstall do + sleep(0.1) if win_platform? refute File.exist?(gem_dir), 'gem_dir should not exist' end @@ -212,7 +214,7 @@ class TestGemUninstaller < Gem::InstallerTestCase default_spec = new_default_spec 'default', '2' install_default_gems default_spec - spec = new_spec 'default', '2' + spec = util_spec 'default', '2' install_gem spec Gem::Specification.reset @@ -482,4 +484,22 @@ create_makefile '#{@spec.name}' assert_match %r!r-1 depends on q \(= 1, development\)!, lines.shift assert_match %r!Successfully uninstalled q-1!, lines.last end + + def test_uninstall_no_permission + uninstaller = Gem::Uninstaller.new @spec.name, :executables => true + + stub_rm_r = lambda do |*args| + _path = args.shift + options = args.shift || Hash.new + # Uninstaller calls a method in RDoc which also calls FileUtils.rm_rf which + # is an alias for FileUtils#rm_r, so skip if we're using the force option + raise Errno::EPERM unless options[:force] + end + + FileUtils.stub :rm_r, stub_rm_r do + assert_raises Gem::UninstallError do + uninstaller.uninstall + end + end + end end diff --git a/test/rubygems/test_gem_util.rb b/test/rubygems/test_gem_util.rb index 3b7887d931..71a26c06ae 100644 --- a/test/rubygems/test_gem_util.rb +++ b/test/rubygems/test_gem_util.rb @@ -42,13 +42,8 @@ class TestGemUtil < Gem::TestCase assert_equal File.join(@tempdir, 'd'), paths[0] assert_equal @tempdir, paths[1] - if File.respond_to?(:realpath) - assert_equal File.realpath(Dir.tmpdir), paths[2] - assert_equal File.realpath("..", Dir.tmpdir), paths[3] - elsif RUBY_PLATFORM !~ /darwin/ - assert_equal Dir.tmpdir, paths[2] - assert_equal '/', paths[3] - end + assert_equal File.realpath(Dir.tmpdir), paths[2] + assert_equal File.realpath("..", Dir.tmpdir), paths[3] ensure # restore default permissions, allow the directory to be removed FileUtils.chmod(0775, 'd/e') unless win_platform? diff --git a/test/rubygems/test_require.rb b/test/rubygems/test_require.rb index e292ce226d..ed856c7648 100644 --- a/test/rubygems/test_require.rb +++ b/test/rubygems/test_require.rb @@ -40,10 +40,10 @@ class TestGemRequire < Gem::TestCase # Providing -I on the commandline should always beat gems def test_dash_i_beats_gems - a1 = new_spec "a", "1", {"b" => "= 1"}, "lib/test_gem_require_a.rb" - b1 = new_spec "b", "1", {"c" => "> 0"}, "lib/b/c.rb" - c1 = new_spec "c", "1", nil, "lib/c/c.rb" - c2 = new_spec "c", "2", nil, "lib/c/c.rb" + a1 = util_spec "a", "1", {"b" => "= 1"}, "lib/test_gem_require_a.rb" + b1 = util_spec "b", "1", {"c" => "> 0"}, "lib/b/c.rb" + c1 = util_spec "c", "1", nil, "lib/c/c.rb" + c2 = util_spec "c", "2", nil, "lib/c/c.rb" install_specs c1, c2, b1, a1 @@ -80,13 +80,11 @@ class TestGemRequire < Gem::TestCase end def test_concurrent_require - skip 'deadlock' if /^1\.8\./ =~ RUBY_VERSION - Object.const_set :FILE_ENTERED_LATCH, Latch.new(2) Object.const_set :FILE_EXIT_LATCH, Latch.new(1) - a1 = new_spec "a", "1", nil, "lib/a.rb" - b1 = new_spec "b", "1", nil, "lib/b.rb" + a1 = util_spec "a", "1", nil, "lib/a.rb" + b1 = util_spec "b", "1", nil, "lib/b.rb" install_specs a1, b1 @@ -107,9 +105,9 @@ class TestGemRequire < Gem::TestCase end def test_require_is_not_lazy_with_exact_req - a1 = new_spec "a", "1", {"b" => "= 1"}, "lib/test_gem_require_a.rb" - b1 = new_spec "b", "1", nil, "lib/b/c.rb" - b2 = new_spec "b", "2", nil, "lib/b/c.rb" + a1 = util_spec "a", "1", {"b" => "= 1"}, "lib/test_gem_require_a.rb" + b1 = util_spec "b", "1", nil, "lib/b/c.rb" + b2 = util_spec "b", "2", nil, "lib/b/c.rb" install_specs b1, b2, a1 @@ -122,9 +120,9 @@ class TestGemRequire < Gem::TestCase end def test_require_is_lazy_with_inexact_req - a1 = new_spec "a", "1", {"b" => ">= 1"}, "lib/test_gem_require_a.rb" - b1 = new_spec "b", "1", nil, "lib/b/c.rb" - b2 = new_spec "b", "2", nil, "lib/b/c.rb" + a1 = util_spec "a", "1", {"b" => ">= 1"}, "lib/test_gem_require_a.rb" + b1 = util_spec "b", "1", nil, "lib/b/c.rb" + b2 = util_spec "b", "2", nil, "lib/b/c.rb" install_specs b1, b2, a1 @@ -137,8 +135,8 @@ class TestGemRequire < Gem::TestCase end def test_require_is_not_lazy_with_one_possible - a1 = new_spec "a", "1", {"b" => ">= 1"}, "lib/test_gem_require_a.rb" - b1 = new_spec "b", "1", nil, "lib/b/c.rb" + a1 = util_spec "a", "1", {"b" => ">= 1"}, "lib/test_gem_require_a.rb" + b1 = util_spec "b", "1", nil, "lib/b/c.rb" install_specs b1, a1 @@ -151,7 +149,7 @@ class TestGemRequire < Gem::TestCase end def test_require_can_use_a_pathname_object - a1 = new_spec "a", "1", nil, "lib/test_gem_require_a.rb" + a1 = util_spec "a", "1", nil, "lib/test_gem_require_a.rb" install_specs a1 @@ -161,9 +159,9 @@ class TestGemRequire < Gem::TestCase end def test_activate_via_require_respects_loaded_files - a1 = new_spec "a", "1", {"b" => ">= 1"}, "lib/test_gem_require_a.rb" - b1 = new_spec "b", "1", nil, "lib/benchmark.rb" - b2 = new_spec "b", "2", nil, "lib/benchmark.rb" + a1 = util_spec "a", "1", {"b" => ">= 1"}, "lib/test_gem_require_a.rb" + b1 = util_spec "b", "1", nil, "lib/benchmark.rb" + b2 = util_spec "b", "2", nil, "lib/benchmark.rb" install_specs b1, b2, a1 @@ -181,11 +179,11 @@ class TestGemRequire < Gem::TestCase end def test_already_activated_direct_conflict - a1 = new_spec "a", "1", { "b" => "> 0" } - b1 = new_spec "b", "1", { "c" => ">= 1" }, "lib/ib.rb" - b2 = new_spec "b", "2", { "c" => ">= 2" }, "lib/ib.rb" - c1 = new_spec "c", "1", nil, "lib/d.rb" - c2 = new_spec("c", "2", nil, "lib/d.rb") + a1 = util_spec "a", "1", { "b" => "> 0" } + b1 = util_spec "b", "1", { "c" => ">= 1" }, "lib/ib.rb" + b2 = util_spec "b", "2", { "c" => ">= 2" }, "lib/ib.rb" + c1 = util_spec "c", "1", nil, "lib/d.rb" + c2 = util_spec("c", "2", nil, "lib/d.rb") install_specs c1, c2, b1, b2, a1 @@ -201,13 +199,13 @@ class TestGemRequire < Gem::TestCase end def test_multiple_gems_with_the_same_path - a1 = new_spec "a", "1", { "b" => "> 0", "x" => "> 0" } - b1 = new_spec "b", "1", { "c" => ">= 1" }, "lib/ib.rb" - b2 = new_spec "b", "2", { "c" => ">= 2" }, "lib/ib.rb" - x1 = new_spec "x", "1", nil, "lib/ib.rb" - x2 = new_spec "x", "2", nil, "lib/ib.rb" - c1 = new_spec "c", "1", nil, "lib/d.rb" - c2 = new_spec("c", "2", nil, "lib/d.rb") + a1 = util_spec "a", "1", { "b" => "> 0", "x" => "> 0" } + b1 = util_spec "b", "1", { "c" => ">= 1" }, "lib/ib.rb" + b2 = util_spec "b", "2", { "c" => ">= 2" }, "lib/ib.rb" + x1 = util_spec "x", "1", nil, "lib/ib.rb" + x2 = util_spec "x", "2", nil, "lib/ib.rb" + c1 = util_spec "c", "1", nil, "lib/d.rb" + c2 = util_spec("c", "2", nil, "lib/d.rb") install_specs c1, c2, x1, x2, b1, b2, a1 @@ -224,13 +222,13 @@ class TestGemRequire < Gem::TestCase end def test_unable_to_find_good_unresolved_version - a1 = new_spec "a", "1", { "b" => "> 0" } - b1 = new_spec "b", "1", { "c" => ">= 2" }, "lib/ib.rb" - b2 = new_spec "b", "2", { "c" => ">= 3" }, "lib/ib.rb" + a1 = util_spec "a", "1", { "b" => "> 0" } + b1 = util_spec "b", "1", { "c" => ">= 2" }, "lib/ib.rb" + b2 = util_spec "b", "2", { "c" => ">= 3" }, "lib/ib.rb" - c1 = new_spec "c", "1", nil, "lib/d.rb" - c2 = new_spec "c", "2", nil, "lib/d.rb" - c3 = new_spec "c", "3", nil, "lib/d.rb" + c1 = util_spec "c", "1", nil, "lib/d.rb" + c2 = util_spec "c", "2", nil, "lib/d.rb" + c3 = util_spec "c", "3", nil, "lib/d.rb" install_specs c1, c2, c3, b1, b2, a1 @@ -273,10 +271,10 @@ class TestGemRequire < Gem::TestCase end def test_require_doesnt_traverse_development_dependencies - a = new_spec("a", "1", nil, "lib/a.rb") - z = new_spec("z", "1", "w" => "> 0") - w1 = new_spec("w", "1") { |s| s.add_development_dependency "non-existent" } - w2 = new_spec("w", "2") { |s| s.add_development_dependency "non-existent" } + a = util_spec("a", "1", nil, "lib/a.rb") + z = util_spec("z", "1", "w" => "> 0") + w1 = util_spec("w", "1") { |s| s.add_development_dependency "non-existent" } + w2 = util_spec("w", "2") { |s| s.add_development_dependency "non-existent" } install_specs a, w1, w2, z @@ -296,7 +294,6 @@ class TestGemRequire < Gem::TestCase end def test_realworld_default_gem - skip "no default gems on ruby < 2.0" unless RUBY_VERSION >= "2" begin gem 'json' rescue Gem::MissingSpecError @@ -316,7 +313,7 @@ class TestGemRequire < Gem::TestCase default_gem_spec = new_default_spec("default", "2.0.0.0", nil, "default/gem.rb") install_default_specs(default_gem_spec) - normal_gem_spec = new_spec("default", "3.0", nil, + normal_gem_spec = util_spec("default", "3.0", nil, "lib/default/gem.rb") install_specs(normal_gem_spec) assert_require "default/gem" @@ -366,7 +363,7 @@ class TestGemRequire < Gem::TestCase end def test_require_default_when_gem_defined - a = new_spec("a", "1", nil, "lib/a.rb") + a = util_spec("a", "1", nil, "lib/a.rb") install_specs a c = Class.new do def self.gem(*args) @@ -379,8 +376,8 @@ class TestGemRequire < Gem::TestCase def test_require_bundler - b1 = new_spec('bundler', '1', nil, "lib/bundler/setup.rb") - b2a = new_spec('bundler', '2.a', nil, "lib/bundler/setup.rb") + b1 = util_spec('bundler', '1', nil, "lib/bundler/setup.rb") + b2a = util_spec('bundler', '2.a', nil, "lib/bundler/setup.rb") install_specs b1, b2a require "rubygems/bundler_version_finder" @@ -392,8 +389,8 @@ class TestGemRequire < Gem::TestCase def test_require_bundler_missing_bundler_version Gem::BundlerVersionFinder.stub(:bundler_version_with_reason, ["55", "reason"]) do - b1 = new_spec('bundler', '1.999999999', nil, "lib/bundler/setup.rb") - b2a = new_spec('bundler', '2.a', nil, "lib/bundler/setup.rb") + b1 = util_spec('bundler', '1.999999999', nil, "lib/bundler/setup.rb") + b2a = util_spec('bundler', '2.a', nil, "lib/bundler/setup.rb") install_specs b1, b2a e = assert_raises Gem::MissingSpecVersionError do @@ -405,8 +402,8 @@ class TestGemRequire < Gem::TestCase def test_require_bundler_with_bundler_version Gem::BundlerVersionFinder.stub(:bundler_version_with_reason, ["1", "reason"]) do - b1 = new_spec('bundler', '1.999999999', nil, "lib/bundler/setup.rb") - b2 = new_spec('bundler', '2', nil, "lib/bundler/setup.rb") + b1 = util_spec('bundler', '1.999999999', nil, "lib/bundler/setup.rb") + b2 = util_spec('bundler', '2', nil, "lib/bundler/setup.rb") install_specs b1, b2 $:.clear