1
0
Fork 0
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:
drbrain 2008-04-11 20:57:02 +00:00
parent 0ae6c7f816
commit e72b71d56a
31 changed files with 272 additions and 888 deletions

View file

@ -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.

View file

@ -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
@ -451,10 +451,21 @@ module Gem
end
##
# Array of platforms this RubyGems supports.
# 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.

View file

@ -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'."

View file

@ -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

View file

@ -126,6 +126,7 @@ revert the gem.
end
installer.generate_bin
installer.build_extensions
end
end

View file

@ -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

View file

@ -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"

View file

@ -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}"

View file

@ -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,

View file

@ -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

View file

@ -1,7 +0,0 @@
#!/usr/bin/env ruby
if RUBY_VERSION > '1.9' then
require 'open-uri'
else
require 'rubygems/open-uri'
end

View file

@ -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"}"

View file

@ -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:

View file

@ -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

View file

@ -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

View file

@ -29,7 +29,7 @@ class Gem::Server
DOC_TEMPLATE = <<-'WEBPAGE'
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
@ -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>
@ -91,8 +91,8 @@ class Gem::Server
Executables are
<%end%>
<%= spec["executables"].map { |v| "<span class=\"context-item-name\">#{v["executable"]}</span>"}.join ', ' %>.
<%= spec["executables"].map { |v| "<span class=\"context-item-name\">#{v["executable"]}</span>"}.join ', ' %>.
<%end%>
<br/>
<br/>

View file

@ -25,6 +25,8 @@ class Gem::SourceIndex
include Gem::UserInteraction
attr_reader :gems # :nodoc:
class << self
include Gem::UserInteraction
@ -50,14 +52,10 @@ 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") }
Gem.path.collect { |dir| File.join(dir, "specifications") }
end
##
@ -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

View file

@ -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.
@ -122,13 +131,6 @@ class Gem::SourceInfoCache
try_file(user_cache_file) or
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

View file

@ -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

View file

@ -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

View file

@ -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'
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'
assert !Gem.path.include?('/tmp/apple_gem_home')
ensure
Gem.send :remove_const, :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
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
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

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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]],

View file

@ -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