diff options
author | drbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2008-09-25 10:13:50 +0000 |
---|---|---|
committer | drbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2008-09-25 10:13:50 +0000 |
commit | d478c7a7342478847cc1148f4134b5f0db04e1d9 () | |
tree | 3bfca425683a94d1360ecdf5857d741b8eaac213 /lib | |
parent | 788001a9c8473130bd357846785838045387b060 (diff) |
Update to RubyGems 1.3.0 r1891
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@19547 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
31 files changed, 1207 insertions, 611 deletions
@@ -104,6 +104,11 @@ module Gem @ruby = nil @sources = [] ## # Activates an installed gem matching +gem+. The gem must satisfy # +version_requirements+. @@ -244,7 +249,10 @@ module Gem def self.clear_paths @gem_home = nil @gem_path = nil @@source_index = nil MUTEX.synchronize do @searcher = nil end @@ -261,9 +269,7 @@ module Gem # The standard configuration object for gems. def self.configuration - return @configuration if @configuration - require 'rubygems/config_file' - @configuration = Gem::ConfigFile.new [] end ## @@ -337,6 +343,22 @@ module Gem end ## # Finds the user's home directory. #-- # Some comments from the ruby-talk list regarding finding the home @@ -353,7 +375,7 @@ module Gem end if ENV['HOMEDRIVE'] && ENV['HOMEPATH'] then - return "#{ENV['HOMEDRIVE']}:#{ENV['HOMEPATH']}" end begin @@ -466,13 +488,11 @@ module Gem ## # manage_gems is useless and deprecated. Don't call it anymore. - #-- - # TODO warn w/ RubyGems 1.2.x release. - def self.manage_gems - #file, lineno = location_of_caller - #warn "#{file}:#{lineno}:Warning: Gem#manage_gems is deprecated and will be removed on or after September 2008." end ## @@ -489,11 +509,7 @@ module Gem @gem_path ||= nil unless @gem_path then - paths = if ENV['GEM_PATH'] then - [ENV['GEM_PATH']] - else - [default_path] - end if defined?(APPLE_GEM_HOME) and not ENV['GEM_PATH'] then paths << APPLE_GEM_HOME @@ -524,6 +540,40 @@ module Gem end ## # The directory prefix this RubyGems was installed at. def self.prefix @@ -600,6 +650,9 @@ module Gem @ruby = File.join(ConfigMap[:bindir], ConfigMap[:ruby_install_name]) @ruby << ConfigMap[:EXEEXT] end @ruby @@ -655,7 +708,13 @@ module Gem end @gem_path.uniq! - @gem_path.each do |gp| ensure_gem_subdirectories(gp) end end private_class_method :set_paths @@ -686,6 +745,14 @@ module Gem end ## # Glob pattern for require-able path suffixes. def self.suffix_pattern @@ -731,6 +798,27 @@ module Gem attr_reader :loaded_specs # :stopdoc: alias cache source_index # an alias for the old name @@ -781,7 +869,10 @@ if defined?(RUBY_ENGINE) then end end if RUBY_VERSION < '1.9' then require 'rubygems/custom_require' end @@ -51,7 +51,7 @@ class Gem::Commands::ContentsCommand < Gem::Command si = Gem::SourceIndex.from_gems_in(*s) - gem_spec = si.search(/\A#{gem}\z/, version).last unless gem_spec then say "Unable to find gem '#{gem}' in #{path_kind}" @@ -18,6 +18,46 @@ class Gem::Commands::EnvironmentCommand < Gem::Command return args.gsub(/^\s+/, '') end def usage # :nodoc: "#{program_name} [arg]" end @@ -20,9 +20,9 @@ Some examples of 'gem' usage. gem install --remote rake --test --rdoc --ri * Install 'rake', but only version 0.3.1, even if dependencies - are not met, and into a specific directory: - gem install rake --version 0.3.1 --force --install-dir $HOME/.gems * List local gems whose name begins with 'D': @@ -38,6 +38,19 @@ class Gem::Commands::InstallCommand < Gem::Command "--no-test --install-dir #{Gem.dir}" end def usage # :nodoc: "#{program_name} GEMNAME [GEMNAME ...] [options] -- --build-flags" end @@ -106,6 +119,8 @@ class Gem::Commands::InstallCommand < Gem::Command installed_gems.each do |gem| Gem::DocManager.new(gem, options[:rdoc_args]).generate_ri end end if options[:generate_rdoc] then @@ -58,15 +58,15 @@ lock it down to the exact version. end def complain(message) - if options.strict then - raise message else say "# #{message}" end end def execute - say 'require "rubygems"' locked = {} @@ -77,15 +77,20 @@ lock it down to the exact version. spec = Gem::SourceIndex.load_specification spec_path(full_name) say "gem '#{spec.name}', '= #{spec.version}'" unless locked[spec.name] locked[spec.name] = true spec.runtime_dependencies.each do |dep| next if locked[dep.name] - candidates = Gem.source_index.search dep.name, dep.requirement_list if candidates.empty? then - complain "Unable to satisfy '#{dep}' from currently installed gems." else pending << candidates.last.full_name end @@ -94,7 +99,11 @@ lock it down to the exact version. end def spec_path(gem_full_name) - File.join Gem.path, "specifications", "#{gem_full_name }.gemspec" end end @@ -19,7 +19,7 @@ class Gem::Commands::OutdatedCommand < Gem::Command locals = Gem::SourceIndex.from_installed_gems locals.outdated.sort.each do |name| - local = locals.search(/^#{name}$/).last dep = Gem::Dependency.new local.name, ">= #{local.version}" remotes = Gem::SpecFetcher.fetcher.fetch dep @@ -57,7 +57,7 @@ revert the gem. end else gem_name = get_one_gem_name - Gem::SourceIndex.from_installed_gems.search(gem_name, options[:version]) end @@ -59,7 +59,7 @@ class Gem::Commands::QueryCommand < Gem::Command if name.source.empty? then alert_error "You must specify a gem name" exit_code |= 4 - elsif installed? name.source, options[:version] then say "true" else say "false" @@ -69,12 +69,16 @@ class Gem::Commands::QueryCommand < Gem::Command raise Gem::SystemExitException, exit_code end if local? then - say - say "*** LOCAL GEMS ***" - say - specs = Gem.source_index.search name spec_tuples = specs.map do |spec| [[spec.name, spec.version, spec.original_platform, spec], :local] @@ -84,13 +88,14 @@ class Gem::Commands::QueryCommand < Gem::Command end if remote? then - say - say "*** REMOTE GEMS ***" - say all = options[:all] - dep = Gem::Dependency.new name, Gem::Requirement.default begin fetcher = Gem::SpecFetcher.fetcher spec_tuples = fetcher.find_matching dep, all, false @@ -59,11 +59,15 @@ module Gem if specs.empty? fail "Failed to find gem #{gem_name} to generate RDoc for #{options[:version]}" end if options[:include_ri] specs.each do |spec| Gem::DocManager.new(spec).generate_ri end end if options[:include_rdoc] specs.each do |spec| Gem::DocManager.new(spec).generate_rdoc @@ -73,6 +77,6 @@ module Gem true end end - end end @@ -40,6 +40,7 @@ class Gem::Commands::SpecificationCommand < Gem::Command def execute specs = [] gem = get_one_gem_name if local? then if File.exist? gem then @@ -47,12 +48,11 @@ class Gem::Commands::SpecificationCommand < Gem::Command end if specs.empty? then - specs.push(*Gem.source_index.search(/\A#{gem}\z/, options[:version])) end end if remote? then - dep = Gem::Dependency.new gem, options[:version] found = Gem::SpecFetcher.fetcher.fetch dep specs.push(*found.map { |spec,| spec }) @@ -68,7 +68,7 @@ class Gem::Commands::UnpackCommand < Gem::Command def get_path(gemname, version_req) return gemname if gemname =~ /\.gem$/i - specs = Gem::source_index.search(/\A#{gemname}\z/, version_req) selected = specs.sort_by { |s| s.version }.last @@ -45,6 +45,8 @@ class Gem::Commands::UpdateCommand < Gem::Command end def execute if options[:system] then say "Updating RubyGems" @@ -52,16 +54,22 @@ class Gem::Commands::UpdateCommand < Gem::Command fail "No gem names are allowed with the --system option" end - options[:args] = ["rubygems-update"] else say "Updating installed gems" - end - hig = {} # highest installed gems - Gem.source_index.each do |name, spec| - if hig[spec.name].nil? or hig[spec.name].version < spec.version then - hig[spec.name] = spec end end @@ -84,14 +92,14 @@ class Gem::Commands::UpdateCommand < Gem::Command end if gems_to_update.include? "rubygems-update" then - latest_ruby_gem = remote_gemspecs.select do |s| - s.name == 'rubygems-update' - end - latest_ruby_gem = latest_ruby_gem.sort_by { |s| s.version }.last - say "Updating version of RubyGems to #{latest_ruby_gem.version}" - installed = do_rubygems_update latest_ruby_gem.version say "RubyGems system software updated" if installed else @@ -103,6 +111,9 @@ class Gem::Commands::UpdateCommand < Gem::Command end end def do_rubygems_update(version) args = [] args.push '--prefix', Gem.prefix unless Gem.prefix.nil? @@ -112,8 +123,6 @@ class Gem::Commands::UpdateCommand < Gem::Command update_dir = File.join Gem.dir, 'gems', "rubygems-update-#{version}" - success = false - Dir.chdir update_dir do say "Installing RubyGems #{version}" setup_cmd = "#{Gem.ruby} setup.rb #{args.join ' '}" @@ -3,10 +3,10 @@ require 'rubygems/gem_path_searcher' class Gem::Commands::WhichCommand < Gem::Command - EXT = %w[.rb .rbw .so .dll] # HACK def initialize - super 'which', 'Find the location of a library', :search_gems_first => false, :show_all => false add_option '-a', '--[no-]all', 'show all matching files' do |show_all, options| @@ -52,7 +52,7 @@ class Gem::Commands::WhichCommand < Gem::Command paths = find_paths arg, dirs if paths.empty? then - say "Can't find #{arg}" else say paths end @@ -84,3 +84,4 @@ class Gem::Commands::WhichCommand < Gem::Command end end @@ -49,6 +49,9 @@ class Gem::ConfigFile # List of arguments supplied to the config file object. attr_reader :args # True if we print backtraces on errors. attr_writer :backtrace @@ -123,9 +126,10 @@ class Gem::ConfigFile @backtrace = @hash[:backtrace] if @hash.key? :backtrace @benchmark = @hash[:benchmark] if @hash.key? :benchmark @bulk_threshold = @hash[:bulk_threshold] if @hash.key? :bulk_threshold - Gem.sources.replace @hash[:sources] if @hash.key? :sources @verbose = @hash[:verbose] if @hash.key? :verbose @update_sources = @hash[:update_sources] if @hash.key? :update_sources handle_arguments arg_list end @@ -1,36 +1,52 @@ module Gem - # An Array of the default sources that come with RubyGems. def self.default_sources %w[http://gems.rubyforge.org/] end # Default home directory path to be used if an alternate value is not - # specified in the environment. def self.default_dir if defined? RUBY_FRAMEWORK_VERSION then File.join File.dirname(ConfigMap[:sitedir]), 'Gems', ConfigMap[:ruby_version] - elsif defined? RUBY_ENGINE then - File.join ConfigMap[:libdir], RUBY_ENGINE, 'gems', - ConfigMap[:ruby_version] else - File.join ConfigMap[:libdir], 'ruby', 'gems', ConfigMap[:ruby_version] end end - # Default gem load path. def self.default_path - [File.join(ENV['HOME'], '.gem'), default_dir] end - # Deduce Ruby's --program-prefix and --program-suffix from its install name. def self.default_exec_format baseruby = ConfigMap[:BASERUBY] || 'ruby' ConfigMap[:RUBY_INSTALL_NAME].sub(baseruby, '%s') rescue '%s' end # The default directory for binaries def self.default_bindir if defined? RUBY_FRAMEWORK_VERSION then # mac framework support '/usr/bin' @@ -39,15 +55,30 @@ module Gem end end - # The default system-wide source info cache directory. def self.default_system_source_cache_dir File.join Gem.dir, 'source_cache' end - # The default user-specific source info cache directory. def self.default_user_source_cache_dir File.join Gem.user_home, '.gem', 'source_cache' end end @@ -38,9 +38,17 @@ class Gem::DependencyInstaller # :ignore_dependencies:: Don't install any dependencies. # :install_dir:: See Gem::Installer#install. # :security_policy:: See Gem::Installer::new and Gem::Security. # :wrappers:: See Gem::Installer::new def initialize(options = {}) options = DEFAULT_OPTIONS.merge options @bin_dir = options[:bin_dir] @@ -51,19 +59,13 @@ class Gem::DependencyInstaller @format_executable = options[:format_executable] @ignore_dependencies = options[:ignore_dependencies] @security_policy = options[:security_policy] @wrappers = options[:wrappers] @installed_gems = [] @install_dir = options[:install_dir] || Gem.dir @cache_dir = options[:cache_dir] || @install_dir - - if options[:install_dir] then - spec_dir = File.join @install_dir, 'specifications' - @source_index = Gem::SourceIndex.from_gems_in spec_dir - else - @source_index = Gem.source_index - end end ## @@ -232,15 +234,17 @@ class Gem::DependencyInstaller end inst = Gem::Installer.new local_gem_path, - :env_shebang => @env_shebang, - :force => @force, - :format_executable => @format_executable, :ignore_dependencies => @ignore_dependencies, - :install_dir => @install_dir, - :security_policy => @security_policy, - :wrappers => @wrappers, - :bin_dir => @bin_dir, - :development => @development spec = inst.install @@ -5,132 +5,194 @@ #++ require 'fileutils' -module Gem - class DocManager - include UserInteraction - # Create a document manager for the given gem spec. - # - # spec:: The Gem::Specification object representing the gem. - # rdoc_args:: Optional arguments for RDoc (template etc.) as a String. - # - def initialize(spec, rdoc_args="") - @spec = spec - @doc_dir = File.join(spec.installation_path, "doc", spec.full_name) - @rdoc_args = rdoc_args.nil? ? [] : rdoc_args.split end - # Is the RDoc documentation installed? - def rdoc_installed? - return File.exist?(File.join(@doc_dir, "rdoc")) end - # Generate the RI documents for this gem spec. - # - # Note that if both RI and RDoc documents are generated from the - # same process, the RI docs should be done first (a likely bug in - # RDoc will cause RI docs generation to fail if run after RDoc). - def generate_ri - if @spec.has_rdoc then - load_rdoc - install_ri # RDoc bug, ri goes first - end - FileUtils.mkdir_p @doc_dir unless File.exist?(@doc_dir) end - # Generate the RDoc documents for this gem spec. - # - # Note that if both RI and RDoc documents are generated from the - # same process, the RI docs should be done first (a likely bug in - # RDoc will cause RI docs generation to fail if run after RDoc). - def generate_rdoc - if @spec.has_rdoc then - load_rdoc - install_rdoc - end - FileUtils.mkdir_p @doc_dir unless File.exist?(@doc_dir) end - # Load the RDoc documentation generator library. - def load_rdoc - if File.exist?(@doc_dir) && !File.writable?(@doc_dir) then - raise Gem::FilePermissionError.new(@doc_dir) - end - 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 - raise Gem::DocumentError, - "ERROR: RDoc documentation generator not installed!" - end - end - def install_rdoc - rdoc_dir = File.join @doc_dir, 'rdoc' - FileUtils.rm_rf rdoc_dir - say "Installing RDoc documentation for #{@spec.full_name}..." - run_rdoc '--op', rdoc_dir - end - def install_ri - ri_dir = File.join @doc_dir, 'ri' - FileUtils.rm_rf ri_dir - say "Installing ri documentation for #{@spec.full_name}..." - run_rdoc '--ri', '--op', ri_dir end - def run_rdoc(*args) - args << @spec.rdoc_options - args << DocManager.configured_args - args << '--quiet' - args << @spec.require_paths.clone - args << @spec.extra_rdoc_files - args = args.flatten.map do |arg| arg.to_s end - - r = RDoc::RDoc.new - - old_pwd = Dir.pwd - Dir.chdir(@spec.full_gem_path) - begin - r.document args - rescue Errno::EACCES => e - dirname = File.dirname e.message.split("-")[1].strip - raise Gem::FilePermissionError.new(dirname) - rescue RuntimeError => ex - alert_error "While generating documentation for #{@spec.full_name}" - ui.errs.puts "... MESSAGE: #{ex}" - ui.errs.puts "... RDOC args: #{args.join(' ')}" - ui.errs.puts "\t#{ex.backtrace.join "\n\t"}" if - Gem.configuration.backtrace - ui.errs.puts "(continuing with the rest of the installation)" - ensure - Dir.chdir(old_pwd) - end end - def uninstall_doc - raise Gem::FilePermissionError.new(@spec.installation_path) unless - File.writable? @spec.installation_path - original_name = [ - @spec.name, @spec.version, @spec.original_platform].join '-' doc_dir = File.join @spec.installation_path, 'doc', @spec.full_name unless File.directory? doc_dir then @@ -146,22 +208,7 @@ module Gem end FileUtils.rm_rf ri_dir - end - - class << self - def configured_args - @configured_args ||= [] - end - - def configured_args=(args) - case args - when Array - @configured_args = args - when String - @configured_args = args.split - end - end - end - end end @@ -6,15 +6,15 @@ require 'rubygems' -# # GemPathSearcher has the capability to find loadable files inside # gems. It generates data up front to speed up searches later. -# class Gem::GemPathSearcher - # # Initialise the data we need to make searches later. - # def initialize # We want a record of all the installed gemspecs, in the order # we wish to examine them. @@ -27,7 +27,7 @@ class Gem::GemPathSearcher end end - # # Look in all the installed gems until a matching _path_ is found. # Return the _gemspec_ of the gem where it was found. If no match # is found, return nil. @@ -46,36 +46,52 @@ class Gem::GemPathSearcher # others), which may or may not already be attached to _file_. # This method doesn't care about the full filename that matches; # only that there is a match. - # def find(path) - @gemspecs.each do |spec| - return spec if matching_file(spec, path) end - nil end - private - # Attempts to find a matching path using the require_paths of the - # given _spec_. - # - # Some of the intermediate results are cached in @lib_dirs for - # speed. - def matching_file(spec, path) # :doc: glob = File.join @lib_dirs[spec.object_id], "#{path}#{Gem.suffix_pattern}" - return true unless Dir[glob].select { |f| File.file?(f.untaint) }.empty? end - # Return a list of all installed gemspecs, sorted by alphabetical - # order and in reverse version order. def init_gemspecs Gem.source_index.map { |_, spec| spec }.sort { |a,b| (a.name <=> b.name).nonzero? || (b.version <=> a.version) } end # Returns library directories glob for a gemspec. For example, # '/usr/local/lib/ruby/gems/1.8/gems/foobar-1.0/{lib,ext}' def lib_dirs_for(spec) "#{spec.full_gem_path}/{#{spec.require_paths.join(',')}}" end @@ -20,6 +20,7 @@ require 'rubygems/require_paths_builder' # filesystem including unpacking the gem into its gem dir, installing the # gemspec in the specifications dir, storing the cached gem in the cache dir, # and installing either wrappers or symlinks for executables. class Gem::Installer ## @@ -31,8 +32,36 @@ class Gem::Installer include Gem::RequirePathsBuilder class << self attr_writer :exec_format # Defaults to use Ruby's program prefix and suffix. @@ -61,11 +90,12 @@ class Gem::Installer @gem = gem options = { - :force => false, - :install_dir => Gem.dir, - :exec_format => false, - :env_shebang => false, - :bin_dir => nil }.merge options @env_shebang = options[:env_shebang] @@ -78,6 +108,7 @@ class Gem::Installer @wrappers = options[:wrappers] @bin_dir = options[:bin_dir] @development = options[:development] begin @format = Gem::Format.from_file_by_path @gem, @security_policy @@ -85,30 +116,41 @@ class Gem::Installer raise Gem::InstallError, "invalid gem format for #{@gem}" end if not File.writable? @gem_home or # TODO: Shouldn't have to test for existence of bindir; tests need it. - (@gem_home.to_s == Gem.dir and File.exist? Gem.bindir and - not File.writable? Gem.bindir) - if options[:user_install] == false # You explicitly don't want to use ~ raise Gem::FilePermissionError, @gem_home - elsif options[:user_install].nil? - say "Warning: falling back to user-level install since #{@gem_home} and #{@bin_dir} aren't both writable." end options[:user_install] = true end - if options[:user_install] - @gem_home = File.join(ENV['HOME'], '.gem') - user_bin_dir = File.join(@gem_home, 'gems', 'bin') - if !ENV['PATH'].split(':').include?(user_bin_dir) - say "You don't have #{user_bin_dir} in your PATH." - say "You won't be able to run gem-installed executables until you add it." end - - Dir.mkdir @gem_home if ! File.directory? @gem_home # If it's still not writable, you've got issues. - raise Gem::FilePermissionError, @gem_home if ! File.writable? @gem_home end @spec = @format.spec @@ -157,6 +199,10 @@ class Gem::Installer end end FileUtils.mkdir_p @gem_home unless File.directory? @gem_home Gem.ensure_gem_subdirectories @gem_home @@ -181,7 +227,11 @@ class Gem::Installer @spec.loaded_from = File.join(@gem_home, 'specifications', "#{@spec.full_name}.gemspec") - Gem.source_index.add_spec @spec return @spec rescue Zlib::GzipFile::Error @@ -204,10 +254,10 @@ class Gem::Installer end ## - # True if the gems in Gem.source_index satisfy +dependency+. def installation_satisfies_dependency?(dependency) - Gem.source_index.find_name(dependency.name, dependency.version_requirements).size > 0 end ## @@ -110,6 +110,13 @@ module Gem::LocalRemoteOptions end ## # Is local fetching enabled? def local? @@ -46,17 +46,17 @@ class Gem::Package::TarReader yield entry skip = (512 - (size % 512)) % 512 - if @io.respond_to? :seek then # avoid reading... - @io.seek(size - entry.bytes_read, IO::SEEK_CUR) - else - pending = size - entry.bytes_read - while pending > 0 do - bread = @io.read([pending, 4096].min).size raise UnexpectedEOF if @io.eof? - pending -= bread end end @@ -13,23 +13,6 @@ class Gem::Platform attr_accessor :version - DEPRECATED_CONSTS = [ - :DARWIN, - :LINUX_586, - :MSWIN32, - :PPC_DARWIN, - :WIN32, - :X86_LINUX - ] - - def self.const_missing(name) # TODO remove six months from 2007/12 - if DEPRECATED_CONSTS.include? name then - raise NameError, "#{name} has been removed, use CURRENT instead" - else - super - end - end - def self.local arch = Gem::ConfigMap[:arch] arch = "#{arch}_60" if arch =~ /mswin32$/ @@ -73,7 +56,7 @@ class Gem::Platform else cpu end - if arch.length == 2 and arch.last =~ /^\d+$/ then # for command-line @os, @version = arch return end @@ -78,7 +78,7 @@ class Gem::RemoteFetcher if File.writable?(install_dir) cache_dir = File.join install_dir, 'cache' else - cache_dir = File.join(ENV['HOME'], '.gem', 'cache') end gem_file_name = "#{spec.full_name}.gem" @@ -93,7 +93,7 @@ class Gem::RemoteFetcher scheme = nil if scheme =~ /^[a-z]$/i case scheme - when 'http' then unless File.exist? local_gem_path then begin say "Downloading gem #{gem_file_name}" if @@ -139,8 +139,8 @@ class Gem::RemoteFetcher # Downloads +uri+ and returns it as a String. def fetch_path(uri, mtime = nil, head = false) - data = open_uri_or_path(uri, mtime, head) - data = Gem.gunzip data if uri.to_s =~ /gz$/ and not head data rescue FetchError raise @@ -216,8 +216,9 @@ class Gem::RemoteFetcher connection = @connections[connection_id] if uri.scheme == 'https' and not connection.started? then - http_obj.use_ssl = true - http_obj.verify_mode = OpenSSL::SSL::VERIFY_NONE end connection.start unless connection.started? @@ -241,9 +242,10 @@ class Gem::RemoteFetcher response = request uri, fetch_type, last_modified case response - when Net::HTTPOK then head ? response : response.body - when Net::HTTPRedirection then raise FetchError.new('too many redirects', uri) if depth > 10 open_uri_or_path(response['Location'], last_modified, head, depth + 1) @@ -274,6 +276,7 @@ class Gem::RemoteFetcher request.add_field 'Keep-Alive', '30' if last_modified then request.add_field 'If-Modified-Since', last_modified.rfc2822 end @@ -282,9 +285,6 @@ class Gem::RemoteFetcher retried = false bad_response = false - # HACK work around EOFError bug in Net::HTTP - # NOTE Errno::ECONNABORTED raised a lot on Windows, and make impossible - # to install gems. begin @requests[connection.object_id] += 1 response = connection.request request @@ -297,6 +297,9 @@ class Gem::RemoteFetcher bad_response = true retry rescue EOFError, Errno::ECONNABORTED, Errno::ECONNRESET requests = @requests[connection.object_id] say "connection reset after #{requests} requests, retrying" if @@ -2,5 +2,5 @@ # This file is auto-generated by build scripts. # See: rake update_version module Gem - RubyGemsVersion = '1.2.0.1824' end @@ -7,7 +7,9 @@ require 'rubygems' require 'rubygems/user_interaction' require 'rubygems/specification' -require 'rubygems/spec_fetcher' ## # The SourceIndex object indexes all the gems available from a @@ -80,8 +82,14 @@ class Gem::SourceIndex def load_specification(file_name) begin - spec_code = File.read(file_name).untaint gemspec = eval spec_code, binding, file_name if gemspec.is_a?(Gem::Specification) gemspec.loaded_from = file_name return gemspec @@ -93,7 +101,7 @@ class Gem::SourceIndex alert_warning e alert_warning spec_code rescue Exception => e - alert_warning(e.inspect.to_s + "\n" + spec_code) alert_warning "Invalid .gemspec format in '#{file_name}'" end return nil @@ -230,7 +238,8 @@ class Gem::SourceIndex # Find a gem by an exact match on the short name. def find_name(gem_name, version_requirement = Gem::Requirement.default) - search(/^#{gem_name}$/, version_requirement) end ## @@ -246,7 +255,13 @@ class Gem::SourceIndex version_requirement = nil only_platform = false - case gem_pattern # TODO warn after 2008/03, remove three months after when Regexp then version_requirement = platform_only || Gem::Requirement.default when Gem::Dependency then @@ -270,7 +285,7 @@ class Gem::SourceIndex specs = @gems.values.select do |spec| spec.name =~ gem_pattern and - version_requirement.satisfied_by? spec.version end if only_platform then @@ -539,7 +554,7 @@ module Gem # objects to load properly. Cache = SourceIndex - # :starddoc: end @@ -284,6 +284,10 @@ class Gem::SourceInfoCache cache_data.map do |source_uri, sic_entry| next unless Gem.sources.include? source_uri sic_entry.source_index.search pattern, platform_only end.flatten.compact end @@ -300,6 +304,11 @@ class Gem::SourceInfoCache cache_data.map do |source_uri, sic_entry| next unless Gem.sources.include? source_uri sic_entry.source_index.search(pattern, only_platform).each do |spec| results << [spec, source_uri] end @@ -167,7 +167,7 @@ class Gem::SpecFetcher if all and @specs.include? source_uri then list[source_uri] = @specs[source_uri] - elsif @latest_specs.include? source_uri then list[source_uri] = @latest_specs[source_uri] else specs = load_specs source_uri, file @@ -182,6 +182,10 @@ class Gem::SpecFetcher list end def load_specs(source_uri, file) file_name = "#{file}.#{Gem.marshal_version}" spec_path = source_uri + "#{file_name}.gz" @@ -192,7 +196,7 @@ class Gem::SpecFetcher if File.exist? local_file then spec_dump = @fetcher.fetch_path spec_path, File.mtime(local_file) - if spec_dump.empty? then spec_dump = Gem.read_binary local_file else loaded = true @@ -24,6 +24,7 @@ class Date; end # for ruby_code if date.rb wasn't required module Gem # == Gem::Specification # # The Specification class contains the metadata for a Gem. Typically @@ -38,7 +39,7 @@ module Gem # # There are many <em>gemspec attributes</em>, and the best place to learn # about them in the "Gemspec Reference" linked from the RubyGems wiki. - # class Specification ## @@ -46,8 +47,6 @@ module Gem attr_accessor :original_platform # :nodoc: - # ------------------------- Specification version constants. - ## # The the version number of a specification that does not specify one # (i.e. RubyGems 0.7 or earlier). @@ -88,77 +87,98 @@ module Gem TODAY = now - ((now.to_i + now.gmt_offset) % 86400) # :startdoc: - # ------------------------- Class variables. - # List of Specification instances. @@list = [] # Optional block used to gather newly defined instances. @@gather = nil # List of attribute names: [:name, :version, ...] @@required_attributes = [] - # List of _all_ attributes and default values: [[:name, nil], [:bindir, 'bin'], ...] @@attributes = [] @@nil_attributes = [] @@non_nil_attributes = [:@original_platform] # List of array attributes @@array_attributes = [] # Map of attribute names to default values. @@default_value = {} - # ------------------------- Convenience class methods. def self.attribute_names @@attributes.map { |name, default| name } end def self.attribute_defaults @@attributes.dup end def self.default_value(name) @@default_value[name] end def self.required_attributes @@required_attributes.dup end def self.required_attribute?(name) @@required_attributes.include? name.to_sym end def self.array_attributes @@array_attributes.dup end - # ------------------------- Infrastructure class methods. - # A list of Specification instances that have been defined in this Ruby instance. def self.list @@list end - # Used to specify the name and default value of a specification - # attribute. The side effects are: - # * the name and default value are added to the @@attributes list - # and @@default_value map - # * a standard _writer_ method (<tt>attribute=</tt>) is created - # * a non-standard _reader method (<tt>attribute</tt>) is created - # - # The reader method behaves like this: - # def attribute - # @attribute ||= (copy of default value) - # end - # - # This allows lazy initialization of attributes to their default - # values. # def self.attribute(name, default=nil) ivar_name = "@#{name}".intern if default.nil? then @@ -172,8 +192,10 @@ module Gem attr_accessor(name) end - # Same as :attribute, but ensures that values assigned to the - # attribute are array values by applying :to_a to the value. def self.array_attribute(name) @@non_nil_attributes << ["@#{name}".intern, []] @@ -192,51 +214,60 @@ module Gem module_eval code, __FILE__, __LINE__ - 9 end # Same as attribute above, but also records this attribute as mandatory. def self.required_attribute(*args) @@required_attributes << args.first attribute(*args) end - # Sometimes we don't want the world to use a setter method for a particular attribute. # +read_only+ makes it private so we can still use it internally. def self.read_only(*names) names.each do |name| private "#{name}=" end end - # Shortcut for creating several attributes at once (each with a default value of - # +nil+). def self.attributes(*args) args.each do |arg| attribute(arg, nil) end end - # Some attributes require special behaviour when they are accessed. This allows for - # that. def self.overwrite_accessor(name, &block) remove_method name define_method(name, &block) end - # Defines a _singular_ version of an existing _plural_ attribute - # (i.e. one whose value is expected to be an array). This means - # just creating a helper method that takes a single value and - # appends it to the array. These are created for convenience, so - # that in a spec, one can write # # s.require_path = 'mylib' # - # instead of # # s.require_paths = ['mylib'] # - # That above convenience is available courtesy of # # attribute_alias_singular :require_path, :require_paths - # def self.attribute_alias_singular(singular, plural) define_method("#{singular}=") { |val| send("#{plural}=", [val]) @@ -320,189 +351,45 @@ module Gem spec end - # REQUIRED gemspec attributes ------------------------------------ - - required_attribute :rubygems_version, Gem::RubyGemsVersion - required_attribute :specification_version, CURRENT_SPECIFICATION_VERSION - required_attribute :name - required_attribute :version - required_attribute :date, TODAY - required_attribute :summary - required_attribute :require_paths, ['lib'] - - # OPTIONAL gemspec attributes ------------------------------------ - - attributes :email, :homepage, :rubyforge_project, :description - attributes :autorequire, :default_executable - - attribute :bindir, 'bin' - attribute :has_rdoc, false - attribute :required_ruby_version, Gem::Requirement.default - attribute :required_rubygems_version, Gem::Requirement.default - attribute :platform, Gem::Platform::RUBY - - attribute :signing_key, nil - attribute :cert_chain, [] - attribute :post_install_message, nil - - array_attribute :authors - array_attribute :files - array_attribute :test_files - array_attribute :rdoc_options - array_attribute :extra_rdoc_files - array_attribute :executables - - # Array of extensions to build. See Gem::Installer#build_extensions for - # valid values. - - array_attribute :extensions - array_attribute :requirements - array_attribute :dependencies - - read_only :dependencies def runtime_dependencies dependencies.select { |d| d.type == :runtime || d.type == nil } end def development_dependencies dependencies.select { |d| d.type == :development } end - # ALIASED gemspec attributes ------------------------------------- - - attribute_alias_singular :executable, :executables - attribute_alias_singular :author, :authors - attribute_alias_singular :require_path, :require_paths - attribute_alias_singular :test_file, :test_files - - # DEPRECATED gemspec attributes ---------------------------------- - - def test_suite_file warn 'test_suite_file deprecated, use test_files' test_files.first end - def test_suite_file=(val) warn 'test_suite_file= deprecated, use test_files=' @test_files = [] unless defined? @test_files @test_files << val end # true when this gemspec has been loaded from a specifications directory. # This attribute is not persisted. - attr_writer :loaded # Path this gemspec was loaded from. This attribute is not persisted. - attr_accessor :loaded_from - - # Special accessor behaviours (overwriting default) -------------- - - overwrite_accessor :version= do |version| - @version = Version.create(version) - end - - overwrite_accessor :platform do - @new_platform - end - - overwrite_accessor :platform= do |platform| - if @original_platform.nil? or - @original_platform == Gem::Platform::RUBY then - @original_platform = platform - end - - case platform - when Gem::Platform::CURRENT then - @new_platform = Gem::Platform.local - @original_platform = @new_platform.to_s - - when Gem::Platform then - @new_platform = platform - - # legacy constants - when nil, Gem::Platform::RUBY then - @new_platform = Gem::Platform::RUBY - when 'mswin32' then # was Gem::Platform::WIN32 - @new_platform = Gem::Platform.new 'x86-mswin32' - when 'i586-linux' then # was Gem::Platform::LINUX_586 - @new_platform = Gem::Platform.new 'x86-linux' - when 'powerpc-darwin' then # was Gem::Platform::DARWIN - @new_platform = Gem::Platform.new 'ppc-darwin' - else - @new_platform = Gem::Platform.new platform - end - - @platform = @new_platform.to_s - - @new_platform - end - - overwrite_accessor :required_ruby_version= do |value| - @required_ruby_version = Gem::Requirement.create(value) - end - - overwrite_accessor :required_rubygems_version= do |value| - @required_rubygems_version = Gem::Requirement.create(value) - end - - overwrite_accessor :date= do |date| - # We want to end up with a Time object with one-day resolution. - # This is the cleanest, most-readable, faster-than-using-Date - # way to do it. - case date - when String then - @date = if /\A(\d{4})-(\d{2})-(\d{2})\Z/ =~ date then - Time.local($1.to_i, $2.to_i, $3.to_i) - else - require 'time' - Time.parse date - end - when Time then - @date = Time.local(date.year, date.month, date.day) - when Date then - @date = Time.local(date.year, date.month, date.day) - else - @date = TODAY - end - end - overwrite_accessor :date do - self.date = nil if @date.nil? # HACK Sets the default value for date - @date - end - - overwrite_accessor :summary= do |str| - @summary = if str then - str.strip. - gsub(/(\w-)\n[ \t]*(\w)/, '\1\2'). - gsub(/\n[ \t]*/, " ") - end - end - - overwrite_accessor :description= do |str| - @description = if str then - str.strip. - gsub(/(\w-)\n[ \t]*(\w)/, '\1\2'). - gsub(/\n[ \t]*/, " ") - end - end - overwrite_accessor :default_executable do - begin - if defined?(@default_executable) and @default_executable - result = @default_executable - elsif @executables and @executables.size == 1 - result = Array(@executables).first - else - result = nil - end - result - rescue - nil - end - end def add_bindir(executables) return nil if executables.nil? @@ -516,17 +403,9 @@ module Gem return nil end - overwrite_accessor :files do - result = [] - result.push(*@files) if defined?(@files) - result.push(*@test_files) if defined?(@test_files) - result.push(*(add_bindir(@executables))) - result.push(*@extra_rdoc_files) if defined?(@extra_rdoc_files) - result.push(*@extensions) if defined?(@extensions) - result.uniq.compact - end - # Files in the Gem under one of the require_paths def lib_files @files.select do |file| require_paths.any? do |path| @@ -535,34 +414,25 @@ module Gem end end - overwrite_accessor :test_files do - # Handle the possibility that we have @test_suite_file but not - # @test_files. This will happen when an old gem is loaded via - # YAML. - if defined? @test_suite_file then - @test_files = [@test_suite_file].flatten - @test_suite_file = nil - end - if defined?(@test_files) and @test_files then - @test_files - else - @test_files = [] - end end - # Predicates ----------------------------------------------------- - - def loaded?; @loaded ? true : false ; end - def has_rdoc?; has_rdoc ? true : false ; end - def has_unit_tests?; not test_files.empty?; end - alias has_test_suite? has_unit_tests? # (deprecated) - - # Constructors --------------------------------------------------- # Specification constructor. Assigns the default values to the # attributes, adds this spec to the list of loaded specs (see # Specification.list), and yields itself for further initialization. - # def initialize @new_platform = nil assign_defaults @@ -575,11 +445,13 @@ module Gem @@gather.call(self) if @@gather end - # Each attribute has a default value (possibly nil). Here, we - # initialize all attributes to their default value. This is - # done through the accessor methods, so special behaviours will - # be honored. Furthermore, we take a _copy_ of the default so - # each specification instance has its own empty arrays, etc. def assign_defaults @@nil_attributes.each do |name| instance_variable_set name, nil @@ -598,13 +470,14 @@ module Gem instance_variable_set :@new_platform, Gem::Platform::RUBY end - # Special loader for YAML files. When a Specification object is - # loaded from a YAML file, it bypasses the normal Ruby object - # initialization routine (#initialize). This method makes up for - # that and deals with gems of different ages. # # 'input' can be anything that YAML.load() accepts: String or IO. - # def self.from_yaml(input) input = normalize_yaml_input input spec = YAML.load input @@ -627,6 +500,9 @@ module Gem spec end def self.load(filename) gemspec = nil fail "NESTED Specification.load calls not allowed!" if @@gather @@ -638,22 +514,25 @@ module Gem @@gather = nil end - # Make sure the yaml specification is properly formatted with dashes. def self.normalize_yaml_input(input) result = input.respond_to?(:read) ? input.read : input result = "--- " + result unless result =~ /^--- / result end - # Instance methods ----------------------------------------------- - - # Sets the rubygems_version to Gem::RubyGemsVersion. - # def mark_version @rubygems_version = RubyGemsVersion end - # Ignore unknown attributes if the def method_missing(sym, *a, &b) # :nodoc: if @specification_version > CURRENT_SPECIFICATION_VERSION and sym.to_s =~ /=$/ then @@ -663,35 +542,39 @@ module Gem end end - # Adds a development dependency to this Gem. For example, - # - # spec.add_development_dependency('jabber4r', '> 0.1', '<= 0.5') # - # Development dependencies aren't installed by default, and - # aren't activated when a gem is required. # - # gem:: [String or Gem::Dependency] The Gem name/dependency. - # requirements:: [default=">= 0"] The version requirements. def add_development_dependency(gem, *requirements) add_dependency_with_type(gem, :development, *requirements) end - # Adds a runtime dependency to this Gem. For example, - # - # spec.add_runtime_dependency('jabber4r', '> 0.1', '<= 0.5') # - # gem:: [String or Gem::Dependency] The Gem name/dependency. - # requirements:: [default=">= 0"] The version requirements. def add_runtime_dependency(gem, *requirements) add_dependency_with_type(gem, :runtime, *requirements) end alias add_dependency add_runtime_dependency # Returns the full name (name-version) of this Gem. Platform information - # is included (name-version-platform) if it is specified (and not the - # default Ruby platform). - # def full_name if platform == Gem::Platform::RUBY or platform.nil? then "#{@name}-#{@version}" @@ -700,9 +583,10 @@ module Gem end end # Returns the full name (name-version) of this gemspec using the original - # platform. - # def original_name # :nodoc: if platform == Gem::Platform::RUBY or platform.nil? then "#{@name}-#{@version}" @@ -736,18 +620,16 @@ module Gem File.expand_path path end - # Checks if this Specification meets the requirement of the supplied - # dependency. - # - # dependency:: [Gem::Dependency] the dependency to check - # return:: [Boolean] true if dependency is met, otherwise false - # def satisfies_requirement?(dependency) return @name == dependency.name && dependency.version_requirements.satisfied_by?(@version) end - # Comparison methods --------------------------------------------- def sort_obj [@name, @version.to_ints, @new_platform == Gem::Platform::RUBY ? -1 : 1] @@ -757,19 +639,25 @@ module Gem sort_obj <=> other.sort_obj end # Tests specs for equality (across all attributes). def ==(other) # :nodoc: self.class === other && same_attributes?(other) end alias eql? == # :nodoc: def same_attributes?(other) @@attributes.each do |name, default| return false unless self.send(name) == other.send(name) end true end private :same_attributes? def hash # :nodoc: @@ -779,8 +667,6 @@ module Gem } end - # Export methods (YAML and Ruby code) ---------------------------- - def to_yaml(opts = {}) # :nodoc: mark_version @@ -825,6 +711,8 @@ module Gem def to_ruby mark_version result = [] result << "Gem::Specification.new do |s|" result << " s.name = #{ruby_code name}" @@ -861,7 +749,7 @@ module Gem result << " s.specification_version = #{specification_version}" result << nil - result << " if current_version >= 3 then" unless dependencies.empty? then dependencies.each do |dep| @@ -895,16 +783,15 @@ module Gem result.join "\n" end - # Validation and normalization methods --------------------------- - - # Checks that the specification contains all required fields, and - # does a very basic sanity check. # - # Raises InvalidSpecificationException if the spec does not pass - # the checks.. def validate extend Gem::UserInteraction - normalize if rubygems_version != RubyGemsVersion then @@ -959,13 +846,14 @@ module Gem true end # Normalize the list of files so that: # * All file lists have redundancies removed. - # * Files referenced in the extra_rdoc_files are included in the - # package file list. # - # Also, the summary and description are converted to a normal - # format. def normalize if defined?(@extra_rdoc_files) and @extra_rdoc_files then @extra_rdoc_files.uniq! @@ -975,15 +863,12 @@ module Gem @files.uniq! if @files end - # Dependency methods --------------------------------------------- - - # Return a list of all gems that have a dependency on this - # gemspec. The list is structured with entries that conform to: # # [depending_gem, dependency, [list_of_gems_that_satisfy_dependency]] - # - # return:: [Array] [[dependent_gem, dependency, [list_of_satisfiers]]] - # def dependent_gems out = [] Gem.source_index.each do |name,gem| @@ -1004,8 +889,6 @@ module Gem "#<Gem::Specification name=#{@name} version=#{@version}>" end - private - def add_dependency_with_type(dependency, type, *requirements) requirements = if requirements.empty? then Gem::Requirement.default @@ -1022,6 +905,8 @@ module Gem dependencies << dependency end def find_all_satisfiers(dep) Gem.source_index.each do |name,gem| if(gem.satisfies_requirement?(dep)) then @@ -1030,8 +915,12 @@ module Gem end end - # Return a string containing a Ruby code representation of the - # given object. def ruby_code(obj) case obj when String then '%q{' + obj + '}' @@ -1046,6 +935,326 @@ module Gem else raise Exception, "ruby_code case not handled: #{obj.class}" end end end @@ -34,16 +34,20 @@ class Gem::FakeFetcher path = path.to_s @paths << path raise ArgumentError, 'need full URI' unless path =~ %r'^http://' - data = @data[path] - if data.nil? then - raise Gem::RemoteFetcher::FetchError.new('no data', path) end if data.respond_to?(:call) then data.call else - data = Gem.gunzip data if path.to_s =~ /gz$/ unless data.empty? data end end @@ -51,13 +55,15 @@ class Gem::FakeFetcher def fetch_size(path) path = path.to_s @paths << path raise ArgumentError, 'need full URI' unless path =~ %r'^http://' - data = @data[path] - if data.nil? then - raise Gem::RemoteFetcher::FetchError.new("no data for #{path}", nil) end data.respond_to?(:call) ? data.call : data.length end @@ -18,9 +18,23 @@ class Gem::Uninstaller include Gem::UserInteraction ## - # Constructs an Uninstaller instance - # - # gem:: [String] The Gem name to uninstall def initialize(gem, options = {}) @gem = gem @@ -31,42 +45,63 @@ class Gem::Uninstaller @force_all = options[:all] @force_ignore = options[:ignore] @bin_dir = options[:bin_dir] end ## - # Performs the uninstall of the Gem. This removes the spec, the - # Gem directory, and the cached .gem file, def uninstall - list = Gem.source_index.search(/^#{@gem}$/, @version) if list.empty? then raise Gem::InstallError, "Unknown gem #{@gem} #{@version}" - elsif list.size > 1 && @force_all - remove_all(list.dup) - remove_executables(list.last) - elsif list.size > 1 - say gem_names = list.collect {|gem| gem.full_name} + ["All versions"] - gem_name, index = - choose_from_list("Select gem to uninstall:", gem_names) - if index == list.size - remove_all(list.dup) - remove_executables(list.last) - elsif index >= 0 && index < list.size - to_remove = list[index] - remove(to_remove, list) - remove_executables(to_remove) else say "Error: must enter a number [1-#{list.size+1}]" end else - remove(list[0], list.dup) - remove_executables(list.last) end end ## # Removes installed executables and batch files (windows only) for # +gemspec+. @@ -76,7 +111,7 @@ class Gem::Uninstaller if gemspec.executables.size > 0 then bindir = @bin_dir ? @bin_dir : (Gem.bindir @gem_home) - list = Gem.source_index.search(gemspec.name).delete_if { |spec| spec.version == gemspec.version } @@ -118,7 +153,7 @@ class Gem::Uninstaller # NOTE: removes uninstalled gems from +list+. def remove_all(list) - list.dup.each { |spec| remove spec, list } end ## @@ -185,8 +220,7 @@ class Gem::Uninstaller def dependencies_ok?(spec) return true if @force_ignore - source_index = Gem::SourceIndex.from_installed_gems - deplist = Gem::DependencyList.from_source_index source_index deplist.ok_to_remove?(spec.full_name) || ask_if_ok(spec) end |