1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

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

@ -39,7 +39,7 @@ require 'rubygems/errors'
# Further RubyGems documentation can be found at:
#
# * {RubyGems Guides}[http://guides.rubygems.org]
# * {RubyGems API}[http://rubygems.rubyforge.org/rdoc] (also available from
# * {RubyGems API}[http://www.rubydoc.info/github/rubygems/rubygems] (also available from
# <tt>gem server</tt>)
#
# == RubyGems Plugins
@ -47,15 +47,16 @@ require 'rubygems/errors'
# As of RubyGems 1.3.2, RubyGems will load plugins installed in gems or
# $LOAD_PATH. Plugins must be named 'rubygems_plugin' (.rb, .so, etc) and
# placed at the root of your gem's #require_path. Plugins are discovered via
# Gem::find_files then loaded. Take care when implementing a plugin as your
# Gem::find_files and then loaded. Take care when implementing a plugin as your
# plugin file may be loaded multiple times if multiple versions of your gem
# are installed.
#
# For an example plugin, see the graph gem which adds a `gem graph` command.
# For an example plugin, see the {Graph gem}[https://github.com/seattlerb/graph]
# which adds a `gem graph` command.
#
# == RubyGems Defaults, Packaging
#
# RubyGems defaults are stored in rubygems/defaults.rb. If you're packaging
# RubyGems defaults are stored in lib/rubygems/defaults.rb. If you're packaging
# RubyGems or implementing Ruby you can change RubyGems' defaults.
#
# For RubyGems packagers, provide lib/rubygems/defaults/operating_system.rb
@ -65,7 +66,7 @@ require 'rubygems/errors'
# override any defaults from lib/rubygems/defaults.rb.
#
# If you need RubyGems to perform extra work on install or uninstall, your
# defaults override file can set pre and post install and uninstall hooks.
# defaults override file can set pre/post install and uninstall hooks.
# See Gem::pre_install, Gem::pre_uninstall, Gem::post_install,
# Gem::post_uninstall.
#
@ -106,6 +107,8 @@ require 'rubygems/errors'
#
# (If your name is missing, PLEASE let us know!)
#
# == License
#
# See {LICENSE.txt}[rdoc-ref:lib/rubygems/LICENSE.txt] for permissions.
#
# Thanks!
@ -130,6 +133,7 @@ module Gem
GEM_DEP_FILES = %w[
gem.deps.rb
gems.rb
Gemfile
Isolate
]
@ -159,7 +163,7 @@ module Gem
# these are defined in Ruby 1.8.7, hence the need for this convoluted setup.
READ_BINARY_ERRORS = begin
read_binary_errors = [Errno::EACCES]
read_binary_errors = [Errno::EACCES, Errno::EROFS]
read_binary_errors << Errno::ENOTSUP if Errno.const_defined?(:ENOTSUP)
read_binary_errors
end.freeze
@ -174,6 +178,8 @@ module Gem
write_binary_errors
end.freeze
USE_BUNDLER_FOR_GEMDEPS = true # :nodoc:
@@win_platform = nil
@configuration = nil
@ -266,17 +272,22 @@ module Gem
return loaded if loaded && dep.matches_spec?(loaded)
specs = dep.matching_specs(true)
raise Gem::GemNotFoundException,
"can't find gem #{dep}" if specs.empty?
find_specs = proc { dep.matching_specs(true) }
if dep.to_s == "bundler (>= 0.a)"
specs = Gem::BundlerVersionFinder.without_filtering(&find_specs)
else
specs = find_specs.call
end
specs = specs.find_all { |spec|
spec.executables.include? exec_name
} if exec_name
unless spec = specs.first
msg = "can't find gem #{name} (#{requirements}) with executable #{exec_name}"
msg = "can't find gem #{dep} with executable #{exec_name}"
if name == "bundler" && bundler_message = Gem::BundlerVersionFinder.missing_version_message
msg = bundler_message
end
raise Gem::GemNotFoundException, msg
end
@ -297,7 +308,10 @@ module Gem
def self.activate_bin_path name, exec_name, requirement # :nodoc:
spec = find_spec_for_exe name, exec_name, [requirement]
Gem::LOADED_SPECS_MUTEX.synchronize { spec.activate }
Gem::LOADED_SPECS_MUTEX.synchronize do
spec.activate
finish_resolve
end
spec.bin_file exec_name
end
@ -356,12 +370,16 @@ module Gem
# package is not available as a gem, return nil.
def self.datadir(gem_name)
# TODO: deprecate
spec = @loaded_specs[gem_name]
return nil if spec.nil?
spec.datadir
end
class << self
extend Gem::Deprecate
deprecate :datadir, "spec.datadir", 2016, 10
end
##
# A Zlib::Deflate.deflate wrapper
@ -594,7 +612,6 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# Zlib::GzipReader wrapper that unzips +data+.
def self.gunzip(data)
require 'rubygems/util'
Gem::Util.gunzip data
end
@ -602,7 +619,6 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# Zlib::GzipWriter wrapper that zips +data+.
def self.gzip(data)
require 'rubygems/util'
Gem::Util.gzip data
end
@ -610,7 +626,6 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# A Zlib::Inflate#inflate wrapper
def self.inflate(data)
require 'rubygems/util'
Gem::Util.inflate data
end
@ -715,9 +730,20 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
##
# The file name and line number of the caller of the caller of this method.
#
# +depth+ is how many layers up the call stack it should go.
#
# e.g.,
#
# def a; Gem.location_of_caller; end
# a #=> ["x.rb", 2] # (it'll vary depending on file name and line number)
#
# def b; c; end
# def c; Gem.location_of_caller(2); end
# b #=> ["x.rb", 6] # (it'll vary depending on file name and line number)
def self.location_of_caller
caller[1] =~ /(.*?):(\d+).*?$/i
def self.location_of_caller(depth = 1)
caller[depth] =~ /(.*?):(\d+).*?$/i
file = $1
lineno = $2.to_i
@ -1148,8 +1174,6 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
path = path.dup
if path == "-" then
require 'rubygems/util'
Gem::Util.traverse_parents Dir.pwd do |directory|
dep_file = GEM_DEP_FILES.find { |f| File.file?(f) }
@ -1168,18 +1192,36 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
raise ArgumentError, "Unable to find gem dependencies file at #{path}"
end
rs = Gem::RequestSet.new
@gemdeps = rs.load_gemdeps path
if USE_BUNDLER_FOR_GEMDEPS
ENV["BUNDLE_GEMFILE"] ||= File.expand_path(path)
require 'rubygems/user_interaction'
Gem::DefaultUserInteraction.use_ui(ui) do
require "bundler"
@gemdeps = Bundler.setup
Bundler.ui = nil
@gemdeps.requested_specs.map(&:to_spec).sort_by(&:name)
end
else
rs = Gem::RequestSet.new
@gemdeps = rs.load_gemdeps path
rs.resolve_current.map do |s|
s.full_spec.tap(&:activate)
end
rs.resolve_current.map do |s|
sp = s.full_spec
sp.activate
sp
end
rescue Gem::LoadError, Gem::UnsatisfiableDependencyError => e
warn e.message
warn "You may need to `gem install -g` to install missing gems"
warn ""
rescue => e
case e
when Gem::LoadError, Gem::UnsatisfiableDependencyError, (defined?(Bundler::GemNotFound) ? Bundler::GemNotFound : Gem::LoadError)
warn e.message
warn "You may need to `gem install -g` to install missing gems"
warn ""
else
raise
end
end
class << self
@ -1225,6 +1267,8 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
prefix_pattern = /^(#{prefix_group})/
end
suffix_pattern = /#{Regexp.union(Gem.suffixes)}\z/
spec.files.each do |file|
if new_format
file = file.sub(prefix_pattern, "")
@ -1232,6 +1276,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
end
@path_to_default_spec_map[file] = spec
@path_to_default_spec_map[file.sub(suffix_pattern, "")] = spec
end
end
@ -1239,11 +1284,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# Find a Gem::Specification of default gem from +path+
def find_unresolved_default_spec(path)
Gem.suffixes.each do |suffix|
spec = @path_to_default_spec_map["#{path}#{suffix}"]
return spec if spec
end
nil
@path_to_default_spec_map[path]
end
##
@ -1314,6 +1355,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
MARSHAL_SPEC_DIR = "quick/Marshal.#{Gem.marshal_version}/"
autoload :BundlerVersionFinder, 'rubygems/bundler_version_finder'
autoload :ConfigFile, 'rubygems/config_file'
autoload :Dependency, 'rubygems/dependency'
autoload :DependencyList, 'rubygems/dependency_list'
@ -1329,6 +1371,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
autoload :SourceList, 'rubygems/source_list'
autoload :SpecFetcher, 'rubygems/spec_fetcher'
autoload :Specification, 'rubygems/specification'
autoload :Util, 'rubygems/util'
autoload :Version, 'rubygems/version'
require "rubygems/specification"

View file

@ -71,7 +71,7 @@ class Gem::BasicSpecification
elsif missing_extensions? then
@ignored = true
warn "Ignoring #{full_name} because its extensions are not built. " +
warn "Ignoring #{full_name} because its extensions are not built. " +
"Try: gem pristine #{name} --version #{version}"
return false
end
@ -275,10 +275,10 @@ class Gem::BasicSpecification
# for this spec.
def lib_dirs_glob
dirs = if self.require_paths.size > 1 then
"{#{self.require_paths.join(',')}}"
dirs = if self.raw_require_paths.size > 1 then
"{#{self.raw_require_paths.join(',')}}"
else
self.require_paths.first
self.raw_require_paths.first
end
"#{self.full_gem_path}/#{dirs}".dup.untaint

View file

@ -0,0 +1,112 @@
module Gem::BundlerVersionFinder
@without_filtering = false
def self.without_filtering
without_filtering, @without_filtering = true, @without_filtering
yield
ensure
@without_filtering = without_filtering
end
def self.bundler_version
version, _ = bundler_version_with_reason
return unless version
Gem::Version.new(version)
end
def self.bundler_version_with_reason
return if @without_filtering
if v = ENV["BUNDLER_VERSION"]
return [v, "`$BUNDLER_VERSION`"]
end
if v = bundle_update_bundler_version
return if v == true
return [v, "`bundle update --bundler`"]
end
v, lockfile = lockfile_version
if v
return [v, "your #{lockfile}"]
end
end
def self.missing_version_message
return unless vr = bundler_version_with_reason
<<-EOS
Could not find 'bundler' (#{vr.first}) required by #{vr.last}.
To update to the lastest version installed on your system, run `bundle update --bundler`.
To install the missing version, run `gem install bundler:#{vr.first}`
EOS
end
def self.compatible?(spec)
return true unless spec.name == "bundler".freeze
return true unless bundler_version = self.bundler_version
if bundler_version.segments.first >= 2
spec.version == bundler_version
else # 1.x
spec.version.segments.first < 2
end
end
def self.filter!(specs)
return unless bundler_version = self.bundler_version
if bundler_version.segments.first >= 2
specs.reject! { |spec| spec.version != bundler_version }
else # 1.x
specs.reject! { |spec| spec.version.segments.first >= 2}
end
end
def self.bundle_update_bundler_version
return unless File.basename($0) == "bundle".freeze
return unless "update".start_with?(ARGV.first || " ")
bundler_version = nil
update_index = nil
ARGV.each_with_index do |a, i|
if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN
bundler_version = a
end
next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
bundler_version = $1 || true
update_index = i
end
bundler_version
end
private_class_method :bundle_update_bundler_version
def self.lockfile_version
return unless lockfile = lockfile_contents
lockfile, contents = lockfile
lockfile ||= "lockfile"
regexp = /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
return unless contents =~ regexp
[$1, lockfile]
end
private_class_method :lockfile_version
def self.lockfile_contents
gemfile = ENV["BUNDLE_GEMFILE"]
gemfile = nil if gemfile && gemfile.empty?
Gem::Util.traverse_parents Dir.pwd do |directory|
next unless gemfile = Gem::GEM_DEP_FILES.find { |f| File.file?(f.untaint) }
gemfile = File.join directory, gemfile
break
end unless gemfile
return unless gemfile
lockfile = case gemfile
when "gems.rb" then "gems.locked"
else "#{gemfile}.lock"
end.untaint
return unless File.file?(lockfile)
[lockfile, File.read(lockfile)]
end
private_class_method :lockfile_contents
end

View file

@ -527,7 +527,7 @@ class Gem::Command
end
add_common_option("--silent",
"Silence rubygems output") do |value, options|
"Silence RubyGems output") do |value, options|
options[:silent] = true
end

View file

@ -58,6 +58,8 @@ class Gem::CommandManager
:rdoc,
:search,
:server,
:signin,
:signout,
:sources,
:specification,
:stale,
@ -161,7 +163,7 @@ class Gem::CommandManager
say Gem::VERSION
terminate_interaction 0
when /^-/ then
alert_error "Invalid option: #{args.first}. See 'gem --help'."
alert_error "Invalid option: #{args.first}. See 'gem --help'."
terminate_interaction 1
else
cmd_name = args.shift.downcase

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

View file

@ -336,6 +336,15 @@ if you believe they were disclosed to a third party.
load_api_keys # reload
end
##
# Remove the +~/.gem/credentials+ file to clear all the current sessions.
def unset_api_key!
return false unless File.exist?(credentials_path)
File.delete(credentials_path)
end
def load_file(filename)
Gem.load_yaml
@ -419,31 +428,11 @@ if you believe they were disclosed to a third party.
# to_yaml only overwrites things you can't override on the command line.
def to_yaml # :nodoc:
yaml_hash = {}
yaml_hash[:backtrace] = if @hash.key?(:backtrace)
@hash[:backtrace]
else
DEFAULT_BACKTRACE
end
yaml_hash[:bulk_threshold] = if @hash.key?(:bulk_threshold)
@hash[:bulk_threshold]
else
DEFAULT_BULK_THRESHOLD
end
yaml_hash[:backtrace] = @hash.fetch(:backtrace, DEFAULT_BACKTRACE)
yaml_hash[:bulk_threshold] = @hash.fetch(:bulk_threshold, DEFAULT_BULK_THRESHOLD)
yaml_hash[:sources] = Gem.sources.to_a
yaml_hash[:update_sources] = if @hash.key?(:update_sources)
@hash[:update_sources]
else
DEFAULT_UPDATE_SOURCES
end
yaml_hash[:verbose] = if @hash.key?(:verbose)
@hash[:verbose]
else
DEFAULT_VERBOSITY
end
yaml_hash[:update_sources] = @hash.fetch(:update_sources, DEFAULT_UPDATE_SOURCES)
yaml_hash[:verbose] = @hash.fetch(:verbose, DEFAULT_VERBOSITY)
yaml_hash[:ssl_verify_mode] =
@hash[:ssl_verify_mode] if @hash.key? :ssl_verify_mode

View file

@ -41,8 +41,7 @@ module Kernel
path = path.to_path if path.respond_to? :to_path
spec = Gem.find_unresolved_default_spec(path)
if spec
if spec = Gem.find_unresolved_default_spec(path)
Gem.remove_unresolved_default_spec(spec)
begin
Kernel.send(:gem, spec.name)
@ -66,12 +65,10 @@ module Kernel
#--
# TODO request access to the C implementation of this to speed up RubyGems
spec = Gem::Specification.find_active_stub_by_path path
begin
if Gem::Specification.find_active_stub_by_path(path)
RUBYGEMS_ACTIVATION_MONITOR.exit
return gem_original_require(path)
end if spec
end
# Attempt to find +path+ in any unresolved gems...
@ -109,7 +106,7 @@ module Kernel
# Ok, now find a gem that has no conflicts, starting
# at the highest version.
valid = found_specs.reject { |s| s.has_conflicts? }.first
valid = found_specs.find { |s| !s.has_conflicts? }
unless valid then
le = Gem::LoadError.new "unable to find a version of '#{names.first}' to activate"
@ -143,4 +140,3 @@ module Kernel
private :require
end

View file

@ -280,6 +280,8 @@ class Gem::Dependency
requirement.satisfied_by?(spec.version) && env_req.satisfied_by?(spec.version)
}.map(&:to_spec)
Gem::BundlerVersionFinder.filter!(matches) if name == "bundler".freeze
if platform_only
matches.reject! { |spec|
spec.nil? || !Gem::Platform.match(spec.platform)

View file

@ -7,6 +7,7 @@ require 'rubygems/spec_fetcher'
require 'rubygems/user_interaction'
require 'rubygems/source'
require 'rubygems/available_set'
require 'rubygems/deprecate'
##
# Installs a gem along with all its dependencies from local and remote gems.
@ -46,6 +47,9 @@ class Gem::DependencyInstaller
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

View file

@ -58,6 +58,9 @@ module Gem
private
def build_message
if name == "bundler" && message = Gem::BundlerVersionFinder.missing_version_message
return message
end
names = specs.map(&:full_name)
"Could not find '#{name}' (#{requirement}) - did find: [#{names.join ','}]\n"
end

View file

@ -154,6 +154,12 @@ class Gem::ImpossibleDependenciesError < Gem::Exception
end
class Gem::InstallError < Gem::Exception; end
class Gem::RuntimeRequirementNotMetError < Gem::InstallError
attr_accessor :suggestion
def message
[suggestion, super].compact.join("\n\t")
end
end
##
# Potentially raised when a specification is validated.

View file

@ -183,7 +183,7 @@ EOF
return if @spec.extensions.empty?
if @build_args.empty?
say "Building native extensions. This could take a while..."
say "Building native extensions. This could take a while..."
else
say "Building native extensions with: '#{@build_args.join ' '}'"
say "This could take a while..."

View file

@ -8,6 +8,7 @@
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
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

View file

@ -6,37 +6,18 @@
#++
require 'rubygems'
# forward-declare
module Gem::Security # :nodoc:
class Policy # :nodoc:
end
end
require 'rubygems/security_option'
##
# Mixin methods for install and update options for Gem::Commands
module Gem::InstallUpdateOptions
include Gem::SecurityOption
##
# Add the install/update options to the option parser.
def add_install_update_options
# TODO: use @parser.accept
OptionParser.accept Gem::Security::Policy do |value|
require 'rubygems/security'
raise OptionParser::InvalidArgument, 'OpenSSL not installed' unless
defined?(Gem::Security::HighSecurity)
value = Gem::Security::Policies[value]
valid = Gem::Security::Policies.keys.sort
message = "#{value} (#{valid.join ', '} are valid)"
raise OptionParser::InvalidArgument, message if value.nil?
value
end
add_option(:"Install/Update", '-i', '--install-dir DIR',
'Gem repository directory to get installed',
'gems') do |value, options|
@ -124,11 +105,7 @@ module Gem::InstallUpdateOptions
options[:wrappers] = value
end
add_option(:"Install/Update", '-P', '--trust-policy POLICY',
Gem::Security::Policy,
'Specify gem trust policy') do |value, options|
options[:security_policy] = value
end
add_security_option
add_option(:"Install/Update", '--ignore-dependencies',
'Do not install any required dependent gems') do |value, options|
@ -136,8 +113,8 @@ module Gem::InstallUpdateOptions
end
add_option(:"Install/Update", '--[no-]format-executable',
'Make installed executable names match ruby.',
'If ruby is ruby18, foo_exec will be',
'Make installed executable names match Ruby.',
'If Ruby is ruby18, foo_exec will be',
'foo_exec18') do |value, options|
options[:format_executable] = value
end

View file

@ -136,8 +136,9 @@ class Gem::Installer
end
##
# Constructs an Installer instance that will install the gem located at
# +gem+. +options+ is a Hash with the following keys:
# Constructs an Installer instance that will install the gem at +package+ which
# can either be a path or an instance of Gem::Package. +options+ is a Hash
# with the following keys:
#
# :bin_dir:: Where to put a bin wrapper if needed.
# :development:: Whether or not development dependencies should be installed.
@ -157,6 +158,7 @@ class Gem::Installer
# :wrappers:: Install wrappers if true, symlinks if false.
# :build_args:: An Array of arguments to pass to the extension builder
# process. If not set, then Gem::Command.build_args is used
# :post_install_message:: Print gem post install message if true
def initialize(package, options={})
require 'fileutils'
@ -471,7 +473,7 @@ class Gem::Installer
unless File.exist? bin_path then
# TODO change this to a more useful warning
warn "#{bin_path} maybe `gem pristine #{spec.name}` will fix it?"
warn "`#{bin_path}` does not exist, maybe `gem pristine #{spec.name}` will fix it?"
next
end
@ -608,7 +610,9 @@ class Gem::Installer
def ensure_required_ruby_version_met # :nodoc:
if rrv = spec.required_ruby_version then
unless rrv.satisfied_by? Gem.ruby_version then
raise Gem::InstallError, "#{spec.name} requires Ruby version #{rrv}."
ruby_version = Gem.ruby_api_version
raise Gem::RuntimeRequirementNotMetError,
"#{spec.name} requires Ruby version #{rrv}. The current ruby version is #{ruby_version}."
end
end
end
@ -616,8 +620,9 @@ class Gem::Installer
def ensure_required_rubygems_version_met # :nodoc:
if rrgv = spec.required_rubygems_version then
unless rrgv.satisfied_by? Gem.rubygems_version then
raise Gem::InstallError,
"#{spec.name} requires RubyGems version #{rrgv}. " +
rg_version = Gem::VERSION
raise Gem::RuntimeRequirementNotMetError,
"#{spec.name} requires RubyGems version #{rrgv}. The current RubyGems version is #{rg_version}. " +
"Try 'gem update --system' to update RubyGems itself."
end
end
@ -821,7 +826,7 @@ TEXT
#
# Version and dependency checks are skipped if this install is forced.
#
# The dependent check will be skipped this install is ignoring dependencies.
# The dependent check will be skipped if the install is ignoring dependencies.
def pre_install_checks
verify_gem_home options[:unpack]

View file

@ -1,6 +1,7 @@
# frozen_string_literal: true
require 'rubygems/test_case'
require 'rubygems/installer'
require 'rubygems/deprecate'
class Gem::Installer
@ -72,7 +73,7 @@ class Gem::InstallerTestCase < Gem::TestCase
# a spec named 'a', intended for regular installs
# @user_spec::
# a spec named 'b', intended for user installs
#
# @gem::
# the path to a built gem from @spec
# @user_spec::
@ -107,15 +108,17 @@ class Gem::InstallerTestCase < Gem::TestCase
end
def util_gem_bindir spec = @spec # :nodoc:
# TODO: deprecate
spec.bin_dir
end
def util_gem_dir spec = @spec # :nodoc:
# TODO: deprecate
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

View file

@ -124,7 +124,7 @@ class Gem::Package::Old < Gem::Package
break unless line
end
raise Gem::Exception, "Failed to find end of ruby script while reading gem"
raise Gem::Exception, "Failed to find end of Ruby script while reading gem"
end
##

View file

@ -83,7 +83,7 @@ class Gem::Request
e.message =~ / -- openssl$/
raise Gem::Exception.new(
'Unable to require openssl, install OpenSSL and rebuild ruby (preferred) or use non-HTTPS sources')
'Unable to require openssl, install OpenSSL and rebuild Ruby (preferred) or use non-HTTPS sources')
end
def self.verify_certificate store_context

