ruby-changes:48021
From: hsbt <ko1@a...>
Date: Sun, 8 Oct 2017 10:32:30 +0900 (JST)
Subject: [ruby-changes:48021] hsbt:r60133 (trunk): Merge rubygems master.
hsbt 2017-10-08 10:32:18 +0900 (Sun, 08 Oct 2017) New Revision: 60133 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=60133 Log: Merge rubygems master. This is RC version of Rubygems 2.7.0. https://github.com/rubygems/rubygems/commit/688fb7e83c13c3fe7c2bb03c49a2db4c82852aee Added files: trunk/lib/rubygems/bundler_version_finder.rb trunk/lib/rubygems/commands/signin_command.rb trunk/lib/rubygems/commands/signout_command.rb trunk/lib/rubygems/security_option.rb trunk/test/rubygems/private3072_key.pem trunk/test/rubygems/public3072_cert.pem trunk/test/rubygems/test_gem_bundler_version_finder.rb trunk/test/rubygems/test_gem_commands_signin_command.rb trunk/test/rubygems/test_gem_commands_signout_command.rb Modified files: trunk/lib/rubygems/basic_specification.rb trunk/lib/rubygems/command.rb trunk/lib/rubygems/command_manager.rb trunk/lib/rubygems/commands/cert_command.rb trunk/lib/rubygems/commands/cleanup_command.rb trunk/lib/rubygems/commands/help_command.rb trunk/lib/rubygems/commands/owner_command.rb trunk/lib/rubygems/commands/pristine_command.rb trunk/lib/rubygems/commands/push_command.rb trunk/lib/rubygems/commands/query_command.rb trunk/lib/rubygems/commands/setup_command.rb trunk/lib/rubygems/commands/uninstall_command.rb trunk/lib/rubygems/commands/unpack_command.rb trunk/lib/rubygems/commands/update_command.rb trunk/lib/rubygems/commands/which_command.rb trunk/lib/rubygems/commands/yank_command.rb trunk/lib/rubygems/config_file.rb trunk/lib/rubygems/core_ext/kernel_require.rb trunk/lib/rubygems/dependency.rb trunk/lib/rubygems/dependency_installer.rb trunk/lib/rubygems/errors.rb trunk/lib/rubygems/exceptions.rb trunk/lib/rubygems/ext/builder.rb trunk/lib/rubygems/gem_runner.rb trunk/lib/rubygems/install_update_options.rb trunk/lib/rubygems/installer.rb trunk/lib/rubygems/installer_test_case.rb trunk/lib/rubygems/package/old.rb trunk/lib/rubygems/request.rb trunk/lib/rubygems/request_set/gem_dependency_api.rb trunk/lib/rubygems/request_set.rb trunk/lib/rubygems/requirement.rb trunk/lib/rubygems/resolver/installer_set.rb trunk/lib/rubygems/resolver.rb trunk/lib/rubygems/security.rb trunk/lib/rubygems/server.rb trunk/lib/rubygems/source/git.rb trunk/lib/rubygems/source/local.rb trunk/lib/rubygems/source/lock.rb trunk/lib/rubygems/source.rb trunk/lib/rubygems/source_local.rb trunk/lib/rubygems/source_specific_file.rb trunk/lib/rubygems/spec_fetcher.rb trunk/lib/rubygems/specification.rb trunk/lib/rubygems/stub_specification.rb trunk/lib/rubygems/test_case.rb trunk/lib/rubygems/user_interaction.rb trunk/lib/rubygems/util.rb trunk/lib/rubygems/version.rb trunk/lib/rubygems/version_option.rb trunk/lib/rubygems.rb trunk/test/rubygems/test_config.rb trunk/test/rubygems/test_gem.rb trunk/test/rubygems/test_gem_command.rb trunk/test/rubygems/test_gem_commands_build_command.rb trunk/test/rubygems/test_gem_commands_cert_command.rb trunk/test/rubygems/test_gem_commands_install_command.rb trunk/test/rubygems/test_gem_commands_pristine_command.rb trunk/test/rubygems/test_gem_commands_query_command.rb trunk/test/rubygems/test_gem_commands_setup_command.rb trunk/test/rubygems/test_gem_commands_uninstall_command.rb trunk/test/rubygems/test_gem_commands_update_command.rb trunk/test/rubygems/test_gem_commands_which_command.rb trunk/test/rubygems/test_gem_dependency.rb trunk/test/rubygems/test_gem_ext_builder.rb trunk/test/rubygems/test_gem_install_update_options.rb trunk/test/rubygems/test_gem_installer.rb trunk/test/rubygems/test_gem_package.rb trunk/test/rubygems/test_gem_remote_fetcher.rb trunk/test/rubygems/test_gem_request_set_gem_dependency_api.rb trunk/test/rubygems/test_gem_requirement.rb trunk/test/rubygems/test_gem_resolver.rb trunk/test/rubygems/test_gem_resolver_conflict.rb trunk/test/rubygems/test_gem_security.rb trunk/test/rubygems/test_gem_security_policy.rb trunk/test/rubygems/test_gem_security_signer.rb trunk/test/rubygems/test_gem_security_trust_dir.rb trunk/test/rubygems/test_gem_server.rb trunk/test/rubygems/test_gem_source.rb trunk/test/rubygems/test_gem_spec_fetcher.rb trunk/test/rubygems/test_gem_specification.rb trunk/test/rubygems/test_gem_stub_specification.rb trunk/test/rubygems/test_gem_util.rb trunk/test/rubygems/test_gem_version.rb trunk/test/rubygems/test_gem_version_option.rb trunk/test/rubygems/test_kernel.rb trunk/test/rubygems/test_require.rb Index: lib/rubygems/commands/signout_command.rb =================================================================== --- lib/rubygems/commands/signout_command.rb (nonexistent) +++ lib/rubygems/commands/signout_command.rb (revision 60133) @@ -0,0 +1,33 @@ https://github.com/ruby/ruby/blob/trunk/lib/rubygems/commands/signout_command.rb#L1 +# frozen_string_literal: true +require 'rubygems/command' + +class Gem::Commands::SignoutCommand < Gem::Command + + def initialize + super 'signout', 'Sign out from all the current sessions.' + end + + def description # :nodoc: + 'The `signout` command is used to sign out from all current sessions,'\ + ' allowing you to sign in using a different set of credentials.' + end + + def usage # :nodoc: + program_name + end + + def execute + credentials_path = Gem.configuration.credentials_path + + if !File.exist?(credentials_path) then + alert_error 'You are not currently signed in.' + elsif !File.writable?(credentials_path) then + alert_error "File '#{Gem.configuration.credentials_path}' is read-only."\ + ' Please make sure it is writable.' + else + Gem.configuration.unset_api_key! + say 'You have successfully signed out from all sessions.' + end + end + +end Index: lib/rubygems/commands/cert_command.rb =================================================================== --- lib/rubygems/commands/cert_command.rb (revision 60132) +++ lib/rubygems/commands/cert_command.rb (revision 60133) @@ -84,6 +84,11 @@ class Gem::Commands::CertCommand < Gem:: https://github.com/ruby/ruby/blob/trunk/lib/rubygems/commands/cert_command.rb#L84 options[:sign] << cert_file end + + add_option('-d', '--days NUMBER_OF_DAYS', + 'Days before the certificate expires') do |days, options| + options[:expiration_length_days] = days.to_i + end end def add_certificate certificate # :nodoc: @@ -105,16 +110,20 @@ class Gem::Commands::CertCommand < Gem:: https://github.com/ruby/ruby/blob/trunk/lib/rubygems/commands/cert_command.rb#L110 list_certificates_matching filter end - options[:build].each do |name| - build name + options[:build].each do |email| + build email end sign_certificates unless options[:sign].empty? end - def build name + def build email + if !valid_email?(email) + raise Gem::CommandLineError, "Invalid email address #{email}" + end + key, key_path = build_key - cert_path = build_cert name, key + cert_path = build_cert email, key say "Certificate: #{cert_path}" @@ -124,8 +133,16 @@ class Gem::Commands::CertCommand < Gem:: https://github.com/ruby/ruby/blob/trunk/lib/rubygems/commands/cert_command.rb#L133 end end - def build_cert name, key # :nodoc: - cert = Gem::Security.create_cert_email name, key + def build_cert email, key # :nodoc: + expiration_length_days = options[:expiration_length_days] + age = + if expiration_length_days.nil? || expiration_length_days == 0 + Gem::Security::ONE_YEAR + else + Gem::Security::ONE_DAY * expiration_length_days + end + + cert = Gem::Security.create_cert_email email, key, age Gem::Security.write cert, "gem-public_cert.pem" end @@ -273,5 +290,13 @@ For further reading on signing gems see https://github.com/ruby/ruby/blob/trunk/lib/rubygems/commands/cert_command.rb#L290 end end + private + + def valid_email? email + # It's simple, but is all we need + email =~ /\A.+@.+\z/ + end + + end if defined?(OpenSSL::SSL) Index: lib/rubygems/source_specific_file.rb =================================================================== --- lib/rubygems/source_specific_file.rb (revision 60132) +++ lib/rubygems/source_specific_file.rb (revision 60133) @@ -1,5 +1,6 @@ https://github.com/ruby/ruby/blob/trunk/lib/rubygems/source_specific_file.rb#L1 # frozen_string_literal: true require 'rubygems/source/specific_file' -# TODO warn upon require, this file is deprecated. - +unless Gem::Deprecate.skip + Kernel.warn "#{Gem.location_of_caller(3).join(':')}: Warning: Requiring rubygems/source_specific_file is deprecated; please use rubygems/source/specific_file instead." +end Index: lib/rubygems/commands/owner_command.rb =================================================================== --- lib/rubygems/commands/owner_command.rb (revision 60132) +++ lib/rubygems/commands/owner_command.rb (revision 60133) @@ -40,7 +40,9 @@ permission to. https://github.com/ruby/ruby/blob/trunk/lib/rubygems/commands/owner_command.rb#L40 options[:remove] << value end - add_option '-h', '--host HOST', 'Use another gemcutter-compatible host' do |value, options| + add_option '-h', '--host HOST', + 'Use another gemcutter-compatible host', + ' (e.g. https://rubygems.org)' do |value, options| options[:host] = value end end Index: lib/rubygems/commands/yank_command.rb =================================================================== --- lib/rubygems/commands/yank_command.rb (revision 60132) +++ lib/rubygems/commands/yank_command.rb (revision 60133) @@ -11,19 +11,11 @@ class Gem::Commands::YankCommand < Gem:: https://github.com/ruby/ruby/blob/trunk/lib/rubygems/commands/yank_command.rb#L11 def description # :nodoc: <<-EOF -The yank command removes a gem you pushed to a server from the server's -index. - -Note that if you push a gem to rubygems.org the yank command does not -prevent other people from downloading the gem via the download link. +The yank command permanently removes a gem you pushed to a server. Once you have pushed a gem several downloads will happen automatically -via the webhooks. If you accidentally pushed passwords or other sensitive +via the webhooks. If you accidentally pushed passwords or other sensitive data you will need to change them immediately and yank your gem. - -If you are yanking a gem due to intellectual property reasons contact -http://help.rubygems.org for permanent removal. Be sure to mention this -as the reason for the removal request. EOF end @@ -42,7 +34,8 @@ as the reason for the removal request. https://github.com/ruby/ruby/blob/trunk/lib/rubygems/commands/yank_command.rb#L34 add_platform_option("remove") add_option('--host HOST', - 'Yank from another gemcutter-compatible host') do |value, options| + 'Yank from another gemcutter-compatible host', + ' (e.g. https://rubygems.org)') do |value, options| options[:host] = value end Index: lib/rubygems/commands/query_command.rb =================================================================== --- lib/rubygems/commands/query_command.rb (revision 60132) +++ lib/rubygems/commands/query_command.rb (revision 60133) @@ -255,22 +255,21 @@ is too hard to use. https://github.com/ruby/ruby/blob/trunk/lib/rubygems/commands/query_command.rb#L255 name_tuples.map { |n| n.version }.uniq else platforms.sort.reverse.map do |version, pls| - if pls == [Gem::Platform::RUBY] then - if options[:domain] == :remote || specs.all? { |spec| spec.is_a? Gem::Source } - version - else - spec = specs.select { |s| s.version == version } - if spec.first.default_gem? - "default: #{version}" - else - version - end + out = version.to_s + + if options[:domain] == :local + default = specs.any? do |s| + !s.is_a?(Gem::Source) && s.version == version && s.default_gem? end - else - ruby = pls.delete Gem::Platform::RUBY - platform_list = [ruby, *pls.sort].compact - "#{version} #{platform_list.join ' '}" + out = "default: #{out}" if default + end + + if pls != [Gem::Platform::RUBY] then + platform_list = [pls.delete(Gem::Platform::RUBY), *pls.sort].compact + out = platform_list.unshift(out).join(' ') end + + out end end Index: lib/rubygems/commands/unpack_command.rb =================================================================== --- lib/rubygems/commands/unpack_command.rb (revision 60132) +++ lib/rubygems/commands/unpack_command.rb (revision 60133) @@ -2,11 +2,20 @@ https://github.com/ruby/ruby/blob/trunk/lib/rubygems/commands/unpack_command.rb#L2 require 'rubygems/command' require 'rubygems/installer' require 'rubygems/version_option' +require 'rubygems/security_option' require 'rubygems/remote_fetcher' +# forward-declare + +module Gem::Security # :nodoc: + class Policy # :nodoc: + end +end + class Gem::Commands::UnpackCommand < Gem::Command include Gem::VersionOption + include Gem::SecurityOption def initialize require 'fileutils' @@ -24,6 +33,7 @@ class Gem::Commands::UnpackCommand < Gem https://github.com/ruby/ruby/blob/trunk/lib/rubygems/commands/unpack_command.rb#L33 options[:spec] = true end + add_security_option add_version_option end @@ -63,6 +73,8 @@ command help for an example. https://github.com/ruby/ruby/blob/trunk/lib/rubygems/commands/unpack_command.rb#L73 # at the same time.) def execute + security_policy = options[:security_policy] + get_all_gem_names.each do |name| dependency = Gem::Dependency.new name, options[:version] path = get_path dependency @@ -73,7 +85,7 @@ command help for an example. https://github.com/ruby/ruby/blob/trunk/lib/rubygems/commands/unpack_command.rb#L85 end if @options[:spec] then - spec, metadata = get_metadata path + spec, metadata = get_metadata path, security_policy if metadata.nil? then alert_error "--spec is unsupported on '#{name}' (old format gem)" @@ -89,7 +101,7 @@ command help for an example. https://github.com/ruby/ruby/blob/trunk/lib/rubygems/commands/unpack_command.rb#L101 basename = File.basename path, '.gem' target_dir = File.expand_path basename, options[:target] - package = Gem::Package.new path + package = Gem::Package.new path, security_policy package.extract_files target_dir say "Unpacked gem: '#{target_dir}'" @@ -158,8 +170,8 @@ command help for an example. https://github.com/ruby/ruby/blob/trunk/lib/rubygems/commands/unpack_command.rb#L170 #-- # TODO move to Gem::Package as #raw_spec or something - def get_metadata path - format = Gem::Package.new path + def get_metadata path, security_policy = nil + format = Gem::Package.new path, security_policy spec = format.spec metadata = nil Index: lib/rubygems/commands/cleanup_command.rb =================================================================== --- lib/rubygems/commands/cleanup_command.rb (revision 60132) +++ lib/rubygems/commands/cleanup_command.rb (revision 60133) @@ -66,7 +66,7 @@ If no gems are named all gems in GEM_HOM https://github.com/ruby/ruby/blob/trunk/lib/rubygems/commands/cleanup_command.rb#L66 clean_gems end - say "Clean Up Complete" + say "Clean up complete" verbose do skipped = @default_gems.map { |spec| spec.full_name } Index: lib/rubygems/commands/pristine_command.rb =================================================================== --- lib/rubygems/commands/pristine_command.rb (revision 60132) +++ lib/rubygems/commands/pristine_command.rb (revision 60133) @@ -125,14 +125,14 @@ extensions will be restored. https://github.com/ruby/ruby/blob/trunk/lib/rubygems/commands/pristine_command.rb#L125 next end - unless spec.extensions.empty? or options[:extensions] then + unless spec.extensions.empty? or options[:extensions] or options[:only_executables] then say "Skipped #{spec.full_name}, it needs to compile an extension" next end gem = spec.cache_file - unless File.exist? gem then + unless File.exist? gem or options[:only_executables] then require 'rubygems/remote_fetcher' say "Cached gem for #{spec.full_name} not found, attempting to fetch..." @@ -157,16 +157,19 @@ extensions will be restored. https://github.com/ruby/ruby/blob/trunk/lib/rubygems/commands/pristine_command.rb#L157 install_defaults.to_s['--env-shebang'] end - installer = Gem::Installer.at(gem, - :wrappers => true, - :force => true, - :install_dir => spec.base_dir, - :env_shebang => env_shebang, - :build_args => spec.build_args) - + installer_options = { + :wrappers => true, + :force => true, + :install_dir => spec.base_dir, + :env_shebang => env_shebang, + :build_args => spec.build_args, + } + if options[:only_executables] then + installer = Gem::Installer.for_spec(spec, installer_options) installer.generate_bin else + installer = Gem::Installer.at(gem, installer_options) installer.install end Index: lib/rubygems/gem_runner.rb =================================================================== --- lib/rubygems/gem_runner.rb (revision 60132) +++ lib/rubygems/gem_runner.rb (revision 60133) @@ -8,6 +8,7 @@ https://github.com/ruby/ruby/blob/trunk/lib/rubygems/gem_runner.rb#L8 require 'rubygems' require 'rubygems/command_manager' require 'rubygems/config_file' +require 'rubygems/deprecate' ## # Load additional plugins from $LOAD_PATH @@ -26,7 +27,10 @@ Gem.load_env_plugins rescue nil https://github.com/ruby/ruby/blob/trunk/lib/rubygems/gem_runner.rb#L27 class Gem::GemRunner def initialize(options={}) - # TODO: nuke these options + if !options.empty? && !Gem::Deprecate.skip + Kernel.warn "NOTE: passing options to Gem::GemRunner.new is deprecated with no replacement. It will be removed on or after 2016-10-01." + end + @command_manager_class = options[:command_manager] || Gem::CommandManager @config_file_class = options[:config_file] || Gem::ConfigFile end Index: lib/rubygems/source/local.rb =================================================================== --- lib/rubygems/source/local.rb (revision 60132) +++ lib/rubygems/source/local.rb (revision 60133) @@ -9,6 +9,7 @@ class Gem::Source::Local < Gem::Source https://github.com/ruby/ruby/blob/trunk/lib/rubygems/source/local.rb#L9 @specs = nil @api_uri = nil @uri = nil + @load_specs_names = {} end ## @@ -34,45 +35,47 @@ class Gem::Source::Local < Gem::Source https://github.com/ruby/ruby/blob/trunk/lib/rubygems/source/local.rb#L35 end def load_specs type # :nodoc: - names = [] + @load_specs_names[type] ||= begin + names = [] - @specs = {} + @specs = {} - Dir["*.gem"].each do |file| - begin - pkg = Gem::Package.new(file) - rescue SystemCallError, Gem::Package::FormatError - # ignore - else - tup = pkg.spec.name_tuple - @specs[tup] = [File.expand_path(file), pkg] - - case type - when :released - unless pkg.spec.version.prerelease? - names << pkg.spec.name_tuple - end - when :prerelease - if pkg.spec.version.prerelease? - names << pkg.spec.name_tuple - end - when :latest + Dir["*.gem"].each do |file| + begin + pkg = Gem::Package.new(file) + rescue SystemCallError, Gem::Package::FormatError + # ignore + else tup = pkg.spec.name_tuple + @specs[tup] = [File.expand_path(file), pkg] - cur = names.find { |x| x.name == tup.name } - if !cur - names << tup - elsif cur.version < tup.version - names.delete cur - names << tup + case type + when :released + unless pkg.spec.version.prerelease? + names << pkg.spec.name_tuple + end + when :prerelease + if pkg.spec.version.prerelease? + names << pkg.spec.name_tuple + end + when :latest + tup = pkg.spec.name_tuple + + cur = names.find { |x| x.name == tup.name } + if !cur + names << tup + elsif cur.version < tup.version + names.delete cur + names << tup + end + else + names << pkg.spec.name_tuple end - else - names << pkg.spec.name_tuple end end - end - names + names + end end def find_gem gem_name, version = Gem::Requirement.default, # :nodoc: @@ -88,7 +91,7 @@ class Gem::Source::Local < Gem::Source https://github.com/ruby/ruby/blob/trunk/lib/rubygems/source/local.rb#L91 if version.satisfied_by?(s.version) if prerelease found << s - elsif !s.version.prerelease? + elsif !s.version.prerelease? || version.prerelease? found << s end end Index: lib/rubygems/source/git.rb =================================================================== --- lib/rubygems/source/git.rb (revision 60132) +++ lib/rubygems/source/git.rb (revision 60133) @@ -1,5 +1,4 @@ https://github.com/ruby/ruby/blob/trunk/lib/rubygems/source/git.rb#L1 # frozen_string_literal: true -require 'digest' require 'rubygems/util' ## @@ -226,6 +225,8 @@ class Gem::Source::Git < Gem::Source https://github.com/ruby/ruby/blob/trunk/lib/rubygems/source/git.rb#L225 # A hash for the git gem based on the git repository URI. def uri_hash # :nodoc: + require 'digest' # required here to avoid deadlocking in Gem.activate_bin_path (because digest is a gem on 2.5+) + normalized = if @repository =~ %r%^\w+://(\w+@)?% then uri = URI(@repository).normalize.to_s.sub %r%/$%,'' Index: lib/rubygems/source/lock.rb =================================================================== --- lib/rubygems/source/lock.rb (revision 60132) +++ lib/rubygems/source/lock.rb (revision 60133) @@ -34,6 +34,10 @@ class Gem::Source::Lock < Gem::Source https://github.com/ruby/ruby/blob/trunk/lib/rubygems/source/lock.rb#L34 0 == (self <=> other) end + def hash # :nodoc: + @wrapped.hash ^ 3 + end + ## # Delegates to the wrapped source's fetch_spec method. @@ -46,4 +50,3 @@ class Gem::Source::Lock < Gem::Source https://github.com/ruby/ruby/blob/trunk/lib/rubygems/source/lock.rb#L50 end end - Index: lib/rubygems/resolver/installer_set.rb =================================================================== --- lib/rubygems/resolver/installer_set.rb (revision 60132) +++ lib/rubygems/resolver/installer_set.rb (revision 60133) @@ -41,6 +41,7 @@ class Gem::Resolver::InstallerSet < Gem: https://github.com/ruby/ruby/blob/trunk/lib/rubygems/resolver/installer_set.rb#L41 @ignore_dependencies = false @ignore_installed = false @local = {} + @local_source = Gem::Source::Local.new @remote_set = Gem::Resolver::BestSet.new @specs = {} end @@ -136,13 +137,11 @@ class Gem::Resolver::InstallerSet < Gem: https://github.com/ruby/ruby/blob/trunk/lib/rubygems/resolver/installer_set.rb#L137 res.concat matching_local - local_source = Gem::Source::Local.new - begin - if local_spec = local_source.find_gem(name, dep.requirement) then + if local_spec = @local_source.find_gem(name, dep.requirement) then res << Gem::Resolver::IndexSpecification.new( self, local_spec.name, local_spec.version, - local_source, local_spec.platform) + @local_source, local_spec.platform) end (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/