Skip to content

Commit

Permalink
Showing 146 changed files with 8,540 additions and 2,248 deletions.
2 changes: 1 addition & 1 deletion lib/ruby/shared/gauntlet_rubygems.rb
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@
# rvsh-0.4.5 : No such file or directory - bin/rvsh
# xen-0.1.2.1 : authors must be Array of Strings

class GemGauntlet < Gauntlet
class GemGauntlet < Gauntlet # :nodoc:
def run(name)
warn name

246 changes: 148 additions & 98 deletions lib/ruby/shared/rubygems.rb

Large diffs are not rendered by default.

9 changes: 6 additions & 3 deletions lib/ruby/shared/rubygems/available_set.rb
Original file line number Diff line number Diff line change
@@ -4,9 +4,12 @@ class Gem::AvailableSet

Tuple = Struct.new(:spec, :source)

attr_accessor :remote # :nodoc:

def initialize
@set = []
@sorted = nil
@remote = true
end

attr_reader :set
@@ -116,18 +119,18 @@ def to_request_set development = :none

##
#
# Used by the DependencyResolver, the protocol to use a AvailableSet as a
# Used by the Resolver, the protocol to use a AvailableSet as a
# search Set.

def find_all(req)
dep = req.dependency

match = @set.find_all do |t|
dep.matches_spec? t.spec
dep.match? t.spec
end

match.map do |t|
Gem::DependencyResolver::InstalledSpecification.new(self, t.spec, t.source)
Gem::Resolver::LocalSpecification.new(self, t.spec, t.source)
end
end

170 changes: 158 additions & 12 deletions lib/ruby/shared/rubygems/basic_specification.rb
Original file line number Diff line number Diff line change
@@ -4,11 +4,31 @@

class Gem::BasicSpecification

##
# Allows installation of extensions for git: gems.

attr_writer :base_dir # :nodoc:

##
# Sets the directory where extensions for this gem will be installed.

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.

attr_reader :loaded_from

##
# Allows correct activation of git: and path: gems.

attr_writer :full_gem_path # :nodoc:

def self.default_specifications_dir
File.join(Gem.default_dir, "specifications", "default")
end
@@ -38,20 +58,50 @@ def base_dir
# Return true if this spec can require +file+.

def contains_requirable_file? file
root = full_gem_path
suffixes = Gem.suffixes

require_paths.any? do |lib|
base = "#{root}/#{lib}/#{file}"
suffixes.any? { |suf| File.file? "#{base}#{suf}" }
end
@contains_requirable_file ||= {}
@contains_requirable_file[file] ||=
begin
if 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 #{name} --version #{version}"
return false
end

suffixes = Gem.suffixes

full_require_paths.any? do |dir|
base = "#{dir}/#{file}"
suffixes.any? { |suf| File.file? "#{base}#{suf}" }
end
end ? :yes : :no
@contains_requirable_file[file] == :yes
end

def default_gem?
loaded_from &&
File.dirname(loaded_from) == self.class.default_specifications_dir
end

##
# Returns full path to the directory where gem's extensions are installed.

def extension_dir
@extension_dir ||= File.expand_path File.join(extensions_dir, full_name)
end

##
# Returns path to the extensions directory.

def extensions_dir
@extensions_dir ||= Gem.default_ext_dir_for(base_dir) ||
File.join(base_dir, 'extensions', Gem::Platform.local.to_s,
Gem.extension_api_version)
end

def find_full_gem_path # :nodoc:
# TODO: also, shouldn't it default to full_name if it hasn't been written?
path = File.expand_path File.join(gems_dir, full_name)
@@ -83,6 +133,53 @@ def full_name
end
end

##
# Full paths in the gem to add to <code>$LOAD_PATH</code> when this gem is
# activated.

def full_require_paths
@full_require_paths ||=
begin
full_paths = raw_require_paths.map do |path|
File.join full_gem_path, path
end

full_paths << extension_dir unless @extensions.nil? || @extensions.empty?

full_paths
end
end

##
# Full path of the target library file.
# If the file is not in this gem, return nil.

def to_fullpath path
if activated? then
@paths_map ||= {}
@paths_map[path] ||=
begin
fullpath = nil
suffixes = Gem.suffixes
full_require_paths.find do |dir|
suffixes.find do |suf|
File.file?(fullpath = "#{dir}/#{path}#{suf}")
end
end ? fullpath : nil
end
else
nil
end
end

##
# Returns the full path to this spec's gem directory.
# eg: /usr/local/lib/ruby/1.8/gems/mygem-1.0

def gem_dir
@gem_dir ||= File.expand_path File.join(gems_dir, full_name)
end

##
# Returns the full path to the gems directory containing this spec's
# gem directory. eg: /usr/local/lib/ruby/1.8/gems
@@ -99,9 +196,12 @@ def gems_dir
def loaded_from= path
@loaded_from = path && path.to_s

@full_gem_path = nil
@gems_dir = nil
@base_dir = nil
@extension_dir = nil
@extensions_dir = nil
@full_gem_path = nil
@gem_dir = nil
@gems_dir = nil
@base_dir = nil
end

##
@@ -118,11 +218,49 @@ def platform
raise NotImplementedError
end

def raw_require_paths # :nodoc:
Array(@require_paths)
end

##
# Require paths of the gem
# Paths in the gem to add to <code>$LOAD_PATH</code> when this gem is
# activated.
#
# See also #require_paths=
#
# If you have an extension you do not need to add <code>"ext"</code> to the
# require path, the extension build process will copy the extension files
# into "lib" for you.
#
# The default value is <code>"lib"</code>
#
# Usage:
#
# # If all library files are in the root directory...
# spec.require_path = '.'

def require_paths
raise NotImplementedError
return raw_require_paths if @extensions.nil? || @extensions.empty?

[extension_dir].concat raw_require_paths
end

##
# Returns the paths to the source files for use with analysis and
# documentation tools. These paths are relative to full_gem_path.

def source_paths
paths = raw_require_paths.dup

if @extensions then
ext_dirs = @extensions.map do |extension|
extension.split(File::SEPARATOR, 2).first
end.uniq

paths.concat ext_dirs
end

paths.uniq
end

##
@@ -139,5 +277,13 @@ def version
raise NotImplementedError
end

##
# Whether this specification is stubbed - i.e. we have information
# about the gem from a stub line, without having to evaluate the
# entire gemspec file.
def stubbed?
raise NotImplementedError
end

end

5 changes: 4 additions & 1 deletion lib/ruby/shared/rubygems/command.rb
Original file line number Diff line number Diff line change
@@ -148,6 +148,8 @@ def execute

##
# 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)
if errors and !errors.empty?
@@ -557,7 +559,8 @@ def wrap(text, width) # :doc:
Further help:
gem help commands list all 'gem' commands
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
(e.g. 'gem help install')
gem server present a web page at
3 changes: 2 additions & 1 deletion lib/ruby/shared/rubygems/command_manager.rb
Original file line number Diff line number Diff line change
@@ -48,6 +48,7 @@ class Gem::CommandManager
:list,
:lock,
:mirror,
:open,
:outdated,
:owner,
:pristine,
@@ -136,7 +137,7 @@ def command_names
def run(args, build_args=nil)
process_args(args, build_args)
rescue StandardError, Timeout::Error => ex
alert_error "While executing gem ... (#{ex.class})\n #{ex.to_s}"
alert_error "While executing gem ... (#{ex.class})\n #{ex}"
ui.backtrace ex

