Merge rubygems master.

This is RC version of Rubygems 2.7.0.
  688fb7e83c

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60133 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
hsbt 2017-10-08 01:32:18 +00:00
parent 6b05153a3a
commit c00e84327f
96 changed files with 2021 additions and 701 deletions

View file

@ -84,6 +84,11 @@ class Gem::Commands::CertCommand < Gem::Command
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::Command
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::Command
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 `ri Gem::Security`.
end
end
private
def valid_email? email
# It's simple, but is all we need
email =~ /\A.+@.+\z/
end
end if defined?(OpenSSL::SSL)

View file

@ -66,7 +66,7 @@ If no gems are named all gems in GEM_HOME are cleaned.
clean_gems
end
say "Clean Up Complete"
say "Clean up complete"
verbose do
skipped = @default_gems.map { |spec| spec.full_name }

View file

@ -367,7 +367,7 @@ platform.
elsif possibilities.size > 1 then
alert_warning "Ambiguous command #{command_name} (#{possibilities.join(', ')})"
else
alert_warning "Unknown command #{command_name}. Try: gem help commands"
alert_warning "Unknown command #{command_name}. Try: gem help commands"
end
end

View file

@ -40,7 +40,9 @@ permission to.
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

View file

@ -125,14 +125,14 @@ extensions will be restored.
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.
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

View file

@ -33,7 +33,8 @@ command. For further discussion see the help for the yank command.
add_key_option
add_option('--host HOST',
'Push to another gemcutter-compatible host') do |value, options|
'Push to another gemcutter-compatible host',
' (e.g. https://rubygems.org)') do |value, options|
options[:host] = value
end

View file

@ -255,22 +255,21 @@ is too hard to use.
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

View file

