mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Update to RubyGems 1.3.4 r2223
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@23659 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
a6afbaeb3b
commit
31c94ffeb5
126 changed files with 7610 additions and 3747 deletions
|
@ -1,3 +1,7 @@
|
|||
Wed Jun 10 06:28:15 2009 Eric Hodel <drbrain@segment7.net>
|
||||
|
||||
* lib/rubygems*: Upgrade to RubyGems 1.3.4 r2223.
|
||||
|
||||
Tue Jun 9 22:38:09 2009 Tadayoshi Funaba <tadf@dotrb.org>
|
||||
|
||||
* lib/cmath.rb (log10): raised exception when the given number is
|
||||
|
|
9
bin/gem
9
bin/gem
|
@ -9,16 +9,13 @@ require 'rubygems'
|
|||
require 'rubygems/gem_runner'
|
||||
require 'rubygems/exceptions'
|
||||
|
||||
required_version = Gem::Requirement.new "> 1.8.3"
|
||||
required_version = Gem::Requirement.new ">= 1.8.6"
|
||||
|
||||
unless required_version.satisfied_by? Gem.ruby_version then
|
||||
abort "Expected Ruby Version #{required_version}, was #{Gem.ruby_version}"
|
||||
abort "Expected Ruby Version #{required_version}, is #{Gem.ruby_version}"
|
||||
end
|
||||
|
||||
# We need to preserve the original ARGV to use for passing gem options
|
||||
# to source gems. If there is a -- in the line, strip all options after
|
||||
# it...its for the source building process.
|
||||
args = !ARGV.include?("--") ? ARGV.clone : ARGV[0...ARGV.index("--")]
|
||||
args = ARGV.clone
|
||||
|
||||
begin
|
||||
Gem::GemRunner.new.run args
|
||||
|
|
110
gem_prelude.rb
110
gem_prelude.rb
|
@ -6,8 +6,11 @@
|
|||
# * Encoding.default_external does not reflects -E.
|
||||
# * Should not expect Encoding.default_internal.
|
||||
# * Locale encoding is available.
|
||||
|
||||
if defined?(Gem) then
|
||||
|
||||
# :stopdoc:
|
||||
|
||||
module Kernel
|
||||
|
||||
def gem(gem_name, *version_requirements)
|
||||
|
@ -18,20 +21,17 @@ if defined?(Gem) then
|
|||
|
||||
module Gem
|
||||
|
||||
class LoadError < ::LoadError
|
||||
end
|
||||
|
||||
ConfigMap = {
|
||||
:sitedir => RbConfig::CONFIG["sitedir"],
|
||||
:ruby_version => RbConfig::CONFIG["ruby_version"],
|
||||
:rubylibprefix => RbConfig::CONFIG["rubylibprefix"],
|
||||
:libdir => RbConfig::CONFIG["libdir"],
|
||||
:sitelibdir => RbConfig::CONFIG["sitelibdir"],
|
||||
:arch => RbConfig::CONFIG["arch"],
|
||||
:bindir => RbConfig::CONFIG["bindir"],
|
||||
:EXEEXT => RbConfig::CONFIG["EXEEXT"],
|
||||
:RUBY_SO_NAME => RbConfig::CONFIG["RUBY_SO_NAME"],
|
||||
:ruby_install_name => RbConfig::CONFIG["ruby_install_name"]
|
||||
:arch => RbConfig::CONFIG["arch"],
|
||||
:bindir => RbConfig::CONFIG["bindir"],
|
||||
:libdir => RbConfig::CONFIG["libdir"],
|
||||
:ruby_install_name => RbConfig::CONFIG["ruby_install_name"],
|
||||
:ruby_version => RbConfig::CONFIG["ruby_version"],
|
||||
:rubylibprefix => RbConfig::CONFIG["rubylibprefix"],
|
||||
:sitedir => RbConfig::CONFIG["sitedir"],
|
||||
:sitelibdir => RbConfig::CONFIG["sitelibdir"],
|
||||
}
|
||||
|
||||
def self.dir
|
||||
|
@ -67,24 +67,30 @@ if defined?(Gem) then
|
|||
end
|
||||
|
||||
def self.set_home(home)
|
||||
home = home.gsub File::ALT_SEPARATOR, File::SEPARATOR if File::ALT_SEPARATOR
|
||||
@gem_home = home
|
||||
ensure_gem_subdirectories(@gem_home)
|
||||
end
|
||||
|
||||
def self.set_paths(gpaths)
|
||||
if gpaths
|
||||
@gem_path = gpaths.split(File::PATH_SEPARATOR)
|
||||
|
||||
if File::ALT_SEPARATOR then
|
||||
@gem_path.map! do |path|
|
||||
path.gsub File::ALT_SEPARATOR, File::SEPARATOR
|
||||
end
|
||||
end
|
||||
|
||||
@gem_path << Gem.dir
|
||||
else
|
||||
# TODO: should this be Gem.default_path instead?
|
||||
@gem_path = [Gem.dir]
|
||||
end
|
||||
|
||||
@gem_path.uniq!
|
||||
@gem_path.each do |gp| ensure_gem_subdirectories(gp) end
|
||||
end
|
||||
|
||||
def self.ensure_gem_subdirectories(path)
|
||||
end
|
||||
|
||||
# begin rubygems/defaults
|
||||
|
||||
@post_install_hooks ||= []
|
||||
@post_uninstall_hooks ||= []
|
||||
|
@ -106,8 +112,13 @@ if defined?(Gem) then
|
|||
if defined? RUBY_FRAMEWORK_VERSION then
|
||||
File.join File.dirname(ConfigMap[:sitedir]), 'Gems',
|
||||
ConfigMap[:ruby_version]
|
||||
# 1.9.2dev reverted to 1.8 style path
|
||||
elsif RUBY_VERSION > '1.9' and RUBY_VERSION < '1.9.2' then
|
||||
File.join(ConfigMap[:libdir], ConfigMap[:ruby_install_name], 'gems',
|
||||
ConfigMap[:ruby_version])
|
||||
else
|
||||
ConfigMap[:sitelibdir].sub(%r'/site_ruby/(?=[^/]+)', '/gems/')
|
||||
File.join(ConfigMap[:libdir], ruby_engine, 'gems',
|
||||
ConfigMap[:ruby_version])
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -123,15 +134,25 @@ if defined?(Gem) then
|
|||
# Default gem load path
|
||||
|
||||
def self.default_path
|
||||
if File.exist?(Gem.user_home)
|
||||
[user_dir, default_dir]
|
||||
else
|
||||
[default_dir]
|
||||
end
|
||||
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'
|
||||
exec_format = ConfigMap[:ruby_install_name].sub('ruby', '%s') rescue '%s'
|
||||
|
||||
unless exec_format =~ /%s/ then
|
||||
raise Gem::Exception,
|
||||
"[BUG] invalid exec_format #{exec_format.inspect}, no %s"
|
||||
end
|
||||
|
||||
exec_format
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -171,7 +192,9 @@ if defined?(Gem) then
|
|||
end
|
||||
|
||||
|
||||
# end rubygems/defaults
|
||||
|
||||
##
|
||||
# Methods before this line will be removed when QuickLoader is replaced
|
||||
# with the real RubyGems
|
||||
|
||||
|
@ -179,7 +202,7 @@ if defined?(Gem) then
|
|||
|
||||
begin
|
||||
verbose, debug = $VERBOSE, $DEBUG
|
||||
$DEBUG = $VERBOSE = nil
|
||||
$VERBOSE = $DEBUG = nil
|
||||
|
||||
begin
|
||||
require 'rubygems/defaults/operating_system'
|
||||
|
@ -226,14 +249,14 @@ if defined?(Gem) then
|
|||
|
||||
def push_gem_version_on_load_path(gem_name, *version_requirements)
|
||||
if version_requirements.empty?
|
||||
unless GemPaths.has_key?(gem_name)
|
||||
raise Gem::LoadError.new("Could not find RubyGem #{gem_name} (>= 0)\n")
|
||||
unless GemPaths.has_key?(gem_name) then
|
||||
raise Gem::LoadError, "Could not find RubyGem #{gem_name} (>= 0)\n"
|
||||
end
|
||||
|
||||
# highest version gems already active
|
||||
return false
|
||||
else
|
||||
if version_requirements.length > 1
|
||||
if version_requirements.length > 1 then
|
||||
QuickLoader.load_full_rubygems_library
|
||||
return gem(gem_name, *version_requirements)
|
||||
end
|
||||
|
@ -241,26 +264,24 @@ if defined?(Gem) then
|
|||
requirement, version = version_requirements[0].split
|
||||
requirement.strip!
|
||||
|
||||
if loaded_version = GemVersions[gem_name]
|
||||
if loaded_version = GemVersions[gem_name] then
|
||||
case requirement
|
||||
when ">", ">="
|
||||
if (loaded_version <=> Gem.calculate_integers_for_gem_version(version)) >= 0
|
||||
return false
|
||||
end
|
||||
when "~>"
|
||||
required_version = Gem.calculate_integers_for_gem_version(version)
|
||||
if (loaded_version[0] == required_version[0])
|
||||
return false
|
||||
end
|
||||
when ">", ">=" then
|
||||
return false if
|
||||
(loaded_version <=> Gem.integers_for(version)) >= 0
|
||||
when "~>" then
|
||||
required_version = Gem.integers_for version
|
||||
|
||||
return false if loaded_version.first == required_version.first
|
||||
end
|
||||
end
|
||||
|
||||
QuickLoader.load_full_rubygems_library
|
||||
gem(gem_name, *version_requirements)
|
||||
gem gem_name, *version_requirements
|
||||
end
|
||||
end
|
||||
|
||||
def calculate_integers_for_gem_version(gem_version)
|
||||
def integers_for(gem_version)
|
||||
numbers = gem_version.split(".").collect {|n| n.to_i}
|
||||
numbers.pop while numbers.last == 0
|
||||
numbers << 0 if numbers.empty?
|
||||
|
@ -270,16 +291,20 @@ if defined?(Gem) then
|
|||
def push_all_highest_version_gems_on_load_path
|
||||
Gem.path.each do |path|
|
||||
gems_directory = File.join(path, "gems")
|
||||
if File.exist?(gems_directory)
|
||||
|
||||
if File.exist?(gems_directory) then
|
||||
Dir.entries(gems_directory).each do |gem_directory_name|
|
||||
next if gem_directory_name == "." || gem_directory_name == ".."
|
||||
|
||||
dash = gem_directory_name.rindex("-")
|
||||
next if dash.nil?
|
||||
|
||||
gem_name = gem_directory_name[0...dash]
|
||||
current_version = GemVersions[gem_name]
|
||||
new_version = calculate_integers_for_gem_version(gem_directory_name[dash+1..-1])
|
||||
if current_version
|
||||
if (current_version <=> new_version) == -1
|
||||
new_version = integers_for(gem_directory_name[dash+1..-1])
|
||||
|
||||
if current_version then
|
||||
if (current_version <=> new_version) == -1 then
|
||||
GemVersions[gem_name] = new_version
|
||||
GemPaths[gem_name] = File.join(gems_directory, gem_directory_name)
|
||||
end
|
||||
|
@ -309,7 +334,7 @@ if defined?(Gem) then
|
|||
# "tag" the first require_path inserted into the $LOAD_PATH to enable
|
||||
# indexing correctly with rubygems proper when it inserts an explicitly
|
||||
# gem version
|
||||
unless require_paths.empty?
|
||||
unless require_paths.empty? then
|
||||
require_paths.first.instance_variable_set(:@gem_prelude_index, true)
|
||||
end
|
||||
# gem directories must come after -I and ENV['RUBYLIB']
|
||||
|
@ -318,8 +343,9 @@ if defined?(Gem) then
|
|||
|
||||
def const_missing(constant)
|
||||
QuickLoader.load_full_rubygems_library
|
||||
if Gem.const_defined?(constant)
|
||||
Gem.const_get(constant)
|
||||
|
||||
if Gem.const_defined?(constant) then
|
||||
Gem.const_get constant
|
||||
else
|
||||
super
|
||||
end
|
||||
|
|
50
lib/gauntlet_rubygems.rb
Normal file
50
lib/gauntlet_rubygems.rb
Normal file
|
@ -0,0 +1,50 @@
|
|||
require 'rubygems'
|
||||
require 'gauntlet'
|
||||
|
||||
##
|
||||
# GemGauntlet validates all current gems. Currently these packages are
|
||||
# borked:
|
||||
#
|
||||
# Asami-0.04 : No such file or directory - bin/Asami.rb
|
||||
# ObjectGraph-1.0.1 : No such file or directory - bin/objectgraph
|
||||
# evil-ruby-0.1.0 : authors must be Array of Strings
|
||||
# fresh_cookies-1.0.0 : authors must be Array of Strings
|
||||
# plugems_deploy-0.2.0 : authors must be Array of Strings
|
||||
# pmsrb-0.2.0 : authors must be Array of Strings
|
||||
# pqa-1.6 : authors must be Array of Strings
|
||||
# rant-0.5.7 : authors must be Array of Strings
|
||||
# rvsh-0.4.5 : No such file or directory - bin/rvsh
|
||||
# xen-0.1.2.1 : authors must be Array of Strings
|
||||
|
||||
class GemGauntlet < Gauntlet
|
||||
def run(name)
|
||||
warn name
|
||||
|
||||
spec = begin
|
||||
Gem::Specification.load 'gemspec'
|
||||
rescue SyntaxError
|
||||
Gem::Specification.from_yaml File.read('gemspec')
|
||||
end
|
||||
spec.validate
|
||||
|
||||
self.data[name] = false
|
||||
self.dirty = true
|
||||
rescue SystemCallError, Gem::InvalidSpecificationException => e
|
||||
self.data[name] = e.message
|
||||
self.dirty = true
|
||||
end
|
||||
|
||||
def should_skip?(name)
|
||||
self.data[name] == false
|
||||
end
|
||||
|
||||
def report
|
||||
self.data.sort.reject { |k,v| !v }.each do |k,v|
|
||||
puts "%-21s: %s" % [k, v]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
gauntlet = GemGauntlet.new
|
||||
gauntlet.run_the_gauntlet ARGV.shift
|
||||
gauntlet.report
|
|
@ -4,20 +4,17 @@
|
|||
# See LICENSE.txt for permissions.
|
||||
#++
|
||||
|
||||
|
||||
module RbConfig
|
||||
|
||||
# Only define datadir if it doesn't already exist.
|
||||
unless RbConfig.respond_to?(:datadir)
|
||||
##
|
||||
# Return the path to the data directory associated with the given package
|
||||
# name. Normally this is just
|
||||
# "#{RbConfig::CONFIG['datadir']}/#{package_name}", but may be modified by
|
||||
# packages like RubyGems to handle versioned data directories.
|
||||
|
||||
# Return the path to the data directory associated with the given
|
||||
# package name. Normally this is just
|
||||
# "#{RbConfig::CONFIG['datadir']}/#{package_name}", but may be
|
||||
# modified by packages like RubyGems to handle versioned data
|
||||
# directories.
|
||||
def RbConfig.datadir(package_name)
|
||||
def self.datadir(package_name)
|
||||
File.join(CONFIG['datadir'], package_name)
|
||||
end
|
||||
end unless RbConfig.respond_to?(:datadir)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
|
330
lib/rubygems.rb
330
lib/rubygems.rb
|
@ -8,11 +8,29 @@
|
|||
require 'rubygems/rubygems_version'
|
||||
require 'rubygems/defaults'
|
||||
require 'thread'
|
||||
require 'etc'
|
||||
|
||||
module Gem
|
||||
|
||||
##
|
||||
# Raised when RubyGems is unable to load or activate a gem. Contains the
|
||||
# name and version requirements of the gem that either conflicts with
|
||||
# already activated gems or that RubyGems is otherwise unable to activate.
|
||||
|
||||
class LoadError < ::LoadError
|
||||
attr_accessor :name, :version_requirement
|
||||
|
||||
##
|
||||
# Name of gem
|
||||
|
||||
attr_accessor :name
|
||||
|
||||
##
|
||||
# Version requirement of gem
|
||||
|
||||
attr_accessor :version_requirement
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
module Kernel
|
||||
|
@ -54,18 +72,102 @@ module Kernel
|
|||
end
|
||||
|
||||
##
|
||||
# Main module to hold all RubyGem classes/modules.
|
||||
# RubyGems is the Ruby standard for publishing and managing third party
|
||||
# libraries.
|
||||
#
|
||||
# For user documentation, see:
|
||||
#
|
||||
# * <tt>gem help</tt> and <tt>gem help [command]</tt>
|
||||
# * {RubyGems User Guide}[http://docs.rubygems.org/read/book/1]
|
||||
# * {Frequently Asked Questions}[http://docs.rubygems.org/read/book/3]
|
||||
#
|
||||
# For gem developer documentation see:
|
||||
#
|
||||
# * {Creating Gems}[http://docs.rubygems.org/read/chapter/5]
|
||||
# * Gem::Specification
|
||||
#
|
||||
# Further RubyGems documentation can be found at:
|
||||
#
|
||||
# * {RubyGems API}[http://rubygems.rubyforge.org/rdoc] (also available from
|
||||
# <tt>gem server</tt>)
|
||||
# * {RubyGems Bookshelf}[http://rubygem.org]
|
||||
#
|
||||
# == RubyGems Plugins
|
||||
#
|
||||
# As of RubyGems 1.3.2, RubyGems will load plugins installed in gems or
|
||||
# $LOAD_PATH. Plugins must be named 'rubygems_plugin' are discovered via
|
||||
# Gem::find_files then loaded. Take care when implementing a plugin as your
|
||||
# plugin file may be loaded multiple times if multiple versions of your gem
|
||||
# are installed.
|
||||
#
|
||||
# For an example plugin, see the graph gem which adds a `gem graph` command.
|
||||
#
|
||||
# == RubyGems Defaults, Packaging
|
||||
#
|
||||
# RubyGems defaults are stored in rubygems/defaults.rb. If you're packaging
|
||||
# RubyGems or implementing Ruby you can change RubyGems' defaults.
|
||||
#
|
||||
# For RubyGems packagers, provide lib/rubygems/operating_system.rb and
|
||||
# override any defaults from lib/rubygems/defaults.rb.
|
||||
#
|
||||
# For Ruby implementers, provide lib/rubygems/#{RUBY_ENGINE}.rb and override
|
||||
# any defaults from lib/rubygems/defaults.rb.
|
||||
#
|
||||
# If you need RubyGems to perform extra work on install or uninstall, your
|
||||
# defaults override file can set pre and post install and uninstall hooks.
|
||||
# See Gem::pre_install, Gem::pre_uninstall, Gem::post_install,
|
||||
# Gem::post_uninstall.
|
||||
#
|
||||
# == Bugs
|
||||
#
|
||||
# You can submit bugs to the
|
||||
# {RubyGems bug tracker}[http://rubyforge.org/tracker/?atid=575&group_id=126&func=browse]
|
||||
# on RubyForge
|
||||
#
|
||||
# == Credits
|
||||
#
|
||||
# RubyGems is currently maintained by Eric Hodel.
|
||||
#
|
||||
# RubyGems was originally developed at RubyConf 2003 by:
|
||||
#
|
||||
# * Rich Kilmer -- rich(at)infoether.com
|
||||
# * Chad Fowler -- chad(at)chadfowler.com
|
||||
# * David Black -- dblack(at)wobblini.net
|
||||
# * Paul Brannan -- paul(at)atdesk.com
|
||||
# * Jim Weirch -- {jim(at)weirichhouse.org}[mailto:jim@weirichhouse.org]
|
||||
#
|
||||
# Contributors:
|
||||
#
|
||||
# * Gavin Sinclair -- gsinclair(at)soyabean.com.au
|
||||
# * George Marrows -- george.marrows(at)ntlworld.com
|
||||
# * Dick Davies -- rasputnik(at)hellooperator.net
|
||||
# * Mauricio Fernandez -- batsman.geo(at)yahoo.com
|
||||
# * Simon Strandgaard -- neoneye(at)adslhome.dk
|
||||
# * Dave Glasser -- glasser(at)mit.edu
|
||||
# * Paul Duncan -- pabs(at)pablotron.org
|
||||
# * Ville Aine -- vaine(at)cs.helsinki.fi
|
||||
# * Eric Hodel -- drbrain(at)segment7.net
|
||||
# * Daniel Berger -- djberg96(at)gmail.com
|
||||
# * Phil Hagelberg -- technomancy(at)gmail.com
|
||||
# * Ryan Davis
|
||||
#
|
||||
# (If your name is missing, PLEASE let us know!)
|
||||
#
|
||||
# Thanks!
|
||||
#
|
||||
# -The RubyGems Team
|
||||
|
||||
module Gem
|
||||
|
||||
##
|
||||
# Configuration settings from ::RbConfig
|
||||
|
||||
ConfigMap = {} unless defined?(ConfigMap)
|
||||
|
||||
require 'rbconfig'
|
||||
RbConfig = Config unless defined? ::RbConfig
|
||||
|
||||
ConfigMap.merge!(
|
||||
:BASERUBY => RbConfig::CONFIG["BASERUBY"],
|
||||
:EXEEXT => RbConfig::CONFIG["EXEEXT"],
|
||||
:RUBY_INSTALL_NAME => RbConfig::CONFIG["RUBY_INSTALL_NAME"],
|
||||
:RUBY_SO_NAME => RbConfig::CONFIG["RUBY_SO_NAME"],
|
||||
:arch => RbConfig::CONFIG["arch"],
|
||||
:bindir => RbConfig::CONFIG["bindir"],
|
||||
|
@ -79,11 +181,16 @@ module Gem
|
|||
:vendorlibdir => RbConfig::CONFIG["vendorlibdir"]
|
||||
)
|
||||
|
||||
##
|
||||
# Default directories in a gem repository
|
||||
|
||||
DIRECTORIES = %w[cache doc gems specifications] unless defined?(DIRECTORIES)
|
||||
|
||||
# :stopdoc:
|
||||
MUTEX = Mutex.new
|
||||
|
||||
RubyGemsPackageVersion = RubyGemsVersion
|
||||
# :startdoc:
|
||||
|
||||
##
|
||||
# An Array of Regexps that match windows ruby platforms.
|
||||
|
@ -102,6 +209,7 @@ module Gem
|
|||
|
||||
@configuration = nil
|
||||
@loaded_specs = {}
|
||||
@loaded_stacks = {}
|
||||
@platforms = []
|
||||
@ruby = nil
|
||||
@sources = []
|
||||
|
@ -128,6 +236,14 @@ module Gem
|
|||
# Gem::Requirement and Gem::Version documentation.
|
||||
|
||||
def self.activate(gem, *version_requirements)
|
||||
if version_requirements.last.is_a?(Hash)
|
||||
options = version_requirements.pop
|
||||
else
|
||||
options = {}
|
||||
end
|
||||
|
||||
sources = options[:sources] || []
|
||||
|
||||
if version_requirements.empty? then
|
||||
version_requirements = Gem::Requirement.default
|
||||
end
|
||||
|
@ -146,8 +262,18 @@ module Gem
|
|||
existing_spec = @loaded_specs[gem.name]
|
||||
|
||||
unless matches.any? { |spec| spec.version == existing_spec.version } then
|
||||
raise Gem::Exception,
|
||||
"can't activate #{gem}, already activated #{existing_spec.full_name}"
|
||||
sources_message = sources.map { |spec| spec.full_name }
|
||||
stack_message = @loaded_stacks[gem.name].map { |spec| spec.full_name }
|
||||
|
||||
msg = "can't activate #{gem} for #{sources_message.inspect}, "
|
||||
msg << "already activated #{existing_spec.full_name} for "
|
||||
msg << "#{stack_message.inspect}"
|
||||
|
||||
e = Gem::LoadError.new msg
|
||||
e.name = gem.name
|
||||
e.version_requirement = gem.version_requirements
|
||||
|
||||
raise e
|
||||
end
|
||||
|
||||
return false
|
||||
|
@ -159,10 +285,11 @@ module Gem
|
|||
|
||||
spec.loaded = true
|
||||
@loaded_specs[spec.name] = spec
|
||||
@loaded_stacks[spec.name] = sources.dup
|
||||
|
||||
# Load dependent gems first
|
||||
spec.runtime_dependencies.each do |dep_gem|
|
||||
activate dep_gem
|
||||
activate dep_gem, :sources => [spec, *sources]
|
||||
end
|
||||
|
||||
# bin directory must come before library directories
|
||||
|
@ -227,6 +354,35 @@ module Gem
|
|||
!Gem.source_index.search(gem).empty?
|
||||
end
|
||||
|
||||
##
|
||||
# Find the full path to the executable for gem +name+. If the +exec_name+
|
||||
# is not given, the gem's default_executable is chosen, otherwise the
|
||||
# specifed executable's path is returned. +version_requirements+ allows you
|
||||
# to specify specific gem versions.
|
||||
|
||||
def self.bin_path(name, exec_name = nil, *version_requirements)
|
||||
version_requirements = Gem::Requirement.default if
|
||||
version_requirements.empty?
|
||||
spec = Gem.source_index.find_name(name, version_requirements).last
|
||||
|
||||
raise Gem::GemNotFoundException,
|
||||
"can't find gem #{name} (#{version_requirements})" unless spec
|
||||
|
||||
exec_name ||= spec.default_executable
|
||||
|
||||
unless exec_name
|
||||
msg = "no default executable for #{spec.full_name}"
|
||||
raise Gem::Exception, msg
|
||||
end
|
||||
|
||||
unless spec.executables.include? exec_name
|
||||
msg = "can't find executable #{exec_name} for #{spec.full_name}"
|
||||
raise Gem::Exception, msg
|
||||
end
|
||||
|
||||
File.join(spec.full_gem_path, spec.bindir, exec_name).sub(/.*\s.*/m, '"\&"')
|
||||
end
|
||||
|
||||
##
|
||||
# The mode needed to read a file as straight binary.
|
||||
|
||||
|
@ -351,14 +507,27 @@ module Gem
|
|||
#
|
||||
# Gem.find_files('rdoc/discover').each do |path| load path end
|
||||
#
|
||||
# find_files does not search $LOAD_PATH for files, only gems.
|
||||
# find_files search $LOAD_PATH for files as well as gems.
|
||||
#
|
||||
# Note that find_files will return all files even if they are from different
|
||||
# versions of the same gem.
|
||||
|
||||
def self.find_files(path)
|
||||
load_path_files = $LOAD_PATH.map do |load_path|
|
||||
files = Dir["#{File.expand_path path, load_path}#{Gem.suffix_pattern}"]
|
||||
|
||||
files.select do |load_path_file|
|
||||
File.file? load_path_file.untaint
|
||||
end
|
||||
end.flatten
|
||||
|
||||
specs = searcher.find_all path
|
||||
|
||||
specs.map do |spec|
|
||||
specs_files = specs.map do |spec|
|
||||
searcher.matching_files spec, path
|
||||
end.flatten
|
||||
|
||||
(load_path_files + specs_files).flatten.uniq
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -373,7 +542,17 @@ module Gem
|
|||
# least on Win32).
|
||||
|
||||
def self.find_home
|
||||
File.expand_path("~")
|
||||
unless RUBY_VERSION > '1.9' then
|
||||
['HOME', 'USERPROFILE'].each do |homekey|
|
||||
return ENV[homekey] if ENV[homekey]
|
||||
end
|
||||
|
||||
if ENV['HOMEDRIVE'] && ENV['HOMEPATH'] then
|
||||
return "#{ENV['HOMEDRIVE']}#{ENV['HOMEPATH']}"
|
||||
end
|
||||
end
|
||||
|
||||
File.expand_path "~"
|
||||
rescue
|
||||
if File::ALT_SEPARATOR then
|
||||
"C:/"
|
||||
|
@ -477,22 +656,13 @@ module Gem
|
|||
# The file name and line number of the caller of the caller of this method.
|
||||
|
||||
def self.location_of_caller
|
||||
caller[1] =~ /(.*?):(\d+)$/i
|
||||
caller[1] =~ /(.*?):(\d+).*?$/i
|
||||
file = $1
|
||||
lineno = $2.to_i
|
||||
|
||||
[file, lineno]
|
||||
end
|
||||
|
||||
##
|
||||
# manage_gems is useless and deprecated. Don't call it anymore.
|
||||
|
||||
def self.manage_gems # :nodoc:
|
||||
file, lineno = location_of_caller
|
||||
|
||||
warn "#{file}:#{lineno}:Warning: Gem::manage_gems is deprecated and will be removed on or after March 2009."
|
||||
end
|
||||
|
||||
##
|
||||
# The version of the Marshal format for your Ruby.
|
||||
|
||||
|
@ -586,6 +756,33 @@ module Gem
|
|||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Promotes the load paths of the +gem_name+ over the load paths of
|
||||
# +over_name+. Useful for allowing one gem to override features in another
|
||||
# using #find_files.
|
||||
|
||||
def self.promote_load_path(gem_name, over_name)
|
||||
gem = Gem.loaded_specs[gem_name]
|
||||
over = Gem.loaded_specs[over_name]
|
||||
|
||||
raise ArgumentError, "gem #{gem_name} is not activated" if gem.nil?
|
||||
raise ArgumentError, "gem #{over_name} is not activated" if over.nil?
|
||||
|
||||
last_gem_path = File.join gem.full_gem_path, gem.require_paths.last
|
||||
|
||||
over_paths = over.require_paths.map do |path|
|
||||
File.join over.full_gem_path, path
|
||||
end
|
||||
|
||||
over_paths.each do |path|
|
||||
$LOAD_PATH.delete path
|
||||
end
|
||||
|
||||
gem = $LOAD_PATH.index(last_gem_path) + 1
|
||||
|
||||
$LOAD_PATH.insert(gem, *over_paths)
|
||||
end
|
||||
|
||||
##
|
||||
# Refresh source_index from disk and clear searcher.
|
||||
|
||||
|
@ -628,15 +825,23 @@ module Gem
|
|||
|
||||
private_class_method :report_activate_error
|
||||
|
||||
def self.required_location(gemname, libfile, *version_constraints)
|
||||
version_constraints = Gem::Requirement.default if version_constraints.empty?
|
||||
matches = Gem.source_index.find_name(gemname, version_constraints)
|
||||
##
|
||||
# Full path to +libfile+ in +gemname+. Searches for the latest gem unless
|
||||
# +requirements+ is given.
|
||||
|
||||
def self.required_location(gemname, libfile, *requirements)
|
||||
requirements = Gem::Requirement.default if requirements.empty?
|
||||
|
||||
matches = Gem.source_index.find_name gemname, requirements
|
||||
|
||||
return nil if matches.empty?
|
||||
|
||||
spec = matches.last
|
||||
spec.require_paths.each do |path|
|
||||
result = File.join(spec.full_gem_path, path, libfile)
|
||||
return result if File.exist?(result)
|
||||
result = File.join spec.full_gem_path, path, libfile
|
||||
return result if File.exist? result
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
|
@ -662,7 +867,13 @@ module Gem
|
|||
def self.ruby_version
|
||||
return @ruby_version if defined? @ruby_version
|
||||
version = RUBY_VERSION.dup
|
||||
version << ".#{RUBY_PATCHLEVEL}" if defined? RUBY_PATCHLEVEL
|
||||
|
||||
if defined?(RUBY_PATCHLEVEL) && RUBY_PATCHLEVEL != -1 then
|
||||
version << ".#{RUBY_PATCHLEVEL}"
|
||||
elsif defined?(RUBY_REVISION) then
|
||||
version << ".dev.#{RUBY_REVISION}"
|
||||
end
|
||||
|
||||
@ruby_version = Gem::Version.new version
|
||||
end
|
||||
|
||||
|
@ -679,7 +890,7 @@ module Gem
|
|||
# Set the Gem home directory (as reported by Gem.dir).
|
||||
|
||||
def self.set_home(home)
|
||||
home = home.gsub(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
|
||||
home = home.gsub File::ALT_SEPARATOR, File::SEPARATOR if File::ALT_SEPARATOR
|
||||
@gem_home = home
|
||||
end
|
||||
|
||||
|
@ -756,6 +967,31 @@ module Gem
|
|||
['', '.rb', '.rbw', '.so', '.bundle', '.dll', '.sl', '.jar']
|
||||
end
|
||||
|
||||
##
|
||||
# Prints the amount of time the supplied block takes to run using the debug
|
||||
# UI output.
|
||||
|
||||
def self.time(msg, width = 0, display = Gem.configuration.verbose)
|
||||
now = Time.now
|
||||
|
||||
value = yield
|
||||
|
||||
elapsed = Time.now - now
|
||||
|
||||
ui.say "%2$*1$s: %3$3.3fs" % [-width, msg, elapsed] if display
|
||||
|
||||
value
|
||||
end
|
||||
|
||||
##
|
||||
# Lazily loads DefaultUserInteraction and returns the default UI.
|
||||
|
||||
def self.ui
|
||||
require 'rubygems/user_interaction'
|
||||
|
||||
Gem::DefaultUserInteraction.ui
|
||||
end
|
||||
|
||||
##
|
||||
# Use the +home+ and +paths+ values for Gem.dir and Gem.path. Used mainly
|
||||
# by the unit tests to provide environment isolation.
|
||||
|
@ -786,6 +1022,9 @@ module Gem
|
|||
|
||||
class << self
|
||||
|
||||
##
|
||||
# Hash of loaded Gem::Specification keyed by name
|
||||
|
||||
attr_reader :loaded_specs
|
||||
|
||||
##
|
||||
|
@ -817,26 +1056,28 @@ module Gem
|
|||
|
||||
end
|
||||
|
||||
##
|
||||
# Location of Marshal quick gemspecs on remote repositories
|
||||
|
||||
MARSHAL_SPEC_DIR = "quick/Marshal.#{Gem.marshal_version}/"
|
||||
|
||||
##
|
||||
# Location of legacy YAML quick gemspecs on remote repositories
|
||||
|
||||
YAML_SPEC_DIR = 'quick/'
|
||||
|
||||
end
|
||||
|
||||
module RbConfig
|
||||
# :stopdoc:
|
||||
class << self
|
||||
# Return the path to the data directory associated with the named
|
||||
# package. If the package is loaded as a gem, return the gem
|
||||
# specific data directory. Otherwise return a path to the share
|
||||
# area as define by "#{ConfigMap[:datadir]}/#{package_name}".
|
||||
def datadir(package_name)
|
||||
##
|
||||
# Return the path to the data directory associated with the named package. If
|
||||
# the package is loaded as a gem, return the gem specific data directory.
|
||||
# Otherwise return a path to the share area as define by
|
||||
# "#{ConfigMap[:datadir]}/#{package_name}".
|
||||
|
||||
def RbConfig.datadir(package_name)
|
||||
Gem.datadir(package_name) ||
|
||||
File.join(Gem::ConfigMap[:datadir], package_name)
|
||||
end
|
||||
end
|
||||
# :startdoc:
|
||||
end
|
||||
|
||||
require 'rubygems/exceptions'
|
||||
require 'rubygems/version'
|
||||
|
@ -866,3 +1107,14 @@ if RUBY_VERSION < '1.9' then
|
|||
end
|
||||
|
||||
Gem.clear_paths
|
||||
|
||||
plugins = Gem.find_files 'rubygems_plugin'
|
||||
|
||||
plugins.each do |plugin|
|
||||
begin
|
||||
load plugin
|
||||
rescue => e
|
||||
warn "error loading #{plugin.inspect}: #{e.message} (#{e.class})"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -4,20 +4,18 @@
|
|||
# See LICENSE.txt for permissions.
|
||||
#++
|
||||
|
||||
module Gem
|
||||
|
||||
##
|
||||
# The Builder class processes RubyGem specification files
|
||||
# to produce a .gem file.
|
||||
#
|
||||
class Builder
|
||||
|
||||
include UserInteraction
|
||||
class Gem::Builder
|
||||
|
||||
include Gem::UserInteraction
|
||||
##
|
||||
# Constructs a builder instance for the provided specification
|
||||
#
|
||||
# spec:: [Gem::Specification] The specification instance
|
||||
#
|
||||
|
||||
def initialize(spec)
|
||||
require "yaml"
|
||||
require "rubygems/package"
|
||||
|
@ -29,7 +27,7 @@ module Gem
|
|||
##
|
||||
# Builds the gem from the specification. Returns the name of the file
|
||||
# written.
|
||||
#
|
||||
|
||||
def build
|
||||
@spec.mark_version
|
||||
@spec.validate
|
||||
|
@ -50,17 +48,21 @@ EOM
|
|||
|
||||
private
|
||||
|
||||
##
|
||||
# If the signing key was specified, then load the file, and swap to the
|
||||
# public key (TODO: we should probably just omit the signing key in favor of
|
||||
# the signing certificate, but that's for the future, also the signature
|
||||
# algorithm should be configurable)
|
||||
|
||||
def sign
|
||||
# if the signing key was specified, then load the file, and swap
|
||||
# to the public key (TODO: we should probably just omit the
|
||||
# signing key in favor of the signing certificate, but that's for
|
||||
# the future, also the signature algorithm should be configurable)
|
||||
signer = nil
|
||||
if @spec.respond_to?(:signing_key) && @spec.signing_key
|
||||
signer = Gem::Security::Signer.new(@spec.signing_key, @spec.cert_chain)
|
||||
|
||||
if @spec.respond_to?(:signing_key) and @spec.signing_key then
|
||||
signer = Gem::Security::Signer.new @spec.signing_key, @spec.cert_chain
|
||||
@spec.signing_key = nil
|
||||
@spec.cert_chain = signer.cert_chain.map { |cert| cert.to_s }
|
||||
end
|
||||
|
||||
signer
|
||||
end
|
||||
|
||||
|
@ -71,6 +73,7 @@ EOM
|
|||
|
||||
@spec.files.each do |file|
|
||||
next if File.directory? file
|
||||
next if file == @spec.file_name # Don't add gem onto itself
|
||||
|
||||
stat = File.stat file
|
||||
mode = stat.mode & 0777
|
||||
|
@ -84,5 +87,4 @@ EOM
|
|||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -5,38 +5,114 @@
|
|||
#++
|
||||
|
||||
require 'optparse'
|
||||
|
||||
require 'rubygems/user_interaction'
|
||||
|
||||
module Gem
|
||||
|
||||
##
|
||||
# Base class for all Gem commands. When creating a new gem command, define
|
||||
# #arguments, #defaults_str, #description and #usage (as appropriate).
|
||||
class Command
|
||||
# #new, #execute, #arguments, #defaults_str, #description and #usage
|
||||
# (as appropriate). See the above mentioned methods for details.
|
||||
#
|
||||
# A very good example to look at is Gem::Commands::ContentsCommand
|
||||
|
||||
include UserInteraction
|
||||
class Gem::Command
|
||||
|
||||
include Gem::UserInteraction
|
||||
|
||||
##
|
||||
# The name of the command.
|
||||
|
||||
attr_reader :command
|
||||
|
||||
##
|
||||
# The options for the command.
|
||||
|
||||
attr_reader :options
|
||||
|
||||
##
|
||||
# The default options for the command.
|
||||
|
||||
attr_accessor :defaults
|
||||
|
||||
##
|
||||
# The name of the command for command-line invocation.
|
||||
|
||||
attr_accessor :program_name
|
||||
|
||||
##
|
||||
# A short description of the command.
|
||||
|
||||
attr_accessor :summary
|
||||
|
||||
##
|
||||
# Arguments used when building gems
|
||||
|
||||
def self.build_args
|
||||
@build_args ||= []
|
||||
end
|
||||
|
||||
def self.build_args=(value)
|
||||
@build_args = value
|
||||
end
|
||||
|
||||
def self.common_options
|
||||
@common_options ||= []
|
||||
end
|
||||
|
||||
def self.add_common_option(*args, &handler)
|
||||
Gem::Command.common_options << [args, handler]
|
||||
end
|
||||
|
||||
def self.extra_args
|
||||
@extra_args ||= []
|
||||
end
|
||||
|
||||
def self.extra_args=(value)
|
||||
case value
|
||||
when Array
|
||||
@extra_args = value
|
||||
when String
|
||||
@extra_args = value.split
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Return an array of extra arguments for the command. The extra arguments
|
||||
# come from the gem configuration file read at program startup.
|
||||
|
||||
def self.specific_extra_args(cmd)
|
||||
specific_extra_args_hash[cmd]
|
||||
end
|
||||
|
||||
##
|
||||
# Add a list of extra arguments for the given command. +args+ may be an
|
||||
# array or a string to be split on white space.
|
||||
|
||||
def self.add_specific_extra_args(cmd,args)
|
||||
args = args.split(/\s+/) if args.kind_of? String
|
||||
specific_extra_args_hash[cmd] = args
|
||||
end
|
||||
|
||||
##
|
||||
# Accessor for the specific extra args hash (self initializing).
|
||||
|
||||
def self.specific_extra_args_hash
|
||||
@specific_extra_args_hash ||= Hash.new do |h,k|
|
||||
h[k] = Array.new
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Initializes a generic gem command named +command+. +summary+ is a short
|
||||
# description displayed in `gem help commands`. +defaults+ are the
|
||||
# default options. Defaults should be mirrored in #defaults_str, unless
|
||||
# there are none.
|
||||
# description displayed in `gem help commands`. +defaults+ are the default
|
||||
# options. Defaults should be mirrored in #defaults_str, unless there are
|
||||
# none.
|
||||
#
|
||||
# Use add_option to add command-line switches.
|
||||
# When defining a new command subclass, use add_option to add command-line
|
||||
# switches.
|
||||
#
|
||||
# Unhandled arguments (gem names, files, etc.) are left in
|
||||
# <tt>options[:args]</tt>.
|
||||
|
||||
def initialize(command, summary=nil, defaults={})
|
||||
@command = command
|
||||
@summary = summary
|
||||
|
@ -48,18 +124,30 @@ module Gem
|
|||
@when_invoked = nil
|
||||
end
|
||||
|
||||
##
|
||||
# True if +long+ begins with the characters from +short+.
|
||||
|
||||
def begins?(long, short)
|
||||
return false if short.nil?
|
||||
long[0, short.length] == short
|
||||
end
|
||||
|
||||
##
|
||||
# Override to provide command handling.
|
||||
#
|
||||
# #options will be filled in with your parsed options, unparsed options will
|
||||
# be left in <tt>options[:args]</tt>.
|
||||
#
|
||||
# See also: #get_all_gem_names, #get_one_gem_name,
|
||||
# #get_one_optional_argument
|
||||
|
||||
def execute
|
||||
fail "Generic command has no actions"
|
||||
raise Gem::Exception, "generic command has no actions"
|
||||
end
|
||||
|
||||
##
|
||||
# Get all gem names from the command line.
|
||||
|
||||
def get_all_gem_names
|
||||
args = options[:args]
|
||||
|
||||
|
@ -71,8 +159,10 @@ module Gem
|
|||
gem_names = args.select { |arg| arg !~ /^-/ }
|
||||
end
|
||||
|
||||
##
|
||||
# Get the single gem name from the command line. Fail if there is no gem
|
||||
# name or if there is more than one gem name given.
|
||||
|
||||
def get_one_gem_name
|
||||
args = options[:args]
|
||||
|
||||
|
@ -89,43 +179,74 @@ module Gem
|
|||
args.first
|
||||
end
|
||||
|
||||
##
|
||||
# Get a single optional argument from the command line. If more than one
|
||||
# argument is given, return only the first. Return nil if none are given.
|
||||
|
||||
def get_one_optional_argument
|
||||
args = options[:args] || []
|
||||
args.first
|
||||
end
|
||||
|
||||
# Override to provide details of the arguments a command takes.
|
||||
# It should return a left-justified string, one argument per line.
|
||||
##
|
||||
# Override to provide details of the arguments a command takes. It should
|
||||
# return a left-justified string, one argument per line.
|
||||
#
|
||||
# For example:
|
||||
#
|
||||
# def usage
|
||||
# "#{program_name} FILE [FILE ...]"
|
||||
# end
|
||||
#
|
||||
# def arguments
|
||||
# "FILE name of file to find"
|
||||
# end
|
||||
|
||||
def arguments
|
||||
""
|
||||
end
|
||||
|
||||
# Override to display the default values of the command
|
||||
# options. (similar to +arguments+, but displays the default
|
||||
# values).
|
||||
##
|
||||
# Override to display the default values of the command options. (similar to
|
||||
# +arguments+, but displays the default values).
|
||||
#
|
||||
# For example:
|
||||
#
|
||||
# def defaults_str
|
||||
# --no-gems-first --no-all
|
||||
# end
|
||||
|
||||
def defaults_str
|
||||
""
|
||||
end
|
||||
|
||||
##
|
||||
# Override to display a longer description of what this command does.
|
||||
|
||||
def description
|
||||
nil
|
||||
end
|
||||
|
||||
##
|
||||
# Override to display the usage for an individual gem command.
|
||||
#
|
||||
# The text "[options]" is automatically appended to the usage text.
|
||||
|
||||
def usage
|
||||
program_name
|
||||
end
|
||||
|
||||
##
|
||||
# Display the help message for the command.
|
||||
|
||||
def show_help
|
||||
parser.program_name = usage
|
||||
say parser
|
||||
end
|
||||
|
||||
##
|
||||
# Invoke the command with the given list of arguments.
|
||||
|
||||
def invoke(*args)
|
||||
handle_options(args)
|
||||
if options[:help]
|
||||
|
@ -137,43 +258,56 @@ module Gem
|
|||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Call the given block when invoked.
|
||||
#
|
||||
# Normal command invocations just executes the +execute+ method of
|
||||
# the command. Specifying an invocation block allows the test
|
||||
# methods to override the normal action of a command to determine
|
||||
# that it has been invoked correctly.
|
||||
# Normal command invocations just executes the +execute+ method of the
|
||||
# command. Specifying an invocation block allows the test methods to
|
||||
# override the normal action of a command to determine that it has been
|
||||
# invoked correctly.
|
||||
|
||||
def when_invoked(&block)
|
||||
@when_invoked = block
|
||||
end
|
||||
|
||||
##
|
||||
# Add a command-line option and handler to the command.
|
||||
#
|
||||
# See OptionParser#make_switch for an explanation of +opts+.
|
||||
#
|
||||
# +handler+ will be called with two values, the value of the argument and
|
||||
# the options hash.
|
||||
#
|
||||
# If the first argument of add_option is a Symbol, it's used to group
|
||||
# options in output. See `gem help list` for an example.
|
||||
|
||||
def add_option(*opts, &handler) # :yields: value, options
|
||||
group_name = Symbol === opts.first ? opts.shift : :options
|
||||
|
||||
@option_groups[group_name] << [opts, handler]
|
||||
end
|
||||
|
||||
##
|
||||
# Remove previously defined command-line argument +name+.
|
||||
|
||||
def remove_option(name)
|
||||
@option_groups.each do |_, option_list|
|
||||
option_list.reject! { |args, _| args.any? { |x| x =~ /^#{name}/ } }
|
||||
end
|
||||
end
|
||||
|
||||
# Merge a set of command options with the set of default options
|
||||
# (without modifying the default option hash).
|
||||
##
|
||||
# Merge a set of command options with the set of default options (without
|
||||
# modifying the default option hash).
|
||||
|
||||
def merge_options(new_options)
|
||||
@options = @defaults.clone
|
||||
new_options.each do |k,v| @options[k] = v end
|
||||
end
|
||||
|
||||
##
|
||||
# True if the command handles the given argument list.
|
||||
|
||||
def handles?(args)
|
||||
begin
|
||||
parser.parse!(args.dup)
|
||||
|
@ -183,8 +317,10 @@ module Gem
|
|||
end
|
||||
end
|
||||
|
||||
# Handle the given list of arguments by parsing them and recording
|
||||
# the results.
|
||||
##
|
||||
# Handle the given list of arguments by parsing them and recording the
|
||||
# results.
|
||||
|
||||
def handle_options(args)
|
||||
args = add_extra_args(args)
|
||||
@options = @defaults.clone
|
||||
|
@ -192,16 +328,22 @@ module Gem
|
|||
@options[:args] = args
|
||||
end
|
||||
|
||||
##
|
||||
# Adds extra args from ~/.gemrc
|
||||
|
||||
def add_extra_args(args)
|
||||
result = []
|
||||
s_extra = Command.specific_extra_args(@command)
|
||||
extra = Command.extra_args + s_extra
|
||||
while ! extra.empty?
|
||||
|
||||
s_extra = Gem::Command.specific_extra_args(@command)
|
||||
extra = Gem::Command.extra_args + s_extra
|
||||
|
||||
until extra.empty? do
|
||||
ex = []
|
||||
ex << extra.shift
|
||||
ex << extra.shift if extra.first.to_s =~ /^[^-]/
|
||||
result << ex if handles?(ex)
|
||||
end
|
||||
|
||||
result.flatten!
|
||||
result.concat(args)
|
||||
result
|
||||
|
@ -209,7 +351,9 @@ module Gem
|
|||
|
||||
private
|
||||
|
||||
##
|
||||
# Create on demand parser.
|
||||
|
||||
def parser
|
||||
create_option_parser if @parser.nil?
|
||||
@parser
|
||||
|
@ -227,7 +371,7 @@ module Gem
|
|||
configure_options group_name, option_list
|
||||
end
|
||||
|
||||
configure_options "Common", Command.common_options
|
||||
configure_options "Common", Gem::Command.common_options
|
||||
|
||||
@parser.separator("")
|
||||
unless arguments.empty?
|
||||
|
@ -280,63 +424,18 @@ module Gem
|
|||
@parser.separator ''
|
||||
end
|
||||
|
||||
##
|
||||
# Wraps +text+ to +width+
|
||||
def wrap(text, width)
|
||||
|
||||
def wrap(text, width) # :doc:
|
||||
text.gsub(/(.{1,#{width}})( +|$\n?)|(.{1,#{width}})/, "\\1\\3\n")
|
||||
end
|
||||
|
||||
##################################################################
|
||||
# Class methods for Command.
|
||||
class << self
|
||||
def common_options
|
||||
@common_options ||= []
|
||||
end
|
||||
|
||||
def add_common_option(*args, &handler)
|
||||
Gem::Command.common_options << [args, handler]
|
||||
end
|
||||
|
||||
def extra_args
|
||||
@extra_args ||= []
|
||||
end
|
||||
|
||||
def extra_args=(value)
|
||||
case value
|
||||
when Array
|
||||
@extra_args = value
|
||||
when String
|
||||
@extra_args = value.split
|
||||
end
|
||||
end
|
||||
|
||||
# Return an array of extra arguments for the command. The extra
|
||||
# arguments come from the gem configuration file read at program
|
||||
# startup.
|
||||
def specific_extra_args(cmd)
|
||||
specific_extra_args_hash[cmd]
|
||||
end
|
||||
|
||||
# Add a list of extra arguments for the given command. +args+
|
||||
# may be an array or a string to be split on white space.
|
||||
def add_specific_extra_args(cmd,args)
|
||||
args = args.split(/\s+/) if args.kind_of? String
|
||||
specific_extra_args_hash[cmd] = args
|
||||
end
|
||||
|
||||
# Accessor for the specific extra args hash (self initializing).
|
||||
def specific_extra_args_hash
|
||||
@specific_extra_args_hash ||= Hash.new do |h,k|
|
||||
h[k] = Array.new
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# Add the options common to all commands.
|
||||
|
||||
add_common_option('-h', '--help',
|
||||
'Get help on this command') do
|
||||
|value, options|
|
||||
'Get help on this command') do |value, options|
|
||||
options[:help] = true
|
||||
end
|
||||
|
||||
|
@ -359,7 +458,7 @@ module Gem
|
|||
# options get parsed.
|
||||
|
||||
add_common_option('--config-file FILE',
|
||||
"Use this config file instead of default") do
|
||||
'Use this config file instead of default') do
|
||||
end
|
||||
|
||||
add_common_option('--backtrace',
|
||||
|
@ -371,6 +470,7 @@ module Gem
|
|||
end
|
||||
|
||||
# :stopdoc:
|
||||
|
||||
HELP = %{
|
||||
RubyGems is a sophisticated package manager for Ruby. This is a
|
||||
basic help message containing pointers to more information.
|
||||
|
@ -392,15 +492,20 @@ module Gem
|
|||
gem help platforms show information about platforms
|
||||
gem help <COMMAND> show help on COMMAND
|
||||
(e.g. 'gem help install')
|
||||
gem server present a web page at
|
||||
http://localhost:8808/
|
||||
with info about installed gems
|
||||
Further information:
|
||||
http://rubygems.rubyforge.org
|
||||
}.gsub(/^ /, "")
|
||||
}.gsub(/^ /, '')
|
||||
|
||||
# :startdoc:
|
||||
|
||||
end # class
|
||||
|
||||
# This is where Commands will be placed in the namespace
|
||||
module Commands; end
|
||||
|
||||
end
|
||||
|
||||
##
|
||||
# This is where Commands will be placed in the namespace
|
||||
|
||||
module Gem::Commands
|
||||
end
|
||||
|
||||
|
|
|
@ -8,20 +8,39 @@ require 'timeout'
|
|||
require 'rubygems/command'
|
||||
require 'rubygems/user_interaction'
|
||||
|
||||
module Gem
|
||||
##
|
||||
# The command manager registers and installs all the individual sub-commands
|
||||
# supported by the gem command.
|
||||
#
|
||||
# Extra commands can be provided by writing a rubygems_plugin.rb
|
||||
# file in an installed gem. You should register your command against the
|
||||
# Gem::CommandManager instance, like this:
|
||||
#
|
||||
# # file rubygems_plugin.rb
|
||||
# require 'rubygems/command_manager'
|
||||
#
|
||||
# class Gem::Commands::EditCommand < Gem::Command
|
||||
# # ...
|
||||
# end
|
||||
#
|
||||
# Gem::CommandManager.instance.register_command :edit
|
||||
#
|
||||
# See Gem::Command for instructions on writing gem commands.
|
||||
|
||||
####################################################################
|
||||
# The command manager registers and installs all the individual
|
||||
# sub-commands supported by the gem command.
|
||||
class CommandManager
|
||||
include UserInteraction
|
||||
class Gem::CommandManager
|
||||
|
||||
include Gem::UserInteraction
|
||||
|
||||
##
|
||||
# Return the authoritative instance of the command manager.
|
||||
|
||||
def self.instance
|
||||
@command_manager ||= CommandManager.new
|
||||
@command_manager ||= new
|
||||
end
|
||||
|
||||
##
|
||||
# Register all the subcommands supported by the gem command.
|
||||
|
||||
def initialize
|
||||
@commands = {}
|
||||
register_command :build
|
||||
|
@ -53,24 +72,32 @@ module Gem
|
|||
register_command :which
|
||||
end
|
||||
|
||||
##
|
||||
# Register the command object.
|
||||
|
||||
def register_command(command_obj)
|
||||
@commands[command_obj] = false
|
||||
end
|
||||
|
||||
##
|
||||
# Return the registered command from the command name.
|
||||
|
||||
def [](command_name)
|
||||
command_name = command_name.intern
|
||||
return nil if @commands[command_name].nil?
|
||||
@commands[command_name] ||= load_and_instantiate(command_name)
|
||||
end
|
||||
|
||||
# Return a list of all command names (as strings).
|
||||
##
|
||||
# Return a sorted list of all command names (as strings).
|
||||
|
||||
def command_names
|
||||
@commands.keys.collect {|key| key.to_s}.sort
|
||||
end
|
||||
|
||||
##
|
||||
# Run the config specified by +args+.
|
||||
|
||||
def run(args)
|
||||
process_args(args)
|
||||
rescue StandardError, Timeout::Error => ex
|
||||
|
@ -107,11 +134,10 @@ module Gem
|
|||
end
|
||||
|
||||
def find_command(cmd_name)
|
||||
possibilities = find_command_possibilities(cmd_name)
|
||||
if possibilities.size > 1
|
||||
possibilities = find_command_possibilities cmd_name
|
||||
if possibilities.size > 1 then
|
||||
raise "Ambiguous command #{cmd_name} matches [#{possibilities.join(', ')}]"
|
||||
end
|
||||
if possibilities.size < 1
|
||||
elsif possibilities.size < 1 then
|
||||
raise "Unknown command #{cmd_name}"
|
||||
end
|
||||
|
||||
|
@ -120,7 +146,8 @@ module Gem
|
|||
|
||||
def find_command_possibilities(cmd_name)
|
||||
len = cmd_name.length
|
||||
self.command_names.select { |n| cmd_name == n[0,len] }
|
||||
|
||||
command_names.select { |n| cmd_name == n[0, len] }
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -142,5 +169,6 @@ module Gem
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -21,6 +21,10 @@ class Gem::Commands::CheckCommand < Gem::Command
|
|||
options[:alien] = true
|
||||
end
|
||||
|
||||
add_option('-v', '--verbose', "Spew more words") do |value, options|
|
||||
options[:verbose] = true
|
||||
end
|
||||
|
||||
add_option('-t', '--test', "Run unit tests for gem") do |value, options|
|
||||
options[:test] = true
|
||||
end
|
||||
|
@ -38,16 +42,17 @@ class Gem::Commands::CheckCommand < Gem::Command
|
|||
|
||||
if options[:alien]
|
||||
say "Performing the 'alien' operation"
|
||||
Gem::Validator.new.alien.each do |key, val|
|
||||
if(val.size > 0)
|
||||
say
|
||||
gems = get_all_gem_names rescue []
|
||||
Gem::Validator.new.alien(gems).sort.each do |key, val|
|
||||
unless val.empty? then
|
||||
say "#{key} has #{val.size} problems"
|
||||
val.each do |error_entry|
|
||||
say "\t#{error_entry.path}:"
|
||||
say "\t#{error_entry.problem}"
|
||||
say
|
||||
say " #{error_entry.path}:"
|
||||
say " #{error_entry.problem}"
|
||||
end
|
||||
else
|
||||
say "#{key} is error-free"
|
||||
say "#{key} is error-free" if options[:verbose]
|
||||
end
|
||||
say
|
||||
end
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
require 'rubygems/command'
|
||||
require 'rubygems/source_index'
|
||||
require 'rubygems/dependency_list'
|
||||
require 'rubygems/uninstaller'
|
||||
|
||||
class Gem::Commands::CleanupCommand < Gem::Command
|
||||
|
||||
|
@ -22,6 +23,13 @@ class Gem::Commands::CleanupCommand < Gem::Command
|
|||
"--no-dryrun"
|
||||
end
|
||||
|
||||
def description # :nodoc:
|
||||
<<-EOF
|
||||
The cleanup command removes old gems from GEM_HOME. If an older version is
|
||||
installed elsewhere in GEM_PATH the cleanup command won't touch it.
|
||||
EOF
|
||||
end
|
||||
|
||||
def usage # :nodoc:
|
||||
"#{program_name} [GEMNAME ...]"
|
||||
end
|
||||
|
@ -41,7 +49,8 @@ class Gem::Commands::CleanupCommand < Gem::Command
|
|||
|
||||
unless options[:args].empty? then
|
||||
options[:args].each do |gem_name|
|
||||
specs = Gem.cache.search(/^#{gem_name}$/i)
|
||||
dep = Gem::Dependency.new gem_name, Gem::Requirement.default
|
||||
specs = Gem.source_index.search dep
|
||||
specs.each do |spec|
|
||||
gems_to_cleanup << spec
|
||||
end
|
||||
|
@ -56,7 +65,6 @@ class Gem::Commands::CleanupCommand < Gem::Command
|
|||
primary_gems[spec.name].version != spec.version
|
||||
}
|
||||
|
||||
uninstall_command = Gem::CommandManager.instance['uninstall']
|
||||
deplist = Gem::DependencyList.new
|
||||
gems_to_cleanup.uniq.each do |spec| deplist.add spec end
|
||||
|
||||
|
@ -69,14 +77,21 @@ class Gem::Commands::CleanupCommand < Gem::Command
|
|||
say "Attempting to uninstall #{spec.full_name}"
|
||||
|
||||
options[:args] = [spec.name]
|
||||
options[:version] = "= #{spec.version}"
|
||||
options[:executables] = false
|
||||
|
||||
uninstaller = Gem::Uninstaller.new spec.name, options
|
||||
uninstall_options = {
|
||||
:executables => false,
|
||||
:version => "= #{spec.version}",
|
||||
}
|
||||
|
||||
if Gem.user_dir == spec.installation_path then
|
||||
uninstall_options[:install_dir] = spec.installation_path
|
||||
end
|
||||
|
||||
uninstaller = Gem::Uninstaller.new spec.name, uninstall_options
|
||||
|
||||
begin
|
||||
uninstaller.uninstall
|
||||
rescue Gem::DependencyRemovalException,
|
||||
rescue Gem::DependencyRemovalException, Gem::InstallError,
|
||||
Gem::GemNotInHomeException => e
|
||||
say "Unable to uninstall #{spec.full_name}:"
|
||||
say "\t#{e.class}: #{e.message}"
|
||||
|
|
|
@ -11,6 +11,11 @@ class Gem::Commands::ContentsCommand < Gem::Command
|
|||
|
||||
add_version_option
|
||||
|
||||
add_option( '--all',
|
||||
"Contents for all gems") do |all, options|
|
||||
options[:all] = all
|
||||
end
|
||||
|
||||
add_option('-s', '--spec-dir a,b,c', Array,
|
||||
"Search for gems under specific paths") do |spec_dirs, options|
|
||||
options[:specdirs] = spec_dirs
|
||||
|
@ -20,6 +25,11 @@ class Gem::Commands::ContentsCommand < Gem::Command
|
|||
"Only return files in the Gem's lib_dirs") do |lib_only, options|
|
||||
options[:lib_only] = lib_only
|
||||
end
|
||||
|
||||
add_option( '--[no-]prefix',
|
||||
"Don't include installed path prefix") do |prefix, options|
|
||||
options[:prefix] = prefix
|
||||
end
|
||||
end
|
||||
|
||||
def arguments # :nodoc:
|
||||
|
@ -27,46 +37,60 @@ class Gem::Commands::ContentsCommand < Gem::Command
|
|||
end
|
||||
|
||||
def defaults_str # :nodoc:
|
||||
"--no-lib-only"
|
||||
"--no-lib-only --prefix"
|
||||
end
|
||||
|
||||
def usage # :nodoc:
|
||||
"#{program_name} GEMNAME"
|
||||
"#{program_name} GEMNAME [GEMNAME ...]"
|
||||
end
|
||||
|
||||
def execute
|
||||
version = options[:version] || Gem::Requirement.default
|
||||
gem = get_one_gem_name
|
||||
|
||||
s = options[:specdirs].map do |i|
|
||||
spec_dirs = options[:specdirs].map do |i|
|
||||
[i, File.join(i, "specifications")]
|
||||
end.flatten
|
||||
|
||||
path_kind = if s.empty? then
|
||||
s = Gem::SourceIndex.installed_spec_directories
|
||||
path_kind = if spec_dirs.empty? then
|
||||
spec_dirs = Gem::SourceIndex.installed_spec_directories
|
||||
"default gem paths"
|
||||
else
|
||||
"specified path"
|
||||
end
|
||||
|
||||
si = Gem::SourceIndex.from_gems_in(*s)
|
||||
si = Gem::SourceIndex.from_gems_in(*spec_dirs)
|
||||
|
||||
gem_spec = si.find_name(gem, version).last
|
||||
gem_names = if options[:all] then
|
||||
si.map { |_, spec| spec.name }
|
||||
else
|
||||
get_all_gem_names
|
||||
end
|
||||
|
||||
gem_names.each do |name|
|
||||
gem_spec = si.find_name(name, version).last
|
||||
|
||||
unless gem_spec then
|
||||
say "Unable to find gem '#{gem}' in #{path_kind}"
|
||||
say "Unable to find gem '#{name}' in #{path_kind}"
|
||||
|
||||
if Gem.configuration.verbose then
|
||||
say "\nDirectories searched:"
|
||||
s.each { |dir| say dir }
|
||||
spec_dirs.each { |dir| say dir }
|
||||
end
|
||||
|
||||
terminate_interaction
|
||||
terminate_interaction 1 if gem_names.length == 1
|
||||
end
|
||||
|
||||
files = options[:lib_only] ? gem_spec.lib_files : gem_spec.files
|
||||
|
||||
files.each do |f|
|
||||
say File.join(gem_spec.full_gem_path, f)
|
||||
path = if options[:prefix] then
|
||||
File.join gem_spec.full_gem_path, f
|
||||
else
|
||||
f
|
||||
end
|
||||
|
||||
say path
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,57 +1,133 @@
|
|||
require 'rubygems/command'
|
||||
require 'rubygems/indexer'
|
||||
|
||||
##
|
||||
# Generates a index files for use as a gem server.
|
||||
#
|
||||
# See `gem help generate_index`
|
||||
|
||||
class Gem::Commands::GenerateIndexCommand < Gem::Command
|
||||
|
||||
def initialize
|
||||
super 'generate_index',
|
||||
'Generates the index files for a gem server directory',
|
||||
:directory => '.'
|
||||
:directory => '.', :build_legacy => true, :build_modern => true
|
||||
|
||||
add_option '-d', '--directory=DIRNAME',
|
||||
'repository base dir containing gems subdir' do |dir, options|
|
||||
options[:directory] = File.expand_path dir
|
||||
end
|
||||
|
||||
add_option '--[no-]legacy',
|
||||
'Generate indexes for RubyGems older than',
|
||||
'1.2.0' do |value, options|
|
||||
unless options[:build_modern] or value then
|
||||
raise OptionParser::InvalidOption, 'no indicies will be built'
|
||||
end
|
||||
|
||||
options[:build_legacy] = value
|
||||
end
|
||||
|
||||
add_option '--[no-]modern',
|
||||
'Generate indexes for RubyGems newer',
|
||||
'than 1.2.0' do |value, options|
|
||||
unless options[:build_legacy] or value then
|
||||
raise OptionParser::InvalidOption, 'no indicies will be built'
|
||||
end
|
||||
|
||||
options[:build_modern] = value
|
||||
end
|
||||
|
||||
add_option '--update',
|
||||
'Update modern indexes with gems added',
|
||||
'since the last update' do |value, options|
|
||||
options[:update] = value
|
||||
end
|
||||
|
||||
add_option :RSS, '--rss-gems-host=GEM_HOST',
|
||||
'Host name where gems are served from,',
|
||||
'used for GUID and enclosure values' do |value, options|
|
||||
options[:rss_gems_host] = value
|
||||
end
|
||||
|
||||
add_option :RSS, '--rss-host=HOST',
|
||||
'Host name for more gems information,',
|
||||
'used for RSS feed link' do |value, options|
|
||||
options[:rss_host] = value
|
||||
end
|
||||
|
||||
add_option :RSS, '--rss-title=TITLE',
|
||||
'Set title for RSS feed' do |value, options|
|
||||
options[:rss_title] = value
|
||||
end
|
||||
end
|
||||
|
||||
def defaults_str # :nodoc:
|
||||
"--directory ."
|
||||
"--directory . --legacy --modern"
|
||||
end
|
||||
|
||||
def description # :nodoc:
|
||||
<<-EOF
|
||||
The generate_index command creates a set of indexes for serving gems
|
||||
statically. The command expects a 'gems' directory under the path given to
|
||||
the --directory option. When done, it will generate a set of files like this:
|
||||
the --directory option. The given directory will be the directory you serve
|
||||
as the gem repository.
|
||||
|
||||
gems/ # .gem files you want to index
|
||||
For `gem generate_index --directory /path/to/repo`, expose /path/to/repo via
|
||||
your HTTP server configuration (not /path/to/repo/gems).
|
||||
|
||||
When done, it will generate a set of files like this:
|
||||
|
||||
gems/*.gem # .gem files you want to
|
||||
# index
|
||||
|
||||
specs.<version>.gz # specs index
|
||||
latest_specs.<version>.gz # latest specs index
|
||||
prerelease_specs.<version>.gz # prerelease specs index
|
||||
quick/Marshal.<version>/<gemname>.gemspec.rz # Marshal quick index file
|
||||
|
||||
# these files support legacy RubyGems
|
||||
quick/index
|
||||
quick/index.rz # quick index manifest
|
||||
quick/<gemname>.gemspec.rz # legacy YAML quick index file
|
||||
quick/Marshal.<version>/<gemname>.gemspec.rz # Marshal quick index file
|
||||
quick/<gemname>.gemspec.rz # legacy YAML quick index
|
||||
# file
|
||||
Marshal.<version>
|
||||
Marshal.<version>.Z # Marshal full index
|
||||
yaml
|
||||
yaml.Z # legacy YAML full index
|
||||
|
||||
The .Z and .rz extension files are compressed with the inflate algorithm. The
|
||||
Marshal version number comes from ruby's Marshal::MAJOR_VERSION and
|
||||
Marshal::MINOR_VERSION constants. It is used to ensure compatibility. The
|
||||
yaml indexes exist for legacy RubyGems clients and fallback in case of Marshal
|
||||
version changes.
|
||||
The .Z and .rz extension files are compressed with the inflate algorithm.
|
||||
The Marshal version number comes from ruby's Marshal::MAJOR_VERSION and
|
||||
Marshal::MINOR_VERSION constants. It is used to ensure compatibility.
|
||||
The yaml indexes exist for legacy RubyGems clients and fallback in case of
|
||||
Marshal version changes.
|
||||
|
||||
If --rss-host and --rss-gem-host are given an RSS feed will be generated at
|
||||
index.rss containing gems released in the last two days.
|
||||
EOF
|
||||
end
|
||||
|
||||
def execute
|
||||
if options[:update] and
|
||||
(options[:rss_host] or options[:rss_gems_host]) then
|
||||
alert_error '--update not compatible with RSS generation'
|
||||
terminate_interaction 1
|
||||
end
|
||||
|
||||
if not File.exist?(options[:directory]) or
|
||||
not File.directory?(options[:directory]) then
|
||||
alert_error "unknown directory name #{directory}."
|
||||
terminate_interaction 1
|
||||
else
|
||||
indexer = Gem::Indexer.new options[:directory]
|
||||
indexer = Gem::Indexer.new options.delete(:directory), options
|
||||
|
||||
if options[:update] then
|
||||
indexer.update_index
|
||||
else
|
||||
indexer.generate_index
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -6,6 +6,11 @@ require 'rubygems/local_remote_options'
|
|||
require 'rubygems/validator'
|
||||
require 'rubygems/version_option'
|
||||
|
||||
##
|
||||
# Gem installer command line tool
|
||||
#
|
||||
# See `gem help install`
|
||||
|
||||
class Gem::Commands::InstallCommand < Gem::Command
|
||||
|
||||
include Gem::VersionOption
|
||||
|
@ -43,11 +48,51 @@ class Gem::Commands::InstallCommand < Gem::Command
|
|||
The install command installs local or remote gem into a gem repository.
|
||||
|
||||
For gems with executables ruby installs a wrapper file into the executable
|
||||
directory by deault. This can be overridden with the --no-wrappers option.
|
||||
directory by default. This can be overridden with the --no-wrappers option.
|
||||
The wrapper allows you to choose among alternate gem versions using _version_.
|
||||
|
||||
For example `rake _0.7.3_ --version` will run rake version 0.7.3 if a newer
|
||||
version is also installed.
|
||||
|
||||
If an extension fails to compile during gem installation the gem
|
||||
specification is not written out, but the gem remains unpacked in the
|
||||
repository. You may need to specify the path to the library's headers and
|
||||
libraries to continue. You can do this by adding a -- between RubyGems'
|
||||
options and the extension's build options:
|
||||
|
||||
$ gem install some_extension_gem
|
||||
[build fails]
|
||||
Gem files will remain installed in \\
|
||||
/path/to/gems/some_extension_gem-1.0 for inspection.
|
||||
Results logged to /path/to/gems/some_extension_gem-1.0/gem_make.out
|
||||
$ gem install some_extension_gem -- --with-extension-lib=/path/to/lib
|
||||
[build succeeds]
|
||||
$ gem list some_extension_gem
|
||||
|
||||
*** LOCAL GEMS ***
|
||||
|
||||
some_extension_gem (1.0)
|
||||
$
|
||||
|
||||
If you correct the compilation errors by editing the gem files you will need
|
||||
to write the specification by hand. For example:
|
||||
|
||||
$ gem install some_extension_gem
|
||||
[build fails]
|
||||
Gem files will remain installed in \\
|
||||
/path/to/gems/some_extension_gem-1.0 for inspection.
|
||||
Results logged to /path/to/gems/some_extension_gem-1.0/gem_make.out
|
||||
$ [cd /path/to/gems/some_extension_gem-1.0]
|
||||
$ [edit files or what-have-you and run make]
|
||||
$ gem spec ../../cache/some_extension_gem-1.0.gem --ruby > \\
|
||||
../../specifications/some_extension_gem-1.0.gemspec
|
||||
$ gem list some_extension_gem
|
||||
|
||||
*** LOCAL GEMS ***
|
||||
|
||||
some_extension_gem (1.0)
|
||||
$
|
||||
|
||||
EOF
|
||||
end
|
||||
|
||||
|
@ -65,24 +110,11 @@ version is also installed.
|
|||
|
||||
ENV.delete 'GEM_PATH' if options[:install_dir].nil? and RUBY_VERSION > '1.9'
|
||||
|
||||
install_options = {
|
||||
:env_shebang => options[:env_shebang],
|
||||
:domain => options[:domain],
|
||||
:force => options[:force],
|
||||
:format_executable => options[:format_executable],
|
||||
:ignore_dependencies => options[:ignore_dependencies],
|
||||
:install_dir => options[:install_dir],
|
||||
:security_policy => options[:security_policy],
|
||||
:wrappers => options[:wrappers],
|
||||
:bin_dir => options[:bin_dir],
|
||||
:development => options[:development],
|
||||
}
|
||||
|
||||
exit_code = 0
|
||||
|
||||
get_all_gem_names.each do |gem_name|
|
||||
begin
|
||||
inst = Gem::DependencyInstaller.new install_options
|
||||
inst = Gem::DependencyInstaller.new options
|
||||
inst.install gem_name, options[:version]
|
||||
|
||||
inst.installed_gems.each do |spec|
|
||||
|
@ -96,24 +128,16 @@ version is also installed.
|
|||
rescue Gem::GemNotFoundException => e
|
||||
alert_error e.message
|
||||
exit_code |= 2
|
||||
# rescue => e
|
||||
# # TODO: Fix this handle to allow the error to propagate to
|
||||
# # the top level handler. Examine the other errors as
|
||||
# # well. This implementation here looks suspicious to me --
|
||||
# # JimWeirich (4/Jan/05)
|
||||
# alert_error "Error installing gem #{gem_name}: #{e.message}"
|
||||
# return
|
||||
end
|
||||
end
|
||||
|
||||
unless installed_gems.empty? then
|
||||
gems = installed_gems.length == 1 ? 'gem' : 'gems'
|
||||
say "#{installed_gems.length} #{gems} installed"
|
||||
end
|
||||
|
||||
# NOTE: *All* of the RI documents must be generated first.
|
||||
# For some reason, RI docs cannot be generated after any RDoc
|
||||
# documents are generated.
|
||||
# NOTE: *All* of the RI documents must be generated first. For some
|
||||
# reason, RI docs cannot be generated after any RDoc documents are
|
||||
# generated.
|
||||
|
||||
if options[:generate_ri] then
|
||||
installed_gems.each do |gem|
|
||||
|
@ -131,15 +155,17 @@ version is also installed.
|
|||
|
||||
if options[:test] then
|
||||
installed_gems.each do |spec|
|
||||
gem_spec = Gem::SourceIndex.from_installed_gems.search(spec.name, spec.version.version).first
|
||||
gem_spec = Gem::SourceIndex.from_installed_gems.find_name(spec.name, spec.version.version).first
|
||||
result = Gem::Validator.new.unit_test(gem_spec)
|
||||
if result and not result.passed?
|
||||
unless ask_yes_no("...keep Gem?", true) then
|
||||
unless ask_yes_no("...keep Gem?", true)
|
||||
require 'rubygems/uninstaller'
|
||||
Gem::Uninstaller.new(spec.name, :version => spec.version.version).uninstall
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
raise Gem::SystemExitException, exit_code
|
||||
end
|
||||
|
|
|
@ -2,9 +2,11 @@ require 'rubygems/command'
|
|||
require 'rubygems/local_remote_options'
|
||||
require 'rubygems/spec_fetcher'
|
||||
require 'rubygems/version_option'
|
||||
require 'rubygems/text'
|
||||
|
||||
class Gem::Commands::QueryCommand < Gem::Command
|
||||
|
||||
include Gem::Text
|
||||
include Gem::LocalRemoteOptions
|
||||
include Gem::VersionOption
|
||||
|
||||
|
@ -43,6 +45,11 @@ class Gem::Commands::QueryCommand < Gem::Command
|
|||
options[:all] = value
|
||||
end
|
||||
|
||||
add_option( '--prerelease',
|
||||
'Display prerelease versions') do |value, options|
|
||||
options[:prerelease] = value
|
||||
end
|
||||
|
||||
add_local_remote_options
|
||||
end
|
||||
|
||||
|
@ -54,6 +61,7 @@ class Gem::Commands::QueryCommand < Gem::Command
|
|||
exit_code = 0
|
||||
|
||||
name = options[:name]
|
||||
prerelease = options[:prerelease]
|
||||
|
||||
if options[:installed] then
|
||||
if name.source.empty? then
|
||||
|
@ -72,6 +80,10 @@ class Gem::Commands::QueryCommand < Gem::Command
|
|||
dep = Gem::Dependency.new name, Gem::Requirement.default
|
||||
|
||||
if local? then
|
||||
if prerelease and not both? then
|
||||
alert_warning "prereleases are always shown locally"
|
||||
end
|
||||
|
||||
if ui.outs.tty? or both? then
|
||||
say
|
||||
say "*** LOCAL GEMS ***"
|
||||
|
@ -98,8 +110,13 @@ class Gem::Commands::QueryCommand < Gem::Command
|
|||
|
||||
begin
|
||||
fetcher = Gem::SpecFetcher.fetcher
|
||||
spec_tuples = fetcher.find_matching dep, all, false
|
||||
spec_tuples = fetcher.find_matching dep, all, false, prerelease
|
||||
rescue Gem::RemoteFetcher::FetchError => e
|
||||
if prerelease then
|
||||
raise Gem::OperationNotSupportedError,
|
||||
"Prereleases not supported on legacy repositories"
|
||||
end
|
||||
|
||||
raise unless fetcher.warn_legacy e do
|
||||
require 'rubygems/source_info_cache'
|
||||
|
||||
|
@ -145,6 +162,12 @@ class Gem::Commands::QueryCommand < Gem::Command
|
|||
version
|
||||
end.reverse
|
||||
|
||||
platforms = Hash.new { |h,version| h[version] = [] }
|
||||
|
||||
matching_tuples.map do |(name, version, platform,_),_|
|
||||
platforms[version] << platform if platform
|
||||
end
|
||||
|
||||
seen = {}
|
||||
|
||||
matching_tuples.delete_if do |(name, version,_),_|
|
||||
|
@ -174,6 +197,28 @@ class Gem::Commands::QueryCommand < Gem::Command
|
|||
end
|
||||
|
||||
entry << "\n"
|
||||
|
||||
non_ruby = platforms.any? do |_, pls|
|
||||
pls.any? { |pl| pl != Gem::Platform::RUBY }
|
||||
end
|
||||
|
||||
if non_ruby then
|
||||
if platforms.length == 1 then
|
||||
title = platforms.values.length == 1 ? 'Platform' : 'Platforms'
|
||||
entry << " #{title}: #{platforms.values.sort.join ', '}\n"
|
||||
else
|
||||
entry << " Platforms:\n"
|
||||
platforms.sort_by do |version,|
|
||||
version
|
||||
end.each do |version, pls|
|
||||
label = " #{version}: "
|
||||
data = format_text pls.sort.join(', '), 68, label.length
|
||||
data[0, label.length] = label
|
||||
entry << data << "\n"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
authors = "Author#{spec.authors.length > 1 ? 's' : ''}: "
|
||||
authors << spec.authors.join(', ')
|
||||
entry << format_text(authors, 68, 4)
|
||||
|
@ -187,6 +232,12 @@ class Gem::Commands::QueryCommand < Gem::Command
|
|||
entry << "\n" << format_text("Homepage: #{spec.homepage}", 68, 4)
|
||||
end
|
||||
|
||||
if spec.license and not spec.license.empty? then
|
||||
licenses = "License#{spec.licenses.length > 1 ? 's' : ''}: "
|
||||
licenses << spec.licenses.join(', ')
|
||||
entry << "\n" << format_text(licenses, 68, 4)
|
||||
end
|
||||
|
||||
if spec.loaded_from then
|
||||
if matching_tuples.length == 1 then
|
||||
loaded_from = File.dirname File.dirname(spec.loaded_from)
|
||||
|
@ -209,25 +260,5 @@ class Gem::Commands::QueryCommand < Gem::Command
|
|||
say output.join(options[:details] ? "\n\n" : "\n")
|
||||
end
|
||||
|
||||
##
|
||||
# Used for wrapping and indenting text
|
||||
|
||||
def format_text(text, wrap, indent=0)
|
||||
result = []
|
||||
work = text.dup
|
||||
|
||||
while work.length > wrap
|
||||
if work =~ /^(.{0,#{wrap}})[ \n]/o then
|
||||
result << $1
|
||||
work.slice!(0, $&.length)
|
||||
else
|
||||
result << work.slice!(0, wrap)
|
||||
end
|
||||
end
|
||||
|
||||
result << work if work.length.nonzero?
|
||||
result.join("\n").gsub(/^/, " " * indent)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -2,34 +2,30 @@ require 'rubygems/command'
|
|||
require 'rubygems/version_option'
|
||||
require 'rubygems/doc_manager'
|
||||
|
||||
module Gem
|
||||
module Commands
|
||||
class RdocCommand < Command
|
||||
include VersionOption
|
||||
class Gem::Commands::RdocCommand < Gem::Command
|
||||
include Gem::VersionOption
|
||||
|
||||
def initialize
|
||||
super('rdoc',
|
||||
'Generates RDoc for pre-installed gems',
|
||||
{
|
||||
super 'rdoc', 'Generates RDoc for pre-installed gems',
|
||||
:version => Gem::Requirement.default,
|
||||
:include_rdoc => true,
|
||||
:include_ri => true,
|
||||
})
|
||||
:include_rdoc => true, :include_ri => true
|
||||
|
||||
add_option('--all',
|
||||
'Generate RDoc/RI documentation for all',
|
||||
'installed gems') do |value, options|
|
||||
options[:all] = value
|
||||
end
|
||||
|
||||
add_option('--[no-]rdoc',
|
||||
'Include RDoc generated documents') do
|
||||
|value, options|
|
||||
'Include RDoc generated documents') do |value, options|
|
||||
options[:include_rdoc] = value
|
||||
end
|
||||
|
||||
add_option('--[no-]ri',
|
||||
'Include RI generated documents'
|
||||
) do |value, options|
|
||||
'Include RI generated documents') do |value, options|
|
||||
options[:include_ri] = value
|
||||
end
|
||||
|
||||
add_version_option
|
||||
end
|
||||
|
||||
|
@ -46,14 +42,14 @@ module Gem
|
|||
end
|
||||
|
||||
def execute
|
||||
if options[:all]
|
||||
if options[:all] then
|
||||
specs = Gem::SourceIndex.from_installed_gems.collect { |name, spec|
|
||||
spec
|
||||
}
|
||||
else
|
||||
gem_name = get_one_gem_name
|
||||
specs = Gem::SourceIndex.from_installed_gems.search(
|
||||
gem_name, options[:version])
|
||||
dep = Gem::Dependency.new gem_name, options[:version]
|
||||
specs = Gem::SourceIndex.from_installed_gems.search dep
|
||||
end
|
||||
|
||||
if specs.empty?
|
||||
|
@ -78,5 +74,3 @@ module Gem
|
|||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,17 +1,12 @@
|
|||
require 'rubygems/command'
|
||||
require 'rubygems/commands/query_command'
|
||||
|
||||
module Gem
|
||||
module Commands
|
||||
|
||||
class SearchCommand < QueryCommand
|
||||
class Gem::Commands::SearchCommand < Gem::Commands::QueryCommand
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'search',
|
||||
'Display all gems whose name contains STRING'
|
||||
)
|
||||
remove_option('--name-matches')
|
||||
super 'search', 'Display all gems whose name contains STRING'
|
||||
|
||||
remove_option '--name-matches'
|
||||
end
|
||||
|
||||
def arguments # :nodoc:
|
||||
|
@ -31,7 +26,6 @@ module Gem
|
|||
options[:name] = /#{string}/i
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -7,7 +7,23 @@ class Gem::Commands::ServerCommand < Gem::Command
|
|||
super 'server', 'Documentation and gem repository HTTP server',
|
||||
:port => 8808, :gemdir => Gem.dir, :daemon => false
|
||||
|
||||
add_option '-p', '--port=PORT', Integer,
|
||||
OptionParser.accept :Port do |port|
|
||||
if port =~ /\A\d+\z/ then
|
||||
port = Integer port
|
||||
raise OptionParser::InvalidArgument, "#{port}: not a port number" if
|
||||
port > 65535
|
||||
|
||||
port
|
||||
else
|
||||
begin
|
||||
Socket.getservbyname port
|
||||
rescue SocketError => e
|
||||
raise OptionParser::InvalidArgument, "#{port}: no such named service"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
add_option '-p', '--port=PORT', :Port,
|
||||
'port to listen on' do |port, options|
|
||||
options[:port] = port
|
||||
end
|
||||
|
@ -37,6 +53,12 @@ for gem installation.
|
|||
|
||||
To install gems from a running server, use `gem install GEMNAME --source
|
||||
http://gem_server_host:8808`
|
||||
|
||||
You can set up a shortcut to gem server documentation using the URL:
|
||||
|
||||
http://localhost:8808/rdoc?q=%s - Firefox
|
||||
http://localhost:8808/rdoc?q=* - LaunchBar
|
||||
|
||||
EOF
|
||||
end
|
||||
|
||||
|
|
353
lib/rubygems/commands/setup_command.rb
Normal file
353
lib/rubygems/commands/setup_command.rb
Normal file
|
@ -0,0 +1,353 @@
|
|||
require 'rubygems/command'
|
||||
require 'fileutils'
|
||||
require 'rbconfig'
|
||||
require 'tmpdir'
|
||||
require 'pathname'
|
||||
|
||||
##
|
||||
# Installs RubyGems itself. This command is ordinarily only available from a
|
||||
# RubyGems checkout or tarball.
|
||||
|
||||
class Gem::Commands::SetupCommand < Gem::Command
|
||||
|
||||
def initialize
|
||||
super 'setup', 'Install RubyGems',
|
||||
:format_executable => true, :rdoc => true, :ri => true,
|
||||
:site_or_vendor => :sitelibdir,
|
||||
:destdir => '', :prefix => ''
|
||||
|
||||
add_option '--prefix=PREFIX',
|
||||
'Prefix path for installing RubyGems',
|
||||
'Will not affect gem repository location' do |prefix, options|
|
||||
options[:prefix] = File.expand_path prefix
|
||||
end
|
||||
|
||||
add_option '--destdir=DESTDIR',
|
||||
'Root directory to install RubyGems into',
|
||||
'Mainly used for packaging RubyGems' do |destdir, options|
|
||||
options[:destdir] = File.expand_path destdir
|
||||
end
|
||||
|
||||
add_option '--[no-]vendor',
|
||||
'Install into vendorlibdir not sitelibdir',
|
||||
'(Requires Ruby 1.8.7)' do |vendor, options|
|
||||
if vendor and Gem.ruby_version < Gem::Version.new('1.8.7') then
|
||||
raise OptionParser::InvalidOption,
|
||||
"requires ruby 1.8.7+ (you have #{Gem.ruby_version})"
|
||||
end
|
||||
|
||||
options[:site_or_vendor] = vendor ? :vendorlibdir : :sitelibdir
|
||||
end
|
||||
|
||||
add_option '--[no-]format-executable',
|
||||
'Makes `gem` match ruby',
|
||||
'If ruby is ruby18, gem will be gem18' do |value, options|
|
||||
options[:format_executable] = value
|
||||
end
|
||||
|
||||
add_option '--[no-]rdoc',
|
||||
'Generate RDoc documentation for RubyGems' do |value, options|
|
||||
options[:rdoc] = value
|
||||
end
|
||||
|
||||
add_option '--[no-]ri',
|
||||
'Generate RI documentation for RubyGems' do |value, options|
|
||||
options[:ri] = value
|
||||
end
|
||||
end
|
||||
|
||||
def check_ruby_version
|
||||
required_version = Gem::Requirement.new '>= 1.8.6'
|
||||
|
||||
unless required_version.satisfied_by? Gem.ruby_version then
|
||||
alert_error "Expected Ruby version #{required_version}, is #{Gem.ruby_version}"
|
||||
terminate_interaction 1
|
||||
end
|
||||
end
|
||||
|
||||
def defaults_str # :nodoc:
|
||||
"--format-executable --rdoc --ri"
|
||||
end
|
||||
|
||||
def description # :nodoc:
|
||||
<<-EOF
|
||||
Installs RubyGems itself.
|
||||
|
||||
RubyGems installs RDoc for itself in GEM_HOME. By default this is:
|
||||
#{Gem.dir}
|
||||
|
||||
If you prefer a different directory, set the GEM_HOME environment variable.
|
||||
|
||||
RubyGems will install the gem command with a name matching ruby's
|
||||
prefix and suffix. If ruby was installed as `ruby18`, gem will be
|
||||
installed as `gem18`.
|
||||
|
||||
By default, this RubyGems will install gem as:
|
||||
#{Gem.default_exec_format % 'gem'}
|
||||
EOF
|
||||
end
|
||||
|
||||
def execute
|
||||
install_destdir = options[:destdir]
|
||||
|
||||
unless install_destdir.empty? then
|
||||
ENV['GEM_HOME'] ||= File.join(install_destdir,
|
||||
Gem.default_dir.gsub(/^[a-zA-Z]:/, ''))
|
||||
end
|
||||
|
||||
check_ruby_version
|
||||
|
||||
if Gem.configuration.really_verbose then
|
||||
extend FileUtils::Verbose
|
||||
else
|
||||
extend FileUtils
|
||||
end
|
||||
|
||||
lib_dir, bin_dir = make_destination_dirs install_destdir
|
||||
|
||||
install_lib lib_dir
|
||||
|
||||
install_executables bin_dir
|
||||
|
||||
remove_old_bin_files bin_dir
|
||||
|
||||
remove_source_caches install_destdir
|
||||
|
||||
install_rdoc
|
||||
|
||||
say
|
||||
say "-" * 78
|
||||
say
|
||||
|
||||
release_notes = File.join Dir.pwd, 'doc', 'release_notes',
|
||||
"rel_#{Gem::RubyGemsVersion.gsub '.', '_'}.rdoc"
|
||||
|
||||
if File.exist? release_notes then
|
||||
say File.read(release_notes)
|
||||
else
|
||||
say "Oh-no! Unable to find release notes!"
|
||||
say "Looked in: #{release_notes}" if Gem.configuration.really_verbose
|
||||
end
|
||||
|
||||
say
|
||||
say "-" * 78
|
||||
say
|
||||
|
||||
say "RubyGems installed the following executables:"
|
||||
say @bin_file_names.map { |name| "\t#{name}\n" }
|
||||
say
|
||||
|
||||
unless @bin_file_names.grep(/#{File::SEPARATOR}gem$/) then
|
||||
say "If `gem` was installed by a previous RubyGems installation, you may need"
|
||||
say "to remove it by hand."
|
||||
say
|
||||
end
|
||||
end
|
||||
|
||||
def install_executables(bin_dir)
|
||||
say "Installing gem executable"
|
||||
|
||||
@bin_file_names = []
|
||||
|
||||
Dir.chdir 'bin' do
|
||||
bin_files = Dir['*']
|
||||
|
||||
bin_files.delete 'update_rubygems'
|
||||
|
||||
bin_files.each do |bin_file|
|
||||
bin_file_formatted = if options[:format_executable] then
|
||||
Gem.default_exec_format % bin_file
|
||||
else
|
||||
bin_file
|
||||
end
|
||||
|
||||
dest_file = File.join bin_dir, bin_file_formatted
|
||||
bin_tmp_file = File.join Dir.tmpdir, bin_file
|
||||
|
||||
begin
|
||||
bin = File.readlines bin_file
|
||||
bin[0] = "#!#{Gem.ruby}\n"
|
||||
|
||||
File.open bin_tmp_file, 'w' do |fp|
|
||||
fp.puts bin.join
|
||||
end
|
||||
|
||||
install bin_tmp_file, dest_file, :mode => 0755
|
||||
@bin_file_names << dest_file
|
||||
ensure
|
||||
rm bin_tmp_file
|
||||
end
|
||||
|
||||
next unless Gem.win_platform?
|
||||
|
||||
begin
|
||||
bin_cmd_file = File.join Dir.tmpdir, "#{bin_file}.bat"
|
||||
|
||||
File.open bin_cmd_file, 'w' do |file|
|
||||
file.puts <<-TEXT
|
||||
@ECHO OFF
|
||||
IF NOT "%~f0" == "~f0" GOTO :WinNT
|
||||
@"#{File.basename(Gem.ruby).chomp('"')}" "#{dest_file}" %1 %2 %3 %4 %5 %6 %7 %8 %9
|
||||
GOTO :EOF
|
||||
:WinNT
|
||||
@"#{File.basename(Gem.ruby).chomp('"')}" "%~dpn0" %*
|
||||
TEXT
|
||||
end
|
||||
|
||||
install bin_cmd_file, "#{dest_file}.bat", :mode => 0755
|
||||
ensure
|
||||
rm bin_cmd_file
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def install_lib(lib_dir)
|
||||
say "Installing RubyGems"
|
||||
|
||||
Dir.chdir 'lib' do
|
||||
lib_files = Dir[File.join('**', '*rb')]
|
||||
|
||||
lib_files.each do |lib_file|
|
||||
dest_file = File.join lib_dir, lib_file
|
||||
dest_dir = File.dirname dest_file
|
||||
mkdir_p dest_dir unless File.directory? dest_dir
|
||||
|
||||
install lib_file, dest_file, :mode => 0644
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def install_rdoc
|
||||
gem_doc_dir = File.join Gem.dir, 'doc'
|
||||
rubygems_name = "rubygems-#{Gem::RubyGemsVersion}"
|
||||
rubygems_doc_dir = File.join gem_doc_dir, rubygems_name
|
||||
|
||||
if File.writable? gem_doc_dir and
|
||||
(not File.exist? rubygems_doc_dir or
|
||||
File.writable? rubygems_doc_dir) then
|
||||
say "Removing old RubyGems RDoc and ri"
|
||||
Dir[File.join(Gem.dir, 'doc', 'rubygems-[0-9]*')].each do |dir|
|
||||
rm_rf dir
|
||||
end
|
||||
|
||||
if options[:ri] then
|
||||
ri_dir = File.join rubygems_doc_dir, 'ri'
|
||||
say "Installing #{rubygems_name} ri into #{ri_dir}"
|
||||
run_rdoc '--ri', '--op', ri_dir
|
||||
end
|
||||
|
||||
if options[:rdoc] then
|
||||
rdoc_dir = File.join rubygems_doc_dir, 'rdoc'
|
||||
say "Installing #{rubygems_name} rdoc into #{rdoc_dir}"
|
||||
run_rdoc '--op', rdoc_dir
|
||||
end
|
||||
else
|
||||
say "Skipping RDoc generation, #{gem_doc_dir} not writable"
|
||||
say "Set the GEM_HOME environment variable if you want RDoc generated"
|
||||
end
|
||||
end
|
||||
|
||||
def make_destination_dirs(install_destdir)
|
||||
lib_dir = nil
|
||||
bin_dir = nil
|
||||
|
||||
prefix = options[:prefix]
|
||||
site_or_vendor = options[:site_or_vendor]
|
||||
|
||||
if prefix.empty? then
|
||||
lib_dir = Gem::ConfigMap[site_or_vendor]
|
||||
bin_dir = Gem::ConfigMap[:bindir]
|
||||
else
|
||||
# Apple installed RubyGems into libdir, and RubyGems <= 1.1.0 gets
|
||||
# confused about installation location, so switch back to
|
||||
# sitelibdir/vendorlibdir.
|
||||
if defined?(APPLE_GEM_HOME) and
|
||||
# just in case Apple and RubyGems don't get this patched up proper.
|
||||
(prefix == Gem::ConfigMap[:libdir] or
|
||||
# this one is important
|
||||
prefix == File.join(Gem::ConfigMap[:libdir], 'ruby')) then
|
||||
lib_dir = Gem::ConfigMap[site_or_vendor]
|
||||
bin_dir = Gem::ConfigMap[:bindir]
|
||||
else
|
||||
lib_dir = File.join prefix, 'lib'
|
||||
bin_dir = File.join prefix, 'bin'
|
||||
end
|
||||
end
|
||||
|
||||
unless install_destdir.empty? then
|
||||
lib_dir = File.join install_destdir, lib_dir.gsub(/^[a-zA-Z]:/, '')
|
||||
bin_dir = File.join install_destdir, bin_dir.gsub(/^[a-zA-Z]:/, '')
|
||||
end
|
||||
|
||||
mkdir_p lib_dir
|
||||
mkdir_p bin_dir
|
||||
|
||||
return lib_dir, bin_dir
|
||||
end
|
||||
|
||||
def remove_old_bin_files(bin_dir)
|
||||
old_bin_files = {
|
||||
'gem_mirror' => 'gem mirror',
|
||||
'gem_server' => 'gem server',
|
||||
'gemlock' => 'gem lock',
|
||||
'gemri' => 'ri',
|
||||
'gemwhich' => 'gem which',
|
||||
'index_gem_repository.rb' => 'gem generate_index',
|
||||
}
|
||||
|
||||
old_bin_files.each do |old_bin_file, new_name|
|
||||
old_bin_path = File.join bin_dir, old_bin_file
|
||||
next unless File.exist? old_bin_path
|
||||
|
||||
deprecation_message = "`#{old_bin_file}` has been deprecated. Use `#{new_name}` instead."
|
||||
|
||||
File.open old_bin_path, 'w' do |fp|
|
||||
fp.write <<-EOF
|
||||
#!#{Gem.ruby}
|
||||
|
||||
abort "#{deprecation_message}"
|
||||
EOF
|
||||
end
|
||||
|
||||
next unless Gem.win_platform?
|
||||
|
||||
File.open "#{old_bin_path}.bat", 'w' do |fp|
|
||||
fp.puts %{@ECHO.#{deprecation_message}}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def remove_source_caches(install_destdir)
|
||||
if install_destdir.empty?
|
||||
require 'rubygems/source_info_cache'
|
||||
|
||||
user_cache_file = File.join(install_destdir,
|
||||
Gem::SourceInfoCache.user_cache_file)
|
||||
system_cache_file = File.join(install_destdir,
|
||||
Gem::SourceInfoCache.system_cache_file)
|
||||
|
||||
say "Removing old source_cache files"
|
||||
rm_f user_cache_file if File.writable? File.dirname(user_cache_file)
|
||||
rm_f system_cache_file if File.writable? File.dirname(system_cache_file)
|
||||
end
|
||||
end
|
||||
|
||||
def run_rdoc(*args)
|
||||
begin
|
||||
gem 'rdoc'
|
||||
rescue Gem::LoadError
|
||||
end
|
||||
|
||||
require 'rdoc/rdoc'
|
||||
|
||||
args << '--quiet'
|
||||
args << '--main' << 'README'
|
||||
args << '.' << 'README' << 'LICENSE.txt' << 'GPL.txt'
|
||||
|
||||
r = RDoc::RDoc.new
|
||||
r.document args
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -3,9 +3,12 @@ require 'rubygems/command'
|
|||
require 'rubygems/remote_fetcher'
|
||||
require 'rubygems/source_info_cache'
|
||||
require 'rubygems/spec_fetcher'
|
||||
require 'rubygems/local_remote_options'
|
||||
|
||||
class Gem::Commands::SourcesCommand < Gem::Command
|
||||
|
||||
include Gem::LocalRemoteOptions
|
||||
|
||||
def initialize
|
||||
super 'sources',
|
||||
'Manage the sources and cache file RubyGems uses to search for gems'
|
||||
|
@ -30,6 +33,8 @@ class Gem::Commands::SourcesCommand < Gem::Command
|
|||
add_option '-u', '--update', 'Update source cache' do |value, options|
|
||||
options[:update] = value
|
||||
end
|
||||
|
||||
add_proxy_option
|
||||
end
|
||||
|
||||
def defaults_str
|
||||
|
|
|
@ -12,7 +12,8 @@ class Gem::Commands::SpecificationCommand < Gem::Command
|
|||
|
||||
def initialize
|
||||
super 'specification', 'Display gem specification (in yaml)',
|
||||
:domain => :local, :version => Gem::Requirement.default
|
||||
:domain => :local, :version => Gem::Requirement.default,
|
||||
:format => :yaml
|
||||
|
||||
add_version_option('examine')
|
||||
add_platform_option
|
||||
|
@ -22,26 +23,62 @@ class Gem::Commands::SpecificationCommand < Gem::Command
|
|||
options[:all] = true
|
||||
end
|
||||
|
||||
add_option('--ruby', 'Output ruby format') do |value, options|
|
||||
options[:format] = :ruby
|
||||
end
|
||||
|
||||
add_option('--yaml', 'Output RUBY format') do |value, options|
|
||||
options[:format] = :yaml
|
||||
end
|
||||
|
||||
add_option('--marshal', 'Output Marshal format') do |value, options|
|
||||
options[:format] = :marshal
|
||||
end
|
||||
|
||||
add_local_remote_options
|
||||
end
|
||||
|
||||
def arguments # :nodoc:
|
||||
"GEMFILE name of gem to show the gemspec for"
|
||||
<<-ARGS
|
||||
GEMFILE name of gem to show the gemspec for
|
||||
FIELD name of gemspec field to show
|
||||
ARGS
|
||||
end
|
||||
|
||||
def defaults_str # :nodoc:
|
||||
"--local --version '#{Gem::Requirement.default}'"
|
||||
"--local --version '#{Gem::Requirement.default}' --yaml"
|
||||
end
|
||||
|
||||
def usage # :nodoc:
|
||||
"#{program_name} [GEMFILE]"
|
||||
"#{program_name} [GEMFILE] [FIELD]"
|
||||
end
|
||||
|
||||
def execute
|
||||
specs = []
|
||||
gem = get_one_gem_name
|
||||
gem = options[:args].shift
|
||||
|
||||
unless gem then
|
||||
raise Gem::CommandLineError,
|
||||
"Please specify a gem name or file on the command line"
|
||||
end
|
||||
|
||||
dep = Gem::Dependency.new gem, options[:version]
|
||||
|
||||
field = get_one_optional_argument
|
||||
|
||||
if field then
|
||||
field = field.intern
|
||||
|
||||
if options[:format] == :ruby then
|
||||
raise Gem::CommandLineError, "--ruby and FIELD are mutually exclusive"
|
||||
end
|
||||
|
||||
unless Gem::Specification.attribute_names.include? field then
|
||||
raise Gem::CommandLineError,
|
||||
"no field %p on Gem::Specification" % field.to_s
|
||||
end
|
||||
end
|
||||
|
||||
if local? then
|
||||
if File.exist? gem then
|
||||
specs << Gem::Format.from_file_by_path(gem).spec rescue nil
|
||||
|
@ -63,7 +100,17 @@ class Gem::Commands::SpecificationCommand < Gem::Command
|
|||
terminate_interaction 1
|
||||
end
|
||||
|
||||
output = lambda { |s| say s.to_yaml; say "\n" }
|
||||
output = lambda do |s|
|
||||
s = s.send field if field
|
||||
|
||||
say case options[:format]
|
||||
when :ruby then s.to_ruby
|
||||
when :marshal then Marshal.dump s
|
||||
else s.to_yaml
|
||||
end
|
||||
|
||||
say "\n"
|
||||
end
|
||||
|
||||
if options[:all] then
|
||||
specs.each(&output)
|
||||
|
|
|
@ -2,15 +2,18 @@ require 'rubygems/command'
|
|||
require 'rubygems/version_option'
|
||||
require 'rubygems/uninstaller'
|
||||
|
||||
module Gem
|
||||
module Commands
|
||||
class UninstallCommand < Command
|
||||
##
|
||||
# Gem uninstaller command line tool
|
||||
#
|
||||
# See `gem help uninstall`
|
||||
|
||||
include VersionOption
|
||||
class Gem::Commands::UninstallCommand < Gem::Command
|
||||
|
||||
include Gem::VersionOption
|
||||
|
||||
def initialize
|
||||
super 'uninstall', 'Uninstall gems from the local repository',
|
||||
:version => Gem::Requirement.default
|
||||
:version => Gem::Requirement.default, :user_install => true
|
||||
|
||||
add_option('-a', '--[no-]all',
|
||||
'Uninstall all matching versions'
|
||||
|
@ -40,6 +43,12 @@ module Gem
|
|||
options[:bin_dir] = File.expand_path(value)
|
||||
end
|
||||
|
||||
add_option('--[no-]user-install',
|
||||
'Uninstall from user\'s home directory',
|
||||
'in addition to GEM_HOME.') do |value, options|
|
||||
options[:user_install] = value
|
||||
end
|
||||
|
||||
add_version_option
|
||||
add_platform_option
|
||||
end
|
||||
|
@ -50,7 +59,8 @@ module Gem
|
|||
|
||||
def defaults_str # :nodoc:
|
||||
"--version '#{Gem::Requirement.default}' --no-force " \
|
||||
"--install-dir #{Gem.dir}"
|
||||
"--install-dir #{Gem.dir}\n" \
|
||||
"--user-install"
|
||||
end
|
||||
|
||||
def usage # :nodoc:
|
||||
|
@ -68,6 +78,6 @@ module Gem
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ class Gem::Commands::UnpackCommand < Gem::Command
|
|||
:version => Gem::Requirement.default,
|
||||
:target => Dir.pwd
|
||||
|
||||
add_option('--target', 'target directory for unpacking') do |value, options|
|
||||
add_option('--target=DIR', 'target directory for unpacking') do |value, options|
|
||||
options[:target] = value
|
||||
end
|
||||
|
||||
|
@ -35,9 +35,10 @@ class Gem::Commands::UnpackCommand < Gem::Command
|
|||
# TODO: allow, e.g., 'gem unpack rake-0.3.1'. Find a general solution for
|
||||
# this, so that it works for uninstall as well. (And check other commands
|
||||
# at the same time.)
|
||||
|
||||
def execute
|
||||
gemname = get_one_gem_name
|
||||
path = get_path(gemname, options[:version])
|
||||
get_all_gem_names.each do |name|
|
||||
path = get_path name, options[:version]
|
||||
|
||||
if path then
|
||||
basename = File.basename(path).sub(/\.gem$/, '')
|
||||
|
@ -46,7 +47,8 @@ class Gem::Commands::UnpackCommand < Gem::Command
|
|||
Gem::Installer.new(path, :unpack => true).unpack target_dir
|
||||
say "Unpacked gem: '#{target_dir}'"
|
||||
else
|
||||
alert_error "Gem '#{gemname}' not installed."
|
||||
alert_error "Gem '#{name}' not installed."
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -80,20 +80,27 @@ class Gem::Commands::UpdateCommand < Gem::Command
|
|||
|
||||
gems_to_update.uniq.sort.each do |name|
|
||||
next if updated.any? { |spec| spec.name == name }
|
||||
success = false
|
||||
|
||||
say "Updating #{name}"
|
||||
begin
|
||||
installer.install name
|
||||
success = true
|
||||
rescue Gem::InstallError => e
|
||||
alert_error "Error installing #{name}:\n\t#{e.message}"
|
||||
success = false
|
||||
end
|
||||
|
||||
installer.installed_gems.each do |spec|
|
||||
updated << spec
|
||||
say "Successfully installed #{spec.full_name}"
|
||||
say "Successfully installed #{spec.full_name}" if success
|
||||
end
|
||||
end
|
||||
|
||||
if gems_to_update.include? "rubygems-update" then
|
||||
Gem.source_index.refresh!
|
||||
|
||||
update_gems = Gem.source_index.search 'rubygems-update'
|
||||
update_gems = Gem.source_index.find_name 'rubygems-update'
|
||||
|
||||
latest_update_gem = update_gems.sort_by { |s| s.version }.last
|
||||
|
||||
|
@ -106,6 +113,20 @@ class Gem::Commands::UpdateCommand < Gem::Command
|
|||
say "Nothing to update"
|
||||
else
|
||||
say "Gems updated: #{updated.map { |spec| spec.name }.join ', '}"
|
||||
|
||||
if options[:generate_ri] then
|
||||
updated.each do |gem|
|
||||
Gem::DocManager.new(gem, options[:rdoc_args]).generate_ri
|
||||
end
|
||||
|
||||
Gem::DocManager.update_ri_cache
|
||||
end
|
||||
|
||||
if options[:generate_rdoc] then
|
||||
updated.each do |gem|
|
||||
Gem::DocManager.new(gem, options[:rdoc_args]).generate_rdoc
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -46,7 +46,7 @@ class Gem::Commands::WhichCommand < Gem::Command
|
|||
end
|
||||
|
||||
say "(checking gem #{spec.full_name} for #{arg})" if
|
||||
Gem.configuration.verbose
|
||||
Gem.configuration.verbose and $stdout.tty?
|
||||
end
|
||||
|
||||
paths = find_paths arg, dirs
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#++
|
||||
|
||||
require 'yaml'
|
||||
require 'rubygems'
|
||||
|
||||
# Store the gem command options specified in the configuration file. The
|
||||
# config file object acts much like a hash.
|
||||
|
@ -36,7 +35,8 @@ class Gem::ConfigFile
|
|||
|
||||
CSIDL_COMMON_APPDATA = 0x0023
|
||||
path = 0.chr * 260
|
||||
SHGetFolderPath = Win32API.new 'shell32', 'SHGetFolderPath', 'PLPLP', 'L', :stdcall
|
||||
SHGetFolderPath = Win32API.new 'shell32', 'SHGetFolderPath', 'PLPLP', 'L',
|
||||
:stdcall
|
||||
SHGetFolderPath.call nil, CSIDL_COMMON_APPDATA, nil, 1, path
|
||||
|
||||
path.strip
|
||||
|
|
|
@ -20,8 +20,13 @@ module Gem
|
|||
if defined? RUBY_FRAMEWORK_VERSION then
|
||||
File.join File.dirname(ConfigMap[:sitedir]), 'Gems',
|
||||
ConfigMap[:ruby_version]
|
||||
# 1.9.2dev reverted to 1.8 style path
|
||||
elsif RUBY_VERSION > '1.9' and RUBY_VERSION < '1.9.2' then
|
||||
File.join(ConfigMap[:libdir], ConfigMap[:ruby_install_name], 'gems',
|
||||
ConfigMap[:ruby_version])
|
||||
else
|
||||
ConfigMap[:sitelibdir].sub(%r'/site_ruby/(?=[^/]+)', '/gems/')
|
||||
File.join(ConfigMap[:libdir], ruby_engine, 'gems',
|
||||
ConfigMap[:ruby_version])
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -37,15 +42,25 @@ module Gem
|
|||
# Default gem load path
|
||||
|
||||
def self.default_path
|
||||
if File.exist?(Gem.user_home)
|
||||
[user_dir, default_dir]
|
||||
else
|
||||
[default_dir]
|
||||
end
|
||||
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'
|
||||
exec_format = ConfigMap[:ruby_install_name].sub('ruby', '%s') rescue '%s'
|
||||
|
||||
unless exec_format =~ /%s/ then
|
||||
raise Gem::Exception,
|
||||
"[BUG] invalid exec_format #{exec_format.inspect}, no %s"
|
||||
end
|
||||
|
||||
exec_format
|
||||
end
|
||||
|
||||
##
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
# See LICENSE.txt for permissions.
|
||||
#++
|
||||
|
||||
require 'rubygems'
|
||||
|
||||
##
|
||||
# The Dependency class holds a Gem name and a Gem::Requirement
|
||||
|
||||
|
@ -72,7 +70,7 @@ class Gem::Dependency
|
|||
alias requirements_list requirement_list
|
||||
|
||||
def normalize
|
||||
ver = @version_requirement.instance_eval { @version }
|
||||
ver = @version_requirement.instance_variable_get :@version
|
||||
@version_requirements = Gem::Requirement.new([ver])
|
||||
@version_requirement = nil
|
||||
end
|
||||
|
@ -81,6 +79,21 @@ class Gem::Dependency
|
|||
"#{name} (#{version_requirements}, #{@type || :runtime})"
|
||||
end
|
||||
|
||||
def pretty_print(q) # :nodoc:
|
||||
q.group 1, 'Gem::Dependency.new(', ')' do
|
||||
q.pp @name
|
||||
q.text ','
|
||||
q.breakable
|
||||
|
||||
q.pp @version_requirements
|
||||
|
||||
q.text ','
|
||||
q.breakable
|
||||
|
||||
q.pp @type
|
||||
end
|
||||
end
|
||||
|
||||
def ==(other) # :nodoc:
|
||||
self.class === other &&
|
||||
self.name == other.name &&
|
||||
|
@ -89,15 +102,22 @@ class Gem::Dependency
|
|||
end
|
||||
|
||||
##
|
||||
# Uses this dependency as a pattern to compare to the dependency +other+.
|
||||
# This dependency will match if the name matches the other's name, and other
|
||||
# has only an equal version requirement that satisfies this dependency.
|
||||
# Uses this dependency as a pattern to compare to +other+. This dependency
|
||||
# will match if the name matches the other's name, and other has only an
|
||||
# equal version requirement that satisfies this dependency.
|
||||
|
||||
def =~(other)
|
||||
return false unless self.class === other
|
||||
other = if self.class === other then
|
||||
other
|
||||
else
|
||||
return false unless other.respond_to? :name and
|
||||
other.respond_to? :version
|
||||
|
||||
Gem::Dependency.new other.name, other.version
|
||||
end
|
||||
|
||||
pattern = @name
|
||||
pattern = /\A#{@name}\Z/ unless Regexp === pattern
|
||||
pattern = /\A#{Regexp.escape @name}\Z/ unless Regexp === pattern
|
||||
|
||||
return false unless pattern =~ other.name
|
||||
|
||||
|
@ -111,9 +131,18 @@ class Gem::Dependency
|
|||
version_requirements.satisfied_by? version
|
||||
end
|
||||
|
||||
def hash # :nodoc:
|
||||
##
|
||||
# A dependency's hash is the sum of the hash of the #name, #type and
|
||||
# #version_requirements
|
||||
|
||||
def hash
|
||||
name.hash + type.hash + version_requirements.hash
|
||||
end
|
||||
|
||||
def inspect # :nodoc:
|
||||
"<%s type=%p name=%p requirements=%p>" % [self.class, @type, @name,
|
||||
version_requirements.to_s]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -20,8 +20,9 @@ class Gem::DependencyInstaller
|
|||
:force => false,
|
||||
:format_executable => false, # HACK dup
|
||||
:ignore_dependencies => false,
|
||||
:prerelease => false,
|
||||
:security_policy => nil, # HACK NoSecurity requires OpenSSL. AlmostNo? Low?
|
||||
:wrappers => true
|
||||
:wrappers => true,
|
||||
}
|
||||
|
||||
##
|
||||
|
@ -37,6 +38,7 @@ class Gem::DependencyInstaller
|
|||
# :format_executable:: See Gem::Installer#initialize.
|
||||
# :ignore_dependencies:: Don't install any dependencies.
|
||||
# :install_dir:: See Gem::Installer#install.
|
||||
# :prerelease:: Allow prerelease versions
|
||||
# :security_policy:: See Gem::Installer::new and Gem::Security.
|
||||
# :user_install:: See Gem::Installer.new
|
||||
# :wrappers:: See Gem::Installer::new
|
||||
|
@ -58,6 +60,7 @@ class Gem::DependencyInstaller
|
|||
@force = options[:force]
|
||||
@format_executable = options[:format_executable]
|
||||
@ignore_dependencies = options[:ignore_dependencies]
|
||||
@prerelease = options[:prerelease]
|
||||
@security_policy = options[:security_policy]
|
||||
@user_install = options[:user_install]
|
||||
@wrappers = options[:wrappers]
|
||||
|
@ -90,10 +93,10 @@ class Gem::DependencyInstaller
|
|||
req
|
||||
end
|
||||
|
||||
all = requirements.length > 1 ||
|
||||
(requirements.first != ">=" and requirements.first != ">")
|
||||
all = !@prerelease && (requirements.length > 1 ||
|
||||
(requirements.first != ">=" and requirements.first != ">"))
|
||||
|
||||
found = Gem::SpecFetcher.fetcher.fetch dep, all
|
||||
found = Gem::SpecFetcher.fetcher.fetch dep, all, true, @prerelease
|
||||
gems_and_sources.push(*found)
|
||||
|
||||
rescue Gem::RemoteFetcher::FetchError => e
|
||||
|
|
|
@ -8,6 +8,7 @@ require 'tsort'
|
|||
|
||||
class Gem::DependencyList
|
||||
|
||||
include Enumerable
|
||||
include TSort
|
||||
|
||||
def self.from_source_index(src_index)
|
||||
|
@ -24,24 +25,27 @@ class Gem::DependencyList
|
|||
@specs = []
|
||||
end
|
||||
|
||||
##
|
||||
# Adds +gemspecs+ to the dependency list.
|
||||
|
||||
def add(*gemspecs)
|
||||
@specs.push(*gemspecs)
|
||||
end
|
||||
|
||||
# Return a list of the specifications in the dependency list,
|
||||
# sorted in order so that no spec in the list depends on a gem
|
||||
# earlier in the list.
|
||||
##
|
||||
# Return a list of the specifications in the dependency list, sorted in
|
||||
# order so that no spec in the list depends on a gem earlier in the list.
|
||||
#
|
||||
# This is useful when removing gems from a set of installed gems.
|
||||
# By removing them in the returned order, you don't get into as
|
||||
# many dependency issues.
|
||||
# This is useful when removing gems from a set of installed gems. By
|
||||
# removing them in the returned order, you don't get into as many dependency
|
||||
# issues.
|
||||
#
|
||||
# If there are circular dependencies (yuck!), then gems will be
|
||||
# returned in order until only the circular dependents and anything
|
||||
# they reference are left. Then arbitrary gemspecs will be returned
|
||||
# until the circular dependency is broken, after which gems will be
|
||||
# returned in dependency order again.
|
||||
# If there are circular dependencies (yuck!), then gems will be returned in
|
||||
# order until only the circular dependents and anything they reference are
|
||||
# left. Then arbitrary gemspecs will be returned until the circular
|
||||
# dependency is broken, after which gems will be returned in dependency
|
||||
# order again.
|
||||
|
||||
def dependency_order
|
||||
sorted = strongly_connected_components.flatten
|
||||
|
||||
|
@ -62,11 +66,20 @@ class Gem::DependencyList
|
|||
result.reverse
|
||||
end
|
||||
|
||||
##
|
||||
# Iterator over dependency_order
|
||||
|
||||
def each(&block)
|
||||
dependency_order.each(&block)
|
||||
end
|
||||
|
||||
def find_name(full_name)
|
||||
@specs.find { |spec| spec.full_name == full_name }
|
||||
end
|
||||
|
||||
##
|
||||
# Are all the dependencies in the list satisfied?
|
||||
|
||||
def ok?
|
||||
@specs.all? do |spec|
|
||||
spec.runtime_dependencies.all? do |dep|
|
||||
|
@ -75,10 +88,12 @@ class Gem::DependencyList
|
|||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Is is ok to remove a gem from the dependency list?
|
||||
#
|
||||
# If removing the gemspec creates breaks a currently ok dependency,
|
||||
# then it is NOT ok to remove the gem.
|
||||
# If removing the gemspec creates breaks a currently ok dependency, then it
|
||||
# is NOT ok to remove the gem.
|
||||
|
||||
def ok_to_remove?(full_name)
|
||||
gem_to_remove = find_name full_name
|
||||
|
||||
|
@ -106,9 +121,10 @@ class Gem::DependencyList
|
|||
@specs.delete_if { |spec| spec.full_name == full_name }
|
||||
end
|
||||
|
||||
# Return a hash of predecessors. <tt>result[spec]</tt> is an
|
||||
# Array of gemspecs that have a dependency satisfied by the named
|
||||
# spec.
|
||||
##
|
||||
# Return a hash of predecessors. <tt>result[spec]</tt> is an Array of
|
||||
# gemspecs that have a dependency satisfied by the named spec.
|
||||
|
||||
def spec_predecessors
|
||||
result = Hash.new { |h,k| h[k] = [] }
|
||||
|
||||
|
@ -151,13 +167,17 @@ class Gem::DependencyList
|
|||
|
||||
private
|
||||
|
||||
##
|
||||
# Count the number of gemspecs in the list +specs+ that are not in
|
||||
# +ignored+.
|
||||
|
||||
def active_count(specs, ignored)
|
||||
result = 0
|
||||
|
||||
specs.each do |spec|
|
||||
result += 1 unless ignored[spec.full_name]
|
||||
end
|
||||
|
||||
result
|
||||
end
|
||||
|
||||
|
|
|
@ -41,12 +41,23 @@ class Gem::DocManager
|
|||
|
||||
begin
|
||||
require 'rdoc/rdoc'
|
||||
|
||||
@rdoc_version = if defined? RDoc::VERSION then
|
||||
Gem::Version.new RDoc::VERSION
|
||||
else
|
||||
Gem::Version.new '1.0.1' # HACK parsing is hard
|
||||
end
|
||||
|
||||
rescue LoadError => e
|
||||
raise Gem::DocumentError,
|
||||
"ERROR: RDoc documentation generator not installed!"
|
||||
"ERROR: RDoc documentation generator not installed: #{e}"
|
||||
end
|
||||
end
|
||||
|
||||
def self.rdoc_version
|
||||
@rdoc_version
|
||||
end
|
||||
|
||||
##
|
||||
# Updates the RI cache for RDoc 2 if it is installed
|
||||
|
||||
|
@ -94,10 +105,8 @@ class Gem::DocManager
|
|||
# RI docs generation to fail if run after RDoc).
|
||||
|
||||
def generate_ri
|
||||
if @spec.has_rdoc then
|
||||
setup_rdoc
|
||||
install_ri # RDoc bug, ri goes first
|
||||
end
|
||||
|
||||
FileUtils.mkdir_p @doc_dir unless File.exist?(@doc_dir)
|
||||
end
|
||||
|
@ -110,10 +119,8 @@ class Gem::DocManager
|
|||
# RI docs generation to fail if run after RDoc).
|
||||
|
||||
def generate_rdoc
|
||||
if @spec.has_rdoc then
|
||||
setup_rdoc
|
||||
install_rdoc
|
||||
end
|
||||
|
||||
FileUtils.mkdir_p @doc_dir unless File.exist?(@doc_dir)
|
||||
end
|
||||
|
@ -151,8 +158,17 @@ class Gem::DocManager
|
|||
args << '--quiet'
|
||||
args << @spec.require_paths.clone
|
||||
args << @spec.extra_rdoc_files
|
||||
args << '--title' << "#{@spec.full_name} Documentation"
|
||||
args = args.flatten.map do |arg| arg.to_s end
|
||||
|
||||
if self.class.rdoc_version >= Gem::Version.new('2.4.0') then
|
||||
args.delete '--inline-source'
|
||||
args.delete '--promiscuous'
|
||||
args.delete '-p'
|
||||
args.delete '--one-file'
|
||||
# HACK more
|
||||
end
|
||||
|
||||
r = RDoc::RDoc.new
|
||||
|
||||
old_pwd = Dir.pwd
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
require 'rubygems'
|
||||
|
||||
##
|
||||
# Base exception class for RubyGems. All exception raised by RubyGems are a
|
||||
# subclass of this one.
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
# See LICENSE.txt for permissions.
|
||||
#++
|
||||
|
||||
require 'rubygems/ext'
|
||||
|
||||
class Gem::Ext::Builder
|
||||
|
||||
def self.class_name
|
||||
|
|
|
@ -11,6 +11,7 @@ class Gem::Ext::ConfigureBuilder < Gem::Ext::Builder
|
|||
def self.build(extension, directory, dest_path, results)
|
||||
unless File.exist?('Makefile') then
|
||||
cmd = "sh ./configure --prefix=#{dest_path}"
|
||||
cmd << " #{Gem::Command.build_args.join ' '}" unless Gem::Command.build_args.empty?
|
||||
|
||||
run cmd, results
|
||||
end
|
||||
|
|
|
@ -5,12 +5,13 @@
|
|||
#++
|
||||
|
||||
require 'rubygems/ext/builder'
|
||||
require 'rubygems/command'
|
||||
|
||||
class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder
|
||||
|
||||
def self.build(extension, directory, dest_path, results)
|
||||
cmd = "#{Gem.ruby} #{File.basename extension}"
|
||||
cmd << " #{ARGV.join ' '}" unless ARGV.empty?
|
||||
cmd << " #{Gem::Command.build_args.join ' '}" unless Gem::Command.build_args.empty?
|
||||
|
||||
run cmd, results
|
||||
|
||||
|
|
|
@ -5,17 +5,21 @@
|
|||
#++
|
||||
|
||||
require 'rubygems/ext/builder'
|
||||
require 'rubygems/command'
|
||||
|
||||
class Gem::Ext::RakeBuilder < Gem::Ext::Builder
|
||||
|
||||
def self.build(extension, directory, dest_path, results)
|
||||
if File.basename(extension) =~ /mkrf_conf/i then
|
||||
cmd = "#{Gem.ruby} #{File.basename extension}"
|
||||
cmd << " #{ARGV.join " "}" unless ARGV.empty?
|
||||
cmd << " #{Gem::Command.build_args.join " "}" unless Gem::Command.build_args.empty?
|
||||
run cmd, results
|
||||
end
|
||||
|
||||
cmd = ENV['rake'] || 'rake'
|
||||
# Deal with possible spaces in the path, e.g. C:/Program Files
|
||||
dest_path = '"' + dest_path + '"' if dest_path.include?(' ')
|
||||
|
||||
cmd = ENV['rake'] || "#{Gem.ruby} -rubygems #{Gem.bin_path('rake')}" rescue Gem.default_exec_format % 'rake'
|
||||
cmd += " RUBYARCHDIR=#{dest_path} RUBYLIBDIR=#{dest_path}" # ENV is frozen
|
||||
|
||||
run cmd, results
|
||||
|
|
|
@ -8,14 +8,14 @@ require 'fileutils'
|
|||
|
||||
require 'rubygems/package'
|
||||
|
||||
module Gem
|
||||
|
||||
##
|
||||
# The format class knows the guts of the RubyGem .gem file format
|
||||
# and provides the capability to read gem files
|
||||
#
|
||||
class Format
|
||||
# Gem::Format knows the guts of the RubyGem .gem file format and provides the
|
||||
# capability to read gem files
|
||||
|
||||
class Gem::Format
|
||||
|
||||
attr_accessor :spec, :file_entries, :gem_path
|
||||
|
||||
extend Gem::UserInteraction
|
||||
|
||||
##
|
||||
|
@ -33,7 +33,7 @@ module Gem
|
|||
# the data from the gem file
|
||||
#
|
||||
# file_path:: [String] Path to the gem file
|
||||
#
|
||||
|
||||
def self.from_file_by_path(file_path, security_policy = nil)
|
||||
format = nil
|
||||
|
||||
|
@ -45,7 +45,7 @@ module Gem
|
|||
if File.read(file_path, 20).include?("MD5SUM =")
|
||||
require 'rubygems/old_format'
|
||||
|
||||
format = OldFormat.from_file_by_path(file_path)
|
||||
format = Gem::OldFormat.from_file_by_path(file_path)
|
||||
else
|
||||
open file_path, Gem.binary_mode do |io|
|
||||
format = from_io io, file_path, security_policy
|
||||
|
@ -60,11 +60,11 @@ module Gem
|
|||
# the data from the gem file
|
||||
#
|
||||
# io:: [IO] Stream from which to read the gem
|
||||
#
|
||||
|
||||
def self.from_io(io, gem_path="(io)", security_policy = nil)
|
||||
format = new gem_path
|
||||
|
||||
Package.open io, 'r', security_policy do |pkg|
|
||||
Gem::Package.open io, 'r', security_policy do |pkg|
|
||||
format.spec = pkg.metadata
|
||||
format.file_entries = []
|
||||
|
||||
|
@ -84,4 +84,4 @@ module Gem
|
|||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -4,23 +4,30 @@
|
|||
# See LICENSE.txt for permissions.
|
||||
#++
|
||||
|
||||
#--
|
||||
# Some system might not have OpenSSL installed, therefore the core
|
||||
# library file openssl might not be available. We localize testing
|
||||
# for the presence of OpenSSL in this file.
|
||||
#++
|
||||
|
||||
module Gem
|
||||
class << self
|
||||
##
|
||||
# Is SSL (used by the signing commands) available on this
|
||||
# platform?
|
||||
|
||||
def ssl_available?
|
||||
require 'rubygems/gem_openssl'
|
||||
@ssl_available
|
||||
end
|
||||
|
||||
# Set the value of the ssl_available flag.
|
||||
##
|
||||
# Is SSL available?
|
||||
|
||||
attr_writer :ssl_available
|
||||
|
||||
##
|
||||
# Ensure that SSL is available. Throw an exception if it is not.
|
||||
|
||||
def ensure_ssl_available
|
||||
unless ssl_available?
|
||||
fail Gem::Exception, "SSL is not installed on this system"
|
||||
|
@ -61,6 +68,8 @@ rescue LoadError, StandardError
|
|||
Gem.ssl_available = false
|
||||
end
|
||||
|
||||
# :stopdoc:
|
||||
|
||||
module Gem::SSL
|
||||
|
||||
# We make our own versions of the constants here. This allows us
|
||||
|
@ -70,7 +79,7 @@ module Gem::SSL
|
|||
# These constants are only used during load time. At runtime, any
|
||||
# method that makes a direct reference to SSL software must be
|
||||
# protected with a Gem.ensure_ssl_available call.
|
||||
#
|
||||
|
||||
if Gem.ssl_available? then
|
||||
PKEY_RSA = OpenSSL::PKey::RSA
|
||||
DIGEST_SHA1 = OpenSSL::Digest::SHA1
|
||||
|
@ -81,3 +90,5 @@ module Gem::SSL
|
|||
|
||||
end
|
||||
|
||||
# :startdoc:
|
||||
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
# See LICENSE.txt for permissions.
|
||||
#++
|
||||
|
||||
require 'rubygems'
|
||||
|
||||
##
|
||||
# GemPathSearcher has the capability to find loadable files inside
|
||||
# gems. It generates data up front to speed up searches later.
|
||||
|
@ -80,11 +78,15 @@ class Gem::GemPathSearcher
|
|||
|
||||
##
|
||||
# Return a list of all installed gemspecs, sorted by alphabetical order and
|
||||
# in reverse version order.
|
||||
# in reverse version order. (bar-2, bar-1, foo-2)
|
||||
|
||||
def init_gemspecs
|
||||
Gem.source_index.map { |_, spec| spec }.sort { |a,b|
|
||||
(a.name <=> b.name).nonzero? || (b.version <=> a.version)
|
||||
specs = Gem.source_index.map { |_, spec| spec }
|
||||
|
||||
specs.sort { |a, b|
|
||||
names = a.name <=> b.name
|
||||
next names if names.nonzero?
|
||||
b.version <=> a.version
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
@ -8,12 +8,16 @@ require 'rubygems/command_manager'
|
|||
require 'rubygems/config_file'
|
||||
require 'rubygems/doc_manager'
|
||||
|
||||
module Gem
|
||||
|
||||
####################################################################
|
||||
##
|
||||
# Run an instance of the gem program.
|
||||
#
|
||||
class GemRunner
|
||||
# Gem::GemRunner is only intended for internal use by RubyGems itself. It
|
||||
# does not form any public API and may change at any time for any reason.
|
||||
#
|
||||
# If you would like to duplicate functionality of `gem` commands, use the
|
||||
# classes they call directly.
|
||||
|
||||
class Gem::GemRunner
|
||||
|
||||
def initialize(options={})
|
||||
@command_manager_class = options[:command_manager] || Gem::CommandManager
|
||||
|
@ -21,11 +25,25 @@ module Gem
|
|||
@doc_manager_class = options[:doc_manager] || Gem::DocManager
|
||||
end
|
||||
|
||||
##
|
||||
# Run the gem command with the following arguments.
|
||||
|
||||
def run(args)
|
||||
start_time = Time.now
|
||||
do_configuration(args)
|
||||
|
||||
if args.include?('--')
|
||||
# We need to preserve the original ARGV to use for passing gem options
|
||||
# to source gems. If there is a -- in the line, strip all options after
|
||||
# it...its for the source building process.
|
||||
build_args = args[args.index("--") + 1...args.length]
|
||||
args = args[0...args.index("--")]
|
||||
end
|
||||
|
||||
Gem::Command.build_args = build_args if build_args
|
||||
|
||||
do_configuration args
|
||||
cmd = @command_manager_class.instance
|
||||
|
||||
cmd.command_names.each do |command_name|
|
||||
config_args = Gem.configuration[command_name]
|
||||
config_args = case config_args
|
||||
|
@ -34,11 +52,13 @@ module Gem
|
|||
else
|
||||
Array(config_args)
|
||||
end
|
||||
Command.add_specific_extra_args command_name, config_args
|
||||
Gem::Command.add_specific_extra_args command_name, config_args
|
||||
end
|
||||
cmd.run(Gem.configuration.args)
|
||||
|
||||
cmd.run Gem.configuration.args
|
||||
end_time = Time.now
|
||||
if Gem.configuration.benchmark
|
||||
|
||||
if Gem.configuration.benchmark then
|
||||
printf "\nExecution time: %0.2f seconds.\n", end_time - start_time
|
||||
puts "Press Enter to finish"
|
||||
STDIN.gets
|
||||
|
@ -54,5 +74,5 @@ module Gem
|
|||
@doc_manager_class.configured_args = Gem.configuration[:rdoc]
|
||||
end
|
||||
|
||||
end # class
|
||||
end # module
|
||||
end
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ require 'rubygems'
|
|||
require 'rubygems/format'
|
||||
|
||||
begin
|
||||
gem 'builder'
|
||||
require 'builder/xchar'
|
||||
rescue LoadError
|
||||
end
|
||||
|
@ -17,11 +18,36 @@ class Gem::Indexer
|
|||
|
||||
include Gem::UserInteraction
|
||||
|
||||
##
|
||||
# Build indexes for RubyGems older than 1.2.0 when true
|
||||
|
||||
attr_accessor :build_legacy
|
||||
|
||||
##
|
||||
# Build indexes for RubyGems 1.2.0 and newer when true
|
||||
|
||||
attr_accessor :build_modern
|
||||
|
||||
##
|
||||
# Index install location
|
||||
|
||||
attr_reader :dest_directory
|
||||
|
||||
##
|
||||
# Specs index install location
|
||||
|
||||
attr_reader :dest_specs_index
|
||||
|
||||
##
|
||||
# Latest specs index install location
|
||||
|
||||
attr_reader :dest_latest_specs_index
|
||||
|
||||
##
|
||||
# Prerelease specs index install location
|
||||
|
||||
attr_reader :dest_prerelease_specs_index
|
||||
|
||||
##
|
||||
# Index build directory
|
||||
|
||||
|
@ -30,12 +56,21 @@ class Gem::Indexer
|
|||
##
|
||||
# Create an indexer that will index the gems in +directory+.
|
||||
|
||||
def initialize(directory)
|
||||
def initialize(directory, options = {})
|
||||
unless ''.respond_to? :to_xs then
|
||||
fail "Gem::Indexer requires that the XML Builder library be installed:" \
|
||||
"\n\tgem install builder"
|
||||
end
|
||||
|
||||
options = { :build_legacy => true, :build_modern => true }.merge options
|
||||
|
||||
@build_legacy = options[:build_legacy]
|
||||
@build_modern = options[:build_modern]
|
||||
|
||||
@rss_title = options[:rss_title]
|
||||
@rss_host = options[:rss_host]
|
||||
@rss_gems_host = options[:rss_gems_host]
|
||||
|
||||
@dest_directory = directory
|
||||
@directory = File.join Dir.tmpdir, "gem_generate_index_#{$$}"
|
||||
|
||||
|
@ -54,22 +89,19 @@ class Gem::Indexer
|
|||
@specs_index = File.join @directory, "specs.#{Gem.marshal_version}"
|
||||
@latest_specs_index = File.join @directory,
|
||||
"latest_specs.#{Gem.marshal_version}"
|
||||
@prerelease_specs_index = File.join(@directory,
|
||||
"prerelease_specs.#{Gem.marshal_version}")
|
||||
|
||||
files = [
|
||||
@specs_index,
|
||||
"#{@specs_index}.gz",
|
||||
@latest_specs_index,
|
||||
"#{@latest_specs_index}.gz",
|
||||
@quick_dir,
|
||||
@master_index,
|
||||
"#{@master_index}.Z",
|
||||
@marshal_index,
|
||||
"#{@marshal_index}.Z",
|
||||
]
|
||||
@dest_specs_index = File.join @dest_directory,
|
||||
"specs.#{Gem.marshal_version}"
|
||||
@dest_latest_specs_index = File.join @dest_directory,
|
||||
"latest_specs.#{Gem.marshal_version}"
|
||||
@dest_prerelease_specs_index = File.join @dest_directory,
|
||||
"prerelease_specs.#{Gem.marshal_version}"
|
||||
|
||||
@files = files.map do |path|
|
||||
path.sub @directory, ''
|
||||
end
|
||||
@rss_index = File.join @directory, 'index.rss'
|
||||
|
||||
@files = []
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -91,78 +123,68 @@ class Gem::Indexer
|
|||
# Build various indicies
|
||||
|
||||
def build_indicies(index)
|
||||
# Marshal gemspecs are used by both modern and legacy RubyGems
|
||||
build_marshal_gemspecs index
|
||||
build_legacy_indicies index if @build_legacy
|
||||
build_modern_indicies index if @build_modern
|
||||
build_rss index
|
||||
|
||||
compress_indicies
|
||||
end
|
||||
|
||||
##
|
||||
# Builds indicies for RubyGems older than 1.2.x
|
||||
|
||||
def build_legacy_indicies(index)
|
||||
progress = ui.progress_reporter index.size,
|
||||
"Generating quick index gemspecs for #{index.size} gems",
|
||||
"Generating YAML quick index gemspecs for #{index.size} gems",
|
||||
"Complete"
|
||||
|
||||
Gem.time 'Generated YAML quick index gemspecs' do
|
||||
index.each do |original_name, spec|
|
||||
spec_file_name = "#{original_name}.gemspec.rz"
|
||||
yaml_name = File.join @quick_dir, spec_file_name
|
||||
marshal_name = File.join @quick_marshal_dir, spec_file_name
|
||||
|
||||
yaml_zipped = Gem.deflate spec.to_yaml
|
||||
open yaml_name, 'wb' do |io| io.write yaml_zipped end
|
||||
|
||||
marshal_zipped = Gem.deflate Marshal.dump(spec)
|
||||
open marshal_name, 'wb' do |io| io.write marshal_zipped end
|
||||
|
||||
progress.updated original_name
|
||||
end
|
||||
|
||||
progress.done
|
||||
|
||||
say "Generating specs index"
|
||||
|
||||
open @specs_index, 'wb' do |io|
|
||||
specs = index.sort.map do |_, spec|
|
||||
platform = spec.original_platform
|
||||
platform = Gem::Platform::RUBY if platform.nil? or platform.empty?
|
||||
[spec.name, spec.version, platform]
|
||||
end
|
||||
|
||||
specs = compact_specs specs
|
||||
|
||||
Marshal.dump specs, io
|
||||
end
|
||||
|
||||
say "Generating latest specs index"
|
||||
|
||||
open @latest_specs_index, 'wb' do |io|
|
||||
specs = index.latest_specs.sort.map do |spec|
|
||||
platform = spec.original_platform
|
||||
platform = Gem::Platform::RUBY if platform.nil? or platform.empty?
|
||||
[spec.name, spec.version, platform]
|
||||
end
|
||||
|
||||
specs = compact_specs specs
|
||||
|
||||
Marshal.dump specs, io
|
||||
end
|
||||
|
||||
say "Generating quick index"
|
||||
|
||||
quick_index = File.join @quick_dir, 'index'
|
||||
open quick_index, 'wb' do |io|
|
||||
Gem.time 'Generated quick index' do
|
||||
open @quick_index, 'wb' do |io|
|
||||
io.puts index.sort.map { |_, spec| spec.original_name }
|
||||
end
|
||||
end
|
||||
|
||||
say "Generating latest index"
|
||||
|
||||
latest_index = File.join @quick_dir, 'latest_index'
|
||||
open latest_index, 'wb' do |io|
|
||||
Gem.time 'Generated latest index' do
|
||||
open @latest_index, 'wb' do |io|
|
||||
io.puts index.latest_specs.sort.map { |spec| spec.original_name }
|
||||
end
|
||||
end
|
||||
|
||||
# Don't need prerelease legacy index
|
||||
|
||||
say "Generating Marshal master index"
|
||||
|
||||
Gem.time 'Generated Marshal master index' do
|
||||
open @marshal_index, 'wb' do |io|
|
||||
io.write index.dump
|
||||
end
|
||||
end
|
||||
|
||||
progress = ui.progress_reporter index.size,
|
||||
"Generating YAML master index for #{index.size} gems (this may take a while)",
|
||||
"Complete"
|
||||
|
||||
Gem.time 'Generated YAML master index' do
|
||||
open @master_index, 'wb' do |io|
|
||||
io.puts "--- !ruby/object:#{index.class}"
|
||||
io.puts "gems:"
|
||||
|
@ -179,37 +201,219 @@ class Gem::Indexer
|
|||
end
|
||||
|
||||
progress.done
|
||||
end
|
||||
|
||||
say "Compressing indicies"
|
||||
# use gzip for future files.
|
||||
@files << @quick_dir
|
||||
@files << @master_index
|
||||
@files << "#{@master_index}.Z"
|
||||
@files << @marshal_index
|
||||
@files << "#{@marshal_index}.Z"
|
||||
end
|
||||
|
||||
compress quick_index, 'rz'
|
||||
paranoid quick_index, 'rz'
|
||||
##
|
||||
# Builds Marshal quick index gemspecs.
|
||||
|
||||
compress latest_index, 'rz'
|
||||
paranoid latest_index, 'rz'
|
||||
def build_marshal_gemspecs(index)
|
||||
progress = ui.progress_reporter index.size,
|
||||
"Generating Marshal quick index gemspecs for #{index.size} gems",
|
||||
"Complete"
|
||||
|
||||
compress @marshal_index, 'Z'
|
||||
paranoid @marshal_index, 'Z'
|
||||
files = []
|
||||
|
||||
compress @master_index, 'Z'
|
||||
paranoid @master_index, 'Z'
|
||||
Gem.time 'Generated Marshal quick index gemspecs' do
|
||||
(index.gems.merge(index.prerelease_gems)).each do |original_name, spec|
|
||||
spec_file_name = "#{original_name}.gemspec.rz"
|
||||
marshal_name = File.join @quick_marshal_dir, spec_file_name
|
||||
|
||||
gzip @specs_index
|
||||
gzip @latest_specs_index
|
||||
marshal_zipped = Gem.deflate Marshal.dump(spec)
|
||||
open marshal_name, 'wb' do |io| io.write marshal_zipped end
|
||||
|
||||
files << marshal_name
|
||||
|
||||
progress.updated original_name
|
||||
end
|
||||
|
||||
progress.done
|
||||
end
|
||||
|
||||
@files << @quick_marshal_dir
|
||||
|
||||
files
|
||||
end
|
||||
|
||||
##
|
||||
# Build a single index for RubyGems 1.2 and newer
|
||||
|
||||
def build_modern_index(index, file, name)
|
||||
say "Generating #{name} index"
|
||||
|
||||
Gem.time "Generated #{name} index" do
|
||||
open(file, 'wb') do |io|
|
||||
specs = index.map do |*spec|
|
||||
# We have to splat here because latest_specs is an array,
|
||||
# while the others are hashes. See the TODO in source_index.rb
|
||||
spec = spec.flatten.last
|
||||
platform = spec.original_platform
|
||||
|
||||
# win32-api-1.0.4-x86-mswin32-60
|
||||
unless String === platform then
|
||||
alert_warning "Skipping invalid platform in gem: #{spec.full_name}"
|
||||
next
|
||||
end
|
||||
|
||||
platform = Gem::Platform::RUBY if platform.nil? or platform.empty?
|
||||
[spec.name, spec.version, platform]
|
||||
end
|
||||
|
||||
specs = compact_specs(specs)
|
||||
Marshal.dump(specs, io)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Builds indicies for RubyGems 1.2 and newer. Handles full, latest, prerelease
|
||||
|
||||
def build_modern_indicies(index)
|
||||
build_modern_index(index.sort, @specs_index, 'specs')
|
||||
build_modern_index(index.latest_specs.sort,
|
||||
@latest_specs_index,
|
||||
'latest specs')
|
||||
build_modern_index(index.prerelease_specs.sort,
|
||||
@prerelease_specs_index,
|
||||
'prerelease specs')
|
||||
|
||||
@files += [@specs_index,
|
||||
"#{@specs_index}.gz",
|
||||
@latest_specs_index,
|
||||
"#{@latest_specs_index}.gz",
|
||||
@prerelease_specs_index,
|
||||
"#{@prerelease_specs_index}.gz"]
|
||||
end
|
||||
|
||||
##
|
||||
# Builds an RSS feed for past two days gem releases according to the gem's
|
||||
# date.
|
||||
|
||||
def build_rss(index)
|
||||
if @rss_host.nil? or @rss_gems_host.nil? then
|
||||
if Gem.configuration.really_verbose then
|
||||
alert_warning "no --rss-host or --rss-gems-host, RSS generation disabled"
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
require 'cgi'
|
||||
require 'rubygems/text'
|
||||
|
||||
extend Gem::Text
|
||||
|
||||
Gem.time 'Generated rss' do
|
||||
open @rss_index, 'wb' do |io|
|
||||
rss_host = CGI.escapeHTML @rss_host
|
||||
rss_title = CGI.escapeHTML(@rss_title || 'gems')
|
||||
|
||||
io.puts <<-HEADER
|
||||
<?xml version="1.0"?>
|
||||
<rss version="2.0">
|
||||
<channel>
|
||||
<title>#{rss_title}</title>
|
||||
<link>http://#{rss_host}</link>
|
||||
<description>Recently released gems from http://#{rss_host}</description>
|
||||
<generator>RubyGems v#{Gem::RubyGemsVersion}</generator>
|
||||
<docs>http://cyber.law.harvard.edu/rss/rss.html</docs>
|
||||
HEADER
|
||||
|
||||
today = Gem::Specification::TODAY
|
||||
yesterday = today - 86400
|
||||
|
||||
index = index.select do |_, spec|
|
||||
spec_date = spec.date
|
||||
|
||||
case spec_date
|
||||
when Date
|
||||
Time.parse(spec_date.to_s) >= yesterday
|
||||
when Time
|
||||
spec_date >= yesterday
|
||||
end
|
||||
end
|
||||
|
||||
index = index.select do |_, spec|
|
||||
spec_date = spec.date
|
||||
|
||||
case spec_date
|
||||
when Date
|
||||
Time.parse(spec_date.to_s) <= today
|
||||
when Time
|
||||
spec_date <= today
|
||||
end
|
||||
end
|
||||
|
||||
index.sort_by { |_, spec| [-spec.date.to_i, spec] }.each do |_, spec|
|
||||
gem_path = CGI.escapeHTML "http://#{@rss_gems_host}/gems/#{spec.full_name}.gem"
|
||||
size = File.stat(spec.loaded_from).size rescue next
|
||||
|
||||
description = spec.description || spec.summary || ''
|
||||
authors = Array spec.authors
|
||||
emails = Array spec.email
|
||||
authors = emails.zip(authors).map do |email, author|
|
||||
email += " (#{author})" if author and not author.empty?
|
||||
end.join ', '
|
||||
|
||||
description = description.split(/\n\n+/).map do |chunk|
|
||||
format_text chunk, 78
|
||||
end
|
||||
|
||||
description = description.join "\n\n"
|
||||
|
||||
item = ''
|
||||
|
||||
item << <<-ITEM
|
||||
<item>
|
||||
<title>#{CGI.escapeHTML spec.full_name}</title>
|
||||
<description>
|
||||
<pre>#{CGI.escapeHTML description.chomp}</pre>
|
||||
</description>
|
||||
<author>#{CGI.escapeHTML authors}</author>
|
||||
<guid>#{CGI.escapeHTML spec.full_name}</guid>
|
||||
<enclosure url=\"#{gem_path}\"
|
||||
length=\"#{size}\" type=\"application/octet-stream\" />
|
||||
<pubDate>#{spec.date.rfc2822}</pubDate>
|
||||
ITEM
|
||||
|
||||
item << <<-ITEM if spec.homepage
|
||||
<link>#{CGI.escapeHTML spec.homepage}</link>
|
||||
ITEM
|
||||
|
||||
item << <<-ITEM
|
||||
</item>
|
||||
ITEM
|
||||
|
||||
io.puts item
|
||||
end
|
||||
|
||||
io.puts <<-FOOTER
|
||||
</channel>
|
||||
</rss>
|
||||
FOOTER
|
||||
end
|
||||
end
|
||||
|
||||
@files << @rss_index
|
||||
end
|
||||
|
||||
##
|
||||
# Collect specifications from .gem files from the gem directory.
|
||||
|
||||
def collect_specs
|
||||
def collect_specs(gems = gem_file_list)
|
||||
index = Gem::SourceIndex.new
|
||||
|
||||
progress = ui.progress_reporter gem_file_list.size,
|
||||
"Loading #{gem_file_list.size} gems from #{@dest_directory}",
|
||||
progress = ui.progress_reporter gems.size,
|
||||
"Loading #{gems.size} gems from #{@dest_directory}",
|
||||
"Loaded all gems"
|
||||
|
||||
gem_file_list.each do |gemfile|
|
||||
Gem.time 'loaded' do
|
||||
gems.each do |gemfile|
|
||||
if File.size(gemfile.to_s) == 0 then
|
||||
alert_warning "Skipping zero-length gem: #{gemfile}"
|
||||
next
|
||||
|
@ -217,16 +421,20 @@ class Gem::Indexer
|
|||
|
||||
begin
|
||||
spec = Gem::Format.from_file_by_path(gemfile).spec
|
||||
spec.loaded_from = gemfile
|
||||
|
||||
unless gemfile =~ /\/#{Regexp.escape spec.original_name}.*\.gem\z/i then
|
||||
alert_warning "Skipping misnamed gem: #{gemfile} => #{spec.full_name} (#{spec.original_name})"
|
||||
expected_name = spec.full_name
|
||||
expected_name << " (#{spec.original_name})" if
|
||||
spec.original_name != spec.full_name
|
||||
alert_warning "Skipping misnamed gem: #{gemfile} should be named #{expected_name}"
|
||||
next
|
||||
end
|
||||
|
||||
abbreviate spec
|
||||
sanitize spec
|
||||
|
||||
index.gems[spec.original_name] = spec
|
||||
index.add_spec spec, spec.original_name
|
||||
|
||||
progress.updated spec.original_name
|
||||
|
||||
|
@ -239,10 +447,42 @@ class Gem::Indexer
|
|||
end
|
||||
|
||||
progress.done
|
||||
end
|
||||
|
||||
index
|
||||
end
|
||||
|
||||
##
|
||||
# Compresses indicies on disk
|
||||
#--
|
||||
# All future files should be compressed using gzip, not deflate
|
||||
|
||||
def compress_indicies
|
||||
say "Compressing indicies"
|
||||
|
||||
Gem.time 'Compressed indicies' do
|
||||
if @build_legacy then
|
||||
compress @quick_index, 'rz'
|
||||
paranoid @quick_index, 'rz'
|
||||
|
||||
compress @latest_index, 'rz'
|
||||
paranoid @latest_index, 'rz'
|
||||
|
||||
compress @marshal_index, 'Z'
|
||||
paranoid @marshal_index, 'Z'
|
||||
|
||||
compress @master_index, 'Z'
|
||||
paranoid @master_index, 'Z'
|
||||
end
|
||||
|
||||
if @build_modern then
|
||||
gzip @specs_index
|
||||
gzip @latest_specs_index
|
||||
gzip @prerelease_specs_index
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Compacts Marshal output for the specs index data source by using identical
|
||||
# objects as much as possible.
|
||||
|
@ -282,7 +522,7 @@ class Gem::Indexer
|
|||
end
|
||||
|
||||
##
|
||||
# Builds and installs indexicies.
|
||||
# Builds and installs indicies.
|
||||
|
||||
def generate_index
|
||||
make_temp_directories
|
||||
|
@ -311,7 +551,27 @@ class Gem::Indexer
|
|||
|
||||
say "Moving index into production dir #{@dest_directory}" if verbose
|
||||
|
||||
@files.each do |file|
|
||||
files = @files.dup
|
||||
files.delete @quick_marshal_dir if files.include? @quick_dir
|
||||
|
||||
if files.include? @quick_marshal_dir and
|
||||
not files.include? @quick_dir then
|
||||
files.delete @quick_marshal_dir
|
||||
quick_marshal_dir = @quick_marshal_dir.sub @directory, ''
|
||||
|
||||
dst_name = File.join @dest_directory, quick_marshal_dir
|
||||
|
||||
FileUtils.mkdir_p File.dirname(dst_name), :verbose => verbose
|
||||
FileUtils.rm_rf dst_name, :verbose => verbose
|
||||
FileUtils.mv @quick_marshal_dir, dst_name, :verbose => verbose,
|
||||
:force => true
|
||||
end
|
||||
|
||||
files = files.map do |path|
|
||||
path.sub @directory, ''
|
||||
end
|
||||
|
||||
files.each do |file|
|
||||
src_name = File.join @directory, file
|
||||
dst_name = File.join @dest_directory, file
|
||||
|
||||
|
@ -366,5 +626,87 @@ class Gem::Indexer
|
|||
string ? string.to_s.to_xs : string
|
||||
end
|
||||
|
||||
##
|
||||
# Perform an in-place update of the repository from newly added gems. Only
|
||||
# works for modern indicies, and sets #build_legacy to false when run.
|
||||
|
||||
def update_index
|
||||
@build_legacy = false
|
||||
|
||||
make_temp_directories
|
||||
|
||||
specs_mtime = File.stat(@dest_specs_index).mtime
|
||||
newest_mtime = Time.at 0
|
||||
|
||||
updated_gems = gem_file_list.select do |gem|
|
||||
gem_mtime = File.stat(gem).mtime
|
||||
newest_mtime = gem_mtime if gem_mtime > newest_mtime
|
||||
gem_mtime >= specs_mtime
|
||||
end
|
||||
|
||||
if updated_gems.empty? then
|
||||
say 'No new gems'
|
||||
terminate_interaction 0
|
||||
end
|
||||
|
||||
index = collect_specs updated_gems
|
||||
|
||||
files = build_marshal_gemspecs index
|
||||
|
||||
Gem.time 'Updated indexes' do
|
||||
update_specs_index index, @dest_specs_index, @specs_index
|
||||
update_specs_index index, @dest_latest_specs_index, @latest_specs_index
|
||||
update_specs_index(index.prerelease_gems, @dest_prerelease_specs_index,
|
||||
@prerelease_specs_index)
|
||||
end
|
||||
|
||||
compress_indicies
|
||||
|
||||
verbose = Gem.configuration.really_verbose
|
||||
|
||||
say "Updating production dir #{@dest_directory}" if verbose
|
||||
|
||||
files << @specs_index
|
||||
files << "#{@specs_index}.gz"
|
||||
files << @latest_specs_index
|
||||
files << "#{@latest_specs_index}.gz"
|
||||
files << @prerelease_specs_index
|
||||
files << "#{@prerelease_specs_index}.gz"
|
||||
|
||||
files = files.map do |path|
|
||||
path.sub @directory, ''
|
||||
end
|
||||
|
||||
files.each do |file|
|
||||
src_name = File.join @directory, file
|
||||
dst_name = File.join @dest_directory, File.dirname(file)
|
||||
|
||||
FileUtils.mv src_name, dst_name, :verbose => verbose,
|
||||
:force => true
|
||||
|
||||
File.utime newest_mtime, newest_mtime, dst_name
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Combines specs in +index+ and +source+ then writes out a new copy to
|
||||
# +dest+. For a latest index, does not ensure the new file is minimal.
|
||||
|
||||
def update_specs_index(index, source, dest)
|
||||
specs_index = Marshal.load Gem.read_binary(source)
|
||||
|
||||
index.each do |_, spec|
|
||||
platform = spec.original_platform
|
||||
platform = Gem::Platform::RUBY if platform.nil? or platform.empty?
|
||||
specs_index << [spec.name, spec.version, platform]
|
||||
end
|
||||
|
||||
specs_index = compact_specs specs_index.uniq.sort
|
||||
|
||||
open dest, 'wb' do |io|
|
||||
Marshal.dump specs_index, io
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -9,9 +9,12 @@ require 'rubygems/security'
|
|||
|
||||
##
|
||||
# Mixin methods for install and update options for Gem::Commands
|
||||
|
||||
module Gem::InstallUpdateOptions
|
||||
|
||||
##
|
||||
# Add the install/update options to the option parser.
|
||||
|
||||
def add_install_update_options
|
||||
OptionParser.accept Gem::Security::Policy do |value|
|
||||
value = Gem::Security::Policies[value]
|
||||
|
@ -92,7 +95,7 @@ module Gem::InstallUpdateOptions
|
|||
|
||||
add_option(:"Install/Update", '--[no-]user-install',
|
||||
'Install in user\'s home directory instead',
|
||||
'of GEM_HOME. Defaults to using home directory',
|
||||
'of GEM_HOME. Defaults to using home',
|
||||
'only if GEM_HOME is not writable.') do |value, options|
|
||||
options[:user_install] = value
|
||||
end
|
||||
|
@ -102,9 +105,18 @@ module Gem::InstallUpdateOptions
|
|||
"dependencies") do |value, options|
|
||||
options[:development] = true
|
||||
end
|
||||
|
||||
add_option(:"Install/Update", "--prerelease",
|
||||
"Install prerelease versions of a gem if",
|
||||
"available. Defaults to skipping",
|
||||
"prereleases.") do |value, options|
|
||||
options[:prerelease] = true
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Default options for the gem install command.
|
||||
|
||||
def install_update_defaults_str
|
||||
'--rdoc --no-force --no-test --wrappers'
|
||||
end
|
||||
|
|
|
@ -13,16 +13,27 @@ require 'rubygems/ext'
|
|||
require 'rubygems/require_paths_builder'
|
||||
|
||||
##
|
||||
# The installer class processes RubyGem .gem files and installs the
|
||||
# files contained in the .gem into the Gem.path.
|
||||
# The installer class processes RubyGem .gem files and installs the files
|
||||
# contained in the .gem into the Gem.path.
|
||||
#
|
||||
# Gem::Installer does the work of putting files in all the right places on the
|
||||
# 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.
|
||||
#
|
||||
# The installer fires pre and post install hooks. Hooks can be added either
|
||||
# through a rubygems_plugin.rb file in an installed gem or via a
|
||||
# rubygems/defaults/#{RUBY_ENGINE}.rb or rubygems/defaults/operating_system.rb
|
||||
# file. See Gem.pre_install and Gem.post_install for details.
|
||||
|
||||
class Gem::Installer
|
||||
|
||||
##
|
||||
# Paths where env(1) might live. Some systems are broken and have it in
|
||||
# /bin
|
||||
|
||||
ENV_PATHS = %w[/usr/bin/env /bin/env]
|
||||
|
||||
##
|
||||
# Raised when there is an error while building extensions.
|
||||
#
|
||||
|
@ -71,8 +82,6 @@ class Gem::Installer
|
|||
|
||||
end
|
||||
|
||||
ENV_PATHS = %w[/usr/bin/env /bin/env]
|
||||
|
||||
##
|
||||
# Constructs an Installer instance that will install the gem located at
|
||||
# +gem+. +options+ is a Hash with the following keys:
|
||||
|
@ -121,7 +130,7 @@ class Gem::Installer
|
|||
begin
|
||||
FileUtils.mkdir_p @gem_home
|
||||
rescue Errno::EACCES, Errno::ENOTDIR
|
||||
# We'll divert to ~/.gem below
|
||||
# We'll divert to ~/.gems below
|
||||
end
|
||||
|
||||
if not File.writable? @gem_home or
|
||||
|
@ -131,7 +140,7 @@ class Gem::Installer
|
|||
if options[:user_install] == false then # You don't want to use ~
|
||||
raise Gem::FilePermissionError, @gem_home
|
||||
elsif options[:user_install].nil? then
|
||||
unless self.class.home_install_warning then
|
||||
unless self.class.home_install_warning or options[:unpack] then
|
||||
alert_warning "Installing to ~/.gem since #{@gem_home} and\n\t #{Gem.bindir} aren't both writable."
|
||||
self.class.home_install_warning = true
|
||||
end
|
||||
|
@ -392,19 +401,21 @@ class Gem::Installer
|
|||
ruby_name = Gem::ConfigMap[:ruby_install_name] if @env_shebang
|
||||
path = File.join @gem_dir, @spec.bindir, bin_file_name
|
||||
first_line = File.open(path, "rb") {|file| file.gets}
|
||||
|
||||
if /\A#!/ =~ first_line then
|
||||
# Preserve extra words on shebang line, like "-w". Thanks RPA.
|
||||
shebang = first_line.sub(/\A\#!.*?ruby\S*(?=(\s+\S+))/, "#!#{Gem.ruby}")
|
||||
opts = $1
|
||||
shebang.strip! # Avoid nasty ^M issues.
|
||||
end
|
||||
if !ruby_name
|
||||
|
||||
if not ruby_name then
|
||||
"#!#{Gem.ruby}#{opts}"
|
||||
elsif opts
|
||||
%{#!/bin/sh\n'exec' #{ruby_name.dump} '-x' "$0" "$@"\n#{shebang}}
|
||||
elsif opts then
|
||||
"#!/bin/sh\n'exec' #{ruby_name.dump} '-x' \"$0\" \"$@\"\n#{shebang}"
|
||||
else
|
||||
# Create a plain shebang line.
|
||||
@env_path ||= ENV_PATHS.find {|path| File.executable?(path)}
|
||||
@env_path ||= ENV_PATHS.find {|env_path| File.executable? env_path }
|
||||
"#!#{@env_path} #{ruby_name}"
|
||||
end
|
||||
end
|
||||
|
@ -432,7 +443,7 @@ if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
|
|||
end
|
||||
|
||||
gem '#{@spec.name}', version
|
||||
load '#{bin_file_name}'
|
||||
load Gem.bin_path('#{@spec.name}', '#{bin_file_name}', version)
|
||||
TEXT
|
||||
end
|
||||
|
||||
|
@ -443,10 +454,10 @@ TEXT
|
|||
<<-TEXT
|
||||
@ECHO OFF
|
||||
IF NOT "%~f0" == "~f0" GOTO :WinNT
|
||||
@"#{File.basename(Gem.ruby)}" "#{File.join(bindir, bin_file_name)}" %1 %2 %3 %4 %5 %6 %7 %8 %9
|
||||
@"#{File.basename(Gem.ruby).chomp('"')}" "#{File.join(bindir, bin_file_name)}" %1 %2 %3 %4 %5 %6 %7 %8 %9
|
||||
GOTO :EOF
|
||||
:WinNT
|
||||
@"#{File.basename(Gem.ruby)}" "%~dpn0" %*
|
||||
@"#{File.basename(Gem.ruby).chomp('"')}" "%~dpn0" %*
|
||||
TEXT
|
||||
end
|
||||
|
||||
|
@ -531,6 +542,7 @@ Results logged to #{File.join(Dir.pwd, 'gem_make.out')}
|
|||
raise Gem::InstallError, msg
|
||||
end
|
||||
|
||||
FileUtils.rm_rf(path) if File.exists?(path)
|
||||
FileUtils.mkdir_p File.dirname(path)
|
||||
|
||||
File.open(path, "wb") do |out|
|
||||
|
|
|
@ -23,7 +23,9 @@ module Gem::LocalRemoteOptions
|
|||
raise OptionParser::InvalidArgument, value
|
||||
end
|
||||
|
||||
raise OptionParser::InvalidArgument, value unless uri.scheme == 'http'
|
||||
unless ['http', 'https', 'file'].include?(uri.scheme)
|
||||
raise OptionParser::InvalidArgument, value
|
||||
end
|
||||
|
||||
value
|
||||
end
|
||||
|
@ -90,7 +92,7 @@ module Gem::LocalRemoteOptions
|
|||
source << '/' if source !~ /\/\z/
|
||||
|
||||
if options[:added_source] then
|
||||
Gem.sources << source
|
||||
Gem.sources << source unless Gem.sources.include?(source)
|
||||
else
|
||||
options[:added_source] = true
|
||||
Gem.sources.replace [source]
|
||||
|
@ -99,10 +101,9 @@ module Gem::LocalRemoteOptions
|
|||
end
|
||||
|
||||
##
|
||||
# Add the --update-source option
|
||||
# Add the --update-sources option
|
||||
|
||||
def add_update_sources_option
|
||||
|
||||
add_option(:"Local/Remote", '-u', '--[no-]update-sources',
|
||||
'Update local source cache') do |value, options|
|
||||
Gem.configuration.update_sources = value
|
||||
|
|
|
@ -4,39 +4,40 @@
|
|||
# See LICENSE.txt for permissions.
|
||||
#++
|
||||
|
||||
require 'rubygems'
|
||||
require 'fileutils'
|
||||
require 'yaml'
|
||||
require 'zlib'
|
||||
|
||||
module Gem
|
||||
|
||||
##
|
||||
# The format class knows the guts of the RubyGem .gem file format
|
||||
# and provides the capability to read gem files
|
||||
#
|
||||
class OldFormat
|
||||
# The format class knows the guts of the RubyGem .gem file format and provides
|
||||
# the capability to read gem files
|
||||
|
||||
class Gem::OldFormat
|
||||
|
||||
attr_accessor :spec, :file_entries, :gem_path
|
||||
|
||||
##
|
||||
# Constructs an instance of a Format object, representing the gem's
|
||||
# data structure.
|
||||
# Constructs an instance of a Format object, representing the gem's data
|
||||
# structure.
|
||||
#
|
||||
# gem:: [String] The file name of the gem
|
||||
#
|
||||
|
||||
def initialize(gem_path)
|
||||
@gem_path = gem_path
|
||||
end
|
||||
|
||||
##
|
||||
# Reads the named gem file and returns a Format object, representing
|
||||
# the data from the gem file
|
||||
# Reads the named gem file and returns a Format object, representing the
|
||||
# data from the gem file
|
||||
#
|
||||
# file_path:: [String] Path to the gem file
|
||||
#
|
||||
|
||||
def self.from_file_by_path(file_path)
|
||||
unless File.exist?(file_path)
|
||||
raise Gem::Exception, "Cannot load gem file [#{file_path}]"
|
||||
end
|
||||
|
||||
File.open(file_path, 'rb') do |file|
|
||||
from_io(file, file_path)
|
||||
end
|
||||
|
@ -47,7 +48,7 @@ module Gem
|
|||
# the data from the gem file
|
||||
#
|
||||
# io:: [IO] Stream from which to read the gem
|
||||
#
|
||||
|
||||
def self.from_io(io, gem_path="(io)")
|
||||
format = self.new(gem_path)
|
||||
skip_ruby(io)
|
||||
|
@ -60,12 +61,13 @@ module Gem
|
|||
end
|
||||
|
||||
private
|
||||
|
||||
##
|
||||
# Skips the Ruby self-install header. After calling this method, the
|
||||
# IO index will be set after the Ruby code.
|
||||
#
|
||||
# file:: [IO] The IO to process (skip the Ruby code)
|
||||
#
|
||||
|
||||
def self.skip_ruby(file)
|
||||
end_seen = false
|
||||
loop {
|
||||
|
@ -75,7 +77,8 @@ module Gem
|
|||
break
|
||||
end
|
||||
}
|
||||
if(end_seen == false) then
|
||||
|
||||
if end_seen == false then
|
||||
raise Gem::Exception.new("Failed to find end of ruby script while reading gem")
|
||||
end
|
||||
end
|
||||
|
@ -86,19 +89,19 @@ module Gem
|
|||
# IO index will be set after the specification header.
|
||||
#
|
||||
# file:: [IO] The IO to process
|
||||
#
|
||||
|
||||
def self.read_spec(file)
|
||||
yaml = ''
|
||||
begin
|
||||
read_until_dashes(file) do |line|
|
||||
|
||||
read_until_dashes file do |line|
|
||||
yaml << line
|
||||
end
|
||||
Specification.from_yaml(yaml)
|
||||
|
||||
Gem::Specification.from_yaml yaml
|
||||
rescue YAML::Error => e
|
||||
raise Gem::Exception.new("Failed to parse gem specification out of gem file")
|
||||
raise Gem::Exception, "Failed to parse gem specification out of gem file"
|
||||
rescue ArgumentError => e
|
||||
raise Gem::Exception.new("Failed to parse gem specification out of gem file")
|
||||
end
|
||||
raise Gem::Exception, "Failed to parse gem specification out of gem file"
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -107,14 +110,13 @@ module Gem
|
|||
#
|
||||
# file:: [IO] The IO to process
|
||||
# block:: [String] The read line
|
||||
#
|
||||
|
||||
def self.read_until_dashes(file)
|
||||
while((line = file.gets) && line.chomp.strip != "---") do
|
||||
yield line
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
##
|
||||
# Reads the embedded file data from a gem file, yielding an entry
|
||||
# containing metadata about the file and the file contents themselves
|
||||
|
@ -123,7 +125,7 @@ module Gem
|
|||
# Gem file read/writer
|
||||
#
|
||||
# gem_file:: [IO] The IO to process
|
||||
#
|
||||
|
||||
def self.read_files_from_gem(gem_file)
|
||||
errstr = "Error reading files from gem"
|
||||
header_yaml = ''
|
||||
|
@ -132,7 +134,8 @@ module Gem
|
|||
header_yaml << line
|
||||
end
|
||||
header = YAML.load(header_yaml)
|
||||
raise Gem::Exception.new(errstr) unless header
|
||||
raise Gem::Exception, errstr unless header
|
||||
|
||||
header.each do |entry|
|
||||
file_data = ''
|
||||
self.read_until_dashes(gem_file) do |line|
|
||||
|
@ -140,9 +143,10 @@ module Gem
|
|||
end
|
||||
yield [entry, Zlib::Inflate.inflate(file_data.strip.unpack("m")[0])]
|
||||
end
|
||||
rescue Exception,Zlib::DataError => e
|
||||
raise Gem::Exception.new(errstr)
|
||||
end
|
||||
rescue Zlib::DataError => e
|
||||
raise Gem::Exception, errstr
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
# See LICENSE.txt for additional licensing information.
|
||||
#--
|
||||
|
||||
require 'rubygems/package'
|
||||
|
||||
module Gem::Package::FSyncDir
|
||||
|
||||
private
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
# See LICENSE.txt for additional licensing information.
|
||||
#--
|
||||
|
||||
require 'rubygems/package'
|
||||
|
||||
##
|
||||
#--
|
||||
# struct tarfile_entry_posix {
|
||||
|
@ -26,9 +24,13 @@ require 'rubygems/package'
|
|||
# char prefix[155]; # ASCII + (Z unless filled)
|
||||
# };
|
||||
#++
|
||||
# A header for a tar file
|
||||
|
||||
class Gem::Package::TarHeader
|
||||
|
||||
##
|
||||
# Fields in the tar header
|
||||
|
||||
FIELDS = [
|
||||
:checksum,
|
||||
:devmajor,
|
||||
|
@ -48,6 +50,9 @@ class Gem::Package::TarHeader
|
|||
:version,
|
||||
]
|
||||
|
||||
##
|
||||
# Pack format for a tar header
|
||||
|
||||
PACK_FORMAT = 'a100' + # name
|
||||
'a8' + # mode
|
||||
'a8' + # uid
|
||||
|
@ -65,6 +70,9 @@ class Gem::Package::TarHeader
|
|||
'a8' + # devminor
|
||||
'a155' # prefix
|
||||
|
||||
##
|
||||
# Unpack format for a tar header
|
||||
|
||||
UNPACK_FORMAT = 'A100' + # name
|
||||
'A8' + # mode
|
||||
'A8' + # uid
|
||||
|
@ -84,6 +92,9 @@ class Gem::Package::TarHeader
|
|||
|
||||
attr_reader(*FIELDS)
|
||||
|
||||
##
|
||||
# Creates a tar header from IO +stream+
|
||||
|
||||
def self.from(stream)
|
||||
header = stream.read 512
|
||||
empty = (header == "\0" * 512)
|
||||
|
@ -147,6 +158,9 @@ class Gem::Package::TarHeader
|
|||
# :empty => empty
|
||||
end
|
||||
|
||||
##
|
||||
# Creates a new TarHeader using +vals+
|
||||
|
||||
def initialize(vals)
|
||||
unless vals[:name] && vals[:size] && vals[:prefix] && vals[:mode] then
|
||||
raise ArgumentError, ":name, :size, :prefix and :mode required"
|
||||
|
@ -171,11 +185,14 @@ class Gem::Package::TarHeader
|
|||
@empty = vals[:empty]
|
||||
end
|
||||
|
||||
##
|
||||
# Is the tar entry empty?
|
||||
|
||||
def empty?
|
||||
@empty
|
||||
end
|
||||
|
||||
def ==(other)
|
||||
def ==(other) # :nodoc:
|
||||
self.class === other and
|
||||
@checksum == other.checksum and
|
||||
@devmajor == other.devmajor and
|
||||
|
@ -195,11 +212,14 @@ class Gem::Package::TarHeader
|
|||
@version == other.version
|
||||
end
|
||||
|
||||
def to_s
|
||||
def to_s # :nodoc:
|
||||
update_checksum
|
||||
header
|
||||
end
|
||||
|
||||
##
|
||||
# Updates the TarHeader's checksum
|
||||
|
||||
def update_checksum
|
||||
header = header " " * 8
|
||||
@checksum = oct calculate_checksum(header), 6
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
# See LICENSE.txt for additional licensing information.
|
||||
#--
|
||||
|
||||
require 'rubygems/package'
|
||||
|
||||
class Gem::Package::TarInput
|
||||
|
||||
include Gem::Package::FSyncDir
|
||||
|
@ -72,9 +70,9 @@ class Gem::Package::TarInput
|
|||
# map trust policy from string to actual class (or a serialized YAML
|
||||
# file, if that exists)
|
||||
if String === security_policy then
|
||||
if Gem::Security::Policy.key? security_policy then
|
||||
if Gem::Security::Policies.key? security_policy then
|
||||
# load one of the pre-defined security policies
|
||||
security_policy = Gem::Security::Policy[security_policy]
|
||||
security_policy = Gem::Security::Policies[security_policy]
|
||||
elsif File.exist? security_policy then
|
||||
# FIXME: this doesn't work yet
|
||||
security_policy = YAML.load File.read(security_policy)
|
||||
|
@ -136,9 +134,9 @@ class Gem::Package::TarInput
|
|||
|
||||
def extract_entry(destdir, entry, expected_md5sum = nil)
|
||||
if entry.directory? then
|
||||
dest = File.join(destdir, entry.full_name)
|
||||
dest = File.join destdir, entry.full_name
|
||||
|
||||
if File.dir? dest then
|
||||
if File.directory? dest then
|
||||
@fileops.chmod entry.header.mode, dest, :verbose => false
|
||||
else
|
||||
@fileops.mkdir_p dest, :mode => entry.header.mode, :verbose => false
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
# See LICENSE.txt for additional licensing information.
|
||||
#--
|
||||
|
||||
require 'rubygems/package'
|
||||
|
||||
##
|
||||
# TarOutput is a wrapper to TarWriter that builds gem-format tar file.
|
||||
#
|
||||
|
@ -66,8 +64,10 @@ class Gem::Package::TarOutput
|
|||
Zlib::GzipWriter.wrap(sio || inner) do |os|
|
||||
|
||||
Gem::Package::TarWriter.new os do |data_tar_writer|
|
||||
# :stopdoc:
|
||||
def data_tar_writer.metadata() @metadata end
|
||||
def data_tar_writer.metadata=(metadata) @metadata = metadata end
|
||||
# :startdoc:
|
||||
|
||||
yield data_tar_writer
|
||||
|
||||
|
|
|
@ -3,14 +3,21 @@
|
|||
# See LICENSE.txt for additional licensing information.
|
||||
#--
|
||||
|
||||
require 'rubygems/package'
|
||||
##
|
||||
# TarReader reads tar files and allows iteration over their items
|
||||
|
||||
class Gem::Package::TarReader
|
||||
|
||||
include Gem::Package
|
||||
|
||||
##
|
||||
# Raised if the tar IO is not seekable
|
||||
|
||||
class UnexpectedEOF < StandardError; end
|
||||
|
||||
##
|
||||
# Creates a new TarReader on +io+ and yields it to the block, if given.
|
||||
|
||||
def self.new(io)
|
||||
reader = super
|
||||
|
||||
|
@ -25,14 +32,24 @@ class Gem::Package::TarReader
|
|||
nil
|
||||
end
|
||||
|
||||
##
|
||||
# Creates a new tar file reader on +io+ which needs to respond to #pos,
|
||||
# #eof?, #read, #getc and #pos=
|
||||
|
||||
def initialize(io)
|
||||
@io = io
|
||||
@init_pos = io.pos
|
||||
end
|
||||
|
||||
##
|
||||
# Close the tar file
|
||||
|
||||
def close
|
||||
end
|
||||
|
||||
##
|
||||
# Iterates over files in the tarball yielding each entry
|
||||
|
||||
def each
|
||||
loop do
|
||||
return if @io.eof?
|
||||
|
@ -84,3 +101,5 @@ class Gem::Package::TarReader
|
|||
|
||||
end
|
||||
|
||||
require 'rubygems/package/tar_reader/entry'
|
||||
|
||||
|
|
|
@ -3,12 +3,19 @@
|
|||
# See LICENSE.txt for additional licensing information.
|
||||
#--
|
||||
|
||||
require 'rubygems/package'
|
||||
##
|
||||
# Class for reading entries out of a tar file
|
||||
|
||||
class Gem::Package::TarReader::Entry
|
||||
|
||||
##
|
||||
# Header for this tar entry
|
||||
|
||||
attr_reader :header
|
||||
|
||||
##
|
||||
# Creates a new tar entry for +header+ that will be read from +io+
|
||||
|
||||
def initialize(header, io)
|
||||
@closed = false
|
||||
@header = header
|
||||
|
@ -21,24 +28,39 @@ class Gem::Package::TarReader::Entry
|
|||
raise IOError, "closed #{self.class}" if closed?
|
||||
end
|
||||
|
||||
##
|
||||
# Number of bytes read out of the tar entry
|
||||
|
||||
def bytes_read
|
||||
@read
|
||||
end
|
||||
|
||||
##
|
||||
# Closes the tar entry
|
||||
|
||||
def close
|
||||
@closed = true
|
||||
end
|
||||
|
||||
##
|
||||
# Is the tar entry closed?
|
||||
|
||||
def closed?
|
||||
@closed
|
||||
end
|
||||
|
||||
##
|
||||
# Are we at the end of the tar entry?
|
||||
|
||||
def eof?
|
||||
check_closed
|
||||
|
||||
@read >= @header.size
|
||||
end
|
||||
|
||||
##
|
||||
# Full name of the tar entry
|
||||
|
||||
def full_name
|
||||
if @header.prefix != "" then
|
||||
File.join @header.prefix, @header.name
|
||||
|
@ -47,6 +69,9 @@ class Gem::Package::TarReader::Entry
|
|||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Read one byte from the tar entry
|
||||
|
||||
def getc
|
||||
check_closed
|
||||
|
||||
|
@ -58,20 +83,33 @@ class Gem::Package::TarReader::Entry
|
|||
ret
|
||||
end
|
||||
|
||||
##
|
||||
# Is this tar entry a directory?
|
||||
|
||||
def directory?
|
||||
@header.typeflag == "5"
|
||||
end
|
||||
|
||||
##
|
||||
# Is this tar entry a file?
|
||||
|
||||
def file?
|
||||
@header.typeflag == "0"
|
||||
end
|
||||
|
||||
##
|
||||
# The position in the tar entry
|
||||
|
||||
def pos
|
||||
check_closed
|
||||
|
||||
bytes_read
|
||||
end
|
||||
|
||||
##
|
||||
# Reads +len+ bytes from the tar file entry, or the rest of the entry if
|
||||
# nil
|
||||
|
||||
def read(len = nil)
|
||||
check_closed
|
||||
|
||||
|
@ -86,6 +124,9 @@ class Gem::Package::TarReader::Entry
|
|||
ret
|
||||
end
|
||||
|
||||
##
|
||||
# Rewinds to the beginning of the tar file entry
|
||||
|
||||
def rewind
|
||||
check_closed
|
||||
|
||||
|
|
|
@ -3,15 +3,30 @@
|
|||
# See LICENSE.txt for additional licensing information.
|
||||
#--
|
||||
|
||||
require 'rubygems/package'
|
||||
##
|
||||
# Allows writing of tar files
|
||||
|
||||
class Gem::Package::TarWriter
|
||||
|
||||
class FileOverflow < StandardError; end
|
||||
|
||||
##
|
||||
# IO wrapper that allows writing a limited amount of data
|
||||
|
||||
class BoundedStream
|
||||
|
||||
attr_reader :limit, :written
|
||||
##
|
||||
# Maximum number of bytes that can be written
|
||||
|
||||
attr_reader :limit
|
||||
|
||||
##
|
||||
# Number of bytes written
|
||||
|
||||
attr_reader :written
|
||||
|
||||
##
|
||||
# Wraps +io+ and allows up to +limit+ bytes to be written
|
||||
|
||||
def initialize(io, limit)
|
||||
@io = io
|
||||
|
@ -19,6 +34,10 @@ class Gem::Package::TarWriter
|
|||
@written = 0
|
||||
end
|
||||
|
||||
##
|
||||
# Writes +data+ onto the IO, raising a FileOverflow exception if the
|
||||
# number of bytes will be more than #limit
|
||||
|
||||
def write(data)
|
||||
if data.size + @written > @limit
|
||||
raise FileOverflow, "You tried to feed more data than fits in the file."
|
||||
|
@ -30,18 +49,30 @@ class Gem::Package::TarWriter
|
|||
|
||||
end
|
||||
|
||||
##
|
||||
# IO wrapper that provides only #write
|
||||
|
||||
class RestrictedStream
|
||||
|
||||
##
|
||||
# Creates a new RestrictedStream wrapping +io+
|
||||
|
||||
def initialize(io)
|
||||
@io = io
|
||||
end
|
||||
|
||||
##
|
||||
# Writes +data+ onto the IO
|
||||
|
||||
def write(data)
|
||||
@io.write data
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
##
|
||||
# Creates a new TarWriter, yielding it if a block is given
|
||||
|
||||
def self.new(io)
|
||||
writer = super
|
||||
|
||||
|
@ -56,12 +87,19 @@ class Gem::Package::TarWriter
|
|||
nil
|
||||
end
|
||||
|
||||
##
|
||||
# Creates a new TarWriter that will write to +io+
|
||||
|
||||
def initialize(io)
|
||||
@io = io
|
||||
@closed = false
|
||||
end
|
||||
|
||||
def add_file(name, mode)
|
||||
##
|
||||
# Adds file +name+ with permissions +mode+, and yields an IO for writing the
|
||||
# file to
|
||||
|
||||
def add_file(name, mode) # :yields: io
|
||||
check_closed
|
||||
|
||||
raise Gem::Package::NonSeekableIO unless @io.respond_to? :pos=
|
||||
|
@ -90,7 +128,11 @@ class Gem::Package::TarWriter
|
|||
self
|
||||
end
|
||||
|
||||
def add_file_simple(name, mode, size)
|
||||
##
|
||||
# Add file +name+ with permissions +mode+ +size+ bytes long. Yields an IO
|
||||
# to write the file to.
|
||||
|
||||
def add_file_simple(name, mode, size) # :yields: io
|
||||
check_closed
|
||||
|
||||
name, prefix = split_name name
|
||||
|
@ -112,10 +154,16 @@ class Gem::Package::TarWriter
|
|||
self
|
||||
end
|
||||
|
||||
##
|
||||
# Raises IOError if the TarWriter is closed
|
||||
|
||||
def check_closed
|
||||
raise IOError, "closed #{self.class}" if closed?
|
||||
end
|
||||
|
||||
##
|
||||
# Closes the TarWriter
|
||||
|
||||
def close
|
||||
check_closed
|
||||
|
||||
|
@ -125,16 +173,25 @@ class Gem::Package::TarWriter
|
|||
@closed = true
|
||||
end
|
||||
|
||||
##
|
||||
# Is the TarWriter closed?
|
||||
|
||||
def closed?
|
||||
@closed
|
||||
end
|
||||
|
||||
##
|
||||
# Flushes the TarWriter's IO
|
||||
|
||||
def flush
|
||||
check_closed
|
||||
|
||||
@io.flush if @io.respond_to? :flush
|
||||
end
|
||||
|
||||
##
|
||||
# Creates a new directory in the tar file +name+ with +mode+
|
||||
|
||||
def mkdir(name, mode)
|
||||
check_closed
|
||||
|
||||
|
@ -149,6 +206,9 @@ class Gem::Package::TarWriter
|
|||
self
|
||||
end
|
||||
|
||||
##
|
||||
# Splits +name+ into a name and prefix that can fit in the TarHeader
|
||||
|
||||
def split_name(name) # :nodoc:
|
||||
raise Gem::Package::TooLongFileName if name.size > 256
|
||||
|
||||
|
|
118
lib/rubygems/package_task.rb
Normal file
118
lib/rubygems/package_task.rb
Normal file
|
@ -0,0 +1,118 @@
|
|||
# Copyright (c) 2003, 2004 Jim Weirich, 2009 Eric Hodel
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
require 'rubygems'
|
||||
begin
|
||||
gem 'rake'
|
||||
rescue Gem::LoadError
|
||||
end
|
||||
|
||||
require 'rake/packagetask'
|
||||
|
||||
##
|
||||
# Create a package based upon a Gem::Specification. Gem packages, as well as
|
||||
# zip files and tar/gzipped packages can be produced by this task.
|
||||
#
|
||||
# In addition to the Rake targets generated by Rake::PackageTask, a
|
||||
# Gem::PackageTask will also generate the following tasks:
|
||||
#
|
||||
# [<b>"<em>package_dir</em>/<em>name</em>-<em>version</em>.gem"</b>]
|
||||
# Create a RubyGems package with the given name and version.
|
||||
#
|
||||
# Example using a Gem::Specification:
|
||||
#
|
||||
# require 'rubygems'
|
||||
# require 'rubygems/package_task'
|
||||
#
|
||||
# spec = Gem::Specification.new do |s|
|
||||
# s.platform = Gem::Platform::RUBY
|
||||
# s.summary = "Ruby based make-like utility."
|
||||
# s.name = 'rake'
|
||||
# s.version = PKG_VERSION
|
||||
# s.requirements << 'none'
|
||||
# s.require_path = 'lib'
|
||||
# s.autorequire = 'rake'
|
||||
# s.files = PKG_FILES
|
||||
# s.description = <<-EOF
|
||||
# Rake is a Make-like program implemented in Ruby. Tasks
|
||||
# and dependencies are specified in standard Ruby syntax.
|
||||
# EOF
|
||||
# end
|
||||
#
|
||||
# Gem::PackageTask.new(spec) do |pkg|
|
||||
# pkg.need_zip = true
|
||||
# pkg.need_tar = true
|
||||
# end
|
||||
|
||||
class Gem::PackageTask < Rake::PackageTask
|
||||
|
||||
##
|
||||
# Ruby Gem::Specification containing the metadata for this package. The
|
||||
# name, version and package_files are automatically determined from the
|
||||
# gemspec and don't need to be explicitly provided.
|
||||
|
||||
attr_accessor :gem_spec
|
||||
|
||||
##
|
||||
# Create a Gem Package task library. Automatically define the gem if a
|
||||
# block is given. If no block is supplied, then #define needs to be called
|
||||
# to define the task.
|
||||
|
||||
def initialize(gem_spec)
|
||||
init gem_spec
|
||||
yield self if block_given?
|
||||
define if block_given?
|
||||
end
|
||||
|
||||
##
|
||||
# Initialization tasks without the "yield self" or define operations.
|
||||
|
||||
def init(gem)
|
||||
super gem.name, gem.version
|
||||
@gem_spec = gem
|
||||
@package_files += gem_spec.files if gem_spec.files
|
||||
end
|
||||
|
||||
##
|
||||
# Create the Rake tasks and actions specified by this Gem::PackageTask.
|
||||
# (+define+ is automatically called if a block is given to +new+).
|
||||
|
||||
def define
|
||||
super
|
||||
task :package => [:gem]
|
||||
desc "Build the gem file #{gem_file}"
|
||||
task :gem => ["#{package_dir}/#{gem_file}"]
|
||||
file "#{package_dir}/#{gem_file}" => [package_dir] + @gem_spec.files do
|
||||
when_writing("Creating #{gem_spec.full_name}.gem") {
|
||||
Gem::Builder.new(gem_spec).build
|
||||
verbose(true) {
|
||||
mv gem_file, "#{package_dir}/#{gem_file}"
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def gem_file
|
||||
"#{@gem_spec.full_name}.gem"
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -1,5 +1,3 @@
|
|||
require 'rubygems'
|
||||
|
||||
##
|
||||
# Available list of platforms for targeting Gem installations.
|
||||
|
||||
|
@ -106,6 +104,10 @@ class Gem::Platform
|
|||
to_a.compact.join '-'
|
||||
end
|
||||
|
||||
def empty?
|
||||
to_s.empty?
|
||||
end
|
||||
|
||||
##
|
||||
# Is +other+ equal to this platform? Two platforms are equal if they have
|
||||
# the same CPU, OS and version.
|
||||
|
|
|
@ -55,7 +55,7 @@ class Gem::RemoteFetcher
|
|||
# HTTP_PROXY_PASS)
|
||||
# * <tt>:no_proxy</tt>: ignore environment variables and _don't_ use a proxy
|
||||
|
||||
def initialize(proxy)
|
||||
def initialize(proxy = nil)
|
||||
Socket.do_not_reverse_lookup = true
|
||||
|
||||
@connections = {}
|
||||
|
@ -86,7 +86,11 @@ class Gem::RemoteFetcher
|
|||
|
||||
FileUtils.mkdir_p cache_dir rescue nil unless File.exist? cache_dir
|
||||
|
||||
source_uri = URI.parse source_uri unless URI::Generic === source_uri
|
||||
# Always escape URI's to deal with potential spaces and such
|
||||
unless URI::Generic === source_uri
|
||||
source_uri = URI.parse(URI.escape(source_uri))
|
||||
end
|
||||
|
||||
scheme = source_uri.scheme
|
||||
|
||||
# URI.parse gets confused by MS Windows paths with forward slashes.
|
||||
|
@ -101,7 +105,7 @@ class Gem::RemoteFetcher
|
|||
|
||||
remote_gem_path = source_uri + "gems/#{gem_file_name}"
|
||||
|
||||
gem = Gem::RemoteFetcher.fetcher.fetch_path remote_gem_path
|
||||
gem = self.fetch_path remote_gem_path
|
||||
rescue Gem::RemoteFetcher::FetchError
|
||||
raise if spec.original_platform == spec.platform
|
||||
|
||||
|
@ -112,16 +116,34 @@ class Gem::RemoteFetcher
|
|||
|
||||
remote_gem_path = source_uri + "gems/#{alternate_name}"
|
||||
|
||||
gem = Gem::RemoteFetcher.fetcher.fetch_path remote_gem_path
|
||||
gem = self.fetch_path remote_gem_path
|
||||
end
|
||||
|
||||
File.open local_gem_path, 'wb' do |fp|
|
||||
fp.write gem
|
||||
end
|
||||
end
|
||||
when nil, 'file' then # TODO test for local overriding cache
|
||||
when 'file' then
|
||||
begin
|
||||
FileUtils.cp source_uri.to_s, local_gem_path
|
||||
path = source_uri.path
|
||||
path = File.dirname(path) if File.extname(path) == '.gem'
|
||||
|
||||
remote_gem_path = File.join(path, 'gems', gem_file_name)
|
||||
|
||||
FileUtils.cp(remote_gem_path, local_gem_path)
|
||||
rescue Errno::EACCES
|
||||
local_gem_path = source_uri.to_s
|
||||
end
|
||||
|
||||
say "Using local gem #{local_gem_path}" if
|
||||
Gem.configuration.really_verbose
|
||||
when nil then # TODO test for local overriding cache
|
||||
begin
|
||||
if Gem.win_platform? && source_uri.scheme && !source_uri.path.include?(':')
|
||||
FileUtils.cp URI.unescape(source_uri.scheme + ':' + source_uri.path), local_gem_path
|
||||
else
|
||||
FileUtils.cp URI.unescape(source_uri.path), local_gem_path
|
||||
end
|
||||
rescue Errno::EACCES
|
||||
local_gem_path = source_uri.to_s
|
||||
end
|
||||
|
@ -177,7 +199,7 @@ class Gem::RemoteFetcher
|
|||
|
||||
return nil if env_proxy.nil? or env_proxy.empty?
|
||||
|
||||
uri = URI.parse env_proxy
|
||||
uri = URI.parse(normalize_uri(env_proxy))
|
||||
|
||||
if uri and uri.user.nil? and uri.password.nil? then
|
||||
# Probably we have http_proxy_* variables?
|
||||
|
@ -233,10 +255,25 @@ class Gem::RemoteFetcher
|
|||
def open_uri_or_path(uri, last_modified = nil, head = false, depth = 0)
|
||||
raise "block is dead" if block_given?
|
||||
|
||||
return open(get_file_uri_path(uri)) if file_uri? uri
|
||||
|
||||
uri = URI.parse uri unless URI::Generic === uri
|
||||
raise ArgumentError, 'uri is not an HTTP URI' unless URI::HTTP === uri
|
||||
|
||||
# This check is redundant unless Gem::RemoteFetcher is likely
|
||||
# to be used directly, since the scheme is checked elsewhere.
|
||||
# - Daniel Berger
|
||||
unless ['http', 'https', 'file'].include?(uri.scheme)
|
||||
raise ArgumentError, 'uri scheme is invalid'
|
||||
end
|
||||
|
||||
if uri.scheme == 'file'
|
||||
path = uri.path
|
||||
|
||||
# Deal with leading slash on Windows paths
|
||||
if path[0].chr == '/' && path[1].chr =~ /[a-zA-Z]/ && path[2].chr == ':'
|
||||
path = path[1..-1]
|
||||
end
|
||||
|
||||
return Gem.read_binary(path)
|
||||
end
|
||||
|
||||
fetch_type = head ? Net::HTTP::Head : Net::HTTP::Get
|
||||
response = request uri, fetch_type, last_modified
|
||||
|
@ -326,19 +363,5 @@ class Gem::RemoteFetcher
|
|||
connection.start
|
||||
end
|
||||
|
||||
##
|
||||
# Checks if the provided string is a file:// URI.
|
||||
|
||||
def file_uri?(uri)
|
||||
uri =~ %r{\Afile://}
|
||||
end
|
||||
|
||||
##
|
||||
# Given a file:// URI, returns its local path.
|
||||
|
||||
def get_file_uri_path(uri)
|
||||
uri.sub(%r{\Afile://}, '')
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
module Gem
|
||||
module RequirePathsBuilder
|
||||
require 'rubygems'
|
||||
|
||||
module Gem::RequirePathsBuilder
|
||||
def write_require_paths_file_if_needed(spec = @spec, gem_home = @gem_home)
|
||||
return if spec.require_paths == ["lib"] && (spec.bindir.nil? || spec.bindir == "bin")
|
||||
return if spec.require_paths == ["lib"] &&
|
||||
(spec.bindir.nil? || spec.bindir == "bin")
|
||||
file_name = File.join(gem_home, 'gems', "#{@spec.full_name}", ".require_paths")
|
||||
file_name.untaint
|
||||
File.open(file_name, "w") do |file|
|
||||
|
@ -12,4 +14,4 @@ module Gem
|
|||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
# See LICENSE.txt for permissions.
|
||||
#++
|
||||
|
||||
require 'rubygems/version'
|
||||
|
||||
##
|
||||
# Requirement version includes a prefaced comparator in addition
|
||||
# to a version number.
|
||||
|
@ -26,10 +24,10 @@ class Gem::Requirement
|
|||
"<" => lambda { |v, r| v < r },
|
||||
">=" => lambda { |v, r| v >= r },
|
||||
"<=" => lambda { |v, r| v <= r },
|
||||
"~>" => lambda { |v, r| v >= r && v < r.bump }
|
||||
"~>" => lambda { |v, r| v = v.release; v >= r && v < r.bump }
|
||||
}
|
||||
|
||||
OP_RE = /#{OPS.keys.map{ |k| Regexp.quote k }.join '|'}/o
|
||||
OP_RE = OPS.keys.map{ |k| Regexp.quote k }.join '|'
|
||||
|
||||
##
|
||||
# Factory method to create a Gem::Requirement object. Input may be a
|
||||
|
@ -65,7 +63,7 @@ class Gem::Requirement
|
|||
|
||||
##
|
||||
# Constructs a Requirement from +requirements+ which can be a String, a
|
||||
# Gem::Version, or an Array of those. See parse for details on the
|
||||
# Gem::Version, or an Array of those. See #parse for details on the
|
||||
# formatting of requirement strings.
|
||||
|
||||
def initialize(requirements)
|
||||
|
@ -99,11 +97,15 @@ class Gem::Requirement
|
|||
as_list.join(", ")
|
||||
end
|
||||
|
||||
def pretty_print(q) # :nodoc:
|
||||
q.group 1, 'Gem::Requirement.new(', ')' do
|
||||
q.pp as_list
|
||||
end
|
||||
end
|
||||
|
||||
def as_list
|
||||
normalize
|
||||
@requirements.collect { |req|
|
||||
"#{req[0]} #{req[1]}"
|
||||
}
|
||||
@requirements.map do |op, version| "#{op} #{version}" end
|
||||
end
|
||||
|
||||
def normalize
|
||||
|
@ -129,18 +131,23 @@ class Gem::Requirement
|
|||
OPS[op].call(version, required_version)
|
||||
end
|
||||
|
||||
def prerelease?
|
||||
# TODO: why is @requirements a nested array?
|
||||
@requirements.any?{ |r| r[1].prerelease? }
|
||||
end
|
||||
|
||||
##
|
||||
# Parse the version requirement obj returning the operator and version.
|
||||
#
|
||||
# The requirement can be a String or a Gem::Version. A String can be an
|
||||
# operator (<, <=, =, =>, >, !=, ~>), a version number, or both, operator
|
||||
# operator (<, <=, =, >=, >, !=, ~>), a version number, or both, operator
|
||||
# first.
|
||||
|
||||
def parse(obj)
|
||||
case obj
|
||||
when /^\s*(#{OP_RE})\s*([0-9.]+)\s*$/o then
|
||||
when /^\s*(#{OP_RE})\s*(#{Gem::Version::VERSION_PATTERN})\s*$/o then
|
||||
[$1, Gem::Version.new($2)]
|
||||
when /^\s*([0-9.]+)\s*$/ then
|
||||
when /^\s*(#{Gem::Version::VERSION_PATTERN})\s*$/o then
|
||||
['=', Gem::Version.new($1)]
|
||||
when /^\s*(#{OP_RE})\s*$/o then
|
||||
[$1, Gem::Version.new('0')]
|
||||
|
|
|
@ -1,6 +1,19 @@
|
|||
#--
|
||||
# DO NOT EDIT
|
||||
# This file is auto-generated by build scripts.
|
||||
# See: rake update_version
|
||||
#++
|
||||
|
||||
module Gem
|
||||
RubyGemsVersion = '1.3.1'
|
||||
|
||||
##
|
||||
# The version of RubyGems you are using
|
||||
|
||||
RubyGemsVersion = '1.3.4'
|
||||
|
||||
##
|
||||
# The version of RubyGems you are using (duplicated for familiarity)
|
||||
|
||||
VERSION = RubyGemsVersion
|
||||
|
||||
end
|
||||
|
|
|
@ -17,6 +17,7 @@ require 'rubygems/doc_manager'
|
|||
# name/version/platform index
|
||||
# * "/quick/" - Individual gemspecs
|
||||
# * "/gems" - Direct access to download the installable gems
|
||||
# * "/rdoc?q=" - Search for installed rdoc documentation
|
||||
# * legacy indexes:
|
||||
# * "/Marshal.#{Gem.marshal_version}" - Full SourceIndex dump of metadata
|
||||
# for installed gems
|
||||
|
@ -32,9 +33,20 @@ require 'rubygems/doc_manager'
|
|||
|
||||
class Gem::Server
|
||||
|
||||
include ERB::Util
|
||||
include Gem::UserInteraction
|
||||
|
||||
DOC_TEMPLATE = <<-'WEBPAGE'
|
||||
SEARCH = <<-SEARCH
|
||||
<form class="headerSearch" name="headerSearchForm" method="get" action="/rdoc">
|
||||
<div id="search" style="float:right">
|
||||
<span>Filter/Search</span>
|
||||
<input id="q" type="text" style="width:10em" name="q"/>
|
||||
<button type="submit" style="display:none" />
|
||||
</div>
|
||||
</form>
|
||||
SEARCH
|
||||
|
||||
DOC_TEMPLATE = <<-'DOC_TEMPLATE'
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!DOCTYPE html
|
||||
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
|
@ -47,6 +59,7 @@ class Gem::Server
|
|||
</head>
|
||||
<body>
|
||||
<div id="fileHeader">
|
||||
<%= SEARCH %>
|
||||
<h1>RubyGems Documentation Index</h1>
|
||||
</div>
|
||||
<!-- banner header -->
|
||||
|
@ -114,10 +127,10 @@ class Gem::Server
|
|||
</div>
|
||||
</body>
|
||||
</html>
|
||||
WEBPAGE
|
||||
DOC_TEMPLATE
|
||||
|
||||
# CSS is copy & paste from rdoc-style.css, RDoc V1.0.1 - 20041108
|
||||
RDOC_CSS = <<-RDOCCSS
|
||||
RDOC_CSS = <<-RDOC_CSS
|
||||
body {
|
||||
font-family: Verdana,Arial,Helvetica,sans-serif;
|
||||
font-size: 90%;
|
||||
|
@ -325,7 +338,92 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
|||
.ruby-comment { color: #b22222; font-weight: bold; background: transparent; }
|
||||
.ruby-regexp { color: #ffa07a; background: transparent; }
|
||||
.ruby-value { color: #7fffd4; background: transparent; }
|
||||
RDOCCSS
|
||||
RDOC_CSS
|
||||
|
||||
RDOC_NO_DOCUMENTATION = <<-'NO_DOC'
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<title>Found documentation</title>
|
||||
<link rel="stylesheet" href="gem-server-rdoc-style.css" type="text/css" media="screen" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="fileHeader">
|
||||
<%= SEARCH %>
|
||||
<h1>No documentation found</h1>
|
||||
</div>
|
||||
|
||||
<div id="bodyContent">
|
||||
<div id="contextContent">
|
||||
<div id="description">
|
||||
<p>No gems matched <%= h query.inspect %></p>
|
||||
|
||||
<p>
|
||||
Back to <a href="/">complete gem index</a>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="validator-badges">
|
||||
<p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
NO_DOC
|
||||
|
||||
RDOC_SEARCH_TEMPLATE = <<-'RDOC_SEARCH'
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<title>Found documentation</title>
|
||||
<link rel="stylesheet" href="gem-server-rdoc-style.css" type="text/css" media="screen" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="fileHeader">
|
||||
<%= SEARCH %>
|
||||
<h1>Found documentation</h1>
|
||||
</div>
|
||||
<!-- banner header -->
|
||||
|
||||
<div id="bodyContent">
|
||||
<div id="contextContent">
|
||||
<div id="description">
|
||||
<h1>Summary</h1>
|
||||
<p><%=doc_items.length%> documentation topics found.</p>
|
||||
<h1>Topics</h1>
|
||||
|
||||
<dl>
|
||||
<% doc_items.each do |doc_item| %>
|
||||
<dt>
|
||||
<b><%=doc_item[:name]%></b>
|
||||
<a href="<%=doc_item[:url]%>">[rdoc]</a>
|
||||
</dt>
|
||||
<dd>
|
||||
<%=doc_item[:summary]%>
|
||||
<br/>
|
||||
<br/>
|
||||
</dd>
|
||||
<% end %>
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
Back to <a href="/">complete gem index</a>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="validator-badges">
|
||||
<p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
RDOC_SEARCH
|
||||
|
||||
def self.run(options)
|
||||
new(options[:gemdir], options[:port], options[:daemon]).run
|
||||
|
@ -533,6 +631,90 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
|||
res.body = result
|
||||
end
|
||||
|
||||
##
|
||||
# Can be used for quick navigation to the rdoc documentation. You can then
|
||||
# define a search shortcut for your browser. E.g. in Firefox connect
|
||||
# 'shortcut:rdoc' to http://localhost:8808/rdoc?q=%s template. Then you can
|
||||
# directly open the ActionPack documentation by typing 'rdoc actionp'. If
|
||||
# there are multiple hits for the search term, they are presented as a list
|
||||
# with links.
|
||||
#
|
||||
# Search algorithm aims for an intuitive search:
|
||||
# 1. first try to find the gems and documentation folders which name
|
||||
# starts with the search term
|
||||
# 2. search for entries, that *contain* the search term
|
||||
# 3. show all the gems
|
||||
#
|
||||
# If there is only one search hit, user is immediately redirected to the
|
||||
# documentation for the particular gem, otherwise a list with results is
|
||||
# shown.
|
||||
#
|
||||
# === Additional trick - install documentation for ruby core
|
||||
#
|
||||
# Note: please adjust paths accordingly use for example 'locate yaml.rb' and
|
||||
# 'gem environment' to identify directories, that are specific for your
|
||||
# local installation
|
||||
#
|
||||
# 1. install ruby sources
|
||||
# cd /usr/src
|
||||
# sudo apt-get source ruby
|
||||
#
|
||||
# 2. generate documentation
|
||||
# rdoc -o /usr/lib/ruby/gems/1.8/doc/core/rdoc \
|
||||
# /usr/lib/ruby/1.8 ruby1.8-1.8.7.72
|
||||
#
|
||||
# By typing 'rdoc core' you can now access the core documentation
|
||||
|
||||
def rdoc(req, res)
|
||||
query = req.query['q']
|
||||
show_rdoc_for_pattern("#{query}*", res) && return
|
||||
show_rdoc_for_pattern("*#{query}*", res) && return
|
||||
|
||||
template = ERB.new RDOC_NO_DOCUMENTATION
|
||||
|
||||
res['content-type'] = 'text/html'
|
||||
res.body = template.result binding
|
||||
end
|
||||
|
||||
##
|
||||
# Returns true and prepares http response, if rdoc for the requested gem
|
||||
# name pattern was found.
|
||||
#
|
||||
# The search is based on the file system content, not on the gems metadata.
|
||||
# This allows additional documentation folders like 'core' for the ruby core
|
||||
# documentation - just put it underneath the main doc folder.
|
||||
|
||||
def show_rdoc_for_pattern(pattern, res)
|
||||
found_gems = Dir.glob("#{@gem_dir}/doc/#{pattern}").select {|path|
|
||||
File.exist? File.join(path, 'rdoc/index.html')
|
||||
}
|
||||
case found_gems.length
|
||||
when 0
|
||||
return false
|
||||
when 1
|
||||
new_path = File.basename(found_gems[0])
|
||||
res.status = 302
|
||||
res['Location'] = "/doc_root/#{new_path}/rdoc/index.html"
|
||||
return true
|
||||
else
|
||||
doc_items = []
|
||||
found_gems.each do |file_name|
|
||||
base_name = File.basename(file_name)
|
||||
doc_items << {
|
||||
:name => base_name,
|
||||
:url => "/doc_root/#{base_name}/rdoc/index.html",
|
||||
:summary => ''
|
||||
}
|
||||
end
|
||||
|
||||
template = ERB.new(RDOC_SEARCH_TEMPLATE)
|
||||
res['content-type'] = 'text/html'
|
||||
result = template.result binding
|
||||
res.body = result
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
def run
|
||||
@server.listen nil, @port
|
||||
|
||||
|
@ -564,6 +746,8 @@ div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
|||
|
||||
@server.mount_proc "/", method(:root)
|
||||
|
||||
@server.mount_proc "/rdoc", method(:rdoc)
|
||||
|
||||
paths = { "/gems" => "/cache/", "/doc_root" => "/doc/" }
|
||||
paths.each do |mount_point, mount_dir|
|
||||
@server.mount(mount_point, WEBrick::HTTPServlet::FileHandler,
|
||||
|
|
|
@ -4,12 +4,14 @@
|
|||
# See LICENSE.txt for permissions.
|
||||
#++
|
||||
|
||||
require 'rubygems'
|
||||
require 'rubygems/user_interaction'
|
||||
require 'rubygems/specification'
|
||||
|
||||
# :stopdoc:
|
||||
module Gem
|
||||
autoload(:SpecFetcher, 'rubygems/spec_fetcher')
|
||||
autoload :SpecFetcher, 'rubygems/spec_fetcher'
|
||||
end
|
||||
# :startdoc:
|
||||
|
||||
##
|
||||
# The SourceIndex object indexes all the gems available from a
|
||||
|
@ -28,7 +30,7 @@ class Gem::SourceIndex
|
|||
|
||||
include Gem::UserInteraction
|
||||
|
||||
attr_reader :gems # :nodoc:
|
||||
attr_reader :gems, :prerelease_gems # :nodoc:
|
||||
|
||||
##
|
||||
# Directories to use to refresh this SourceIndex when calling refresh!
|
||||
|
@ -81,13 +83,15 @@ class Gem::SourceIndex
|
|||
# loaded spec.
|
||||
|
||||
def load_specification(file_name)
|
||||
begin
|
||||
return nil unless file_name and File.exist? file_name
|
||||
|
||||
spec_code = if RUBY_VERSION < '1.9' then
|
||||
File.read file_name
|
||||
else
|
||||
File.read file_name, :encoding => 'UTF-8'
|
||||
end.untaint
|
||||
|
||||
begin
|
||||
gemspec = eval spec_code, binding, file_name
|
||||
|
||||
if gemspec.is_a?(Gem::Specification)
|
||||
|
@ -104,23 +108,32 @@ class Gem::SourceIndex
|
|||
alert_warning "#{e.inspect}\n#{spec_code}"
|
||||
alert_warning "Invalid .gemspec format in '#{file_name}'"
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
##
|
||||
# Constructs a source index instance from the provided
|
||||
# specifications
|
||||
#
|
||||
# specifications::
|
||||
# [Hash] hash of [Gem name, Gem::Specification] pairs
|
||||
# Constructs a source index instance from the provided specifications, which
|
||||
# is a Hash of gem full names and Gem::Specifications.
|
||||
#--
|
||||
# TODO merge @gems and @prerelease_gems and provide a separate method
|
||||
# #prerelease_gems
|
||||
|
||||
def initialize(specifications={})
|
||||
@gems = specifications
|
||||
@gems, @prerelease_gems = [{}, {}]
|
||||
specifications.each{ |full_name, spec| add_spec spec }
|
||||
@spec_dirs = nil
|
||||
end
|
||||
|
||||
##
|
||||
# Both regular and prerelease gems
|
||||
|
||||
def all_gems
|
||||
@gems.merge @prerelease_gems
|
||||
end
|
||||
|
||||
##
|
||||
# Reconstruct the source index from the specifications in +spec_dirs+.
|
||||
|
||||
|
@ -170,14 +183,29 @@ class Gem::SourceIndex
|
|||
result[name] << spec
|
||||
end
|
||||
|
||||
# TODO: why is this a hash while @gems is an array? Seems like
|
||||
# structural similarity would be good.
|
||||
result.values.flatten
|
||||
end
|
||||
|
||||
##
|
||||
# An array including only the prerelease gemspecs
|
||||
|
||||
def prerelease_specs
|
||||
@prerelease_gems.values
|
||||
end
|
||||
|
||||
##
|
||||
# Add a gem specification to the source index.
|
||||
|
||||
def add_spec(gem_spec)
|
||||
@gems[gem_spec.full_name] = gem_spec
|
||||
def add_spec(gem_spec, name = gem_spec.full_name)
|
||||
# No idea why, but the Indexer wants to insert them using original_name
|
||||
# instead of full_name. So we make it an optional arg.
|
||||
if gem_spec.version.prerelease?
|
||||
@prerelease_gems[name] = gem_spec
|
||||
else
|
||||
@gems[name] = gem_spec
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -193,7 +221,11 @@ class Gem::SourceIndex
|
|||
# Remove a gem specification named +full_name+.
|
||||
|
||||
def remove_spec(full_name)
|
||||
@gems.delete(full_name)
|
||||
if @gems.key? full_name then
|
||||
@gems.delete full_name
|
||||
else
|
||||
@prerelease_gems.delete full_name
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -215,18 +247,18 @@ class Gem::SourceIndex
|
|||
# change in the index.
|
||||
|
||||
def index_signature
|
||||
require 'rubygems/digest/sha2'
|
||||
require 'digest'
|
||||
|
||||
Gem::SHA256.new.hexdigest(@gems.keys.sort.join(',')).to_s
|
||||
Digest::SHA256.new.hexdigest(@gems.keys.sort.join(',')).to_s
|
||||
end
|
||||
|
||||
##
|
||||
# The signature for the given gem specification.
|
||||
|
||||
def gem_signature(gem_full_name)
|
||||
require 'rubygems/digest/sha2'
|
||||
require 'digest'
|
||||
|
||||
Gem::SHA256.new.hexdigest(@gems[gem_full_name].to_yaml).to_s
|
||||
Digest::SHA256.new.hexdigest(@gems[gem_full_name].to_yaml).to_s
|
||||
end
|
||||
|
||||
def size
|
||||
|
@ -238,7 +270,7 @@ class Gem::SourceIndex
|
|||
# Find a gem by an exact match on the short name.
|
||||
|
||||
def find_name(gem_name, version_requirement = Gem::Requirement.default)
|
||||
dep = Gem::Dependency.new(/^#{gem_name}$/, version_requirement)
|
||||
dep = Gem::Dependency.new gem_name, version_requirement
|
||||
search dep
|
||||
end
|
||||
|
||||
|
@ -257,7 +289,7 @@ class Gem::SourceIndex
|
|||
|
||||
# TODO - Remove support and warning for legacy arguments after 2008/11
|
||||
unless Gem::Dependency === gem_pattern
|
||||
warn "#{Gem.location_of_caller.join ':'}:Warning: Gem::SourceIndex#search support for #{gem_pattern.class} patterns is deprecated"
|
||||
warn "#{Gem.location_of_caller.join ':'}:Warning: Gem::SourceIndex#search support for #{gem_pattern.class} patterns is deprecated, use #find_name"
|
||||
end
|
||||
|
||||
case gem_pattern
|
||||
|
@ -282,7 +314,7 @@ class Gem::SourceIndex
|
|||
version_requirement = Gem::Requirement.create version_requirement
|
||||
end
|
||||
|
||||
specs = @gems.values.select do |spec|
|
||||
specs = all_gems.values.select do |spec|
|
||||
spec.name =~ gem_pattern and
|
||||
version_requirement.satisfied_by? spec.version
|
||||
end
|
||||
|
@ -545,15 +577,15 @@ class Gem::SourceIndex
|
|||
|
||||
end
|
||||
|
||||
# :stopdoc:
|
||||
module Gem
|
||||
|
||||
# :stopdoc:
|
||||
|
||||
##
|
||||
# Cache is an alias for SourceIndex to allow older YAMLized source index
|
||||
# objects to load properly.
|
||||
|
||||
Cache = SourceIndex
|
||||
|
||||
end
|
||||
# :startdoc:
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -13,8 +13,8 @@ class Gem::SourceInfoCacheEntry
|
|||
attr_reader :source_index
|
||||
|
||||
##
|
||||
# The size of the of the source entry. Used to determine if the
|
||||
# source index has changed.
|
||||
# The size of the source entry. Used to determine if the source index has
|
||||
# changed.
|
||||
|
||||
attr_reader :size
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
require 'zlib'
|
||||
require 'fileutils'
|
||||
|
||||
require 'rubygems'
|
||||
require 'rubygems/remote_fetcher'
|
||||
require 'rubygems/user_interaction'
|
||||
|
||||
|
@ -26,6 +26,11 @@ class Gem::SpecFetcher
|
|||
|
||||
attr_reader :specs # :nodoc:
|
||||
|
||||
##
|
||||
# Cache of prerelease specs
|
||||
|
||||
attr_reader :prerelease_specs # :nodoc:
|
||||
|
||||
@fetcher = nil
|
||||
|
||||
def self.fetcher
|
||||
|
@ -42,6 +47,7 @@ class Gem::SpecFetcher
|
|||
|
||||
@specs = {}
|
||||
@latest_specs = {}
|
||||
@prerelease_specs = {}
|
||||
|
||||
@fetcher = Gem::RemoteFetcher.fetcher
|
||||
end
|
||||
|
@ -56,10 +62,10 @@ class Gem::SpecFetcher
|
|||
##
|
||||
# Fetch specs matching +dependency+. If +all+ is true, all matching
|
||||
# versions are returned. If +matching_platform+ is false, all platforms are
|
||||
# returned.
|
||||
# returned. If +prerelease+ is true, prerelease versions are included.
|
||||
|
||||
def fetch(dependency, all = false, matching_platform = true)
|
||||
specs_and_sources = find_matching dependency, all, matching_platform
|
||||
def fetch(dependency, all = false, matching_platform = true, prerelease = false)
|
||||
specs_and_sources = find_matching dependency, all, matching_platform, prerelease
|
||||
|
||||
specs_and_sources.map do |spec_tuple, source_uri|
|
||||
[fetch_spec(spec_tuple, URI.parse(source_uri)), source_uri]
|
||||
|
@ -110,10 +116,10 @@ class Gem::SpecFetcher
|
|||
# versions are returned. If +matching_platform+ is false, gems for all
|
||||
# platforms are returned.
|
||||
|
||||
def find_matching(dependency, all = false, matching_platform = true)
|
||||
def find_matching(dependency, all = false, matching_platform = true, prerelease = false)
|
||||
found = {}
|
||||
|
||||
list(all).each do |source_uri, specs|
|
||||
list(all, prerelease).each do |source_uri, specs|
|
||||
found[source_uri] = specs.select do |spec_name, version, spec_platform|
|
||||
dependency =~ Gem::Dependency.new(spec_name, version) and
|
||||
(not matching_platform or Gem::Platform.match(spec_platform))
|
||||
|
@ -155,28 +161,37 @@ class Gem::SpecFetcher
|
|||
|
||||
##
|
||||
# Returns a list of gems available for each source in Gem::sources. If
|
||||
# +all+ is true, all versions are returned instead of only latest versions.
|
||||
# +all+ is true, all versions are returned instead of only latest
|
||||
# versions. If +prerelease+ is true, include prerelease versions.
|
||||
|
||||
def list(all = false, prerelease = false)
|
||||
# TODO: make type the only argument
|
||||
type = if all
|
||||
:all
|
||||
elsif prerelease
|
||||
:prerelease
|
||||
else
|
||||
:latest
|
||||
end
|
||||
|
||||
def list(all = false)
|
||||
list = {}
|
||||
|
||||
file = all ? 'specs' : 'latest_specs'
|
||||
file = { :latest => 'latest_specs',
|
||||
:prerelease => 'prerelease_specs',
|
||||
:all => 'specs' }[type]
|
||||
|
||||
cache = { :latest => @latest_specs,
|
||||
:prerelease => @prerelease_specs,
|
||||
:all => @specs }[type]
|
||||
|
||||
Gem.sources.each do |source_uri|
|
||||
source_uri = URI.parse source_uri
|
||||
|
||||
if all and @specs.include? source_uri then
|
||||
list[source_uri] = @specs[source_uri]
|
||||
elsif not all and @latest_specs.include? source_uri then
|
||||
list[source_uri] = @latest_specs[source_uri]
|
||||
else
|
||||
specs = load_specs source_uri, file
|
||||
|
||||
cache = all ? @specs : @latest_specs
|
||||
|
||||
cache[source_uri] = specs
|
||||
list[source_uri] = specs
|
||||
unless cache.include? source_uri
|
||||
cache[source_uri] = load_specs source_uri, file
|
||||
end
|
||||
|
||||
list[source_uri] = cache[source_uri]
|
||||
end
|
||||
|
||||
list
|
||||
|
@ -206,7 +221,14 @@ class Gem::SpecFetcher
|
|||
loaded = true
|
||||
end
|
||||
|
||||
specs = Marshal.load spec_dump
|
||||
specs = begin
|
||||
Marshal.load spec_dump
|
||||
rescue ArgumentError
|
||||
spec_dump = @fetcher.fetch_path spec_path
|
||||
loaded = true
|
||||
|
||||
Marshal.load spec_dump
|
||||
end
|
||||
|
||||
if loaded and @update_cache then
|
||||
begin
|
||||
|
|
|
@ -4,29 +4,15 @@
|
|||
# See LICENSE.txt for permissions.
|
||||
#++
|
||||
|
||||
require 'rubygems'
|
||||
require 'rubygems/version'
|
||||
require 'rubygems/requirement'
|
||||
require 'rubygems/platform'
|
||||
|
||||
# :stopdoc:
|
||||
# Time::today has been deprecated in 0.9.5 and will be removed.
|
||||
if RUBY_VERSION < '1.9' then
|
||||
def Time.today
|
||||
t = Time.now
|
||||
t - ((t.to_f + t.gmt_offset) % 86400)
|
||||
end unless defined? Time.today
|
||||
end
|
||||
|
||||
class Date; end # for ruby_code if date.rb wasn't required
|
||||
|
||||
# :startdoc:
|
||||
|
||||
module Gem
|
||||
|
||||
##
|
||||
# == Gem::Specification
|
||||
#
|
||||
# The Specification class contains the metadata for a Gem. Typically
|
||||
# defined in a .gemspec file or a Rakefile, and looks like this:
|
||||
#
|
||||
|
@ -37,10 +23,9 @@ module Gem
|
|||
# ...
|
||||
# end
|
||||
#
|
||||
# There are many <em>gemspec attributes</em>, and the best place to learn
|
||||
# about them in the "Gemspec Reference" linked from the RubyGems wiki.
|
||||
# For a great way to package gems, use Hoe.
|
||||
|
||||
class Specification
|
||||
class Gem::Specification
|
||||
|
||||
##
|
||||
# Allows deinstallation of gems with legacy platforms.
|
||||
|
@ -62,7 +47,7 @@ module Gem
|
|||
#
|
||||
# NOTE RubyGems < 1.2 cannot load specification versions > 2.
|
||||
|
||||
CURRENT_SPECIFICATION_VERSION = 2
|
||||
CURRENT_SPECIFICATION_VERSION = 3
|
||||
|
||||
##
|
||||
# An informal list of changes to the specification. The highest-valued
|
||||
|
@ -78,20 +63,18 @@ module Gem
|
|||
'Added "required_rubygems_version"',
|
||||
'Now forward-compatible with future versions',
|
||||
],
|
||||
3 => [
|
||||
'Added Fixnum validation to the specification_version'
|
||||
]
|
||||
}
|
||||
|
||||
# :stopdoc:
|
||||
MARSHAL_FIELDS = { -1 => 16, 1 => 16, 2 => 16 }
|
||||
MARSHAL_FIELDS = { -1 => 16, 1 => 16, 2 => 16, 3 => 17 }
|
||||
|
||||
now = Time.at(Time.now.to_i)
|
||||
TODAY = now - ((now.to_i + now.gmt_offset) % 86400)
|
||||
# :startdoc:
|
||||
|
||||
##
|
||||
# List of Specification instances.
|
||||
|
||||
@@list = []
|
||||
|
||||
##
|
||||
# Optional block used to gather newly defined instances.
|
||||
|
||||
|
@ -99,6 +82,7 @@ module Gem
|
|||
|
||||
##
|
||||
# List of attribute names: [:name, :version, ...]
|
||||
|
||||
@@required_attributes = []
|
||||
|
||||
##
|
||||
|
@ -165,14 +149,6 @@ module Gem
|
|||
@@array_attributes.dup
|
||||
end
|
||||
|
||||
##
|
||||
# A list of Specification instances that have been defined in this Ruby
|
||||
# instance.
|
||||
|
||||
def self.list
|
||||
@@list
|
||||
end
|
||||
|
||||
##
|
||||
# Specifies the +name+ and +default+ for a specification attribute, and
|
||||
# creates a reader and writer method like Module#attr_accessor.
|
||||
|
@ -302,6 +278,7 @@ module Gem
|
|||
@homepage,
|
||||
@has_rdoc,
|
||||
@new_platform,
|
||||
@licenses
|
||||
]
|
||||
end
|
||||
|
||||
|
@ -346,6 +323,7 @@ module Gem
|
|||
spec.instance_variable_set :@has_rdoc, array[15]
|
||||
spec.instance_variable_set :@new_platform, array[16]
|
||||
spec.instance_variable_set :@platform, array[16].to_s
|
||||
spec.instance_variable_set :@license, array[17]
|
||||
spec.instance_variable_set :@loaded, false
|
||||
|
||||
spec
|
||||
|
@ -426,25 +404,40 @@ module Gem
|
|||
not test_files.empty?
|
||||
end
|
||||
|
||||
alias has_test_suite? has_unit_tests? # :nodoc: deprecated
|
||||
# :stopdoc:
|
||||
alias has_test_suite? has_unit_tests?
|
||||
# :startdoc:
|
||||
|
||||
##
|
||||
# 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.
|
||||
# Specification constructor. Assigns the default values to the attributes
|
||||
# and yields itself for further initialization.
|
||||
|
||||
def initialize
|
||||
@new_platform = nil
|
||||
assign_defaults
|
||||
@loaded = false
|
||||
@loaded_from = nil
|
||||
@@list << self
|
||||
|
||||
yield self if block_given?
|
||||
|
||||
@@gather.call(self) if @@gather
|
||||
end
|
||||
|
||||
##
|
||||
# Duplicates array_attributes from +other_spec+ so state isn't shared.
|
||||
|
||||
def initialize_copy(other_spec)
|
||||
other_ivars = other_spec.instance_variables
|
||||
other_ivars = other_ivars.map { |ivar| ivar.intern } if # for 1.9
|
||||
other_ivars.any? { |ivar| String === ivar }
|
||||
|
||||
self.class.array_attributes.each do |name|
|
||||
name = :"@#{name}"
|
||||
next unless other_ivars.include? name
|
||||
instance_variable_set name, other_spec.instance_variable_get(name).dup
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Each attribute has a default value (possibly nil). Here, we initialize
|
||||
# all attributes to their default value. This is done through the
|
||||
|
@ -527,7 +520,7 @@ module Gem
|
|||
# Sets the rubygems_version to the current RubyGems version
|
||||
|
||||
def mark_version
|
||||
@rubygems_version = RubyGemsVersion
|
||||
@rubygems_version = Gem::RubyGemsVersion
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -615,9 +608,11 @@ module Gem
|
|||
# The directory that this gem was installed into.
|
||||
|
||||
def installation_path
|
||||
path = File.dirname(@loaded_from).split(File::SEPARATOR)[0..-2]
|
||||
path = path.join File::SEPARATOR
|
||||
File.expand_path path
|
||||
unless @loaded_from then
|
||||
raise Gem::Exception, "spec #{full_name} is not from an installed gem"
|
||||
end
|
||||
|
||||
File.expand_path File.dirname(File.dirname(@loaded_from))
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -632,7 +627,7 @@ module Gem
|
|||
# Returns an object you can use to sort specifications in #sort_by.
|
||||
|
||||
def sort_obj
|
||||
[@name, @version.to_ints, @new_platform == Gem::Platform::RUBY ? -1 : 1]
|
||||
[@name, @version, @new_platform == Gem::Platform::RUBY ? -1 : 1]
|
||||
end
|
||||
|
||||
def <=>(other) # :nodoc:
|
||||
|
@ -794,9 +789,9 @@ module Gem
|
|||
extend Gem::UserInteraction
|
||||
normalize
|
||||
|
||||
if rubygems_version != RubyGemsVersion then
|
||||
if rubygems_version != Gem::RubyGemsVersion then
|
||||
raise Gem::InvalidSpecificationException,
|
||||
"expected RubyGems version #{RubyGemsVersion}, was #{rubygems_version}"
|
||||
"expected RubyGems version #{Gem::RubyGemsVersion}, was #{rubygems_version}"
|
||||
end
|
||||
|
||||
@@required_attributes.each do |symbol|
|
||||
|
@ -806,13 +801,41 @@ module Gem
|
|||
end
|
||||
end
|
||||
|
||||
unless String === name then
|
||||
raise Gem::InvalidSpecificationException,
|
||||
"invalid value for attribute name: \"#{name.inspect}\""
|
||||
end
|
||||
|
||||
if require_paths.empty? then
|
||||
raise Gem::InvalidSpecificationException,
|
||||
"specification must have at least one require_path"
|
||||
'specification must have at least one require_path'
|
||||
end
|
||||
|
||||
@files.delete_if do |file| File.directory? file end
|
||||
@test_files.delete_if do |file| File.directory? file end
|
||||
@executables.delete_if do |file|
|
||||
File.directory? File.join(bindir, file)
|
||||
end
|
||||
@extra_rdoc_files.delete_if do |file| File.directory? file end
|
||||
@extensions.delete_if do |file| File.directory? file end
|
||||
|
||||
non_files = files.select do |file|
|
||||
!File.file? file
|
||||
end
|
||||
|
||||
unless non_files.empty? then
|
||||
non_files = non_files.map { |file| file.inspect }
|
||||
raise Gem::InvalidSpecificationException,
|
||||
"[#{non_files.join ", "}] are not files"
|
||||
end
|
||||
|
||||
unless specification_version.is_a?(Fixnum)
|
||||
raise Gem::InvalidSpecificationException,
|
||||
'specification_version must be a Fixnum (did you mean version?)'
|
||||
end
|
||||
|
||||
case platform
|
||||
when Gem::Platform, Platform::RUBY then # ok
|
||||
when Gem::Platform, Gem::Platform::RUBY then # ok
|
||||
else
|
||||
raise Gem::InvalidSpecificationException,
|
||||
"invalid platform #{platform.inspect}, see Gem::Platform"
|
||||
|
@ -824,15 +847,51 @@ module Gem
|
|||
'authors must be Array of Strings'
|
||||
end
|
||||
|
||||
licenses.each { |license|
|
||||
if license.length > 64
|
||||
raise Gem::InvalidSpecificationException,
|
||||
"each license must be 64 characters or less"
|
||||
end
|
||||
}
|
||||
|
||||
# reject FIXME and TODO
|
||||
|
||||
unless authors.grep(/FIXME|TODO/).empty? then
|
||||
raise Gem::InvalidSpecificationException,
|
||||
'"FIXME" or "TODO" is not an author'
|
||||
end
|
||||
|
||||
unless Array(email).grep(/FIXME|TODO/).empty? then
|
||||
raise Gem::InvalidSpecificationException,
|
||||
'"FIXME" or "TODO" is not an email address'
|
||||
end
|
||||
|
||||
if description =~ /FIXME|TODO/ then
|
||||
raise Gem::InvalidSpecificationException,
|
||||
'"FIXME" or "TODO" is not a description'
|
||||
end
|
||||
|
||||
if summary =~ /FIXME|TODO/ then
|
||||
raise Gem::InvalidSpecificationException,
|
||||
'"FIXME" or "TODO" is not a summary'
|
||||
end
|
||||
|
||||
if homepage and not homepage.empty? and
|
||||
homepage !~ /\A[a-z][a-z\d+.-]*:/i then
|
||||
raise Gem::InvalidSpecificationException,
|
||||
"\"#{homepage}\" is not a URI"
|
||||
end
|
||||
|
||||
# Warnings
|
||||
|
||||
%w[author email homepage rubyforge_project summary].each do |attribute|
|
||||
%w[author description email homepage rubyforge_project summary].each do |attribute|
|
||||
value = self.send attribute
|
||||
alert_warning "no #{attribute} specified" if value.nil? or value.empty?
|
||||
end
|
||||
|
||||
alert_warning "RDoc will not be generated (has_rdoc == false)" unless
|
||||
has_rdoc
|
||||
if summary and not summary.empty? and description == summary then
|
||||
alert_warning 'description and summary are identical'
|
||||
end
|
||||
|
||||
alert_warning "deprecated autorequire specified" if autorequire
|
||||
|
||||
|
@ -851,8 +910,6 @@ module Gem
|
|||
# * 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
|
||||
|
@ -885,10 +942,42 @@ module Gem
|
|||
out
|
||||
end
|
||||
|
||||
def to_s
|
||||
def to_s # :nodoc:
|
||||
"#<Gem::Specification name=#{@name} version=#{@version}>"
|
||||
end
|
||||
|
||||
def pretty_print(q) # :nodoc:
|
||||
q.group 2, 'Gem::Specification.new do |s|', 'end' do
|
||||
q.breakable
|
||||
|
||||
attributes = @@attributes.sort_by { |attr_name,| attr_name.to_s }
|
||||
|
||||
attributes.each do |attr_name, default|
|
||||
current_value = self.send attr_name
|
||||
if current_value != default or
|
||||
self.class.required_attribute? attr_name then
|
||||
|
||||
q.text "s.#{attr_name} = "
|
||||
|
||||
if attr_name == :date then
|
||||
current_value = current_value.utc
|
||||
|
||||
q.text "Time.utc(#{current_value.year}, #{current_value.month}, #{current_value.day})"
|
||||
else
|
||||
q.pp current_value
|
||||
end
|
||||
|
||||
q.breakable
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Adds a dependency on gem +dependency+ with type +type+ that requires
|
||||
# +requirements+. Valid types are currently <tt>:runtime</tt> and
|
||||
# <tt>:development</tt>.
|
||||
|
||||
def add_dependency_with_type(dependency, type, *requirements)
|
||||
requirements = if requirements.empty? then
|
||||
Gem::Requirement.default
|
||||
|
@ -899,7 +988,7 @@ module Gem
|
|||
unless dependency.respond_to?(:name) &&
|
||||
dependency.respond_to?(:version_requirements)
|
||||
|
||||
dependency = Dependency.new(dependency, requirements, type)
|
||||
dependency = Gem::Dependency.new(dependency, requirements, type)
|
||||
end
|
||||
|
||||
dependencies << dependency
|
||||
|
@ -907,11 +996,12 @@ module Gem
|
|||
|
||||
private :add_dependency_with_type
|
||||
|
||||
##
|
||||
# Finds all gems that satisfy +dep+
|
||||
|
||||
def find_all_satisfiers(dep)
|
||||
Gem.source_index.each do |name,gem|
|
||||
if(gem.satisfies_requirement?(dep)) then
|
||||
yield gem
|
||||
end
|
||||
Gem.source_index.each do |_, gem|
|
||||
yield gem if gem.satisfies_requirement? dep
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -932,7 +1022,7 @@ module Gem
|
|||
when true, false, nil then obj.inspect
|
||||
when Gem::Platform then "Gem::Platform.new(#{obj.to_a.inspect})"
|
||||
when Gem::Requirement then "Gem::Requirement.new(#{obj.to_s.inspect})"
|
||||
else raise Exception, "ruby_code case not handled: #{obj.class}"
|
||||
else raise Gem::Exception, "ruby_code case not handled: #{obj.class}"
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -941,36 +1031,50 @@ module Gem
|
|||
# :section: Required gemspec attributes
|
||||
|
||||
##
|
||||
# :attr_accessor: rubygems_version
|
||||
#
|
||||
# The version of RubyGems used to create this gem
|
||||
|
||||
required_attribute :rubygems_version, Gem::RubyGemsVersion
|
||||
|
||||
##
|
||||
# :attr_accessor: specification_version
|
||||
#
|
||||
# The Gem::Specification version of this gemspec
|
||||
|
||||
required_attribute :specification_version, CURRENT_SPECIFICATION_VERSION
|
||||
|
||||
##
|
||||
# :attr_accessor: name
|
||||
#
|
||||
# This gem's name
|
||||
|
||||
required_attribute :name
|
||||
|
||||
##
|
||||
# :attr_accessor: version
|
||||
#
|
||||
# This gem's version
|
||||
|
||||
required_attribute :version
|
||||
|
||||
##
|
||||
# :attr_accessor: date
|
||||
#
|
||||
# The date this gem was created
|
||||
|
||||
required_attribute :date, TODAY
|
||||
|
||||
##
|
||||
# :attr_accessor: summary
|
||||
#
|
||||
# A short summary of this gem's description. Displayed in `gem list -d`.
|
||||
|
||||
required_attribute :summary
|
||||
|
||||
##
|
||||
# :attr_accessor: require_paths
|
||||
#
|
||||
# Paths in the gem to add to $LOAD_PATH when this gem is activated
|
||||
|
||||
required_attribute :require_paths, ['lib']
|
||||
|
@ -978,46 +1082,64 @@ module Gem
|
|||
# :section: Optional gemspec attributes
|
||||
|
||||
##
|
||||
# :attr_accessor: email
|
||||
#
|
||||
# A contact email for this gem
|
||||
|
||||
attribute :email
|
||||
|
||||
##
|
||||
# :attr_accessor: homepage
|
||||
#
|
||||
# The URL of this gem's home page
|
||||
|
||||
attribute :homepage
|
||||
|
||||
##
|
||||
# :attr_accessor: rubyforge_project
|
||||
#
|
||||
# The rubyforge project this gem lives under. i.e. RubyGems'
|
||||
# rubyforge_project is "rubygems".
|
||||
|
||||
attribute :rubyforge_project
|
||||
|
||||
##
|
||||
# :attr_accessor: description
|
||||
#
|
||||
# A long description of this gem
|
||||
|
||||
attribute :description
|
||||
|
||||
##
|
||||
# :attr_accessor: autorequire
|
||||
#
|
||||
# Autorequire was used by old RubyGems to automatically require a file.
|
||||
# It no longer is supported.
|
||||
|
||||
attribute :autorequire
|
||||
|
||||
##
|
||||
# :attr_accessor: default_executable
|
||||
#
|
||||
# The default executable for this gem.
|
||||
|
||||
attribute :default_executable
|
||||
|
||||
##
|
||||
# :attr_accessor: bindir
|
||||
#
|
||||
# The path in the gem for executable scripts
|
||||
|
||||
attribute :bindir, 'bin'
|
||||
|
||||
##
|
||||
# True if this gem is RDoc-compliant
|
||||
# :attr_accessor: has_rdoc
|
||||
#
|
||||
# Deprecated and ignored, defaults to true.
|
||||
#
|
||||
# Formerly used to indicate this gem was RDoc-capable.
|
||||
|
||||
attribute :has_rdoc, false
|
||||
attribute :has_rdoc, true
|
||||
|
||||
##
|
||||
# True if this gem supports RDoc
|
||||
|
@ -1025,80 +1147,125 @@ module Gem
|
|||
alias :has_rdoc? :has_rdoc
|
||||
|
||||
##
|
||||
# :attr_accessor: required_ruby_version
|
||||
#
|
||||
# The ruby of version required by this gem
|
||||
|
||||
attribute :required_ruby_version, Gem::Requirement.default
|
||||
|
||||
##
|
||||
# :attr_accessor: required_rubygems_version
|
||||
#
|
||||
# The RubyGems version required by this gem
|
||||
|
||||
attribute :required_rubygems_version, Gem::Requirement.default
|
||||
|
||||
##
|
||||
# :attr_accessor: platform
|
||||
#
|
||||
# The platform this gem runs on. See Gem::Platform for details.
|
||||
|
||||
attribute :platform, Gem::Platform::RUBY
|
||||
|
||||
##
|
||||
# :attr_accessor: signing_key
|
||||
#
|
||||
# The key used to sign this gem. See Gem::Security for details.
|
||||
|
||||
attribute :signing_key, nil
|
||||
|
||||
##
|
||||
# :attr_accessor: cert_chain
|
||||
#
|
||||
# The certificate chain used to sign this gem. See Gem::Security for
|
||||
# details.
|
||||
|
||||
attribute :cert_chain, []
|
||||
|
||||
##
|
||||
# :attr_accessor: post_install_message
|
||||
#
|
||||
# A message that gets displayed after the gem is installed
|
||||
|
||||
attribute :post_install_message, nil
|
||||
|
||||
##
|
||||
# :attr_accessor: authors
|
||||
#
|
||||
# The list of authors who wrote this gem
|
||||
|
||||
array_attribute :authors
|
||||
|
||||
##
|
||||
# Files included in this gem
|
||||
# :attr_accessor: licenses
|
||||
#
|
||||
# The license(s) for the library. Each license must be a short name, no
|
||||
# more than 64 characters.
|
||||
|
||||
array_attribute :licenses
|
||||
|
||||
##
|
||||
# :attr_accessor: files
|
||||
#
|
||||
# Files included in this gem. You cannot append to this accessor, you must
|
||||
# assign to it.
|
||||
#
|
||||
# Only add files you can require to this list, not directories, etc.
|
||||
#
|
||||
# Directories are automatically stripped from this list when building a gem,
|
||||
# other non-files cause an error.
|
||||
|
||||
array_attribute :files
|
||||
|
||||
##
|
||||
# Test files included in this gem
|
||||
# :attr_accessor: test_files
|
||||
#
|
||||
# Test files included in this gem. You cannot append to this accessor, you
|
||||
# must assign to it.
|
||||
|
||||
array_attribute :test_files
|
||||
|
||||
##
|
||||
# :attr_accessor: rdoc_options
|
||||
#
|
||||
# An ARGV-style array of options to RDoc
|
||||
|
||||
array_attribute :rdoc_options
|
||||
|
||||
##
|
||||
# :attr_accessor: extra_rdoc_files
|
||||
#
|
||||
# Extra files to add to RDoc
|
||||
|
||||
array_attribute :extra_rdoc_files
|
||||
|
||||
##
|
||||
# :attr_accessor: executables
|
||||
#
|
||||
# Executables included in the gem
|
||||
|
||||
array_attribute :executables
|
||||
|
||||
##
|
||||
# :attr_accessor: extensions
|
||||
#
|
||||
# Extensions to build when installing the gem. See
|
||||
# Gem::Installer#build_extensions for valid values.
|
||||
|
||||
array_attribute :extensions
|
||||
|
||||
##
|
||||
# :attr_accessor: requirements
|
||||
#
|
||||
# An array or things required by this gem. Not used by anything
|
||||
# presently.
|
||||
|
||||
array_attribute :requirements
|
||||
|
||||
##
|
||||
# A list of Gem::Dependency objects this gem depends on. Only appendable.
|
||||
# :attr_reader: dependencies
|
||||
#
|
||||
# A list of Gem::Dependency objects this gem depends on.
|
||||
|
||||
array_attribute :dependencies
|
||||
|
||||
|
@ -1107,27 +1274,48 @@ module Gem
|
|||
# :section: Aliased gemspec attributes
|
||||
|
||||
##
|
||||
# Singular accessor for executables
|
||||
# Singular accessor for #executables
|
||||
|
||||
attribute_alias_singular :executable, :executables
|
||||
|
||||
##
|
||||
# Singular accessor for authors
|
||||
# Singular accessor for #authors
|
||||
|
||||
attribute_alias_singular :author, :authors
|
||||
|
||||
##
|
||||
# Singular accessor for require_paths
|
||||
# Singular accessor for #licenses
|
||||
|
||||
attribute_alias_singular :license, :licenses
|
||||
|
||||
##
|
||||
# Singular accessor for #require_paths
|
||||
|
||||
attribute_alias_singular :require_path, :require_paths
|
||||
|
||||
##
|
||||
# Singular accessor for test_files
|
||||
# Singular accessor for #test_files
|
||||
|
||||
attribute_alias_singular :test_file, :test_files
|
||||
|
||||
##
|
||||
# has_rdoc is now ignored
|
||||
|
||||
overwrite_accessor :has_rdoc do
|
||||
true
|
||||
end
|
||||
|
||||
##
|
||||
# has_rdoc is now ignored
|
||||
|
||||
overwrite_accessor :has_rdoc= do |value|
|
||||
@has_rdoc = true
|
||||
end
|
||||
|
||||
overwrite_accessor :version= do |version|
|
||||
@version = Version.create(version)
|
||||
@version = Gem::Version.create(version)
|
||||
self.required_rubygems_version = '> 1.3.1' if @version.prerelease?
|
||||
return @version
|
||||
end
|
||||
|
||||
overwrite_accessor :platform do
|
||||
|
@ -1153,8 +1341,6 @@ module Gem
|
|||
@new_platform = Gem::Platform::RUBY
|
||||
when 'mswin32' then # was Gem::Platform::WIN32
|
||||
@new_platform = Gem::Platform.new 'x86-mswin32'
|
||||
when 'mswin64' then
|
||||
@new_platform = Gem::Platform.new 'x86-mswin64'
|
||||
when 'i586-linux' then # was Gem::Platform::LINUX_586
|
||||
@new_platform = Gem::Platform.new 'x86-linux'
|
||||
when 'powerpc-darwin' then # was Gem::Platform::DARWIN
|
||||
|
@ -1211,11 +1397,7 @@ module Gem
|
|||
end
|
||||
|
||||
overwrite_accessor :description= do |str|
|
||||
@description = if str then
|
||||
str.strip.
|
||||
gsub(/(\w-)\n[ \t]*(\w)/, '\1\2').
|
||||
gsub(/\n[ \t]*/, " ")
|
||||
end
|
||||
@description = str.to_s
|
||||
end
|
||||
|
||||
overwrite_accessor :default_executable do
|
||||
|
@ -1260,5 +1442,3 @@ module Gem
|
|||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
30
lib/rubygems/text.rb
Normal file
30
lib/rubygems/text.rb
Normal file
|
@ -0,0 +1,30 @@
|
|||
require 'rubygems'
|
||||
|
||||
##
|
||||
# A collection of text-wrangling methods
|
||||
|
||||
module Gem::Text
|
||||
|
||||
##
|
||||
# Wraps +text+ to +wrap+ characters and optionally indents by +indent+
|
||||
# characters
|
||||
|
||||
def format_text(text, wrap, indent=0)
|
||||
result = []
|
||||
work = text.dup
|
||||
|
||||
while work.length > wrap do
|
||||
if work =~ /^(.{0,#{wrap}})[ \n]/ then
|
||||
result << $1
|
||||
work.slice!(0, $&.length)
|
||||
else
|
||||
result << work.slice!(0, wrap)
|
||||
end
|
||||
end
|
||||
|
||||
result << work if work.length.nonzero?
|
||||
result.join("\n").gsub(/^/, " " * indent)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
#
|
||||
# This file defines a $log variable for logging, and a time() method for recording timing
|
||||
# information.
|
||||
# This file defines a $log variable for logging, and a time() method for
|
||||
# recording timing information.
|
||||
#
|
||||
#--
|
||||
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
|
||||
|
@ -8,18 +8,21 @@
|
|||
# See LICENSE.txt for permissions.
|
||||
#++
|
||||
|
||||
require 'rubygems'
|
||||
|
||||
file, lineno = Gem.location_of_caller
|
||||
|
||||
warn "#{file}:#{lineno}:Warning: RubyGems' lib/rubygems/timer.rb deprecated and will be removed on or after June 2009."
|
||||
|
||||
$log = Object.new
|
||||
def $log.debug(str)
|
||||
STDERR.puts str
|
||||
|
||||
# :stopdoc:
|
||||
def $log.debug(message)
|
||||
Gem.debug message
|
||||
end
|
||||
|
||||
def time(msg, width=25)
|
||||
t = Time.now
|
||||
return_value = yield
|
||||
elapsed = Time.now.to_f - t.to_f
|
||||
elapsed = sprintf("%3.3f", elapsed)
|
||||
$log.debug "#{msg.ljust(width)}: #{elapsed}s"
|
||||
return_value
|
||||
def time(msg, width=25, &block)
|
||||
Gem.time(msg, width, &block)
|
||||
end
|
||||
# :startdoc:
|
||||
|
||||
|
|
|
@ -12,6 +12,11 @@ require 'rubygems/user_interaction'
|
|||
|
||||
##
|
||||
# An Uninstaller.
|
||||
#
|
||||
# The uninstaller fires pre and post uninstall hooks. Hooks can be added
|
||||
# either through a rubygems_plugin.rb file in an installed gem or via a
|
||||
# rubygems/defaults/#{RUBY_ENGINE}.rb or rubygems/defaults/operating_system.rb
|
||||
# file. See Gem.pre_uninstall and Gem.post_uninstall for details.
|
||||
|
||||
class Gem::Uninstaller
|
||||
|
||||
|
@ -46,8 +51,17 @@ class Gem::Uninstaller
|
|||
@force_ignore = options[:ignore]
|
||||
@bin_dir = options[:bin_dir]
|
||||
|
||||
# only add user directory if install_dir is not set
|
||||
@user_install = false
|
||||
@user_install = options[:user_install] unless options[:install_dir]
|
||||
|
||||
spec_dir = File.join @gem_home, 'specifications'
|
||||
@source_index = Gem::SourceIndex.from_gems_in spec_dir
|
||||
|
||||
if @user_install then
|
||||
user_dir = File.join Gem.user_dir, 'specifications'
|
||||
@user_index = Gem::SourceIndex.from_gems_in user_dir
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -56,9 +70,10 @@ class Gem::Uninstaller
|
|||
|
||||
def uninstall
|
||||
list = @source_index.find_name @gem, @version
|
||||
list += @user_index.find_name @gem, @version if @user_install
|
||||
|
||||
if list.empty? then
|
||||
raise Gem::InstallError, "Unknown gem #{@gem} #{@version}"
|
||||
raise Gem::InstallError, "cannot uninstall, check `gem list -d #{@gem}`"
|
||||
|
||||
elsif list.size > 1 and @force_all then
|
||||
remove_all list.dup
|
||||
|
@ -91,8 +106,8 @@ class Gem::Uninstaller
|
|||
hook.call self
|
||||
end
|
||||
|
||||
specs.each { |s| remove_executables s }
|
||||
remove spec, specs
|
||||
remove_executables @spec
|
||||
remove @spec, specs
|
||||
|
||||
Gem.post_uninstall_hooks.each do |hook|
|
||||
hook.call self
|
||||
|
@ -105,29 +120,29 @@ class Gem::Uninstaller
|
|||
# Removes installed executables and batch files (windows only) for
|
||||
# +gemspec+.
|
||||
|
||||
def remove_executables(gemspec)
|
||||
return if gemspec.nil?
|
||||
def remove_executables(spec)
|
||||
return if spec.nil?
|
||||
|
||||
if gemspec.executables.size > 0 then
|
||||
bindir = @bin_dir ? @bin_dir : (Gem.bindir @gem_home)
|
||||
unless spec.executables.empty? then
|
||||
bindir = @bin_dir ? @bin_dir : Gem.bindir(spec.installation_path)
|
||||
|
||||
list = @source_index.find_name(gemspec.name).delete_if { |spec|
|
||||
spec.version == gemspec.version
|
||||
list = @source_index.find_name(spec.name).delete_if { |s|
|
||||
s.version == spec.version
|
||||
}
|
||||
|
||||
executables = gemspec.executables.clone
|
||||
executables = spec.executables.clone
|
||||
|
||||
list.each do |spec|
|
||||
spec.executables.each do |exe_name|
|
||||
executables.delete(exe_name)
|
||||
list.each do |s|
|
||||
s.executables.each do |exe_name|
|
||||
executables.delete exe_name
|
||||
end
|
||||
end
|
||||
|
||||
return if executables.size == 0
|
||||
return if executables.empty?
|
||||
|
||||
answer = if @force_executables.nil? then
|
||||
ask_yes_no("Remove executables:\n" \
|
||||
"\t#{gemspec.executables.join(", ")}\n\nin addition to the gem?",
|
||||
"\t#{spec.executables.join(", ")}\n\nin addition to the gem?",
|
||||
true) # " # appease ruby-mode - don't ask
|
||||
else
|
||||
@force_executables
|
||||
|
@ -138,7 +153,7 @@ class Gem::Uninstaller
|
|||
else
|
||||
raise Gem::FilePermissionError, bindir unless File.writable? bindir
|
||||
|
||||
gemspec.executables.each do |exe_name|
|
||||
spec.executables.each do |exe_name|
|
||||
say "Removing #{exe_name}"
|
||||
FileUtils.rm_f File.join(bindir, exe_name)
|
||||
FileUtils.rm_f File.join(bindir, "#{exe_name}.bat")
|
||||
|
@ -169,7 +184,8 @@ class Gem::Uninstaller
|
|||
"Uninstallation aborted due to dependent gem(s)"
|
||||
end
|
||||
|
||||
unless path_ok? spec then
|
||||
unless path_ok?(@gem_home, spec) or
|
||||
(@user_install and path_ok?(Gem.user_dir, spec)) then
|
||||
e = Gem::GemNotInHomeException.new \
|
||||
"Gem is not installed in directory #{@gem_home}"
|
||||
e.spec = spec
|
||||
|
@ -210,9 +226,12 @@ class Gem::Uninstaller
|
|||
list.delete spec
|
||||
end
|
||||
|
||||
def path_ok?(spec)
|
||||
full_path = File.join @gem_home, 'gems', spec.full_name
|
||||
original_path = File.join @gem_home, 'gems', spec.original_name
|
||||
##
|
||||
# Is +spec+ in +gem_dir+?
|
||||
|
||||
def path_ok?(gem_dir, spec)
|
||||
full_path = File.join gem_dir, 'gems', spec.full_name
|
||||
original_path = File.join gem_dir, 'gems', spec.original_name
|
||||
|
||||
full_path == spec.full_gem_path || original_path == spec.full_gem_path
|
||||
end
|
||||
|
@ -221,6 +240,7 @@ class Gem::Uninstaller
|
|||
return true if @force_ignore
|
||||
|
||||
deplist = Gem::DependencyList.from_source_index @source_index
|
||||
deplist.add(*@user_index.gems.values) if @user_install
|
||||
deplist.ok_to_remove?(spec.full_name) || ask_if_ok(spec)
|
||||
end
|
||||
|
||||
|
|
|
@ -4,13 +4,11 @@
|
|||
# See LICENSE.txt for permissions.
|
||||
#++
|
||||
|
||||
module Gem
|
||||
|
||||
##
|
||||
# Module that defines the default UserInteraction. Any class including this
|
||||
# module will have access to the +ui+ method that returns the default UI.
|
||||
|
||||
module DefaultUserInteraction
|
||||
module Gem::DefaultUserInteraction
|
||||
|
||||
##
|
||||
# The default UI is a class variable of the singleton class for this
|
||||
|
@ -48,21 +46,21 @@ module Gem
|
|||
# See DefaultUserInteraction::ui
|
||||
|
||||
def ui
|
||||
DefaultUserInteraction.ui
|
||||
Gem::DefaultUserInteraction.ui
|
||||
end
|
||||
|
||||
##
|
||||
# See DefaultUserInteraction::ui=
|
||||
|
||||
def ui=(new_ui)
|
||||
DefaultUserInteraction.ui = new_ui
|
||||
Gem::DefaultUserInteraction.ui = new_ui
|
||||
end
|
||||
|
||||
##
|
||||
# See DefaultUserInteraction::use_ui
|
||||
|
||||
def use_ui(new_ui, &block)
|
||||
DefaultUserInteraction.use_ui(new_ui, &block)
|
||||
Gem::DefaultUserInteraction.use_ui(new_ui, &block)
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -82,9 +80,33 @@ module Gem
|
|||
# end
|
||||
# end
|
||||
|
||||
module UserInteraction
|
||||
module Gem::UserInteraction
|
||||
|
||||
include DefaultUserInteraction
|
||||
include Gem::DefaultUserInteraction
|
||||
|
||||
##
|
||||
# :method: alert
|
||||
|
||||
##
|
||||
# :method: alert_error
|
||||
|
||||
##
|
||||
# :method: alert_warning
|
||||
|
||||
##
|
||||
# :method: ask
|
||||
|
||||
##
|
||||
# :method: ask_yes_no
|
||||
|
||||
##
|
||||
# :method: choose_from_list
|
||||
|
||||
##
|
||||
# :method: say
|
||||
|
||||
##
|
||||
# :method: terminate_interaction
|
||||
|
||||
[:alert,
|
||||
:alert_error,
|
||||
|
@ -103,9 +125,9 @@ module Gem
|
|||
end
|
||||
|
||||
##
|
||||
# StreamUI implements a simple stream based user interface.
|
||||
# Gem::StreamUI implements a simple stream based user interface.
|
||||
|
||||
class StreamUI
|
||||
class Gem::StreamUI
|
||||
|
||||
attr_reader :ins, :outs, :errs
|
||||
|
||||
|
@ -228,6 +250,13 @@ module Gem
|
|||
ask(question) if question
|
||||
end
|
||||
|
||||
##
|
||||
# Display a debug message on the same location as error messages.
|
||||
|
||||
def debug(statement)
|
||||
@errs.puts statement
|
||||
end
|
||||
|
||||
##
|
||||
# Terminate the application with exit code +status+, running any exit
|
||||
# handlers that might have been defined.
|
||||
|
@ -270,7 +299,8 @@ module Gem
|
|||
# A basic dotted progress reporter.
|
||||
|
||||
class SimpleProgressReporter
|
||||
include DefaultUserInteraction
|
||||
|
||||
include Gem::DefaultUserInteraction
|
||||
|
||||
attr_reader :count
|
||||
|
||||
|
@ -306,7 +336,8 @@ module Gem
|
|||
# A progress reporter that prints out messages about the current progress.
|
||||
|
||||
class VerboseProgressReporter
|
||||
include DefaultUserInteraction
|
||||
|
||||
include Gem::DefaultUserInteraction
|
||||
|
||||
attr_reader :count
|
||||
|
||||
|
@ -335,26 +366,25 @@ module Gem
|
|||
@out.puts @terminal_message
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
##
|
||||
# Subclass of StreamUI that instantiates the user interaction using STDIN,
|
||||
# STDOUT, and STDERR.
|
||||
|
||||
class ConsoleUI < StreamUI
|
||||
class Gem::ConsoleUI < Gem::StreamUI
|
||||
def initialize
|
||||
super(STDIN, STDOUT, STDERR)
|
||||
super STDIN, STDOUT, STDERR
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# SilentUI is a UI choice that is absolutely silent.
|
||||
|
||||
class SilentUI
|
||||
class Gem::SilentUI
|
||||
def method_missing(sym, *args, &block)
|
||||
self
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -6,10 +6,17 @@
|
|||
|
||||
require 'find'
|
||||
|
||||
require 'rubygems/digest/md5'
|
||||
require 'digest'
|
||||
require 'rubygems/format'
|
||||
require 'rubygems/installer'
|
||||
|
||||
# Load test-unit 2.x if it's a gem
|
||||
begin
|
||||
Gem.activate('test-unit')
|
||||
rescue Gem::LoadError
|
||||
# Ignore - use the test-unit library that's part of the standard library
|
||||
end
|
||||
|
||||
##
|
||||
# Validator performs various gem file and gem database validation
|
||||
|
||||
|
@ -33,7 +40,7 @@ class Gem::Validator
|
|||
sum_data = gem_data.gsub(/MD5SUM = "([a-z0-9]+)"/,
|
||||
"MD5SUM = \"#{"F" * 32}\"")
|
||||
|
||||
unless Gem::MD5.hexdigest(sum_data) == $1.to_s then
|
||||
unless Digest::MD5.hexdigest(sum_data) == $1.to_s then
|
||||
raise Gem::VerificationError, 'invalid checksum for gem file'
|
||||
end
|
||||
end
|
||||
|
@ -48,7 +55,7 @@ class Gem::Validator
|
|||
gem_data = file.read
|
||||
verify_gem gem_data
|
||||
end
|
||||
rescue Errno::ENOENT
|
||||
rescue Errno::ENOENT, Errno::EINVAL
|
||||
raise Gem::VerificationError, "missing gem file #{gem_path}"
|
||||
end
|
||||
|
||||
|
@ -56,13 +63,11 @@ class Gem::Validator
|
|||
|
||||
def find_files_for_gem(gem_directory)
|
||||
installed_files = []
|
||||
Find.find(gem_directory) {|file_name|
|
||||
fn = file_name.slice((gem_directory.size)..(file_name.size-1)).sub(/^\//, "")
|
||||
if(!(fn =~ /CVS/ || File.directory?(fn) || fn == "")) then
|
||||
installed_files << fn
|
||||
Find.find gem_directory do |file_name|
|
||||
fn = file_name[gem_directory.size..file_name.size-1].sub(/^\//, "")
|
||||
installed_files << fn unless
|
||||
fn =~ /CVS/ || fn.empty? || File.directory?(file_name)
|
||||
end
|
||||
|
||||
}
|
||||
installed_files
|
||||
end
|
||||
|
||||
|
@ -81,53 +86,82 @@ class Gem::Validator
|
|||
#
|
||||
# returns a hash of ErrorData objects, keyed on the problem gem's name.
|
||||
|
||||
def alien
|
||||
errors = {}
|
||||
def alien(gems=[])
|
||||
errors = Hash.new { |h,k| h[k] = {} }
|
||||
|
||||
Gem::SourceIndex.from_installed_gems.each do |gem_name, gem_spec|
|
||||
errors[gem_name] ||= []
|
||||
next unless gems.include? gem_spec.name unless gems.empty?
|
||||
|
||||
gem_path = File.join(Gem.dir, "cache", gem_spec.full_name) + ".gem"
|
||||
spec_path = File.join(Gem.dir, "specifications", gem_spec.full_name) + ".gemspec"
|
||||
gem_directory = File.join(Gem.dir, "gems", gem_spec.full_name)
|
||||
install_dir = gem_spec.installation_path
|
||||
gem_path = File.join(install_dir, "cache", gem_spec.full_name) + ".gem"
|
||||
spec_path = File.join(install_dir, "specifications",
|
||||
gem_spec.full_name) + ".gemspec"
|
||||
gem_directory = gem_spec.full_gem_path
|
||||
|
||||
installed_files = find_files_for_gem(gem_directory)
|
||||
unless File.directory? gem_directory then
|
||||
errors[gem_name][gem_spec.full_name] =
|
||||
"Gem registered but doesn't exist at #{gem_directory}"
|
||||
next
|
||||
end
|
||||
|
||||
unless File.exist? spec_path then
|
||||
errors[gem_name] << ErrorData.new(spec_path, "Spec file doesn't exist for installed gem")
|
||||
errors[gem_name][spec_path] = "Spec file missing for installed gem"
|
||||
end
|
||||
|
||||
begin
|
||||
verify_gem_file(gem_path)
|
||||
|
||||
good, gone, unreadable = nil, nil, nil, nil
|
||||
|
||||
open gem_path, Gem.binary_mode do |file|
|
||||
format = Gem::Format.from_file_by_path(gem_path)
|
||||
format.file_entries.each do |entry, data|
|
||||
# Found this file. Delete it from list
|
||||
installed_files.delete remove_leading_dot_dir(entry['path'])
|
||||
|
||||
good, gone = format.file_entries.partition { |entry, _|
|
||||
File.exist? File.join(gem_directory, entry['path'])
|
||||
}
|
||||
|
||||
gone.map! { |entry, _| entry['path'] }
|
||||
gone.sort.each do |path|
|
||||
errors[gem_name][path] = "Missing file"
|
||||
end
|
||||
|
||||
good, unreadable = good.partition { |entry, _|
|
||||
File.readable? File.join(gem_directory, entry['path'])
|
||||
}
|
||||
|
||||
unreadable.map! { |entry, _| entry['path'] }
|
||||
unreadable.sort.each do |path|
|
||||
errors[gem_name][path] = "Unreadable file"
|
||||
end
|
||||
|
||||
good.each do |entry, data|
|
||||
begin
|
||||
next unless data # HACK `gem check -a mkrf`
|
||||
|
||||
open File.join(gem_directory, entry['path']), Gem.binary_mode do |f|
|
||||
unless Gem::MD5.hexdigest(f.read).to_s ==
|
||||
Gem::MD5.hexdigest(data).to_s then
|
||||
errors[gem_name] << ErrorData.new(entry['path'], "installed file doesn't match original from gem")
|
||||
unless Digest::MD5.hexdigest(f.read).to_s ==
|
||||
Digest::MD5.hexdigest(data).to_s then
|
||||
errors[gem_name][entry['path']] = "Modified from original"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
rescue Gem::VerificationError => e
|
||||
errors[gem_name] << ErrorData.new(gem_path, e.message)
|
||||
end
|
||||
|
||||
# Clean out directories that weren't explicitly included in the gemspec
|
||||
# FIXME: This still allows arbitrary incorrect directories.
|
||||
installed_files.delete_if {|potential_directory|
|
||||
File.directory?(File.join(gem_directory, potential_directory))
|
||||
}
|
||||
if(installed_files.size > 0) then
|
||||
errors[gem_name] << ErrorData.new(gem_path, "Unmanaged files in gem: #{installed_files.inspect}")
|
||||
installed_files = find_files_for_gem(gem_directory)
|
||||
good.map! { |entry, _| entry['path'] }
|
||||
extras = installed_files - good - unreadable
|
||||
|
||||
extras.each do |extra|
|
||||
errors[gem_name][extra] = "Extra file"
|
||||
end
|
||||
rescue Gem::VerificationError => e
|
||||
errors[gem_name][gem_path] = e.message
|
||||
end
|
||||
end
|
||||
|
||||
errors.each do |name, subhash|
|
||||
errors[name] = subhash.map { |path, msg| ErrorData.new(path, msg) }
|
||||
end
|
||||
|
||||
errors
|
||||
|
@ -167,7 +201,7 @@ class Gem::Validator
|
|||
def unit_test(gem_spec)
|
||||
start_dir = Dir.pwd
|
||||
Dir.chdir(gem_spec.full_gem_path)
|
||||
$: << File.join(Gem.dir, "gems", gem_spec.full_name)
|
||||
$: << gem_spec.full_gem_path
|
||||
# XXX: why do we need this gem_spec when we've already got 'spec'?
|
||||
test_files = gem_spec.test_files
|
||||
|
||||
|
@ -200,7 +234,6 @@ class Gem::Validator
|
|||
Dir.chdir(start_dir)
|
||||
end
|
||||
|
||||
private
|
||||
def remove_leading_dot_dir(path)
|
||||
path.sub(/^\.\//, "")
|
||||
end
|
||||
|
|
|
@ -4,27 +4,81 @@
|
|||
# See LICENSE.txt for permissions.
|
||||
#++
|
||||
|
||||
require 'rubygems'
|
||||
|
||||
##
|
||||
# The Version class processes string versions into comparable values
|
||||
# The Version class processes string versions into comparable
|
||||
# values. A version string should normally be a series of numbers
|
||||
# separated by periods. Each part (digits separated by periods) is
|
||||
# considered its own number, and these are used for sorting. So for
|
||||
# instance, 3.10 sorts higher than 3.2 because ten is greater than
|
||||
# two.
|
||||
#
|
||||
# If any part contains letters (currently only a-z are supported) then
|
||||
# that version is considered prerelease. Versions with a prerelease
|
||||
# part in the Nth part sort less than versions with N-1 parts. Prerelease
|
||||
# parts are sorted alphabetically using the normal Ruby string sorting
|
||||
# rules.
|
||||
#
|
||||
# Prereleases sort between real releases (newest to oldest):
|
||||
#
|
||||
# 1. 1.0
|
||||
# 2. 1.0.b
|
||||
# 3. 1.0.a
|
||||
# 4. 0.9
|
||||
|
||||
class Gem::Version
|
||||
|
||||
class Part
|
||||
include Comparable
|
||||
|
||||
attr_reader :ints
|
||||
attr_reader :value
|
||||
|
||||
def initialize(value)
|
||||
@value = (value =~ /\A\d+\z/) ? value.to_i : value
|
||||
end
|
||||
|
||||
def to_s
|
||||
self.value.to_s
|
||||
end
|
||||
|
||||
def inspect
|
||||
@value
|
||||
end
|
||||
|
||||
def alpha?
|
||||
String === value
|
||||
end
|
||||
|
||||
def numeric?
|
||||
Fixnum === value
|
||||
end
|
||||
|
||||
def <=>(other)
|
||||
if self.numeric? && other.alpha? then
|
||||
1
|
||||
elsif self.alpha? && other.numeric? then
|
||||
-1
|
||||
else
|
||||
self.value <=> other.value
|
||||
end
|
||||
end
|
||||
|
||||
def succ
|
||||
self.class.new(self.value.succ)
|
||||
end
|
||||
end
|
||||
|
||||
include Comparable
|
||||
|
||||
VERSION_PATTERN = '[0-9]+(\.[0-9a-z]+)*'
|
||||
|
||||
attr_reader :version
|
||||
|
||||
##
|
||||
# Returns true if +version+ is a valid version string.
|
||||
|
||||
def self.correct?(version)
|
||||
case version
|
||||
when Integer, /\A\s*(\d+(\.-?\d+)*)*\s*\z/ then true
|
||||
else false
|
||||
end
|
||||
pattern = /\A\s*(#{VERSION_PATTERN})*\s*\z/
|
||||
|
||||
version.is_a? Integer or
|
||||
version =~ pattern or
|
||||
version.to_s =~ pattern
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -47,7 +101,7 @@ class Gem::Version
|
|||
|
||||
##
|
||||
# Constructs a Version from the +version+ string. A version string is a
|
||||
# series of digits separated by dots.
|
||||
# series of digits or ASCII letters separated by dots.
|
||||
|
||||
def initialize(version)
|
||||
raise ArgumentError, "Malformed version number string #{version}" unless
|
||||
|
@ -60,46 +114,43 @@ class Gem::Version
|
|||
"#<#{self.class} #{@version.inspect}>"
|
||||
end
|
||||
|
||||
##
|
||||
# Dump only the raw version string, not the complete object
|
||||
|
||||
def marshal_dump
|
||||
[@version]
|
||||
end
|
||||
|
||||
##
|
||||
# Load custom marshal format
|
||||
|
||||
def marshal_load(array)
|
||||
self.version = array[0]
|
||||
end
|
||||
|
||||
def parts
|
||||
@parts ||= normalize
|
||||
end
|
||||
|
||||
##
|
||||
# Strip ignored trailing zeros.
|
||||
|
||||
def normalize
|
||||
@ints = build_array_from_version_string
|
||||
|
||||
return if @ints.length == 1
|
||||
|
||||
@ints.pop while @ints.last == 0
|
||||
|
||||
@ints = [0] if @ints.empty?
|
||||
parts_arr = parse_parts_from_version_string
|
||||
if parts_arr.length != 1
|
||||
parts_arr.pop while parts_arr.last && parts_arr.last.value == 0
|
||||
parts_arr = [Part.new(0)] if parts_arr.empty?
|
||||
end
|
||||
parts_arr
|
||||
end
|
||||
|
||||
##
|
||||
# Returns the text representation of the version
|
||||
#
|
||||
# return:: [String] version as string
|
||||
#
|
||||
|
||||
def to_s
|
||||
@version
|
||||
end
|
||||
|
||||
##
|
||||
# Returns an integer array representation of this Version.
|
||||
|
||||
def to_ints
|
||||
normalize unless @ints
|
||||
@ints
|
||||
end
|
||||
|
||||
def to_yaml_properties
|
||||
['@version']
|
||||
end
|
||||
|
@ -109,6 +160,23 @@ class Gem::Version
|
|||
normalize
|
||||
end
|
||||
|
||||
##
|
||||
# A version is considered a prerelease if any part contains a letter.
|
||||
|
||||
def prerelease?
|
||||
parts.any? { |part| part.alpha? }
|
||||
end
|
||||
|
||||
##
|
||||
# The release for this version (e.g. 1.2.0.a -> 1.2.0)
|
||||
# Non-prerelease versions return themselves
|
||||
def release
|
||||
return self unless prerelease?
|
||||
rel_parts = parts.dup
|
||||
rel_parts.pop while rel_parts.any? { |part| part.alpha? }
|
||||
self.class.new(rel_parts.join('.'))
|
||||
end
|
||||
|
||||
def yaml_initialize(tag, values)
|
||||
self.version = values['version']
|
||||
end
|
||||
|
@ -120,7 +188,14 @@ class Gem::Version
|
|||
def <=>(other)
|
||||
return nil unless self.class === other
|
||||
return 1 unless other
|
||||
@ints <=> other.ints
|
||||
mine, theirs = balance(self.parts.dup, other.parts.dup)
|
||||
mine <=> theirs
|
||||
end
|
||||
|
||||
def balance(a, b)
|
||||
a << Part.new(0) while a.size < b.size
|
||||
b << Part.new(0) while b.size < a.size
|
||||
[a, b]
|
||||
end
|
||||
|
||||
##
|
||||
|
@ -135,24 +210,33 @@ class Gem::Version
|
|||
@version.hash
|
||||
end
|
||||
|
||||
# Return a new version object where the next to the last revision
|
||||
# number is one greater. (e.g. 5.3.1 => 5.4)
|
||||
##
|
||||
# Return a new version object where the next to the last revision number is
|
||||
# one greater. (e.g. 5.3.1 => 5.4)
|
||||
#
|
||||
# Pre-release (alpha) parts are ignored. (e.g 5.3.1.b2 => 5.4)
|
||||
|
||||
def bump
|
||||
ints = build_array_from_version_string
|
||||
ints.pop if ints.size > 1
|
||||
ints[-1] += 1
|
||||
self.class.new(ints.join("."))
|
||||
parts = parse_parts_from_version_string
|
||||
parts.pop while parts.any? { |part| part.alpha? }
|
||||
parts.pop if parts.size > 1
|
||||
parts[-1] = parts[-1].succ
|
||||
self.class.new(parts.join("."))
|
||||
end
|
||||
|
||||
def build_array_from_version_string
|
||||
@version.to_s.scan(/\d+/).map { |s| s.to_i }
|
||||
def parse_parts_from_version_string # :nodoc:
|
||||
@version.to_s.scan(/[0-9a-z]+/i).map { |s| Part.new(s) }
|
||||
end
|
||||
|
||||
def pretty_print(q) # :nodoc:
|
||||
q.text "Gem::Version.new(#{@version.inspect})"
|
||||
end
|
||||
private :build_array_from_version_string
|
||||
|
||||
#:stopdoc:
|
||||
|
||||
require 'rubygems/requirement'
|
||||
|
||||
##
|
||||
# Gem::Requirement's original definition is nested in Version.
|
||||
# Although an inappropriate place, current gems specs reference the nested
|
||||
# class name explicitly. To remain compatible with old software loading
|
||||
|
|
|
@ -41,6 +41,7 @@ module Gem::VersionOption
|
|||
"Specify version of gem to #{task}", *wrap) do
|
||||
|value, options|
|
||||
options[:version] = value
|
||||
options[:prerelease] = true if value.prerelease?
|
||||
end
|
||||
end
|
||||
|
||||
|
|
0
test/rubygems/foo/discover.rb
Normal file
0
test/rubygems/foo/discover.rb
Normal file
|
@ -1,4 +1,3 @@
|
|||
require 'minitest/unit'
|
||||
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
|
||||
require 'rubygems/installer'
|
||||
|
||||
|
@ -20,17 +19,17 @@ class GemInstallerTestCase < RubyGemTestCase
|
|||
def setup
|
||||
super
|
||||
|
||||
@spec = quick_gem "a"
|
||||
@spec = quick_gem 'a'
|
||||
@gem = File.join @tempdir, "#{@spec.full_name}.gem"
|
||||
|
||||
util_build_gem @spec
|
||||
FileUtils.mv File.join(@gemhome, 'cache', "#{@spec.full_name}.gem"),
|
||||
@tempdir
|
||||
@installer = util_installer @spec, @gem, @gemhome
|
||||
|
||||
@installer = Gem::Installer.new @gem
|
||||
@installer.gem_dir = util_gem_dir
|
||||
@installer.gem_home = @gemhome
|
||||
@installer.spec = @spec
|
||||
@user_spec = quick_gem 'b'
|
||||
@user_gem = File.join @tempdir, "#{@user_spec.full_name}.gem"
|
||||
|
||||
@user_installer = util_installer @user_spec, @user_gem, Gem.user_dir
|
||||
@user_installer.gem_dir = File.join(Gem.user_dir, 'gems',
|
||||
@user_spec.full_name)
|
||||
end
|
||||
|
||||
def util_gem_bindir(version = '2')
|
||||
|
@ -49,8 +48,7 @@ class GemInstallerTestCase < RubyGemTestCase
|
|||
@spec.executables = ["my_exec"]
|
||||
|
||||
FileUtils.mkdir_p util_gem_bindir(version)
|
||||
exec_file = @installer.formatted_program_filename "my_exec"
|
||||
exec_path = File.join util_gem_bindir(version), exec_file
|
||||
exec_path = File.join util_gem_bindir(version), "my_exec"
|
||||
File.open exec_path, 'w' do |f|
|
||||
f.puts shebang
|
||||
end
|
||||
|
@ -82,5 +80,18 @@ class GemInstallerTestCase < RubyGemTestCase
|
|||
@installer = Gem::Installer.new @gem
|
||||
end
|
||||
|
||||
def util_installer(spec, gem_path, gem_home)
|
||||
util_build_gem spec
|
||||
FileUtils.mv File.join(@gemhome, 'cache', "#{spec.full_name}.gem"),
|
||||
@tempdir
|
||||
|
||||
installer = Gem::Installer.new gem_path
|
||||
installer.gem_dir = util_gem_dir
|
||||
installer.gem_home = gem_home
|
||||
installer.spec = spec
|
||||
|
||||
installer
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -1,20 +1,6 @@
|
|||
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
|
||||
require 'rubygems/package'
|
||||
|
||||
class File
|
||||
|
||||
# straight from setup.rb
|
||||
def self.dir?(path)
|
||||
# for corrupted windows stat()
|
||||
File.directory?((path[-1,1] == '/') ? path : path + '/')
|
||||
end
|
||||
|
||||
def self.read_b(name)
|
||||
File.open(name, "rb") { |f| f.read }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class TarTestCase < RubyGemTestCase
|
||||
|
||||
def ASCIIZ(str, length)
|
||||
|
|
|
@ -8,24 +8,35 @@ at_exit { $SAFE = 1 }
|
|||
|
||||
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
||||
|
||||
if RUBY_VERSION > '1.9' then
|
||||
Gem::QuickLoader.load_full_rubygems_library
|
||||
else
|
||||
require 'rubygems'
|
||||
end
|
||||
require 'fileutils'
|
||||
begin
|
||||
gem 'minitest', '>= 1.3.1'
|
||||
require 'minitest/unit'
|
||||
rescue LoadError
|
||||
warn "Install minitest gem"
|
||||
rescue Gem::LoadError
|
||||
warn "Install minitest gem >= 1.3.1"
|
||||
raise
|
||||
end
|
||||
require 'tmpdir'
|
||||
require 'uri'
|
||||
require 'rubygems/package'
|
||||
require 'rubygems/test_utilities'
|
||||
require 'pp'
|
||||
|
||||
begin
|
||||
gem 'rdoc'
|
||||
rescue Gem::LoadError
|
||||
end
|
||||
|
||||
require 'rdoc/rdoc'
|
||||
|
||||
require File.join(File.expand_path(File.dirname(__FILE__)), 'mockgemui')
|
||||
|
||||
module Gem
|
||||
@ruby = ENV['RUBY']
|
||||
|
||||
def self.searcher=(searcher)
|
||||
MUTEX.synchronize do @searcher = searcher end
|
||||
end
|
||||
|
@ -64,6 +75,8 @@ class RubyGemTestCase < MiniTest::Unit::TestCase
|
|||
@latest_usrcache = File.join(@gemhome, ".gem", "latest_user_cache")
|
||||
@userhome = File.join @tempdir, 'userhome'
|
||||
|
||||
Gem.ensure_gem_subdirectories @gemhome
|
||||
|
||||
@orig_ENV_HOME = ENV['HOME']
|
||||
ENV['HOME'] = @userhome
|
||||
Gem.instance_variable_set :@user_home, nil
|
||||
|
@ -85,7 +98,7 @@ class RubyGemTestCase < MiniTest::Unit::TestCase
|
|||
Gem::SpecFetcher.fetcher = nil
|
||||
|
||||
@orig_BASERUBY = Gem::ConfigMap[:BASERUBY]
|
||||
Gem::ConfigMap[:BASERUBY] = Gem::ConfigMap[:RUBY_INSTALL_NAME]
|
||||
Gem::ConfigMap[:BASERUBY] = Gem::ConfigMap[:ruby_install_name]
|
||||
|
||||
@orig_arch = Gem::ConfigMap[:arch]
|
||||
|
||||
|
@ -160,6 +173,13 @@ class RubyGemTestCase < MiniTest::Unit::TestCase
|
|||
Gem::Installer.new(gem, :wrappers => true).install
|
||||
end
|
||||
|
||||
def mu_pp(obj)
|
||||
s = ''
|
||||
s = PP.pp obj, s
|
||||
s = s.force_encoding(Encoding.default_external) if defined? Encoding
|
||||
s.chomp
|
||||
end
|
||||
|
||||
def prep_cache_files(lc)
|
||||
@usr_si ||= Gem::SourceIndex.new
|
||||
@usr_sice ||= Gem::SourceInfoCacheEntry.new @usr_si, 0
|
||||
|
@ -254,10 +274,8 @@ class RubyGemTestCase < MiniTest::Unit::TestCase
|
|||
Gem::Builder.new(spec).build
|
||||
end
|
||||
|
||||
cache_dir = File.join(@gemhome, 'cache')
|
||||
FileUtils.mkdir_p cache_dir
|
||||
FileUtils.mv "#{spec.full_name}.gem",
|
||||
File.join(cache_dir, "#{spec.original_name}.gem")
|
||||
File.join(@gemhome, 'cache', "#{spec.original_name}.gem")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -294,14 +312,30 @@ class RubyGemTestCase < MiniTest::Unit::TestCase
|
|||
out.string
|
||||
end
|
||||
|
||||
def util_make_gems
|
||||
def util_make_gems(prerelease = false)
|
||||
@a1 = quick_gem 'a', '1' do |s|
|
||||
s.files = %w[lib/code.rb]
|
||||
s.require_paths = %w[lib]
|
||||
s.date = Gem::Specification::TODAY - 86400
|
||||
s.homepage = 'http://a.example.com'
|
||||
s.email = %w[example@example.com example2@example.com]
|
||||
s.authors = %w[Example Example2]
|
||||
s.description = <<-DESC
|
||||
This line is really, really long. So long, in fact, that it is more than eighty characters long! The purpose of this line is for testing wrapping behavior because sometimes people don't wrap their text to eighty characters. Without the wrapping, the text might not look good in the RSS feed.
|
||||
|
||||
Also, a list:
|
||||
* An entry that's actually kind of sort
|
||||
* an entry that's really long, which will probably get wrapped funny. That's ok, somebody wasn't thinking straight when they made it more than eighty characters.
|
||||
DESC
|
||||
end
|
||||
|
||||
init = proc do |s|
|
||||
s.files = %w[lib/code.rb]
|
||||
s.require_paths = %w[lib]
|
||||
end
|
||||
|
||||
@a1 = quick_gem('a', '1', &init)
|
||||
@a2 = quick_gem('a', '2', &init)
|
||||
@a3a = quick_gem('a', '3.a', &init)
|
||||
@a_evil9 = quick_gem('a_evil', '9', &init)
|
||||
@b2 = quick_gem('b', '2', &init)
|
||||
@c1_2 = quick_gem('c', '1.2', &init)
|
||||
|
@ -312,13 +346,23 @@ class RubyGemTestCase < MiniTest::Unit::TestCase
|
|||
s.instance_variable_set :@original_platform, 'i386-linux'
|
||||
end
|
||||
|
||||
if prerelease
|
||||
@a2_pre = quick_gem('a', '2.a', &init)
|
||||
write_file File.join(*%W[gems #{@a2_pre.original_name} lib code.rb]) do
|
||||
end
|
||||
util_build_gem @a2_pre
|
||||
end
|
||||
|
||||
write_file File.join(*%W[gems #{@a1.original_name} lib code.rb]) do end
|
||||
write_file File.join(*%W[gems #{@a2.original_name} lib code.rb]) do end
|
||||
write_file File.join(*%W[gems #{@a3a.original_name} lib code.rb]) do end
|
||||
write_file File.join(*%W[gems #{@b2.original_name} lib code.rb]) do end
|
||||
write_file File.join(*%W[gems #{@c1_2.original_name} lib code.rb]) do end
|
||||
write_file File.join(*%W[gems #{@pl1.original_name} lib code.rb]) do end
|
||||
|
||||
[@a1, @a2, @a_evil9, @b2, @c1_2, @pl1].each { |spec| util_build_gem spec }
|
||||
[@a1, @a2, @a3a, @a_evil9, @b2, @c1_2, @pl1].each do |spec|
|
||||
util_build_gem spec
|
||||
end
|
||||
|
||||
FileUtils.rm_r File.join(@gemhome, 'gems', @pl1.original_name)
|
||||
|
||||
|
@ -338,26 +382,28 @@ class RubyGemTestCase < MiniTest::Unit::TestCase
|
|||
platform
|
||||
end
|
||||
|
||||
def util_setup_fake_fetcher
|
||||
def util_setup_fake_fetcher(prerelease = false)
|
||||
require 'zlib'
|
||||
require 'socket'
|
||||
require 'rubygems/remote_fetcher'
|
||||
|
||||
@fetcher = Gem::FakeFetcher.new
|
||||
|
||||
util_make_gems
|
||||
util_make_gems(prerelease)
|
||||
|
||||
@all_gems = [@a1, @a2, @a_evil9, @b2, @c1_2].sort
|
||||
@all_gems = [@a1, @a2, @a3a, @a_evil9, @b2, @c1_2].sort
|
||||
@all_gem_names = @all_gems.map { |gem| gem.full_name }
|
||||
|
||||
gem_names = [@a1.full_name, @a2.full_name, @b2.full_name]
|
||||
gem_names = [@a1.full_name, @a2.full_name, @a3a.full_name, @b2.full_name]
|
||||
@gem_names = gem_names.sort.join("\n")
|
||||
|
||||
@source_index = Gem::SourceIndex.new
|
||||
@source_index.add_spec @a1
|
||||
@source_index.add_spec @a2
|
||||
@source_index.add_spec @a3a
|
||||
@source_index.add_spec @a_evil9
|
||||
@source_index.add_spec @c1_2
|
||||
@source_index.add_spec @a2_pre if prerelease
|
||||
|
||||
Gem::RemoteFetcher.fetcher = @fetcher
|
||||
end
|
||||
|
@ -400,7 +446,13 @@ class RubyGemTestCase < MiniTest::Unit::TestCase
|
|||
spec_fetcher.latest_specs[@uri] << spec_tuple
|
||||
end
|
||||
|
||||
si.gems.sort_by { |_,spec| spec }.each do |_, spec|
|
||||
spec_fetcher.prerelease_specs[@uri] = []
|
||||
si.prerelease_specs.sort.each do |spec|
|
||||
spec_tuple = [spec.name, spec.version, spec.original_platform]
|
||||
spec_fetcher.prerelease_specs[@uri] << spec_tuple
|
||||
end
|
||||
|
||||
(si.gems.merge si.prerelease_gems).sort_by { |_,spec| spec }.each do |_, spec|
|
||||
path = "#{@gem_repo}quick/Marshal.#{Gem.marshal_version}/#{spec.original_name}.gemspec.rz"
|
||||
data = Marshal.dump spec
|
||||
data_deflate = Zlib::Deflate.deflate data
|
||||
|
@ -422,6 +474,42 @@ class RubyGemTestCase < MiniTest::Unit::TestCase
|
|||
Gem.win_platform?
|
||||
end
|
||||
|
||||
# Returns whether or not we're on a version of Ruby built with VC++ (or
|
||||
# Borland) versus Cygwin, Mingw, etc.
|
||||
#
|
||||
def self.vc_windows?
|
||||
RUBY_PLATFORM.match('mswin')
|
||||
end
|
||||
|
||||
# Returns whether or not we're on a version of Ruby built with VC++ (or
|
||||
# Borland) versus Cygwin, Mingw, etc.
|
||||
#
|
||||
def vc_windows?
|
||||
RUBY_PLATFORM.match('mswin')
|
||||
end
|
||||
|
||||
# Returns the make command for the current platform. For versions of Ruby
|
||||
# built on MS Windows with VC++ or Borland it will return 'nmake'. On all
|
||||
# other platforms, including Cygwin, it will return 'make'.
|
||||
#
|
||||
def self.make_command
|
||||
vc_windows? ? 'nmake' : 'make'
|
||||
end
|
||||
|
||||
# Returns the make command for the current platform. For versions of Ruby
|
||||
# built on MS Windows with VC++ or Borland it will return 'nmake'. On all
|
||||
# other platforms, including Cygwin, it will return 'make'.
|
||||
#
|
||||
def make_command
|
||||
vc_windows? ? 'nmake' : 'make'
|
||||
end
|
||||
|
||||
# Returns whether or not the nmake command could be found.
|
||||
#
|
||||
def nmake_found?
|
||||
system('nmake /? 1>NUL 2>&1')
|
||||
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.
|
||||
|
|
|
@ -56,7 +56,8 @@ class MockGemUi < Gem::StreamUI
|
|||
def terminate_interaction(status=0)
|
||||
@terminated = true
|
||||
|
||||
raise TermError
|
||||
raise TermError unless status == 0
|
||||
raise Gem::SystemExitException, status
|
||||
end
|
||||
|
||||
end
|
||||
|
|
16
test/rubygems/rubygems_plugin.rb
Normal file
16
test/rubygems/rubygems_plugin.rb
Normal file
|
@ -0,0 +1,16 @@
|
|||
require 'rubygems/command_manager'
|
||||
|
||||
class Gem::Commands::InterruptCommand < Gem::Command
|
||||
|
||||
def initialize
|
||||
super('interrupt', 'Raises an Interrupt Exception', {})
|
||||
end
|
||||
|
||||
def execute
|
||||
raise Interrupt, "Interrupt exception"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
Gem::CommandManager.instance.register_command :interrupt
|
||||
|
|
@ -5,28 +5,24 @@
|
|||
#++
|
||||
|
||||
SIMPLE_GEM = <<-GEMDATA
|
||||
MD5SUM = "954df67d9475aa2f4fbba20aa33649c8"
|
||||
MD5SUM = "e3701f9db765a2358aef94c40ded71c8"
|
||||
if $0 == __FILE__
|
||||
require 'optparse'
|
||||
|
||||
options = {}
|
||||
ARGV.options do |opts|
|
||||
opts.on_tail("--help", "show this message") {puts opts; exit}
|
||||
opts.on('--dir=DIRNAME', "Installation directory for the Gem") {|x|
|
||||
options[:directory] = x
|
||||
}
|
||||
opts.on('--force', "Force Gem to intall, bypassing dependency checks") {|x|
|
||||
options[:force] = x
|
||||
}
|
||||
opts.on('--gen-rdoc', "Generate RDoc documentation for the Gem") {|x|
|
||||
options[:gen_rdoc] = x
|
||||
}
|
||||
opts.on('--dir=DIRNAME', "Installation directory for the Gem") {|options[:directory]|}
|
||||
opts.on('--force', "Force Gem to intall, bypassing dependency checks") {|options[:force]|}
|
||||
opts.on('--gen-rdoc', "Generate RDoc documentation for the Gem") {|options[:gen_rdoc]|}
|
||||
opts.parse!
|
||||
end
|
||||
|
||||
require 'rubygems/installer'
|
||||
require 'rubygems'
|
||||
@directory = options[:directory] || Gem.dir
|
||||
@force = options[:force]
|
||||
|
||||
gem = Gem::Installer.new(__FILE__, options).install
|
||||
gem = Gem::Installer.new(__FILE__).install(@force, @directory)
|
||||
if options[:gen_rdoc]
|
||||
Gem::DocManager.new(gem).generate_rdoc
|
||||
end
|
||||
|
|
|
@ -24,6 +24,7 @@ class TestGem < RubyGemTestCase
|
|||
expected = [
|
||||
File.join(@gemhome, *%W[gems #{@a1.full_name} lib]),
|
||||
File.join(@gemhome, *%W[gems #{@a2.full_name} lib]),
|
||||
File.join(@gemhome, *%W[gems #{@a3a.full_name} lib]),
|
||||
File.join(@gemhome, *%W[gems #{@a_evil9.full_name} lib]),
|
||||
File.join(@gemhome, *%W[gems #{@b2.full_name} lib]),
|
||||
File.join(@gemhome, *%W[gems #{@c1_2.full_name} lib]),
|
||||
|
@ -41,6 +42,56 @@ class TestGem < RubyGemTestCase
|
|||
assert(!Gem.available?("monkeys"))
|
||||
end
|
||||
|
||||
def test_self_bin_path_bin_name
|
||||
util_exec_gem
|
||||
assert_equal @abin_path, Gem.bin_path('a', 'abin')
|
||||
end
|
||||
|
||||
def test_self_bin_path_bin_name_version
|
||||
util_exec_gem
|
||||
assert_equal @abin_path, Gem.bin_path('a', 'abin', '4')
|
||||
end
|
||||
|
||||
def test_self_bin_path_name
|
||||
util_exec_gem
|
||||
assert_equal @exec_path, Gem.bin_path('a')
|
||||
end
|
||||
|
||||
def test_self_bin_path_name_version
|
||||
util_exec_gem
|
||||
assert_equal @exec_path, Gem.bin_path('a', nil, '4')
|
||||
end
|
||||
|
||||
def test_self_bin_path_no_default_bin
|
||||
quick_gem 'a', '2' do |s|
|
||||
s.executables = ['exec']
|
||||
end
|
||||
assert_raises(Gem::Exception) do
|
||||
Gem.bin_path('a', '2')
|
||||
end
|
||||
end
|
||||
|
||||
def test_self_bin_path_no_bin_file
|
||||
quick_gem 'a', '1'
|
||||
assert_raises(Gem::Exception) do
|
||||
Gem.bin_path('a', '1')
|
||||
end
|
||||
end
|
||||
|
||||
def test_self_bin_path_with_spaces
|
||||
quick_gem 'sp ace', '3' do |s|
|
||||
s.executables = ['exec']
|
||||
end
|
||||
path = Gem.bin_path('sp ace', 'exec')
|
||||
assert_equal %w(" "), [path[0,1], path[-1,1]], "Path should be escaped"
|
||||
end
|
||||
|
||||
def test_self_bin_path_not_found
|
||||
assert_raises(Gem::GemNotFoundException) do
|
||||
Gem.bin_path('non-existent')
|
||||
end
|
||||
end
|
||||
|
||||
def test_self_bindir
|
||||
assert_equal File.join(@gemhome, 'bin'), Gem.bindir
|
||||
assert_equal File.join(@gemhome, 'bin'), Gem.bindir(Gem.dir)
|
||||
|
@ -111,39 +162,30 @@ class TestGem < RubyGemTestCase
|
|||
end
|
||||
|
||||
def test_self_default_exec_format
|
||||
orig_BASERUBY = Gem::ConfigMap[:BASERUBY]
|
||||
orig_RUBY_INSTALL_NAME = Gem::ConfigMap[:RUBY_INSTALL_NAME]
|
||||
Gem::ConfigMap[:BASERUBY] = 'ruby'
|
||||
Gem::ConfigMap[:RUBY_INSTALL_NAME] = 'ruby'
|
||||
orig_RUBY_INSTALL_NAME = Gem::ConfigMap[:ruby_install_name]
|
||||
Gem::ConfigMap[:ruby_install_name] = 'ruby'
|
||||
|
||||
assert_equal '%s', Gem.default_exec_format
|
||||
ensure
|
||||
Gem::ConfigMap[:BASERUBY] = orig_BASERUBY
|
||||
Gem::ConfigMap[:RUBY_INSTALL_NAME] = orig_RUBY_INSTALL_NAME
|
||||
Gem::ConfigMap[:ruby_install_name] = orig_RUBY_INSTALL_NAME
|
||||
end
|
||||
|
||||
def test_self_default_exec_format_18
|
||||
orig_BASERUBY = Gem::ConfigMap[:BASERUBY]
|
||||
orig_RUBY_INSTALL_NAME = Gem::ConfigMap[:RUBY_INSTALL_NAME]
|
||||
Gem::ConfigMap[:BASERUBY] = 'ruby'
|
||||
Gem::ConfigMap[:RUBY_INSTALL_NAME] = 'ruby18'
|
||||
orig_RUBY_INSTALL_NAME = Gem::ConfigMap[:ruby_install_name]
|
||||
Gem::ConfigMap[:ruby_install_name] = 'ruby18'
|
||||
|
||||
assert_equal '%s18', Gem.default_exec_format
|
||||
ensure
|
||||
Gem::ConfigMap[:BASERUBY] = orig_BASERUBY
|
||||
Gem::ConfigMap[:RUBY_INSTALL_NAME] = orig_RUBY_INSTALL_NAME
|
||||
Gem::ConfigMap[:ruby_install_name] = orig_RUBY_INSTALL_NAME
|
||||
end
|
||||
|
||||
def test_self_default_exec_format_jruby
|
||||
orig_BASERUBY = Gem::ConfigMap[:BASERUBY]
|
||||
orig_RUBY_INSTALL_NAME = Gem::ConfigMap[:RUBY_INSTALL_NAME]
|
||||
Gem::ConfigMap[:BASERUBY] = 'ruby'
|
||||
Gem::ConfigMap[:RUBY_INSTALL_NAME] = 'jruby'
|
||||
orig_RUBY_INSTALL_NAME = Gem::ConfigMap[:ruby_install_name]
|
||||
Gem::ConfigMap[:ruby_install_name] = 'jruby'
|
||||
|
||||
assert_equal 'j%s', Gem.default_exec_format
|
||||
ensure
|
||||
Gem::ConfigMap[:BASERUBY] = orig_BASERUBY
|
||||
Gem::ConfigMap[:RUBY_INSTALL_NAME] = orig_RUBY_INSTALL_NAME
|
||||
Gem::ConfigMap[:ruby_install_name] = orig_RUBY_INSTALL_NAME
|
||||
end
|
||||
|
||||
def test_self_default_sources
|
||||
|
@ -166,7 +208,7 @@ class TestGem < RubyGemTestCase
|
|||
def test_self_ensure_gem_directories_missing_parents
|
||||
gemdir = File.join @tempdir, 'a/b/c/gemdir'
|
||||
FileUtils.rm_rf File.join(@tempdir, 'a') rescue nil
|
||||
assert !File.exist?(File.join(@tempdir, 'a')),
|
||||
refute File.exist?(File.join(@tempdir, 'a')),
|
||||
"manually remove #{File.join @tempdir, 'a'}, tests are broken"
|
||||
Gem.use_paths gemdir
|
||||
|
||||
|
@ -179,14 +221,14 @@ class TestGem < RubyGemTestCase
|
|||
def test_self_ensure_gem_directories_write_protected
|
||||
gemdir = File.join @tempdir, "egd"
|
||||
FileUtils.rm_r gemdir rescue nil
|
||||
assert !File.exist?(gemdir), "manually remove #{gemdir}, tests are broken"
|
||||
refute File.exist?(gemdir), "manually remove #{gemdir}, tests are broken"
|
||||
FileUtils.mkdir_p gemdir
|
||||
FileUtils.chmod 0400, gemdir
|
||||
Gem.use_paths gemdir
|
||||
|
||||
Gem.ensure_gem_subdirectories gemdir
|
||||
|
||||
assert !File.exist?("#{gemdir}/cache")
|
||||
refute File.exist?("#{gemdir}/cache")
|
||||
ensure
|
||||
FileUtils.chmod 0600, gemdir
|
||||
end
|
||||
|
@ -196,14 +238,14 @@ class TestGem < RubyGemTestCase
|
|||
gemdir = "#{parent}/a/b/c"
|
||||
|
||||
FileUtils.rm_r parent rescue nil
|
||||
assert !File.exist?(parent), "manually remove #{parent}, tests are broken"
|
||||
refute File.exist?(parent), "manually remove #{parent}, tests are broken"
|
||||
FileUtils.mkdir_p parent
|
||||
FileUtils.chmod 0400, parent
|
||||
Gem.use_paths(gemdir)
|
||||
|
||||
Gem.ensure_gem_subdirectories gemdir
|
||||
|
||||
assert !File.exist?("#{gemdir}/cache")
|
||||
refute File.exist?("#{gemdir}/cache")
|
||||
ensure
|
||||
FileUtils.chmod 0600, parent
|
||||
end
|
||||
|
@ -223,18 +265,20 @@ class TestGem < RubyGemTestCase
|
|||
end
|
||||
|
||||
def test_self_find_files
|
||||
discover_path = File.join 'lib', 'foo', 'discover.rb'
|
||||
|
||||
foo1 = quick_gem 'foo', '1' do |s|
|
||||
s.files << 'lib/foo/discover.rb'
|
||||
s.files << discover_path
|
||||
end
|
||||
|
||||
foo2 = quick_gem 'foo', '2' do |s|
|
||||
s.files << 'lib/foo/discover.rb'
|
||||
s.files << discover_path
|
||||
end
|
||||
|
||||
path = File.join 'gems', foo1.full_name, 'lib', 'foo', 'discover.rb'
|
||||
path = File.join 'gems', foo1.full_name, discover_path
|
||||
write_file(path) { |fp| fp.puts "# #{path}" }
|
||||
|
||||
path = File.join 'gems', foo2.full_name, 'lib', 'foo', 'discover.rb'
|
||||
path = File.join 'gems', foo2.full_name, discover_path
|
||||
write_file(path) { |fp| fp.puts "# #{path}" }
|
||||
|
||||
@fetcher = Gem::FakeFetcher.new
|
||||
|
@ -245,18 +289,19 @@ class TestGem < RubyGemTestCase
|
|||
Gem.searcher = nil
|
||||
|
||||
expected = [
|
||||
File.join(foo1.full_gem_path, 'lib', 'foo', 'discover.rb'),
|
||||
File.join(foo2.full_gem_path, 'lib', 'foo', 'discover.rb'),
|
||||
File.expand_path('foo/discover.rb', File.dirname(__FILE__)),
|
||||
File.join(foo2.full_gem_path, discover_path),
|
||||
File.join(foo1.full_gem_path, discover_path),
|
||||
]
|
||||
|
||||
assert_equal expected, Gem.find_files('foo/discover').sort
|
||||
assert_equal expected, Gem.find_files('foo/discover')
|
||||
end
|
||||
|
||||
def test_self_latest_load_paths
|
||||
util_make_gems
|
||||
|
||||
expected = [
|
||||
File.join(@gemhome, *%W[gems #{@a2.full_name} lib]),
|
||||
File.join(@gemhome, *%W[gems #{@a3a.full_name} lib]),
|
||||
File.join(@gemhome, *%W[gems #{@a_evil9.full_name} lib]),
|
||||
File.join(@gemhome, *%W[gems #{@b2.full_name} lib]),
|
||||
File.join(@gemhome, *%W[gems #{@c1_2.full_name} lib]),
|
||||
|
@ -298,7 +343,7 @@ class TestGem < RubyGemTestCase
|
|||
apple_gem_home = File.join @tempdir, 'apple_gem_home'
|
||||
Gem.const_set :APPLE_GEM_HOME, apple_gem_home
|
||||
|
||||
assert Gem.path.include?(apple_gem_home)
|
||||
assert_includes Gem.path, apple_gem_home
|
||||
ensure
|
||||
Gem.send :remove_const, :APPLE_GEM_HOME
|
||||
end
|
||||
|
@ -309,7 +354,7 @@ class TestGem < RubyGemTestCase
|
|||
apple_gem_home = File.join @tempdir, 'apple_gem_home'
|
||||
Gem.const_set :APPLE_GEM_HOME, apple_gem_home
|
||||
|
||||
assert !Gem.path.include?(apple_gem_home)
|
||||
refute Gem.path.include?(apple_gem_home)
|
||||
ensure
|
||||
Gem.send :remove_const, :APPLE_GEM_HOME
|
||||
end
|
||||
|
@ -404,13 +449,13 @@ class TestGem < RubyGemTestCase
|
|||
|
||||
FileUtils.mv a1_spec, @tempdir
|
||||
|
||||
assert !Gem.source_index.gems.include?(@a1.full_name)
|
||||
refute 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_includes Gem.source_index.gems, @a1.full_name
|
||||
assert_equal nil, Gem.instance_variable_get(:@searcher)
|
||||
end
|
||||
|
||||
|
@ -463,11 +508,28 @@ class TestGem < RubyGemTestCase
|
|||
Gem::ConfigMap[:EXEEXT] = orig_exe_ext
|
||||
end
|
||||
|
||||
def test_self_ruby_version
|
||||
version = RUBY_VERSION.dup
|
||||
version << ".#{RUBY_PATCHLEVEL}" if defined? RUBY_PATCHLEVEL
|
||||
def test_self_ruby_version_1_8_5
|
||||
util_set_RUBY_VERSION '1.8.5'
|
||||
|
||||
assert_equal Gem::Version.new(version), Gem.ruby_version
|
||||
assert_equal Gem::Version.new('1.8.5'), Gem.ruby_version
|
||||
ensure
|
||||
util_restore_RUBY_VERSION
|
||||
end
|
||||
|
||||
def test_self_ruby_version_1_8_6p287
|
||||
util_set_RUBY_VERSION '1.8.6', 287
|
||||
|
||||
assert_equal Gem::Version.new('1.8.6.287'), Gem.ruby_version
|
||||
ensure
|
||||
util_restore_RUBY_VERSION
|
||||
end
|
||||
|
||||
def test_self_ruby_version_1_9_2dev_r23493
|
||||
util_set_RUBY_VERSION '1.9.2', -1, 23493
|
||||
|
||||
assert_equal Gem::Version.new('1.9.2.dev.23493'), Gem.ruby_version
|
||||
ensure
|
||||
util_restore_RUBY_VERSION
|
||||
end
|
||||
|
||||
def test_self_searcher
|
||||
|
@ -478,13 +540,12 @@ class TestGem < RubyGemTestCase
|
|||
other = File.join @tempdir, 'other'
|
||||
path = [@userhome, other].join File::PATH_SEPARATOR
|
||||
Gem.send :set_paths, path
|
||||
path = Gem.path
|
||||
|
||||
assert_equal path[0], @userhome
|
||||
assert_equal path[1], other
|
||||
assert_equal [@userhome, other, @gemhome], Gem.path
|
||||
end
|
||||
|
||||
def test_self_set_paths_nonexistent_home
|
||||
ENV['GEM_HOME'] = @gemhome
|
||||
Gem.clear_paths
|
||||
|
||||
other = File.join @tempdir, 'other'
|
||||
|
@ -493,7 +554,7 @@ class TestGem < RubyGemTestCase
|
|||
|
||||
Gem.send :set_paths, other
|
||||
|
||||
refute File.exist?(File.join(other, 'gems'))
|
||||
assert_equal [other, @gemhome], Gem.path
|
||||
end
|
||||
|
||||
def test_self_source_index
|
||||
|
@ -538,6 +599,28 @@ class TestGem < RubyGemTestCase
|
|||
end
|
||||
end
|
||||
|
||||
def test_self_user_home_user_drive_and_path
|
||||
Gem.clear_paths
|
||||
|
||||
# safe-keep env variables
|
||||
orig_home, orig_user_profile = ENV['HOME'], ENV['USERPROFILE']
|
||||
orig_user_drive, orig_user_path = ENV['HOMEDRIVE'], ENV['HOMEPATH']
|
||||
|
||||
# prepare the environment
|
||||
ENV.delete('HOME')
|
||||
ENV.delete('USERPROFILE')
|
||||
ENV['HOMEDRIVE'] = 'Z:'
|
||||
ENV['HOMEPATH'] = '\\Users\\RubyUser'
|
||||
|
||||
assert_equal "Z:\\Users\\RubyUser", Gem.user_home
|
||||
|
||||
ensure
|
||||
ENV['HOME'] = orig_home
|
||||
ENV['USERPROFILE'] = orig_user_profile
|
||||
ENV['USERDRIVE'] = orig_user_drive
|
||||
ENV['USERPATH'] = orig_user_path
|
||||
end if '1.9' > RUBY_VERSION
|
||||
|
||||
def util_ensure_gem_dirs
|
||||
Gem.ensure_gem_subdirectories @gemhome
|
||||
@additional.each do |dir|
|
||||
|
@ -545,5 +628,46 @@ class TestGem < RubyGemTestCase
|
|||
end
|
||||
end
|
||||
|
||||
def util_exec_gem
|
||||
spec, _ = quick_gem 'a', '4' do |s|
|
||||
s.default_executable = 'exec'
|
||||
s.executables = ['exec', 'abin']
|
||||
end
|
||||
|
||||
@exec_path = File.join spec.full_gem_path, spec.bindir, 'exec'
|
||||
@abin_path = File.join spec.full_gem_path, spec.bindir, 'abin'
|
||||
end
|
||||
|
||||
def util_set_RUBY_VERSION(version, patchlevel = nil, revision = nil)
|
||||
if Gem.instance_variables.include? :@ruby_version or
|
||||
Gem.instance_variables.include? '@ruby_version' then
|
||||
Gem.send :remove_instance_variable, :@ruby_version
|
||||
end
|
||||
|
||||
@RUBY_VERSION = RUBY_VERSION
|
||||
@RUBY_PATCHLEVEL = RUBY_PATCHLEVEL if defined?(RUBY_PATCHLEVEL)
|
||||
@RUBY_REVISION = RUBY_REVISION if defined?(RUBY_REVISION)
|
||||
|
||||
Object.send :remove_const, :RUBY_VERSION
|
||||
Object.send :remove_const, :RUBY_PATCHLEVEL if defined?(RUBY_PATCHLEVEL)
|
||||
Object.send :remove_const, :RUBY_REVISION if defined?(RUBY_REVISION)
|
||||
|
||||
Object.const_set :RUBY_VERSION, version
|
||||
Object.const_set :RUBY_PATCHLEVEL, patchlevel if patchlevel
|
||||
Object.const_set :RUBY_REVISION, revision if revision
|
||||
end
|
||||
|
||||
def util_restore_RUBY_VERSION
|
||||
Object.send :remove_const, :RUBY_VERSION
|
||||
Object.send :remove_const, :RUBY_PATCHLEVEL if defined?(RUBY_PATCHLEVEL)
|
||||
Object.send :remove_const, :RUBY_REVISION if defined?(RUBY_REVISION)
|
||||
|
||||
Object.const_set :RUBY_VERSION, @RUBY_VERSION
|
||||
Object.const_set :RUBY_PATCHLEVEL, @RUBY_PATCHLEVEL if
|
||||
defined?(@RUBY_PATCHLEVEL)
|
||||
Object.const_set :RUBY_REVISION, @RUBY_REVISION if
|
||||
defined?(@RUBY_REVISION)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -55,16 +55,6 @@ class TestGemCommand < RubyGemTestCase
|
|||
assert_equal [], h
|
||||
end
|
||||
|
||||
def test_add_option_overlapping_common_and_local_options
|
||||
@cmd.add_option('-x', '--zip', 'BAD!') do end
|
||||
@cmd.add_option('-z', '--exe', 'BAD!') do end
|
||||
@cmd.add_option('-x', '--exe', 'BAD!') do end
|
||||
|
||||
assert_match %r|-x, --exe|, @cmd.parser.to_s
|
||||
refute_match %r|-z, --exe|, @cmd.parser.to_s
|
||||
refute_match %r|-x, --zip|, @cmd.parser.to_s
|
||||
end
|
||||
|
||||
def test_basic_accessors
|
||||
assert_equal "doit", @cmd.command
|
||||
assert_equal "gem doit", @cmd.program_name
|
||||
|
@ -182,9 +172,9 @@ class TestGemCommand < RubyGemTestCase
|
|||
assert @cmd.handles?(['--help', 'command'])
|
||||
assert @cmd.handles?(['-f', 'filename'])
|
||||
assert @cmd.handles?(['--file=filename'])
|
||||
assert ! @cmd.handles?(['-z'])
|
||||
assert ! @cmd.handles?(['-f'])
|
||||
assert ! @cmd.handles?(['--toothpaste'])
|
||||
refute @cmd.handles?(['-z'])
|
||||
refute @cmd.handles?(['-f'])
|
||||
refute @cmd.handles?(['--toothpaste'])
|
||||
|
||||
args = ['-h', 'command']
|
||||
@cmd.handles?(args)
|
||||
|
|
|
@ -7,29 +7,16 @@
|
|||
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
|
||||
require 'rubygems/command_manager'
|
||||
|
||||
class InterruptCommand < Gem::Command
|
||||
|
||||
def initialize
|
||||
super('interrupt', 'Raises an Interrupt Exception', {})
|
||||
end
|
||||
|
||||
def execute
|
||||
raise Interrupt, "Interrupt exception"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class TestGemCommandManager < RubyGemTestCase
|
||||
|
||||
def setup
|
||||
super
|
||||
|
||||
@command_manager = Gem::CommandManager.new
|
||||
@command_manager = Gem::CommandManager.instance
|
||||
end
|
||||
|
||||
def test_run_interrupt
|
||||
use_ui @ui do
|
||||
@command_manager.register_command :interrupt
|
||||
assert_raises MockGemUi::TermError do
|
||||
@command_manager.run 'interrupt'
|
||||
end
|
||||
|
|
|
@ -105,7 +105,7 @@ class TestGemCommandsCertCommand < RubyGemTestCase
|
|||
assert_equal "Removed '/CN=rubygems/DC=example/DC=com'\n", @ui.output
|
||||
assert_equal '', @ui.error
|
||||
|
||||
assert !File.exist?(@cert_file_name)
|
||||
refute File.exist?(@cert_file_name)
|
||||
end
|
||||
|
||||
def test_execute_sign
|
||||
|
|
|
@ -24,6 +24,27 @@ class TestGemCommandsContentsCommand < RubyGemTestCase
|
|||
assert_equal "", @ui.error
|
||||
end
|
||||
|
||||
def test_execute_all
|
||||
@cmd.options[:all] = true
|
||||
|
||||
quick_gem 'foo' do |gem|
|
||||
gem.files = %w[lib/foo.rb Rakefile]
|
||||
end
|
||||
|
||||
quick_gem 'bar' do |gem|
|
||||
gem.files = %w[lib/bar.rb Rakefile]
|
||||
end
|
||||
|
||||
use_ui @ui do
|
||||
@cmd.execute
|
||||
end
|
||||
|
||||
assert_match %r|lib/foo\.rb|, @ui.output
|
||||
assert_match %r|lib/bar\.rb|, @ui.output
|
||||
assert_match %r|Rakefile|, @ui.output
|
||||
assert_equal "", @ui.error
|
||||
end
|
||||
|
||||
def test_execute_bad_gem
|
||||
@cmd.options[:args] = %w[foo]
|
||||
|
||||
|
@ -75,6 +96,48 @@ class TestGemCommandsContentsCommand < RubyGemTestCase
|
|||
assert_equal "", @ui.error
|
||||
end
|
||||
|
||||
def test_execute_multiple
|
||||
@cmd.options[:args] = %w[foo bar]
|
||||
quick_gem 'foo' do |gem|
|
||||
gem.files = %w[lib/foo.rb Rakefile]
|
||||
end
|
||||
|
||||
quick_gem 'bar' do |gem|
|
||||
gem.files = %w[lib/bar.rb Rakefile]
|
||||
end
|
||||
|
||||
use_ui @ui do
|
||||
@cmd.execute
|
||||
end
|
||||
|
||||
assert_match %r|lib/foo\.rb|, @ui.output
|
||||
assert_match %r|lib/bar\.rb|, @ui.output
|
||||
assert_match %r|Rakefile|, @ui.output
|
||||
assert_equal "", @ui.error
|
||||
end
|
||||
|
||||
def test_execute_no_prefix
|
||||
@cmd.options[:args] = %w[foo]
|
||||
@cmd.options[:prefix] = false
|
||||
|
||||
quick_gem 'foo' do |gem|
|
||||
gem.files = %w[lib/foo.rb Rakefile]
|
||||
end
|
||||
|
||||
use_ui @ui do
|
||||
@cmd.execute
|
||||
end
|
||||
|
||||
expected = <<-EOF
|
||||
lib/foo.rb
|
||||
Rakefile
|
||||
EOF
|
||||
|
||||
assert_equal expected, @ui.output
|
||||
|
||||
assert_equal "", @ui.error
|
||||
end
|
||||
|
||||
def test_handle_options
|
||||
assert_equal false, @cmd.options[:lib_only]
|
||||
assert_equal [], @cmd.options[:specdirs]
|
||||
|
|
|
@ -24,7 +24,7 @@ class TestGemCommandsEnvironmentCommand < RubyGemTestCase
|
|||
assert_match %r|INSTALLATION DIRECTORY: #{Regexp.escape @gemhome}|,
|
||||
@ui.output
|
||||
assert_match %r|RUBYGEMS PREFIX: |, @ui.output
|
||||
assert_match %r|RUBY EXECUTABLE:.*#{Gem::ConfigMap[:RUBY_INSTALL_NAME]}|,
|
||||
assert_match %r|RUBY EXECUTABLE:.*#{Gem::ConfigMap[:ruby_install_name]}|,
|
||||
@ui.output
|
||||
assert_match %r|EXECUTABLE DIRECTORY:|, @ui.output
|
||||
assert_match %r|RUBYGEMS PLATFORMS:|, @ui.output
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
require 'minitest/unit'
|
||||
require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
|
||||
require 'rubygems/indexer'
|
||||
require 'rubygems/commands/generate_index_command'
|
||||
|
@ -28,5 +27,109 @@ class TestGemCommandsGenerateIndexCommand < RubyGemTestCase
|
|||
assert File.exist?(quick_index_rz), quick_index_rz
|
||||
end
|
||||
|
||||
def test_execute_rss_update
|
||||
@cmd.options[:update] = true
|
||||
@cmd.options[:rss_host] = 'example.com'
|
||||
@cmd.options[:rss_gems_host] = 'gems.example.com'
|
||||
|
||||
use_ui @ui do
|
||||
assert_raises MockGemUi::TermError do
|
||||
@cmd.execute
|
||||
end
|
||||
end
|
||||
|
||||
assert_equal "ERROR: --update not compatible with RSS generation\n",
|
||||
@ui.error
|
||||
assert_empty @ui.output
|
||||
end
|
||||
|
||||
def test_handle_options_directory
|
||||
return if win_platform?
|
||||
refute_equal '/nonexistent', @cmd.options[:directory]
|
||||
|
||||
@cmd.handle_options %w[--directory /nonexistent]
|
||||
|
||||
assert_equal '/nonexistent', @cmd.options[:directory]
|
||||
end
|
||||
|
||||
def test_handle_options_directory_windows
|
||||
return unless win_platform?
|
||||
|
||||
refute_equal '/nonexistent', @cmd.options[:directory]
|
||||
|
||||
@cmd.handle_options %w[--directory C:/nonexistent]
|
||||
|
||||
assert_equal 'C:/nonexistent', @cmd.options[:directory]
|
||||
end
|
||||
|
||||
def test_handle_options_invalid
|
||||
e = assert_raises OptionParser::InvalidOption do
|
||||
@cmd.handle_options %w[--no-modern --no-legacy]
|
||||
end
|
||||
|
||||
assert_equal 'invalid option: --no-legacy no indicies will be built',
|
||||
e.message
|
||||
|
||||
@cmd = Gem::Commands::GenerateIndexCommand.new
|
||||
e = assert_raises OptionParser::InvalidOption do
|
||||
@cmd.handle_options %w[--no-legacy --no-modern]
|
||||
end
|
||||
|
||||
assert_equal 'invalid option: --no-modern no indicies will be built',
|
||||
e.message
|
||||
end
|
||||
|
||||
def test_handle_options_legacy
|
||||
@cmd.handle_options %w[--legacy]
|
||||
|
||||
assert @cmd.options[:build_legacy]
|
||||
assert @cmd.options[:build_modern], ':build_modern not set'
|
||||
end
|
||||
|
||||
def test_handle_options_modern
|
||||
@cmd.handle_options %w[--modern]
|
||||
|
||||
assert @cmd.options[:build_legacy]
|
||||
assert @cmd.options[:build_modern], ':build_modern not set'
|
||||
end
|
||||
|
||||
def test_handle_options_no_legacy
|
||||
@cmd.handle_options %w[--no-legacy]
|
||||
|
||||
refute @cmd.options[:build_legacy]
|
||||
assert @cmd.options[:build_modern]
|
||||
end
|
||||
|
||||
def test_handle_options_no_modern
|
||||
@cmd.handle_options %w[--no-modern]
|
||||
|
||||
assert @cmd.options[:build_legacy]
|
||||
refute @cmd.options[:build_modern]
|
||||
end
|
||||
|
||||
def test_handle_options_rss_gems_host
|
||||
@cmd.handle_options %w[--rss-gems-host gems.example.com]
|
||||
|
||||
assert_equal 'gems.example.com', @cmd.options[:rss_gems_host]
|
||||
end
|
||||
|
||||
def test_handle_options_rss_host
|
||||
@cmd.handle_options %w[--rss-host example.com]
|
||||
|
||||
assert_equal 'example.com', @cmd.options[:rss_host]
|
||||
end
|
||||
|
||||
def test_handle_options_rss_title
|
||||
@cmd.handle_options %w[--rss-title Example\ Gems]
|
||||
|
||||
assert_equal 'Example Gems', @cmd.options[:rss_title]
|
||||
end
|
||||
|
||||
def test_handle_options_update
|
||||
@cmd.handle_options %w[--update]
|
||||
|
||||
assert @cmd.options[:update]
|
||||
end
|
||||
|
||||
end if ''.respond_to? :to_xs
|
||||
|
||||
|
|
|
@ -11,6 +11,52 @@ class TestGemCommandsInstallCommand < RubyGemTestCase
|
|||
@cmd.options[:generate_ri] = false
|
||||
end
|
||||
|
||||
def test_execute_exclude_prerelease
|
||||
util_setup_fake_fetcher(:prerelease)
|
||||
util_setup_spec_fetcher @a2, @a2_pre
|
||||
|
||||
@fetcher.data["#{@gem_repo}gems/#{@a2.full_name}.gem"] =
|
||||
read_binary(File.join(@gemhome, 'cache', "#{@a2.full_name}.gem"))
|
||||
@fetcher.data["#{@gem_repo}gems/#{@a2_pre.full_name}.gem"] =
|
||||
read_binary(File.join(@gemhome, 'cache', "#{@a2_pre.full_name}.gem"))
|
||||
|
||||
@cmd.options[:args] = [@a2.name]
|
||||
|
||||
use_ui @ui do
|
||||
e = assert_raises Gem::SystemExitException do
|
||||
@cmd.execute
|
||||
end
|
||||
assert_equal 0, e.exit_code, @ui.error
|
||||
end
|
||||
|
||||
assert_match(/Successfully installed #{@a2.full_name}$/, @ui.output)
|
||||
refute_match(/Successfully installed #{@a2_pre.full_name}$/, @ui.output)
|
||||
end
|
||||
|
||||
def test_execute_explicit_version_includes_prerelease
|
||||
util_setup_fake_fetcher(:prerelease)
|
||||
util_setup_spec_fetcher @a2, @a2_pre
|
||||
|
||||
@fetcher.data["#{@gem_repo}gems/#{@a2.full_name}.gem"] =
|
||||
read_binary(File.join(@gemhome, 'cache', "#{@a2.full_name}.gem"))
|
||||
@fetcher.data["#{@gem_repo}gems/#{@a2_pre.full_name}.gem"] =
|
||||
read_binary(File.join(@gemhome, 'cache', "#{@a2_pre.full_name}.gem"))
|
||||
|
||||
@cmd.handle_options [@a2_pre.name, '--version', @a2_pre.version.to_s]
|
||||
assert @cmd.options[:prerelease]
|
||||
assert @cmd.options[:version].satisfied_by?(@a2_pre.version)
|
||||
|
||||
use_ui @ui do
|
||||
e = assert_raises Gem::SystemExitException do
|
||||
@cmd.execute
|
||||
end
|
||||
assert_equal 0, e.exit_code, @ui.error
|
||||
end
|
||||
|
||||
refute_match(/Successfully installed #{@a2.full_name}$/, @ui.output)
|
||||
assert_match(/Successfully installed #{@a2_pre.full_name}$/, @ui.output)
|
||||
end
|
||||
|
||||
def test_execute_include_dependencies
|
||||
@cmd.options[:include_dependencies] = true
|
||||
@cmd.options[:args] = []
|
||||
|
@ -57,6 +103,34 @@ class TestGemCommandsInstallCommand < RubyGemTestCase
|
|||
assert out.empty?, out.inspect
|
||||
end
|
||||
|
||||
def test_no_user_install
|
||||
skip 'skipped on MS Windows (chmod has no effect)' if win_platform?
|
||||
|
||||
util_setup_fake_fetcher
|
||||
@cmd.options[:user_install] = false
|
||||
|
||||
FileUtils.mv File.join(@gemhome, 'cache', "#{@a2.full_name}.gem"),
|
||||
File.join(@tempdir)
|
||||
|
||||
@cmd.options[:args] = [@a2.name]
|
||||
|
||||
use_ui @ui do
|
||||
orig_dir = Dir.pwd
|
||||
begin
|
||||
File.chmod 0755, @userhome
|
||||
File.chmod 0555, @gemhome
|
||||
|
||||
Dir.chdir @tempdir
|
||||
assert_raises Gem::FilePermissionError do
|
||||
@cmd.execute
|
||||
end
|
||||
ensure
|
||||
Dir.chdir orig_dir
|
||||
File.chmod 0755, @gemhome
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_execute_local_missing
|
||||
util_setup_fake_fetcher
|
||||
@cmd.options[:domain] = :local
|
||||
|
@ -100,6 +174,29 @@ class TestGemCommandsInstallCommand < RubyGemTestCase
|
|||
@ui.error
|
||||
end
|
||||
|
||||
def test_execute_prerelease
|
||||
util_setup_fake_fetcher(:prerelease)
|
||||
util_setup_spec_fetcher @a2, @a2_pre
|
||||
|
||||
@fetcher.data["#{@gem_repo}gems/#{@a2.full_name}.gem"] =
|
||||
read_binary(File.join(@gemhome, 'cache', "#{@a2.full_name}.gem"))
|
||||
@fetcher.data["#{@gem_repo}gems/#{@a2_pre.full_name}.gem"] =
|
||||
read_binary(File.join(@gemhome, 'cache', "#{@a2_pre.full_name}.gem"))
|
||||
|
||||
@cmd.options[:prerelease] = true
|
||||
@cmd.options[:args] = [@a2_pre.name]
|
||||
|
||||
use_ui @ui do
|
||||
e = assert_raises Gem::SystemExitException do
|
||||
@cmd.execute
|
||||
end
|
||||
assert_equal 0, e.exit_code, @ui.error
|
||||
end
|
||||
|
||||
refute_match(/Successfully installed #{@a2.full_name}$/, @ui.output)
|
||||
assert_match(/Successfully installed #{@a2_pre.full_name}$/, @ui.output)
|
||||
end
|
||||
|
||||
def test_execute_remote
|
||||
@cmd.options[:generate_rdoc] = true
|
||||
@cmd.options[:generate_ri] = true
|
||||
|
@ -112,17 +209,10 @@ class TestGemCommandsInstallCommand < RubyGemTestCase
|
|||
|
||||
@cmd.options[:args] = [@a2.name]
|
||||
|
||||
err = ""
|
||||
class << err
|
||||
alias write <<
|
||||
end
|
||||
use_ui @ui do
|
||||
e = assert_raises Gem::SystemExitException do
|
||||
stderr, $stderr = $stderr, err
|
||||
begin
|
||||
capture_io do
|
||||
@cmd.execute
|
||||
ensure
|
||||
$stderr = stderr
|
||||
end
|
||||
end
|
||||
assert_equal 0, e.exit_code
|
||||
|
@ -136,7 +226,6 @@ class TestGemCommandsInstallCommand < RubyGemTestCase
|
|||
assert_equal "Installing RDoc documentation for #{@a2.full_name}...",
|
||||
out.shift
|
||||
assert out.empty?, out.inspect
|
||||
assert_match /^Updating class cache with \d+ classes/, err
|
||||
end
|
||||
|
||||
def test_execute_two
|
||||
|
|
|
@ -35,7 +35,7 @@ class TestGemCommandsPristineCommand < RubyGemTestCase
|
|||
|
||||
assert_equal "Restoring gem(s) to pristine condition...", out.shift
|
||||
assert_equal "Restored #{a.full_name}", out.shift
|
||||
assert out.empty?, out.inspect
|
||||
assert_empty out, out.inspect
|
||||
end
|
||||
|
||||
def test_execute_all
|
||||
|
@ -63,7 +63,7 @@ class TestGemCommandsPristineCommand < RubyGemTestCase
|
|||
|
||||
assert_equal "Restoring gem(s) to pristine condition...", out.shift
|
||||
assert_equal "Restored #{a.full_name}", out.shift
|
||||
assert out.empty?, out.inspect
|
||||
assert_empty out, out.inspect
|
||||
end
|
||||
|
||||
def test_execute_missing_cache_gem
|
||||
|
@ -86,7 +86,7 @@ class TestGemCommandsPristineCommand < RubyGemTestCase
|
|||
out = @ui.output.split "\n"
|
||||
|
||||
assert_equal "Restoring gem\(s\) to pristine condition...", out.shift
|
||||
assert out.empty?, out.inspect
|
||||
assert_empty out, out.inspect
|
||||
|
||||
assert_equal "ERROR: Cached gem for #{a.full_name} not found, use `gem install` to restore\n",
|
||||
@ui.error
|
||||
|
|
|
@ -10,7 +10,7 @@ class TestGemCommandsQueryCommand < RubyGemTestCase
|
|||
|
||||
util_setup_fake_fetcher
|
||||
|
||||
@si = util_setup_spec_fetcher @a1, @a2, @pl1
|
||||
@si = util_setup_spec_fetcher @a1, @a2, @pl1, @a3a
|
||||
|
||||
@fetcher.data["#{@gem_repo}Marshal.#{Gem.marshal_version}"] = proc do
|
||||
raise Gem::RemoteFetcher::FetchError
|
||||
|
@ -85,6 +85,51 @@ a (2)
|
|||
This is a lot of text.
|
||||
|
||||
pl (1)
|
||||
Platform: i386-linux
|
||||
Author: A User
|
||||
Homepage: http://example.com
|
||||
|
||||
this is a summary
|
||||
EOF
|
||||
|
||||
assert_equal expected, @ui.output
|
||||
assert_equal '', @ui.error
|
||||
end
|
||||
|
||||
def test_execute_details_platform
|
||||
@a1.platform = 'x86-linux'
|
||||
|
||||
@a2.summary = 'This is a lot of text. ' * 4
|
||||
@a2.authors = ['Abraham Lincoln', 'Hirohito']
|
||||
@a2.homepage = 'http://a.example.com/'
|
||||
@a2.rubyforge_project = 'rubygems'
|
||||
@a2.platform = 'universal-darwin'
|
||||
|
||||
@si = util_setup_spec_fetcher @a1, @a2, @pl1
|
||||
|
||||
@cmd.handle_options %w[-r -d]
|
||||
|
||||
use_ui @ui do
|
||||
@cmd.execute
|
||||
end
|
||||
|
||||
expected = <<-EOF
|
||||
|
||||
*** REMOTE GEMS ***
|
||||
|
||||
a (2, 1)
|
||||
Platforms:
|
||||
1: x86-linux
|
||||
2: universal-darwin
|
||||
Authors: Abraham Lincoln, Hirohito
|
||||
Rubyforge: http://rubyforge.org/projects/rubygems
|
||||
Homepage: http://a.example.com/
|
||||
|
||||
This is a lot of text. This is a lot of text. This is a lot of text.
|
||||
This is a lot of text.
|
||||
|
||||
pl (1)
|
||||
Platform: i386-linux
|
||||
Author: A User
|
||||
Homepage: http://example.com
|
||||
|
||||
|
@ -207,11 +252,30 @@ RubyGems will revert to legacy indexes degrading performance.
|
|||
assert_equal expected, @ui.error
|
||||
end
|
||||
|
||||
def test_execute_legacy_prerelease
|
||||
Gem::SpecFetcher.fetcher = nil
|
||||
si = util_setup_source_info_cache @a1, @a2, @pl1
|
||||
|
||||
@fetcher.data["#{@gem_repo}yaml"] = YAML.dump si
|
||||
@fetcher.data["#{@gem_repo}Marshal.#{Gem.marshal_version}"] =
|
||||
si.dump
|
||||
|
||||
@fetcher.data.delete "#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"
|
||||
|
||||
@cmd.handle_options %w[-r --prerelease]
|
||||
|
||||
e = assert_raises Gem::OperationNotSupportedError do
|
||||
@cmd.execute
|
||||
end
|
||||
|
||||
assert_equal 'Prereleases not supported on legacy repositories', e.message
|
||||
end
|
||||
|
||||
def test_execute_local_details
|
||||
@a2.summary = 'This is a lot of text. ' * 4
|
||||
@a2.authors = ['Abraham Lincoln', 'Hirohito']
|
||||
@a2.homepage = 'http://a.example.com/'
|
||||
@a2.rubyforge_project = 'rubygems'
|
||||
@a3a.summary = 'This is a lot of text. ' * 4
|
||||
@a3a.authors = ['Abraham Lincoln', 'Hirohito']
|
||||
@a3a.homepage = 'http://a.example.com/'
|
||||
@a3a.rubyforge_project = 'rubygems'
|
||||
|
||||
@cmd.handle_options %w[--local --details]
|
||||
|
||||
|
@ -223,10 +287,11 @@ RubyGems will revert to legacy indexes degrading performance.
|
|||
|
||||
*** LOCAL GEMS ***
|
||||
|
||||
a (2, 1)
|
||||
a (3.a, 2, 1)
|
||||
Author: A User
|
||||
Homepage: http://example.com
|
||||
Installed at (2): #{@gemhome}
|
||||
Installed at (3.a): #{@gemhome}
|
||||
(2): #{@gemhome}
|
||||
(1): #{@gemhome}
|
||||
|
||||
this is a summary
|
||||
|
@ -253,6 +318,7 @@ c (1.2)
|
|||
this is a summary
|
||||
|
||||
pl (1)
|
||||
Platform: i386-linux
|
||||
Author: A User
|
||||
Homepage: http://example.com
|
||||
Installed at: #{@gemhome}
|
||||
|
@ -274,7 +340,7 @@ pl (1)
|
|||
end
|
||||
|
||||
expected = <<-EOF
|
||||
a (2, 1)
|
||||
a (3.a, 2, 1)
|
||||
a_evil (9)
|
||||
b (2)
|
||||
c (1.2)
|
||||
|
@ -322,5 +388,45 @@ pl (1)
|
|||
assert_equal '', @ui.error
|
||||
end
|
||||
|
||||
def test_execute_prerelease
|
||||
@cmd.handle_options %w[-r --prerelease]
|
||||
|
||||
use_ui @ui do
|
||||
@cmd.execute
|
||||
end
|
||||
|
||||
expected = <<-EOF
|
||||
|
||||
*** REMOTE GEMS ***
|
||||
|
||||
a (3.a)
|
||||
EOF
|
||||
|
||||
assert_equal expected, @ui.output
|
||||
assert_equal '', @ui.error
|
||||
end
|
||||
|
||||
def test_execute_prerelease_local
|
||||
@cmd.handle_options %w[-l --prerelease]
|
||||
|
||||
use_ui @ui do
|
||||
@cmd.execute
|
||||
end
|
||||
|
||||
expected = <<-EOF
|
||||
|
||||
*** LOCAL GEMS ***
|
||||
|
||||
a (3.a, 2, 1)
|
||||
a_evil (9)
|
||||
b (2)
|
||||
c (1.2)
|
||||
pl (1)
|
||||
EOF
|
||||
|
||||
assert_equal expected, @ui.output
|
||||
assert_equal "WARNING: prereleases are always shown locally\n", @ui.error
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -22,5 +22,31 @@ class TestGemCommandsServerCommand < RubyGemTestCase
|
|||
assert_equal File.expand_path('/nonexistent'), @cmd.options[:gemdir]
|
||||
assert_equal 9999, @cmd.options[:port]
|
||||
end
|
||||
|
||||
def test_handle_options_port
|
||||
@cmd.send :handle_options, %w[-p 0]
|
||||
assert_equal 0, @cmd.options[:port]
|
||||
|
||||
@cmd.send :handle_options, %w[-p 65535]
|
||||
assert_equal 65535, @cmd.options[:port]
|
||||
|
||||
@cmd.send :handle_options, %w[-p http]
|
||||
assert_equal 80, @cmd.options[:port]
|
||||
|
||||
e = assert_raises OptionParser::InvalidArgument do
|
||||
@cmd.send :handle_options, %w[-p nonexistent]
|
||||
end
|
||||
|
||||
assert_equal 'invalid argument: -p nonexistent: no such named service',
|
||||
e.message
|
||||
|
||||
e = assert_raises OptionParser::InvalidArgument do
|
||||
@cmd.send :handle_options, %w[-p 65536]
|
||||
end
|
||||
|
||||
assert_equal 'invalid argument: -p 65536: not a port number',
|
||||
e.message
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -11,6 +11,10 @@ class TestGemCommandsSourcesCommand < RubyGemTestCase
|
|||
@new_repo = "http://beta-gems.example.com"
|
||||
end
|
||||
|
||||
def test_initialize_proxy
|
||||
assert @cmd.handles?(['--http-proxy', 'http://proxy.example.com'])
|
||||
end
|
||||
|
||||
def test_execute
|
||||
util_setup_spec_fetcher
|
||||
@cmd.handle_options []
|
||||
|
@ -175,12 +179,12 @@ Will cause RubyGems to revert to legacy indexes, degrading performance.
|
|||
assert_equal expected, @ui.output
|
||||
assert_equal '', @ui.error
|
||||
|
||||
assert !File.exist?(cache.system_cache_file),
|
||||
refute File.exist?(cache.system_cache_file),
|
||||
'system cache file'
|
||||
assert !File.exist?(cache.latest_system_cache_file),
|
||||
refute File.exist?(cache.latest_system_cache_file),
|
||||
'latest system cache file'
|
||||
|
||||
assert !File.exist?(fetcher.dir), 'cache dir removed'
|
||||
refute File.exist?(fetcher.dir), 'cache dir removed'
|
||||
end
|
||||
|
||||
def test_execute_remove
|
||||
|
|
|
@ -70,6 +70,34 @@ class TestGemCommandsSpecificationCommand < RubyGemTestCase
|
|||
assert_equal '', @ui.error
|
||||
end
|
||||
|
||||
def test_execute_field
|
||||
foo = quick_gem 'foo'
|
||||
Gem.source_index.add_spec foo
|
||||
|
||||
@cmd.options[:args] = %w[foo name]
|
||||
|
||||
use_ui @ui do
|
||||
@cmd.execute
|
||||
end
|
||||
|
||||
assert_equal "--- foo\n\n", @ui.output
|
||||
end
|
||||
|
||||
def test_execute_marshal
|
||||
foo = quick_gem 'foo'
|
||||
Gem.source_index.add_spec foo
|
||||
|
||||
@cmd.options[:args] = %w[foo]
|
||||
@cmd.options[:format] = :marshal
|
||||
|
||||
use_ui @ui do
|
||||
@cmd.execute
|
||||
end
|
||||
|
||||
assert_equal foo, Marshal.load(@ui.output)
|
||||
assert_equal '', @ui.error
|
||||
end
|
||||
|
||||
def test_execute_remote
|
||||
foo = quick_gem 'foo'
|
||||
|
||||
|
@ -92,5 +120,21 @@ class TestGemCommandsSpecificationCommand < RubyGemTestCase
|
|||
assert_match %r|name: foo|, @ui.output
|
||||
end
|
||||
|
||||
def test_execute_ruby
|
||||
foo = quick_gem 'foo'
|
||||
Gem.source_index.add_spec foo
|
||||
|
||||
@cmd.options[:args] = %w[foo]
|
||||
@cmd.options[:format] = :ruby
|
||||
|
||||
use_ui @ui do
|
||||
@cmd.execute
|
||||
end
|
||||
|
||||
assert_match %r|Gem::Specification.new|, @ui.output
|
||||
assert_match %r|s.name = %q\{foo\}|, @ui.output
|
||||
assert_equal '', @ui.error
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -53,9 +53,10 @@ class TestGemCommandsUninstallCommand < GemInstallerTestCase
|
|||
end
|
||||
end
|
||||
|
||||
assert_match(/\AUnknown gem foo >= 0$/, e.message)
|
||||
assert_match(/\Acannot uninstall, check `gem list -d foo`$/, e.message)
|
||||
output = @ui.output.split "\n"
|
||||
assert output.empty?, "UI output should be empty after an uninstall error"
|
||||
end
|
||||
assert_empty output, "UI output should be empty after an uninstall error"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ class TestGemCommandsUnpackCommand < RubyGemTestCase
|
|||
def test_execute
|
||||
util_make_gems
|
||||
|
||||
@cmd.options[:args] = %w[a]
|
||||
@cmd.options[:args] = %w[a b]
|
||||
|
||||
use_ui @ui do
|
||||
Dir.chdir @tempdir do
|
||||
|
@ -22,7 +22,8 @@ class TestGemCommandsUnpackCommand < RubyGemTestCase
|
|||
end
|
||||
end
|
||||
|
||||
assert File.exist?(File.join(@tempdir, 'a-2'))
|
||||
assert File.exist?(File.join(@tempdir, 'a-3.a')), 'a should be installed'
|
||||
assert File.exist?(File.join(@tempdir, 'b-2')), 'b should be installed'
|
||||
end
|
||||
|
||||
def test_execute_gem_path
|
||||
|
@ -43,7 +44,7 @@ class TestGemCommandsUnpackCommand < RubyGemTestCase
|
|||
end
|
||||
end
|
||||
|
||||
assert File.exist?(File.join(@tempdir, 'a-2'))
|
||||
assert File.exist?(File.join(@tempdir, 'a-3.a'))
|
||||
end
|
||||
|
||||
def test_execute_gem_path_missing
|
||||
|
@ -80,7 +81,7 @@ class TestGemCommandsUnpackCommand < RubyGemTestCase
|
|||
end
|
||||
end
|
||||
|
||||
assert File.exist?(File.join(@tempdir, target, 'a-2'))
|
||||
assert File.exist?(File.join(@tempdir, target, 'a-3.a'))
|
||||
end
|
||||
|
||||
def test_execute_exact_match
|
||||
|
|
|
@ -8,6 +8,9 @@ class TestGemCommandsUpdateCommand < RubyGemTestCase
|
|||
|
||||
@cmd = Gem::Commands::UpdateCommand.new
|
||||
|
||||
@cmd.options[:generate_rdoc] = false
|
||||
@cmd.options[:generate_ri] = false
|
||||
|
||||
util_setup_fake_fetcher
|
||||
|
||||
@a1_path = File.join @gemhome, 'cache', "#{@a1.full_name}.gem"
|
||||
|
@ -27,6 +30,8 @@ class TestGemCommandsUpdateCommand < RubyGemTestCase
|
|||
Gem::Installer.new(@a1_path).install
|
||||
|
||||
@cmd.options[:args] = []
|
||||
@cmd.options[:generate_rdoc] = true
|
||||
@cmd.options[:generate_ri] = true
|
||||
|
||||
use_ui @ui do
|
||||
@cmd.execute
|
||||
|
@ -37,8 +42,10 @@ class TestGemCommandsUpdateCommand < RubyGemTestCase
|
|||
assert_equal "Updating #{@a2.name}", out.shift
|
||||
assert_equal "Successfully installed #{@a2.full_name}", out.shift
|
||||
assert_equal "Gems updated: #{@a2.name}", out.shift
|
||||
assert_equal "Installing ri documentation for a-2...", out.shift
|
||||
assert_equal "Installing RDoc documentation for a-2...", out.shift
|
||||
|
||||
assert out.empty?, out.inspect
|
||||
assert_empty out
|
||||
end
|
||||
|
||||
# before:
|
||||
|
@ -101,7 +108,7 @@ class TestGemCommandsUpdateCommand < RubyGemTestCase
|
|||
assert_equal "Gems updated: #{@c2.name}, #{@b2.name}, #{@a2.name}",
|
||||
out.shift
|
||||
|
||||
assert out.empty?, out.inspect
|
||||
assert_empty out
|
||||
end
|
||||
|
||||
def test_execute_named
|
||||
|
@ -121,7 +128,7 @@ class TestGemCommandsUpdateCommand < RubyGemTestCase
|
|||
assert_equal "Successfully installed #{@a2.full_name}", out.shift
|
||||
assert_equal "Gems updated: #{@a2.name}", out.shift
|
||||
|
||||
assert out.empty?, out.inspect
|
||||
assert_empty out
|
||||
end
|
||||
|
||||
def test_execute_named_up_to_date
|
||||
|
@ -139,7 +146,7 @@ class TestGemCommandsUpdateCommand < RubyGemTestCase
|
|||
assert_equal "Updating installed gems", out.shift
|
||||
assert_equal "Nothing to update", out.shift
|
||||
|
||||
assert out.empty?, out.inspect
|
||||
assert_empty out
|
||||
end
|
||||
|
||||
def test_execute_up_to_date
|
||||
|
@ -157,8 +164,6 @@ class TestGemCommandsUpdateCommand < RubyGemTestCase
|
|||
assert_equal "Updating installed gems", out.shift
|
||||
assert_equal "Nothing to update", out.shift
|
||||
|
||||
assert out.empty?, out.inspect
|
||||
assert_empty out
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -20,6 +20,10 @@ class TestGemDependency < RubyGemTestCase
|
|||
@r1_0 = Gem::Requirement.new ['> 1.0']
|
||||
end
|
||||
|
||||
def dep(name, version)
|
||||
Gem::Dependency.new name, version
|
||||
end
|
||||
|
||||
def test_initialize
|
||||
assert_equal "pkg", @pkg1_0.name
|
||||
assert_equal @r1_0, @pkg1_0.version_requirements
|
||||
|
@ -96,10 +100,6 @@ class TestGemDependency < RubyGemTestCase
|
|||
end
|
||||
|
||||
def test_equals_tilde
|
||||
def dep(name, version)
|
||||
Gem::Dependency.new name, version
|
||||
end
|
||||
|
||||
a0 = dep 'a', '0'
|
||||
a1 = dep 'a', '1'
|
||||
b0 = dep 'b', '0'
|
||||
|
@ -108,14 +108,64 @@ class TestGemDependency < RubyGemTestCase
|
|||
pa0r = dep(/a/, '>= 0')
|
||||
pab0r = dep(/a|b/, '>= 0')
|
||||
|
||||
assert((a0 =~ a0), 'match self')
|
||||
assert((pa0 =~ a0), 'match version exact')
|
||||
assert((pa0 =~ a1), 'match version')
|
||||
assert((pa0r =~ a0), 'match regex simple')
|
||||
assert((pab0r =~ a0), 'match regex complex')
|
||||
assert_match a0, a0, 'match self'
|
||||
assert_match pa0, a0, 'match version exact'
|
||||
assert_match pa0, a1, 'match version'
|
||||
assert_match pa0r, a0, 'match regex simple'
|
||||
assert_match pab0r, a0, 'match regex complex'
|
||||
|
||||
assert(!(pa0r =~ b0), 'fail match regex')
|
||||
assert(!(pa0r =~ Object.new), 'fail match Object')
|
||||
refute_match pa0r, b0, 'fail match regex'
|
||||
refute_match pa0r, Object.new, 'fail match Object'
|
||||
end
|
||||
|
||||
def test_equals_tilde_escape
|
||||
a1 = Gem::Dependency.new 'a', '1'
|
||||
|
||||
pab1 = Gem::Dependency.new 'a|b', '>= 1'
|
||||
pab1r = Gem::Dependency.new(/a|b/, '>= 1')
|
||||
|
||||
refute_match pab1, a1, 'escaped'
|
||||
assert_match pab1r, a1, 'exact regexp'
|
||||
end
|
||||
|
||||
def test_equals_tilde_object
|
||||
a0 = Object.new
|
||||
|
||||
def a0.name() 'a' end
|
||||
def a0.version() '0' end
|
||||
|
||||
pa0 = Gem::Dependency.new 'a', '>= 0'
|
||||
|
||||
assert_match pa0, a0, 'match version exact'
|
||||
end
|
||||
|
||||
def test_equals_tilde_spec
|
||||
def spec(name, version)
|
||||
Gem::Specification.new do |spec|
|
||||
spec.name = name
|
||||
spec.version = version
|
||||
end
|
||||
end
|
||||
|
||||
a0 = spec 'a', '0'
|
||||
a1 = spec 'a', '1'
|
||||
b0 = spec 'b', '0'
|
||||
|
||||
pa0 = dep 'a', '>= 0'
|
||||
pa0r = dep(/a/, '>= 0')
|
||||
pab0r = dep(/a|b/, '>= 0')
|
||||
|
||||
assert_match pa0, a0, 'match version exact'
|
||||
assert_match pa0, a1, 'match version'
|
||||
|
||||
assert_match pa0r, a0, 'match regex simple'
|
||||
assert_match pa0r, a1, 'match regex simple'
|
||||
|
||||
assert_match pab0r, a0, 'match regex complex'
|
||||
assert_match pab0r, b0, 'match regex complex'
|
||||
|
||||
refute_match pa0r, b0, 'fail match regex'
|
||||
refute_match pa0r, Object.new, 'fail match Object'
|
||||
end
|
||||
|
||||
def test_hash
|
||||
|
@ -135,5 +185,6 @@ class TestGemDependency < RubyGemTestCase
|
|||
|
||||
refute_equal(runtime.hash, development.hash)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -13,8 +13,10 @@ class TestGemDependencyInstaller < RubyGemTestCase
|
|||
write_file File.join('gems', 'a-1', 'bin', 'a_bin') do |fp|
|
||||
fp.puts "#!/usr/bin/ruby"
|
||||
end
|
||||
|
||||
@a1, @a1_gem = util_gem 'a', '1' do |s| s.executables << 'a_bin' end
|
||||
@aa1, @aa1_gem = util_gem 'aa', '1'
|
||||
@a1_pre, @a1_pre_gem = util_gem 'a', '1.a'
|
||||
|
||||
@b1, @b1_gem = util_gem 'b', '1' do |s|
|
||||
s.add_dependency 'a'
|
||||
|
@ -44,8 +46,8 @@ class TestGemDependencyInstaller < RubyGemTestCase
|
|||
@fetcher = Gem::FakeFetcher.new
|
||||
Gem::RemoteFetcher.fetcher = @fetcher
|
||||
|
||||
si = util_setup_spec_fetcher @a1, @b1, @d1, @d2, @x1_m, @x1_o, @w1, @y1,
|
||||
@y1_1_p, @z1
|
||||
si = util_setup_spec_fetcher(@a1, @a1_pre, @b1, @d1, @d2, @x1_m, @x1_o, @w1, @y1,
|
||||
@y1_1_p, @z1)
|
||||
|
||||
util_clear_gems
|
||||
end
|
||||
|
@ -257,7 +259,7 @@ class TestGemDependencyInstaller < RubyGemTestCase
|
|||
inst.install 'a'
|
||||
end
|
||||
|
||||
assert_match %r|\A#!/\S+/env #{Gem::ConfigMap[:RUBY_INSTALL_NAME]}\n|,
|
||||
assert_match %r|\A#!/\S+/env #{Gem::ConfigMap[:ruby_install_name]}\n|,
|
||||
File.read(File.join(@gemhome, 'bin', 'a_bin'))
|
||||
end
|
||||
|
||||
|
@ -356,13 +358,15 @@ class TestGemDependencyInstaller < RubyGemTestCase
|
|||
FileUtils.mv @b1_gem, @tempdir
|
||||
inst = nil
|
||||
|
||||
Gem.source_index.gems.delete @a1.full_name
|
||||
Gem.source_index.remove_spec @a1.full_name
|
||||
Gem.source_index.remove_spec @a1_pre.full_name
|
||||
|
||||
Dir.chdir @tempdir do
|
||||
e = assert_raises Gem::InstallError do
|
||||
inst = Gem::DependencyInstaller.new :domain => :local
|
||||
inst.install 'b'
|
||||
end
|
||||
|
||||
assert_equal 'b requires a (>= 0, runtime)', e.message
|
||||
end
|
||||
|
||||
|
@ -632,5 +636,16 @@ class TestGemDependencyInstaller < RubyGemTestCase
|
|||
assert_equal %w[d-1 e-1], inst.gems_to_install.map { |s| s.full_name }
|
||||
end
|
||||
|
||||
end
|
||||
def test_prerelease_uses_pre_index
|
||||
installer = Gem::DependencyInstaller.new
|
||||
pre_installer = Gem::DependencyInstaller.new(:prerelease => true)
|
||||
dependency = Gem::Dependency.new('a', Gem::Requirement.default)
|
||||
|
||||
releases = installer.find_gems_with_sources(dependency).map{ |gems, *| gems }
|
||||
prereleases = pre_installer.find_gems_with_sources(dependency).map{ |gems, *| gems }
|
||||
|
||||
assert releases.select{ |s| s.name == 'a' and s.version.to_s == '1' }.first
|
||||
assert releases.select{ |s| s.name == 'a' and s.version.to_s == '1.a' }.empty?
|
||||
assert_equal [@a1_pre], prereleases
|
||||
end
|
||||
end
|
||||
|
|
|
@ -105,7 +105,7 @@ class TestGemDependencyList < RubyGemTestCase
|
|||
|
||||
@deplist.add @b2
|
||||
|
||||
assert ! @deplist.ok?, 'unsatisfied dependency'
|
||||
refute @deplist.ok?, 'unsatisfied dependency'
|
||||
|
||||
@deplist.add @a1
|
||||
|
||||
|
@ -144,7 +144,7 @@ class TestGemDependencyList < RubyGemTestCase
|
|||
|
||||
@deplist.add @b2
|
||||
|
||||
assert ! @deplist.ok_to_remove?("a-1")
|
||||
refute @deplist.ok_to_remove?("a-1")
|
||||
|
||||
@deplist.add @a2
|
||||
|
||||
|
@ -161,7 +161,7 @@ class TestGemDependencyList < RubyGemTestCase
|
|||
|
||||
@deplist.remove_by_name("a-1")
|
||||
|
||||
assert ! @deplist.ok_to_remove?("a-2")
|
||||
refute @deplist.ok_to_remove?("a-2")
|
||||
end
|
||||
|
||||
def test_remove_by_name
|
||||
|
@ -169,7 +169,7 @@ class TestGemDependencyList < RubyGemTestCase
|
|||
|
||||
@deplist.remove_by_name "a-1"
|
||||
|
||||
assert ! @deplist.ok?
|
||||
refute @deplist.ok?
|
||||
end
|
||||
|
||||
def test_tsort_each_node
|
||||
|
@ -181,7 +181,7 @@ class TestGemDependencyList < RubyGemTestCase
|
|||
assert_equal order.shift, node.full_name
|
||||
end
|
||||
|
||||
assert order.empty?
|
||||
assert_empty order
|
||||
end
|
||||
|
||||
def test_tsort_each_child
|
||||
|
@ -193,7 +193,7 @@ class TestGemDependencyList < RubyGemTestCase
|
|||
assert_equal order.shift, node.full_name
|
||||
end
|
||||
|
||||
assert order.empty?
|
||||
assert_empty order
|
||||
end
|
||||
|
||||
# d1 -> b1 -> a1
|
||||
|
|
|
@ -18,7 +18,13 @@ class TestGemDocManager < RubyGemTestCase
|
|||
|
||||
def test_uninstall_doc_unwritable
|
||||
orig_mode = File.stat(@spec.installation_path).mode
|
||||
File.chmod 0, @spec.installation_path
|
||||
|
||||
# File.chmod has no effect on MS Windows directories (it needs ACL).
|
||||
if win_platform?
|
||||
skip("test_uninstall_doc_unwritable skipped on MS Windows")
|
||||
else
|
||||
File.chmod(0, @spec.installation_path)
|
||||
end
|
||||
|
||||
assert_raises Gem::FilePermissionError do
|
||||
@manager.uninstall_doc
|
||||
|
|
|
@ -16,7 +16,7 @@ class TestGemExtConfigureBuilder < RubyGemTestCase
|
|||
end
|
||||
|
||||
def test_self_build
|
||||
return if RUBY_PLATFORM =~ /mswin/ # HACK
|
||||
skip("test_self_build skipped on MS Windows (VC++)") if vc_windows?
|
||||
|
||||
File.open File.join(@ext, './configure'), 'w' do |configure|
|
||||
configure.puts "#!/bin/sh\necho \"#{@makefile_body}\" > Makefile"
|
||||
|
@ -37,7 +37,7 @@ class TestGemExtConfigureBuilder < RubyGemTestCase
|
|||
end
|
||||
|
||||
def test_self_build_fail
|
||||
return if RUBY_PLATFORM =~ /mswin/ # HACK
|
||||
skip("test_self_build_fail skipped on MS Windows (VC++)") if vc_windows?
|
||||
output = []
|
||||
|
||||
error = assert_raises Gem::InstallError do
|
||||
|
@ -63,6 +63,10 @@ class TestGemExtConfigureBuilder < RubyGemTestCase
|
|||
end
|
||||
|
||||
def test_self_build_has_makefile
|
||||
if vc_windows? && !nmake_found?
|
||||
skip("test_self_build_has_makefile skipped - nmake not found")
|
||||
end
|
||||
|
||||
File.open File.join(@ext, 'Makefile'), 'w' do |makefile|
|
||||
makefile.puts @makefile_body
|
||||
end
|
||||
|
@ -72,14 +76,8 @@ class TestGemExtConfigureBuilder < RubyGemTestCase
|
|||
Gem::Ext::ConfigureBuilder.build nil, nil, @dest_path, output
|
||||
end
|
||||
|
||||
case RUBY_PLATFORM
|
||||
when /mswin/ then
|
||||
assert_equal 'nmake', output[0]
|
||||
assert_equal 'nmake install', output[2]
|
||||
else
|
||||
assert_equal 'make', output[0]
|
||||
assert_equal 'make install', output[2]
|
||||
end
|
||||
assert_equal make_command, output[0]
|
||||
assert_equal "#{make_command} install", output[2]
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -14,6 +14,10 @@ class TestGemExtExtConfBuilder < RubyGemTestCase
|
|||
end
|
||||
|
||||
def test_class_build
|
||||
if vc_windows? && !nmake_found?
|
||||
skip("test_class_build skipped - nmake not found")
|
||||
end
|
||||
|
||||
File.open File.join(@ext, 'extconf.rb'), 'w' do |extconf|
|
||||
extconf.puts "require 'mkmf'\ncreate_makefile 'foo'"
|
||||
end
|
||||
|
@ -46,6 +50,10 @@ class TestGemExtExtConfBuilder < RubyGemTestCase
|
|||
end
|
||||
|
||||
def test_class_build_extconf_fail
|
||||
if vc_windows? && !nmake_found?
|
||||
skip("test_class_build_extconf_fail skipped - nmake not found")
|
||||
end
|
||||
|
||||
File.open File.join(@ext, 'extconf.rb'), 'w' do |extconf|
|
||||
extconf.puts "require 'mkmf'"
|
||||
extconf.puts "have_library 'nonexistent' or abort 'need libnonexistent'"
|
||||
|
@ -69,6 +77,10 @@ checking for main\(\) in .*?nonexistent/m, error.message)
|
|||
end
|
||||
|
||||
def test_class_make
|
||||
if vc_windows? && !nmake_found?
|
||||
skip("test_class_make skipped - nmake not found")
|
||||
end
|
||||
|
||||
output = []
|
||||
makefile_path = File.join(@ext, 'Makefile')
|
||||
File.open makefile_path, 'w' do |makefile|
|
||||
|
@ -82,14 +94,8 @@ checking for main\(\) in .*?nonexistent/m, error.message)
|
|||
Gem::Ext::ExtConfBuilder.make @ext, output
|
||||
end
|
||||
|
||||
case RUBY_PLATFORM
|
||||
when /mswin/ then
|
||||
assert_equal 'nmake', output[0]
|
||||
assert_equal 'nmake install', output[2]
|
||||
else
|
||||
assert_equal 'make', output[0]
|
||||
assert_equal 'make install', output[2]
|
||||
end
|
||||
assert_equal make_command, output[0]
|
||||
assert_equal "#{make_command} install", output[2]
|
||||
|
||||
edited_makefile = <<-EOF
|
||||
RUBYARCHDIR = #{@ext}$(target_prefix)
|
||||
|
|
|
@ -21,7 +21,7 @@ class TestGemFormat < RubyGemTestCase
|
|||
|
||||
gems = Dir[File.join(@gemhome, 'cache', '*.gem')]
|
||||
|
||||
names = [@a1, @a2, @a_evil9, @b2, @c1_2, @pl1].map do |spec|
|
||||
names = [@a1, @a2, @a3a, @a_evil9, @b2, @c1_2, @pl1].map do |spec|
|
||||
spec.original_name
|
||||
end
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue