mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Update to RubyGems 1.1.1 r1701.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@15980 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
0ae6c7f816
commit
e72b71d56a
31 changed files with 272 additions and 888 deletions
|
@ -1,3 +1,7 @@
|
|||
Sat Apr 12 05:55:57 2008 Eric Hodel <drbrain@segment7.net>
|
||||
|
||||
* lib/rubygems*, test/rubygems*: Update to RubyGems 1.1.1 r1701.
|
||||
|
||||
Sat Apr 12 03:13:38 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* file.c (file_expand_path): set external encoding.
|
||||
|
|
|
@ -97,7 +97,7 @@ module Gem
|
|||
|
||||
@configuration = nil
|
||||
@loaded_specs = {}
|
||||
@platforms = nil
|
||||
@platforms = []
|
||||
@ruby = nil
|
||||
@sources = []
|
||||
|
||||
|
@ -215,7 +215,7 @@ module Gem
|
|||
|
||||
def self.bindir(install_dir=Gem.dir)
|
||||
return File.join(install_dir, 'bin') unless
|
||||
install_dir.to_s == Gem.default_dir
|
||||
install_dir.to_s == Gem.default_dir
|
||||
Gem.default_bindir
|
||||
end
|
||||
|
||||
|
@ -450,11 +450,22 @@ module Gem
|
|||
@gem_path
|
||||
end
|
||||
|
||||
##
|
||||
# Set array of platforms this RubyGems supports (primarily for testing).
|
||||
|
||||
def self.platforms=(platforms)
|
||||
@platforms = platforms
|
||||
end
|
||||
|
||||
##
|
||||
# Array of platforms this RubyGems supports.
|
||||
|
||||
def self.platforms
|
||||
@platforms ||= [Gem::Platform::RUBY, Gem::Platform.local]
|
||||
@platforms ||= []
|
||||
if @platforms.empty?
|
||||
@platforms = [Gem::Platform::RUBY, Gem::Platform.local]
|
||||
end
|
||||
@platforms
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -463,13 +474,26 @@ module Gem
|
|||
def self.prefix
|
||||
prefix = File.dirname File.expand_path(__FILE__)
|
||||
|
||||
if prefix == File.expand_path(ConfigMap[:sitelibdir]) then
|
||||
if File.dirname(prefix) == File.expand_path(ConfigMap[:sitelibdir]) or
|
||||
File.dirname(prefix) == File.expand_path(ConfigMap[:libdir]) or
|
||||
'lib' != File.basename(prefix) then
|
||||
nil
|
||||
else
|
||||
File.dirname prefix
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Refresh source_index from disk and clear searcher.
|
||||
|
||||
def self.refresh
|
||||
source_index.refresh!
|
||||
|
||||
MUTEX.synchronize do
|
||||
@searcher = nil
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Safely read a file in binary mode on all platforms.
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ module Gem
|
|||
say Gem::Command::HELP
|
||||
terminate_interaction(0)
|
||||
when '-v', '--version'
|
||||
say Gem::RubyGemsPackageVersion
|
||||
say Gem::RubyGemsVersion
|
||||
terminate_interaction(0)
|
||||
when /^-/
|
||||
alert_error "Invalid option: #{args[0]}. See 'gem --help'."
|
||||
|
|
|
@ -39,7 +39,7 @@ class Gem::Commands::EnvironmentCommand < Gem::Command
|
|||
when nil then
|
||||
out = "RubyGems Environment:\n"
|
||||
|
||||
out << " - RUBYGEMS VERSION: #{Gem::RubyGemsVersion} (#{Gem::RubyGemsPackageVersion})\n"
|
||||
out << " - RUBYGEMS VERSION: #{Gem::RubyGemsVersion}\n"
|
||||
|
||||
out << " - RUBY VERSION: #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}"
|
||||
out << " patchlevel #{RUBY_PATCHLEVEL}" if defined? RUBY_PATCHLEVEL
|
||||
|
|
|
@ -126,6 +126,7 @@ revert the gem.
|
|||
end
|
||||
|
||||
installer.generate_bin
|
||||
installer.build_extensions
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -82,13 +82,15 @@ class Gem::Commands::QueryCommand < Gem::Command
|
|||
say "*** REMOTE GEMS ***"
|
||||
say
|
||||
|
||||
all = options[:all]
|
||||
|
||||
begin
|
||||
Gem::SourceInfoCache.cache.refresh options[:all]
|
||||
Gem::SourceInfoCache.cache all
|
||||
rescue Gem::RemoteFetcher::FetchError
|
||||
# no network
|
||||
end
|
||||
|
||||
output_query_results Gem::SourceInfoCache.search(name, false, true)
|
||||
output_query_results Gem::SourceInfoCache.search(name, false, all)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ class Gem::Commands::SourcesCommand < Gem::Command
|
|||
end
|
||||
|
||||
if options[:update] then
|
||||
Gem::SourceInfoCache.cache.refresh true
|
||||
Gem::SourceInfoCache.cache true
|
||||
Gem::SourceInfoCache.cache.flush
|
||||
|
||||
say "source cache successfully updated"
|
||||
|
|
|
@ -58,7 +58,7 @@ class Gem::Commands::UpdateCommand < Gem::Command
|
|||
say "Updating installed gems"
|
||||
end
|
||||
|
||||
hig = {}
|
||||
hig = {} # highest installed gems
|
||||
|
||||
Gem::SourceIndex.from_installed_gems.each do |name, spec|
|
||||
if hig[spec.name].nil? or hig[spec.name].version < spec.version then
|
||||
|
@ -67,7 +67,7 @@ class Gem::Commands::UpdateCommand < Gem::Command
|
|||
end
|
||||
|
||||
pattern = if options[:args].empty? then
|
||||
//
|
||||
//
|
||||
else
|
||||
Regexp.union(*options[:args])
|
||||
end
|
||||
|
@ -78,12 +78,14 @@ class Gem::Commands::UpdateCommand < Gem::Command
|
|||
|
||||
updated = []
|
||||
|
||||
# HACK use the real API
|
||||
installer = Gem::DependencyInstaller.new options
|
||||
|
||||
gems_to_update.uniq.sort.each do |name|
|
||||
next if updated.any? { |spec| spec.name == name }
|
||||
|
||||
say "Updating #{name}"
|
||||
installer = Gem::DependencyInstaller.new options
|
||||
installer.install name
|
||||
|
||||
installer.installed_gems.each do |spec|
|
||||
updated << spec
|
||||
say "Successfully installed #{spec.full_name}"
|
||||
|
@ -115,6 +117,7 @@ class Gem::Commands::UpdateCommand < Gem::Command
|
|||
args.push '--prefix', Gem.prefix unless Gem.prefix.nil?
|
||||
args << '--no-rdoc' unless options[:generate_rdoc]
|
||||
args << '--no-ri' unless options[:generate_ri]
|
||||
args << '--no-format-executable' if options[:no_format_executable]
|
||||
|
||||
update_dir = File.join Gem.dir, 'gems', "rubygems-update-#{version}"
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ class Gem::DependencyInstaller
|
|||
end
|
||||
|
||||
all = requirements.length > 1 ||
|
||||
requirements.first != ">=" || requirements.first != ">"
|
||||
(requirements.first != ">=" and requirements.first != ">")
|
||||
|
||||
found = Gem::SourceInfoCache.search_with_source dep, true, all
|
||||
|
||||
|
@ -189,7 +189,13 @@ class Gem::DependencyInstaller
|
|||
say "Installing gem #{spec.full_name}" if Gem.configuration.really_verbose
|
||||
|
||||
_, source_uri = @specs_and_sources.assoc spec
|
||||
local_gem_path = Gem::RemoteFetcher.fetcher.download spec, source_uri
|
||||
begin
|
||||
local_gem_path = Gem::RemoteFetcher.fetcher.download spec, source_uri,
|
||||
@install_dir
|
||||
rescue Gem::RemoteFetcher::FetchError
|
||||
next if @force
|
||||
raise
|
||||
end
|
||||
|
||||
inst = Gem::Installer.new local_gem_path,
|
||||
:env_shebang => @env_shebang,
|
||||
|
|
|
@ -64,6 +64,12 @@ module Gem
|
|||
|
||||
FileUtils.mkdir_p @doc_dir unless File.exist?(@doc_dir)
|
||||
|
||||
begin
|
||||
gem 'rdoc'
|
||||
rescue Gem::LoadError
|
||||
# use built-in RDoc
|
||||
end
|
||||
|
||||
begin
|
||||
require 'rdoc/rdoc'
|
||||
rescue LoadError => e
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
if RUBY_VERSION > '1.9' then
|
||||
require 'open-uri'
|
||||
else
|
||||
require 'rubygems/open-uri'
|
||||
end
|
|
@ -85,7 +85,7 @@ class Gem::Indexer
|
|||
progress.updated spec.original_name
|
||||
|
||||
rescue SignalException => e
|
||||
alert_error "Recieved signal, exiting"
|
||||
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"}"
|
||||
|
|
|
@ -1,773 +0,0 @@
|
|||
require 'uri'
|
||||
require 'stringio'
|
||||
require 'time'
|
||||
|
||||
# :stopdoc:
|
||||
module Kernel
|
||||
private
|
||||
alias rubygems_open_uri_original_open open # :nodoc:
|
||||
|
||||
# makes possible to open various resources including URIs.
|
||||
# If the first argument respond to `open' method,
|
||||
# the method is called with the rest arguments.
|
||||
#
|
||||
# If the first argument is a string which begins with xxx://,
|
||||
# it is parsed by URI.parse. If the parsed object respond to `open' method,
|
||||
# the method is called with the rest arguments.
|
||||
#
|
||||
# Otherwise original open is called.
|
||||
#
|
||||
# Since open-uri.rb provides URI::HTTP#open, URI::HTTPS#open and
|
||||
# URI::FTP#open,
|
||||
# Kernel[#.]open can accepts such URIs and strings which begins with
|
||||
# http://, https:// and ftp://.
|
||||
# In these case, the opened file object is extended by OpenURI::Meta.
|
||||
def open(name, *rest, &block) # :doc:
|
||||
if name.respond_to?(:open)
|
||||
name.open(*rest, &block)
|
||||
elsif name.respond_to?(:to_str) &&
|
||||
%r{\A[A-Za-z][A-Za-z0-9+\-\.]*://} =~ name &&
|
||||
(uri = URI.parse(name)).respond_to?(:open)
|
||||
uri.open(*rest, &block)
|
||||
else
|
||||
rubygems_open_uri_original_open(name, *rest, &block)
|
||||
end
|
||||
end
|
||||
module_function :open
|
||||
end
|
||||
|
||||
# OpenURI is an easy-to-use wrapper for net/http, net/https and net/ftp.
|
||||
#
|
||||
#== Example
|
||||
#
|
||||
# It is possible to open http/https/ftp URL as usual like opening a file:
|
||||
#
|
||||
# open("http://www.ruby-lang.org/") {|f|
|
||||
# f.each_line {|line| p line}
|
||||
# }
|
||||
#
|
||||
# The opened file has several methods for meta information as follows since
|
||||
# it is extended by OpenURI::Meta.
|
||||
#
|
||||
# open("http://www.ruby-lang.org/en") {|f|
|
||||
# f.each_line {|line| p line}
|
||||
# p f.base_uri # <URI::HTTP:0x40e6ef2 URL:http://www.ruby-lang.org/en/>
|
||||
# p f.content_type # "text/html"
|
||||
# p f.charset # "iso-8859-1"
|
||||
# p f.content_encoding # []
|
||||
# p f.last_modified # Thu Dec 05 02:45:02 UTC 2002
|
||||
# }
|
||||
#
|
||||
# Additional header fields can be specified by an optional hash argument.
|
||||
#
|
||||
# open("http://www.ruby-lang.org/en/",
|
||||
# "User-Agent" => "Ruby/#{RUBY_VERSION}",
|
||||
# "From" => "foo@bar.invalid",
|
||||
# "Referer" => "http://www.ruby-lang.org/") {|f|
|
||||
# # ...
|
||||
# }
|
||||
#
|
||||
# The environment variables such as http_proxy, https_proxy and ftp_proxy
|
||||
# are in effect by default. :proxy => nil disables proxy.
|
||||
#
|
||||
# open("http://www.ruby-lang.org/en/raa.html", :proxy => nil) {|f|
|
||||
# # ...
|
||||
# }
|
||||
#
|
||||
# URI objects can be opened in a similar way.
|
||||
#
|
||||
# uri = URI.parse("http://www.ruby-lang.org/en/")
|
||||
# uri.open {|f|
|
||||
# # ...
|
||||
# }
|
||||
#
|
||||
# URI objects can be read directly. The returned string is also extended by
|
||||
# OpenURI::Meta.
|
||||
#
|
||||
# str = uri.read
|
||||
# p str.base_uri
|
||||
#
|
||||
# Author:: Tanaka Akira <akr@m17n.org>
|
||||
|
||||
module OpenURI
|
||||
Options = {
|
||||
:proxy => true,
|
||||
:proxy_http_basic_authentication => true,
|
||||
:progress_proc => true,
|
||||
:content_length_proc => true,
|
||||
:http_basic_authentication => true,
|
||||
:read_timeout => true,
|
||||
:ssl_ca_cert => nil,
|
||||
:ssl_verify_mode => nil,
|
||||
}
|
||||
|
||||
def OpenURI.check_options(options) # :nodoc:
|
||||
options.each {|k, v|
|
||||
next unless Symbol === k
|
||||
unless Options.include? k
|
||||
raise ArgumentError, "unrecognized option: #{k}"
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def OpenURI.scan_open_optional_arguments(*rest) # :nodoc:
|
||||
if !rest.empty? && (String === rest.first || Integer === rest.first)
|
||||
mode = rest.shift
|
||||
if !rest.empty? && Integer === rest.first
|
||||
perm = rest.shift
|
||||
end
|
||||
end
|
||||
return mode, perm, rest
|
||||
end
|
||||
|
||||
def OpenURI.open_uri(name, *rest) # :nodoc:
|
||||
uri = URI::Generic === name ? name : URI.parse(name)
|
||||
mode, perm, rest = OpenURI.scan_open_optional_arguments(*rest)
|
||||
options = rest.shift if !rest.empty? && Hash === rest.first
|
||||
raise ArgumentError.new("extra arguments") if !rest.empty?
|
||||
options ||= {}
|
||||
OpenURI.check_options(options)
|
||||
|
||||
unless mode == nil ||
|
||||
mode == 'r' || mode == 'rb' ||
|
||||
mode == File::RDONLY
|
||||
raise ArgumentError.new("invalid access mode #{mode} (#{uri.class} resource is read only.)")
|
||||
end
|
||||
|
||||
io = open_loop(uri, options)
|
||||
if block_given?
|
||||
begin
|
||||
yield io
|
||||
ensure
|
||||
io.close
|
||||
end
|
||||
else
|
||||
io
|
||||
end
|
||||
end
|
||||
|
||||
def OpenURI.open_loop(uri, options) # :nodoc:
|
||||
proxy_opts = []
|
||||
proxy_opts << :proxy_http_basic_authentication if options.include? :proxy_http_basic_authentication
|
||||
proxy_opts << :proxy if options.include? :proxy
|
||||
proxy_opts.compact!
|
||||
if 1 < proxy_opts.length
|
||||
raise ArgumentError, "multiple proxy options specified"
|
||||
end
|
||||
case proxy_opts.first
|
||||
when :proxy_http_basic_authentication
|
||||
opt_proxy, proxy_user, proxy_pass = options.fetch(:proxy_http_basic_authentication)
|
||||
proxy_user = proxy_user.to_str
|
||||
proxy_pass = proxy_pass.to_str
|
||||
if opt_proxy == true
|
||||
raise ArgumentError.new("Invalid authenticated proxy option: #{options[:proxy_http_basic_authentication].inspect}")
|
||||
end
|
||||
when :proxy
|
||||
opt_proxy = options.fetch(:proxy)
|
||||
proxy_user = nil
|
||||
proxy_pass = nil
|
||||
when nil
|
||||
opt_proxy = true
|
||||
proxy_user = nil
|
||||
proxy_pass = nil
|
||||
end
|
||||
case opt_proxy
|
||||
when true
|
||||
find_proxy = lambda {|u| pxy = u.find_proxy; pxy ? [pxy, nil, nil] : nil}
|
||||
when nil, false
|
||||
find_proxy = lambda {|u| nil}
|
||||
when String
|
||||
opt_proxy = URI.parse(opt_proxy)
|
||||
find_proxy = lambda {|u| [opt_proxy, proxy_user, proxy_pass]}
|
||||
when URI::Generic
|
||||
find_proxy = lambda {|u| [opt_proxy, proxy_user, proxy_pass]}
|
||||
else
|
||||
raise ArgumentError.new("Invalid proxy option: #{opt_proxy}")
|
||||
end
|
||||
|
||||
uri_set = {}
|
||||
buf = nil
|
||||
while true
|
||||
redirect = catch(:open_uri_redirect) {
|
||||
buf = Buffer.new
|
||||
uri.buffer_open(buf, find_proxy.call(uri), options)
|
||||
nil
|
||||
}
|
||||
if redirect
|
||||
if redirect.relative?
|
||||
# Although it violates RFC2616, Location: field may have relative
|
||||
# URI. It is converted to absolute URI using uri as a base URI.
|
||||
redirect = uri + redirect
|
||||
end
|
||||
unless OpenURI.redirectable?(uri, redirect)
|
||||
raise "redirection forbidden: #{uri} -> #{redirect}"
|
||||
end
|
||||
if options.include? :http_basic_authentication
|
||||
# send authentication only for the URI directly specified.
|
||||
options = options.dup
|
||||
options.delete :http_basic_authentication
|
||||
end
|
||||
uri = redirect
|
||||
raise "HTTP redirection loop: #{uri}" if uri_set.include? uri.to_s
|
||||
uri_set[uri.to_s] = true
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
io = buf.io
|
||||
io.base_uri = uri
|
||||
io
|
||||
end
|
||||
|
||||
def OpenURI.redirectable?(uri1, uri2) # :nodoc:
|
||||
# This test is intended to forbid a redirection from http://... to
|
||||
# file:///etc/passwd.
|
||||
# However this is ad hoc. It should be extensible/configurable.
|
||||
uri1.scheme.downcase == uri2.scheme.downcase ||
|
||||
(/\A(?:http|ftp)\z/i =~ uri1.scheme && /\A(?:http|ftp)\z/i =~ uri2.scheme)
|
||||
end
|
||||
|
||||
def OpenURI.open_http(buf, target, proxy, options) # :nodoc:
|
||||
if proxy
|
||||
proxy_uri, proxy_user, proxy_pass = proxy
|
||||
raise "Non-HTTP proxy URI: #{proxy_uri}" if proxy_uri.class != URI::HTTP
|
||||
end
|
||||
|
||||
if target.userinfo && "1.9.0" <= RUBY_VERSION
|
||||
# don't raise for 1.8 because compatibility.
|
||||
raise ArgumentError, "userinfo not supported. [RFC3986]"
|
||||
end
|
||||
|
||||
header = {}
|
||||
options.each {|k, v| header[k] = v if String === k }
|
||||
|
||||
require 'net/http'
|
||||
klass = Net::HTTP
|
||||
if URI::HTTP === target
|
||||
# HTTP or HTTPS
|
||||
if proxy
|
||||
if proxy_user && proxy_pass
|
||||
klass = Net::HTTP::Proxy(proxy_uri.host, proxy_uri.port, proxy_user, proxy_pass)
|
||||
else
|
||||
klass = Net::HTTP::Proxy(proxy_uri.host, proxy_uri.port)
|
||||
end
|
||||
end
|
||||
target_host = target.host
|
||||
target_port = target.port
|
||||
request_uri = target.request_uri
|
||||
else
|
||||
# FTP over HTTP proxy
|
||||
target_host = proxy_uri.host
|
||||
target_port = proxy_uri.port
|
||||
request_uri = target.to_s
|
||||
if proxy_user && proxy_pass
|
||||
header["Proxy-Authorization"] = 'Basic ' + ["#{proxy_user}:#{proxy_pass}"].pack('m').delete("\r\n")
|
||||
end
|
||||
end
|
||||
|
||||
http = klass.new(target_host, target_port)
|
||||
if target.class == URI::HTTPS
|
||||
require 'net/https'
|
||||
http.use_ssl = true
|
||||
http.verify_mode = options[:ssl_verify_mode] || OpenSSL::SSL::VERIFY_PEER
|
||||
store = OpenSSL::X509::Store.new
|
||||
if options[:ssl_ca_cert]
|
||||
if File.directory? options[:ssl_ca_cert]
|
||||
store.add_path options[:ssl_ca_cert]
|
||||
else
|
||||
store.add_file options[:ssl_ca_cert]
|
||||
end
|
||||
else
|
||||
store.set_default_paths
|
||||
end
|
||||
store.set_default_paths
|
||||
http.cert_store = store
|
||||
end
|
||||
if options.include? :read_timeout
|
||||
http.read_timeout = options[:read_timeout]
|
||||
end
|
||||
|
||||
resp = nil
|
||||
http.start {
|
||||
if target.class == URI::HTTPS
|
||||
# xxx: information hiding violation
|
||||
sock = http.instance_variable_get(:@socket)
|
||||
if sock.respond_to?(:io)
|
||||
sock = sock.io # 1.9
|
||||
else
|
||||
sock = sock.instance_variable_get(:@socket) # 1.8
|
||||
end
|
||||
sock.post_connection_check(target_host)
|
||||
end
|
||||
req = Net::HTTP::Get.new(request_uri, header)
|
||||
if options.include? :http_basic_authentication
|
||||
user, pass = options[:http_basic_authentication]
|
||||
req.basic_auth user, pass
|
||||
end
|
||||
http.request(req) {|response|
|
||||
resp = response
|
||||
if options[:content_length_proc] && Net::HTTPSuccess === resp
|
||||
if resp.key?('Content-Length')
|
||||
options[:content_length_proc].call(resp['Content-Length'].to_i)
|
||||
else
|
||||
options[:content_length_proc].call(nil)
|
||||
end
|
||||
end
|
||||
resp.read_body {|str|
|
||||
buf << str
|
||||
if options[:progress_proc] && Net::HTTPSuccess === resp
|
||||
options[:progress_proc].call(buf.size)
|
||||
end
|
||||
}
|
||||
}
|
||||
}
|
||||
io = buf.io
|
||||
io.rewind
|
||||
io.status = [resp.code, resp.message]
|
||||
resp.each {|name,value| buf.io.meta_add_field name, value }
|
||||
case resp
|
||||
when Net::HTTPSuccess
|
||||
when Net::HTTPMovedPermanently, # 301
|
||||
Net::HTTPFound, # 302
|
||||
Net::HTTPSeeOther, # 303
|
||||
Net::HTTPTemporaryRedirect # 307
|
||||
throw :open_uri_redirect, URI.parse(resp['location'])
|
||||
else
|
||||
raise OpenURI::HTTPError.new(io.status.join(' '), io)
|
||||
end
|
||||
end
|
||||
|
||||
class HTTPError < StandardError
|
||||
def initialize(message, io)
|
||||
super(message)
|
||||
@io = io
|
||||
end
|
||||
attr_reader :io
|
||||
end
|
||||
|
||||
class Buffer # :nodoc:
|
||||
def initialize
|
||||
@io = StringIO.new
|
||||
@size = 0
|
||||
end
|
||||
attr_reader :size
|
||||
|
||||
StringMax = 10240
|
||||
def <<(str)
|
||||
@io << str
|
||||
@size += str.length
|
||||
if StringIO === @io && StringMax < @size
|
||||
require 'tempfile'
|
||||
io = Tempfile.new('open-uri')
|
||||
io.binmode
|
||||
Meta.init io, @io if @io.respond_to? :meta
|
||||
io << @io.string
|
||||
@io = io
|
||||
end
|
||||
end
|
||||
|
||||
def io
|
||||
Meta.init @io unless @io.respond_to? :meta
|
||||
@io
|
||||
end
|
||||
end
|
||||
|
||||
# Mixin for holding meta-information.
|
||||
module Meta
|
||||
def Meta.init(obj, src=nil) # :nodoc:
|
||||
obj.extend Meta
|
||||
obj.instance_eval {
|
||||
@base_uri = nil
|
||||
@meta = {}
|
||||
}
|
||||
if src
|
||||
obj.status = src.status
|
||||
obj.base_uri = src.base_uri
|
||||
src.meta.each {|name, value|
|
||||
obj.meta_add_field(name, value)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
# returns an Array which consists status code and message.
|
||||
attr_accessor :status
|
||||
|
||||
# returns a URI which is base of relative URIs in the data.
|
||||
# It may differ from the URI supplied by a user because redirection.
|
||||
attr_accessor :base_uri
|
||||
|
||||
# returns a Hash which represents header fields.
|
||||
# The Hash keys are downcased for canonicalization.
|
||||
attr_reader :meta
|
||||
|
||||
def meta_add_field(name, value) # :nodoc:
|
||||
@meta[name.downcase] = value
|
||||
end
|
||||
|
||||
# returns a Time which represents Last-Modified field.
|
||||
def last_modified
|
||||
if v = @meta['last-modified']
|
||||
Time.httpdate(v)
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
RE_LWS = /[\r\n\t ]+/n
|
||||
RE_TOKEN = %r{[^\x00- ()<>@,;:\\"/\[\]?={}\x7f]+}n
|
||||
RE_QUOTED_STRING = %r{"(?:[\r\n\t !#-\[\]-~\x80-\xff]|\\[\x00-\x7f])*"}n
|
||||
RE_PARAMETERS = %r{(?:;#{RE_LWS}?#{RE_TOKEN}#{RE_LWS}?=#{RE_LWS}?(?:#{RE_TOKEN}|#{RE_QUOTED_STRING})#{RE_LWS}?)*}n
|
||||
|
||||
def content_type_parse # :nodoc:
|
||||
v = @meta['content-type']
|
||||
# The last (?:;#{RE_LWS}?)? matches extra ";" which violates RFC2045.
|
||||
if v && %r{\A#{RE_LWS}?(#{RE_TOKEN})#{RE_LWS}?/(#{RE_TOKEN})#{RE_LWS}?(#{RE_PARAMETERS})(?:;#{RE_LWS}?)?\z}no =~ v
|
||||
type = $1.downcase
|
||||
subtype = $2.downcase
|
||||
parameters = []
|
||||
$3.scan(/;#{RE_LWS}?(#{RE_TOKEN})#{RE_LWS}?=#{RE_LWS}?(?:(#{RE_TOKEN})|(#{RE_QUOTED_STRING}))/no) {|att, val, qval|
|
||||
val = qval.gsub(/[\r\n\t !#-\[\]-~\x80-\xff]+|(\\[\x00-\x7f])/n) { $1 ? $1[1,1] : $& } if qval
|
||||
parameters << [att.downcase, val]
|
||||
}
|
||||
["#{type}/#{subtype}", *parameters]
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# returns "type/subtype" which is MIME Content-Type.
|
||||
# It is downcased for canonicalization.
|
||||
# Content-Type parameters are stripped.
|
||||
def content_type
|
||||
type, *parameters = content_type_parse
|
||||
type || 'application/octet-stream'
|
||||
end
|
||||
|
||||
# returns a charset parameter in Content-Type field.
|
||||
# It is downcased for canonicalization.
|
||||
#
|
||||
# If charset parameter is not given but a block is given,
|
||||
# the block is called and its result is returned.
|
||||
# It can be used to guess charset.
|
||||
#
|
||||
# If charset parameter and block is not given,
|
||||
# nil is returned except text type in HTTP.
|
||||
# In that case, "iso-8859-1" is returned as defined by RFC2616 3.7.1.
|
||||
def charset
|
||||
type, *parameters = content_type_parse
|
||||
if pair = parameters.assoc('charset')
|
||||
pair.last.downcase
|
||||
elsif block_given?
|
||||
yield
|
||||
elsif type && %r{\Atext/} =~ type &&
|
||||
@base_uri && /\Ahttp\z/i =~ @base_uri.scheme
|
||||
"iso-8859-1" # RFC2616 3.7.1
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# returns a list of encodings in Content-Encoding field
|
||||
# as an Array of String.
|
||||
# The encodings are downcased for canonicalization.
|
||||
def content_encoding
|
||||
v = @meta['content-encoding']
|
||||
if v && %r{\A#{RE_LWS}?#{RE_TOKEN}#{RE_LWS}?(?:,#{RE_LWS}?#{RE_TOKEN}#{RE_LWS}?)*}o =~ v
|
||||
v.scan(RE_TOKEN).map {|content_coding| content_coding.downcase}
|
||||
else
|
||||
[]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Mixin for HTTP and FTP URIs.
|
||||
module OpenRead
|
||||
# OpenURI::OpenRead#open provides `open' for URI::HTTP and URI::FTP.
|
||||
#
|
||||
# OpenURI::OpenRead#open takes optional 3 arguments as:
|
||||
# OpenURI::OpenRead#open([mode [, perm]] [, options]) [{|io| ... }]
|
||||
#
|
||||
# `mode', `perm' is same as Kernel#open.
|
||||
#
|
||||
# However, `mode' must be read mode because OpenURI::OpenRead#open doesn't
|
||||
# support write mode (yet).
|
||||
# Also `perm' is just ignored because it is meaningful only for file
|
||||
# creation.
|
||||
#
|
||||
# `options' must be a hash.
|
||||
#
|
||||
# Each pairs which key is a string in the hash specify a extra header
|
||||
# field for HTTP.
|
||||
# I.e. it is ignored for FTP without HTTP proxy.
|
||||
#
|
||||
# The hash may include other options which key is a symbol:
|
||||
#
|
||||
# [:proxy]
|
||||
# Synopsis:
|
||||
# :proxy => "http://proxy.foo.com:8000/"
|
||||
# :proxy => URI.parse("http://proxy.foo.com:8000/")
|
||||
# :proxy => true
|
||||
# :proxy => false
|
||||
# :proxy => nil
|
||||
#
|
||||
# If :proxy option is specified, the value should be String, URI,
|
||||
# boolean or nil.
|
||||
# When String or URI is given, it is treated as proxy URI.
|
||||
# When true is given or the option itself is not specified,
|
||||
# environment variable `scheme_proxy' is examined.
|
||||
# `scheme' is replaced by `http', `https' or `ftp'.
|
||||
# When false or nil is given, the environment variables are ignored and
|
||||
# connection will be made to a server directly.
|
||||
#
|
||||
# [:proxy_http_basic_authentication]
|
||||
# Synopsis:
|
||||
# :proxy_http_basic_authentication => ["http://proxy.foo.com:8000/", "proxy-user", "proxy-password"]
|
||||
# :proxy_http_basic_authentication => [URI.parse("http://proxy.foo.com:8000/"), "proxy-user", "proxy-password"]
|
||||
#
|
||||
# If :proxy option is specified, the value should be an Array with 3 elements.
|
||||
# It should contain a proxy URI, a proxy user name and a proxy password.
|
||||
# The proxy URI should be a String, an URI or nil.
|
||||
# The proxy user name and password should be a String.
|
||||
#
|
||||
# If nil is given for the proxy URI, this option is just ignored.
|
||||
#
|
||||
# If :proxy and :proxy_http_basic_authentication is specified,
|
||||
# ArgumentError is raised.
|
||||
#
|
||||
# [:http_basic_authentication]
|
||||
# Synopsis:
|
||||
# :http_basic_authentication=>[user, password]
|
||||
#
|
||||
# If :http_basic_authentication is specified,
|
||||
# the value should be an array which contains 2 strings:
|
||||
# username and password.
|
||||
# It is used for HTTP Basic authentication defined by RFC 2617.
|
||||
#
|
||||
# [:content_length_proc]
|
||||
# Synopsis:
|
||||
# :content_length_proc => lambda {|content_length| ... }
|
||||
#
|
||||
# If :content_length_proc option is specified, the option value procedure
|
||||
# is called before actual transfer is started.
|
||||
# It takes one argument which is expected content length in bytes.
|
||||
#
|
||||
# If two or more transfer is done by HTTP redirection, the procedure
|
||||
# is called only one for a last transfer.
|
||||
#
|
||||
# When expected content length is unknown, the procedure is called with
|
||||
# nil.
|
||||
# It is happen when HTTP response has no Content-Length header.
|
||||
#
|
||||
# [:progress_proc]
|
||||
# Synopsis:
|
||||
# :progress_proc => lambda {|size| ...}
|
||||
#
|
||||
# If :progress_proc option is specified, the proc is called with one
|
||||
# argument each time when `open' gets content fragment from network.
|
||||
# The argument `size' `size' is a accumulated transfered size in bytes.
|
||||
#
|
||||
# If two or more transfer is done by HTTP redirection, the procedure
|
||||
# is called only one for a last transfer.
|
||||
#
|
||||
# :progress_proc and :content_length_proc are intended to be used for
|
||||
# progress bar.
|
||||
# For example, it can be implemented as follows using Ruby/ProgressBar.
|
||||
#
|
||||
# pbar = nil
|
||||
# open("http://...",
|
||||
# :content_length_proc => lambda {|t|
|
||||
# if t && 0 < t
|
||||
# pbar = ProgressBar.new("...", t)
|
||||
# pbar.file_transfer_mode
|
||||
# end
|
||||
# },
|
||||
# :progress_proc => lambda {|s|
|
||||
# pbar.set s if pbar
|
||||
# }) {|f| ... }
|
||||
#
|
||||
# [:read_timeout]
|
||||
# Synopsis:
|
||||
# :read_timeout=>nil (no timeout)
|
||||
# :read_timeout=>10 (10 second)
|
||||
#
|
||||
# :read_timeout option specifies a timeout of read for http connections.
|
||||
#
|
||||
# [:ssl_ca_cert]
|
||||
# Synopsis:
|
||||
# :ssl_ca_cert=>filename
|
||||
#
|
||||
# :ssl_ca_cert is used to specify CA certificate for SSL.
|
||||
# If it is given, default certificates are not used.
|
||||
#
|
||||
# [:ssl_verify_mode]
|
||||
# Synopsis:
|
||||
# :ssl_verify_mode=>mode
|
||||
#
|
||||
# :ssl_verify_mode is used to specify openssl verify mode.
|
||||
#
|
||||
# OpenURI::OpenRead#open returns an IO like object if block is not given.
|
||||
# Otherwise it yields the IO object and return the value of the block.
|
||||
# The IO object is extended with OpenURI::Meta.
|
||||
def open(*rest, &block)
|
||||
OpenURI.open_uri(self, *rest, &block)
|
||||
end
|
||||
|
||||
# OpenURI::OpenRead#read([options]) reads a content referenced by self and
|
||||
# returns the content as string.
|
||||
# The string is extended with OpenURI::Meta.
|
||||
# The argument `options' is same as OpenURI::OpenRead#open.
|
||||
def read(options={})
|
||||
self.open(options) {|f|
|
||||
str = f.read
|
||||
Meta.init str, f
|
||||
str
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module URI
|
||||
class Generic
|
||||
# returns a proxy URI.
|
||||
# The proxy URI is obtained from environment variables such as http_proxy,
|
||||
# ftp_proxy, no_proxy, etc.
|
||||
# If there is no proper proxy, nil is returned.
|
||||
#
|
||||
# Note that capitalized variables (HTTP_PROXY, FTP_PROXY, NO_PROXY, etc.)
|
||||
# are examined too.
|
||||
#
|
||||
# But http_proxy and HTTP_PROXY is treated specially under CGI environment.
|
||||
# It's because HTTP_PROXY may be set by Proxy: header.
|
||||
# So HTTP_PROXY is not used.
|
||||
# http_proxy is not used too if the variable is case insensitive.
|
||||
# CGI_HTTP_PROXY can be used instead.
|
||||
def find_proxy
|
||||
name = self.scheme.downcase + '_proxy'
|
||||
proxy_uri = nil
|
||||
if name == 'http_proxy' && ENV.include?('REQUEST_METHOD') # CGI?
|
||||
# HTTP_PROXY conflicts with *_proxy for proxy settings and
|
||||
# HTTP_* for header information in CGI.
|
||||
# So it should be careful to use it.
|
||||
pairs = ENV.reject {|k, v| /\Ahttp_proxy\z/i !~ k }
|
||||
case pairs.length
|
||||
when 0 # no proxy setting anyway.
|
||||
proxy_uri = nil
|
||||
when 1
|
||||
k, v = pairs.shift
|
||||
if k == 'http_proxy' && ENV[k.upcase] == nil
|
||||
# http_proxy is safe to use because ENV is case sensitive.
|
||||
proxy_uri = ENV[name]
|
||||
else
|
||||
proxy_uri = nil
|
||||
end
|
||||
else # http_proxy is safe to use because ENV is case sensitive.
|
||||
proxy_uri = ENV[name]
|
||||
end
|
||||
if !proxy_uri
|
||||
# Use CGI_HTTP_PROXY. cf. libwww-perl.
|
||||
proxy_uri = ENV["CGI_#{name.upcase}"]
|
||||
end
|
||||
elsif name == 'http_proxy'
|
||||
unless proxy_uri = ENV[name]
|
||||
if proxy_uri = ENV[name.upcase]
|
||||
warn 'The environment variable HTTP_PROXY is discouraged. Use http_proxy.'
|
||||
end
|
||||
end
|
||||
else
|
||||
proxy_uri = ENV[name] || ENV[name.upcase]
|
||||
end
|
||||
|
||||
if proxy_uri && self.host
|
||||
require 'socket'
|
||||
begin
|
||||
addr = IPSocket.getaddress(self.host)
|
||||
proxy_uri = nil if /\A127\.|\A::1\z/ =~ addr
|
||||
rescue SocketError
|
||||
end
|
||||
end
|
||||
|
||||
if proxy_uri
|
||||
proxy_uri = URI.parse(proxy_uri)
|
||||
name = 'no_proxy'
|
||||
if no_proxy = ENV[name] || ENV[name.upcase]
|
||||
no_proxy.scan(/([^:,]*)(?::(\d+))?/) {|host, port|
|
||||
if /(\A|\.)#{Regexp.quote host}\z/i =~ self.host &&
|
||||
(!port || self.port == port.to_i)
|
||||
proxy_uri = nil
|
||||
break
|
||||
end
|
||||
}
|
||||
end
|
||||
proxy_uri
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class HTTP
|
||||
def buffer_open(buf, proxy, options) # :nodoc:
|
||||
OpenURI.open_http(buf, self, proxy, options)
|
||||
end
|
||||
|
||||
include OpenURI::OpenRead
|
||||
end
|
||||
|
||||
class FTP
|
||||
def buffer_open(buf, proxy, options) # :nodoc:
|
||||
if proxy
|
||||
OpenURI.open_http(buf, self, proxy, options)
|
||||
return
|
||||
end
|
||||
require 'net/ftp'
|
||||
|
||||
directories = self.path.split(%r{/}, -1)
|
||||
directories.shift if directories[0] == '' # strip a field before leading slash
|
||||
directories.each {|d|
|
||||
d.gsub!(/%([0-9A-Fa-f][0-9A-Fa-f])/) { [$1].pack("H2") }
|
||||
}
|
||||
unless filename = directories.pop
|
||||
raise ArgumentError, "no filename: #{self.inspect}"
|
||||
end
|
||||
directories.each {|d|
|
||||
if /[\r\n]/ =~ d
|
||||
raise ArgumentError, "invalid directory: #{d.inspect}"
|
||||
end
|
||||
}
|
||||
if /[\r\n]/ =~ filename
|
||||
raise ArgumentError, "invalid filename: #{filename.inspect}"
|
||||
end
|
||||
typecode = self.typecode
|
||||
if typecode && /\A[aid]\z/ !~ typecode
|
||||
raise ArgumentError, "invalid typecode: #{typecode.inspect}"
|
||||
end
|
||||
|
||||
# The access sequence is defined by RFC 1738
|
||||
ftp = Net::FTP.open(self.host)
|
||||
# todo: extract user/passwd from .netrc.
|
||||
user = 'anonymous'
|
||||
passwd = nil
|
||||
user, passwd = self.userinfo.split(/:/) if self.userinfo
|
||||
ftp.login(user, passwd)
|
||||
directories.each {|cwd|
|
||||
ftp.voidcmd("CWD #{cwd}")
|
||||
}
|
||||
if typecode
|
||||
# xxx: typecode D is not handled.
|
||||
ftp.voidcmd("TYPE #{typecode.upcase}")
|
||||
end
|
||||
if options[:content_length_proc]
|
||||
options[:content_length_proc].call(ftp.size(filename))
|
||||
end
|
||||
ftp.retrbinary("RETR #{filename}", 4096) { |str|
|
||||
buf << str
|
||||
options[:progress_proc].call(buf.size) if options[:progress_proc]
|
||||
}
|
||||
ftp.close
|
||||
buf.io.rewind
|
||||
end
|
||||
|
||||
include OpenURI::OpenRead
|
||||
end
|
||||
end
|
||||
# :startdoc:
|
|
@ -236,11 +236,13 @@ class Gem::RemoteFetcher
|
|||
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
|
||||
rescue EOFError, Errno::ECONNABORTED
|
||||
requests = @requests[connection_id]
|
||||
say "connection reset after #{requests} requests, retrying" if
|
||||
Gem.configuration.really_verbose
|
||||
|
|
|
@ -2,5 +2,5 @@
|
|||
# This file is auto-generated by build scripts.
|
||||
# See: rake update_version
|
||||
module Gem
|
||||
RubyGemsVersion = '1.1.0'
|
||||
RubyGemsVersion = '1.1.1'
|
||||
end
|
||||
|
|
|
@ -51,7 +51,7 @@ class Gem::Server
|
|||
<h1>Summary</h1>
|
||||
<p>There are <%=values["gem_count"]%> gems installed:</p>
|
||||
<p>
|
||||
<%= values["specs"].map { |v| "<a href=\"#{v["name"]}\">#{v["name"]}</a>" }.join ', ' %>.
|
||||
<%= values["specs"].map { |v| "<a href=\"##{v["name"]}\">#{v["name"]}</a>" }.join ', ' %>.
|
||||
<h1>Gems</h1>
|
||||
|
||||
<dl>
|
||||
|
@ -77,7 +77,7 @@ class Gem::Server
|
|||
|
||||
<% if spec["has_deps"] then %>
|
||||
- depends on
|
||||
<%= spec["dependencies"].map { |v| "<a href=\"#{v["name"]}\">#{v["name"]}</a>" }.join ', ' %>.
|
||||
<%= spec["dependencies"].map { |v| "<a href=\"##{v["name"]}\">#{v["name"]}</a>" }.join ', ' %>.
|
||||
<% end %>
|
||||
</dt>
|
||||
<dd>
|
||||
|
|
|
@ -25,6 +25,8 @@ class Gem::SourceIndex
|
|||
|
||||
include Gem::UserInteraction
|
||||
|
||||
attr_reader :gems # :nodoc:
|
||||
|
||||
class << self
|
||||
include Gem::UserInteraction
|
||||
|
||||
|
@ -50,11 +52,7 @@ class Gem::SourceIndex
|
|||
end
|
||||
|
||||
##
|
||||
# Return a list of directories in the current gem path that
|
||||
# contain specifications.
|
||||
#
|
||||
# return::
|
||||
# List of directory paths (all ending in "../specifications").
|
||||
# Returns a list of directories from Gem.path that contain specifications.
|
||||
|
||||
def installed_spec_directories
|
||||
Gem.path.collect { |dir| File.join(dir, "specifications") }
|
||||
|
@ -272,12 +270,11 @@ class Gem::SourceIndex
|
|||
end
|
||||
|
||||
##
|
||||
# Refresh the source index from the local file system.
|
||||
#
|
||||
# return:: Returns a pointer to itself.
|
||||
# Replaces the gems in the source index from specifications in the
|
||||
# installed_spec_directories,
|
||||
|
||||
def refresh!
|
||||
load_gems_in(self.class.installed_spec_directories)
|
||||
load_gems_in(*self.class.installed_spec_directories)
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -347,10 +344,6 @@ class Gem::SourceIndex
|
|||
Marshal.dump(self)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
attr_reader :gems
|
||||
|
||||
private
|
||||
|
||||
def fetcher
|
||||
|
@ -430,15 +423,22 @@ class Gem::SourceIndex
|
|||
# Make a list of full names for all the missing gemspecs.
|
||||
|
||||
def find_missing(spec_names)
|
||||
unless defined? @originals then
|
||||
@originals = {}
|
||||
each do |full_name, spec|
|
||||
@originals[spec.original_name] = spec
|
||||
end
|
||||
end
|
||||
|
||||
spec_names.find_all { |full_name|
|
||||
specification(full_name).nil?
|
||||
@originals[full_name].nil?
|
||||
}
|
||||
end
|
||||
|
||||
def remove_extra(spec_names)
|
||||
dictionary = spec_names.inject({}) { |h, k| h[k] = true; h }
|
||||
each do |name, spec|
|
||||
remove_spec name unless dictionary.include? name
|
||||
remove_spec name unless dictionary.include? spec.original_name
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -22,8 +22,8 @@ require 'rubygems/user_interaction'
|
|||
# Gem::SourceInfoCache
|
||||
# @cache_data = {
|
||||
# source_uri => Gem::SourceInfoCacheEntry
|
||||
# @size => source index size
|
||||
# @source_index => Gem::SourceIndex
|
||||
# @size = source index size
|
||||
# @source_index = Gem::SourceIndex
|
||||
# ...
|
||||
# }
|
||||
|
||||
|
@ -31,14 +31,14 @@ class Gem::SourceInfoCache
|
|||
|
||||
include Gem::UserInteraction
|
||||
|
||||
@cache = nil
|
||||
@system_cache_file = nil
|
||||
@user_cache_file = nil
|
||||
##
|
||||
# The singleton Gem::SourceInfoCache. If +all+ is true, a full refresh will
|
||||
# be performed if the singleton instance is being initialized.
|
||||
|
||||
def self.cache
|
||||
def self.cache(all = false)
|
||||
return @cache if @cache
|
||||
@cache = new
|
||||
@cache.refresh false if Gem.configuration.update_sources
|
||||
@cache.refresh all if Gem.configuration.update_sources
|
||||
@cache
|
||||
end
|
||||
|
||||
|
@ -62,6 +62,15 @@ class Gem::SourceInfoCache
|
|||
"latest_#{File.basename user_cache_file}"
|
||||
end
|
||||
|
||||
##
|
||||
# Reset all singletons, discarding any changes.
|
||||
|
||||
def self.reset
|
||||
@cache = nil
|
||||
@system_cache_file = nil
|
||||
@user_cache_file = nil
|
||||
end
|
||||
|
||||
##
|
||||
# Search all source indexes. See Gem::SourceInfoCache#search.
|
||||
|
||||
|
@ -123,13 +132,6 @@ class Gem::SourceInfoCache
|
|||
raise "unable to locate a writable cache file")
|
||||
end
|
||||
|
||||
##
|
||||
# Force cache file to be reset, useful for integration testing of rubygems
|
||||
|
||||
def reset_cache_file
|
||||
@cache_file = nil
|
||||
end
|
||||
|
||||
##
|
||||
# Write the cache to a local file (if it is dirty).
|
||||
|
||||
|
@ -175,13 +177,30 @@ class Gem::SourceInfoCache
|
|||
self.class.latest_user_cache_file
|
||||
end
|
||||
|
||||
##
|
||||
# Merges the complete cache file into this Gem::SourceInfoCache.
|
||||
|
||||
def read_all_cache_data
|
||||
if @only_latest then
|
||||
@only_latest = false
|
||||
@cache_data = read_cache_data cache_file
|
||||
all_data = read_cache_data cache_file
|
||||
|
||||
cache_data.update all_data do |source_uri, latest_sice, all_sice|
|
||||
all_sice.source_index.gems.update latest_sice.source_index.gems
|
||||
|
||||
Gem::SourceInfoCacheEntry.new all_sice.source_index, latest_sice.size
|
||||
end
|
||||
|
||||
begin
|
||||
refresh true
|
||||
rescue Gem::RemoteFetcher::FetchError
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Reads cached data from +file+.
|
||||
|
||||
def read_cache_data(file)
|
||||
# Marshal loads 30-40% faster from a String, and 2MB on 20061116 is small
|
||||
data = open file, 'rb' do |fp| fp.read end
|
||||
|
@ -203,6 +222,8 @@ class Gem::SourceInfoCache
|
|||
end
|
||||
|
||||
cache_data
|
||||
rescue Errno::ENOENT
|
||||
{}
|
||||
rescue => e
|
||||
if Gem.configuration.really_verbose then
|
||||
say "Exception during cache_data handling: #{e.class} - #{e}"
|
||||
|
@ -243,6 +264,14 @@ class Gem::SourceInfoCache
|
|||
|
||||
def reset_cache_data
|
||||
@cache_data = nil
|
||||
@only_latest = true
|
||||
end
|
||||
|
||||
##
|
||||
# Force cache file to be reset, useful for integration testing of rubygems
|
||||
|
||||
def reset_cache_file
|
||||
@cache_file = nil
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -315,10 +344,7 @@ class Gem::SourceInfoCache
|
|||
end
|
||||
end
|
||||
|
||||
if File.writable? dir then
|
||||
open path, "wb" do |io| io.write Marshal.dump({}) end
|
||||
return path
|
||||
end
|
||||
return path if File.writable? dir
|
||||
|
||||
nil
|
||||
end
|
||||
|
@ -338,11 +364,13 @@ class Gem::SourceInfoCache
|
|||
end
|
||||
|
||||
##
|
||||
# Write data to the proper cache.
|
||||
# Write data to the proper cache files.
|
||||
|
||||
def write_cache
|
||||
open cache_file, 'wb' do |io|
|
||||
io.write Marshal.dump(cache_data)
|
||||
if not File.exist?(cache_file) or not @only_latest then
|
||||
open cache_file, 'wb' do |io|
|
||||
io.write Marshal.dump(cache_data)
|
||||
end
|
||||
end
|
||||
|
||||
open latest_cache_file, 'wb' do |io|
|
||||
|
@ -350,5 +378,7 @@ class Gem::SourceInfoCache
|
|||
end
|
||||
end
|
||||
|
||||
reset
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -23,8 +23,7 @@ module Gem::VersionOption
|
|||
"Specify the platform of gem to #{task}", *wrap) do
|
||||
|value, options|
|
||||
unless options[:added_platform] then
|
||||
Gem.platforms.clear
|
||||
Gem.platforms << Gem::Platform::RUBY
|
||||
Gem.platforms = [Gem::Platform::RUBY]
|
||||
options[:added_platform] = true
|
||||
end
|
||||
|
||||
|
|
|
@ -61,6 +61,8 @@ class FakeFetcher
|
|||
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))
|
||||
|
@ -369,6 +371,17 @@ class RubyGemTestCase < Test::Unit::TestCase
|
|||
Gem.win_platform?
|
||||
end
|
||||
|
||||
# NOTE Allow tests to use a random (but controlled) port number instead of
|
||||
# a hardcoded one. This helps CI tools when running parallels builds on
|
||||
# the same builder slave.
|
||||
def self.process_based_port
|
||||
@@process_based_port ||= 8000 + $$ % 1000
|
||||
end
|
||||
|
||||
def process_based_port
|
||||
self.class.process_based_port
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class TempIO
|
||||
|
|
|
@ -237,23 +237,25 @@ class TestGem < RubyGemTestCase
|
|||
assert_equal [Gem.dir], Gem.path
|
||||
end
|
||||
|
||||
def test_self_path_APPLE_GEM_HOME
|
||||
Gem.clear_paths
|
||||
Gem.const_set :APPLE_GEM_HOME, '/tmp/apple_gem_home'
|
||||
unless win_platform?
|
||||
def test_self_path_APPLE_GEM_HOME
|
||||
Gem.clear_paths
|
||||
Gem.const_set :APPLE_GEM_HOME, '/tmp/apple_gem_home'
|
||||
|
||||
assert Gem.path.include?('/tmp/apple_gem_home')
|
||||
ensure
|
||||
Gem.send :remove_const, :APPLE_GEM_HOME
|
||||
end
|
||||
assert Gem.path.include?('/tmp/apple_gem_home')
|
||||
ensure
|
||||
Gem.send :remove_const, :APPLE_GEM_HOME
|
||||
end
|
||||
|
||||
def test_self_path_APPLE_GEM_HOME_GEM_PATH
|
||||
Gem.clear_paths
|
||||
ENV['GEM_PATH'] = @gemhome
|
||||
Gem.const_set :APPLE_GEM_HOME, '/tmp/apple_gem_home'
|
||||
def test_self_path_APPLE_GEM_HOME_GEM_PATH
|
||||
Gem.clear_paths
|
||||
ENV['GEM_PATH'] = @gemhome
|
||||
Gem.const_set :APPLE_GEM_HOME, '/tmp/apple_gem_home'
|
||||
|
||||
assert !Gem.path.include?('/tmp/apple_gem_home')
|
||||
ensure
|
||||
Gem.send :remove_const, :APPLE_GEM_HOME
|
||||
assert !Gem.path.include?('/tmp/apple_gem_home')
|
||||
ensure
|
||||
Gem.send :remove_const, :APPLE_GEM_HOME
|
||||
end
|
||||
end
|
||||
|
||||
def test_self_path_ENV_PATH
|
||||
|
@ -303,21 +305,56 @@ class TestGem < RubyGemTestCase
|
|||
|
||||
def test_self_prefix
|
||||
file_name = File.expand_path __FILE__
|
||||
assert_equal File.dirname(File.dirname(file_name)), Gem.prefix
|
||||
|
||||
prefix = File.dirname File.dirname(file_name)
|
||||
prefix = File.dirname prefix if File.basename(prefix) == 'test'
|
||||
|
||||
assert_equal prefix, Gem.prefix
|
||||
end
|
||||
|
||||
def test_self_prefix_odd
|
||||
def test_self_prefix_libdir
|
||||
orig_libdir = Gem::ConfigMap[:libdir]
|
||||
|
||||
file_name = File.expand_path __FILE__
|
||||
prefix = File.dirname File.dirname(file_name)
|
||||
|
||||
Gem::ConfigMap[:libdir] = prefix
|
||||
|
||||
assert_nil Gem.prefix
|
||||
ensure
|
||||
Gem::ConfigMap[:libdir] = orig_libdir
|
||||
end
|
||||
|
||||
def test_self_prefix_sitelibdir
|
||||
orig_sitelibdir = Gem::ConfigMap[:sitelibdir]
|
||||
|
||||
file_name = File.expand_path __FILE__
|
||||
prefix = File.join File.dirname(File.dirname(file_name)), 'lib'
|
||||
Gem::ConfigMap[:sitelibdir] = prefix.sub(/[\w]\//, '\&/')
|
||||
prefix = File.dirname File.dirname(file_name)
|
||||
|
||||
Gem::ConfigMap[:sitelibdir] = prefix
|
||||
|
||||
assert_nil Gem.prefix
|
||||
ensure
|
||||
Gem::ConfigMap[:sitelibdir] = orig_sitelibdir
|
||||
end
|
||||
|
||||
def test_self_refresh
|
||||
util_make_gems
|
||||
|
||||
a1_spec = File.join @gemhome, "specifications", "#{@a1.full_name}.gemspec"
|
||||
|
||||
FileUtils.mv a1_spec, @tempdir
|
||||
|
||||
assert !Gem.source_index.gems.include?(@a1.full_name)
|
||||
|
||||
FileUtils.mv File.join(@tempdir, "#{@a1.full_name}.gemspec"), a1_spec
|
||||
|
||||
Gem.refresh
|
||||
|
||||
assert Gem.source_index.gems.include?(@a1.full_name)
|
||||
assert_equal nil, Gem.instance_variable_get(:@searcher)
|
||||
end
|
||||
|
||||
def test_self_required_location
|
||||
util_make_gems
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ class TestGemCommandsEnvironmentCommand < RubyGemTestCase
|
|||
@cmd.execute
|
||||
end
|
||||
|
||||
assert_match %r|RUBYGEMS VERSION: (\d\.)+\d \((\d\.)+\d\)|, @ui.output
|
||||
assert_match %r|RUBYGEMS VERSION: (\d\.)+\d|, @ui.output
|
||||
assert_match %r|RUBY VERSION: \d\.\d\.\d \(.*\) \[.*\]|, @ui.output
|
||||
assert_match %r|INSTALLATION DIRECTORY: #{Regexp.escape @gemhome}|,
|
||||
@ui.output
|
||||
|
|
|
@ -26,6 +26,7 @@ class TestGemCommandsQueryCommand < RubyGemTestCase
|
|||
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
|
||||
|
@ -43,6 +44,9 @@ class TestGemCommandsQueryCommand < RubyGemTestCase
|
|||
|
||||
*** REMOTE GEMS ***
|
||||
|
||||
Updating metadata for 1 gems from http://gems.example.com/
|
||||
.
|
||||
complete
|
||||
a (2)
|
||||
EOF
|
||||
|
||||
|
@ -55,6 +59,7 @@ a (2)
|
|||
cache.update
|
||||
cache.write_cache
|
||||
cache.reset_cache_data
|
||||
Gem::SourceInfoCache.reset
|
||||
|
||||
a1_name = @a1.full_name
|
||||
a2_name = @a2.full_name
|
||||
|
@ -76,8 +81,8 @@ a (2)
|
|||
|
||||
*** REMOTE GEMS ***
|
||||
|
||||
Updating metadata for 1 gems from http://gems.example.com/
|
||||
.
|
||||
Updating metadata for 2 gems from http://gems.example.com/
|
||||
..
|
||||
complete
|
||||
a (2, 1)
|
||||
EOF
|
||||
|
@ -97,7 +102,7 @@ a (2, 1)
|
|||
|
||||
*** REMOTE GEMS ***
|
||||
|
||||
a (2, 1)
|
||||
a (2)
|
||||
This is a lot of text. This is a lot of text. This is a lot of text.
|
||||
This is a lot of text.
|
||||
|
||||
|
|
|
@ -181,6 +181,8 @@ beta-gems.example.com is not a URI
|
|||
@cmd.handle_options %w[--update]
|
||||
|
||||
util_setup_source_info_cache
|
||||
Gem::SourceInfoCache.reset
|
||||
|
||||
util_setup_fake_fetcher
|
||||
si = Gem::SourceIndex.new
|
||||
si.add_spec @a1
|
||||
|
|
|
@ -97,6 +97,7 @@ class TestGemCommandsUpdateCommand < RubyGemTestCase
|
|||
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
|
||||
|
|
|
@ -216,6 +216,8 @@ class TestGemDependencyInstaller < RubyGemTestCase
|
|||
|
||||
assert File.exist?(File.join(gemhome2, 'specifications',
|
||||
"#{@a1.full_name}.gemspec"))
|
||||
assert File.exist?(File.join(gemhome2, 'cache',
|
||||
"#{@a1.full_name}.gem"))
|
||||
end
|
||||
|
||||
def test_install_domain_both
|
||||
|
|
|
@ -76,8 +76,9 @@ gems:
|
|||
|
||||
# don't let 1.8 and 1.9 autotest collide
|
||||
RUBY_VERSION =~ /(\d+)\.(\d+)\.(\d+)/
|
||||
PROXY_PORT = 12345 + $1.to_i * 100 + $2.to_i * 10 + $3.to_i
|
||||
SERVER_PORT = 23456 + $1.to_i * 100 + $2.to_i * 10 + $3.to_i
|
||||
# don't let parallel runners collide
|
||||
PROXY_PORT = process_based_port + 100 + $1.to_i * 100 + $2.to_i * 10 + $3.to_i
|
||||
SERVER_PORT = process_based_port + 200 + $1.to_i * 100 + $2.to_i * 10 + $3.to_i
|
||||
|
||||
def setup
|
||||
super
|
||||
|
|
|
@ -15,7 +15,7 @@ class TestGemServer < RubyGemTestCase
|
|||
|
||||
@a1 = quick_gem 'a', '1'
|
||||
|
||||
@server = Gem::Server.new Gem.dir, 8809, false
|
||||
@server = Gem::Server.new Gem.dir, process_based_port, false
|
||||
@req = WEBrick::HTTPRequest.new :Logger => nil
|
||||
@res = WEBrick::HTTPResponse.new :HTTPVersion => '1.0'
|
||||
end
|
||||
|
|
|
@ -395,13 +395,31 @@ class TestGemSourceIndex < RubyGemTestCase
|
|||
assert_equal [updated_platform.name], @source_index.outdated
|
||||
end
|
||||
|
||||
def test_refresh_bang
|
||||
a1_spec = File.join @gemhome, "specifications", "#{@a1.full_name}.gemspec"
|
||||
|
||||
FileUtils.mv a1_spec, @tempdir
|
||||
|
||||
source_index = Gem::SourceIndex.from_installed_gems
|
||||
|
||||
assert !source_index.gems.include?(@a1.full_name)
|
||||
|
||||
FileUtils.mv File.join(@tempdir, "#{@a1.full_name}.gemspec"), a1_spec
|
||||
|
||||
source_index.refresh!
|
||||
|
||||
assert source_index.gems.include?(@a1.full_name)
|
||||
end
|
||||
|
||||
def test_remove_extra
|
||||
@source_index.add_spec @a1
|
||||
@source_index.add_spec @a2
|
||||
@source_index.add_spec @pl1
|
||||
|
||||
@source_index.remove_extra [@a1.full_name]
|
||||
@source_index.remove_extra [@a1.full_name, @pl1.full_name]
|
||||
|
||||
assert_equal [@a1.full_name], @source_index.gems.map { |n,s| n }
|
||||
assert_equal [@a1.full_name],
|
||||
@source_index.gems.map { |n,s| n }.sort
|
||||
end
|
||||
|
||||
def test_remove_extra_no_changes
|
||||
|
|
|
@ -287,6 +287,7 @@ class TestGemSourceInfoCache < RubyGemTestCase
|
|||
|
||||
@sic.set_cache_data @gem_repo => sice
|
||||
@sic.update
|
||||
@sic.instance_variable_set :@only_latest, false
|
||||
@sic.write_cache
|
||||
@sic.reset_cache_data
|
||||
|
||||
|
@ -358,6 +359,7 @@ class TestGemSourceInfoCache < RubyGemTestCase
|
|||
@sic.set_cache_data({@gem_repo => @sice_new})
|
||||
@sic.update
|
||||
@sic.write_cache
|
||||
@sic.instance_variable_set :@only_latest, false
|
||||
|
||||
assert File.exist?(@sic.user_cache_file), 'user_cache_file'
|
||||
assert File.exist?(@sic.latest_user_cache_file),
|
||||
|
@ -383,6 +385,7 @@ class TestGemSourceInfoCache < RubyGemTestCase
|
|||
|
||||
@sic.set_cache_data({ @gem_repo => @sice })
|
||||
@sic.update
|
||||
|
||||
@sic.write_cache
|
||||
|
||||
assert File.exist?(@sic.user_cache_file), 'system_cache_file'
|
||||
|
@ -390,7 +393,7 @@ class TestGemSourceInfoCache < RubyGemTestCase
|
|||
'latest_system_cache_file'
|
||||
|
||||
user_cache_data = read_cache(@sic.user_cache_file).to_a.sort
|
||||
assert_equal 1, user_cache_data.length
|
||||
assert_equal 1, user_cache_data.length, 'user_cache_data length'
|
||||
user_cache_data = user_cache_data.first
|
||||
|
||||
assert_equal @gem_repo, user_cache_data.first
|
||||
|
@ -415,6 +418,24 @@ class TestGemSourceInfoCache < RubyGemTestCase
|
|||
@sic.update
|
||||
@sic.write_cache
|
||||
|
||||
assert_equal [[@gem_repo, @sys_sice]],
|
||||
read_cache(@sic.system_cache_file).to_a.sort
|
||||
assert_equal [[@gem_repo, @sys_sice]],
|
||||
read_cache(@sic.user_cache_file).to_a.sort
|
||||
assert_equal [[@gem_repo, @sice_new]],
|
||||
read_cache(@sic.latest_user_cache_file).to_a.sort
|
||||
end
|
||||
|
||||
def test_write_cache_user_only_latest
|
||||
FileUtils.chmod 0444, @sic.system_cache_file
|
||||
@sic.set_cache_data({@gem_repo => @sice_new})
|
||||
@sic.update
|
||||
@sic.write_cache
|
||||
|
||||
assert File.exist?(@sic.user_cache_file), 'user_cache_file'
|
||||
assert File.exist?(@sic.latest_user_cache_file),
|
||||
'latest_user_cache_file exists'
|
||||
|
||||
assert_equal [[@gem_repo, @sys_sice]],
|
||||
read_cache(@sic.system_cache_file).to_a.sort
|
||||
assert_equal [[@gem_repo, @sice_new]],
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
require 'test/unit'
|
||||
require 'rubygems/gem_open_uri'
|
||||
|
||||
class TestOpenURI < Test::Unit::TestCase
|
||||
|
||||
def test_open_uri_not_broken
|
||||
assert_nothing_raised do
|
||||
open __FILE__ do end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
Loading…
Reference in a new issue