@ -15,10 +15,11 @@ class Gem::Commands::SetupCommand < Gem::Command
super 'setup', 'Install RubyGems',
:format_executable => true, :document => %w[ri],
:site_or_vendor => 'sitelibdir',
:destdir => '', :prefix => '', :previous_version => ''
:destdir => '', :prefix => '', :previous_version => '',
:regenerate_binstubs => true
add_option '--previous-version=VERSION',
'Previous version of rubygems',
'Previous version of RubyGems',
'Used for changelog processing' do |version, options|
options[:previous_version] = version
end
@ -42,7 +43,7 @@ class Gem::Commands::SetupCommand < Gem::Command
add_option '--[no-]format-executable',
'Makes `gem` match ruby',
'If ruby is ruby18, gem will be gem18' do |value, options|
'If Ruby is ruby18, gem will be gem18' do |value, options|
options[:format_executable] = value
end
@ -79,6 +80,15 @@ class Gem::Commands::SetupCommand < Gem::Command
options[:document].uniq!
end
add_option '--[no-]regenerate-binstubs',
'Regenerate gem binstubs' do |value, options|
if value then
options[:regenerate_binstubs] = true
else
options.delete(:regenerate_binstubs)
end
end
@verbose = nil
end
@ -92,7 +102,7 @@ class Gem::Commands::SetupCommand < Gem::Command
end
def defaults_str # :nodoc:
"--format-executable --document ri"
"--format-executable --document ri --regenerate-binstubs"
end
def description # :nodoc:
@ -142,8 +152,12 @@ By default, this RubyGems will install gem as:
remove_old_lib_files lib_dir
install_default_bundler_gem
say "RubyGems #{Gem::VERSION} installed"
regenerate_binstubs
uninstall_old_gemcutter
documentation_success = install_rdoc
@ -190,7 +204,7 @@ By default, this RubyGems will install gem as:
if options[:document].include? 'ri' then
say "Ruby Interactive (ri) documentation was installed. ri is kind of like man "
say "pages for ruby libraries. You may access it like this:"
say "pages for Ruby libraries. You may access it like this:"
say " ri Classname"
say " ri Classname.class_method"
say " ri Classname#instance_method"
@ -202,59 +216,64 @@ By default, this RubyGems will install gem as:
end
end
def install_executables(bin_dir)
say "Installing gem executable" if @verbose
def install_executables(bin_dir)
@bin_file_names = []
Dir.chdir 'bin' do
bin_files = Dir['*']
executables = { 'gem' => 'bin' }
executables['bundler'] = 'bundler/exe' if Gem::USE_BUNDLER_FOR_GEMDEPS
executables.each do |tool, path|
say "Installing #{tool} executable" if @verbose
bin_files.delete 'update_rubygems'
Dir.chdir path do
bin_files = Dir['*']
bin_files.each do |bin_file|
bin_file_formatted = if options[:format_executable] then
Gem.default_exec_format % bin_file
else
bin_file
end
bin_files -= %w[update_rubygems bundler bundle_ruby]
dest_file = File.join bin_dir, bin_file_formatted
bin_tmp_file = File.join Dir.tmpdir, "#{bin_file}.#{$$}"
bin_files.each do |bin_file|
bin_file_formatted = if options[:format_executable] then
Gem.default_exec_format % bin_file
else
bin_file
end
begin
bin = File.readlines bin_file
bin[0] = "#!#{Gem.ruby}\n"
dest_file = File.join bin_dir, bin_file_formatted
bin_tmp_file = File.join Dir.tmpdir, "#{bin_file}.#{$$}"
File.open bin_tmp_file, 'w' do |fp|
fp.puts bin.join
begin
bin = File.readlines bin_file
bin[0] = "#!#{Gem.ruby}\n"
File.open bin_tmp_file, 'w' do |fp|
fp.puts bin.join
end
install bin_tmp_file, dest_file, :mode => 0755
@bin_file_names << dest_file
ensure
rm bin_tmp_file
end
install bin_tmp_file, dest_file, :mode => 0755
@bin_file_names << dest_file
ensure
rm bin_tmp_file
end
next unless Gem.win_platform?
next unless Gem.win_platform?
begin
bin_cmd_file = File.join Dir.tmpdir, "#{bin_file}.bat"
begin
bin_cmd_file = File.join Dir.tmpdir, "#{bin_file}.bat"
File.open bin_cmd_file, 'w' do |file|
file.puts <<-TEXT
@ECHO OFF
IF NOT "%~f0" == "~f0" GOTO :WinNT
@"#{File.basename(Gem.ruby).chomp('"')}" "#{dest_file}" %1 %2 %3 %4 %5 %6 %7 %8 %9
GOTO :EOF
:WinNT
@"#{File.basename(Gem.ruby).chomp('"')}" "%~dpn0" %*
TEXT
end
File.open bin_cmd_file, 'w' do |file|
file.puts <<-TEXT
@ECHO OFF
IF NOT "%~f0" == "~f0" GOTO :WinNT
@"#{File.basename(Gem.ruby).chomp('"')}" "#{dest_file}" %1 %2 %3 %4 %5 %6 %7 %8 %9
GOTO :EOF
:WinNT
@"#{File.basename(Gem.ruby).chomp('"')}" "%~dpn0" %*
TEXT
install bin_cmd_file, "#{dest_file}.bat", :mode => 0755
ensure
rm bin_cmd_file
end
install bin_cmd_file, "#{dest_file}.bat", :mode => 0755
ensure
rm bin_cmd_file
end
end
end
@ -269,18 +288,22 @@ TEXT
end
def install_lib(lib_dir)
say "Installing RubyGems" if @verbose
libs = { 'RubyGems' => 'lib' }
libs['Bundler'] = 'bundler/lib' if Gem::USE_BUNDLER_FOR_GEMDEPS
libs.each do |tool, path|
say "Installing #{tool}" if @verbose
lib_files = rb_files_in 'lib'
pem_files = pem_files_in 'lib'
lib_files = rb_files_in path
pem_files = pem_files_in path
Dir.chdir 'lib' do
lib_files.each do |lib_file|
install_file lib_file, lib_dir
end
Dir.chdir path do
lib_files.each do |lib_file|
install_file lib_file, lib_dir
end
pem_files.each do |pem_file|
install_file pem_file, lib_dir
pem_files.each do |pem_file|
install_file pem_file, lib_dir
end
end
end
end
@ -326,6 +349,29 @@ TEXT
return false
end
def install_default_bundler_gem
return unless Gem::USE_BUNDLER_FOR_GEMDEPS
bundler_spec = Gem::Specification.load("bundler/bundler.gemspec")
bundler_spec.files = Dir["bundler/{*.md,{lib,exe,man}/**/*}"]
bundler_spec.executables -= %w[bundler bundle_ruby]
Dir.entries(Gem::Specification.default_specifications_dir).
select {|gs| gs.start_with?("bundler-") }.
each {|gs| File.delete(File.join(Gem::Specification.default_specifications_dir, gs)) }
default_spec_path = File.join(Gem::Specification.default_specifications_dir, "#{bundler_spec.full_name}.gemspec")
Gem.write_binary(default_spec_path, bundler_spec.to_ruby)
bundler_spec = Gem::Specification.load(default_spec_path)
Dir.entries(bundler_spec.gems_dir).
select {|default_gem| default_gem.start_with?("bundler-") }.
each {|default_gem| rm_r File.join(bundler_spec.gems_dir, default_gem) }
mkdir_p bundler_spec.bin_dir
bundler_spec.executables.each {|e| cp File.join("bundler", bundler_spec.bindir, e), File.join(bundler_spec.bin_dir, e) }
end
def make_destination_dirs(install_destdir)
lib_dir, bin_dir = Gem.default_rubygems_dirs
@ -397,7 +443,7 @@ TEXT
old_bin_path = File.join bin_dir, old_bin_file
next unless File.exist? old_bin_path
deprecation_message = "`#{old_bin_file}` has been deprecated. Use `#{new_name}` instead."
deprecation_message = "`#{old_bin_file}` has been deprecated. Use `#{new_name}` instead."
File.open old_bin_path, 'w' do |fp|
fp.write <<-EOF
@ -416,23 +462,26 @@ abort "#{deprecation_message}"
end
def remove_old_lib_files lib_dir
rubygems_dir = File.join lib_dir, 'rubygems'
lib_files = rb_files_in 'lib/rubygems'
lib_dirs = { File.join(lib_dir, 'rubygems') => 'lib/rubygems' }
lib_dirs[File.join(lib_dir, 'bundler')] = 'bundler/lib/bundler' if Gem::USE_BUNDLER_FOR_GEMDEPS
lib_dirs.each do |old_lib_dir, new_lib_dir|
lib_files = rb_files_in(new_lib_dir)
old_lib_files = rb_files_in rubygems_dir
old_lib_files = rb_files_in(old_lib_dir)
to_remove = old_lib_files - lib_files
to_remove = old_lib_files - lib_files
to_remove.delete_if do |file|
file.start_with? 'defaults'
end
to_remove.delete_if do |file|
file.start_with? 'defaults'
end
Dir.chdir rubygems_dir do
to_remove.each do |file|
FileUtils.rm_f file
Dir.chdir old_lib_dir do
to_remove.each do |file|
FileUtils.rm_f file
warn "unable to remove old file #{file} please remove it by hand" if
File.exist? file
warn "unable to remove old file #{file} please remove it by hand" if
File.exist? file
end
end
end
end
@ -480,5 +529,11 @@ abort "#{deprecation_message}"
rescue Gem::InstallError
end
end
def regenerate_binstubs
require "rubygems/commands/pristine_command"
say "Regenerating binstubs"
command = Gem::Commands::PristineCommand.new
command.invoke(*%w[--all --only-executables --silent])
end
end

View file

@ -0,0 +1,33 @@
# frozen_string_literal: true
require 'rubygems/command'
require 'rubygems/gemcutter_utilities'
class Gem::Commands::SigninCommand < Gem::Command
include Gem::GemcutterUtilities
def initialize
super 'signin', 'Sign in to any gemcutter-compatible host. '\
'It defaults to https://rubygems.org'
add_option('--host HOST', 'Push to another gemcutter-compatible host') do |value, options|
options[:host] = value
end
end
def description # :nodoc:
'The signin command executes host sign in for a push server (the default is'\
' https://rubygems.org). The host can be provided with the host flag or can'\
' be inferred from the provided gem. Host resolution matches the resolution'\
' strategy for the push command.'
end
def usage # :nodoc:
program_name
end
def execute
sign_in options[:host]
end
end

View file

@ -0,0 +1,33 @@
# 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

View file

@ -30,7 +30,7 @@ class Gem::Commands::UninstallCommand < Gem::Command
options[:ignore] = value
end
add_option('-D', '--[no-]-check-development',
add_option('-D', '--[no-]check-development',
'Check development dependencies while uninstalling',
'(default: false)') do |value, options|
options[:check_dev] = value
@ -143,7 +143,9 @@ that is a dependency of an existing gem. You can use the
deplist = Gem::DependencyList.new
get_all_gem_names.uniq.each do |name|
Gem::Specification.find_all_by_name(name).each do |spec|
gem_specs = Gem::Specification.find_all_by_name(name)
say("Gem '#{name}' is not installed") if gem_specs.empty?
gem_specs.each do |spec|
deplist.add spec
end
end
@ -162,4 +164,3 @@ that is a dependency of an existing gem. You can use the
end
end

View file

@ -2,11 +2,20 @@
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::Command
options[:spec] = true
end
add_security_option
add_version_option
end
@ -63,6 +73,8 @@ command help for an example.
# 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.
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.
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.
#--
# 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

View file

@ -70,7 +70,7 @@ command to remove old versions.
def check_latest_rubygems version # :nodoc:
if Gem.rubygems_version == version then
say "Latest version currently installed. Aborting."
say "Latest version already installed. Done."
terminate_interaction
end

View file

@ -56,7 +56,7 @@ requiring to see why it does not behave as you expect.
paths = find_paths arg, dirs
if paths.empty? then
alert_error "Can't find ruby library file or shared library #{arg}"
alert_error "Can't find Ruby library file or shared library #{arg}"
found &&= false
else

View file

@ -11,19 +11,11 @@ class Gem::Commands::YankCommand < Gem::Command
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.
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