summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authordrbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-07-09 23:21:36 +0000
committerdrbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-07-09 23:21:36 +0000
commit47f0248b0858898dd24d1e654cedf174059ca677 ()
tree493e84160f8609db408d88349f0624a3ff92c3c2 /lib
parentcd9f9e471977447a991ced4ea38efb2309459ef5 (diff)
* lib/rubygems: Import RubyGems 2.1
* test/rubygems: Ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@41873 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--lib/rubygems.rb58
-rw-r--r--lib/rubygems/available_set.rb68
-rw-r--r--lib/rubygems/basic_specification.rb139
-rw-r--r--lib/rubygems/commands/cert_command.rb40
-rw-r--r--lib/rubygems/commands/cleanup_command.rb4
-rw-r--r--lib/rubygems/commands/environment_command.rb21
-rw-r--r--lib/rubygems/commands/help_command.rb20
-rw-r--r--lib/rubygems/commands/install_command.rb17
-rw-r--r--lib/rubygems/commands/owner_command.rb6
-rw-r--r--lib/rubygems/commands/pristine_command.rb19
-rw-r--r--lib/rubygems/commands/sources_command.rb2
-rw-r--r--lib/rubygems/commands/uninstall_command.rb6
-rw-r--r--lib/rubygems/config_file.rb17
-rwxr-xr-xlib/rubygems/core_ext/kernel_require.rb2
-rw-r--r--lib/rubygems/defaults.rb8
-rw-r--r--lib/rubygems/dependency.rb6
-rw-r--r--lib/rubygems/dependency_installer.rb342
-rw-r--r--lib/rubygems/dependency_resolver.rb717
-rw-r--r--lib/rubygems/dependency_resolver/activation_request.rb109
-rw-r--r--lib/rubygems/dependency_resolver/api_set.rb65
-rw-r--r--lib/rubygems/dependency_resolver/api_specification.rb36
-rw-r--r--lib/rubygems/dependency_resolver/composed_set.rb18
-rw-r--r--lib/rubygems/dependency_resolver/current_set.rb16
-rw-r--r--lib/rubygems/dependency_resolver/dependency_conflict.rb85
-rw-r--r--lib/rubygems/dependency_resolver/dependency_request.rb51
-rw-r--r--lib/rubygems/dependency_resolver/index_set.rb59
-rw-r--r--lib/rubygems/dependency_resolver/index_specification.rb53
-rw-r--r--lib/rubygems/dependency_resolver/installed_specification.rb38
-rw-r--r--lib/rubygems/dependency_resolver/installer_set.rb130
-rw-r--r--lib/rubygems/exceptions.rb81
-rw-r--r--lib/rubygems/ext/builder.rb2
-rw-r--r--lib/rubygems/gem_runner.rb26
-rw-r--r--lib/rubygems/gemcutter_utilities.rb111
-rw-r--r--lib/rubygems/install_default_message.rb12
-rw-r--r--lib/rubygems/install_update_options.rb3
-rw-r--r--lib/rubygems/installer.rb62
-rw-r--r--lib/rubygems/name_tuple.rb25
-rw-r--r--lib/rubygems/package.rb73
-rw-r--r--lib/rubygems/package/tar_test_case.rb18
-rw-r--r--lib/rubygems/package/tar_writer.rb47
-rw-r--r--lib/rubygems/path_support.rb8
-rw-r--r--lib/rubygems/platform.rb8
-rw-r--r--lib/rubygems/remote_fetcher.rb261
-rw-r--r--lib/rubygems/request.rb262
-rw-r--r--lib/rubygems/request_set.rb248
-rw-r--r--lib/rubygems/request_set/gem_dependency_api.rb39
-rw-r--r--lib/rubygems/security.rb55
-rw-r--r--lib/rubygems/security/policy.rb44
-rw-r--r--lib/rubygems/security/signer.rb4
-rw-r--r--lib/rubygems/source.rb32
-rw-r--r--lib/rubygems/source/installed.rb28
-rw-r--r--lib/rubygems/source/local.rb122
-rw-r--r--lib/rubygems/source/specific_file.rb28
-rw-r--r--lib/rubygems/source_local.rb91
-rw-r--r--lib/rubygems/source_specific_file.rb28
-rw-r--r--lib/rubygems/spec_fetcher.rb1
-rw-r--r--lib/rubygems/specification.rb256
-rw-r--r--lib/rubygems/stub_specification.rb112
-rw-r--r--lib/rubygems/test_case.rb155
-rw-r--r--lib/rubygems/uninstaller.rb23
-rw-r--r--lib/rubygems/uri_formatter.rb39
-rw-r--r--lib/rubygems/util/list.rb44
-rw-r--r--lib/rubygems/version.rb16
-rw-r--r--lib/rubygems/version_option.rb10
64 files changed, 2958 insertions, 1568 deletions
@@ -8,7 +8,7 @@
require 'rbconfig'
module Gem
- VERSION = '2.0.4'
end
# Must be first since it unloads the prelude from 1.9.2
@@ -143,6 +143,14 @@ module Gem
specifications
]
@@win_platform = nil
@configuration = nil
@@ -379,6 +387,10 @@ module Gem
paths.path
end
##
# Quietly ensure the Gem directory +dir+ contains all the proper
# subdirectories. If we can't create a directory due to a permission
@@ -389,6 +401,23 @@ module Gem
# World-writable directories will never be created.
def self.ensure_gem_subdirectories dir = Gem.dir, mode = nil
old_umask = File.umask
File.umask old_umask | 002
@@ -398,7 +427,7 @@ module Gem
options[:mode] = mode if mode
- REPOSITORY_SUBDIRECTORIES.each do |name|
subdir = File.join dir, name
next if File.exist? subdir
FileUtils.mkdir_p subdir, options rescue nil
@@ -971,10 +1000,33 @@ module Gem
attr_reader :loaded_specs
##
- # Register a Gem::Specification for default gem
def register_default_spec(spec)
spec.files.each do |file|
@path_to_default_spec_map[file] = spec
end
end
@@ -1,4 +1,7 @@
class Gem::AvailableSet
Tuple = Struct.new(:spec, :source)
def initialize
@@ -36,6 +39,28 @@ class Gem::AvailableSet
self
end
def empty?
@set.empty?
end
@@ -66,6 +91,49 @@ class Gem::AvailableSet
f.source
end
def pick_best!
return self if empty?
@@ -0,0 +1,139 @@
@@ -1,6 +1,11 @@
require 'rubygems/command'
require 'rubygems/security'
-require 'openssl'
class Gem::Commands::CertCommand < Gem::Command
@@ -21,7 +26,8 @@ class Gem::Commands::CertCommand < Gem::Command
OptionParser.accept OpenSSL::PKey::RSA do |key_file|
begin
- key = OpenSSL::PKey::RSA.new File.read key_file
rescue Errno::ENOENT
raise OptionParser::InvalidArgument, "#{key_file}: does not exist"
rescue OpenSSL::PKey::RSAError
@@ -115,16 +121,31 @@ class Gem::Commands::CertCommand < Gem::Command
end
def build name
- key = options[:key] || Gem::Security.create_key
- cert = Gem::Security.create_cert_email name, key
- key_path = Gem::Security.write key, "gem-private_key.pem"
cert_path = Gem::Security.write cert, "gem-public_cert.pem"
say "Certificate: #{cert_path}"
- say "Private Key: #{key_path}"
- say "Don't forget to move the key file to somewhere private!"
end
def certificates_matching filter
@@ -198,7 +219,8 @@ For further reading on signing gems see `ri Gem::Security`.
def load_default_key
key_file = File.join Gem.default_key_path
key = File.read key_file
- options[:key] = OpenSSL::PKey::RSA.new key
rescue Errno::ENOENT
alert_error \
"--private-key not specified and ~/.gem/gem-private_key.pem does not exist"
@@ -225,5 +247,5 @@ For further reading on signing gems see `ri Gem::Security`.
Gem::Security.write cert, cert_file, permissions
end
-end
@@ -9,7 +9,8 @@ class Gem::Commands::CleanupCommand < Gem::Command
'Clean up old versions of installed gems in the local repository',
:force => false, :install_dir => Gem.dir
- add_option('-d', '--dryrun', "") do |value, options|
options[:dryrun] = true
end
@@ -162,4 +163,3 @@ are not removed.
end
end
-
@@ -99,6 +99,8 @@ lib/rubygems/defaults/operating_system.rb
out << " - EXECUTABLE DIRECTORY: #{Gem.bindir}\n"
out << " - RUBYGEMS PLATFORMS:\n"
Gem.platforms.each do |platform|
out << " - #{platform}\n"
@@ -107,11 +109,9 @@ lib/rubygems/defaults/operating_system.rb
out << " - GEM PATHS:\n"
out << " - #{Gem.dir}\n"
- path = Gem.path.dup
- path.delete Gem.dir
- path.each do |p|
- out << " - #{p}\n"
- end
out << " - GEM CONFIGURATION:\n"
Gem.configuration.each do |name, value|
@@ -124,6 +124,11 @@ lib/rubygems/defaults/operating_system.rb
out << " - #{s}\n"
end
else
raise Gem::CommandLineError, "Unknown environment option [#{arg}]"
end
@@ -131,5 +136,11 @@ lib/rubygems/defaults/operating_system.rb
true
end
end
@@ -46,6 +46,10 @@ Some examples of 'gem' usage.
* Update all gems on your system:
gem update
EOF
PLATFORMS = <<-'EOF'
@@ -55,8 +59,9 @@ your current platform by running `gem environment`.
RubyGems matches platforms as follows:
- * The CPU must match exactly, unless one of the platforms has
- "universal" as the CPU.
* The OS must match exactly.
* The versions must match exactly unless one of the versions is nil.
@@ -66,11 +71,20 @@ you pass must match "#{cpu}-#{os}" or "#{cpu}-#{os}-#{version}". On mswin
platforms, the version is the compiler version, not the OS version. (Ruby
compiled with VC6 uses "60" as the compiler version, VC8 uses "80".)
Example platforms:
x86-freebsd # Any FreeBSD version on an x86 CPU
universal-darwin-8 # Darwin 8 only gems that run on any CPU
x86-mswin32-80 # Windows gems compiled with VC8
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
@@ -119,7 +133,7 @@ platform.
if command then
command.summary
else
- "[No command found for #{cmd_name}, bug?]"
end
summary = wrap(summary, summary_width).split "\n"
@@ -4,8 +4,6 @@ require 'rubygems/dependency_installer'
require 'rubygems/local_remote_options'
require 'rubygems/validator'
require 'rubygems/version_option'
-require 'rubygems/install_message' # must come before rdoc for messaging
-require 'rubygems/rdoc'
##
# Gem installer command line tool
@@ -39,6 +37,12 @@ class Gem::Commands::InstallCommand < Gem::Command
'install the listed gems') do |v,o|
o[:gemdeps] = v
end
@installed_specs = nil
end
@@ -153,7 +157,14 @@ to write the specification by hand. For example:
alert_error "Can't use --version w/ multiple gems. Use name:ver instead."
terminate_interaction 1
end
-
get_all_gem_names_and_versions.each do |gem_name, gem_version|
gem_version ||= options[:version]
@@ -31,9 +31,15 @@ class Gem::Commands::OwnerCommand < Gem::Command
add_option '-r', '--remove EMAIL', 'Remove an owner' do |value, options|
options[:remove] << value
end
end
def execute
sign_in
name = get_one_gem_name
@@ -30,6 +30,12 @@ class Gem::Commands::PristineCommand < Gem::Command
options[:only_executables] = value
end
add_version_option('restore to', 'pristine condition')
end
@@ -104,16 +110,21 @@ with extensions.
Gem::RemoteFetcher.fetcher.download_to_cache dep
end
- # TODO use installer options
- install_defaults = Gem::ConfigFile::PLATFORM_DEFAULTS['install']
- installer_env_shebang = install_defaults.to_s['--env-shebang']
installer = Gem::Installer.new(gem,
:wrappers => true,
:force => true,
:install_dir => spec.base_dir,
- :env_shebang => installer_env_shebang,
:build_args => spec.build_args)
if options[:only_executables] then
installer.generate_bin
else
@@ -48,7 +48,7 @@ class Gem::Commands::SourcesCommand < Gem::Command
options[:update])
if options[:clear_all] then
- path = File.join Gem.user_home, '.gem', 'specs'
FileUtils.rm_rf path
unless File.exist? path then
@@ -67,6 +67,12 @@ class Gem::Commands::UninstallCommand < Gem::Command
options[:force] = value
end
add_version_option
add_platform_option
end
@@ -141,6 +141,11 @@ class Gem::ConfigFile
attr_reader :ssl_ca_cert
##
# Create the config file object. +args+ is the list of arguments
# from the command line.
#
@@ -210,6 +215,7 @@ class Gem::ConfigFile
@ssl_verify_mode = @hash[:ssl_verify_mode] if @hash.key? :ssl_verify_mode
@ssl_ca_cert = @hash[:ssl_ca_cert] if @hash.key? :ssl_ca_cert
@api_keys = nil
@rubygems_api_key = nil
@@ -246,6 +252,10 @@ Your gem push credentials file located at:
has file permissions of 0#{existing_permissions.to_s 8} but 0600 is required.
You should reset your credentials at:
\thttps://rubygems.org/profile/edit
@@ -309,6 +319,9 @@ if you believe they were disclosed to a third party.
@rubygems_api_key = api_key
end
def load_file(filename)
Gem.load_yaml
@@ -321,8 +334,8 @@ if you believe they were disclosed to a third party.
return {}
end
return content
- rescue ArgumentError
- warn "Failed to load #{filename}"
rescue Errno::EACCES
warn "Failed to load #{filename} due to permissions problem."
end
@@ -57,7 +57,7 @@ module Kernel
#--
# TODO request access to the C implementation of this to speed up RubyGems
- spec = Gem::Specification.find { |s|
s.activated? and s.contains_requirable_file? path
}
@@ -15,6 +15,14 @@ module Gem
end
##
# Default home directory path to be used if an alternate value is not
# specified in the environment
@@ -203,6 +203,8 @@ class Gem::Dependency
requirement.satisfied_by? version
end
# DOC: this method needs either documented or :nodoc'd
def match? obj, version=nil
@@ -250,10 +252,10 @@ class Gem::Dependency
# DOC: this method needs either documented or :nodoc'd
def matching_specs platform_only = false
- matches = Gem::Specification.find_all { |spec|
self.name === spec.name and # TODO: == instead of ===
requirement.satisfied_by? spec.version
- }
if platform_only
matches.reject! { |spec|
@@ -1,11 +1,12 @@
require 'rubygems'
require 'rubygems/dependency_list'
require 'rubygems/package'
require 'rubygems/installer'
require 'rubygems/spec_fetcher'
require 'rubygems/user_interaction'
-require 'rubygems/source_local'
-require 'rubygems/source_specific_file'
require 'rubygems/available_set'
##
@@ -15,15 +16,7 @@ class Gem::DependencyInstaller
include Gem::UserInteraction
- attr_reader :gems_to_install
- attr_reader :installed_gems
-
- ##
- # Documentation types. For use by the Gem.done_installing hook
-
- attr_reader :document
-
- DEFAULT_OPTIONS = {
:env_shebang => false,
:document => %w[ri],
:domain => :both, # HACK dup
@@ -35,9 +28,31 @@ class Gem::DependencyInstaller
:wrappers => true,
:build_args => nil,
:build_docs_in_background => false,
}.freeze
##
# Creates a new installer instance.
#
# Options are:
@@ -56,7 +71,8 @@ class Gem::DependencyInstaller
# :wrappers:: See Gem::Installer::new
# :build_args:: See Gem::Installer::new
- def initialize(options = {})
@install_dir = options[:install_dir] || Gem.dir
if options[:install_dir] then
@@ -82,6 +98,7 @@ class Gem::DependencyInstaller
@wrappers = options[:wrappers]
@build_args = options[:build_args]
@build_docs_in_background = options[:build_docs_in_background]
# Indicates that we should not try to update any deps unless
# we absolutely must.
@@ -93,13 +110,61 @@ class Gem::DependencyInstaller
@cache_dir = options[:cache_dir] || @install_dir
- # Set with any errors that SpecFetcher finds while search through
- # gemspecs for a dep
@errors = nil
end
- attr_reader :errors
##
# Creates an AvailableSet to install from based on +dep_or_name+ and
# +version+
@@ -138,7 +203,7 @@ class Gem::DependencyInstaller
# sources. Gems are sorted with newer gems preferred over older gems, and
# local gems preferred over remote gems.
- def find_gems_with_sources(dep)
set = Gem::AvailableSet.new
if consider_local?
@@ -179,10 +244,52 @@ class Gem::DependencyInstaller
end
##
# Gathers all dependencies necessary for the installation from local and
# remote sources unless the ignore_dependencies was given.
- def gather_dependencies
specs = @available.all_specs
# these gems were listed by the user, always install them
@@ -214,93 +321,19 @@ class Gem::DependencyInstaller
@gems_to_install = dependency_list.dependency_order.reverse
end
- def add_found_dependencies to_do, dependency_list
- seen = {}
- dependencies = Hash.new { |h, name| h[name] = Gem::Dependency.new name }
-
- until to_do.empty? do
- spec = to_do.shift
-
- # HACK why is spec nil?
- next if spec.nil? or seen[spec.name]
- seen[spec.name] = true
-
- deps = spec.runtime_dependencies
-
- if @development
- if @dev_shallow
- if @toplevel_specs.include? spec.full_name
- deps |= spec.development_dependencies
- end
- else
- deps |= spec.development_dependencies
- end
- end
-
- deps.each do |dep|
- dependencies[dep.name] = dependencies[dep.name].merge dep
-
- if @minimal_deps
- next if Gem::Specification.any? do |installed_spec|
- dep.name == installed_spec.name and
- dep.requirement.satisfied_by? installed_spec.version
- end
- end
-
- results = find_gems_with_sources(dep)
-
- results.sorted.each do |t|
- to_do.push t.spec
- end
-
- results.remove_installed! dep
-
- @available << results
- results.inject_into_list dependency_list
- end
- end
-
- dependency_list.remove_specs_unsatisfied_by dependencies
- end
-
- ##
- # Finds a spec and the source_uri it came from for gem +gem_name+ and
- # +version+. Returns an Array of specs and sources required for
- # installation of the gem.
-
- def find_spec_by_name_and_version(gem_name,
- version = Gem::Requirement.default,
- prerelease = false)
-
- set = Gem::AvailableSet.new
-
- if consider_local?
- if gem_name =~ /\.gem$/ and File.file? gem_name then
- src = Gem::Source::SpecificFile.new(gem_name)
- set.add src.spec, src
- else
- local = Gem::Source::Local.new
-
- if s = local.find_gem(gem_name, version)
- set.add s, local
end
end
end
-
- if set.empty?
- dep = Gem::Dependency.new gem_name, version
- # HACK Dependency objects should be immutable
- dep.prerelease = true if prerelease
-
- set = find_gems_with_sources(dep)
- set.match_platform!
- end
-
- if set.empty?
- raise Gem::SpecificGemNotFoundException.new(gem_name, version, @errors)
- end
-
- @available = set
end
##
@@ -318,61 +351,30 @@ class Gem::DependencyInstaller
# separately.
def install dep_or_name, version = Gem::Requirement.default
- available_set_for dep_or_name, version
@installed_gems = []
- gather_dependencies
-
- # REFACTOR is the last gem always the one that the user requested?
- # This code assumes that but is that actually validated by the code?
-
- last = @gems_to_install.size - 1
- @gems_to_install.each_with_index do |spec, index|
- # REFACTOR more current spec set hardcoding, should be abstracted?
- next if Gem::Specification.include?(spec) and index != last
-
- # TODO: make this sorta_verbose so other users can benefit from it
- say "Installing gem #{spec.full_name}" if Gem.configuration.really_verbose
-
- source = @available.source_for spec
-
- begin
- # REFACTOR make the fetcher to use configurable
- local_gem_path = source.download spec, @cache_dir
- rescue Gem::RemoteFetcher::FetchError
- # TODO I doubt all fetch errors are recoverable, we should at least
- # report the errors probably.
- next if @force
- raise
- end
-
- if @development
- if @dev_shallow
- is_dev = @toplevel_specs.include? spec.full_name
- else
- is_dev = true
- end
- end
- inst = Gem::Installer.new local_gem_path,
- :bin_dir => @bin_dir,
- :development => is_dev,
- :env_shebang => @env_shebang,
- :force => @force,
- :format_executable => @format_executable,
- :ignore_dependencies => @ignore_dependencies,
- :install_dir => @install_dir,
- :security_policy => @security_policy,
- :user_install => @user_install,
- :wrappers => @wrappers,
- :build_args => @build_args
-
- spec = inst.install
-
- @installed_gems << spec
end
# Since this is currently only called for docs, we can be lazy and just say
# it's documentation. Ideally the hook adder could decide whether to be in
# the background or not, and what to call it.
@@ -385,18 +387,34 @@ class Gem::DependencyInstaller
@installed_gems
end
- def in_background what
- fork_happened = false
- if @build_docs_in_background and Process.respond_to?(:fork)
- begin
- Process.fork do
- yield
- end
- fork_happened = true
- say "#{what} in a background process."
- rescue NotImplementedError
- end
end
- yield unless fork_happened
end
end
@@ -1,575 +1,240 @@
require 'rubygems'
require 'rubygems/dependency'
require 'rubygems/exceptions'
require 'uri'
require 'net/http'
-module Gem
- # Raised when a DependencyConflict reaches the toplevel.
- # Indicates which dependencies were incompatible.
- #
- class DependencyResolutionError < Gem::Exception
- def initialize(conflict)
- @conflict = conflict
- a, b = conflicting_dependencies
- super "unable to resolve conflicting dependencies '#{a}' and '#{b}'"
- end
- attr_reader :conflict
- def conflicting_dependencies
- @conflict.conflicting_dependencies
- end
- end
- # Raised when a dependency requests a gem for which there is
- # no spec.
- #
- class UnsatisfiableDepedencyError < Gem::Exception
- def initialize(dep)
- super "unable to find any gem matching dependency '#{dep}'"
- @dependency = dep
- end
- attr_reader :dependency
- end
- # Raised when dependencies conflict and create the inability to
- # find a valid possible spec for a request.
- #
- class ImpossibleDependenciesError < Gem::Exception
- def initialize(request, conflicts)
- s = conflicts.size == 1 ? "" : "s"
- super "detected #{conflicts.size} conflict#{s} with dependency '#{request.dependency}'"
- @request = request
- @conflicts = conflicts
- end
- def dependency
- @request.dependency
- end
- attr_reader :conflicts
end
- # Given a set of Gem::Dependency objects as +needed+ and a way
- # to query the set of available specs via +set+, calculates
- # a set of ActivationRequest objects which indicate all the specs
- # that should be activated to meet the all the requirements.
#
- class DependencyResolver
-
- # Represents a specification retrieved via the rubygems.org
- # API. This is used to avoid having to load the full
- # Specification object when all we need is the name, version,
- # and dependencies.
- #
- class APISpecification
- attr_reader :set # :nodoc:
-
- def initialize(set, api_data)
- @set = set
- @name = api_data[:name]
- @version = Gem::Version.new api_data[:number]
- @dependencies = api_data[:dependencies].map do |name, ver|
- Gem::Dependency.new name, ver.split(/\s*,\s*/)
- end
- end
-
- attr_reader :name, :version, :dependencies
-
- def == other # :nodoc:
- self.class === other and
- @set == other.set and
- @name == other.name and
- @version == other.version and
- @dependencies == other.dependencies
- end
-
- def full_name
- "#{@name}-#{@version}"
- end
- end
-
- # The global rubygems pool, available via the rubygems.org API.
- # Returns instances of APISpecification.
- #
- class APISet
- def initialize
- @data = Hash.new { |h,k| h[k] = [] }
- @dep_uri = URI 'https://rubygems.org/api/v1/dependencies'
- end
-
- # Return data for all versions of the gem +name+.
- #
- def versions(name)
- if @data.key?(name)
- return @data[name]
- end
-
- uri = @dep_uri + "?gems=#{name}"
- str = Gem::RemoteFetcher.fetcher.fetch_path uri
-
- Marshal.load(str).each do |ver|
- @data[ver[:name]] << ver
- end
-
- @data[name]
- end
-
- # Return an array of APISpecification objects matching
- # DependencyRequest +req+.
- #
- def find_all(req)
- res = []
-
- versions(req.name).each do |ver|
- if req.dependency.match? req.name, ver[:number]
- res << APISpecification.new(self, ver)
- end
- end
-
- res
- end
-
- # A hint run by the resolver to allow the Set to fetch
- # data for DependencyRequests +reqs+.
- #
- def prefetch(reqs)
- names = reqs.map { |r| r.dependency.name }
- needed = names.find_all { |d| [email protected]?(d) }
-
- return if needed.empty?
-
- uri = @dep_uri + "?gems=#{needed.sort.join ','}"
- str = Gem::RemoteFetcher.fetcher.fetch_path uri
-
- Marshal.load(str).each do |ver|
- @data[ver[:name]] << ver
- end
- end
- end
-
- # Represents a possible Specification object returned
- # from IndexSet. Used to delay needed to download full
- # Specification objects when only the +name+ and +version+
- # are needed.
- #
- class IndexSpecification
- def initialize(set, name, version, source, plat)
- @set = set
- @name = name
- @version = version
- @source = source
- @platform = plat
-
- @spec = nil
- end
-
- attr_reader :name, :version, :source
-
- def full_name
- "#{@name}-#{@version}"
- end
-
- def spec
- @spec ||= @set.load_spec(@name, @version, @source)
- end
-
- def dependencies
- spec.dependencies
- end
- end
-
- # The global rubygems pool represented via the traditional
- # source index.
- #
- class IndexSet
- def initialize
- @f = Gem::SpecFetcher.fetcher
-
- @all = Hash.new { |h,k| h[k] = [] }
-
- list, _ = @f.available_specs(:released)
- list.each do |uri, specs|
- specs.each do |n|
- @all[n.name] << [uri, n]
- end
- end
-
- @specs = {}
- end
-
- # Return an array of IndexSpecification objects matching
- # DependencyRequest +req+.
- #
- def find_all(req)
- res = []
-
- name = req.dependency.name
-
- @all[name].each do |uri, n|
- if req.dependency.match? n
- res << IndexSpecification.new(self, n.name, n.version,
- uri, n.platform)
- end
- end
-
- res
- end
-
- # No prefetching needed since we load the whole index in
- # initially.
- #
- def prefetch(gems)
- end
-
- # Called from IndexSpecification to get a true Specification
- # object.
- #
- def load_spec(name, ver, source)
- key = "#{name}-#{ver}"
- @specs[key] ||= source.fetch_spec(Gem::NameTuple.new(name, ver))
- end
- end
-
- # A set which represents the installed gems. Respects
- # all the normal settings that control where to look
- # for installed gems.
- #
- class CurrentSet
- def find_all(req)
- req.dependency.matching_specs
- end
-
- def prefetch(gems)
- end
- end
-
- # Create DependencyResolver object which will resolve
- # the tree starting with +needed+ Depedency objects.
- #
- # +set+ is an object that provides where to look for
- # specifications to satisify the Dependencies. This
- # defaults to IndexSet, which will query rubygems.org.
- #
- def initialize(needed, set=IndexSet.new)
- @set = set || IndexSet.new # Allow nil to mean IndexSet
- @needed = needed
-
- @conflicts = nil
- end
-
- # Provide a DependencyResolver that queries only against
- # the already installed gems.
- #
- def self.for_current_gems(needed)
- new needed, CurrentSet.new
- end
-
- # Contains all the conflicts encountered while doing resolution
- #
- attr_reader :conflicts
-
- # Proceed with resolution! Returns an array of ActivationRequest
- # objects.
- #
- def resolve
- @conflicts = []
-
- needed = @needed.map { |n| DependencyRequest.new(n, nil) }
-
- res = resolve_for needed, []
-
- if res.kind_of? DependencyConflict
- raise DependencyResolutionError.new(res)
- end
-
- res
- end
-
- # Used internally to indicate that a dependency conflicted
- # with a spec that would be activated.
- #
- class DependencyConflict
- def initialize(dependency, activated, failed_dep=dependency)
- @dependency = dependency
- @activated = activated
- @failed_dep = failed_dep
- end
-
- attr_reader :dependency, :activated
-
- # Return the Specification that listed the dependency
- #
- def requester
- @failed_dep.requester
- end
-
- def for_spec?(spec)
- @dependency.name == spec.name
- end
- # Return the 2 dependency objects that conflicted
- #
- def conflicting_dependencies
- [@failed_dep.dependency, @activated.request.dependency]
- end
end
- # Used Internally. Wraps a Depedency object to also track
- # which spec contained the Dependency.
- #
- class DependencyRequest
- def initialize(dep, act)
- @dependency = dep
- @requester = act
- end
- attr_reader :dependency, :requester
- def name
- @dependency.name
- end
- def matches_spec?(spec)
- @dependency.matches_spec? spec
- end
- def to_s
- @dependency.to_s
- end
- def ==(other)
- case other
- when Dependency
- @dependency == other
- when DependencyRequest
- @dependency == other.dependency && @requester == other.requester
- else
- false
- end
- end
end
- # Specifies a Specification object that should be activated.
- # Also contains a dependency that was used to introduce this
- # activation.
- #
- class ActivationRequest
- def initialize(spec, req, others_possible=true)
- @spec = spec
- @request = req
- @others_possible = others_possible
- end
-
- attr_reader :spec, :request
- # Indicate if this activation is one of a set of possible
- # requests for the same Dependency request.
- #
- def others_possible?
- @others_possible
- end
- # Return the ActivationRequest that contained the dependency
- # that we were activated for.
- #
- def parent
- @request.requester
- end
-
- def name
- @spec.name
- end
-
- def full_name
- @spec.full_name
- end
-
- def version
- @spec.version
- end
-
- def full_spec
- Gem::Specification === @spec ? @spec : @spec.spec
- end
- def download(path)
- if @spec.respond_to? :source
- source = @spec.source
else
- source = Gem.sources.first
end
- Gem.ensure_gem_subdirectories path
-
- source.download full_spec, path
- end
-
- def ==(other)
- case other
- when Gem::Specification
- @spec == other
- when ActivationRequest
- @spec == other.spec && @request == other.request
- else
- false
- end
end
- ##
- # Indicates if the requested gem has already been installed.
- def installed?
- this_spec = full_spec
- Gem::Specification.any? do |s|
- s == this_spec
end
- end
- end
-
- def requests(s, act)
- reqs = []
- s.dependencies.each do |d|
- next unless d.type == :runtime
- reqs << DependencyRequest.new(d, act)
- end
-
- @set.prefetch(reqs)
-
- reqs
- end
-
- # The meat of the algorithm. Given +needed+ DependencyRequest objects
- # and +specs+ being a list to ActivationRequest, calculate a new list
- # of ActivationRequest objects.
- #
- def resolve_for(needed, specs)
- until needed.empty?
- dep = needed.shift
-
- # If there is already a spec activated for the requested name...
- if existing = specs.find { |s| dep.name == s.name }
-
- # then we're done since this new dep matches the
- # existing spec.
- next if dep.matches_spec? existing
-
- # There is a conflict! We return the conflict
- # object which will be seen by the caller and be
- # handled at the right level.
-
- # If the existing activation indicates that there
- # are other possibles for it, then issue the conflict
- # on the dep for the activation itself. Otherwise, issue
- # it on the requester's request itself.
- #
- if existing.others_possible?
- conflict = DependencyConflict.new(dep, existing)
else
- depreq = existing.request.requester.request
- conflict = DependencyConflict.new(depreq, existing, dep)
end
- @conflicts << conflict
-
- return conflict
end
- # Get a list of all specs that satisfy dep
- possible = @set.find_all(dep)
-
- case possible.size
- when 0
- # If there are none, then our work here is done.
- raise UnsatisfiableDepedencyError.new(dep)
- when 1
- # If there is one, then we just add it to specs
- # and process the specs dependencies by adding
- # them to needed.
-
- spec = possible.first
- act = ActivationRequest.new(spec, dep, false)
-
- specs << act
-
- # Put the deps for at the beginning of needed
- # rather than the end to match the depth first
- # searching done by the multiple case code below.
- #
- # This keeps the error messages consistent.
- needed = requests(spec, act) + needed
- else
- # There are multiple specs for this dep. This is
- # the case that this class is built to handle.
-
- # Sort them so that we try the highest versions
- # first.
- possible = possible.sort_by { |s| s.version }
-
- # We track the conflicts seen so that we can report them
- # to help the user figure out how to fix the situation.
- conflicts = []
-
- # To figure out which to pick, we keep resolving
- # given each one being activated and if there isn't
- # a conflict, we know we've found a full set.
- #
- # We use an until loop rather than #reverse_each
- # to keep the stack short since we're using a recursive
- # algorithm.
- #
- until possible.empty?
- s = possible.pop
-
- # Recursively call #resolve_for with this spec
- # and add it's dependencies into the picture...
-
- act = ActivationRequest.new(s, dep)
-
- try = requests(s, act) + needed
-
- res = resolve_for(try, specs + [act])
-
- # While trying to resolve these dependencies, there may
- # be a conflict!
-
- if res.kind_of? DependencyConflict
- # The conflict might be created not by this invocation
- # but rather one up the stack, so if we can't attempt
- # to resolve this conflict (conflict isn't with the spec +s+)
- # then just return it so the caller can try to sort it out.
- return res unless res.for_spec? s
-
- # Otherwise, this is a conflict that we can attempt to fix
- conflicts << [s, res]
-
- # Optimization:
- #
- # Because the conflict indicates the dependency that trigger
- # it, we can prune possible based on this new information.
- #
- # This cuts down on the number of iterations needed.
- possible.delete_if { |x| !res.dependency.matches_spec? x }
- else
- # No conflict, return the specs
- return res
- end
- end
-
- # We tried all possibles and nothing worked, so we let the user
- # know and include as much information about the problem since
- # the user is going to have to take action to fix this.
- raise ImpossibleDependenciesError.new(dep, conflicts)
- end
end
-
- specs
end
end
end
@@ -0,0 +1,109 @@
@@ -0,0 +1,65 @@
@@ -0,0 +1,36 @@
@@ -0,0 +1,18 @@
@@ -0,0 +1,16 @@
@@ -0,0 +1,85 @@
@@ -0,0 +1,51 @@
@@ -0,0 +1,59 @@
@@ -0,0 +1,53 @@
@@ -0,0 +1,38 @@
@@ -0,0 +1,130 @@
@@ -17,6 +17,28 @@ class Gem::DependencyError < Gem::Exception; end
class Gem::DependencyRemovalException < Gem::Exception; end
##
# Raised when attempting to uninstall a gem that isn't in GEM_HOME.
class Gem::GemNotInHomeException < Gem::Exception
@@ -65,6 +87,42 @@ class Gem::SpecificGemNotFoundException < Gem::GemNotFoundException
attr_reader :name, :version, :errors
end
class Gem::InstallError < Gem::Exception; end
##
@@ -107,3 +165,26 @@ class Gem::SystemExitException < SystemExit
end
@@ -18,7 +18,7 @@ class Gem::Ext::Builder
# try to find make program from Ruby configure arguments first
RbConfig::CONFIG['configure_args'] =~ /with-make-prog\=(\w+)/
- make_program = $1 || ENV['MAKE'] || ENV['make']
unless make_program then
make_program = (/mswin/ =~ RUBY_PLATFORM) ? 'nmake' : 'make'
end
@@ -33,17 +33,11 @@ class Gem::GemRunner
##
# Run the gem command with the following arguments.
- def run(args)
- if args.include?('--')
- # We need to preserve the original ARGV to use for passing gem options
- # to source gems. If there is a -- in the line, strip all options after
- # it...its for the source building process.
- # TODO use slice!
- build_args = args[args.index("--") + 1...args.length]
- args = args[0...args.index("--")]
- end
do_configuration args
cmd = @command_manager_class.instance
cmd.command_names.each do |command_name|
@@ -60,6 +54,20 @@ class Gem::GemRunner
cmd.run Gem.configuration.args, build_args
end
private
def do_configuration(args)
@@ -1,11 +1,17 @@
require 'rubygems/remote_fetcher'
module Gem::GemcutterUtilities
# TODO: move to Gem::Command
OptionParser.accept Symbol do |value|
value.to_sym
end
##
# Add the --key option
@@ -17,6 +23,9 @@ module Gem::GemcutterUtilities
end
end
def api_key
if options[:key] then
verify_api_key options[:key]
@@ -27,6 +36,47 @@ module Gem::GemcutterUtilities
end
end
def sign_in sign_in_host = self.host
return if Gem.configuration.rubygems_api_key
@@ -55,47 +105,36 @@ module Gem::GemcutterUtilities
end
end
- attr_writer :host
- def host
- configured_host = Gem.host unless
- Gem.configuration.disable_default_gem_server
-
- @host ||=
- begin
- env_rubygems_host = ENV['RUBYGEMS_HOST']
- env_rubygems_host = nil if
- env_rubygems_host and env_rubygems_host.empty?
-
- env_rubygems_host|| configured_host
- end
- end
-
- def rubygems_api_request(method, path, host = nil, &block)
- require 'net/http'
- self.host = host if host
- unless self.host
- alert_error "You must specify a gem server"
terminate_interaction 1 # TODO: question this
end
-
- uri = URI.parse "#{self.host}/#{path}"
-
- request_method = Net::HTTP.const_get method.to_s.capitalize
-
- Gem::RemoteFetcher.fetcher.request(uri, request_method, &block)
end
- def with_response resp, error_prefix = nil
- case resp
when Net::HTTPSuccess then
if block_given? then
- yield resp
else
- say resp.body
end
else
- message = resp.body
message = "#{error_prefix}: #{message}" if error_prefix
say message
@@ -103,13 +142,5 @@ module Gem::GemcutterUtilities
end
end
- def verify_api_key(key)
- if Gem.configuration.api_keys.key? key then
- Gem.configuration.api_keys[key]
- else
- alert_error "No such API key. Please add it to your configuration (done automatically on initial `gem push`)."
- terminate_interaction 1 # TODO: question this
- end
- end
-
end
@@ -0,0 +1,12 @@
@@ -26,6 +26,9 @@ module Gem::InstallUpdateOptions
OptionParser.accept Gem::Security::Policy do |value|
require 'rubygems/security'
value = Gem::Security::Policies[value]
valid = Gem::Security::Policies.keys.sort
message = "#{value} (#{valid.join ', '} are valid)"
@@ -212,16 +212,21 @@ class Gem::Installer
FileUtils.rm_rf gem_dir
FileUtils.mkdir_p gem_dir
-
- extract_files
-
- build_extensions
- write_build_info_file
- run_post_build_hooks
-
- generate_bin
- write_spec
- write_cache_file
say spec.post_install_message unless spec.post_install_message.nil?
@@ -327,6 +332,14 @@ class Gem::Installer
end
##
# Writes the .gemspec specification (in Ruby) to the gem home's
# specifications directory.
@@ -336,6 +349,16 @@ class Gem::Installer
file.fsync rescue nil # for filesystems without fsync(2)
end
end
##
# Creates windows .bat files for easy running of commands
@@ -538,13 +561,13 @@ class Gem::Installer
:bin_dir => nil,
:env_shebang => false,
:force => false,
- :install_dir => Gem.dir,
:only_install_dir => false
}.merge options
@env_shebang = options[:env_shebang]
@force = options[:force]
- @gem_home = options[:install_dir]
@ignore_dependencies = options[:ignore_dependencies]
@format_executable = options[:format_executable]
@security_policy = options[:security_policy]
@@ -715,6 +738,15 @@ EOF
def extract_files
@package.extract_files gem_dir
end
##
# Prefix and suffix the program filename the same as ruby.
@@ -756,7 +788,11 @@ EOF
ensure_loadable_spec
- Gem.ensure_gem_subdirectories gem_home
return true if @force
@@ -43,6 +43,20 @@ class Gem::NameTuple
end
##
# Indicate if this NameTuple matches the current platform.
def match_platform?
@@ -59,12 +73,7 @@ class Gem::NameTuple
# Return the name that the gemspec file would be
def spec_name
- case @platform
- when nil, 'ruby', ''
- "#{@name}-#{@version}.gemspec"
- else
- "#{@name}-#{@version}-#{@platform}.gemspec"
- end
end
##
@@ -74,10 +83,12 @@ class Gem::NameTuple
[@name, @version, @platform]
end
- def to_s
"#<Gem::NameTuple #{@name}, #{@version}, #{@platform}>"
end
def <=> other
to_a <=> other.to_a
end
@@ -280,11 +280,16 @@ EOM
algorithms = if @checksums then
@checksums.keys
else
- [Gem::Security::DIGEST_NAME]
end
algorithms.each do |algorithm|
- digester = OpenSSL::Digest.new algorithm
digester << entry.read(16384) until entry.eof?
@@ -298,8 +303,11 @@ EOM
##
# Extracts the files in this package into +destination_dir+
- def extract_files destination_dir
verify unless @spec
FileUtils.mkdir_p destination_dir
@@ -310,7 +318,7 @@ EOM
reader.each do |entry|
next unless entry.full_name == 'data.tar.gz'
- extract_tar_gz entry, destination_dir
return # ignore further entries
end
@@ -324,10 +332,15 @@ EOM
# If an entry in the archive contains a relative path above
# +destination_dir+ or an absolute path is encountered an exception is
# raised.
- def extract_tar_gz io, destination_dir # :nodoc:
open_tar_gz io do |tar|
tar.each do |entry|
destination = install_location entry.full_name, destination_dir
FileUtils.rm_rf destination
@@ -428,12 +441,13 @@ EOM
# certificate and key are not present only checksum generation is set up.
def setup_signer
if @spec.signing_key then
- @signer = Gem::Security::Signer.new @spec.signing_key, @spec.cert_chain
@spec.signing_key = nil
@spec.cert_chain = @signer.cert_chain.map { |cert| cert.to_s }
else
- @signer = Gem::Security::Signer.new nil, nil
@spec.cert_chain = @signer.cert_chain.map { |cert| cert.to_pem } if
@signer.cert_chain
end
@@ -510,27 +524,38 @@ EOM
end
##
# Verifies the files of the +gem+
def verify_files gem
gem.each do |entry|
- file_name = entry.full_name
- @files << file_name
-
- case file_name
- when /\.sig$/ then
- @signatures[$`] = entry.read if @security_policy
- next
- else
- digest entry
- end
-
- case file_name
- when /^metadata(.gz)?$/ then
- load_spec entry
- when 'data.tar.gz' then
- verify_gz entry
- end
end
unless @spec then
@@ -71,7 +71,7 @@ class Gem::Package::TarTestCase < Gem::TestCase
SP(Z(to_oct(sum, 6)))
end
- def header(type, fname, dname, length, mode, checksum = nil)
checksum ||= " " * 8
arr = [ # struct tarfile_entry_posix
@@ -80,7 +80,7 @@ class Gem::Package::TarTestCase < Gem::TestCase
Z(to_oct(0, 7)), # char uid[8]; ditto
Z(to_oct(0, 7)), # char gid[8]; ditto
Z(to_oct(length, 11)), # char size[12]; 0 padded, octal, null
- Z(to_oct(0, 11)), # char mtime[12]; 0 padded, octal, null
checksum, # char checksum[8]; 0 padded, octal, null, space
type, # char typeflag[1]; file: "0" dir: "5"
"\0" * 100, # char linkname[100]; ASCII + (Z unless filled)
@@ -105,16 +105,16 @@ class Gem::Package::TarTestCase < Gem::TestCase
ret
end
- def tar_dir_header(name, prefix, mode)
- h = header("5", name, prefix, 0, mode)
checksum = calc_checksum(h)
- header("5", name, prefix, 0, mode, checksum)
end
- def tar_file_header(fname, dname, mode, length)
- h = header("0", fname, dname, length, mode)
checksum = calc_checksum(h)
- header("0", fname, dname, length, mode, checksum)
end
def to_oct(n, pad_size)
@@ -130,7 +130,7 @@ class Gem::Package::TarTestCase < Gem::TestCase
end
def util_dir_entry
- util_entry tar_dir_header("foo", "bar", 0)
end
end
@@ -4,6 +4,8 @@
# See LICENSE.txt for additional licensing information.
#++
##
# Allows writing of tar files
@@ -121,7 +123,8 @@ class Gem::Package::TarWriter
@io.pos = init_pos
header = Gem::Package::TarHeader.new :name => name, :mode => mode,
- :size => size, :prefix => prefix
@io.write header
@io.pos = final_pos
@@ -140,7 +143,15 @@ class Gem::Package::TarWriter
def add_file_digest name, mode, digest_algorithms # :yields: io
digests = digest_algorithms.map do |digest_algorithm|
digest = digest_algorithm.new
- [digest.name, digest]
end
digests = Hash[*digests.flatten]
@@ -165,22 +176,32 @@ class Gem::Package::TarWriter
def add_file_signed name, mode, signer
digest_algorithms = [
signer.digest_algorithm,
- OpenSSL::Digest::SHA512,
- ].uniq
digests = add_file_digest name, mode, digest_algorithms do |io|
yield io
end
- signature_digest = digests.values.find do |digest|
- digest.name == signer.digest_name
end
- signature = signer.sign signature_digest.digest
- add_file_simple "#{name}.sig", 0444, signature.length do |io|
- io.write signature
- end if signature
digests
end
@@ -195,7 +216,8 @@ class Gem::Package::TarWriter
name, prefix = split_name name
header = Gem::Package::TarHeader.new(:name => name, :mode => mode,
- :size => size, :prefix => prefix).to_s
@io.write header
os = BoundedStream.new @io, size
@@ -256,7 +278,8 @@ class Gem::Package::TarWriter
header = Gem::Package::TarHeader.new :name => name, :mode => mode,
:typeflag => "5", :size => 0,
- :prefix => prefix
@io.write header
@@ -13,6 +13,10 @@ class Gem::PathSupport
attr_reader :path
##
#
# Constructor. Takes a single argument which is to be treated like a
# hashtable, or defaults to ENV, the system environment.
@@ -28,6 +32,10 @@ class Gem::PathSupport
end
self.path = env["GEM_PATH"] || ENV["GEM_PATH"]
end
private
@@ -2,6 +2,8 @@ require "rubygems/deprecate"
##
# Available list of platforms for targeting Gem installations.
class Gem::Platform
@@ -129,12 +131,16 @@ class Gem::Platform
# Does +other+ match this platform? Two platforms match if they have the
# same CPU, or either has a CPU of 'universal', they have the same OS, and
# they have the same version, or either has no version.
def ===(other)
return nil unless Gem::Platform === other
# cpu
- (@cpu == 'universal' or other.cpu == 'universal' or @cpu == other.cpu) and
# os
@os == other.os and
@@ -1,6 +1,7 @@
require 'rubygems'
require 'rubygems/user_interaction'
-require 'uri'
require 'resolv'
##
@@ -71,17 +72,7 @@ class Gem::RemoteFetcher
Socket.do_not_reverse_lookup = true
- @connections = {}
- @requests = Hash.new 0
- @proxy_uri =
- case proxy
- when :no_proxy then nil
- when nil then get_proxy_from_env
- when URI::HTTP then proxy
- else URI.parse(proxy)
- end
- @user_agent = user_agent
- @env_no_proxy = get_no_proxy_from_env
@dns = dns
end
@@ -200,7 +191,7 @@ class Gem::RemoteFetcher
source_uri.path
end
- source_path = unescape source_path
begin
FileUtils.cp source_path, local_gem_path unless
@@ -319,125 +310,6 @@ class Gem::RemoteFetcher
response['content-length'].to_i
end
- def escape(str)
- return unless str
- @uri_parser ||= uri_escaper
- @uri_parser.escape str
- end
-
- def unescape(str)
- return unless str
- @uri_parser ||= uri_escaper
- @uri_parser.unescape str
- end
-
- def uri_escaper
- URI::Parser.new
- rescue NameError
- URI
- end
-
- ##
- # 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 an HTTP proxy URI if one is set in the environment variables.
-
- def get_proxy_from_env
- env_proxy = ENV['http_proxy'] || ENV['HTTP_PROXY']
-
- return nil if env_proxy.nil? or env_proxy.empty?
-
- uri = URI.parse(normalize_uri(env_proxy))
-
- if uri and uri.user.nil? and uri.password.nil? then
- # Probably we have http_proxy_* variables?
- uri.user = escape(ENV['http_proxy_user'] || ENV['HTTP_PROXY_USER'])
- uri.password = escape(ENV['http_proxy_pass'] || ENV['HTTP_PROXY_PASS'])
- end
-
- uri
- end
-
- ##
- # Normalize the URI by adding "http://" if it is missing.
-
- def normalize_uri(uri)
- (uri =~ /^(https?|ftp|file):/i) ? uri : "http://#{uri}"
- end
-
- ##
- # Creates or an HTTP connection based on +uri+, or retrieves an existing
- # connection, using a proxy if needed.
-
- def connection_for(uri)
- net_http_args = [uri.host, uri.port]
-
- if @proxy_uri and not no_proxy?(uri.host) then
- net_http_args += [
- @proxy_uri.host,
- @proxy_uri.port,
- @proxy_uri.user,
- @proxy_uri.password
- ]
- end
-
- connection_id = [Thread.current.object_id, *net_http_args].join ':'
- @connections[connection_id] ||= Net::HTTP.new(*net_http_args)
- connection = @connections[connection_id]
-
- 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,
- Errno::EHOSTDOWN => e
- raise FetchError.new(e.message, uri)
- end
-
- def configure_connection_for_https(connection)
- require 'net/https'
- connection.use_ssl = true
- connection.verify_mode =
- Gem.configuration.ssl_verify_mode || OpenSSL::SSL::VERIFY_PEER
- store = OpenSSL::X509::Store.new
- if Gem.configuration.ssl_ca_cert
- if File.directory? Gem.configuration.ssl_ca_cert
- store.add_path Gem.configuration.ssl_ca_cert
- else
- store.add_file Gem.configuration.ssl_ca_cert
- end
- else
- store.set_default_paths
- add_rubygems_trusted_certs(store)
- end
- connection.cert_store = store
- rescue LoadError => e
- raise unless (e.respond_to?(:path) && e.path == 'openssl') ||
- e.message =~ / -- openssl$/
-
- raise Gem::Exception.new(
- 'Unable to require openssl, install OpenSSL and rebuild ruby (preferred) or use non-HTTPS sources')
- end
-
- def add_rubygems_trusted_certs(store)
- pattern = File.expand_path("./ssl_certs/*.pem", File.dirname(__FILE__))
- Dir.glob(pattern).each do |ssl_cert_file|
- store.add_file ssl_cert_file
- end
- end
-
def correct_for_windows_path(path)
if path[0].chr == '/' && path[1].chr =~ /[a-z]/i && path[2].chr == ':'
path = path[1..-1]
@@ -446,136 +318,13 @@ class Gem::RemoteFetcher
end
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
-
##
# Performs a Net::HTTP request of type +request_class+ on +uri+ returning
# a Net::HTTP response object. request maintains a table of persistent
# connections to reduce connect overhead.
def request(uri, request_class, last_modified = nil)
- request = request_class.new uri.request_uri
-
- unless uri.nil? || uri.user.nil? || uri.user.empty? then
- request.basic_auth uri.user, uri.password
- end
-
- request.add_field 'User-Agent', @user_agent
- request.add_field 'Connection', 'keep-alive'
- request.add_field 'Keep-Alive', '30'
-
- if last_modified then
- last_modified = last_modified.utc
- request.add_field 'If-Modified-Since', last_modified.rfc2822
- end
-
- yield request if block_given?
-
- connection = connection_for uri
-
- retried = false
- bad_response = false
-
- begin
- @requests[connection.object_id] += 1
-
- say "#{request.method} #{uri}" if
- Gem.configuration.really_verbose
-
- file_name = File.basename(uri.path)
- # perform download progress reporter only for gems
- if request.response_body_permitted? && file_name =~ /\.gem$/
- reporter = ui.download_reporter
- response = connection.request(request) do |incomplete_response|
- if Net::HTTPOK === incomplete_response
- reporter.fetch(file_name, incomplete_response.content_length)
- downloaded = 0
- data = ''
-
- incomplete_response.read_body do |segment|
- data << segment
- downloaded += segment.length
- reporter.update(downloaded)
- end
- reporter.done
- if incomplete_response.respond_to? :body=
- incomplete_response.body = data
- else
- incomplete_response.instance_variable_set(:@body, data)
- end
- end
- end
- else
- response = connection.request request
- end
-
- say "#{response.code} #{response.message}" if
- Gem.configuration.really_verbose
-
- rescue Net::HTTPBadResponse
- say "bad response" if Gem.configuration.really_verbose
-
- reset connection
-
- raise FetchError.new('too many bad responses', uri) if bad_response
-
- bad_response = true
- retry
- # HACK work around EOFError bug in Net::HTTP
- # NOTE Errno::ECONNABORTED raised a lot on Windows, and make impossible
- # to install gems.
- rescue EOFError, Timeout::Error,
- Errno::ECONNABORTED, Errno::ECONNRESET, Errno::EPIPE
-
- requests = @requests[connection.object_id]
- say "connection reset after #{requests} requests, retrying" if
- Gem.configuration.really_verbose
-
- raise FetchError.new('too many connection resets', uri) if retried
-
- reset connection
-
- retried = true
- retry
- end
-
- response
- end
-
- ##
- # Resets HTTP connection +connection+.
-
- def reset(connection)
- @requests.delete connection.object_id
-
- connection.finish
- connection.start
- end
-
- def user_agent
- ua = "RubyGems/#{Gem::VERSION} #{Gem::Platform.local}"
-
- ruby_version = RUBY_VERSION
- ruby_version += 'dev' if RUBY_LEVEL == -1
-
- ua << " Ruby/#{ruby_version} (#{RUBY_RELEASE_DATE}"
- if RUBY_LEVEL >= 0 then
- ua << " level #{RUBY_LEVEL}"
- elsif defined?(RUBY_REVISION) then
- ua << " revision #{RUBY_REVISION}"
- end
- ua << ")"
-
- ua << " #{RUBY_ENGINE}" if defined?(RUBY_ENGINE) and RUBY_ENGINE != 'ruby'
-
- ua
end
def https?(uri)
@@ -0,0 +1,262 @@
@@ -5,178 +5,176 @@ require 'rubygems/dependency_list'
require 'rubygems/installer'
require 'tsort'
-module Gem
- class RequestSet
- include TSort
- def initialize(*deps)
- @dependencies = deps
- yield self if block_given?
- end
- attr_reader :dependencies
- # Declare that a gem of name +name+ with +reqs+ requirements
- # is needed.
- #
- def gem(name, *reqs)
- @dependencies << Gem::Dependency.new(name, reqs)
- end
- # Add +deps+ Gem::Depedency objects to the set.
- #
- def import(deps)
- @dependencies += deps
- end
- # Resolve the requested dependencies and return an Array of
- # Specification objects to be activated.
- #
- def resolve(set=nil)
- r = Gem::DependencyResolver.new(@dependencies, set)
- @requests = r.resolve
- end
- # Resolve the requested dependencies against the gems
- # available via Gem.path and return an Array of Specification
- # objects to be activated.
- #
- def resolve_current
- resolve DependencyResolver::CurrentSet.new
- end
- # Load a dependency management file.
- #
- def load_gemdeps(path)
- gf = GemDepedencyAPI.new(self, path)
- gf.load
- end
- def specs
- @specs ||= @requests.map { |r| r.full_spec }
- end
- def tsort_each_node(&block)
- @requests.each(&block)
- end
- def tsort_each_child(node)
- node.spec.dependencies.each do |dep|
- next if dep.type == :development
-
- match = @requests.find { |r| dep.match? r.spec.name, r.spec.version }
- if match
- begin
- yield match
- rescue TSort::Cyclic
- end
- else
- raise Gem::DependencyError, "Unresolved depedency found during sorting - #{dep}"
- end
- end
- end
- def sorted_requests
- @sorted ||= strongly_connected_components.flatten
end
- def specs_in(dir)
- Dir["#{dir}/specifications/*.gemspec"].map do |g|
- Gem::Specification.load g
end
- end
- def install_into(dir, force=true, &b)
- existing = force ? [] : specs_in(dir)
- dir = File.expand_path dir
- installed = []
- sorted_requests.each do |req|
- if existing.find { |s| s.full_name == req.spec.full_name }
- b.call req, nil if b
- next
- end
- path = req.download(dir)
- inst = Gem::Installer.new path, :install_dir => dir,
- :only_install_dir => true
- b.call req, inst if b
- inst.install
- installed << req
end
- installed
- end
- def install(options, &b)
- if dir = options[:install_dir]
- return install_into(dir, false, &b)
end
- cache_dir = options[:cache_dir] || Gem.dir
- specs = []
- sorted_requests.each do |req|
- if req.installed?
- b.call req, nil if b
- next
- end
- path = req.download cache_dir
- inst = Gem::Installer.new path, options
- b.call req, inst if b
- specs << inst.install
- end
- specs
- end
- # A semi-compatible DSL for Bundler's Gemfile format
- #
- class GemDepedencyAPI
- def initialize(set, path)
- @set = set
- @path = path
- end
- def load
- instance_eval File.read(@path).untaint, @path, 1
- end
- # DSL
- def source(url)
- end
- def gem(name, *reqs)
- # Ignore the opts for now.
- reqs.pop if reqs.last.kind_of?(Hash)
- @set.gem name, *reqs
- end
- def platform(what)
- if what == :ruby
- yield
- end
- end
- alias_method :platforms, :platform
- def group(*what)
end
end
end
end
@@ -0,0 +1,39 @@
@@ -12,20 +12,6 @@ begin
rescue LoadError => e
raise unless (e.respond_to?(:path) && e.path == 'openssl') ||
e.message =~ / -- openssl$/
-
- module OpenSSL # :nodoc:
- class Digest # :nodoc:
- class SHA1 # :nodoc:
- def name
- 'SHA1'
- end
- end
- end
- module PKey # :nodoc:
- class RSA # :nodoc:
- end
- end
- end
end
##
@@ -352,17 +338,26 @@ module Gem::Security
##
# Digest algorithm used to sign gems
- DIGEST_ALGORITHM = OpenSSL::Digest::SHA1
##
# Used internally to select the signing digest from all computed digests
- DIGEST_NAME = DIGEST_ALGORITHM.new.name # :nodoc:
##
# Algorithm for creating the key pair used to sign gems
- KEY_ALGORITHM = OpenSSL::PKey::RSA
##
# Length of keys created by KEY_ALGORITHM
@@ -370,6 +365,12 @@ module Gem::Security
KEY_LENGTH = 2048
##
# One year in seconds
ONE_YEAR = 86400 * 365
@@ -563,13 +564,18 @@ module Gem::Security
##
# Writes +pemmable+, which must respond to +to_pem+ to +path+ with the given
- # +permissions+.
- def self.write pemmable, path, permissions = 0600
path = File.expand_path path
open path, 'wb', permissions do |io|
- io.write pemmable.to_pem
end
path
@@ -579,8 +585,11 @@ module Gem::Security
end
-require 'rubygems/security/policy'
-require 'rubygems/security/policies'
require 'rubygems/security/signer'
-require 'rubygems/security/trust_dir'
@@ -1,3 +1,5 @@
##
# A Gem::Security::Policy object encapsulates the settings for verifying
# signed gem files. This is the base class. You can either declare an
@@ -6,6 +8,8 @@
class Gem::Security::Policy
attr_reader :name
attr_accessor :only_signed
@@ -175,6 +179,19 @@ class Gem::Security::Policy
true
end
def inspect # :nodoc:
("[Policy: %s - data: %p signer: %p chain: %p root: %p " +
"signed-only: %p trusted-only: %p]") % [
@@ -184,16 +201,21 @@ class Gem::Security::Policy
end
##
- # Verifies the certificate +chain+ is valid, the +digests+ match the
- # signatures +signatures+ created by the signer depending on the +policy+
- # settings.
#
# If +key+ is given it is used to validate the signing certificate.
- def verify chain, key = nil, digests = {}, signatures = {}
- if @only_signed and signatures.empty? then
- raise Gem::Security::Exception,
- "unsigned gems are not allowed by the #{name} policy"
end
opt = @opt
@@ -222,7 +244,11 @@ class Gem::Security::Policy
check_root chain, time if @verify_root
- check_trust chain, digester, trust_dir if @only_trusted
signatures.each do |file, _|
digest = signer_digests[file]
@@ -252,7 +278,7 @@ class Gem::Security::Policy
OpenSSL::X509::Certificate.new cert_pem
end
- verify chain, nil, digests, signatures
true
end
@@ -29,7 +29,7 @@ class Gem::Security::Signer
# +chain+ containing X509 certificates, encoding certificates or paths to
# certificates.
- def initialize key, cert_chain
@cert_chain = cert_chain
@key = key
@@ -46,7 +46,7 @@ class Gem::Security::Signer
@digest_algorithm = Gem::Security::DIGEST_ALGORITHM
@digest_name = Gem::Security::DIGEST_NAME
- @key = OpenSSL::PKey::RSA.new File.read @key if
@key and not OpenSSL::PKey::RSA === @key
if @cert_chain then
@@ -25,14 +25,21 @@ class Gem::Source
end
def <=>(other)
- if !@uri
- return 0 unless other.uri
- return -1
- end
- return 1 if !other.uri
- @uri.to_s <=> other.uri.to_s
end
include Comparable
@@ -58,8 +65,7 @@ class Gem::Source
def cache_dir(uri)
# Correct for windows paths
escaped_path = uri.path.sub(/^\/([a-z]):\//i, '/\\1-/')
- root = File.join Gem.user_home, '.gem', 'specs'
- File.join root, "#{uri.host}%#{uri.port}", File.dirname(escaped_path)
end
def update_cache?
@@ -141,4 +147,14 @@ class Gem::Source
fetcher = Gem::RemoteFetcher.fetcher
fetcher.download spec, @uri.to_s, dir
end
end
@@ -0,0 +1,28 @@
@@ -0,0 +1,122 @@
@@ -0,0 +1,28 @@
@@ -1,92 +1,5 @@
require 'rubygems/source'
-class Gem::Source::Local < Gem::Source
- def initialize
- @uri = nil
- end
- def load_specs(type)
- names = []
-
- @specs = {}
-
- Dir["*.gem"].each do |file|
- begin
- pkg = Gem::Package.new(file)
- rescue SystemCallError, Gem::Package::FormatError
- # ignore
- else
- tup = pkg.spec.name_tuple
- @specs[tup] = [File.expand_path(file), pkg]
-
- case type
- when :released
- unless pkg.spec.version.prerelease?
- names << pkg.spec.name_tuple
- end
- when :prerelease
- if pkg.spec.version.prerelease?
- names << pkg.spec.name_tuple
- end
- when :latest
- tup = pkg.spec.name_tuple
-
- cur = names.find { |x| x.name == tup.name }
- if !cur
- names << tup
- elsif cur.version < tup.version
- names.delete cur
- names << tup
- end
- else
- names << pkg.spec.name_tuple
- end
- end
- end
-
- names
- end
-
- def find_gem(gem_name, version=Gem::Requirement.default,
- prerelease=false)
- load_specs :complete
-
- found = []
-
- @specs.each do |n, data|
- if n.name == gem_name
- s = data[1].spec
-
- if version.satisfied_by?(s.version)
- if prerelease
- found << s
- elsif !s.version.prerelease?
- found << s
- end
- end
- end
- end
-
- found.sort_by { |s| s.version }.last
- end
-
- def fetch_spec(name)
- load_specs :complete
-
- if data = @specs[name]
- data.last.spec
- else
- raise Gem::Exception, "Unable to find spec for '#{name}'"
- end
- end
-
- def download(spec, cache_dir=nil)
- load_specs :complete
-
- @specs.each do |name, data|
- return data[0] if data[1].spec == spec
- end
-
- raise Gem::Exception, "Unable to find file for '#{spec.full_name}'"
- end
-end
@@ -1,28 +1,4 @@
-class Gem::Source::SpecificFile < Gem::Source
- def initialize(file)
- @uri = nil
- @path = ::File.expand_path(file)
- @package = Gem::Package.new @path
- @spec = @package.spec
- @name = @spec.name_tuple
- end
- attr_reader :spec
-
- def load_specs(*a)
- [@name]
- end
-
- def fetch_spec(name)
- return @spec if name == @name
- raise Gem::Exception, "Unable to find '#{name}'"
- @spec
- end
-
- def download(spec, dir=nil)
- return @path if spec == @spec
- raise Gem::Exception, "Unable to download '#{spec.full_name}'"
- end
-
-end
@@ -38,7 +38,6 @@ class Gem::SpecFetcher
end
def initialize
- @dir = File.join Gem.user_home, '.gem', 'specs'
@update_cache = File.stat(Gem.user_home).uid == Process.uid
@specs = {}
@@ -5,10 +5,13 @@
# See LICENSE.txt for permissions.
#++
require 'rubygems/version'
require 'rubygems/requirement'
require 'rubygems/platform'
require 'rubygems/deprecate'
# :stopdoc:
# date.rb can't be loaded for `make install` due to miniruby
@@ -45,7 +48,7 @@ class Date; end
#
# s.metadata = { "bugtracker" => "http://somewhere.com/blah" }
-class Gem::Specification
# REFACTOR: Consider breaking out this version stuff into a separate
# module. There's enough special stuff around it that it may justify
@@ -107,6 +110,10 @@ class Gem::Specification
today = Time.now.utc
TODAY = Time.utc(today.year, today.month, today.day)
# :startdoc:
##
@@ -156,6 +163,17 @@ class Gem::Specification
:version => nil,
}
@@attributes = @@default_value.keys.sort_by { |s| s.to_s }
@@array_attributes = @@default_value.reject { |k,v| v != [] }.keys
@@nil_attributes, @@non_nil_attributes = @@default_value.keys.partition { |k|
@@ -584,11 +602,6 @@ class Gem::Specification
attr_writer :default_executable
##
- # Path this gemspec was loaded from. This attribute is not persisted.
-
- attr_reader :loaded_from
-
- ##
# Allows deinstallation of gems with legacy platforms.
attr_writer :original_platform # :nodoc:
@@ -615,58 +628,68 @@ class Gem::Specification
attr_accessor :specification_version
- class << self
- def default_specifications_dir
- File.join(Gem.default_dir, "specifications", "default")
end
- def each_spec(search_dirs) # :nodoc:
- search_dirs.each { |dir|
- Dir[File.join(dir, "*.gemspec")].each { |path|
- spec = Gem::Specification.load path.untaint
- # #load returns nil if the spec is bad, so we just ignore
- # it at this stage
- yield(spec) if spec
- }
- }
end
- def each_default(&block) # :nodoc:
- each_spec([default_specifications_dir],
- &block)
end
- def each_normal(&block) # :nodoc:
- each_spec(dirs, &block)
end
end
- def self._all # :nodoc:
- unless defined?(@@all) && @@all then
- specs = {}
- each_default do |spec|
- specs[spec.full_name] ||= spec
end
- each_normal do |spec|
- specs[spec.full_name] ||= spec
- end
-
- @@all = specs.values
-
- # After a reset, make sure already loaded specs
- # are still marked as activated.
- specs = {}
- Gem.loaded_specs.each_value{|s| specs[s] = true}
- @@all.each{|s| s.activated = true if specs[s]}
- _resort!
end
- @@all
end
- def self._resort! # :nodoc:
- @@all.sort! { |a, b|
names = a.name <=> b.name
next names if names.nonzero?
b.version <=> a.version
@@ -677,7 +700,9 @@ class Gem::Specification
# Loads the default specifications. It should be called only once.
def self.load_defaults
- each_default do |spec|
Gem.register_default_spec(spec)
end
end
@@ -700,7 +725,9 @@ class Gem::Specification
return if _all.include? spec
_all << spec
- _resort!
end
##
@@ -843,9 +870,10 @@ class Gem::Specification
# amongst the specs that are not activated.
def self.find_inactive_by_path path
- self.find { |spec|
- spec.contains_requirable_file? path unless spec.activated?
}
end
##
@@ -937,6 +965,9 @@ class Gem::Specification
file = file.dup.untaint
return unless File.file?(file)
code = if defined? Encoding
File.read file, :mode => 'r:UTF-8:-'
else
@@ -950,6 +981,7 @@ class Gem::Specification
if Gem::Specification === spec
spec.loaded_from = file.to_s
return spec
end
@@ -1013,6 +1045,7 @@ class Gem::Specification
raise "wtf: #{spec.full_name} not in #{all_names.inspect}" unless
_all.include? spec
_all.delete spec
end
##
@@ -1037,6 +1070,8 @@ class Gem::Specification
@@dirs = nil
Gem.pre_reset_hooks.each { |hook| hook.call }
@@all = nil
unresolved = unresolved_deps
unless unresolved.empty? then
w = "W" + "ARN"
@@ -1281,20 +1316,6 @@ class Gem::Specification
end
##
- # Returns the full path to the base gem directory.
- #
- # eg: /usr/local/lib/ruby/gems/1.8
-
- def base_dir
- return Gem.dir unless loaded_from
- @base_dir ||= if default_gem? then
- File.dirname File.dirname File.dirname loaded_from
- else
- File.dirname File.dirname loaded_from
- end
- end
-
- ##
# Returns the full path to installed gem's bin directory.
#
# NOTE: do not confuse this with +bindir+, which is just 'bin', not
@@ -1368,19 +1389,6 @@ class Gem::Specification
end
##
- # 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
- end
-
- ##
# The date this gem was created. Lazily defaults to TODAY.
def date
@@ -1623,35 +1631,14 @@ class Gem::Specification
spec
end
- ##
- # The full path to the gem (install path + full name).
-
- def full_gem_path
- # TODO: This is a heavily used method by gems, so we'll need
- # to aleast just alias it to #gem_dir rather than remove it.
-
- # TODO: also, shouldn't it default to full_name if it hasn't been written?
- return @full_gem_path if defined?(@full_gem_path) && @full_gem_path
-
- @full_gem_path = File.expand_path File.join(gems_dir, full_name)
- @full_gem_path.untaint
-
- return @full_gem_path if File.directory? @full_gem_path
-
- @full_gem_path = File.expand_path File.join(gems_dir, original_name)
end
-
- ##
- # Returns the full name (name-version) of this Gem. Platform information
- # is included (name-version-platform) if it is specified and not the
- # default Ruby platform.
def full_name
- @full_name ||= if platform == Gem::Platform::RUBY or platform.nil? then
- "#{@name}-#{@version}".untaint
- else
- "#{@name}-#{@version}-#{platform}".untaint
- end
end
##
@@ -1663,15 +1650,6 @@ class Gem::Specification
end
##
- # Returns the full path to the gems directory containing this spec's
- # gem directory. eg: /usr/local/lib/ruby/1.8/gems
-
- def gems_dir
- # TODO: this logic seems terribly broken, but tests fail if just base_dir
- @gems_dir ||= File.join(loaded_from && base_dir || Gem.dir, "gems")
- end
-
- ##
# Deprecated and ignored, defaults to true.
#
# Formerly used to indicate this gem was RDoc-capable.
@@ -1703,9 +1681,7 @@ class Gem::Specification
# :startdoc:
def hash # :nodoc:
- @@attributes.inject(0) { |hash_code, (name, _)|
- hash_code ^ self.send(name).hash
- }
end
def init_with coder # :nodoc:
@@ -1720,7 +1696,7 @@ class Gem::Specification
def initialize name = nil, version = nil
@loaded = false
@activated = false
- @loaded_from = nil
@original_platform = nil
@@nil_attributes.each do |key|
@@ -1729,11 +1705,7 @@ class Gem::Specification
@@non_nil_attributes.each do |key|
default = default_value(key)
- value = case default
- when Time, Numeric, Symbol, true, false, nil then default
- else default.dup
- end
-
instance_variable_set "@#{key}", value
end
@@ -1828,28 +1800,31 @@ class Gem::Specification
@licenses ||= []
end
- ##
- # Set the location a Specification was loaded from. +obj+ is converted
- # to a String.
- def loaded_from= path
- @loaded_from = path.to_s
-
- # reset everything @loaded_from depends upon
- @base_dir = nil
@bin_dir = nil
@cache_dir = nil
@cache_file = nil
@doc_dir = nil
- @full_gem_path = nil
@gem_dir = nil
- @gems_dir = nil
@ri_dir = nil
@spec_dir = nil
@spec_file = nil
end
##
# Sets the rubygems_version to the current RubyGems version.
def mark_version
@@ -1878,6 +1853,11 @@ class Gem::Specification
end
end
##
# Normalize the list of files so that:
# * All file lists have redundancies removed.
@@ -2094,6 +2074,13 @@ class Gem::Specification
end
##
# Returns the full path to the directory containing this spec's
# gemspec file. eg: /usr/local/lib/ruby/gems/1.8/specifications
@@ -2172,6 +2159,7 @@ class Gem::Specification
mark_version
result = []
result << "# -*- encoding: utf-8 -*-"
result << nil
result << "Gem::Specification.new do |s|"
@@ -2259,6 +2247,13 @@ class Gem::Specification
"#<Gem::Specification name=#{@name} version=#{@version}>"
end
def to_yaml(opts = {}) # :nodoc:
if YAML.const_defined?(:ENGINE) && !YAML::ENGINE.syck? then
# Because the user can switch the YAML engine behind our
@@ -2559,11 +2554,6 @@ class Gem::Specification
end
end
- def default_gem?
- loaded_from &&
- File.dirname(loaded_from) == self.class.default_specifications_dir
- end
-
extend Gem::Deprecate
# TODO:
@@ -0,0 +1,112 @@
@@ -78,6 +78,23 @@ end
class Gem::TestCase < MiniTest::Unit::TestCase
# TODO: move to minitest
def assert_path_exists path, msg = nil
msg = message(msg) { "Expected path '#{path}' to exist" }
@@ -200,6 +217,7 @@ class Gem::TestCase < MiniTest::Unit::TestCase
@gemhome = File.join @tempdir, 'gemhome'
@userhome = File.join @tempdir, 'userhome'
@orig_ruby = if ENV['RUBY'] then
ruby = Gem.instance_variable_get :@ruby
@@ -221,6 +239,9 @@ class Gem::TestCase < MiniTest::Unit::TestCase
FileUtils.mkdir_p @gemhome
FileUtils.mkdir_p @userhome
@default_dir = File.join @tempdir, 'default'
@default_spec_dir = File.join @default_dir, "specifications", "default"
Gem.instance_variable_set :@default_dir, @default_dir
@@ -266,39 +287,6 @@ class Gem::TestCase < MiniTest::Unit::TestCase
end
@marshal_version = "#{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}"
-
- # TODO: move to installer test cases
- Gem.post_build_hooks.clear
- Gem.post_install_hooks.clear
- Gem.done_installing_hooks.clear
- Gem.post_reset_hooks.clear
- Gem.post_uninstall_hooks.clear
- Gem.pre_install_hooks.clear
- Gem.pre_reset_hooks.clear
- Gem.pre_uninstall_hooks.clear
-
- # TODO: move to installer test cases
- Gem.post_build do |installer|
- @post_build_hook_arg = installer
- true
- end
-
- Gem.post_install do |installer|
- @post_install_hook_arg = installer
- end
-
- Gem.post_uninstall do |uninstaller|
- @post_uninstall_hook_arg = uninstaller
- end
-
- Gem.pre_install do |installer|
- @pre_install_hook_arg = installer
- true
- end
-
- Gem.pre_uninstall do |uninstaller|
- @pre_uninstall_hook_arg = uninstaller
- end
end
##
@@ -332,6 +320,47 @@ class Gem::TestCase < MiniTest::Unit::TestCase
end
Gem.instance_variable_set :@default_dir, nil
end
##
@@ -560,6 +589,21 @@ class Gem::TestCase < MiniTest::Unit::TestCase
end
end
##
# Create a new spec (or gem if passed an array of files) and set it
# up properly. Use this instead of util_spec and util_gem.
@@ -1006,6 +1050,24 @@ Also, a list:
end
##
# Constructs a new Gem::Requirement.
def req *requirements
@@ -1074,18 +1136,18 @@ Also, a list:
end
##
- # Loads an RSA private key named +key_name+ in <tt>test/rubygems/</tt>
- def self.load_key key_name
key_file = key_path key_name
key = File.read key_file
- OpenSSL::PKey::RSA.new key
end
##
- # Returns the path tot he key named +key_name+ from <tt>test/rubygems</tt>
def self.key_path key_name
File.expand_path "../../../test/rubygems/#{key_name}_key.pem", __FILE__
@@ -1094,17 +1156,24 @@ Also, a list:
# :stopdoc:
# only available in RubyGems tests
begin
- PRIVATE_KEY = load_key 'private'
- PRIVATE_KEY_PATH = key_path 'private'
- PUBLIC_KEY = PRIVATE_KEY.public_key
- PUBLIC_CERT = load_cert 'public'
- PUBLIC_CERT_PATH = cert_path 'public'
rescue Errno::ENOENT
PRIVATE_KEY = nil
PUBLIC_KEY = nil
PUBLIC_CERT = nil
- end
end
@@ -43,14 +43,15 @@ class Gem::Uninstaller
def initialize(gem, options = {})
# TODO document the valid options
- @gem = gem
- @version = options[:version] || Gem::Requirement.default
- @gem_home = File.expand_path(options[:install_dir] || Gem.dir)
- @force_executables = options[:executables]
- @force_all = options[:all]
- @force_ignore = options[:ignore]
- @bin_dir = options[:bin_dir]
- @format_executable = options[:format_executable]
# Indicate if development dependencies should be checked when
# uninstalling. (default: false)
@@ -143,7 +144,7 @@ class Gem::Uninstaller
@spec = spec
unless dependencies_ok? spec
- unless ask_if_ok(spec)
raise Gem::DependencyRemovalException,
"Uninstallation aborted due to dependent gem(s)"
end
@@ -290,6 +291,10 @@ class Gem::Uninstaller
deplist.ok_to_remove?(spec.full_name, @check_dev)
end
def ask_if_ok(spec)
msg = ['']
msg << 'You have requested to uninstall the gem:'
@@ -0,0 +1,39 @@
@@ -0,0 +1,44 @@
@@ -147,13 +147,16 @@ class Gem::Version
# FIX: These are only used once, in .correct?. Do they deserve to be
# constants?
- VERSION_PATTERN = '[0-9]+(\.[0-9a-zA-Z]+)*' # :nodoc:
ANCHORED_VERSION_PATTERN = /\A\s*(#{VERSION_PATTERN})*\s*\z/ # :nodoc:
##
# A string representation of this Version.
- attr_reader :version
alias to_s version
##
@@ -183,6 +186,12 @@ class Gem::Version
end
end
##
# Constructs a Version from the +version+ string. A version string is a
# series of digits or ASCII letters separated by dots.
@@ -191,7 +200,8 @@ class Gem::Version
raise ArgumentError, "Malformed version number string #{version}" unless
self.class.correct?(version)
- @version = version.to_s.dup.strip
end
##
@@ -42,6 +42,7 @@ module Gem::VersionOption
add_option("--[no-]prerelease",
"Allow prerelease versions of a gem", *wrap) do |value, options|
options[:prerelease] = value
end
end
@@ -50,14 +51,19 @@ module Gem::VersionOption
def add_version_option(task = command, *wrap)
OptionParser.accept Gem::Requirement do |value|
- Gem::Requirement.new value
end
add_option('-v', '--version VERSION', Gem::Requirement,
"Specify version of gem to #{task}", *wrap) do
|value, options|
options[:version] = value
- options[:prerelease] = true if value.prerelease?
end
end