terminate_interaction(1)
24 changes: 11 additions & 13 deletions lib/ruby/shared/rubygems/commands/cert_command.rb
Original file line number Diff line number Diff line change
@@ -129,23 +129,21 @@ def build_cert name, key # :nodoc:
end

def build_key # :nodoc:
if options[:key] then
options[:key]
else
passphrase = ask_for_password 'Passphrase for your Private Key:'
say "\n"
return options[:key] if options[:key]

passphrase_confirmation = ask_for_password 'Please repeat the passphrase for your Private Key:'
say "\n"
passphrase = ask_for_password 'Passphrase for your Private Key:'
say "\n"

raise Gem::CommandLineError,
"Passphrase and passphrase confirmation don't match" unless passphrase == passphrase_confirmation
passphrase_confirmation = ask_for_password 'Please repeat the passphrase for your Private Key:'
say "\n"

key = Gem::Security.create_key
key_path = Gem::Security.write key, "gem-private_key.pem", 0600, passphrase
raise Gem::CommandLineError,
"Passphrase and passphrase confirmation don't match" unless passphrase == passphrase_confirmation

return key, key_path
end
key = Gem::Security.create_key
key_path = Gem::Security.write key, "gem-private_key.pem", 0600, passphrase

return key, key_path
end

def certificates_matching filter
4 changes: 2 additions & 2 deletions lib/ruby/shared/rubygems/commands/cleanup_command.rb
Original file line number Diff line number Diff line change
@@ -67,10 +67,10 @@ def execute

say "Clean Up Complete"

if Gem.configuration.really_verbose then
verbose do
skipped = @default_gems.map { |spec| spec.full_name }

say "Skipped default gems: #{skipped.join ', '}"
"Skipped default gems: #{skipped.join ', '}"
end
end

34 changes: 27 additions & 7 deletions lib/ruby/shared/rubygems/commands/contents_command.rb
Original file line number Diff line number Diff line change
@@ -8,7 +8,8 @@ class Gem::Commands::ContentsCommand < Gem::Command

def initialize
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

@@ -32,6 +33,11 @@ def initialize
options[:prefix] = prefix
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
@spec_dirs = nil
@version = nil
@@ -65,7 +71,12 @@ def execute
names = gem_names

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
end
@@ -91,14 +102,14 @@ def files_in_gem spec
end

def files_in_default_gem spec
spec.files.sort.map do |file|
spec.files.map do |file|
case file
when /\A#{spec.bindir}\//
[Gem::ConfigMap[:bindir], $POSTMATCH]
[RbConfig::CONFIG['bindir'], $POSTMATCH]
when /\.so\z/
[Gem::ConfigMap[:archdir], file]
[RbConfig::CONFIG['archdir'], file]
else
[Gem::ConfigMap[:rubylibdir], file]
[RbConfig::CONFIG['rubylibdir'], file]
end
end
end
@@ -115,6 +126,16 @@ def gem_contents name
true
end

def gem_install_dir name
spec = spec_for name

return false unless spec

say spec.gem_dir

true
end

def gem_names # :nodoc:
if options[:all] then
Gem::Specification.map(&:name)
@@ -125,7 +146,6 @@ def gem_names # :nodoc:

def path_description spec_dirs # :nodoc:
if spec_dirs.empty? then
spec_dirs = Gem::Specification.dirs
"default gem paths"
else
"specified path"
4 changes: 2 additions & 2 deletions lib/ruby/shared/rubygems/commands/dependency_command.rb
Original file line number Diff line number Diff line change
@@ -31,7 +31,7 @@ def initialize
end

def arguments # :nodoc:
"GEMNAME name of gem to show dependencies for"
"REGEXP show dependencies for gems whose names start with REGEXP"
end

def defaults_str # :nodoc:
@@ -50,7 +50,7 @@ def description # :nodoc:
end

def usage # :nodoc:
"#{program_name} GEMNAME"
"#{program_name} REGEXP"
end

def fetch_remote_specs dependency # :nodoc:
7 changes: 5 additions & 2 deletions lib/ruby/shared/rubygems/commands/environment_command.rb
Original file line number Diff line number Diff line change
@@ -28,8 +28,9 @@ def description # :nodoc:
gemrc files, environment variables and built-in defaults.
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
files are YAML files with the following YAML keys:
~/.gemrc file for individual users and a gemrc in the SYSTEM CONFIGURATION
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
:verbose: Verbosity of the gem command. false, true, and :really are the
@@ -120,6 +121,8 @@ def show_environment # :nodoc:

out << " - SPEC CACHE DIRECTORY: #{Gem.spec_cache_dir}\n"

out << " - SYSTEM CONFIGURATION DIRECTORY: #{Gem::ConfigFile::SYSTEM_CONFIG_PATH}\n"

out << " - RUBYGEMS PLATFORMS:\n"
Gem.platforms.each do |platform|
out << " - #{platform}\n"
Original file line number Diff line number Diff line change
@@ -62,7 +62,7 @@ def description # :nodoc:
end

def execute
# This is always true becasue it's the only way now.
# This is always true because it's the only way now.
options[:build_modern] = true

if not File.exist?(options[:directory]) or
219 changes: 199 additions & 20 deletions lib/ruby/shared/rubygems/commands/help_command.rb
Original file line number Diff line number Diff line change
@@ -52,6 +52,183 @@ class Gem::Commands::HelpCommand < Gem::Command
gem update --system
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 specify 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 overridden with the :development_group option:
gemspec development_group: :other
EOF

PLATFORMS = <<-'EOF'
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
@@ -90,6 +267,16 @@ class Gem::Commands::HelpCommand < Gem::Command
Gem::Platform::CURRENT. This will correctly mark the gem with your ruby's
platform.
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:

def initialize
@@ -98,35 +285,27 @@ def initialize
@command_manager = Gem::CommandManager.instance
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:
"#{program_name} ARGUMENT"
end

def execute
arg = options[:args][0]

if begins? "commands", arg then
show_commands

elsif begins? "options", arg then
say Gem::Command::HELP

elsif begins? "examples", arg then
say EXAMPLES
_, help = SUBCOMMANDS.find do |command,|
begins? command, arg
end

elsif begins? "platforms", arg then
say PLATFORMS
if help then
if Symbol === help then
send help
else
say help
end
return
end

elsif options[:help] then
if options[:help] then
show_help

elsif arg then
145 changes: 126 additions & 19 deletions lib/ruby/shared/rubygems/commands/install_command.rb
Original file line number Diff line number Diff line change
@@ -21,7 +21,10 @@ class Gem::Commands::InstallCommand < Gem::Command
def initialize
defaults = Gem::DependencyInstaller::DEFAULT_OPTIONS.merge({
:format_executable => false,
:lock => true,
:suggest_alternate => true,
:version => Gem::Requirement.default,
:without_groups => [],
})

super 'install', 'Install a gem into the local repository', defaults
@@ -32,19 +35,53 @@ def initialize
add_version_option
add_prerelease_option "to be installed. (Only for listed gems)"

add_option(:"Install/Update", '-g', '--file FILE',
add_option(:"Install/Update", '-g', '--file [FILE]',
'Read from a gem dependencies API file and',
'install the listed gems') do |v,o|
v = Gem::GEM_DEP_FILES.find do |file|
File.exist? file
end unless v

unless v then
message = v ? v : "(tried #{Gem::GEM_DEP_FILES.join ', '})"

raise OptionParser::InvalidArgument,
"cannot find gem dependencies file #{message}"
end

o[:gemdeps] = v
end

add_option(:"Install/Update", '--without GROUPS', Array,
'Omit the named groups (comma separated)',
'when installing from a gem dependencies',
'file') do |v,o|
o[:without_groups].concat v.map { |without| without.intern }
end

add_option(:"Install/Update", '--default',
'Add the gem\'s full specification to',
'specifications/default and extract only its bin') do |v,o|
o[:install_as_default] = v
end

@installed_specs = nil
add_option(:"Install/Update", '--explain',
'Rather than install the gems, indicate which would',
'be installed') do |v,o|
o[:explain] = v
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 = []
end

def arguments # :nodoc:
@@ -53,7 +90,7 @@ def arguments # :nodoc:

def defaults_str # :nodoc:
"--both --version '#{Gem::Requirement.default}' --document --no-force\n" +
"--install-dir #{Gem.dir}"
"--install-dir #{Gem.dir} --lock"
end

def description # :nodoc:
@@ -67,6 +104,25 @@ def description # :nodoc:
For example `rake _0.7.3_ --version` will run rake version 0.7.3 if a newer
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
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
@@ -129,9 +185,9 @@ def check_version # :nodoc:
end

def execute
if gf = options[:gemdeps] then
install_from_gemdeps gf
return
if options.include? :gemdeps then
install_from_gemdeps
return # not reached
end

@installed_specs = []
@@ -147,17 +203,14 @@ def execute

show_installed

raise Gem::SystemExitException, exit_code
terminate_interaction exit_code
end

def install_from_gemdeps gf # :nodoc:
def install_from_gemdeps # :nodoc:
require 'rubygems/request_set'
rs = Gem::RequestSet.new
rs.load_gemdeps gf

rs.resolve

specs = rs.install options do |req, inst|
specs = rs.install_from_gemdeps options do |req, inst|
s = req.full_spec

if inst
@@ -169,19 +222,71 @@ def install_from_gemdeps gf # :nodoc:

@installed_specs = specs

raise Gem::SystemExitException, 0
terminate_interaction
end

def install_gem name, version # :nodoc:
return if options[:conservative] and
not Gem::Dependency.new(name, version).matching_specs.empty?

inst = Gem::DependencyInstaller.new options
inst.install name, Gem::Requirement.create(version)
req = Gem::Requirement.create(version)

if options[:ignore_dependencies] then
install_gem_without_dependencies name, req
else
inst = Gem::DependencyInstaller.new options
request_set = inst.resolve_dependencies name, req

if options[:explain]
puts "Gems to install:"

request_set.sorted_requests.each do |s|
puts " #{s.full_name}"
end

return
else
@installed_specs.concat request_set.install options
end

show_install_errors inst.errors
end
end

def install_gem_without_dependencies name, req # :nodoc:
gem = nil

if local? then
if name =~ /\.gem$/ and File.file? name then
source = Gem::Source::SpecificFile.new name
spec = source.spec
else
source = Gem::Source::Local.new
spec = source.find_gem name, req
end
gem = source.download spec if spec
end

if remote? and not gem then
dependency = Gem::Dependency.new name, req
dependency.prerelease = options[:prerelease]

fetcher = Gem::RemoteFetcher.fetcher
gem = fetcher.download_to_cache dependency
end

inst = Gem::Installer.new gem, options
inst.install

require 'rubygems/dependency_installer'
dinst = Gem::DependencyInstaller.new options
dinst.installed_gems.replace [inst.spec]

@installed_specs.push(*inst.installed_gems)
Gem.done_installing_hooks.each do |hook|
hook.call dinst, [inst.spec]
end unless Gem.done_installing_hooks.empty?

show_install_errors inst.errors
@installed_specs.push(inst.spec)
end

def install_gems # :nodoc:
@@ -195,8 +300,10 @@ def install_gems # :nodoc:
rescue Gem::InstallError => e
alert_error "Error installing #{gem_name}:\n\t#{e.message}"
exit_code |= 1
rescue Gem::GemNotFoundException => e
show_lookup_failure e.name, e.version, e.errors, options[:domain]
rescue Gem::GemNotFoundException, Gem::UnsatisfiableDependencyError => e
domain = options[:domain]
domain = :local unless options[:suggest_alternate]
show_lookup_failure e.name, e.version, e.errors, domain

exit_code |= 2
end
12 changes: 3 additions & 9 deletions lib/ruby/shared/rubygems/commands/list_command.rb
Original file line number Diff line number Diff line change
@@ -8,13 +8,13 @@
class Gem::Commands::ListCommand < Gem::Commands::QueryCommand

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')
end

def arguments # :nodoc:
"STRING start of gem name to look for"
"REGEXP regexp to look for in gem name"
end

def defaults_str # :nodoc:
@@ -33,13 +33,7 @@ def description # :nodoc:
end

def usage # :nodoc:
"#{program_name} [STRING]"
end

def execute
string = get_one_optional_argument || ''
options[:name] = /^#{string}/i
super
"#{program_name} [STRING ...]"
end

end
32 changes: 17 additions & 15 deletions lib/ruby/shared/rubygems/commands/mirror_command.rb
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
require 'rubygems/command'

class Gem::Commands::MirrorCommand < Gem::Command
def initialize
super('mirror', 'Mirror all gem files (requires rubygems-mirror)')
begin
Gem::Specification.find_by_name('rubygems-mirror').activate
rescue Gem::LoadError
# no-op
unless defined? Gem::Commands::MirrorCommand
class Gem::Commands::MirrorCommand < Gem::Command
def initialize
super('mirror', 'Mirror all gem files (requires rubygems-mirror)')
begin
Gem::Specification.find_by_name('rubygems-mirror').activate
rescue Gem::LoadError
# no-op
end
end
end

def description # :nodoc:
<<-EOF
def description # :nodoc:
<<-EOF
The mirror command has been moved to the rubygems-mirror gem.
EOF
end
EOF
end

def execute
alert_error "Install the rubygems-mirror gem for the mirror command"
end
def execute
alert_error "Install the rubygems-mirror gem for the mirror command"
end

end
end
76 changes: 76 additions & 0 deletions lib/ruby/shared/rubygems/commands/open_command.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
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
Dir.chdir(path) do
system(*@editor.split(/\s+/) + [path])
end
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
2 changes: 1 addition & 1 deletion lib/ruby/shared/rubygems/commands/outdated_command.rb
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@ def initialize

def description # :nodoc:
<<-EOF
The outdated command lists gems you way wish to upgrade to a newer version.
The outdated command lists gems you may wish to upgrade to a newer version.
You can check for dependency mismatches using the dependency command and
update the gems with the update or install commands.
4 changes: 3 additions & 1 deletion lib/ruby/shared/rubygems/commands/owner_command.rb
Original file line number Diff line number Diff line change
@@ -86,7 +86,9 @@ def manage_owners method, name, owners
request.add_field "Authorization", api_key
end

with_response response, "Removing #{owner}"
action = method == :delete ? "Removing" : "Adding"

with_response response, "#{action} #{owner}"
rescue
# ignore
end
31 changes: 29 additions & 2 deletions lib/ruby/shared/rubygems/commands/pristine_command.rb
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@ def initialize
'Restores installed gems to pristine condition from files located in the gem cache',
:version => Gem::Requirement.default,
:extensions => true,
:extensions_set => false,
:all => false

add_option('--all',
@@ -23,7 +24,8 @@ def initialize
add_option('--[no-]extensions',
'Restore gems with extensions',
'in addition to regular gems') do |value, options|
options[:extensions] = value
options[:extensions_set] = true
options[:extensions] = value
end

add_option('--only-executables',
@@ -62,6 +64,9 @@ def description # :nodoc:
If --no-extensions is provided pristine will not attempt to restore a gem
with an extension.
If --extensions is given (but not --all or gem names) only gems with
extensions will be restored.
EOF
end

@@ -72,6 +77,14 @@ def usage # :nodoc:
def execute
specs = if options[:all] then
Gem::Specification.map

# `--extensions` must be explicitly given to pristine only gems
# with extensions.
elsif options[:extensions_set] and
options[:extensions] and options[:args].empty? then
Gem::Specification.select do |spec|
spec.extensions and not spec.extensions.empty?
end
else
get_all_gem_names.map do |gem_name|
Gem::Specification.find_all_by_name gem_name, options[:version]
@@ -96,6 +109,11 @@ def execute
next
end

if spec.bundled_gem_in_old_ruby?
say "Skipped #{spec.full_name}, it is bundled with old Ruby"
next
end

unless spec.extensions.empty? or options[:extensions] then
say "Skipped #{spec.full_name}, it needs to compile an extension"
next
@@ -107,8 +125,17 @@ def execute
require 'rubygems/remote_fetcher'

say "Cached gem for #{spec.full_name} not found, attempting to fetch..."

dep = Gem::Dependency.new spec.name, spec.version
Gem::RemoteFetcher.fetcher.download_to_cache dep
found, _ = Gem::SpecFetcher.fetcher.spec_for_dependency dep

if found.empty?
say "Skipped #{spec.full_name}, it was not found from cache and remote sources"
next
end

spec_candidate, source = found.first
Gem::RemoteFetcher.fetcher.download spec_candidate, source.uri.to_s, spec.base_dir
end

env_shebang =
13 changes: 9 additions & 4 deletions lib/ruby/shared/rubygems/commands/push_command.rb
Original file line number Diff line number Diff line change
@@ -69,13 +69,18 @@ def send_gem name
terminate_interaction 1
end

gem_data = Gem::Package.new(name)

unless @host then
if gem_data = Gem::Package.new(name) then
@host = gem_data.spec.metadata['default_gem_server']
end
@host = gem_data.spec.metadata['default_gem_server']
end

args << @host if @host
# Always include this, even if it's nil
args << @host

if gem_data.spec.metadata.has_key?('allowed_push_host')
args << gem_data.spec.metadata['allowed_push_host']
end

say "Pushing gem to #{@host || Gem.host}..."

50 changes: 33 additions & 17 deletions lib/ruby/shared/rubygems/commands/query_command.rb
Original file line number Diff line number Diff line change
@@ -72,16 +72,26 @@ def description # :nodoc:

def execute
exit_code = 0
if options[:args].to_a.empty? and options[:name].source.empty?
name = options[:name]
no_name = true
elsif !options[:name].source.empty?
name = Array(options[:name])
else
name = options[:args].to_a.map{|arg| /#{arg}/i }
end

name = options[:name]
prerelease = options[:prerelease]

unless options[:installed].nil? then
if name.source.empty? then
if no_name then
alert_error "You must specify a gem name"
exit_code |= 4
elsif name.count > 1
alert_error "You must specify only ONE gem!"
exit_code |= 4
else
installed = installed? name, options[:version]
installed = installed? name.first, options[:version]
installed = !installed unless options[:installed]

if installed then
@@ -95,6 +105,22 @@ def execute
terminate_interaction exit_code
end

names = Array(name)
names.each { |n| show_gems n, prerelease }
end

private

def display_header type
if (ui.outs.tty? and Gem.configuration.verbose) or both? then
say
say "*** #{type} GEMS ***"
say
end
end

#Guts of original execute
def show_gems name, prerelease
req = Gem::Requirement.default
# TODO: deprecate for real
dep = Gem::Deprecate.skip_during { Gem::Dependency.new name, req }
@@ -105,11 +131,7 @@ def execute
alert_warning "prereleases are always shown locally"
end

if ui.outs.tty? or both? then
say
say "*** LOCAL GEMS ***"
say
end
display_header 'LOCAL'

specs = Gem::Specification.find_all { |s|
s.name =~ name and req =~ s.version
@@ -123,11 +145,7 @@ def execute
end

if remote? then
if ui.outs.tty? or both? then
say
say "*** REMOTE GEMS ***"
say
end
display_header 'REMOTE'

fetcher = Gem::SpecFetcher.fetcher

@@ -143,20 +161,18 @@ def execute
:latest
end

if options[:name].source.empty?
if name.source.empty?
spec_tuples = fetcher.detect(type) { true }
else
spec_tuples = fetcher.detect(type) do |name_tuple|
options[:name] === name_tuple.name
name === name_tuple.name
end
end

output_query_results spec_tuples
end
end

private

##
# Check if gem +name+ version +version+ is installed.

16 changes: 5 additions & 11 deletions lib/ruby/shared/rubygems/commands/search_command.rb
Original file line number Diff line number Diff line change
@@ -4,15 +4,15 @@
class Gem::Commands::SearchCommand < Gem::Commands::QueryCommand

def initialize
super 'search', 'Display remote gems whose name contains STRING'
super 'search', 'Display remote gems whose name matches REGEXP'

remove_option '--name-matches'

defaults[:domain] = :remote
end

def arguments # :nodoc:
"STRING fragment of gem name to search for"
"REGEXP regexp to search for in gem name"
end

def defaults_str # :nodoc:
@@ -21,8 +21,8 @@ def defaults_str # :nodoc:

def description # :nodoc:
<<-EOF
The search command displays remote gems whose name contains the given
string.
The search command displays remote gems whose name matches the given
regexp.
The --details option displays additional details from the gem but will
take a little longer to complete as it must download the information
@@ -33,13 +33,7 @@ def description # :nodoc:
end

def usage # :nodoc:
"#{program_name} [STRING]"
end

def execute
string = get_one_optional_argument
options[:name] = /#{string}/i
super
"#{program_name} [REGEXP]"
end

end
18 changes: 9 additions & 9 deletions lib/ruby/shared/rubygems/commands/setup_command.rb
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ def initialize

super 'setup', 'Install RubyGems',
:format_executable => true, :document => %w[ri],
:site_or_vendor => :sitelibdir,
:site_or_vendor => 'sitelibdir',
:destdir => '', :prefix => '', :previous_version => ''

add_option '--previous-version=VERSION',
@@ -36,7 +36,7 @@ def initialize

add_option '--[no-]vendor',
'Install into vendorlibdir not sitelibdir' do |vendor, options|
options[:site_or_vendor] = vendor ? :vendorlibdir : :sitelibdir
options[:site_or_vendor] = vendor ? 'vendorlibdir' : 'sitelibdir'
end

add_option '--[no-]format-executable',
@@ -343,19 +343,19 @@ def generate_default_dirs(install_destdir)
site_or_vendor = options[:site_or_vendor]

if prefix.empty? then
lib_dir = Gem::ConfigMap[site_or_vendor]
bin_dir = Gem::ConfigMap[:bindir]
lib_dir = RbConfig::CONFIG[site_or_vendor]
bin_dir = RbConfig::CONFIG['bindir']
else
# Apple installed RubyGems into libdir, and RubyGems <= 1.1.0 gets
# confused about installation location, so switch back to
# sitelibdir/vendorlibdir.
if defined?(APPLE_GEM_HOME) and
# just in case Apple and RubyGems don't get this patched up proper.
(prefix == Gem::ConfigMap[:libdir] or
(prefix == RbConfig::CONFIG['libdir'] or
# this one is important
prefix == File.join(Gem::ConfigMap[:libdir], 'ruby')) then
lib_dir = Gem::ConfigMap[site_or_vendor]
bin_dir = Gem::ConfigMap[:bindir]
prefix == File.join(RbConfig::CONFIG['libdir'], 'ruby')) then
lib_dir = RbConfig::CONFIG[site_or_vendor]
bin_dir = RbConfig::CONFIG['bindir']
else
lib_dir = File.join prefix, 'lib'
bin_dir = File.join prefix, 'bin'
@@ -446,7 +446,7 @@ def show_release_notes
history.force_encoding Encoding::UTF_8 if
Object.const_defined? :Encoding

history = history.sub(/^# coding:.*?^=/m, '')
history = history.sub(/^# coding:.*?(?=^=)/m, '')

text = history.split(HISTORY_HEADER)
text.shift # correct an off-by-one generated by split
2 changes: 1 addition & 1 deletion lib/ruby/shared/rubygems/commands/specification_command.rb
Original file line number Diff line number Diff line change
@@ -127,7 +127,7 @@ def execute
end

unless options[:all] then
specs = [specs.sort_by { |s| s.version }.last]
specs = [specs.max_by { |s| s.version }]
end

specs.each do |s|
16 changes: 14 additions & 2 deletions lib/ruby/shared/rubygems/commands/uninstall_command.rb
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@ class Gem::Commands::UninstallCommand < Gem::Command
def initialize
super 'uninstall', 'Uninstall gems from the local repository',
:version => Gem::Requirement.default, :user_install => true,
:check_dev => false
:check_dev => false, :vendor => false

add_option('-a', '--[no-]all',
'Uninstall all matching versions'
@@ -76,6 +76,18 @@ def initialize

add_version_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

def arguments # :nodoc:
@@ -112,7 +124,7 @@ def execute
end

def uninstall_all
_, specs = Gem::Specification.partition { |spec| spec.default_gem? }
specs = Gem::Specification.reject { |spec| spec.default_gem? }

specs.each do |spec|
options[:version] = spec.version
2 changes: 1 addition & 1 deletion lib/ruby/shared/rubygems/commands/unpack_command.rb
Original file line number Diff line number Diff line change
@@ -134,7 +134,7 @@ def get_path dependency

specs = dependency.matching_specs

selected = specs.sort_by { |s| s.version }.last # HACK: hunt last down
selected = specs.max_by { |s| s.version }

return Gem::RemoteFetcher.fetcher.download_to_cache(dependency) unless
selected
39 changes: 24 additions & 15 deletions lib/ruby/shared/rubygems/commands/update_command.rb
Original file line number Diff line number Diff line change
@@ -16,6 +16,8 @@ class Gem::Commands::UpdateCommand < Gem::Command

attr_reader :installer # :nodoc:

attr_reader :updated # :nodoc:

def initialize
super 'update', 'Update installed gems to the latest version',
:document => %w[rdoc ri],
@@ -45,7 +47,7 @@ def initialize
end

def arguments # :nodoc:
"GEMNAME name of gem to update"
"REGEXP regexp to search for in gem name"
end

def defaults_str # :nodoc:
@@ -56,13 +58,13 @@ def description # :nodoc:
<<-EOF
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.
EOF
end

def usage # :nodoc:
"#{program_name} GEMNAME [GEMNAME ...]"
"#{program_name} REGEXP [REGEXP ...]"
end

def check_latest_rubygems version # :nodoc:
@@ -82,8 +84,6 @@ def check_update_arguments # :nodoc:
end

def execute
hig = {}

if options[:system] then
update_rubygems
return
@@ -97,10 +97,14 @@ def execute

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
say "Nothing to update"
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

@@ -110,7 +114,11 @@ def fetch_remote_gems spec # :nodoc:

fetcher = Gem::SpecFetcher.fetcher

spec_tuples, _ = fetcher.search_for_dependency dependency
spec_tuples, errors = fetcher.search_for_dependency dependency

error = errors.find { |e| e.respond_to? :exception }

raise error if error

spec_tuples
end
@@ -134,7 +142,7 @@ def highest_remote_version spec # :nodoc:
g.name == spec.name and g.match_platform?
end

highest_remote_gem = matching_gems.sort_by { |g,_| g.version }.last
highest_remote_gem = matching_gems.max_by { |g,_| g.version }

highest_remote_gem ||= [Gem::NameTuple.null]

@@ -193,17 +201,16 @@ def rubygems_target_version
def update_gem name, version = Gem::Requirement.default
return if @updated.any? { |spec| spec.name == name }

@installer ||= Gem::DependencyInstaller.new options
update_options = options.dup
update_options[:prerelease] = version.prerelease?

success = false
@installer = Gem::DependencyInstaller.new update_options

say "Updating #{name}"
begin
@installer.install name, Gem::Requirement.new(version)
success = true
rescue Gem::InstallError => e
rescue Gem::InstallError, Gem::DependencyError => e
alert_error "Error installing #{name}:\n\t#{e.message}"
success = false
end

@installer.installed_gems.each do |spec|
@@ -244,6 +251,9 @@ def update_rubygems_arguments # :nodoc:
args << '--no-rdoc' unless options[:document].include? 'rdoc'
args << '--no-ri' unless options[:document].include? 'ri'
args << '--no-format-executable' if options[:no_format_executable]
args << '--previous-version' << Gem::VERSION if
options[:system] == true or
Gem::Version.new(options[:system]) >= Gem::Version.new(2)
args
end

@@ -252,7 +262,7 @@ def which_to_update highest_installed_gems, gem_names, system = false

highest_installed_gems.each do |l_name, l_spec|
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

@@ -265,4 +275,3 @@ def which_to_update highest_installed_gems, gem_names, system = false
end

end

13 changes: 5 additions & 8 deletions lib/ruby/shared/rubygems/commands/which_command.rb
Original file line number Diff line number Diff line change
@@ -35,7 +35,7 @@ def description # :nodoc:
end

def execute
found = false
found = true

options[:args].each do |arg|
arg = arg.sub(/#{Regexp.union(*Gem.suffixes)}$/, '')
@@ -45,9 +45,9 @@ def execute

if spec then
if options[:search_gems_first] then
dirs = gem_paths(spec) + $LOAD_PATH
dirs = spec.full_require_paths + $LOAD_PATH
else
dirs = $LOAD_PATH + gem_paths(spec)
dirs = $LOAD_PATH + spec.full_require_paths
end
end

@@ -56,9 +56,10 @@ def execute

if paths.empty? then
alert_error "Can't find ruby library file or shared library #{arg}"

found &&= false
else
say paths
found = true
end
end

@@ -81,10 +82,6 @@ def find_paths(package_name, dirs)
result
end

def gem_paths(spec)
spec.require_paths.collect { |d| File.join spec.full_gem_path, d }
end

def usage # :nodoc:
"#{program_name} FILE [FILE ...]"
end
23 changes: 9 additions & 14 deletions lib/ruby/shared/rubygems/commands/yank_command.rb
Original file line number Diff line number Diff line change
@@ -21,7 +21,7 @@ def description # :nodoc:
data you will need to change them immediately and yank your gem.
If you are yanking a gem due to intellectual property reasons contact
http://help.rubygems.org for permanant removal. Be sure to mention this
http://help.rubygems.org for permanent removal. Be sure to mention this
as the reason for the removal request.
EOF
end
@@ -44,45 +44,40 @@ def initialize
options[:undo] = true
end

add_option('-k', '--key KEY_NAME',
'Use API key from your gem credentials file') do |value, options|
options[:key] = value
end
add_key_option
end

def execute
sign_in

version = get_version_from_requirements(options[:version])
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 options[:undo] then
unyank_gem(version, platform, api_key)
unyank_gem(version, platform)
else
yank_gem(version, platform, api_key)
yank_gem(version, platform)
end
else
say "A version argument is required: #{usage}"
terminate_interaction
end
end

def yank_gem(version, platform, api_key)
def yank_gem(version, platform)
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

def unyank_gem(version, platform, api_key)
def unyank_gem(version, platform)
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

private

def yank_api_request(method, version, platform, api, api_key)
def yank_api_request(method, version, platform, api)
name = get_one_gem_name
response = rubygems_api_request(method, api) do |request|
request.add_field("Authorization", api_key)
10 changes: 7 additions & 3 deletions lib/ruby/shared/rubygems/compatibility.rb
Original file line number Diff line number Diff line change
@@ -20,8 +20,7 @@ module Gem

$LOADED_FEATURES.delete Gem::QuickLoader.path_to_full_rubygems_library

if $LOADED_FEATURES.any? do |path| path.end_with? '/rubygems.rb' end then
# TODO path does not exist here
if path = $LOADED_FEATURES.find {|n| n.end_with? '/rubygems.rb'} then
raise LoadError, "another rubygems is already loaded from #{path}"
end

@@ -33,7 +32,12 @@ class << Gem
module Gem
RubyGemsVersion = VERSION

# TODO remove at RubyGems 3

RbConfigPriorities = %w[
MAJOR
MINOR
TEENY
EXEEXT RUBY_SO_NAME arch bindir datadir libdir ruby_install_name
ruby_version rubylibprefix sitedir sitelibdir vendordir vendorlibdir
rubylibdir
@@ -42,7 +46,7 @@ module Gem
unless defined?(ConfigMap)
##
# Configuration settings from ::RbConfig
ConfigMap = Hash.new do |cm, key|
ConfigMap = Hash.new do |cm, key| # TODO remove at RubyGems 3
cm[key] = RbConfig::CONFIG[key.to_s]
end
else
22 changes: 17 additions & 5 deletions lib/ruby/shared/rubygems/config_file.rb
Original file line number Diff line number Diff line change
@@ -57,7 +57,7 @@ class Gem::ConfigFile

# :stopdoc:

system_config_path =
SYSTEM_CONFIG_PATH =
begin
require "etc"
Etc.sysconfdir
@@ -86,7 +86,7 @@ class Gem::ConfigFile

# :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.
@@ -137,9 +137,10 @@ class Gem::ConfigFile
attr_reader :ssl_verify_mode

##
# Path name of directory or file of openssl CA certificate, used for remote https connection
# Path name of directory or file of openssl CA certificate, used for remote
# https connection

attr_reader :ssl_ca_cert
attr_accessor :ssl_ca_cert

##
# Path name of directory or file of openssl client certificate, used for remote https connection with client authentication
@@ -336,7 +337,7 @@ def load_file(filename)
end
return content
rescue *YAMLErrors => e
warn "Failed to load #{filename}, #{e.to_s}"
warn "Failed to load #{filename}, #{e}"
rescue Errno::EACCES
warn "Failed to load #{filename} due to permissions problem."
end
@@ -382,6 +383,8 @@ def handle_arguments(arg_list)
@backtrace = true
when /^--debug$/ then
$DEBUG = true

warn 'NOTE: Debugging mode prints all exceptions even when rescued'
else
@args << arg
end
@@ -427,6 +430,15 @@ def to_yaml # :nodoc:
DEFAULT_VERBOSITY
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 << 'debug'
re = Regexp.union(*keys)
24 changes: 22 additions & 2 deletions lib/ruby/shared/rubygems/core_ext/kernel_gem.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
##
# RubyGems adds the #gem method to allow activation of specific gem versions
# and overrides the #require method on Kernel to make gems appear as if they
# live on the <code>$LOAD_PATH</code>. See the documentation of these methods
# for further detail.

module Kernel

# REFACTOR: This should be pulled out into some kind of hacks file.
@@ -20,6 +26,11 @@ module Kernel
# Kernel#gem should be called *before* any require statements (otherwise
# 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
# 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
@@ -44,8 +55,17 @@ def gem(gem_name, *requirements) # :doc:
gem_name = gem_name.name
end

spec = Gem::Dependency.new(gem_name, *requirements).to_spec
spec.activate if spec
dep = Gem::Dependency.new(gem_name, *requirements)

loaded = Gem.loaded_specs[gem_name]

return false if loaded && dep.matches_spec?(loaded)

spec = dep.to_spec

Gem::LOADED_SPECS_MUTEX.synchronize {
spec.activate
} if spec
end

private :gem
36 changes: 13 additions & 23 deletions lib/ruby/shared/rubygems/core_ext/kernel_require.rb
Original file line number Diff line number Diff line change
@@ -50,12 +50,8 @@ def require path
# normal require handle loading a gem from the rescue below.

if Gem::Specification.unresolved_deps.empty? then
begin
RUBYGEMS_ACTIVATION_MONITOR.exit
return gem_original_require(path)
ensure
RUBYGEMS_ACTIVATION_MONITOR.enter
end
RUBYGEMS_ACTIVATION_MONITOR.exit
return gem_original_require(path)
end

# If +path+ is for a gem that has already been loaded, don't
@@ -70,9 +66,7 @@ def require path

begin
RUBYGEMS_ACTIVATION_MONITOR.exit
return gem_original_require(path)
ensure
RUBYGEMS_ACTIVATION_MONITOR.enter
return gem_original_require(spec.to_fullpath(path) || path)
end if spec

# Attempt to find +path+ in any unresolved gems...
@@ -105,6 +99,7 @@ def require path
names = found_specs.map(&:name).uniq

if names.size > 1 then
RUBYGEMS_ACTIVATION_MONITOR.exit
raise Gem::LoadError, "#{path} found in multiple gems: #{names.join ', '}"
end

@@ -115,32 +110,27 @@ def require path
unless valid then
le = Gem::LoadError.new "unable to find a version of '#{names.first}' to activate"
le.name = names.first
RUBYGEMS_ACTIVATION_MONITOR.exit
raise le
end

valid.activate
end

begin
RUBYGEMS_ACTIVATION_MONITOR.exit
return gem_original_require(path)
ensure
RUBYGEMS_ACTIVATION_MONITOR.enter
end
RUBYGEMS_ACTIVATION_MONITOR.exit
return gem_original_require(path)
rescue LoadError => load_error
RUBYGEMS_ACTIVATION_MONITOR.enter

if load_error.message.start_with?("Could not find") or
(load_error.message.end_with?(path) and Gem.try_activate(path)) then
begin
RUBYGEMS_ACTIVATION_MONITOR.exit
return gem_original_require(path)
ensure
RUBYGEMS_ACTIVATION_MONITOR.enter
end
RUBYGEMS_ACTIVATION_MONITOR.exit
return gem_original_require(path)
else
RUBYGEMS_ACTIVATION_MONITOR.exit
end

raise load_error
ensure
RUBYGEMS_ACTIVATION_MONITOR.exit
end

private :require
63 changes: 48 additions & 15 deletions lib/ruby/shared/rubygems/defaults.rb
Original file line number Diff line number Diff line change
@@ -29,28 +29,39 @@ def self.default_spec_cache_dir
def self.default_dir
path = if defined? RUBY_FRAMEWORK_VERSION then
[
File.dirname(ConfigMap[:sitedir]),
File.dirname(RbConfig::CONFIG['sitedir']),
'Gems',
ConfigMap[:ruby_version]
RbConfig::CONFIG['ruby_version']
]
elsif ConfigMap[:rubylibprefix] then
elsif RbConfig::CONFIG['rubylibprefix'] then
[
ConfigMap[:rubylibprefix],
RbConfig::CONFIG['rubylibprefix'],
'gems',
ConfigMap[:ruby_version]
RbConfig::CONFIG['ruby_version']
]
else
[
ConfigMap[:libdir],
RbConfig::CONFIG['libdir'],
ruby_engine,
'gems',
ConfigMap[:ruby_version]
RbConfig::CONFIG['ruby_version']
]
end

@default_dir ||= File.join(*path)
end

##
# Returns binary extensions dir for specified RubyGems base dir or nil
# if such directory cannot be determined.
#
# By default, the binary extensions are located side by side with their
# Ruby counterparts, therefore nil is returned

def self.default_ext_dir_for base_dir
nil
end

##
# Paths where RubyGems' .rb files and bin files are installed

@@ -63,7 +74,7 @@ def self.default_rubygems_dirs

def self.user_dir
parts = [Gem.user_home, '.gem', ruby_engine]
parts << ConfigMap[:ruby_version] unless ConfigMap[:ruby_version].empty?
parts << RbConfig::CONFIG['ruby_version'] unless RbConfig::CONFIG['ruby_version'].empty?
File.join parts
end

@@ -78,18 +89,18 @@ def self.path_separator
# Default gem load path

def self.default_path
if Gem.user_home && File.exist?(Gem.user_home) then
[user_dir, default_dir]
else
[default_dir]
end
path = []
path << user_dir if user_home && File.exist?(user_home)
path << default_dir
path << vendor_dir if vendor_dir and File.directory? vendor_dir
path
end

##
# Deduce Ruby's --program-prefix and --program-suffix from its install name

def self.default_exec_format
exec_format = ConfigMap[:ruby_install_name].sub('ruby', '%s') rescue '%s'
exec_format = RbConfig::CONFIG['ruby_install_name'].sub('ruby', '%s') rescue '%s'

unless exec_format =~ /%s/ then
raise Gem::Exception,
@@ -106,7 +117,7 @@ def self.default_bindir
if defined? RUBY_FRAMEWORK_VERSION then # mac framework support
'/usr/bin'
else # generic install
ConfigMap[:bindir]
RbConfig::CONFIG['bindir']
end
end

@@ -141,4 +152,26 @@ def self.default_cert_path
def self.default_gems_use_full_paths?
ruby_engine != 'ruby'
end

##
# Install extensions into lib as well as into the extension directory.

def self.install_extension_in_lib # :nodoc:
true
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
59 changes: 40 additions & 19 deletions lib/ruby/shared/rubygems/dependency.rb
Original file line number Diff line number Diff line change
@@ -74,7 +74,7 @@ def hash # :nodoc:
end

def inspect # :nodoc:
if @prerelease
if prerelease? then
"<%s type=%p name=%p requirements=%p prerelease=ok>" %
[self.class, self.type, self.name, requirement.to_s]
else
@@ -145,7 +145,6 @@ def requirement
@requirement = @version_requirements if defined?(@version_requirements)
end

# DOC: this method needs documentation or :nodoc''d
def requirements_list
requirement.as_list
end
@@ -205,9 +204,19 @@ def =~ other

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
name = obj.name
version = obj.version
@@ -216,12 +225,23 @@ def match? obj, version=nil
end

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

# 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
return false unless name === spec.name
@@ -249,8 +269,6 @@ def merge other
self.class.new name, self_req.as_list.concat(other_req.as_list)
end

# DOC: this method needs either documented or :nodoc'd

def matching_specs platform_only = false
matches = Gem::Specification.stubs.find_all { |spec|
self.name === spec.name and # TODO: == instead of ===
@@ -263,7 +281,7 @@ def matching_specs platform_only = false
}
end

matches = matches.sort_by { |s| s.sort_obj } # HACK: shouldn't be needed
matches.sort_by { |s| s.sort_obj } # HACK: shouldn't be needed
end

##
@@ -273,8 +291,6 @@ def specific?
@requirement.specific?
end

# DOC: this method needs either documented or :nodoc'd

def to_specs
matches = matching_specs true

@@ -287,12 +303,13 @@ def to_specs

if specs.empty?
total = Gem::Specification.to_a.size
error = Gem::LoadError.new \
"Could not find '#{name}' (#{requirement}) among #{total} total gem(s)"
msg = "Could not find '#{name}' (#{requirement}) among #{total} total gem(s)\n"
else
error = Gem::LoadError.new \
"Could not find '#{name}' (#{requirement}) - did find: [#{specs.join ','}]"
msg = "Could not find '#{name}' (#{requirement}) - did find: [#{specs.join ','}]\n"
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.requirement = self.requirement
raise error
@@ -303,11 +320,15 @@ def to_specs
matches
end

# DOC: this method needs either documented or :nodoc'd

def to_spec
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
113 changes: 95 additions & 18 deletions lib/ruby/shared/rubygems/dependency_installer.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
require 'rubygems'
require 'rubygems/dependency_list'
require 'rubygems/dependency_resolver'
require 'rubygems/package'
require 'rubygems/installer'
require 'rubygems/spec_fetcher'
@@ -73,6 +72,7 @@ class Gem::DependencyInstaller
def initialize options = {}
@only_install_dir = !!options[:install_dir]
@install_dir = options[:install_dir] || Gem.dir
@build_root = options[:build_root]

options = DEFAULT_OPTIONS.merge options

@@ -103,7 +103,7 @@ def initialize options = {}

@cache_dir = options[:cache_dir] || @install_dir

@errors = nil
@errors = []
end

##
@@ -158,6 +158,7 @@ def add_found_dependencies to_do, dependency_list # :nodoc:

dependency_list.remove_specs_unsatisfied_by dependencies
end

##
# Creates an AvailableSet to install from based on +dep_or_name+ and
# +version+
@@ -196,7 +197,7 @@ def consider_remote?
# sources. Gems are sorted with newer gems preferred over older gems, and
# local gems preferred over remote gems.

def find_gems_with_sources dep # :nodoc:
def find_gems_with_sources dep, best_only=false # :nodoc:
set = Gem::AvailableSet.new

if consider_local?
@@ -211,23 +212,52 @@ def find_gems_with_sources dep # :nodoc:

if consider_remote?
begin
found, errors = Gem::SpecFetcher.fetcher.spec_for_dependency dep
# TODO this is pulled from #spec_for_dependency to allow
# us to filter tuples before fetching specs.
#
tuples, errors = Gem::SpecFetcher.fetcher.search_for_dependency dep

if best_only && !tuples.empty?
tuples.sort! do |a,b|
if b[0].version == a[0].version
if b[0].platform != Gem::Platform::RUBY
1
else
-1
end
else
b[0].version <=> a[0].version
end
end
tuples = [tuples.first]
end

specs = []
tuples.each do |tup, source|
begin
spec = source.fetch_spec(tup)
rescue Gem::RemoteFetcher::FetchError => e
errors << Gem::SourceFetchProblem.new(source, e)
else
specs << [spec, source]
end
end

if @errors
@errors += errors
else
@errors = errors
end

set << found
set << specs

rescue Gem::RemoteFetcher::FetchError => e
# 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
# couldn't find their requested gem.
if Gem.configuration.really_verbose then
say "Error fetching remote data:\t\t#{e.message}"
say "Falling back to local-only install"
verbose do
"Error fetching remote data:\t\t#{e.message}\n" \
"Falling back to local-only install"
end
@domain = :local
end
@@ -250,6 +280,14 @@ def find_spec_by_name_and_version gem_name,
if gem_name =~ /\.gem$/ and File.file? gem_name then
src = Gem::Source::SpecificFile.new(gem_name)
set.add src.spec, src
elsif gem_name =~ /\.gem$/ then
Dir[gem_name].each do |name|
begin
src = Gem::Source::SpecificFile.new name
set.add src.spec, src
rescue Gem::Package::FormatError
end
end
else
local = Gem::Source::Local.new

@@ -263,7 +301,7 @@ def find_spec_by_name_and_version gem_name,
dep = Gem::Dependency.new gem_name, version
dep.prerelease = true if prerelease

set = find_gems_with_sources(dep)
set = find_gems_with_sources(dep, true)
set.match_platform!
end

@@ -278,7 +316,7 @@ def find_spec_by_name_and_version gem_name,
# Gathers all dependencies necessary for the installation from local and
# remote sources unless the ignore_dependencies was given.
#--
# TODO remove, no longer used
# TODO remove at RubyGems 3

def gather_dependencies # :nodoc:
specs = @available.all_specs
@@ -349,13 +387,16 @@ def install dep_or_name, version = Gem::Requirement.default
options = {
:bin_dir => @bin_dir,
:build_args => @build_args,
:document => @document,
:env_shebang => @env_shebang,
:force => @force,
:format_executable => @format_executable,
:ignore_dependencies => @ignore_dependencies,
:prerelease => @prerelease,
:security_policy => @security_policy,
:user_install => @user_install,
:wrappers => @wrappers,
:build_root => @build_root,
:install_as_default => @install_as_default
}
options[:install_dir] = @install_dir if @only_install_dir
@@ -389,23 +430,59 @@ def install_development_deps # :nodoc:
end

def resolve_dependencies dep_or_name, version # :nodoc:
as = available_set_for dep_or_name, version

request_set = as.to_request_set install_development_deps
request_set = Gem::RequestSet.new
request_set.development = @development
request_set.development_shallow = @dev_shallow
request_set.soft_missing = @force
request_set.prerelease = @prerelease
request_set.remote = false unless consider_remote?

installer_set = Gem::DependencyResolver::InstallerSet.new @domain
installer_set.always_install.concat request_set.always_install
installer_set = Gem::Resolver::InstallerSet.new @domain
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
installer_set.ignore_dependencies = true
request_set.soft_missing = true
request_set.ignore_dependencies = true
request_set.soft_missing = true
end

composed_set = Gem::DependencyResolver.compose_sets as, installer_set
request_set.resolve installer_set

request_set.resolve composed_set
@errors.concat request_set.errors

request_set
end
6 changes: 1 addition & 5 deletions lib/ruby/shared/rubygems/dependency_list.rb
Original file line number Diff line number Diff line change
@@ -219,11 +219,7 @@ def tsort_each_child(node)
dependencies.each do |dep|
specs.each do |spec|
if spec.satisfies_requirement? dep then
begin
yield spec
rescue TSort::Cyclic
# do nothing
end
yield spec
break
end
end
254 changes: 0 additions & 254 deletions lib/ruby/shared/rubygems/dependency_resolver.rb

This file was deleted.

109 changes: 0 additions & 109 deletions lib/ruby/shared/rubygems/dependency_resolver/activation_request.rb

This file was deleted.

65 changes: 0 additions & 65 deletions lib/ruby/shared/rubygems/dependency_resolver/api_set.rb

This file was deleted.

39 changes: 0 additions & 39 deletions lib/ruby/shared/rubygems/dependency_resolver/api_specification.rb

This file was deleted.

18 changes: 0 additions & 18 deletions lib/ruby/shared/rubygems/dependency_resolver/composed_set.rb

This file was deleted.

This file was deleted.

Loading

0 comments on commit e3f23d3

Please sign in to comment.