View file

@ -163,9 +163,26 @@ class Gem::RequestSet
end
end
spec = req.spec.install options do |installer|
yield req, installer if block_given?
end
spec =
begin
req.spec.install options do |installer|
yield req, installer if block_given?
end
rescue Gem::RuntimeRequirementNotMetError => e
recent_match = req.spec.set.find_all(req.request).sort_by(&:version).reverse_each.find do |s|
s = s.spec
s.required_ruby_version.satisfied_by?(Gem.ruby_version) && s.required_rubygems_version.satisfied_by?(Gem.rubygems_version)
end
if recent_match
suggestion = "The last version of #{req.request} to support your Ruby & RubyGems was #{recent_match.version}. Try installing it with `gem install #{recent_match.name} -v #{recent_match.version}`"
suggestion += " and then running the current command again" unless @always_install.include?(req.spec.spec)
else
suggestion = "There are no versions of #{req.request} compatible with your Ruby & RubyGems"
suggestion += ". Maybe try installing an older version of the gem you're looking for?" unless @always_install.include?(req.spec.spec)
end
e.suggestion = suggestion
raise
end
requests << spec
end

View file

@ -786,7 +786,7 @@ Gem dependencies file #{@path} includes git reference for both ref/branch and ta
engine_version = options[:engine_version]
raise ArgumentError,
'you must specify engine_version along with the ruby engine' if
'You must specify engine_version along with the Ruby engine' if
engine and not engine_version
return true if @installing
@ -799,7 +799,7 @@ Gem dependencies file #{@path} includes git reference for both ref/branch and ta
end
if engine and engine != Gem.ruby_engine then
message = "Your ruby engine is #{Gem.ruby_engine}, " +
message = "Your Ruby engine is #{Gem.ruby_engine}, " +
"but your #{gem_deps_file} requires #{engine}"
raise Gem::RubyVersionMismatch, message
@ -810,7 +810,7 @@ Gem dependencies file #{@path} includes git reference for both ref/branch and ta
if engine_version != my_engine_version then
message =
"Your ruby engine version is #{Gem.ruby_engine} #{my_engine_version}, " +
"Your Ruby engine version is #{Gem.ruby_engine} #{my_engine_version}, " +
"but your #{gem_deps_file} requires #{engine} #{engine_version}"
raise Gem::RubyVersionMismatch, message

View file

@ -51,7 +51,11 @@ class Gem::Requirement
# If the input is "weird", the default version requirement is
# returned.
def self.create input
def self.create *inputs
return new inputs if inputs.length > 1
input = inputs.shift
case input
when Gem::Requirement then
input

View file

@ -230,8 +230,28 @@ class Gem::Resolver
exc.errors = @set.errors
raise exc
end
possibles.sort_by { |s| [s.source, s.version, Gem::Platform.local =~ s.platform ? 1 : 0] }.
map { |s| ActivationRequest.new s, dependency, [] }
sources = []
groups = Hash.new { |hash, key| hash[key] = [] }
# create groups & sources in the same loop
sources = possibles.map { |spec|
source = spec.source
groups[source] << spec
source
}.uniq.reverse
activation_requests = []
sources.each do |source|
groups[source].
sort_by { |spec| [spec.version, Gem::Platform.local =~ spec.platform ? 1 : 0] }.
map { |spec| ActivationRequest.new spec, dependency, [] }.
each { |activation_request| activation_requests << activation_request }
end
activation_requests
end
def dependencies_for(specification)

View file

@ -41,6 +41,7 @@ class Gem::Resolver::InstallerSet < Gem::Resolver::Set
@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::Resolver::Set
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
rescue Gem::Package::FormatError
# ignore
@ -194,7 +193,7 @@ class Gem::Resolver::InstallerSet < Gem::Resolver::Set
# Has a local gem for +dep_name+ been added to this set?
def local? dep_name # :nodoc:
spec, = @local[dep_name]
spec, _ = @local[dep_name]
spec
end
@ -226,4 +225,3 @@ class Gem::Resolver::InstallerSet < Gem::Resolver::Set
end
end

View file

@ -340,7 +340,9 @@ module Gem::Security
# Digest algorithm used to sign gems
DIGEST_ALGORITHM =
if defined?(OpenSSL::Digest::SHA1) then
if defined?(OpenSSL::Digest::SHA256) then
OpenSSL::Digest::SHA256
elsif defined?(OpenSSL::Digest::SHA1) then
OpenSSL::Digest::SHA1
end
@ -363,7 +365,7 @@ module Gem::Security
##
# Length of keys created by KEY_ALGORITHM
KEY_LENGTH = 2048
KEY_LENGTH = 3072
##
# Cipher used to encrypt the key pair used to sign gems.
@ -371,10 +373,15 @@ module Gem::Security
KEY_CIPHER = OpenSSL::Cipher.new('AES-256-CBC') if defined?(OpenSSL::Cipher)
##
# One day in seconds
ONE_DAY = 86400
##
# One year in seconds
ONE_YEAR = 86400 * 365
ONE_YEAR = ONE_DAY * 365
##
# The default set of extensions are:

View file

@ -0,0 +1,43 @@
# frozen_string_literal: true
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++
require 'rubygems'
# forward-declare
module Gem::Security # :nodoc:
class Policy # :nodoc:
end
end
##
# Mixin methods for security option for Gem::Commands
module Gem::SecurityOption
def add_security_option
# TODO: use @parser.accept
OptionParser.accept Gem::Security::Policy do |value|
require 'rubygems/security'
raise OptionParser::InvalidArgument, 'OpenSSL not installed' unless
defined?(Gem::Security::HighSecurity)
policy = Gem::Security::Policies[value]
unless policy
valid = Gem::Security::Policies.keys.sort
raise OptionParser::InvalidArgument, "#{value} (#{valid.join ', '} are valid)"
end
policy
end
add_option(:"Install/Update", '-P', '--trust-policy POLICY',
Gem::Security::Policy,
'Specify gem trust policy') do |value, options|
options[:security_policy] = value
end
end
end

View file

@ -573,19 +573,11 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
add_date res
case req.request_uri.path
when %r|^/quick/(Marshal.#{Regexp.escape Gem.marshal_version}/)?(.*?)-([0-9.]+[^-]*?)(-.*?)?\.gemspec\.rz$| then
marshal_format, name, version, platform = $1, $2, $3, $4
specs = Gem::Specification.find_all_by_name name, version
when %r|^/quick/(Marshal.#{Regexp.escape Gem.marshal_version}/)?(.*?)\.gemspec\.rz$| then
marshal_format, full_name = $1, $2
specs = Gem::Specification.find_all_by_full_name(full_name)
selector = [name, version, platform].map(&:inspect).join ' '
platform = if platform then
Gem::Platform.new platform.sub(/^-/, '')
else
Gem::Platform::RUBY
end
specs = specs.select { |s| s.platform == platform }
selector = full_name.inspect
if specs.empty? then
res.status = 404

View file

@ -1,6 +1,6 @@
# frozen_string_literal: true
require 'uri'
require 'fileutils'
autoload :FileUtils, 'fileutils'
autoload :URI, 'uri'
##
# A Source knows how to list and fetch gems from a RubyGems marshal index.
@ -67,7 +67,11 @@ class Gem::Source
return -1 if !other.uri
@uri.to_s <=> other.uri.to_s
# Returning 1 here ensures that when sorting a list of sources, the
# original ordering of sources supplied by the user is preserved.
return 1 unless @uri.to_s == other.uri.to_s
0
else
nil
end
@ -232,4 +236,3 @@ require 'rubygems/source/specific_file'
require 'rubygems/source/local'
require 'rubygems/source/lock'
require 'rubygems/source/vendor'

View file

@ -1,5 +1,4 @@
# frozen_string_literal: true
require 'digest'
require 'rubygems/util'
##
@ -226,6 +225,8 @@ class Gem::Source::Git < Gem::Source
# 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%/$%,''

View file

@ -9,6 +9,7 @@ class Gem::Source::Local < Gem::Source
@specs = nil
@api_uri = nil
@uri = nil
@load_specs_names = {}
end
##
@ -34,45 +35,47 @@ class Gem::Source::Local < Gem::Source
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
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
Dir["*.gem"].each do |file|
begin
pkg = Gem::Package.new(file)
rescue SystemCallError, Gem::Package::FormatError
# ignore
else
names << pkg.spec.name_tuple
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
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
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
if version.satisfied_by?(s.version)
if prerelease
found << s
elsif !s.version.prerelease?
elsif !s.version.prerelease? || version.prerelease?
found << s
end
end

View file

@ -34,6 +34,10 @@ class Gem::Source::Lock < Gem::Source
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
end
end

View file

@ -2,5 +2,7 @@
require 'rubygems/source'
require 'rubygems/source_local'
# TODO warn upon require, this file is deprecated.
unless Gem::Deprecate.skip
Kernel.warn "#{Gem.location_of_caller(3).join(':')}: Warning: Requiring rubygems/source_local is deprecated; please use rubygems/source/local instead."
end

View file

@ -1,5 +1,6 @@
# 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

View file

@ -184,10 +184,10 @@ class Gem::SpecFetcher
# Suggests gems based on the supplied +gem_name+. Returns an array of
# alternative gem names.
def suggest_gems_from_name gem_name
def suggest_gems_from_name(gem_name, type = :latest)
gem_name = gem_name.downcase.tr('_-', '')
max = gem_name.size / 2
names = available_specs(:latest).first.values.flatten(1)
names = available_specs(type).first.values.flatten(1)
matches = names.map { |n|
next unless n.match_platform?
@ -201,7 +201,11 @@ class Gem::SpecFetcher
[n.name, distance]
}.compact
matches = matches.uniq.sort_by { |name, dist| dist }
matches = if matches.empty? && type != :prerelease
suggest_gems_from_name gem_name, :prerelease
else
matches.uniq.sort_by { |name, dist| dist }
end
matches.first(5).map { |name, dist| name }
end

View file

@ -30,6 +30,7 @@ require 'stringio'
# s.email = 'rubycoder@example.com'
# s.files = ["lib/example.rb"]
# s.homepage = 'https://rubygems.org/gems/example'
# s.metadata = { "source_code_uri" => "https://github.com/example/example" }
# end
#
# Starting in RubyGems 2.0, a Specification can hold arbitrary
@ -157,16 +158,20 @@ class Gem::Specification < Gem::BasicSpecification
:summary => nil,
:test_files => [],
:version => nil,
}
}.freeze
Dupable = { } # :nodoc:
INITIALIZE_CODE_FOR_DEFAULTS = { } # :nodoc:
@@default_value.each do |k,v|
case v
when Time, Numeric, Symbol, true, false, nil
Dupable[k] = false
INITIALIZE_CODE_FOR_DEFAULTS[k] = case v
when [], {}, true, false, nil, Numeric, Symbol
v.inspect
when String
v.dump
when Numeric
"default_value(:#{k})"
else
Dupable[k] = true
"default_value(:#{k}).dup"
end
end
@ -208,34 +213,6 @@ class Gem::Specification < Gem::BasicSpecification
attr_reader :version
##
# Paths in the gem to add to <code>$LOAD_PATH</code> when this gem is
# activated.
#--
# See also #require_paths
#++
# If you have an extension you do not need to add <code>"ext"</code> to the
# require path, the extension build process will copy the extension files
# into "lib" for you.
#
# The default value is <code>"lib"</code>
#
# Usage:
#
# # If all library files are in the root directory...
# spec.require_paths = ['.']
def require_paths=(val)
@require_paths = Array(val)
end
##
# The version of RubyGems used to create this gem.
#
# Do not set this, it is set automatically when the gem is packaged.
attr_accessor :rubygems_version
##
# A short summary of this gem's description. Displayed in `gem list -d`.
#
@ -247,6 +224,42 @@ class Gem::Specification < Gem::BasicSpecification
attr_reader :summary
##
# Files included in this gem. You cannot append to this accessor, you must
# assign to it.
#
# Only add files you can require to this list, not directories, etc.
#
# Directories are automatically stripped from this list when building a gem,
# other non-files cause an error.
#
# Usage:
#
# require 'rake'
# spec.files = FileList['lib/**/*.rb',
# 'bin/*',
# '[A-Z]*',
# 'test/**/*'].to_a
#
# # or without Rake...
# spec.files = Dir['lib/**/*.rb'] + Dir['bin/*']
# spec.files += Dir['[A-Z]*'] + Dir['test/**/*']
# spec.files.reject! { |fn| fn.include? "CVS" }
def files
# DO NOT CHANGE TO ||= ! This is not a normal accessor. (yes, it sucks)
# DOC: Why isn't it normal? Why does it suck? How can we fix this?
@files = [@files,
@test_files,
add_bindir(@executables),
@extra_rdoc_files,
@extensions,
].flatten.compact.uniq.sort
end
######################################################################
# :section: Recommended gemspec attributes
##
# Singular writer for #authors
#
@ -269,6 +282,148 @@ class Gem::Specification < Gem::BasicSpecification
@authors = Array(value).flatten.grep(String)
end
##
# A long description of this gem
#
# The description should be more detailed than the summary but not
# excessively long. A few paragraphs is a recommended length with no
# examples or formatting.
#
# Usage:
#
# spec.description = <<-EOF
# Rake is a Make-like program implemented in Ruby. Tasks and
# dependencies are specified in standard Ruby syntax.
# EOF
attr_reader :description
##
# A contact email address (or addresses) for this gem
#
# Usage:
#
# spec.email = 'john.jones@example.com'
# spec.email = ['jack@example.com', 'jill@example.com']
attr_accessor :email
##
# The URL of this gem's home page
#
# Usage:
#
# spec.homepage = 'https://github.com/ruby/rake'
attr_accessor :homepage
##
# The license for this gem.
#
# The license must be no more than 64 characters.
#
# This should just be the name of your license. The full text of the license
# should be inside of the gem (at the top level) when you build it.
#
# The simplest way, is to specify the standard SPDX ID
# https://spdx.org/licenses/ for the license.
# Ideally you should pick one that is OSI (Open Source Initiative)
# http://opensource.org/licenses/alphabetical approved.
#
# The most commonly used OSI approved licenses are MIT and Apache-2.0.
# GitHub also provides a license picker at http://choosealicense.com/.
#
# You should specify a license for your gem so that people know how they are
# permitted to use it, and any restrictions you're placing on it. Not
# specifying a license means all rights are reserved; others have no rights
# to use the code for any purpose.
#
# You can set multiple licenses with #licenses=
#
# Usage:
# spec.license = 'MIT'
def license=o
self.licenses = [o]
end
##
# The license(s) for the library.
#
# Each license must be a short name, no more than 64 characters.
#
# This should just be the name of your license. The full
# text of the license should be inside of the gem when you build it.
#
# See #license= for more discussion
#
# Usage:
# spec.licenses = ['MIT', 'GPL-2.0']
def licenses= licenses
@licenses = Array licenses
end
##
# The metadata holds extra data for this gem that may be useful to other
# consumers and is settable by gem authors without requiring an update to
# the rubygems software.
#
# Metadata items have the following restrictions:
#
# * The metadata must be a Hash object
# * All keys and values must be Strings
# * Keys can be a maximum of 128 bytes and values can be a maximum of 1024
# bytes
# * All strings must be UTF-8, no binary data is allowed
#
# You can use metadata to specify links to your gem's homepage, codebase,
# documentation, wiki, mailing list, issue tracker and changelog.
#
# s.metadata = {
# "bug_tracker_uri" => "https://example.com/user/bestgemever/issues",
# "changelog_uri" => "https://example.com/user/bestgemever/CHANGELOG.md",
# "documentation_uri" => "https://www.example.info/gems/bestgemever/0.0.1",
# "homepage_uri" => "https://bestgemever.example.io",
# "mailing_list_uri" => "https://groups.example.com/bestgemever",
# "source_code_uri" => "https://example.com/user/bestgemever",
# "wiki_uri" => "https://example.com/user/bestgemever/wiki"
# }
#
# These links will be used on your gem's page on rubygems.org and must pass
# validation against following regex.
#
# %r{\Ahttps?:\/\/([^\s:@]+:[^\s:@]*@)?[A-Za-z\d\-]+(\.[A-Za-z\d\-]+)+\.?(:\d{1,5})?([\/?]\S*)?\z}
attr_accessor :metadata
######################################################################
# :section: Optional gemspec attributes
##
# The path in the gem for executable scripts. Usually 'bin'
#
# Usage:
#
# spec.bindir = 'bin'
attr_accessor :bindir
##
# The certificate chain used to sign this gem. See Gem::Security for
# details.
attr_accessor :cert_chain
##
# A message that gets displayed after the gem is installed.
#
# Usage:
#
# spec.post_install_message = "Thanks for installing!"
attr_accessor :post_install_message
##
# The platform this gem runs on.
#
@ -327,104 +482,26 @@ class Gem::Specification < Gem::BasicSpecification
end
##
# Files included in this gem. You cannot append to this accessor, you must
# assign to it.
# Paths in the gem to add to <code>$LOAD_PATH</code> when this gem is
# activated.
#--
# See also #require_paths
#++
# If you have an extension you do not need to add <code>"ext"</code> to the
# require path, the extension build process will copy the extension files
# into "lib" for you.
#
# Only add files you can require to this list, not directories, etc.
#
# Directories are automatically stripped from this list when building a gem,
# other non-files cause an error.
# The default value is <code>"lib"</code>
#
# Usage:
#
# require 'rake'
# spec.files = FileList['lib/**/*.rb',
# 'bin/*',
# '[A-Z]*',
# 'test/**/*'].to_a
#
# # or without Rake...
# spec.files = Dir['lib/**/*.rb'] + Dir['bin/*']
# spec.files += Dir['[A-Z]*'] + Dir['test/**/*']
# spec.files.reject! { |fn| fn.include? "CVS" }
# # If all library files are in the root directory...
# spec.require_paths = ['.']
def files
# DO NOT CHANGE TO ||= ! This is not a normal accessor. (yes, it sucks)
# DOC: Why isn't it normal? Why does it suck? How can we fix this?
@files = [@files,
@test_files,
add_bindir(@executables),
@extra_rdoc_files,
@extensions,
].flatten.compact.uniq.sort
def require_paths=(val)
@require_paths = Array(val)
end
######################################################################
# :section: Optional gemspec attributes
##
# The path in the gem for executable scripts. Usually 'bin'
#
# Usage:
#
# spec.bindir = 'bin'
attr_accessor :bindir
##
# The certificate chain used to sign this gem. See Gem::Security for
# details.
attr_accessor :cert_chain
##
# A long description of this gem
#
# The description should be more detailed than the summary but not
# excessively long. A few paragraphs is a recommended length with no
# examples or formatting.
#
# Usage:
#
# spec.description = <<-EOF
# Rake is a Make-like program implemented in Ruby. Tasks and
# dependencies are specified in standard Ruby syntax.
# EOF
attr_reader :description
##
# :category: Recommended gemspec attributes
#
# A contact email address (or addresses) for this gem
#
# Usage:
#
# spec.email = 'john.jones@example.com'
# spec.email = ['jack@example.com', 'jill@example.com']
attr_accessor :email
##
# :category: Recommended gemspec attributes
#
# The URL of this gem's home page
#
# Usage:
#
# spec.homepage = 'https://github.com/ruby/rake'
attr_accessor :homepage
##
# A message that gets displayed after the gem is installed.
#
# Usage:
#
# spec.post_install_message = "Thanks for installing!"
attr_accessor :post_install_message
##
# The version of Ruby required by this gem
@ -435,32 +512,18 @@ class Gem::Specification < Gem::BasicSpecification
attr_reader :required_rubygems_version
##
# The version of RubyGems used to create this gem.
#
# Do not set this, it is set automatically when the gem is packaged.
attr_accessor :rubygems_version
##
# The key used to sign this gem. See Gem::Security for details.
attr_accessor :signing_key
##
# :attr_accessor: metadata
#
# The metadata holds extra data for this gem that may be useful to other
# consumers and is settable by gem authors without requiring an update to
# the rubygems software.
#
# Metadata items have the following restrictions:
#
# * The metadata must be a Hash object
# * All keys and values must be Strings
# * Keys can be a maximum of 128 bytes and values can be a maximum of 1024
# bytes
# * All strings must be UTF-8, no binary data is allowed
#
# To add metadata for the location of a issue tracker:
#
# s.metadata = { "issue_tracker" => "https://example/issues" }
attr_accessor :metadata
##
# Adds a development dependency named +gem+ with +requirements+ to this
# gem.
@ -473,7 +536,7 @@ class Gem::Specification < Gem::BasicSpecification
# activated when a gem is required.
def add_development_dependency(gem, *requirements)
add_dependency_with_type(gem, :development, *requirements)
add_dependency_with_type(gem, :development, requirements)
end
##
@ -484,7 +547,7 @@ class Gem::Specification < Gem::BasicSpecification
# spec.add_runtime_dependency 'example', '~> 1.1', '>= 1.1.4'
def add_runtime_dependency(gem, *requirements)
add_dependency_with_type(gem, :runtime, *requirements)
add_dependency_with_type(gem, :runtime, requirements)
end
##
@ -556,56 +619,6 @@ class Gem::Specification < Gem::BasicSpecification
@installed_by_version = Gem::Version.new version
end
##
# :category: Recommended gemspec attributes
#
# The license for this gem.
#
# The license must be no more than 64 characters.
#
# This should just be the name of your license. The full text of the license
# should be inside of the gem (at the top level) when you build it.
#
# The simplest way, is to specify the standard SPDX ID
# https://spdx.org/licenses/ for the license.
# Ideally you should pick one that is OSI (Open Source Initiative)
# http://opensource.org/licenses/alphabetical approved.
#
# The most commonly used OSI approved licenses are MIT and Apache-2.0.
# GitHub also provides a license picker at http://choosealicense.com/.
#
# You should specify a license for your gem so that people know how they are
# permitted to use it, and any restrictions you're placing on it. Not
# specifying a license means all rights are reserved; others have no rights
# to use the code for any purpose.
#
# You can set multiple licenses with #licenses=
#
# Usage:
# spec.license = 'MIT'
def license=o
self.licenses = [o]
end
##
# :category: Recommended gemspec attributes
# The license(s) for the library.
#
# Each license must be a short name, no more than 64 characters.
#
# This should just be the name of your license. The full
# text of the license should be inside of the gem when you build it.
#
# See #license= for more discussion
#
# Usage:
# spec.licenses = ['MIT', 'GPL-2.0']
def licenses= licenses
@licenses = Array licenses
end
##
# Specifies the rdoc options to be used when generating API documentation.
#
@ -885,7 +898,7 @@ class Gem::Specification < Gem::BasicSpecification
# properly sorted.
def self.add_spec spec
warn "Gem::Specification.add_spec is deprecated and will be removed in Rubygems 3.0" unless Gem::Deprecate.skip
warn "Gem::Specification.add_spec is deprecated and will be removed in RubyGems 3.0" unless Gem::Deprecate.skip
# TODO: find all extraneous adds
# puts
# p :add_spec => [spec.full_name, caller.reject { |s| s =~ /minitest/ }]
@ -910,7 +923,7 @@ class Gem::Specification < Gem::BasicSpecification
# Adds multiple specs to the known specifications.
def self.add_specs *specs
warn "Gem::Specification.add_specs is deprecated and will be removed in Rubygems 3.0" unless Gem::Deprecate.skip
warn "Gem::Specification.add_specs is deprecated and will be removed in RubyGems 3.0" unless Gem::Deprecate.skip
raise "nil spec!" if specs.any?(&:nil?) # TODO: remove once we're happy
@ -1022,6 +1035,13 @@ class Gem::Specification < Gem::BasicSpecification
Gem::Dependency.new(name, *requirements).matching_specs
end
##
# Returns every spec that has the given +full_name+
def self.find_all_by_full_name(full_name)
stubs.select {|s| s.full_name == full_name }.map(&:to_spec)
end
##
# Find the best specification matching a +name+ and +requirements+. Raises
# if the dependency doesn't resolve to a valid specification.
@ -1040,6 +1060,7 @@ class Gem::Specification < Gem::BasicSpecification
def self.find_by_path path
path = path.dup.freeze
spec = @@spec_with_requirable_file[path] ||= (stubs.find { |s|
next unless Gem::BundlerVersionFinder.compatible?(s)
s.contains_requirable_file? path
} || NOT_FOUND)
spec.to_spec
@ -1051,7 +1072,9 @@ class Gem::Specification < Gem::BasicSpecification
def self.find_inactive_by_path path
stub = stubs.find { |s|
s.contains_requirable_file? path unless s.activated?
next if s.activated?
next unless Gem::BundlerVersionFinder.compatible?(s)
s.contains_requirable_file? path
}
stub && stub.to_spec
end
@ -1250,7 +1273,7 @@ class Gem::Specification < Gem::BasicSpecification
# Removes +spec+ from the known specs.
def self.remove_spec spec
warn "Gem::Specification.remove_spec is deprecated and will be removed in Rubygems 3.0" unless Gem::Deprecate.skip
warn "Gem::Specification.remove_spec is deprecated and will be removed in RubyGems 3.0" unless Gem::Deprecate.skip
_all.delete spec
stubs.delete_if { |s| s.full_name == spec.full_name }
(@@stubs_by_name[spec.name] || []).delete_if { |s| s.full_name == spec.full_name }
@ -1520,7 +1543,7 @@ class Gem::Specification < Gem::BasicSpecification
# +requirements+. Valid types are currently <tt>:runtime</tt> and
# <tt>:development</tt>.
def add_dependency_with_type(dependency, type, *requirements)
def add_dependency_with_type(dependency, type, requirements)
requirements = if requirements.empty? then
Gem::Requirement.default
else
@ -2026,6 +2049,20 @@ class Gem::Specification < Gem::BasicSpecification
yaml_initialize coder.tag, coder.map
end
eval <<-RB, binding, __FILE__, __LINE__ + 1
def set_nil_attributes_to_nil
#{@@nil_attributes.map {|key| "@#{key} = nil" }.join "; "}
end
private :set_nil_attributes_to_nil
def set_not_nil_attributes_to_default_values
#{@@non_nil_attributes.map {|key| "@#{key} = #{INITIALIZE_CODE_FOR_DEFAULTS[key]}" }.join ";"}
end
private :set_not_nil_attributes_to_default_values
RB
##
# Specification constructor. Assigns the default values to the attributes
# and yields itself for further initialization. Optionally takes +name+ and
@ -2041,15 +2078,8 @@ class Gem::Specification < Gem::BasicSpecification
@original_platform = nil
@installed_by_version = nil
@@nil_attributes.each do |key|
instance_variable_set "@#{key}", nil
end
@@non_nil_attributes.each do |key|
default = default_value(key)
value = Dupable[key] ? default.dup : default
instance_variable_set "@#{key}", value
end
set_nil_attributes_to_nil
set_not_nil_attributes_to_default_values
@new_platform = Gem::Platform::RUBY
@ -2746,29 +2776,7 @@ class Gem::Specification < Gem::BasicSpecification
'metadata must be a hash'
end
metadata.keys.each do |k|
if !k.kind_of?(String)
raise Gem::InvalidSpecificationException,
'metadata keys must be a String'
end
if k.size > 128
raise Gem::InvalidSpecificationException,
"metadata key too large (#{k.size} > 128)"
end
end
metadata.values.each do |k|
if !k.kind_of?(String)
raise Gem::InvalidSpecificationException,
'metadata values must be a String'
end
if k.size > 1024
raise Gem::InvalidSpecificationException,
"metadata value too large (#{k.size} > 1024)"
end
end
validate_metadata
licenses.each { |license|
if license.length > 64
@ -2822,7 +2830,7 @@ http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard li
# Warnings
%w[author email homepage summary].each do |attribute|
%w[author homepage summary files].each do |attribute|
value = self.send attribute
warning "no #{attribute} specified" if value.nil? or value.empty?
end
@ -2855,6 +2863,48 @@ http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard li
end
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
end
##
# Checks that dependencies use requirements as we recommend. Warnings are
# issued when dependencies are open-ended or overly strict for semantic

View file

@ -188,9 +188,8 @@ class Gem::StubSpecification < Gem::BasicSpecification
def to_spec
@spec ||= if @data then
Gem.loaded_specs.values.find { |spec|
spec.name == name and spec.version == version
}
loaded = Gem.loaded_specs[name]
loaded if loaded && loaded.version == version
end
@spec ||= Gem::Specification.load(loaded_from)

View file

@ -25,6 +25,7 @@ unless Gem::Dependency.new('rdoc', '>= 3.10').matching_specs.empty?
gem 'json'
end
require 'bundler'
require 'minitest/autorun'
require 'rubygems/deprecate'
@ -222,6 +223,7 @@ class Gem::TestCase < MiniTest::Unit::TestCase
@orig_gem_vendor = ENV['GEM_VENDOR']
@orig_gem_spec_cache = ENV['GEM_SPEC_CACHE']
@orig_rubygems_gemdeps = ENV['RUBYGEMS_GEMDEPS']
@orig_bundle_gemfile = ENV['BUNDLE_GEMFILE']
@orig_rubygems_host = ENV['RUBYGEMS_HOST']
ENV.keys.find_all { |k| k.start_with?('GEM_REQUIREMENT_') }.each do |k|
ENV.delete k
@ -232,7 +234,12 @@ class Gem::TestCase < MiniTest::Unit::TestCase
@current_dir = Dir.pwd
@fetcher = nil
@ui = Gem::MockGemUi.new
Bundler.ui = Bundler::UI::Silent.new
@ui = Gem::MockGemUi.new
# This needs to be a new instance since we call use_ui(@ui) when we want to
# capture output
Gem::DefaultUserInteraction.ui = Gem::MockGemUi.new
tmpdir = File.expand_path Dir.tmpdir
tmpdir.untaint
@ -323,6 +330,7 @@ class Gem::TestCase < MiniTest::Unit::TestCase
Gem.loaded_specs.clear
Gem.clear_default_specs
Gem::Specification.unresolved_deps.clear
Bundler.reset!
Gem.configuration.verbose = true
Gem.configuration.update_sources = true
@ -394,6 +402,7 @@ class Gem::TestCase < MiniTest::Unit::TestCase
ENV['GEM_VENDOR'] = @orig_gem_vendor
ENV['GEM_SPEC_CACHE'] = @orig_gem_spec_cache
ENV['RUBYGEMS_GEMDEPS'] = @orig_rubygems_gemdeps
ENV['BUNDLE_GEMFILE'] = @orig_bundle_gemfile
ENV['RUBYGEMS_HOST'] = @orig_rubygems_host
Gem.ruby = @orig_ruby if @orig_ruby

View file

@ -7,11 +7,6 @@
require 'rubygems/util'
begin
require 'io/console'
rescue LoadError
end
##
# Module that defines the default UserInteraction. Any class including this
# module will have access to the +ui+ method that returns the default UI.
@ -314,12 +309,21 @@ class Gem::StreamUI
password
end
if IO.method_defined?(:noecho) then
def _gets_noecho
@ins.noecho {@ins.gets}
def require_io_console
@require_io_console ||= begin
begin
require 'io/console'
rescue LoadError
end
true
end
elsif Gem.win_platform?
def _gets_noecho
end
def _gets_noecho
require_io_console
if IO.method_defined?(:noecho) then
@ins.noecho {@ins.gets}
elsif Gem.win_platform?
require "Win32API"
password = ''
@ -332,9 +336,7 @@ class Gem::StreamUI
end
end
password
end
else
def _gets_noecho
else
system "stty -echo"
begin
@ins.gets

View file

@ -109,26 +109,15 @@ module Gem::Util
##
# Enumerates the parents of +directory+.
def self.traverse_parents directory
def self.traverse_parents directory, &block
return enum_for __method__, directory unless block_given?
here = File.expand_path directory
start = here
Dir.chdir start
begin
loop do
yield here
Dir.chdir '..'
return if Dir.pwd == here # toplevel
here = Dir.pwd
end
ensure
Dir.chdir start
loop do
Dir.chdir here, &block
new_here = File.expand_path('..', here)
return if new_here == here # toplevel
here = new_here
end
end

View file

@ -170,7 +170,7 @@ class Gem::Version
# True if the +version+ string matches RubyGems' requirements.
def self.correct? version
version.to_s =~ ANCHORED_VERSION_PATTERN
!!(version.to_s =~ ANCHORED_VERSION_PATTERN)
end
##
@ -241,7 +241,7 @@ class Gem::Version
end
def hash # :nodoc:
@version.hash
canonical_segments.hash
end
def init_with coder # :nodoc:
@ -335,7 +335,7 @@ class Gem::Version
def <=> other
return unless Gem::Version === other
return 0 if @version == other._version
return 0 if @version == other._version || canonical_segments == other.canonical_segments
lhsegments = _segments
rhsegments = other._segments
@ -360,6 +360,13 @@ class Gem::Version
return 0
end
def canonical_segments
@canonical_segments ||=
_split_segments.map! do |segments|
segments.reverse_each.drop_while {|s| s == 0 }.reverse
end.reduce(&:concat)
end
protected
def _version
@ -375,4 +382,11 @@ class Gem::Version
/^\d+$/ =~ s ? s.to_i : s
end.freeze
end
def _split_segments
string_start = _segments.index {|s| s.is_a?(String) }
string_segments = segments
numeric_segments = string_segments.slice!(0, string_start || string_segments.size)
return numeric_segments, string_segments
end
end

View file

@ -58,7 +58,12 @@ module Gem::VersionOption
add_option('-v', '--version VERSION', Gem::Requirement,
"Specify version of gem to #{task}", *wrap) do
|value, options|
options[:version] = value
# Allow handling for multiple --version operators
if options[:version] && !options[:version].none?
options[:version].concat([value])
else
options[:version] = value
end
explicit_prerelease_set = !options[:explicit_prerelease].nil?
options[:explicit_prerelease] = false unless explicit_prerelease_set

View file

@ -0,0 +1,40 @@
-----BEGIN PRIVATE KEY-----
MIIG/gIBADANBgkqhkiG9w0BAQEFAASCBugwggbkAgEAAoIBgQDIl6Ne1eCreYAe
j+Qkbygv06KqtcarwjNpSPJFq+G/R6xzGfbiuJDGePnlzqyAN6sti8r/tDD8orMS
l3EUSQTvFAVJKxbBDnklHUozdaX+giw+fi7onRJ3sQE2j7GhjahXZB0vmx20wU9v
sazZ0IU/x7k8X7WbVRCYig99UVn28zsq586LN5u/w7qXo50156bfmeDS8tt+TKSK
PkQQYuO+AulWDVdwHycKSzCE7SPWiZ/scFUirN4Stfw0bJZbr8VQ6QBAhHcHgd6B
tcZ1vBDC656zsWgpGWNTCU9mSBWV3UMk8mdwkO/jz8mXYSBfbyLESkhc8slf47zd
dqs1iZZOmVVlz/TXYc9N9d8DTl3OR/YYy04mdrysf4ijB6HV9U7NrRbjcKqKwTjW
xMWsFDdc1d5WCTsXzKjvB582LspGYxv9zgs0KkhSChGTA0qCqGdl0ZVx1Q0suW5O
7XlcEWAp9gSww0RW3E1zkrUARcB4mQgyC89kvE4y9RW4/KzZDcsCAwEAAQKCAYEA
uhQJBkGLgCZe1nsO3UmMUwmVPZ0QpmapgIKd1EnFScb4T3IHl3w1ORgiYa9eUDbU
AZVLg/co9kMLsTRxPqsZ+5pr6Nsi6YY+lVJdce0yRi2FU5eEdl63MfcuM+oKkt4x
CpihhnbzkKk+wlNlEE2iPm9NA5eZhXXcxlRUWCEuPqqV+ZA+BuFYBwVPw7mQbd/t
6kD50VZejQQWIvPt+fFyaOKUiDIqKaWMdr0XTkgZ1bunchMmttr7ywms4wjUVktv
LWMmI8wEMXfxR+xOtigwolSuFn+djWgh02KEc4gSQD3KGKshps5cMrLxxkwIoaC8
rDxKfdUtixBx6JzrN0Wmq7f/oLpvzxTXoQTu30BvpUOr9evZjE/3ZYXiGCxoSDEL
cvdZHvd+4r0TEkuxNBebq5106bJCBTuq6awwiwAodrsH5DCnqkkrv9tnkVi71NnV
UfnF/C4i5clpJK+Rx4bub9SiqJuyEfQBDlEHdCDwKVASk6B3gXD2mgkJu+EdShkp
AoHBAPx27s3iBN1gRGzD9GU0x2z7uMrgXzXh71kCvzzkfOli5fpIvCyoOR8CIfok
Ph8Kth4c+Bz4bmp6c859yxm5aBdQb3y34LDvCkqEeFCs9XX31QTMjJ1Y3R6Iyun5
nJzzZ5BtJbLFTHw9/p/pCUmJscUP8nQLwBMLIk4HzmrVXVLKJyaakK4LbsCChBc5
XwCqzWFKbMRZM3X8PaZp3DCo9iA5/TyzkQMTucLSYaxDDG+YNtYQPB8J5wkFWTD8
5//WZQKBwQDLZr9CnPR8HcrG46+rDzoZO1nXqaaEQMZhmm25lpL5oSHLrm4elGDp
vH5SRcCPz986InRszMROI3xvYpGtFsAzff3UVY0M8uDQcEKucHtd4wmFHefzYmKo
cvR9PuGmotk6yYpb+cMITT6sCzC4OHPz3DQAclmswRZchHYd2Zkv7tjgE0dXS9nw
XKaH5vQC4wjWBc857scHz0WYJLlj8s8UM9Fludz7kuagXczrsFIONxvrFKNJXeYl
muFCQl8hOG8CgcEA4ZZkTBNpxWX/vjBacRR4HinPNXjHmp4IAMEzoHWKKAD2/m1/
t2eZotuFAL7hw1sO4FmCWmCiSQKh+CDvGk1RdYOqGwcy/uaZi3xTBcOGkaKh9WfR
PcfpzR7uMaOZDaVxJNxikxs4/MtoefsBEXS4JB3bx1W4i0unm5HeIBgHC7MWyKfU
H7CXhe0Zmqbo/O+iFQ0ro0cRdJuvesOcvN49Dw7B+Tt6mAVIN41FOWev9QdN+HkJ
P7LZfnYI/Hz/0NsBAoHADm2+eZI6wac3YD58kqzk2S9doy/UsSMLL5dN21F0IaMt
i45XH3I1Ib+OUnXCQDFly3DwQ1uPPV/FDv22CcpIXh6859gdxmJgUkj0Yf12suVN
IpVJg/lhuENXVp8kULbSpBnx565jCG66WGf+z8Kpbw4a3kE+XUPhOzTmUB3EgSL3
XYXglK+7yRI5egCHJMFIOi51Uc2/bq1kaXOJdy6dQ/idDRNPOsVj+NJOnBWI7Js6
LsXrA2RW1CoVeqbMqsWfAoHAAabWXkQ74BuTo+P7lbfnFa6qLfTRnkWBkKKpWSAZ
ZBLfGsw2F5ZzrfwXtLriPcQJNA+3q3u1WPiGZkjV4QnFMt+Kgcg8ahW94vDEgfex
OSQyrlioT2m9DLJNXXHxo3+0ePNQkmoMQbNRUwdYjBuK7dqNDmFQ8Oo8SxtlV2sL
ntLc47NvFaxDlOvnj9ftQv6ZhdzXQmKGiuZWxtrrjFgHJm8KhMS8IF9xHM3d0uYb
sbykscVdmz3lOmUZrxCeIJvk
-----END PRIVATE KEY-----

View file

@ -0,0 +1,25 @@
-----BEGIN CERTIFICATE-----
MIIENDCCApygAwIBAgIBATANBgkqhkiG9w0BAQsFADAqMQ8wDQYDVQQDDAZub2Jv
ZHkxFzAVBgoJkiaJk/IsZAEZFgdleGFtcGxlMCAXDTE2MDEwMTAwMDAwMFoYDzk5
OTkxMjMxMjM1OTU5WjAqMQ8wDQYDVQQDDAZub2JvZHkxFzAVBgoJkiaJk/IsZAEZ
FgdleGFtcGxlMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAyJejXtXg
q3mAHo/kJG8oL9OiqrXGq8IzaUjyRavhv0escxn24riQxnj55c6sgDerLYvK/7Qw
/KKzEpdxFEkE7xQFSSsWwQ55JR1KM3Wl/oIsPn4u6J0Sd7EBNo+xoY2oV2QdL5sd
tMFPb7Gs2dCFP8e5PF+1m1UQmIoPfVFZ9vM7KufOizebv8O6l6OdNeem35ng0vLb
fkykij5EEGLjvgLpVg1XcB8nCkswhO0j1omf7HBVIqzeErX8NGyWW6/FUOkAQIR3
B4HegbXGdbwQwuues7FoKRljUwlPZkgVld1DJPJncJDv48/Jl2EgX28ixEpIXPLJ
X+O83XarNYmWTplVZc/012HPTfXfA05dzkf2GMtOJna8rH+Ioweh1fVOza0W43Cq
isE41sTFrBQ3XNXeVgk7F8yo7wefNi7KRmMb/c4LNCpIUgoRkwNKgqhnZdGVcdUN
LLluTu15XBFgKfYEsMNEVtxNc5K1AEXAeJkIMgvPZLxOMvUVuPys2Q3LAgMBAAGj
YzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMB0GA1UdDgQWBBSf
hxDG5kMk4VhQNMcuLhULi3gMpTAfBgNVHSMEGDAWgBSfhxDG5kMk4VhQNMcuLhUL
i3gMpTANBgkqhkiG9w0BAQsFAAOCAYEAuvY1Nc8lkjCWEnVlAB0yfx85+xa/6zoQ
9w4cG/Nk+M2XNXRmp0c6FQgy7Y/aRxIobJnJfo2S1yJIPfzBuxb/oOy4ikYGmrYV
JUJFs4KaMPz8nM13YVI+KtskNEs0Pb8kcb0ZO640f0ptkgFDN/rvezu2uxqTlaD+
NSy+O+2Xr5T1Qq2eT2ui3mint26sA2g2cZqkqIdeEWHz/wf5ECMANvgCvE4efduI
oSwFbdb32UKKzppGW+usUbCgEH++EVNWN7VG8F7bvsnPDmuW2J2p2jjvg76H5eK2
OtnI180JV2Qb80d2lKOS24Mq9edhCzh9AUFsTAfaQ1iBUE4P353G67RF88ZNvV1A
n9DIgbMBf97bByUmp+5MWMXWJ9AcqyXQFsQutEQMudor8P9UqwpCVUkxijpfFxvM
HOBVArYRsdhbjNRGpVAVHdzpJ2AQNTQVeSS7YdzHAzGIVksKHL3K5QJuUJCgNa52
9H5201wSTxSAhlhoPTT06OHmIGiTvXZS
-----END CERTIFICATE-----

View file

@ -8,7 +8,7 @@ class TestConfig < Gem::TestCase
util_make_gems
spec = Gem::Specification.find_by_name("a")
spec.activate
assert_equal "#{spec.full_gem_path}/data/a", Gem.datadir('a')
assert_equal "#{spec.full_gem_path}/data/a", spec.datadir
end
def test_good_rake_path_is_escaped

View file

@ -180,6 +180,35 @@ class TestGem < Gem::TestCase
assert_match 'a-2/bin/exec', Gem.bin_path('a', 'exec', '>= 0')
end
def test_activate_bin_path_resolves_eagerly
a1 = util_spec 'a', '1' do |s|
s.executables = ['exec']
s.add_dependency 'b'
end
b1 = util_spec 'b', '1' do |s|
s.add_dependency 'c', '2'
end
b2 = util_spec 'b', '2' do |s|
s.add_dependency 'c', '1'
end
c1 = util_spec 'c', '1'
c2 = util_spec 'c', '2'
install_specs c1, c2, b1, b2, a1
Gem.activate_bin_path("a", "exec", ">= 0")
# If we didn't eagerly resolve, this would activate c-2 and then the
# finish_resolve would cause a conflict
gem 'c'
Gem.finish_resolve
assert_equal %w(a-1 b-2 c-1), loaded_spec_names
end
def test_self_bin_path_no_exec_name
e = assert_raises ArgumentError do
Gem.bin_path 'a'
@ -275,11 +304,13 @@ class TestGem < Gem::TestCase
expected = File.join @gemhome, 'gems', foo.full_name, 'data', 'foo'
assert_equal expected, Gem.datadir('foo')
assert_equal expected, Gem::Specification.find_by_name("foo").datadir
end
def test_self_datadir_nonexistent_package
assert_nil Gem.datadir('xyzzy')
assert_raises(Gem::MissingSpecError) do
Gem::Specification.find_by_name("xyzzy").datadir
end
end
def test_self_default_exec_format
@ -368,7 +399,7 @@ class TestGem < Gem::TestCase
begin
Dir.chdir 'detect/a/b'
assert_empty Gem.detect_gemdeps
assert_equal add_bundler_full_name([]), Gem.detect_gemdeps.map(&:full_name)
ensure
Dir.chdir @tempdir
end
@ -1068,7 +1099,7 @@ class TestGem < Gem::TestCase
refute Gem.try_activate 'nonexistent'
end
expected = "Ignoring ext-1 because its extensions are not built. " +
expected = "Ignoring ext-1 because its extensions are not built. " +
"Try: gem pristine ext --version 1\n"
assert_equal expected, err
@ -1079,7 +1110,8 @@ class TestGem < Gem::TestCase
orig_path = ENV.delete 'GEM_PATH'
Gem.use_paths nil, nil
assert_equal Gem.default_dir, Gem.paths.home
assert_equal (Gem.default_path + [Gem.paths.home]).uniq, Gem.paths.path
path = (Gem.default_path + [Gem.paths.home]).uniq
assert_equal path, Gem.paths.path
ensure
ENV['GEM_HOME'] = orig_home
ENV['GEM_PATH'] = orig_path
@ -1420,7 +1452,7 @@ class TestGem < Gem::TestCase
Gem.detect_gemdeps
assert_equal %w!a-1 b-1 c-1!, loaded_spec_names
assert_equal add_bundler_full_name(%W(a-1 b-1 c-1)), loaded_spec_names
end
def test_auto_activation_of_detected_gemdeps_file
@ -1443,10 +1475,20 @@ class TestGem < Gem::TestCase
ENV['RUBYGEMS_GEMDEPS'] = "-"
assert_equal [a,b,c], Gem.detect_gemdeps.sort_by { |s| s.name }
expected_specs = [a, b, (Gem::USE_BUNDLER_FOR_GEMDEPS || nil) && util_spec("bundler", Bundler::VERSION), c].compact
assert_equal expected_specs, Gem.detect_gemdeps.sort_by { |s| s.name }
end
LIB_PATH = File.expand_path "../../../lib".dup.untaint, __FILE__.dup.untaint
BUNDLER_LIB_PATH = File.expand_path $LOAD_PATH.find {|lp| File.file?(File.join(lp, "bundler.rb")) }.dup.untaint
BUNDLER_FULL_NAME = "bundler-#{Bundler::VERSION}"
def add_bundler_full_name(names)
return names unless Gem::USE_BUNDLER_FOR_GEMDEPS
names << BUNDLER_FULL_NAME
names.sort!
names
end
def test_looks_for_gemdeps_files_automatically_on_start
util_clear_gems
@ -1466,7 +1508,8 @@ class TestGem < Gem::TestCase
ENV['RUBYGEMS_GEMDEPS'] = "-"
path = File.join @tempdir, "gem.deps.rb"
cmd = [Gem.ruby.dup.untaint, "-I#{LIB_PATH.untaint}", "-rrubygems"]
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(' ')
@ -1508,7 +1551,8 @@ class TestGem < Gem::TestCase
Dir.mkdir "sub1"
path = File.join @tempdir, "gem.deps.rb"
cmd = [Gem.ruby.dup.untaint, "-Csub1", "-I#{LIB_PATH.untaint}", "-rrubygems"]
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(' ')
@ -1603,7 +1647,7 @@ class TestGem < Gem::TestCase
Gem.use_gemdeps gem_deps_file
assert spec.activated?
assert_equal add_bundler_full_name(%W(a-1)), loaded_spec_names
refute_nil Gem.gemdeps
end
@ -1664,7 +1708,7 @@ class TestGem < Gem::TestCase
Gem.use_gemdeps
assert spec.activated?
assert_equal add_bundler_full_name(%W(a-1)), loaded_spec_names
ensure
ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
end
@ -1706,11 +1750,25 @@ class TestGem < Gem::TestCase
io.write 'gem "a"'
end
expected = <<-EXPECTED
platform = Bundler::GemHelpers.generic_local_platform
if platform == Gem::Platform::RUBY
platform = ''
else
platform = " #{platform}"
end
expected = if Gem::USE_BUNDLER_FOR_GEMDEPS
<<-EXPECTED
Could not find gem 'a#{platform}' in any of the gem sources listed in your Gemfile.
You may need to `gem install -g` to install missing gems
EXPECTED
else
<<-EXPECTED
Unable to resolve dependency: user requested 'a (>= 0)'
You may need to `gem install -g` to install missing gems
EXPECTED
EXPECTED
end
assert_output nil, expected do
Gem.use_gemdeps
@ -1735,7 +1793,7 @@ You may need to `gem install -g` to install missing gems
Gem.use_gemdeps
assert spec.activated?
assert_equal add_bundler_full_name(%W(a-1)), loaded_spec_names
ensure
ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
end

View file

@ -0,0 +1,125 @@
# frozen_string_literal: true
require 'rubygems/test_case'
class TestGemBundlerVersionFinder < Gem::TestCase
def setup
@argv = ARGV.dup
@env = ENV.to_hash.clone
ENV.delete("BUNDLER_VERSION")
@dollar_0 = $0
end
def teardown
ARGV.replace @argv
ENV.replace @env
$0 = @dollar_0
end
def bvf
Gem::BundlerVersionFinder
end
def test_bundler_version_defaults_to_nil
assert_nil bvf.bundler_version
end
def test_bundler_version_with_env_var
ENV["BUNDLER_VERSION"] = "1.1.1.1"
assert_equal v("1.1.1.1"), bvf.bundler_version
end
def test_bundler_version_with_bundle_update_bundler
ARGV.replace %w[update --bundler]
assert_nil bvf.bundler_version
$0 = "/foo/bar/bundle"
assert_nil bvf.bundler_version
ARGV.replace %w[update --bundler=1.1.1.1 gem_name]
assert_equal v("1.1.1.1"), bvf.bundler_version
ARGV.replace %w[update --bundler 1.1.1.1 gem_name]
assert_equal v("1.1.1.1"), bvf.bundler_version
ARGV.replace %w[update --bundler\ 1.1.1.1 gem_name]
assert_equal v("1.1.1.1"), bvf.bundler_version
ARGV.replace %w[update --bundler\ 1.1.1.2 --bundler --bundler 1.1.1.1 gem_name]
assert_equal v("1.1.1.1"), bvf.bundler_version
$0 = "other"
assert_nil bvf.bundler_version
end
def test_bundler_version_with_lockfile
bvf.stub(:lockfile_contents, [nil, ""]) do
assert_nil bvf.bundler_version
end
bvf.stub(:lockfile_contents, [nil, "\n\nBUNDLED WITH\n 1.1.1.1\n"]) do
assert_equal v("1.1.1.1"), bvf.bundler_version
end
bvf.stub(:lockfile_contents, [nil, "\n\nBUNDLED WITH\n fjdkslfjdkslfjsldk\n"]) do
assert_nil bvf.bundler_version
end
end
def test_bundler_version_with_reason
assert_nil bvf.bundler_version_with_reason
bvf.stub(:lockfile_contents, [nil, "\n\nBUNDLED WITH\n 1.1.1.1\n"]) do
assert_equal ["1.1.1.1", "your lockfile"], bvf.bundler_version_with_reason
$0 = "bundle"
ARGV.replace %w[update --bundler]
assert_nil bvf.bundler_version_with_reason
ARGV.replace %w[update --bundler=1.1.1.2]
assert_equal ["1.1.1.2", "`bundle update --bundler`"], bvf.bundler_version_with_reason
ENV["BUNDLER_VERSION"] = "1.1.1.3"
assert_equal ["1.1.1.3", "`$BUNDLER_VERSION`"], bvf.bundler_version_with_reason
end
end
def test_compatible
assert bvf.compatible?(util_spec("foo"))
assert bvf.compatible?(util_spec("bundler", 1.1))
bvf.stub(:bundler_version, v("1.1.1.1")) do
assert bvf.compatible?(util_spec("foo"))
assert bvf.compatible?(util_spec("bundler", "1.1.1.1"))
assert bvf.compatible?(util_spec("bundler", "1.1.1.a"))
assert bvf.compatible?(util_spec("bundler", "1.999"))
refute bvf.compatible?(util_spec("bundler", "2.999"))
end
bvf.stub(:bundler_version, v("2.1.1.1")) do
assert bvf.compatible?(util_spec("foo"))
assert bvf.compatible?(util_spec("bundler", "2.1.1.1"))
refute bvf.compatible?(util_spec("bundler", "2.1.1.a"))
refute bvf.compatible?(util_spec("bundler", "1.999"))
refute bvf.compatible?(util_spec("bundler", "2.999"))
end
end
def test_filter
versions = %w[1 1.0 1.0.1.1 2.a 3 3.0]
specs = versions.map { |v| util_spec("bundler", v) }
assert_equal %w[1 1.0 1.0.1.1 2.a 3 3.0], util_filter_specs(specs).map(&:version).map(&:to_s)
bvf.stub(:bundler_version, v("2.1.1.1")) do
assert_empty util_filter_specs(specs).map(&:version).map(&:to_s)
end
bvf.stub(:bundler_version, v("1.1.1.1")) do
assert_equal %w[1 1.0 1.0.1.1], util_filter_specs(specs).map(&:version).map(&:to_s)
end
bvf.stub(:bundler_version, v("1")) do
assert_equal %w[1 1.0 1.0.1.1], util_filter_specs(specs).map(&:version).map(&:to_s)
end
bvf.stub(:bundler_version, v("2.a")) do
assert_equal %w[2.a], util_filter_specs(specs).map(&:version).map(&:to_s)
end
bvf.stub(:bundler_version, v("3")) do
assert_equal %w[3 3.0], util_filter_specs(specs).map(&:version).map(&:to_s)
end
end
def util_filter_specs(specs)
specs = specs.dup
bvf.filter!(specs)
specs
end
end

View file

@ -170,7 +170,7 @@ class TestGemCommand < Gem::TestCase
@cmd.add_option('-f', '--file FILE', 'File option') do |value, options|
options[:help] = true
end
@cmd.add_option('--silent', 'Silence rubygems output') do |value, options|
@cmd.add_option('--silent', 'Silence RubyGems output') do |value, options|
options[:silent] = true
end
assert @cmd.handles?(['-x'])

View file

@ -1,3 +1,4 @@
# frozen_string_literal: true
require 'rubygems/test_case'
require 'rubygems/commands/build_command'
@ -117,5 +118,30 @@ class TestGemCommandsBuildCommand < Gem::TestCase
util_test_build_gem @gem, gemspec_file, false
end
end
CERT_FILE = cert_path 'public3072'
SIGNING_KEY = key_path 'private3072'
def test_build_signed_gem
trust_dir = Gem::Security.trust_dir
spec = util_spec 'some_gem' do |s|
s.signing_key = SIGNING_KEY
s.cert_chain = [CERT_FILE]
end
gemspec_file = File.join(@tempdir, spec.spec_name)
File.open gemspec_file, 'w' do |gs|
gs.write spec.to_ruby
end
util_test_build_gem spec, gemspec_file
trust_dir.trust_cert OpenSSL::X509::Certificate.new(File.read(CERT_FILE))
gem = Gem::Package.new(File.join(@tempdir, spec.file_name),
Gem::Security::HighSecurity)
assert gem.verify
end
end

View file

@ -130,6 +130,70 @@ Added '/CN=alternate/DC=example'
assert_path_exists File.join(@tempdir, 'gem-public_cert.pem')
end
def test_execute_build_bad_email_address
passphrase = 'Foo bar'
email = "nobody@"
@cmd.handle_options %W[--build #{email}]
@build_ui = Gem::MockGemUi.new "#{passphrase}\n#{passphrase}"
use_ui @build_ui do
e = assert_raises Gem::CommandLineError do
@cmd.execute
end
assert_equal "Invalid email address #{email}",
e.message
refute_path_exists File.join(@tempdir, 'gem-private_key.pem')
refute_path_exists File.join(@tempdir, 'gem-public_cert.pem')
end
end
def test_execute_build_expiration_days
passphrase = 'Foo bar'
@cmd.handle_options %W[
--build nobody@example.com
--days 26
]
@build_ui = Gem::MockGemUi.new "#{passphrase}\n#{passphrase}"
use_ui @build_ui do
@cmd.execute
end
output = @build_ui.output.squeeze("\n").split "\n"
assert_equal "Passphrase for your Private Key: ",
output.shift
assert_equal "Please repeat the passphrase for your Private Key: ",
output.shift
assert_equal "Certificate: #{File.join @tempdir, 'gem-public_cert.pem'}",
output.shift
assert_equal "Private Key: #{File.join @tempdir, 'gem-private_key.pem'}",
output.shift
assert_equal "Don't forget to move the key file to somewhere private!",
output.shift
assert_empty output
assert_empty @build_ui.error
assert_path_exists File.join(@tempdir, 'gem-private_key.pem')
assert_path_exists File.join(@tempdir, 'gem-public_cert.pem')
pem = File.read("#{@tempdir}/gem-public_cert.pem")
cert = OpenSSL::X509::Certificate.new(pem)
test = (cert.not_after - cert.not_before).to_i / (24 * 60 * 60)
assert_equal(test, 26)
end
def test_execute_build_bad_passphrase_confirmation
passphrase = 'Foo bar'
passphrase_confirmation = 'Fu bar'

View file

@ -96,6 +96,39 @@ class TestGemCommandsInstallCommand < Gem::TestCase
assert_match "1 gem installed", @ui.output
end
def test_execute_local_transitive_prerelease
specs = spec_fetcher do |fetcher|
fetcher.download 'a', 2, 'b' => "2.a", 'c' => '3'
fetcher.download 'b', '2.a'
fetcher.download 'c', '3'
end
@cmd.options[:domain] = :local
FileUtils.mv specs['a-2'].cache_file, @tempdir
FileUtils.mv specs['b-2.a'].cache_file, @tempdir
FileUtils.mv specs['c-3'].cache_file, @tempdir
@cmd.options[:args] = %w[a]
use_ui @ui do
orig_dir = Dir.pwd
begin
Dir.chdir @tempdir
FileUtils.rm_r [@gemhome, "gems"]
assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
@cmd.execute
end
ensure
Dir.chdir orig_dir
end
end
assert_equal %w[a-2 b-2.a c-3], @cmd.installed_specs.map { |spec| spec.full_name }.sort
assert_match "3 gems installed", @ui.output
end
def test_execute_no_user_install
skip 'skipped on MS Windows (chmod has no effect)' if win_platform?
@ -588,7 +621,7 @@ ERROR: Possible alternatives: non_existent_with_hint
done_installing = true
end
spec = quick_spec 'a', 2
spec = util_spec 'a', 2
util_build_gem spec
@ -616,7 +649,7 @@ ERROR: Possible alternatives: non_existent_with_hint
end
def test_install_gem_ignore_dependencies_specific_file
spec = quick_spec 'a', 2
spec = util_spec 'a', 2
util_build_gem spec

View file

@ -145,7 +145,7 @@ class TestGemCommandsPristineCommand < Gem::TestCase
out = @ui.output.split "\n"
assert_equal 'Restoring gems to pristine condition...', out.shift
assert_equal 'Building native extensions. This could take a while...',
assert_equal 'Building native extensions. This could take a while...',
out.shift
assert_equal "Restored #{a.full_name}", out.shift
assert_empty out, out.inspect

View file

@ -637,6 +637,25 @@ EOF
assert_equal expected, @ui.output
end
def test_execute_show_default_gems_with_platform
a1 = new_default_spec 'a', 1
a1.platform = 'java'
install_default_specs a1
use_ui @ui do
@cmd.execute
end
expected = <<-EOF
*** LOCAL GEMS ***
a (default: 1 java)
EOF
assert_equal expected, @ui.output
end
def test_execute_default_details
spec_fetcher do |fetcher|
fetcher.spec 'a', 2

View file

@ -20,6 +20,13 @@ class TestGemCommandsSetupCommand < Gem::TestCase
open 'lib/rubygems.rb', 'w' do |io| io.puts '# rubygems.rb' end
open 'lib/rubygems/test_case.rb', 'w' do |io| io.puts '# test_case.rb' end
open 'lib/rubygems/ssl_certs/rubygems.org/foo.pem', 'w' do |io| io.puts 'PEM' end
FileUtils.mkdir_p 'bundler/exe'
FileUtils.mkdir_p 'bundler/lib/bundler'
open 'bundler/exe/bundle', 'w' do |io| io.puts '# bundle' end
open 'bundler/lib/bundler.rb', 'w' do |io| io.puts '# bundler.rb' end
open 'bundler/lib/bundler/b.rb', 'w' do |io| io.puts '# b.rb' end
end
def test_pem_files_in
@ -40,12 +47,18 @@ class TestGemCommandsSetupCommand < Gem::TestCase
assert_path_exists File.join(dir, 'rubygems.rb')
assert_path_exists File.join(dir, 'rubygems/ssl_certs/rubygems.org/foo.pem')
if Gem::USE_BUNDLER_FOR_GEMDEPS
assert_path_exists File.join(dir, 'bundler.rb')
assert_path_exists File.join(dir, 'bundler/b.rb')
end
end
end
def test_remove_old_lib_files
lib = File.join @install_dir, 'lib'
lib_rubygems = File.join lib, 'rubygems'
lib_bundler = File.join lib, 'bundler'
lib_rubygems_defaults = File.join lib_rubygems, 'defaults'
securerandom_rb = File.join lib, 'securerandom.rb'
@ -55,13 +68,16 @@ class TestGemCommandsSetupCommand < Gem::TestCase
old_builder_rb = File.join lib_rubygems, 'builder.rb'
old_format_rb = File.join lib_rubygems, 'format.rb'
old_bundler_c_rb = File.join lib_bundler, 'c.rb'
FileUtils.mkdir_p lib_rubygems_defaults
FileUtils.mkdir_p lib_bundler
open securerandom_rb, 'w' do |io| io.puts '# securerandom.rb' end
open old_builder_rb, 'w' do |io| io.puts '# builder.rb' end
open old_format_rb, 'w' do |io| io.puts '# format.rb' end
open old_bundler_c_rb, 'w' do |io| io.puts '# c.rb' end
open engine_defaults_rb, 'w' do |io| io.puts '# jruby.rb' end
open os_defaults_rb, 'w' do |io| io.puts '# operating_system.rb' end
@ -70,6 +86,7 @@ class TestGemCommandsSetupCommand < Gem::TestCase
refute_path_exists old_builder_rb
refute_path_exists old_format_rb
refute_path_exists old_bundler_c_rb if Gem::USE_BUNDLER_FOR_GEMDEPS
assert_path_exists securerandom_rb
assert_path_exists engine_defaults_rb

View file

@ -0,0 +1,95 @@
# frozen_string_literal: true
require 'rubygems/test_case'
require 'rubygems/commands/signin_command'
require 'rubygems/installer'
class TestGemCommandsSigninCommand < Gem::TestCase
def setup
super
Gem.configuration.rubygems_api_key = nil
Gem.configuration.api_keys.clear
@cmd = Gem::Commands::SigninCommand.new
end
def teardown
credentials_path = Gem.configuration.credentials_path
File.delete(credentials_path) if File.exist?(credentials_path)
super
end
def test_execute_when_not_already_signed_in
sign_in_ui = util_capture() { @cmd.execute }
assert_match %r{Signed in.}, sign_in_ui.output
end
def test_execute_when_already_signed_in_with_same_host
host = 'http://some-gemcutter-compatible-host.org'
sign_in_ui = util_capture(nil, host) { @cmd.execute }
old_credentials = YAML.load_file Gem.configuration.credentials_path
sign_in_ui = util_capture(nil, host) { @cmd.execute }
new_credentials = YAML.load_file Gem.configuration.credentials_path
assert_equal old_credentials[host], new_credentials[host]
end
def test_execute_when_already_signed_in_with_different_host
api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf04045xxxx'
sign_in_ui = util_capture(nil, nil, api_key) { @cmd.execute }
host = 'http://some-gemcutter-compatible-host.org'
sign_in_ui = util_capture(nil, host, api_key) { @cmd.execute }
credentials = YAML.load_file Gem.configuration.credentials_path
assert_equal credentials[:rubygems_api_key], api_key
assert_equal credentials[host], nil
end
def test_execute_with_host_supplied
host = 'http://some-gemcutter-compatible-host.org'
sign_in_ui = util_capture(nil, host) { @cmd.execute }
assert_match %r{Enter your #{host} credentials.}, sign_in_ui.output
assert_match %r{Signed in.}, sign_in_ui.output
api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903'
credentials = YAML.load_file Gem.configuration.credentials_path
assert_equal api_key, credentials[host]
end
def test_execute_with_valid_creds_set_for_default_host
util_capture {@cmd.execute}
api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903'
credentials = YAML.load_file Gem.configuration.credentials_path
assert_equal api_key, credentials[:rubygems_api_key]
end
# Utility method to capture IO/UI within the block passed
def util_capture ui_stub = nil, host = nil, api_key = nil
api_key ||= 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903'
response = [api_key, 200, 'OK']
email = 'you@example.com'
password = 'secret'
fetcher = Gem::FakeFetcher.new
# Set the expected response for the Web-API supplied
ENV['RUBYGEMS_HOST'] = host || Gem::DEFAULT_HOST
data_key = "#{ENV['RUBYGEMS_HOST']}/api/v1/api_key"
fetcher.data[data_key] = response
Gem::RemoteFetcher.fetcher = fetcher
sign_in_ui = ui_stub || Gem::MockGemUi.new("#{email}\n#{password}\n")
use_ui sign_in_ui do
yield
end
sign_in_ui
end
end

View file

@ -0,0 +1,37 @@
# frozen_string_literal: true
require 'rubygems/test_case'
require 'rubygems/commands/signout_command'
require 'rubygems/installer'
class TestGemCommandsSignoutCommand < Gem::TestCase
def setup
super
@cmd = Gem::Commands::SignoutCommand.new
end
def teardown
super
File.delete Gem.configuration.credentials_path if File.exist?(Gem.configuration.credentials_path)
end
def test_execute_when_user_is_signed_in
FileUtils.mkdir_p File.dirname(Gem.configuration.credentials_path)
FileUtils::touch Gem.configuration.credentials_path
@sign_out_ui = Gem::MockGemUi.new
use_ui(@sign_out_ui) { @cmd.execute }
assert_match %r{You have successfully signed out}, @sign_out_ui.output
assert_equal false, File.exist?(Gem.configuration.credentials_path)
end
def test_execute_when_not_signed_in # i.e. no credential file created
@sign_out_ui = Gem::MockGemUi.new
use_ui(@sign_out_ui) { @cmd.execute }
assert_match %r{You are not currently signed in}, @sign_out_ui.error
end
end

View file

@ -279,5 +279,17 @@ WARNING: Use your OS package manager to uninstall vendor gems
RbConfig::CONFIG['vendordir'] = orig_vendordir
end
def test_execute_with_gem_not_installed
@cmd.options[:args] = ['d']
use_ui ui do
@cmd.execute
end
output = ui.output.split "\n"
assert_equal output.first, "Gem 'd' is not installed"
end
end

View file

@ -107,7 +107,7 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
end
out = @ui.output.split "\n"
assert_equal "Latest version currently installed. Aborting.", out.shift
assert_equal "Latest version already installed. Done.", out.shift
assert_empty out
end

View file

@ -33,7 +33,7 @@ class TestGemCommandsWhichCommand < Gem::TestCase
end
assert_equal '', @ui.output
assert_match %r%Can.t find ruby library file or shared library directory\n%,
assert_match %r%Can.t find Ruby library file or shared library directory\n%,
@ui.error
end
@ -51,7 +51,7 @@ class TestGemCommandsWhichCommand < Gem::TestCase
end
assert_equal "#{@foo_bar.full_gem_path}/lib/foo_bar.rb\n", @ui.output
assert_match %r%Can.t find ruby library file or shared library missinglib\n%,
assert_match %r%Can.t find Ruby library file or shared library missinglib\n%,
@ui.error
end
@ -65,7 +65,7 @@ class TestGemCommandsWhichCommand < Gem::TestCase
end
assert_equal '', @ui.output
assert_match %r%Can.t find ruby library file or shared library missinglib\n%,
assert_match %r%Can.t find Ruby library file or shared library missinglib\n%,
@ui.error
end

View file

@ -338,6 +338,34 @@ class TestGemDependency < Gem::TestCase
assert_match "Could not find 'a' (= 2.0) - did find: [a-1.0]", e.message
end
def test_to_specs_respects_bundler_version
b = util_spec 'bundler', '2.0.0.pre.1'
b_1 = util_spec 'bundler', '1'
install_specs b, b_1
b_file = File.join b.gem_dir, 'lib', 'bundler', 'setup.rb'
write_file b_file do |io|
io.puts '# setup.rb'
end
dep = Gem::Dependency.new "bundler", ">= 0.a"
assert_equal [b, b_1], dep.to_specs
Gem::BundlerVersionFinder.stub(:bundler_version_with_reason, ["3.5", "reason"]) do
e = assert_raises Gem::MissingSpecVersionError do
dep.to_specs
end
assert_match "Could not find 'bundler' (3.5) required by reason.\nTo update to the lastest version installed on your system, run `bundle update --bundler`.\nTo install the missing version, run `gem install bundler:3.5`\n", e.message
end
Gem::BundlerVersionFinder.stub(:bundler_version_with_reason, ["2.0.0.pre.1", "reason"]) do
assert_equal [b], dep.to_specs
end
end
def test_to_specs_indicates_total_gem_set_size
a = util_spec 'a', '1.0'
install_specs a

View file

@ -239,7 +239,7 @@ install:
assert_match(/\AERROR: Failed to build gem native extension.$/, e.message)
assert_equal "Building native extensions. This could take a while...\n",
assert_equal "Building native extensions. This could take a while...\n",
@ui.output
assert_equal '', @ui.error
@ -272,7 +272,7 @@ install:
assert_match(/^\s*No builder for extension ''$/, e.message)
assert_equal "Building native extensions. This could take a while...\n",
assert_equal "Building native extensions. This could take a while...\n",
@ui.output
assert_equal '', @ui.error

View file

@ -121,9 +121,10 @@ class TestGemInstallUpdateOptions < Gem::InstallerTestCase
def test_security_policy_unknown
@cmd.add_install_update_options
assert_raises OptionParser::InvalidArgument do
e = assert_raises OptionParser::InvalidArgument do
@cmd.handle_options %w[-P UnknownSecurity]
end
assert_includes e.message, "UnknownSecurity"
end
def test_user_install_enabled

View file

@ -87,7 +87,7 @@ end
end
util_make_exec
@installer.gem_dir = util_gem_dir @spec
@installer.gem_dir = @spec.gem_dir
@installer.wrappers = true
@installer.generate_bin
@ -304,7 +304,7 @@ gem 'other', version
def test_extract_files
@installer.extract_files
assert_path_exists File.join util_gem_dir, 'bin/executable'
assert_path_exists File.join @spec.gem_dir, 'bin/executable'
end
def test_generate_bin_bindir
@ -314,12 +314,12 @@ gem 'other', version
@spec.bindir = '.'
exec_file = @installer.formatted_program_filename 'executable'
exec_path = File.join util_gem_dir(@spec), exec_file
exec_path = File.join @spec.gem_dir, exec_file
File.open exec_path, 'w' do |f|
f.puts '#!/usr/bin/ruby'
end
@installer.gem_dir = util_gem_dir
@installer.gem_dir = @spec.gem_dir
@installer.generate_bin
@ -355,7 +355,7 @@ gem 'other', version
def test_generate_bin_script
@installer.wrappers = true
util_make_exec
@installer.gem_dir = util_gem_dir
@installer.gem_dir = @spec.gem_dir
@installer.generate_bin
assert File.directory? util_inst_bindir
@ -371,7 +371,7 @@ gem 'other', version
@installer.format_executable = true
@installer.wrappers = true
util_make_exec
@installer.gem_dir = util_gem_dir
@installer.gem_dir = @spec.gem_dir
Gem::Installer.exec_format = 'foo-%s-bar'
@installer.generate_bin
@ -385,7 +385,7 @@ gem 'other', version
def test_generate_bin_script_format_disabled
@installer.wrappers = true
util_make_exec
@installer.gem_dir = util_gem_dir
@installer.gem_dir = @spec.gem_dir
Gem::Installer.exec_format = 'foo-%s-bar'
@installer.generate_bin
@ -474,10 +474,10 @@ gem 'other', version
def test_generate_bin_script_wrappers
@installer.wrappers = true
util_make_exec
@installer.gem_dir = util_gem_dir
@installer.gem_dir = @spec.gem_dir
installed_exec = File.join(util_inst_bindir, 'executable')
real_exec = File.join util_gem_dir, 'bin', 'executable'
real_exec = File.join @spec.gem_dir, 'bin', 'executable'
# fake --no-wrappers for previous install
unless Gem.win_platform? then
@ -501,13 +501,13 @@ gem 'other', version
@installer.wrappers = false
util_make_exec
@installer.gem_dir = util_gem_dir
@installer.gem_dir = @spec.gem_dir
@installer.generate_bin
assert_equal true, File.directory?(util_inst_bindir)
installed_exec = File.join util_inst_bindir, 'executable'
assert_equal true, File.symlink?(installed_exec)
assert_equal(File.join(util_gem_dir, 'bin', 'executable'),
assert_equal(File.join(@spec.gem_dir, 'bin', 'executable'),
File.readlink(installed_exec))
end
@ -523,7 +523,7 @@ gem 'other', version
def test_generate_bin_symlink_no_perms
@installer.wrappers = false
util_make_exec
@installer.gem_dir = util_gem_dir
@installer.gem_dir = @spec.gem_dir
Dir.mkdir util_inst_bindir
@ -545,11 +545,11 @@ gem 'other', version
@installer.wrappers = false
util_make_exec
@installer.gem_dir = util_gem_dir
@installer.gem_dir = @spec.gem_dir
@installer.generate_bin
installed_exec = File.join(util_inst_bindir, 'executable')
assert_equal(File.join(util_gem_dir, 'bin', 'executable'),
assert_equal(File.join(@spec.gem_dir, 'bin', 'executable'),
File.readlink(installed_exec))
@spec = Gem::Specification.new do |s|
@ -562,7 +562,7 @@ gem 'other', version
end
util_make_exec
@installer.gem_dir = util_gem_dir @spec
@installer.gem_dir = @spec.gem_dir
@installer.generate_bin
installed_exec = File.join(util_inst_bindir, 'executable')
assert_equal(@spec.bin_file('executable'),
@ -575,11 +575,11 @@ gem 'other', version
@installer.wrappers = false
util_make_exec
@installer.gem_dir = util_gem_dir
@installer.gem_dir = @spec.gem_dir
@installer.generate_bin
installed_exec = File.join(util_inst_bindir, 'executable')
assert_equal(File.join(util_gem_dir, 'bin', 'executable'),
assert_equal(File.join(@spec.gem_dir, 'bin', 'executable'),
File.readlink(installed_exec))
spec = Gem::Specification.new do |s|
@ -595,12 +595,12 @@ gem 'other', version
one = @spec.dup
one.version = 1
@installer = Gem::Installer.for_spec spec
@installer.gem_dir = util_gem_dir one
@installer.gem_dir = one.gem_dir
@installer.generate_bin
installed_exec = File.join util_inst_bindir, 'executable'
expected = File.join util_gem_dir, 'bin', 'executable'
expected = File.join @spec.gem_dir, 'bin', 'executable'
assert_equal(expected,
File.readlink(installed_exec),
"Ensure symlink not moved")
@ -611,7 +611,7 @@ gem 'other', version
@installer.wrappers = true
util_make_exec
@installer.gem_dir = util_gem_dir
@installer.gem_dir = @spec.gem_dir
@installer.generate_bin
@ -630,7 +630,7 @@ gem 'other', version
util_installer @spec, @gemhome
@installer.wrappers = false
@installer.gem_dir = util_gem_dir
@installer.gem_dir = @spec.gem_dir
@installer.generate_bin
@ -648,7 +648,7 @@ gem 'other', version
File.const_set(:ALT_SEPARATOR, '\\')
@installer.wrappers = false
util_make_exec
@installer.gem_dir = util_gem_dir
@installer.gem_dir = @spec.gem_dir
use_ui @ui do
@installer.generate_bin
@ -1421,10 +1421,11 @@ gem 'other', version
def test_pre_install_checks_ruby_version
use_ui @ui do
installer = Gem::Installer.at old_ruby_required
e = assert_raises Gem::InstallError do
e = assert_raises Gem::RuntimeRequirementNotMetError do
installer.pre_install_checks
end
assert_equal 'old_ruby_required requires Ruby version = 1.4.6.',
rv = Gem.ruby_api_version
assert_equal "old_ruby_required requires Ruby version = 1.4.6. The current ruby version is #{rv}.",
e.message
end
end
@ -1440,10 +1441,11 @@ gem 'other', version
use_ui @ui do
@installer = Gem::Installer.at gem
e = assert_raises Gem::InstallError do
e = assert_raises Gem::RuntimeRequirementNotMetError do
@installer.pre_install_checks
end
assert_equal 'old_rubygems_required requires RubyGems version < 0. ' +
rgv = Gem::VERSION
assert_equal "old_rubygems_required requires RubyGems version < 0. The current RubyGems version is #{rgv}. " +
"Try 'gem update --system' to update RubyGems itself.", e.message
end
end
@ -1739,7 +1741,7 @@ gem 'other', version
@installer.wrappers = true
@installer.options[:install_as_default] = true
@installer.gem_dir = util_gem_dir @spec
@installer.gem_dir = @spec.gem_dir
@installer.generate_bin
use_ui @ui do

View file

@ -1,4 +1,4 @@
# coding: UTF-8
# coding: utf-8
# frozen_string_literal: true
require 'rubygems/package/tar_test_case'
@ -84,7 +84,7 @@ class TestGemPackage < Gem::Package::TarTestCase
io.write spec.to_yaml
end
metadata_sha1 = Digest::SHA1.hexdigest s.string
metadata_sha256 = Digest::SHA256.hexdigest s.string
metadata_sha512 = Digest::SHA512.hexdigest s.string
expected = {
@ -95,9 +95,9 @@ class TestGemPackage < Gem::Package::TarTestCase
}
if defined?(OpenSSL::Digest) then
expected['SHA1'] = {
'metadata.gz' => metadata_sha1,
'data.tar.gz' => Digest::SHA1.hexdigest(tar),
expected['SHA256'] = {
'metadata.gz' => metadata_sha256,
'data.tar.gz' => Digest::SHA256.hexdigest(tar),
}
end

View file

@ -555,7 +555,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
nil
end
assert_equal nil, fetcher.fetch_path(@uri + 'foo.gz', Time.at(0))
assert_nil fetcher.fetch_path(@uri + 'foo.gz', Time.at(0))
end
def test_fetch_path_io_error
@ -621,7 +621,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
nil
end
assert_equal nil, fetcher.fetch_path(URI.parse(@gem_repo), Time.at(0))
assert_nil fetcher.fetch_path(URI.parse(@gem_repo), Time.at(0))
end
def test_implicit_no_proxy

View file

@ -753,7 +753,7 @@ end
@gda.ruby RUBY_VERSION, :engine => 'jruby', :engine_version => '1.7.4'
end
assert_equal 'Your ruby engine is ruby, but your gem.deps.rb requires jruby',
assert_equal 'Your Ruby engine is ruby, but your gem.deps.rb requires jruby',
e.message
end
end
@ -764,7 +764,7 @@ end
@gda.ruby RUBY_VERSION, :engine => 'jruby', :engine_version => '1.7.4'
end
assert_equal 'Your ruby engine version is jruby 1.7.6, but your gem.deps.rb requires jruby 1.7.4',
assert_equal 'Your Ruby engine version is jruby 1.7.6, but your gem.deps.rb requires jruby 1.7.4',
e.message
end
end
@ -774,7 +774,7 @@ end
@gda.ruby RUBY_VERSION, :engine => 'jruby'
end
assert_equal 'you must specify engine_version along with the ruby engine',
assert_equal 'You must specify engine_version along with the Ruby engine',
e.message
end

View file

@ -30,6 +30,12 @@ class TestGemRequirement < Gem::TestCase
assert_requirement_equal "= 2", v(2)
end
def test_create
assert_equal req("= 1"), Gem::Requirement.create("= 1")
assert_equal req(">= 1.2", "<= 1.3"), Gem::Requirement.create([">= 1.2", "<= 1.3"])
assert_equal req(">= 1.2", "<= 1.3"), Gem::Requirement.create(">= 1.2", "<= 1.3")
end
def test_empty_requirements_is_none
r = Gem::Requirement.new
assert_equal true, r.none?

View file

@ -683,6 +683,32 @@ class TestGemResolver < Gem::TestCase
assert_resolves_to [b1, c1, d2], r
end
def test_sorts_by_source_then_version
sourceA = Gem::Source.new 'http://example.com/a'
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'
set = StaticSet.new [
Gem::Resolver::SpecSpecification.new(nil, spec_B_1, sourceB),
Gem::Resolver::SpecSpecification.new(nil, spec_B_2, sourceB),
Gem::Resolver::SpecSpecification.new(nil, spec_C_1, sourceC),
Gem::Resolver::SpecSpecification.new(nil, spec_A_2, sourceA),
Gem::Resolver::SpecSpecification.new(nil, spec_A_1, sourceA),
]
dependency = make_dep 'some-dep', '> 0'
resolver = Gem::Resolver.new [dependency], set
assert_resolves_to [spec_B_2], resolver
end
def test_select_local_platforms
r = Gem::Resolver.new nil, nil

View file

@ -15,7 +15,7 @@ class TestGemResolverConflict < Gem::TestCase
dep = Gem::Resolver::DependencyRequest.new dep('net-ssh', '>= 2.0.13'), nil
spec = quick_spec 'net-ssh', '2.2.2'
spec = util_spec 'net-ssh', '2.2.2'
active =
Gem::Resolver::ActivationRequest.new spec, dep

View file

@ -61,6 +61,7 @@ class TestGemSecurity < Gem::TestCase
cert = @SEC.create_cert_self_signed subject, PRIVATE_KEY, 60
assert_equal '/CN=nobody/DC=example', cert.issuer.to_s
assert_equal "sha256WithRSAEncryption", cert.signature_algorithm
end
def test_class_create_cert_email
@ -120,6 +121,7 @@ class TestGemSecurity < Gem::TestCase
end
def test_class_re_sign
assert_equal "sha1WithRSAEncryption", EXPIRED_CERT.signature_algorithm
re_signed = Gem::Security.re_sign EXPIRED_CERT, PRIVATE_KEY, 60
assert_in_delta Time.now, re_signed.not_before, 10
@ -127,6 +129,7 @@ class TestGemSecurity < Gem::TestCase
assert_equal EXPIRED_CERT.serial + 1, re_signed.serial
assert re_signed.verify PUBLIC_KEY
assert_equal "sha256WithRSAEncryption", re_signed.signature_algorithm
end
def test_class_re_sign_not_self_signed
@ -218,6 +221,8 @@ class TestGemSecurity < Gem::TestCase
assert_in_delta Time.now, signed.not_before, 10
assert_in_delta Time.now + 60, signed.not_after, 10
assert_equal "sha256WithRSAEncryption", signed.signature_algorithm
assert_equal 5, signed.extensions.length,
signed.extensions.map { |e| e.to_a.first }

View file

@ -1,4 +1,4 @@
# coding: UTF-8
# coding: utf-8
# frozen_string_literal: true
require 'rubygems/test_case'
@ -34,7 +34,7 @@ class TestGemSecurityPolicy < Gem::TestCase
s.files = %w[lib/code.rb]
end
@sha1 = OpenSSL::Digest::SHA1
@digest = Gem::Security::DIGEST_ALGORITHM
@trust_dir = Gem::Security.trust_dir.dir # HACK use the object
@no = Gem::Security::NoSecurity
@ -69,7 +69,7 @@ class TestGemSecurityPolicy < Gem::TestCase
signature = sign data
assert @almost_no.check_data(PUBLIC_KEY, @sha1, signature, data)
assert @almost_no.check_data(PUBLIC_KEY, @digest, signature, data)
end
def test_check_data_invalid
@ -80,7 +80,7 @@ class TestGemSecurityPolicy < Gem::TestCase
invalid = digest 'hello!'
e = assert_raises Gem::Security::Exception do
@almost_no.check_data PUBLIC_KEY, @sha1, signature, invalid
@almost_no.check_data PUBLIC_KEY, @digest, signature, invalid
end
assert_equal 'invalid signature', e.message
@ -238,18 +238,18 @@ class TestGemSecurityPolicy < Gem::TestCase
def test_check_trust
Gem::Security.trust_dir.trust_cert PUBLIC_CERT
assert @high.check_trust [PUBLIC_CERT], @sha1, @trust_dir
assert @high.check_trust [PUBLIC_CERT], @digest, @trust_dir
end
def test_check_trust_child
Gem::Security.trust_dir.trust_cert PUBLIC_CERT
assert @high.check_trust [PUBLIC_CERT, CHILD_CERT], @sha1, @trust_dir
assert @high.check_trust [PUBLIC_CERT, CHILD_CERT], @digest, @trust_dir
end
def test_check_trust_empty_chain
e = assert_raises Gem::Security::Exception do
@chain.check_trust [], @sha1, @trust_dir
@chain.check_trust [], @digest, @trust_dir
end
assert_equal 'missing root certificate', e.message
@ -259,7 +259,7 @@ class TestGemSecurityPolicy < Gem::TestCase
Gem::Security.trust_dir.trust_cert PUBLIC_CERT
e = assert_raises Gem::Security::Exception do
@high.check_trust [WRONG_KEY_CERT], @sha1, @trust_dir
@high.check_trust [WRONG_KEY_CERT], @digest, @trust_dir
end
assert_equal "trusted root certificate #{PUBLIC_CERT.subject} checksum " +
@ -268,7 +268,7 @@ class TestGemSecurityPolicy < Gem::TestCase
def test_check_trust_no_chain
e = assert_raises Gem::Security::Exception do
@chain.check_trust nil, @sha1, @trust_dir
@chain.check_trust nil, @digest, @trust_dir
end
assert_equal 'missing signing chain', e.message
@ -276,7 +276,7 @@ class TestGemSecurityPolicy < Gem::TestCase
def test_check_trust_no_trust
e = assert_raises Gem::Security::Exception do
@high.check_trust [PUBLIC_CERT], @sha1, @trust_dir
@high.check_trust [PUBLIC_CERT], @digest, @trust_dir
end
assert_equal "root cert #{PUBLIC_CERT.subject} is not trusted", e.message
@ -284,7 +284,7 @@ class TestGemSecurityPolicy < Gem::TestCase
def test_check_trust_no_trust_child
e = assert_raises Gem::Security::Exception do
@high.check_trust [PUBLIC_CERT, CHILD_CERT], @sha1, @trust_dir
@high.check_trust [PUBLIC_CERT, CHILD_CERT], @digest, @trust_dir
end
assert_equal "root cert #{PUBLIC_CERT.subject} is not trusted " +
@ -370,7 +370,7 @@ class TestGemSecurityPolicy < Gem::TestCase
data = digest 'goodbye'
signatures[1] = PRIVATE_KEY.sign @sha1.new, data.digest
signatures[1] = PRIVATE_KEY.sign @digest.new, data.digest
e = assert_raises Gem::Security::Exception do
@almost_no.verify [PUBLIC_CERT], nil, digests, signatures
@ -453,17 +453,17 @@ class TestGemSecurityPolicy < Gem::TestCase
metadata_gz = Gem.gzip @spec.to_yaml
package = Gem::Package.new 'nonexistent.gem'
package.checksums['SHA1'] = {}
package.checksums[Gem::Security::DIGEST_NAME] = {}
s = StringIO.new metadata_gz
def s.full_name() 'metadata.gz' end
digests = package.digest s
metadata_gz_digest = digests['SHA1']['metadata.gz']
metadata_gz_digest = digests[Gem::Security::DIGEST_NAME]['metadata.gz']
signatures = {}
signatures['metadata.gz'] =
PRIVATE_KEY.sign @sha1.new, metadata_gz_digest.digest
PRIVATE_KEY.sign @digest.new, metadata_gz_digest.digest
assert @high.verify_signatures @spec, digests, signatures
end
@ -476,19 +476,19 @@ class TestGemSecurityPolicy < Gem::TestCase
metadata_gz = Gem.gzip @spec.to_yaml
package = Gem::Package.new 'nonexistent.gem'
package.checksums['SHA1'] = {}
package.checksums[Gem::Security::DIGEST_NAME] = {}
s = StringIO.new metadata_gz
def s.full_name() 'metadata.gz' end
digests = package.digest s
digests['SHA1']['data.tar.gz'] = OpenSSL::Digest.new 'SHA1', 'hello'
digests[Gem::Security::DIGEST_NAME]['data.tar.gz'] = @digest.new 'hello'
metadata_gz_digest = digests['SHA1']['metadata.gz']
metadata_gz_digest = digests[Gem::Security::DIGEST_NAME]['metadata.gz']
signatures = {}
signatures['metadata.gz'] =
PRIVATE_KEY.sign @sha1.new, metadata_gz_digest.digest
PRIVATE_KEY.sign @digest.new, metadata_gz_digest.digest
e = assert_raises Gem::Security::Exception do
@high.verify_signatures @spec, digests, signatures
@ -505,13 +505,13 @@ class TestGemSecurityPolicy < Gem::TestCase
metadata_gz = Gem.gzip @spec.to_yaml
package = Gem::Package.new 'nonexistent.gem'
package.checksums['SHA1'] = {}
package.checksums[Gem::Security::DIGEST_NAME] = {}
s = StringIO.new metadata_gz
def s.full_name() 'metadata.gz' end
digests = package.digest s
digests['SHA1']['data.tar.gz'] = OpenSSL::Digest.new 'SHA1', 'hello'
digests[Gem::Security::DIGEST_NAME]['data.tar.gz'] = @digest.new 'hello'
assert_raises Gem::Security::Exception do
@high.verify_signatures @spec, digests, {}
@ -519,19 +519,19 @@ class TestGemSecurityPolicy < Gem::TestCase
end
def digest data
digester = @sha1.new
digester = @digest.new
digester << data
digester
end
def sign data, key = PRIVATE_KEY
key.sign @sha1.new, data.digest
key.sign @digest.new, data.digest
end
def dummy_signatures key = PRIVATE_KEY
data = digest 'hello'
digests = { 'SHA1' => { 0 => data } }
digests = { Gem::Security::DIGEST_NAME => { 0 => data } }
signatures = { 0 => sign(data, key) }
return digests, signatures

View file

@ -121,12 +121,12 @@ class TestGemSecuritySigner < Gem::TestCase
signature = signer.sign 'hello'
expected = <<-EXPECTED
pxSf9ScaghbMNmNp8fqSJj7BiIGpbuoOVYCOM3TJNH9STLILA5z3xKp3gM6w
VJ7aGsh9KCP485ftS3J9Kb/lKJsyoSkkRSQ5QG+LnyZwMuWlThPDR5o7q6al
0oxE7vvbbqxFqcT4ojWIkwxJxOluFWmt2D8I6QTX2vLAn09y+Kl66AOrT7R5
UinbXkz04VwcNvkBqJyko3yWxFKiGNpntZQg4jIw4L+h97EOaZp8H96udzQH
Da3K0YZ6FsqLDFNnWAFhve3kmpE3CludpvDqH0piq0zKqnOiqAcvICIpPaJP
c7NM7KZZjj7G++SXjYTEI1PHSA7aFQ/i/+qSUvx+Pg==
cHze2sEfRysoUMCfGVAx/7o8jxj5liJJ2ptNxe2jf3l+EZvyjdqpXo9Ndzxx
6xLp2rxLG4K2//ip4aCH5Sh7hnia+F5u6iuLBETPlklPrmw5dnuKZxolz+vM
0O1aOZsQHcVzQoESTGjkms3KZk+gn3lg0sSBbAV5/LyDYoHCEjxlcA5D+Olb
rDmRyBMOnMS+q489OZ5Hr6B2YJJ3QbUwIZNhUeNmOxIBEYTrrKkZ92qkxbRN
qhlqFP4jR6zXFeyBCOr0KpTiWBNuxBFXDsxmhGyt2BOIjD6qmKn7RSIfYg/U
toqvglr0kdbknSRRjBVLK6tsgr07aLT9gNP7mTW2PA==
EXPECTED
assert_equal expected, [signature].pack('m')

View file

@ -18,7 +18,7 @@ class TestGemSecurityTrustDir < Gem::TestCase
end
def test_cert_path
digest = OpenSSL::Digest::SHA1.hexdigest PUBLIC_CERT.subject.to_s
digest = Gem::Security::DIGEST_ALGORITHM.hexdigest PUBLIC_CERT.subject.to_s
expected = File.join @dest_dir, "cert-#{digest}.pem"
@ -42,7 +42,7 @@ class TestGemSecurityTrustDir < Gem::TestCase
end
def test_name_path
digest = OpenSSL::Digest::SHA1.hexdigest PUBLIC_CERT.subject.to_s
digest = Gem::Security::DIGEST_ALGORITHM.hexdigest PUBLIC_CERT.subject.to_s
expected = File.join @dest_dir, "cert-#{digest}.pem"

View file

@ -222,7 +222,7 @@ class TestGemServer < Gem::TestCase
assert_equal 404, @res.status, @res.body
assert_match %r| \d\d:\d\d:\d\d |, @res['date']
assert_equal 'text/plain', @res['content-type']
assert_equal 'No gems found matching "z" "9" nil', @res.body
assert_equal 'No gems found matching "z-9"', @res.body
assert_equal 404, @res.status
end
@ -291,6 +291,23 @@ class TestGemServer < Gem::TestCase
assert_equal v('3.a'), spec.version
end
def test_quick_marshal_a_b_1_3_a_gemspec_rz
quick_gem 'a-b-1', '3.a'
data = StringIO.new "GET /quick/Marshal.#{Gem.marshal_version}/a-b-1-3.a.gemspec.rz HTTP/1.0\r\n\r\n"
@req.parse data
@server.quick @req, @res
assert_equal 200, @res.status, @res.body
assert @res['date']
assert_equal 'application/x-deflate', @res['content-type']
spec = Marshal.load Gem.inflate(@res.body)
assert_equal 'a-b-1', spec.name
assert_equal v('3.a'), spec.version
end
def test_rdoc
data = StringIO.new "GET /rdoc?q=a HTTP/1.0\r\n\r\n"
@req.parse data

View file

@ -228,6 +228,15 @@ class TestGemSource < Gem::TestCase
assert_equal(-1, remote. <=>(no_uri), 'remote <=> no_uri')
end
def test_spaceship_order_is_preserved_when_uri_differs
sourceA = Gem::Source.new "http://example.com/a"
sourceB = Gem::Source.new "http://example.com/b"
assert_equal( 0, sourceA. <=>(sourceA), 'sourceA <=> sourceA')
assert_equal( 1, sourceA. <=>(sourceB), 'sourceA <=> sourceB')
assert_equal( 1, sourceB. <=>(sourceA), 'sourceB <=> sourceA')
end
def test_update_cache_eh
assert @source.update_cache?
end

View file

@ -169,6 +169,26 @@ class TestGemSpecFetcher < Gem::TestCase
assert_equal "bad news from the internet (#{@gem_repo})", sfp.error.message
end
def test_suggest_gems_from_name_latest
spec_fetcher do|fetcher|
fetcher.spec 'example', 1
fetcher.spec 'other-example', 1
end
suggestions = @sf.suggest_gems_from_name('examplw')
assert_equal ['example'], suggestions
end
def test_suggest_gems_from_name_prerelease
spec_fetcher do|fetcher|
fetcher.spec 'example', '1.a'
fetcher.spec 'other-example', 1
end
suggestions = @sf.suggest_gems_from_name('examplw')
assert_equal ['example'], suggestions
end
def test_available_specs_latest
spec_fetcher do |fetcher|
fetcher.spec 'a', 1

View file

@ -1586,7 +1586,7 @@ dependencies: []
refute @ext.contains_requirable_file? 'nonexistent'
end
expected = "Ignoring ext-1 because its extensions are not built. " +
expected = "Ignoring ext-1 because its extensions are not built. " +
"Try: gem pristine ext --version 1\n"
assert_equal expected, err
@ -2748,14 +2748,6 @@ duplicate dependency on c (>= 1.2.3, development), (~> 1.2) use:
util_setup_validate
Dir.chdir @tempdir do
@a1.email = ""
use_ui @ui do
@a1.validate
end
assert_match "#{w}: no email specified\n", @ui.error, "error"
@a1.email = "FIxxxXME (your e-mail)".sub(/xxx/, "")
e = assert_raises Gem::InvalidSpecificationException do
@ -2977,6 +2969,43 @@ Did you mean 'Ruby'?
warning
end
def test_validate_empty_files
util_setup_validate
use_ui @ui do
# we have to set all of these for #files to be empty
@a1.files = []
@a1.test_files = []
@a1.executables = []
@a1.validate
end
assert_match "no files specified", @ui.error
end
def test_validate_empty_homepage
util_setup_validate
use_ui @ui do
@a1.homepage = nil
@a1.validate
end
assert_match "no homepage specified", @ui.error
end
def test_validate_empty_summary
util_setup_validate
use_ui @ui do
@a1.summary = nil
@a1.validate
end
assert_match "no summary specified", @ui.error
end
def test_validate_name
util_setup_validate
@ -3252,7 +3281,11 @@ Did you mean 'Ruby'?
Dir.chdir @tempdir do
@m1 = quick_gem 'm', '1' do |s|
s.files = %w[lib/code.rb]
s.metadata = { 'one' => "two", 'two' => "three" }
s.metadata = {
"one" => "two",
"home" => "three",
"homepage_uri" => "https://example.com/user/repo"
}
end
use_ui @ui do
@ -3329,6 +3362,23 @@ Did you mean 'Ruby'?
end
end
def test_metadata_link_validation_fails
util_setup_validate
Dir.chdir @tempdir do
@m2 = quick_gem 'm', '2' do |s|
s.files = %w[lib/code.rb]
s.metadata = { 'homepage_uri' => 'http:/example.com' }
end
e = assert_raises Gem::InvalidSpecificationException do
@m2.validate
end
assert_equal "metadata['homepage_uri'] has invalid link: \"http:/example.com\"", e.message
end
end
def test_metadata_specs
valid_ruby_spec = <<-EOF
# -*- encoding: utf-8 -*-
@ -3406,6 +3456,31 @@ end
refute @a1.missing_extensions?
end
def test_find_all_by_full_name
pl = Gem::Platform.new 'i386-linux'
a1 = util_spec "a", "1"
a1_pre = util_spec "a", "1.0.0.pre.1"
a_1_platform = util_spec("a", "1") {|s| s.platform = pl }
a_b_1 = util_spec "a-b", "1"
a_b_1_platform = util_spec("a-b", "1") {|s| s.platform = pl }
a_b_1_1 = util_spec "a-b-1", "1"
a_b_1_1_platform = util_spec("a-b-1", "1") {|s| s.platform = pl }
install_specs(a1, a1_pre, a_1_platform, a_b_1, a_b_1_platform,
a_b_1_1, a_b_1_1_platform)
assert_equal [a1], Gem::Specification.find_all_by_full_name("a-1")
assert_equal [a1_pre], Gem::Specification.find_all_by_full_name("a-1.0.0.pre.1")
assert_equal [a_1_platform], Gem::Specification.find_all_by_full_name("a-1-x86-linux")
assert_equal [a_b_1_1], Gem::Specification.find_all_by_full_name("a-b-1-1")
assert_equal [a_b_1_1_platform], Gem::Specification.find_all_by_full_name("a-b-1-1-x86-linux")
assert_equal [], Gem::Specification.find_all_by_full_name("monkeys")
assert_equal [], Gem::Specification.find_all_by_full_name("a-1-foo")
end
def test_find_by_name
install_specs util_spec "a"
install_specs util_spec "a", 1

View file

@ -71,7 +71,7 @@ class TestStubSpecification < Gem::TestCase
refute stub.contains_requirable_file? 'nonexistent'
end
expected = "Ignoring stub_e-2 because its extensions are not built. " +
expected = "Ignoring stub_e-2 because its extensions are not built. " +
"Try: gem pristine stub_e --version 2\n"
assert_equal expected, err
@ -95,6 +95,12 @@ class TestStubSpecification < Gem::TestCase
assert_equal File.join(stub.full_gem_path, 'lib'), stub.lib_dirs_glob
end
def test_lib_dirs_glob_with_extension
stub = stub_with_extension
assert_equal File.join(stub.full_gem_path, 'lib'), stub.lib_dirs_glob
end
def test_matches_for_glob
stub = stub_without_extension
code_rb = File.join stub.gem_dir, 'lib', 'code.rb'

View file

@ -26,6 +26,7 @@ class TestGemUtil < Gem::TestCase
assert_equal File.join(@tempdir, 'a/b/c'), enum.next
assert_equal File.join(@tempdir, 'a/b'), enum.next
assert_equal File.join(@tempdir, 'a'), enum.next
loop { break if enum.next.nil? } # exhaust the enumerator
end
def test_linked_list_find

View file

@ -41,6 +41,11 @@ class TestGemVersion < Gem::TestCase
assert_equal v('1.1'), Gem::Version.create(ver)
end
def test_class_correct
assert_equal true, Gem::Version.correct?("5.1")
assert_equal false, Gem::Version.correct?("an incorrect version")
end
def test_class_new_subclass
v1 = Gem::Version.new '1'
v2 = V.new '1'
@ -65,7 +70,8 @@ class TestGemVersion < Gem::TestCase
def test_hash
assert_equal v("1.2").hash, v("1.2").hash
refute_equal v("1.2").hash, v("1.3").hash
refute_equal v("1.2").hash, v("1.2.0").hash
assert_equal v("1.2").hash, v("1.2.0").hash
assert_equal v("1.2.pre.1").hash, v("1.2.0.pre.1.0").hash
end
def test_initialize
@ -76,18 +82,23 @@ class TestGemVersion < Gem::TestCase
assert_version_equal "1", 1
end
def test_initialize_bad
%W[
def test_initialize_invalid
invalid_versions = %W[
junk
1.0\n2.0
1..2
1.2\ 3.4
].each do |bad|
e = assert_raises ArgumentError, bad do
Gem::Version.new bad
]
# DON'T TOUCH THIS WITHOUT CHECKING CVE-2013-4287
invalid_versions << "2.3422222.222.222222222.22222.ads0as.dasd0.ddd2222.2.qd3e."
invalid_versions.each do |invalid|
e = assert_raises ArgumentError, invalid do
Gem::Version.new invalid
end
assert_equal "Malformed version number string #{bad}", e.message, bad
assert_equal "Malformed version number string #{invalid}", e.message, invalid
end
end
@ -105,6 +116,9 @@ class TestGemVersion < Gem::TestCase
assert_prerelease '1.A'
assert_prerelease '1-1'
assert_prerelease '1-a'
refute_prerelease "1.2.0"
refute_prerelease "2.9"
refute_prerelease "22.1.50.0"
@ -160,6 +174,12 @@ class TestGemVersion < Gem::TestCase
assert_equal [9,8,7], v("9.8.7").segments
end
def test_canonical_segments
assert_equal [1], v("1.0.0").canonical_segments
assert_equal [1, "a", 1], v("1.0.0.a.1.0").canonical_segments
assert_equal [1, 2, 3, "pre", 1], v("1.2.3-1").canonical_segments
end
# Asserts that +version+ is a prerelease.
def assert_prerelease version
@ -189,6 +209,7 @@ class TestGemVersion < Gem::TestCase
def assert_version_equal expected, actual
assert_equal v(expected), v(actual)
assert_equal v(expected).hash, v(actual).hash, "since #{actual} == #{expected}, they must have the same hash"
end
# Assert that two versions are eql?. Checks both directions.

View file

@ -106,6 +106,21 @@ class TestGemVersionOption < Gem::TestCase
assert_equal expected, @cmd.options
end
def test_multiple_version_operator_option_compound
@cmd.add_version_option
@cmd.handle_options ['--version', '< 1', '--version', '> 0.9']
expected = {
:args => [],
:explicit_prerelease => false,
:prerelease => false,
:version => Gem::Requirement.new('< 1', '> 0.9'),
}
assert_equal expected, @cmd.options
end
def test_version_option_explicit_prerelease
@cmd.add_prerelease_option
@cmd.add_version_option

View file

@ -90,4 +90,34 @@ class TestKernel < Gem::TestCase
assert gem('a', '= 1'), "Should load"
refute $:.any? { |p| %r{a-1/bin} =~ p }
end
def test_gem_bundler
quick_gem 'bundler', '1'
quick_gem 'bundler', '2.a'
assert gem('bundler')
assert $:.any? { |p| %r{bundler-1/lib} =~ p }
end
def test_gem_bundler_missing_bundler_version
Gem::BundlerVersionFinder.stub(:bundler_version_with_reason, ["55", "reason"]) do
quick_gem 'bundler', '1'
quick_gem 'bundler', '2.a'
e = assert_raises Gem::MissingSpecVersionError do
gem('bundler')
end
assert_match "Could not find 'bundler' (55) required by reason.", e.message
end
end
def test_gem_bundler_inferred_bundler_version
Gem::BundlerVersionFinder.stub(:bundler_version_with_reason, ["1", "reason"]) do
quick_gem 'bundler', '1'
quick_gem 'bundler', '2.a'
assert gem('bundler', '>= 0.a')
assert $:.any? { |p| %r{bundler-1/lib} =~ p }
end
end
end

View file

@ -383,6 +383,44 @@ class TestGemRequire < Gem::TestCase
assert_equal %w(a-1), loaded_spec_names
end
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")
install_specs b1, b2a
require "rubygems/bundler_version_finder"
$:.clear
assert_require 'bundler/setup'
assert_equal %w[bundler-2.a], loaded_spec_names
assert_empty unresolved_names
end
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")
install_specs b1, b2a
e = assert_raises Gem::MissingSpecVersionError do
gem('bundler')
end
assert_match "Could not find 'bundler' (55) required by reason.", e.message
end
end
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")
install_specs b1, b2
$:.clear
assert_require 'bundler/setup'
assert_equal %w[bundler-1.999999999], loaded_spec_names
end
end
def silence_warnings
old_verbose, $VERBOSE = $VERBOSE, false
yield