зеркало из https://github.com/github/ruby.git
* lib/rubygems: Update to RubyGems 2.4.1 master(713ab65)
Complete history at: https://github.com/rubygems/rubygems/blob/master/History.txt#L3-L216 * test/rubygems: ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@47582 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
e548c09d42
Коммит
4de117a615
|
@ -1,3 +1,11 @@
|
||||||
|
Sun Sep 14 12:29:02 2014 SHIBATA Hiroshi <shibata.hiroshi@gmail.com>
|
||||||
|
|
||||||
|
* lib/rubygems: Update to RubyGems 2.4.1 master(713ab65)
|
||||||
|
Complete history at:
|
||||||
|
https://github.com/rubygems/rubygems/blob/master/History.txt#L3-L216
|
||||||
|
|
||||||
|
* test/rubygems: ditto.
|
||||||
|
|
||||||
Sun Sep 14 11:03:24 2014 Aaron Patterson <aaron@tenderlovemaking.com>
|
Sun Sep 14 11:03:24 2014 Aaron Patterson <aaron@tenderlovemaking.com>
|
||||||
|
|
||||||
* ext/psych/lib/psych.rb: update version
|
* ext/psych/lib/psych.rb: update version
|
||||||
|
|
|
@ -6,9 +6,10 @@
|
||||||
#++
|
#++
|
||||||
|
|
||||||
require 'rbconfig'
|
require 'rbconfig'
|
||||||
|
require 'thread'
|
||||||
|
|
||||||
module Gem
|
module Gem
|
||||||
VERSION = '2.2.2'
|
VERSION = '2.4.1'
|
||||||
end
|
end
|
||||||
|
|
||||||
# Must be first since it unloads the prelude from 1.9.2
|
# Must be first since it unloads the prelude from 1.9.2
|
||||||
|
@ -56,8 +57,8 @@ require 'rubygems/errors'
|
||||||
# RubyGems defaults are stored in rubygems/defaults.rb. If you're packaging
|
# RubyGems defaults are stored in rubygems/defaults.rb. If you're packaging
|
||||||
# RubyGems or implementing Ruby you can change RubyGems' defaults.
|
# RubyGems or implementing Ruby you can change RubyGems' defaults.
|
||||||
#
|
#
|
||||||
# For RubyGems packagers, provide lib/rubygems/operating_system.rb and
|
# For RubyGems packagers, provide lib/rubygems/defaults/operating_system.rb
|
||||||
# override any defaults from lib/rubygems/defaults.rb.
|
# and override any defaults from lib/rubygems/defaults.rb.
|
||||||
#
|
#
|
||||||
# For Ruby implementers, provide lib/rubygems/defaults/#{RUBY_ENGINE}.rb and
|
# For Ruby implementers, provide lib/rubygems/defaults/#{RUBY_ENGINE}.rb and
|
||||||
# override any defaults from lib/rubygems/defaults.rb.
|
# override any defaults from lib/rubygems/defaults.rb.
|
||||||
|
@ -83,7 +84,7 @@ require 'rubygems/errors'
|
||||||
# * Chad Fowler -- chad(at)chadfowler.com
|
# * Chad Fowler -- chad(at)chadfowler.com
|
||||||
# * David Black -- dblack(at)wobblini.net
|
# * David Black -- dblack(at)wobblini.net
|
||||||
# * Paul Brannan -- paul(at)atdesk.com
|
# * Paul Brannan -- paul(at)atdesk.com
|
||||||
# * Jim Weirich -- jim(at)weirichhouse.org
|
# * Jim Weirich -- jim(at)weirichhouse.org
|
||||||
#
|
#
|
||||||
# Contributors:
|
# Contributors:
|
||||||
#
|
#
|
||||||
|
@ -156,6 +157,7 @@ module Gem
|
||||||
|
|
||||||
@configuration = nil
|
@configuration = nil
|
||||||
@loaded_specs = {}
|
@loaded_specs = {}
|
||||||
|
LOADED_SPECS_MUTEX = Mutex.new
|
||||||
@path_to_default_spec_map = {}
|
@path_to_default_spec_map = {}
|
||||||
@platforms = []
|
@platforms = []
|
||||||
@ruby = nil
|
@ruby = nil
|
||||||
|
@ -298,7 +300,7 @@ module Gem
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# The path the the data directory specified by the gem name. If the
|
# The path to the data directory specified by the gem name. If the
|
||||||
# package is not available as a gem, return nil.
|
# package is not available as a gem, return nil.
|
||||||
|
|
||||||
def self.datadir(gem_name)
|
def self.datadir(gem_name)
|
||||||
|
@ -544,9 +546,9 @@ module Gem
|
||||||
# Fetching: minitest-3.0.1.gem (100%)
|
# Fetching: minitest-3.0.1.gem (100%)
|
||||||
# => [#<Gem::Specification:0x1013b4528 @name="minitest", ...>]
|
# => [#<Gem::Specification:0x1013b4528 @name="minitest", ...>]
|
||||||
|
|
||||||
def self.install name, version = Gem::Requirement.default, **options
|
def self.install name, version = Gem::Requirement.default, *options
|
||||||
require "rubygems/dependency_installer"
|
require "rubygems/dependency_installer"
|
||||||
inst = Gem::DependencyInstaller.new(**options)
|
inst = Gem::DependencyInstaller.new(*options)
|
||||||
inst.install name, version
|
inst.install name, version
|
||||||
inst.installed_gems
|
inst.installed_gems
|
||||||
end
|
end
|
||||||
|
@ -995,19 +997,31 @@ module Gem
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Looks for gem dependency files (gem.deps.rb, Gemfile, Isolate) from the
|
# Looks for a gem dependency file at +path+ and activates the gems in the
|
||||||
# current directory up and activates the gems in the first file found.
|
# file if found. If the file is not found an ArgumentError is raised.
|
||||||
|
#
|
||||||
|
# If +path+ is not given the RUBYGEMS_GEMDEPS environment variable is used,
|
||||||
|
# but if no file is found no exception is raised.
|
||||||
|
#
|
||||||
|
# If '-' is given for +path+ RubyGems searches up from the current working
|
||||||
|
# directory for gem dependency files (gem.deps.rb, Gemfile, Isolate) and
|
||||||
|
# activates the gems in the first one found.
|
||||||
#
|
#
|
||||||
# You can run this automatically when rubygems starts. To enable, set
|
# You can run this automatically when rubygems starts. To enable, set
|
||||||
# the <code>RUBYGEMS_GEMDEPS</code> environment variable to either the path
|
# the <code>RUBYGEMS_GEMDEPS</code> environment variable to either the path
|
||||||
# of your Gemfile or "-" to auto-discover in parent directories.
|
# of your gem dependencies file or "-" to auto-discover in parent
|
||||||
|
# directories.
|
||||||
#
|
#
|
||||||
# NOTE: Enabling automatic discovery on multiuser systems can lead to
|
# NOTE: Enabling automatic discovery on multiuser systems can lead to
|
||||||
# execution of arbitrary code when used from directories outside your
|
# execution of arbitrary code when used from directories outside your
|
||||||
# control.
|
# control.
|
||||||
|
|
||||||
def self.use_gemdeps
|
def self.use_gemdeps path = nil
|
||||||
return unless path = ENV['RUBYGEMS_GEMDEPS']
|
raise_exception = path
|
||||||
|
|
||||||
|
path ||= ENV['RUBYGEMS_GEMDEPS']
|
||||||
|
return unless path
|
||||||
|
|
||||||
path = path.dup
|
path = path.dup
|
||||||
|
|
||||||
if path == "-" then
|
if path == "-" then
|
||||||
|
@ -1025,7 +1039,11 @@ module Gem
|
||||||
|
|
||||||
path.untaint
|
path.untaint
|
||||||
|
|
||||||
return unless File.file? path
|
unless File.file? path then
|
||||||
|
return unless raise_exception
|
||||||
|
|
||||||
|
raise ArgumentError, "Unable to find gem dependencies file at #{path}"
|
||||||
|
end
|
||||||
|
|
||||||
rs = Gem::RequestSet.new
|
rs = Gem::RequestSet.new
|
||||||
rs.load_gemdeps path
|
rs.load_gemdeps path
|
||||||
|
@ -1035,6 +1053,10 @@ module Gem
|
||||||
sp.activate
|
sp.activate
|
||||||
sp
|
sp
|
||||||
end
|
end
|
||||||
|
rescue Gem::LoadError, Gem::UnsatisfiableDependencyError => e
|
||||||
|
warn e.message
|
||||||
|
warn "You may need to `gem install -g` to install missing gems"
|
||||||
|
warn ""
|
||||||
end
|
end
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
|
|
|
@ -126,7 +126,7 @@ class Gem::AvailableSet
|
||||||
dep = req.dependency
|
dep = req.dependency
|
||||||
|
|
||||||
match = @set.find_all do |t|
|
match = @set.find_all do |t|
|
||||||
dep.matches_spec? t.spec
|
dep.match? t.spec
|
||||||
end
|
end
|
||||||
|
|
||||||
match.map do |t|
|
match.map do |t|
|
||||||
|
|
|
@ -14,6 +14,11 @@ class Gem::BasicSpecification
|
||||||
|
|
||||||
attr_writer :extension_dir # :nodoc:
|
attr_writer :extension_dir # :nodoc:
|
||||||
|
|
||||||
|
##
|
||||||
|
# Is this specification ignored for activation purposes?
|
||||||
|
|
||||||
|
attr_writer :ignored # :nodoc:
|
||||||
|
|
||||||
##
|
##
|
||||||
# The path this gemspec was loaded from. This attribute is not persisted.
|
# The path this gemspec was loaded from. This attribute is not persisted.
|
||||||
|
|
||||||
|
@ -53,7 +58,16 @@ class Gem::BasicSpecification
|
||||||
# Return true if this spec can require +file+.
|
# Return true if this spec can require +file+.
|
||||||
|
|
||||||
def contains_requirable_file? file
|
def contains_requirable_file? file
|
||||||
build_extensions
|
if instance_variable_defined?(:@ignored) or
|
||||||
|
instance_variable_defined?('@ignored') then
|
||||||
|
return false
|
||||||
|
elsif missing_extensions? then
|
||||||
|
@ignored = true
|
||||||
|
|
||||||
|
warn "Ignoring #{full_name} because its extensions are not built. " +
|
||||||
|
"Try: gem pristine #{full_name}"
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
suffixes = Gem.suffixes
|
suffixes = Gem.suffixes
|
||||||
|
|
||||||
|
@ -120,11 +134,11 @@ class Gem::BasicSpecification
|
||||||
# activated.
|
# activated.
|
||||||
|
|
||||||
def full_require_paths
|
def full_require_paths
|
||||||
full_paths = @require_paths.map do |path|
|
full_paths = raw_require_paths.map do |path|
|
||||||
File.join full_gem_path, path
|
File.join full_gem_path, path
|
||||||
end
|
end
|
||||||
|
|
||||||
full_paths.unshift extension_dir unless @extensions.empty?
|
full_paths.unshift extension_dir unless @extensions.nil? || @extensions.empty?
|
||||||
|
|
||||||
full_paths
|
full_paths
|
||||||
end
|
end
|
||||||
|
@ -176,7 +190,7 @@ class Gem::BasicSpecification
|
||||||
end
|
end
|
||||||
|
|
||||||
def raw_require_paths # :nodoc:
|
def raw_require_paths # :nodoc:
|
||||||
@require_paths
|
Array(@require_paths)
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -197,13 +211,9 @@ class Gem::BasicSpecification
|
||||||
# spec.require_path = '.'
|
# spec.require_path = '.'
|
||||||
|
|
||||||
def require_paths
|
def require_paths
|
||||||
return @require_paths if @extensions.empty?
|
return raw_require_paths if @extensions.nil? || @extensions.empty?
|
||||||
|
|
||||||
relative_extension_dir =
|
[extension_dir].concat raw_require_paths
|
||||||
File.join '..', '..', 'extensions', Gem::Platform.local.to_s,
|
|
||||||
Gem.extension_api_version, full_name
|
|
||||||
|
|
||||||
[relative_extension_dir].concat @require_paths
|
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
|
|
@ -148,6 +148,8 @@ class Gem::Command
|
||||||
|
|
||||||
##
|
##
|
||||||
# Display to the user that a gem couldn't be found and reasons why
|
# Display to the user that a gem couldn't be found and reasons why
|
||||||
|
#--
|
||||||
|
# TODO: replace +domain+ with a parameter to suppress suggestions
|
||||||
|
|
||||||
def show_lookup_failure(gem_name, version, errors, domain)
|
def show_lookup_failure(gem_name, version, errors, domain)
|
||||||
if errors and !errors.empty?
|
if errors and !errors.empty?
|
||||||
|
@ -557,7 +559,8 @@ basic help message containing pointers to more information.
|
||||||
Further help:
|
Further help:
|
||||||
gem help commands list all 'gem' commands
|
gem help commands list all 'gem' commands
|
||||||
gem help examples show some examples of usage
|
gem help examples show some examples of usage
|
||||||
gem help platforms show information about platforms
|
gem help gem_dependencies gem dependencies file guide
|
||||||
|
gem help platforms gem platforms guide
|
||||||
gem help <COMMAND> show help on COMMAND
|
gem help <COMMAND> show help on COMMAND
|
||||||
(e.g. 'gem help install')
|
(e.g. 'gem help install')
|
||||||
gem server present a web page at
|
gem server present a web page at
|
||||||
|
|
|
@ -48,6 +48,7 @@ class Gem::CommandManager
|
||||||
:list,
|
:list,
|
||||||
:lock,
|
:lock,
|
||||||
:mirror,
|
:mirror,
|
||||||
|
:open,
|
||||||
:outdated,
|
:outdated,
|
||||||
:owner,
|
:owner,
|
||||||
:pristine,
|
:pristine,
|
||||||
|
|
|
@ -129,23 +129,21 @@ class Gem::Commands::CertCommand < Gem::Command
|
||||||
end
|
end
|
||||||
|
|
||||||
def build_key # :nodoc:
|
def build_key # :nodoc:
|
||||||
if options[:key] then
|
return options[:key] if options[:key]
|
||||||
options[:key]
|
|
||||||
else
|
|
||||||
passphrase = ask_for_password 'Passphrase for your Private Key:'
|
|
||||||
say "\n"
|
|
||||||
|
|
||||||
passphrase_confirmation = ask_for_password 'Please repeat the passphrase for your Private Key:'
|
passphrase = ask_for_password 'Passphrase for your Private Key:'
|
||||||
say "\n"
|
say "\n"
|
||||||
|
|
||||||
raise Gem::CommandLineError,
|
passphrase_confirmation = ask_for_password 'Please repeat the passphrase for your Private Key:'
|
||||||
"Passphrase and passphrase confirmation don't match" unless passphrase == passphrase_confirmation
|
say "\n"
|
||||||
|
|
||||||
key = Gem::Security.create_key
|
raise Gem::CommandLineError,
|
||||||
key_path = Gem::Security.write key, "gem-private_key.pem", 0600, passphrase
|
"Passphrase and passphrase confirmation don't match" unless passphrase == passphrase_confirmation
|
||||||
|
|
||||||
return key, key_path
|
key = Gem::Security.create_key
|
||||||
end
|
key_path = Gem::Security.write key, "gem-private_key.pem", 0600, passphrase
|
||||||
|
|
||||||
|
return key, key_path
|
||||||
end
|
end
|
||||||
|
|
||||||
def certificates_matching filter
|
def certificates_matching filter
|
||||||
|
|
|
@ -67,10 +67,10 @@ If no gems are named all gems in GEM_HOME are cleaned.
|
||||||
|
|
||||||
say "Clean Up Complete"
|
say "Clean Up Complete"
|
||||||
|
|
||||||
if Gem.configuration.really_verbose then
|
verbose do
|
||||||
skipped = @default_gems.map { |spec| spec.full_name }
|
skipped = @default_gems.map { |spec| spec.full_name }
|
||||||
|
|
||||||
say "Skipped default gems: #{skipped.join ', '}"
|
"Skipped default gems: #{skipped.join ', '}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,8 @@ class Gem::Commands::ContentsCommand < Gem::Command
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
super 'contents', 'Display the contents of the installed gems',
|
super 'contents', 'Display the contents of the installed gems',
|
||||||
:specdirs => [], :lib_only => false, :prefix => true
|
:specdirs => [], :lib_only => false, :prefix => true,
|
||||||
|
:show_install_dir => false
|
||||||
|
|
||||||
add_version_option
|
add_version_option
|
||||||
|
|
||||||
|
@ -32,6 +33,11 @@ class Gem::Commands::ContentsCommand < Gem::Command
|
||||||
options[:prefix] = prefix
|
options[:prefix] = prefix
|
||||||
end
|
end
|
||||||
|
|
||||||
|
add_option( '--[no-]show-install-dir',
|
||||||
|
'Show only the gem install dir') do |show, options|
|
||||||
|
options[:show_install_dir] = show
|
||||||
|
end
|
||||||
|
|
||||||
@path_kind = nil
|
@path_kind = nil
|
||||||
@spec_dirs = nil
|
@spec_dirs = nil
|
||||||
@version = nil
|
@version = nil
|
||||||
|
@ -65,7 +71,12 @@ prefix or only the files that are requireable.
|
||||||
names = gem_names
|
names = gem_names
|
||||||
|
|
||||||
names.each do |name|
|
names.each do |name|
|
||||||
found = gem_contents name
|
found =
|
||||||
|
if options[:show_install_dir] then
|
||||||
|
gem_install_dir name
|
||||||
|
else
|
||||||
|
gem_contents name
|
||||||
|
end
|
||||||
|
|
||||||
terminate_interaction 1 unless found or names.length > 1
|
terminate_interaction 1 unless found or names.length > 1
|
||||||
end
|
end
|
||||||
|
@ -115,6 +126,16 @@ prefix or only the files that are requireable.
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def gem_install_dir name
|
||||||
|
spec = spec_for name
|
||||||
|
|
||||||
|
return false unless spec
|
||||||
|
|
||||||
|
say spec.gem_dir
|
||||||
|
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
def gem_names # :nodoc:
|
def gem_names # :nodoc:
|
||||||
if options[:all] then
|
if options[:all] then
|
||||||
Gem::Specification.map(&:name)
|
Gem::Specification.map(&:name)
|
||||||
|
|
|
@ -31,7 +31,7 @@ class Gem::Commands::DependencyCommand < Gem::Command
|
||||||
end
|
end
|
||||||
|
|
||||||
def arguments # :nodoc:
|
def arguments # :nodoc:
|
||||||
"GEMNAME name of gem to show dependencies for"
|
"REGEXP show dependencies for gems whose names start with REGEXP"
|
||||||
end
|
end
|
||||||
|
|
||||||
def defaults_str # :nodoc:
|
def defaults_str # :nodoc:
|
||||||
|
@ -50,7 +50,7 @@ use with other commands.
|
||||||
end
|
end
|
||||||
|
|
||||||
def usage # :nodoc:
|
def usage # :nodoc:
|
||||||
"#{program_name} GEMNAME"
|
"#{program_name} REGEXP"
|
||||||
end
|
end
|
||||||
|
|
||||||
def fetch_remote_specs dependency # :nodoc:
|
def fetch_remote_specs dependency # :nodoc:
|
||||||
|
|
|
@ -28,8 +28,9 @@ The RubyGems environment can be controlled through command line arguments,
|
||||||
gemrc files, environment variables and built-in defaults.
|
gemrc files, environment variables and built-in defaults.
|
||||||
|
|
||||||
Command line argument defaults and some RubyGems defaults can be set in a
|
Command line argument defaults and some RubyGems defaults can be set in a
|
||||||
~/.gemrc file for individual users and a /etc/gemrc for all users. These
|
~/.gemrc file for individual users and a gemrc in the SYSTEM CONFIGURATION
|
||||||
files are YAML files with the following YAML keys:
|
DIRECTORY for all users. These files are YAML files with the following YAML
|
||||||
|
keys:
|
||||||
|
|
||||||
:sources: A YAML array of remote gem repositories to install gems from
|
:sources: A YAML array of remote gem repositories to install gems from
|
||||||
:verbose: Verbosity of the gem command. false, true, and :really are the
|
:verbose: Verbosity of the gem command. false, true, and :really are the
|
||||||
|
@ -120,6 +121,8 @@ lib/rubygems/defaults/operating_system.rb
|
||||||
|
|
||||||
out << " - SPEC CACHE DIRECTORY: #{Gem.spec_cache_dir}\n"
|
out << " - SPEC CACHE DIRECTORY: #{Gem.spec_cache_dir}\n"
|
||||||
|
|
||||||
|
out << " - SYSTEM CONFIGURATION DIRECTORY: #{Gem::ConfigFile::SYSTEM_CONFIG_PATH}\n"
|
||||||
|
|
||||||
out << " - RUBYGEMS PLATFORMS:\n"
|
out << " - RUBYGEMS PLATFORMS:\n"
|
||||||
Gem.platforms.each do |platform|
|
Gem.platforms.each do |platform|
|
||||||
out << " - #{platform}\n"
|
out << " - #{platform}\n"
|
||||||
|
|
|
@ -52,6 +52,183 @@ Some examples of 'gem' usage.
|
||||||
gem update --system
|
gem update --system
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
GEM_DEPENDENCIES = <<-EOF
|
||||||
|
A gem dependencies file allows installation of a consistent set of gems across
|
||||||
|
multiple environments. The RubyGems implementation is designed to be
|
||||||
|
compatible with Bundler's Gemfile format. You can see additional
|
||||||
|
documentation on the format at:
|
||||||
|
|
||||||
|
http://bundler.io
|
||||||
|
|
||||||
|
RubyGems automatically looks for these gem dependencies files:
|
||||||
|
|
||||||
|
* gem.deps.rb
|
||||||
|
* Gemfile
|
||||||
|
* Isolate
|
||||||
|
|
||||||
|
These files are looked up automatically using `gem install -g`, or you can
|
||||||
|
specify a custom file.
|
||||||
|
|
||||||
|
When the RUBYGEMS_GEMDEPS environment variable is set to a gem dependencies
|
||||||
|
file the gems from that file will be activated at startup time. Set it to a
|
||||||
|
specific filename or to "-" to have RubyGems automatically discover the gem
|
||||||
|
dependencies file by walking up from the current directory.
|
||||||
|
|
||||||
|
You can also activate gem dependencies at program startup using
|
||||||
|
Gem.use_gemdeps.
|
||||||
|
|
||||||
|
NOTE: Enabling automatic discovery on multiuser systems can lead to execution
|
||||||
|
of arbitrary code when used from directories outside your control.
|
||||||
|
|
||||||
|
Gem Dependencies
|
||||||
|
================
|
||||||
|
|
||||||
|
Use #gem to declare which gems you directly depend upon:
|
||||||
|
|
||||||
|
gem 'rake'
|
||||||
|
|
||||||
|
To depend on a specific set of versions:
|
||||||
|
|
||||||
|
gem 'rake', '~> 10.3', '>= 10.3.2'
|
||||||
|
|
||||||
|
RubyGems will require the gem name when activating the gem using
|
||||||
|
the RUBYGEMS_GEMDEPS environment variable or Gem::use_gemdeps. Use the
|
||||||
|
require: option to override this behavior if the gem does not have a file of
|
||||||
|
that name or you don't want to require those files:
|
||||||
|
|
||||||
|
gem 'my_gem', require: 'other_file'
|
||||||
|
|
||||||
|
To prevent RubyGems from requiring any files use:
|
||||||
|
|
||||||
|
gem 'my_gem', require: false
|
||||||
|
|
||||||
|
To load dependencies from a .gemspec file:
|
||||||
|
|
||||||
|
gemspec
|
||||||
|
|
||||||
|
RubyGems looks for the first .gemspec file in the current directory. To
|
||||||
|
override this use the name: option:
|
||||||
|
|
||||||
|
gemspec name: 'specific_gem'
|
||||||
|
|
||||||
|
To look in a different directory use the path: option:
|
||||||
|
|
||||||
|
gemspec name: 'specific_gem', path: 'gemspecs'
|
||||||
|
|
||||||
|
To depend on a gem unpacked into a local directory:
|
||||||
|
|
||||||
|
gem 'modified_gem', path: 'vendor/modified_gem'
|
||||||
|
|
||||||
|
To depend on a gem from git:
|
||||||
|
|
||||||
|
gem 'private_gem', git: 'git@my.company.example:private_gem.git'
|
||||||
|
|
||||||
|
To depend on a gem from github:
|
||||||
|
|
||||||
|
gem 'private_gem', github: 'my_company/private_gem'
|
||||||
|
|
||||||
|
To depend on a gem from a github gist:
|
||||||
|
|
||||||
|
gem 'bang', gist: '1232884'
|
||||||
|
|
||||||
|
Git, github and gist support the ref:, branch: and tag: options to specify a
|
||||||
|
commit reference or hash, branch or tag respectively to use for the gem.
|
||||||
|
|
||||||
|
Setting the submodules: option to true for git, github and gist dependencies
|
||||||
|
causes fetching of submodules when fetching the repository.
|
||||||
|
|
||||||
|
You can depend on multiple gems from a single repository with the git method:
|
||||||
|
|
||||||
|
git 'https://github.com/rails/rails.git' do
|
||||||
|
gem 'activesupport'
|
||||||
|
gem 'activerecord'
|
||||||
|
end
|
||||||
|
|
||||||
|
Gem Sources
|
||||||
|
===========
|
||||||
|
|
||||||
|
RubyGems uses the default sources for regular `gem install` for gem
|
||||||
|
dependencies files. Unlike bundler, you do need to specify a source.
|
||||||
|
|
||||||
|
You can override the sources used for downloading gems with:
|
||||||
|
|
||||||
|
source 'https://gem_server.example'
|
||||||
|
|
||||||
|
You may specify multiple sources. Unlike bundler the prepend: option is not
|
||||||
|
supported. Sources are used in-order, to prepend a source place it at the
|
||||||
|
front of the list.
|
||||||
|
|
||||||
|
Gem Platform
|
||||||
|
============
|
||||||
|
|
||||||
|
You can restrict gem dependencies to specific platforms with the #platform
|
||||||
|
and #platforms methods:
|
||||||
|
|
||||||
|
platform :ruby_21 do
|
||||||
|
gem 'debugger'
|
||||||
|
end
|
||||||
|
|
||||||
|
See the bundler Gemfile manual page for a list of platforms supported in a gem
|
||||||
|
dependencies file.:
|
||||||
|
|
||||||
|
http://bundler.io/v1.6/man/gemfile.5.html
|
||||||
|
|
||||||
|
Ruby Version and Engine Dependency
|
||||||
|
==================================
|
||||||
|
|
||||||
|
You can specifiy the version, engine and engine version of ruby to use with
|
||||||
|
your gem dependencies file. If you are not running the specified version
|
||||||
|
RubyGems will raise an exception.
|
||||||
|
|
||||||
|
To depend on a specific version of ruby:
|
||||||
|
|
||||||
|
ruby '2.1.2'
|
||||||
|
|
||||||
|
To depend on a specific ruby engine:
|
||||||
|
|
||||||
|
ruby '1.9.3', engine: 'jruby'
|
||||||
|
|
||||||
|
To depend on a specific ruby engine version:
|
||||||
|
|
||||||
|
ruby '1.9.3', engine: 'jruby', engine_version: '1.7.11'
|
||||||
|
|
||||||
|
Grouping Dependencies
|
||||||
|
=====================
|
||||||
|
|
||||||
|
Gem dependencies may be placed in groups that can be excluded from install.
|
||||||
|
Dependencies required for development or testing of your code may be excluded
|
||||||
|
when installed in a production environment.
|
||||||
|
|
||||||
|
A #gem dependency may be placed in a group using the group: option:
|
||||||
|
|
||||||
|
gem 'minitest', group: :test
|
||||||
|
|
||||||
|
To install dependencies from a gemfile without specific groups use the
|
||||||
|
`--without` option for `gem install -g`:
|
||||||
|
|
||||||
|
$ gem install -g --without test
|
||||||
|
|
||||||
|
The group: option also accepts multiple groups if the gem fits in multiple
|
||||||
|
categories.
|
||||||
|
|
||||||
|
Multiple groups may be excluded during install by comma-separating the groups for `--without` or by specifying `--without` multiple times.
|
||||||
|
|
||||||
|
The #group method can also be used to place gems in groups:
|
||||||
|
|
||||||
|
group :test do
|
||||||
|
gem 'minitest'
|
||||||
|
gem 'minitest-emoji'
|
||||||
|
end
|
||||||
|
|
||||||
|
The #group method allows multiple groups.
|
||||||
|
|
||||||
|
The #gemspec development dependencies are placed in the :development group by
|
||||||
|
default. This may be overriden with the :development_group option:
|
||||||
|
|
||||||
|
gemspec development_group: :other
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
PLATFORMS = <<-'EOF'
|
PLATFORMS = <<-'EOF'
|
||||||
RubyGems platforms are composed of three parts, a CPU, an OS, and a
|
RubyGems platforms are composed of three parts, a CPU, an OS, and a
|
||||||
version. These values are taken from values in rbconfig.rb. You can view
|
version. These values are taken from values in rbconfig.rb. You can view
|
||||||
|
@ -90,6 +267,16 @@ When building platform gems, set the platform in the gem specification to
|
||||||
Gem::Platform::CURRENT. This will correctly mark the gem with your ruby's
|
Gem::Platform::CURRENT. This will correctly mark the gem with your ruby's
|
||||||
platform.
|
platform.
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
# NOTE when updating also update Gem::Command::HELP
|
||||||
|
|
||||||
|
SUBCOMMANDS = [
|
||||||
|
["commands", :show_commands],
|
||||||
|
["options", Gem::Command::HELP],
|
||||||
|
["examples", EXAMPLES],
|
||||||
|
["gem_dependencies", GEM_DEPENDENCIES],
|
||||||
|
["platforms", PLATFORMS],
|
||||||
|
]
|
||||||
# :startdoc:
|
# :startdoc:
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
|
@ -98,15 +285,6 @@ platform.
|
||||||
@command_manager = Gem::CommandManager.instance
|
@command_manager = Gem::CommandManager.instance
|
||||||
end
|
end
|
||||||
|
|
||||||
def arguments # :nodoc:
|
|
||||||
args = <<-EOF
|
|
||||||
commands List all 'gem' commands
|
|
||||||
examples Show examples of 'gem' usage
|
|
||||||
<command> Show specific help for <command>
|
|
||||||
EOF
|
|
||||||
return args.gsub(/^\s+/, '')
|
|
||||||
end
|
|
||||||
|
|
||||||
def usage # :nodoc:
|
def usage # :nodoc:
|
||||||
"#{program_name} ARGUMENT"
|
"#{program_name} ARGUMENT"
|
||||||
end
|
end
|
||||||
|
@ -114,19 +292,20 @@ platform.
|
||||||
def execute
|
def execute
|
||||||
arg = options[:args][0]
|
arg = options[:args][0]
|
||||||
|
|
||||||
if begins? "commands", arg then
|
_, help = SUBCOMMANDS.find do |command,|
|
||||||
show_commands
|
begins? command, arg
|
||||||
|
end
|
||||||
|
|
||||||
elsif begins? "options", arg then
|
if help then
|
||||||
say Gem::Command::HELP
|
if Symbol === help then
|
||||||
|
send help
|
||||||
|
else
|
||||||
|
say help
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
elsif begins? "examples", arg then
|
if options[:help] then
|
||||||
say EXAMPLES
|
|
||||||
|
|
||||||
elsif begins? "platforms", arg then
|
|
||||||
say PLATFORMS
|
|
||||||
|
|
||||||
elsif options[:help] then
|
|
||||||
show_help
|
show_help
|
||||||
|
|
||||||
elsif arg then
|
elsif arg then
|
||||||
|
|
|
@ -21,6 +21,8 @@ class Gem::Commands::InstallCommand < Gem::Command
|
||||||
def initialize
|
def initialize
|
||||||
defaults = Gem::DependencyInstaller::DEFAULT_OPTIONS.merge({
|
defaults = Gem::DependencyInstaller::DEFAULT_OPTIONS.merge({
|
||||||
:format_executable => false,
|
:format_executable => false,
|
||||||
|
:lock => true,
|
||||||
|
:suggest_alternate => true,
|
||||||
:version => Gem::Requirement.default,
|
:version => Gem::Requirement.default,
|
||||||
:without_groups => [],
|
:without_groups => [],
|
||||||
})
|
})
|
||||||
|
@ -69,6 +71,16 @@ class Gem::Commands::InstallCommand < Gem::Command
|
||||||
o[:explain] = v
|
o[:explain] = v
|
||||||
end
|
end
|
||||||
|
|
||||||
|
add_option(:"Install/Update", '--[no-]lock',
|
||||||
|
'Create a lock file (when used with -g/--file)') do |v,o|
|
||||||
|
o[:lock] = v
|
||||||
|
end
|
||||||
|
|
||||||
|
add_option(:"Install/Update", '--[no-]suggestions',
|
||||||
|
'Suggest alternates when gems are not found') do |v,o|
|
||||||
|
o[:suggest_alternate] = v
|
||||||
|
end
|
||||||
|
|
||||||
@installed_specs = []
|
@installed_specs = []
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -78,7 +90,7 @@ class Gem::Commands::InstallCommand < Gem::Command
|
||||||
|
|
||||||
def defaults_str # :nodoc:
|
def defaults_str # :nodoc:
|
||||||
"--both --version '#{Gem::Requirement.default}' --document --no-force\n" +
|
"--both --version '#{Gem::Requirement.default}' --document --no-force\n" +
|
||||||
"--install-dir #{Gem.dir}"
|
"--install-dir #{Gem.dir} --lock"
|
||||||
end
|
end
|
||||||
|
|
||||||
def description # :nodoc:
|
def description # :nodoc:
|
||||||
|
@ -92,6 +104,25 @@ The wrapper allows you to choose among alternate gem versions using _version_.
|
||||||
For example `rake _0.7.3_ --version` will run rake version 0.7.3 if a newer
|
For example `rake _0.7.3_ --version` will run rake version 0.7.3 if a newer
|
||||||
version is also installed.
|
version is also installed.
|
||||||
|
|
||||||
|
Gem Dependency Files
|
||||||
|
====================
|
||||||
|
|
||||||
|
RubyGems can install a consistent set of gems across multiple environments
|
||||||
|
using `gem install -g` when a gem dependencies file (gem.deps.rb, Gemfile or
|
||||||
|
Isolate) is present. If no explicit file is given RubyGems attempts to find
|
||||||
|
one in the current directory.
|
||||||
|
|
||||||
|
When the RUBYGEMS_GEMDEPS environment variable is set to a gem dependencies
|
||||||
|
file the gems from that file will be activated at startup time. Set it to a
|
||||||
|
specific filename or to "-" to have RubyGems automatically discover the gem
|
||||||
|
dependencies file by walking up from the current directory.
|
||||||
|
|
||||||
|
NOTE: Enabling automatic discovery on multiuser systems can lead to
|
||||||
|
execution of arbitrary code when used from directories outside your control.
|
||||||
|
|
||||||
|
Extension Install Failures
|
||||||
|
==========================
|
||||||
|
|
||||||
If an extension fails to compile during gem installation the gem
|
If an extension fails to compile during gem installation the gem
|
||||||
specification is not written out, but the gem remains unpacked in the
|
specification is not written out, but the gem remains unpacked in the
|
||||||
repository. You may need to specify the path to the library's headers and
|
repository. You may need to specify the path to the library's headers and
|
||||||
|
@ -204,23 +235,20 @@ to write the specification by hand. For example:
|
||||||
install_gem_without_dependencies name, req
|
install_gem_without_dependencies name, req
|
||||||
else
|
else
|
||||||
inst = Gem::DependencyInstaller.new options
|
inst = Gem::DependencyInstaller.new options
|
||||||
|
request_set = inst.resolve_dependencies name, req
|
||||||
|
|
||||||
if options[:explain]
|
if options[:explain]
|
||||||
request_set = inst.resolve_dependencies name, req
|
|
||||||
|
|
||||||
puts "Gems to install:"
|
puts "Gems to install:"
|
||||||
|
|
||||||
request_set.specs.map { |s| s.full_name }.sort.each do |s|
|
request_set.sorted_requests.each do |s|
|
||||||
puts " #{s}"
|
puts " #{s.full_name}"
|
||||||
end
|
end
|
||||||
|
|
||||||
return
|
return
|
||||||
else
|
else
|
||||||
inst.install name, req
|
@installed_specs.concat request_set.install options
|
||||||
end
|
end
|
||||||
|
|
||||||
@installed_specs.push(*inst.installed_gems)
|
|
||||||
|
|
||||||
show_install_errors inst.errors
|
show_install_errors inst.errors
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -250,6 +278,14 @@ to write the specification by hand. For example:
|
||||||
inst = Gem::Installer.new gem, options
|
inst = Gem::Installer.new gem, options
|
||||||
inst.install
|
inst.install
|
||||||
|
|
||||||
|
require 'rubygems/dependency_installer'
|
||||||
|
dinst = Gem::DependencyInstaller.new options
|
||||||
|
dinst.installed_gems.replace [inst.spec]
|
||||||
|
|
||||||
|
Gem.done_installing_hooks.each do |hook|
|
||||||
|
hook.call dinst, [inst.spec]
|
||||||
|
end unless Gem.done_installing_hooks.empty?
|
||||||
|
|
||||||
@installed_specs.push(inst.spec)
|
@installed_specs.push(inst.spec)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -264,8 +300,10 @@ to write the specification by hand. For example:
|
||||||
rescue Gem::InstallError => e
|
rescue Gem::InstallError => e
|
||||||
alert_error "Error installing #{gem_name}:\n\t#{e.message}"
|
alert_error "Error installing #{gem_name}:\n\t#{e.message}"
|
||||||
exit_code |= 1
|
exit_code |= 1
|
||||||
rescue Gem::GemNotFoundException => e
|
rescue Gem::GemNotFoundException, Gem::UnsatisfiableDependencyError => e
|
||||||
show_lookup_failure e.name, e.version, e.errors, options[:domain]
|
domain = options[:domain]
|
||||||
|
domain = :local unless options[:suggest_alternate]
|
||||||
|
show_lookup_failure e.name, e.version, e.errors, domain
|
||||||
|
|
||||||
exit_code |= 2
|
exit_code |= 2
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,13 +8,13 @@ require 'rubygems/commands/query_command'
|
||||||
class Gem::Commands::ListCommand < Gem::Commands::QueryCommand
|
class Gem::Commands::ListCommand < Gem::Commands::QueryCommand
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
super 'list', 'Display local gems whose name starts with STRING'
|
super 'list', 'Display local gems whose name matches REGEXP'
|
||||||
|
|
||||||
remove_option('--name-matches')
|
remove_option('--name-matches')
|
||||||
end
|
end
|
||||||
|
|
||||||
def arguments # :nodoc:
|
def arguments # :nodoc:
|
||||||
"STRING start of gem name to look for"
|
"REGEXP regexp to look for in gem name"
|
||||||
end
|
end
|
||||||
|
|
||||||
def defaults_str # :nodoc:
|
def defaults_str # :nodoc:
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
require 'English'
|
||||||
|
require 'rubygems/command'
|
||||||
|
require 'rubygems/version_option'
|
||||||
|
require 'rubygems/util'
|
||||||
|
|
||||||
|
class Gem::Commands::OpenCommand < Gem::Command
|
||||||
|
|
||||||
|
include Gem::VersionOption
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
super 'open', 'Open gem sources in editor'
|
||||||
|
|
||||||
|
add_option('-e', '--editor EDITOR', String,
|
||||||
|
"Opens gem sources in EDITOR") do |editor, options|
|
||||||
|
options[:editor] = editor || get_env_editor
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def arguments # :nodoc:
|
||||||
|
"GEMNAME name of gem to open in editor"
|
||||||
|
end
|
||||||
|
|
||||||
|
def defaults_str # :nodoc:
|
||||||
|
"-e #{get_env_editor}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def description # :nodoc:
|
||||||
|
<<-EOF
|
||||||
|
The open command opens gem in editor and changes current path
|
||||||
|
to gem's source directory. Editor can be specified with -e option,
|
||||||
|
otherwise rubygems will look for editor in $EDITOR, $VISUAL and
|
||||||
|
$GEM_EDITOR variables.
|
||||||
|
EOF
|
||||||
|
end
|
||||||
|
|
||||||
|
def usage # :nodoc:
|
||||||
|
"#{program_name} GEMNAME [-e EDITOR]"
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_env_editor
|
||||||
|
ENV['GEM_EDITOR'] ||
|
||||||
|
ENV['VISUAL'] ||
|
||||||
|
ENV['EDITOR'] ||
|
||||||
|
'vi'
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute
|
||||||
|
@version = options[:version] || Gem::Requirement.default
|
||||||
|
@editor = options[:editor] || get_env_editor
|
||||||
|
|
||||||
|
found = open_gem(get_one_gem_name)
|
||||||
|
|
||||||
|
terminate_interaction 1 unless found
|
||||||
|
end
|
||||||
|
|
||||||
|
def open_gem name
|
||||||
|
spec = spec_for name
|
||||||
|
return false unless spec
|
||||||
|
|
||||||
|
open_editor(spec.full_gem_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
def open_editor path
|
||||||
|
system(*@editor.split(/\s+/) + [path])
|
||||||
|
end
|
||||||
|
|
||||||
|
def spec_for name
|
||||||
|
spec = Gem::Specification.find_all_by_name(name, @version).last
|
||||||
|
|
||||||
|
return spec if spec
|
||||||
|
|
||||||
|
say "Unable to find gem '#{name}'"
|
||||||
|
end
|
||||||
|
end
|
|
@ -86,7 +86,9 @@ permission to.
|
||||||
request.add_field "Authorization", api_key
|
request.add_field "Authorization", api_key
|
||||||
end
|
end
|
||||||
|
|
||||||
with_response response, "Removing #{owner}"
|
action = method == :delete ? "Removing" : "Adding"
|
||||||
|
|
||||||
|
with_response response, "#{action} #{owner}"
|
||||||
rescue
|
rescue
|
||||||
# ignore
|
# ignore
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,7 +4,7 @@ require 'rubygems/commands/query_command'
|
||||||
class Gem::Commands::SearchCommand < Gem::Commands::QueryCommand
|
class Gem::Commands::SearchCommand < Gem::Commands::QueryCommand
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
super 'search', 'Display remote gems whose name contains STRING'
|
super 'search', 'Display remote gems whose name matches REGEXP'
|
||||||
|
|
||||||
remove_option '--name-matches'
|
remove_option '--name-matches'
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ class Gem::Commands::SearchCommand < Gem::Commands::QueryCommand
|
||||||
end
|
end
|
||||||
|
|
||||||
def arguments # :nodoc:
|
def arguments # :nodoc:
|
||||||
"STRING fragment of gem name to search for"
|
"REGEXP regexp to search for in gem name"
|
||||||
end
|
end
|
||||||
|
|
||||||
def defaults_str # :nodoc:
|
def defaults_str # :nodoc:
|
||||||
|
@ -21,8 +21,8 @@ class Gem::Commands::SearchCommand < Gem::Commands::QueryCommand
|
||||||
|
|
||||||
def description # :nodoc:
|
def description # :nodoc:
|
||||||
<<-EOF
|
<<-EOF
|
||||||
The search command displays remote gems whose name contains the given
|
The search command displays remote gems whose name matches the given
|
||||||
string.
|
regexp.
|
||||||
|
|
||||||
The --details option displays additional details from the gem but will
|
The --details option displays additional details from the gem but will
|
||||||
take a little longer to complete as it must download the information
|
take a little longer to complete as it must download the information
|
||||||
|
@ -33,7 +33,7 @@ To list local gems use the list command.
|
||||||
end
|
end
|
||||||
|
|
||||||
def usage # :nodoc:
|
def usage # :nodoc:
|
||||||
"#{program_name} [STRING]"
|
"#{program_name} [REGEXP]"
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -446,7 +446,7 @@ abort "#{deprecation_message}"
|
||||||
history.force_encoding Encoding::UTF_8 if
|
history.force_encoding Encoding::UTF_8 if
|
||||||
Object.const_defined? :Encoding
|
Object.const_defined? :Encoding
|
||||||
|
|
||||||
history = history.sub(/^# coding:.*?^=/m, '')
|
history = history.sub(/^# coding:.*?(?=^=)/m, '')
|
||||||
|
|
||||||
text = history.split(HISTORY_HEADER)
|
text = history.split(HISTORY_HEADER)
|
||||||
text.shift # correct an off-by-one generated by split
|
text.shift # correct an off-by-one generated by split
|
||||||
|
|
|
@ -15,7 +15,7 @@ class Gem::Commands::UninstallCommand < Gem::Command
|
||||||
def initialize
|
def initialize
|
||||||
super 'uninstall', 'Uninstall gems from the local repository',
|
super 'uninstall', 'Uninstall gems from the local repository',
|
||||||
:version => Gem::Requirement.default, :user_install => true,
|
:version => Gem::Requirement.default, :user_install => true,
|
||||||
:check_dev => false
|
:check_dev => false, :vendor => false
|
||||||
|
|
||||||
add_option('-a', '--[no-]all',
|
add_option('-a', '--[no-]all',
|
||||||
'Uninstall all matching versions'
|
'Uninstall all matching versions'
|
||||||
|
@ -76,6 +76,18 @@ class Gem::Commands::UninstallCommand < Gem::Command
|
||||||
|
|
||||||
add_version_option
|
add_version_option
|
||||||
add_platform_option
|
add_platform_option
|
||||||
|
|
||||||
|
add_option('--vendor',
|
||||||
|
'Uninstall gem from the vendor directory.',
|
||||||
|
'Only for use by gem repackagers.') do |value, options|
|
||||||
|
unless Gem.vendor_dir then
|
||||||
|
raise OptionParser::InvalidOption.new 'your platform is not supported'
|
||||||
|
end
|
||||||
|
|
||||||
|
alert_warning 'Use your OS package manager to uninstall vendor gems'
|
||||||
|
options[:vendor] = true
|
||||||
|
options[:install_dir] = Gem.vendor_dir
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def arguments # :nodoc:
|
def arguments # :nodoc:
|
||||||
|
|
|
@ -16,6 +16,8 @@ class Gem::Commands::UpdateCommand < Gem::Command
|
||||||
|
|
||||||
attr_reader :installer # :nodoc:
|
attr_reader :installer # :nodoc:
|
||||||
|
|
||||||
|
attr_reader :updated # :nodoc:
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
super 'update', 'Update installed gems to the latest version',
|
super 'update', 'Update installed gems to the latest version',
|
||||||
:document => %w[rdoc ri],
|
:document => %w[rdoc ri],
|
||||||
|
@ -45,7 +47,7 @@ class Gem::Commands::UpdateCommand < Gem::Command
|
||||||
end
|
end
|
||||||
|
|
||||||
def arguments # :nodoc:
|
def arguments # :nodoc:
|
||||||
"GEMNAME name of gem to update"
|
"REGEXP regexp to search for in gem name"
|
||||||
end
|
end
|
||||||
|
|
||||||
def defaults_str # :nodoc:
|
def defaults_str # :nodoc:
|
||||||
|
@ -56,13 +58,13 @@ class Gem::Commands::UpdateCommand < Gem::Command
|
||||||
<<-EOF
|
<<-EOF
|
||||||
The update command will update your gems to the latest version.
|
The update command will update your gems to the latest version.
|
||||||
|
|
||||||
The update comamnd does not remove the previous version. Use the cleanup
|
The update command does not remove the previous version. Use the cleanup
|
||||||
command to remove old versions.
|
command to remove old versions.
|
||||||
EOF
|
EOF
|
||||||
end
|
end
|
||||||
|
|
||||||
def usage # :nodoc:
|
def usage # :nodoc:
|
||||||
"#{program_name} GEMNAME [GEMNAME ...]"
|
"#{program_name} REGEXP [REGEXP ...]"
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_latest_rubygems version # :nodoc:
|
def check_latest_rubygems version # :nodoc:
|
||||||
|
@ -97,10 +99,14 @@ command to remove old versions.
|
||||||
|
|
||||||
updated = update_gems gems_to_update
|
updated = update_gems gems_to_update
|
||||||
|
|
||||||
|
updated_names = updated.map { |spec| spec.name }
|
||||||
|
not_updated_names = options[:args].uniq - updated_names
|
||||||
|
|
||||||
if updated.empty? then
|
if updated.empty? then
|
||||||
say "Nothing to update"
|
say "Nothing to update"
|
||||||
else
|
else
|
||||||
say "Gems updated: #{updated.map { |spec| spec.name }.join ' '}"
|
say "Gems updated: #{updated_names.join(' ')}"
|
||||||
|
say "Gems already up-to-date: #{not_updated_names.join(' ')}" unless not_updated_names.empty?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -199,15 +205,11 @@ command to remove old versions.
|
||||||
|
|
||||||
@installer ||= Gem::DependencyInstaller.new options
|
@installer ||= Gem::DependencyInstaller.new options
|
||||||
|
|
||||||
success = false
|
|
||||||
|
|
||||||
say "Updating #{name}"
|
say "Updating #{name}"
|
||||||
begin
|
begin
|
||||||
@installer.install name, Gem::Requirement.new(version)
|
@installer.install name, Gem::Requirement.new(version)
|
||||||
success = true
|
rescue Gem::InstallError, Gem::DependencyError => e
|
||||||
rescue Gem::InstallError => e
|
|
||||||
alert_error "Error installing #{name}:\n\t#{e.message}"
|
alert_error "Error installing #{name}:\n\t#{e.message}"
|
||||||
success = false
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@installer.installed_gems.each do |spec|
|
@installer.installed_gems.each do |spec|
|
||||||
|
@ -259,7 +261,7 @@ command to remove old versions.
|
||||||
|
|
||||||
highest_installed_gems.each do |l_name, l_spec|
|
highest_installed_gems.each do |l_name, l_spec|
|
||||||
next if not gem_names.empty? and
|
next if not gem_names.empty? and
|
||||||
gem_names.all? { |name| /#{name}/ !~ l_spec.name }
|
gem_names.none? { |name| name == l_spec.name }
|
||||||
|
|
||||||
highest_remote_ver = highest_remote_version l_spec
|
highest_remote_ver = highest_remote_version l_spec
|
||||||
|
|
||||||
|
@ -272,4 +274,3 @@ command to remove old versions.
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -44,10 +44,7 @@ as the reason for the removal request.
|
||||||
options[:undo] = true
|
options[:undo] = true
|
||||||
end
|
end
|
||||||
|
|
||||||
add_option('-k', '--key KEY_NAME',
|
add_key_option
|
||||||
'Use API key from your gem credentials file') do |value, options|
|
|
||||||
options[:key] = value
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def execute
|
def execute
|
||||||
|
@ -55,14 +52,12 @@ as the reason for the removal request.
|
||||||
|
|
||||||
version = get_version_from_requirements(options[:version])
|
version = get_version_from_requirements(options[:version])
|
||||||
platform = get_platform_from_requirements(options)
|
platform = get_platform_from_requirements(options)
|
||||||
api_key = Gem.configuration.rubygems_api_key
|
|
||||||
api_key = Gem.configuration.api_keys[options[:key].to_sym] if options[:key]
|
|
||||||
|
|
||||||
if version then
|
if version then
|
||||||
if options[:undo] then
|
if options[:undo] then
|
||||||
unyank_gem(version, platform, api_key)
|
unyank_gem(version, platform)
|
||||||
else
|
else
|
||||||
yank_gem(version, platform, api_key)
|
yank_gem(version, platform)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
say "A version argument is required: #{usage}"
|
say "A version argument is required: #{usage}"
|
||||||
|
@ -70,19 +65,19 @@ as the reason for the removal request.
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def yank_gem(version, platform, api_key)
|
def yank_gem(version, platform)
|
||||||
say "Yanking gem from #{self.host}..."
|
say "Yanking gem from #{self.host}..."
|
||||||
yank_api_request(:delete, version, platform, "api/v1/gems/yank", api_key)
|
yank_api_request(:delete, version, platform, "api/v1/gems/yank")
|
||||||
end
|
end
|
||||||
|
|
||||||
def unyank_gem(version, platform, api_key)
|
def unyank_gem(version, platform)
|
||||||
say "Unyanking gem from #{host}..."
|
say "Unyanking gem from #{host}..."
|
||||||
yank_api_request(:put, version, platform, "api/v1/gems/unyank", api_key)
|
yank_api_request(:put, version, platform, "api/v1/gems/unyank")
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def yank_api_request(method, version, platform, api, api_key)
|
def yank_api_request(method, version, platform, api)
|
||||||
name = get_one_gem_name
|
name = get_one_gem_name
|
||||||
response = rubygems_api_request(method, api) do |request|
|
response = rubygems_api_request(method, api) do |request|
|
||||||
request.add_field("Authorization", api_key)
|
request.add_field("Authorization", api_key)
|
||||||
|
|
|
@ -57,7 +57,7 @@ class Gem::ConfigFile
|
||||||
|
|
||||||
# :stopdoc:
|
# :stopdoc:
|
||||||
|
|
||||||
system_config_path =
|
SYSTEM_CONFIG_PATH =
|
||||||
begin
|
begin
|
||||||
require "etc"
|
require "etc"
|
||||||
Etc.sysconfdir
|
Etc.sysconfdir
|
||||||
|
@ -86,7 +86,7 @@ class Gem::ConfigFile
|
||||||
|
|
||||||
# :startdoc:
|
# :startdoc:
|
||||||
|
|
||||||
SYSTEM_WIDE_CONFIG_FILE = File.join system_config_path, 'gemrc'
|
SYSTEM_WIDE_CONFIG_FILE = File.join SYSTEM_CONFIG_PATH, 'gemrc'
|
||||||
|
|
||||||
##
|
##
|
||||||
# List of arguments supplied to the config file object.
|
# List of arguments supplied to the config file object.
|
||||||
|
@ -383,6 +383,8 @@ if you believe they were disclosed to a third party.
|
||||||
@backtrace = true
|
@backtrace = true
|
||||||
when /^--debug$/ then
|
when /^--debug$/ then
|
||||||
$DEBUG = true
|
$DEBUG = true
|
||||||
|
|
||||||
|
warn 'NOTE: Debugging mode prints all exceptions even when rescued'
|
||||||
else
|
else
|
||||||
@args << arg
|
@args << arg
|
||||||
end
|
end
|
||||||
|
@ -428,6 +430,15 @@ if you believe they were disclosed to a third party.
|
||||||
DEFAULT_VERBOSITY
|
DEFAULT_VERBOSITY
|
||||||
end
|
end
|
||||||
|
|
||||||
|
yaml_hash[:ssl_verify_mode] =
|
||||||
|
@hash[:ssl_verify_mode] if @hash.key? :ssl_verify_mode
|
||||||
|
|
||||||
|
yaml_hash[:ssl_ca_cert] =
|
||||||
|
@hash[:ssl_ca_cert] if @hash.key? :ssl_ca_cert
|
||||||
|
|
||||||
|
yaml_hash[:ssl_client_cert] =
|
||||||
|
@hash[:ssl_client_cert] if @hash.key? :ssl_client_cert
|
||||||
|
|
||||||
keys = yaml_hash.keys.map { |key| key.to_s }
|
keys = yaml_hash.keys.map { |key| key.to_s }
|
||||||
keys << 'debug'
|
keys << 'debug'
|
||||||
re = Regexp.union(*keys)
|
re = Regexp.union(*keys)
|
||||||
|
|
|
@ -26,6 +26,11 @@ module Kernel
|
||||||
# Kernel#gem should be called *before* any require statements (otherwise
|
# Kernel#gem should be called *before* any require statements (otherwise
|
||||||
# RubyGems may load a conflicting library version).
|
# RubyGems may load a conflicting library version).
|
||||||
#
|
#
|
||||||
|
# Kernel#gem only loads prerelease versions when prerelease +requirements+
|
||||||
|
# are given:
|
||||||
|
#
|
||||||
|
# gem 'rake', '>= 1.1.a', '< 2'
|
||||||
|
#
|
||||||
# In older RubyGems versions, the environment variable GEM_SKIP could be
|
# In older RubyGems versions, the environment variable GEM_SKIP could be
|
||||||
# used to skip activation of specified gems, for example to test out changes
|
# used to skip activation of specified gems, for example to test out changes
|
||||||
# that haven't been installed yet. Now RubyGems defers to -I and the
|
# that haven't been installed yet. Now RubyGems defers to -I and the
|
||||||
|
@ -51,7 +56,9 @@ module Kernel
|
||||||
end
|
end
|
||||||
|
|
||||||
spec = Gem::Dependency.new(gem_name, *requirements).to_spec
|
spec = Gem::Dependency.new(gem_name, *requirements).to_spec
|
||||||
spec.activate if spec
|
Gem::LOADED_SPECS_MUTEX.synchronize {
|
||||||
|
spec.activate
|
||||||
|
} if spec
|
||||||
end
|
end
|
||||||
|
|
||||||
private :gem
|
private :gem
|
||||||
|
|
|
@ -50,12 +50,8 @@ module Kernel
|
||||||
# normal require handle loading a gem from the rescue below.
|
# normal require handle loading a gem from the rescue below.
|
||||||
|
|
||||||
if Gem::Specification.unresolved_deps.empty? then
|
if Gem::Specification.unresolved_deps.empty? then
|
||||||
begin
|
RUBYGEMS_ACTIVATION_MONITOR.exit
|
||||||
RUBYGEMS_ACTIVATION_MONITOR.exit
|
return gem_original_require(path)
|
||||||
return gem_original_require(path)
|
|
||||||
ensure
|
|
||||||
RUBYGEMS_ACTIVATION_MONITOR.enter
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# If +path+ is for a gem that has already been loaded, don't
|
# If +path+ is for a gem that has already been loaded, don't
|
||||||
|
@ -71,8 +67,6 @@ module Kernel
|
||||||
begin
|
begin
|
||||||
RUBYGEMS_ACTIVATION_MONITOR.exit
|
RUBYGEMS_ACTIVATION_MONITOR.exit
|
||||||
return gem_original_require(path)
|
return gem_original_require(path)
|
||||||
ensure
|
|
||||||
RUBYGEMS_ACTIVATION_MONITOR.enter
|
|
||||||
end if spec
|
end if spec
|
||||||
|
|
||||||
# Attempt to find +path+ in any unresolved gems...
|
# Attempt to find +path+ in any unresolved gems...
|
||||||
|
@ -105,6 +99,7 @@ module Kernel
|
||||||
names = found_specs.map(&:name).uniq
|
names = found_specs.map(&:name).uniq
|
||||||
|
|
||||||
if names.size > 1 then
|
if names.size > 1 then
|
||||||
|
RUBYGEMS_ACTIVATION_MONITOR.exit
|
||||||
raise Gem::LoadError, "#{path} found in multiple gems: #{names.join ', '}"
|
raise Gem::LoadError, "#{path} found in multiple gems: #{names.join ', '}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -115,32 +110,27 @@ module Kernel
|
||||||
unless valid then
|
unless valid then
|
||||||
le = Gem::LoadError.new "unable to find a version of '#{names.first}' to activate"
|
le = Gem::LoadError.new "unable to find a version of '#{names.first}' to activate"
|
||||||
le.name = names.first
|
le.name = names.first
|
||||||
|
RUBYGEMS_ACTIVATION_MONITOR.exit
|
||||||
raise le
|
raise le
|
||||||
end
|
end
|
||||||
|
|
||||||
valid.activate
|
valid.activate
|
||||||
end
|
end
|
||||||
|
|
||||||
begin
|
RUBYGEMS_ACTIVATION_MONITOR.exit
|
||||||
RUBYGEMS_ACTIVATION_MONITOR.exit
|
return gem_original_require(path)
|
||||||
return gem_original_require(path)
|
|
||||||
ensure
|
|
||||||
RUBYGEMS_ACTIVATION_MONITOR.enter
|
|
||||||
end
|
|
||||||
rescue LoadError => load_error
|
rescue LoadError => load_error
|
||||||
|
RUBYGEMS_ACTIVATION_MONITOR.enter
|
||||||
|
|
||||||
if load_error.message.start_with?("Could not find") or
|
if load_error.message.start_with?("Could not find") or
|
||||||
(load_error.message.end_with?(path) and Gem.try_activate(path)) then
|
(load_error.message.end_with?(path) and Gem.try_activate(path)) then
|
||||||
begin
|
RUBYGEMS_ACTIVATION_MONITOR.exit
|
||||||
RUBYGEMS_ACTIVATION_MONITOR.exit
|
return gem_original_require(path)
|
||||||
return gem_original_require(path)
|
else
|
||||||
ensure
|
RUBYGEMS_ACTIVATION_MONITOR.exit
|
||||||
RUBYGEMS_ACTIVATION_MONITOR.enter
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
raise load_error
|
raise load_error
|
||||||
ensure
|
|
||||||
RUBYGEMS_ACTIVATION_MONITOR.exit
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private :require
|
private :require
|
||||||
|
|
|
@ -89,11 +89,11 @@ module Gem
|
||||||
# Default gem load path
|
# Default gem load path
|
||||||
|
|
||||||
def self.default_path
|
def self.default_path
|
||||||
if Gem.user_home && File.exist?(Gem.user_home) then
|
path = []
|
||||||
[user_dir, default_dir]
|
path << user_dir if user_home && File.exist?(user_home)
|
||||||
else
|
path << default_dir
|
||||||
[default_dir]
|
path << vendor_dir if vendor_dir and File.directory? vendor_dir
|
||||||
end
|
path
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -160,4 +160,18 @@ module Gem
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Directory where vendor gems are installed.
|
||||||
|
|
||||||
|
def self.vendor_dir # :nodoc:
|
||||||
|
if vendor_dir = ENV['GEM_VENDOR'] then
|
||||||
|
return vendor_dir.dup
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil unless RbConfig::CONFIG.key? 'vendordir'
|
||||||
|
|
||||||
|
File.join RbConfig::CONFIG['vendordir'], 'gems',
|
||||||
|
RbConfig::CONFIG['ruby_version']
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -74,7 +74,7 @@ class Gem::Dependency
|
||||||
end
|
end
|
||||||
|
|
||||||
def inspect # :nodoc:
|
def inspect # :nodoc:
|
||||||
if @prerelease
|
if prerelease? then
|
||||||
"<%s type=%p name=%p requirements=%p prerelease=ok>" %
|
"<%s type=%p name=%p requirements=%p prerelease=ok>" %
|
||||||
[self.class, self.type, self.name, requirement.to_s]
|
[self.class, self.type, self.name, requirement.to_s]
|
||||||
else
|
else
|
||||||
|
@ -145,7 +145,6 @@ class Gem::Dependency
|
||||||
@requirement = @version_requirements if defined?(@version_requirements)
|
@requirement = @version_requirements if defined?(@version_requirements)
|
||||||
end
|
end
|
||||||
|
|
||||||
# DOC: this method needs documentation or :nodoc''d
|
|
||||||
def requirements_list
|
def requirements_list
|
||||||
requirement.as_list
|
requirement.as_list
|
||||||
end
|
end
|
||||||
|
@ -205,9 +204,19 @@ class Gem::Dependency
|
||||||
|
|
||||||
alias === =~
|
alias === =~
|
||||||
|
|
||||||
# DOC: this method needs either documented or :nodoc'd
|
##
|
||||||
|
# :call-seq:
|
||||||
|
# dep.match? name => true or false
|
||||||
|
# dep.match? name, version => true or false
|
||||||
|
# dep.match? spec => true or false
|
||||||
|
#
|
||||||
|
# Does this dependency match the specification described by +name+ and
|
||||||
|
# +version+ or match +spec+?
|
||||||
|
#
|
||||||
|
# NOTE: Unlike #matches_spec? this method does not return true when the
|
||||||
|
# version is a prerelease version unless this is a prerelease dependency.
|
||||||
|
|
||||||
def match? obj, version=nil
|
def match? obj, version=nil, allow_prerelease=false
|
||||||
if !version
|
if !version
|
||||||
name = obj.name
|
name = obj.name
|
||||||
version = obj.version
|
version = obj.version
|
||||||
|
@ -216,12 +225,23 @@ class Gem::Dependency
|
||||||
end
|
end
|
||||||
|
|
||||||
return false unless self.name === name
|
return false unless self.name === name
|
||||||
return true if requirement.none?
|
|
||||||
|
|
||||||
requirement.satisfied_by? Gem::Version.new(version)
|
version = Gem::Version.new version
|
||||||
|
|
||||||
|
return true if requirement.none? and not version.prerelease?
|
||||||
|
return false if version.prerelease? and
|
||||||
|
not allow_prerelease and
|
||||||
|
not prerelease?
|
||||||
|
|
||||||
|
requirement.satisfied_by? version
|
||||||
end
|
end
|
||||||
|
|
||||||
# DOC: this method needs either documented or :nodoc'd
|
##
|
||||||
|
# Does this dependency match +spec+?
|
||||||
|
#
|
||||||
|
# NOTE: This is not a convenience method. Unlike #match? this method
|
||||||
|
# returns true when +spec+ is a prerelease version even if this dependency
|
||||||
|
# is not a prerelease dependency.
|
||||||
|
|
||||||
def matches_spec? spec
|
def matches_spec? spec
|
||||||
return false unless name === spec.name
|
return false unless name === spec.name
|
||||||
|
@ -249,8 +269,6 @@ class Gem::Dependency
|
||||||
self.class.new name, self_req.as_list.concat(other_req.as_list)
|
self.class.new name, self_req.as_list.concat(other_req.as_list)
|
||||||
end
|
end
|
||||||
|
|
||||||
# DOC: this method needs either documented or :nodoc'd
|
|
||||||
|
|
||||||
def matching_specs platform_only = false
|
def matching_specs platform_only = false
|
||||||
matches = Gem::Specification.stubs.find_all { |spec|
|
matches = Gem::Specification.stubs.find_all { |spec|
|
||||||
self.name === spec.name and # TODO: == instead of ===
|
self.name === spec.name and # TODO: == instead of ===
|
||||||
|
@ -273,8 +291,6 @@ class Gem::Dependency
|
||||||
@requirement.specific?
|
@requirement.specific?
|
||||||
end
|
end
|
||||||
|
|
||||||
# DOC: this method needs either documented or :nodoc'd
|
|
||||||
|
|
||||||
def to_specs
|
def to_specs
|
||||||
matches = matching_specs true
|
matches = matching_specs true
|
||||||
|
|
||||||
|
@ -287,12 +303,13 @@ class Gem::Dependency
|
||||||
|
|
||||||
if specs.empty?
|
if specs.empty?
|
||||||
total = Gem::Specification.to_a.size
|
total = Gem::Specification.to_a.size
|
||||||
error = Gem::LoadError.new \
|
msg = "Could not find '#{name}' (#{requirement}) among #{total} total gem(s)\n"
|
||||||
"Could not find '#{name}' (#{requirement}) among #{total} total gem(s)"
|
|
||||||
else
|
else
|
||||||
error = Gem::LoadError.new \
|
msg = "Could not find '#{name}' (#{requirement}) - did find: [#{specs.join ','}]\n"
|
||||||
"Could not find '#{name}' (#{requirement}) - did find: [#{specs.join ','}]"
|
|
||||||
end
|
end
|
||||||
|
msg << "Checked in 'GEM_PATH=#{Gem.path.join(File::PATH_SEPARATOR)}', execute `gem env` for more information"
|
||||||
|
|
||||||
|
error = Gem::LoadError.new(msg)
|
||||||
error.name = self.name
|
error.name = self.name
|
||||||
error.requirement = self.requirement
|
error.requirement = self.requirement
|
||||||
raise error
|
raise error
|
||||||
|
@ -303,11 +320,15 @@ class Gem::Dependency
|
||||||
matches
|
matches
|
||||||
end
|
end
|
||||||
|
|
||||||
# DOC: this method needs either documented or :nodoc'd
|
|
||||||
|
|
||||||
def to_spec
|
def to_spec
|
||||||
matches = self.to_specs
|
matches = self.to_specs
|
||||||
|
|
||||||
matches.find { |spec| spec.activated? } or matches.last
|
active = matches.find { |spec| spec.activated? }
|
||||||
|
|
||||||
|
return active if active
|
||||||
|
|
||||||
|
matches.delete_if { |spec| spec.version.prerelease? } unless prerelease?
|
||||||
|
|
||||||
|
matches.last
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -72,6 +72,7 @@ class Gem::DependencyInstaller
|
||||||
def initialize options = {}
|
def initialize options = {}
|
||||||
@only_install_dir = !!options[:install_dir]
|
@only_install_dir = !!options[:install_dir]
|
||||||
@install_dir = options[:install_dir] || Gem.dir
|
@install_dir = options[:install_dir] || Gem.dir
|
||||||
|
@build_root = options[:build_root]
|
||||||
|
|
||||||
options = DEFAULT_OPTIONS.merge options
|
options = DEFAULT_OPTIONS.merge options
|
||||||
|
|
||||||
|
@ -102,7 +103,7 @@ class Gem::DependencyInstaller
|
||||||
|
|
||||||
@cache_dir = options[:cache_dir] || @install_dir
|
@cache_dir = options[:cache_dir] || @install_dir
|
||||||
|
|
||||||
@errors = nil
|
@errors = []
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -157,6 +158,7 @@ class Gem::DependencyInstaller
|
||||||
|
|
||||||
dependency_list.remove_specs_unsatisfied_by dependencies
|
dependency_list.remove_specs_unsatisfied_by dependencies
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Creates an AvailableSet to install from based on +dep_or_name+ and
|
# Creates an AvailableSet to install from based on +dep_or_name+ and
|
||||||
# +version+
|
# +version+
|
||||||
|
@ -243,9 +245,9 @@ class Gem::DependencyInstaller
|
||||||
# FIX if there is a problem talking to the network, we either need to always tell
|
# FIX if there is a problem talking to the network, we either need to always tell
|
||||||
# the user (no really_verbose) or fail hard, not silently tell them that we just
|
# the user (no really_verbose) or fail hard, not silently tell them that we just
|
||||||
# couldn't find their requested gem.
|
# couldn't find their requested gem.
|
||||||
if Gem.configuration.really_verbose then
|
verbose do
|
||||||
say "Error fetching remote data:\t\t#{e.message}"
|
"Error fetching remote data:\t\t#{e.message}\n" \
|
||||||
say "Falling back to local-only install"
|
"Falling back to local-only install"
|
||||||
end
|
end
|
||||||
@domain = :local
|
@domain = :local
|
||||||
end
|
end
|
||||||
|
@ -375,13 +377,16 @@ class Gem::DependencyInstaller
|
||||||
options = {
|
options = {
|
||||||
:bin_dir => @bin_dir,
|
:bin_dir => @bin_dir,
|
||||||
:build_args => @build_args,
|
:build_args => @build_args,
|
||||||
|
:document => @document,
|
||||||
:env_shebang => @env_shebang,
|
:env_shebang => @env_shebang,
|
||||||
:force => @force,
|
:force => @force,
|
||||||
:format_executable => @format_executable,
|
:format_executable => @format_executable,
|
||||||
:ignore_dependencies => @ignore_dependencies,
|
:ignore_dependencies => @ignore_dependencies,
|
||||||
|
:prerelease => @prerelease,
|
||||||
:security_policy => @security_policy,
|
:security_policy => @security_policy,
|
||||||
:user_install => @user_install,
|
:user_install => @user_install,
|
||||||
:wrappers => @wrappers,
|
:wrappers => @wrappers,
|
||||||
|
:build_root => @build_root,
|
||||||
:install_as_default => @install_as_default
|
:install_as_default => @install_as_default
|
||||||
}
|
}
|
||||||
options[:install_dir] = @install_dir if @only_install_dir
|
options[:install_dir] = @install_dir if @only_install_dir
|
||||||
|
@ -415,25 +420,59 @@ class Gem::DependencyInstaller
|
||||||
end
|
end
|
||||||
|
|
||||||
def resolve_dependencies dep_or_name, version # :nodoc:
|
def resolve_dependencies dep_or_name, version # :nodoc:
|
||||||
as = available_set_for dep_or_name, version
|
request_set = Gem::RequestSet.new
|
||||||
|
request_set.development = @development
|
||||||
request_set = as.to_request_set install_development_deps
|
request_set.development_shallow = @dev_shallow
|
||||||
request_set.soft_missing = @force
|
request_set.soft_missing = @force
|
||||||
|
request_set.prerelease = @prerelease
|
||||||
request_set.remote = false unless consider_remote?
|
request_set.remote = false unless consider_remote?
|
||||||
|
|
||||||
installer_set = Gem::Resolver::InstallerSet.new @domain
|
installer_set = Gem::Resolver::InstallerSet.new @domain
|
||||||
installer_set.always_install.concat request_set.always_install
|
|
||||||
installer_set.ignore_installed = @only_install_dir
|
installer_set.ignore_installed = @only_install_dir
|
||||||
|
|
||||||
|
if consider_local?
|
||||||
|
if dep_or_name =~ /\.gem$/ and File.file? dep_or_name then
|
||||||
|
src = Gem::Source::SpecificFile.new dep_or_name
|
||||||
|
installer_set.add_local dep_or_name, src.spec, src
|
||||||
|
version = src.spec.version if version == Gem::Requirement.default
|
||||||
|
elsif dep_or_name =~ /\.gem$/ then
|
||||||
|
Dir[dep_or_name].each do |name|
|
||||||
|
begin
|
||||||
|
src = Gem::Source::SpecificFile.new name
|
||||||
|
installer_set.add_local dep_or_name, src.spec, src
|
||||||
|
rescue Gem::Package::FormatError
|
||||||
|
end
|
||||||
|
end
|
||||||
|
# else This is a dependency. InstallerSet handles this case
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
dependency =
|
||||||
|
if spec = installer_set.local?(dep_or_name) then
|
||||||
|
Gem::Dependency.new spec.name, version
|
||||||
|
elsif String === dep_or_name then
|
||||||
|
Gem::Dependency.new dep_or_name, version
|
||||||
|
else
|
||||||
|
dep_or_name
|
||||||
|
end
|
||||||
|
|
||||||
|
dependency.prerelease = @prerelease
|
||||||
|
|
||||||
|
request_set.import [dependency]
|
||||||
|
|
||||||
|
installer_set.add_always_install dependency
|
||||||
|
|
||||||
|
request_set.always_install = installer_set.always_install
|
||||||
|
|
||||||
if @ignore_dependencies then
|
if @ignore_dependencies then
|
||||||
installer_set.ignore_dependencies = true
|
installer_set.ignore_dependencies = true
|
||||||
request_set.ignore_dependencies = true
|
request_set.ignore_dependencies = true
|
||||||
request_set.soft_missing = true
|
request_set.soft_missing = true
|
||||||
end
|
end
|
||||||
|
|
||||||
composed_set = Gem::Resolver.compose_sets as, installer_set
|
request_set.resolve installer_set
|
||||||
|
|
||||||
request_set.resolve composed_set
|
@errors.concat request_set.errors
|
||||||
|
|
||||||
request_set
|
request_set
|
||||||
end
|
end
|
||||||
|
|
|
@ -105,7 +105,7 @@ class Gem::Doctor
|
||||||
next if ent == "." || ent == ".."
|
next if ent == "." || ent == ".."
|
||||||
|
|
||||||
child = File.join(directory, ent)
|
child = File.join(directory, ent)
|
||||||
next unless File.exists?(child)
|
next unless File.exist?(child)
|
||||||
|
|
||||||
basename = File.basename(child, extension)
|
basename = File.basename(child, extension)
|
||||||
next if installed_specs.include? basename
|
next if installed_specs.include? basename
|
||||||
|
|
|
@ -19,6 +19,36 @@ module Gem
|
||||||
attr_accessor :requirement
|
attr_accessor :requirement
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Raised when there are conflicting gem specs loaded
|
||||||
|
|
||||||
|
class ConflictError < LoadError
|
||||||
|
|
||||||
|
##
|
||||||
|
# A Hash mapping conflicting specifications to the dependencies that
|
||||||
|
# caused the conflict
|
||||||
|
|
||||||
|
attr_reader :conflicts
|
||||||
|
|
||||||
|
##
|
||||||
|
# The specification that had the conflict
|
||||||
|
|
||||||
|
attr_reader :target
|
||||||
|
|
||||||
|
def initialize target, conflicts
|
||||||
|
@target = target
|
||||||
|
@conflicts = conflicts
|
||||||
|
@name = target.name
|
||||||
|
|
||||||
|
reason = conflicts.map { |act, dependencies|
|
||||||
|
"#{act.full_name} conflicts with #{dependencies.join(", ")}"
|
||||||
|
}.join ", "
|
||||||
|
|
||||||
|
# TODO: improve message by saying who activated `con`
|
||||||
|
|
||||||
|
super("Unable to activate #{target.full_name}, because #{reason}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
class ErrorReason; end
|
class ErrorReason; end
|
||||||
|
|
||||||
# Generated when trying to lookup a gem to indicate that the gem
|
# Generated when trying to lookup a gem to indicate that the gem
|
||||||
|
|
|
@ -27,7 +27,7 @@ class Gem::DependencyRemovalException < Gem::Exception; end
|
||||||
# toplevel. Indicates which dependencies were incompatible through #conflict
|
# toplevel. Indicates which dependencies were incompatible through #conflict
|
||||||
# and #conflicting_dependencies
|
# and #conflicting_dependencies
|
||||||
|
|
||||||
class Gem::DependencyResolutionError < Gem::Exception
|
class Gem::DependencyResolutionError < Gem::DependencyError
|
||||||
|
|
||||||
attr_reader :conflict
|
attr_reader :conflict
|
||||||
|
|
||||||
|
@ -214,7 +214,7 @@ end
|
||||||
# Raised by Resolver when a dependency requests a gem for which
|
# Raised by Resolver when a dependency requests a gem for which
|
||||||
# there is no spec.
|
# there is no spec.
|
||||||
|
|
||||||
class Gem::UnsatisfiableDependencyError < Gem::Exception
|
class Gem::UnsatisfiableDependencyError < Gem::DependencyError
|
||||||
|
|
||||||
##
|
##
|
||||||
# The unsatisfiable dependency. This is a
|
# The unsatisfiable dependency. This is a
|
||||||
|
@ -222,6 +222,11 @@ class Gem::UnsatisfiableDependencyError < Gem::Exception
|
||||||
|
|
||||||
attr_reader :dependency
|
attr_reader :dependency
|
||||||
|
|
||||||
|
##
|
||||||
|
# Errors encountered which may have contributed to this exception
|
||||||
|
|
||||||
|
attr_accessor :errors
|
||||||
|
|
||||||
##
|
##
|
||||||
# Creates a new UnsatisfiableDependencyError for the unsatisfiable
|
# Creates a new UnsatisfiableDependencyError for the unsatisfiable
|
||||||
# Gem::Resolver::DependencyRequest +dep+
|
# Gem::Resolver::DependencyRequest +dep+
|
||||||
|
@ -239,6 +244,21 @@ class Gem::UnsatisfiableDependencyError < Gem::Exception
|
||||||
end
|
end
|
||||||
|
|
||||||
@dependency = dep
|
@dependency = dep
|
||||||
|
@errors = []
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# The name of the unresolved dependency
|
||||||
|
|
||||||
|
def name
|
||||||
|
@dependency.name
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# The Requirement of the unresolved dependency (not Version).
|
||||||
|
|
||||||
|
def version
|
||||||
|
@dependency.requirement
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -161,7 +161,7 @@ EOF
|
||||||
results = builder.build(extension, @gem_dir, dest_path,
|
results = builder.build(extension, @gem_dir, dest_path,
|
||||||
results, @build_args, lib_dir)
|
results, @build_args, lib_dir)
|
||||||
|
|
||||||
say results.join("\n") if Gem.configuration.really_verbose
|
verbose { results.join("\n") }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -11,13 +11,15 @@ class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder
|
||||||
FileEntry = FileUtils::Entry_ # :nodoc:
|
FileEntry = FileUtils::Entry_ # :nodoc:
|
||||||
|
|
||||||
def self.build(extension, directory, dest_path, results, args=[], lib_dir=nil)
|
def self.build(extension, directory, dest_path, results, args=[], lib_dir=nil)
|
||||||
tmp_dest = Dir.mktmpdir(".gem.", ".")
|
# relative path required as some versions of mktmpdir return an absolute
|
||||||
|
# path which breaks make if it includes a space in the name
|
||||||
|
tmp_dest = get_relative_path(Dir.mktmpdir(".gem.", "."))
|
||||||
|
|
||||||
t = nil
|
t = nil
|
||||||
Tempfile.open %w"siteconf .rb", "." do |siteconf|
|
Tempfile.open %w"siteconf .rb", "." do |siteconf|
|
||||||
t = siteconf
|
t = siteconf
|
||||||
siteconf.puts "require 'rbconfig'"
|
siteconf.puts "require 'rbconfig'"
|
||||||
siteconf.puts "dest_path = #{(tmp_dest || dest_path).dump}"
|
siteconf.puts "dest_path = #{tmp_dest.dump}"
|
||||||
%w[sitearchdir sitelibdir].each do |dir|
|
%w[sitearchdir sitelibdir].each do |dir|
|
||||||
siteconf.puts "RbConfig::MAKEFILE_CONFIG['#{dir}'] = dest_path"
|
siteconf.puts "RbConfig::MAKEFILE_CONFIG['#{dir}'] = dest_path"
|
||||||
siteconf.puts "RbConfig::CONFIG['#{dir}'] = dest_path"
|
siteconf.puts "RbConfig::CONFIG['#{dir}'] = dest_path"
|
||||||
|
@ -25,14 +27,10 @@ class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder
|
||||||
|
|
||||||
siteconf.flush
|
siteconf.flush
|
||||||
|
|
||||||
siteconf_path = File.expand_path siteconf.path
|
|
||||||
|
|
||||||
rubyopt = ENV["RUBYOPT"]
|
|
||||||
destdir = ENV["DESTDIR"]
|
destdir = ENV["DESTDIR"]
|
||||||
|
|
||||||
begin
|
begin
|
||||||
ENV["RUBYOPT"] = ["-r#{siteconf_path}", rubyopt].compact.join(' ')
|
cmd = [Gem.ruby, "-r", get_relative_path(siteconf.path), File.basename(extension), *args].join ' '
|
||||||
cmd = [Gem.ruby, File.basename(extension), *args].join ' '
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
run cmd, results
|
run cmd, results
|
||||||
|
@ -42,7 +40,6 @@ class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder
|
||||||
end
|
end
|
||||||
|
|
||||||
ENV["DESTDIR"] = nil
|
ENV["DESTDIR"] = nil
|
||||||
ENV["RUBYOPT"] = rubyopt
|
|
||||||
|
|
||||||
make dest_path, results
|
make dest_path, results
|
||||||
|
|
||||||
|
@ -57,11 +54,10 @@ class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder
|
||||||
|
|
||||||
FileEntry.new(tmp_dest).traverse do |ent|
|
FileEntry.new(tmp_dest).traverse do |ent|
|
||||||
destent = ent.class.new(dest_path, ent.rel)
|
destent = ent.class.new(dest_path, ent.rel)
|
||||||
destent.exist? or File.rename(ent.path, destent.path)
|
destent.exist? or FileUtils.mv(ent.path, destent.path)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
ensure
|
ensure
|
||||||
ENV["RUBYOPT"] = rubyopt
|
|
||||||
ENV["DESTDIR"] = destdir
|
ENV["DESTDIR"] = destdir
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -72,5 +68,11 @@ class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder
|
||||||
FileUtils.rm_rf tmp_dest if tmp_dest
|
FileUtils.rm_rf tmp_dest if tmp_dest
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def self.get_relative_path(path)
|
||||||
|
path[0..Dir.pwd.length-1] = '.' if path.start_with?(Dir.pwd)
|
||||||
|
path
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,7 @@ module Gem::GemcutterUtilities
|
||||||
|
|
||||||
def sign_in sign_in_host = nil
|
def sign_in sign_in_host = nil
|
||||||
sign_in_host ||= self.host
|
sign_in_host ||= self.host
|
||||||
return if Gem.configuration.rubygems_api_key
|
return if api_key
|
||||||
|
|
||||||
pretty_host = if Gem::DEFAULT_HOST == sign_in_host then
|
pretty_host = if Gem::DEFAULT_HOST == sign_in_host then
|
||||||
'RubyGems.org'
|
'RubyGems.org'
|
||||||
|
|
|
@ -59,6 +59,23 @@ module Gem::InstallUpdateOptions
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
add_option(:"Install/Update", '--build-root DIR',
|
||||||
|
'Temporary installation root. Useful for building',
|
||||||
|
'packages. Do not use this when installing remote gems.') do |value, options|
|
||||||
|
options[:build_root] = File.expand_path(value)
|
||||||
|
end
|
||||||
|
|
||||||
|
add_option(:"Install/Update", '--vendor',
|
||||||
|
'Install gem into the vendor directory.',
|
||||||
|
'Only for use by gem repackagers.') do |value, options|
|
||||||
|
unless Gem.vendor_dir then
|
||||||
|
raise OptionParser::InvalidOption.new 'your platform is not supported'
|
||||||
|
end
|
||||||
|
|
||||||
|
options[:vendor] = true
|
||||||
|
options[:install_dir] = Gem.vendor_dir
|
||||||
|
end
|
||||||
|
|
||||||
add_option(:"Install/Update", '-N', '--no-document',
|
add_option(:"Install/Update", '-N', '--no-document',
|
||||||
'Disable documentation generation') do |value, options|
|
'Disable documentation generation') do |value, options|
|
||||||
options[:document] = []
|
options[:document] = []
|
||||||
|
|
|
@ -39,7 +39,9 @@ class Gem::Installer
|
||||||
|
|
||||||
include Gem::UserInteraction
|
include Gem::UserInteraction
|
||||||
|
|
||||||
# DOC: Missing docs or :nodoc:.
|
##
|
||||||
|
# Filename of the gem being installed.
|
||||||
|
|
||||||
attr_reader :gem
|
attr_reader :gem
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -47,6 +49,8 @@ class Gem::Installer
|
||||||
|
|
||||||
attr_reader :bin_dir
|
attr_reader :bin_dir
|
||||||
|
|
||||||
|
attr_reader :build_root # :nodoc:
|
||||||
|
|
||||||
##
|
##
|
||||||
# The gem repository the gem will be installed into
|
# The gem repository the gem will be installed into
|
||||||
|
|
||||||
|
@ -64,6 +68,8 @@ class Gem::Installer
|
||||||
|
|
||||||
@path_warning = false
|
@path_warning = false
|
||||||
|
|
||||||
|
@install_lock = Mutex.new
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -71,7 +77,19 @@ class Gem::Installer
|
||||||
|
|
||||||
attr_accessor :path_warning
|
attr_accessor :path_warning
|
||||||
|
|
||||||
# DOC: Missing docs or :nodoc:.
|
##
|
||||||
|
# Certain aspects of the install process are not thread-safe. This lock is
|
||||||
|
# used to allow multiple threads to install Gems at the same time.
|
||||||
|
|
||||||
|
attr_reader :install_lock
|
||||||
|
|
||||||
|
##
|
||||||
|
# Overrides the executable format.
|
||||||
|
#
|
||||||
|
# This is a sprintf format with a "%s" which will be replaced with the
|
||||||
|
# executable name. It is based off the ruby executable name's difference
|
||||||
|
# from "ruby".
|
||||||
|
|
||||||
attr_writer :exec_format
|
attr_writer :exec_format
|
||||||
|
|
||||||
# Defaults to use Ruby's program prefix and suffix.
|
# Defaults to use Ruby's program prefix and suffix.
|
||||||
|
@ -240,7 +258,7 @@ class Gem::Installer
|
||||||
|
|
||||||
say spec.post_install_message unless spec.post_install_message.nil?
|
say spec.post_install_message unless spec.post_install_message.nil?
|
||||||
|
|
||||||
Gem::Specification.add_spec spec unless Gem::Specification.include? spec
|
Gem::Installer.install_lock.synchronize { Gem::Specification.add_spec spec }
|
||||||
|
|
||||||
run_post_install_hooks
|
run_post_install_hooks
|
||||||
|
|
||||||
|
@ -318,6 +336,7 @@ class Gem::Installer
|
||||||
# True if the gems in the system satisfy +dependency+.
|
# True if the gems in the system satisfy +dependency+.
|
||||||
|
|
||||||
def installation_satisfies_dependency?(dependency)
|
def installation_satisfies_dependency?(dependency)
|
||||||
|
return true if @options[:development] and dependency.type == :development
|
||||||
return true if installed_specs.detect { |s| dependency.matches_spec? s }
|
return true if installed_specs.detect { |s| dependency.matches_spec? s }
|
||||||
return false if @only_install_dir
|
return false if @only_install_dir
|
||||||
not dependency.matching_specs.empty?
|
not dependency.matching_specs.empty?
|
||||||
|
@ -382,12 +401,11 @@ class Gem::Installer
|
||||||
file.puts windows_stub_script(bindir, filename)
|
file.puts windows_stub_script(bindir, filename)
|
||||||
end
|
end
|
||||||
|
|
||||||
say script_path if Gem.configuration.really_verbose
|
verbose script_path
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# DOC: Missing docs or :nodoc:.
|
def generate_bin # :nodoc:
|
||||||
def generate_bin
|
|
||||||
return if spec.executables.nil? or spec.executables.empty?
|
return if spec.executables.nil? or spec.executables.empty?
|
||||||
|
|
||||||
Dir.mkdir @bin_dir unless File.exist? @bin_dir
|
Dir.mkdir @bin_dir unless File.exist? @bin_dir
|
||||||
|
@ -433,7 +451,7 @@ class Gem::Installer
|
||||||
file.print app_script_text(filename)
|
file.print app_script_text(filename)
|
||||||
end
|
end
|
||||||
|
|
||||||
say bin_script_path if Gem.configuration.really_verbose
|
verbose bin_script_path
|
||||||
|
|
||||||
generate_windows_script filename, bindir
|
generate_windows_script filename, bindir
|
||||||
end
|
end
|
||||||
|
@ -536,8 +554,7 @@ class Gem::Installer
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# DOC: Missing docs or :nodoc:.
|
def ensure_required_ruby_version_met # :nodoc:
|
||||||
def ensure_required_ruby_version_met
|
|
||||||
if rrv = spec.required_ruby_version then
|
if rrv = spec.required_ruby_version then
|
||||||
unless rrv.satisfied_by? Gem.ruby_version then
|
unless rrv.satisfied_by? Gem.ruby_version then
|
||||||
raise Gem::InstallError, "#{spec.name} requires Ruby version #{rrv}."
|
raise Gem::InstallError, "#{spec.name} requires Ruby version #{rrv}."
|
||||||
|
@ -545,8 +562,7 @@ class Gem::Installer
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# DOC: Missing docs or :nodoc:.
|
def ensure_required_rubygems_version_met # :nodoc:
|
||||||
def ensure_required_rubygems_version_met
|
|
||||||
if rrgv = spec.required_rubygems_version then
|
if rrgv = spec.required_rubygems_version then
|
||||||
unless rrgv.satisfied_by? Gem.rubygems_version then
|
unless rrgv.satisfied_by? Gem.rubygems_version then
|
||||||
raise Gem::InstallError,
|
raise Gem::InstallError,
|
||||||
|
@ -556,8 +572,7 @@ class Gem::Installer
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# DOC: Missing docs or :nodoc:.
|
def ensure_dependencies_met # :nodoc:
|
||||||
def ensure_dependencies_met
|
|
||||||
deps = spec.runtime_dependencies
|
deps = spec.runtime_dependencies
|
||||||
deps |= spec.development_dependencies if @development
|
deps |= spec.development_dependencies if @development
|
||||||
|
|
||||||
|
@ -566,8 +581,7 @@ class Gem::Installer
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# DOC: Missing docs or :nodoc:.
|
def process_options # :nodoc:
|
||||||
def process_options
|
|
||||||
@options = {
|
@options = {
|
||||||
:bin_dir => nil,
|
:bin_dir => nil,
|
||||||
:env_shebang => false,
|
:env_shebang => false,
|
||||||
|
@ -590,12 +604,20 @@ class Gem::Installer
|
||||||
# (or use) a new bin dir under the gem_home.
|
# (or use) a new bin dir under the gem_home.
|
||||||
@bin_dir = options[:bin_dir] || Gem.bindir(gem_home)
|
@bin_dir = options[:bin_dir] || Gem.bindir(gem_home)
|
||||||
@development = options[:development]
|
@development = options[:development]
|
||||||
|
@build_root = options[:build_root]
|
||||||
|
|
||||||
@build_args = options[:build_args] || Gem::Command.build_args
|
@build_args = options[:build_args] || Gem::Command.build_args
|
||||||
|
|
||||||
|
unless @build_root.nil?
|
||||||
|
require 'pathname'
|
||||||
|
@build_root = Pathname.new(@build_root).expand_path
|
||||||
|
@bin_dir = File.join(@build_root, options[:bin_dir] || Gem.bindir(@gem_home))
|
||||||
|
@gem_home = File.join(@build_root, @gem_home)
|
||||||
|
alert_warning "You build with buildroot.\n Build root: #{@build_root}\n Bin dir: #{@bin_dir}\n Gem home: #{@gem_home}"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# DOC: Missing docs or :nodoc:.
|
def check_that_user_bin_dir_is_in_path # :nodoc:
|
||||||
def check_that_user_bin_dir_is_in_path
|
|
||||||
user_bin_dir = @bin_dir || Gem.bindir(gem_home)
|
user_bin_dir = @bin_dir || Gem.bindir(gem_home)
|
||||||
user_bin_dir = user_bin_dir.gsub(File::SEPARATOR, File::ALT_SEPARATOR) if
|
user_bin_dir = user_bin_dir.gsub(File::SEPARATOR, File::ALT_SEPARATOR) if
|
||||||
File::ALT_SEPARATOR
|
File::ALT_SEPARATOR
|
||||||
|
@ -606,16 +628,19 @@ class Gem::Installer
|
||||||
user_bin_dir = user_bin_dir.downcase
|
user_bin_dir = user_bin_dir.downcase
|
||||||
end
|
end
|
||||||
|
|
||||||
unless path.split(File::PATH_SEPARATOR).include? user_bin_dir then
|
path = path.split(File::PATH_SEPARATOR)
|
||||||
unless self.class.path_warning then
|
|
||||||
alert_warning "You don't have #{user_bin_dir} in your PATH,\n\t gem executables will not run."
|
unless path.include? user_bin_dir then
|
||||||
self.class.path_warning = true
|
unless !Gem.win_platform? && (path.include? user_bin_dir.sub(ENV['HOME'], '~'))
|
||||||
|
unless self.class.path_warning then
|
||||||
|
alert_warning "You don't have #{user_bin_dir} in your PATH,\n\t gem executables will not run."
|
||||||
|
self.class.path_warning = true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# DOC: Missing docs or :nodoc:.
|
def verify_gem_home(unpack = false) # :nodoc:
|
||||||
def verify_gem_home(unpack = false)
|
|
||||||
FileUtils.mkdir_p gem_home
|
FileUtils.mkdir_p gem_home
|
||||||
raise Gem::FilePermissionError, gem_home unless
|
raise Gem::FilePermissionError, gem_home unless
|
||||||
unpack or File.writable?(gem_home)
|
unpack or File.writable?(gem_home)
|
||||||
|
@ -660,10 +685,10 @@ TEXT
|
||||||
return <<-TEXT
|
return <<-TEXT
|
||||||
@ECHO OFF
|
@ECHO OFF
|
||||||
IF NOT "%~f0" == "~f0" GOTO :WinNT
|
IF NOT "%~f0" == "~f0" GOTO :WinNT
|
||||||
@"#{ruby}" "#{File.join(bindir, bin_file_name)}" %1 %2 %3 %4 %5 %6 %7 %8 %9
|
@"#{bindir.tr(File::SEPARATOR, File::ALT_SEPARATOR)}\\#{ruby}" "#{File.join(bindir, bin_file_name)}" %1 %2 %3 %4 %5 %6 %7 %8 %9
|
||||||
GOTO :EOF
|
GOTO :EOF
|
||||||
:WinNT
|
:WinNT
|
||||||
@"#{ruby}" "%~dpn0" %*
|
@"%~dp0#{ruby}" "%~dpn0" %*
|
||||||
TEXT
|
TEXT
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -101,6 +101,8 @@ class Gem::InstallerTestCase < Gem::TestCase
|
||||||
|
|
||||||
@installer = util_installer @spec, @gemhome
|
@installer = util_installer @spec, @gemhome
|
||||||
@user_installer = util_installer @user_spec, Gem.user_dir, :user
|
@user_installer = util_installer @user_spec, Gem.user_dir, :user
|
||||||
|
|
||||||
|
Gem::Installer.path_warning = false
|
||||||
end
|
end
|
||||||
|
|
||||||
def util_gem_bindir spec = @spec # :nodoc:
|
def util_gem_bindir spec = @spec # :nodoc:
|
||||||
|
|
|
@ -100,8 +100,8 @@ module Gem::LocalRemoteOptions
|
||||||
def add_source_option
|
def add_source_option
|
||||||
accept_uri_http
|
accept_uri_http
|
||||||
|
|
||||||
add_option(:"Local/Remote", '--source URL', URI::HTTP,
|
add_option(:"Local/Remote", '-s', '--source URL', URI::HTTP,
|
||||||
'Add URL as a remote source for gems') do |source, options|
|
'Append URL to list of remote gem sources') do |source, options|
|
||||||
|
|
||||||
source << '/' if source !~ /\/\z/
|
source << '/' if source !~ /\/\z/
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ class Gem::NameTuple
|
||||||
"#{@name}-#{@version}"
|
"#{@name}-#{@version}"
|
||||||
else
|
else
|
||||||
"#{@name}-#{@version}-#{@platform}"
|
"#{@name}-#{@version}-#{@platform}"
|
||||||
end
|
end.untaint
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -90,7 +90,9 @@ class Gem::NameTuple
|
||||||
alias to_s inspect # :nodoc:
|
alias to_s inspect # :nodoc:
|
||||||
|
|
||||||
def <=> other
|
def <=> other
|
||||||
to_a <=> other.to_a
|
[@name, @version, @platform == Gem::Platform::RUBY ? -1 : 1] <=>
|
||||||
|
[other.name, other.version,
|
||||||
|
other.platform == Gem::Platform::RUBY ? -1 : 1]
|
||||||
end
|
end
|
||||||
|
|
||||||
include Comparable
|
include Comparable
|
||||||
|
|
|
@ -54,10 +54,12 @@ class Gem::Package
|
||||||
class FormatError < Error
|
class FormatError < Error
|
||||||
attr_reader :path
|
attr_reader :path
|
||||||
|
|
||||||
def initialize message, path = nil
|
def initialize message, source = nil
|
||||||
@path = path
|
if source
|
||||||
|
@path = source.path
|
||||||
|
|
||||||
message << " in #{path}" if path
|
message << " in #{path}" if path
|
||||||
|
end
|
||||||
|
|
||||||
super message
|
super message
|
||||||
end
|
end
|
||||||
|
@ -80,6 +82,7 @@ class Gem::Package
|
||||||
|
|
||||||
class TarInvalidError < Error; end
|
class TarInvalidError < Error; end
|
||||||
|
|
||||||
|
|
||||||
attr_accessor :build_time # :nodoc:
|
attr_accessor :build_time # :nodoc:
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -114,19 +117,26 @@ class Gem::Package
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Creates a new Gem::Package for the file at +gem+.
|
# Creates a new Gem::Package for the file at +gem+. +gem+ can also be
|
||||||
|
# provided as an IO object.
|
||||||
#
|
#
|
||||||
# If +gem+ is an existing file in the old format a Gem::Package::Old will be
|
# If +gem+ is an existing file in the old format a Gem::Package::Old will be
|
||||||
# returned.
|
# returned.
|
||||||
|
|
||||||
def self.new gem
|
def self.new gem
|
||||||
return super unless Gem::Package == self
|
gem = if gem.is_a?(Gem::Package::Source)
|
||||||
return super unless File.exist? gem
|
gem
|
||||||
|
elsif gem.respond_to? :read
|
||||||
|
Gem::Package::IOSource.new gem
|
||||||
|
else
|
||||||
|
Gem::Package::FileSource.new gem
|
||||||
|
end
|
||||||
|
|
||||||
start = File.read gem, 20
|
return super(gem) unless Gem::Package == self
|
||||||
|
return super unless gem.present?
|
||||||
|
|
||||||
return super unless start
|
return super unless gem.start
|
||||||
return super unless start.include? 'MD5SUM ='
|
return super unless gem.start.include? 'MD5SUM ='
|
||||||
|
|
||||||
Gem::Package::Old.new gem
|
Gem::Package::Old.new gem
|
||||||
end
|
end
|
||||||
|
@ -227,7 +237,7 @@ class Gem::Package
|
||||||
|
|
||||||
setup_signer
|
setup_signer
|
||||||
|
|
||||||
open @gem, 'wb' do |gem_io|
|
@gem.with_write_io do |gem_io|
|
||||||
Gem::Package::TarWriter.new gem_io do |gem|
|
Gem::Package::TarWriter.new gem_io do |gem|
|
||||||
add_metadata gem
|
add_metadata gem
|
||||||
add_contents gem
|
add_contents gem
|
||||||
|
@ -255,7 +265,7 @@ EOM
|
||||||
|
|
||||||
@contents = []
|
@contents = []
|
||||||
|
|
||||||
open @gem, 'rb' do |io|
|
@gem.with_read_io do |io|
|
||||||
gem_tar = Gem::Package::TarReader.new io
|
gem_tar = Gem::Package::TarReader.new io
|
||||||
|
|
||||||
gem_tar.each do |entry|
|
gem_tar.each do |entry|
|
||||||
|
@ -312,7 +322,7 @@ EOM
|
||||||
|
|
||||||
FileUtils.mkdir_p destination_dir
|
FileUtils.mkdir_p destination_dir
|
||||||
|
|
||||||
open @gem, 'rb' do |io|
|
@gem.with_read_io do |io|
|
||||||
reader = Gem::Package::TarReader.new io
|
reader = Gem::Package::TarReader.new io
|
||||||
|
|
||||||
reader.each do |entry|
|
reader.each do |entry|
|
||||||
|
@ -360,7 +370,7 @@ EOM
|
||||||
out.write entry.read
|
out.write entry.read
|
||||||
end if entry.file?
|
end if entry.file?
|
||||||
|
|
||||||
say destination if Gem.configuration.really_verbose
|
verbose destination
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -490,7 +500,7 @@ EOM
|
||||||
@files = []
|
@files = []
|
||||||
@spec = nil
|
@spec = nil
|
||||||
|
|
||||||
open @gem, 'rb' do |io|
|
@gem.with_read_io do |io|
|
||||||
Gem::Package::TarReader.new io do |reader|
|
Gem::Package::TarReader.new io do |reader|
|
||||||
read_checksums reader
|
read_checksums reader
|
||||||
|
|
||||||
|
@ -592,6 +602,9 @@ EOM
|
||||||
end
|
end
|
||||||
|
|
||||||
require 'rubygems/package/digest_io'
|
require 'rubygems/package/digest_io'
|
||||||
|
require 'rubygems/package/source'
|
||||||
|
require 'rubygems/package/file_source'
|
||||||
|
require 'rubygems/package/io_source'
|
||||||
require 'rubygems/package/old'
|
require 'rubygems/package/old'
|
||||||
require 'rubygems/package/tar_header'
|
require 'rubygems/package/tar_header'
|
||||||
require 'rubygems/package/tar_reader'
|
require 'rubygems/package/tar_reader'
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
##
|
||||||
|
# The primary source of gems is a file on disk, including all usages
|
||||||
|
# internal to rubygems.
|
||||||
|
#
|
||||||
|
# This is a private class, do not depend on it directly. Instead, pass a path
|
||||||
|
# object to `Gem::Package.new`.
|
||||||
|
|
||||||
|
class Gem::Package::FileSource < Gem::Package::Source # :nodoc: all
|
||||||
|
|
||||||
|
attr_reader :path
|
||||||
|
|
||||||
|
def initialize path
|
||||||
|
@path = path
|
||||||
|
end
|
||||||
|
|
||||||
|
def start
|
||||||
|
@start ||= File.read path, 20
|
||||||
|
end
|
||||||
|
|
||||||
|
def present?
|
||||||
|
File.exist? path
|
||||||
|
end
|
||||||
|
|
||||||
|
def with_write_io &block
|
||||||
|
open path, 'wb', &block
|
||||||
|
end
|
||||||
|
|
||||||
|
def with_read_io &block
|
||||||
|
open path, 'rb', &block
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
##
|
||||||
|
# Supports reading and writing gems from/to a generic IO object. This is
|
||||||
|
# useful for other applications built on top of rubygems, such as
|
||||||
|
# rubygems.org.
|
||||||
|
#
|
||||||
|
# This is a private class, do not depend on it directly. Instead, pass an IO
|
||||||
|
# object to `Gem::Package.new`.
|
||||||
|
|
||||||
|
class Gem::Package::IOSource < Gem::Package::Source # :nodoc: all
|
||||||
|
|
||||||
|
attr_reader :io
|
||||||
|
|
||||||
|
def initialize io
|
||||||
|
@io = io
|
||||||
|
end
|
||||||
|
|
||||||
|
def start
|
||||||
|
@start ||= begin
|
||||||
|
if io.pos > 0
|
||||||
|
raise Gem::Package::Error, "Cannot read start unless IO is at start"
|
||||||
|
end
|
||||||
|
|
||||||
|
value = io.read 20
|
||||||
|
io.rewind
|
||||||
|
value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def present?
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def with_read_io
|
||||||
|
yield io
|
||||||
|
end
|
||||||
|
|
||||||
|
def with_write_io
|
||||||
|
yield io
|
||||||
|
end
|
||||||
|
|
||||||
|
def path
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
|
@ -37,7 +37,7 @@ class Gem::Package::Old < Gem::Package
|
||||||
|
|
||||||
return @contents if @contents
|
return @contents if @contents
|
||||||
|
|
||||||
open @gem, 'rb' do |io|
|
@gem.with_read_io do |io|
|
||||||
read_until_dashes io # spec
|
read_until_dashes io # spec
|
||||||
header = file_list io
|
header = file_list io
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ class Gem::Package::Old < Gem::Package
|
||||||
|
|
||||||
errstr = "Error reading files from gem"
|
errstr = "Error reading files from gem"
|
||||||
|
|
||||||
open @gem, 'rb' do |io|
|
@gem.with_read_io do |io|
|
||||||
read_until_dashes io # spec
|
read_until_dashes io # spec
|
||||||
header = file_list io
|
header = file_list io
|
||||||
raise Gem::Exception, errstr unless header
|
raise Gem::Exception, errstr unless header
|
||||||
|
@ -83,7 +83,7 @@ class Gem::Package::Old < Gem::Package
|
||||||
out.write file_data
|
out.write file_data
|
||||||
end
|
end
|
||||||
|
|
||||||
say destination if Gem.configuration.really_verbose
|
verbose destination
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
rescue Zlib::DataError
|
rescue Zlib::DataError
|
||||||
|
@ -136,7 +136,7 @@ class Gem::Package::Old < Gem::Package
|
||||||
|
|
||||||
yaml = ''
|
yaml = ''
|
||||||
|
|
||||||
open @gem, 'rb' do |io|
|
@gem.with_read_io do |io|
|
||||||
skip_ruby io
|
skip_ruby io
|
||||||
read_until_dashes io do |line|
|
read_until_dashes io do |line|
|
||||||
yaml << line
|
yaml << line
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
class Gem::Package::Source # :nodoc:
|
||||||
|
end
|
||||||
|
|
|
@ -129,6 +129,8 @@ class Gem::Package::TarReader::Entry
|
||||||
ret
|
ret
|
||||||
end
|
end
|
||||||
|
|
||||||
|
alias readpartial read # :nodoc:
|
||||||
|
|
||||||
##
|
##
|
||||||
# Rewinds to the beginning of the tar file entry
|
# Rewinds to the beginning of the tar file entry
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ class Gem::Platform
|
||||||
|
|
||||||
def self.local
|
def self.local
|
||||||
arch = RbConfig::CONFIG['arch']
|
arch = RbConfig::CONFIG['arch']
|
||||||
arch = "#{arch}_60" if arch =~ /mswin32$/
|
arch = "#{arch}_60" if arch =~ /mswin(?:32|64)$/
|
||||||
@local ||= new(arch)
|
@local ||= new(arch)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -173,6 +173,7 @@ class Gem::Platform
|
||||||
when /^dalvik(\d+)?$/ then [nil, 'dalvik', $1 ]
|
when /^dalvik(\d+)?$/ then [nil, 'dalvik', $1 ]
|
||||||
when /dotnet(\-(\d+\.\d+))?/ then ['universal','dotnet', $2 ]
|
when /dotnet(\-(\d+\.\d+))?/ then ['universal','dotnet', $2 ]
|
||||||
when /mswin32(\_(\d+))?/ then ['x86', 'mswin32', $2 ]
|
when /mswin32(\_(\d+))?/ then ['x86', 'mswin32', $2 ]
|
||||||
|
when /mswin64(\_(\d+))?/ then ['x64', 'mswin64', $2 ]
|
||||||
when 'powerpc-darwin' then ['powerpc', 'darwin', nil ]
|
when 'powerpc-darwin' then ['powerpc', 'darwin', nil ]
|
||||||
when /powerpc-darwin(\d)/ then ['powerpc', 'darwin', $1 ]
|
when /powerpc-darwin(\d)/ then ['powerpc', 'darwin', $1 ]
|
||||||
when /sparc-solaris2.8/ then ['sparc', 'solaris', '2.8' ]
|
when /sparc-solaris2.8/ then ['sparc', 'solaris', '2.8' ]
|
||||||
|
|
|
@ -263,7 +263,7 @@ class Gem::RDoc # :nodoc: all
|
||||||
Gem::Requirement.new('>= 2.4.0') =~ self.class.rdoc_version
|
Gem::Requirement.new('>= 2.4.0') =~ self.class.rdoc_version
|
||||||
|
|
||||||
r = new_rdoc
|
r = new_rdoc
|
||||||
say "rdoc #{args.join ' '}" if Gem.configuration.really_verbose
|
verbose { "rdoc #{args.join ' '}" }
|
||||||
|
|
||||||
Dir.chdir @spec.full_gem_path do
|
Dir.chdir @spec.full_gem_path do
|
||||||
begin
|
begin
|
||||||
|
@ -279,7 +279,6 @@ class Gem::RDoc # :nodoc: all
|
||||||
ui.errs.puts "... RDOC args: #{args.join(' ')}"
|
ui.errs.puts "... RDOC args: #{args.join(' ')}"
|
||||||
ui.backtrace ex
|
ui.backtrace ex
|
||||||
ui.errs.puts "(continuing with the rest of the installation)"
|
ui.errs.puts "(continuing with the rest of the installation)"
|
||||||
ensure
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,6 +2,7 @@ require 'rubygems'
|
||||||
require 'rubygems/request'
|
require 'rubygems/request'
|
||||||
require 'rubygems/uri_formatter'
|
require 'rubygems/uri_formatter'
|
||||||
require 'rubygems/user_interaction'
|
require 'rubygems/user_interaction'
|
||||||
|
require 'rubygems/request/connection_pools'
|
||||||
require 'resolv'
|
require 'resolv'
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -73,6 +74,9 @@ class Gem::RemoteFetcher
|
||||||
Socket.do_not_reverse_lookup = true
|
Socket.do_not_reverse_lookup = true
|
||||||
|
|
||||||
@proxy = proxy
|
@proxy = proxy
|
||||||
|
@pools = {}
|
||||||
|
@pool_lock = Mutex.new
|
||||||
|
@cert_files = Gem::Request.get_cert_files
|
||||||
|
|
||||||
@dns = dns
|
@dns = dns
|
||||||
end
|
end
|
||||||
|
@ -154,11 +158,10 @@ class Gem::RemoteFetcher
|
||||||
# REFACTOR: split this up and dispatch on scheme (eg download_http)
|
# REFACTOR: split this up and dispatch on scheme (eg download_http)
|
||||||
# REFACTOR: be sure to clean up fake fetcher when you do this... cleaner
|
# REFACTOR: be sure to clean up fake fetcher when you do this... cleaner
|
||||||
case scheme
|
case scheme
|
||||||
when 'http', 'https' then
|
when 'http', 'https', 's3' then
|
||||||
unless File.exist? local_gem_path then
|
unless File.exist? local_gem_path then
|
||||||
begin
|
begin
|
||||||
say "Downloading gem #{gem_file_name}" if
|
verbose "Downloading gem #{gem_file_name}"
|
||||||
Gem.configuration.really_verbose
|
|
||||||
|
|
||||||
remote_gem_path = source_uri + "gems/#{gem_file_name}"
|
remote_gem_path = source_uri + "gems/#{gem_file_name}"
|
||||||
|
|
||||||
|
@ -168,8 +171,7 @@ class Gem::RemoteFetcher
|
||||||
|
|
||||||
alternate_name = "#{spec.original_name}.gem"
|
alternate_name = "#{spec.original_name}.gem"
|
||||||
|
|
||||||
say "Failed, downloading gem #{alternate_name}" if
|
verbose "Failed, downloading gem #{alternate_name}"
|
||||||
Gem.configuration.really_verbose
|
|
||||||
|
|
||||||
remote_gem_path = source_uri + "gems/#{alternate_name}"
|
remote_gem_path = source_uri + "gems/#{alternate_name}"
|
||||||
|
|
||||||
|
@ -188,8 +190,7 @@ class Gem::RemoteFetcher
|
||||||
local_gem_path = source_uri.to_s
|
local_gem_path = source_uri.to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
say "Using local gem #{local_gem_path}" if
|
verbose "Using local gem #{local_gem_path}"
|
||||||
Gem.configuration.really_verbose
|
|
||||||
when nil then # TODO test for local overriding cache
|
when nil then # TODO test for local overriding cache
|
||||||
source_path = if Gem.win_platform? && source_uri.scheme &&
|
source_path = if Gem.win_platform? && source_uri.scheme &&
|
||||||
!source_uri.path.include?(':') then
|
!source_uri.path.include?(':') then
|
||||||
|
@ -207,8 +208,7 @@ class Gem::RemoteFetcher
|
||||||
local_gem_path = source_uri.to_s
|
local_gem_path = source_uri.to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
say "Using local gem #{local_gem_path}" if
|
verbose "Using local gem #{local_gem_path}"
|
||||||
Gem.configuration.really_verbose
|
|
||||||
else
|
else
|
||||||
raise ArgumentError, "unsupported URI scheme #{source_uri.scheme}"
|
raise ArgumentError, "unsupported URI scheme #{source_uri.scheme}"
|
||||||
end
|
end
|
||||||
|
@ -232,6 +232,7 @@ class Gem::RemoteFetcher
|
||||||
|
|
||||||
case response
|
case response
|
||||||
when Net::HTTPOK, Net::HTTPNotModified then
|
when Net::HTTPOK, Net::HTTPNotModified then
|
||||||
|
response.uri = uri if response.respond_to? :uri
|
||||||
head ? response : response.body
|
head ? response : response.body
|
||||||
when Net::HTTPMovedPermanently, Net::HTTPFound, Net::HTTPSeeOther,
|
when Net::HTTPMovedPermanently, Net::HTTPFound, Net::HTTPSeeOther,
|
||||||
Net::HTTPTemporaryRedirect then
|
Net::HTTPTemporaryRedirect then
|
||||||
|
@ -265,7 +266,7 @@ class Gem::RemoteFetcher
|
||||||
|
|
||||||
data = send "fetch_#{uri.scheme}", uri, mtime, head
|
data = send "fetch_#{uri.scheme}", uri, mtime, head
|
||||||
|
|
||||||
if data and !head and uri.to_s =~ /gz$/
|
if data and !head and uri.to_s =~ /\.gz$/
|
||||||
begin
|
begin
|
||||||
data = Gem.gunzip data
|
data = Gem.gunzip data
|
||||||
rescue Zlib::GzipFile::Error
|
rescue Zlib::GzipFile::Error
|
||||||
|
@ -286,6 +287,11 @@ class Gem::RemoteFetcher
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def fetch_s3(uri, mtime = nil, head = false)
|
||||||
|
public_uri = sign_s3_url(uri)
|
||||||
|
fetch_https public_uri, mtime, head
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Downloads +uri+ to +path+ if necessary. If no path is given, it just
|
# Downloads +uri+ to +path+ if necessary. If no path is given, it just
|
||||||
# passes the data.
|
# passes the data.
|
||||||
|
@ -332,18 +338,57 @@ class Gem::RemoteFetcher
|
||||||
# connections to reduce connect overhead.
|
# connections to reduce connect overhead.
|
||||||
|
|
||||||
def request(uri, request_class, last_modified = nil)
|
def request(uri, request_class, last_modified = nil)
|
||||||
request = Gem::Request.new uri, request_class, last_modified, @proxy
|
proxy = proxy_for @proxy, uri
|
||||||
|
pool = pools_for(proxy).pool_for uri
|
||||||
|
|
||||||
|
request = Gem::Request.new uri, request_class, last_modified, pool
|
||||||
|
|
||||||
request.fetch do |req|
|
request.fetch do |req|
|
||||||
yield req if block_given?
|
yield req if block_given?
|
||||||
end
|
end
|
||||||
ensure
|
|
||||||
request.close if request
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def https?(uri)
|
def https?(uri)
|
||||||
uri.scheme.downcase == 'https'
|
uri.scheme.downcase == 'https'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
# we have our own signing code here to avoid a dependency on the aws-sdk gem
|
||||||
|
# fortunately, a simple GET request isn't too complex to sign properly
|
||||||
|
def sign_s3_url(uri, expiration = nil)
|
||||||
|
require 'base64'
|
||||||
|
require 'openssl'
|
||||||
|
|
||||||
|
unless uri.user && uri.password
|
||||||
|
raise FetchError.new("credentials needed in s3 source, like s3://key:secret@bucket-name/", uri.to_s)
|
||||||
|
end
|
||||||
|
|
||||||
|
expiration ||= s3_expiration
|
||||||
|
canonical_path = "/#{uri.host}#{uri.path}"
|
||||||
|
payload = "GET\n\n\n#{expiration}\n#{canonical_path}"
|
||||||
|
digest = OpenSSL::HMAC.digest('sha1', uri.password, payload)
|
||||||
|
# URI.escape is deprecated, and there isn't yet a replacement that does quite what we want
|
||||||
|
signature = Base64.encode64(digest).gsub("\n", '').gsub(/[\+\/=]/) { |c| BASE64_URI_TRANSLATE[c] }
|
||||||
|
URI.parse("https://#{uri.host}.s3.amazonaws.com#{uri.path}?AWSAccessKeyId=#{uri.user}&Expires=#{expiration}&Signature=#{signature}")
|
||||||
|
end
|
||||||
|
|
||||||
|
def s3_expiration
|
||||||
|
(Time.now + 3600).to_i # one hour from now
|
||||||
|
end
|
||||||
|
|
||||||
|
BASE64_URI_TRANSLATE = { '+' => '%2B', '/' => '%2F', '=' => '%3D' }.freeze
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def proxy_for proxy, uri
|
||||||
|
Gem::Request.proxy_uri(proxy || Gem::Request.get_proxy_from_env(uri.scheme))
|
||||||
|
end
|
||||||
|
|
||||||
|
def pools_for proxy
|
||||||
|
@pool_lock.synchronize do
|
||||||
|
@pools[proxy] ||= Gem::Request::ConnectionPools.new proxy, @cert_files
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -7,41 +7,43 @@ class Gem::Request
|
||||||
|
|
||||||
include Gem::UserInteraction
|
include Gem::UserInteraction
|
||||||
|
|
||||||
attr_reader :proxy_uri
|
###
|
||||||
|
# Legacy. This is used in tests.
|
||||||
|
def self.create_with_proxy uri, request_class, last_modified, proxy # :nodoc:
|
||||||
|
cert_files = get_cert_files
|
||||||
|
proxy ||= get_proxy_from_env(uri.scheme)
|
||||||
|
pool = ConnectionPools.new proxy_uri(proxy), cert_files
|
||||||
|
|
||||||
def initialize(uri, request_class, last_modified, proxy)
|
new(uri, request_class, last_modified, pool.pool_for(uri))
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.proxy_uri proxy # :nodoc:
|
||||||
|
case proxy
|
||||||
|
when :no_proxy then nil
|
||||||
|
when URI::HTTP then proxy
|
||||||
|
else URI.parse(proxy)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize(uri, request_class, last_modified, pool)
|
||||||
@uri = uri
|
@uri = uri
|
||||||
@request_class = request_class
|
@request_class = request_class
|
||||||
@last_modified = last_modified
|
@last_modified = last_modified
|
||||||
@requests = Hash.new 0
|
@requests = Hash.new 0
|
||||||
@connections = {}
|
|
||||||
@connections_mutex = Mutex.new
|
|
||||||
@user_agent = user_agent
|
@user_agent = user_agent
|
||||||
|
|
||||||
@proxy_uri =
|
@connection_pool = pool
|
||||||
case proxy
|
|
||||||
when :no_proxy then nil
|
|
||||||
when nil then get_proxy_from_env uri.scheme
|
|
||||||
when URI::HTTP then proxy
|
|
||||||
else URI.parse(proxy)
|
|
||||||
end
|
|
||||||
@env_no_proxy = get_no_proxy_from_env
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def close
|
def proxy_uri; @connection_pool.proxy_uri; end
|
||||||
@connections.each_value do |conn|
|
def cert_files; @connection_pool.cert_files; end
|
||||||
conn.finish
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_rubygems_trusted_certs(store)
|
def self.get_cert_files
|
||||||
pattern = File.expand_path("./ssl_certs/*.pem", File.dirname(__FILE__))
|
pattern = File.expand_path("./ssl_certs/*.pem", File.dirname(__FILE__))
|
||||||
Dir.glob(pattern).each do |ssl_cert_file|
|
Dir.glob(pattern)
|
||||||
store.add_file ssl_cert_file
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def configure_connection_for_https(connection)
|
def self.configure_connection_for_https(connection, cert_files)
|
||||||
require 'net/https'
|
require 'net/https'
|
||||||
connection.use_ssl = true
|
connection.use_ssl = true
|
||||||
connection.verify_mode =
|
connection.verify_mode =
|
||||||
|
@ -55,7 +57,9 @@ class Gem::Request
|
||||||
end
|
end
|
||||||
|
|
||||||
store.set_default_paths
|
store.set_default_paths
|
||||||
add_rubygems_trusted_certs(store)
|
cert_files.each do |ssl_cert_file|
|
||||||
|
store.add_file ssl_cert_file
|
||||||
|
end
|
||||||
if Gem.configuration.ssl_ca_cert
|
if Gem.configuration.ssl_ca_cert
|
||||||
if File.directory? Gem.configuration.ssl_ca_cert
|
if File.directory? Gem.configuration.ssl_ca_cert
|
||||||
store.add_path Gem.configuration.ssl_ca_cert
|
store.add_path Gem.configuration.ssl_ca_cert
|
||||||
|
@ -64,6 +68,7 @@ class Gem::Request
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
connection.cert_store = store
|
connection.cert_store = store
|
||||||
|
connection
|
||||||
rescue LoadError => e
|
rescue LoadError => e
|
||||||
raise unless (e.respond_to?(:path) && e.path == 'openssl') ||
|
raise unless (e.respond_to?(:path) && e.path == 'openssl') ||
|
||||||
e.message =~ / -- openssl$/
|
e.message =~ / -- openssl$/
|
||||||
|
@ -77,31 +82,7 @@ class Gem::Request
|
||||||
# connection, using a proxy if needed.
|
# connection, using a proxy if needed.
|
||||||
|
|
||||||
def connection_for(uri)
|
def connection_for(uri)
|
||||||
net_http_args = [uri.host, uri.port]
|
@connection_pool.checkout
|
||||||
|
|
||||||
if @proxy_uri and not no_proxy?(uri.host) then
|
|
||||||
net_http_args += [
|
|
||||||
@proxy_uri.host,
|
|
||||||
@proxy_uri.port,
|
|
||||||
Gem::UriFormatter.new(@proxy_uri.user).unescape,
|
|
||||||
Gem::UriFormatter.new(@proxy_uri.password).unescape,
|
|
||||||
]
|
|
||||||
end
|
|
||||||
|
|
||||||
connection_id = [Thread.current.object_id, *net_http_args].join ':'
|
|
||||||
|
|
||||||
connection = @connections_mutex.synchronize do
|
|
||||||
@connections[connection_id] ||= Net::HTTP.new(*net_http_args)
|
|
||||||
@connections[connection_id]
|
|
||||||
end
|
|
||||||
|
|
||||||
if https?(uri) and not connection.started? then
|
|
||||||
configure_connection_for_https(connection)
|
|
||||||
end
|
|
||||||
|
|
||||||
connection.start unless connection.started?
|
|
||||||
|
|
||||||
connection
|
|
||||||
rescue defined?(OpenSSL::SSL) ? OpenSSL::SSL::SSLError : Errno::EHOSTDOWN,
|
rescue defined?(OpenSSL::SSL) ? OpenSSL::SSL::SSLError : Errno::EHOSTDOWN,
|
||||||
Errno::EHOSTDOWN => e
|
Errno::EHOSTDOWN => e
|
||||||
raise Gem::RemoteFetcher::FetchError.new(e.message, uri)
|
raise Gem::RemoteFetcher::FetchError.new(e.message, uri)
|
||||||
|
@ -125,6 +106,37 @@ class Gem::Request
|
||||||
|
|
||||||
yield request if block_given?
|
yield request if block_given?
|
||||||
|
|
||||||
|
perform_request request
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Returns a proxy URI for the given +scheme+ if one is set in the
|
||||||
|
# environment variables.
|
||||||
|
|
||||||
|
def self.get_proxy_from_env scheme = 'http'
|
||||||
|
_scheme = scheme.downcase
|
||||||
|
_SCHEME = scheme.upcase
|
||||||
|
env_proxy = ENV["#{_scheme}_proxy"] || ENV["#{_SCHEME}_PROXY"]
|
||||||
|
|
||||||
|
no_env_proxy = env_proxy.nil? || env_proxy.empty?
|
||||||
|
|
||||||
|
return get_proxy_from_env 'http' if no_env_proxy and _scheme != 'http'
|
||||||
|
return :no_proxy if no_env_proxy
|
||||||
|
|
||||||
|
uri = URI(Gem::UriFormatter.new(env_proxy).normalize)
|
||||||
|
|
||||||
|
if uri and uri.user.nil? and uri.password.nil? then
|
||||||
|
user = ENV["#{_scheme}_proxy_user"] || ENV["#{_SCHEME}_PROXY_USER"]
|
||||||
|
password = ENV["#{_scheme}_proxy_pass"] || ENV["#{_SCHEME}_PROXY_PASS"]
|
||||||
|
|
||||||
|
uri.user = Gem::UriFormatter.new(user).escape
|
||||||
|
uri.password = Gem::UriFormatter.new(password).escape
|
||||||
|
end
|
||||||
|
|
||||||
|
uri
|
||||||
|
end
|
||||||
|
|
||||||
|
def perform_request request # :nodoc:
|
||||||
connection = connection_for @uri
|
connection = connection_for @uri
|
||||||
|
|
||||||
retried = false
|
retried = false
|
||||||
|
@ -133,8 +145,7 @@ class Gem::Request
|
||||||
begin
|
begin
|
||||||
@requests[connection.object_id] += 1
|
@requests[connection.object_id] += 1
|
||||||
|
|
||||||
say "#{request.method} #{@uri}" if
|
verbose "#{request.method} #{@uri}"
|
||||||
Gem.configuration.really_verbose
|
|
||||||
|
|
||||||
file_name = File.basename(@uri.path)
|
file_name = File.basename(@uri.path)
|
||||||
# perform download progress reporter only for gems
|
# perform download progress reporter only for gems
|
||||||
|
@ -163,11 +174,10 @@ class Gem::Request
|
||||||
response = connection.request request
|
response = connection.request request
|
||||||
end
|
end
|
||||||
|
|
||||||
say "#{response.code} #{response.message}" if
|
verbose "#{response.code} #{response.message}"
|
||||||
Gem.configuration.really_verbose
|
|
||||||
|
|
||||||
rescue Net::HTTPBadResponse
|
rescue Net::HTTPBadResponse
|
||||||
say "bad response" if Gem.configuration.really_verbose
|
verbose "bad response"
|
||||||
|
|
||||||
reset connection
|
reset connection
|
||||||
|
|
||||||
|
@ -182,8 +192,7 @@ class Gem::Request
|
||||||
Errno::ECONNABORTED, Errno::ECONNRESET, Errno::EPIPE
|
Errno::ECONNABORTED, Errno::ECONNRESET, Errno::EPIPE
|
||||||
|
|
||||||
requests = @requests[connection.object_id]
|
requests = @requests[connection.object_id]
|
||||||
say "connection reset after #{requests} requests, retrying" if
|
verbose "connection reset after #{requests} requests, retrying"
|
||||||
Gem.configuration.really_verbose
|
|
||||||
|
|
||||||
raise Gem::RemoteFetcher::FetchError.new('too many connection resets', @uri) if retried
|
raise Gem::RemoteFetcher::FetchError.new('too many connection resets', @uri) if retried
|
||||||
|
|
||||||
|
@ -194,57 +203,8 @@ class Gem::Request
|
||||||
end
|
end
|
||||||
|
|
||||||
response
|
response
|
||||||
end
|
ensure
|
||||||
|
@connection_pool.checkin connection
|
||||||
##
|
|
||||||
# Returns list of no_proxy entries (if any) from the environment
|
|
||||||
|
|
||||||
def get_no_proxy_from_env
|
|
||||||
env_no_proxy = ENV['no_proxy'] || ENV['NO_PROXY']
|
|
||||||
|
|
||||||
return [] if env_no_proxy.nil? or env_no_proxy.empty?
|
|
||||||
|
|
||||||
env_no_proxy.split(/\s*,\s*/)
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# Returns a proxy URI for the given +scheme+ if one is set in the
|
|
||||||
# environment variables.
|
|
||||||
|
|
||||||
def get_proxy_from_env scheme = 'http'
|
|
||||||
_scheme = scheme.downcase
|
|
||||||
_SCHEME = scheme.upcase
|
|
||||||
env_proxy = ENV["#{_scheme}_proxy"] || ENV["#{_SCHEME}_PROXY"]
|
|
||||||
|
|
||||||
no_env_proxy = env_proxy.nil? || env_proxy.empty?
|
|
||||||
|
|
||||||
return get_proxy_from_env 'http' if no_env_proxy and _scheme != 'http'
|
|
||||||
return nil if no_env_proxy
|
|
||||||
|
|
||||||
uri = URI(Gem::UriFormatter.new(env_proxy).normalize)
|
|
||||||
|
|
||||||
if uri and uri.user.nil? and uri.password.nil? then
|
|
||||||
user = ENV["#{_scheme}_proxy_user"] || ENV["#{_SCHEME}_PROXY_USER"]
|
|
||||||
password = ENV["#{_scheme}_proxy_pass"] || ENV["#{_SCHEME}_PROXY_PASS"]
|
|
||||||
|
|
||||||
uri.user = Gem::UriFormatter.new(user).escape
|
|
||||||
uri.password = Gem::UriFormatter.new(password).escape
|
|
||||||
end
|
|
||||||
|
|
||||||
uri
|
|
||||||
end
|
|
||||||
|
|
||||||
def https?(uri)
|
|
||||||
uri.scheme.downcase == 'https'
|
|
||||||
end
|
|
||||||
|
|
||||||
def no_proxy? host
|
|
||||||
host = host.downcase
|
|
||||||
@env_no_proxy.each do |pattern|
|
|
||||||
pattern = pattern.downcase
|
|
||||||
return true if host[-pattern.length, pattern.length ] == pattern
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -278,3 +238,7 @@ class Gem::Request
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require 'rubygems/request/http_pool'
|
||||||
|
require 'rubygems/request/https_pool'
|
||||||
|
require 'rubygems/request/connection_pools'
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
require 'thread'
|
||||||
|
|
||||||
|
class Gem::Request::ConnectionPools # :nodoc:
|
||||||
|
|
||||||
|
@client = Net::HTTP
|
||||||
|
|
||||||
|
class << self
|
||||||
|
attr_accessor :client
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize proxy_uri, cert_files
|
||||||
|
@proxy_uri = proxy_uri
|
||||||
|
@cert_files = cert_files
|
||||||
|
@pools = {}
|
||||||
|
@pool_mutex = Mutex.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def pool_for uri
|
||||||
|
http_args = net_http_args(uri, @proxy_uri)
|
||||||
|
key = http_args + [https?(uri)]
|
||||||
|
@pool_mutex.synchronize do
|
||||||
|
@pools[key] ||=
|
||||||
|
if https? uri then
|
||||||
|
Gem::Request::HTTPSPool.new(http_args, @cert_files, @proxy_uri)
|
||||||
|
else
|
||||||
|
Gem::Request::HTTPPool.new(http_args, @cert_files, @proxy_uri)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
##
|
||||||
|
# Returns list of no_proxy entries (if any) from the environment
|
||||||
|
|
||||||
|
def get_no_proxy_from_env
|
||||||
|
env_no_proxy = ENV['no_proxy'] || ENV['NO_PROXY']
|
||||||
|
|
||||||
|
return [] if env_no_proxy.nil? or env_no_proxy.empty?
|
||||||
|
|
||||||
|
env_no_proxy.split(/\s*,\s*/)
|
||||||
|
end
|
||||||
|
|
||||||
|
def https? uri
|
||||||
|
uri.scheme.downcase == 'https'
|
||||||
|
end
|
||||||
|
|
||||||
|
def no_proxy? host, env_no_proxy
|
||||||
|
host = host.downcase
|
||||||
|
|
||||||
|
env_no_proxy.any? do |pattern|
|
||||||
|
pattern = pattern.downcase
|
||||||
|
|
||||||
|
host[-pattern.length, pattern.length] == pattern or
|
||||||
|
(pattern.start_with? '.' and pattern[1..-1] == host)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def net_http_args uri, proxy_uri
|
||||||
|
net_http_args = [uri.host, uri.port]
|
||||||
|
|
||||||
|
no_proxy = get_no_proxy_from_env
|
||||||
|
|
||||||
|
if proxy_uri and not no_proxy?(uri.host, no_proxy) then
|
||||||
|
net_http_args + [
|
||||||
|
proxy_uri.host,
|
||||||
|
proxy_uri.port,
|
||||||
|
Gem::UriFormatter.new(proxy_uri.user).unescape,
|
||||||
|
Gem::UriFormatter.new(proxy_uri.password).unescape,
|
||||||
|
]
|
||||||
|
elsif no_proxy? uri.host, no_proxy then
|
||||||
|
net_http_args += [nil, nil]
|
||||||
|
else
|
||||||
|
net_http_args
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
##
|
||||||
|
# A connection "pool" that only manages one connection for now. Provides
|
||||||
|
# thread safe `checkout` and `checkin` methods. The pool consists of one
|
||||||
|
# connection that corresponds to `http_args`. This class is private, do not
|
||||||
|
# use it.
|
||||||
|
|
||||||
|
class Gem::Request::HTTPPool # :nodoc:
|
||||||
|
attr_reader :cert_files, :proxy_uri
|
||||||
|
|
||||||
|
def initialize http_args, cert_files, proxy_uri
|
||||||
|
@http_args = http_args
|
||||||
|
@cert_files = cert_files
|
||||||
|
@proxy_uri = proxy_uri
|
||||||
|
@queue = SizedQueue.new 1
|
||||||
|
@queue << nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def checkout
|
||||||
|
@queue.pop || make_connection
|
||||||
|
end
|
||||||
|
|
||||||
|
def checkin connection
|
||||||
|
@queue.push connection
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def make_connection
|
||||||
|
setup_connection Gem::Request::ConnectionPools.client.new(*@http_args)
|
||||||
|
end
|
||||||
|
|
||||||
|
def setup_connection connection
|
||||||
|
connection.start
|
||||||
|
connection
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
class Gem::Request::HTTPSPool < Gem::Request::HTTPPool # :nodoc:
|
||||||
|
private
|
||||||
|
|
||||||
|
def setup_connection connection
|
||||||
|
Gem::Request.configure_connection_for_https(connection, @cert_files)
|
||||||
|
super
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
require 'rubygems'
|
|
||||||
require 'tsort'
|
require 'tsort'
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -21,12 +20,22 @@ class Gem::RequestSet
|
||||||
##
|
##
|
||||||
# Array of gems to install even if already installed
|
# Array of gems to install even if already installed
|
||||||
|
|
||||||
attr_reader :always_install
|
attr_accessor :always_install
|
||||||
|
|
||||||
attr_reader :dependencies
|
attr_reader :dependencies
|
||||||
|
|
||||||
attr_accessor :development
|
attr_accessor :development
|
||||||
|
|
||||||
|
##
|
||||||
|
# Errors fetching gems during resolution.
|
||||||
|
|
||||||
|
attr_reader :errors
|
||||||
|
|
||||||
|
##
|
||||||
|
# Set to true if you want to install only direct development dependencies.
|
||||||
|
|
||||||
|
attr_accessor :development_shallow
|
||||||
|
|
||||||
##
|
##
|
||||||
# The set of git gems imported via load_gemdeps.
|
# The set of git gems imported via load_gemdeps.
|
||||||
|
|
||||||
|
@ -38,11 +47,20 @@ class Gem::RequestSet
|
||||||
|
|
||||||
attr_accessor :ignore_dependencies
|
attr_accessor :ignore_dependencies
|
||||||
|
|
||||||
|
attr_reader :install_dir # :nodoc:
|
||||||
|
|
||||||
|
##
|
||||||
|
# If true, allow dependencies to match prerelease gems.
|
||||||
|
|
||||||
|
attr_accessor :prerelease
|
||||||
|
|
||||||
##
|
##
|
||||||
# When false no remote sets are used for resolving gems.
|
# When false no remote sets are used for resolving gems.
|
||||||
|
|
||||||
attr_accessor :remote
|
attr_accessor :remote
|
||||||
|
|
||||||
|
attr_reader :resolver # :nodoc:
|
||||||
|
|
||||||
##
|
##
|
||||||
# Sets used for resolution
|
# Sets used for resolution
|
||||||
|
|
||||||
|
@ -71,11 +89,15 @@ class Gem::RequestSet
|
||||||
@dependencies = deps
|
@dependencies = deps
|
||||||
|
|
||||||
@always_install = []
|
@always_install = []
|
||||||
|
@conservative = false
|
||||||
@dependency_names = {}
|
@dependency_names = {}
|
||||||
@development = false
|
@development = false
|
||||||
|
@development_shallow = false
|
||||||
|
@errors = []
|
||||||
@git_set = nil
|
@git_set = nil
|
||||||
@ignore_dependencies = false
|
@ignore_dependencies = false
|
||||||
@install_dir = Gem.dir
|
@install_dir = Gem.dir
|
||||||
|
@prerelease = false
|
||||||
@remote = true
|
@remote = true
|
||||||
@requests = []
|
@requests = []
|
||||||
@sets = []
|
@sets = []
|
||||||
|
@ -116,12 +138,14 @@ class Gem::RequestSet
|
||||||
|
|
||||||
def install options, &block # :yields: request, installer
|
def install options, &block # :yields: request, installer
|
||||||
if dir = options[:install_dir]
|
if dir = options[:install_dir]
|
||||||
return install_into dir, false, options, &block
|
requests = install_into dir, false, options, &block
|
||||||
|
return requests
|
||||||
end
|
end
|
||||||
|
|
||||||
cache_dir = options[:cache_dir] || Gem.dir
|
cache_dir = options[:cache_dir] || Gem.dir
|
||||||
|
@prerelease = options[:prerelease]
|
||||||
|
|
||||||
specs = []
|
requests = []
|
||||||
|
|
||||||
sorted_requests.each do |req|
|
sorted_requests.each do |req|
|
||||||
if req.installed? then
|
if req.installed? then
|
||||||
|
@ -139,10 +163,30 @@ class Gem::RequestSet
|
||||||
|
|
||||||
yield req, inst if block_given?
|
yield req, inst if block_given?
|
||||||
|
|
||||||
specs << inst.install
|
requests << inst.install
|
||||||
end
|
end
|
||||||
|
|
||||||
specs
|
requests
|
||||||
|
ensure
|
||||||
|
raise if $!
|
||||||
|
return requests if options[:gemdeps]
|
||||||
|
|
||||||
|
specs = requests.map do |request|
|
||||||
|
case request
|
||||||
|
when Gem::Resolver::ActivationRequest then
|
||||||
|
request.spec.spec
|
||||||
|
else
|
||||||
|
request
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
require 'rubygems/dependency_installer'
|
||||||
|
inst = Gem::DependencyInstaller.new options
|
||||||
|
inst.installed_gems.replace specs
|
||||||
|
|
||||||
|
Gem.done_installing_hooks.each do |hook|
|
||||||
|
hook.call inst, specs
|
||||||
|
end unless Gem.done_installing_hooks.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -156,17 +200,19 @@ class Gem::RequestSet
|
||||||
gemdeps = options[:gemdeps]
|
gemdeps = options[:gemdeps]
|
||||||
|
|
||||||
@install_dir = options[:install_dir] || Gem.dir
|
@install_dir = options[:install_dir] || Gem.dir
|
||||||
|
@prerelease = options[:prerelease]
|
||||||
@remote = options[:domain] != :local
|
@remote = options[:domain] != :local
|
||||||
|
@conservative = true if options[:conservative]
|
||||||
|
|
||||||
load_gemdeps gemdeps, options[:without_groups]
|
gem_deps_api = load_gemdeps gemdeps, options[:without_groups], true
|
||||||
|
|
||||||
resolve
|
resolve
|
||||||
|
|
||||||
if options[:explain]
|
if options[:explain]
|
||||||
puts "Gems to install:"
|
puts "Gems to install:"
|
||||||
|
|
||||||
specs.map { |s| s.full_name }.sort.each do |s|
|
sorted_requests.each do |spec|
|
||||||
puts " #{s}"
|
puts " #{spec.full_name}"
|
||||||
end
|
end
|
||||||
|
|
||||||
if Gem.configuration.really_verbose
|
if Gem.configuration.really_verbose
|
||||||
|
@ -175,8 +221,11 @@ class Gem::RequestSet
|
||||||
else
|
else
|
||||||
installed = install options, &block
|
installed = install options, &block
|
||||||
|
|
||||||
lockfile = Gem::RequestSet::Lockfile.new self, gemdeps
|
if options.fetch :lock, true then
|
||||||
lockfile.write
|
lockfile =
|
||||||
|
Gem::RequestSet::Lockfile.new self, gemdeps, gem_deps_api.dependencies
|
||||||
|
lockfile.write
|
||||||
|
end
|
||||||
|
|
||||||
installed
|
installed
|
||||||
end
|
end
|
||||||
|
@ -192,8 +241,10 @@ class Gem::RequestSet
|
||||||
|
|
||||||
installed = []
|
installed = []
|
||||||
|
|
||||||
|
options[:development] = false
|
||||||
options[:install_dir] = dir
|
options[:install_dir] = dir
|
||||||
options[:only_install_dir] = true
|
options[:only_install_dir] = true
|
||||||
|
@prerelease = options[:prerelease]
|
||||||
|
|
||||||
sorted_requests.each do |request|
|
sorted_requests.each do |request|
|
||||||
spec = request.spec
|
spec = request.spec
|
||||||
|
@ -218,7 +269,7 @@ class Gem::RequestSet
|
||||||
##
|
##
|
||||||
# Load a dependency management file.
|
# Load a dependency management file.
|
||||||
|
|
||||||
def load_gemdeps path, without_groups = []
|
def load_gemdeps path, without_groups = [], installing = false
|
||||||
@git_set = Gem::Resolver::GitSet.new
|
@git_set = Gem::Resolver::GitSet.new
|
||||||
@vendor_set = Gem::Resolver::VendorSet.new
|
@vendor_set = Gem::Resolver::VendorSet.new
|
||||||
|
|
||||||
|
@ -228,6 +279,7 @@ class Gem::RequestSet
|
||||||
lockfile.parse
|
lockfile.parse
|
||||||
|
|
||||||
gf = Gem::RequestSet::GemDependencyAPI.new self, path
|
gf = Gem::RequestSet::GemDependencyAPI.new self, path
|
||||||
|
gf.installing = installing
|
||||||
gf.without_groups = without_groups if without_groups
|
gf.without_groups = without_groups if without_groups
|
||||||
gf.load
|
gf.load
|
||||||
end
|
end
|
||||||
|
@ -243,15 +295,29 @@ class Gem::RequestSet
|
||||||
|
|
||||||
set = Gem::Resolver.compose_sets(*@sets)
|
set = Gem::Resolver.compose_sets(*@sets)
|
||||||
set.remote = @remote
|
set.remote = @remote
|
||||||
|
set.prerelease = @prerelease
|
||||||
|
|
||||||
resolver = Gem::Resolver.new @dependencies, set
|
resolver = Gem::Resolver.new @dependencies, set
|
||||||
resolver.development = @development
|
resolver.development = @development
|
||||||
|
resolver.development_shallow = @development_shallow
|
||||||
resolver.ignore_dependencies = @ignore_dependencies
|
resolver.ignore_dependencies = @ignore_dependencies
|
||||||
resolver.soft_missing = @soft_missing
|
resolver.soft_missing = @soft_missing
|
||||||
|
|
||||||
|
if @conservative
|
||||||
|
installed_gems = {}
|
||||||
|
Gem::Specification.find_all do |spec|
|
||||||
|
(installed_gems[spec.name] ||= []) << spec
|
||||||
|
end
|
||||||
|
resolver.skip_gems = installed_gems
|
||||||
|
end
|
||||||
|
|
||||||
@resolver = resolver
|
@resolver = resolver
|
||||||
|
|
||||||
@requests = resolver.resolve
|
@requests = resolver.resolve
|
||||||
|
|
||||||
|
@errors = set.errors
|
||||||
|
|
||||||
|
@requests
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -284,16 +350,20 @@ class Gem::RequestSet
|
||||||
node.spec.dependencies.each do |dep|
|
node.spec.dependencies.each do |dep|
|
||||||
next if dep.type == :development and not @development
|
next if dep.type == :development and not @development
|
||||||
|
|
||||||
match = @requests.find { |r| dep.match? r.spec.name, r.spec.version }
|
match = @requests.find { |r|
|
||||||
if match
|
dep.match? r.spec.name, r.spec.version, @prerelease
|
||||||
begin
|
}
|
||||||
yield match
|
|
||||||
rescue TSort::Cyclic
|
unless match then
|
||||||
end
|
next if dep.type == :development and @development_shallow
|
||||||
else
|
next if @soft_missing
|
||||||
unless @soft_missing
|
raise Gem::DependencyError,
|
||||||
raise Gem::DependencyError, "Unresolved dependency found during sorting - #{dep} (requested by #{node.spec.full_name})"
|
"Unresolved dependency found during sorting - #{dep} (requested by #{node.spec.full_name})"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
begin
|
||||||
|
yield match
|
||||||
|
rescue TSort::Cyclic
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,33 @@
|
||||||
##
|
##
|
||||||
# A semi-compatible DSL for the Bundler Gemfile and Isolate formats.
|
# A semi-compatible DSL for the Bundler Gemfile and Isolate gem dependencies
|
||||||
|
# files.
|
||||||
|
#
|
||||||
|
# To work with both the Bundler Gemfile and Isolate formats this
|
||||||
|
# implementation takes some liberties to allow compatibility with each, most
|
||||||
|
# notably in #source.
|
||||||
|
#
|
||||||
|
# A basic gem dependencies file will look like the following:
|
||||||
|
#
|
||||||
|
# source 'https://rubygems.org'
|
||||||
|
#
|
||||||
|
# gem 'rails', '3.2.14a
|
||||||
|
# gem 'devise', '~> 2.1', '>= 2.1.3'
|
||||||
|
# gem 'cancan'
|
||||||
|
# gem 'airbrake'
|
||||||
|
# gem 'pg'
|
||||||
|
#
|
||||||
|
# RubyGems recommends saving this as gem.deps.rb over Gemfile or Isolate.
|
||||||
|
#
|
||||||
|
# To install the gems in this Gemfile use `gem install -g` to install it and
|
||||||
|
# create a lockfile. The lockfile will ensure that when you make changes to
|
||||||
|
# your gem dependencies file a minimum amount of change is made to the
|
||||||
|
# dependencies of your gems.
|
||||||
|
#
|
||||||
|
# RubyGems can activate all the gems in your dependencies file at startup
|
||||||
|
# using the RUBYGEMS_GEMDEPS environment variable or through Gem.use_gemdeps.
|
||||||
|
# See Gem.use_gemdeps for details and warnings.
|
||||||
|
#
|
||||||
|
# See `gem help install` and `gem help gem_dependencies` for further details.
|
||||||
|
|
||||||
class Gem::RequestSet::GemDependencyAPI
|
class Gem::RequestSet::GemDependencyAPI
|
||||||
|
|
||||||
|
@ -21,6 +49,8 @@ class Gem::RequestSet::GemDependencyAPI
|
||||||
:ruby_21 => %w[ruby rbx maglev],
|
:ruby_21 => %w[ruby rbx maglev],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mswin = Gem::Platform.new 'x86-mswin32'
|
||||||
|
mswin64 = Gem::Platform.new 'x64-mswin64'
|
||||||
x86_mingw = Gem::Platform.new 'x86-mingw32'
|
x86_mingw = Gem::Platform.new 'x86-mingw32'
|
||||||
x64_mingw = Gem::Platform.new 'x64-mingw32'
|
x64_mingw = Gem::Platform.new 'x64-mingw32'
|
||||||
|
|
||||||
|
@ -39,7 +69,15 @@ class Gem::RequestSet::GemDependencyAPI
|
||||||
:mri_19 => Gem::Platform::RUBY,
|
:mri_19 => Gem::Platform::RUBY,
|
||||||
:mri_20 => Gem::Platform::RUBY,
|
:mri_20 => Gem::Platform::RUBY,
|
||||||
:mri_21 => Gem::Platform::RUBY,
|
:mri_21 => Gem::Platform::RUBY,
|
||||||
:mswin => Gem::Platform::RUBY,
|
:mswin => mswin,
|
||||||
|
:mswin_18 => mswin,
|
||||||
|
:mswin_19 => mswin,
|
||||||
|
:mswin_20 => mswin,
|
||||||
|
:mswin_21 => mswin,
|
||||||
|
:mswin64 => mswin64,
|
||||||
|
:mswin64_19 => mswin64,
|
||||||
|
:mswin64_20 => mswin64,
|
||||||
|
:mswin64_21 => mswin64,
|
||||||
:rbx => Gem::Platform::RUBY,
|
:rbx => Gem::Platform::RUBY,
|
||||||
:ruby => Gem::Platform::RUBY,
|
:ruby => Gem::Platform::RUBY,
|
||||||
:ruby_18 => Gem::Platform::RUBY,
|
:ruby_18 => Gem::Platform::RUBY,
|
||||||
|
@ -73,6 +111,14 @@ class Gem::RequestSet::GemDependencyAPI
|
||||||
:mri_20 => tilde_gt_2_0_0,
|
:mri_20 => tilde_gt_2_0_0,
|
||||||
:mri_21 => tilde_gt_2_1_0,
|
:mri_21 => tilde_gt_2_1_0,
|
||||||
:mswin => gt_eq_0,
|
:mswin => gt_eq_0,
|
||||||
|
:mswin_18 => tilde_gt_1_8_0,
|
||||||
|
:mswin_19 => tilde_gt_1_9_0,
|
||||||
|
:mswin_20 => tilde_gt_2_0_0,
|
||||||
|
:mswin_21 => tilde_gt_2_1_0,
|
||||||
|
:mswin64 => gt_eq_0,
|
||||||
|
:mswin64_19 => tilde_gt_1_9_0,
|
||||||
|
:mswin64_20 => tilde_gt_2_0_0,
|
||||||
|
:mswin64_21 => tilde_gt_2_1_0,
|
||||||
:rbx => gt_eq_0,
|
:rbx => gt_eq_0,
|
||||||
:ruby => gt_eq_0,
|
:ruby => gt_eq_0,
|
||||||
:ruby_18 => tilde_gt_1_8_0,
|
:ruby_18 => tilde_gt_1_8_0,
|
||||||
|
@ -96,6 +142,14 @@ class Gem::RequestSet::GemDependencyAPI
|
||||||
:mri_20 => :never,
|
:mri_20 => :never,
|
||||||
:mri_21 => :never,
|
:mri_21 => :never,
|
||||||
:mswin => :only,
|
:mswin => :only,
|
||||||
|
:mswin_18 => :only,
|
||||||
|
:mswin_19 => :only,
|
||||||
|
:mswin_20 => :only,
|
||||||
|
:mswin_21 => :only,
|
||||||
|
:mswin64 => :only,
|
||||||
|
:mswin64_19 => :only,
|
||||||
|
:mswin64_20 => :only,
|
||||||
|
:mswin64_21 => :only,
|
||||||
:rbx => :never,
|
:rbx => :never,
|
||||||
:ruby => :never,
|
:ruby => :never,
|
||||||
:ruby_18 => :never,
|
:ruby_18 => :never,
|
||||||
|
@ -107,6 +161,11 @@ class Gem::RequestSet::GemDependencyAPI
|
||||||
:x64_mingw_21 => :only,
|
:x64_mingw_21 => :only,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
##
|
||||||
|
# The gems required by #gem statements in the gem.deps.rb file
|
||||||
|
|
||||||
|
attr_reader :dependencies
|
||||||
|
|
||||||
##
|
##
|
||||||
# A set of gems that are loaded via the +:git+ option to #gem
|
# A set of gems that are loaded via the +:git+ option to #gem
|
||||||
|
|
||||||
|
@ -136,14 +195,31 @@ class Gem::RequestSet::GemDependencyAPI
|
||||||
@path = path
|
@path = path
|
||||||
|
|
||||||
@current_groups = nil
|
@current_groups = nil
|
||||||
@current_platform = nil
|
@current_platforms = nil
|
||||||
@current_repository = nil
|
@current_repository = nil
|
||||||
|
@dependencies = {}
|
||||||
@default_sources = true
|
@default_sources = true
|
||||||
@git_set = @set.git_set
|
@git_set = @set.git_set
|
||||||
|
@git_sources = {}
|
||||||
|
@installing = false
|
||||||
@requires = Hash.new { |h, name| h[name] = [] }
|
@requires = Hash.new { |h, name| h[name] = [] }
|
||||||
@vendor_set = @set.vendor_set
|
@vendor_set = @set.vendor_set
|
||||||
@gem_sources = {}
|
@gem_sources = {}
|
||||||
@without_groups = []
|
@without_groups = []
|
||||||
|
|
||||||
|
git_source :github do |repo_name|
|
||||||
|
repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include? "/"
|
||||||
|
|
||||||
|
"git://github.com/#{repo_name}.git"
|
||||||
|
end
|
||||||
|
|
||||||
|
git_source :bitbucket do |repo_name|
|
||||||
|
repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include? "/"
|
||||||
|
|
||||||
|
user, = repo_name.split "/", 2
|
||||||
|
|
||||||
|
"https://#{user}@bitbucket.org/#{repo_name}.git"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -187,14 +263,26 @@ class Gem::RequestSet::GemDependencyAPI
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Loads the gem dependency file
|
# Changes the behavior of gem dependency file loading to installing mode.
|
||||||
|
# In installing mode certain restrictions are ignored such as ruby version
|
||||||
|
# mismatch checks.
|
||||||
|
|
||||||
|
def installing= installing # :nodoc:
|
||||||
|
@installing = installing
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Loads the gem dependency file and returns self.
|
||||||
|
|
||||||
def load
|
def load
|
||||||
instance_eval File.read(@path).untaint, @path, 1
|
instance_eval File.read(@path).untaint, @path, 1
|
||||||
|
|
||||||
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# :category: Gem Dependencies DSL
|
# :category: Gem Dependencies DSL
|
||||||
|
#
|
||||||
# :call-seq:
|
# :call-seq:
|
||||||
# gem(name)
|
# gem(name)
|
||||||
# gem(name, *requirements)
|
# gem(name, *requirements)
|
||||||
|
@ -202,6 +290,66 @@ class Gem::RequestSet::GemDependencyAPI
|
||||||
#
|
#
|
||||||
# Specifies a gem dependency with the given +name+ and +requirements+. You
|
# Specifies a gem dependency with the given +name+ and +requirements+. You
|
||||||
# may also supply +options+ following the +requirements+
|
# may also supply +options+ following the +requirements+
|
||||||
|
#
|
||||||
|
# +options+ include:
|
||||||
|
#
|
||||||
|
# require: ::
|
||||||
|
# RubyGems does not provide any autorequire features so requires in a gem
|
||||||
|
# dependencies file are recorded but ignored.
|
||||||
|
#
|
||||||
|
# In bundler the require: option overrides the file to require during
|
||||||
|
# Bundler.require. By default the name of the dependency is required in
|
||||||
|
# Bundler. A single file or an Array of files may be given.
|
||||||
|
#
|
||||||
|
# To disable requiring any file give +false+:
|
||||||
|
#
|
||||||
|
# gem 'rake', require: false
|
||||||
|
#
|
||||||
|
# group: ::
|
||||||
|
# Place the dependencies in the given dependency group. A single group or
|
||||||
|
# an Array of groups may be given.
|
||||||
|
#
|
||||||
|
# See also #group
|
||||||
|
#
|
||||||
|
# platform: ::
|
||||||
|
# Only install the dependency on the given platform. A single platform or
|
||||||
|
# an Array of platforms may be given.
|
||||||
|
#
|
||||||
|
# See #platform for a list of platforms available.
|
||||||
|
#
|
||||||
|
# path: ::
|
||||||
|
# Install this dependency from an unpacked gem in the given directory.
|
||||||
|
#
|
||||||
|
# gem 'modified_gem', path: 'vendor/modified_gem'
|
||||||
|
#
|
||||||
|
# git: ::
|
||||||
|
# Install this dependency from a git repository:
|
||||||
|
#
|
||||||
|
# gem 'private_gem', git: git@my.company.example:private_gem.git'
|
||||||
|
#
|
||||||
|
# gist: ::
|
||||||
|
# Install this dependency from the gist ID:
|
||||||
|
#
|
||||||
|
# gem 'bang', gist: '1232884'
|
||||||
|
#
|
||||||
|
# github: ::
|
||||||
|
# Install this dependency from a github git repository:
|
||||||
|
#
|
||||||
|
# gem 'private_gem', github: 'my_company/private_gem'
|
||||||
|
#
|
||||||
|
# submodules: ::
|
||||||
|
# Set to +true+ to include submodules when fetching the git repository for
|
||||||
|
# git:, gist: and github: dependencies.
|
||||||
|
#
|
||||||
|
# ref: ::
|
||||||
|
# Use the given commit name or SHA for git:, gist: and github:
|
||||||
|
# dependencies.
|
||||||
|
#
|
||||||
|
# branch: ::
|
||||||
|
# Use the given branch for git:, gist: and github: dependencies.
|
||||||
|
#
|
||||||
|
# tag: ::
|
||||||
|
# Use the given tag for git:, gist: and github: dependencies.
|
||||||
|
|
||||||
def gem name, *requirements
|
def gem name, *requirements
|
||||||
options = requirements.pop if requirements.last.kind_of?(Hash)
|
options = requirements.pop if requirements.last.kind_of?(Hash)
|
||||||
|
@ -211,9 +359,20 @@ class Gem::RequestSet::GemDependencyAPI
|
||||||
|
|
||||||
source_set = false
|
source_set = false
|
||||||
|
|
||||||
source_set ||= gem_path name, options
|
source_set ||= gem_path name, options
|
||||||
source_set ||= gem_git name, options
|
source_set ||= gem_git name, options
|
||||||
source_set ||= gem_github name, options
|
source_set ||= gem_git_source name, options
|
||||||
|
|
||||||
|
duplicate = @dependencies.include? name
|
||||||
|
|
||||||
|
@dependencies[name] =
|
||||||
|
if requirements.empty? and not source_set then
|
||||||
|
nil
|
||||||
|
elsif source_set then
|
||||||
|
'!'
|
||||||
|
else
|
||||||
|
requirements
|
||||||
|
end
|
||||||
|
|
||||||
return unless gem_platforms options
|
return unless gem_platforms options
|
||||||
|
|
||||||
|
@ -225,6 +384,12 @@ class Gem::RequestSet::GemDependencyAPI
|
||||||
|
|
||||||
gem_requires name, options
|
gem_requires name, options
|
||||||
|
|
||||||
|
if duplicate then
|
||||||
|
warn <<-WARNING
|
||||||
|
Gem dependencies file #{@path} requires #{name} more than once.
|
||||||
|
WARNING
|
||||||
|
end
|
||||||
|
|
||||||
@set.gem name, *requirements
|
@set.gem name, *requirements
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -258,21 +423,27 @@ class Gem::RequestSet::GemDependencyAPI
|
||||||
private :gem_git
|
private :gem_git
|
||||||
|
|
||||||
##
|
##
|
||||||
# Handles the github: option from +options+ for gem +name+.
|
# Handles a git gem option from +options+ for gem +name+ for a git source
|
||||||
|
# registered through git_source.
|
||||||
#
|
#
|
||||||
# Returns +true+ if the path option was handled.
|
# Returns +true+ if the custom source option was handled.
|
||||||
|
|
||||||
def gem_github name, options # :nodoc:
|
def gem_git_source name, options # :nodoc:
|
||||||
return unless path = options.delete(:github)
|
return unless git_source = (@git_sources.keys & options.keys).last
|
||||||
|
|
||||||
options[:git] = "git://github.com/#{path}.git"
|
source_callback = @git_sources[git_source]
|
||||||
|
source_param = options.delete git_source
|
||||||
|
|
||||||
|
git_url = source_callback.call source_param
|
||||||
|
|
||||||
|
options[:git] = git_url
|
||||||
|
|
||||||
gem_git name, options
|
gem_git name, options
|
||||||
|
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
private :gem_github
|
private :gem_git_source
|
||||||
|
|
||||||
##
|
##
|
||||||
# Handles the :group and :groups +options+ for the gem with the given
|
# Handles the :group and :groups +options+ for the gem with the given
|
||||||
|
@ -314,8 +485,9 @@ class Gem::RequestSet::GemDependencyAPI
|
||||||
# platform matches the current platform.
|
# platform matches the current platform.
|
||||||
|
|
||||||
def gem_platforms options # :nodoc:
|
def gem_platforms options # :nodoc:
|
||||||
platform_names = Array(options.delete :platforms)
|
platform_names = Array(options.delete :platform)
|
||||||
platform_names << @current_platform if @current_platform
|
platform_names.concat Array(options.delete :platforms)
|
||||||
|
platform_names.concat @current_platforms if @current_platforms
|
||||||
|
|
||||||
return true if platform_names.empty?
|
return true if platform_names.empty?
|
||||||
|
|
||||||
|
@ -343,7 +515,7 @@ class Gem::RequestSet::GemDependencyAPI
|
||||||
private :gem_platforms
|
private :gem_platforms
|
||||||
|
|
||||||
##
|
##
|
||||||
# Handles the require: option from +options+ and adds those files, or the
|
# Records the require: option from +options+ and adds those files, or the
|
||||||
# default file to the require list for +name+.
|
# default file to the require list for +name+.
|
||||||
|
|
||||||
def gem_requires name, options # :nodoc:
|
def gem_requires name, options # :nodoc:
|
||||||
|
@ -362,6 +534,11 @@ class Gem::RequestSet::GemDependencyAPI
|
||||||
# :category: Gem Dependencies DSL
|
# :category: Gem Dependencies DSL
|
||||||
#
|
#
|
||||||
# Block form for specifying gems from a git +repository+.
|
# Block form for specifying gems from a git +repository+.
|
||||||
|
#
|
||||||
|
# git 'https://github.com/rails/rails.git' do
|
||||||
|
# gem 'activesupport'
|
||||||
|
# gem 'activerecord'
|
||||||
|
# end
|
||||||
|
|
||||||
def git repository
|
def git repository
|
||||||
@current_repository = repository
|
@current_repository = repository
|
||||||
|
@ -372,6 +549,15 @@ class Gem::RequestSet::GemDependencyAPI
|
||||||
@current_repository = nil
|
@current_repository = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Defines a custom git source that uses +name+ to expand git repositories
|
||||||
|
# for use in gems built from git repositories. You must provide a block
|
||||||
|
# that accepts a git repository name for expansion.
|
||||||
|
|
||||||
|
def git_source name, &callback
|
||||||
|
@git_sources[name] = callback
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Returns the basename of the file the dependencies were loaded from
|
# Returns the basename of the file the dependencies were loaded from
|
||||||
|
|
||||||
|
@ -383,6 +569,23 @@ class Gem::RequestSet::GemDependencyAPI
|
||||||
# :category: Gem Dependencies DSL
|
# :category: Gem Dependencies DSL
|
||||||
#
|
#
|
||||||
# Loads dependencies from a gemspec file.
|
# Loads dependencies from a gemspec file.
|
||||||
|
#
|
||||||
|
# +options+ include:
|
||||||
|
#
|
||||||
|
# name: ::
|
||||||
|
# The name portion of the gemspec file. Defaults to searching for any
|
||||||
|
# gemspec file in the current directory.
|
||||||
|
#
|
||||||
|
# gemspec name: 'my_gem'
|
||||||
|
#
|
||||||
|
# path: ::
|
||||||
|
# The path the gemspec lives in. Defaults to the current directory:
|
||||||
|
#
|
||||||
|
# gemspec 'my_gem', path: 'gemspecs', name: 'my_gem'
|
||||||
|
#
|
||||||
|
# development_group: ::
|
||||||
|
# The group to add development dependencies to. By default this is
|
||||||
|
# :development. Only one group may be specified.
|
||||||
|
|
||||||
def gemspec options = {}
|
def gemspec options = {}
|
||||||
name = options.delete(:name) || '{,*}'
|
name = options.delete(:name) || '{,*}'
|
||||||
|
@ -404,7 +607,20 @@ class Gem::RequestSet::GemDependencyAPI
|
||||||
|
|
||||||
##
|
##
|
||||||
# :category: Gem Dependencies DSL
|
# :category: Gem Dependencies DSL
|
||||||
|
#
|
||||||
# Block form for placing a dependency in the given +groups+.
|
# Block form for placing a dependency in the given +groups+.
|
||||||
|
#
|
||||||
|
# group :development do
|
||||||
|
# gem 'debugger'
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# group :development, :test do
|
||||||
|
# gem 'minitest'
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# Groups can be excluded at install time using `gem install -g --without
|
||||||
|
# development`. See `gem help install` and `gem help gem_dependencies` for
|
||||||
|
# further details.
|
||||||
|
|
||||||
def group *groups
|
def group *groups
|
||||||
@current_groups = groups
|
@current_groups = groups
|
||||||
|
@ -440,28 +656,72 @@ class Gem::RequestSet::GemDependencyAPI
|
||||||
##
|
##
|
||||||
# :category: Gem Dependencies DSL
|
# :category: Gem Dependencies DSL
|
||||||
#
|
#
|
||||||
# Block form for restricting gems to a particular platform.
|
# Block form for restricting gems to a set of platforms.
|
||||||
|
#
|
||||||
|
# The gem dependencies platform is different from Gem::Platform. A platform
|
||||||
|
# gem.deps.rb platform matches on the ruby engine, the ruby version and
|
||||||
|
# whether or not windows is allowed.
|
||||||
|
#
|
||||||
|
# :ruby, :ruby_XY ::
|
||||||
|
# Matches non-windows, non-jruby implementations where X and Y can be used
|
||||||
|
# to match releases in the 1.8, 1.9, 2.0 or 2.1 series.
|
||||||
|
#
|
||||||
|
# :mri, :mri_XY ::
|
||||||
|
# Matches non-windows C Ruby (Matz Ruby) or only the 1.8, 1.9, 2.0 or
|
||||||
|
# 2.1 series.
|
||||||
|
#
|
||||||
|
# :mingw, :mingw_XY ::
|
||||||
|
# Matches 32 bit C Ruby on MinGW or only the 1.8, 1.9, 2.0 or 2.1 series.
|
||||||
|
#
|
||||||
|
# :x64_mingw, :x64_mingw_XY ::
|
||||||
|
# Matches 64 bit C Ruby on MinGW or only the 1.8, 1.9, 2.0 or 2.1 series.
|
||||||
|
#
|
||||||
|
# :mswin, :mswin_XY ::
|
||||||
|
# Matches 32 bit C Ruby on Microsoft Windows or only the 1.8, 1.9, 2.0 or
|
||||||
|
# 2.1 series.
|
||||||
|
#
|
||||||
|
# :mswin64, :mswin64_XY ::
|
||||||
|
# Matches 64 bit C Ruby on Microsoft Windows or only the 1.8, 1.9, 2.0 or
|
||||||
|
# 2.1 series.
|
||||||
|
#
|
||||||
|
# :jruby, :jruby_XY ::
|
||||||
|
# Matches JRuby or JRuby in 1.8 or 1.9 mode.
|
||||||
|
#
|
||||||
|
# :maglev ::
|
||||||
|
# Matches Maglev
|
||||||
|
#
|
||||||
|
# :rbx ::
|
||||||
|
# Matches non-windows Rubinius
|
||||||
|
#
|
||||||
|
# NOTE: There is inconsistency in what environment a platform matches. You
|
||||||
|
# may need to read the source to know the exact details.
|
||||||
|
|
||||||
def platform what
|
def platform *platforms
|
||||||
@current_platform = what
|
@current_platforms = platforms
|
||||||
|
|
||||||
yield
|
yield
|
||||||
|
|
||||||
ensure
|
ensure
|
||||||
@current_platform = nil
|
@current_platforms = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# :category: Gem Dependencies DSL
|
# :category: Gem Dependencies DSL
|
||||||
#
|
#
|
||||||
# Block form for restricting gems to a particular platform.
|
# Block form for restricting gems to a particular set of platforms. See
|
||||||
|
# #platform.
|
||||||
|
|
||||||
alias :platforms :platform
|
alias :platforms :platform
|
||||||
|
|
||||||
##
|
##
|
||||||
# :category: Gem Dependencies DSL
|
# :category: Gem Dependencies DSL
|
||||||
# Restricts this gem dependencies file to the given ruby +version+. The
|
#
|
||||||
# +:engine+ options from Bundler are currently ignored.
|
# Restricts this gem dependencies file to the given ruby +version+.
|
||||||
|
#
|
||||||
|
# You may also provide +engine:+ and +engine_version:+ options to restrict
|
||||||
|
# this gem dependencies file to a particular ruby engine and its engine
|
||||||
|
# version. This matching is performed by using the RUBY_ENGINE and
|
||||||
|
# engine_specific VERSION constants. (For JRuby, JRUBY_VERSION).
|
||||||
|
|
||||||
def ruby version, options = {}
|
def ruby version, options = {}
|
||||||
engine = options[:engine]
|
engine = options[:engine]
|
||||||
|
@ -471,6 +731,8 @@ class Gem::RequestSet::GemDependencyAPI
|
||||||
'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
|
engine and not engine_version
|
||||||
|
|
||||||
|
return true if @installing
|
||||||
|
|
||||||
unless RUBY_VERSION == version then
|
unless RUBY_VERSION == version then
|
||||||
message = "Your Ruby version is #{RUBY_VERSION}, " +
|
message = "Your Ruby version is #{RUBY_VERSION}, " +
|
||||||
"but your #{gem_deps_file} requires #{version}"
|
"but your #{gem_deps_file} requires #{version}"
|
||||||
|
@ -503,7 +765,16 @@ class Gem::RequestSet::GemDependencyAPI
|
||||||
##
|
##
|
||||||
# :category: Gem Dependencies DSL
|
# :category: Gem Dependencies DSL
|
||||||
#
|
#
|
||||||
# Sets +url+ as a source for gems for this dependency API.
|
# Sets +url+ as a source for gems for this dependency API. RubyGems uses
|
||||||
|
# the default configured sources if no source was given. If a source is set
|
||||||
|
# only that source is used.
|
||||||
|
#
|
||||||
|
# This method differs in behavior from Bundler:
|
||||||
|
#
|
||||||
|
# * The +:gemcutter+, # +:rubygems+ and +:rubyforge+ sources are not
|
||||||
|
# supported as they are deprecated in bundler.
|
||||||
|
# * The +prepend:+ option is not supported. If you wish to order sources
|
||||||
|
# then list them in your preferred order.
|
||||||
|
|
||||||
def source url
|
def source url
|
||||||
Gem.sources.clear if @default_sources
|
Gem.sources.clear if @default_sources
|
||||||
|
|
|
@ -49,11 +49,14 @@ class Gem::RequestSet::Lockfile
|
||||||
# Creates a new Lockfile for the given +request_set+ and +gem_deps_file+
|
# Creates a new Lockfile for the given +request_set+ and +gem_deps_file+
|
||||||
# location.
|
# location.
|
||||||
|
|
||||||
def initialize request_set, gem_deps_file
|
def initialize request_set, gem_deps_file, dependencies = nil
|
||||||
@set = request_set
|
@set = request_set
|
||||||
|
@dependencies = dependencies
|
||||||
@gem_deps_file = File.expand_path(gem_deps_file)
|
@gem_deps_file = File.expand_path(gem_deps_file)
|
||||||
@gem_deps_dir = File.dirname(@gem_deps_file)
|
@gem_deps_dir = File.dirname(@gem_deps_file)
|
||||||
|
|
||||||
|
@gem_deps_file.untaint unless gem_deps_file.tainted?
|
||||||
|
|
||||||
@current_token = nil
|
@current_token = nil
|
||||||
@line = 0
|
@line = 0
|
||||||
@line_pos = 0
|
@line_pos = 0
|
||||||
|
@ -64,19 +67,42 @@ class Gem::RequestSet::Lockfile
|
||||||
def add_DEPENDENCIES out # :nodoc:
|
def add_DEPENDENCIES out # :nodoc:
|
||||||
out << "DEPENDENCIES"
|
out << "DEPENDENCIES"
|
||||||
|
|
||||||
@requests.sort_by { |r| r.name }.each do |request|
|
dependencies =
|
||||||
spec = request.spec
|
if @dependencies then
|
||||||
|
@dependencies.sort_by { |name,| name }.map do |name, requirement|
|
||||||
|
requirement_string =
|
||||||
|
if '!' == requirement then
|
||||||
|
requirement
|
||||||
|
else
|
||||||
|
Gem::Requirement.new(requirement).for_lockfile
|
||||||
|
end
|
||||||
|
|
||||||
if [Gem::Resolver::VendorSpecification,
|
[name, requirement_string]
|
||||||
Gem::Resolver::GitSpecification].include? spec.class then
|
end
|
||||||
out << " #{request.name}!"
|
|
||||||
else
|
else
|
||||||
requirement = request.request.dependency.requirement
|
@requests.sort_by { |r| r.name }.map do |request|
|
||||||
|
spec = request.spec
|
||||||
|
name = request.name
|
||||||
|
requirement = request.request.dependency.requirement
|
||||||
|
|
||||||
out << " #{request.name}#{requirement.for_lockfile}"
|
requirement_string =
|
||||||
|
if [Gem::Resolver::VendorSpecification,
|
||||||
|
Gem::Resolver::GitSpecification].include? spec.class then
|
||||||
|
"!"
|
||||||
|
else
|
||||||
|
requirement.for_lockfile
|
||||||
|
end
|
||||||
|
|
||||||
|
[name, requirement_string]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
dependencies = dependencies.map do |name, requirement_string|
|
||||||
|
" #{name}#{requirement_string}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
out.concat dependencies
|
||||||
|
|
||||||
out << nil
|
out << nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -93,12 +119,15 @@ class Gem::RequestSet::Lockfile
|
||||||
out << " specs:"
|
out << " specs:"
|
||||||
|
|
||||||
requests.sort_by { |request| request.name }.each do |request|
|
requests.sort_by { |request| request.name }.each do |request|
|
||||||
|
next if request.spec.name == 'bundler'
|
||||||
platform = "-#{request.spec.platform}" unless
|
platform = "-#{request.spec.platform}" unless
|
||||||
Gem::Platform::RUBY == request.spec.platform
|
Gem::Platform::RUBY == request.spec.platform
|
||||||
|
|
||||||
out << " #{request.name} (#{request.version}#{platform})"
|
out << " #{request.name} (#{request.version}#{platform})"
|
||||||
|
|
||||||
request.full_spec.dependencies.sort.each do |dependency|
|
request.full_spec.dependencies.sort.each do |dependency|
|
||||||
|
next if dependency.type == :development
|
||||||
|
|
||||||
requirement = dependency.requirement
|
requirement = dependency.requirement
|
||||||
out << " #{dependency.name}#{requirement.for_lockfile}"
|
out << " #{dependency.name}#{requirement.for_lockfile}"
|
||||||
end
|
end
|
||||||
|
@ -166,9 +195,8 @@ class Gem::RequestSet::Lockfile
|
||||||
out << "PLATFORMS"
|
out << "PLATFORMS"
|
||||||
|
|
||||||
platforms = @requests.map { |request| request.spec.platform }.uniq
|
platforms = @requests.map { |request| request.spec.platform }.uniq
|
||||||
platforms.delete Gem::Platform::RUBY if platforms.length > 1
|
|
||||||
|
|
||||||
platforms.each do |platform|
|
platforms.sort.each do |platform|
|
||||||
out << " #{platform}"
|
out << " #{platform}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -250,7 +278,7 @@ class Gem::RequestSet::Lockfile
|
||||||
Gem::Resolver::VendorSet === set
|
Gem::Resolver::VendorSet === set
|
||||||
}.map { |set|
|
}.map { |set|
|
||||||
set.specs[name]
|
set.specs[name]
|
||||||
}.first
|
}.compact.first
|
||||||
|
|
||||||
requirements << spec.version
|
requirements << spec.version
|
||||||
when :l_paren then
|
when :l_paren then
|
||||||
|
@ -277,26 +305,33 @@ class Gem::RequestSet::Lockfile
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_GEM # :nodoc:
|
def parse_GEM # :nodoc:
|
||||||
get :entry, 'remote'
|
sources = []
|
||||||
_, data, = get :text
|
|
||||||
|
|
||||||
source = Gem::Source.new data
|
while [:entry, 'remote'] == peek.first(2) do
|
||||||
|
get :entry, 'remote'
|
||||||
|
_, data, = get :text
|
||||||
|
skip :newline
|
||||||
|
|
||||||
skip :newline
|
sources << Gem::Source.new(data)
|
||||||
|
end
|
||||||
|
|
||||||
|
sources << Gem::Source.new(Gem::DEFAULT_HOST) if sources.empty?
|
||||||
|
|
||||||
get :entry, 'specs'
|
get :entry, 'specs'
|
||||||
|
|
||||||
skip :newline
|
skip :newline
|
||||||
|
|
||||||
set = Gem::Resolver::LockSet.new source
|
set = Gem::Resolver::LockSet.new sources
|
||||||
last_spec = nil
|
last_specs = nil
|
||||||
|
|
||||||
while not @tokens.empty? and :text == peek.first do
|
while not @tokens.empty? and :text == peek.first do
|
||||||
_, name, column, = get :text
|
_, name, column, = get :text
|
||||||
|
|
||||||
case peek[0]
|
case peek[0]
|
||||||
when :newline then
|
when :newline then
|
||||||
last_spec.add_dependency Gem::Dependency.new name if column == 6
|
last_specs.each do |spec|
|
||||||
|
spec.add_dependency Gem::Dependency.new name if column == 6
|
||||||
|
end
|
||||||
when :l_paren then
|
when :l_paren then
|
||||||
get :l_paren
|
get :l_paren
|
||||||
|
|
||||||
|
@ -308,11 +343,13 @@ class Gem::RequestSet::Lockfile
|
||||||
platform =
|
platform =
|
||||||
platform ? Gem::Platform.new(platform) : Gem::Platform::RUBY
|
platform ? Gem::Platform.new(platform) : Gem::Platform::RUBY
|
||||||
|
|
||||||
last_spec = set.add name, version, platform
|
last_specs = set.add name, version, platform
|
||||||
else
|
else
|
||||||
dependency = parse_dependency name, data
|
dependency = parse_dependency name, data
|
||||||
|
|
||||||
last_spec.add_dependency dependency
|
last_specs.each do |spec|
|
||||||
|
spec.add_dependency dependency
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
get :r_paren
|
get :r_paren
|
||||||
|
@ -337,11 +374,21 @@ class Gem::RequestSet::Lockfile
|
||||||
|
|
||||||
skip :newline
|
skip :newline
|
||||||
|
|
||||||
|
type, value = peek.first 2
|
||||||
|
if type == :entry and %w[branch ref tag].include? value then
|
||||||
|
get
|
||||||
|
get :text
|
||||||
|
|
||||||
|
skip :newline
|
||||||
|
end
|
||||||
|
|
||||||
get :entry, 'specs'
|
get :entry, 'specs'
|
||||||
|
|
||||||
skip :newline
|
skip :newline
|
||||||
|
|
||||||
set = Gem::Resolver::GitSet.new
|
set = Gem::Resolver::GitSet.new
|
||||||
|
set.root_dir = @set.install_dir
|
||||||
|
|
||||||
last_spec = nil
|
last_spec = nil
|
||||||
|
|
||||||
while not @tokens.empty? and :text == peek.first do
|
while not @tokens.empty? and :text == peek.first do
|
||||||
|
@ -360,7 +407,7 @@ class Gem::RequestSet::Lockfile
|
||||||
else
|
else
|
||||||
dependency = parse_dependency name, data
|
dependency = parse_dependency name, data
|
||||||
|
|
||||||
last_spec.spec.dependencies << dependency
|
last_spec.add_dependency dependency
|
||||||
end
|
end
|
||||||
|
|
||||||
get :r_paren
|
get :r_paren
|
||||||
|
@ -403,7 +450,7 @@ class Gem::RequestSet::Lockfile
|
||||||
else
|
else
|
||||||
dependency = parse_dependency name, data
|
dependency = parse_dependency name, data
|
||||||
|
|
||||||
last_spec.spec.dependencies << dependency
|
last_spec.dependencies << dependency
|
||||||
end
|
end
|
||||||
|
|
||||||
get :r_paren
|
get :r_paren
|
||||||
|
@ -432,7 +479,7 @@ class Gem::RequestSet::Lockfile
|
||||||
# the first token of the requirements and returns a Gem::Dependency object.
|
# the first token of the requirements and returns a Gem::Dependency object.
|
||||||
|
|
||||||
def parse_dependency name, op # :nodoc:
|
def parse_dependency name, op # :nodoc:
|
||||||
return Gem::Dependency.new name unless peek[0] == :text
|
return Gem::Dependency.new name, op unless peek[0] == :text
|
||||||
|
|
||||||
_, version, = get :text
|
_, version, = get :text
|
||||||
|
|
||||||
|
@ -575,8 +622,10 @@ class Gem::RequestSet::Lockfile
|
||||||
# Writes the lock file alongside the gem dependencies file
|
# Writes the lock file alongside the gem dependencies file
|
||||||
|
|
||||||
def write
|
def write
|
||||||
|
content = to_s
|
||||||
|
|
||||||
open "#{@gem_deps_file}.lock", 'w' do |io|
|
open "#{@gem_deps_file}.lock", 'w' do |io|
|
||||||
io.write to_s
|
io.write content
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,9 @@ Gem.load_yaml if defined? ::YAML
|
||||||
##
|
##
|
||||||
# A Requirement is a set of one or more version restrictions. It supports a
|
# A Requirement is a set of one or more version restrictions. It supports a
|
||||||
# few (<tt>=, !=, >, <, >=, <=, ~></tt>) different restriction operators.
|
# few (<tt>=, !=, >, <, >=, <=, ~></tt>) different restriction operators.
|
||||||
|
#
|
||||||
|
# See Gem::Version for a description on how versions and requirements work
|
||||||
|
# together in RubyGems.
|
||||||
|
|
||||||
class Gem::Requirement
|
class Gem::Requirement
|
||||||
OPS = { #:nodoc:
|
OPS = { #:nodoc:
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
require 'rubygems'
|
|
||||||
require 'rubygems/dependency'
|
require 'rubygems/dependency'
|
||||||
require 'rubygems/exceptions'
|
require 'rubygems/exceptions'
|
||||||
require 'rubygems/util/list'
|
require 'rubygems/util/list'
|
||||||
|
@ -21,16 +20,23 @@ class Gem::Resolver
|
||||||
|
|
||||||
DEBUG_RESOLVER = !ENV['DEBUG_RESOLVER'].nil?
|
DEBUG_RESOLVER = !ENV['DEBUG_RESOLVER'].nil?
|
||||||
|
|
||||||
|
require 'pp' if DEBUG_RESOLVER
|
||||||
|
|
||||||
##
|
##
|
||||||
# Contains all the conflicts encountered while doing resolution
|
# Contains all the conflicts encountered while doing resolution
|
||||||
|
|
||||||
attr_reader :conflicts
|
attr_reader :conflicts
|
||||||
|
|
||||||
##
|
##
|
||||||
# Set to true if development dependencies should be considered.
|
# Set to true if all development dependencies should be considered.
|
||||||
|
|
||||||
attr_accessor :development
|
attr_accessor :development
|
||||||
|
|
||||||
|
##
|
||||||
|
# Set to true if immediate development dependencies should be considered.
|
||||||
|
|
||||||
|
attr_accessor :development_shallow
|
||||||
|
|
||||||
##
|
##
|
||||||
# When true, no dependencies are looked up for requested gems.
|
# When true, no dependencies are looked up for requested gems.
|
||||||
|
|
||||||
|
@ -43,6 +49,12 @@ class Gem::Resolver
|
||||||
|
|
||||||
attr_reader :stats
|
attr_reader :stats
|
||||||
|
|
||||||
|
##
|
||||||
|
# Hash of gems to skip resolution. Keyed by gem name, with arrays of
|
||||||
|
# gem specifications as values.
|
||||||
|
|
||||||
|
attr_accessor :skip_gems
|
||||||
|
|
||||||
##
|
##
|
||||||
# When a missing dependency, don't stop. Just go on and record what was
|
# When a missing dependency, don't stop. Just go on and record what was
|
||||||
# missing.
|
# missing.
|
||||||
|
@ -100,26 +112,27 @@ class Gem::Resolver
|
||||||
|
|
||||||
@conflicts = []
|
@conflicts = []
|
||||||
@development = false
|
@development = false
|
||||||
|
@development_shallow = false
|
||||||
@ignore_dependencies = false
|
@ignore_dependencies = false
|
||||||
@missing = []
|
@missing = []
|
||||||
|
@skip_gems = {}
|
||||||
@soft_missing = false
|
@soft_missing = false
|
||||||
@stats = Gem::Resolver::Stats.new
|
@stats = Gem::Resolver::Stats.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def explain stage, *data # :nodoc:
|
def explain stage, *data # :nodoc:
|
||||||
if DEBUG_RESOLVER
|
return unless DEBUG_RESOLVER
|
||||||
d = data.map { |x| x.inspect }.join(", ")
|
|
||||||
STDOUT.printf "%20s %s\n", stage.to_s.upcase, d
|
d = data.map { |x| x.pretty_inspect }.join(", ")
|
||||||
end
|
$stderr.printf "%10s %s\n", stage.to_s.upcase, d
|
||||||
end
|
end
|
||||||
|
|
||||||
def explain_list stage, data # :nodoc:
|
def explain_list stage # :nodoc:
|
||||||
if DEBUG_RESOLVER
|
return unless DEBUG_RESOLVER
|
||||||
STDOUT.printf "%20s (%d entries)\n", stage.to_s.upcase, data.size
|
|
||||||
data.each do |d|
|
data = yield
|
||||||
STDOUT.printf "%20s %s\n", "", d
|
$stderr.printf "%10s (%d entries)\n", stage.to_s.upcase, data.size
|
||||||
end
|
PP.pp data, $stderr unless data.empty?
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -132,6 +145,7 @@ class Gem::Resolver
|
||||||
spec = possible.pop
|
spec = possible.pop
|
||||||
|
|
||||||
explain :activate, [spec.full_name, possible.size]
|
explain :activate, [spec.full_name, possible.size]
|
||||||
|
explain :possible, possible
|
||||||
|
|
||||||
activation_request =
|
activation_request =
|
||||||
Gem::Resolver::ActivationRequest.new spec, dep, possible
|
Gem::Resolver::ActivationRequest.new spec, dep, possible
|
||||||
|
@ -142,8 +156,15 @@ class Gem::Resolver
|
||||||
def requests s, act, reqs=nil # :nodoc:
|
def requests s, act, reqs=nil # :nodoc:
|
||||||
return reqs if @ignore_dependencies
|
return reqs if @ignore_dependencies
|
||||||
|
|
||||||
|
s.fetch_development_dependencies if @development
|
||||||
|
|
||||||
s.dependencies.reverse_each do |d|
|
s.dependencies.reverse_each do |d|
|
||||||
next if d.type == :development and not @development
|
next if d.type == :development and not @development
|
||||||
|
next if d.type == :development and @development_shallow and
|
||||||
|
act.development?
|
||||||
|
next if d.type == :development and @development_shallow and
|
||||||
|
act.parent
|
||||||
|
|
||||||
reqs.add Gem::Resolver::DependencyRequest.new(d, act)
|
reqs.add Gem::Resolver::DependencyRequest.new(d, act)
|
||||||
@stats.requirement!
|
@stats.requirement!
|
||||||
end
|
end
|
||||||
|
@ -186,6 +207,15 @@ class Gem::Resolver
|
||||||
|
|
||||||
def find_possible dependency # :nodoc:
|
def find_possible dependency # :nodoc:
|
||||||
all = @set.find_all dependency
|
all = @set.find_all dependency
|
||||||
|
|
||||||
|
if (skip_dep_gems = skip_gems[dependency.name]) && !skip_dep_gems.empty?
|
||||||
|
matching = all.select do |api_spec|
|
||||||
|
skip_dep_gems.any? { |s| api_spec.version == s.version }
|
||||||
|
end
|
||||||
|
|
||||||
|
all = matching unless matching.empty?
|
||||||
|
end
|
||||||
|
|
||||||
matching_platform = select_local_platforms all
|
matching_platform = select_local_platforms all
|
||||||
|
|
||||||
return matching_platform, all
|
return matching_platform, all
|
||||||
|
@ -270,8 +300,8 @@ class Gem::Resolver
|
||||||
|
|
||||||
dep = needed.remove
|
dep = needed.remove
|
||||||
explain :try, [dep, dep.requester ? dep.requester.request : :toplevel]
|
explain :try, [dep, dep.requester ? dep.requester.request : :toplevel]
|
||||||
explain_list :next5, needed.next5
|
explain_list(:next5) { needed.next5 }
|
||||||
explain_list :specs, Array(specs).map { |x| x.full_name }.sort
|
explain_list(:specs) { Array(specs).map { |x| x.full_name }.sort }
|
||||||
|
|
||||||
# If there is already a spec activated for the requested name...
|
# If there is already a spec activated for the requested name...
|
||||||
if specs && existing = specs.find { |s| dep.name == s.name }
|
if specs && existing = specs.find { |s| dep.name == s.name }
|
||||||
|
@ -403,7 +433,10 @@ class Gem::Resolver
|
||||||
@missing << dep
|
@missing << dep
|
||||||
|
|
||||||
unless @soft_missing
|
unless @soft_missing
|
||||||
raise Gem::UnsatisfiableDependencyError.new(dep, platform_mismatch)
|
exc = Gem::UnsatisfiableDependencyError.new dep, platform_mismatch
|
||||||
|
exc.errors = @set.errors
|
||||||
|
|
||||||
|
raise exc
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,13 @@ class Gem::Resolver::ActivationRequest
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Is this activation request for a development dependency?
|
||||||
|
|
||||||
|
def development?
|
||||||
|
@request.development?
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Downloads a gem at +path+ and returns the file path.
|
# Downloads a gem at +path+ and returns the file path.
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,8 @@ class Gem::Resolver::APISet < Gem::Resolver::Set
|
||||||
|
|
||||||
@data = Hash.new { |h,k| h[k] = [] }
|
@data = Hash.new { |h,k| h[k] = [] }
|
||||||
@source = Gem::Source.new @uri
|
@source = Gem::Source.new @uri
|
||||||
|
|
||||||
|
@to_fetch = []
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -45,6 +47,10 @@ class Gem::Resolver::APISet < Gem::Resolver::Set
|
||||||
|
|
||||||
return res unless @remote
|
return res unless @remote
|
||||||
|
|
||||||
|
if @to_fetch.include?(req.name)
|
||||||
|
prefetch_now
|
||||||
|
end
|
||||||
|
|
||||||
versions(req.name).each do |ver|
|
versions(req.name).each do |ver|
|
||||||
if req.dependency.match? req.name, ver[:number]
|
if req.dependency.match? req.name, ver[:number]
|
||||||
res << Gem::Resolver::APISpecification.new(self, ver)
|
res << Gem::Resolver::APISpecification.new(self, ver)
|
||||||
|
@ -61,9 +67,13 @@ class Gem::Resolver::APISet < Gem::Resolver::Set
|
||||||
def prefetch reqs
|
def prefetch reqs
|
||||||
return unless @remote
|
return unless @remote
|
||||||
names = reqs.map { |r| r.dependency.name }
|
names = reqs.map { |r| r.dependency.name }
|
||||||
needed = names - @data.keys
|
needed = names - @data.keys - @to_fetch
|
||||||
|
|
||||||
return if needed.empty?
|
@to_fetch += needed
|
||||||
|
end
|
||||||
|
|
||||||
|
def prefetch_now
|
||||||
|
needed, @to_fetch = @to_fetch, []
|
||||||
|
|
||||||
uri = @dep_uri + "?gems=#{needed.sort.join ','}"
|
uri = @dep_uri + "?gems=#{needed.sort.join ','}"
|
||||||
str = Gem::RemoteFetcher.fetcher.fetch_path uri
|
str = Gem::RemoteFetcher.fetcher.fetch_path uri
|
||||||
|
|
|
@ -34,6 +34,12 @@ class Gem::Resolver::APISpecification < Gem::Resolver::Specification
|
||||||
@dependencies == other.dependencies
|
@dependencies == other.dependencies
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def fetch_development_dependencies # :nodoc:
|
||||||
|
spec = source.fetch_spec Gem::NameTuple.new @name, @version, @platform
|
||||||
|
|
||||||
|
@dependencies = spec.dependencies
|
||||||
|
end
|
||||||
|
|
||||||
def installable_platform? # :nodoc:
|
def installable_platform? # :nodoc:
|
||||||
Gem::Platform.match @platform
|
Gem::Platform.match @platform
|
||||||
end
|
end
|
||||||
|
|
|
@ -28,6 +28,10 @@ class Gem::Resolver::BestSet < Gem::Resolver::ComposedSet
|
||||||
pick_sets if @remote and @sets.empty?
|
pick_sets if @remote and @sets.empty?
|
||||||
|
|
||||||
super
|
super
|
||||||
|
rescue Gem::RemoteFetcher::FetchError => e
|
||||||
|
replace_failed_api_set e
|
||||||
|
|
||||||
|
retry
|
||||||
end
|
end
|
||||||
|
|
||||||
def prefetch reqs # :nodoc:
|
def prefetch reqs # :nodoc:
|
||||||
|
@ -46,5 +50,29 @@ class Gem::Resolver::BestSet < Gem::Resolver::ComposedSet
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Replaces a failed APISet for the URI in +error+ with an IndexSet.
|
||||||
|
#
|
||||||
|
# If no matching APISet can be found the original +error+ is raised.
|
||||||
|
#
|
||||||
|
# The calling method must retry the exception to repeat the lookup.
|
||||||
|
|
||||||
|
def replace_failed_api_set error # :nodoc:
|
||||||
|
uri = error.uri
|
||||||
|
uri = URI uri unless URI === uri
|
||||||
|
uri.query = nil
|
||||||
|
|
||||||
|
raise error unless api_set = @sets.find { |set|
|
||||||
|
Gem::Resolver::APISet === set and set.dep_uri == uri
|
||||||
|
}
|
||||||
|
|
||||||
|
index_set = Gem::Resolver::IndexSet.new api_set.source
|
||||||
|
|
||||||
|
@sets.map! do |set|
|
||||||
|
next set unless set == api_set
|
||||||
|
index_set
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,18 @@ class Gem::Resolver::ComposedSet < Gem::Resolver::Set
|
||||||
@sets = sets
|
@sets = sets
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# When +allow_prerelease+ is set to +true+ prereleases gems are allowed to
|
||||||
|
# match dependencies.
|
||||||
|
|
||||||
|
def prerelease= allow_prerelease
|
||||||
|
super
|
||||||
|
|
||||||
|
sets.each do |set|
|
||||||
|
set.prerelease = allow_prerelease
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Sets the remote network access for all composed sets.
|
# Sets the remote network access for all composed sets.
|
||||||
|
|
||||||
|
@ -30,6 +42,10 @@ class Gem::Resolver::ComposedSet < Gem::Resolver::Set
|
||||||
@sets.each { |set| set.remote = remote }
|
@sets.each { |set| set.remote = remote }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def errors
|
||||||
|
@errors + @sets.map { |set| set.errors }.flatten
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Finds all specs matching +req+ in all sets.
|
# Finds all specs matching +req+ in all sets.
|
||||||
|
|
||||||
|
|
|
@ -52,11 +52,40 @@ class Gem::Resolver::Conflict
|
||||||
|
|
||||||
def explanation
|
def explanation
|
||||||
activated = @activated.spec.full_name
|
activated = @activated.spec.full_name
|
||||||
requirement = @failed_dep.dependency.requirement
|
dependency = @failed_dep.dependency
|
||||||
|
requirement = dependency.requirement
|
||||||
|
alternates = dependency.matching_specs.map { |spec| spec.full_name }
|
||||||
|
|
||||||
" Activated %s via:\n %s\n instead of (%s) via:\n %s\n" % [
|
unless alternates.empty? then
|
||||||
activated, request_path(@activated).join(', '),
|
matching = <<-MATCHING.chomp
|
||||||
requirement, request_path(requester).join(', '),
|
|
||||||
|
Gems matching %s:
|
||||||
|
%s
|
||||||
|
MATCHING
|
||||||
|
|
||||||
|
matching = matching % [
|
||||||
|
dependency,
|
||||||
|
alternates.join(', '),
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
explanation = <<-EXPLANATION
|
||||||
|
Activated %s
|
||||||
|
which does not match conflicting dependency (%s)
|
||||||
|
|
||||||
|
Conflicting dependency chains:
|
||||||
|
%s
|
||||||
|
|
||||||
|
versus:
|
||||||
|
%s
|
||||||
|
%s
|
||||||
|
EXPLANATION
|
||||||
|
|
||||||
|
explanation % [
|
||||||
|
activated, requirement,
|
||||||
|
request_path(@activated).reverse.join(", depends on\n "),
|
||||||
|
request_path(@failed_dep).reverse.join(", depends on\n "),
|
||||||
|
matching,
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -95,10 +124,19 @@ class Gem::Resolver::Conflict
|
||||||
path = []
|
path = []
|
||||||
|
|
||||||
while current do
|
while current do
|
||||||
requirement = current.request.dependency.requirement
|
case current
|
||||||
path << "#{current.spec.full_name} (#{requirement})"
|
when Gem::Resolver::ActivationRequest then
|
||||||
|
path <<
|
||||||
|
"#{current.request.dependency}, #{current.spec.version} activated"
|
||||||
|
|
||||||
current = current.parent
|
current = current.parent
|
||||||
|
when Gem::Resolver::DependencyRequest then
|
||||||
|
path << "#{current.dependency}"
|
||||||
|
|
||||||
|
current = current.requester
|
||||||
|
else
|
||||||
|
raise Gem::Exception, "[BUG] unknown request class #{current.class}"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
path = ['user request (gem command or Gemfile)'] if path.empty?
|
path = ['user request (gem command or Gemfile)'] if path.empty?
|
||||||
|
|
|
@ -35,7 +35,26 @@ class Gem::Resolver::DependencyRequest
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Does this dependency request match +spec+
|
# Is this dependency a development dependency?
|
||||||
|
|
||||||
|
def development?
|
||||||
|
@dependency.type == :development
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Does this dependency request match +spec+?
|
||||||
|
#
|
||||||
|
# NOTE: #match? only matches prerelease versions when #dependency is a
|
||||||
|
# prerelease dependency.
|
||||||
|
|
||||||
|
def match? spec, allow_prerelease = false
|
||||||
|
@dependency.match? spec, nil, allow_prerelease
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Does this dependency request match +spec+?
|
||||||
|
#
|
||||||
|
# NOTE: #matches_spec? matches prerelease versions. See also #match?
|
||||||
|
|
||||||
def matches_spec?(spec)
|
def matches_spec?(spec)
|
||||||
@dependency.matches_spec? spec
|
@dependency.matches_spec? spec
|
||||||
|
|
|
@ -80,7 +80,7 @@ class Gem::Resolver::GitSet < Gem::Resolver::Set
|
||||||
prefetch nil
|
prefetch nil
|
||||||
|
|
||||||
specs.values.select do |spec|
|
specs.values.select do |spec|
|
||||||
req.matches_spec? spec
|
req.match? spec
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -12,11 +12,15 @@ class Gem::Resolver::GitSpecification < Gem::Resolver::SpecSpecification
|
||||||
@source == other.source
|
@source == other.source
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def add_dependency dependency # :nodoc:
|
||||||
|
spec.dependencies << dependency
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Installing a git gem only involves building the extensions and generating
|
# Installing a git gem only involves building the extensions and generating
|
||||||
# the executables.
|
# the executables.
|
||||||
|
|
||||||
def install options
|
def install options = {}
|
||||||
require 'rubygems/installer'
|
require 'rubygems/installer'
|
||||||
|
|
||||||
installer = Gem::Installer.new '', options
|
installer = Gem::Installer.new '', options
|
||||||
|
@ -31,5 +35,25 @@ class Gem::Resolver::GitSpecification < Gem::Resolver::SpecSpecification
|
||||||
installer.run_post_install_hooks
|
installer.run_post_install_hooks
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def pretty_print q # :nodoc:
|
||||||
|
q.group 2, '[GitSpecification', ']' do
|
||||||
|
q.breakable
|
||||||
|
q.text "name: #{name}"
|
||||||
|
|
||||||
|
q.breakable
|
||||||
|
q.text "version: #{version}"
|
||||||
|
|
||||||
|
q.breakable
|
||||||
|
q.text 'dependencies:'
|
||||||
|
q.breakable
|
||||||
|
q.pp dependencies
|
||||||
|
|
||||||
|
q.breakable
|
||||||
|
q.text "source:"
|
||||||
|
q.breakable
|
||||||
|
q.pp @source
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,9 @@ class Gem::Resolver::IndexSet < Gem::Resolver::Set
|
||||||
|
|
||||||
@all = Hash.new { |h,k| h[k] = [] }
|
@all = Hash.new { |h,k| h[k] = [] }
|
||||||
|
|
||||||
list, = @f.available_specs :released
|
list, errors = @f.available_specs :complete
|
||||||
|
|
||||||
|
@errors.concat errors
|
||||||
|
|
||||||
list.each do |uri, specs|
|
list.each do |uri, specs|
|
||||||
specs.each do |n|
|
specs.each do |n|
|
||||||
|
@ -41,7 +43,7 @@ class Gem::Resolver::IndexSet < Gem::Resolver::Set
|
||||||
name = req.dependency.name
|
name = req.dependency.name
|
||||||
|
|
||||||
@all[name].each do |uri, n|
|
@all[name].each do |uri, n|
|
||||||
if req.dependency.match? n then
|
if req.match? n, @prerelease then
|
||||||
res << Gem::Resolver::IndexSpecification.new(
|
res << Gem::Resolver::IndexSpecification.new(
|
||||||
self, n.name, n.version, uri, n.platform)
|
self, n.name, n.version, uri, n.platform)
|
||||||
end
|
end
|
||||||
|
|
|
@ -14,7 +14,7 @@ class Gem::Resolver::InstalledSpecification < Gem::Resolver::SpecSpecification
|
||||||
# This is a null install as this specification is already installed.
|
# This is a null install as this specification is already installed.
|
||||||
# +options+ are ignored.
|
# +options+ are ignored.
|
||||||
|
|
||||||
def install options
|
def install options = {}
|
||||||
yield nil
|
yield nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -29,6 +29,24 @@ class Gem::Resolver::InstalledSpecification < Gem::Resolver::SpecSpecification
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def pretty_print q # :nodoc:
|
||||||
|
q.group 2, '[InstalledSpecification', ']' do
|
||||||
|
q.breakable
|
||||||
|
q.text "name: #{name}"
|
||||||
|
|
||||||
|
q.breakable
|
||||||
|
q.text "version: #{version}"
|
||||||
|
|
||||||
|
q.breakable
|
||||||
|
q.text "platform: #{platform}"
|
||||||
|
|
||||||
|
q.breakable
|
||||||
|
q.text 'dependencies:'
|
||||||
|
q.breakable
|
||||||
|
q.pp spec.dependencies
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# The source for this specification
|
# The source for this specification
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,11 @@ class Gem::Resolver::InstallerSet < Gem::Resolver::Set
|
||||||
|
|
||||||
attr_accessor :ignore_installed # :nodoc:
|
attr_accessor :ignore_installed # :nodoc:
|
||||||
|
|
||||||
|
##
|
||||||
|
# The remote_set looks up remote gems for installation.
|
||||||
|
|
||||||
|
attr_reader :remote_set # :nodoc:
|
||||||
|
|
||||||
##
|
##
|
||||||
# Creates a new InstallerSet that will look for gems in +domain+.
|
# Creates a new InstallerSet that will look for gems in +domain+.
|
||||||
|
|
||||||
|
@ -34,10 +39,52 @@ class Gem::Resolver::InstallerSet < Gem::Resolver::Set
|
||||||
@always_install = []
|
@always_install = []
|
||||||
@ignore_dependencies = false
|
@ignore_dependencies = false
|
||||||
@ignore_installed = false
|
@ignore_installed = false
|
||||||
|
@local = {}
|
||||||
@remote_set = Gem::Resolver::BestSet.new
|
@remote_set = Gem::Resolver::BestSet.new
|
||||||
@specs = {}
|
@specs = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Looks up the latest specification for +dependency+ and adds it to the
|
||||||
|
# always_install list.
|
||||||
|
|
||||||
|
def add_always_install dependency
|
||||||
|
request = Gem::Resolver::DependencyRequest.new dependency, nil
|
||||||
|
|
||||||
|
found = find_all request
|
||||||
|
|
||||||
|
found.delete_if { |s|
|
||||||
|
s.version.prerelease? and not s.local?
|
||||||
|
} unless dependency.prerelease?
|
||||||
|
|
||||||
|
found = found.select do |s|
|
||||||
|
Gem::Source::SpecificFile === s.source or
|
||||||
|
Gem::Platform::RUBY == s.platform or
|
||||||
|
Gem::Platform.local === s.platform
|
||||||
|
end
|
||||||
|
|
||||||
|
if found.empty? then
|
||||||
|
exc = Gem::UnsatisfiableDependencyError.new request
|
||||||
|
exc.errors = errors
|
||||||
|
|
||||||
|
raise exc
|
||||||
|
end
|
||||||
|
|
||||||
|
newest = found.max_by do |s|
|
||||||
|
[s.version, s.platform == Gem::Platform::RUBY ? -1 : 1]
|
||||||
|
end
|
||||||
|
|
||||||
|
@always_install << newest.spec
|
||||||
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Adds a local gem requested using +dep_name+ with the given +spec+ that can
|
||||||
|
# be loaded and installed using the +source+.
|
||||||
|
|
||||||
|
def add_local dep_name, spec, source
|
||||||
|
@local[dep_name] = [spec, source]
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Should local gems should be considered?
|
# Should local gems should be considered?
|
||||||
|
|
||||||
|
@ -52,6 +99,13 @@ class Gem::Resolver::InstallerSet < Gem::Resolver::Set
|
||||||
@domain == :both or @domain == :remote
|
@domain == :both or @domain == :remote
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Errors encountered while resolving gems
|
||||||
|
|
||||||
|
def errors
|
||||||
|
@errors + @remote_set.errors
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Returns an array of IndexSpecification objects matching DependencyRequest
|
# Returns an array of IndexSpecification objects matching DependencyRequest
|
||||||
# +req+.
|
# +req+.
|
||||||
|
@ -62,30 +116,53 @@ class Gem::Resolver::InstallerSet < Gem::Resolver::Set
|
||||||
dep = req.dependency
|
dep = req.dependency
|
||||||
|
|
||||||
return res if @ignore_dependencies and
|
return res if @ignore_dependencies and
|
||||||
@always_install.none? { |spec| dep.matches_spec? spec }
|
@always_install.none? { |spec| dep.match? spec }
|
||||||
|
|
||||||
name = dep.name
|
name = dep.name
|
||||||
|
|
||||||
dep.matching_specs.each do |gemspec|
|
dep.matching_specs.each do |gemspec|
|
||||||
next if @always_install.include? gemspec
|
next if @always_install.any? { |spec| spec.name == gemspec.name }
|
||||||
|
|
||||||
res << Gem::Resolver::InstalledSpecification.new(self, gemspec)
|
res << Gem::Resolver::InstalledSpecification.new(self, gemspec)
|
||||||
end unless @ignore_installed
|
end unless @ignore_installed
|
||||||
|
|
||||||
if consider_local? then
|
if consider_local? then
|
||||||
|
matching_local = @local.values.select do |spec, _|
|
||||||
|
req.match? spec
|
||||||
|
end.map do |spec, source|
|
||||||
|
Gem::Resolver::LocalSpecification.new self, spec, source
|
||||||
|
end
|
||||||
|
|
||||||
|
res.concat matching_local
|
||||||
|
|
||||||
local_source = Gem::Source::Local.new
|
local_source = Gem::Source::Local.new
|
||||||
|
|
||||||
if 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(
|
res << Gem::Resolver::IndexSpecification.new(
|
||||||
self, spec.name, spec.version, local_source, spec.platform)
|
self, local_spec.name, local_spec.version,
|
||||||
|
local_source, local_spec.platform)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
res.delete_if do |spec|
|
||||||
|
spec.version.prerelease? and not dep.prerelease?
|
||||||
|
end
|
||||||
|
|
||||||
res.concat @remote_set.find_all req if consider_remote?
|
res.concat @remote_set.find_all req if consider_remote?
|
||||||
|
|
||||||
res
|
res
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def prefetch(reqs)
|
||||||
|
@remote_set.prefetch(reqs)
|
||||||
|
end
|
||||||
|
|
||||||
|
def prerelease= allow_prerelease
|
||||||
|
super
|
||||||
|
|
||||||
|
@remote_set.prerelease = allow_prerelease
|
||||||
|
end
|
||||||
|
|
||||||
def inspect # :nodoc:
|
def inspect # :nodoc:
|
||||||
always_install = @always_install.map { |s| s.full_name }
|
always_install = @always_install.map { |s| s.full_name }
|
||||||
|
|
||||||
|
@ -108,6 +185,15 @@ class Gem::Resolver::InstallerSet < Gem::Resolver::Set
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Has a local gem for +dep_name+ been added to this set?
|
||||||
|
|
||||||
|
def local? dep_name # :nodoc:
|
||||||
|
spec, = @local[dep_name]
|
||||||
|
|
||||||
|
spec
|
||||||
|
end
|
||||||
|
|
||||||
def pretty_print q # :nodoc:
|
def pretty_print q # :nodoc:
|
||||||
q.group 2, '[InstallerSet', ']' do
|
q.group 2, '[InstallerSet', ']' do
|
||||||
q.breakable
|
q.breakable
|
||||||
|
|
|
@ -12,5 +12,30 @@ class Gem::Resolver::LocalSpecification < Gem::Resolver::SpecSpecification
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def local? # :nodoc:
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
def pretty_print q # :nodoc:
|
||||||
|
q.group 2, '[LocalSpecification', ']' do
|
||||||
|
q.breakable
|
||||||
|
q.text "name: #{name}"
|
||||||
|
|
||||||
|
q.breakable
|
||||||
|
q.text "version: #{version}"
|
||||||
|
|
||||||
|
q.breakable
|
||||||
|
q.text "platform: #{platform}"
|
||||||
|
|
||||||
|
q.breakable
|
||||||
|
q.text 'dependencies:'
|
||||||
|
q.breakable
|
||||||
|
q.pp dependencies
|
||||||
|
|
||||||
|
q.breakable
|
||||||
|
q.text "source: #{@source.path}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -6,13 +6,16 @@ class Gem::Resolver::LockSet < Gem::Resolver::Set
|
||||||
attr_reader :specs # :nodoc:
|
attr_reader :specs # :nodoc:
|
||||||
|
|
||||||
##
|
##
|
||||||
# Creates a new LockSet from the given +source+
|
# Creates a new LockSet from the given +sources+
|
||||||
|
|
||||||
def initialize source
|
def initialize sources
|
||||||
super()
|
super()
|
||||||
|
|
||||||
@source = Gem::Source::Lock.new source
|
@sources = sources.map do |source|
|
||||||
@specs = []
|
Gem::Source::Lock.new source
|
||||||
|
end
|
||||||
|
|
||||||
|
@specs = []
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -25,13 +28,14 @@ class Gem::Resolver::LockSet < Gem::Resolver::Set
|
||||||
def add name, version, platform # :nodoc:
|
def add name, version, platform # :nodoc:
|
||||||
version = Gem::Version.new version
|
version = Gem::Version.new version
|
||||||
|
|
||||||
spec =
|
specs = @sources.map do |source|
|
||||||
Gem::Resolver::LockSpecification.new self, name, version, @source,
|
Gem::Resolver::LockSpecification.new self, name, version, source,
|
||||||
platform
|
platform
|
||||||
|
end
|
||||||
|
|
||||||
@specs << spec
|
@specs.concat specs
|
||||||
|
|
||||||
spec
|
specs
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -40,7 +44,7 @@ class Gem::Resolver::LockSet < Gem::Resolver::Set
|
||||||
|
|
||||||
def find_all req
|
def find_all req
|
||||||
@specs.select do |spec|
|
@specs.select do |spec|
|
||||||
req.matches_spec? spec
|
req.match? spec
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ class Gem::Resolver::LockSpecification < Gem::Resolver::Specification
|
||||||
# This is a null install as a locked specification is considered installed.
|
# This is a null install as a locked specification is considered installed.
|
||||||
# +options+ are ignored.
|
# +options+ are ignored.
|
||||||
|
|
||||||
def install options
|
def install options = {}
|
||||||
destination = options[:install_dir] || Gem.dir
|
destination = options[:install_dir] || Gem.dir
|
||||||
|
|
||||||
if File.exist? File.join(destination, 'specifications', spec.spec_name) then
|
if File.exist? File.join(destination, 'specifications', spec.spec_name) then
|
||||||
|
@ -41,10 +41,36 @@ class Gem::Resolver::LockSpecification < Gem::Resolver::Specification
|
||||||
@dependencies << dependency
|
@dependencies << dependency
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def pretty_print q # :nodoc:
|
||||||
|
q.group 2, '[LockSpecification', ']' do
|
||||||
|
q.breakable
|
||||||
|
q.text "name: #{@name}"
|
||||||
|
|
||||||
|
q.breakable
|
||||||
|
q.text "version: #{@version}"
|
||||||
|
|
||||||
|
unless @platform == Gem::Platform::RUBY then
|
||||||
|
q.breakable
|
||||||
|
q.text "platform: #{@platform}"
|
||||||
|
end
|
||||||
|
|
||||||
|
unless @dependencies.empty? then
|
||||||
|
q.breakable
|
||||||
|
q.text 'dependencies:'
|
||||||
|
q.breakable
|
||||||
|
q.pp @dependencies
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# A specification constructed from the lockfile is returned
|
# A specification constructed from the lockfile is returned
|
||||||
|
|
||||||
def spec
|
def spec
|
||||||
|
@spec ||= Gem::Specification.find { |spec|
|
||||||
|
spec.name == @name and spec.version == @version
|
||||||
|
}
|
||||||
|
|
||||||
@spec ||= Gem::Specification.new do |s|
|
@spec ||= Gem::Specification.new do |s|
|
||||||
s.name = @name
|
s.name = @name
|
||||||
s.version = @version
|
s.version = @version
|
||||||
|
|
|
@ -9,8 +9,20 @@ class Gem::Resolver::Set
|
||||||
|
|
||||||
attr_accessor :remote
|
attr_accessor :remote
|
||||||
|
|
||||||
|
##
|
||||||
|
# Errors encountered when resolving gems
|
||||||
|
|
||||||
|
attr_accessor :errors
|
||||||
|
|
||||||
|
##
|
||||||
|
# When true, allows matching of requests to prerelease gems.
|
||||||
|
|
||||||
|
attr_accessor :prerelease
|
||||||
|
|
||||||
def initialize # :nodoc:
|
def initialize # :nodoc:
|
||||||
@remote = true
|
@prerelease = false
|
||||||
|
@remote = true
|
||||||
|
@errors = []
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
|
|
@ -4,8 +4,6 @@
|
||||||
|
|
||||||
class Gem::Resolver::SpecSpecification < Gem::Resolver::Specification
|
class Gem::Resolver::SpecSpecification < Gem::Resolver::Specification
|
||||||
|
|
||||||
attr_reader :spec # :nodoc:
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# A SpecSpecification is created for a +set+ for a Gem::Specification in
|
# A SpecSpecification is created for a +set+ for a Gem::Specification in
|
||||||
# +spec+. The +source+ is either where the +spec+ came from, or should be
|
# +spec+. The +source+ is either where the +spec+ came from, or should be
|
||||||
|
|
|
@ -30,6 +30,14 @@ class Gem::Resolver::Specification
|
||||||
|
|
||||||
attr_reader :source
|
attr_reader :source
|
||||||
|
|
||||||
|
##
|
||||||
|
# The Gem::Specification for this Resolver::Specification.
|
||||||
|
#
|
||||||
|
# Implementers, note that #install updates @spec, so be sure to cache the
|
||||||
|
# Gem::Specification in @spec when overriding.
|
||||||
|
|
||||||
|
attr_reader :spec
|
||||||
|
|
||||||
##
|
##
|
||||||
# The version of the gem for this specification.
|
# The version of the gem for this specification.
|
||||||
|
|
||||||
|
@ -47,6 +55,13 @@ class Gem::Resolver::Specification
|
||||||
@version = nil
|
@version = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Fetches development dependencies if the source does not provide them by
|
||||||
|
# default (see APISpecification).
|
||||||
|
|
||||||
|
def fetch_development_dependencies # :nodoc:
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# The name and version of the specification.
|
# The name and version of the specification.
|
||||||
#
|
#
|
||||||
|
@ -61,8 +76,11 @@ class Gem::Resolver::Specification
|
||||||
# install method yields a Gem::Installer instance, which indicates the
|
# install method yields a Gem::Installer instance, which indicates the
|
||||||
# gem will be installed, or +nil+, which indicates the gem is already
|
# gem will be installed, or +nil+, which indicates the gem is already
|
||||||
# installed.
|
# installed.
|
||||||
|
#
|
||||||
|
# After installation #spec is updated to point to the just-installed
|
||||||
|
# specification.
|
||||||
|
|
||||||
def install options
|
def install options = {}
|
||||||
require 'rubygems/installer'
|
require 'rubygems/installer'
|
||||||
|
|
||||||
destination = options[:install_dir] || Gem.dir
|
destination = options[:install_dir] || Gem.dir
|
||||||
|
@ -75,7 +93,7 @@ class Gem::Resolver::Specification
|
||||||
|
|
||||||
yield installer if block_given?
|
yield installer if block_given?
|
||||||
|
|
||||||
installer.install
|
@spec = installer.install
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -85,5 +103,8 @@ class Gem::Resolver::Specification
|
||||||
Gem::Platform.match spec.platform
|
Gem::Platform.match spec.platform
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def local? # :nodoc:
|
||||||
|
false
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,8 @@ class Gem::Resolver::VendorSet < Gem::Resolver::Set
|
||||||
|
|
||||||
@specs[spec.name] = spec
|
@specs[spec.name] = spec
|
||||||
@directories[spec] = directory
|
@directories[spec] = directory
|
||||||
|
|
||||||
|
spec
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -51,7 +53,7 @@ class Gem::Resolver::VendorSet < Gem::Resolver::Set
|
||||||
|
|
||||||
def find_all req
|
def find_all req
|
||||||
@specs.values.select do |spec|
|
@specs.values.select do |spec|
|
||||||
req.matches_spec? spec
|
req.match? spec
|
||||||
end.map do |spec|
|
end.map do |spec|
|
||||||
source = Gem::Source::Vendor.new @directories[spec]
|
source = Gem::Source::Vendor.new @directories[spec]
|
||||||
Gem::Resolver::VendorSpecification.new self, spec, source
|
Gem::Resolver::VendorSpecification.new self, spec, source
|
||||||
|
|
|
@ -16,7 +16,7 @@ class Gem::Resolver::VendorSpecification < Gem::Resolver::SpecSpecification
|
||||||
# This is a null install as this gem was unpacked into a directory.
|
# This is a null install as this gem was unpacked into a directory.
|
||||||
# +options+ are ignored.
|
# +options+ are ignored.
|
||||||
|
|
||||||
def install options
|
def install options = {}
|
||||||
yield nil
|
yield nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -218,6 +218,7 @@ class Gem::Security::Policy
|
||||||
# against
|
# against
|
||||||
else
|
else
|
||||||
alert_warning "#{full_name} is not signed"
|
alert_warning "#{full_name} is not signed"
|
||||||
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -530,6 +530,36 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def prerelease_specs req, res
|
||||||
|
reset_gems
|
||||||
|
|
||||||
|
res['content-type'] = 'application/x-gzip'
|
||||||
|
|
||||||
|
add_date res
|
||||||
|
|
||||||
|
specs = Gem::Specification.select do |spec|
|
||||||
|
spec.version.prerelease?
|
||||||
|
end.sort.map do |spec|
|
||||||
|
platform = spec.original_platform || Gem::Platform::RUBY
|
||||||
|
[spec.name, spec.version, platform]
|
||||||
|
end
|
||||||
|
|
||||||
|
specs = Marshal.dump specs
|
||||||
|
|
||||||
|
if req.path =~ /\.gz$/ then
|
||||||
|
specs = Gem.gzip specs
|
||||||
|
res['content-type'] = 'application/x-gzip'
|
||||||
|
else
|
||||||
|
res['content-type'] = 'application/octet-stream'
|
||||||
|
end
|
||||||
|
|
||||||
|
if req.request_method == 'HEAD' then
|
||||||
|
res['content-length'] = specs.length
|
||||||
|
else
|
||||||
|
res.body << specs
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def quick(req, res)
|
def quick(req, res)
|
||||||
reset_gems
|
reset_gems
|
||||||
|
|
||||||
|
@ -537,7 +567,7 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
||||||
add_date res
|
add_date res
|
||||||
|
|
||||||
case req.request_uri.path
|
case req.request_uri.path
|
||||||
when %r|^/quick/(Marshal.#{Regexp.escape Gem.marshal_version}/)?(.*?)-([0-9.]+)(-.*?)?\.gemspec\.rz$| then
|
when %r|^/quick/(Marshal.#{Regexp.escape Gem.marshal_version}/)?(.*?)-([0-9.]+[^-]*?)(-.*?)?\.gemspec\.rz$| then
|
||||||
marshal_format, name, version, platform = $1, $2, $3, $4
|
marshal_format, name, version, platform = $1, $2, $3, $4
|
||||||
specs = Gem::Specification.find_all_by_name name, version
|
specs = Gem::Specification.find_all_by_name name, version
|
||||||
|
|
||||||
|
@ -757,6 +787,11 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
||||||
@server.mount_proc "/latest_specs.#{Gem.marshal_version}.gz",
|
@server.mount_proc "/latest_specs.#{Gem.marshal_version}.gz",
|
||||||
method(:latest_specs)
|
method(:latest_specs)
|
||||||
|
|
||||||
|
@server.mount_proc "/prerelease_specs.#{Gem.marshal_version}",
|
||||||
|
method(:prerelease_specs)
|
||||||
|
@server.mount_proc "/prerelease_specs.#{Gem.marshal_version}.gz",
|
||||||
|
method(:prerelease_specs)
|
||||||
|
|
||||||
@server.mount_proc "/quick/", method(:quick)
|
@server.mount_proc "/quick/", method(:quick)
|
||||||
|
|
||||||
@server.mount_proc("/gem-server-rdoc-style.css") do |req, res|
|
@server.mount_proc("/gem-server-rdoc-style.css") do |req, res|
|
||||||
|
|
|
@ -78,15 +78,21 @@ class Gem::Source
|
||||||
# Returns a Set that can fetch specifications from this source.
|
# Returns a Set that can fetch specifications from this source.
|
||||||
|
|
||||||
def dependency_resolver_set # :nodoc:
|
def dependency_resolver_set # :nodoc:
|
||||||
|
return Gem::Resolver::IndexSet.new self if 'file' == api_uri.scheme
|
||||||
|
|
||||||
bundler_api_uri = api_uri + './api/v1/dependencies'
|
bundler_api_uri = api_uri + './api/v1/dependencies'
|
||||||
|
|
||||||
begin
|
begin
|
||||||
fetcher = Gem::RemoteFetcher.fetcher
|
fetcher = Gem::RemoteFetcher.fetcher
|
||||||
fetcher.fetch_path bundler_api_uri, nil, true
|
response = fetcher.fetch_path bundler_api_uri, nil, true
|
||||||
rescue Gem::RemoteFetcher::FetchError
|
rescue Gem::RemoteFetcher::FetchError
|
||||||
Gem::Resolver::IndexSet.new self
|
Gem::Resolver::IndexSet.new self
|
||||||
else
|
else
|
||||||
Gem::Resolver::APISet.new bundler_api_uri
|
if response.respond_to? :uri then
|
||||||
|
Gem::Resolver::APISet.new response.uri
|
||||||
|
else
|
||||||
|
Gem::Resolver::APISet.new bundler_api_uri
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -100,6 +106,8 @@ class Gem::Source
|
||||||
def cache_dir(uri)
|
def cache_dir(uri)
|
||||||
# Correct for windows paths
|
# Correct for windows paths
|
||||||
escaped_path = uri.path.sub(/^\/([a-z]):\//i, '/\\1-/')
|
escaped_path = uri.path.sub(/^\/([a-z]):\//i, '/\\1-/')
|
||||||
|
escaped_path.untaint
|
||||||
|
|
||||||
File.join Gem.spec_cache_dir, "#{uri.host}%#{uri.port}", File.dirname(escaped_path)
|
File.join Gem.spec_cache_dir, "#{uri.host}%#{uri.port}", File.dirname(escaped_path)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ class Gem::Source::Git < Gem::Source
|
||||||
# will be checked out when the gem is installed.
|
# will be checked out when the gem is installed.
|
||||||
|
|
||||||
def initialize name, repository, reference, submodules = false
|
def initialize name, repository, reference, submodules = false
|
||||||
super(nil)
|
super repository
|
||||||
|
|
||||||
@name = name
|
@name = name
|
||||||
@repository = repository
|
@repository = repository
|
||||||
|
@ -67,7 +67,7 @@ class Gem::Source::Git < Gem::Source
|
||||||
case other
|
case other
|
||||||
when Gem::Source::Git then
|
when Gem::Source::Git then
|
||||||
0
|
0
|
||||||
when Gem::Source::Installed,
|
when Gem::Source::Vendor,
|
||||||
Gem::Source::Lock then
|
Gem::Source::Lock then
|
||||||
-1
|
-1
|
||||||
when Gem::Source then
|
when Gem::Source then
|
||||||
|
@ -101,7 +101,7 @@ class Gem::Source::Git < Gem::Source
|
||||||
Dir.chdir install_dir do
|
Dir.chdir install_dir do
|
||||||
system @git, 'fetch', '--quiet', '--force', '--tags', install_dir
|
system @git, 'fetch', '--quiet', '--force', '--tags', install_dir
|
||||||
|
|
||||||
success = system @git, 'reset', '--quiet', '--hard', @reference
|
success = system @git, 'reset', '--quiet', '--hard', rev_parse
|
||||||
|
|
||||||
success &&=
|
success &&=
|
||||||
Gem::Util.silent_system @git, 'submodule', 'update',
|
Gem::Util.silent_system @git, 'submodule', 'update',
|
||||||
|
|
|
@ -12,7 +12,8 @@ class Gem::Source::Installed < Gem::Source
|
||||||
|
|
||||||
def <=> other
|
def <=> other
|
||||||
case other
|
case other
|
||||||
when Gem::Source::Lock,
|
when Gem::Source::Git,
|
||||||
|
Gem::Source::Lock,
|
||||||
Gem::Source::Vendor then
|
Gem::Source::Vendor then
|
||||||
-1
|
-1
|
||||||
when Gem::Source::Installed then
|
when Gem::Source::Installed then
|
||||||
|
@ -31,5 +32,9 @@ class Gem::Source::Installed < Gem::Source
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def pretty_print q # :nodoc:
|
||||||
|
q.text '[Installed]'
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,11 @@
|
||||||
|
|
||||||
class Gem::Source::SpecificFile < Gem::Source
|
class Gem::Source::SpecificFile < Gem::Source
|
||||||
|
|
||||||
|
##
|
||||||
|
# The path to the gem for this specific file.
|
||||||
|
|
||||||
|
attr_reader :path
|
||||||
|
|
||||||
##
|
##
|
||||||
# Creates a new SpecificFile for the gem in +file+
|
# Creates a new SpecificFile for the gem in +file+
|
||||||
|
|
||||||
|
@ -37,7 +42,7 @@ class Gem::Source::SpecificFile < Gem::Source
|
||||||
end
|
end
|
||||||
|
|
||||||
def pretty_print q # :nodoc:
|
def pretty_print q # :nodoc:
|
||||||
q.group 2, '[Local:', ']' do
|
q.group 2, '[SpecificFile:', ']' do
|
||||||
q.breakable
|
q.breakable
|
||||||
q.text @path
|
q.text @path
|
||||||
end
|
end
|
||||||
|
|
|
@ -186,7 +186,7 @@ class Gem::SpecFetcher
|
||||||
def suggest_gems_from_name gem_name
|
def suggest_gems_from_name gem_name
|
||||||
gem_name = gem_name.downcase.tr('_-', '')
|
gem_name = gem_name.downcase.tr('_-', '')
|
||||||
max = gem_name.size / 2
|
max = gem_name.size / 2
|
||||||
names = available_specs(:complete).first.values.flatten(1)
|
names = available_specs(:latest).first.values.flatten(1)
|
||||||
|
|
||||||
matches = names.map { |n|
|
matches = names.map { |n|
|
||||||
next unless n.match_platform?
|
next unless n.match_platform?
|
||||||
|
@ -258,18 +258,11 @@ class Gem::SpecFetcher
|
||||||
# etc.). If +gracefully_ignore+ is true, errors are ignored.
|
# etc.). If +gracefully_ignore+ is true, errors are ignored.
|
||||||
|
|
||||||
def tuples_for(source, type, gracefully_ignore=false) # :nodoc:
|
def tuples_for(source, type, gracefully_ignore=false) # :nodoc:
|
||||||
cache = @caches[type]
|
@caches[type][source.uri] ||=
|
||||||
|
source.load_specs(type).sort_by { |tup| tup.name }
|
||||||
tuples =
|
rescue Gem::RemoteFetcher::FetchError
|
||||||
begin
|
raise unless gracefully_ignore
|
||||||
cache[source.uri] ||=
|
[]
|
||||||
source.load_specs(type).sort_by { |tup| tup.name }
|
|
||||||
rescue Gem::RemoteFetcher::FetchError
|
|
||||||
raise unless gracefully_ignore
|
|
||||||
[]
|
|
||||||
end
|
|
||||||
|
|
||||||
tuples
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -14,12 +14,6 @@ require 'rubygems/basic_specification'
|
||||||
require 'rubygems/stub_specification'
|
require 'rubygems/stub_specification'
|
||||||
require 'rubygems/util/stringio'
|
require 'rubygems/util/stringio'
|
||||||
|
|
||||||
# :stopdoc:
|
|
||||||
# date.rb can't be loaded for `make install` due to miniruby
|
|
||||||
# Date is needed for old gems that stored #date as Date instead of Time.
|
|
||||||
class Date; end
|
|
||||||
# :startdoc:
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# The Specification class contains the information for a Gem. Typically
|
# The Specification class contains the information for a Gem. Typically
|
||||||
# defined in a .gemspec file or a Rakefile, and looks like this:
|
# defined in a .gemspec file or a Rakefile, and looks like this:
|
||||||
|
@ -218,9 +212,11 @@ class Gem::Specification < Gem::BasicSpecification
|
||||||
# Usage:
|
# Usage:
|
||||||
#
|
#
|
||||||
# # If all library files are in the root directory...
|
# # If all library files are in the root directory...
|
||||||
# spec.require_path = '.'
|
# spec.require_paths = ['.']
|
||||||
|
|
||||||
attr_writer :require_paths
|
def require_paths=(val)
|
||||||
|
@require_paths = Array(val)
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# The version of RubyGems used to create this gem.
|
# The version of RubyGems used to create this gem.
|
||||||
|
@ -373,7 +369,9 @@ class Gem::Specification < Gem::BasicSpecification
|
||||||
##
|
##
|
||||||
# A long description of this gem
|
# A long description of this gem
|
||||||
#
|
#
|
||||||
# The description should be more detailed than the summary.
|
# 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:
|
# Usage:
|
||||||
#
|
#
|
||||||
|
@ -412,6 +410,16 @@ class Gem::Specification < Gem::BasicSpecification
|
||||||
|
|
||||||
attr_accessor :post_install_message
|
attr_accessor :post_install_message
|
||||||
|
|
||||||
|
##
|
||||||
|
# The version of Ruby required by this gem
|
||||||
|
|
||||||
|
attr_reader :required_ruby_version
|
||||||
|
|
||||||
|
##
|
||||||
|
# The RubyGems version required by this gem
|
||||||
|
|
||||||
|
attr_reader :required_rubygems_version
|
||||||
|
|
||||||
##
|
##
|
||||||
# The key used to sign this gem. See Gem::Security for details.
|
# The key used to sign this gem. See Gem::Security for details.
|
||||||
|
|
||||||
|
@ -472,6 +480,9 @@ class Gem::Specification < Gem::BasicSpecification
|
||||||
# found in bindir. These files must be executable Ruby files. Files that
|
# found in bindir. These files must be executable Ruby files. Files that
|
||||||
# use bash or other interpreters will not work.
|
# use bash or other interpreters will not work.
|
||||||
#
|
#
|
||||||
|
# Executables included may only be ruby scripts, not scripts for other
|
||||||
|
# languages or compiled binaries.
|
||||||
|
#
|
||||||
# Usage:
|
# Usage:
|
||||||
#
|
#
|
||||||
# spec.executables << 'rake'
|
# spec.executables << 'rake'
|
||||||
|
@ -532,20 +543,26 @@ class Gem::Specification < Gem::BasicSpecification
|
||||||
|
|
||||||
##
|
##
|
||||||
# :category: Recommended gemspec attributes
|
# :category: Recommended gemspec attributes
|
||||||
|
#
|
||||||
# The license for this gem.
|
# The license for this gem.
|
||||||
#
|
#
|
||||||
# The license must be a short name, no more than 64 characters.
|
# The license must be no more than 64 characters.
|
||||||
#
|
#
|
||||||
# This should just be the name of your license. The full
|
# This should just be the name of your license. The full text of the license
|
||||||
# text of the license should be inside of the gem when you build it.
|
# should be inside of the gem (at the top level) when you build it.
|
||||||
#
|
#
|
||||||
# See http://opensource.org/licenses/alphabetical for a list of licenses and
|
# The simplest way, is to specify the standard SPDX ID
|
||||||
# their abbreviations (or short names). GitHub also provides a
|
# https://spdx.org/licenses/ for the license.
|
||||||
# license picker at http://choosealicense.com/
|
# Ideally you should pick one that is OSI (Open Source Initiative)
|
||||||
|
# http://opensource.org/licenses/alphabetical approved.
|
||||||
#
|
#
|
||||||
# According to copyright law, not having an OSI-approved open source license
|
# The most commonly used OSI approved licenses are BSD-3-Clause and MIT.
|
||||||
# means you have no rights to use the code for any purpose-- in other words,
|
# GitHub also provides a license picker at http://choosealicense.com/.
|
||||||
# "all rights reserved".
|
#
|
||||||
|
# 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=
|
# You can set multiple licenses with #licenses=
|
||||||
#
|
#
|
||||||
|
@ -607,6 +624,13 @@ class Gem::Specification < Gem::BasicSpecification
|
||||||
@required_ruby_version = Gem::Requirement.create req
|
@required_ruby_version = Gem::Requirement.create req
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# The RubyGems version required by this gem
|
||||||
|
|
||||||
|
def required_rubygems_version= req
|
||||||
|
@required_rubygems_version = Gem::Requirement.create req
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Lists the external (to RubyGems) requirements that must be met for this gem
|
# Lists the external (to RubyGems) requirements that must be met for this gem
|
||||||
# to work. It's simply information for the user.
|
# to work. It's simply information for the user.
|
||||||
|
@ -628,7 +652,7 @@ class Gem::Specification < Gem::BasicSpecification
|
||||||
# spec.test_files = Dir.glob('test/tc_*.rb')
|
# spec.test_files = Dir.glob('test/tc_*.rb')
|
||||||
# spec.test_files = ['tests/test-suite.rb']
|
# spec.test_files = ['tests/test-suite.rb']
|
||||||
|
|
||||||
def test_files= files
|
def test_files= files # :nodoc:
|
||||||
@test_files = Array files
|
@test_files = Array files
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -661,16 +685,6 @@ class Gem::Specification < Gem::BasicSpecification
|
||||||
|
|
||||||
attr_writer :original_platform # :nodoc:
|
attr_writer :original_platform # :nodoc:
|
||||||
|
|
||||||
##
|
|
||||||
# The version of Ruby required by this gem
|
|
||||||
|
|
||||||
attr_reader :required_ruby_version
|
|
||||||
|
|
||||||
##
|
|
||||||
# The RubyGems version required by this gem
|
|
||||||
|
|
||||||
attr_reader :required_rubygems_version
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# The rubyforge project this gem lives under. i.e. RubyGems'
|
# The rubyforge project this gem lives under. i.e. RubyGems'
|
||||||
# rubyforge_project is "rubygems".
|
# rubyforge_project is "rubygems".
|
||||||
|
@ -1259,9 +1273,13 @@ class Gem::Specification < Gem::BasicSpecification
|
||||||
# there are conflicts upon activation.
|
# there are conflicts upon activation.
|
||||||
|
|
||||||
def activate
|
def activate
|
||||||
raise_if_conflicts
|
other = Gem.loaded_specs[self.name]
|
||||||
|
if other then
|
||||||
|
check_version_conflict other
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
return false if Gem.loaded_specs[self.name]
|
raise_if_conflicts
|
||||||
|
|
||||||
activate_dependencies
|
activate_dependencies
|
||||||
add_self_to_load_path
|
add_self_to_load_path
|
||||||
|
@ -1403,7 +1421,10 @@ class Gem::Specification < Gem::BasicSpecification
|
||||||
|
|
||||||
def build_args
|
def build_args
|
||||||
if File.exist? build_info_file
|
if File.exist? build_info_file
|
||||||
File.readlines(build_info_file).map { |x| x.strip }
|
build_info = File.readlines build_info_file
|
||||||
|
build_info = build_info.map { |x| x.strip }
|
||||||
|
build_info.delete ""
|
||||||
|
build_info
|
||||||
else
|
else
|
||||||
[]
|
[]
|
||||||
end
|
end
|
||||||
|
@ -1418,8 +1439,8 @@ class Gem::Specification < Gem::BasicSpecification
|
||||||
return if extensions.empty?
|
return if extensions.empty?
|
||||||
return if installed_by_version < Gem::Version.new('2.2.0.preview.2')
|
return if installed_by_version < Gem::Version.new('2.2.0.preview.2')
|
||||||
return if File.exist? gem_build_complete_path
|
return if File.exist? gem_build_complete_path
|
||||||
return if !File.writable?(base_dir) &&
|
return if !File.writable?(base_dir)
|
||||||
!File.exist?(File.join(base_dir, 'extensions'))
|
return if !File.exist?(File.join(base_dir, 'extensions'))
|
||||||
|
|
||||||
begin
|
begin
|
||||||
# We need to require things in $LOAD_PATH without looking for the
|
# We need to require things in $LOAD_PATH without looking for the
|
||||||
|
@ -1477,13 +1498,12 @@ class Gem::Specification < Gem::BasicSpecification
|
||||||
|
|
||||||
def conflicts
|
def conflicts
|
||||||
conflicts = {}
|
conflicts = {}
|
||||||
Gem.loaded_specs.values.each do |spec|
|
self.runtime_dependencies.each { |dep|
|
||||||
bad = self.runtime_dependencies.find_all { |dep|
|
spec = Gem.loaded_specs[dep.name]
|
||||||
spec.name == dep.name and not spec.satisfies_requirement? dep
|
if spec and not spec.satisfies_requirement? dep
|
||||||
}
|
(conflicts[spec] ||= []) << dep
|
||||||
|
end
|
||||||
conflicts[spec] = bad unless bad.empty?
|
}
|
||||||
end
|
|
||||||
conflicts
|
conflicts
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1496,6 +1516,11 @@ class Gem::Specification < Gem::BasicSpecification
|
||||||
@date ||= TODAY
|
@date ||= TODAY
|
||||||
end
|
end
|
||||||
|
|
||||||
|
DateLike = Object.new # :nodoc:
|
||||||
|
def DateLike.===(obj) # :nodoc:
|
||||||
|
defined?(::Date) and Date === obj
|
||||||
|
end
|
||||||
|
|
||||||
DateTimeFormat = # :nodoc:
|
DateTimeFormat = # :nodoc:
|
||||||
/\A
|
/\A
|
||||||
(\d{4})-(\d{2})-(\d{2})
|
(\d{4})-(\d{2})-(\d{2})
|
||||||
|
@ -1525,7 +1550,7 @@ class Gem::Specification < Gem::BasicSpecification
|
||||||
raise(Gem::InvalidSpecificationException,
|
raise(Gem::InvalidSpecificationException,
|
||||||
"invalid date format in specification: #{date.inspect}")
|
"invalid date format in specification: #{date.inspect}")
|
||||||
end
|
end
|
||||||
when Time, Date then
|
when Time, DateLike then
|
||||||
Time.utc(date.year, date.month, date.day)
|
Time.utc(date.year, date.month, date.day)
|
||||||
else
|
else
|
||||||
TODAY
|
TODAY
|
||||||
|
@ -1779,7 +1804,7 @@ class Gem::Specification < Gem::BasicSpecification
|
||||||
##
|
##
|
||||||
# True if this gem has files in test_files
|
# True if this gem has files in test_files
|
||||||
|
|
||||||
def has_unit_tests?
|
def has_unit_tests? # :nodoc:
|
||||||
not test_files.empty?
|
not test_files.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1952,6 +1977,19 @@ class Gem::Specification < Gem::BasicSpecification
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Is this specification missing its extensions? When this returns true you
|
||||||
|
# probably want to build_extensions
|
||||||
|
|
||||||
|
def missing_extensions?
|
||||||
|
return false if default_gem?
|
||||||
|
return false if extensions.empty?
|
||||||
|
return false if installed_by_version < Gem::Version.new('2.2.0.preview.2')
|
||||||
|
return false if File.exist? gem_build_complete_path
|
||||||
|
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Normalize the list of files so that:
|
# Normalize the list of files so that:
|
||||||
# * All file lists have redundancies removed.
|
# * All file lists have redundancies removed.
|
||||||
|
@ -2035,35 +2073,35 @@ class Gem::Specification < Gem::BasicSpecification
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Raise an exception if the version of this spec conflicts with the one
|
||||||
|
# that is already loaded (+other+)
|
||||||
|
|
||||||
|
def check_version_conflict other # :nodoc:
|
||||||
|
return if self.version == other.version
|
||||||
|
|
||||||
|
# This gem is already loaded. If the currently loaded gem is not in the
|
||||||
|
# list of candidate gems, then we have a version conflict.
|
||||||
|
|
||||||
|
msg = "can't activate #{full_name}, already activated #{other.full_name}"
|
||||||
|
|
||||||
|
e = Gem::LoadError.new msg
|
||||||
|
e.name = self.name
|
||||||
|
# TODO: e.requirement = dep.requirement
|
||||||
|
|
||||||
|
raise e
|
||||||
|
end
|
||||||
|
|
||||||
|
private :check_version_conflict
|
||||||
|
|
||||||
##
|
##
|
||||||
# Check the spec for possible conflicts and freak out if there are any.
|
# Check the spec for possible conflicts and freak out if there are any.
|
||||||
|
|
||||||
def raise_if_conflicts
|
def raise_if_conflicts # :nodoc:
|
||||||
other = Gem.loaded_specs[self.name]
|
|
||||||
|
|
||||||
if other and self.version != other.version then
|
|
||||||
# This gem is already loaded. If the currently loaded gem is not in the
|
|
||||||
# list of candidate gems, then we have a version conflict.
|
|
||||||
|
|
||||||
msg = "can't activate #{full_name}, already activated #{other.full_name}"
|
|
||||||
|
|
||||||
e = Gem::LoadError.new msg
|
|
||||||
e.name = self.name
|
|
||||||
# TODO: e.requirement = dep.requirement
|
|
||||||
|
|
||||||
raise e
|
|
||||||
end
|
|
||||||
|
|
||||||
conf = self.conflicts
|
conf = self.conflicts
|
||||||
|
|
||||||
unless conf.empty? then
|
unless conf.empty? then
|
||||||
y = conf.map { |act,con|
|
raise Gem::ConflictError.new self, conf
|
||||||
"#{act.full_name} conflicts with #{con.join(", ")}"
|
|
||||||
}.join ", "
|
|
||||||
|
|
||||||
# TODO: improve message by saying who activated `con`
|
|
||||||
|
|
||||||
raise Gem::LoadError, "Unable to activate #{self.full_name}, because #{y}"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -2087,14 +2125,7 @@ class Gem::Specification < Gem::BasicSpecification
|
||||||
# Singular accessor for #require_paths
|
# Singular accessor for #require_paths
|
||||||
|
|
||||||
def require_path= path
|
def require_path= path
|
||||||
self.require_paths = [path]
|
self.require_paths = Array(path)
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# The RubyGems version required by this gem
|
|
||||||
|
|
||||||
def required_rubygems_version= req
|
|
||||||
@required_rubygems_version = Gem::Requirement.create req
|
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -2129,7 +2160,7 @@ class Gem::Specification < Gem::BasicSpecification
|
||||||
seg = obj.keys.sort.map { |k| "#{k.to_s.dump} => #{obj[k].to_s.dump}" }
|
seg = obj.keys.sort.map { |k| "#{k.to_s.dump} => #{obj[k].to_s.dump}" }
|
||||||
"{ #{seg.join(', ')} }"
|
"{ #{seg.join(', ')} }"
|
||||||
when Gem::Version then obj.to_s.dump
|
when Gem::Version then obj.to_s.dump
|
||||||
when Date then obj.strftime('%Y-%m-%d').dump
|
when DateLike then obj.strftime('%Y-%m-%d').dump
|
||||||
when Time then obj.strftime('%Y-%m-%d').dump
|
when Time then obj.strftime('%Y-%m-%d').dump
|
||||||
when Numeric then obj.inspect
|
when Numeric then obj.inspect
|
||||||
when true, false, nil then obj.inspect
|
when true, false, nil then obj.inspect
|
||||||
|
@ -2217,14 +2248,14 @@ class Gem::Specification < Gem::BasicSpecification
|
||||||
##
|
##
|
||||||
# Singular accessor for #test_files
|
# Singular accessor for #test_files
|
||||||
|
|
||||||
def test_file
|
def test_file # :nodoc:
|
||||||
val = test_files and val.first
|
val = test_files and val.first
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Singular mutator for #test_files
|
# Singular mutator for #test_files
|
||||||
|
|
||||||
def test_file= file
|
def test_file= file # :nodoc:
|
||||||
self.test_files = [file]
|
self.test_files = [file]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -2232,7 +2263,7 @@ class Gem::Specification < Gem::BasicSpecification
|
||||||
# Test files included in this gem. You cannot append to this accessor, you
|
# Test files included in this gem. You cannot append to this accessor, you
|
||||||
# must assign to it.
|
# must assign to it.
|
||||||
|
|
||||||
def test_files
|
def test_files # :nodoc:
|
||||||
# Handle the possibility that we have @test_suite_file but not
|
# Handle the possibility that we have @test_suite_file but not
|
||||||
# @test_files. This will happen when an old gem is loaded via
|
# @test_files. This will happen when an old gem is loaded via
|
||||||
# YAML.
|
# YAML.
|
||||||
|
@ -2256,7 +2287,7 @@ class Gem::Specification < Gem::BasicSpecification
|
||||||
mark_version
|
mark_version
|
||||||
result = []
|
result = []
|
||||||
result << "# -*- encoding: utf-8 -*-"
|
result << "# -*- encoding: utf-8 -*-"
|
||||||
result << "#{Gem::StubSpecification::PREFIX}#{name} #{version} #{platform} #{@require_paths.join("\0")}"
|
result << "#{Gem::StubSpecification::PREFIX}#{name} #{version} #{platform} #{raw_require_paths.join("\0")}"
|
||||||
result << "#{Gem::StubSpecification::PREFIX}#{extensions.join "\0"}" unless
|
result << "#{Gem::StubSpecification::PREFIX}#{extensions.join "\0"}" unless
|
||||||
extensions.empty?
|
extensions.empty?
|
||||||
result << nil
|
result << nil
|
||||||
|
@ -2273,7 +2304,7 @@ class Gem::Specification < Gem::BasicSpecification
|
||||||
if metadata and !metadata.empty?
|
if metadata and !metadata.empty?
|
||||||
result << " s.metadata = #{ruby_code metadata} if s.respond_to? :metadata="
|
result << " s.metadata = #{ruby_code metadata} if s.respond_to? :metadata="
|
||||||
end
|
end
|
||||||
result << " s.require_paths = #{ruby_code @require_paths}"
|
result << " s.require_paths = #{ruby_code raw_require_paths}"
|
||||||
|
|
||||||
handled = [
|
handled = [
|
||||||
:dependencies,
|
:dependencies,
|
||||||
|
@ -2443,7 +2474,7 @@ class Gem::Specification < Gem::BasicSpecification
|
||||||
"invalid value for attribute name: \"#{name.inspect}\""
|
"invalid value for attribute name: \"#{name.inspect}\""
|
||||||
end
|
end
|
||||||
|
|
||||||
if @require_paths.empty? then
|
if raw_require_paths.empty? then
|
||||||
raise Gem::InvalidSpecificationException,
|
raise Gem::InvalidSpecificationException,
|
||||||
'specification must have at least one require_path'
|
'specification must have at least one require_path'
|
||||||
end
|
end
|
||||||
|
@ -2627,7 +2658,8 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
|
||||||
dep.requirement.requirements.any? do |op, version|
|
dep.requirement.requirements.any? do |op, version|
|
||||||
op == '~>' and
|
op == '~>' and
|
||||||
not version.prerelease? and
|
not version.prerelease? and
|
||||||
version.segments.length > 2
|
version.segments.length > 2 and
|
||||||
|
version.segments.first != 0
|
||||||
end
|
end
|
||||||
|
|
||||||
if overly_strict then
|
if overly_strict then
|
||||||
|
|
|
@ -120,6 +120,13 @@ class Gem::StubSpecification < Gem::BasicSpecification
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def missing_extensions?
|
||||||
|
return false if default_gem?
|
||||||
|
return false if extensions.empty?
|
||||||
|
|
||||||
|
to_spec.missing_extensions?
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Name of the gem
|
# Name of the gem
|
||||||
|
|
||||||
|
@ -147,7 +154,14 @@ class Gem::StubSpecification < Gem::BasicSpecification
|
||||||
# The full Gem::Specification for this gem, loaded from evalling its gemspec
|
# The full Gem::Specification for this gem, loaded from evalling its gemspec
|
||||||
|
|
||||||
def to_spec
|
def to_spec
|
||||||
|
@spec ||= Gem.loaded_specs.values.find { |spec|
|
||||||
|
spec.name == @name and spec.version == @version
|
||||||
|
}
|
||||||
|
|
||||||
@spec ||= Gem::Specification.load(loaded_from)
|
@spec ||= Gem::Specification.load(loaded_from)
|
||||||
|
@spec.ignored = @ignored if instance_variable_defined? :@ignored
|
||||||
|
|
||||||
|
@spec
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
|
|
@ -218,8 +218,11 @@ class Gem::TestCase < MiniTest::Unit::TestCase
|
||||||
def setup
|
def setup
|
||||||
super
|
super
|
||||||
|
|
||||||
@orig_gem_home = ENV['GEM_HOME']
|
@orig_gem_home = ENV['GEM_HOME']
|
||||||
@orig_gem_path = ENV['GEM_PATH']
|
@orig_gem_path = ENV['GEM_PATH']
|
||||||
|
@orig_gem_vendor = ENV['GEM_VENDOR']
|
||||||
|
|
||||||
|
ENV['GEM_VENDOR'] = nil
|
||||||
|
|
||||||
@current_dir = Dir.pwd
|
@current_dir = Dir.pwd
|
||||||
@fetcher = nil
|
@fetcher = nil
|
||||||
|
@ -347,8 +350,9 @@ class Gem::TestCase < MiniTest::Unit::TestCase
|
||||||
|
|
||||||
FileUtils.rm_rf @tempdir unless ENV['KEEP_FILES']
|
FileUtils.rm_rf @tempdir unless ENV['KEEP_FILES']
|
||||||
|
|
||||||
ENV['GEM_HOME'] = @orig_gem_home
|
ENV['GEM_HOME'] = @orig_gem_home
|
||||||
ENV['GEM_PATH'] = @orig_gem_path
|
ENV['GEM_PATH'] = @orig_gem_path
|
||||||
|
ENV['GEM_VENDOR'] = @orig_gem_vendor
|
||||||
|
|
||||||
Gem.ruby = @orig_ruby if @orig_ruby
|
Gem.ruby = @orig_ruby if @orig_ruby
|
||||||
|
|
||||||
|
@ -1263,7 +1267,7 @@ Also, a list:
|
||||||
# The StaticSet is a static set of gem specifications used for testing only.
|
# The StaticSet is a static set of gem specifications used for testing only.
|
||||||
# It is available by requiring Gem::TestCase.
|
# It is available by requiring Gem::TestCase.
|
||||||
|
|
||||||
class StaticSet
|
class StaticSet < Gem::Resolver::Set
|
||||||
|
|
||||||
##
|
##
|
||||||
# A StaticSet ignores remote because it has a fixed set of gems.
|
# A StaticSet ignores remote because it has a fixed set of gems.
|
||||||
|
@ -1274,6 +1278,8 @@ Also, a list:
|
||||||
# Creates a new StaticSet for the given +specs+
|
# Creates a new StaticSet for the given +specs+
|
||||||
|
|
||||||
def initialize(specs)
|
def initialize(specs)
|
||||||
|
super()
|
||||||
|
|
||||||
@specs = specs
|
@specs = specs
|
||||||
|
|
||||||
@remote = true
|
@remote = true
|
||||||
|
@ -1299,7 +1305,7 @@ Also, a list:
|
||||||
# Finds all gems matching +dep+ in this set.
|
# Finds all gems matching +dep+ in this set.
|
||||||
|
|
||||||
def find_all(dep)
|
def find_all(dep)
|
||||||
@specs.find_all { |s| dep.matches_spec? s }
|
@specs.find_all { |s| dep.match? s, @prerelease }
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
|
|
@ -38,6 +38,8 @@ class Gem::FakeFetcher
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_data(path)
|
def find_data(path)
|
||||||
|
return File.read path.path if URI === path and 'file' == path.scheme
|
||||||
|
|
||||||
if URI === path and "URI::#{path.scheme.upcase}" != path.class.name then
|
if URI === path and "URI::#{path.scheme.upcase}" != path.class.name then
|
||||||
raise ArgumentError,
|
raise ArgumentError,
|
||||||
"mismatch for scheme #{path.scheme} and class #{path.class}"
|
"mismatch for scheme #{path.scheme} and class #{path.class}"
|
||||||
|
|
|
@ -26,6 +26,16 @@ module Gem::Text
|
||||||
result.join("\n").gsub(/^/, " " * indent)
|
result.join("\n").gsub(/^/, " " * indent)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def min3 a, b, c # :nodoc:
|
||||||
|
if a < b && a < c
|
||||||
|
a
|
||||||
|
elsif b < a && b < c
|
||||||
|
b
|
||||||
|
else
|
||||||
|
c
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# This code is based directly on the Text gem implementation
|
# This code is based directly on the Text gem implementation
|
||||||
# Returns a value representing the "cost" of transforming str1 into str2
|
# Returns a value representing the "cost" of transforming str1 into str2
|
||||||
def levenshtein_distance str1, str2
|
def levenshtein_distance str1, str2
|
||||||
|
@ -42,16 +52,16 @@ module Gem::Text
|
||||||
d = (0..m).to_a
|
d = (0..m).to_a
|
||||||
x = nil
|
x = nil
|
||||||
|
|
||||||
n.times do |i|
|
str1.each_char.each_with_index do |char1,i|
|
||||||
e = i+1
|
e = i+1
|
||||||
|
|
||||||
m.times do |j|
|
str2.each_char.each_with_index do |char2,j|
|
||||||
cost = (s[i] == t[j]) ? 0 : 1
|
cost = (char1 == char2) ? 0 : 1
|
||||||
x = [
|
x = min3(
|
||||||
d[j+1] + 1, # insertion
|
d[j+1] + 1, # insertion
|
||||||
e + 1, # deletion
|
e + 1, # deletion
|
||||||
d[j] + cost # substitution
|
d[j] + cost # substitution
|
||||||
].min
|
)
|
||||||
d[j] = e
|
d[j] = e
|
||||||
e = x
|
e = x
|
||||||
end
|
end
|
||||||
|
|
|
@ -96,6 +96,8 @@ class Gem::Uninstaller
|
||||||
(@user_install and spec.base_dir == Gem.user_dir)
|
(@user_install and spec.base_dir == Gem.user_dir)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
list.sort!
|
||||||
|
|
||||||
if list.empty? then
|
if list.empty? then
|
||||||
if other_repo_specs.empty?
|
if other_repo_specs.empty?
|
||||||
if default_specs.empty?
|
if default_specs.empty?
|
||||||
|
@ -120,7 +122,8 @@ class Gem::Uninstaller
|
||||||
remove_all list
|
remove_all list
|
||||||
|
|
||||||
elsif list.size > 1 then
|
elsif list.size > 1 then
|
||||||
gem_names = list.collect {|gem| gem.full_name} + ["All versions"]
|
gem_names = list.map { |gem| gem.full_name }
|
||||||
|
gem_names << "All versions"
|
||||||
|
|
||||||
say
|
say
|
||||||
_, index = choose_from_list "Select gem to uninstall:", gem_names
|
_, index = choose_from_list "Select gem to uninstall:", gem_names
|
||||||
|
|
|
@ -157,6 +157,14 @@ module Gem::UserInteraction
|
||||||
def terminate_interaction exit_code = 0
|
def terminate_interaction exit_code = 0
|
||||||
ui.terminate_interaction exit_code
|
ui.terminate_interaction exit_code
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Calls +say+ with +msg+ or the results of the block if really_verbose
|
||||||
|
# is true.
|
||||||
|
|
||||||
|
def verbose msg = nil
|
||||||
|
say(msg || yield) if Gem.configuration.really_verbose
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
|
|
@ -143,6 +143,10 @@
|
||||||
# "~> 3.0.0" 3.0.0 ... 3.1
|
# "~> 3.0.0" 3.0.0 ... 3.1
|
||||||
# "~> 3.5" 3.5 ... 4.0
|
# "~> 3.5" 3.5 ... 4.0
|
||||||
# "~> 3.5.0" 3.5.0 ... 3.6
|
# "~> 3.5.0" 3.5.0 ... 3.6
|
||||||
|
# "~> 3" 3.0 ... 4.0
|
||||||
|
#
|
||||||
|
# For the last example, single-digit versions are automatically extended with
|
||||||
|
# a zero to give a sensible result.
|
||||||
|
|
||||||
class Gem::Version
|
class Gem::Version
|
||||||
autoload :Requirement, 'rubygems/requirement'
|
autoload :Requirement, 'rubygems/requirement'
|
||||||
|
@ -189,7 +193,7 @@ class Gem::Version
|
||||||
@@all = {}
|
@@all = {}
|
||||||
|
|
||||||
def self.new version # :nodoc:
|
def self.new version # :nodoc:
|
||||||
return super unless Gem::VERSION == self.class
|
return super unless Gem::Version == self
|
||||||
|
|
||||||
@@all[version] ||= super
|
@@all[version] ||= super
|
||||||
end
|
end
|
||||||
|
|
|
@ -75,6 +75,21 @@ class TestGem < Gem::TestCase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_self_install
|
||||||
|
spec_fetcher do |f|
|
||||||
|
f.gem 'a', 1
|
||||||
|
f.spec 'a', 2
|
||||||
|
end
|
||||||
|
|
||||||
|
gemhome2 = "#{@gemhome}2"
|
||||||
|
|
||||||
|
installed = Gem.install 'a', '= 1', :install_dir => gemhome2
|
||||||
|
|
||||||
|
assert_equal %w[a-1], installed.map { |spec| spec.full_name }
|
||||||
|
|
||||||
|
assert_path_exists File.join(gemhome2, 'gems', 'a-1')
|
||||||
|
end
|
||||||
|
|
||||||
def test_require_missing
|
def test_require_missing
|
||||||
save_loaded_features do
|
save_loaded_features do
|
||||||
assert_raises ::LoadError do
|
assert_raises ::LoadError do
|
||||||
|
@ -216,6 +231,58 @@ class TestGem < Gem::TestCase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_default_path
|
||||||
|
orig_vendordir = RbConfig::CONFIG['vendordir']
|
||||||
|
RbConfig::CONFIG['vendordir'] = File.join @tempdir, 'vendor'
|
||||||
|
|
||||||
|
FileUtils.rm_rf Gem.user_home
|
||||||
|
|
||||||
|
expected = [Gem.default_dir]
|
||||||
|
|
||||||
|
assert_equal expected, Gem.default_path
|
||||||
|
ensure
|
||||||
|
RbConfig::CONFIG['vendordir'] = orig_vendordir
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_default_path_missing_vendor
|
||||||
|
orig_vendordir = RbConfig::CONFIG['vendordir']
|
||||||
|
RbConfig::CONFIG.delete 'vendordir'
|
||||||
|
|
||||||
|
FileUtils.rm_rf Gem.user_home
|
||||||
|
|
||||||
|
expected = [Gem.default_dir]
|
||||||
|
|
||||||
|
assert_equal expected, Gem.default_path
|
||||||
|
ensure
|
||||||
|
RbConfig::CONFIG['vendordir'] = orig_vendordir
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_default_path_user_home
|
||||||
|
orig_vendordir = RbConfig::CONFIG['vendordir']
|
||||||
|
RbConfig::CONFIG['vendordir'] = File.join @tempdir, 'vendor'
|
||||||
|
|
||||||
|
expected = [Gem.user_dir, Gem.default_dir]
|
||||||
|
|
||||||
|
assert_equal expected, Gem.default_path
|
||||||
|
ensure
|
||||||
|
RbConfig::CONFIG['vendordir'] = orig_vendordir
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_default_path_vendor_dir
|
||||||
|
orig_vendordir = RbConfig::CONFIG['vendordir']
|
||||||
|
RbConfig::CONFIG['vendordir'] = File.join @tempdir, 'vendor'
|
||||||
|
|
||||||
|
FileUtils.mkdir_p Gem.vendor_dir
|
||||||
|
|
||||||
|
FileUtils.rm_rf Gem.user_home
|
||||||
|
|
||||||
|
expected = [Gem.default_dir, Gem.vendor_dir]
|
||||||
|
|
||||||
|
assert_equal expected, Gem.default_path
|
||||||
|
ensure
|
||||||
|
RbConfig::CONFIG['vendordir'] = orig_vendordir
|
||||||
|
end
|
||||||
|
|
||||||
def test_self_default_sources
|
def test_self_default_sources
|
||||||
assert_equal %w[https://rubygems.org/], Gem.default_sources
|
assert_equal %w[https://rubygems.org/], Gem.default_sources
|
||||||
end
|
end
|
||||||
|
@ -816,6 +883,23 @@ class TestGem < Gem::TestCase
|
||||||
assert_match %r%Could not find 'b' %, e.message
|
assert_match %r%Could not find 'b' %, e.message
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_self_try_activate_missing_extensions
|
||||||
|
util_spec 'ext', '1' do |s|
|
||||||
|
s.extensions = %w[ext/extconf.rb]
|
||||||
|
s.mark_version
|
||||||
|
s.installed_by_version = v('2.2')
|
||||||
|
end
|
||||||
|
|
||||||
|
_, err = capture_io do
|
||||||
|
refute Gem.try_activate 'nonexistent'
|
||||||
|
end
|
||||||
|
|
||||||
|
expected = "Ignoring ext-1 because its extensions are not built. " +
|
||||||
|
"Try: gem pristine ext-1\n"
|
||||||
|
|
||||||
|
assert_equal expected, err
|
||||||
|
end
|
||||||
|
|
||||||
def test_self_use_paths
|
def test_self_use_paths
|
||||||
util_ensure_gem_dirs
|
util_ensure_gem_dirs
|
||||||
|
|
||||||
|
@ -951,6 +1035,30 @@ class TestGem < Gem::TestCase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_self_vendor_dir
|
||||||
|
expected =
|
||||||
|
File.join RbConfig::CONFIG['vendordir'], 'gems',
|
||||||
|
RbConfig::CONFIG['ruby_version']
|
||||||
|
|
||||||
|
assert_equal expected, Gem.vendor_dir
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_self_vendor_dir_ENV_GEM_VENDOR
|
||||||
|
ENV['GEM_VENDOR'] = File.join @tempdir, 'vendor', 'gems'
|
||||||
|
|
||||||
|
assert_equal ENV['GEM_VENDOR'], Gem.vendor_dir
|
||||||
|
refute Gem.vendor_dir.frozen?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_self_vendor_dir_missing
|
||||||
|
orig_vendordir = RbConfig::CONFIG['vendordir']
|
||||||
|
RbConfig::CONFIG.delete 'vendordir'
|
||||||
|
|
||||||
|
assert_nil Gem.vendor_dir
|
||||||
|
ensure
|
||||||
|
RbConfig::CONFIG['vendordir'] = orig_vendordir
|
||||||
|
end
|
||||||
|
|
||||||
def test_load_plugins
|
def test_load_plugins
|
||||||
skip 'Insecure operation - chdir' if RUBY_VERSION <= "1.8.7"
|
skip 'Insecure operation - chdir' if RUBY_VERSION <= "1.8.7"
|
||||||
plugin_path = File.join "lib", "rubygems_plugin.rb"
|
plugin_path = File.join "lib", "rubygems_plugin.rb"
|
||||||
|
@ -1251,13 +1359,28 @@ class TestGem < Gem::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_use_gemdeps
|
def test_use_gemdeps
|
||||||
|
gem_deps_file = 'gem.deps.rb'.untaint
|
||||||
|
spec = util_spec 'a', 1
|
||||||
|
|
||||||
|
refute spec.activated?
|
||||||
|
|
||||||
|
open gem_deps_file, 'w' do |io|
|
||||||
|
io.write 'gem "a"'
|
||||||
|
end
|
||||||
|
|
||||||
|
Gem.use_gemdeps gem_deps_file
|
||||||
|
|
||||||
|
assert spec.activated?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_use_gemdeps_ENV
|
||||||
rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], nil
|
rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], nil
|
||||||
|
|
||||||
spec = util_spec 'a', 1
|
spec = util_spec 'a', 1
|
||||||
|
|
||||||
refute spec.activated?
|
refute spec.activated?
|
||||||
|
|
||||||
open 'Gemfile', 'w' do |io|
|
open 'gem.deps.rb', 'w' do |io|
|
||||||
io.write 'gem "a"'
|
io.write 'gem "a"'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1268,6 +1391,29 @@ class TestGem < Gem::TestCase
|
||||||
ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
|
ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_use_gemdeps_argument_missing
|
||||||
|
e = assert_raises ArgumentError do
|
||||||
|
Gem.use_gemdeps 'gem.deps.rb'
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_equal 'Unable to find gem dependencies file at gem.deps.rb',
|
||||||
|
e.message
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_use_gemdeps_argument_missing_match_ENV
|
||||||
|
rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] =
|
||||||
|
ENV['RUBYGEMS_GEMDEPS'], 'gem.deps.rb'
|
||||||
|
|
||||||
|
e = assert_raises ArgumentError do
|
||||||
|
Gem.use_gemdeps 'gem.deps.rb'
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_equal 'Unable to find gem dependencies file at gem.deps.rb',
|
||||||
|
e.message
|
||||||
|
ensure
|
||||||
|
ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
|
||||||
|
end
|
||||||
|
|
||||||
def test_use_gemdeps_automatic
|
def test_use_gemdeps_automatic
|
||||||
skip 'Insecure operation - chdir' if RUBY_VERSION <= "1.8.7"
|
skip 'Insecure operation - chdir' if RUBY_VERSION <= "1.8.7"
|
||||||
rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-'
|
rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-'
|
||||||
|
@ -1287,6 +1433,17 @@ class TestGem < Gem::TestCase
|
||||||
ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
|
ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_use_gemdeps_automatic_missing
|
||||||
|
skip 'Insecure operation - chdir' if RUBY_VERSION <= "1.8.7"
|
||||||
|
rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-'
|
||||||
|
|
||||||
|
Gem.use_gemdeps
|
||||||
|
|
||||||
|
assert true # count
|
||||||
|
ensure
|
||||||
|
ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
|
||||||
|
end
|
||||||
|
|
||||||
def test_use_gemdeps_disabled
|
def test_use_gemdeps_disabled
|
||||||
rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], ''
|
rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], ''
|
||||||
|
|
||||||
|
@ -1294,7 +1451,7 @@ class TestGem < Gem::TestCase
|
||||||
|
|
||||||
refute spec.activated?
|
refute spec.activated?
|
||||||
|
|
||||||
open 'Gemfile', 'w' do |io|
|
open 'gem.deps.rb', 'w' do |io|
|
||||||
io.write 'gem "a"'
|
io.write 'gem "a"'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1305,6 +1462,27 @@ class TestGem < Gem::TestCase
|
||||||
ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
|
ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_use_gemdeps_missing_gem
|
||||||
|
skip 'Insecure operation - read' if RUBY_VERSION <= "1.8.7"
|
||||||
|
rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], 'x'
|
||||||
|
|
||||||
|
open 'x', 'w' do |io|
|
||||||
|
io.write 'gem "a"'
|
||||||
|
end
|
||||||
|
|
||||||
|
expected = <<-EXPECTED
|
||||||
|
Unable to resolve dependency: user requested 'a (>= 0)'
|
||||||
|
You may need to `gem install -g` to install missing gems
|
||||||
|
|
||||||
|
EXPECTED
|
||||||
|
|
||||||
|
assert_output nil, expected do
|
||||||
|
Gem.use_gemdeps
|
||||||
|
end
|
||||||
|
ensure
|
||||||
|
ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
|
||||||
|
end
|
||||||
|
|
||||||
def test_use_gemdeps_specific
|
def test_use_gemdeps_specific
|
||||||
skip 'Insecure operation - read' if RUBY_VERSION <= "1.8.7"
|
skip 'Insecure operation - read' if RUBY_VERSION <= "1.8.7"
|
||||||
rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], 'x'
|
rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], 'x'
|
||||||
|
|
|
@ -3,6 +3,7 @@ require 'rubygems/available_set'
|
||||||
require 'rubygems/security'
|
require 'rubygems/security'
|
||||||
|
|
||||||
class TestGemAvailableSet < Gem::TestCase
|
class TestGemAvailableSet < Gem::TestCase
|
||||||
|
|
||||||
def setup
|
def setup
|
||||||
super
|
super
|
||||||
|
|
||||||
|
@ -23,22 +24,24 @@ class TestGemAvailableSet < Gem::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_find_all
|
def test_find_all
|
||||||
a1, a1_gem = util_gem 'a', 1
|
a1, a1_gem = util_gem 'a', 1
|
||||||
|
a1a, a1a_gem = util_gem 'a', '1.a'
|
||||||
|
|
||||||
source = Gem::Source::SpecificFile.new a1_gem
|
a1_source = Gem::Source::SpecificFile.new a1_gem
|
||||||
|
a1a_source = Gem::Source::SpecificFile.new a1a_gem
|
||||||
|
|
||||||
set = Gem::AvailableSet.new
|
set = Gem::AvailableSet.new
|
||||||
set.add a1, source
|
set.add a1, a1_source
|
||||||
|
set.add a1a, a1a_source
|
||||||
|
|
||||||
dep = Gem::Resolver::DependencyRequest.new dep('a'), nil
|
dep = Gem::Resolver::DependencyRequest.new dep('a'), nil
|
||||||
|
|
||||||
specs = set.find_all dep
|
assert_equal %w[a-1], set.find_all(dep).map { |spec| spec.full_name }
|
||||||
|
|
||||||
spec = specs.first
|
dep = Gem::Resolver::DependencyRequest.new dep('a', '>= 0.a'), nil
|
||||||
|
|
||||||
assert_kind_of Gem::Resolver::LocalSpecification, spec
|
assert_equal %w[a-1 a-1.a],
|
||||||
|
set.find_all(dep).map { |spec| spec.full_name }.sort
|
||||||
assert_equal 'a-1', spec.full_name
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_match_platform
|
def test_match_platform
|
||||||
|
|
|
@ -184,5 +184,60 @@ class TestGemCommand < Gem::TestCase
|
||||||
assert_equal ['-h', 'command'], args
|
assert_equal ['-h', 'command'], args
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_show_lookup_failure_suggestions_local
|
||||||
|
correct = "non_existent_with_hint"
|
||||||
|
misspelled = "nonexistent_with_hint"
|
||||||
|
|
||||||
|
spec_fetcher do |fetcher|
|
||||||
|
fetcher.spec correct, 2
|
||||||
|
end
|
||||||
|
|
||||||
|
use_ui @ui do
|
||||||
|
@cmd.show_lookup_failure misspelled, Gem::Requirement.default, [], :local
|
||||||
|
end
|
||||||
|
|
||||||
|
expected = <<-EXPECTED
|
||||||
|
ERROR: Could not find a valid gem 'nonexistent_with_hint' (>= 0) in any repository
|
||||||
|
EXPECTED
|
||||||
|
|
||||||
|
assert_equal expected, @ui.error
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_show_lookup_failure_suggestions_none
|
||||||
|
spec_fetcher do |fetcher|
|
||||||
|
fetcher.spec 'correct', 2
|
||||||
|
end
|
||||||
|
|
||||||
|
use_ui @ui do
|
||||||
|
@cmd.show_lookup_failure 'other', Gem::Requirement.default, [], :remote
|
||||||
|
end
|
||||||
|
|
||||||
|
expected = <<-EXPECTED
|
||||||
|
ERROR: Could not find a valid gem 'other' (>= 0) in any repository
|
||||||
|
EXPECTED
|
||||||
|
|
||||||
|
assert_equal expected, @ui.error
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_show_lookup_failure_suggestions_remote
|
||||||
|
correct = "non_existent_with_hint"
|
||||||
|
misspelled = "nonexistent_with_hint"
|
||||||
|
|
||||||
|
spec_fetcher do |fetcher|
|
||||||
|
fetcher.spec correct, 2
|
||||||
|
end
|
||||||
|
|
||||||
|
use_ui @ui do
|
||||||
|
@cmd.show_lookup_failure misspelled, Gem::Requirement.default, [], :remote
|
||||||
|
end
|
||||||
|
|
||||||
|
expected = <<-EXPECTED
|
||||||
|
ERROR: Could not find a valid gem 'nonexistent_with_hint' (>= 0) in any repository
|
||||||
|
ERROR: Possible alternatives: non_existent_with_hint
|
||||||
|
EXPECTED
|
||||||
|
|
||||||
|
assert_equal expected, @ui.error
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -179,6 +179,7 @@ Added '/CN=alternate/DC=example'
|
||||||
assert_empty @ui.error
|
assert_empty @ui.error
|
||||||
|
|
||||||
assert_path_exists File.join(@tempdir, 'gem-public_cert.pem')
|
assert_path_exists File.join(@tempdir, 'gem-public_cert.pem')
|
||||||
|
refute_path_exists File.join(@tempdir, 'gem-private_key.pem')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_execute_build_encrypted_key
|
def test_execute_build_encrypted_key
|
||||||
|
|
|
@ -9,8 +9,8 @@ class TestGemCommandsContentsCommand < Gem::TestCase
|
||||||
@cmd = Gem::Commands::ContentsCommand.new
|
@cmd = Gem::Commands::ContentsCommand.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def gem name
|
def gem name, version = 2
|
||||||
spec = quick_gem name do |gem|
|
spec = quick_gem name, version do |gem|
|
||||||
gem.files = %W[lib/#{name}.rb Rakefile]
|
gem.files = %W[lib/#{name}.rb Rakefile]
|
||||||
end
|
end
|
||||||
write_file File.join(*%W[gems #{spec.full_name} lib #{name}.rb])
|
write_file File.join(*%W[gems #{spec.full_name} lib #{name}.rb])
|
||||||
|
@ -135,6 +135,40 @@ class TestGemCommandsContentsCommand < Gem::TestCase
|
||||||
assert_equal "", @ui.error
|
assert_equal "", @ui.error
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_execute_show_install_dir
|
||||||
|
@cmd.options[:args] = %w[foo]
|
||||||
|
@cmd.options[:show_install_dir] = true
|
||||||
|
|
||||||
|
gem 'foo'
|
||||||
|
|
||||||
|
use_ui @ui do
|
||||||
|
@cmd.execute
|
||||||
|
end
|
||||||
|
|
||||||
|
expected = File.join @gemhome, 'gems', 'foo-2'
|
||||||
|
|
||||||
|
assert_equal "#{expected}\n", @ui.output
|
||||||
|
assert_equal "", @ui.error
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_execute_show_install_dir_version
|
||||||
|
@cmd.options[:args] = %w[foo]
|
||||||
|
@cmd.options[:show_install_dir] = true
|
||||||
|
@cmd.options[:version] = Gem::Requirement.new '= 1'
|
||||||
|
|
||||||
|
gem 'foo', 1
|
||||||
|
gem 'foo', 2
|
||||||
|
|
||||||
|
use_ui @ui do
|
||||||
|
@cmd.execute
|
||||||
|
end
|
||||||
|
|
||||||
|
expected = File.join @gemhome, 'gems', 'foo-1'
|
||||||
|
|
||||||
|
assert_equal "#{expected}\n", @ui.output
|
||||||
|
assert_equal "", @ui.error
|
||||||
|
end
|
||||||
|
|
||||||
def test_execute_no_prefix
|
def test_execute_no_prefix
|
||||||
@cmd.options[:args] = %w[foo]
|
@cmd.options[:args] = %w[foo]
|
||||||
@cmd.options[:prefix] = false
|
@cmd.options[:prefix] = false
|
||||||
|
@ -183,13 +217,22 @@ lib/foo.rb
|
||||||
assert @cmd.options[:prefix]
|
assert @cmd.options[:prefix]
|
||||||
assert_empty @cmd.options[:specdirs]
|
assert_empty @cmd.options[:specdirs]
|
||||||
assert_nil @cmd.options[:version]
|
assert_nil @cmd.options[:version]
|
||||||
|
refute @cmd.options[:show_install_dir]
|
||||||
|
|
||||||
@cmd.send :handle_options, %w[-l -s foo --version 0.0.2 --no-prefix]
|
@cmd.send :handle_options, %w[
|
||||||
|
-l
|
||||||
|
-s
|
||||||
|
foo
|
||||||
|
--version 0.0.2
|
||||||
|
--no-prefix
|
||||||
|
--show-install-dir
|
||||||
|
]
|
||||||
|
|
||||||
assert @cmd.options[:lib_only]
|
assert @cmd.options[:lib_only]
|
||||||
refute @cmd.options[:prefix]
|
refute @cmd.options[:prefix]
|
||||||
assert_equal %w[foo], @cmd.options[:specdirs]
|
assert_equal %w[foo], @cmd.options[:specdirs]
|
||||||
assert_equal Gem::Requirement.new('0.0.2'), @cmd.options[:version]
|
assert_equal Gem::Requirement.new('0.0.2'), @cmd.options[:version]
|
||||||
|
assert @cmd.options[:show_install_dir]
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -28,6 +28,7 @@ class TestGemCommandsEnvironmentCommand < Gem::TestCase
|
||||||
assert_match %r|RUBYGEMS PREFIX: |, @ui.output
|
assert_match %r|RUBYGEMS PREFIX: |, @ui.output
|
||||||
assert_match %r|RUBY EXECUTABLE:.*#{RbConfig::CONFIG['ruby_install_name']}|,
|
assert_match %r|RUBY EXECUTABLE:.*#{RbConfig::CONFIG['ruby_install_name']}|,
|
||||||
@ui.output
|
@ui.output
|
||||||
|
assert_match %r|SYSTEM CONFIGURATION DIRECTORY:|, @ui.output
|
||||||
assert_match %r|EXECUTABLE DIRECTORY:|, @ui.output
|
assert_match %r|EXECUTABLE DIRECTORY:|, @ui.output
|
||||||
assert_match %r|RUBYGEMS PLATFORMS:|, @ui.output
|
assert_match %r|RUBYGEMS PLATFORMS:|, @ui.output
|
||||||
assert_match %r|- #{Gem::Platform.local}|, @ui.output
|
assert_match %r|- #{Gem::Platform.local}|, @ui.output
|
||||||
|
|
|
@ -22,6 +22,13 @@ class TestGemCommandsHelpCommand < Gem::TestCase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_gem_help_gem_dependencies
|
||||||
|
util_gem 'gem_dependencies' do |out, err|
|
||||||
|
assert_match 'gem.deps.rb', out
|
||||||
|
assert_equal '', err
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def test_gem_help_platforms
|
def test_gem_help_platforms
|
||||||
util_gem 'platforms' do |out, err|
|
util_gem 'platforms' do |out, err|
|
||||||
assert_match(/x86-freebsd/, out)
|
assert_match(/x86-freebsd/, out)
|
||||||
|
|
|
@ -24,6 +24,7 @@ class TestGemCommandsInstallCommand < Gem::TestCase
|
||||||
|
|
||||||
Gem::Command.build_args = @orig_args
|
Gem::Command.build_args = @orig_args
|
||||||
File.unlink @gemdeps if File.file? @gemdeps
|
File.unlink @gemdeps if File.file? @gemdeps
|
||||||
|
File.unlink "#{@gemdeps}.lock" if File.file? "#{@gemdeps}.lock"
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_execute_exclude_prerelease
|
def test_execute_exclude_prerelease
|
||||||
|
@ -194,6 +195,32 @@ class TestGemCommandsInstallCommand < Gem::TestCase
|
||||||
assert_match(%r!Unable to download data from http://not-there.nothing!, errs.shift)
|
assert_match(%r!Unable to download data from http://not-there.nothing!, errs.shift)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_execute_nonexistent_hint_disabled
|
||||||
|
misspelled = "nonexistent_with_hint"
|
||||||
|
correctly_spelled = "non_existent_with_hint"
|
||||||
|
|
||||||
|
spec_fetcher do |fetcher|
|
||||||
|
fetcher.spec correctly_spelled, 2
|
||||||
|
end
|
||||||
|
|
||||||
|
@cmd.options[:args] = [misspelled]
|
||||||
|
@cmd.options[:suggest_alternate] = false
|
||||||
|
|
||||||
|
use_ui @ui do
|
||||||
|
e = assert_raises Gem::MockGemUi::TermError do
|
||||||
|
@cmd.execute
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_equal 2, e.exit_code
|
||||||
|
end
|
||||||
|
|
||||||
|
expected = <<-EXPECTED
|
||||||
|
ERROR: Could not find a valid gem 'nonexistent_with_hint' (>= 0) in any repository
|
||||||
|
EXPECTED
|
||||||
|
|
||||||
|
assert_equal expected, @ui.error
|
||||||
|
end
|
||||||
|
|
||||||
def test_execute_nonexistent_with_hint
|
def test_execute_nonexistent_with_hint
|
||||||
misspelled = "nonexistent_with_hint"
|
misspelled = "nonexistent_with_hint"
|
||||||
correctly_spelled = "non_existent_with_hint"
|
correctly_spelled = "non_existent_with_hint"
|
||||||
|
@ -238,7 +265,10 @@ ERROR: Possible alternatives: non_existent_with_hint
|
||||||
assert_equal 2, e.exit_code
|
assert_equal 2, e.exit_code
|
||||||
end
|
end
|
||||||
|
|
||||||
expected = ["ERROR: Could not find a valid gem 'non-existent_with-hint' (>= 0) in any repository", "ERROR: Possible alternatives: nonexistent-with_hint"]
|
expected = [
|
||||||
|
"ERROR: Could not find a valid gem 'non-existent_with-hint' (>= 0) in any repository",
|
||||||
|
"ERROR: Possible alternatives: nonexistent-with_hint"
|
||||||
|
]
|
||||||
|
|
||||||
output = @ui.error.split "\n"
|
output = @ui.error.split "\n"
|
||||||
|
|
||||||
|
@ -535,6 +565,11 @@ ERROR: Possible alternatives: non_existent_with_hint
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_install_gem_ignore_dependencies_both
|
def test_install_gem_ignore_dependencies_both
|
||||||
|
done_installing = false
|
||||||
|
Gem.done_installing do
|
||||||
|
done_installing = true
|
||||||
|
end
|
||||||
|
|
||||||
spec = quick_spec 'a', 2
|
spec = quick_spec 'a', 2
|
||||||
|
|
||||||
util_build_gem spec
|
util_build_gem spec
|
||||||
|
@ -546,6 +581,8 @@ ERROR: Possible alternatives: non_existent_with_hint
|
||||||
@cmd.install_gem 'a', '>= 0'
|
@cmd.install_gem 'a', '>= 0'
|
||||||
|
|
||||||
assert_equal %w[a-2], @cmd.installed_specs.map { |s| s.full_name }
|
assert_equal %w[a-2], @cmd.installed_specs.map { |s| s.full_name }
|
||||||
|
|
||||||
|
assert done_installing, 'documentation was not generated'
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_install_gem_ignore_dependencies_remote
|
def test_install_gem_ignore_dependencies_remote
|
||||||
|
@ -622,8 +659,8 @@ ERROR: Possible alternatives: non_existent_with_hint
|
||||||
end
|
end
|
||||||
|
|
||||||
assert_equal 2, e.exit_code
|
assert_equal 2, e.exit_code
|
||||||
assert_match %r!Could not find a valid gem 'blah' \(>= 0\)!, @ui.error
|
|
||||||
assert_match %r!Unable to download data from http://not-there\.nothing!, @ui.error
|
assert_match 'Unable to download data', @ui.error
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_show_source_problems_even_on_success
|
def test_show_source_problems_even_on_success
|
||||||
|
@ -648,7 +685,7 @@ ERROR: Possible alternatives: non_existent_with_hint
|
||||||
|
|
||||||
e = @ui.error
|
e = @ui.error
|
||||||
|
|
||||||
x = "WARNING: Unable to pull data from 'http://nonexistent.example': no data for http://nonexistent.example/latest_specs.4.8.gz (http://nonexistent.example/latest_specs.4.8.gz)\n"
|
x = "WARNING: Unable to pull data from 'http://nonexistent.example': no data for http://nonexistent.example/specs.4.8.gz (http://nonexistent.example/specs.4.8.gz)\n"
|
||||||
assert_equal x, e
|
assert_equal x, e
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -672,6 +709,56 @@ ERROR: Possible alternatives: non_existent_with_hint
|
||||||
assert_equal %w[], @cmd.installed_specs.map { |spec| spec.full_name }
|
assert_equal %w[], @cmd.installed_specs.map { |spec| spec.full_name }
|
||||||
|
|
||||||
assert_match "Using a (2)", @ui.output
|
assert_match "Using a (2)", @ui.output
|
||||||
|
assert File.exist?("#{@gemdeps}.lock")
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_execute_uses_from_a_gemdeps_with_no_lock
|
||||||
|
spec_fetcher do |fetcher|
|
||||||
|
fetcher.gem 'a', 2
|
||||||
|
end
|
||||||
|
|
||||||
|
File.open @gemdeps, "w" do |f|
|
||||||
|
f << "gem 'a'"
|
||||||
|
end
|
||||||
|
|
||||||
|
@cmd.handle_options %w[--no-lock]
|
||||||
|
@cmd.options[:gemdeps] = @gemdeps
|
||||||
|
|
||||||
|
use_ui @ui do
|
||||||
|
assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
|
||||||
|
@cmd.execute
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_equal %w[], @cmd.installed_specs.map { |spec| spec.full_name }
|
||||||
|
|
||||||
|
assert_match "Using a (2)", @ui.output
|
||||||
|
assert !File.exist?("#{@gemdeps}.lock")
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_execute_installs_from_a_gemdeps_with_conservative
|
||||||
|
spec_fetcher do |fetcher|
|
||||||
|
fetcher.gem 'a', 2
|
||||||
|
fetcher.clear
|
||||||
|
fetcher.gem 'a', 1
|
||||||
|
end
|
||||||
|
|
||||||
|
File.open @gemdeps, "w" do |f|
|
||||||
|
f << "gem 'a'"
|
||||||
|
end
|
||||||
|
|
||||||
|
@cmd.handle_options %w[--conservative]
|
||||||
|
@cmd.options[:gemdeps] = @gemdeps
|
||||||
|
|
||||||
|
use_ui @ui do
|
||||||
|
assert_raises Gem::MockGemUi::SystemExitException, @ui.error do
|
||||||
|
@cmd.execute
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_equal %w[], @cmd.installed_specs.map { |spec| spec.full_name }
|
||||||
|
|
||||||
|
assert_match "Using a (1)", @ui.output
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_execute_installs_from_a_gemdeps
|
def test_execute_installs_from_a_gemdeps
|
||||||
|
@ -885,6 +972,18 @@ ERROR: Possible alternatives: non_existent_with_hint
|
||||||
assert_equal 'gem.deps.rb', @cmd.options[:gemdeps]
|
assert_equal 'gem.deps.rb', @cmd.options[:gemdeps]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_handle_options_suggest
|
||||||
|
assert @cmd.options[:suggest_alternate]
|
||||||
|
|
||||||
|
@cmd.handle_options %w[--no-suggestions]
|
||||||
|
|
||||||
|
refute @cmd.options[:suggest_alternate]
|
||||||
|
|
||||||
|
@cmd.handle_options %w[--suggestions]
|
||||||
|
|
||||||
|
assert @cmd.options[:suggest_alternate]
|
||||||
|
end
|
||||||
|
|
||||||
def test_handle_options_without
|
def test_handle_options_without
|
||||||
@cmd.handle_options %w[--without test]
|
@cmd.handle_options %w[--without test]
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
require 'rubygems/test_case'
|
||||||
|
require 'rubygems/commands/open_command'
|
||||||
|
|
||||||
|
class TestGemCommandsOpenCommand < Gem::TestCase
|
||||||
|
|
||||||
|
def setup
|
||||||
|
super
|
||||||
|
|
||||||
|
@cmd = Gem::Commands::OpenCommand.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def gem name
|
||||||
|
spec = quick_gem name do |gem|
|
||||||
|
gem.files = %W[lib/#{name}.rb Rakefile]
|
||||||
|
end
|
||||||
|
write_file File.join(*%W[gems #{spec.full_name} lib #{name}.rb])
|
||||||
|
write_file File.join(*%W[gems #{spec.full_name} Rakefile])
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_execute
|
||||||
|
@cmd.options[:args] = %w[foo]
|
||||||
|
@cmd.options[:editor] = "#{Gem.ruby} -e0 --"
|
||||||
|
|
||||||
|
gem 'foo'
|
||||||
|
|
||||||
|
use_ui @ui do
|
||||||
|
@cmd.execute
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_equal "", @ui.error
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_execute_bad_gem
|
||||||
|
@cmd.options[:args] = %w[foo]
|
||||||
|
|
||||||
|
assert_raises Gem::MockGemUi::TermError do
|
||||||
|
use_ui @ui do
|
||||||
|
@cmd.execute
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assert_match %r|Unable to find gem 'foo'|, @ui.output
|
||||||
|
assert_equal "", @ui.error
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче