mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Update RubyGems to 1.1.1 r1778 (almost 1.2)
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@17392 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
f98e6b91de
commit
9d4f37f51f
71 changed files with 3765 additions and 1127 deletions
|
@ -1,3 +1,7 @@
|
|||
Wed Jun 18 07:03:30 2008 Eric Hodel <drbrain@egment7.net>
|
||||
|
||||
* lib/rubygems/*: Update to RubyGems r1778 (pre 1.2).
|
||||
|
||||
Wed Jun 18 04:27:58 2008 Koichi Sasada <ko1@atdot.net>
|
||||
|
||||
* KNOWNBUGS.rb, bootstraptest/pending.rb: move pending bug.
|
||||
|
|
|
@ -67,11 +67,14 @@ module Gem
|
|||
:RUBY_SO_NAME => RbConfig::CONFIG["RUBY_SO_NAME"],
|
||||
:arch => RbConfig::CONFIG["arch"],
|
||||
:bindir => RbConfig::CONFIG["bindir"],
|
||||
:datadir => RbConfig::CONFIG["datadir"],
|
||||
:libdir => RbConfig::CONFIG["libdir"],
|
||||
:ruby_install_name => RbConfig::CONFIG["ruby_install_name"],
|
||||
:ruby_version => RbConfig::CONFIG["ruby_version"],
|
||||
:sitedir => RbConfig::CONFIG["sitedir"],
|
||||
:sitelibdir => RbConfig::CONFIG["sitelibdir"]
|
||||
:sitelibdir => RbConfig::CONFIG["sitelibdir"],
|
||||
:vendordir => RbConfig::CONFIG["vendordir"] ,
|
||||
:vendorlibdir => RbConfig::CONFIG["vendorlibdir"]
|
||||
)
|
||||
|
||||
DIRECTORIES = %w[cache doc gems specifications] unless defined?(DIRECTORIES)
|
||||
|
@ -137,7 +140,7 @@ module Gem
|
|||
|
||||
unless matches.any? { |spec| spec.version == existing_spec.version } then
|
||||
raise Gem::Exception,
|
||||
"can't activate #{gem}, already activated #{existing_spec.full_name}]"
|
||||
"can't activate #{gem}, already activated #{existing_spec.full_name}"
|
||||
end
|
||||
|
||||
return false
|
||||
|
@ -151,7 +154,7 @@ module Gem
|
|||
@loaded_specs[spec.name] = spec
|
||||
|
||||
# Load dependent gems first
|
||||
spec.dependencies.each do |dep_gem|
|
||||
spec.runtime_dependencies.each do |dep_gem|
|
||||
activate dep_gem
|
||||
end
|
||||
|
||||
|
@ -203,6 +206,19 @@ module Gem
|
|||
|
||||
private_class_method :all_partials
|
||||
|
||||
##
|
||||
# See if a given gem is available.
|
||||
|
||||
def self.available?(gem, *requirements)
|
||||
requirements = Gem::Requirement.default if requirements.empty?
|
||||
|
||||
unless gem.respond_to?(:name) && gem.respond_to?(:version_requirements)
|
||||
gem = Gem::Dependency.new(gem, requirements)
|
||||
end
|
||||
|
||||
!Gem.source_index.search(gem).empty?
|
||||
end
|
||||
|
||||
##
|
||||
# The mode needed to read a file as straight binary.
|
||||
|
||||
|
@ -267,6 +283,13 @@ module Gem
|
|||
File.join(spec.full_gem_path, 'data', gem_name)
|
||||
end
|
||||
|
||||
##
|
||||
# A Zlib::Deflate.deflate wrapper
|
||||
|
||||
def self.deflate(data)
|
||||
Zlib::Deflate.deflate data
|
||||
end
|
||||
|
||||
##
|
||||
# The path where gems are to be installed.
|
||||
|
||||
|
@ -345,6 +368,33 @@ module Gem
|
|||
|
||||
private_class_method :find_home
|
||||
|
||||
##
|
||||
# Zlib::GzipReader wrapper that unzips +data+.
|
||||
|
||||
def self.gunzip(data)
|
||||
data = StringIO.new data
|
||||
|
||||
Zlib::GzipReader.new(data).read
|
||||
end
|
||||
|
||||
##
|
||||
# Zlib::GzipWriter wrapper that zips +data+.
|
||||
|
||||
def self.gzip(data)
|
||||
zipped = StringIO.new
|
||||
|
||||
Zlib::GzipWriter.wrap zipped do |io| io.write data end
|
||||
|
||||
zipped.string
|
||||
end
|
||||
|
||||
##
|
||||
# A Zlib::Inflate#inflate wrapper
|
||||
|
||||
def self.inflate(data)
|
||||
Zlib::Inflate.inflate data
|
||||
end
|
||||
|
||||
##
|
||||
# Return a list of all possible load paths for the latest version for all
|
||||
# gems in the Gem installation.
|
||||
|
@ -438,7 +488,11 @@ module Gem
|
|||
@gem_path ||= nil
|
||||
|
||||
unless @gem_path then
|
||||
paths = [ENV['GEM_PATH']] || [default_path]
|
||||
paths = if ENV['GEM_PATH'] then
|
||||
[ENV['GEM_PATH']]
|
||||
else
|
||||
[default_path]
|
||||
end
|
||||
|
||||
if defined?(APPLE_GEM_HOME) and not ENV['GEM_PATH'] then
|
||||
paths << APPLE_GEM_HOME
|
||||
|
@ -459,7 +513,7 @@ module Gem
|
|||
|
||||
##
|
||||
# Array of platforms this RubyGems supports.
|
||||
|
||||
|
||||
def self.platforms
|
||||
@platforms ||= []
|
||||
if @platforms.empty?
|
||||
|
@ -586,13 +640,13 @@ module Gem
|
|||
def self.set_paths(gpaths)
|
||||
if gpaths
|
||||
@gem_path = gpaths.split(File::PATH_SEPARATOR)
|
||||
|
||||
|
||||
if File::ALT_SEPARATOR then
|
||||
@gem_path.map! do |path|
|
||||
path.gsub File::ALT_SEPARATOR, File::SEPARATOR
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@gem_path << Gem.dir
|
||||
else
|
||||
@gem_path = [Gem.dir]
|
||||
|
@ -683,24 +737,25 @@ module Gem
|
|||
|
||||
end
|
||||
|
||||
MARSHAL_SPEC_DIR = "quick/Marshal.#{Gem.marshal_version}/"
|
||||
|
||||
YAML_SPEC_DIR = 'quick/'
|
||||
|
||||
end
|
||||
|
||||
# Modify the non-gem version of datadir to handle gem package names.
|
||||
|
||||
require 'rbconfig/datadir'
|
||||
|
||||
module Config # :nodoc:
|
||||
module Config
|
||||
# :stopdoc:
|
||||
class << self
|
||||
alias gem_original_datadir datadir
|
||||
|
||||
# Return the path to the data directory associated with the named
|
||||
# package. If the package is loaded as a gem, return the gem
|
||||
# specific data directory. Otherwise return a path to the share
|
||||
# area as define by "#{ConfigMap[:datadir]}/#{package_name}".
|
||||
def datadir(package_name)
|
||||
Gem.datadir(package_name) || Config.gem_original_datadir(package_name)
|
||||
Gem.datadir(package_name) ||
|
||||
File.join(Gem::ConfigMap[:datadir], package_name)
|
||||
end
|
||||
end
|
||||
# :startdoc:
|
||||
end
|
||||
|
||||
require 'rubygems/exceptions'
|
||||
|
@ -712,6 +767,18 @@ require 'rubygems/source_index' # Needed for Kernel#gem
|
|||
require 'rubygems/platform'
|
||||
require 'rubygems/builder' # HACK: Needed for rake's package task.
|
||||
|
||||
begin
|
||||
require 'rubygems/defaults/operating_system'
|
||||
rescue LoadError
|
||||
end
|
||||
|
||||
if defined?(RUBY_ENGINE) then
|
||||
begin
|
||||
require "rubygems/defaults/#{RUBY_ENGINE}"
|
||||
rescue LoadError
|
||||
end
|
||||
end
|
||||
|
||||
if RUBY_VERSION < '1.9' then
|
||||
require 'rubygems/custom_require'
|
||||
end
|
||||
|
|
|
@ -46,6 +46,7 @@ module Gem
|
|||
register_command :server
|
||||
register_command :sources
|
||||
register_command :specification
|
||||
register_command :stale
|
||||
register_command :uninstall
|
||||
register_command :unpack
|
||||
register_command :update
|
||||
|
|
|
@ -46,37 +46,67 @@ class Gem::Commands::DependencyCommand < Gem::Command
|
|||
options[:args] << '.' if options[:args].empty?
|
||||
specs = {}
|
||||
|
||||
source_indexes = []
|
||||
source_indexes = Hash.new do |h, source_uri|
|
||||
h[source_uri] = Gem::SourceIndex.new
|
||||
end
|
||||
|
||||
pattern = /\A#{Regexp.union(*options[:args])}/
|
||||
dependency = Gem::Dependency.new pattern, options[:version]
|
||||
|
||||
if options[:reverse_dependencies] and remote? and not local? then
|
||||
alert_error 'Only reverse dependencies for local gems are supported.'
|
||||
terminate_interaction 1
|
||||
end
|
||||
|
||||
if local? then
|
||||
source_indexes << Gem::SourceIndex.from_installed_gems
|
||||
end
|
||||
|
||||
if remote? then
|
||||
Gem::SourceInfoCache.cache_data.map do |_, sice|
|
||||
source_indexes << sice.source_index
|
||||
Gem.source_index.search(dependency).each do |spec|
|
||||
source_indexes[:local].add_spec spec
|
||||
end
|
||||
end
|
||||
|
||||
options[:args].each do |name|
|
||||
new_specs = nil
|
||||
source_indexes.each do |source_index|
|
||||
new_specs = find_gems(name, source_index)
|
||||
if remote? and not options[:reverse_dependencies] then
|
||||
fetcher = Gem::SpecFetcher.fetcher
|
||||
|
||||
begin
|
||||
fetcher.find_matching(dependency).each do |spec_tuple, source_uri|
|
||||
spec = fetcher.fetch_spec spec_tuple, URI.parse(source_uri)
|
||||
|
||||
source_indexes[source_uri].add_spec spec
|
||||
end
|
||||
rescue Gem::RemoteFetcher::FetchError => e
|
||||
raise unless fetcher.warn_legacy e do
|
||||
require 'rubygems/source_info_cache'
|
||||
|
||||
specs = Gem::SourceInfoCache.search_with_source dependency, false
|
||||
|
||||
specs.each do |spec, source_uri|
|
||||
source_indexes[source_uri].add_spec spec
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
say "No match found for #{name} (#{options[:version]})" if
|
||||
new_specs.empty?
|
||||
|
||||
specs = specs.merge new_specs
|
||||
end
|
||||
|
||||
terminate_interaction 1 if specs.empty?
|
||||
if source_indexes.empty? then
|
||||
patterns = options[:args].join ','
|
||||
say "No gems found matching #{patterns} (#{options[:version]})" if
|
||||
Gem.configuration.verbose
|
||||
|
||||
terminate_interaction 1
|
||||
end
|
||||
|
||||
specs = {}
|
||||
|
||||
source_indexes.values.each do |source_index|
|
||||
source_index.gems.each do |name, spec|
|
||||
specs[spec.full_name] = [source_index, spec]
|
||||
end
|
||||
end
|
||||
|
||||
reverse = Hash.new { |h, k| h[k] = [] }
|
||||
|
||||
if options[:reverse_dependencies] then
|
||||
specs.values.each do |source_index, spec|
|
||||
reverse[spec.full_name] = find_reverse_dependencies spec, source_index
|
||||
specs.values.each do |_, spec|
|
||||
reverse[spec.full_name] = find_reverse_dependencies spec
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -118,10 +148,10 @@ class Gem::Commands::DependencyCommand < Gem::Command
|
|||
end
|
||||
|
||||
# Retuns list of [specification, dep] that are satisfied by spec.
|
||||
def find_reverse_dependencies(spec, source_index)
|
||||
def find_reverse_dependencies(spec)
|
||||
result = []
|
||||
|
||||
source_index.each do |name, sp|
|
||||
Gem.source_index.each do |name, sp|
|
||||
sp.dependencies.each do |dep|
|
||||
dep = Gem::Dependency.new(*dep) unless Gem::Dependency === dep
|
||||
|
||||
|
@ -146,5 +176,6 @@ class Gem::Commands::DependencyCommand < Gem::Command
|
|||
|
||||
specs
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -51,6 +51,8 @@ class Gem::Commands::EnvironmentCommand < Gem::Command
|
|||
|
||||
out << " - RUBY EXECUTABLE: #{Gem.ruby}\n"
|
||||
|
||||
out << " - EXECUTABLE DIRECTORY: #{Gem.bindir}\n"
|
||||
|
||||
out << " - RUBYGEMS PLATFORMS:\n"
|
||||
Gem.platforms.each do |platform|
|
||||
out << " - #{platform}\n"
|
||||
|
|
|
@ -33,12 +33,14 @@ class Gem::Commands::FetchCommand < Gem::Command
|
|||
|
||||
def execute
|
||||
version = options[:version] || Gem::Requirement.default
|
||||
all = Gem::Requirement.default
|
||||
|
||||
gem_names = get_all_gem_names
|
||||
|
||||
gem_names.each do |gem_name|
|
||||
dep = Gem::Dependency.new gem_name, version
|
||||
specs_and_sources = Gem::SourceInfoCache.search_with_source dep, true
|
||||
|
||||
specs_and_sources = Gem::SpecFetcher.fetcher.fetch dep, all
|
||||
|
||||
specs_and_sources.sort_by { |spec,| spec.version }
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@ class Gem::Commands::InstallCommand < Gem::Command
|
|||
defaults = Gem::DependencyInstaller::DEFAULT_OPTIONS.merge({
|
||||
:generate_rdoc => true,
|
||||
:generate_ri => true,
|
||||
:install_dir => Gem.dir,
|
||||
:format_executable => false,
|
||||
:test => false,
|
||||
:version => Gem::Requirement.default,
|
||||
|
@ -62,7 +61,8 @@ class Gem::Commands::InstallCommand < Gem::Command
|
|||
:install_dir => options[:install_dir],
|
||||
:security_policy => options[:security_policy],
|
||||
:wrappers => options[:wrappers],
|
||||
:bin_dir => options[:bin_dir]
|
||||
:bin_dir => options[:bin_dir],
|
||||
:development => options[:development],
|
||||
}
|
||||
|
||||
exit_code = 0
|
||||
|
|
|
@ -1,33 +1,35 @@
|
|||
require 'rubygems/command'
|
||||
require 'rubygems/commands/query_command'
|
||||
|
||||
module Gem
|
||||
module Commands
|
||||
class ListCommand < QueryCommand
|
||||
##
|
||||
# An alternate to Gem::Commands::QueryCommand that searches for gems starting
|
||||
# with the the supplied argument.
|
||||
|
||||
def initialize
|
||||
super 'list', 'Display gems whose name starts with STRING'
|
||||
class Gem::Commands::ListCommand < Gem::Commands::QueryCommand
|
||||
|
||||
remove_option('--name-matches')
|
||||
end
|
||||
def initialize
|
||||
super 'list', 'Display gems whose name starts with STRING'
|
||||
|
||||
def arguments # :nodoc:
|
||||
"STRING start of gem name to look for"
|
||||
end
|
||||
|
||||
def defaults_str # :nodoc:
|
||||
"--local --no-details"
|
||||
end
|
||||
|
||||
def usage # :nodoc:
|
||||
"#{program_name} [STRING]"
|
||||
end
|
||||
|
||||
def execute
|
||||
string = get_one_optional_argument || ''
|
||||
options[:name] = /^#{string}/i
|
||||
super
|
||||
end
|
||||
end
|
||||
remove_option('--name-matches')
|
||||
end
|
||||
|
||||
def arguments # :nodoc:
|
||||
"STRING start of gem name to look for"
|
||||
end
|
||||
|
||||
def defaults_str # :nodoc:
|
||||
"--local --no-details"
|
||||
end
|
||||
|
||||
def usage # :nodoc:
|
||||
"#{program_name} [STRING]"
|
||||
end
|
||||
|
||||
def execute
|
||||
string = get_one_optional_argument || ''
|
||||
options[:name] = /^#{string}/i
|
||||
super
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ lock it down to the exact version.
|
|||
say "gem '#{spec.name}', '= #{spec.version}'" unless locked[spec.name]
|
||||
locked[spec.name] = true
|
||||
|
||||
spec.dependencies.each do |dep|
|
||||
spec.runtime_dependencies.each do |dep|
|
||||
next if locked[dep.name]
|
||||
candidates = Gem.source_index.search dep.name, dep.requirement_list
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
require 'rubygems/command'
|
||||
require 'rubygems/local_remote_options'
|
||||
require 'rubygems/source_info_cache'
|
||||
require 'rubygems/spec_fetcher'
|
||||
require 'rubygems/version_option'
|
||||
|
||||
class Gem::Commands::OutdatedCommand < Gem::Command
|
||||
|
@ -20,8 +20,11 @@ class Gem::Commands::OutdatedCommand < Gem::Command
|
|||
|
||||
locals.outdated.sort.each do |name|
|
||||
local = locals.search(/^#{name}$/).last
|
||||
remotes = Gem::SourceInfoCache.search_with_source(/^#{name}$/, true)
|
||||
|
||||
dep = Gem::Dependency.new local.name, ">= #{local.version}"
|
||||
remotes = Gem::SpecFetcher.fetcher.fetch dep
|
||||
remote = remotes.last.first
|
||||
|
||||
say "#{local.name} (#{local.version} < #{remote.version})"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -82,51 +82,10 @@ revert the gem.
|
|||
end
|
||||
|
||||
# TODO use installer options
|
||||
installer = Gem::Installer.new gem, :wrappers => true
|
||||
installer = Gem::Installer.new gem, :wrappers => true, :force => true
|
||||
installer.install
|
||||
|
||||
gem_file = File.join install_dir, "cache", "#{spec.full_name}.gem"
|
||||
|
||||
security_policy = nil # TODO use installer option
|
||||
|
||||
format = Gem::Format.from_file_by_path gem_file, security_policy
|
||||
|
||||
target_directory = File.join(install_dir, "gems", format.spec.full_name)
|
||||
target_directory.untaint
|
||||
|
||||
pristine_files = format.file_entries.collect { |data| data[0]["path"] }
|
||||
file_map = {}
|
||||
|
||||
format.file_entries.each do |entry, file_data|
|
||||
file_map[entry["path"]] = file_data
|
||||
end
|
||||
|
||||
Dir.chdir target_directory do
|
||||
deployed_files = Dir.glob(File.join("**", "*")) +
|
||||
Dir.glob(File.join("**", ".*"))
|
||||
|
||||
pristine_files = pristine_files.map { |f| File.expand_path f }
|
||||
deployed_files = deployed_files.map { |f| File.expand_path f }
|
||||
|
||||
to_redeploy = (pristine_files - deployed_files)
|
||||
to_redeploy = to_redeploy.map { |path| path.untaint}
|
||||
|
||||
if to_redeploy.length > 0 then
|
||||
say "Restoring #{to_redeploy.length} file#{to_redeploy.length == 1 ? "" : "s"} to #{spec.full_name}..."
|
||||
|
||||
to_redeploy.each do |path|
|
||||
say " #{path}"
|
||||
FileUtils.mkdir_p File.dirname(path)
|
||||
File.open(path, "wb") do |out|
|
||||
out.write file_map[path]
|
||||
end
|
||||
end
|
||||
else
|
||||
say "#{spec.full_name} is in pristine condition"
|
||||
end
|
||||
end
|
||||
|
||||
installer.generate_bin
|
||||
installer.build_extensions
|
||||
say "Restored #{spec.full_name}"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
require 'rubygems/command'
|
||||
require 'rubygems/local_remote_options'
|
||||
require 'rubygems/source_info_cache'
|
||||
require 'rubygems/spec_fetcher'
|
||||
require 'rubygems/version_option'
|
||||
|
||||
class Gem::Commands::QueryCommand < Gem::Command
|
||||
|
@ -74,7 +74,13 @@ class Gem::Commands::QueryCommand < Gem::Command
|
|||
say "*** LOCAL GEMS ***"
|
||||
say
|
||||
|
||||
output_query_results Gem.source_index.search(name)
|
||||
specs = Gem.source_index.search name
|
||||
|
||||
spec_tuples = specs.map do |spec|
|
||||
[[spec.name, spec.version, spec.original_platform, spec], :local]
|
||||
end
|
||||
|
||||
output_query_results spec_tuples
|
||||
end
|
||||
|
||||
if remote? then
|
||||
|
@ -84,13 +90,26 @@ class Gem::Commands::QueryCommand < Gem::Command
|
|||
|
||||
all = options[:all]
|
||||
|
||||
dep = Gem::Dependency.new name, Gem::Requirement.default
|
||||
begin
|
||||
Gem::SourceInfoCache.cache all
|
||||
rescue Gem::RemoteFetcher::FetchError
|
||||
# no network
|
||||
fetcher = Gem::SpecFetcher.fetcher
|
||||
spec_tuples = fetcher.find_matching dep, all, false
|
||||
rescue Gem::RemoteFetcher::FetchError => e
|
||||
raise unless fetcher.warn_legacy e do
|
||||
require 'rubygems/source_info_cache'
|
||||
|
||||
dep.name = '' if dep.name == //
|
||||
|
||||
specs = Gem::SourceInfoCache.search_with_source dep, false, all
|
||||
|
||||
spec_tuples = specs.map do |spec, source_uri|
|
||||
[[spec.name, spec.version, spec.original_platform, spec],
|
||||
source_uri]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
output_query_results Gem::SourceInfoCache.search(name, false, all)
|
||||
output_query_results spec_tuples
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -104,28 +123,30 @@ class Gem::Commands::QueryCommand < Gem::Command
|
|||
!Gem.source_index.search(dep).empty?
|
||||
end
|
||||
|
||||
def output_query_results(gemspecs)
|
||||
def output_query_results(spec_tuples)
|
||||
output = []
|
||||
gem_list_with_version = {}
|
||||
versions = Hash.new { |h,name| h[name] = [] }
|
||||
|
||||
gemspecs.flatten.each do |gemspec|
|
||||
gem_list_with_version[gemspec.name] ||= []
|
||||
gem_list_with_version[gemspec.name] << gemspec
|
||||
spec_tuples.each do |spec_tuple, source_uri|
|
||||
versions[spec_tuple.first] << [spec_tuple, source_uri]
|
||||
end
|
||||
|
||||
gem_list_with_version = gem_list_with_version.sort_by do |name, spec|
|
||||
versions = versions.sort_by do |(name,),|
|
||||
name.downcase
|
||||
end
|
||||
|
||||
gem_list_with_version.each do |gem_name, list_of_matching|
|
||||
list_of_matching = list_of_matching.sort_by { |x| x.version.to_ints }.reverse
|
||||
seen_versions = {}
|
||||
versions.each do |gem_name, matching_tuples|
|
||||
matching_tuples = matching_tuples.sort_by do |(name, version,),|
|
||||
version
|
||||
end.reverse
|
||||
|
||||
list_of_matching.delete_if do |item|
|
||||
if seen_versions[item.version] then
|
||||
seen = {}
|
||||
|
||||
matching_tuples.delete_if do |(name, version,),|
|
||||
if seen[version] then
|
||||
true
|
||||
else
|
||||
seen_versions[item.version] = true
|
||||
seen[version] = true
|
||||
false
|
||||
end
|
||||
end
|
||||
|
@ -133,12 +154,50 @@ class Gem::Commands::QueryCommand < Gem::Command
|
|||
entry = gem_name.dup
|
||||
|
||||
if options[:versions] then
|
||||
versions = list_of_matching.map { |s| s.version }.uniq
|
||||
versions = matching_tuples.map { |(name, version,),| version }.uniq
|
||||
entry << " (#{versions.join ', '})"
|
||||
end
|
||||
|
||||
entry << "\n" << format_text(list_of_matching[0].summary, 68, 4) if
|
||||
options[:details]
|
||||
if options[:details] then
|
||||
detail_tuple = matching_tuples.first
|
||||
|
||||
spec = if detail_tuple.first.length == 4 then
|
||||
detail_tuple.first.last
|
||||
else
|
||||
uri = URI.parse detail_tuple.last
|
||||
Gem::SpecFetcher.fetcher.fetch_spec detail_tuple.first, uri
|
||||
end
|
||||
|
||||
entry << "\n"
|
||||
authors = "Author#{spec.authors.length > 1 ? 's' : ''}: "
|
||||
authors << spec.authors.join(', ')
|
||||
entry << format_text(authors, 68, 4)
|
||||
|
||||
if spec.rubyforge_project and not spec.rubyforge_project.empty? then
|
||||
rubyforge = "Rubyforge: http://rubyforge.org/projects/#{spec.rubyforge_project}"
|
||||
entry << "\n" << format_text(rubyforge, 68, 4)
|
||||
end
|
||||
|
||||
if spec.homepage and not spec.homepage.empty? then
|
||||
entry << "\n" << format_text("Homepage: #{spec.homepage}", 68, 4)
|
||||
end
|
||||
|
||||
if spec.loaded_from then
|
||||
if matching_tuples.length == 1 then
|
||||
loaded_from = File.dirname File.dirname(spec.loaded_from)
|
||||
entry << "\n" << " Installed at: #{loaded_from}"
|
||||
else
|
||||
label = 'Installed at'
|
||||
matching_tuples.each do |(_,version,_,s),|
|
||||
loaded_from = File.dirname File.dirname(s.loaded_from)
|
||||
entry << "\n" << " #{label} (#{version}): #{loaded_from}"
|
||||
label = ' ' * label.length
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
entry << "\n\n" << format_text(spec.summary, 68, 4)
|
||||
end
|
||||
output << entry
|
||||
end
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
require 'fileutils'
|
||||
require 'rubygems/command'
|
||||
require 'rubygems/remote_fetcher'
|
||||
require 'rubygems/source_info_cache'
|
||||
require 'rubygems/source_info_cache_entry'
|
||||
require 'rubygems/spec_fetcher'
|
||||
|
||||
class Gem::Commands::SourcesCommand < Gem::Command
|
||||
|
||||
|
@ -21,14 +22,14 @@ class Gem::Commands::SourcesCommand < Gem::Command
|
|||
options[:remove] = value
|
||||
end
|
||||
|
||||
add_option '-u', '--update', 'Update source cache' do |value, options|
|
||||
options[:update] = value
|
||||
end
|
||||
|
||||
add_option '-c', '--clear-all',
|
||||
'Remove all sources (clear the cache)' do |value, options|
|
||||
options[:clear_all] = value
|
||||
end
|
||||
|
||||
add_option '-u', '--update', 'Update source cache' do |value, options|
|
||||
options[:update] = value
|
||||
end
|
||||
end
|
||||
|
||||
def defaults_str
|
||||
|
@ -36,9 +37,23 @@ class Gem::Commands::SourcesCommand < Gem::Command
|
|||
end
|
||||
|
||||
def execute
|
||||
options[:list] = !(options[:add] || options[:remove] || options[:clear_all] || options[:update])
|
||||
options[:list] = !(options[:add] ||
|
||||
options[:clear_all] ||
|
||||
options[:remove] ||
|
||||
options[:update])
|
||||
|
||||
if options[:clear_all] then
|
||||
path = Gem::SpecFetcher.fetcher.dir
|
||||
FileUtils.rm_rf path
|
||||
|
||||
if not File.exist?(path) then
|
||||
say "*** Removed specs cache ***"
|
||||
elsif not File.writable?(path) then
|
||||
say "*** Unable to remove source cache (write protected) ***"
|
||||
else
|
||||
say "*** Unable to remove source cache ***"
|
||||
end
|
||||
|
||||
sic = Gem::SourceInfoCache
|
||||
remove_cache_file 'user', sic.user_cache_file
|
||||
remove_cache_file 'latest user', sic.latest_user_cache_file
|
||||
|
@ -48,15 +63,10 @@ class Gem::Commands::SourcesCommand < Gem::Command
|
|||
|
||||
if options[:add] then
|
||||
source_uri = options[:add]
|
||||
uri = URI.parse source_uri
|
||||
|
||||
sice = Gem::SourceInfoCacheEntry.new nil, nil
|
||||
begin
|
||||
sice.refresh source_uri, true
|
||||
|
||||
Gem::SourceInfoCache.cache_data[source_uri] = sice
|
||||
Gem::SourceInfoCache.cache.update
|
||||
Gem::SourceInfoCache.cache.flush
|
||||
|
||||
Gem::SpecFetcher.fetcher.load_specs uri, 'specs'
|
||||
Gem.sources << source_uri
|
||||
Gem.configuration.write
|
||||
|
||||
|
@ -64,31 +74,32 @@ class Gem::Commands::SourcesCommand < Gem::Command
|
|||
rescue URI::Error, ArgumentError
|
||||
say "#{source_uri} is not a URI"
|
||||
rescue Gem::RemoteFetcher::FetchError => e
|
||||
say "Error fetching #{source_uri}:\n\t#{e.message}"
|
||||
yaml_uri = uri + 'yaml'
|
||||
gem_repo = Gem::RemoteFetcher.fetcher.fetch_size yaml_uri rescue false
|
||||
|
||||
if e.uri =~ /specs\.#{Regexp.escape Gem.marshal_version}\.gz$/ and
|
||||
gem_repo then
|
||||
|
||||
alert_warning <<-EOF
|
||||
RubyGems 1.2+ index not found for:
|
||||
\t#{source_uri}
|
||||
|
||||
Will cause RubyGems to revert to legacy indexes, degrading performance.
|
||||
EOF
|
||||
|
||||
say "#{source_uri} added to sources"
|
||||
else
|
||||
say "Error fetching #{source_uri}:\n\t#{e.message}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if options[:update] then
|
||||
Gem::SourceInfoCache.cache true
|
||||
Gem::SourceInfoCache.cache.flush
|
||||
|
||||
say "source cache successfully updated"
|
||||
end
|
||||
|
||||
if options[:remove] then
|
||||
source_uri = options[:remove]
|
||||
|
||||
unless Gem.sources.include? source_uri then
|
||||
say "source #{source_uri} not present in cache"
|
||||
else
|
||||
begin # HACK figure out how to get the cache w/o update
|
||||
Gem::SourceInfoCache.cache
|
||||
rescue Gem::RemoteFetcher::FetchError
|
||||
end
|
||||
|
||||
Gem::SourceInfoCache.cache_data.delete source_uri
|
||||
Gem::SourceInfoCache.cache.update
|
||||
Gem::SourceInfoCache.cache.flush
|
||||
Gem.sources.delete source_uri
|
||||
Gem.configuration.write
|
||||
|
||||
|
@ -96,6 +107,23 @@ class Gem::Commands::SourcesCommand < Gem::Command
|
|||
end
|
||||
end
|
||||
|
||||
if options[:update] then
|
||||
fetcher = Gem::SpecFetcher.fetcher
|
||||
|
||||
if fetcher.legacy_repos.empty? then
|
||||
Gem.sources.each do |source_uri|
|
||||
source_uri = URI.parse source_uri
|
||||
fetcher.load_specs source_uri, 'specs'
|
||||
fetcher.load_specs source_uri, 'latest_specs'
|
||||
end
|
||||
else
|
||||
Gem::SourceInfoCache.cache true
|
||||
Gem::SourceInfoCache.cache.flush
|
||||
end
|
||||
|
||||
say "source cache successfully updated"
|
||||
end
|
||||
|
||||
if options[:list] then
|
||||
say "*** CURRENT SOURCES ***"
|
||||
say
|
||||
|
|
|
@ -52,9 +52,10 @@ class Gem::Commands::SpecificationCommand < Gem::Command
|
|||
end
|
||||
|
||||
if remote? then
|
||||
Gem::SourceInfoCache.cache_data.each do |_,sice|
|
||||
specs.push(*sice.source_index.search(gem, options[:version]))
|
||||
end
|
||||
dep = Gem::Dependency.new gem, options[:version]
|
||||
found = Gem::SpecFetcher.fetcher.fetch dep
|
||||
|
||||
specs.push(*found.map { |spec,| spec })
|
||||
end
|
||||
|
||||
if specs.empty? then
|
||||
|
|
27
lib/rubygems/commands/stale_command.rb
Normal file
27
lib/rubygems/commands/stale_command.rb
Normal file
|
@ -0,0 +1,27 @@
|
|||
require 'rubygems/command'
|
||||
|
||||
class Gem::Commands::StaleCommand < Gem::Command
|
||||
def initialize
|
||||
super('stale', 'List gems along with access times')
|
||||
end
|
||||
|
||||
def usage # :nodoc:
|
||||
"#{program_name}"
|
||||
end
|
||||
|
||||
def execute
|
||||
gem_to_atime = {}
|
||||
Gem.source_index.each do |name, spec|
|
||||
Dir["#{spec.full_gem_path}/**/*.*"].each do |file|
|
||||
next if File.directory?(file)
|
||||
stat = File.stat(file)
|
||||
gem_to_atime[name] ||= stat.atime
|
||||
gem_to_atime[name] = stat.atime if gem_to_atime[name] < stat.atime
|
||||
end
|
||||
end
|
||||
|
||||
gem_to_atime.sort_by { |_, atime| atime }.each do |name, atime|
|
||||
say "#{name} at #{atime.strftime '%c'}"
|
||||
end
|
||||
end
|
||||
end
|
|
@ -2,7 +2,7 @@ require 'rubygems/command'
|
|||
require 'rubygems/command_manager'
|
||||
require 'rubygems/install_update_options'
|
||||
require 'rubygems/local_remote_options'
|
||||
require 'rubygems/source_info_cache'
|
||||
require 'rubygems/spec_fetcher'
|
||||
require 'rubygems/version_option'
|
||||
require 'rubygems/commands/install_command'
|
||||
|
||||
|
@ -15,11 +15,10 @@ class Gem::Commands::UpdateCommand < Gem::Command
|
|||
def initialize
|
||||
super 'update',
|
||||
'Update the named gems (or all installed gems) in the local repository',
|
||||
:generate_rdoc => true,
|
||||
:generate_ri => true,
|
||||
:force => false,
|
||||
:test => false,
|
||||
:install_dir => Gem.dir
|
||||
:generate_rdoc => true,
|
||||
:generate_ri => true,
|
||||
:force => false,
|
||||
:test => false
|
||||
|
||||
add_install_update_options
|
||||
|
||||
|
@ -60,21 +59,13 @@ class Gem::Commands::UpdateCommand < Gem::Command
|
|||
|
||||
hig = {} # highest installed gems
|
||||
|
||||
Gem::SourceIndex.from_installed_gems.each do |name, spec|
|
||||
Gem.source_index.each do |name, spec|
|
||||
if hig[spec.name].nil? or hig[spec.name].version < spec.version then
|
||||
hig[spec.name] = spec
|
||||
end
|
||||
end
|
||||
|
||||
pattern = if options[:args].empty? then
|
||||
//
|
||||
else
|
||||
Regexp.union(*options[:args])
|
||||
end
|
||||
|
||||
remote_gemspecs = Gem::SourceInfoCache.search pattern
|
||||
|
||||
gems_to_update = which_to_update hig, remote_gemspecs
|
||||
gems_to_update = which_to_update hig, options[:args]
|
||||
|
||||
updated = []
|
||||
|
||||
|
@ -135,20 +126,42 @@ class Gem::Commands::UpdateCommand < Gem::Command
|
|||
end
|
||||
end
|
||||
|
||||
def which_to_update(highest_installed_gems, remote_gemspecs)
|
||||
def which_to_update(highest_installed_gems, gem_names)
|
||||
result = []
|
||||
|
||||
highest_installed_gems.each do |l_name, l_spec|
|
||||
matching_gems = remote_gemspecs.select do |spec|
|
||||
spec.name == l_name and Gem.platforms.any? do |platform|
|
||||
platform == spec.platform
|
||||
next if not gem_names.empty? and
|
||||
gem_names.all? { |name| /#{name}/ !~ l_spec.name }
|
||||
|
||||
dependency = Gem::Dependency.new l_spec.name, "> #{l_spec.version}"
|
||||
|
||||
begin
|
||||
fetcher = Gem::SpecFetcher.fetcher
|
||||
spec_tuples = fetcher.find_matching dependency
|
||||
rescue Gem::RemoteFetcher::FetchError => e
|
||||
raise unless fetcher.warn_legacy e do
|
||||
require 'rubygems/source_info_cache'
|
||||
|
||||
dependency.name = '' if dependency.name == //
|
||||
|
||||
specs = Gem::SourceInfoCache.search_with_source dependency
|
||||
|
||||
spec_tuples = specs.map do |spec, source_uri|
|
||||
[[spec.name, spec.version, spec.original_platform], source_uri]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
highest_remote_gem = matching_gems.sort_by { |spec| spec.version }.last
|
||||
matching_gems = spec_tuples.select do |(name, version, platform),|
|
||||
name == l_name and Gem::Platform.match platform
|
||||
end
|
||||
|
||||
highest_remote_gem = matching_gems.sort_by do |(name, version),|
|
||||
version
|
||||
end.last
|
||||
|
||||
if highest_remote_gem and
|
||||
l_spec.version < highest_remote_gem.version then
|
||||
l_spec.version < highest_remote_gem.first[1] then
|
||||
result << l_name
|
||||
end
|
||||
end
|
||||
|
|
|
@ -18,6 +18,22 @@ class Gem::ConfigFile
|
|||
DEFAULT_VERBOSITY = true
|
||||
DEFAULT_UPDATE_SOURCES = true
|
||||
|
||||
system_config_path =
|
||||
begin
|
||||
require 'Win32API'
|
||||
|
||||
CSIDL_COMMON_APPDATA = 0x0023
|
||||
path = 0.chr * 260
|
||||
SHGetFolderPath = Win32API.new 'shell32', 'SHGetFolderPath', 'LLLLP', 'L'
|
||||
SHGetFolderPath.call 0, CSIDL_COMMON_APPDATA, 0, 1, path
|
||||
|
||||
path.strip
|
||||
rescue LoadError
|
||||
'/etc'
|
||||
end
|
||||
|
||||
SYSTEM_WIDE_CONFIG_FILE = File.join system_config_path, 'gemrc'
|
||||
|
||||
# List of arguments supplied to the config file object.
|
||||
attr_reader :args
|
||||
|
||||
|
@ -81,18 +97,8 @@ class Gem::ConfigFile
|
|||
@verbose = DEFAULT_VERBOSITY
|
||||
@update_sources = DEFAULT_UPDATE_SOURCES
|
||||
|
||||
begin
|
||||
# HACK $SAFE ok?
|
||||
@hash = open(config_file_name.dup.untaint) {|f| YAML.load(f) }
|
||||
rescue ArgumentError
|
||||
warn "Failed to load #{config_file_name}"
|
||||
rescue Errno::ENOENT
|
||||
# Ignore missing config file error.
|
||||
rescue Errno::EACCES
|
||||
warn "Failed to load #{config_file_name} due to permissions problem."
|
||||
end
|
||||
|
||||
@hash ||= {}
|
||||
@hash = load_file(SYSTEM_WIDE_CONFIG_FILE)
|
||||
@hash.merge!(load_file(config_file_name.dup.untaint))
|
||||
|
||||
# HACK these override command-line args, which is bad
|
||||
@backtrace = @hash[:backtrace] if @hash.key? :backtrace
|
||||
|
@ -105,6 +111,16 @@ class Gem::ConfigFile
|
|||
handle_arguments arg_list
|
||||
end
|
||||
|
||||
def load_file(filename)
|
||||
begin
|
||||
YAML.load(File.read(filename)) if filename and File.exist?(filename)
|
||||
rescue ArgumentError
|
||||
warn "Failed to load #{config_file_name}"
|
||||
rescue Errno::EACCES
|
||||
warn "Failed to load #{config_file_name} due to permissions problem."
|
||||
end or {}
|
||||
end
|
||||
|
||||
# True if the backtrace option has been specified, or debug is on.
|
||||
def backtrace
|
||||
@backtrace or $DEBUG
|
||||
|
|
|
@ -26,7 +26,7 @@ module Kernel
|
|||
def require(path) # :nodoc:
|
||||
gem_original_require path
|
||||
rescue LoadError => load_error
|
||||
if load_error.message =~ /\A[Nn]o such file to load -- #{Regexp.escape path}\z/ and
|
||||
if load_error.message =~ /#{Regexp.escape path}\z/ and
|
||||
spec = Gem.searcher.find(path) then
|
||||
Gem.activate(spec.name, "= #{spec.version}")
|
||||
gem_original_require path
|
||||
|
|
|
@ -2,7 +2,7 @@ module Gem
|
|||
|
||||
# An Array of the default sources that come with RubyGems.
|
||||
def self.default_sources
|
||||
%w[http://gems.rubyforge.org]
|
||||
%w[http://gems.rubyforge.org/]
|
||||
end
|
||||
|
||||
# Default home directory path to be used if an alternate value is not
|
||||
|
|
|
@ -8,24 +8,54 @@ require 'rubygems'
|
|||
|
||||
##
|
||||
# The Dependency class holds a Gem name and a Gem::Requirement
|
||||
|
||||
class Gem::Dependency
|
||||
|
||||
##
|
||||
# Valid dependency types.
|
||||
#--
|
||||
# When this list is updated, be sure to change
|
||||
# Gem::Specification::CURRENT_SPECIFICATION_VERSION as well.
|
||||
|
||||
TYPES = [
|
||||
:development,
|
||||
:runtime,
|
||||
]
|
||||
|
||||
##
|
||||
# Dependency name or regular expression.
|
||||
|
||||
attr_accessor :name
|
||||
|
||||
##
|
||||
# Dependency type.
|
||||
|
||||
attr_reader :type
|
||||
|
||||
##
|
||||
# Dependent versions.
|
||||
|
||||
attr_writer :version_requirements
|
||||
|
||||
##
|
||||
# Orders dependencies by name only.
|
||||
|
||||
def <=>(other)
|
||||
[@name] <=> [other.name]
|
||||
end
|
||||
|
||||
##
|
||||
# Constructs the dependency
|
||||
#
|
||||
# name:: [String] name of the Gem
|
||||
# version_requirements:: [String Array] version requirement (e.g. ["> 1.2"])
|
||||
#
|
||||
def initialize(name, version_requirements)
|
||||
# Constructs a dependency with +name+ and +requirements+.
|
||||
|
||||
def initialize(name, version_requirements, type=:runtime)
|
||||
@name = name
|
||||
|
||||
unless TYPES.include? type
|
||||
raise ArgumentError, "Valid types are #{TYPES.inspect}, not #{@type.inspect}"
|
||||
end
|
||||
|
||||
@type = type
|
||||
|
||||
@version_requirements = Gem::Requirement.create version_requirements
|
||||
@version_requirement = nil # Avoid warnings.
|
||||
end
|
||||
|
@ -48,17 +78,41 @@ class Gem::Dependency
|
|||
end
|
||||
|
||||
def to_s # :nodoc:
|
||||
"#{name} (#{version_requirements})"
|
||||
"#{name} (#{version_requirements}, #{@type || :runtime})"
|
||||
end
|
||||
|
||||
def ==(other) # :nodoc:
|
||||
self.class === other &&
|
||||
self.name == other.name &&
|
||||
self.type == other.type &&
|
||||
self.version_requirements == other.version_requirements
|
||||
end
|
||||
|
||||
def hash
|
||||
name.hash + version_requirements.hash
|
||||
##
|
||||
# Uses this dependency as a pattern to compare to the dependency +other+.
|
||||
# This dependency will match if the name matches the other's name, and other
|
||||
# has only an equal version requirement that satisfies this dependency.
|
||||
|
||||
def =~(other)
|
||||
return false unless self.class === other
|
||||
|
||||
pattern = @name
|
||||
pattern = /\A#{@name}\Z/ unless Regexp === pattern
|
||||
|
||||
return false unless pattern =~ other.name
|
||||
|
||||
reqs = other.version_requirements.requirements
|
||||
|
||||
return false unless reqs.length == 1
|
||||
return false unless reqs.first.first == '='
|
||||
|
||||
version = reqs.first.last
|
||||
|
||||
version_requirements.satisfied_by? version
|
||||
end
|
||||
|
||||
def hash # :nodoc:
|
||||
name.hash + type.hash + version_requirements.hash
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
require 'rubygems'
|
||||
require 'rubygems/dependency_list'
|
||||
require 'rubygems/installer'
|
||||
require 'rubygems/source_info_cache'
|
||||
require 'rubygems/spec_fetcher'
|
||||
require 'rubygems/user_interaction'
|
||||
|
||||
##
|
||||
# Installs a gem along with all its dependencies from local and remote gems.
|
||||
|
||||
class Gem::DependencyInstaller
|
||||
|
||||
include Gem::UserInteraction
|
||||
|
@ -25,36 +28,50 @@ class Gem::DependencyInstaller
|
|||
# Creates a new installer instance.
|
||||
#
|
||||
# Options are:
|
||||
# :env_shebang:: See Gem::Installer::new.
|
||||
# :cache_dir:: Alternate repository path to store .gem files in.
|
||||
# :domain:: :local, :remote, or :both. :local only searches gems in the
|
||||
# current directory. :remote searches only gems in Gem::sources.
|
||||
# :both searches both.
|
||||
# :env_shebang:: See Gem::Installer::new.
|
||||
# :force:: See Gem::Installer#install.
|
||||
# :format_executable:: See Gem::Installer#initialize.
|
||||
# :ignore_dependencies: Don't install any dependencies.
|
||||
# :install_dir: See Gem::Installer#install.
|
||||
# :security_policy: See Gem::Installer::new and Gem::Security.
|
||||
# :wrappers: See Gem::Installer::new
|
||||
# :ignore_dependencies:: Don't install any dependencies.
|
||||
# :install_dir:: See Gem::Installer#install.
|
||||
# :security_policy:: See Gem::Installer::new and Gem::Security.
|
||||
# :wrappers:: See Gem::Installer::new
|
||||
|
||||
def initialize(options = {})
|
||||
options = DEFAULT_OPTIONS.merge options
|
||||
@env_shebang = options[:env_shebang]
|
||||
|
||||
@bin_dir = options[:bin_dir]
|
||||
@development = options[:development]
|
||||
@domain = options[:domain]
|
||||
@env_shebang = options[:env_shebang]
|
||||
@force = options[:force]
|
||||
@format_executable = options[:format_executable]
|
||||
@ignore_dependencies = options[:ignore_dependencies]
|
||||
@install_dir = options[:install_dir] || Gem.dir
|
||||
@security_policy = options[:security_policy]
|
||||
@wrappers = options[:wrappers]
|
||||
@bin_dir = options[:bin_dir]
|
||||
|
||||
@installed_gems = []
|
||||
|
||||
@install_dir = options[:install_dir] || Gem.dir
|
||||
@cache_dir = options[:cache_dir] || @install_dir
|
||||
|
||||
if options[:install_dir] then
|
||||
spec_dir = File.join @install_dir, 'specifications'
|
||||
@source_index = Gem::SourceIndex.from_gems_in spec_dir
|
||||
else
|
||||
@source_index = Gem.source_index
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Returns a list of pairs of gemspecs and source_uris that match
|
||||
# Gem::Dependency +dep+ from both local (Dir.pwd) and remote (Gem.sources)
|
||||
# sources. Gems are sorted with newer gems preferred over older gems, and
|
||||
# sources. Gems are sorted with newer gems prefered over older gems, and
|
||||
# local gems preferred over remote gems.
|
||||
|
||||
def find_gems_with_sources(dep)
|
||||
gems_and_sources = []
|
||||
|
||||
|
@ -74,8 +91,7 @@ class Gem::DependencyInstaller
|
|||
all = requirements.length > 1 ||
|
||||
(requirements.first != ">=" and requirements.first != ">")
|
||||
|
||||
found = Gem::SourceInfoCache.search_with_source dep, true, all
|
||||
|
||||
found = Gem::SpecFetcher.fetcher.fetch dep, all
|
||||
gems_and_sources.push(*found)
|
||||
|
||||
rescue Gem::RemoteFetcher::FetchError => e
|
||||
|
@ -95,6 +111,7 @@ class Gem::DependencyInstaller
|
|||
##
|
||||
# Gathers all dependencies necessary for the installation from local and
|
||||
# remote sources unless the ignore_dependencies was given.
|
||||
|
||||
def gather_dependencies
|
||||
specs = @specs_and_sources.map { |spec,_| spec }
|
||||
|
||||
|
@ -110,8 +127,18 @@ class Gem::DependencyInstaller
|
|||
next if spec.nil? or seen[spec.name]
|
||||
seen[spec.name] = true
|
||||
|
||||
spec.dependencies.each do |dep|
|
||||
results = find_gems_with_sources(dep).reverse # local gems first
|
||||
deps = spec.runtime_dependencies
|
||||
deps |= spec.development_dependencies if @development
|
||||
|
||||
deps.each do |dep|
|
||||
results = find_gems_with_sources(dep).reverse
|
||||
|
||||
results.reject! do |spec,|
|
||||
@source_index.any? do |_, installed_spec|
|
||||
dep.name == installed_spec.name and
|
||||
dep.version_requirements.satisfied_by? installed_spec.version
|
||||
end
|
||||
end
|
||||
|
||||
results.each do |dep_spec, source_uri|
|
||||
next if seen[dep_spec.name]
|
||||
|
@ -126,6 +153,11 @@ class Gem::DependencyInstaller
|
|||
@gems_to_install = dependency_list.dependency_order.reverse
|
||||
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
|
||||
spec_and_source = nil
|
||||
|
||||
|
@ -160,14 +192,16 @@ class Gem::DependencyInstaller
|
|||
|
||||
if spec_and_source.nil? then
|
||||
raise Gem::GemNotFoundException,
|
||||
"could not find #{gem_name} locally or in a repository"
|
||||
"could not find gem #{gem_name} locally or in a repository"
|
||||
end
|
||||
|
||||
@specs_and_sources = [spec_and_source]
|
||||
end
|
||||
|
||||
##
|
||||
# Installs the gem and all its dependencies.
|
||||
# Installs the gem and all its dependencies. Returns an Array of installed
|
||||
# gems specifications.
|
||||
|
||||
def install dep_or_name, version = Gem::Requirement.default
|
||||
if String === dep_or_name then
|
||||
find_spec_by_name_and_version dep_or_name, version
|
||||
|
@ -175,15 +209,14 @@ class Gem::DependencyInstaller
|
|||
@specs_and_sources = [find_gems_with_sources(dep_or_name).last]
|
||||
end
|
||||
|
||||
gather_dependencies
|
||||
@installed_gems = []
|
||||
|
||||
spec_dir = File.join @install_dir, 'specifications'
|
||||
source_index = Gem::SourceIndex.from_gems_in spec_dir
|
||||
gather_dependencies
|
||||
|
||||
@gems_to_install.each do |spec|
|
||||
last = spec == @gems_to_install.last
|
||||
# HACK is this test for full_name acceptable?
|
||||
next if source_index.any? { |n,_| n == spec.full_name } and not last
|
||||
next if @source_index.any? { |n,_| n == spec.full_name } and not last
|
||||
|
||||
# TODO: make this sorta_verbose so other users can benefit from it
|
||||
say "Installing gem #{spec.full_name}" if Gem.configuration.really_verbose
|
||||
|
@ -191,7 +224,7 @@ class Gem::DependencyInstaller
|
|||
_, source_uri = @specs_and_sources.assoc spec
|
||||
begin
|
||||
local_gem_path = Gem::RemoteFetcher.fetcher.download spec, source_uri,
|
||||
@install_dir
|
||||
@cache_dir
|
||||
rescue Gem::RemoteFetcher::FetchError
|
||||
next if @force
|
||||
raise
|
||||
|
@ -205,12 +238,15 @@ class Gem::DependencyInstaller
|
|||
:install_dir => @install_dir,
|
||||
:security_policy => @security_policy,
|
||||
:wrappers => @wrappers,
|
||||
:bin_dir => @bin_dir
|
||||
:bin_dir => @bin_dir,
|
||||
:development => @development
|
||||
|
||||
spec = inst.install
|
||||
|
||||
@installed_gems << spec
|
||||
end
|
||||
|
||||
@installed_gems
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -69,7 +69,7 @@ class Gem::DependencyList
|
|||
# Are all the dependencies in the list satisfied?
|
||||
def ok?
|
||||
@specs.all? do |spec|
|
||||
spec.dependencies.all? do |dep|
|
||||
spec.runtime_dependencies.all? do |dep|
|
||||
@specs.find { |s| s.satisfies_requirement? dep }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,9 +9,9 @@ require 'fileutils'
|
|||
module Gem
|
||||
|
||||
class DocManager
|
||||
|
||||
|
||||
include UserInteraction
|
||||
|
||||
|
||||
# Create a document manager for the given gem spec.
|
||||
#
|
||||
# spec:: The Gem::Specification object representing the gem.
|
||||
|
@ -22,12 +22,12 @@ module Gem
|
|||
@doc_dir = File.join(spec.installation_path, "doc", spec.full_name)
|
||||
@rdoc_args = rdoc_args.nil? ? [] : rdoc_args.split
|
||||
end
|
||||
|
||||
|
||||
# Is the RDoc documentation installed?
|
||||
def rdoc_installed?
|
||||
return File.exist?(File.join(@doc_dir, "rdoc"))
|
||||
end
|
||||
|
||||
|
||||
# Generate the RI documents for this gem spec.
|
||||
#
|
||||
# Note that if both RI and RDoc documents are generated from the
|
||||
|
@ -102,7 +102,7 @@ module Gem
|
|||
args << '--quiet'
|
||||
args << @spec.require_paths.clone
|
||||
args << @spec.extra_rdoc_files
|
||||
args.flatten!
|
||||
args = args.flatten.map do |arg| arg.to_s end
|
||||
|
||||
r = RDoc::RDoc.new
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
require 'fileutils'
|
||||
require 'tmpdir'
|
||||
require 'zlib'
|
||||
|
||||
require 'rubygems'
|
||||
require 'rubygems/format'
|
||||
|
@ -40,104 +41,43 @@ class Gem::Indexer
|
|||
|
||||
marshal_name = "Marshal.#{Gem.marshal_version}"
|
||||
|
||||
@master_index = Gem::Indexer::MasterIndexBuilder.new "yaml", @directory
|
||||
@marshal_index = Gem::Indexer::MarshalIndexBuilder.new marshal_name, @directory
|
||||
@quick_index = Gem::Indexer::QuickIndexBuilder.new 'index', @directory
|
||||
@master_index = File.join @directory, 'yaml'
|
||||
@marshal_index = File.join @directory, marshal_name
|
||||
|
||||
quick_dir = File.join @directory, 'quick'
|
||||
@latest_index = Gem::Indexer::LatestIndexBuilder.new 'latest_index', quick_dir
|
||||
@quick_dir = File.join @directory, 'quick'
|
||||
|
||||
@quick_marshal_dir = File.join @quick_dir, marshal_name
|
||||
|
||||
@quick_index = File.join @quick_dir, 'index'
|
||||
@latest_index = File.join @quick_dir, 'latest_index'
|
||||
|
||||
@specs_index = File.join @directory, "specs.#{Gem.marshal_version}"
|
||||
@latest_specs_index = File.join @directory,
|
||||
"latest_specs.#{Gem.marshal_version}"
|
||||
|
||||
files = [
|
||||
@specs_index,
|
||||
"#{@specs_index}.gz",
|
||||
@latest_specs_index,
|
||||
"#{@latest_specs_index}.gz",
|
||||
@quick_dir,
|
||||
@master_index,
|
||||
"#{@master_index}.Z",
|
||||
@marshal_index,
|
||||
"#{@marshal_index}.Z",
|
||||
]
|
||||
|
||||
@files = files.map do |path|
|
||||
path.sub @directory, ''
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Build the index.
|
||||
# Abbreviate the spec for downloading. Abbreviated specs are only used for
|
||||
# searching, downloading and related activities and do not need deployment
|
||||
# specific information (e.g. list of files). So we abbreviate the spec,
|
||||
# making it much smaller for quicker downloads.
|
||||
|
||||
def build_index
|
||||
@master_index.build do
|
||||
@quick_index.build do
|
||||
@marshal_index.build do
|
||||
@latest_index.build do
|
||||
progress = ui.progress_reporter gem_file_list.size,
|
||||
"Generating index for #{gem_file_list.size} gems in #{@dest_directory}",
|
||||
"Loaded all gems"
|
||||
|
||||
gem_file_list.each do |gemfile|
|
||||
if File.size(gemfile.to_s) == 0 then
|
||||
alert_warning "Skipping zero-length gem: #{gemfile}"
|
||||
next
|
||||
end
|
||||
|
||||
begin
|
||||
spec = Gem::Format.from_file_by_path(gemfile).spec
|
||||
|
||||
unless gemfile =~ /\/#{Regexp.escape spec.original_name}.*\.gem\z/i then
|
||||
alert_warning "Skipping misnamed gem: #{gemfile} => #{spec.full_name} (#{spec.original_name})"
|
||||
next
|
||||
end
|
||||
|
||||
abbreviate spec
|
||||
sanitize spec
|
||||
|
||||
@master_index.add spec
|
||||
@quick_index.add spec
|
||||
@marshal_index.add spec
|
||||
@latest_index.add spec
|
||||
|
||||
progress.updated spec.original_name
|
||||
|
||||
rescue SignalException => e
|
||||
alert_error "Received signal, exiting"
|
||||
raise
|
||||
rescue Exception => e
|
||||
alert_error "Unable to process #{gemfile}\n#{e.message} (#{e.class})\n\t#{e.backtrace.join "\n\t"}"
|
||||
end
|
||||
end
|
||||
|
||||
progress.done
|
||||
|
||||
say "Generating master indexes (this may take a while)"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def install_index
|
||||
verbose = Gem.configuration.really_verbose
|
||||
|
||||
say "Moving index into production dir #{@dest_directory}" if verbose
|
||||
|
||||
files = @master_index.files + @quick_index.files + @marshal_index.files +
|
||||
@latest_index.files
|
||||
|
||||
files.each do |file|
|
||||
src_name = File.join @directory, file
|
||||
dst_name = File.join @dest_directory, file
|
||||
|
||||
FileUtils.rm_rf dst_name, :verbose => verbose
|
||||
FileUtils.mv src_name, @dest_directory, :verbose => verbose
|
||||
end
|
||||
end
|
||||
|
||||
def generate_index
|
||||
FileUtils.rm_rf @directory
|
||||
FileUtils.mkdir_p @directory, :mode => 0700
|
||||
|
||||
build_index
|
||||
install_index
|
||||
rescue SignalException
|
||||
ensure
|
||||
FileUtils.rm_rf @directory
|
||||
end
|
||||
|
||||
# List of gem file names to index.
|
||||
def gem_file_list
|
||||
Dir.glob(File.join(@dest_directory, "gems", "*.gem"))
|
||||
end
|
||||
|
||||
# Abbreviate the spec for downloading. Abbreviated specs are only
|
||||
# used for searching, downloading and related activities and do not
|
||||
# need deployment specific information (e.g. list of files). So we
|
||||
# abbreviate the spec, making it much smaller for quicker downloads.
|
||||
def abbreviate(spec)
|
||||
spec.files = []
|
||||
spec.test_files = []
|
||||
|
@ -147,9 +87,257 @@ class Gem::Indexer
|
|||
spec
|
||||
end
|
||||
|
||||
##
|
||||
# Build various indicies
|
||||
|
||||
def build_indicies(index)
|
||||
progress = ui.progress_reporter index.size,
|
||||
"Generating quick index gemspecs for #{index.size} gems",
|
||||
"Complete"
|
||||
|
||||
index.each do |original_name, spec|
|
||||
spec_file_name = "#{original_name}.gemspec.rz"
|
||||
yaml_name = File.join @quick_dir, spec_file_name
|
||||
marshal_name = File.join @quick_marshal_dir, spec_file_name
|
||||
|
||||
yaml_zipped = Gem.deflate spec.to_yaml
|
||||
open yaml_name, 'wb' do |io| io.write yaml_zipped end
|
||||
|
||||
marshal_zipped = Gem.deflate Marshal.dump(spec)
|
||||
open marshal_name, 'wb' do |io| io.write marshal_zipped end
|
||||
|
||||
progress.updated original_name
|
||||
end
|
||||
|
||||
progress.done
|
||||
|
||||
say "Generating specs index"
|
||||
|
||||
open @specs_index, 'wb' do |io|
|
||||
specs = index.sort.map do |_, spec|
|
||||
platform = spec.original_platform
|
||||
platform = Gem::Platform::RUBY if platform.nil?
|
||||
[spec.name, spec.version, platform]
|
||||
end
|
||||
|
||||
specs = compact_specs specs
|
||||
|
||||
Marshal.dump specs, io
|
||||
end
|
||||
|
||||
say "Generating latest specs index"
|
||||
|
||||
open @latest_specs_index, 'wb' do |io|
|
||||
specs = index.latest_specs.sort.map do |spec|
|
||||
[spec.name, spec.version, spec.original_platform]
|
||||
end
|
||||
|
||||
specs = compact_specs specs
|
||||
|
||||
Marshal.dump specs, io
|
||||
end
|
||||
|
||||
say "Generating quick index"
|
||||
|
||||
quick_index = File.join @quick_dir, 'index'
|
||||
open quick_index, 'wb' do |io|
|
||||
io.puts index.sort.map { |_, spec| spec.original_name }
|
||||
end
|
||||
|
||||
say "Generating latest index"
|
||||
|
||||
latest_index = File.join @quick_dir, 'latest_index'
|
||||
open latest_index, 'wb' do |io|
|
||||
io.puts index.latest_specs.sort.map { |spec| spec.original_name }
|
||||
end
|
||||
|
||||
say "Generating Marshal master index"
|
||||
|
||||
open @marshal_index, 'wb' do |io|
|
||||
io.write index.dump
|
||||
end
|
||||
|
||||
progress = ui.progress_reporter index.size,
|
||||
"Generating YAML master index for #{index.size} gems (this may take a while)",
|
||||
"Complete"
|
||||
|
||||
open @master_index, 'wb' do |io|
|
||||
io.puts "--- !ruby/object:#{index.class}"
|
||||
io.puts "gems:"
|
||||
|
||||
gems = index.sort_by { |name, gemspec| gemspec.sort_obj }
|
||||
gems.each do |original_name, gemspec|
|
||||
yaml = gemspec.to_yaml.gsub(/^/, ' ')
|
||||
yaml = yaml.sub(/\A ---/, '') # there's a needed extra ' ' here
|
||||
io.print " #{original_name}:"
|
||||
io.puts yaml
|
||||
|
||||
progress.updated original_name
|
||||
end
|
||||
end
|
||||
|
||||
progress.done
|
||||
|
||||
say "Compressing indicies"
|
||||
# use gzip for future files.
|
||||
|
||||
compress quick_index, 'rz'
|
||||
paranoid quick_index, 'rz'
|
||||
|
||||
compress latest_index, 'rz'
|
||||
paranoid latest_index, 'rz'
|
||||
|
||||
compress @marshal_index, 'Z'
|
||||
paranoid @marshal_index, 'Z'
|
||||
|
||||
compress @master_index, 'Z'
|
||||
paranoid @master_index, 'Z'
|
||||
|
||||
gzip @specs_index
|
||||
gzip @latest_specs_index
|
||||
end
|
||||
|
||||
##
|
||||
# Collect specifications from .gem files from the gem directory.
|
||||
|
||||
def collect_specs
|
||||
index = Gem::SourceIndex.new
|
||||
|
||||
progress = ui.progress_reporter gem_file_list.size,
|
||||
"Loading #{gem_file_list.size} gems from #{@dest_directory}",
|
||||
"Loaded all gems"
|
||||
|
||||
gem_file_list.each do |gemfile|
|
||||
if File.size(gemfile.to_s) == 0 then
|
||||
alert_warning "Skipping zero-length gem: #{gemfile}"
|
||||
next
|
||||
end
|
||||
|
||||
begin
|
||||
spec = Gem::Format.from_file_by_path(gemfile).spec
|
||||
|
||||
unless gemfile =~ /\/#{Regexp.escape spec.original_name}.*\.gem\z/i then
|
||||
alert_warning "Skipping misnamed gem: #{gemfile} => #{spec.full_name} (#{spec.original_name})"
|
||||
next
|
||||
end
|
||||
|
||||
abbreviate spec
|
||||
sanitize spec
|
||||
|
||||
index.gems[spec.original_name] = spec
|
||||
|
||||
progress.updated spec.original_name
|
||||
|
||||
rescue SignalException => e
|
||||
alert_error "Received signal, exiting"
|
||||
raise
|
||||
rescue Exception => e
|
||||
alert_error "Unable to process #{gemfile}\n#{e.message} (#{e.class})\n\t#{e.backtrace.join "\n\t"}"
|
||||
end
|
||||
end
|
||||
|
||||
progress.done
|
||||
|
||||
index
|
||||
end
|
||||
|
||||
##
|
||||
# Compacts Marshal output for the specs index data source by using identical
|
||||
# objects as much as possible.
|
||||
|
||||
def compact_specs(specs)
|
||||
names = {}
|
||||
versions = {}
|
||||
platforms = {}
|
||||
|
||||
specs.map do |(name, version, platform)|
|
||||
names[name] = name unless names.include? name
|
||||
versions[version] = version unless versions.include? version
|
||||
platforms[platform] = platform unless platforms.include? platform
|
||||
|
||||
[names[name], versions[version], platforms[platform]]
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Compress +filename+ with +extension+.
|
||||
|
||||
def compress(filename, extension)
|
||||
data = Gem.read_binary filename
|
||||
|
||||
zipped = Gem.deflate data
|
||||
|
||||
open "#{filename}.#{extension}", 'wb' do |io|
|
||||
io.write zipped
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# List of gem file names to index.
|
||||
|
||||
def gem_file_list
|
||||
Dir.glob(File.join(@dest_directory, "gems", "*.gem"))
|
||||
end
|
||||
|
||||
##
|
||||
# Builds and installs indexicies.
|
||||
|
||||
def generate_index
|
||||
FileUtils.rm_rf @directory
|
||||
FileUtils.mkdir_p @directory, :mode => 0700
|
||||
FileUtils.mkdir_p @quick_marshal_dir
|
||||
|
||||
index = collect_specs
|
||||
build_indicies index
|
||||
install_indicies
|
||||
rescue SignalException
|
||||
ensure
|
||||
FileUtils.rm_rf @directory
|
||||
end
|
||||
|
||||
##
|
||||
# Zlib::GzipWriter wrapper that gzips +filename+ on disk.
|
||||
|
||||
def gzip(filename)
|
||||
Zlib::GzipWriter.open "#{filename}.gz" do |io|
|
||||
io.write Gem.read_binary(filename)
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Install generated indicies into the destination directory.
|
||||
|
||||
def install_indicies
|
||||
verbose = Gem.configuration.really_verbose
|
||||
|
||||
say "Moving index into production dir #{@dest_directory}" if verbose
|
||||
|
||||
@files.each do |file|
|
||||
src_name = File.join @directory, file
|
||||
dst_name = File.join @dest_directory, file
|
||||
|
||||
FileUtils.rm_rf dst_name, :verbose => verbose
|
||||
FileUtils.mv src_name, @dest_directory, :verbose => verbose
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Ensure +path+ and path with +extension+ are identical.
|
||||
|
||||
def paranoid(path, extension)
|
||||
data = Gem.read_binary path
|
||||
compressed_data = Gem.read_binary "#{path}.#{extension}"
|
||||
|
||||
unless data == Gem.inflate(compressed_data) then
|
||||
raise "Compressed file #{compressed_path} does not match uncompressed file #{path}"
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Sanitize the descriptive fields in the spec. Sometimes non-ASCII
|
||||
# characters will garble the site index. Non-ASCII characters will
|
||||
# be replaced by their XML entity equivalent.
|
||||
|
||||
def sanitize(spec)
|
||||
spec.summary = sanitize_string(spec.summary)
|
||||
spec.description = sanitize_string(spec.description)
|
||||
|
@ -158,7 +346,9 @@ class Gem::Indexer
|
|||
spec
|
||||
end
|
||||
|
||||
##
|
||||
# Sanitize a single string.
|
||||
|
||||
def sanitize_string(string)
|
||||
# HACK the #to_s is in here because RSpec has an Array of Arrays of
|
||||
# Strings for authors. Need a way to disallow bad values on gempsec
|
||||
|
@ -168,9 +358,3 @@ class Gem::Indexer
|
|||
|
||||
end
|
||||
|
||||
require 'rubygems/indexer/abstract_index_builder'
|
||||
require 'rubygems/indexer/master_index_builder'
|
||||
require 'rubygems/indexer/quick_index_builder'
|
||||
require 'rubygems/indexer/marshal_index_builder'
|
||||
require 'rubygems/indexer/latest_index_builder'
|
||||
|
||||
|
|
|
@ -89,6 +89,12 @@ module Gem::InstallUpdateOptions
|
|||
'foo_exec18') do |value, options|
|
||||
options[:format_executable] = value
|
||||
end
|
||||
|
||||
add_option(:"Install/Update", "--development",
|
||||
"Install any additional development",
|
||||
"dependencies") do |value, options|
|
||||
options[:development] = true
|
||||
end
|
||||
end
|
||||
|
||||
# Default options for the gem install command.
|
||||
|
|
|
@ -56,6 +56,7 @@ class Gem::Installer
|
|||
# foo_exec18.
|
||||
# :security_policy:: Use the specified security policy. See Gem::Security
|
||||
# :wrappers:: Install wrappers if true, symlinks if false.
|
||||
|
||||
def initialize(gem, options={})
|
||||
@gem = gem
|
||||
|
||||
|
@ -76,6 +77,7 @@ class Gem::Installer
|
|||
@security_policy = options[:security_policy]
|
||||
@wrappers = options[:wrappers]
|
||||
@bin_dir = options[:bin_dir]
|
||||
@development = options[:development]
|
||||
|
||||
begin
|
||||
@format = Gem::Format.from_file_by_path @gem, @security_policy
|
||||
|
@ -98,6 +100,7 @@ class Gem::Installer
|
|||
# cache/<gem-version>.gem #=> a cached copy of the installed gem
|
||||
# gems/<gem-version>/... #=> extracted files
|
||||
# specifications/<gem-version>.gemspec #=> the Gem::Specification
|
||||
|
||||
def install
|
||||
# If we're forcing the install then disable security unless the security
|
||||
# policy says that we only install singed gems.
|
||||
|
@ -119,7 +122,10 @@ class Gem::Installer
|
|||
end
|
||||
|
||||
unless @ignore_dependencies then
|
||||
@spec.dependencies.each do |dep_gem|
|
||||
deps = @spec.runtime_dependencies
|
||||
deps |= @spec.development_dependencies if @development
|
||||
|
||||
deps.each do |dep_gem|
|
||||
ensure_dependency @spec, dep_gem
|
||||
end
|
||||
end
|
||||
|
@ -150,6 +156,8 @@ class Gem::Installer
|
|||
@spec.loaded_from = File.join(@gem_home, 'specifications',
|
||||
"#{@spec.full_name}.gemspec")
|
||||
|
||||
Gem.source_index.add_spec @spec
|
||||
|
||||
return @spec
|
||||
rescue Zlib::GzipFile::Error
|
||||
raise Gem::InstallError, "gzip error installing #{@gem}"
|
||||
|
@ -161,6 +169,7 @@ class Gem::Installer
|
|||
#
|
||||
# spec :: Gem::Specification
|
||||
# dependency :: Gem::Dependency
|
||||
|
||||
def ensure_dependency(spec, dependency)
|
||||
unless installation_satisfies_dependency? dependency then
|
||||
raise Gem::InstallError, "#{spec.name} requires #{dependency}"
|
||||
|
@ -170,17 +179,15 @@ class Gem::Installer
|
|||
end
|
||||
|
||||
##
|
||||
# True if the current installed gems satisfy the given dependency.
|
||||
#
|
||||
# dependency :: Gem::Dependency
|
||||
# True if the gems in Gem.source_index satisfy +dependency+.
|
||||
|
||||
def installation_satisfies_dependency?(dependency)
|
||||
current_index = Gem::SourceIndex.from_installed_gems
|
||||
current_index.find_name(dependency.name, dependency.version_requirements).size > 0
|
||||
Gem.source_index.find_name(dependency.name, dependency.version_requirements).size > 0
|
||||
end
|
||||
|
||||
##
|
||||
# Unpacks the gem into the given directory.
|
||||
#
|
||||
|
||||
def unpack(directory)
|
||||
@gem_dir = directory
|
||||
@format = Gem::Format.from_file_by_path @gem, @security_policy
|
||||
|
@ -193,7 +200,7 @@ class Gem::Installer
|
|||
#
|
||||
# spec:: [Gem::Specification] The Gem specification to output
|
||||
# spec_path:: [String] The location (path) to write the gemspec to
|
||||
#
|
||||
|
||||
def write_spec
|
||||
rubycode = @spec.to_ruby
|
||||
|
||||
|
@ -208,7 +215,7 @@ class Gem::Installer
|
|||
|
||||
##
|
||||
# Creates windows .bat files for easy running of commands
|
||||
#
|
||||
|
||||
def generate_windows_script(bindir, filename)
|
||||
if Gem.win_platform? then
|
||||
script_name = filename + ".bat"
|
||||
|
@ -227,7 +234,7 @@ class Gem::Installer
|
|||
# If the user has asked for the gem to be installed in a directory that is
|
||||
# the system gem directory, then use the system bin directory, else create
|
||||
# (or use) a new bin dir under the gem_home.
|
||||
bindir = @bin_dir ? @bin_dir : (Gem.bindir @gem_home)
|
||||
bindir = @bin_dir ? @bin_dir : Gem.bindir(@gem_home)
|
||||
|
||||
Dir.mkdir bindir unless File.exist? bindir
|
||||
raise Gem::FilePermissionError.new(bindir) unless File.writable? bindir
|
||||
|
@ -252,7 +259,7 @@ class Gem::Installer
|
|||
# The Windows script is generated in addition to the regular one due to a
|
||||
# bug or misfeature in the Windows shell's pipe. See
|
||||
# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/193379
|
||||
#
|
||||
|
||||
def generate_bin_script(filename, bindir)
|
||||
bin_script_path = File.join bindir, formatted_program_filename(filename)
|
||||
|
||||
|
@ -260,6 +267,8 @@ class Gem::Installer
|
|||
|
||||
# HACK some gems don't have #! in their executables, restore 2008/06
|
||||
#if File.read(exec_path, 2) == '#!' then
|
||||
FileUtils.rm_f bin_script_path # prior install may have been --no-wrappers
|
||||
|
||||
File.open bin_script_path, 'w', 0755 do |file|
|
||||
file.print app_script_text(filename)
|
||||
end
|
||||
|
@ -277,7 +286,7 @@ class Gem::Installer
|
|||
##
|
||||
# Creates the symlinks to run the applications in the gem. Moves
|
||||
# the symlink if the gem being installed has a newer version.
|
||||
#
|
||||
|
||||
def generate_bin_symlink(filename, bindir)
|
||||
if Gem.win_platform? then
|
||||
alert_warning "Unable to use symlinks on Windows, installing wrapper"
|
||||
|
@ -303,6 +312,7 @@ class Gem::Installer
|
|||
##
|
||||
# Generates a #! line for +bin_file_name+'s wrapper copying arguments if
|
||||
# necessary.
|
||||
|
||||
def shebang(bin_file_name)
|
||||
if @env_shebang then
|
||||
"#!/usr/bin/env " + Gem::ConfigMap[:ruby_install_name]
|
||||
|
@ -324,7 +334,9 @@ class Gem::Installer
|
|||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Return the text for an application file.
|
||||
|
||||
def app_script_text(bin_file_name)
|
||||
<<-TEXT
|
||||
#{shebang bin_file_name}
|
||||
|
@ -349,7 +361,9 @@ load '#{bin_file_name}'
|
|||
TEXT
|
||||
end
|
||||
|
||||
##
|
||||
# return the stub script text used to launch the true ruby script
|
||||
|
||||
def windows_stub_script(bindir, bin_file_name)
|
||||
<<-TEXT
|
||||
@ECHO OFF
|
||||
|
@ -361,8 +375,10 @@ GOTO :EOF
|
|||
TEXT
|
||||
end
|
||||
|
||||
##
|
||||
# Builds extensions. Valid types of extensions are extconf.rb files,
|
||||
# configure scripts and rakefiles or mkrf_conf files.
|
||||
|
||||
def build_extensions
|
||||
return if @spec.extensions.empty?
|
||||
say "Building native extensions. This could take a while..."
|
||||
|
@ -418,6 +434,7 @@ Results logged to #{File.join(Dir.pwd, 'gem_make.out')}
|
|||
# Reads the file index and extracts each file into the gem directory.
|
||||
#
|
||||
# Ensures that files can't be installed outside the gem directory.
|
||||
|
||||
def extract_files
|
||||
expand_and_validate_gem_dir
|
||||
|
||||
|
@ -445,11 +462,15 @@ Results logged to #{File.join(Dir.pwd, 'gem_make.out')}
|
|||
out.write file_data
|
||||
end
|
||||
|
||||
FileUtils.chmod entry['mode'], path
|
||||
|
||||
say path if Gem.configuration.really_verbose
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Prefix and suffix the program filename the same as ruby.
|
||||
|
||||
def formatted_program_filename(filename)
|
||||
if @format_executable then
|
||||
self.class.exec_format % File.basename(filename)
|
||||
|
@ -460,7 +481,9 @@ Results logged to #{File.join(Dir.pwd, 'gem_make.out')}
|
|||
|
||||
private
|
||||
|
||||
##
|
||||
# HACK Pathname is broken on windows.
|
||||
|
||||
def absolute_path? pathname
|
||||
pathname.absolute? or (Gem.win_platform? and pathname.to_s =~ /\A[a-z]:/i)
|
||||
end
|
||||
|
|
|
@ -4,27 +4,34 @@
|
|||
# See LICENSE.txt for permissions.
|
||||
#++
|
||||
|
||||
require 'uri'
|
||||
require 'rubygems'
|
||||
|
||||
##
|
||||
# Mixin methods for local and remote Gem::Command options.
|
||||
|
||||
module Gem::LocalRemoteOptions
|
||||
|
||||
##
|
||||
# Allows OptionParser to handle HTTP URIs.
|
||||
|
||||
def accept_uri_http
|
||||
OptionParser.accept URI::HTTP do |value|
|
||||
begin
|
||||
value = URI.parse value
|
||||
uri = URI.parse value
|
||||
rescue URI::InvalidURIError
|
||||
raise OptionParser::InvalidArgument, value
|
||||
end
|
||||
|
||||
raise OptionParser::InvalidArgument, value unless value.scheme == 'http'
|
||||
raise OptionParser::InvalidArgument, value unless uri.scheme == 'http'
|
||||
|
||||
value
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Add local/remote options to the command line parser.
|
||||
|
||||
def add_local_remote_options
|
||||
add_option(:"Local/Remote", '-l', '--local',
|
||||
'Restrict operations to the LOCAL domain') do |value, options|
|
||||
|
@ -47,7 +54,9 @@ module Gem::LocalRemoteOptions
|
|||
add_update_sources_option
|
||||
end
|
||||
|
||||
##
|
||||
# Add the --bulk-threshold option
|
||||
|
||||
def add_bulk_threshold_option
|
||||
add_option(:"Local/Remote", '-B', '--bulk-threshold COUNT',
|
||||
"Threshold for switching to bulk",
|
||||
|
@ -57,7 +66,9 @@ module Gem::LocalRemoteOptions
|
|||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Add the --http-proxy option
|
||||
|
||||
def add_proxy_option
|
||||
accept_uri_http
|
||||
|
||||
|
@ -68,22 +79,28 @@ module Gem::LocalRemoteOptions
|
|||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Add the --source option
|
||||
|
||||
def add_source_option
|
||||
accept_uri_http
|
||||
|
||||
add_option(:"Local/Remote", '--source URL', URI::HTTP,
|
||||
'Use URL as the remote source for gems') do |value, options|
|
||||
'Use URL as the remote source for gems') do |source, options|
|
||||
source << '/' if source !~ /\/\z/
|
||||
|
||||
if options[:added_source] then
|
||||
Gem.sources << value
|
||||
Gem.sources << source
|
||||
else
|
||||
options[:added_source] = true
|
||||
Gem.sources.replace [value]
|
||||
Gem.sources.replace [source]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Add the --source option
|
||||
|
||||
def add_update_sources_option
|
||||
|
||||
add_option(:"Local/Remote", '-u', '--[no-]update-sources',
|
||||
|
@ -92,12 +109,16 @@ module Gem::LocalRemoteOptions
|
|||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Is local fetching enabled?
|
||||
|
||||
def local?
|
||||
options[:domain] == :local || options[:domain] == :both
|
||||
end
|
||||
|
||||
##
|
||||
# Is remote fetching enabled?
|
||||
|
||||
def remote?
|
||||
options[:domain] == :remote || options[:domain] == :both
|
||||
end
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
require 'rubygems'
|
||||
|
||||
##
|
||||
# Available list of platforms for targeting Gem installations.
|
||||
#
|
||||
|
||||
class Gem::Platform
|
||||
|
||||
@local = nil
|
||||
|
@ -122,11 +123,20 @@ class Gem::Platform
|
|||
to_a.compact.join '-'
|
||||
end
|
||||
|
||||
##
|
||||
# Is +other+ equal to this platform? Two platforms are equal if they have
|
||||
# the same CPU, OS and version.
|
||||
|
||||
def ==(other)
|
||||
self.class === other and
|
||||
@cpu == other.cpu and @os == other.os and @version == other.version
|
||||
end
|
||||
|
||||
##
|
||||
# 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
|
||||
|
||||
|
@ -140,6 +150,10 @@ class Gem::Platform
|
|||
(@version.nil? or other.version.nil? or @version == other.version)
|
||||
end
|
||||
|
||||
##
|
||||
# Does +other+ match this platform? If +other+ is a String it will be
|
||||
# converted to a Gem::Platform first. See #=== for matching rules.
|
||||
|
||||
def =~(other)
|
||||
case other
|
||||
when Gem::Platform then # nop
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
require 'net/http'
|
||||
require 'stringio'
|
||||
require 'uri'
|
||||
|
||||
require 'rubygems'
|
||||
|
@ -11,15 +12,38 @@ class Gem::RemoteFetcher
|
|||
|
||||
include Gem::UserInteraction
|
||||
|
||||
class FetchError < Gem::Exception; end
|
||||
##
|
||||
# A FetchError exception wraps up the various possible IO and HTTP failures
|
||||
# that could happen while downloading from the internet.
|
||||
|
||||
class FetchError < Gem::Exception
|
||||
|
||||
##
|
||||
# The URI which was being accessed when the exception happened.
|
||||
|
||||
attr_accessor :uri
|
||||
|
||||
def initialize(message, uri)
|
||||
super message
|
||||
@uri = uri
|
||||
end
|
||||
|
||||
def to_s # :nodoc:
|
||||
"#{super} (#{uri})"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@fetcher = nil
|
||||
|
||||
##
|
||||
# Cached RemoteFetcher instance.
|
||||
|
||||
def self.fetcher
|
||||
@fetcher ||= self.new Gem.configuration[:http_proxy]
|
||||
end
|
||||
|
||||
##
|
||||
# Initialize a remote fetcher using the source URI and possible proxy
|
||||
# information.
|
||||
#
|
||||
|
@ -29,6 +53,7 @@ class Gem::RemoteFetcher
|
|||
# * nil: respect environment variables (HTTP_PROXY, HTTP_PROXY_USER,
|
||||
# HTTP_PROXY_PASS)
|
||||
# * <tt>:no_proxy</tt>: ignore environment variables and _don't_ use a proxy
|
||||
|
||||
def initialize(proxy)
|
||||
Socket.do_not_reverse_lookup = true
|
||||
|
||||
|
@ -47,11 +72,13 @@ class Gem::RemoteFetcher
|
|||
# Moves the gem +spec+ from +source_uri+ to the cache dir unless it is
|
||||
# already there. If the source_uri is local the gem cache dir copy is
|
||||
# always replaced.
|
||||
def download(spec, source_uri, install_dir = Gem.dir)
|
||||
gem_file_name = "#{spec.full_name}.gem"
|
||||
local_gem_path = File.join install_dir, 'cache', gem_file_name
|
||||
|
||||
Gem.ensure_gem_subdirectories install_dir
|
||||
def download(spec, source_uri, install_dir = Gem.dir)
|
||||
cache_dir = File.join install_dir, 'cache'
|
||||
gem_file_name = "#{spec.full_name}.gem"
|
||||
local_gem_path = File.join cache_dir, gem_file_name
|
||||
|
||||
FileUtils.mkdir_p cache_dir rescue nil unless File.exist? cache_dir
|
||||
|
||||
source_uri = URI.parse source_uri unless URI::Generic === source_uri
|
||||
scheme = source_uri.scheme
|
||||
|
@ -102,21 +129,26 @@ class Gem::RemoteFetcher
|
|||
local_gem_path
|
||||
end
|
||||
|
||||
# Downloads +uri+.
|
||||
##
|
||||
# Downloads +uri+ and returns it as a String.
|
||||
|
||||
def fetch_path(uri)
|
||||
open_uri_or_path(uri) do |input|
|
||||
input.read
|
||||
end
|
||||
rescue FetchError
|
||||
raise
|
||||
rescue Timeout::Error
|
||||
raise FetchError, "timed out fetching #{uri}"
|
||||
raise FetchError.new('timed out', uri)
|
||||
rescue IOError, SocketError, SystemCallError => e
|
||||
raise FetchError, "#{e.class}: #{e} reading #{uri}"
|
||||
raise FetchError.new("#{e.class}: #{e}", uri)
|
||||
rescue => e
|
||||
message = "#{e.class}: #{e} reading #{uri}"
|
||||
raise FetchError, message
|
||||
raise FetchError.new("#{e.class}: #{e}", uri)
|
||||
end
|
||||
|
||||
##
|
||||
# Returns the size of +uri+ in bytes.
|
||||
|
||||
def fetch_size(uri)
|
||||
return File.size(get_file_uri_path(uri)) if file_uri? uri
|
||||
|
||||
|
@ -124,30 +156,21 @@ class Gem::RemoteFetcher
|
|||
|
||||
raise ArgumentError, 'uri is not an HTTP URI' unless URI::HTTP === uri
|
||||
|
||||
http = connect_to uri.host, uri.port
|
||||
response = request uri, Net::HTTP::Head
|
||||
|
||||
request = Net::HTTP::Head.new uri.request_uri
|
||||
|
||||
request.basic_auth unescape(uri.user), unescape(uri.password) unless
|
||||
uri.user.nil? or uri.user.empty?
|
||||
|
||||
resp = http.request request
|
||||
|
||||
if resp.code !~ /^2/ then
|
||||
raise Gem::RemoteSourceException,
|
||||
"HTTP Response #{resp.code} fetching #{uri}"
|
||||
if response.code !~ /^2/ then
|
||||
raise FetchError.new("bad response #{response.message} #{response.code}", uri)
|
||||
end
|
||||
|
||||
if resp['content-length'] then
|
||||
return resp['content-length'].to_i
|
||||
if response['content-length'] then
|
||||
return response['content-length'].to_i
|
||||
else
|
||||
resp = http.get uri.request_uri
|
||||
return resp.body.size
|
||||
response = http.get uri.request_uri
|
||||
return response.body.size
|
||||
end
|
||||
|
||||
rescue SocketError, SystemCallError, Timeout::Error => e
|
||||
raise Gem::RemoteFetcher::FetchError,
|
||||
"#{e.message} (#{e.class})\n\tgetting size of #{uri}"
|
||||
raise FetchError.new("#{e.message} (#{e.class})\n\tfetching size", uri)
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -162,7 +185,9 @@ class Gem::RemoteFetcher
|
|||
URI.unescape(str)
|
||||
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']
|
||||
|
||||
|
@ -179,104 +204,129 @@ class Gem::RemoteFetcher
|
|||
uri
|
||||
end
|
||||
|
||||
##
|
||||
# Normalize the URI by adding "http://" if it is missing.
|
||||
|
||||
def normalize_uri(uri)
|
||||
(uri =~ /^(https?|ftp|file):/) ? uri : "http://#{uri}"
|
||||
end
|
||||
|
||||
# Connect to the source host/port, using a proxy if needed.
|
||||
def connect_to(host, port)
|
||||
if @proxy_uri
|
||||
Net::HTTP::Proxy(@proxy_uri.host, @proxy_uri.port, unescape(@proxy_uri.user), unescape(@proxy_uri.password)).new(host, port)
|
||||
else
|
||||
Net::HTTP.new(host, port)
|
||||
##
|
||||
# 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 then
|
||||
net_http_args += [
|
||||
@proxy_uri.host,
|
||||
@proxy_uri.port,
|
||||
@proxy_uri.user,
|
||||
@proxy_uri.password
|
||||
]
|
||||
end
|
||||
|
||||
connection_id = net_http_args.join ':'
|
||||
@connections[connection_id] ||= Net::HTTP.new(*net_http_args)
|
||||
connection = @connections[connection_id]
|
||||
|
||||
if uri.scheme == 'https' and not connection.started? then
|
||||
http_obj.use_ssl = true
|
||||
http_obj.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
||||
end
|
||||
|
||||
connection.start unless connection.started?
|
||||
|
||||
connection
|
||||
end
|
||||
|
||||
##
|
||||
# Read the data from the (source based) URI, but if it is a file:// URI,
|
||||
# read from the filesystem instead.
|
||||
|
||||
def open_uri_or_path(uri, depth = 0, &block)
|
||||
if file_uri?(uri)
|
||||
open(get_file_uri_path(uri), &block)
|
||||
else
|
||||
uri = URI.parse uri unless URI::Generic === uri
|
||||
net_http_args = [uri.host, uri.port]
|
||||
|
||||
if @proxy_uri then
|
||||
net_http_args += [ @proxy_uri.host,
|
||||
@proxy_uri.port,
|
||||
@proxy_uri.user,
|
||||
@proxy_uri.password
|
||||
]
|
||||
end
|
||||
|
||||
connection_id = net_http_args.join ':'
|
||||
@connections[connection_id] ||= Net::HTTP.new(*net_http_args)
|
||||
connection = @connections[connection_id]
|
||||
|
||||
if uri.scheme == 'https' && ! connection.started?
|
||||
http_obj.use_ssl = true
|
||||
http_obj.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
||||
end
|
||||
|
||||
connection.start unless connection.started?
|
||||
|
||||
request = Net::HTTP::Get.new(uri.request_uri)
|
||||
unless uri.nil? || uri.user.nil? || uri.user.empty? then
|
||||
request.basic_auth(uri.user, uri.password)
|
||||
end
|
||||
|
||||
ua = "RubyGems/#{Gem::RubyGemsVersion} #{Gem::Platform.local}"
|
||||
ua << " Ruby/#{RUBY_VERSION} (#{RUBY_RELEASE_DATE}"
|
||||
ua << " patchlevel #{RUBY_PATCHLEVEL}" if defined? RUBY_PATCHLEVEL
|
||||
ua << ")"
|
||||
|
||||
request.add_field 'User-Agent', ua
|
||||
request.add_field 'Connection', 'keep-alive'
|
||||
request.add_field 'Keep-Alive', '30'
|
||||
|
||||
# HACK work around EOFError bug in Net::HTTP
|
||||
# NOTE Errno::ECONNABORTED raised a lot on Windows, and make impossible
|
||||
# to install gems.
|
||||
retried = false
|
||||
begin
|
||||
@requests[connection_id] += 1
|
||||
response = connection.request(request)
|
||||
rescue EOFError, Errno::ECONNABORTED
|
||||
requests = @requests[connection_id]
|
||||
say "connection reset after #{requests} requests, retrying" if
|
||||
Gem.configuration.really_verbose
|
||||
|
||||
raise Gem::RemoteFetcher::FetchError, 'too many connection resets' if
|
||||
retried
|
||||
|
||||
@requests[connection_id] = 0
|
||||
|
||||
connection.finish
|
||||
connection.start
|
||||
retried = true
|
||||
retry
|
||||
end
|
||||
response = request uri
|
||||
|
||||
case response
|
||||
when Net::HTTPOK then
|
||||
block.call(StringIO.new(response.body)) if block
|
||||
when Net::HTTPRedirection then
|
||||
raise Gem::RemoteFetcher::FetchError, "too many redirects" if depth > 10
|
||||
raise FetchError.new('too many redirects', uri) if depth > 10
|
||||
|
||||
open_uri_or_path(response['Location'], depth + 1, &block)
|
||||
else
|
||||
raise Gem::RemoteFetcher::FetchError,
|
||||
"bad response #{response.message} #{response.code}"
|
||||
raise FetchError.new("bad response #{response.message} #{response.code}", uri)
|
||||
end
|
||||
end
|
||||
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 = Net::HTTP::Get)
|
||||
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
|
||||
|
||||
ua = "RubyGems/#{Gem::RubyGemsVersion} #{Gem::Platform.local}"
|
||||
ua << " Ruby/#{RUBY_VERSION} (#{RUBY_RELEASE_DATE}"
|
||||
ua << " patchlevel #{RUBY_PATCHLEVEL}" if defined? RUBY_PATCHLEVEL
|
||||
ua << ")"
|
||||
|
||||
request.add_field 'User-Agent', ua
|
||||
request.add_field 'Connection', 'keep-alive'
|
||||
request.add_field 'Keep-Alive', '30'
|
||||
|
||||
connection = connection_for uri
|
||||
|
||||
retried = false
|
||||
|
||||
# HACK work around EOFError bug in Net::HTTP
|
||||
# NOTE Errno::ECONNABORTED raised a lot on Windows, and make impossible
|
||||
# to install gems.
|
||||
begin
|
||||
@requests[connection.object_id] += 1
|
||||
response = connection.request request
|
||||
say "#{request.method} #{response.code} #{response.message}: #{uri}" if
|
||||
Gem.configuration.really_verbose
|
||||
rescue EOFError, Errno::ECONNABORTED, Errno::ECONNRESET
|
||||
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
|
||||
|
||||
@requests.delete connection.object_id
|
||||
|
||||
connection.finish
|
||||
connection.start
|
||||
retried = true
|
||||
retry
|
||||
end
|
||||
|
||||
response
|
||||
end
|
||||
|
||||
##
|
||||
# Checks if the provided string is a file:// URI.
|
||||
|
||||
def file_uri?(uri)
|
||||
uri =~ %r{\Afile://}
|
||||
end
|
||||
|
||||
##
|
||||
# Given a file:// URI, returns its local path.
|
||||
|
||||
def get_file_uri_path(uri)
|
||||
uri.sub(%r{\Afile://}, '')
|
||||
end
|
||||
|
|
|
@ -12,6 +12,7 @@ require 'rubygems/version'
|
|||
#
|
||||
# A Requirement object can actually contain multiple, er,
|
||||
# requirements, as in (> 1.2, < 2.0).
|
||||
|
||||
class Gem::Requirement
|
||||
|
||||
include Comparable
|
||||
|
@ -35,7 +36,7 @@ class Gem::Requirement
|
|||
# Version, a String, or nil. Intended to simplify client code.
|
||||
#
|
||||
# If the input is "weird", the default version requirement is returned.
|
||||
#
|
||||
|
||||
def self.create(input)
|
||||
case input
|
||||
when Gem::Requirement then
|
||||
|
@ -57,6 +58,7 @@ class Gem::Requirement
|
|||
# This comment once said:
|
||||
#
|
||||
# "A default "version requirement" can surely _only_ be '> 0'."
|
||||
|
||||
def self.default
|
||||
self.new ['>= 0']
|
||||
end
|
||||
|
@ -65,6 +67,7 @@ class Gem::Requirement
|
|||
# Constructs a Requirement from +requirements+ which can be a String, a
|
||||
# Gem::Version, or an Array of those. See parse for details on the
|
||||
# formatting of requirement strings.
|
||||
|
||||
def initialize(requirements)
|
||||
@requirements = case requirements
|
||||
when Array then
|
||||
|
@ -77,13 +80,17 @@ class Gem::Requirement
|
|||
@version = nil # Avoid warnings.
|
||||
end
|
||||
|
||||
##
|
||||
# Marshal raw requirements, rather than the full object
|
||||
def marshal_dump
|
||||
|
||||
def marshal_dump # :nodoc:
|
||||
[@requirements]
|
||||
end
|
||||
|
||||
##
|
||||
# Load custom marshal format
|
||||
def marshal_load(array)
|
||||
|
||||
def marshal_load(array) # :nodoc:
|
||||
@requirements = array[0]
|
||||
@version = nil
|
||||
end
|
||||
|
@ -108,20 +115,16 @@ class Gem::Requirement
|
|||
end
|
||||
|
||||
##
|
||||
# Is the requirement satisfied by +version+.
|
||||
#
|
||||
# version:: [Gem::Version] the version to compare against
|
||||
# return:: [Boolean] true if this requirement is satisfied by
|
||||
# the version, otherwise false
|
||||
#
|
||||
# True if this requirement satisfied by the Gem::Version +version+.
|
||||
|
||||
def satisfied_by?(version)
|
||||
normalize
|
||||
@requirements.all? { |op, rv| satisfy?(op, version, rv) }
|
||||
end
|
||||
|
||||
##
|
||||
# Is "version op required_version" satisfied?
|
||||
#
|
||||
# Is "+version+ +op+ +required_version+" satisfied?
|
||||
|
||||
def satisfy?(op, version, required_version)
|
||||
OPS[op].call(version, required_version)
|
||||
end
|
||||
|
@ -132,6 +135,7 @@ class Gem::Requirement
|
|||
# The requirement can be a String or a Gem::Version. A String can be an
|
||||
# operator (<, <=, =, =>, >, !=, ~>), a version number, or both, operator
|
||||
# first.
|
||||
|
||||
def parse(obj)
|
||||
case obj
|
||||
when /^\s*(#{OP_RE})\s*([0-9.]+)\s*$/o then
|
||||
|
@ -147,7 +151,7 @@ class Gem::Requirement
|
|||
end
|
||||
end
|
||||
|
||||
def <=>(other)
|
||||
def <=>(other) # :nodoc:
|
||||
to_s <=> other.to_s
|
||||
end
|
||||
|
||||
|
|
|
@ -2,5 +2,5 @@
|
|||
# This file is auto-generated by build scripts.
|
||||
# See: rake update_version
|
||||
module Gem
|
||||
RubyGemsVersion = '1.1.1'
|
||||
RubyGemsVersion = '1.1.1.1778'
|
||||
end
|
||||
|
|
|
@ -4,6 +4,7 @@ require 'zlib'
|
|||
require 'erb'
|
||||
|
||||
require 'rubygems'
|
||||
require 'rubygems/doc_manager'
|
||||
|
||||
##
|
||||
# Gem::Server and allows users to serve gems for consumption by
|
||||
|
@ -11,18 +12,24 @@ require 'rubygems'
|
|||
#
|
||||
# gem_server starts an HTTP server on the given port and serves the following:
|
||||
# * "/" - Browsing of gem spec files for installed gems
|
||||
# * "/Marshal" - Full SourceIndex dump of metadata for installed gems
|
||||
# * "/yaml" - YAML dump of metadata for installed gems - deprecated
|
||||
# * "/specs.#{Gem.marshal_version}.gz" - specs name/version/platform index
|
||||
# * "/latest_specs.#{Gem.marshal_version}.gz" - latest specs
|
||||
# name/version/platform index
|
||||
# * "/quick/" - Individual gemspecs
|
||||
# * "/gems" - Direct access to download the installable gems
|
||||
# * legacy indexes:
|
||||
# * "/Marshal.#{Gem.marshal_version}" - Full SourceIndex dump of metadata
|
||||
# for installed gems
|
||||
# * "/yaml" - YAML dump of metadata for installed gems - deprecated
|
||||
#
|
||||
# == Usage
|
||||
#
|
||||
# gem server [-p portnum] [-d gem_path]
|
||||
# gem_server = Gem::Server.new Gem.dir, 8089, false
|
||||
# gem_server.run
|
||||
#
|
||||
# port_num:: The TCP port the HTTP server will bind to
|
||||
# gem_path::
|
||||
# Root gem directory containing both "cache" and "specifications"
|
||||
# subdirectories.
|
||||
#--
|
||||
# TODO Refactor into a real WEBrick servlet to remove code duplication.
|
||||
|
||||
class Gem::Server
|
||||
|
||||
include Gem::UserInteraction
|
||||
|
@ -36,7 +43,6 @@ class Gem::Server
|
|||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<title>RubyGems Documentation Index</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
||||
<link rel="stylesheet" href="gem-server-rdoc-style.css" type="text/css" media="screen" />
|
||||
</head>
|
||||
<body>
|
||||
|
@ -325,32 +331,99 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
|||
new(options[:gemdir], options[:port], options[:daemon]).run
|
||||
end
|
||||
|
||||
def initialize(gemdir, port, daemon)
|
||||
def initialize(gem_dir, port, daemon)
|
||||
Socket.do_not_reverse_lookup = true
|
||||
|
||||
@gemdir = gemdir
|
||||
@gem_dir = gem_dir
|
||||
@port = port
|
||||
@daemon = daemon
|
||||
logger = WEBrick::Log.new nil, WEBrick::BasicLog::FATAL
|
||||
@server = WEBrick::HTTPServer.new :DoNotListen => true, :Logger => logger
|
||||
|
||||
@spec_dir = File.join @gemdir, "specifications"
|
||||
@spec_dir = File.join @gem_dir, 'specifications'
|
||||
|
||||
unless File.directory? @spec_dir then
|
||||
raise ArgumentError, "#{@gem_dir} does not appear to be a gem repository"
|
||||
end
|
||||
|
||||
@source_index = Gem::SourceIndex.from_gems_in @spec_dir
|
||||
end
|
||||
|
||||
def Marshal(req, res)
|
||||
@source_index.refresh!
|
||||
|
||||
res['date'] = File.stat(@spec_dir).mtime
|
||||
|
||||
index = Marshal.dump @source_index
|
||||
|
||||
if req.request_method == 'HEAD' then
|
||||
res['content-length'] = index.length
|
||||
return
|
||||
end
|
||||
|
||||
if req.path =~ /Z$/ then
|
||||
res['content-type'] = 'application/x-deflate'
|
||||
index = Gem.deflate index
|
||||
else
|
||||
res['content-type'] = 'application/octet-stream'
|
||||
end
|
||||
|
||||
res.body << index
|
||||
end
|
||||
|
||||
def latest_specs(req, res)
|
||||
@source_index.refresh!
|
||||
|
||||
res['content-type'] = 'application/x-gzip'
|
||||
|
||||
res['date'] = File.stat(@spec_dir).mtime
|
||||
|
||||
specs = @source_index.latest_specs.sort.map do |spec|
|
||||
platform = spec.original_platform
|
||||
platform = Gem::Platform::RUBY if platform.nil?
|
||||
[spec.name, spec.version, platform]
|
||||
end
|
||||
|
||||
specs = Marshal.dump specs
|
||||
|
||||
if req.path =~ /\.gz$/ then
|
||||
specs = Gem.gzip specs
|
||||
res['content-type'] = 'application/x-gzip'
|
||||
else
|
||||
res['content-type'] = 'application/octet-stream'
|
||||
end
|
||||
|
||||
if req.request_method == 'HEAD' then
|
||||
res['content-length'] = specs.length
|
||||
else
|
||||
res.body << specs
|
||||
end
|
||||
end
|
||||
|
||||
def quick(req, res)
|
||||
@source_index.refresh!
|
||||
|
||||
res['content-type'] = 'text/plain'
|
||||
res['date'] = File.stat(@spec_dir).mtime
|
||||
|
||||
case req.request_uri.request_uri
|
||||
case req.request_uri.path
|
||||
when '/quick/index' then
|
||||
res.body << @source_index.map { |name,_| name }.join("\n")
|
||||
res.body << @source_index.map { |name,| name }.sort.join("\n")
|
||||
when '/quick/index.rz' then
|
||||
index = @source_index.map { |name,_| name }.join("\n")
|
||||
res.body << Zlib::Deflate.deflate(index)
|
||||
index = @source_index.map { |name,| name }.sort.join("\n")
|
||||
res['content-type'] = 'application/x-deflate'
|
||||
res.body << Gem.deflate(index)
|
||||
when '/quick/latest_index' then
|
||||
index = @source_index.latest_specs.map { |spec| spec.full_name }
|
||||
res.body << index.sort.join("\n")
|
||||
when '/quick/latest_index.rz' then
|
||||
index = @source_index.latest_specs.map { |spec| spec.full_name }
|
||||
res['content-type'] = 'application/x-deflate'
|
||||
res.body << Gem.deflate(index.sort.join("\n"))
|
||||
when %r|^/quick/(Marshal.#{Regexp.escape Gem.marshal_version}/)?(.*?)-([0-9.]+)(-.*?)?\.gemspec\.rz$| then
|
||||
dep = Gem::Dependency.new $2, $3
|
||||
specs = @source_index.search dep
|
||||
marshal_format = $1
|
||||
|
||||
selector = [$2, $3, $4].map { |s| s.inspect }.join ' '
|
||||
|
||||
|
@ -368,17 +441,98 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
|||
elsif specs.length > 1 then
|
||||
res.status = 500
|
||||
res.body = "Multiple gems found matching #{selector}"
|
||||
elsif $1 then # marshal quickindex instead of YAML
|
||||
res.body << Zlib::Deflate.deflate(Marshal.dump(specs.first))
|
||||
elsif marshal_format then
|
||||
res['content-type'] = 'application/x-deflate'
|
||||
res.body << Gem.deflate(Marshal.dump(specs.first))
|
||||
else # deprecated YAML format
|
||||
res.body << Zlib::Deflate.deflate(specs.first.to_yaml)
|
||||
res['content-type'] = 'application/x-deflate'
|
||||
res.body << Gem.deflate(specs.first.to_yaml)
|
||||
end
|
||||
else
|
||||
res.status = 404
|
||||
res.body = "#{req.request_uri} not found"
|
||||
raise WEBrick::HTTPStatus::NotFound, "`#{req.path}' not found."
|
||||
end
|
||||
end
|
||||
|
||||
def root(req, res)
|
||||
@source_index.refresh!
|
||||
res['date'] = File.stat(@spec_dir).mtime
|
||||
|
||||
raise WEBrick::HTTPStatus::NotFound, "`#{req.path}' not found." unless
|
||||
req.path == '/'
|
||||
|
||||
specs = []
|
||||
total_file_count = 0
|
||||
|
||||
@source_index.each do |path, spec|
|
||||
total_file_count += spec.files.size
|
||||
deps = spec.dependencies.map do |dep|
|
||||
{ "name" => dep.name,
|
||||
"type" => dep.type,
|
||||
"version" => dep.version_requirements.to_s, }
|
||||
end
|
||||
|
||||
deps = deps.sort_by { |dep| [dep["name"].downcase, dep["version"]] }
|
||||
deps.last["is_last"] = true unless deps.empty?
|
||||
|
||||
# executables
|
||||
executables = spec.executables.sort.collect { |exec| {"executable" => exec} }
|
||||
executables = nil if executables.empty?
|
||||
executables.last["is_last"] = true if executables
|
||||
|
||||
specs << {
|
||||
"authors" => spec.authors.sort.join(", "),
|
||||
"date" => spec.date.to_s,
|
||||
"dependencies" => deps,
|
||||
"doc_path" => "/doc_root/#{spec.full_name}/rdoc/index.html",
|
||||
"executables" => executables,
|
||||
"only_one_executable" => (executables && executables.size == 1),
|
||||
"full_name" => spec.full_name,
|
||||
"has_deps" => !deps.empty?,
|
||||
"homepage" => spec.homepage,
|
||||
"name" => spec.name,
|
||||
"rdoc_installed" => Gem::DocManager.new(spec).rdoc_installed?,
|
||||
"summary" => spec.summary,
|
||||
"version" => spec.version.to_s,
|
||||
}
|
||||
end
|
||||
|
||||
specs << {
|
||||
"authors" => "Chad Fowler, Rich Kilmer, Jim Weirich, Eric Hodel and others",
|
||||
"dependencies" => [],
|
||||
"doc_path" => "/doc_root/rubygems-#{Gem::RubyGemsVersion}/rdoc/index.html",
|
||||
"executables" => [{"executable" => 'gem', "is_last" => true}],
|
||||
"only_one_executable" => true,
|
||||
"full_name" => "rubygems-#{Gem::RubyGemsVersion}",
|
||||
"has_deps" => false,
|
||||
"homepage" => "http://rubygems.org/",
|
||||
"name" => 'rubygems',
|
||||
"rdoc_installed" => true,
|
||||
"summary" => "RubyGems itself",
|
||||
"version" => Gem::RubyGemsVersion,
|
||||
}
|
||||
|
||||
specs = specs.sort_by { |spec| [spec["name"].downcase, spec["version"]] }
|
||||
specs.last["is_last"] = true
|
||||
|
||||
# tag all specs with first_name_entry
|
||||
last_spec = nil
|
||||
specs.each do |spec|
|
||||
is_first = last_spec.nil? || (last_spec["name"].downcase != spec["name"].downcase)
|
||||
spec["first_name_entry"] = is_first
|
||||
last_spec = spec
|
||||
end
|
||||
|
||||
# create page from template
|
||||
template = ERB.new(DOC_TEMPLATE)
|
||||
res['content-type'] = 'text/html'
|
||||
|
||||
values = { "gem_count" => specs.size.to_s, "specs" => specs,
|
||||
"total_file_count" => total_file_count.to_s }
|
||||
|
||||
result = template.result binding
|
||||
res.body = result
|
||||
end
|
||||
|
||||
def run
|
||||
@server.listen nil, @port
|
||||
|
||||
|
@ -386,27 +540,21 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
|||
|
||||
WEBrick::Daemon.start if @daemon
|
||||
|
||||
@server.mount_proc("/yaml") do |req, res|
|
||||
res['content-type'] = 'text/plain'
|
||||
res['date'] = File.stat(@spec_dir).mtime
|
||||
if req.request_method == 'HEAD' then
|
||||
res['content-length'] = @source_index.to_yaml.length
|
||||
else
|
||||
res.body << @source_index.to_yaml
|
||||
end
|
||||
end
|
||||
@server.mount_proc "/yaml", method(:yaml)
|
||||
@server.mount_proc "/yaml.Z", method(:yaml)
|
||||
|
||||
@server.mount_proc("/Marshal") do |req, res|
|
||||
res['content-type'] = 'text/plain'
|
||||
res['date'] = File.stat(@spec_dir).mtime
|
||||
if req.request_method == 'HEAD' then
|
||||
res['content-length'] = Marshal.dump(@source_index).length
|
||||
else
|
||||
res.body << Marshal.dump(@source_index)
|
||||
end
|
||||
end
|
||||
@server.mount_proc "/Marshal.#{Gem.marshal_version}", method(:Marshal)
|
||||
@server.mount_proc "/Marshal.#{Gem.marshal_version}.Z", method(:Marshal)
|
||||
|
||||
@server.mount_proc("/quick/", &method(:quick))
|
||||
@server.mount_proc "/specs.#{Gem.marshal_version}", method(:specs)
|
||||
@server.mount_proc "/specs.#{Gem.marshal_version}.gz", method(:specs)
|
||||
|
||||
@server.mount_proc "/latest_specs.#{Gem.marshal_version}",
|
||||
method(:latest_specs)
|
||||
@server.mount_proc "/latest_specs.#{Gem.marshal_version}.gz",
|
||||
method(:latest_specs)
|
||||
|
||||
@server.mount_proc "/quick/", method(:quick)
|
||||
|
||||
@server.mount_proc("/gem-server-rdoc-style.css") do |req, res|
|
||||
res['content-type'] = 'text/css'
|
||||
|
@ -414,80 +562,12 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
|||
res.body << RDOC_CSS
|
||||
end
|
||||
|
||||
@server.mount_proc("/") do |req, res|
|
||||
specs = []
|
||||
total_file_count = 0
|
||||
|
||||
@source_index.each do |path, spec|
|
||||
total_file_count += spec.files.size
|
||||
deps = spec.dependencies.collect { |dep|
|
||||
{ "name" => dep.name,
|
||||
"version" => dep.version_requirements.to_s, }
|
||||
}
|
||||
deps = deps.sort_by { |dep| [dep["name"].downcase, dep["version"]] }
|
||||
deps.last["is_last"] = true unless deps.empty?
|
||||
|
||||
# executables
|
||||
executables = spec.executables.sort.collect { |exec| {"executable" => exec} }
|
||||
executables = nil if executables.empty?
|
||||
executables.last["is_last"] = true if executables
|
||||
|
||||
specs << {
|
||||
"authors" => spec.authors.sort.join(", "),
|
||||
"date" => spec.date.to_s,
|
||||
"dependencies" => deps,
|
||||
"doc_path" => ('/doc_root/' + spec.full_name + '/rdoc/index.html'),
|
||||
"executables" => executables,
|
||||
"only_one_executable" => (executables && executables.size==1),
|
||||
"full_name" => spec.full_name,
|
||||
"has_deps" => !deps.empty?,
|
||||
"homepage" => spec.homepage,
|
||||
"name" => spec.name,
|
||||
"rdoc_installed" => Gem::DocManager.new(spec).rdoc_installed?,
|
||||
"summary" => spec.summary,
|
||||
"version" => spec.version.to_s,
|
||||
}
|
||||
end
|
||||
|
||||
specs << {
|
||||
"authors" => "Chad Fowler, Rich Kilmer, Jim Weirich, Eric Hodel and others",
|
||||
"dependencies" => [],
|
||||
"doc_path" => "/doc_root/rubygems-#{Gem::RubyGemsVersion}/rdoc/index.html",
|
||||
"executables" => [{"executable" => 'gem', "is_last" => true}],
|
||||
"only_one_executable" => true,
|
||||
"full_name" => "rubygems-#{Gem::RubyGemsVersion}",
|
||||
"has_deps" => false,
|
||||
"homepage" => "http://rubygems.org/",
|
||||
"name" => 'rubygems',
|
||||
"rdoc_installed" => true,
|
||||
"summary" => "RubyGems itself",
|
||||
"version" => Gem::RubyGemsVersion,
|
||||
}
|
||||
|
||||
specs = specs.sort_by { |spec| [spec["name"].downcase, spec["version"]] }
|
||||
specs.last["is_last"] = true
|
||||
|
||||
# tag all specs with first_name_entry
|
||||
last_spec = nil
|
||||
specs.each do |spec|
|
||||
is_first = last_spec.nil? || (last_spec["name"].downcase != spec["name"].downcase)
|
||||
spec["first_name_entry"] = is_first
|
||||
last_spec = spec
|
||||
end
|
||||
|
||||
# create page from template
|
||||
template = ERB.new(DOC_TEMPLATE)
|
||||
res['content-type'] = 'text/html'
|
||||
values = { "gem_count" => specs.size.to_s, "specs" => specs,
|
||||
"total_file_count" => total_file_count.to_s }
|
||||
result = template.result binding
|
||||
res.body = result
|
||||
end
|
||||
@server.mount_proc "/", method(:root)
|
||||
|
||||
paths = { "/gems" => "/cache/", "/doc_root" => "/doc/" }
|
||||
paths.each do |mount_point, mount_dir|
|
||||
@server.mount(mount_point, WEBrick::HTTPServlet::FileHandler,
|
||||
File.join(@gemdir, mount_dir), true)
|
||||
File.join(@gem_dir, mount_dir), true)
|
||||
end
|
||||
|
||||
trap("INT") { @server.shutdown; exit! }
|
||||
|
@ -496,5 +576,54 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
|||
@server.start
|
||||
end
|
||||
|
||||
def specs(req, res)
|
||||
@source_index.refresh!
|
||||
|
||||
res['date'] = File.stat(@spec_dir).mtime
|
||||
|
||||
specs = @source_index.sort.map do |_, spec|
|
||||
platform = spec.original_platform
|
||||
platform = Gem::Platform::RUBY if platform.nil?
|
||||
[spec.name, spec.version, platform]
|
||||
end
|
||||
|
||||
specs = Marshal.dump specs
|
||||
|
||||
if req.path =~ /\.gz$/ then
|
||||
specs = Gem.gzip specs
|
||||
res['content-type'] = 'application/x-gzip'
|
||||
else
|
||||
res['content-type'] = 'application/octet-stream'
|
||||
end
|
||||
|
||||
if req.request_method == 'HEAD' then
|
||||
res['content-length'] = specs.length
|
||||
else
|
||||
res.body << specs
|
||||
end
|
||||
end
|
||||
|
||||
def yaml(req, res)
|
||||
@source_index.refresh!
|
||||
|
||||
res['date'] = File.stat(@spec_dir).mtime
|
||||
|
||||
index = @source_index.to_yaml
|
||||
|
||||
if req.path =~ /Z$/ then
|
||||
res['content-type'] = 'application/x-deflate'
|
||||
index = Gem.deflate index
|
||||
else
|
||||
res['content-type'] = 'text/plain'
|
||||
end
|
||||
|
||||
if req.request_method == 'HEAD' then
|
||||
res['content-length'] = index.length
|
||||
return
|
||||
end
|
||||
|
||||
res.body << index
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
require 'rubygems'
|
||||
require 'rubygems/user_interaction'
|
||||
require 'rubygems/specification'
|
||||
require 'rubygems/spec_fetcher'
|
||||
|
||||
##
|
||||
# The SourceIndex object indexes all the gems available from a
|
||||
|
@ -27,6 +28,11 @@ class Gem::SourceIndex
|
|||
|
||||
attr_reader :gems # :nodoc:
|
||||
|
||||
##
|
||||
# Directories to use to refresh this SourceIndex when calling refresh!
|
||||
|
||||
attr_accessor :spec_dirs
|
||||
|
||||
class << self
|
||||
include Gem::UserInteraction
|
||||
|
||||
|
@ -39,7 +45,7 @@ class Gem::SourceIndex
|
|||
# +from_gems_in+. This argument is deprecated and is provided
|
||||
# just for backwards compatibility, and should not generally
|
||||
# be used.
|
||||
#
|
||||
#
|
||||
# return::
|
||||
# SourceIndex instance
|
||||
|
||||
|
@ -63,7 +69,9 @@ class Gem::SourceIndex
|
|||
# +spec_dirs+.
|
||||
|
||||
def from_gems_in(*spec_dirs)
|
||||
self.new.load_gems_in(*spec_dirs)
|
||||
source_index = new
|
||||
source_index.spec_dirs = spec_dirs
|
||||
source_index.refresh!
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -79,6 +87,8 @@ class Gem::SourceIndex
|
|||
return gemspec
|
||||
end
|
||||
alert_warning "File '#{file_name}' does not evaluate to a gem specification"
|
||||
rescue SignalException, SystemExit
|
||||
raise
|
||||
rescue SyntaxError => e
|
||||
alert_warning e
|
||||
alert_warning spec_code
|
||||
|
@ -100,6 +110,7 @@ class Gem::SourceIndex
|
|||
|
||||
def initialize(specifications={})
|
||||
@gems = specifications
|
||||
@spec_dirs = nil
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -121,8 +132,8 @@ class Gem::SourceIndex
|
|||
end
|
||||
|
||||
##
|
||||
# Returns a Hash of name => Specification of the latest versions of each
|
||||
# gem in this index.
|
||||
# Returns an Array specifications for the latest versions of each gem in
|
||||
# this index.
|
||||
|
||||
def latest_specs
|
||||
result = Hash.new { |h,k| h[k] = [] }
|
||||
|
@ -241,7 +252,9 @@ class Gem::SourceIndex
|
|||
when Gem::Dependency then
|
||||
only_platform = platform_only
|
||||
version_requirement = gem_pattern.version_requirements
|
||||
gem_pattern = if gem_pattern.name.empty? then
|
||||
gem_pattern = if Regexp === gem_pattern.name then
|
||||
gem_pattern.name
|
||||
elsif gem_pattern.name.empty? then
|
||||
//
|
||||
else
|
||||
/^#{Regexp.escape gem_pattern.name}$/
|
||||
|
@ -271,29 +284,43 @@ class Gem::SourceIndex
|
|||
|
||||
##
|
||||
# Replaces the gems in the source index from specifications in the
|
||||
# installed_spec_directories,
|
||||
# directories this source index was created from. Raises an exception if
|
||||
# this source index wasn't created from a directory (via from_gems_in or
|
||||
# from_installed_gems, or having spec_dirs set).
|
||||
|
||||
def refresh!
|
||||
load_gems_in(*self.class.installed_spec_directories)
|
||||
raise 'source index not created from disk' if @spec_dirs.nil?
|
||||
load_gems_in(*@spec_dirs)
|
||||
end
|
||||
|
||||
##
|
||||
# Returns an Array of Gem::Specifications that are not up to date.
|
||||
|
||||
def outdated
|
||||
dep = Gem::Dependency.new '', Gem::Requirement.default
|
||||
|
||||
remotes = Gem::SourceInfoCache.search dep, true
|
||||
|
||||
outdateds = []
|
||||
|
||||
latest_specs.each do |local|
|
||||
name = local.name
|
||||
remote = remotes.select { |spec| spec.name == name }.
|
||||
sort_by { |spec| spec.version.to_ints }.
|
||||
last
|
||||
|
||||
outdateds << name if remote and local.version < remote.version
|
||||
dependency = Gem::Dependency.new name, ">= #{local.version}"
|
||||
|
||||
begin
|
||||
fetcher = Gem::SpecFetcher.fetcher
|
||||
remotes = fetcher.find_matching dependency
|
||||
remotes = remotes.map { |(name, version,),| version }
|
||||
rescue Gem::RemoteFetcher::FetchError => e
|
||||
raise unless fetcher.warn_legacy e do
|
||||
require 'rubygems/source_info_cache'
|
||||
|
||||
specs = Gem::SourceInfoCache.search_with_source dependency, true
|
||||
|
||||
remotes = specs.map { |spec,| spec.version }
|
||||
end
|
||||
end
|
||||
|
||||
latest = remotes.sort.last
|
||||
|
||||
outdateds << name if latest and local.version < latest
|
||||
end
|
||||
|
||||
outdateds
|
||||
|
@ -387,7 +414,8 @@ class Gem::SourceIndex
|
|||
end
|
||||
|
||||
def fetch_bulk_index(source_uri)
|
||||
say "Bulk updating Gem source index for: #{source_uri}"
|
||||
say "Bulk updating Gem source index for: #{source_uri}" if
|
||||
Gem.configuration.verbose
|
||||
|
||||
index = fetch_index_from(source_uri)
|
||||
if index.nil? then
|
||||
|
@ -447,7 +475,7 @@ class Gem::SourceIndex
|
|||
|
||||
def unzip(string)
|
||||
require 'zlib'
|
||||
Zlib::Inflate.inflate(string)
|
||||
Gem.inflate string
|
||||
end
|
||||
|
||||
##
|
||||
|
|
251
lib/rubygems/spec_fetcher.rb
Normal file
251
lib/rubygems/spec_fetcher.rb
Normal file
|
@ -0,0 +1,251 @@
|
|||
require 'zlib'
|
||||
|
||||
require 'rubygems'
|
||||
require 'rubygems/remote_fetcher'
|
||||
require 'rubygems/user_interaction'
|
||||
|
||||
##
|
||||
# SpecFetcher handles metadata updates from remote gem repositories.
|
||||
|
||||
class Gem::SpecFetcher
|
||||
|
||||
include Gem::UserInteraction
|
||||
|
||||
##
|
||||
# The SpecFetcher cache dir.
|
||||
|
||||
attr_reader :dir # :nodoc:
|
||||
|
||||
##
|
||||
# Cache of latest specs
|
||||
|
||||
attr_reader :latest_specs # :nodoc:
|
||||
|
||||
##
|
||||
# Cache of all spces
|
||||
|
||||
attr_reader :specs # :nodoc:
|
||||
|
||||
@fetcher = nil
|
||||
|
||||
def self.fetcher
|
||||
@fetcher ||= new
|
||||
end
|
||||
|
||||
def self.fetcher=(fetcher) # :nodoc:
|
||||
@fetcher = fetcher
|
||||
end
|
||||
|
||||
def initialize
|
||||
@dir = File.join Gem.user_home, '.gem', 'specs'
|
||||
@update_cache = File.stat(Gem.user_home).uid == Process.uid
|
||||
|
||||
@specs = {}
|
||||
@latest_specs = {}
|
||||
|
||||
@fetcher = Gem::RemoteFetcher.fetcher
|
||||
end
|
||||
|
||||
##
|
||||
# Retuns the local directory to write +uri+ to.
|
||||
|
||||
def cache_dir(uri)
|
||||
File.join @dir, "#{uri.host}%#{uri.port}", File.dirname(uri.path)
|
||||
end
|
||||
|
||||
##
|
||||
# Fetch specs matching +dependency+. If +all+ is true, all matching
|
||||
# versions are returned. If +matching_platform+ is false, all platforms are
|
||||
# returned.
|
||||
|
||||
def fetch(dependency, all = false, matching_platform = true)
|
||||
specs_and_sources = find_matching dependency, all, matching_platform
|
||||
|
||||
specs_and_sources.map do |spec_tuple, source_uri|
|
||||
[fetch_spec(spec_tuple, URI.parse(source_uri)), source_uri]
|
||||
end
|
||||
|
||||
rescue Gem::RemoteFetcher::FetchError => e
|
||||
raise unless warn_legacy e do
|
||||
require 'rubygems/source_info_cache'
|
||||
|
||||
return Gem::SourceInfoCache.search_with_source(dependency,
|
||||
matching_platform, all)
|
||||
end
|
||||
end
|
||||
|
||||
def fetch_spec(spec, source_uri)
|
||||
spec = spec - [nil, 'ruby', '']
|
||||
spec_file_name = "#{spec.join '-'}.gemspec"
|
||||
|
||||
uri = source_uri + "#{Gem::MARSHAL_SPEC_DIR}#{spec_file_name}"
|
||||
|
||||
cache_dir = cache_dir uri
|
||||
|
||||
local_spec = File.join cache_dir, spec_file_name
|
||||
|
||||
if File.exist? local_spec then
|
||||
spec = Gem.read_binary local_spec
|
||||
else
|
||||
uri.path << '.rz'
|
||||
|
||||
spec = @fetcher.fetch_path uri
|
||||
spec = Gem.inflate spec
|
||||
|
||||
if @update_cache then
|
||||
FileUtils.mkdir_p cache_dir
|
||||
|
||||
open local_spec, 'wb' do |io|
|
||||
io.write spec
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# TODO: Investigate setting Gem::Specification#loaded_from to a URI
|
||||
Marshal.load spec
|
||||
end
|
||||
|
||||
##
|
||||
# Find spec names that match +dependency+. If +all+ is true, all matching
|
||||
# versions are returned. If +matching_platform+ is false, gems for all
|
||||
# platforms are returned.
|
||||
|
||||
def find_matching(dependency, all = false, matching_platform = true)
|
||||
found = {}
|
||||
|
||||
list(all).each do |source_uri, specs|
|
||||
found[source_uri] = specs.select do |spec_name, version, spec_platform|
|
||||
dependency =~ Gem::Dependency.new(spec_name, version) and
|
||||
(not matching_platform or Gem::Platform.match(spec_platform))
|
||||
end
|
||||
end
|
||||
|
||||
specs_and_sources = []
|
||||
|
||||
found.each do |source_uri, specs|
|
||||
uri_str = source_uri.to_s
|
||||
specs_and_sources.push(*specs.map { |spec| [spec, uri_str] })
|
||||
end
|
||||
|
||||
specs_and_sources
|
||||
end
|
||||
|
||||
##
|
||||
# Returns Array of gem repositories that were generated with RubyGems less
|
||||
# than 1.2.
|
||||
|
||||
def legacy_repos
|
||||
Gem.sources.reject do |source_uri|
|
||||
source_uri = URI.parse source_uri
|
||||
spec_path = source_uri + "specs.#{Gem.marshal_version}.gz"
|
||||
|
||||
begin
|
||||
@fetcher.fetch_size spec_path
|
||||
rescue Gem::RemoteFetcher::FetchError
|
||||
begin
|
||||
@fetcher.fetch_size(source_uri + 'yaml') # re-raise if non-repo
|
||||
rescue Gem::RemoteFetcher::FetchError
|
||||
alert_error "#{source_uri} does not appear to be a repository"
|
||||
raise
|
||||
end
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Returns a list of gems available for each source in Gem::sources. If
|
||||
# +all+ is true, all versions are returned instead of only latest versions.
|
||||
|
||||
def list(all = false)
|
||||
list = {}
|
||||
|
||||
file = all ? 'specs' : 'latest_specs'
|
||||
|
||||
Gem.sources.each do |source_uri|
|
||||
source_uri = URI.parse source_uri
|
||||
|
||||
if all and @specs.include? source_uri then
|
||||
list[source_uri] = @specs[source_uri]
|
||||
elsif @latest_specs.include? source_uri then
|
||||
list[source_uri] = @latest_specs[source_uri]
|
||||
else
|
||||
specs = load_specs source_uri, file
|
||||
|
||||
cache = all ? @specs : @latest_specs
|
||||
|
||||
cache[source_uri] = specs
|
||||
list[source_uri] = specs
|
||||
end
|
||||
end
|
||||
|
||||
list
|
||||
end
|
||||
|
||||
def load_specs(source_uri, file)
|
||||
file_name = "#{file}.#{Gem.marshal_version}.gz"
|
||||
|
||||
spec_path = source_uri + file_name
|
||||
|
||||
cache_dir = cache_dir spec_path
|
||||
|
||||
local_file = File.join(cache_dir, file_name).chomp '.gz'
|
||||
|
||||
if File.exist? local_file then
|
||||
local_size = File.stat(local_file).size
|
||||
|
||||
remote_file = spec_path.dup
|
||||
remote_file.path = remote_file.path.chomp '.gz'
|
||||
remote_size = @fetcher.fetch_size remote_file
|
||||
|
||||
spec_dump = Gem.read_binary local_file if remote_size == local_size
|
||||
end
|
||||
|
||||
unless spec_dump then
|
||||
loaded = true
|
||||
|
||||
spec_dump_gz = @fetcher.fetch_path spec_path
|
||||
spec_dump = Gem.gunzip spec_dump_gz
|
||||
end
|
||||
|
||||
specs = Marshal.load spec_dump
|
||||
|
||||
if loaded and @update_cache then
|
||||
begin
|
||||
FileUtils.mkdir_p cache_dir
|
||||
|
||||
open local_file, 'wb' do |io|
|
||||
Marshal.dump specs, io
|
||||
end
|
||||
rescue
|
||||
end
|
||||
end
|
||||
|
||||
specs
|
||||
end
|
||||
|
||||
##
|
||||
# Warn about legacy repositories if +exception+ indicates only legacy
|
||||
# repositories are available, and yield to the block. Returns false if the
|
||||
# exception indicates some other FetchError.
|
||||
|
||||
def warn_legacy(exception)
|
||||
uri = exception.uri.to_s
|
||||
if uri =~ /specs\.#{Regexp.escape Gem.marshal_version}\.gz$/ then
|
||||
alert_warning <<-EOF
|
||||
RubyGems 1.2+ index not found for:
|
||||
\t#{legacy_repos.join "\n\t"}
|
||||
|
||||
RubyGems will revert to legacy indexes degrading performance.
|
||||
EOF
|
||||
|
||||
yield
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
false
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
require 'rubygems'
|
||||
require 'rubygems/version'
|
||||
require 'rubygems/requirement'
|
||||
require 'rubygems/platform'
|
||||
|
||||
# :stopdoc:
|
||||
|
@ -16,6 +17,9 @@ if RUBY_VERSION < '1.9' then
|
|||
t - ((t.to_f + t.gmt_offset) % 86400)
|
||||
end unless defined? Time.today
|
||||
end
|
||||
|
||||
class Date; end # for ruby_code if date.rb wasn't required
|
||||
|
||||
# :startdoc:
|
||||
|
||||
module Gem
|
||||
|
@ -37,22 +41,32 @@ module Gem
|
|||
#
|
||||
class Specification
|
||||
|
||||
##
|
||||
# Allows deinstallation of gems with legacy platforms.
|
||||
|
||||
attr_accessor :original_platform # :nodoc:
|
||||
|
||||
# ------------------------- Specification version constants.
|
||||
|
||||
##
|
||||
# The the version number of a specification that does not specify one
|
||||
# (i.e. RubyGems 0.7 or earlier).
|
||||
|
||||
NONEXISTENT_SPECIFICATION_VERSION = -1
|
||||
|
||||
##
|
||||
# The specification version applied to any new Specification instances
|
||||
# created. This should be bumped whenever something in the spec format
|
||||
# changes.
|
||||
CURRENT_SPECIFICATION_VERSION = 2
|
||||
#--
|
||||
# When updating this number, be sure to also update #to_ruby.
|
||||
|
||||
CURRENT_SPECIFICATION_VERSION = 3
|
||||
|
||||
##
|
||||
# An informal list of changes to the specification. The highest-valued
|
||||
# key should be equal to the CURRENT_SPECIFICATION_VERSION.
|
||||
|
||||
SPECIFICATION_VERSION_HISTORY = {
|
||||
-1 => ['(RubyGems versions up to and including 0.7 did not have versioned specifications)'],
|
||||
1 => [
|
||||
|
@ -63,10 +77,13 @@ module Gem
|
|||
'Added "required_rubygems_version"',
|
||||
'Now forward-compatible with future versions',
|
||||
],
|
||||
3 => [
|
||||
'Added dependency types',
|
||||
],
|
||||
}
|
||||
|
||||
# :stopdoc:
|
||||
MARSHAL_FIELDS = { -1 => 16, 1 => 16, 2 => 16 }
|
||||
MARSHAL_FIELDS = { -1 => 16, 1 => 16, 2 => 16, 3 => 16 }
|
||||
|
||||
now = Time.at(Time.now.to_i)
|
||||
TODAY = now - ((now.to_i + now.gmt_offset) % 86400)
|
||||
|
@ -335,6 +352,14 @@ module Gem
|
|||
|
||||
read_only :dependencies
|
||||
|
||||
def runtime_dependencies
|
||||
dependencies.select { |d| d.type == :runtime || d.type == nil }
|
||||
end
|
||||
|
||||
def development_dependencies
|
||||
dependencies.select { |d| d.type == :development }
|
||||
end
|
||||
|
||||
# ALIASED gemspec attributes -------------------------------------
|
||||
|
||||
attribute_alias_singular :executable, :executables
|
||||
|
@ -629,27 +654,31 @@ module Gem
|
|||
end
|
||||
end
|
||||
|
||||
# Adds a dependency to this Gem. For example,
|
||||
# Adds a development dependency to this Gem. For example,
|
||||
#
|
||||
# spec.add_dependency('jabber4r', '> 0.1', '<= 0.5')
|
||||
# spec.add_development_dependency('jabber4r', '> 0.1', '<= 0.5')
|
||||
#
|
||||
# Development dependencies aren't installed by default, and
|
||||
# aren't activated when a gem is required.
|
||||
#
|
||||
# gem:: [String or Gem::Dependency] The Gem name/dependency.
|
||||
# requirements:: [default=">= 0"] The version requirements.
|
||||
#
|
||||
def add_dependency(gem, *requirements)
|
||||
requirements = if requirements.empty? then
|
||||
Gem::Requirement.default
|
||||
else
|
||||
requirements.flatten
|
||||
end
|
||||
|
||||
unless gem.respond_to?(:name) && gem.respond_to?(:version_requirements)
|
||||
gem = Dependency.new(gem, requirements)
|
||||
end
|
||||
|
||||
dependencies << gem
|
||||
def add_development_dependency(gem, *requirements)
|
||||
add_dependency_with_type(gem, :development, *requirements)
|
||||
end
|
||||
|
||||
|
||||
# Adds a runtime dependency to this Gem. For example,
|
||||
#
|
||||
# spec.add_runtime_dependency('jabber4r', '> 0.1', '<= 0.5')
|
||||
#
|
||||
# gem:: [String or Gem::Dependency] The Gem name/dependency.
|
||||
# requirements:: [default=">= 0"] The version requirements.
|
||||
def add_runtime_dependency(gem, *requirements)
|
||||
add_dependency_with_type(gem, :runtime, *requirements)
|
||||
end
|
||||
|
||||
alias add_dependency add_runtime_dependency
|
||||
|
||||
# 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).
|
||||
|
@ -673,30 +702,31 @@ module Gem
|
|||
end
|
||||
end
|
||||
|
||||
##
|
||||
# The full path to the gem (install path + full name).
|
||||
#
|
||||
# return:: [String] the full gem path
|
||||
#
|
||||
|
||||
def full_gem_path
|
||||
path = File.join installation_path, 'gems', full_name
|
||||
return path if File.directory? path
|
||||
File.join installation_path, 'gems', original_name
|
||||
end
|
||||
|
||||
|
||||
##
|
||||
# The default (generated) file name of the gem.
|
||||
|
||||
def file_name
|
||||
full_name + ".gem"
|
||||
end
|
||||
|
||||
# The root directory that the gem was installed into.
|
||||
#
|
||||
# return:: [String] the installation path
|
||||
#
|
||||
|
||||
##
|
||||
# The directory that this gem was installed into.
|
||||
|
||||
def installation_path
|
||||
(File.dirname(@loaded_from).split(File::SEPARATOR)[0..-2]).
|
||||
join(File::SEPARATOR)
|
||||
path = File.dirname(@loaded_from).split(File::SEPARATOR)[0..-2]
|
||||
path = path.join File::SEPARATOR
|
||||
File.expand_path path
|
||||
end
|
||||
|
||||
|
||||
# Checks if this Specification meets the requirement of the supplied
|
||||
# dependency.
|
||||
#
|
||||
|
@ -778,9 +808,11 @@ module Gem
|
|||
self.platform = Gem::Platform.new @platform
|
||||
end
|
||||
|
||||
##
|
||||
# Returns a Ruby code representation of this specification, such that it
|
||||
# can be eval'ed and reconstruct the same specification later. Attributes
|
||||
# that still have their default values are omitted.
|
||||
|
||||
def to_ruby
|
||||
mark_version
|
||||
result = []
|
||||
|
@ -792,8 +824,6 @@ module Gem
|
|||
result << " s.platform = #{ruby_code original_platform}"
|
||||
end
|
||||
result << ""
|
||||
result << " s.specification_version = #{specification_version} if s.respond_to? :specification_version="
|
||||
result << ""
|
||||
result << " s.required_rubygems_version = #{ruby_code required_rubygems_version} if s.respond_to? :required_rubygems_version="
|
||||
|
||||
handled = [
|
||||
|
@ -816,15 +846,42 @@ module Gem
|
|||
end
|
||||
end
|
||||
|
||||
result << "" unless dependencies.empty?
|
||||
result << nil
|
||||
result << " if s.respond_to? :specification_version then"
|
||||
result << " current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION"
|
||||
result << " s.specification_version = #{specification_version}"
|
||||
result << nil
|
||||
|
||||
dependencies.each do |dep|
|
||||
version_reqs_param = dep.requirements_list.inspect
|
||||
result << " s.add_dependency(%q<#{dep.name}>, #{version_reqs_param})"
|
||||
result << " if current_version >= 3 then"
|
||||
|
||||
unless dependencies.empty? then
|
||||
dependencies.each do |dep|
|
||||
version_reqs_param = dep.requirements_list.inspect
|
||||
dep.instance_variable_set :@type, :runtime if dep.type.nil? # HACK
|
||||
result << " s.add_#{dep.type}_dependency(%q<#{dep.name}>, #{version_reqs_param})"
|
||||
end
|
||||
end
|
||||
|
||||
result << " else"
|
||||
|
||||
unless dependencies.empty? then
|
||||
dependencies.each do |dep|
|
||||
version_reqs_param = dep.requirements_list.inspect
|
||||
result << " s.add_dependency(%q<#{dep.name}>, #{version_reqs_param})"
|
||||
end
|
||||
end
|
||||
|
||||
result << ' end'
|
||||
|
||||
result << " else"
|
||||
dependencies.each do |dep|
|
||||
version_reqs_param = dep.requirements_list.inspect
|
||||
result << " s.add_dependency(%q<#{dep.name}>, #{version_reqs_param})"
|
||||
end
|
||||
result << " end"
|
||||
|
||||
result << "end"
|
||||
result << ""
|
||||
result << nil
|
||||
|
||||
result.join "\n"
|
||||
end
|
||||
|
@ -940,6 +997,22 @@ module Gem
|
|||
|
||||
private
|
||||
|
||||
def add_dependency_with_type(dependency, type, *requirements)
|
||||
requirements = if requirements.empty? then
|
||||
Gem::Requirement.default
|
||||
else
|
||||
requirements.flatten
|
||||
end
|
||||
|
||||
unless dependency.respond_to?(:name) &&
|
||||
dependency.respond_to?(:version_requirements)
|
||||
|
||||
dependency = Dependency.new(dependency, requirements, type)
|
||||
end
|
||||
|
||||
dependencies << dependency
|
||||
end
|
||||
|
||||
def find_all_satisfiers(dep)
|
||||
Gem.source_index.each do |name,gem|
|
||||
if(gem.satisfies_requirement?(dep)) then
|
||||
|
|
120
lib/rubygems/test_utilities.rb
Normal file
120
lib/rubygems/test_utilities.rb
Normal file
|
@ -0,0 +1,120 @@
|
|||
require 'tempfile'
|
||||
require 'rubygems'
|
||||
require 'rubygems/remote_fetcher'
|
||||
|
||||
##
|
||||
# A fake Gem::RemoteFetcher for use in tests or to avoid real live HTTP
|
||||
# requests when testing code that uses RubyGems.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# @fetcher = Gem::FakeFetcher.new
|
||||
# @fetcher.data['http://gems.example.com/yaml'] = source_index.to_yaml
|
||||
# Gem::RemoteFetcher.fetcher = @fetcher
|
||||
#
|
||||
# # invoke RubyGems code
|
||||
#
|
||||
# paths = @fetcher.paths
|
||||
# assert_equal 'http://gems.example.com/yaml', paths.shift
|
||||
# assert paths.empty?, paths.join(', ')
|
||||
#
|
||||
# See RubyGems' tests for more examples of FakeFetcher.
|
||||
|
||||
class Gem::FakeFetcher
|
||||
|
||||
attr_reader :data
|
||||
attr_accessor :paths
|
||||
|
||||
def initialize
|
||||
@data = {}
|
||||
@paths = []
|
||||
end
|
||||
|
||||
def fetch_path(path)
|
||||
path = path.to_s
|
||||
@paths << path
|
||||
raise ArgumentError, 'need full URI' unless path =~ %r'^http://'
|
||||
data = @data[path]
|
||||
|
||||
if data.nil? then
|
||||
raise Gem::RemoteFetcher::FetchError.new('no data', path)
|
||||
end
|
||||
|
||||
data.respond_to?(:call) ? data.call : data
|
||||
end
|
||||
|
||||
def fetch_size(path)
|
||||
path = path.to_s
|
||||
@paths << path
|
||||
raise ArgumentError, 'need full URI' unless path =~ %r'^http://'
|
||||
data = @data[path]
|
||||
|
||||
if data.nil? then
|
||||
raise Gem::RemoteFetcher::FetchError.new("no data for #{path}", nil)
|
||||
end
|
||||
|
||||
data.respond_to?(:call) ? data.call : data.length
|
||||
end
|
||||
|
||||
def download spec, source_uri, install_dir = Gem.dir
|
||||
name = "#{spec.full_name}.gem"
|
||||
path = File.join(install_dir, 'cache', name)
|
||||
|
||||
Gem.ensure_gem_subdirectories install_dir
|
||||
|
||||
if source_uri =~ /^http/ then
|
||||
File.open(path, "wb") do |f|
|
||||
f.write fetch_path(File.join(source_uri, "gems", name))
|
||||
end
|
||||
else
|
||||
FileUtils.cp source_uri, path
|
||||
end
|
||||
|
||||
path
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# :stopdoc:
|
||||
class Gem::RemoteFetcher
|
||||
|
||||
def self.fetcher=(fetcher)
|
||||
@fetcher = fetcher
|
||||
end
|
||||
|
||||
end
|
||||
# :startdoc:
|
||||
|
||||
##
|
||||
# A StringIO duck-typed class that uses Tempfile instead of String as the
|
||||
# backing store.
|
||||
#--
|
||||
# This class was added to flush out problems in Rubinius' IO implementation.
|
||||
|
||||
class TempIO
|
||||
|
||||
@@count = 0
|
||||
|
||||
def initialize(string = '')
|
||||
@tempfile = Tempfile.new "TempIO-#{@@count += 1}"
|
||||
@tempfile.binmode
|
||||
@tempfile.write string
|
||||
@tempfile.rewind
|
||||
end
|
||||
|
||||
def method_missing(meth, *args, &block)
|
||||
@tempfile.send(meth, *args, &block)
|
||||
end
|
||||
|
||||
def respond_to?(meth)
|
||||
@tempfile.respond_to? meth
|
||||
end
|
||||
|
||||
def string
|
||||
@tempfile.flush
|
||||
|
||||
Gem.read_binary @tempfile.path
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -176,9 +176,10 @@ class Gem::Uninstaller
|
|||
end
|
||||
|
||||
def path_ok?(spec)
|
||||
match_path = File.join @gem_home, 'gems', spec.full_name
|
||||
full_path = File.join @gem_home, 'gems', spec.full_name
|
||||
original_path = File.join @gem_home, 'gems', spec.original_name
|
||||
|
||||
match_path == spec.full_gem_path
|
||||
full_path == spec.full_gem_path || original_path == spec.full_gem_path
|
||||
end
|
||||
|
||||
def dependencies_ok?(spec)
|
||||
|
|
|
@ -6,54 +6,71 @@
|
|||
|
||||
module Gem
|
||||
|
||||
####################################################################
|
||||
# Module that defines the default UserInteraction. Any class
|
||||
# including this module will have access to the +ui+ method that
|
||||
# returns the default UI.
|
||||
##
|
||||
# Module that defines the default UserInteraction. Any class including this
|
||||
# module will have access to the +ui+ method that returns the default UI.
|
||||
|
||||
module DefaultUserInteraction
|
||||
|
||||
##
|
||||
# The default UI is a class variable of the singleton class for this
|
||||
# module.
|
||||
|
||||
@ui = nil
|
||||
|
||||
##
|
||||
# Return the default UI.
|
||||
|
||||
def self.ui
|
||||
@ui ||= Gem::ConsoleUI.new
|
||||
end
|
||||
|
||||
##
|
||||
# Set the default UI. If the default UI is never explicitly set, a simple
|
||||
# console based UserInteraction will be used automatically.
|
||||
|
||||
def self.ui=(new_ui)
|
||||
@ui = new_ui
|
||||
end
|
||||
|
||||
##
|
||||
# Use +new_ui+ for the duration of +block+.
|
||||
|
||||
def self.use_ui(new_ui)
|
||||
old_ui = @ui
|
||||
@ui = new_ui
|
||||
yield
|
||||
ensure
|
||||
@ui = old_ui
|
||||
end
|
||||
|
||||
##
|
||||
# See DefaultUserInteraction::ui
|
||||
|
||||
def ui
|
||||
DefaultUserInteraction.ui
|
||||
end
|
||||
|
||||
# Set the default UI. If the default UI is never explicitly set, a
|
||||
# simple console based UserInteraction will be used automatically.
|
||||
##
|
||||
# See DefaultUserInteraction::ui=
|
||||
|
||||
def ui=(new_ui)
|
||||
DefaultUserInteraction.ui = new_ui
|
||||
end
|
||||
|
||||
##
|
||||
# See DefaultUserInteraction::use_ui
|
||||
|
||||
def use_ui(new_ui, &block)
|
||||
DefaultUserInteraction.use_ui(new_ui, &block)
|
||||
end
|
||||
|
||||
# The default UI is a class variable of the singleton class for
|
||||
# this module.
|
||||
|
||||
@ui = nil
|
||||
|
||||
class << self
|
||||
def ui
|
||||
@ui ||= Gem::ConsoleUI.new
|
||||
end
|
||||
def ui=(new_ui)
|
||||
@ui = new_ui
|
||||
end
|
||||
def use_ui(new_ui)
|
||||
old_ui = @ui
|
||||
@ui = new_ui
|
||||
yield
|
||||
ensure
|
||||
@ui = old_ui
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
####################################################################
|
||||
##
|
||||
# Make the default UI accessable without the "ui." prefix. Classes
|
||||
# including this module may use the interaction methods on the
|
||||
# default UI directly. Classes may also reference the +ui+ and
|
||||
# <tt>ui=</tt> methods.
|
||||
# including this module may use the interaction methods on the default UI
|
||||
# directly. Classes may also reference the ui and ui= methods.
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
|
@ -64,22 +81,30 @@ module Gem
|
|||
# n = ask("What is the meaning of life?")
|
||||
# end
|
||||
# end
|
||||
|
||||
module UserInteraction
|
||||
|
||||
include DefaultUserInteraction
|
||||
[
|
||||
:choose_from_list, :ask, :ask_yes_no, :say, :alert, :alert_warning,
|
||||
:alert_error, :terminate_interaction
|
||||
].each do |methname|
|
||||
|
||||
[:alert,
|
||||
:alert_error,
|
||||
:alert_warning,
|
||||
:ask,
|
||||
:ask_yes_no,
|
||||
:choose_from_list,
|
||||
:say,
|
||||
:terminate_interaction ].each do |methname|
|
||||
class_eval %{
|
||||
def #{methname}(*args)
|
||||
ui.#{methname}(*args)
|
||||
end
|
||||
}
|
||||
}, __FILE__, __LINE__
|
||||
end
|
||||
end
|
||||
|
||||
####################################################################
|
||||
##
|
||||
# StreamUI implements a simple stream based user interface.
|
||||
|
||||
class StreamUI
|
||||
|
||||
attr_reader :ins, :outs, :errs
|
||||
|
@ -89,15 +114,19 @@ module Gem
|
|||
@outs = out_stream
|
||||
@errs = err_stream
|
||||
end
|
||||
|
||||
# Choose from a list of options. +question+ is a prompt displayed
|
||||
# above the list. +list+ is a list of option strings. Returns
|
||||
# the pair [option_name, option_index].
|
||||
|
||||
##
|
||||
# Choose from a list of options. +question+ is a prompt displayed above
|
||||
# the list. +list+ is a list of option strings. Returns the pair
|
||||
# [option_name, option_index].
|
||||
|
||||
def choose_from_list(question, list)
|
||||
@outs.puts question
|
||||
|
||||
list.each_with_index do |item, index|
|
||||
@outs.puts " #{index+1}. #{item}"
|
||||
end
|
||||
|
||||
@outs.print "> "
|
||||
@outs.flush
|
||||
|
||||
|
@ -109,28 +138,32 @@ module Gem
|
|||
return list[result], result
|
||||
end
|
||||
|
||||
# Ask a question. Returns a true for yes, false for no. If not
|
||||
# connected to a tty, raises an exception if default is nil,
|
||||
# otherwise returns default.
|
||||
##
|
||||
# Ask a question. Returns a true for yes, false for no. If not connected
|
||||
# to a tty, raises an exception if default is nil, otherwise returns
|
||||
# default.
|
||||
|
||||
def ask_yes_no(question, default=nil)
|
||||
if not @ins.tty? then
|
||||
unless @ins.tty? then
|
||||
if default.nil? then
|
||||
raise(
|
||||
Gem::OperationNotSupportedError,
|
||||
"Not connected to a tty and no default specified")
|
||||
raise Gem::OperationNotSupportedError,
|
||||
"Not connected to a tty and no default specified"
|
||||
else
|
||||
return default
|
||||
end
|
||||
end
|
||||
|
||||
qstr = case default
|
||||
when nil
|
||||
'yn'
|
||||
when true
|
||||
'Yn'
|
||||
else
|
||||
'yN'
|
||||
end
|
||||
when nil
|
||||
'yn'
|
||||
when true
|
||||
'Yn'
|
||||
else
|
||||
'yN'
|
||||
end
|
||||
|
||||
result = nil
|
||||
|
||||
while result.nil?
|
||||
result = ask("#{question} [#{qstr}]")
|
||||
result = case result
|
||||
|
@ -144,51 +177,68 @@ module Gem
|
|||
nil
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
# Ask a question. Returns an answer if connected to a tty, nil
|
||||
# otherwise.
|
||||
|
||||
##
|
||||
# Ask a question. Returns an answer if connected to a tty, nil otherwise.
|
||||
|
||||
def ask(question)
|
||||
return nil if not @ins.tty?
|
||||
|
||||
@outs.print(question + " ")
|
||||
@outs.flush
|
||||
|
||||
result = @ins.gets
|
||||
result.chomp! if result
|
||||
result
|
||||
end
|
||||
|
||||
|
||||
##
|
||||
# Display a statement.
|
||||
|
||||
def say(statement="")
|
||||
@outs.puts statement
|
||||
end
|
||||
|
||||
# Display an informational alert.
|
||||
|
||||
##
|
||||
# Display an informational alert. Will ask +question+ if it is not nil.
|
||||
|
||||
def alert(statement, question=nil)
|
||||
@outs.puts "INFO: #{statement}"
|
||||
return ask(question) if question
|
||||
ask(question) if question
|
||||
end
|
||||
|
||||
# Display a warning in a location expected to get error messages.
|
||||
|
||||
##
|
||||
# Display a warning in a location expected to get error messages. Will
|
||||
# ask +question+ if it is not nil.
|
||||
|
||||
def alert_warning(statement, question=nil)
|
||||
@errs.puts "WARNING: #{statement}"
|
||||
ask(question) if question
|
||||
ask(question) if question
|
||||
end
|
||||
|
||||
# Display an error message in a location expected to get error
|
||||
# messages.
|
||||
|
||||
##
|
||||
# Display an error message in a location expected to get error messages.
|
||||
# Will ask +question+ if it is not nil.
|
||||
|
||||
def alert_error(statement, question=nil)
|
||||
@errs.puts "ERROR: #{statement}"
|
||||
ask(question) if question
|
||||
end
|
||||
|
||||
# Terminate the application normally, running any exit handlers
|
||||
# that might have been defined.
|
||||
##
|
||||
# Terminate the application with exit code +status+, running any exit
|
||||
# handlers that might have been defined.
|
||||
|
||||
def terminate_interaction(status = 0)
|
||||
raise Gem::SystemExitException, status
|
||||
end
|
||||
|
||||
# Return a progress reporter object
|
||||
##
|
||||
# Return a progress reporter object chosen from the current verbosity.
|
||||
|
||||
def progress_reporter(*args)
|
||||
case Gem.configuration.verbose
|
||||
when nil, false
|
||||
|
@ -200,6 +250,9 @@ module Gem
|
|||
end
|
||||
end
|
||||
|
||||
##
|
||||
# An absolutely silent progress reporter.
|
||||
|
||||
class SilentProgressReporter
|
||||
attr_reader :count
|
||||
|
||||
|
@ -213,6 +266,9 @@ module Gem
|
|||
end
|
||||
end
|
||||
|
||||
##
|
||||
# A basic dotted progress reporter.
|
||||
|
||||
class SimpleProgressReporter
|
||||
include DefaultUserInteraction
|
||||
|
||||
|
@ -228,17 +284,27 @@ module Gem
|
|||
@out.puts initial_message
|
||||
end
|
||||
|
||||
##
|
||||
# Prints out a dot and ignores +message+.
|
||||
|
||||
def updated(message)
|
||||
@count += 1
|
||||
@out.print "."
|
||||
@out.flush
|
||||
end
|
||||
|
||||
##
|
||||
# Prints out the terminal message.
|
||||
|
||||
def done
|
||||
@out.puts "\n#{@terminal_message}"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
##
|
||||
# A progress reporter that prints out messages about the current progress.
|
||||
|
||||
class VerboseProgressReporter
|
||||
include DefaultUserInteraction
|
||||
|
||||
|
@ -254,32 +320,41 @@ module Gem
|
|||
@out.puts initial_message
|
||||
end
|
||||
|
||||
##
|
||||
# Prints out the position relative to the total and the +message+.
|
||||
|
||||
def updated(message)
|
||||
@count += 1
|
||||
@out.puts "#{@count}/#{@total}: #{message}"
|
||||
end
|
||||
|
||||
##
|
||||
# Prints out the terminal message.
|
||||
|
||||
def done
|
||||
@out.puts @terminal_message
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
####################################################################
|
||||
# Subclass of StreamUI that instantiates the user interaction using
|
||||
# standard in, out and error.
|
||||
##
|
||||
# Subclass of StreamUI that instantiates the user interaction using STDIN,
|
||||
# STDOUT, and STDERR.
|
||||
|
||||
class ConsoleUI < StreamUI
|
||||
def initialize
|
||||
super(STDIN, STDOUT, STDERR)
|
||||
end
|
||||
end
|
||||
|
||||
####################################################################
|
||||
##
|
||||
# SilentUI is a UI choice that is absolutely silent.
|
||||
|
||||
class SilentUI
|
||||
def method_missing(sym, *args, &block)
|
||||
self
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ require 'rubygems'
|
|||
|
||||
##
|
||||
# The Version class processes string versions into comparable values
|
||||
|
||||
class Gem::Version
|
||||
|
||||
include Comparable
|
||||
|
@ -17,11 +18,8 @@ class Gem::Version
|
|||
attr_reader :version
|
||||
|
||||
##
|
||||
# Checks if version string is valid format
|
||||
#
|
||||
# str:: [String] the version string
|
||||
# return:: [Boolean] true if the string format is correct, otherwise false
|
||||
#
|
||||
# Returns true if +version+ is a valid version string.
|
||||
|
||||
def self.correct?(version)
|
||||
case version
|
||||
when Integer, /\A\s*(\d+(\.\d+)*)*\s*\z/ then true
|
||||
|
@ -36,7 +34,7 @@ class Gem::Version
|
|||
# ver1 = Version.create('1.3.17') # -> (Version object)
|
||||
# ver2 = Version.create(ver1) # -> (ver1)
|
||||
# ver3 = Version.create(nil) # -> nil
|
||||
#
|
||||
|
||||
def self.create(input)
|
||||
if input.respond_to? :version then
|
||||
input
|
||||
|
@ -48,10 +46,9 @@ class Gem::Version
|
|||
end
|
||||
|
||||
##
|
||||
# Constructs a version from the supplied string
|
||||
#
|
||||
# version:: [String] The version string. Format is digit.digit...
|
||||
#
|
||||
# Constructs a Version from the +version+ string. A version string is a
|
||||
# series of digits separated by dots.
|
||||
|
||||
def initialize(version)
|
||||
raise ArgumentError, "Malformed version number string #{version}" unless
|
||||
self.class.correct?(version)
|
||||
|
@ -73,7 +70,9 @@ class Gem::Version
|
|||
self.version = array[0]
|
||||
end
|
||||
|
||||
##
|
||||
# Strip ignored trailing zeros.
|
||||
|
||||
def normalize
|
||||
@ints = build_array_from_version_string
|
||||
|
||||
|
@ -94,10 +93,8 @@ class Gem::Version
|
|||
end
|
||||
|
||||
##
|
||||
# Convert version to integer array
|
||||
#
|
||||
# return:: [Array] list of integers
|
||||
#
|
||||
# Returns an integer array representation of this Version.
|
||||
|
||||
def to_ints
|
||||
normalize unless @ints
|
||||
@ints
|
||||
|
@ -117,20 +114,25 @@ class Gem::Version
|
|||
end
|
||||
|
||||
##
|
||||
# Compares two versions
|
||||
#
|
||||
# other:: [Version or .ints] other version to compare to
|
||||
# return:: [Fixnum] -1, 0, 1
|
||||
#
|
||||
# Compares this version with +other+ returning -1, 0, or 1 if the other
|
||||
# version is larger, the same, or smaller than this one.
|
||||
|
||||
def <=>(other)
|
||||
return nil unless self.class === other
|
||||
return 1 unless other
|
||||
@ints <=> other.ints
|
||||
end
|
||||
|
||||
alias eql? == # :nodoc:
|
||||
##
|
||||
# A Version is only eql? to another version if it has the same version
|
||||
# string. "1.0" is not the same version as "1".
|
||||
|
||||
def eql?(other)
|
||||
self.class === other and @version == other.version
|
||||
end
|
||||
|
||||
def hash # :nodoc:
|
||||
to_ints.inject { |hash_code, n| hash_code + n }
|
||||
@version.hash
|
||||
end
|
||||
|
||||
# Return a new version object where the next to the last revision
|
||||
|
|
|
@ -10,10 +10,9 @@ at_exit { $SAFE = 1 }
|
|||
require 'fileutils'
|
||||
require 'test/unit'
|
||||
require 'tmpdir'
|
||||
require 'tempfile'
|
||||
require 'uri'
|
||||
require 'rubygems/source_info_cache'
|
||||
require 'rubygems/package'
|
||||
require 'rubygems/test_utilities'
|
||||
|
||||
require File.join(File.expand_path(File.dirname(__FILE__)), 'mockgemui')
|
||||
|
||||
|
@ -27,54 +26,6 @@ module Gem
|
|||
end
|
||||
end
|
||||
|
||||
class FakeFetcher
|
||||
|
||||
attr_reader :data
|
||||
attr_accessor :uri
|
||||
attr_accessor :paths
|
||||
|
||||
def initialize
|
||||
@data = {}
|
||||
@paths = []
|
||||
@uri = nil
|
||||
end
|
||||
|
||||
def fetch_path(path)
|
||||
path = path.to_s
|
||||
@paths << path
|
||||
raise ArgumentError, 'need full URI' unless path =~ %r'^http://'
|
||||
data = @data[path]
|
||||
raise Gem::RemoteFetcher::FetchError, "no data for #{path}" if data.nil?
|
||||
data.respond_to?(:call) ? data.call : data
|
||||
end
|
||||
|
||||
def fetch_size(path)
|
||||
path = path.to_s
|
||||
@paths << path
|
||||
raise ArgumentError, 'need full URI' unless path =~ %r'^http://'
|
||||
data = @data[path]
|
||||
raise Gem::RemoteFetcher::FetchError, "no data for #{path}" if data.nil?
|
||||
data.respond_to?(:call) ? data.call : data.length
|
||||
end
|
||||
|
||||
def download spec, source_uri, install_dir = Gem.dir
|
||||
name = "#{spec.full_name}.gem"
|
||||
path = File.join(install_dir, 'cache', name)
|
||||
|
||||
Gem.ensure_gem_subdirectories install_dir
|
||||
|
||||
if source_uri =~ /^http/ then
|
||||
File.open(path, "wb") do |f|
|
||||
f.write fetch_path(File.join(source_uri, "gems", name))
|
||||
end
|
||||
else
|
||||
FileUtils.cp source_uri, path
|
||||
end
|
||||
|
||||
path
|
||||
end
|
||||
end
|
||||
|
||||
class RubyGemTestCase < Test::Unit::TestCase
|
||||
|
||||
include Gem::DefaultUserInteraction
|
||||
|
@ -94,8 +45,13 @@ class RubyGemTestCase < Test::Unit::TestCase
|
|||
@gemcache = File.join(@gemhome, "source_cache")
|
||||
@usrcache = File.join(@gemhome, ".gem", "user_cache")
|
||||
@latest_usrcache = File.join(@gemhome, ".gem", "latest_user_cache")
|
||||
@userhome = File.join @tempdir, 'userhome'
|
||||
|
||||
ENV['HOME'] = @userhome
|
||||
Gem.instance_variable_set :@user_home, nil
|
||||
|
||||
FileUtils.mkdir_p @gemhome
|
||||
FileUtils.mkdir_p @userhome
|
||||
|
||||
ENV['GEMCACHE'] = @usrcache
|
||||
Gem.use_paths(@gemhome)
|
||||
|
@ -104,9 +60,12 @@ class RubyGemTestCase < Test::Unit::TestCase
|
|||
Gem.configuration.verbose = true
|
||||
Gem.configuration.update_sources = true
|
||||
|
||||
@gem_repo = "http://gems.example.com"
|
||||
@gem_repo = "http://gems.example.com/"
|
||||
@uri = URI.parse @gem_repo
|
||||
Gem.sources.replace [@gem_repo]
|
||||
|
||||
Gem::SpecFetcher.fetcher = nil
|
||||
|
||||
@orig_BASERUBY = Gem::ConfigMap[:BASERUBY]
|
||||
Gem::ConfigMap[:BASERUBY] = Gem::ConfigMap[:RUBY_INSTALL_NAME]
|
||||
|
||||
|
@ -131,7 +90,7 @@ class RubyGemTestCase < Test::Unit::TestCase
|
|||
Gem::ConfigMap[:arch] = @orig_arch
|
||||
|
||||
if defined? Gem::RemoteFetcher then
|
||||
Gem::RemoteFetcher.instance_variable_set :@fetcher, nil
|
||||
Gem::RemoteFetcher.fetcher = nil
|
||||
end
|
||||
|
||||
FileUtils.rm_rf @tempdir
|
||||
|
@ -141,7 +100,6 @@ class RubyGemTestCase < Test::Unit::TestCase
|
|||
ENV.delete 'GEM_PATH'
|
||||
|
||||
Gem.clear_paths
|
||||
Gem::SourceInfoCache.instance_variable_set :@cache, nil
|
||||
end
|
||||
|
||||
def install_gem gem
|
||||
|
@ -154,7 +112,7 @@ class RubyGemTestCase < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
gem = File.join(@tempdir, "#{gem.full_name}.gem").untaint
|
||||
Gem::Installer.new(gem).install
|
||||
Gem::Installer.new(gem, :wrappers => true).install
|
||||
end
|
||||
|
||||
def prep_cache_files(lc)
|
||||
|
@ -231,6 +189,8 @@ class RubyGemTestCase < Test::Unit::TestCase
|
|||
|
||||
spec.loaded_from = written_path
|
||||
|
||||
Gem.source_index.add_spec spec
|
||||
|
||||
return spec
|
||||
end
|
||||
|
||||
|
@ -254,6 +214,12 @@ class RubyGemTestCase < Test::Unit::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
def util_clear_gems
|
||||
FileUtils.rm_r File.join(@gemhome, 'gems')
|
||||
FileUtils.rm_r File.join(@gemhome, 'specifications')
|
||||
Gem.source_index.refresh!
|
||||
end
|
||||
|
||||
def util_gem(name, version, &block)
|
||||
spec = quick_gem(name, version, &block)
|
||||
|
||||
|
@ -271,6 +237,16 @@ class RubyGemTestCase < Test::Unit::TestCase
|
|||
[spec, cache_file]
|
||||
end
|
||||
|
||||
def util_gzip(data)
|
||||
out = StringIO.new
|
||||
|
||||
Zlib::GzipWriter.wrap out do |io|
|
||||
io.write data
|
||||
end
|
||||
|
||||
out.string
|
||||
end
|
||||
|
||||
def util_make_gems
|
||||
init = proc do |s|
|
||||
s.files = %w[lib/code.rb]
|
||||
|
@ -303,7 +279,7 @@ class RubyGemTestCase < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
##
|
||||
# Set the platform to +cpu+ and +os+
|
||||
# Set the platform to +arch+
|
||||
|
||||
def util_set_arch(arch)
|
||||
Gem::ConfigMap[:arch] = arch
|
||||
|
@ -320,9 +296,7 @@ class RubyGemTestCase < Test::Unit::TestCase
|
|||
require 'socket'
|
||||
require 'rubygems/remote_fetcher'
|
||||
|
||||
@uri = URI.parse @gem_repo
|
||||
@fetcher = FakeFetcher.new
|
||||
@fetcher.uri = @uri
|
||||
@fetcher = Gem::FakeFetcher.new
|
||||
|
||||
util_make_gems
|
||||
|
||||
|
@ -338,10 +312,11 @@ class RubyGemTestCase < Test::Unit::TestCase
|
|||
@source_index.add_spec @a_evil9
|
||||
@source_index.add_spec @c1_2
|
||||
|
||||
Gem::RemoteFetcher.instance_variable_set :@fetcher, @fetcher
|
||||
Gem::RemoteFetcher.fetcher = @fetcher
|
||||
end
|
||||
|
||||
def util_setup_source_info_cache(*specs)
|
||||
require 'rubygems/source_info_cache'
|
||||
require 'rubygems/source_info_cache_entry'
|
||||
|
||||
specs = Hash[*specs.map { |spec| [spec.full_name, spec] }.flatten]
|
||||
|
@ -356,6 +331,35 @@ class RubyGemTestCase < Test::Unit::TestCase
|
|||
sic.reset_cache_data
|
||||
|
||||
Gem::SourceInfoCache.instance_variable_set :@cache, sic
|
||||
|
||||
si
|
||||
end
|
||||
|
||||
def util_setup_spec_fetcher(*specs)
|
||||
specs = Hash[*specs.map { |spec| [spec.full_name, spec] }.flatten]
|
||||
si = Gem::SourceIndex.new specs
|
||||
|
||||
spec_fetcher = Gem::SpecFetcher.fetcher
|
||||
|
||||
spec_fetcher.specs[@uri] = []
|
||||
si.gems.sort_by { |_, spec| spec }.each do |_, spec|
|
||||
spec_tuple = [spec.name, spec.version, spec.original_platform]
|
||||
spec_fetcher.specs[@uri] << spec_tuple
|
||||
end
|
||||
|
||||
spec_fetcher.latest_specs[@uri] = []
|
||||
si.latest_specs.sort.each do |spec|
|
||||
spec_tuple = [spec.name, spec.version, spec.original_platform]
|
||||
spec_fetcher.latest_specs[@uri] << spec_tuple
|
||||
end
|
||||
|
||||
si.gems.sort_by { |_,spec| spec }.each do |_, spec|
|
||||
path = "#{@gem_repo}quick/Marshal.#{Gem.marshal_version}/#{spec.original_name}.gemspec.rz"
|
||||
data = Marshal.dump spec
|
||||
data_deflate = Zlib::Deflate.deflate data
|
||||
@fetcher.data[path] = data_deflate
|
||||
end
|
||||
|
||||
si
|
||||
end
|
||||
|
||||
|
@ -384,30 +388,3 @@ class RubyGemTestCase < Test::Unit::TestCase
|
|||
|
||||
end
|
||||
|
||||
class TempIO
|
||||
|
||||
@@count = 0
|
||||
|
||||
def initialize(string = '')
|
||||
@tempfile = Tempfile.new "TempIO-#{@@count ++ 1}"
|
||||
@tempfile.binmode
|
||||
@tempfile.write string
|
||||
@tempfile.rewind
|
||||
end
|
||||
|
||||
def method_missing(meth, *args, &block)
|
||||
@tempfile.send(meth, *args, &block)
|
||||
end
|
||||
|
||||
def respond_to?(meth)
|
||||
@tempfile.respond_to? meth
|
||||
end
|
||||
|
||||
def string
|
||||
@tempfile.flush
|
||||
|
||||
Gem.read_binary @tempfile.path
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -12,11 +12,6 @@ require 'rubygems'
|
|||
|
||||
class TestConfig < RubyGemTestCase
|
||||
|
||||
def test_gem_original_datadir
|
||||
datadir = Config::CONFIG['datadir']
|
||||
assert_equal "#{datadir}/xyz", Config.gem_original_datadir('xyz')
|
||||
end
|
||||
|
||||
def test_datadir
|
||||
datadir = Config::CONFIG['datadir']
|
||||
assert_equal "#{datadir}/xyz", Config.datadir('xyz')
|
||||
|
|
|
@ -27,6 +27,14 @@ class TestGem < RubyGemTestCase
|
|||
|
||||
assert_equal expected, Gem.all_load_paths.sort
|
||||
end
|
||||
|
||||
def test_self_available?
|
||||
util_make_gems
|
||||
assert(Gem.available?("a"))
|
||||
assert(Gem.available?("a", "1"))
|
||||
assert(Gem.available?("a", ">1"))
|
||||
assert(!Gem.available?("monkeys"))
|
||||
end
|
||||
|
||||
def test_self_bindir
|
||||
assert_equal File.join(@gemhome, 'bin'), Gem.bindir
|
||||
|
@ -129,7 +137,7 @@ class TestGem < RubyGemTestCase
|
|||
end
|
||||
|
||||
def test_self_default_sources
|
||||
assert_equal %w[http://gems.rubyforge.org], Gem.default_sources
|
||||
assert_equal %w[http://gems.rubyforge.org/], Gem.default_sources
|
||||
end
|
||||
|
||||
def test_self_dir
|
||||
|
@ -237,6 +245,18 @@ class TestGem < RubyGemTestCase
|
|||
assert_equal [Gem.dir], Gem.path
|
||||
end
|
||||
|
||||
def test_self_path_default
|
||||
if defined? APPLE_GEM_HOME
|
||||
orig_APPLE_GEM_HOME = APPLE_GEM_HOME
|
||||
Object.send :remove_const, :APPLE_GEM_HOME
|
||||
end
|
||||
Gem.instance_variable_set :@gem_path, nil
|
||||
|
||||
assert_equal [Gem.default_path, Gem.dir], Gem.path
|
||||
ensure
|
||||
Object.const_set :APPLE_GEM_HOME, orig_APPLE_GEM_HOME
|
||||
end
|
||||
|
||||
unless win_platform?
|
||||
def test_self_path_APPLE_GEM_HOME
|
||||
Gem.clear_paths
|
||||
|
@ -382,7 +402,7 @@ class TestGem < RubyGemTestCase
|
|||
end
|
||||
|
||||
def test_self_sources
|
||||
assert_equal %w[http://gems.example.com], Gem.sources
|
||||
assert_equal %w[http://gems.example.com/], Gem.sources
|
||||
end
|
||||
|
||||
def test_ssl_available_eh
|
||||
|
|
|
@ -66,7 +66,7 @@ class TestGemCommandManager < RubyGemTestCase
|
|||
assert_equal :both, check_options[:domain]
|
||||
assert_equal true, check_options[:wrappers]
|
||||
assert_equal Gem::Requirement.default, check_options[:version]
|
||||
assert_equal Gem.dir, check_options[:install_dir]
|
||||
assert_equal nil, check_options[:install_dir]
|
||||
assert_equal nil, check_options[:bin_dir]
|
||||
|
||||
#check settings
|
||||
|
|
|
@ -9,6 +9,8 @@ class TestGemCommandsDependencyCommand < RubyGemTestCase
|
|||
|
||||
@cmd = Gem::Commands::DependencyCommand.new
|
||||
@cmd.options[:domain] = :local
|
||||
|
||||
util_setup_fake_fetcher
|
||||
end
|
||||
|
||||
def test_execute
|
||||
|
@ -16,13 +18,15 @@ class TestGemCommandsDependencyCommand < RubyGemTestCase
|
|||
gem.add_dependency 'bar', '> 1'
|
||||
end
|
||||
|
||||
Gem.source_index = nil
|
||||
|
||||
@cmd.options[:args] = %w[foo]
|
||||
|
||||
use_ui @ui do
|
||||
@cmd.execute
|
||||
end
|
||||
|
||||
assert_equal "Gem foo-2\n bar (> 1)\n\n", @ui.output
|
||||
assert_equal "Gem foo-2\n bar (> 1, runtime)\n\n", @ui.output
|
||||
assert_equal '', @ui.error
|
||||
end
|
||||
|
||||
|
@ -35,7 +39,7 @@ class TestGemCommandsDependencyCommand < RubyGemTestCase
|
|||
end
|
||||
end
|
||||
|
||||
assert_equal "No match found for foo (>= 0)\n", @ui.output
|
||||
assert_equal "No gems found matching foo (>= 0)\n", @ui.output
|
||||
assert_equal '', @ui.error
|
||||
end
|
||||
|
||||
|
@ -64,6 +68,8 @@ class TestGemCommandsDependencyCommand < RubyGemTestCase
|
|||
gem.add_dependency 'foo'
|
||||
end
|
||||
|
||||
Gem.source_index = nil
|
||||
|
||||
@cmd.options[:args] = %w[foo]
|
||||
@cmd.options[:reverse_dependencies] = true
|
||||
|
||||
|
@ -73,9 +79,9 @@ class TestGemCommandsDependencyCommand < RubyGemTestCase
|
|||
|
||||
expected = <<-EOF
|
||||
Gem foo-2
|
||||
bar (> 1)
|
||||
bar (> 1, runtime)
|
||||
Used by
|
||||
baz-2 (foo (>= 0))
|
||||
baz-2 (foo (>= 0, runtime))
|
||||
|
||||
EOF
|
||||
|
||||
|
@ -83,12 +89,34 @@ Gem foo-2
|
|||
assert_equal '', @ui.error
|
||||
end
|
||||
|
||||
def test_execute_reverse_remote
|
||||
@cmd.options[:args] = %w[foo]
|
||||
@cmd.options[:reverse_dependencies] = true
|
||||
@cmd.options[:domain] = :remote
|
||||
|
||||
assert_raise MockGemUi::TermError do
|
||||
use_ui @ui do
|
||||
@cmd.execute
|
||||
end
|
||||
end
|
||||
|
||||
expected = <<-EOF
|
||||
ERROR: Only reverse dependencies for local gems are supported.
|
||||
EOF
|
||||
|
||||
assert_equal '', @ui.output
|
||||
assert_equal expected, @ui.error
|
||||
end
|
||||
|
||||
def test_execute_remote
|
||||
foo = quick_gem 'foo' do |gem|
|
||||
gem.add_dependency 'bar', '> 1'
|
||||
end
|
||||
|
||||
util_setup_source_info_cache foo
|
||||
@fetcher = Gem::FakeFetcher.new
|
||||
Gem::RemoteFetcher.fetcher = @fetcher
|
||||
|
||||
util_setup_spec_fetcher foo
|
||||
|
||||
FileUtils.rm File.join(@gemhome, 'specifications',
|
||||
"#{foo.full_name}.gemspec")
|
||||
|
@ -100,9 +128,48 @@ Gem foo-2
|
|||
@cmd.execute
|
||||
end
|
||||
|
||||
assert_equal "Gem foo-2\n bar (> 1)\n\n", @ui.output
|
||||
assert_equal "Gem foo-2\n bar (> 1, runtime)\n\n", @ui.output
|
||||
assert_equal '', @ui.error
|
||||
end
|
||||
|
||||
def test_execute_remote_legacy
|
||||
foo = quick_gem 'foo' do |gem|
|
||||
gem.add_dependency 'bar', '> 1'
|
||||
end
|
||||
|
||||
@fetcher = Gem::FakeFetcher.new
|
||||
Gem::RemoteFetcher.fetcher = @fetcher
|
||||
|
||||
Gem::SpecFetcher.fetcher = nil
|
||||
si = util_setup_source_info_cache foo
|
||||
|
||||
@fetcher.data["#{@gem_repo}yaml"] = YAML.dump si
|
||||
@fetcher.data["#{@gem_repo}Marshal.#{Gem.marshal_version}"] =
|
||||
si.dump
|
||||
|
||||
@fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"] = nil
|
||||
|
||||
FileUtils.rm File.join(@gemhome, 'specifications',
|
||||
"#{foo.full_name}.gemspec")
|
||||
|
||||
@cmd.options[:args] = %w[foo]
|
||||
@cmd.options[:domain] = :remote
|
||||
|
||||
use_ui @ui do
|
||||
@cmd.execute
|
||||
end
|
||||
|
||||
assert_equal "Gem foo-2\n bar (> 1, runtime)\n\n", @ui.output
|
||||
|
||||
expected = <<-EOF
|
||||
WARNING: RubyGems 1.2+ index not found for:
|
||||
\t#{@gem_repo}
|
||||
|
||||
RubyGems will revert to legacy indexes degrading performance.
|
||||
EOF
|
||||
|
||||
assert_equal expected, @ui.error
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ class TestGemCommandsEnvironmentCommand < RubyGemTestCase
|
|||
assert_match %r|RUBYGEMS PREFIX: |, @ui.output
|
||||
assert_match %r|RUBY EXECUTABLE:.*#{Gem::ConfigMap[:RUBY_INSTALL_NAME]}|,
|
||||
@ui.output
|
||||
assert_match %r|EXECUTABLE DIRECTORY:|, @ui.output
|
||||
assert_match %r|RUBYGEMS PLATFORMS:|, @ui.output
|
||||
assert_match %r|- #{Gem::Platform.local}|, @ui.output
|
||||
assert_match %r|GEM PATHS:|, @ui.output
|
||||
|
|
|
@ -14,10 +14,9 @@ class TestGemCommandsFetchCommand < RubyGemTestCase
|
|||
|
||||
def test_execute
|
||||
util_setup_fake_fetcher
|
||||
util_setup_spec_fetcher @a2
|
||||
|
||||
@fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] =
|
||||
@source_index.dump
|
||||
@fetcher.data["#{@gem_repo}/gems/#{@a2.full_name}.gem"] =
|
||||
@fetcher.data["#{@gem_repo}gems/#{@a2.full_name}.gem"] =
|
||||
File.read(File.join(@gemhome, 'cache', "#{@a2.full_name}.gem"))
|
||||
|
||||
@cmd.options[:args] = [@a2.name]
|
||||
|
@ -28,7 +27,28 @@ class TestGemCommandsFetchCommand < RubyGemTestCase
|
|||
end
|
||||
end
|
||||
|
||||
assert File.exist?(File.join(@tempdir, "#{@a2.full_name}.gem"))
|
||||
assert File.exist?(File.join(@tempdir, "#{@a2.full_name}.gem")),
|
||||
"#{@a2.full_name} fetched"
|
||||
end
|
||||
|
||||
def test_execute_legacy
|
||||
util_setup_fake_fetcher
|
||||
util_setup_source_info_cache @a2
|
||||
|
||||
@fetcher.data["#{@gem_repo}yaml"] = ''
|
||||
@fetcher.data["#{@gem_repo}gems/#{@a2.full_name}.gem"] =
|
||||
File.read(File.join(@gemhome, 'cache', "#{@a2.full_name}.gem"))
|
||||
|
||||
@cmd.options[:args] = [@a2.name]
|
||||
|
||||
use_ui @ui do
|
||||
Dir.chdir @tempdir do
|
||||
@cmd.execute
|
||||
end
|
||||
end
|
||||
|
||||
assert File.exist?(File.join(@tempdir, "#{@a2.full_name}.gem")),
|
||||
"#{@a2.full_name} fetched"
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -72,7 +72,7 @@ class TestGemCommandsInstallCommand < RubyGemTestCase
|
|||
end
|
||||
|
||||
# HACK no repository was checked
|
||||
assert_equal "ERROR: could not find no_such_gem locally or in a repository\n",
|
||||
assert_equal "ERROR: could not find gem no_such_gem locally or in a repository\n",
|
||||
@ui.error
|
||||
end
|
||||
|
||||
|
@ -86,8 +86,7 @@ class TestGemCommandsInstallCommand < RubyGemTestCase
|
|||
|
||||
def test_execute_nonexistent
|
||||
util_setup_fake_fetcher
|
||||
@fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] =
|
||||
@source_index.dump
|
||||
util_setup_spec_fetcher
|
||||
|
||||
@cmd.options[:args] = %w[nonexistent]
|
||||
|
||||
|
@ -98,18 +97,18 @@ class TestGemCommandsInstallCommand < RubyGemTestCase
|
|||
assert_equal 2, e.exit_code
|
||||
end
|
||||
|
||||
assert_equal "ERROR: could not find nonexistent locally or in a repository\n",
|
||||
assert_equal "ERROR: could not find gem nonexistent locally or in a repository\n",
|
||||
@ui.error
|
||||
end
|
||||
|
||||
def test_execute_remote
|
||||
@cmd.options[:generate_rdoc] = true
|
||||
@cmd.options[:generate_ri] = true
|
||||
util_setup_fake_fetcher
|
||||
|
||||
@fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] =
|
||||
@source_index.dump
|
||||
@fetcher.data["#{@gem_repo}/gems/#{@a2.full_name}.gem"] =
|
||||
util_setup_fake_fetcher
|
||||
util_setup_spec_fetcher @a2
|
||||
|
||||
@fetcher.data["#{@gem_repo}gems/#{@a2.full_name}.gem"] =
|
||||
read_binary(File.join(@gemhome, 'cache', "#{@a2.full_name}.gem"))
|
||||
|
||||
@cmd.options[:args] = [@a2.name]
|
||||
|
@ -122,7 +121,6 @@ class TestGemCommandsInstallCommand < RubyGemTestCase
|
|||
end
|
||||
|
||||
out = @ui.output.split "\n"
|
||||
assert_match %r|Bulk updating|, out.shift
|
||||
assert_equal "Successfully installed #{@a2.full_name}", out.shift
|
||||
assert_equal "1 gem installed", out.shift
|
||||
assert_equal "Installing ri documentation for #{@a2.full_name}...",
|
||||
|
|
43
test/rubygems/test_gem_commands_outdated_command.rb
Normal file
43
test/rubygems/test_gem_commands_outdated_command.rb
Normal file
|
@ -0,0 +1,43 @@
|
|||
require 'test/unit'
|
||||
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
|
||||
require 'rubygems/commands/outdated_command'
|
||||
|
||||
class TestGemCommandsOutdatedCommand < RubyGemTestCase
|
||||
|
||||
def setup
|
||||
super
|
||||
|
||||
@cmd = Gem::Commands::OutdatedCommand.new
|
||||
end
|
||||
|
||||
def test_initialize
|
||||
assert @cmd.handles?(%W[--platform #{Gem::Platform.local}])
|
||||
end
|
||||
|
||||
def test_execute
|
||||
local_01 = quick_gem 'foo', '0.1'
|
||||
local_02 = quick_gem 'foo', '0.2'
|
||||
remote_10 = quick_gem 'foo', '1.0'
|
||||
remote_20 = quick_gem 'foo', '2.0'
|
||||
|
||||
remote_spec_file = File.join @gemhome, 'specifications',
|
||||
remote_10.full_name + ".gemspec"
|
||||
FileUtils.rm remote_spec_file
|
||||
|
||||
remote_spec_file = File.join @gemhome, 'specifications',
|
||||
remote_20.full_name + ".gemspec"
|
||||
FileUtils.rm remote_spec_file
|
||||
|
||||
@fetcher = Gem::FakeFetcher.new
|
||||
Gem::RemoteFetcher.fetcher = @fetcher
|
||||
|
||||
util_setup_spec_fetcher remote_10, remote_20
|
||||
|
||||
use_ui @ui do @cmd.execute end
|
||||
|
||||
assert_equal "foo (0.2 < 2.0)\n", @ui.output
|
||||
assert_equal "", @ui.error
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -18,16 +18,24 @@ class TestGemCommandsPristineCommand < RubyGemTestCase
|
|||
|
||||
install_gem a
|
||||
|
||||
foo_path = File.join @gemhome, 'gems', a.full_name, 'bin', 'foo'
|
||||
|
||||
File.open foo_path, 'w' do |io|
|
||||
io.puts 'I changed it!'
|
||||
end
|
||||
|
||||
@cmd.options[:args] = %w[a]
|
||||
|
||||
use_ui @ui do
|
||||
@cmd.execute
|
||||
end
|
||||
|
||||
assert_equal "#!/usr/bin/ruby\n", File.read(foo_path), foo_path
|
||||
|
||||
out = @ui.output.split "\n"
|
||||
|
||||
assert_equal "Restoring gem(s) to pristine condition...", out.shift
|
||||
assert_equal "#{a.full_name} is in pristine condition", out.shift
|
||||
assert_equal "Restored #{a.full_name}", out.shift
|
||||
assert out.empty?, out.inspect
|
||||
end
|
||||
|
||||
|
@ -40,7 +48,7 @@ class TestGemCommandsPristineCommand < RubyGemTestCase
|
|||
|
||||
install_gem a
|
||||
|
||||
gem_bin = File.join @gemhome, 'gems', "#{a.full_name}", 'bin', 'foo'
|
||||
gem_bin = File.join @gemhome, 'gems', a.full_name, 'bin', 'foo'
|
||||
|
||||
FileUtils.rm gem_bin
|
||||
|
||||
|
@ -50,11 +58,12 @@ class TestGemCommandsPristineCommand < RubyGemTestCase
|
|||
@cmd.execute
|
||||
end
|
||||
|
||||
assert File.exist?(gem_bin)
|
||||
|
||||
out = @ui.output.split "\n"
|
||||
|
||||
assert_equal "Restoring gem(s) to pristine condition...", out.shift
|
||||
assert_equal "Restoring 1 file to #{a.full_name}...", out.shift
|
||||
assert_equal " #{gem_bin}", out.shift
|
||||
assert_equal "Restored #{a.full_name}", out.shift
|
||||
assert out.empty?, out.inspect
|
||||
end
|
||||
|
||||
|
|
|
@ -7,33 +7,18 @@ class TestGemCommandsQueryCommand < RubyGemTestCase
|
|||
def setup
|
||||
super
|
||||
|
||||
util_make_gems
|
||||
|
||||
@a2.summary = 'This is a lot of text. ' * 4
|
||||
|
||||
@cmd = Gem::Commands::QueryCommand.new
|
||||
|
||||
@si = util_setup_source_info_cache @a1, @a2, @pl1
|
||||
util_setup_fake_fetcher
|
||||
|
||||
@fetcher.data["#{@gem_repo}/Marshal.#{Gem.marshal_version}"] = proc do
|
||||
@si = util_setup_spec_fetcher @a1, @a2, @pl1
|
||||
|
||||
@fetcher.data["#{@gem_repo}Marshal.#{Gem.marshal_version}"] = proc do
|
||||
raise Gem::RemoteFetcher::FetchError
|
||||
end
|
||||
end
|
||||
|
||||
def test_execute
|
||||
cache = Gem::SourceInfoCache.cache
|
||||
cache.update
|
||||
cache.write_cache
|
||||
cache.reset_cache_data
|
||||
Gem::SourceInfoCache.reset
|
||||
|
||||
a2_name = @a2.full_name
|
||||
@fetcher.data["#{@gem_repo}/quick/latest_index.rz"] = util_zip a2_name
|
||||
@fetcher.data["#{@gem_repo}/quick/Marshal.#{Gem.marshal_version}/#{a2_name}.gemspec.rz"] = util_zip Marshal.dump(@a2)
|
||||
@fetcher.data["#{@gem_repo}/Marshal.#{Gem.marshal_version}"] =
|
||||
Marshal.dump @si
|
||||
|
||||
@cmd.handle_options %w[-r]
|
||||
|
||||
use_ui @ui do
|
||||
|
@ -44,10 +29,8 @@ class TestGemCommandsQueryCommand < RubyGemTestCase
|
|||
|
||||
*** REMOTE GEMS ***
|
||||
|
||||
Updating metadata for 1 gems from http://gems.example.com/
|
||||
.
|
||||
complete
|
||||
a (2)
|
||||
pl (1)
|
||||
EOF
|
||||
|
||||
assert_equal expected, @ui.output
|
||||
|
@ -55,21 +38,8 @@ a (2)
|
|||
end
|
||||
|
||||
def test_execute_all
|
||||
cache = Gem::SourceInfoCache.cache
|
||||
cache.update
|
||||
cache.write_cache
|
||||
cache.reset_cache_data
|
||||
Gem::SourceInfoCache.reset
|
||||
|
||||
a1_name = @a1.full_name
|
||||
a2_name = @a2.full_name
|
||||
@fetcher.data["#{@gem_repo}/quick/index.rz"] =
|
||||
util_zip [a1_name, a2_name].join("\n")
|
||||
@fetcher.data["#{@gem_repo}/quick/latest_index.rz"] = util_zip a2_name
|
||||
@fetcher.data["#{@gem_repo}/quick/Marshal.#{Gem.marshal_version}/#{a1_name}.gemspec.rz"] = util_zip Marshal.dump(@a1)
|
||||
@fetcher.data["#{@gem_repo}/quick/Marshal.#{Gem.marshal_version}/#{a2_name}.gemspec.rz"] = util_zip Marshal.dump(@a2)
|
||||
@fetcher.data["#{@gem_repo}/Marshal.#{Gem.marshal_version}"] =
|
||||
Marshal.dump @si
|
||||
|
||||
@cmd.handle_options %w[-r --all]
|
||||
|
||||
|
@ -81,10 +51,8 @@ a (2)
|
|||
|
||||
*** REMOTE GEMS ***
|
||||
|
||||
Updating metadata for 2 gems from http://gems.example.com/
|
||||
..
|
||||
complete
|
||||
a (2, 1)
|
||||
pl (1)
|
||||
EOF
|
||||
|
||||
assert_equal expected, @ui.output
|
||||
|
@ -92,6 +60,13 @@ a (2, 1)
|
|||
end
|
||||
|
||||
def test_execute_details
|
||||
@a2.summary = 'This is a lot of text. ' * 4
|
||||
@a2.authors = ['Abraham Lincoln', 'Hirohito']
|
||||
@a2.homepage = 'http://a.example.com/'
|
||||
@a2.rubyforge_project = 'rubygems'
|
||||
|
||||
@si = util_setup_spec_fetcher @a1, @a2, @pl1
|
||||
|
||||
@cmd.handle_options %w[-r -d]
|
||||
|
||||
use_ui @ui do
|
||||
|
@ -103,10 +78,17 @@ a (2, 1)
|
|||
*** REMOTE GEMS ***
|
||||
|
||||
a (2)
|
||||
Authors: Abraham Lincoln, Hirohito
|
||||
Rubyforge: http://rubyforge.org/projects/rubygems
|
||||
Homepage: http://a.example.com/
|
||||
|
||||
This is a lot of text. This is a lot of text. This is a lot of text.
|
||||
This is a lot of text.
|
||||
|
||||
pl (1)
|
||||
Author: A User
|
||||
Homepage: http://example.com
|
||||
|
||||
this is a summary
|
||||
EOF
|
||||
|
||||
|
@ -126,6 +108,7 @@ pl (1)
|
|||
assert_equal 0, e.exit_code
|
||||
|
||||
assert_equal "true\n", @ui.output
|
||||
|
||||
assert_equal '', @ui.error
|
||||
end
|
||||
|
||||
|
@ -189,6 +172,99 @@ pl (1)
|
|||
assert_equal 1, e.exit_code
|
||||
end
|
||||
|
||||
def test_execute_legacy
|
||||
Gem::SpecFetcher.fetcher = nil
|
||||
si = util_setup_source_info_cache @a1, @a2, @pl1
|
||||
|
||||
@fetcher.data["#{@gem_repo}yaml"] = YAML.dump si
|
||||
@fetcher.data["#{@gem_repo}Marshal.#{Gem.marshal_version}"] =
|
||||
si.dump
|
||||
|
||||
@fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"] = nil
|
||||
|
||||
@cmd.handle_options %w[-r]
|
||||
|
||||
use_ui @ui do
|
||||
@cmd.execute
|
||||
end
|
||||
|
||||
expected = <<-EOF
|
||||
|
||||
*** REMOTE GEMS ***
|
||||
|
||||
a (2)
|
||||
pl (1)
|
||||
EOF
|
||||
|
||||
assert_equal expected, @ui.output
|
||||
|
||||
expected = <<-EOF
|
||||
WARNING: RubyGems 1.2+ index not found for:
|
||||
\t#{@gem_repo}
|
||||
|
||||
RubyGems will revert to legacy indexes degrading performance.
|
||||
EOF
|
||||
|
||||
assert_equal expected, @ui.error
|
||||
end
|
||||
|
||||
def test_execute_local_details
|
||||
@a2.summary = 'This is a lot of text. ' * 4
|
||||
@a2.authors = ['Abraham Lincoln', 'Hirohito']
|
||||
@a2.homepage = 'http://a.example.com/'
|
||||
@a2.rubyforge_project = 'rubygems'
|
||||
|
||||
@cmd.handle_options %w[--local --details]
|
||||
|
||||
use_ui @ui do
|
||||
@cmd.execute
|
||||
end
|
||||
|
||||
expected = <<-EOF
|
||||
|
||||
*** LOCAL GEMS ***
|
||||
|
||||
a (2, 1)
|
||||
Author: A User
|
||||
Homepage: http://example.com
|
||||
Installed at (2): #{@gemhome}
|
||||
(1): #{@gemhome}
|
||||
|
||||
this is a summary
|
||||
|
||||
a_evil (9)
|
||||
Author: A User
|
||||
Homepage: http://example.com
|
||||
Installed at: #{@gemhome}
|
||||
|
||||
this is a summary
|
||||
|
||||
b (2)
|
||||
Author: A User
|
||||
Homepage: http://example.com
|
||||
Installed at: #{@gemhome}
|
||||
|
||||
this is a summary
|
||||
|
||||
c (1.2)
|
||||
Author: A User
|
||||
Homepage: http://example.com
|
||||
Installed at: #{@gemhome}
|
||||
|
||||
this is a summary
|
||||
|
||||
pl (1)
|
||||
Author: A User
|
||||
Homepage: http://example.com
|
||||
Installed at: #{@gemhome}
|
||||
|
||||
this is a summary
|
||||
EOF
|
||||
|
||||
assert_equal expected, @ui.output
|
||||
assert_equal '', @ui.error
|
||||
end
|
||||
|
||||
def test_execute_no_versions
|
||||
@cmd.handle_options %w[-r --no-versions]
|
||||
|
||||
|
|
|
@ -8,10 +8,12 @@ class TestGemCommandsSourcesCommand < RubyGemTestCase
|
|||
super
|
||||
|
||||
@cmd = Gem::Commands::SourcesCommand.new
|
||||
|
||||
@new_repo = "http://beta-gems.example.com"
|
||||
end
|
||||
|
||||
def test_execute
|
||||
util_setup_source_info_cache
|
||||
util_setup_spec_fetcher
|
||||
@cmd.handle_options []
|
||||
|
||||
use_ui @ui do
|
||||
|
@ -34,43 +36,49 @@ class TestGemCommandsSourcesCommand < RubyGemTestCase
|
|||
si = Gem::SourceIndex.new
|
||||
si.add_spec @a1
|
||||
|
||||
@fetcher.data["http://beta-gems.example.com/Marshal.#{@marshal_version}"] =
|
||||
si.dump
|
||||
specs = si.map do |_, spec|
|
||||
[spec.name, spec.version, spec.original_platform]
|
||||
end
|
||||
|
||||
@cmd.handle_options %w[--add http://beta-gems.example.com]
|
||||
specs_dump_gz = StringIO.new
|
||||
Zlib::GzipWriter.wrap specs_dump_gz do |io|
|
||||
Marshal.dump specs, io
|
||||
end
|
||||
|
||||
util_setup_source_info_cache
|
||||
@fetcher.data["#{@new_repo}/specs.#{@marshal_version}.gz"] =
|
||||
specs_dump_gz.string
|
||||
|
||||
@cmd.handle_options %W[--add #{@new_repo}]
|
||||
|
||||
util_setup_spec_fetcher
|
||||
|
||||
use_ui @ui do
|
||||
@cmd.execute
|
||||
end
|
||||
|
||||
assert_equal [@gem_repo, @new_repo], Gem.sources
|
||||
|
||||
expected = <<-EOF
|
||||
Bulk updating Gem source index for: http://beta-gems.example.com/
|
||||
http://beta-gems.example.com added to sources
|
||||
#{@new_repo} added to sources
|
||||
EOF
|
||||
|
||||
assert_equal expected, @ui.output
|
||||
assert_equal '', @ui.error
|
||||
|
||||
Gem::SourceInfoCache.cache.flush
|
||||
assert_equal %W[http://beta-gems.example.com #{@gem_repo}],
|
||||
Gem::SourceInfoCache.cache_data.keys.sort
|
||||
end
|
||||
|
||||
def test_execute_add_nonexistent_source
|
||||
util_setup_fake_fetcher
|
||||
|
||||
@fetcher.data["http://beta-gems.example.com/Marshal.#{@marshal_version}"] =
|
||||
proc do
|
||||
raise Gem::RemoteFetcher::FetchError, 'it died'
|
||||
end
|
||||
uri = "http://beta-gems.example.com/specs.#{@marshal_version}.gz"
|
||||
@fetcher.data[uri] = proc do
|
||||
raise Gem::RemoteFetcher::FetchError.new('it died', uri)
|
||||
end
|
||||
|
||||
Gem::RemoteFetcher.instance_variable_set :@fetcher, @fetcher
|
||||
Gem::RemoteFetcher.fetcher = @fetcher
|
||||
|
||||
@cmd.handle_options %w[--add http://beta-gems.example.com]
|
||||
|
||||
util_setup_source_info_cache
|
||||
util_setup_spec_fetcher
|
||||
|
||||
use_ui @ui do
|
||||
@cmd.execute
|
||||
|
@ -78,7 +86,7 @@ http://beta-gems.example.com added to sources
|
|||
|
||||
expected = <<-EOF
|
||||
Error fetching http://beta-gems.example.com:
|
||||
\tit died
|
||||
\tit died (#{uri})
|
||||
EOF
|
||||
|
||||
assert_equal expected, @ui.output
|
||||
|
@ -88,12 +96,14 @@ Error fetching http://beta-gems.example.com:
|
|||
def test_execute_add_bad_uri
|
||||
@cmd.handle_options %w[--add beta-gems.example.com]
|
||||
|
||||
util_setup_source_info_cache
|
||||
util_setup_spec_fetcher
|
||||
|
||||
use_ui @ui do
|
||||
@cmd.execute
|
||||
end
|
||||
|
||||
assert_equal [@gem_repo], Gem.sources
|
||||
|
||||
expected = <<-EOF
|
||||
beta-gems.example.com is not a URI
|
||||
EOF
|
||||
|
@ -102,6 +112,34 @@ beta-gems.example.com is not a URI
|
|||
assert_equal '', @ui.error
|
||||
end
|
||||
|
||||
def test_execute_add_legacy
|
||||
util_setup_fake_fetcher
|
||||
util_setup_source_info_cache
|
||||
|
||||
si = Gem::SourceIndex.new
|
||||
si.add_spec @a1
|
||||
|
||||
@fetcher.data["#{@new_repo}/yaml"] = ''
|
||||
|
||||
@cmd.handle_options %W[--add #{@new_repo}]
|
||||
|
||||
use_ui @ui do
|
||||
@cmd.execute
|
||||
end
|
||||
|
||||
assert_equal [@gem_repo], Gem.sources
|
||||
|
||||
expected = <<-EOF
|
||||
WARNING: RubyGems 1.2+ index not found for:
|
||||
\t#{@new_repo}
|
||||
|
||||
Will cause RubyGems to revert to legacy indexes, degrading performance.
|
||||
EOF
|
||||
|
||||
assert_equal "#{@new_repo} added to sources\n", @ui.output
|
||||
assert_equal expected, @ui.error
|
||||
end
|
||||
|
||||
def test_execute_clear_all
|
||||
@cmd.handle_options %w[--clear-all]
|
||||
|
||||
|
@ -116,11 +154,19 @@ beta-gems.example.com is not a URI
|
|||
assert File.exist?(cache.latest_system_cache_file),
|
||||
'latest system cache file'
|
||||
|
||||
util_setup_spec_fetcher
|
||||
|
||||
fetcher = Gem::SpecFetcher.fetcher
|
||||
|
||||
# HACK figure out how to force directory creation via fetcher
|
||||
#assert File.directory?(fetcher.dir), 'cache dir exists'
|
||||
|
||||
use_ui @ui do
|
||||
@cmd.execute
|
||||
end
|
||||
|
||||
expected = <<-EOF
|
||||
*** Removed specs cache ***
|
||||
*** Removed user source cache ***
|
||||
*** Removed latest user source cache ***
|
||||
*** Removed system source cache ***
|
||||
|
@ -135,12 +181,13 @@ beta-gems.example.com is not a URI
|
|||
assert !File.exist?(cache.latest_system_cache_file),
|
||||
'latest system cache file'
|
||||
|
||||
assert !File.exist?(fetcher.dir), 'cache dir removed'
|
||||
end
|
||||
|
||||
def test_execute_remove
|
||||
@cmd.handle_options %W[--remove #{@gem_repo}]
|
||||
|
||||
util_setup_source_info_cache
|
||||
util_setup_spec_fetcher
|
||||
|
||||
use_ui @ui do
|
||||
@cmd.execute
|
||||
|
@ -150,9 +197,6 @@ beta-gems.example.com is not a URI
|
|||
|
||||
assert_equal expected, @ui.output
|
||||
assert_equal '', @ui.error
|
||||
|
||||
Gem::SourceInfoCache.cache.flush
|
||||
assert_equal [], Gem::SourceInfoCache.cache_data.keys
|
||||
end
|
||||
|
||||
def test_execute_remove_no_network
|
||||
|
@ -160,7 +204,7 @@ beta-gems.example.com is not a URI
|
|||
|
||||
util_setup_fake_fetcher
|
||||
|
||||
@fetcher.data["#{@gem_repo}/Marshal.#{Gem.marshal_version}"] = proc do
|
||||
@fetcher.data["#{@gem_repo}Marshal.#{Gem.marshal_version}"] = proc do
|
||||
raise Gem::RemoteFetcher::FetchError
|
||||
end
|
||||
|
||||
|
@ -172,34 +216,60 @@ beta-gems.example.com is not a URI
|
|||
|
||||
assert_equal expected, @ui.output
|
||||
assert_equal '', @ui.error
|
||||
|
||||
Gem::SourceInfoCache.cache.flush
|
||||
assert_equal [], Gem::SourceInfoCache.cache_data.keys
|
||||
end
|
||||
|
||||
def test_execute_update
|
||||
@cmd.handle_options %w[--update]
|
||||
|
||||
util_setup_fake_fetcher
|
||||
source_index = util_setup_spec_fetcher @a1
|
||||
|
||||
specs = source_index.map do |name, spec|
|
||||
[spec.name, spec.version, spec.original_platform]
|
||||
end
|
||||
|
||||
@fetcher.data["#{@gem_repo}specs.#{Gem.marshal_version}.gz"] =
|
||||
util_gzip Marshal.dump(specs)
|
||||
|
||||
latest_specs = source_index.latest_specs.map do |spec|
|
||||
[spec.name, spec.version, spec.original_platform]
|
||||
end
|
||||
|
||||
@fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"] =
|
||||
util_gzip Marshal.dump(latest_specs)
|
||||
|
||||
use_ui @ui do
|
||||
@cmd.execute
|
||||
end
|
||||
|
||||
assert_equal "source cache successfully updated\n", @ui.output
|
||||
assert_equal '', @ui.error
|
||||
end
|
||||
|
||||
def test_execute_update_legacy
|
||||
@cmd.handle_options %w[--update]
|
||||
|
||||
util_setup_fake_fetcher
|
||||
util_setup_source_info_cache
|
||||
Gem::SourceInfoCache.reset
|
||||
|
||||
util_setup_fake_fetcher
|
||||
si = Gem::SourceIndex.new
|
||||
si.add_spec @a1
|
||||
@fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] = si.dump
|
||||
@fetcher.data["#{@gem_repo}yaml"] = YAML.dump si
|
||||
@fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}"] = si.dump
|
||||
|
||||
use_ui @ui do
|
||||
@cmd.execute
|
||||
end
|
||||
|
||||
expected = <<-EOF
|
||||
Bulk updating Gem source index for: #{@gem_repo}/
|
||||
Bulk updating Gem source index for: #{@gem_repo}
|
||||
source cache successfully updated
|
||||
EOF
|
||||
|
||||
assert_equal expected, @ui.output
|
||||
assert_equal '', @ui.error
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -74,7 +74,10 @@ class TestGemCommandsSpecificationCommand < RubyGemTestCase
|
|||
def test_execute_remote
|
||||
foo = quick_gem 'foo'
|
||||
|
||||
util_setup_source_info_cache foo
|
||||
@fetcher = Gem::FakeFetcher.new
|
||||
Gem::RemoteFetcher.fetcher = @fetcher
|
||||
|
||||
util_setup_spec_fetcher foo
|
||||
|
||||
FileUtils.rm File.join(@gemhome, 'specifications',
|
||||
"#{foo.full_name}.gemspec")
|
||||
|
|
39
test/rubygems/test_gem_commands_stale_command.rb
Normal file
39
test/rubygems/test_gem_commands_stale_command.rb
Normal file
|
@ -0,0 +1,39 @@
|
|||
require 'test/unit'
|
||||
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
|
||||
require 'rubygems/commands/stale_command'
|
||||
|
||||
class TestGemCommandsStaleCommand < RubyGemTestCase
|
||||
|
||||
def setup
|
||||
super
|
||||
@cmd = Gem::Commands::StaleCommand.new
|
||||
end
|
||||
|
||||
def test_execute_sorts
|
||||
files = %w[lib/foo_bar.rb Rakefile]
|
||||
foo_bar = quick_gem 'foo_bar' do |gem|
|
||||
gem.files = files
|
||||
end
|
||||
bar_baz = quick_gem 'bar_baz' do |gem|
|
||||
gem.files = files
|
||||
end
|
||||
|
||||
files.each do |file|
|
||||
filename = bar_baz.full_gem_path + "/#{file}"
|
||||
FileUtils.mkdir_p(File.dirname(filename))
|
||||
FileUtils.touch(filename, :mtime => Time.now)
|
||||
|
||||
filename = foo_bar.full_gem_path + "/#{file}"
|
||||
FileUtils.mkdir_p(File.dirname(filename))
|
||||
FileUtils.touch(filename, :mtime => Time.now - 86400)
|
||||
end
|
||||
|
||||
use_ui @ui do
|
||||
@cmd.execute
|
||||
end
|
||||
lines = @ui.output.split("\n")
|
||||
assert_equal("#{foo_bar.name}-#{foo_bar.version}", lines[0].split.first)
|
||||
assert_equal("#{bar_baz.name}-#{bar_baz.version}", lines[1].split.first)
|
||||
end
|
||||
|
||||
end
|
|
@ -14,14 +14,16 @@ class TestGemCommandsUpdateCommand < RubyGemTestCase
|
|||
@a1_path = File.join @gemhome, 'cache', "#{@a1.full_name}.gem"
|
||||
@a2_path = File.join @gemhome, 'cache', "#{@a2.full_name}.gem"
|
||||
|
||||
@fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] =
|
||||
@source_index.dump
|
||||
@fetcher.data["#{@gem_repo}/gems/#{@a1.full_name}.gem"] = read_binary @a1_path
|
||||
@fetcher.data["#{@gem_repo}/gems/#{@a2.full_name}.gem"] = read_binary @a2_path
|
||||
util_setup_spec_fetcher @a1, @a2
|
||||
|
||||
@fetcher.data["#{@gem_repo}gems/#{@a1.full_name}.gem"] =
|
||||
read_binary @a1_path
|
||||
@fetcher.data["#{@gem_repo}gems/#{@a2.full_name}.gem"] =
|
||||
read_binary @a2_path
|
||||
end
|
||||
|
||||
def test_execute
|
||||
util_remove_gems
|
||||
util_clear_gems
|
||||
|
||||
Gem::Installer.new(@a1_path).install
|
||||
|
||||
|
@ -33,7 +35,6 @@ class TestGemCommandsUpdateCommand < RubyGemTestCase
|
|||
|
||||
out = @ui.output.split "\n"
|
||||
assert_equal "Updating installed gems", out.shift
|
||||
assert_match %r|Bulk updating|, out.shift
|
||||
assert_equal "Updating #{@a2.name}", out.shift
|
||||
assert_equal "Successfully installed #{@a2.full_name}", out.shift
|
||||
assert_equal "Gems updated: #{@a2.name}", out.shift
|
||||
|
@ -73,16 +74,15 @@ class TestGemCommandsUpdateCommand < RubyGemTestCase
|
|||
util_build_gem @a2
|
||||
util_build_gem @c2
|
||||
|
||||
@fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] =
|
||||
@source_index.dump
|
||||
@fetcher.data["#{@gem_repo}/gems/#{@a1.full_name}.gem"] = read_binary @a1_path
|
||||
@fetcher.data["#{@gem_repo}/gems/#{@a2.full_name}.gem"] = read_binary @a2_path
|
||||
@fetcher.data["#{@gem_repo}/gems/#{@b2.full_name}.gem"] = read_binary @b2_path
|
||||
@fetcher.data["#{@gem_repo}/gems/#{@c1_2.full_name}.gem"] =
|
||||
@fetcher.data["#{@gem_repo}gems/#{@a1.full_name}.gem"] = read_binary @a1_path
|
||||
@fetcher.data["#{@gem_repo}gems/#{@a2.full_name}.gem"] = read_binary @a2_path
|
||||
@fetcher.data["#{@gem_repo}gems/#{@b2.full_name}.gem"] = read_binary @b2_path
|
||||
@fetcher.data["#{@gem_repo}gems/#{@c1_2.full_name}.gem"] =
|
||||
read_binary @c1_2_path
|
||||
@fetcher.data["#{@gem_repo}/gems/#{@c2.full_name}.gem"] = read_binary @c2_path
|
||||
@fetcher.data["#{@gem_repo}gems/#{@c2.full_name}.gem"] = read_binary @c2_path
|
||||
|
||||
util_remove_gems
|
||||
util_setup_spec_fetcher @a1, @a2, @b2, @c1_2, @c2
|
||||
util_clear_gems
|
||||
|
||||
Gem::Installer.new(@c1_2_path).install
|
||||
Gem::Installer.new(@a1_path).install
|
||||
|
@ -95,9 +95,7 @@ class TestGemCommandsUpdateCommand < RubyGemTestCase
|
|||
|
||||
out = @ui.output.split "\n"
|
||||
assert_equal "Updating installed gems", out.shift
|
||||
assert_match %r|Bulk updating|, out.shift
|
||||
assert_equal "Updating #{@a2.name}", out.shift
|
||||
assert_match %r|Bulk updating|, out.shift
|
||||
assert_equal "Successfully installed #{@c2.full_name}", out.shift
|
||||
assert_equal "Successfully installed #{@b2.full_name}", out.shift
|
||||
assert_equal "Successfully installed #{@a2.full_name}", out.shift
|
||||
|
@ -108,7 +106,7 @@ class TestGemCommandsUpdateCommand < RubyGemTestCase
|
|||
end
|
||||
|
||||
def test_execute_named
|
||||
util_remove_gems
|
||||
util_clear_gems
|
||||
|
||||
Gem::Installer.new(@a1_path).install
|
||||
|
||||
|
@ -120,7 +118,6 @@ class TestGemCommandsUpdateCommand < RubyGemTestCase
|
|||
|
||||
out = @ui.output.split "\n"
|
||||
assert_equal "Updating installed gems", out.shift
|
||||
assert_match %r|Bulk updating|, out.shift
|
||||
assert_equal "Updating #{@a2.name}", out.shift
|
||||
assert_equal "Successfully installed #{@a2.full_name}", out.shift
|
||||
assert_equal "Gems updated: #{@a2.name}", out.shift
|
||||
|
@ -129,7 +126,7 @@ class TestGemCommandsUpdateCommand < RubyGemTestCase
|
|||
end
|
||||
|
||||
def test_execute_named_up_to_date
|
||||
util_remove_gems
|
||||
util_clear_gems
|
||||
|
||||
Gem::Installer.new(@a2_path).install
|
||||
|
||||
|
@ -141,14 +138,13 @@ class TestGemCommandsUpdateCommand < RubyGemTestCase
|
|||
|
||||
out = @ui.output.split "\n"
|
||||
assert_equal "Updating installed gems", out.shift
|
||||
assert_match %r|Bulk updating|, out.shift
|
||||
assert_equal "Nothing to update", out.shift
|
||||
|
||||
assert out.empty?, out.inspect
|
||||
end
|
||||
|
||||
def test_execute_up_to_date
|
||||
util_remove_gems
|
||||
util_clear_gems
|
||||
|
||||
Gem::Installer.new(@a2_path).install
|
||||
|
||||
|
@ -160,16 +156,10 @@ class TestGemCommandsUpdateCommand < RubyGemTestCase
|
|||
|
||||
out = @ui.output.split "\n"
|
||||
assert_equal "Updating installed gems", out.shift
|
||||
assert_match %r|Bulk updating|, out.shift
|
||||
assert_equal "Nothing to update", out.shift
|
||||
|
||||
assert out.empty?, out.inspect
|
||||
end
|
||||
|
||||
def util_remove_gems
|
||||
FileUtils.rm_r File.join(@gemhome, 'gems')
|
||||
FileUtils.rm_r File.join(@gemhome, 'specifications')
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -17,9 +17,23 @@ class TestGemConfigFile < RubyGemTestCase
|
|||
@temp_conf = File.join @tempdir, '.gemrc'
|
||||
|
||||
@cfg_args = %W[--config-file #{@temp_conf}]
|
||||
|
||||
@orig_SYSTEM_WIDE_CONFIG_FILE = Gem::ConfigFile::SYSTEM_WIDE_CONFIG_FILE
|
||||
Gem::ConfigFile.send :remove_const, :SYSTEM_WIDE_CONFIG_FILE
|
||||
Gem::ConfigFile.send :const_set, :SYSTEM_WIDE_CONFIG_FILE,
|
||||
File.join(@tempdir, 'system-gemrc')
|
||||
|
||||
util_config_file
|
||||
end
|
||||
|
||||
def teardown
|
||||
Gem::ConfigFile.send :remove_const, :SYSTEM_WIDE_CONFIG_FILE
|
||||
Gem::ConfigFile.send :const_set, :SYSTEM_WIDE_CONFIG_FILE,
|
||||
@orig_SYSTEM_WIDE_CONFIG_FILE
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
def test_initialize
|
||||
assert_equal @temp_conf, @cfg.config_file_name
|
||||
|
||||
|
@ -28,7 +42,7 @@ class TestGemConfigFile < RubyGemTestCase
|
|||
assert_equal false, @cfg.benchmark
|
||||
assert_equal Gem::ConfigFile::DEFAULT_BULK_THRESHOLD, @cfg.bulk_threshold
|
||||
assert_equal true, @cfg.verbose
|
||||
assert_equal %w[http://gems.example.com], Gem.sources
|
||||
assert_equal [@gem_repo], Gem.sources
|
||||
|
||||
File.open @temp_conf, 'w' do |fp|
|
||||
fp.puts ":backtrace: true"
|
||||
|
@ -202,6 +216,23 @@ class TestGemConfigFile < RubyGemTestCase
|
|||
assert_equal %w[http://even-more-gems.example.com], Gem.sources
|
||||
end
|
||||
|
||||
def test_global_config_file
|
||||
File.open(@temp_conf, 'w') do |fp|
|
||||
fp.puts ":backtrace: true"
|
||||
end
|
||||
|
||||
File.open(File.join(Gem::ConfigFile::SYSTEM_WIDE_CONFIG_FILE),
|
||||
'w') do |fp|
|
||||
fp.puts ":backtrace: false"
|
||||
fp.puts ":bulk_threshold: 2048"
|
||||
end
|
||||
|
||||
util_config_file
|
||||
|
||||
assert_equal 2048, @cfg.bulk_threshold
|
||||
assert @cfg.backtrace
|
||||
end
|
||||
|
||||
def util_config_file(args = @cfg_args)
|
||||
@cfg = Gem::ConfigFile.new args
|
||||
end
|
||||
|
|
|
@ -60,6 +60,21 @@ class TestGemDependency < RubyGemTestCase
|
|||
assert_equal Gem::Requirement.new('= 2'), dep.version_requirements
|
||||
end
|
||||
|
||||
def test_initialize_with_type
|
||||
dep = Gem::Dependency.new("pkg", [], :development)
|
||||
assert_equal(:development, dep.type)
|
||||
end
|
||||
|
||||
def test_type_is_runtime_by_default
|
||||
assert_equal(:runtime, Gem::Dependency.new("pkg", []).type)
|
||||
end
|
||||
|
||||
def test_type_is_restricted
|
||||
assert_raise(ArgumentError) do
|
||||
Gem::Dependency.new("pkg", [:sometimes])
|
||||
end
|
||||
end
|
||||
|
||||
def test_equals2
|
||||
assert_equal @pkg1_0, @pkg1_0.dup
|
||||
assert_equal @pkg1_0.dup, @pkg1_0
|
||||
|
@ -74,6 +89,36 @@ class TestGemDependency < RubyGemTestCase
|
|||
assert_not_equal Object.new, @pkg1_0
|
||||
end
|
||||
|
||||
def test_equals2_type
|
||||
runtime = Gem::Dependency.new("pkg", [])
|
||||
development = Gem::Dependency.new("pkg", [], :development)
|
||||
|
||||
assert_not_equal(runtime, development)
|
||||
end
|
||||
|
||||
def test_equals_tilde
|
||||
def dep(name, version)
|
||||
Gem::Dependency.new name, version
|
||||
end
|
||||
|
||||
a0 = dep 'a', '0'
|
||||
a1 = dep 'a', '1'
|
||||
b0 = dep 'b', '0'
|
||||
|
||||
pa0 = dep 'a', '>= 0'
|
||||
pa0r = dep(/a/, '>= 0')
|
||||
pab0r = dep(/a|b/, '>= 0')
|
||||
|
||||
assert((a0 =~ a0), 'match self')
|
||||
assert((pa0 =~ a0), 'match version exact')
|
||||
assert((pa0 =~ a1), 'match version')
|
||||
assert((pa0r =~ a0), 'match regex simple')
|
||||
assert((pab0r =~ a0), 'match regex complex')
|
||||
|
||||
assert(!(pa0r =~ b0), 'fail match regex')
|
||||
assert(!(pa0r =~ Object.new), 'fail match Object')
|
||||
end
|
||||
|
||||
def test_hash
|
||||
assert_equal @pkg1_0.hash, @pkg1_0.dup.hash
|
||||
assert_equal @pkg1_0.dup.hash, @pkg1_0.hash
|
||||
|
@ -85,5 +130,11 @@ class TestGemDependency < RubyGemTestCase
|
|||
assert_not_equal @oth1_0.hash, @pkg1_0.hash, "names different"
|
||||
end
|
||||
|
||||
def test_hash_type
|
||||
runtime = Gem::Dependency.new("pkg", [])
|
||||
development = Gem::Dependency.new("pkg", [], :development)
|
||||
|
||||
assert_not_equal(runtime.hash, development.hash)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -15,8 +15,12 @@ class TestGemDependencyInstaller < RubyGemTestCase
|
|||
fp.puts "#!/usr/bin/ruby"
|
||||
end
|
||||
@a1, @a1_gem = util_gem 'a', '1' do |s| s.executables << 'a_bin' end
|
||||
@aa1, @aa1_gem = util_gem 'aa', '1'
|
||||
|
||||
@b1, @b1_gem = util_gem 'b', '1' do |s| s.add_dependency 'a' end
|
||||
@b1, @b1_gem = util_gem 'b', '1' do |s|
|
||||
s.add_dependency 'a'
|
||||
s.add_development_dependency 'aa'
|
||||
end
|
||||
|
||||
@d1, @d1_gem = util_gem 'd', '1'
|
||||
@d2, @d2_gem = util_gem 'd', '2'
|
||||
|
@ -38,15 +42,13 @@ class TestGemDependencyInstaller < RubyGemTestCase
|
|||
|
||||
@z1, @z1_gem = util_gem 'z', '1' do |s| s.add_dependency 'y' end
|
||||
|
||||
si = util_setup_source_info_cache @a1, @b1, @d1, @d2, @x1_m, @x1_o, @w1,
|
||||
@y1, @y1_1_p, @z1
|
||||
@fetcher = Gem::FakeFetcher.new
|
||||
Gem::RemoteFetcher.fetcher = @fetcher
|
||||
|
||||
@fetcher = FakeFetcher.new
|
||||
Gem::RemoteFetcher.instance_variable_set :@fetcher, @fetcher
|
||||
@fetcher.uri = URI.parse 'http://gems.example.com'
|
||||
@fetcher.data['http://gems.example.com/gems/yaml'] = si.to_yaml
|
||||
si = util_setup_spec_fetcher @a1, @b1, @d1, @d2, @x1_m, @x1_o, @w1, @y1,
|
||||
@y1_1_p, @z1
|
||||
|
||||
FileUtils.rm_rf File.join(@gemhome, 'gems')
|
||||
util_clear_gems
|
||||
end
|
||||
|
||||
def test_install
|
||||
|
@ -64,6 +66,52 @@ class TestGemDependencyInstaller < RubyGemTestCase
|
|||
assert_equal [@a1], inst.installed_gems
|
||||
end
|
||||
|
||||
def test_install_cache_dir
|
||||
FileUtils.mv @a1_gem, @tempdir
|
||||
FileUtils.mv @b1_gem, @tempdir
|
||||
inst = nil
|
||||
|
||||
Dir.chdir @tempdir do
|
||||
inst = Gem::DependencyInstaller.new :cache_dir => @tempdir
|
||||
inst.install 'b'
|
||||
end
|
||||
|
||||
assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
|
||||
|
||||
assert File.exist?(File.join(@tempdir, 'cache', "#{@a1.full_name}.gem"))
|
||||
assert File.exist?(File.join(@tempdir, 'cache', "#{@b1.full_name}.gem"))
|
||||
end
|
||||
|
||||
def test_install_dependencies_satisfied
|
||||
a2, a2_gem = util_gem 'a', '2'
|
||||
|
||||
FileUtils.rm_rf File.join(@gemhome, 'gems')
|
||||
Gem.source_index.refresh!
|
||||
|
||||
FileUtils.mv @a1_gem, @tempdir
|
||||
FileUtils.mv a2_gem, @tempdir # not in index
|
||||
FileUtils.mv @b1_gem, @tempdir
|
||||
inst = nil
|
||||
|
||||
Dir.chdir @tempdir do
|
||||
inst = Gem::DependencyInstaller.new
|
||||
inst.install 'a-2'
|
||||
end
|
||||
|
||||
FileUtils.rm File.join(@tempdir, "#{a2.full_name}.gem")
|
||||
|
||||
Dir.chdir @tempdir do
|
||||
inst = Gem::DependencyInstaller.new
|
||||
inst.install 'b'
|
||||
end
|
||||
|
||||
installed = Gem::SourceIndex.from_installed_gems.map { |n,s| s.full_name }
|
||||
|
||||
assert_equal %w[a-2 b-1], installed.sort
|
||||
|
||||
assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
|
||||
end
|
||||
|
||||
def test_install_dependency
|
||||
FileUtils.mv @a1_gem, @tempdir
|
||||
FileUtils.mv @b1_gem, @tempdir
|
||||
|
@ -77,6 +125,20 @@ class TestGemDependencyInstaller < RubyGemTestCase
|
|||
assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name }
|
||||
end
|
||||
|
||||
def test_install_dependency_development
|
||||
FileUtils.mv @a1_gem, @tempdir
|
||||
FileUtils.mv @aa1_gem, @tempdir
|
||||
FileUtils.mv @b1_gem, @tempdir
|
||||
inst = nil
|
||||
|
||||
Dir.chdir @tempdir do
|
||||
inst = Gem::DependencyInstaller.new(:development => true)
|
||||
inst.install 'b'
|
||||
end
|
||||
|
||||
assert_equal %w[a-1 aa-1 b-1], inst.installed_gems.map { |s| s.full_name }
|
||||
end
|
||||
|
||||
def test_install_dependency_existing
|
||||
Gem::Installer.new(@a1_gem).install
|
||||
FileUtils.mv @a1_gem, @tempdir
|
||||
|
@ -177,7 +239,7 @@ class TestGemDependencyInstaller < RubyGemTestCase
|
|||
|
||||
def test_install_force
|
||||
FileUtils.mv @b1_gem, @tempdir
|
||||
si = util_setup_source_info_cache @b1
|
||||
si = util_setup_spec_fetcher @b1
|
||||
@fetcher.data['http://gems.example.com/gems/yaml'] = si.to_yaml
|
||||
inst = nil
|
||||
|
||||
|
@ -249,8 +311,6 @@ class TestGemDependencyInstaller < RubyGemTestCase
|
|||
end
|
||||
|
||||
def test_install_domain_both_no_network
|
||||
Gem::SourceInfoCache.instance_variable_set :@cache, nil
|
||||
|
||||
@fetcher.data["http://gems.example.com/gems/Marshal.#{@marshal_version}"] =
|
||||
proc do
|
||||
raise Gem::RemoteFetcher::FetchError
|
||||
|
@ -272,12 +332,14 @@ class TestGemDependencyInstaller < RubyGemTestCase
|
|||
FileUtils.mv @b1_gem, @tempdir
|
||||
inst = nil
|
||||
|
||||
Gem.source_index.gems.delete @a1.full_name
|
||||
|
||||
Dir.chdir @tempdir do
|
||||
e = assert_raise Gem::InstallError do
|
||||
inst = Gem::DependencyInstaller.new :domain => :local
|
||||
inst.install 'b'
|
||||
end
|
||||
assert_equal 'b requires a (>= 0)', e.message
|
||||
assert_equal 'b requires a (>= 0, runtime)', e.message
|
||||
end
|
||||
|
||||
assert_equal [], inst.installed_gems.map { |s| s.full_name }
|
||||
|
@ -297,6 +359,30 @@ class TestGemDependencyInstaller < RubyGemTestCase
|
|||
assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name }
|
||||
end
|
||||
|
||||
def test_install_dual_repository
|
||||
FileUtils.mv @a1_gem, @tempdir
|
||||
FileUtils.mv @b1_gem, @tempdir
|
||||
inst = nil
|
||||
|
||||
gemhome2 = "#{@gemhome}2"
|
||||
|
||||
Dir.chdir @tempdir do
|
||||
inst = Gem::DependencyInstaller.new :install_dir => gemhome2
|
||||
inst.install 'a'
|
||||
end
|
||||
|
||||
ENV['GEM_HOME'] = @gemhome
|
||||
ENV['GEM_PATH'] = [@gemhome, gemhome2].join ':'
|
||||
Gem.clear_paths
|
||||
|
||||
Dir.chdir @tempdir do
|
||||
inst = Gem::DependencyInstaller.new
|
||||
inst.install 'b'
|
||||
end
|
||||
|
||||
assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name }
|
||||
end
|
||||
|
||||
def test_install_remote
|
||||
a1_data = nil
|
||||
File.open @a1_gem, 'rb' do |fp|
|
||||
|
@ -337,7 +423,9 @@ class TestGemDependencyInstaller < RubyGemTestCase
|
|||
s.platform = Gem::Platform.new %w[cpu other_platform 1]
|
||||
end
|
||||
|
||||
si = util_setup_source_info_cache @a1, a2_o
|
||||
util_clear_gems
|
||||
|
||||
si = util_setup_spec_fetcher @a1, a2_o
|
||||
|
||||
@fetcher.data['http://gems.example.com/gems/yaml'] = si.to_yaml
|
||||
|
||||
|
@ -439,7 +527,7 @@ class TestGemDependencyInstaller < RubyGemTestCase
|
|||
inst = Gem::DependencyInstaller.new
|
||||
dep = Gem::Dependency.new 'b', '>= 0'
|
||||
|
||||
assert_equal [[@b1, 'http://gems.example.com']],
|
||||
assert_equal [[@b1, @gem_repo]],
|
||||
inst.find_gems_with_sources(dep)
|
||||
end
|
||||
|
||||
|
@ -456,7 +544,7 @@ class TestGemDependencyInstaller < RubyGemTestCase
|
|||
assert_equal 2, gems.length
|
||||
remote = gems.first
|
||||
assert_equal 'a-1', remote.first.full_name, 'remote spec'
|
||||
assert_equal 'http://gems.example.com', remote.last, 'remote path'
|
||||
assert_equal @gem_repo, remote.last, 'remote path'
|
||||
|
||||
local = gems.last
|
||||
assert_equal 'a-1', local.first.full_name, 'local spec'
|
||||
|
@ -476,12 +564,9 @@ class TestGemDependencyInstaller < RubyGemTestCase
|
|||
b2, = util_gem 'b', '2'
|
||||
c1, = util_gem 'c', '1' do |s| s.add_dependency 'b' end
|
||||
|
||||
si = util_setup_source_info_cache @a1, @b1, b2, c1
|
||||
util_clear_gems
|
||||
|
||||
@fetcher = FakeFetcher.new
|
||||
Gem::RemoteFetcher.instance_variable_set :@fetcher, @fetcher
|
||||
@fetcher.uri = URI.parse 'http://gems.example.com'
|
||||
@fetcher.data['http://gems.example.com/gems/yaml'] = si.to_yaml
|
||||
si = util_setup_spec_fetcher @a1, @b1, b2, c1
|
||||
|
||||
inst = Gem::DependencyInstaller.new
|
||||
inst.find_spec_by_name_and_version 'c'
|
||||
|
@ -512,12 +597,9 @@ class TestGemDependencyInstaller < RubyGemTestCase
|
|||
def test_gather_dependencies_old_required
|
||||
e1, = util_gem 'e', '1' do |s| s.add_dependency 'd', '= 1' end
|
||||
|
||||
si = util_setup_source_info_cache @d1, @d2, e1
|
||||
util_clear_gems
|
||||
|
||||
@fetcher = FakeFetcher.new
|
||||
Gem::RemoteFetcher.instance_variable_set :@fetcher, @fetcher
|
||||
@fetcher.uri = URI.parse 'http://gems.example.com'
|
||||
@fetcher.data['http://gems.example.com/gems/yaml'] = si.to_yaml
|
||||
si = util_setup_spec_fetcher @d1, @d2, e1
|
||||
|
||||
inst = Gem::DependencyInstaller.new
|
||||
inst.find_spec_by_name_and_version 'e'
|
||||
|
@ -525,5 +607,6 @@ class TestGemDependencyInstaller < RubyGemTestCase
|
|||
|
||||
assert_equal %w[d-1 e-1], inst.gems_to_install.map { |s| s.full_name }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -28,7 +28,10 @@ class TestGemGemPathSearcher < RubyGemTestCase
|
|||
@bar1 = quick_gem 'bar', '0.1'
|
||||
@bar2 = quick_gem 'bar', '0.2'
|
||||
|
||||
Gem.source_index = util_setup_source_info_cache @foo1, @foo2, @bar1, @bar2
|
||||
@fetcher = Gem::FakeFetcher.new
|
||||
Gem::RemoteFetcher.fetcher = @fetcher
|
||||
|
||||
Gem.source_index = util_setup_spec_fetcher @foo1, @foo2, @bar1, @bar2
|
||||
|
||||
@gps = Gem::GemPathSearcher.new
|
||||
end
|
||||
|
|
|
@ -20,6 +20,10 @@ class TestGemIndexer < RubyGemTestCase
|
|||
|
||||
util_make_gems
|
||||
|
||||
@d2_0 = quick_gem 'd', '2.0'
|
||||
write_file File.join(*%W[gems #{@d2_0.original_name} lib code.rb]) do end
|
||||
util_build_gem @d2_0
|
||||
|
||||
gems = File.join(@tempdir, 'gems')
|
||||
FileUtils.mkdir_p gems
|
||||
cache_gems = File.join @gemhome, 'cache', '*.gem'
|
||||
|
@ -39,10 +43,10 @@ class TestGemIndexer < RubyGemTestCase
|
|||
@indexer.generate_index
|
||||
end
|
||||
|
||||
assert File.exist?(File.join(@tempdir, 'yaml'))
|
||||
assert File.exist?(File.join(@tempdir, 'yaml.Z'))
|
||||
assert File.exist?(File.join(@tempdir, "Marshal.#{@marshal_version}"))
|
||||
assert File.exist?(File.join(@tempdir, "Marshal.#{@marshal_version}.Z"))
|
||||
assert_indexed @tempdir, 'yaml'
|
||||
assert_indexed @tempdir, 'yaml.Z'
|
||||
assert_indexed @tempdir, "Marshal.#{@marshal_version}"
|
||||
assert_indexed @tempdir, "Marshal.#{@marshal_version}.Z"
|
||||
|
||||
quickdir = File.join @tempdir, 'quick'
|
||||
marshal_quickdir = File.join quickdir, "Marshal.#{@marshal_version}"
|
||||
|
@ -53,10 +57,33 @@ class TestGemIndexer < RubyGemTestCase
|
|||
assert_indexed quickdir, "index"
|
||||
assert_indexed quickdir, "index.rz"
|
||||
|
||||
quick_index = File.read File.join(quickdir, 'index')
|
||||
expected = <<-EOF
|
||||
a-1
|
||||
a-2
|
||||
a_evil-9
|
||||
b-2
|
||||
c-1.2
|
||||
d-2.0
|
||||
pl-1-i386-linux
|
||||
EOF
|
||||
|
||||
assert_equal expected, quick_index
|
||||
|
||||
assert_indexed quickdir, "latest_index"
|
||||
assert_indexed quickdir, "latest_index.rz"
|
||||
|
||||
assert_no_match %r|a-1|, File.read(File.join(quickdir, 'latest_index'))
|
||||
latest_quick_index = File.read File.join(quickdir, 'latest_index')
|
||||
expected = <<-EOF
|
||||
a-2
|
||||
a_evil-9
|
||||
b-2
|
||||
c-1.2
|
||||
d-2.0
|
||||
pl-1-i386-linux
|
||||
EOF
|
||||
|
||||
assert_equal expected, latest_quick_index
|
||||
|
||||
assert_indexed quickdir, "#{@a1.full_name}.gemspec.rz"
|
||||
assert_indexed quickdir, "#{@a2.full_name}.gemspec.rz"
|
||||
|
@ -64,13 +91,19 @@ class TestGemIndexer < RubyGemTestCase
|
|||
assert_indexed quickdir, "#{@c1_2.full_name}.gemspec.rz"
|
||||
|
||||
assert_indexed quickdir, "#{@pl1.original_name}.gemspec.rz"
|
||||
deny_indexed quickdir, "#{@pl1.full_name}.gemspec.rz"
|
||||
refute_indexed quickdir, "#{@pl1.full_name}.gemspec.rz"
|
||||
|
||||
assert_indexed marshal_quickdir, "#{@a1.full_name}.gemspec.rz"
|
||||
assert_indexed marshal_quickdir, "#{@a2.full_name}.gemspec.rz"
|
||||
|
||||
deny_indexed quickdir, "#{@c1_2.full_name}.gemspec"
|
||||
deny_indexed marshal_quickdir, "#{@c1_2.full_name}.gemspec"
|
||||
refute_indexed quickdir, "#{@c1_2.full_name}.gemspec"
|
||||
refute_indexed marshal_quickdir, "#{@c1_2.full_name}.gemspec"
|
||||
|
||||
assert_indexed @tempdir, "specs.#{@marshal_version}"
|
||||
assert_indexed @tempdir, "specs.#{@marshal_version}.gz"
|
||||
|
||||
assert_indexed @tempdir, "latest_specs.#{@marshal_version}"
|
||||
assert_indexed @tempdir, "latest_specs.#{@marshal_version}.gz"
|
||||
end
|
||||
|
||||
def test_generate_index_ui
|
||||
|
@ -79,28 +112,37 @@ class TestGemIndexer < RubyGemTestCase
|
|||
end
|
||||
|
||||
expected = <<-EOF
|
||||
Generating index for 6 gems in #{@tempdir}
|
||||
......
|
||||
Loading 7 gems from #{@tempdir}
|
||||
.......
|
||||
Loaded all gems
|
||||
Generating master indexes (this may take a while)
|
||||
Generating quick index gemspecs for 7 gems
|
||||
.......
|
||||
Complete
|
||||
Generating specs index
|
||||
Generating latest specs index
|
||||
Generating quick index
|
||||
Generating latest index
|
||||
Generating Marshal master index
|
||||
Generating YAML master index for 7 gems (this may take a while)
|
||||
.......
|
||||
Complete
|
||||
Compressing indicies
|
||||
EOF
|
||||
|
||||
assert_equal expected, @ui.output
|
||||
assert_equal '', @ui.error
|
||||
end
|
||||
|
||||
def test_generate_index_contents
|
||||
def test_generate_index_master
|
||||
use_ui @ui do
|
||||
@indexer.generate_index
|
||||
end
|
||||
|
||||
yaml_path = File.join(@tempdir, 'yaml')
|
||||
dump_path = File.join(@tempdir, "Marshal.#{@marshal_version}")
|
||||
yaml_path = File.join @tempdir, 'yaml'
|
||||
dump_path = File.join @tempdir, "Marshal.#{@marshal_version}"
|
||||
|
||||
yaml_index = YAML.load_file(yaml_path)
|
||||
dump_str = nil
|
||||
File.open dump_path, 'rb' do |fp| dump_str = fp.read end
|
||||
dump_index = Marshal.load dump_str
|
||||
yaml_index = YAML.load_file yaml_path
|
||||
dump_index = Marshal.load Gem.read_binary(dump_path)
|
||||
|
||||
dump_index.each do |_,gem|
|
||||
gem.send :remove_instance_variable, :@loaded
|
||||
|
@ -110,12 +152,75 @@ Generating master indexes (this may take a while)
|
|||
"expected YAML and Marshal to produce identical results"
|
||||
end
|
||||
|
||||
def test_generate_index_specs
|
||||
use_ui @ui do
|
||||
@indexer.generate_index
|
||||
end
|
||||
|
||||
specs_path = File.join @tempdir, "specs.#{@marshal_version}"
|
||||
|
||||
specs_dump = Gem.read_binary specs_path
|
||||
specs = Marshal.load specs_dump
|
||||
|
||||
expected = [
|
||||
['a', Gem::Version.new(1), 'ruby'],
|
||||
['a', Gem::Version.new(2), 'ruby'],
|
||||
['a_evil', Gem::Version.new(9), 'ruby'],
|
||||
['b', Gem::Version.new(2), 'ruby'],
|
||||
['c', Gem::Version.new('1.2'), 'ruby'],
|
||||
['d', Gem::Version.new('2.0'), 'ruby'],
|
||||
['pl', Gem::Version.new(1), 'i386-linux'],
|
||||
]
|
||||
|
||||
assert_equal expected, specs
|
||||
|
||||
assert_same specs[0].first, specs[1].first,
|
||||
'identical names not identical'
|
||||
|
||||
assert_same specs[0][1], specs[-1][1],
|
||||
'identical versions not identical'
|
||||
|
||||
assert_same specs[0].last, specs[1].last,
|
||||
'identical platforms not identical'
|
||||
|
||||
assert_not_same specs[1][1], specs[5][1],
|
||||
'different versions not different'
|
||||
end
|
||||
|
||||
def test_generate_index_latest_specs
|
||||
use_ui @ui do
|
||||
@indexer.generate_index
|
||||
end
|
||||
|
||||
latest_specs_path = File.join @tempdir, "latest_specs.#{@marshal_version}"
|
||||
|
||||
latest_specs_dump = Gem.read_binary latest_specs_path
|
||||
latest_specs = Marshal.load latest_specs_dump
|
||||
|
||||
expected = [
|
||||
['a', Gem::Version.new(2), 'ruby'],
|
||||
['a_evil', Gem::Version.new(9), 'ruby'],
|
||||
['b', Gem::Version.new(2), 'ruby'],
|
||||
['c', Gem::Version.new('1.2'), 'ruby'],
|
||||
['d', Gem::Version.new('2.0'), 'ruby'],
|
||||
['pl', Gem::Version.new(1), 'i386-linux'],
|
||||
]
|
||||
|
||||
assert_equal expected, latest_specs
|
||||
|
||||
assert_same latest_specs[0][1], latest_specs[2][1],
|
||||
'identical versions not identical'
|
||||
|
||||
assert_same latest_specs[0].last, latest_specs[1].last,
|
||||
'identical platforms not identical'
|
||||
end
|
||||
|
||||
def assert_indexed(dir, name)
|
||||
file = File.join dir, name
|
||||
assert File.exist?(file), "#{file} does not exist"
|
||||
end
|
||||
|
||||
def deny_indexed(dir, name)
|
||||
def refute_indexed(dir, name)
|
||||
file = File.join dir, name
|
||||
assert !File.exist?(file), "#{file} exists"
|
||||
end
|
||||
|
|
|
@ -102,7 +102,7 @@ load 'my_exec'
|
|||
@installer.ensure_dependency @spec, dep
|
||||
end
|
||||
|
||||
assert_equal 'a requires b (> 2)', e.message
|
||||
assert_equal 'a requires b (> 2, runtime)', e.message
|
||||
end
|
||||
|
||||
def test_expand_and_validate_gem_dir
|
||||
|
@ -128,7 +128,12 @@ load 'my_exec'
|
|||
|
||||
@installer.extract_files
|
||||
|
||||
assert_equal 'thefile', File.read(File.join(util_gem_dir, 'thefile'))
|
||||
thefile_path = File.join(util_gem_dir, 'thefile')
|
||||
assert_equal 'thefile', File.read(thefile_path)
|
||||
|
||||
unless Gem.win_platform? then
|
||||
assert_equal 0400, File.stat(thefile_path).mode & 0777
|
||||
end
|
||||
end
|
||||
|
||||
def test_extract_files_bad_dest
|
||||
|
@ -313,6 +318,29 @@ load 'my_exec'
|
|||
#assert_no_match %r|generated by RubyGems|, wrapper
|
||||
end
|
||||
|
||||
def test_generate_bin_script_wrappers
|
||||
@installer.wrappers = true
|
||||
util_make_exec
|
||||
@installer.gem_dir = util_gem_dir
|
||||
installed_exec = File.join(util_inst_bindir, "my_exec")
|
||||
|
||||
real_exec = File.join util_gem_dir, 'bin', 'my_exec'
|
||||
|
||||
# fake --no-wrappers for previous install
|
||||
FileUtils.mkdir_p File.dirname(installed_exec)
|
||||
FileUtils.ln_s real_exec, installed_exec
|
||||
|
||||
@installer.generate_bin
|
||||
assert_equal true, File.directory?(util_inst_bindir)
|
||||
assert_equal true, File.exist?(installed_exec)
|
||||
assert_equal(0100755, File.stat(installed_exec).mode) unless win_platform?
|
||||
|
||||
assert_match %r|generated by RubyGems|, File.read(installed_exec)
|
||||
|
||||
assert_no_match %r|generated by RubyGems|, File.read(real_exec),
|
||||
'real executable overwritten'
|
||||
end
|
||||
|
||||
def test_generate_bin_symlink
|
||||
return if win_platform? #Windows FS do not support symlinks
|
||||
|
||||
|
|
|
@ -46,12 +46,13 @@ class TestGemLocalRemoteOptions < RubyGemTestCase
|
|||
def test_source_option
|
||||
@cmd.add_source_option
|
||||
|
||||
s1 = URI.parse 'http://more-gems.example.com'
|
||||
s2 = URI.parse 'http://even-more-gems.example.com'
|
||||
s1 = URI.parse 'http://more-gems.example.com/'
|
||||
s2 = URI.parse 'http://even-more-gems.example.com/'
|
||||
s3 = URI.parse 'http://other-gems.example.com/some_subdir'
|
||||
|
||||
@cmd.handle_options %W[--source #{s1} --source #{s2}]
|
||||
@cmd.handle_options %W[--source #{s1} --source #{s2} --source #{s3}]
|
||||
|
||||
assert_equal [s1, s2], Gem.sources
|
||||
assert_equal [s1.to_s, s2.to_s, "#{s3}/"], Gem.sources
|
||||
end
|
||||
|
||||
def test_update_sources_option
|
||||
|
@ -77,7 +78,7 @@ class TestGemLocalRemoteOptions < RubyGemTestCase
|
|||
@cmd.handle_options %W[--source #{s1}]
|
||||
end
|
||||
|
||||
assert_equal %w[http://gems.example.com], Gem.sources
|
||||
assert_equal [@gem_repo], Gem.sources
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -24,7 +24,7 @@ require 'rubygems/remote_fetcher'
|
|||
# Note that the proxy server is not a *real* proxy server. But our
|
||||
# software doesn't really care, as long as we hit the proxy URL when a
|
||||
# proxy is configured.
|
||||
#
|
||||
|
||||
class TestGemRemoteFetcher < RubyGemTestCase
|
||||
|
||||
include Gem::DefaultUserInteraction
|
||||
|
@ -105,7 +105,7 @@ gems:
|
|||
|
||||
@a1, @a1_gem = util_gem 'a', '1' do |s| s.executables << 'a_bin' end
|
||||
|
||||
Gem::RemoteFetcher.instance_variable_set :@fetcher, nil
|
||||
Gem::RemoteFetcher.fetcher = nil
|
||||
end
|
||||
|
||||
def test_self_fetcher
|
||||
|
@ -144,7 +144,7 @@ gems:
|
|||
|
||||
def test_fetch_size_socket_error
|
||||
fetcher = Gem::RemoteFetcher.new nil
|
||||
def fetcher.connect_to(host, port)
|
||||
def fetcher.connection_for(uri)
|
||||
raise SocketError
|
||||
end
|
||||
|
||||
|
@ -153,7 +153,8 @@ gems:
|
|||
fetcher.fetch_size uri
|
||||
end
|
||||
|
||||
assert_equal "SocketError (SocketError)\n\tgetting size of #{uri}", e.message
|
||||
assert_equal "SocketError (SocketError)\n\tfetching size (#{uri})",
|
||||
e.message
|
||||
end
|
||||
|
||||
def test_no_proxy
|
||||
|
@ -182,7 +183,7 @@ gems:
|
|||
@test_data
|
||||
end
|
||||
|
||||
raise Gem::RemoteFetcher::FetchError, "haha!"
|
||||
raise Gem::RemoteFetcher::FetchError.new("haha!", nil)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -371,7 +372,8 @@ gems:
|
|||
fetcher.fetch_path 'uri'
|
||||
end
|
||||
|
||||
assert_equal 'EOFError: EOFError reading uri', e.message
|
||||
assert_equal 'EOFError: EOFError (uri)', e.message
|
||||
assert_equal 'uri', e.uri
|
||||
end
|
||||
|
||||
def test_fetch_path_socket_error
|
||||
|
@ -383,7 +385,8 @@ gems:
|
|||
fetcher.fetch_path 'uri'
|
||||
end
|
||||
|
||||
assert_equal 'SocketError: SocketError reading uri', e.message
|
||||
assert_equal 'SocketError: SocketError (uri)', e.message
|
||||
assert_equal 'uri', e.uri
|
||||
end
|
||||
|
||||
def test_fetch_path_system_call_error
|
||||
|
@ -397,8 +400,9 @@ gems:
|
|||
fetcher.fetch_path 'uri'
|
||||
end
|
||||
|
||||
assert_match %r|ECONNREFUSED:.*connect\(2\) reading uri\z|,
|
||||
assert_match %r|ECONNREFUSED:.*connect\(2\) \(uri\)\z|,
|
||||
e.message
|
||||
assert_equal 'uri', e.uri
|
||||
end
|
||||
|
||||
def test_get_proxy_from_env_empty
|
||||
|
@ -494,7 +498,8 @@ gems:
|
|||
fetcher.send :open_uri_or_path, 'http://gems.example.com/redirect'
|
||||
end
|
||||
|
||||
assert_equal 'too many redirects', e.message
|
||||
assert_equal 'too many redirects (http://gems.example.com/redirect)',
|
||||
e.message
|
||||
end
|
||||
|
||||
def test_zip
|
||||
|
|
|
@ -14,12 +14,121 @@ class TestGemServer < RubyGemTestCase
|
|||
super
|
||||
|
||||
@a1 = quick_gem 'a', '1'
|
||||
@a2 = quick_gem 'a', '2'
|
||||
|
||||
@server = Gem::Server.new Gem.dir, process_based_port, false
|
||||
@req = WEBrick::HTTPRequest.new :Logger => nil
|
||||
@res = WEBrick::HTTPResponse.new :HTTPVersion => '1.0'
|
||||
end
|
||||
|
||||
def test_Marshal
|
||||
data = StringIO.new "GET /Marshal.#{Gem.marshal_version} HTTP/1.0\r\n\r\n"
|
||||
@req.parse data
|
||||
|
||||
@server.Marshal @req, @res
|
||||
|
||||
assert_equal 200, @res.status, @res.body
|
||||
assert_match %r| \d\d:\d\d:\d\d |, @res['date']
|
||||
assert_equal 'application/octet-stream', @res['content-type']
|
||||
|
||||
si = Gem::SourceIndex.new
|
||||
si.add_specs @a1, @a2
|
||||
|
||||
assert_equal si, Marshal.load(@res.body)
|
||||
end
|
||||
|
||||
def test_Marshal_Z
|
||||
data = StringIO.new "GET /Marshal.#{Gem.marshal_version}.Z HTTP/1.0\r\n\r\n"
|
||||
@req.parse data
|
||||
|
||||
@server.Marshal @req, @res
|
||||
|
||||
assert_equal 200, @res.status, @res.body
|
||||
assert_match %r| \d\d:\d\d:\d\d |, @res['date']
|
||||
assert_equal 'application/x-deflate', @res['content-type']
|
||||
|
||||
si = Gem::SourceIndex.new
|
||||
si.add_specs @a1, @a2
|
||||
|
||||
assert_equal si, Marshal.load(Gem.inflate(@res.body))
|
||||
end
|
||||
|
||||
def test_latest_specs
|
||||
data = StringIO.new "GET /latest_specs.#{Gem.marshal_version} HTTP/1.0\r\n\r\n"
|
||||
@req.parse data
|
||||
|
||||
@server.latest_specs @req, @res
|
||||
|
||||
assert_equal 200, @res.status, @res.body
|
||||
assert_match %r| \d\d:\d\d:\d\d |, @res['date']
|
||||
assert_equal 'application/octet-stream', @res['content-type']
|
||||
assert_equal [['a', Gem::Version.new(2), Gem::Platform::RUBY]],
|
||||
Marshal.load(@res.body)
|
||||
end
|
||||
|
||||
def test_latest_specs_gz
|
||||
data = StringIO.new "GET /latest_specs.#{Gem.marshal_version}.gz HTTP/1.0\r\n\r\n"
|
||||
@req.parse data
|
||||
|
||||
@server.latest_specs @req, @res
|
||||
|
||||
assert_equal 200, @res.status, @res.body
|
||||
assert_match %r| \d\d:\d\d:\d\d |, @res['date']
|
||||
assert_equal 'application/x-gzip', @res['content-type']
|
||||
assert_equal [['a', Gem::Version.new(2), Gem::Platform::RUBY]],
|
||||
Marshal.load(Gem.gunzip(@res.body))
|
||||
end
|
||||
|
||||
def test_quick_a_1_gemspec_rz
|
||||
data = StringIO.new "GET /quick/a-1.gemspec.rz HTTP/1.0\r\n\r\n"
|
||||
@req.parse data
|
||||
|
||||
@server.quick @req, @res
|
||||
|
||||
assert_equal 200, @res.status, @res.body
|
||||
assert @res['date']
|
||||
assert_equal 'application/x-deflate', @res['content-type']
|
||||
|
||||
spec = YAML.load Gem.inflate(@res.body)
|
||||
assert_equal 'a', spec.name
|
||||
assert_equal Gem::Version.new(1), spec.version
|
||||
end
|
||||
|
||||
def test_quick_a_1_mswin32_gemspec_rz
|
||||
a1_p = quick_gem 'a', '1' do |s| s.platform = Gem::Platform.local end
|
||||
|
||||
data = StringIO.new "GET /quick/a-1-#{Gem::Platform.local}.gemspec.rz HTTP/1.0\r\n\r\n"
|
||||
@req.parse data
|
||||
|
||||
@server.quick @req, @res
|
||||
|
||||
assert_equal 200, @res.status, @res.body
|
||||
assert @res['date']
|
||||
assert_equal 'application/x-deflate', @res['content-type']
|
||||
|
||||
spec = YAML.load Gem.inflate(@res.body)
|
||||
assert_equal 'a', spec.name
|
||||
assert_equal Gem::Version.new(1), spec.version
|
||||
assert_equal Gem::Platform.local, spec.platform
|
||||
end
|
||||
|
||||
def test_quick_common_substrings
|
||||
ab1 = quick_gem 'ab', '1'
|
||||
|
||||
data = StringIO.new "GET /quick/a-1.gemspec.rz HTTP/1.0\r\n\r\n"
|
||||
@req.parse data
|
||||
|
||||
@server.quick @req, @res
|
||||
|
||||
assert_equal 200, @res.status, @res.body
|
||||
assert @res['date']
|
||||
assert_equal 'application/x-deflate', @res['content-type']
|
||||
|
||||
spec = YAML.load Gem.inflate(@res.body)
|
||||
assert_equal 'a', spec.name
|
||||
assert_equal Gem::Version.new(1), spec.version
|
||||
end
|
||||
|
||||
def test_quick_index
|
||||
data = StringIO.new "GET /quick/index HTTP/1.0\r\n\r\n"
|
||||
@req.parse data
|
||||
|
@ -29,7 +138,7 @@ class TestGemServer < RubyGemTestCase
|
|||
assert_equal 200, @res.status, @res.body
|
||||
assert_match %r| \d\d:\d\d:\d\d |, @res['date']
|
||||
assert_equal 'text/plain', @res['content-type']
|
||||
assert_equal "a-1", @res.body
|
||||
assert_equal "a-1\na-2", @res.body
|
||||
end
|
||||
|
||||
def test_quick_index_rz
|
||||
|
@ -40,65 +149,35 @@ class TestGemServer < RubyGemTestCase
|
|||
|
||||
assert_equal 200, @res.status, @res.body
|
||||
assert_match %r| \d\d:\d\d:\d\d |, @res['date']
|
||||
assert_equal 'text/plain', @res['content-type']
|
||||
assert_equal "a-1", Zlib::Inflate.inflate(@res.body)
|
||||
assert_equal 'application/x-deflate', @res['content-type']
|
||||
assert_equal "a-1\na-2", Gem.inflate(@res.body)
|
||||
end
|
||||
|
||||
def test_quick_a_1_gemspec_rz
|
||||
data = StringIO.new "GET /quick/a-1.gemspec.rz HTTP/1.0\r\n\r\n"
|
||||
def test_quick_latest_index
|
||||
data = StringIO.new "GET /quick/latest_index HTTP/1.0\r\n\r\n"
|
||||
@req.parse data
|
||||
|
||||
@server.quick @req, @res
|
||||
|
||||
assert_equal 200, @res.status, @res.body
|
||||
assert @res['date']
|
||||
assert_match %r| \d\d:\d\d:\d\d |, @res['date']
|
||||
assert_equal 'text/plain', @res['content-type']
|
||||
|
||||
spec = YAML.load Zlib::Inflate.inflate(@res.body)
|
||||
assert_equal 'a', spec.name
|
||||
assert_equal Gem::Version.new(1), spec.version
|
||||
assert_equal 'a-2', @res.body
|
||||
end
|
||||
|
||||
def test_quick_a_1_mswin32_gemspec_rz
|
||||
a1_p = quick_gem 'a', '1' do |s| s.platform = Gem::Platform.local end
|
||||
si = Gem::SourceIndex.new @a1.full_name => @a1, a1_p.full_name => a1_p
|
||||
@server.source_index = si
|
||||
|
||||
data = StringIO.new "GET /quick/a-1-#{Gem::Platform.local}.gemspec.rz HTTP/1.0\r\n\r\n"
|
||||
def test_quick_latest_index_rz
|
||||
data = StringIO.new "GET /quick/latest_index.rz HTTP/1.0\r\n\r\n"
|
||||
@req.parse data
|
||||
|
||||
@server.quick @req, @res
|
||||
|
||||
assert_equal 200, @res.status, @res.body
|
||||
assert @res['date']
|
||||
assert_equal 'text/plain', @res['content-type']
|
||||
|
||||
spec = YAML.load Zlib::Inflate.inflate(@res.body)
|
||||
assert_equal 'a', spec.name
|
||||
assert_equal Gem::Version.new(1), spec.version
|
||||
assert_equal Gem::Platform.local, spec.platform
|
||||
assert_match %r| \d\d:\d\d:\d\d |, @res['date']
|
||||
assert_equal 'application/x-deflate', @res['content-type']
|
||||
assert_equal 'a-2', Gem.inflate(@res.body)
|
||||
end
|
||||
|
||||
def test_quick_common_substrings
|
||||
ab1 = quick_gem 'ab', '1'
|
||||
si = Gem::SourceIndex.new @a1.full_name => @a1, ab1.full_name => ab1
|
||||
@server.source_index = si
|
||||
|
||||
data = StringIO.new "GET /quick/a-1.gemspec.rz HTTP/1.0\r\n\r\n"
|
||||
@req.parse data
|
||||
|
||||
@server.quick @req, @res
|
||||
|
||||
assert_equal 200, @res.status, @res.body
|
||||
assert @res['date']
|
||||
assert_equal 'text/plain', @res['content-type']
|
||||
|
||||
spec = YAML.load Zlib::Inflate.inflate(@res.body)
|
||||
assert_equal 'a', spec.name
|
||||
assert_equal Gem::Version.new(1), spec.version
|
||||
end
|
||||
|
||||
def test_quick_z_9_gemspec_rz
|
||||
def test_quick_missing
|
||||
data = StringIO.new "GET /quick/z-9.gemspec.rz HTTP/1.0\r\n\r\n"
|
||||
@req.parse data
|
||||
|
||||
|
@ -111,5 +190,112 @@ class TestGemServer < RubyGemTestCase
|
|||
assert_equal 404, @res.status
|
||||
end
|
||||
|
||||
def test_quick_marshal_a_1_gemspec_rz
|
||||
data = StringIO.new "GET /quick/Marshal.#{Gem.marshal_version}/a-1.gemspec.rz HTTP/1.0\r\n\r\n"
|
||||
@req.parse data
|
||||
|
||||
@server.quick @req, @res
|
||||
|
||||
assert_equal 200, @res.status, @res.body
|
||||
assert @res['date']
|
||||
assert_equal 'application/x-deflate', @res['content-type']
|
||||
|
||||
spec = Marshal.load Gem.inflate(@res.body)
|
||||
assert_equal 'a', spec.name
|
||||
assert_equal Gem::Version.new(1), spec.version
|
||||
end
|
||||
|
||||
def test_quick_marshal_a_1_mswin32_gemspec_rz
|
||||
a1_p = quick_gem 'a', '1' do |s| s.platform = Gem::Platform.local end
|
||||
|
||||
data = StringIO.new "GET /quick/Marshal.#{Gem.marshal_version}/a-1-#{Gem::Platform.local}.gemspec.rz HTTP/1.0\r\n\r\n"
|
||||
@req.parse data
|
||||
|
||||
@server.quick @req, @res
|
||||
|
||||
assert_equal 200, @res.status, @res.body
|
||||
assert @res['date']
|
||||
assert_equal 'application/x-deflate', @res['content-type']
|
||||
|
||||
spec = Marshal.load Gem.inflate(@res.body)
|
||||
assert_equal 'a', spec.name
|
||||
assert_equal Gem::Version.new(1), spec.version
|
||||
assert_equal Gem::Platform.local, spec.platform
|
||||
end
|
||||
|
||||
|
||||
def test_root
|
||||
data = StringIO.new "GET / HTTP/1.0\r\n\r\n"
|
||||
@req.parse data
|
||||
|
||||
@server.root @req, @res
|
||||
|
||||
assert_equal 200, @res.status, @res.body
|
||||
assert_match %r| \d\d:\d\d:\d\d |, @res['date']
|
||||
assert_equal 'text/html', @res['content-type']
|
||||
end
|
||||
|
||||
def test_specs
|
||||
data = StringIO.new "GET /specs.#{Gem.marshal_version} HTTP/1.0\r\n\r\n"
|
||||
@req.parse data
|
||||
|
||||
@server.specs @req, @res
|
||||
|
||||
assert_equal 200, @res.status, @res.body
|
||||
assert_match %r| \d\d:\d\d:\d\d |, @res['date']
|
||||
assert_equal 'application/octet-stream', @res['content-type']
|
||||
|
||||
assert_equal [['a', Gem::Version.new(1), Gem::Platform::RUBY],
|
||||
['a', Gem::Version.new(2), Gem::Platform::RUBY]],
|
||||
Marshal.load(@res.body)
|
||||
end
|
||||
|
||||
def test_specs_gz
|
||||
data = StringIO.new "GET /specs.#{Gem.marshal_version}.gz HTTP/1.0\r\n\r\n"
|
||||
@req.parse data
|
||||
|
||||
@server.specs @req, @res
|
||||
|
||||
assert_equal 200, @res.status, @res.body
|
||||
assert_match %r| \d\d:\d\d:\d\d |, @res['date']
|
||||
assert_equal 'application/x-gzip', @res['content-type']
|
||||
|
||||
assert_equal [['a', Gem::Version.new(1), Gem::Platform::RUBY],
|
||||
['a', Gem::Version.new(2), Gem::Platform::RUBY]],
|
||||
Marshal.load(Gem.gunzip(@res.body))
|
||||
end
|
||||
|
||||
def test_yaml
|
||||
data = StringIO.new "GET /yaml.#{Gem.marshal_version} HTTP/1.0\r\n\r\n"
|
||||
@req.parse data
|
||||
|
||||
@server.yaml @req, @res
|
||||
|
||||
assert_equal 200, @res.status, @res.body
|
||||
assert_match %r| \d\d:\d\d:\d\d |, @res['date']
|
||||
assert_equal 'text/plain', @res['content-type']
|
||||
|
||||
si = Gem::SourceIndex.new
|
||||
si.add_specs @a1, @a2
|
||||
|
||||
assert_equal si, YAML.load(@res.body)
|
||||
end
|
||||
|
||||
def test_yaml_Z
|
||||
data = StringIO.new "GET /yaml.#{Gem.marshal_version}.Z HTTP/1.0\r\n\r\n"
|
||||
@req.parse data
|
||||
|
||||
@server.yaml @req, @res
|
||||
|
||||
assert_equal 200, @res.status, @res.body
|
||||
assert_match %r| \d\d:\d\d:\d\d |, @res['date']
|
||||
assert_equal 'application/x-deflate', @res['content-type']
|
||||
|
||||
si = Gem::SourceIndex.new
|
||||
si.add_specs @a1, @a2
|
||||
|
||||
assert_equal si, YAML.load(Gem.inflate(@res.body))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -23,6 +23,141 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
util_setup_fake_fetcher
|
||||
end
|
||||
|
||||
def test_self_from_gems_in
|
||||
spec_dir = File.join @gemhome, 'specifications'
|
||||
|
||||
FileUtils.rm_r spec_dir
|
||||
|
||||
FileUtils.mkdir_p spec_dir
|
||||
|
||||
a1 = quick_gem 'a', '1' do |spec| spec.author = 'author 1' end
|
||||
|
||||
spec_file = File.join spec_dir, "#{a1.full_name}.gemspec"
|
||||
|
||||
File.open spec_file, 'w' do |fp|
|
||||
fp.write a1.to_ruby
|
||||
end
|
||||
|
||||
si = Gem::SourceIndex.from_gems_in spec_dir
|
||||
|
||||
assert_equal [spec_dir], si.spec_dirs
|
||||
assert_equal [a1.full_name], si.gems.keys
|
||||
end
|
||||
|
||||
def test_self_load_specification
|
||||
spec_dir = File.join @gemhome, 'specifications'
|
||||
|
||||
FileUtils.rm_r spec_dir
|
||||
|
||||
FileUtils.mkdir_p spec_dir
|
||||
|
||||
a1 = quick_gem 'a', '1' do |spec| spec.author = 'author 1' end
|
||||
|
||||
spec_file = File.join spec_dir, "#{a1.full_name}.gemspec"
|
||||
|
||||
File.open spec_file, 'w' do |fp|
|
||||
fp.write a1.to_ruby
|
||||
end
|
||||
|
||||
spec = Gem::SourceIndex.load_specification spec_file
|
||||
|
||||
assert_equal a1.author, spec.author
|
||||
end
|
||||
|
||||
def test_self_load_specification_exception
|
||||
spec_dir = File.join @gemhome, 'specifications'
|
||||
|
||||
FileUtils.mkdir_p spec_dir
|
||||
|
||||
spec_file = File.join spec_dir, 'a-1.gemspec'
|
||||
|
||||
File.open spec_file, 'w' do |fp|
|
||||
fp.write 'raise Exception, "epic fail"'
|
||||
end
|
||||
|
||||
use_ui @ui do
|
||||
assert_equal nil, Gem::SourceIndex.load_specification(spec_file)
|
||||
end
|
||||
|
||||
assert_equal '', @ui.output
|
||||
|
||||
expected = <<-EOF
|
||||
WARNING: #<Exception: epic fail>
|
||||
raise Exception, "epic fail"
|
||||
WARNING: Invalid .gemspec format in '#{spec_file}'
|
||||
EOF
|
||||
|
||||
assert_equal expected, @ui.error
|
||||
end
|
||||
|
||||
def test_self_load_specification_interrupt
|
||||
spec_dir = File.join @gemhome, 'specifications'
|
||||
|
||||
FileUtils.mkdir_p spec_dir
|
||||
|
||||
spec_file = File.join spec_dir, 'a-1.gemspec'
|
||||
|
||||
File.open spec_file, 'w' do |fp|
|
||||
fp.write 'raise Interrupt, "^C"'
|
||||
end
|
||||
|
||||
use_ui @ui do
|
||||
assert_raise Interrupt do
|
||||
Gem::SourceIndex.load_specification(spec_file)
|
||||
end
|
||||
end
|
||||
|
||||
assert_equal '', @ui.output
|
||||
assert_equal '', @ui.error
|
||||
end
|
||||
|
||||
def test_self_load_specification_syntax_error
|
||||
spec_dir = File.join @gemhome, 'specifications'
|
||||
|
||||
FileUtils.mkdir_p spec_dir
|
||||
|
||||
spec_file = File.join spec_dir, 'a-1.gemspec'
|
||||
|
||||
File.open spec_file, 'w' do |fp|
|
||||
fp.write '1 +'
|
||||
end
|
||||
|
||||
use_ui @ui do
|
||||
assert_equal nil, Gem::SourceIndex.load_specification(spec_file)
|
||||
end
|
||||
|
||||
assert_equal '', @ui.output
|
||||
|
||||
expected = <<-EOF
|
||||
WARNING: compile error
|
||||
#{spec_file}:1: syntax error, unexpected $end
|
||||
WARNING: 1 +
|
||||
EOF
|
||||
|
||||
assert_equal expected, @ui.error
|
||||
end
|
||||
|
||||
def test_self_load_specification_system_exit
|
||||
spec_dir = File.join @gemhome, 'specifications'
|
||||
|
||||
FileUtils.mkdir_p spec_dir
|
||||
|
||||
spec_file = File.join spec_dir, 'a-1.gemspec'
|
||||
|
||||
File.open spec_file, 'w' do |fp|
|
||||
fp.write 'raise SystemExit, "bye-bye"'
|
||||
end
|
||||
|
||||
use_ui @ui do
|
||||
assert_raise SystemExit do
|
||||
Gem::SourceIndex.load_specification(spec_file)
|
||||
end
|
||||
end
|
||||
|
||||
assert_equal '', @ui.output
|
||||
assert_equal '', @ui.error
|
||||
end
|
||||
|
||||
def test_create_from_directory
|
||||
# TODO
|
||||
end
|
||||
|
@ -43,16 +178,16 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
|
||||
paths = @fetcher.paths
|
||||
|
||||
assert_equal "#{@gem_repo}/Marshal.#{@marshal_version}.Z", paths.shift
|
||||
assert_equal "#{@gem_repo}Marshal.#{@marshal_version}.Z", paths.shift
|
||||
|
||||
assert paths.empty?, paths.join(', ')
|
||||
end
|
||||
|
||||
def test_fetch_bulk_index_error
|
||||
@fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}.Z"] = proc { raise SocketError }
|
||||
@fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] = proc { raise SocketError }
|
||||
@fetcher.data["#{@gem_repo}/yaml.Z"] = proc { raise SocketError }
|
||||
@fetcher.data["#{@gem_repo}/yaml"] = proc { raise SocketError }
|
||||
@fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}.Z"] = proc { raise SocketError }
|
||||
@fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}"] = proc { raise SocketError }
|
||||
@fetcher.data["#{@gem_repo}yaml.Z"] = proc { raise SocketError }
|
||||
@fetcher.data["#{@gem_repo}yaml"] = proc { raise SocketError }
|
||||
|
||||
e = assert_raise Gem::RemoteSourceException do
|
||||
use_ui @ui do
|
||||
|
@ -62,10 +197,10 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
|
||||
paths = @fetcher.paths
|
||||
|
||||
assert_equal "#{@gem_repo}/Marshal.#{@marshal_version}.Z", paths.shift
|
||||
assert_equal "#{@gem_repo}/Marshal.#{@marshal_version}", paths.shift
|
||||
assert_equal "#{@gem_repo}/yaml.Z", paths.shift
|
||||
assert_equal "#{@gem_repo}/yaml", paths.shift
|
||||
assert_equal "#{@gem_repo}Marshal.#{@marshal_version}.Z", paths.shift
|
||||
assert_equal "#{@gem_repo}Marshal.#{@marshal_version}", paths.shift
|
||||
assert_equal "#{@gem_repo}yaml.Z", paths.shift
|
||||
assert_equal "#{@gem_repo}yaml", paths.shift
|
||||
|
||||
assert paths.empty?, paths.join(', ')
|
||||
|
||||
|
@ -74,12 +209,12 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
end
|
||||
|
||||
def test_fetch_bulk_index_fallback
|
||||
@fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}.Z"] =
|
||||
@fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}.Z"] =
|
||||
proc { raise SocketError }
|
||||
@fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] =
|
||||
@fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}"] =
|
||||
proc { raise SocketError }
|
||||
@fetcher.data["#{@gem_repo}/yaml.Z"] = proc { raise SocketError }
|
||||
@fetcher.data["#{@gem_repo}/yaml"] = @source_index.to_yaml
|
||||
@fetcher.data["#{@gem_repo}yaml.Z"] = proc { raise SocketError }
|
||||
@fetcher.data["#{@gem_repo}yaml"] = @source_index.to_yaml
|
||||
|
||||
use_ui @ui do
|
||||
fetched_index = @source_index.fetch_bulk_index @uri
|
||||
|
@ -90,10 +225,10 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
|
||||
paths = @fetcher.paths
|
||||
|
||||
assert_equal "#{@gem_repo}/Marshal.#{@marshal_version}.Z", paths.shift
|
||||
assert_equal "#{@gem_repo}/Marshal.#{@marshal_version}", paths.shift
|
||||
assert_equal "#{@gem_repo}/yaml.Z", paths.shift
|
||||
assert_equal "#{@gem_repo}/yaml", paths.shift
|
||||
assert_equal "#{@gem_repo}Marshal.#{@marshal_version}.Z", paths.shift
|
||||
assert_equal "#{@gem_repo}Marshal.#{@marshal_version}", paths.shift
|
||||
assert_equal "#{@gem_repo}yaml.Z", paths.shift
|
||||
assert_equal "#{@gem_repo}yaml", paths.shift
|
||||
|
||||
assert paths.empty?, paths.join(', ')
|
||||
end
|
||||
|
@ -102,8 +237,8 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
marshal = @source_index.dump
|
||||
marshal[0] = (Marshal::MAJOR_VERSION - 1).chr
|
||||
|
||||
@fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] = marshal
|
||||
@fetcher.data["#{@gem_repo}/yaml"] = @source_index.to_yaml
|
||||
@fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}"] = marshal
|
||||
@fetcher.data["#{@gem_repo}yaml"] = @source_index.to_yaml
|
||||
|
||||
use_ui @ui do
|
||||
fetched_index = @source_index.fetch_bulk_index @uri
|
||||
|
@ -114,10 +249,10 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
|
||||
paths = @fetcher.paths
|
||||
|
||||
assert_equal "#{@gem_repo}/Marshal.#{@marshal_version}.Z", paths.shift
|
||||
assert_equal "#{@gem_repo}/Marshal.#{@marshal_version}", paths.shift
|
||||
assert_equal "#{@gem_repo}/yaml.Z", paths.shift
|
||||
assert_equal "#{@gem_repo}/yaml", paths.shift
|
||||
assert_equal "#{@gem_repo}Marshal.#{@marshal_version}.Z", paths.shift
|
||||
assert_equal "#{@gem_repo}Marshal.#{@marshal_version}", paths.shift
|
||||
assert_equal "#{@gem_repo}yaml.Z", paths.shift
|
||||
assert_equal "#{@gem_repo}yaml", paths.shift
|
||||
|
||||
assert paths.empty?, paths.join(', ')
|
||||
end
|
||||
|
@ -133,8 +268,8 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
|
||||
paths = @fetcher.paths
|
||||
|
||||
assert_equal "#{@gem_repo}/Marshal.#{@marshal_version}.Z", paths.shift
|
||||
assert_equal "#{@gem_repo}/Marshal.#{@marshal_version}", paths.shift
|
||||
assert_equal "#{@gem_repo}Marshal.#{@marshal_version}.Z", paths.shift
|
||||
assert_equal "#{@gem_repo}Marshal.#{@marshal_version}", paths.shift
|
||||
|
||||
assert paths.empty?, paths.join(', ')
|
||||
end
|
||||
|
@ -143,8 +278,8 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
index = util_zip @gem_names
|
||||
latest_index = util_zip [@a2.full_name, @b2.full_name].join("\n")
|
||||
|
||||
@fetcher.data["#{@gem_repo}/quick/index.rz"] = index
|
||||
@fetcher.data["#{@gem_repo}/quick/latest_index.rz"] = latest_index
|
||||
@fetcher.data["#{@gem_repo}quick/index.rz"] = index
|
||||
@fetcher.data["#{@gem_repo}quick/latest_index.rz"] = latest_index
|
||||
|
||||
quick_index = @source_index.fetch_quick_index @uri, false
|
||||
assert_equal [@a2.full_name, @b2.full_name].sort,
|
||||
|
@ -152,7 +287,7 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
|
||||
paths = @fetcher.paths
|
||||
|
||||
assert_equal "#{@gem_repo}/quick/latest_index.rz", paths.shift
|
||||
assert_equal "#{@gem_repo}quick/latest_index.rz", paths.shift
|
||||
|
||||
assert paths.empty?, paths.join(', ')
|
||||
end
|
||||
|
@ -161,8 +296,8 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
index = util_zip @gem_names
|
||||
latest_index = util_zip [@a2.full_name, @b2.full_name].join("\n")
|
||||
|
||||
@fetcher.data["#{@gem_repo}/quick/index.rz"] = index
|
||||
@fetcher.data["#{@gem_repo}/quick/latest_index.rz"] = latest_index
|
||||
@fetcher.data["#{@gem_repo}quick/index.rz"] = index
|
||||
@fetcher.data["#{@gem_repo}quick/latest_index.rz"] = latest_index
|
||||
|
||||
quick_index = @source_index.fetch_quick_index @uri, true
|
||||
assert_equal [@a1.full_name, @a2.full_name, @b2.full_name].sort,
|
||||
|
@ -170,13 +305,13 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
|
||||
paths = @fetcher.paths
|
||||
|
||||
assert_equal "#{@gem_repo}/quick/index.rz", paths.shift
|
||||
assert_equal "#{@gem_repo}quick/index.rz", paths.shift
|
||||
|
||||
assert paths.empty?, paths.join(', ')
|
||||
end
|
||||
|
||||
def test_fetch_quick_index_error
|
||||
@fetcher.data["#{@gem_repo}/quick/index.rz"] =
|
||||
@fetcher.data["#{@gem_repo}quick/index.rz"] =
|
||||
proc { raise Exception }
|
||||
|
||||
e = assert_raise Gem::OperationNotSupportedError do
|
||||
|
@ -187,7 +322,7 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
|
||||
paths = @fetcher.paths
|
||||
|
||||
assert_equal "#{@gem_repo}/quick/index.rz", paths.shift
|
||||
assert_equal "#{@gem_repo}quick/index.rz", paths.shift
|
||||
|
||||
assert paths.empty?, paths.join(', ')
|
||||
end
|
||||
|
@ -195,22 +330,22 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
def test_fetch_quick_index_fallback
|
||||
index = util_zip @gem_names
|
||||
|
||||
@fetcher.data["#{@gem_repo}/quick/index.rz"] = index
|
||||
@fetcher.data["#{@gem_repo}quick/index.rz"] = index
|
||||
|
||||
quick_index = @source_index.fetch_quick_index @uri, false
|
||||
assert_equal @gem_names.split, quick_index.sort
|
||||
|
||||
paths = @fetcher.paths
|
||||
|
||||
assert_equal "#{@gem_repo}/quick/latest_index.rz", paths.shift
|
||||
assert_equal "#{@gem_repo}/quick/index.rz", paths.shift
|
||||
assert_equal "#{@gem_repo}quick/latest_index.rz", paths.shift
|
||||
assert_equal "#{@gem_repo}quick/index.rz", paths.shift
|
||||
|
||||
assert paths.empty?, paths.join(', ')
|
||||
end
|
||||
|
||||
def test_fetch_quick_index_subdir
|
||||
latest_index = util_zip [@a2.full_name, @b2.full_name].join("\n")
|
||||
repo = URI.parse "#{@gem_repo}/~nobody/mirror/"
|
||||
repo = URI.parse "#{@gem_repo}~nobody/mirror/"
|
||||
|
||||
@fetcher.data["#{repo}quick/latest_index.rz"] = latest_index
|
||||
|
||||
|
@ -226,7 +361,7 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
end
|
||||
|
||||
def test_fetch_single_spec
|
||||
a1_spec_url = "#{@gem_repo}/quick/Marshal.#{Gem.marshal_version}/#{@a1.full_name}.gemspec.rz"
|
||||
a1_spec_url = "#{@gem_repo}quick/Marshal.#{Gem.marshal_version}/#{@a1.full_name}.gemspec.rz"
|
||||
@fetcher.data[a1_spec_url] = util_zip Marshal.dump(@a1)
|
||||
|
||||
spec = @source_index.send :fetch_single_spec, URI.parse(@gem_repo),
|
||||
|
@ -242,7 +377,7 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
end
|
||||
|
||||
def test_fetch_single_spec_subdir
|
||||
repo = URI.parse "#{@gem_repo}/~nobody/mirror/"
|
||||
repo = URI.parse "#{@gem_repo}~nobody/mirror/"
|
||||
|
||||
a1_spec_url = "#{repo}quick/Marshal.#{Gem.marshal_version}/#{@a1.full_name}.gemspec.rz"
|
||||
@fetcher.data[a1_spec_url] = util_zip Marshal.dump(@a1)
|
||||
|
@ -259,7 +394,7 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
end
|
||||
|
||||
def test_fetch_single_spec_yaml
|
||||
a1_spec_url = "#{@gem_repo}/quick/#{@a1.full_name}.gemspec.rz"
|
||||
a1_spec_url = "#{@gem_repo}quick/#{@a1.full_name}.gemspec.rz"
|
||||
@fetcher.data[a1_spec_url] = util_zip @a1.to_yaml
|
||||
|
||||
repo = URI.parse @gem_repo
|
||||
|
@ -270,14 +405,14 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
|
||||
paths = @fetcher.paths
|
||||
|
||||
assert_equal "#{@gem_repo}/quick/Marshal.#{Gem.marshal_version}/#{@a1.full_name}.gemspec.rz", paths.shift
|
||||
assert_equal "#{@gem_repo}quick/Marshal.#{Gem.marshal_version}/#{@a1.full_name}.gemspec.rz", paths.shift
|
||||
assert_equal a1_spec_url, paths.shift
|
||||
|
||||
assert paths.empty?, paths.join(', ')
|
||||
end
|
||||
|
||||
def test_fetch_single_spec_yaml_subdir
|
||||
repo = URI.parse "#{@gem_repo}/~nobody/mirror/"
|
||||
repo = URI.parse "#{@gem_repo}~nobody/mirror/"
|
||||
|
||||
a1_spec_url = "#{repo}quick/#{@a1.full_name}.gemspec.rz"
|
||||
@fetcher.data[a1_spec_url] = util_zip @a1.to_yaml
|
||||
|
@ -377,12 +512,12 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
end
|
||||
|
||||
def test_outdated
|
||||
util_setup_source_info_cache
|
||||
util_setup_spec_fetcher
|
||||
|
||||
assert_equal [], @source_index.outdated
|
||||
|
||||
updated = quick_gem @a2.name, (@a2.version.bump)
|
||||
util_setup_source_info_cache updated
|
||||
util_setup_spec_fetcher updated
|
||||
|
||||
assert_equal [updated.name], @source_index.outdated
|
||||
|
||||
|
@ -390,7 +525,7 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
s.platform = Gem::Platform.new 'x86-other_platform1'
|
||||
end
|
||||
|
||||
util_setup_source_info_cache updated, updated_platform
|
||||
util_setup_spec_fetcher updated, updated_platform
|
||||
|
||||
assert_equal [updated_platform.name], @source_index.outdated
|
||||
end
|
||||
|
@ -411,6 +546,16 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
assert source_index.gems.include?(@a1.full_name)
|
||||
end
|
||||
|
||||
def test_refresh_bang_not_from_dir
|
||||
source_index = Gem::SourceIndex.new
|
||||
|
||||
e = assert_raise RuntimeError do
|
||||
source_index.refresh!
|
||||
end
|
||||
|
||||
assert_equal 'source index not created from disk', e.message
|
||||
end
|
||||
|
||||
def test_remove_extra
|
||||
@source_index.add_spec @a1
|
||||
@source_index.add_spec @a2
|
||||
|
@ -516,8 +661,8 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
|
||||
paths = @fetcher.paths
|
||||
|
||||
assert_equal "#{@gem_repo}/quick/index.rz", paths.shift
|
||||
assert_equal "#{@gem_repo}/Marshal.#{@marshal_version}.Z", paths.shift
|
||||
assert_equal "#{@gem_repo}quick/index.rz", paths.shift
|
||||
assert_equal "#{@gem_repo}Marshal.#{@marshal_version}.Z", paths.shift
|
||||
|
||||
assert paths.empty?, paths.join(', ')
|
||||
end
|
||||
|
@ -528,7 +673,7 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
|
||||
latest_names = [@a2, @a_evil9, @b2, @c1_2].map { |s| s.full_name }
|
||||
latest_index = util_zip latest_names.join("\n")
|
||||
@fetcher.data["#{@gem_repo}/quick/latest_index.rz"] = latest_index
|
||||
@fetcher.data["#{@gem_repo}quick/latest_index.rz"] = latest_index
|
||||
|
||||
marshal_uri = File.join @gem_repo, "quick", "Marshal.#{@marshal_version}",
|
||||
"#{@b2.full_name}.gemspec.rz"
|
||||
|
@ -541,7 +686,7 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
end
|
||||
|
||||
paths = @fetcher.paths
|
||||
assert_equal "#{@gem_repo}/quick/latest_index.rz", paths.shift
|
||||
assert_equal "#{@gem_repo}quick/latest_index.rz", paths.shift
|
||||
assert_equal marshal_uri, paths.shift
|
||||
|
||||
assert paths.empty?, paths.join(', ')
|
||||
|
@ -554,7 +699,7 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
Gem.configuration = Gem::ConfigFile.new([])
|
||||
|
||||
quick_index = util_zip @all_gem_names.join("\n")
|
||||
@fetcher.data["#{@gem_repo}/quick/index.rz"] = quick_index
|
||||
@fetcher.data["#{@gem_repo}quick/index.rz"] = quick_index
|
||||
|
||||
marshal_uri = File.join @gem_repo, "quick", "Marshal.#{@marshal_version}",
|
||||
"#{@b2.full_name}.gemspec.rz"
|
||||
|
@ -567,7 +712,7 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
end
|
||||
|
||||
paths = @fetcher.paths
|
||||
assert_equal "#{@gem_repo}/quick/index.rz", paths.shift
|
||||
assert_equal "#{@gem_repo}quick/index.rz", paths.shift
|
||||
assert_equal marshal_uri, paths.shift
|
||||
|
||||
assert paths.empty?, paths.join(', ')
|
||||
|
@ -580,12 +725,12 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
Gem.configuration = Gem::ConfigFile.new([])
|
||||
|
||||
quick_index = util_zip @all_gem_names.join("\n")
|
||||
@fetcher.data["#{@gem_repo}/quick/index.rz"] = quick_index
|
||||
@fetcher.data["#{@gem_repo}quick/index.rz"] = quick_index
|
||||
|
||||
marshal_uri = File.join @gem_repo, "quick", "Marshal.#{@marshal_version}",
|
||||
"#{@b2.full_name}.gemspec.rz"
|
||||
|
||||
yaml_uri = "#{@gem_repo}/quick/#{@b2.full_name}.gemspec.rz"
|
||||
yaml_uri = "#{@gem_repo}quick/#{@b2.full_name}.gemspec.rz"
|
||||
@fetcher.data[yaml_uri] = util_zip @b2.to_yaml
|
||||
|
||||
use_ui @ui do
|
||||
|
@ -595,7 +740,7 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
end
|
||||
|
||||
paths = @fetcher.paths
|
||||
assert_equal "#{@gem_repo}/quick/index.rz", paths.shift
|
||||
assert_equal "#{@gem_repo}quick/index.rz", paths.shift
|
||||
assert_equal marshal_uri, paths.shift
|
||||
assert_equal yaml_uri, paths.shift
|
||||
|
||||
|
@ -609,7 +754,7 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
Gem.configuration = Gem::ConfigFile.new([])
|
||||
|
||||
quick_index = util_zip @all_gem_names.join("\n")
|
||||
@fetcher.data["#{@gem_repo}/quick/index.rz"] = quick_index
|
||||
@fetcher.data["#{@gem_repo}quick/index.rz"] = quick_index
|
||||
|
||||
marshal_uri = File.join @gem_repo, "quick", "Marshal.#{@marshal_version}",
|
||||
"#{@b2.full_name}.gemspec.rz"
|
||||
|
@ -617,7 +762,7 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
marshal_data[0] = (Marshal::MAJOR_VERSION - 1).chr
|
||||
@fetcher.data[marshal_uri] = util_zip marshal_data
|
||||
|
||||
yaml_uri = "#{@gem_repo}/quick/#{@b2.full_name}.gemspec.rz"
|
||||
yaml_uri = "#{@gem_repo}quick/#{@b2.full_name}.gemspec.rz"
|
||||
@fetcher.data[yaml_uri] = util_zip @b2.to_yaml
|
||||
|
||||
use_ui @ui do
|
||||
|
@ -627,7 +772,7 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
end
|
||||
|
||||
paths = @fetcher.paths
|
||||
assert_equal "#{@gem_repo}/quick/index.rz", paths.shift
|
||||
assert_equal "#{@gem_repo}quick/index.rz", paths.shift
|
||||
assert_equal marshal_uri, paths.shift
|
||||
assert_equal yaml_uri, paths.shift
|
||||
|
||||
|
@ -637,14 +782,14 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
end
|
||||
|
||||
def test_update_subdir
|
||||
@gem_repo = @gem_repo + "/subdir"
|
||||
@gem_repo = @gem_repo + 'subdir/'
|
||||
|
||||
util_setup_bulk_fetch true
|
||||
|
||||
@source_index.gems.replace({})
|
||||
assert_equal [], @source_index.gems.keys.sort
|
||||
|
||||
uri = @uri.to_s + "/subdir"
|
||||
uri = @uri.to_s + 'subdir/'
|
||||
|
||||
use_ui @ui do
|
||||
@source_index.update uri, true
|
||||
|
@ -656,8 +801,8 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
|
||||
paths = @fetcher.paths
|
||||
|
||||
assert_equal "#{@gem_repo}/quick/index.rz", paths.shift
|
||||
assert_equal "#{@gem_repo}/Marshal.#{@marshal_version}.Z", paths.shift
|
||||
assert_equal "#{@gem_repo}quick/index.rz", paths.shift
|
||||
assert_equal "#{@gem_repo}Marshal.#{@marshal_version}.Z", paths.shift
|
||||
|
||||
assert paths.empty?, paths.join(', ')
|
||||
end
|
||||
|
@ -684,9 +829,9 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
source_index = @source_index.dump
|
||||
|
||||
if compressed then
|
||||
@fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}.Z"] = util_zip source_index
|
||||
@fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}.Z"] = util_zip source_index
|
||||
else
|
||||
@fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] = source_index
|
||||
@fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}"] = source_index
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ class TestGemSourceInfoCache < RubyGemTestCase
|
|||
def teardown
|
||||
super
|
||||
Gem.sources.replace @original_sources
|
||||
Gem::SourceInfoCache.instance_variable_set :@cache, nil
|
||||
end
|
||||
|
||||
def test_self_cache_refreshes
|
||||
|
@ -43,7 +44,7 @@ class TestGemSourceInfoCache < RubyGemTestCase
|
|||
si = Gem::SourceIndex.new
|
||||
si.add_spec @a1
|
||||
|
||||
@fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] = si.dump
|
||||
@fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}"] = si.dump
|
||||
|
||||
Gem.sources.replace %W[#{@gem_repo}]
|
||||
|
||||
|
@ -52,8 +53,9 @@ class TestGemSourceInfoCache < RubyGemTestCase
|
|||
assert_kind_of Gem::SourceInfoCache, Gem::SourceInfoCache.cache
|
||||
assert_equal Gem::SourceInfoCache.cache.object_id,
|
||||
Gem::SourceInfoCache.cache.object_id
|
||||
assert_match %r|Bulk updating|, @ui.output
|
||||
end
|
||||
|
||||
assert_match %r|Bulk updating|, @ui.output
|
||||
end
|
||||
|
||||
def test_self_cache_skips_refresh_based_on_configuration
|
||||
|
@ -61,7 +63,7 @@ class TestGemSourceInfoCache < RubyGemTestCase
|
|||
si = Gem::SourceIndex.new
|
||||
si.add_spec @a1
|
||||
|
||||
@fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] = si.dump
|
||||
@fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}"] = si.dump
|
||||
|
||||
Gem.sources.replace %w[#{@gem_repo}]
|
||||
|
||||
|
@ -78,7 +80,7 @@ class TestGemSourceInfoCache < RubyGemTestCase
|
|||
si = Gem::SourceIndex.new
|
||||
si.add_spec @a1
|
||||
|
||||
@fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] = si.dump
|
||||
@fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}"] = si.dump
|
||||
|
||||
Gem::SourceInfoCache.instance_variable_set :@cache, nil
|
||||
sice = Gem::SourceInfoCacheEntry.new si, 0
|
||||
|
@ -106,7 +108,7 @@ class TestGemSourceInfoCache < RubyGemTestCase
|
|||
end
|
||||
|
||||
def test_cache_data_irreparable
|
||||
@fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] = @source_index.dump
|
||||
@fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}"] = @source_index.dump
|
||||
|
||||
data = { @gem_repo => { 'totally' => 'borked' } }
|
||||
|
||||
|
|
|
@ -15,9 +15,9 @@ class TestGemSourceInfoCacheEntry < RubyGemTestCase
|
|||
end
|
||||
|
||||
def test_refresh
|
||||
@fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}.Z"] =
|
||||
@fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}.Z"] =
|
||||
proc { raise }
|
||||
@fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] = @si.dump
|
||||
@fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}"] = @si.dump
|
||||
|
||||
use_ui @ui do
|
||||
@sic_e.refresh @gem_repo, true
|
||||
|
@ -30,18 +30,20 @@ class TestGemSourceInfoCacheEntry < RubyGemTestCase
|
|||
a1_name = @a1.full_name
|
||||
a2_name = @a2.full_name
|
||||
|
||||
@fetcher.data["#{@gem_repo}/quick/index.rz"] =
|
||||
@fetcher.data["#{@gem_repo}quick/index.rz"] =
|
||||
util_zip [a1_name, a2_name].join("\n")
|
||||
@fetcher.data["#{@gem_repo}/quick/latest_index.rz"] = util_zip a2_name
|
||||
@fetcher.data["#{@gem_repo}/quick/Marshal.#{Gem.marshal_version}/#{a1_name}.gemspec.rz"] = util_zip Marshal.dump(@a1)
|
||||
@fetcher.data["#{@gem_repo}/quick/Marshal.#{Gem.marshal_version}/#{a2_name}.gemspec.rz"] = util_zip Marshal.dump(@a2)
|
||||
@fetcher.data["#{@gem_repo}/Marshal.#{Gem.marshal_version}"] =
|
||||
@fetcher.data["#{@gem_repo}quick/latest_index.rz"] = util_zip a2_name
|
||||
@fetcher.data["#{@gem_repo}quick/Marshal.#{Gem.marshal_version}/#{a1_name}.gemspec.rz"] = util_zip Marshal.dump(@a1)
|
||||
@fetcher.data["#{@gem_repo}quick/Marshal.#{Gem.marshal_version}/#{a2_name}.gemspec.rz"] = util_zip Marshal.dump(@a2)
|
||||
@fetcher.data["#{@gem_repo}Marshal.#{Gem.marshal_version}"] =
|
||||
Marshal.dump @si
|
||||
|
||||
sic_e = Gem::SourceInfoCacheEntry.new Gem::SourceIndex.new, 0
|
||||
|
||||
assert_equal [], sic_e.source_index.map { |n,| n }
|
||||
|
||||
use_ui @ui do
|
||||
sic_e.refresh @gem_repo, false
|
||||
assert sic_e.refresh(@gem_repo, false)
|
||||
end
|
||||
|
||||
assert_equal [a2_name], sic_e.source_index.map { |n,| n }.sort
|
||||
|
@ -63,7 +65,7 @@ class TestGemSourceInfoCacheEntry < RubyGemTestCase
|
|||
si = Gem::SourceIndex.new
|
||||
si.add_spec @a1
|
||||
si.add_spec @b2
|
||||
@fetcher.data["#{@gem_repo}/Marshal.#{@marshal_version}"] = si.dump
|
||||
@fetcher.data["#{@gem_repo}Marshal.#{@marshal_version}"] = si.dump
|
||||
|
||||
use_ui @ui do
|
||||
@sic_e.refresh @gem_repo, true
|
||||
|
|
303
test/rubygems/test_gem_spec_fetcher.rb
Normal file
303
test/rubygems/test_gem_spec_fetcher.rb
Normal file
|
@ -0,0 +1,303 @@
|
|||
require 'test/unit'
|
||||
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
|
||||
require 'rubygems/spec_fetcher'
|
||||
|
||||
class TestGemSpecFetcher < RubyGemTestCase
|
||||
|
||||
def setup
|
||||
super
|
||||
|
||||
@uri = URI.parse @gem_repo
|
||||
|
||||
util_setup_fake_fetcher
|
||||
|
||||
@source_index.add_spec @pl1
|
||||
|
||||
@specs = @source_index.gems.sort.map do |name, spec|
|
||||
[spec.name, spec.version, spec.original_platform]
|
||||
end.sort
|
||||
|
||||
@fetcher.data["#{@gem_repo}specs.#{Gem.marshal_version}.gz"] =
|
||||
util_gzip(Marshal.dump(@specs))
|
||||
|
||||
@latest_specs = @source_index.latest_specs.sort.map do |spec|
|
||||
[spec.name, spec.version, spec.original_platform]
|
||||
end
|
||||
|
||||
@fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"] =
|
||||
util_gzip(Marshal.dump(@latest_specs))
|
||||
|
||||
@sf = Gem::SpecFetcher.new
|
||||
end
|
||||
|
||||
def test_fetch_all
|
||||
@fetcher.data["#{@gem_repo}#{Gem::MARSHAL_SPEC_DIR}#{@a1.full_name}.gemspec.rz"] =
|
||||
util_zip(Marshal.dump(@a1))
|
||||
@fetcher.data["#{@gem_repo}#{Gem::MARSHAL_SPEC_DIR}#{@a2.full_name}.gemspec.rz"] =
|
||||
util_zip(Marshal.dump(@a2))
|
||||
|
||||
dep = Gem::Dependency.new 'a', 1
|
||||
specs_and_sources = @sf.fetch dep, true
|
||||
|
||||
spec_names = specs_and_sources.map do |spec, source_uri|
|
||||
[spec.full_name, source_uri]
|
||||
end
|
||||
|
||||
expected = [[@a1.full_name, @gem_repo], [@a2.full_name, @gem_repo]]
|
||||
|
||||
assert_equal expected, spec_names
|
||||
|
||||
assert_same specs_and_sources.first.last, specs_and_sources.last.last
|
||||
end
|
||||
|
||||
def test_fetch_latest
|
||||
@fetcher.data["#{@gem_repo}#{Gem::MARSHAL_SPEC_DIR}#{@a1.full_name}.gemspec.rz"] =
|
||||
util_zip(Marshal.dump(@a1))
|
||||
@fetcher.data["#{@gem_repo}#{Gem::MARSHAL_SPEC_DIR}#{@a2.full_name}.gemspec.rz"] =
|
||||
util_zip(Marshal.dump(@a2))
|
||||
|
||||
dep = Gem::Dependency.new 'a', 1
|
||||
specs_and_sources = @sf.fetch dep
|
||||
|
||||
spec_names = specs_and_sources.map do |spec, source_uri|
|
||||
[spec.full_name, source_uri]
|
||||
end
|
||||
|
||||
assert_equal [[@a2.full_name, @gem_repo]], spec_names
|
||||
end
|
||||
|
||||
def test_fetch_legacy_repo
|
||||
@fetcher.data["#{@gem_repo}specs.#{Gem.marshal_version}.gz"] = nil
|
||||
@fetcher.data["#{@gem_repo}yaml"] = ''
|
||||
util_setup_source_info_cache @a1, @a2
|
||||
|
||||
dep = Gem::Dependency.new 'a', 1
|
||||
specs = nil
|
||||
|
||||
use_ui @ui do
|
||||
specs = @sf.fetch dep, true
|
||||
end
|
||||
|
||||
expected = <<-EOF
|
||||
WARNING: RubyGems 1.2+ index not found for:
|
||||
\thttp://gems.example.com/
|
||||
|
||||
RubyGems will revert to legacy indexes degrading performance.
|
||||
EOF
|
||||
|
||||
assert_equal expected, @ui.error
|
||||
|
||||
specs = specs.map { |spec, source_uri| [spec.full_name, source_uri] }
|
||||
|
||||
expected = [
|
||||
[@a1.full_name, @gem_repo],
|
||||
[@a2.full_name, @gem_repo],
|
||||
]
|
||||
|
||||
assert_equal expected, specs
|
||||
end
|
||||
|
||||
def test_fetch_platform
|
||||
util_set_arch 'i386-linux'
|
||||
|
||||
@fetcher.data["#{@gem_repo}#{Gem::MARSHAL_SPEC_DIR}#{@pl1.original_name}.gemspec.rz"] =
|
||||
util_zip(Marshal.dump(@pl1))
|
||||
|
||||
dep = Gem::Dependency.new 'pl', 1
|
||||
specs_and_sources = @sf.fetch dep
|
||||
|
||||
spec_names = specs_and_sources.map do |spec, source_uri|
|
||||
[spec.full_name, source_uri]
|
||||
end
|
||||
|
||||
assert_equal [[@pl1.full_name, @gem_repo]], spec_names
|
||||
end
|
||||
|
||||
def test_fetch_spec
|
||||
spec_uri = "#{@gem_repo}#{Gem::MARSHAL_SPEC_DIR}#{@a1.full_name}.gemspec"
|
||||
@fetcher.data["#{spec_uri}.rz"] = util_zip(Marshal.dump(@a1))
|
||||
|
||||
spec = @sf.fetch_spec ['a', Gem::Version.new(1), 'ruby'], @uri
|
||||
assert_equal @a1.full_name, spec.full_name
|
||||
|
||||
cache_dir = @sf.cache_dir URI.parse(spec_uri)
|
||||
|
||||
cache_file = File.join cache_dir, "#{@a1.full_name}.gemspec"
|
||||
|
||||
assert File.exist?(cache_file)
|
||||
end
|
||||
|
||||
def test_fetch_spec_cached
|
||||
spec_uri = "#{@gem_repo}/#{Gem::MARSHAL_SPEC_DIR}#{@a1.full_name}.gemspec"
|
||||
@fetcher.data["#{spec_uri}.rz"] = nil
|
||||
|
||||
cache_dir = @sf.cache_dir URI.parse(spec_uri)
|
||||
FileUtils.mkdir_p cache_dir
|
||||
|
||||
cache_file = File.join cache_dir, "#{@a1.full_name}.gemspec"
|
||||
|
||||
open cache_file, 'wb' do |io|
|
||||
Marshal.dump @a1, io
|
||||
end
|
||||
|
||||
spec = @sf.fetch_spec ['a', Gem::Version.new(1), 'ruby'], @uri
|
||||
assert_equal @a1.full_name, spec.full_name
|
||||
end
|
||||
|
||||
def test_fetch_spec_platform
|
||||
@fetcher.data["#{@gem_repo}#{Gem::MARSHAL_SPEC_DIR}#{@pl1.original_name}.gemspec.rz"] =
|
||||
util_zip(Marshal.dump(@pl1))
|
||||
|
||||
spec = @sf.fetch_spec ['pl', Gem::Version.new(1), 'i386-linux'], @uri
|
||||
|
||||
assert_equal @pl1.full_name, spec.full_name
|
||||
end
|
||||
|
||||
def test_fetch_spec_platform_ruby
|
||||
@fetcher.data["#{@gem_repo}#{Gem::MARSHAL_SPEC_DIR}#{@a1.full_name}.gemspec.rz"] =
|
||||
util_zip(Marshal.dump(@a1))
|
||||
|
||||
spec = @sf.fetch_spec ['a', Gem::Version.new(1), nil], @uri
|
||||
assert_equal @a1.full_name, spec.full_name
|
||||
|
||||
spec = @sf.fetch_spec ['a', Gem::Version.new(1), ''], @uri
|
||||
assert_equal @a1.full_name, spec.full_name
|
||||
end
|
||||
|
||||
def test_find_matching_all
|
||||
dep = Gem::Dependency.new 'a', 1
|
||||
specs = @sf.find_matching dep, true
|
||||
|
||||
expected = [
|
||||
[['a', Gem::Version.new(1), Gem::Platform::RUBY], @gem_repo],
|
||||
[['a', Gem::Version.new(2), Gem::Platform::RUBY], @gem_repo],
|
||||
]
|
||||
|
||||
assert_equal expected, specs
|
||||
end
|
||||
|
||||
def test_find_matching_latest
|
||||
dep = Gem::Dependency.new 'a', 1
|
||||
specs = @sf.find_matching dep
|
||||
|
||||
expected = [
|
||||
[['a', Gem::Version.new(2), Gem::Platform::RUBY], @gem_repo],
|
||||
]
|
||||
|
||||
assert_equal expected, specs
|
||||
end
|
||||
|
||||
def test_find_matching_platform
|
||||
util_set_arch 'i386-linux'
|
||||
|
||||
dep = Gem::Dependency.new 'pl', 1
|
||||
specs = @sf.find_matching dep
|
||||
|
||||
expected = [
|
||||
[['pl', Gem::Version.new(1), 'i386-linux'], @gem_repo],
|
||||
]
|
||||
|
||||
assert_equal expected, specs
|
||||
|
||||
util_set_arch 'i386-freebsd6'
|
||||
|
||||
dep = Gem::Dependency.new 'pl', 1
|
||||
specs = @sf.find_matching dep
|
||||
|
||||
assert_equal [], specs
|
||||
end
|
||||
|
||||
def test_find_all_platforms
|
||||
util_set_arch 'i386-freebsd6'
|
||||
|
||||
dep = Gem::Dependency.new 'pl', 1
|
||||
specs = @sf.find_matching dep, false, false
|
||||
|
||||
expected = [
|
||||
[['pl', Gem::Version.new(1), 'i386-linux'], @gem_repo],
|
||||
]
|
||||
|
||||
assert_equal expected, specs
|
||||
end
|
||||
|
||||
def test_list
|
||||
specs = @sf.list
|
||||
|
||||
assert_equal [@uri], specs.keys
|
||||
assert_equal @latest_specs, specs[@uri].sort
|
||||
end
|
||||
|
||||
def test_list_all
|
||||
specs = @sf.list true
|
||||
|
||||
assert_equal [@uri], specs.keys
|
||||
|
||||
assert_equal @specs, specs[@uri].sort
|
||||
end
|
||||
|
||||
def test_list_cache
|
||||
specs = @sf.list
|
||||
|
||||
assert !specs[@uri].empty?
|
||||
|
||||
@fetcher.data["#{@gem_repo}/latest_specs.#{Gem.marshal_version}.gz"] = nil
|
||||
|
||||
cached_specs = @sf.list
|
||||
|
||||
assert_equal specs, cached_specs
|
||||
end
|
||||
|
||||
def test_list_cache_all
|
||||
specs = @sf.list true
|
||||
|
||||
assert !specs[@uri].empty?
|
||||
|
||||
@fetcher.data["#{@gem_repo}/specs.#{Gem.marshal_version}.gz"] = nil
|
||||
|
||||
cached_specs = @sf.list true
|
||||
|
||||
assert_equal specs, cached_specs
|
||||
end
|
||||
|
||||
def test_load_specs
|
||||
specs = @sf.load_specs @uri, 'specs'
|
||||
|
||||
expected = [
|
||||
['a', Gem::Version.new(1), Gem::Platform::RUBY],
|
||||
['a', Gem::Version.new(2), Gem::Platform::RUBY],
|
||||
['a_evil', Gem::Version.new(9), Gem::Platform::RUBY],
|
||||
['c', Gem::Version.new('1.2'), Gem::Platform::RUBY],
|
||||
['pl', Gem::Version.new(1), 'i386-linux'],
|
||||
]
|
||||
|
||||
assert_equal expected, specs
|
||||
|
||||
cache_dir = File.join Gem.user_home, '.gem', 'specs', 'gems.example.com%80'
|
||||
assert File.exist?(cache_dir), "#{cache_dir} does not exist"
|
||||
|
||||
cache_file = File.join cache_dir, "specs.#{Gem.marshal_version}"
|
||||
assert File.exist?(cache_file)
|
||||
end
|
||||
|
||||
def test_load_specs_cached
|
||||
@fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"] = nil
|
||||
@fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}"] =
|
||||
' ' * Marshal.dump(@latest_specs).length
|
||||
|
||||
cache_dir = File.join Gem.user_home, '.gem', 'specs', 'gems.example.com:80'
|
||||
|
||||
FileUtils.mkdir_p cache_dir
|
||||
|
||||
cache_file = File.join cache_dir, "latest_specs.#{Gem.marshal_version}"
|
||||
|
||||
open cache_file, 'wb' do |io|
|
||||
Marshal.dump @latest_specs, io
|
||||
end
|
||||
|
||||
specs = @sf.load_specs @uri, 'specs'
|
||||
|
||||
assert_equal @specs, specs
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -213,6 +213,15 @@ end
|
|||
assert_equal 'old_platform', same_spec.original_platform
|
||||
end
|
||||
|
||||
def test_add_dependency_with_explicit_type
|
||||
gem = quick_gem "awesome", "1.0" do |awesome|
|
||||
awesome.add_development_dependency "monkey"
|
||||
end
|
||||
|
||||
monkey = gem.dependencies.detect { |d| d.name == "monkey" }
|
||||
assert_equal(:development, monkey.type)
|
||||
end
|
||||
|
||||
def test_author
|
||||
assert_equal 'A User', @a1.author
|
||||
end
|
||||
|
@ -282,6 +291,20 @@ end
|
|||
assert_equal [rake, jabber, pqa], @a1.dependencies
|
||||
end
|
||||
|
||||
def test_dependencies_scoped_by_type
|
||||
gem = quick_gem "awesome", "1.0" do |awesome|
|
||||
awesome.add_runtime_dependency "bonobo", []
|
||||
awesome.add_development_dependency "monkey", []
|
||||
end
|
||||
|
||||
bonobo = Gem::Dependency.new("bonobo", [])
|
||||
monkey = Gem::Dependency.new("monkey", [], :development)
|
||||
|
||||
assert_equal([bonobo, monkey], gem.dependencies)
|
||||
assert_equal([bonobo], gem.runtime_dependencies)
|
||||
assert_equal([monkey], gem.development_dependencies)
|
||||
end
|
||||
|
||||
def test_description
|
||||
assert_equal 'This is a test description', @a1.description
|
||||
end
|
||||
|
@ -423,6 +446,15 @@ end
|
|||
@a1.full_gem_path
|
||||
end
|
||||
|
||||
def test_full_gem_path_double_slash
|
||||
gemhome = @gemhome.sub(/\w\//, '\&/')
|
||||
@a1.loaded_from = File.join gemhome, 'specifications',
|
||||
"#{@a1.full_name}.gemspec"
|
||||
|
||||
assert_equal File.join(@gemhome, 'gems', @a1.full_name),
|
||||
@a1.full_gem_path
|
||||
end
|
||||
|
||||
def test_full_name
|
||||
assert_equal 'a-1', @a1.full_name
|
||||
|
||||
|
@ -531,6 +563,17 @@ end
|
|||
assert_equal ['A working computer'], @a1.requirements
|
||||
end
|
||||
|
||||
def test_runtime_dependencies_legacy
|
||||
# legacy gems don't have a type
|
||||
@a1.runtime_dependencies.each do |dep|
|
||||
dep.instance_variable_set :@type, nil
|
||||
end
|
||||
|
||||
expected = %w[rake jabber4r pqa]
|
||||
|
||||
assert_equal expected, @a1.runtime_dependencies.map { |d| d.name }
|
||||
end
|
||||
|
||||
def test_spaceship_name
|
||||
s1 = quick_gem 'a', '1'
|
||||
s2 = quick_gem 'b', '1'
|
||||
|
@ -570,6 +613,8 @@ end
|
|||
end
|
||||
|
||||
def test_to_ruby
|
||||
@a2.add_runtime_dependency 'b', '1'
|
||||
@a2.dependencies.first.instance_variable_set :@type, nil
|
||||
@a2.required_rubygems_version = Gem::Requirement.new '> 0'
|
||||
|
||||
ruby_code = @a2.to_ruby
|
||||
|
@ -578,8 +623,6 @@ end
|
|||
s.name = %q{a}
|
||||
s.version = \"2\"
|
||||
|
||||
s.specification_version = #{Gem::Specification::CURRENT_SPECIFICATION_VERSION} if s.respond_to? :specification_version=
|
||||
|
||||
s.required_rubygems_version = Gem::Requirement.new(\"> 0\") if s.respond_to? :required_rubygems_version=
|
||||
s.authors = [\"A User\"]
|
||||
s.date = %q{#{Gem::Specification::TODAY.strftime "%Y-%m-%d"}}
|
||||
|
@ -591,6 +634,19 @@ end
|
|||
s.require_paths = [\"lib\"]
|
||||
s.rubygems_version = %q{#{Gem::RubyGemsVersion}}
|
||||
s.summary = %q{this is a summary}
|
||||
|
||||
if s.respond_to? :specification_version then
|
||||
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
||||
s.specification_version = #{Gem::Specification::CURRENT_SPECIFICATION_VERSION}
|
||||
|
||||
if current_version >= 3 then
|
||||
s.add_runtime_dependency(%q<b>, [\"= 1\"])
|
||||
else
|
||||
s.add_dependency(%q<b>, [\"= 1\"])
|
||||
end
|
||||
else
|
||||
s.add_dependency(%q<b>, [\"= 1\"])
|
||||
end
|
||||
end
|
||||
"
|
||||
|
||||
|
@ -613,8 +669,6 @@ end
|
|||
s.version = \"1\"
|
||||
s.platform = Gem::Platform.new(#{expected_platform})
|
||||
|
||||
s.specification_version = 2 if s.respond_to? :specification_version=
|
||||
|
||||
s.required_rubygems_version = Gem::Requirement.new(\">= 0\") if s.respond_to? :required_rubygems_version=
|
||||
s.authors = [\"A User\"]
|
||||
s.date = %q{#{Gem::Specification::TODAY.strftime "%Y-%m-%d"}}
|
||||
|
@ -633,9 +687,24 @@ end
|
|||
s.summary = %q{this is a summary}
|
||||
s.test_files = [\"test/suite.rb\"]
|
||||
|
||||
s.add_dependency(%q<rake>, [\"> 0.4\"])
|
||||
s.add_dependency(%q<jabber4r>, [\"> 0.0.0\"])
|
||||
s.add_dependency(%q<pqa>, [\"> 0.4\", \"<= 0.6\"])
|
||||
if s.respond_to? :specification_version then
|
||||
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
||||
s.specification_version = 3
|
||||
|
||||
if current_version >= 3 then
|
||||
s.add_runtime_dependency(%q<rake>, [\"> 0.4\"])
|
||||
s.add_runtime_dependency(%q<jabber4r>, [\"> 0.0.0\"])
|
||||
s.add_runtime_dependency(%q<pqa>, [\"> 0.4\", \"<= 0.6\"])
|
||||
else
|
||||
s.add_dependency(%q<rake>, [\"> 0.4\"])
|
||||
s.add_dependency(%q<jabber4r>, [\"> 0.0.0\"])
|
||||
s.add_dependency(%q<pqa>, [\"> 0.4\", \"<= 0.6\"])
|
||||
end
|
||||
else
|
||||
s.add_dependency(%q<rake>, [\"> 0.4\"])
|
||||
s.add_dependency(%q<jabber4r>, [\"> 0.0.0\"])
|
||||
s.add_dependency(%q<pqa>, [\"> 0.4\", \"<= 0.6\"])
|
||||
end
|
||||
end
|
||||
"
|
||||
|
||||
|
|
|
@ -15,6 +15,12 @@ class TestGemUninstaller < GemInstallerTestCase
|
|||
end
|
||||
end
|
||||
|
||||
def test_initialize_expand_path
|
||||
uninstaller = Gem::Uninstaller.new nil, :install_dir => '/foo//bar'
|
||||
|
||||
assert_match %r|/foo/bar$|, uninstaller.instance_variable_get(:@gem_home)
|
||||
end
|
||||
|
||||
def test_remove_executables_force_keep
|
||||
uninstaller = Gem::Uninstaller.new nil, :executables => false
|
||||
|
||||
|
@ -39,5 +45,20 @@ class TestGemUninstaller < GemInstallerTestCase
|
|||
assert_equal false, File.exist?(File.join(@gemhome, 'bin', 'executable'))
|
||||
end
|
||||
|
||||
def test_path_ok_eh
|
||||
uninstaller = Gem::Uninstaller.new nil
|
||||
|
||||
assert_equal true, uninstaller.path_ok?(@spec)
|
||||
end
|
||||
|
||||
def test_path_ok_eh_legacy
|
||||
uninstaller = Gem::Uninstaller.new nil
|
||||
|
||||
@spec.loaded_from.gsub! @spec.full_name, '\&-legacy'
|
||||
@spec.platform = 'legacy'
|
||||
|
||||
assert_equal true, uninstaller.path_ok?(@spec)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -71,10 +71,14 @@ class TestGemVersion < RubyGemTestCase
|
|||
end
|
||||
|
||||
def test_eql_eh
|
||||
v = Gem::Version.new("1.2")
|
||||
v1_2 = Gem::Version.new '1.2'
|
||||
v1_2_0 = Gem::Version.new '1.2.0'
|
||||
|
||||
assert_equal true, v.eql?(@v1_2)
|
||||
assert_equal true, @v1_2.eql?(v)
|
||||
assert_equal true, v1_2.eql?(@v1_2)
|
||||
assert_equal true, @v1_2.eql?(v1_2)
|
||||
|
||||
assert_equal false, v1_2_0.eql?(@v1_2)
|
||||
assert_equal false, @v1_2.eql?(v1_2_0)
|
||||
|
||||
assert_equal false, @v1_2.eql?(@v1_3)
|
||||
assert_equal false, @v1_3.eql?(@v1_2)
|
||||
|
@ -91,8 +95,13 @@ class TestGemVersion < RubyGemTestCase
|
|||
end
|
||||
|
||||
def test_hash
|
||||
v = Gem::Version.new("1.2")
|
||||
assert_equal v.hash, @v1_2.hash
|
||||
v1_2 = Gem::Version.new "1.2"
|
||||
v1_2_0 = Gem::Version.new "1.2.0"
|
||||
|
||||
assert_equal v1_2.hash, @v1_2.hash
|
||||
|
||||
assert_not_equal v1_2_0.hash, @v1_2.hash
|
||||
|
||||
assert_not_equal @v1_2.hash, @v1_3.hash
|
||||
end
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ class TestKernel < RubyGemTestCase
|
|||
gem 'a', '= 2'
|
||||
end
|
||||
|
||||
assert_match(/activate a \(= 2\)/, ex.message)
|
||||
assert_match(/activate a \(= 2, runtime\)/, ex.message)
|
||||
assert_match(/activated a-1/, ex.message)
|
||||
|
||||
assert $:.any? { |p| %r{a-1/lib} =~ p }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue