summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--lib/rubygems.rb121
-rw-r--r--lib/rubygems/commands/contents_command.rb2
-rw-r--r--lib/rubygems/commands/environment_command.rb40
-rw-r--r--lib/rubygems/commands/help_command.rb4
-rw-r--r--lib/rubygems/commands/install_command.rb15
-rw-r--r--lib/rubygems/commands/lock_command.rb21
-rw-r--r--lib/rubygems/commands/outdated_command.rb2
-rw-r--r--lib/rubygems/commands/pristine_command.rb2
-rw-r--r--lib/rubygems/commands/query_command.rb23
-rw-r--r--lib/rubygems/commands/rdoc_command.rb6
-rw-r--r--lib/rubygems/commands/specification_command.rb4
-rw-r--r--lib/rubygems/commands/unpack_command.rb2
-rw-r--r--lib/rubygems/commands/update_command.rb37
-rw-r--r--lib/rubygems/commands/which_command.rb7
-rw-r--r--lib/rubygems/config_file.rb6
-rw-r--r--lib/rubygems/defaults.rb53
-rw-r--r--lib/rubygems/dependency_installer.rb34
-rw-r--r--lib/rubygems/doc_manager.rb277
-rw-r--r--lib/rubygems/gem_path_searcher.rb54
-rw-r--r--lib/rubygems/installer.rb94
-rw-r--r--lib/rubygems/local_remote_options.rb7
-rw-r--r--lib/rubygems/package/tar_reader.rb14
-rw-r--r--lib/rubygems/platform.rb19
-rw-r--r--lib/rubygems/remote_fetcher.rb25
-rw-r--r--lib/rubygems/rubygems_version.rb2
-rw-r--r--lib/rubygems/source_index.rb29
-rw-r--r--lib/rubygems/source_info_cache.rb9
-rw-r--r--lib/rubygems/spec_fetcher.rb8
-rw-r--r--lib/rubygems/specification.rb795
-rw-r--r--lib/rubygems/test_utilities.rb20
-rw-r--r--lib/rubygems/uninstaller.rb86
-rw-r--r--test/rubygems/gemutilities.rb37
-rw-r--r--test/rubygems/mockgemui.rb24
-rw-r--r--test/rubygems/test_gem.rb121
-rw-r--r--test/rubygems/test_gem_builder.rb2
-rw-r--r--test/rubygems/test_gem_command_manager.rb4
-rw-r--r--test/rubygems/test_gem_commands_dependency_command.rb2
-rw-r--r--test/rubygems/test_gem_commands_install_command.rb10
-rw-r--r--test/rubygems/test_gem_commands_list_command.rb37
-rw-r--r--test/rubygems/test_gem_commands_lock_command.rb69
-rw-r--r--test/rubygems/test_gem_commands_query_command.rb41
-rw-r--r--test/rubygems/test_gem_commands_uninstall_command.rb60
-rw-r--r--test/rubygems/test_gem_config_file.rb5
-rw-r--r--test/rubygems/test_gem_ext_configure_builder.rb5
-rw-r--r--test/rubygems/test_gem_ext_rake_builder.rb10
-rw-r--r--test/rubygems/test_gem_gem_path_searcher.rb22
-rw-r--r--test/rubygems/test_gem_install_update_options.rb6
-rw-r--r--test/rubygems/test_gem_installer.rb60
-rw-r--r--test/rubygems/test_gem_local_remote_options.rb12
-rw-r--r--test/rubygems/test_gem_package_tar_header.rb8
-rw-r--r--test/rubygems/test_gem_platform.rb19
-rw-r--r--test/rubygems/test_gem_remote_fetcher.rb24
-rw-r--r--test/rubygems/test_gem_source_index.rb95
-rw-r--r--test/rubygems/test_gem_source_info_cache.rb3
-rw-r--r--test/rubygems/test_gem_spec_fetcher.rb14
-rw-r--r--test/rubygems/test_gem_specification.rb20
-rw-r--r--test/rubygems/test_gem_stream_ui.rb2
-rw-r--r--test/rubygems/test_gem_uninstaller.rb21
-rw-r--r--test/rubygems/test_gem_version.rb2
60 files changed, 1841 insertions, 716 deletions
diff --git a/ChangeLog b/ChangeLog
index 3c9f11be701..f76610b7945 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+Thu Sep 25 19:13:12 2008
+
+ * lib/rubygems*: Update to RubyGems 1.3.0 r1891.
+
Thu Sep 25 18:40:42 2008 Yuki Sonoda (Yugui) <yugui@yugui.jp>
* class.c (rb_make_metaclass): Made class of class of class
diff --git a/lib/rubygems.rb b/lib/rubygems.rb
index fde91bfd4b3..40c6defb66c 100644
--- a/lib/rubygems.rb
+++ b/lib/rubygems.rb
@@ -104,6 +104,11 @@ module Gem
@ruby = nil
@sources = []
+ @post_install_hooks = []
+ @post_uninstall_hooks = []
+ @pre_uninstall_hooks = []
+ @pre_install_hooks = []
+
##
# Activates an installed gem matching +gem+. The gem must satisfy
# +version_requirements+.
@@ -244,7 +249,10 @@ module Gem
def self.clear_paths
@gem_home = nil
@gem_path = nil
+ @user_home = nil
+
@@source_index = nil
+
MUTEX.synchronize do
@searcher = nil
end
@@ -261,9 +269,7 @@ module Gem
# The standard configuration object for gems.
def self.configuration
- return @configuration if @configuration
- require 'rubygems/config_file'
- @configuration = Gem::ConfigFile.new []
+ @configuration ||= Gem::ConfigFile.new []
end
##
@@ -337,6 +343,22 @@ module Gem
end
##
+ # Returns a list of paths matching +file+ that can be used by a gem to pick
+ # up features from other gems. For example:
+ #
+ # Gem.find_files('rdoc/discover').each do |path| load path end
+ #
+ # find_files does not search $LOAD_PATH for files, only gems.
+
+ def self.find_files(path)
+ specs = searcher.find_all path
+
+ specs.map do |spec|
+ searcher.matching_files spec, path
+ end.flatten
+ end
+
+ ##
# Finds the user's home directory.
#--
# Some comments from the ruby-talk list regarding finding the home
@@ -353,7 +375,7 @@ module Gem
end
if ENV['HOMEDRIVE'] && ENV['HOMEPATH'] then
- return "#{ENV['HOMEDRIVE']}:#{ENV['HOMEPATH']}"
+ return "#{ENV['HOMEDRIVE']}#{ENV['HOMEPATH']}"
end
begin
@@ -466,13 +488,11 @@ module Gem
##
# manage_gems is useless and deprecated. Don't call it anymore.
- #--
- # TODO warn w/ RubyGems 1.2.x release.
- def self.manage_gems
- #file, lineno = location_of_caller
+ 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 September 2008."
+ warn "#{file}:#{lineno}:Warning: Gem::manage_gems is deprecated and will be removed on or after March 2009."
end
##
@@ -489,11 +509,7 @@ module Gem
@gem_path ||= nil
unless @gem_path then
- paths = if ENV['GEM_PATH'] then
- [ENV['GEM_PATH']]
- else
- [default_path]
- end
+ paths = [ENV['GEM_PATH'] || Gem.configuration.path || default_path]
if defined?(APPLE_GEM_HOME) and not ENV['GEM_PATH'] then
paths << APPLE_GEM_HOME
@@ -524,6 +540,40 @@ module Gem
end
##
+ # Adds a post-install hook that will be passed an Gem::Installer instance
+ # when Gem::Installer#install is called
+
+ def self.post_install(&hook)
+ @post_install_hooks << hook
+ end
+
+ ##
+ # Adds a post-uninstall hook that will be passed a Gem::Uninstaller instance
+ # and the spec that was uninstalled when Gem::Uninstaller#uninstall is
+ # called
+
+ def self.post_uninstall(&hook)
+ @post_uninstall_hooks << hook
+ end
+
+ ##
+ # Adds a pre-install hook that will be passed an Gem::Installer instance
+ # when Gem::Installer#install is called
+
+ def self.pre_install(&hook)
+ @pre_install_hooks << hook
+ end
+
+ ##
+ # Adds a pre-uninstall hook that will be passed an Gem::Uninstaller instance
+ # and the spec that will be uninstalled when Gem::Uninstaller#uninstall is
+ # called
+
+ def self.pre_uninstall(&hook)
+ @pre_uninstall_hooks << hook
+ end
+
+ ##
# The directory prefix this RubyGems was installed at.
def self.prefix
@@ -600,6 +650,9 @@ module Gem
@ruby = File.join(ConfigMap[:bindir],
ConfigMap[:ruby_install_name])
@ruby << ConfigMap[:EXEEXT]
+
+ # escape string in case path to ruby executable contain spaces.
+ @ruby.sub!(/.*\s.*/m, '"\&"')
end
@ruby
@@ -655,7 +708,13 @@ module Gem
end
@gem_path.uniq!
- @gem_path.each do |gp| ensure_gem_subdirectories(gp) end
+ @gem_path.each do |path|
+ if 0 == File.expand_path(path).index(Gem.user_home) and
+ Etc.getpwuid.uid != File::Stat.new(Gem.user_home).uid then
+ next # only create by matching user
+ end
+ ensure_gem_subdirectories path
+ end
end
private_class_method :set_paths
@@ -686,6 +745,14 @@ module Gem
end
##
+ # Need to be able to set the sources without calling
+ # Gem.sources.replace since that would cause an infinite loop.
+
+ def self.sources=(new_sources)
+ @sources = new_sources
+ end
+
+ ##
# Glob pattern for require-able path suffixes.
def self.suffix_pattern
@@ -731,6 +798,27 @@ module Gem
attr_reader :loaded_specs
+ ##
+ # The list of hooks to be run before Gem::Install#install does any work
+
+ attr_reader :post_install_hooks
+
+ ##
+ # The list of hooks to be run before Gem::Uninstall#uninstall does any
+ # work
+
+ attr_reader :post_uninstall_hooks
+
+ ##
+ # The list of hooks to be run after Gem::Install#install is finished
+
+ attr_reader :pre_install_hooks
+
+ ##
+ # The list of hooks to be run after Gem::Uninstall#uninstall is finished
+
+ attr_reader :pre_uninstall_hooks
+
# :stopdoc:
alias cache source_index # an alias for the old name
@@ -781,7 +869,10 @@ if defined?(RUBY_ENGINE) then
end
end
+require 'rubygems/config_file'
+
if RUBY_VERSION < '1.9' then
require 'rubygems/custom_require'
end
+Gem.clear_paths
diff --git a/lib/rubygems/commands/contents_command.rb b/lib/rubygems/commands/contents_command.rb
index 5060403fd82..bc75fb5c03b 100644
--- a/lib/rubygems/commands/contents_command.rb
+++ b/lib/rubygems/commands/contents_command.rb
@@ -51,7 +51,7 @@ class Gem::Commands::ContentsCommand < Gem::Command
si = Gem::SourceIndex.from_gems_in(*s)
- gem_spec = si.search(/\A#{gem}\z/, version).last
+ gem_spec = si.find_name(gem, version).last
unless gem_spec then
say "Unable to find gem '#{gem}' in #{path_kind}"
diff --git a/lib/rubygems/commands/environment_command.rb b/lib/rubygems/commands/environment_command.rb
index a67c00bfd6f..e672da54f02 100644
--- a/lib/rubygems/commands/environment_command.rb
+++ b/lib/rubygems/commands/environment_command.rb
@@ -18,6 +18,46 @@ class Gem::Commands::EnvironmentCommand < Gem::Command
return args.gsub(/^\s+/, '')
end
+ def description # :nodoc:
+ <<-EOF
+The RubyGems environment can be controlled through command line arguments,
+gemrc files, environment variables and built-in defaults.
+
+Command line argument defaults and some RubyGems defaults can be set in
+~/.gemrc file for individual users and a /etc/gemrc for all users. A gemrc
+is a YAML file with the following YAML keys:
+
+ :sources: A YAML array of remote gem repositories to install gems from
+ :verbose: Verbosity of the gem command. false, true, and :really are the
+ levels
+ :update_sources: Enable/disable automatic updating of repository metadata
+ :backtrace: Print backtrace when RubyGems encounters an error
+ :bulk_threshold: Switch to a bulk update when this many sources are out of
+ date (legacy setting)
+ :gempath: The paths in which to look for gems
+ gem_command: A string containing arguments for the specified gem command
+
+Example:
+
+ :verbose: false
+ install: --no-wrappers
+ update: --no-wrappers
+
+RubyGems' default local repository can be overriden with the GEM_PATH and
+GEM_HOME environment variables. GEM_HOME sets the default repository to
+install into. GEM_PATH allows multiple local repositories to be searched for
+gems.
+
+If you are behind a proxy server, RubyGems uses the HTTP_PROXY,
+HTTP_PROXY_USER and HTTP_PROXY_PASS environment variables to discover the
+proxy server.
+
+If you are packaging RubyGems all of RubyGems' defaults are in
+lib/rubygems/defaults.rb. You may override these in
+lib/rubygems/defaults/operating_system.rb
+ EOF
+ end
+
def usage # :nodoc:
"#{program_name} [arg]"
end
diff --git a/lib/rubygems/commands/help_command.rb b/lib/rubygems/commands/help_command.rb
index 05ea3f7a717..0c4a4ec16f0 100644
--- a/lib/rubygems/commands/help_command.rb
+++ b/lib/rubygems/commands/help_command.rb
@@ -20,9 +20,9 @@ Some examples of 'gem' usage.
gem install --remote rake --test --rdoc --ri
* Install 'rake', but only version 0.3.1, even if dependencies
- are not met, and into a specific directory:
+ are not met, and into a user-specific directory:
- gem install rake --version 0.3.1 --force --install-dir $HOME/.gems
+ gem install rake --version 0.3.1 --force --user-install
* List local gems whose name begins with 'D':
diff --git a/lib/rubygems/commands/install_command.rb b/lib/rubygems/commands/install_command.rb
index 923d578a151..1a6eb68a8ba 100644
--- a/lib/rubygems/commands/install_command.rb
+++ b/lib/rubygems/commands/install_command.rb
@@ -38,6 +38,19 @@ class Gem::Commands::InstallCommand < Gem::Command
"--no-test --install-dir #{Gem.dir}"
end
+ def description # :nodoc:
+ <<-EOF
+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.
+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.
+ EOF
+ end
+
def usage # :nodoc:
"#{program_name} GEMNAME [GEMNAME ...] [options] -- --build-flags"
end
@@ -106,6 +119,8 @@ class Gem::Commands::InstallCommand < Gem::Command
installed_gems.each do |gem|
Gem::DocManager.new(gem, options[:rdoc_args]).generate_ri
end
+
+ Gem::DocManager.update_ri_cache
end
if options[:generate_rdoc] then
diff --git a/lib/rubygems/commands/lock_command.rb b/lib/rubygems/commands/lock_command.rb
index 6be2774e926..5a43978dd94 100644
--- a/lib/rubygems/commands/lock_command.rb
+++ b/lib/rubygems/commands/lock_command.rb
@@ -58,15 +58,15 @@ lock it down to the exact version.
end
def complain(message)
- if options.strict then
- raise message
+ if options[:strict] then
+ raise Gem::Exception, message
else
say "# #{message}"
end
end
def execute
- say 'require "rubygems"'
+ say "require 'rubygems'"
locked = {}
@@ -77,15 +77,20 @@ lock it down to the exact version.
spec = Gem::SourceIndex.load_specification spec_path(full_name)
+ if spec.nil? then
+ complain "Could not find gem #{full_name}, try using the full name"
+ next
+ end
+
say "gem '#{spec.name}', '= #{spec.version}'" unless locked[spec.name]
locked[spec.name] = true
spec.runtime_dependencies.each do |dep|
next if locked[dep.name]
- candidates = Gem.source_index.search dep.name, dep.requirement_list
+ candidates = Gem.source_index.search dep
if candidates.empty? then
- complain "Unable to satisfy '#{dep}' from currently installed gems."
+ complain "Unable to satisfy '#{dep}' from currently installed gems"
else
pending << candidates.last.full_name
end
@@ -94,7 +99,11 @@ lock it down to the exact version.
end
def spec_path(gem_full_name)
- File.join Gem.path, "specifications", "#{gem_full_name }.gemspec"
+ gemspecs = Gem.path.map do |path|
+ File.join path, "specifications", "#{gem_full_name}.gemspec"
+ end
+
+ gemspecs.find { |gemspec| File.exist? gemspec }
end
end
diff --git a/lib/rubygems/commands/outdated_command.rb b/lib/rubygems/commands/outdated_command.rb
index 1cd1087dd1b..9e054f988cf 100644
--- a/lib/rubygems/commands/outdated_command.rb
+++ b/lib/rubygems/commands/outdated_command.rb
@@ -19,7 +19,7 @@ class Gem::Commands::OutdatedCommand < Gem::Command
locals = Gem::SourceIndex.from_installed_gems
locals.outdated.sort.each do |name|
- local = locals.search(/^#{name}$/).last
+ local = locals.find_name(name).last
dep = Gem::Dependency.new local.name, ">= #{local.version}"
remotes = Gem::SpecFetcher.fetcher.fetch dep
diff --git a/lib/rubygems/commands/pristine_command.rb b/lib/rubygems/commands/pristine_command.rb
index 3e55a1bb308..d47fe54edd6 100644
--- a/lib/rubygems/commands/pristine_command.rb
+++ b/lib/rubygems/commands/pristine_command.rb
@@ -57,7 +57,7 @@ revert the gem.
end
else
gem_name = get_one_gem_name
- Gem::SourceIndex.from_installed_gems.search(gem_name,
+ Gem::SourceIndex.from_installed_gems.find_name(gem_name,
options[:version])
end
diff --git a/lib/rubygems/commands/query_command.rb b/lib/rubygems/commands/query_command.rb
index f4d6120bcd0..29fe8acb796 100644
--- a/lib/rubygems/commands/query_command.rb
+++ b/lib/rubygems/commands/query_command.rb
@@ -59,7 +59,7 @@ class Gem::Commands::QueryCommand < Gem::Command
if name.source.empty? then
alert_error "You must specify a gem name"
exit_code |= 4
- elsif installed? name.source, options[:version] then
+ elsif installed? name, options[:version] then
say "true"
else
say "false"
@@ -69,12 +69,16 @@ class Gem::Commands::QueryCommand < Gem::Command
raise Gem::SystemExitException, exit_code
end
+ dep = Gem::Dependency.new name, Gem::Requirement.default
+
if local? then
- say
- say "*** LOCAL GEMS ***"
- say
+ if ui.outs.tty? or both? then
+ say
+ say "*** LOCAL GEMS ***"
+ say
+ end
- specs = Gem.source_index.search name
+ specs = Gem.source_index.search dep
spec_tuples = specs.map do |spec|
[[spec.name, spec.version, spec.original_platform, spec], :local]
@@ -84,13 +88,14 @@ class Gem::Commands::QueryCommand < Gem::Command
end
if remote? then
- say
- say "*** REMOTE GEMS ***"
- say
+ if ui.outs.tty? or both? then
+ say
+ say "*** REMOTE GEMS ***"
+ say
+ end
all = options[:all]
- dep = Gem::Dependency.new name, Gem::Requirement.default
begin
fetcher = Gem::SpecFetcher.fetcher
spec_tuples = fetcher.find_matching dep, all, false
diff --git a/lib/rubygems/commands/rdoc_command.rb b/lib/rubygems/commands/rdoc_command.rb
index f2e677c1159..82180d485c6 100644
--- a/lib/rubygems/commands/rdoc_command.rb
+++ b/lib/rubygems/commands/rdoc_command.rb
@@ -59,11 +59,15 @@ module Gem
if specs.empty?
fail "Failed to find gem #{gem_name} to generate RDoc for #{options[:version]}"
end
+
if options[:include_ri]
specs.each do |spec|
Gem::DocManager.new(spec).generate_ri
end
+
+ Gem::DocManager.update_ri_cache
end
+
if options[:include_rdoc]
specs.each do |spec|
Gem::DocManager.new(spec).generate_rdoc
@@ -73,6 +77,6 @@ module Gem
true
end
end
-
+
end
end
diff --git a/lib/rubygems/commands/specification_command.rb b/lib/rubygems/commands/specification_command.rb
index 689f2560c99..5aaf6d17973 100644
--- a/lib/rubygems/commands/specification_command.rb
+++ b/lib/rubygems/commands/specification_command.rb
@@ -40,6 +40,7 @@ class Gem::Commands::SpecificationCommand < Gem::Command
def execute
specs = []
gem = get_one_gem_name
+ dep = Gem::Dependency.new gem, options[:version]
if local? then
if File.exist? gem then
@@ -47,12 +48,11 @@ class Gem::Commands::SpecificationCommand < Gem::Command
end
if specs.empty? then
- specs.push(*Gem.source_index.search(/\A#{gem}\z/, options[:version]))
+ specs.push(*Gem.source_index.search(dep))
end
end
if remote? then
- dep = Gem::Dependency.new gem, options[:version]
found = Gem::SpecFetcher.fetcher.fetch dep
specs.push(*found.map { |spec,| spec })
diff --git a/lib/rubygems/commands/unpack_command.rb b/lib/rubygems/commands/unpack_command.rb
index d187f8a9ea4..ef9436ae34c 100644
--- a/lib/rubygems/commands/unpack_command.rb
+++ b/lib/rubygems/commands/unpack_command.rb
@@ -68,7 +68,7 @@ class Gem::Commands::UnpackCommand < Gem::Command
def get_path(gemname, version_req)
return gemname if gemname =~ /\.gem$/i
- specs = Gem::source_index.search(/\A#{gemname}\z/, version_req)
+ specs = Gem::source_index.find_name gemname, version_req
selected = specs.sort_by { |s| s.version }.last
diff --git a/lib/rubygems/commands/update_command.rb b/lib/rubygems/commands/update_command.rb
index 78baa8ba565..4490f385dc1 100644
--- a/lib/rubygems/commands/update_command.rb
+++ b/lib/rubygems/commands/update_command.rb
@@ -45,6 +45,8 @@ class Gem::Commands::UpdateCommand < Gem::Command
end
def execute
+ hig = {}
+
if options[:system] then
say "Updating RubyGems"
@@ -52,16 +54,22 @@ class Gem::Commands::UpdateCommand < Gem::Command
fail "No gem names are allowed with the --system option"
end
- options[:args] = ["rubygems-update"]
+ spec = Gem::Specification.new
+ spec.name = 'rubygems-update'
+ spec.version = Gem::Version.new Gem::RubyGemsVersion
+ spec.version = Gem::Version.new '1.1.1'
+ hig['rubygems-update'] = spec
+
+ options[:user_install] = false
else
say "Updating installed gems"
- end
- hig = {} # highest installed gems
+ hig = {} # highest installed gems
- Gem.source_index.each do |name, spec|
- if hig[spec.name].nil? or hig[spec.name].version < spec.version then
- hig[spec.name] = spec
+ Gem.source_index.each do |name, spec|
+ if hig[spec.name].nil? or hig[spec.name].version < spec.version then
+ hig[spec.name] = spec
+ end
end
end
@@ -84,14 +92,14 @@ class Gem::Commands::UpdateCommand < Gem::Command
end
if gems_to_update.include? "rubygems-update" then
- latest_ruby_gem = remote_gemspecs.select do |s|
- s.name == 'rubygems-update'
- end
+ Gem.source_index.refresh!
+
+ update_gems = Gem.source_index.search 'rubygems-update'
- latest_ruby_gem = latest_ruby_gem.sort_by { |s| s.version }.last
+ latest_update_gem = update_gems.sort_by { |s| s.version }.last
- say "Updating version of RubyGems to #{latest_ruby_gem.version}"
- installed = do_rubygems_update latest_ruby_gem.version
+ say "Updating RubyGems to #{latest_update_gem.version}"
+ installed = do_rubygems_update latest_update_gem.version
say "RubyGems system software updated" if installed
else
@@ -103,6 +111,9 @@ class Gem::Commands::UpdateCommand < Gem::Command
end
end
+ ##
+ # Update the RubyGems software to +version+.
+
def do_rubygems_update(version)
args = []
args.push '--prefix', Gem.prefix unless Gem.prefix.nil?
@@ -112,8 +123,6 @@ class Gem::Commands::UpdateCommand < Gem::Command
update_dir = File.join Gem.dir, 'gems', "rubygems-update-#{version}"
- success = false
-
Dir.chdir update_dir do
say "Installing RubyGems #{version}"
setup_cmd = "#{Gem.ruby} setup.rb #{args.join ' '}"
diff --git a/lib/rubygems/commands/which_command.rb b/lib/rubygems/commands/which_command.rb
index b42244ce7d3..2267e44b119 100644
--- a/lib/rubygems/commands/which_command.rb
+++ b/lib/rubygems/commands/which_command.rb
@@ -3,10 +3,10 @@ require 'rubygems/gem_path_searcher'
class Gem::Commands::WhichCommand < Gem::Command
- EXT = %w[.rb .rbw .so .dll] # HACK
+ EXT = %w[.rb .rbw .so .dll .bundle] # HACK
def initialize
- super 'which', 'Find the location of a library',
+ super 'which', 'Find the location of a library file you can require',
:search_gems_first => false, :show_all => false
add_option '-a', '--[no-]all', 'show all matching files' do |show_all, options|
@@ -52,7 +52,7 @@ class Gem::Commands::WhichCommand < Gem::Command
paths = find_paths arg, dirs
if paths.empty? then
- say "Can't find #{arg}"
+ say "Can't find ruby library file or shared library #{arg}"
else
say paths
end
@@ -84,3 +84,4 @@ class Gem::Commands::WhichCommand < Gem::Command
end
end
+
diff --git a/lib/rubygems/config_file.rb b/lib/rubygems/config_file.rb
index c093c31a1bc..0a35ca9417b 100644
--- a/lib/rubygems/config_file.rb
+++ b/lib/rubygems/config_file.rb
@@ -49,6 +49,9 @@ class Gem::ConfigFile
# List of arguments supplied to the config file object.
attr_reader :args
+ # Where to look for gems
+ attr_accessor :path
+
# True if we print backtraces on errors.
attr_writer :backtrace
@@ -123,9 +126,10 @@ class Gem::ConfigFile
@backtrace = @hash[:backtrace] if @hash.key? :backtrace
@benchmark = @hash[:benchmark] if @hash.key? :benchmark
@bulk_threshold = @hash[:bulk_threshold] if @hash.key? :bulk_threshold
- Gem.sources.replace @hash[:sources] if @hash.key? :sources
+ Gem.sources = @hash[:sources] if @hash.key? :sources
@verbose = @hash[:verbose] if @hash.key? :verbose
@update_sources = @hash[:update_sources] if @hash.key? :update_sources
+ @path = @hash[:gempath]
handle_arguments arg_list
end
diff --git a/lib/rubygems/defaults.rb b/lib/rubygems/defaults.rb
index 8bb9776575e..7eba0cb0491 100644
--- a/lib/rubygems/defaults.rb
+++ b/lib/rubygems/defaults.rb
@@ -1,36 +1,52 @@
module Gem
- # An Array of the default sources that come with RubyGems.
+ ##
+ # An Array of the default sources that come with RubyGems
+
def self.default_sources
%w[http://gems.rubyforge.org/]
end
+ ##
# Default home directory path to be used if an alternate value is not
- # specified in the environment.
+ # specified in the environment
+
def self.default_dir
if defined? RUBY_FRAMEWORK_VERSION then
File.join File.dirname(ConfigMap[:sitedir]), 'Gems',
ConfigMap[:ruby_version]
- elsif defined? RUBY_ENGINE then
- File.join ConfigMap[:libdir], RUBY_ENGINE, 'gems',
- ConfigMap[:ruby_version]
else
- File.join ConfigMap[:libdir], 'ruby', 'gems', ConfigMap[:ruby_version]
+ File.join(ConfigMap[:libdir], ruby_engine, 'gems',
+ ConfigMap[:ruby_version])
end
end
- # Default gem load path.
+ ##
+ # Path for gems in the user's home directory
+
+ def self.user_dir
+ File.join(Gem.user_home, '.gem', ruby_engine,
+ ConfigMap[:ruby_version])
+ end
+
+ ##
+ # Default gem load path
+
def self.default_path
- [File.join(ENV['HOME'], '.gem'), default_dir]
+ [user_dir, default_dir]
end
- # Deduce Ruby's --program-prefix and --program-suffix from its install name.
+ ##
+ # Deduce Ruby's --program-prefix and --program-suffix from its install name
+
def self.default_exec_format
baseruby = ConfigMap[:BASERUBY] || 'ruby'
ConfigMap[:RUBY_INSTALL_NAME].sub(baseruby, '%s') rescue '%s'
end
+ ##
# The default directory for binaries
+
def self.default_bindir
if defined? RUBY_FRAMEWORK_VERSION then # mac framework support
'/usr/bin'
@@ -39,15 +55,30 @@ module Gem
end
end
- # The default system-wide source info cache directory.
+ ##
+ # The default system-wide source info cache directory
+
def self.default_system_source_cache_dir
File.join Gem.dir, 'source_cache'
end
- # The default user-specific source info cache directory.
+ ##
+ # The default user-specific source info cache directory
+
def self.default_user_source_cache_dir
File.join Gem.user_home, '.gem', 'source_cache'
end
+ ##
+ # A wrapper around RUBY_ENGINE const that may not be defined
+
+ def self.ruby_engine
+ if defined? RUBY_ENGINE then
+ RUBY_ENGINE
+ else
+ 'ruby'
+ end
+ end
+
end
diff --git a/lib/rubygems/dependency_installer.rb b/lib/rubygems/dependency_installer.rb
index 8406844e79f..9ae26595364 100644
--- a/lib/rubygems/dependency_installer.rb
+++ b/lib/rubygems/dependency_installer.rb
@@ -38,9 +38,17 @@ class Gem::DependencyInstaller
# :ignore_dependencies:: Don't install any dependencies.
# :install_dir:: See Gem::Installer#install.
# :security_policy:: See Gem::Installer::new and Gem::Security.
+ # :user_install:: See Gem::Installer.new
# :wrappers:: See Gem::Installer::new
def initialize(options = {})
+ if options[:install_dir] then
+ spec_dir = options[:install_dir], 'specifications'
+ @source_index = Gem::SourceIndex.from_gems_in spec_dir
+ else
+ @source_index = Gem.source_index
+ end
+
options = DEFAULT_OPTIONS.merge options
@bin_dir = options[:bin_dir]
@@ -51,19 +59,13 @@ class Gem::DependencyInstaller
@format_executable = options[:format_executable]
@ignore_dependencies = options[:ignore_dependencies]
@security_policy = options[:security_policy]
+ @user_install = options[:user_install]
@wrappers = options[:wrappers]
@installed_gems = []
@install_dir = options[:install_dir] || Gem.dir
@cache_dir = options[:cache_dir] || @install_dir
-
- if options[:install_dir] then
- spec_dir = File.join @install_dir, 'specifications'
- @source_index = Gem::SourceIndex.from_gems_in spec_dir
- else
- @source_index = Gem.source_index
- end
end
##
@@ -232,15 +234,17 @@ class Gem::DependencyInstaller
end
inst = Gem::Installer.new local_gem_path,
- :env_shebang => @env_shebang,
- :force => @force,
- :format_executable => @format_executable,
+ :bin_dir => @bin_dir,
+ :development => @development,
+ :env_shebang => @env_shebang,
+ :force => @force,
+ :format_executable => @format_executable,
:ignore_dependencies => @ignore_dependencies,
- :install_dir => @install_dir,
- :security_policy => @security_policy,
- :wrappers => @wrappers,
- :bin_dir => @bin_dir,
- :development => @development
+ :install_dir => @install_dir,
+ :security_policy => @security_policy,
+ :source_index => @source_index,
+ :user_install => @user_install,
+ :wrappers => @wrappers
spec = inst.install
diff --git a/lib/rubygems/doc_manager.rb b/lib/rubygems/doc_manager.rb
index 88d7964d859..00ef4c51e3a 100644
--- a/lib/rubygems/doc_manager.rb
+++ b/lib/rubygems/doc_manager.rb
@@ -5,132 +5,194 @@
#++
require 'fileutils'
+require 'rubygems'
-module Gem
+##
+# The documentation manager generates RDoc and RI for RubyGems.
- class DocManager
+class Gem::DocManager
- include UserInteraction
+ include Gem::UserInteraction
- # Create a document manager for the given gem spec.
- #
- # spec:: The Gem::Specification object representing the gem.
- # rdoc_args:: Optional arguments for RDoc (template etc.) as a String.
- #
- def initialize(spec, rdoc_args="")
- @spec = spec
- @doc_dir = File.join(spec.installation_path, "doc", spec.full_name)
- @rdoc_args = rdoc_args.nil? ? [] : rdoc_args.split
+ @configured_args = []
+
+ def self.configured_args
+ @configured_args ||= []
+ end
+
+ def self.configured_args=(args)
+ case args
+ when Array
+ @configured_args = args
+ when String
+ @configured_args = args.split
end
+ end
+
+ ##
+ # Load RDoc from a gem if it is available, otherwise from Ruby's stdlib
- # Is the RDoc documentation installed?
- def rdoc_installed?
- return File.exist?(File.join(@doc_dir, "rdoc"))
+ def self.load_rdoc
+ begin
+ gem 'rdoc'
+ rescue Gem::LoadError
+ # use built-in RDoc
end
- # Generate the RI documents for this gem spec.
- #
- # Note that if both RI and RDoc documents are generated from the
- # same process, the RI docs should be done first (a likely bug in
- # RDoc will cause RI docs generation to fail if run after RDoc).
- def generate_ri
- if @spec.has_rdoc then
- load_rdoc
- install_ri # RDoc bug, ri goes first
- end
+ begin
+ require 'rdoc/rdoc'
+ rescue LoadError => e
+ raise Gem::DocumentError,
+ "ERROR: RDoc documentation generator not installed!"
+ end
+ end
+
+ ##
+ # Updates the RI cache for RDoc 2 if it is installed
+
+ def self.update_ri_cache
+ load_rdoc rescue return
+
+ return unless defined? RDoc::VERSION # RDoc 1 does not have VERSION
- FileUtils.mkdir_p @doc_dir unless File.exist?(@doc_dir)
+ require 'rdoc/ri/driver'
+
+ options = {
+ :use_cache => true,
+ :use_system => true,
+ :use_site => true,
+ :use_home => true,
+ :use_gems => true,
+ :formatter => RDoc::RI::Formatter,
+ }
+
+ driver = RDoc::RI::Driver.new(options).class_cache
+ end
+
+ ##
+ # Create a document manager for +spec+. +rdoc_args+ contains arguments for
+ # RDoc (template etc.) as a String.
+
+ def initialize(spec, rdoc_args="")
+ @spec = spec
+ @doc_dir = File.join(spec.installation_path, "doc", spec.full_name)
+ @rdoc_args = rdoc_args.nil? ? [] : rdoc_args.split
+ end
+
+ ##
+ # Is the RDoc documentation installed?
+
+ def rdoc_installed?
+ File.exist?(File.join(@doc_dir, "rdoc"))
+ end
+
+ ##
+ # Generate the RI documents for this gem spec.
+ #
+ # Note that if both RI and RDoc documents are generated from the same
+ # process, the RI docs should be done first (a likely bug in RDoc will cause
+ # RI docs generation to fail if run after RDoc).
+
+ def generate_ri
+ if @spec.has_rdoc then
+ setup_rdoc
+ install_ri # RDoc bug, ri goes first
end
- # Generate the RDoc documents for this gem spec.
- #
- # Note that if both RI and RDoc documents are generated from the
- # same process, the RI docs should be done first (a likely bug in
- # RDoc will cause RI docs generation to fail if run after RDoc).
- def generate_rdoc
- if @spec.has_rdoc then
- load_rdoc
- install_rdoc
- end
+ FileUtils.mkdir_p @doc_dir unless File.exist?(@doc_dir)
+ end
- FileUtils.mkdir_p @doc_dir unless File.exist?(@doc_dir)
+ ##
+ # Generate the RDoc documents for this gem spec.
+ #
+ # Note that if both RI and RDoc documents are generated from the same
+ # process, the RI docs should be done first (a likely bug in RDoc will cause
+ # RI docs generation to fail if run after RDoc).
+
+ def generate_rdoc
+ if @spec.has_rdoc then
+ setup_rdoc
+ install_rdoc
end
- # Load the RDoc documentation generator library.
- def load_rdoc
- if File.exist?(@doc_dir) && !File.writable?(@doc_dir) then
- raise Gem::FilePermissionError.new(@doc_dir)
- end
+ FileUtils.mkdir_p @doc_dir unless File.exist?(@doc_dir)
+ end
- FileUtils.mkdir_p @doc_dir unless File.exist?(@doc_dir)
+ ##
+ # Generate and install RDoc into the documentation directory
- begin
- gem 'rdoc'
- rescue Gem::LoadError
- # use built-in RDoc
- end
+ def install_rdoc
+ rdoc_dir = File.join @doc_dir, 'rdoc'
- begin
- require 'rdoc/rdoc'
- rescue LoadError => e
- raise Gem::DocumentError,
- "ERROR: RDoc documentation generator not installed!"
- end
- end
+ FileUtils.rm_rf rdoc_dir
- def install_rdoc
- rdoc_dir = File.join @doc_dir, 'rdoc'
+ say "Installing RDoc documentation for #{@spec.full_name}..."
+ run_rdoc '--op', rdoc_dir
+ end
- FileUtils.rm_rf rdoc_dir
+ ##
+ # Generate and install RI into the documentation directory
- say "Installing RDoc documentation for #{@spec.full_name}..."
- run_rdoc '--op', rdoc_dir
- end
+ def install_ri
+ ri_dir = File.join @doc_dir, 'ri'
- def install_ri
- ri_dir = File.join @doc_dir, 'ri'
+ FileUtils.rm_rf ri_dir
- FileUtils.rm_rf ri_dir
+ say "Installing ri documentation for #{@spec.full_name}..."
+ run_rdoc '--ri', '--op', ri_dir
+ end
- say "Installing ri documentation for #{@spec.full_name}..."
- run_rdoc '--ri', '--op', ri_dir
+ ##
+ # Run RDoc with +args+, which is an ARGV style argument list
+
+ def run_rdoc(*args)
+ args << @spec.rdoc_options
+ args << self.class.configured_args
+ args << '--quiet'
+ args << @spec.require_paths.clone
+ args << @spec.extra_rdoc_files
+ args = args.flatten.map do |arg| arg.to_s end
+
+ r = RDoc::RDoc.new
+
+ old_pwd = Dir.pwd
+ Dir.chdir(@spec.full_gem_path)
+ begin
+ r.document args
+ rescue Errno::EACCES => e
+ dirname = File.dirname e.message.split("-")[1].strip
+ raise Gem::FilePermissionError.new(dirname)
+ rescue RuntimeError => ex
+ alert_error "While generating documentation for #{@spec.full_name}"
+ ui.errs.puts "... MESSAGE: #{ex}"
+ ui.errs.puts "... RDOC args: #{args.join(' ')}"
+ ui.errs.puts "\t#{ex.backtrace.join "\n\t"}" if
+ Gem.configuration.backtrace
+ ui.errs.puts "(continuing with the rest of the installation)"
+ ensure
+ Dir.chdir(old_pwd)
end
+ end
- def run_rdoc(*args)
- args << @spec.rdoc_options
- args << DocManager.configured_args
- args << '--quiet'
- args << @spec.require_paths.clone
- args << @spec.extra_rdoc_files
- args = args.flatten.map do |arg| arg.to_s end
-
- r = RDoc::RDoc.new
-
- old_pwd = Dir.pwd
- Dir.chdir(@spec.full_gem_path)
- begin
- r.document args
- rescue Errno::EACCES => e
- dirname = File.dirname e.message.split("-")[1].strip
- raise Gem::FilePermissionError.new(dirname)
- rescue RuntimeError => ex
- alert_error "While generating documentation for #{@spec.full_name}"
- ui.errs.puts "... MESSAGE: #{ex}"
- ui.errs.puts "... RDOC args: #{args.join(' ')}"
- ui.errs.puts "\t#{ex.backtrace.join "\n\t"}" if
- Gem.configuration.backtrace
- ui.errs.puts "(continuing with the rest of the installation)"
- ensure
- Dir.chdir(old_pwd)
- end
+ def setup_rdoc
+ if File.exist?(@doc_dir) && !File.writable?(@doc_dir) then
+ raise Gem::FilePermissionError.new(@doc_dir)
end
- def uninstall_doc
- raise Gem::FilePermissionError.new(@spec.installation_path) unless
- File.writable? @spec.installation_path
+ FileUtils.mkdir_p @doc_dir unless File.exist?(@doc_dir)
- original_name = [
- @spec.name, @spec.version, @spec.original_platform].join '-'
+ self.class.load_rdoc
+ end
+
+ ##
+ # Remove RDoc and RI documentation
+
+ def uninstall_doc
+ raise Gem::FilePermissionError.new(@spec.installation_path) unless
+ File.writable? @spec.installation_path
+
+ original_name = [
+ @spec.name, @spec.version, @spec.original_platform].join '-'
doc_dir = File.join @spec.installation_path, 'doc', @spec.full_name
unless File.directory? doc_dir then
@@ -146,22 +208,7 @@ module Gem
end
FileUtils.rm_rf ri_dir
- end
-
- class << self
- def configured_args
- @configured_args ||= []
- end
-
- def configured_args=(args)
- case args
- when Array
- @configured_args = args
- when String
- @configured_args = args.split
- end
- end
- end
-
end
+
end
+
diff --git a/lib/rubygems/gem_path_searcher.rb b/lib/rubygems/gem_path_searcher.rb
index dadad662899..e2b8543bb0a 100644
--- a/lib/rubygems/gem_path_searcher.rb
+++ b/lib/rubygems/gem_path_searcher.rb
@@ -6,15 +6,15 @@
require 'rubygems'
-#
+##
# GemPathSearcher has the capability to find loadable files inside
# gems. It generates data up front to speed up searches later.
-#
+
class Gem::GemPathSearcher
- #
+ ##
# Initialise the data we need to make searches later.
- #
+
def initialize
# We want a record of all the installed gemspecs, in the order
# we wish to examine them.
@@ -27,7 +27,7 @@ class Gem::GemPathSearcher
end
end
- #
+ ##
# Look in all the installed gems until a matching _path_ is found.
# Return the _gemspec_ of the gem where it was found. If no match
# is found, return nil.
@@ -46,36 +46,52 @@ class Gem::GemPathSearcher
# others), which may or may not already be attached to _file_.
# This method doesn't care about the full filename that matches;
# only that there is a match.
- #
+
def find(path)
- @gemspecs.each do |spec|
- return spec if matching_file(spec, path)
+ @gemspecs.find do |spec| matching_file? spec, path end
+ end
+
+ ##
+ # Works like #find, but finds all gemspecs matching +path+.
+
+ def find_all(path)
+ @gemspecs.select do |spec|
+ matching_file? spec, path
end
- nil
end
- private
+ ##
+ # Attempts to find a matching path using the require_paths of the given
+ # +spec+.
- # Attempts to find a matching path using the require_paths of the
- # given _spec_.
- #
- # Some of the intermediate results are cached in @lib_dirs for
- # speed.
- def matching_file(spec, path) # :doc:
+ def matching_file?(spec, path)
+ !matching_files(spec, path).empty?
+ end
+
+ ##
+ # Returns files matching +path+ in +spec+.
+ #--
+ # Some of the intermediate results are cached in @lib_dirs for speed.
+
+ def matching_files(spec, path)
glob = File.join @lib_dirs[spec.object_id], "#{path}#{Gem.suffix_pattern}"
- return true unless Dir[glob].select { |f| File.file?(f.untaint) }.empty?
+ Dir[glob].select { |f| File.file? f.untaint }
end
- # Return a list of all installed gemspecs, sorted by alphabetical
- # order and in reverse version order.
+ ##
+ # Return a list of all installed gemspecs, sorted by alphabetical order and
+ # in reverse version order.
+
def init_gemspecs
Gem.source_index.map { |_, spec| spec }.sort { |a,b|
(a.name <=> b.name).nonzero? || (b.version <=> a.version)
}
end
+ ##
# Returns library directories glob for a gemspec. For example,
# '/usr/local/lib/ruby/gems/1.8/gems/foobar-1.0/{lib,ext}'
+
def lib_dirs_for(spec)
"#{spec.full_gem_path}/{#{spec.require_paths.join(',')}}"
end
diff --git a/lib/rubygems/installer.rb b/lib/rubygems/installer.rb
index 5e2e8e0f42f..d9006f9fc7f 100644
--- a/lib/rubygems/installer.rb
+++ b/lib/rubygems/installer.rb
@@ -20,6 +20,7 @@ require 'rubygems/require_paths_builder'
# filesystem including unpacking the gem into its gem dir, installing the
# gemspec in the specifications dir, storing the cached gem in the cache dir,
# and installing either wrappers or symlinks for executables.
+
class Gem::Installer
##
@@ -31,8 +32,36 @@ class Gem::Installer
include Gem::RequirePathsBuilder
+ ##
+ # The directory a gem's executables will be installed into
+
+ attr_reader :bin_dir
+
+ ##
+ # The gem repository the gem will be installed into
+
+ attr_reader :gem_home
+
+ ##
+ # The Gem::Specification for the gem being installed
+
+ attr_reader :spec
+
+ @home_install_warning = false
+ @path_warning = false
+
class << self
+ ##
+ # True if we've warned about ~/.gems install
+
+ attr_accessor :home_install_warning
+
+ ##
+ # True if we've warned about PATH not including Gem.bindir
+
+ attr_accessor :path_warning
+
attr_writer :exec_format
# Defaults to use Ruby's program prefix and suffix.
@@ -61,11 +90,12 @@ class Gem::Installer
@gem = gem
options = {
- :force => false,
- :install_dir => Gem.dir,
- :exec_format => false,
- :env_shebang => false,
- :bin_dir => nil
+ :bin_dir => nil,
+ :env_shebang => false,
+ :exec_format => false,
+ :force => false,
+ :install_dir => Gem.dir,
+ :source_index => Gem.source_index,
}.merge options
@env_shebang = options[:env_shebang]
@@ -78,6 +108,7 @@ class Gem::Installer
@wrappers = options[:wrappers]
@bin_dir = options[:bin_dir]
@development = options[:development]
+ @source_index = options[:source_index]
begin
@format = Gem::Format.from_file_by_path @gem, @security_policy
@@ -85,30 +116,41 @@ class Gem::Installer
raise Gem::InstallError, "invalid gem format for #{@gem}"
end
+ begin
+ FileUtils.mkdir_p @gem_home
+ rescue Errno::EACCESS, Errno::ENOTDIR
+ # We'll divert to ~/.gems below
+ end
+
if not File.writable? @gem_home or
# TODO: Shouldn't have to test for existence of bindir; tests need it.
- (@gem_home.to_s == Gem.dir and File.exist? Gem.bindir and
- not File.writable? Gem.bindir)
- if options[:user_install] == false # You explicitly don't want to use ~
+ (@gem_home.to_s == Gem.dir and File.exist? Gem.bindir and
+ not File.writable? Gem.bindir) then
+ if options[:user_install] == false then # You don't want to use ~
raise Gem::FilePermissionError, @gem_home
- elsif options[:user_install].nil?
- say "Warning: falling back to user-level install since #{@gem_home} and #{@bin_dir} aren't both writable."
+ elsif options[:user_install].nil? then
+ unless self.class.home_install_warning 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
end
options[:user_install] = true
end
- if options[:user_install]
- @gem_home = File.join(ENV['HOME'], '.gem')
+ if options[:user_install] then
+ @gem_home = Gem.user_dir
- user_bin_dir = File.join(@gem_home, 'gems', 'bin')
- if !ENV['PATH'].split(':').include?(user_bin_dir)
- say "You don't have #{user_bin_dir} in your PATH."
- say "You won't be able to run gem-installed executables until you add it."
+ user_bin_dir = File.join(@gem_home, 'bin')
+ unless ENV['PATH'].split(File::PATH_SEPARATOR).include? user_bin_dir then
+ unless self.class.path_warning then
+ alert_warning "You don't have #{user_bin_dir} in your PATH,\n\t gem executables will not run."
+ self.class.path_warning = true
+ end
end
-
- Dir.mkdir @gem_home if ! File.directory? @gem_home
+
+ FileUtils.mkdir_p @gem_home unless File.directory? @gem_home
# If it's still not writable, you've got issues.
- raise Gem::FilePermissionError, @gem_home if ! File.writable? @gem_home
+ raise Gem::FilePermissionError, @gem_home unless File.writable? @gem_home
end
@spec = @format.spec
@@ -157,6 +199,10 @@ class Gem::Installer
end
end
+ Gem.pre_install_hooks.each do |hook|
+ hook.call self
+ end
+
FileUtils.mkdir_p @gem_home unless File.directory? @gem_home
Gem.ensure_gem_subdirectories @gem_home
@@ -181,7 +227,11 @@ class Gem::Installer
@spec.loaded_from = File.join(@gem_home, 'specifications',
"#{@spec.full_name}.gemspec")
- Gem.source_index.add_spec @spec
+ @source_index.add_spec @spec
+
+ Gem.post_install_hooks.each do |hook|
+ hook.call self
+ end
return @spec
rescue Zlib::GzipFile::Error
@@ -204,10 +254,10 @@ class Gem::Installer
end
##
- # True if the gems in Gem.source_index satisfy +dependency+.
+ # True if the gems in the source_index satisfy +dependency+.
def installation_satisfies_dependency?(dependency)
- Gem.source_index.find_name(dependency.name, dependency.version_requirements).size > 0
+ @source_index.find_name(dependency.name, dependency.version_requirements).size > 0
end
##
diff --git a/lib/rubygems/local_remote_options.rb b/lib/rubygems/local_remote_options.rb
index 799b9d5893e..d77d600ec6f 100644
--- a/lib/rubygems/local_remote_options.rb
+++ b/lib/rubygems/local_remote_options.rb
@@ -110,6 +110,13 @@ module Gem::LocalRemoteOptions
end
##
+ # Is fetching of local and remote information enabled?
+
+ def both?
+ options[:domain] == :both
+ end
+
+ ##
# Is local fetching enabled?
def local?
diff --git a/lib/rubygems/package/tar_reader.rb b/lib/rubygems/package/tar_reader.rb
index 8359399207e..4aa9c26cc9c 100644
--- a/lib/rubygems/package/tar_reader.rb
+++ b/lib/rubygems/package/tar_reader.rb
@@ -46,17 +46,17 @@ class Gem::Package::TarReader
yield entry
skip = (512 - (size % 512)) % 512
+ pending = size - entry.bytes_read
- if @io.respond_to? :seek then
+ begin
# avoid reading...
- @io.seek(size - entry.bytes_read, IO::SEEK_CUR)
- else
- pending = size - entry.bytes_read
-
+ @io.seek pending, IO::SEEK_CUR
+ pending = 0
+ rescue Errno::EINVAL, NameError
while pending > 0 do
- bread = @io.read([pending, 4096].min).size
+ bytes_read = @io.read([pending, 4096].min).size
raise UnexpectedEOF if @io.eof?
- pending -= bread
+ pending -= bytes_read
end
end
diff --git a/lib/rubygems/platform.rb b/lib/rubygems/platform.rb
index 5e932cd592d..3e5b5cde666 100644
--- a/lib/rubygems/platform.rb
+++ b/lib/rubygems/platform.rb
@@ -13,23 +13,6 @@ class Gem::Platform
attr_accessor :version
- DEPRECATED_CONSTS = [
- :DARWIN,
- :LINUX_586,
- :MSWIN32,
- :PPC_DARWIN,
- :WIN32,
- :X86_LINUX
- ]
-
- def self.const_missing(name) # TODO remove six months from 2007/12
- if DEPRECATED_CONSTS.include? name then
- raise NameError, "#{name} has been removed, use CURRENT instead"
- else
- super
- end
- end
-
def self.local
arch = Gem::ConfigMap[:arch]
arch = "#{arch}_60" if arch =~ /mswin32$/
@@ -73,7 +56,7 @@ class Gem::Platform
else cpu
end
- if arch.length == 2 and arch.last =~ /^\d+$/ then # for command-line
+ if arch.length == 2 and arch.last =~ /^\d+(\.\d+)?$/ then # for command-line
@os, @version = arch
return
end
diff --git a/lib/rubygems/remote_fetcher.rb b/lib/rubygems/remote_fetcher.rb
index 3c747f1d656..15707401639 100644
--- a/lib/rubygems/remote_fetcher.rb
+++ b/lib/rubygems/remote_fetcher.rb
@@ -78,7 +78,7 @@ class Gem::RemoteFetcher
if File.writable?(install_dir)
cache_dir = File.join install_dir, 'cache'
else
- cache_dir = File.join(ENV['HOME'], '.gem', 'cache')
+ cache_dir = File.join(Gem.user_dir, 'cache')
end
gem_file_name = "#{spec.full_name}.gem"
@@ -93,7 +93,7 @@ class Gem::RemoteFetcher
scheme = nil if scheme =~ /^[a-z]$/i
case scheme
- when 'http' then
+ when 'http', 'https' then
unless File.exist? local_gem_path then
begin
say "Downloading gem #{gem_file_name}" if
@@ -139,8 +139,8 @@ class Gem::RemoteFetcher
# Downloads +uri+ and returns it as a String.
def fetch_path(uri, mtime = nil, head = false)
- data = open_uri_or_path(uri, mtime, head)
- data = Gem.gunzip data if uri.to_s =~ /gz$/ and not head
+ data = open_uri_or_path uri, mtime, head
+ data = Gem.gunzip data if data and not head and uri.to_s =~ /gz$/
data
rescue FetchError
raise
@@ -216,8 +216,9 @@ class Gem::RemoteFetcher
connection = @connections[connection_id]
if uri.scheme == 'https' and not connection.started? then
- http_obj.use_ssl = true
- http_obj.verify_mode = OpenSSL::SSL::VERIFY_NONE
+ require 'net/https'
+ connection.use_ssl = true
+ connection.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
connection.start unless connection.started?
@@ -241,9 +242,10 @@ class Gem::RemoteFetcher
response = request uri, fetch_type, last_modified
case response
- when Net::HTTPOK then
+ when Net::HTTPOK, Net::HTTPNotModified then
head ? response : response.body
- when Net::HTTPRedirection then
+ when Net::HTTPMovedPermanently, Net::HTTPFound, Net::HTTPSeeOther,
+ Net::HTTPTemporaryRedirect then
raise FetchError.new('too many redirects', uri) if depth > 10
open_uri_or_path(response['Location'], last_modified, head, depth + 1)
@@ -274,6 +276,7 @@ class Gem::RemoteFetcher
request.add_field 'Keep-Alive', '30'
if last_modified then
+ last_modified = last_modified.utc
request.add_field 'If-Modified-Since', last_modified.rfc2822
end
@@ -282,9 +285,6 @@ class Gem::RemoteFetcher
retried = false
bad_response = false
- # HACK work around EOFError bug in Net::HTTP
- # NOTE Errno::ECONNABORTED raised a lot on Windows, and make impossible
- # to install gems.
begin
@requests[connection.object_id] += 1
response = connection.request request
@@ -297,6 +297,9 @@ class Gem::RemoteFetcher
bad_response = true
retry
+ # HACK work around EOFError bug in Net::HTTP
+ # NOTE Errno::ECONNABORTED raised a lot on Windows, and make impossible
+ # to install gems.
rescue EOFError, Errno::ECONNABORTED, Errno::ECONNRESET
requests = @requests[connection.object_id]
say "connection reset after #{requests} requests, retrying" if
diff --git a/lib/rubygems/rubygems_version.rb b/lib/rubygems/rubygems_version.rb
index d393e57a09b..06e2104715b 100644
--- a/lib/rubygems/rubygems_version.rb
+++ b/lib/rubygems/rubygems_version.rb
@@ -2,5 +2,5 @@
# This file is auto-generated by build scripts.
# See: rake update_version
module Gem
- RubyGemsVersion = '1.2.0.1824'
+ RubyGemsVersion = '1.3.0'
end
diff --git a/lib/rubygems/source_index.rb b/lib/rubygems/source_index.rb
index 1eefd8c1490..c6499ed2a86 100644
--- a/lib/rubygems/source_index.rb
+++ b/lib/rubygems/source_index.rb
@@ -7,7 +7,9 @@
require 'rubygems'
require 'rubygems/user_interaction'
require 'rubygems/specification'
-require 'rubygems/spec_fetcher'
+module Gem
+ autoload(:SpecFetcher, 'rubygems/spec_fetcher')
+end
##
# The SourceIndex object indexes all the gems available from a
@@ -80,8 +82,14 @@ class Gem::SourceIndex
def load_specification(file_name)
begin
- spec_code = File.read(file_name).untaint
+ spec_code = if RUBY_VERSION < '1.9' then
+ File.read file_name
+ else
+ File.read file_name, :encoding => 'UTF-8'
+ end.untaint
+
gemspec = eval spec_code, binding, file_name
+
if gemspec.is_a?(Gem::Specification)
gemspec.loaded_from = file_name
return gemspec
@@ -93,7 +101,7 @@ class Gem::SourceIndex
alert_warning e
alert_warning spec_code
rescue Exception => e
- alert_warning(e.inspect.to_s + "\n" + spec_code)
+ alert_warning "#{e.inspect}\n#{spec_code}"
alert_warning "Invalid .gemspec format in '#{file_name}'"
end
return nil
@@ -230,7 +238,8 @@ class Gem::SourceIndex
# Find a gem by an exact match on the short name.
def find_name(gem_name, version_requirement = Gem::Requirement.default)
- search(/^#{gem_name}$/, version_requirement)
+ dep = Gem::Dependency.new(/^#{gem_name}$/, version_requirement)
+ search dep
end
##
@@ -246,7 +255,13 @@ class Gem::SourceIndex
version_requirement = nil
only_platform = false
- case gem_pattern # TODO warn after 2008/03, remove three months after
+ # TODO - Remove support and warning for legacy arguments after 2008/11
+ unless Gem::Dependency === gem_pattern
+ warn "Gem::SourceIndex#search support for #{gem_pattern.class} patterns is deprecated"
+ warn "#{caller[0]} is outdated"
+ end
+
+ case gem_pattern
when Regexp then
version_requirement = platform_only || Gem::Requirement.default
when Gem::Dependency then
@@ -270,7 +285,7 @@ class Gem::SourceIndex
specs = @gems.values.select do |spec|
spec.name =~ gem_pattern and
- version_requirement.satisfied_by? spec.version
+ version_requirement.satisfied_by? spec.version
end
if only_platform then
@@ -539,7 +554,7 @@ module Gem
# objects to load properly.
Cache = SourceIndex
- # :starddoc:
+ # :startdoc:
end
diff --git a/lib/rubygems/source_info_cache.rb b/lib/rubygems/source_info_cache.rb
index ec6928c00da..fdb30ad8d31 100644
--- a/lib/rubygems/source_info_cache.rb
+++ b/lib/rubygems/source_info_cache.rb
@@ -284,6 +284,10 @@ class Gem::SourceInfoCache
cache_data.map do |source_uri, sic_entry|
next unless Gem.sources.include? source_uri
+ # TODO - Remove this gunk after 2008/11
+ unless pattern.kind_of?(Gem::Dependency)
+ pattern = Gem::Dependency.new(pattern, Gem::Requirement.default)
+ end
sic_entry.source_index.search pattern, platform_only
end.flatten.compact
end
@@ -300,6 +304,11 @@ class Gem::SourceInfoCache
cache_data.map do |source_uri, sic_entry|
next unless Gem.sources.include? source_uri
+ # TODO - Remove this gunk after 2008/11
+ unless pattern.kind_of?(Gem::Dependency)
+ pattern = Gem::Dependency.new(pattern, Gem::Requirement.default)
+ end
+
sic_entry.source_index.search(pattern, only_platform).each do |spec|
results << [spec, source_uri]
end
diff --git a/lib/rubygems/spec_fetcher.rb b/lib/rubygems/spec_fetcher.rb
index 66b4ee36c7c..a1fc82ed4f2 100644
--- a/lib/rubygems/spec_fetcher.rb
+++ b/lib/rubygems/spec_fetcher.rb
@@ -167,7 +167,7 @@ class Gem::SpecFetcher
if all and @specs.include? source_uri then
list[source_uri] = @specs[source_uri]
- elsif @latest_specs.include? source_uri then
+ elsif not all and @latest_specs.include? source_uri then
list[source_uri] = @latest_specs[source_uri]
else
specs = load_specs source_uri, file
@@ -182,6 +182,10 @@ class Gem::SpecFetcher
list
end
+ ##
+ # Loads specs in +file+, fetching from +source_uri+ if the on-disk cache is
+ # out of date.
+
def load_specs(source_uri, file)
file_name = "#{file}.#{Gem.marshal_version}"
spec_path = source_uri + "#{file_name}.gz"
@@ -192,7 +196,7 @@ class Gem::SpecFetcher
if File.exist? local_file then
spec_dump = @fetcher.fetch_path spec_path, File.mtime(local_file)
- if spec_dump.empty? then
+ if spec_dump.nil? then
spec_dump = Gem.read_binary local_file
else
loaded = true
diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb
index f3f38e50333..2e6cdc1b046 100644
--- a/lib/rubygems/specification.rb
+++ b/lib/rubygems/specification.rb
@@ -24,6 +24,7 @@ class Date; end # for ruby_code if date.rb wasn't required
module Gem
+ ##
# == Gem::Specification
#
# The Specification class contains the metadata for a Gem. Typically
@@ -38,7 +39,7 @@ module Gem
#
# There are many <em>gemspec attributes</em>, and the best place to learn
# about them in the "Gemspec Reference" linked from the RubyGems wiki.
- #
+
class Specification
##
@@ -46,8 +47,6 @@ module Gem
attr_accessor :original_platform # :nodoc:
- # ------------------------- Specification version constants.
-
##
# The the version number of a specification that does not specify one
# (i.e. RubyGems 0.7 or earlier).
@@ -88,77 +87,98 @@ module Gem
TODAY = now - ((now.to_i + now.gmt_offset) % 86400)
# :startdoc:
- # ------------------------- Class variables.
-
+ ##
# List of Specification instances.
+
@@list = []
+ ##
# Optional block used to gather newly defined instances.
+
@@gather = nil
+ ##
# List of attribute names: [:name, :version, ...]
@@required_attributes = []
- # List of _all_ attributes and default values: [[:name, nil], [:bindir, 'bin'], ...]
+ ##
+ # List of _all_ attributes and default values:
+ #
+ # [[:name, nil],
+ # [:bindir, 'bin'],
+ # ...]
+
@@attributes = []
@@nil_attributes = []
@@non_nil_attributes = [:@original_platform]
+ ##
# List of array attributes
+
@@array_attributes = []
+ ##
# Map of attribute names to default values.
+
@@default_value = {}
- # ------------------------- Convenience class methods.
+ ##
+ # Names of all specification attributes
def self.attribute_names
@@attributes.map { |name, default| name }
end
+ ##
+ # Default values for specification attributes
+
def self.attribute_defaults
@@attributes.dup
end
+ ##
+ # The default value for specification attribute +name+
+
def self.default_value(name)
@@default_value[name]
end
+ ##
+ # Required specification attributes
+
def self.required_attributes
@@required_attributes.dup
end
+ ##
+ # Is +name+ a required attribute?
+
def self.required_attribute?(name)
@@required_attributes.include? name.to_sym
end
+ ##
+ # Specification attributes that are arrays (appendable and so-forth)
+
def self.array_attributes
@@array_attributes.dup
end
- # ------------------------- Infrastructure class methods.
+ ##
+ # A list of Specification instances that have been defined in this Ruby
+ # instance.
- # A list of Specification instances that have been defined in this Ruby instance.
def self.list
@@list
end
- # Used to specify the name and default value of a specification
- # attribute. The side effects are:
- # * the name and default value are added to the @@attributes list
- # and @@default_value map
- # * a standard _writer_ method (<tt>attribute=</tt>) is created
- # * a non-standard _reader method (<tt>attribute</tt>) is created
- #
- # The reader method behaves like this:
- # def attribute
- # @attribute ||= (copy of default value)
- # end
- #
- # This allows lazy initialization of attributes to their default
- # values.
+ ##
+ # Specifies the +name+ and +default+ for a specification attribute, and
+ # creates a reader and writer method like Module#attr_accessor.
#
+ # The reader method returns the default if the value hasn't been set.
+
def self.attribute(name, default=nil)
ivar_name = "@#{name}".intern
if default.nil? then
@@ -172,8 +192,10 @@ module Gem
attr_accessor(name)
end
- # Same as :attribute, but ensures that values assigned to the
- # attribute are array values by applying :to_a to the value.
+ ##
+ # Same as :attribute, but ensures that values assigned to the attribute
+ # are array values by applying :to_a to the value.
+
def self.array_attribute(name)
@@non_nil_attributes << ["@#{name}".intern, []]
@@ -192,51 +214,60 @@ module Gem
module_eval code, __FILE__, __LINE__ - 9
end
+ ##
# Same as attribute above, but also records this attribute as mandatory.
+
def self.required_attribute(*args)
@@required_attributes << args.first
attribute(*args)
end
- # Sometimes we don't want the world to use a setter method for a particular attribute.
+ ##
+ # Sometimes we don't want the world to use a setter method for a
+ # particular attribute.
+ #
# +read_only+ makes it private so we can still use it internally.
+
def self.read_only(*names)
names.each do |name|
private "#{name}="
end
end
- # Shortcut for creating several attributes at once (each with a default value of
- # +nil+).
+ # Shortcut for creating several attributes at once (each with a default
+ # value of +nil+).
+
def self.attributes(*args)
args.each do |arg|
attribute(arg, nil)
end
end
- # Some attributes require special behaviour when they are accessed. This allows for
- # that.
+ ##
+ # Some attributes require special behaviour when they are accessed. This
+ # allows for that.
+
def self.overwrite_accessor(name, &block)
remove_method name
define_method(name, &block)
end
- # Defines a _singular_ version of an existing _plural_ attribute
- # (i.e. one whose value is expected to be an array). This means
- # just creating a helper method that takes a single value and
- # appends it to the array. These are created for convenience, so
- # that in a spec, one can write
+ ##
+ # Defines a _singular_ version of an existing _plural_ attribute (i.e. one
+ # whose value is expected to be an array). This means just creating a
+ # helper method that takes a single value and appends it to the array.
+ # These are created for convenience, so that in a spec, one can write
#
# s.require_path = 'mylib'
#
- # instead of
+ # instead of:
#
# s.require_paths = ['mylib']
#
- # That above convenience is available courtesy of
+ # That above convenience is available courtesy of:
#
# attribute_alias_singular :require_path, :require_paths
- #
+
def self.attribute_alias_singular(singular, plural)
define_method("#{singular}=") { |val|
send("#{plural}=", [val])
@@ -320,189 +351,45 @@ module Gem
spec
end
- # REQUIRED gemspec attributes ------------------------------------
-
- required_attribute :rubygems_version, Gem::RubyGemsVersion
- required_attribute :specification_version, CURRENT_SPECIFICATION_VERSION
- required_attribute :name
- required_attribute :version
- required_attribute :date, TODAY
- required_attribute :summary
- required_attribute :require_paths, ['lib']
-
- # OPTIONAL gemspec attributes ------------------------------------
-
- attributes :email, :homepage, :rubyforge_project, :description
- attributes :autorequire, :default_executable
-
- attribute :bindir, 'bin'
- attribute :has_rdoc, false
- attribute :required_ruby_version, Gem::Requirement.default
- attribute :required_rubygems_version, Gem::Requirement.default
- attribute :platform, Gem::Platform::RUBY
-
- attribute :signing_key, nil
- attribute :cert_chain, []
- attribute :post_install_message, nil
-
- array_attribute :authors
- array_attribute :files
- array_attribute :test_files
- array_attribute :rdoc_options
- array_attribute :extra_rdoc_files
- array_attribute :executables
-
- # Array of extensions to build. See Gem::Installer#build_extensions for
- # valid values.
-
- array_attribute :extensions
- array_attribute :requirements
- array_attribute :dependencies
-
- read_only :dependencies
+ ##
+ # List of depedencies that will automatically be activated at runtime.
def runtime_dependencies
dependencies.select { |d| d.type == :runtime || d.type == nil }
end
+ ##
+ # List of dependencies that are used for development
+
def development_dependencies
dependencies.select { |d| d.type == :development }
end
- # ALIASED gemspec attributes -------------------------------------
-
- attribute_alias_singular :executable, :executables
- attribute_alias_singular :author, :authors
- attribute_alias_singular :require_path, :require_paths
- attribute_alias_singular :test_file, :test_files
-
- # DEPRECATED gemspec attributes ----------------------------------
-
- def test_suite_file
+ def test_suite_file # :nodoc:
warn 'test_suite_file deprecated, use test_files'
test_files.first
end
- def test_suite_file=(val)
+ def test_suite_file=(val) # :nodoc:
warn 'test_suite_file= deprecated, use test_files='
@test_files = [] unless defined? @test_files
@test_files << val
end
+ ##
# true when this gemspec has been loaded from a specifications directory.
# This attribute is not persisted.
- attr_writer :loaded
+ attr_accessor :loaded
+ ##
# Path this gemspec was loaded from. This attribute is not persisted.
- attr_accessor :loaded_from
-
- # Special accessor behaviours (overwriting default) --------------
-
- overwrite_accessor :version= do |version|
- @version = Version.create(version)
- end
-
- overwrite_accessor :platform do
- @new_platform
- end
-
- overwrite_accessor :platform= do |platform|
- if @original_platform.nil? or
- @original_platform == Gem::Platform::RUBY then
- @original_platform = platform
- end
-
- case platform
- when Gem::Platform::CURRENT then
- @new_platform = Gem::Platform.local
- @original_platform = @new_platform.to_s
-
- when Gem::Platform then
- @new_platform = platform
-
- # legacy constants
- when nil, Gem::Platform::RUBY then
- @new_platform = Gem::Platform::RUBY
- when 'mswin32' then # was Gem::Platform::WIN32
- @new_platform = Gem::Platform.new 'x86-mswin32'
- when 'i586-linux' then # was Gem::Platform::LINUX_586
- @new_platform = Gem::Platform.new 'x86-linux'
- when 'powerpc-darwin' then # was Gem::Platform::DARWIN
- @new_platform = Gem::Platform.new 'ppc-darwin'
- else
- @new_platform = Gem::Platform.new platform
- end
-
- @platform = @new_platform.to_s
-
- @new_platform
- end
-
- overwrite_accessor :required_ruby_version= do |value|
- @required_ruby_version = Gem::Requirement.create(value)
- end
-
- overwrite_accessor :required_rubygems_version= do |value|
- @required_rubygems_version = Gem::Requirement.create(value)
- end
-
- overwrite_accessor :date= do |date|
- # We want to end up with a Time object with one-day resolution.
- # This is the cleanest, most-readable, faster-than-using-Date
- # way to do it.
- case date
- when String then
- @date = if /\A(\d{4})-(\d{2})-(\d{2})\Z/ =~ date then
- Time.local($1.to_i, $2.to_i, $3.to_i)
- else
- require 'time'
- Time.parse date
- end
- when Time then
- @date = Time.local(date.year, date.month, date.day)
- when Date then
- @date = Time.local(date.year, date.month, date.day)
- else
- @date = TODAY
- end
- end
- overwrite_accessor :date do
- self.date = nil if @date.nil? # HACK Sets the default value for date
- @date
- end
-
- overwrite_accessor :summary= do |str|
- @summary = if str then
- str.strip.
- gsub(/(\w-)\n[ \t]*(\w)/, '\1\2').
- gsub(/\n[ \t]*/, " ")
- end
- end
-
- overwrite_accessor :description= do |str|
- @description = if str then
- str.strip.
- gsub(/(\w-)\n[ \t]*(\w)/, '\1\2').
- gsub(/\n[ \t]*/, " ")
- end
- end
+ attr_accessor :loaded_from
- overwrite_accessor :default_executable do
- begin
- if defined?(@default_executable) and @default_executable
- result = @default_executable
- elsif @executables and @executables.size == 1
- result = Array(@executables).first
- else
- result = nil
- end
- result
- rescue
- nil
- end
- end
+ ##
+ # Returns an array with bindir attached to each executable in the
+ # executables list
def add_bindir(executables)
return nil if executables.nil?
@@ -516,17 +403,9 @@ module Gem
return nil
end
- overwrite_accessor :files do
- result = []
- result.push(*@files) if defined?(@files)
- result.push(*@test_files) if defined?(@test_files)
- result.push(*(add_bindir(@executables)))
- result.push(*@extra_rdoc_files) if defined?(@extra_rdoc_files)
- result.push(*@extensions) if defined?(@extensions)
- result.uniq.compact
- end
-
+ ##
# Files in the Gem under one of the require_paths
+
def lib_files
@files.select do |file|
require_paths.any? do |path|
@@ -535,34 +414,25 @@ module Gem
end
end
- overwrite_accessor :test_files do
- # Handle the possibility that we have @test_suite_file but not
- # @test_files. This will happen when an old gem is loaded via
- # YAML.
- if defined? @test_suite_file then
- @test_files = [@test_suite_file].flatten
- @test_suite_file = nil
- end
- if defined?(@test_files) and @test_files then
- @test_files
- else
- @test_files = []
- end
+ ##
+ # True if this gem was loaded from disk
+
+ alias :loaded? :loaded
+
+ ##
+ # True if this gem has files in test_files
+
+ def has_unit_tests?
+ not test_files.empty?
end
- # Predicates -----------------------------------------------------
-
- def loaded?; @loaded ? true : false ; end
- def has_rdoc?; has_rdoc ? true : false ; end
- def has_unit_tests?; not test_files.empty?; end
- alias has_test_suite? has_unit_tests? # (deprecated)
-
- # Constructors ---------------------------------------------------
+ alias has_test_suite? has_unit_tests? # :nodoc: deprecated
+ ##
# Specification constructor. Assigns the default values to the
# attributes, adds this spec to the list of loaded specs (see
# Specification.list), and yields itself for further initialization.
- #
+
def initialize
@new_platform = nil
assign_defaults
@@ -575,11 +445,13 @@ module Gem
@@gather.call(self) if @@gather
end
- # Each attribute has a default value (possibly nil). Here, we
- # initialize all attributes to their default value. This is
- # done through the accessor methods, so special behaviours will
- # be honored. Furthermore, we take a _copy_ of the default so
- # each specification instance has its own empty arrays, etc.
+ ##
+ # Each attribute has a default value (possibly nil). Here, we initialize
+ # all attributes to their default value. This is done through the
+ # accessor methods, so special behaviours will be honored. Furthermore,
+ # we take a _copy_ of the default so each specification instance has its
+ # own empty arrays, etc.
+
def assign_defaults
@@nil_attributes.each do |name|
instance_variable_set name, nil
@@ -598,13 +470,14 @@ module Gem
instance_variable_set :@new_platform, Gem::Platform::RUBY
end
- # Special loader for YAML files. When a Specification object is
- # loaded from a YAML file, it bypasses the normal Ruby object
- # initialization routine (#initialize). This method makes up for
- # that and deals with gems of different ages.
+ ##
+ # Special loader for YAML files. When a Specification object is loaded
+ # from a YAML file, it bypasses the normal Ruby object initialization
+ # routine (#initialize). This method makes up for that and deals with
+ # gems of different ages.
#
# 'input' can be anything that YAML.load() accepts: String or IO.
- #
+
def self.from_yaml(input)
input = normalize_yaml_input input
spec = YAML.load input
@@ -627,6 +500,9 @@ module Gem
spec
end
+ ##
+ # Loads ruby format gemspec from +filename+
+
def self.load(filename)
gemspec = nil
fail "NESTED Specification.load calls not allowed!" if @@gather
@@ -638,22 +514,25 @@ module Gem
@@gather = nil
end
- # Make sure the yaml specification is properly formatted with dashes.
+ ##
+ # Make sure the YAML specification is properly formatted with dashes
+
def self.normalize_yaml_input(input)
result = input.respond_to?(:read) ? input.read : input
result = "--- " + result unless result =~ /^--- /
result
end
- # Instance methods -----------------------------------------------
-
- # Sets the rubygems_version to Gem::RubyGemsVersion.
- #
+ ##
+ # Sets the rubygems_version to the current RubyGems version
+
def mark_version
@rubygems_version = RubyGemsVersion
end
- # Ignore unknown attributes if the
+ ##
+ # Ignore unknown attributes while loading
+
def method_missing(sym, *a, &b) # :nodoc:
if @specification_version > CURRENT_SPECIFICATION_VERSION and
sym.to_s =~ /=$/ then
@@ -663,35 +542,39 @@ module Gem
end
end
- # Adds a development dependency to this Gem. For example,
- #
- # spec.add_development_dependency('jabber4r', '> 0.1', '<= 0.5')
+ ##
+ # Adds a development dependency named +gem+ with +requirements+ to this
+ # Gem. For example:
#
- # Development dependencies aren't installed by default, and
- # aren't activated when a gem is required.
+ # spec.add_development_dependency 'jabber4r', '> 0.1', '<= 0.5'
#
- # gem:: [String or Gem::Dependency] The Gem name/dependency.
- # requirements:: [default=">= 0"] The version requirements.
+ # Development dependencies aren't installed by default and aren't
+ # activated when a gem is required.
+
def add_development_dependency(gem, *requirements)
add_dependency_with_type(gem, :development, *requirements)
end
- # Adds a runtime dependency to this Gem. For example,
- #
- # spec.add_runtime_dependency('jabber4r', '> 0.1', '<= 0.5')
+ ##
+ # Adds a runtime dependency named +gem+ with +requirements+ to this Gem.
+ # For example:
#
- # gem:: [String or Gem::Dependency] The Gem name/dependency.
- # requirements:: [default=">= 0"] The version requirements.
+ # spec.add_runtime_dependency 'jabber4r', '> 0.1', '<= 0.5'
+
def add_runtime_dependency(gem, *requirements)
add_dependency_with_type(gem, :runtime, *requirements)
end
+ ##
+ # Adds a runtime dependency
+
alias add_dependency add_runtime_dependency
+ ##
# Returns the full name (name-version) of this Gem. Platform information
- # is included (name-version-platform) if it is specified (and not the
- # default Ruby platform).
- #
+ # is included (name-version-platform) if it is specified and not the
+ # default Ruby platform.
+
def full_name
if platform == Gem::Platform::RUBY or platform.nil? then
"#{@name}-#{@version}"
@@ -700,9 +583,10 @@ module Gem
end
end
+ ##
# Returns the full name (name-version) of this gemspec using the original
- # platform.
- #
+ # platform. For use with legacy gems.
+
def original_name # :nodoc:
if platform == Gem::Platform::RUBY or platform.nil? then
"#{@name}-#{@version}"
@@ -736,18 +620,16 @@ module Gem
File.expand_path path
end
- # Checks if this Specification meets the requirement of the supplied
- # dependency.
- #
- # dependency:: [Gem::Dependency] the dependency to check
- # return:: [Boolean] true if dependency is met, otherwise false
- #
+ ##
+ # Checks if this specification meets the requirement of +dependency+.
+
def satisfies_requirement?(dependency)
return @name == dependency.name &&
dependency.version_requirements.satisfied_by?(@version)
end
- # Comparison methods ---------------------------------------------
+ ##
+ # 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]
@@ -757,19 +639,25 @@ module Gem
sort_obj <=> other.sort_obj
end
+ ##
# Tests specs for equality (across all attributes).
+
def ==(other) # :nodoc:
self.class === other && same_attributes?(other)
end
alias eql? == # :nodoc:
+ ##
+ # True if this gem has the same attributes as +other+.
+
def same_attributes?(other)
@@attributes.each do |name, default|
return false unless self.send(name) == other.send(name)
end
true
end
+
private :same_attributes?
def hash # :nodoc:
@@ -779,8 +667,6 @@ module Gem
}
end
- # Export methods (YAML and Ruby code) ----------------------------
-
def to_yaml(opts = {}) # :nodoc:
mark_version
@@ -825,6 +711,8 @@ module Gem
def to_ruby
mark_version
result = []
+ result << "# -*- encoding: utf-8 -*-"
+ result << nil
result << "Gem::Specification.new do |s|"
result << " s.name = #{ruby_code name}"
@@ -861,7 +749,7 @@ module Gem
result << " s.specification_version = #{specification_version}"
result << nil
- result << " if current_version >= 3 then"
+ result << " if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then"
unless dependencies.empty? then
dependencies.each do |dep|
@@ -895,16 +783,15 @@ module Gem
result.join "\n"
end
- # Validation and normalization methods ---------------------------
-
- # Checks that the specification contains all required fields, and
- # does a very basic sanity check.
+ ##
+ # Checks that the specification contains all required fields, and does a
+ # very basic sanity check.
#
- # Raises InvalidSpecificationException if the spec does not pass
- # the checks..
+ # Raises InvalidSpecificationException if the spec does not pass the
+ # checks..
+
def validate
extend Gem::UserInteraction
-
normalize
if rubygems_version != RubyGemsVersion then
@@ -959,13 +846,14 @@ module Gem
true
end
+ ##
# Normalize the list of files so that:
# * All file lists have redundancies removed.
- # * Files referenced in the extra_rdoc_files are included in the
- # package file list.
+ # * 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.
+ # Also, the summary and description are converted to a normal format.
+
def normalize
if defined?(@extra_rdoc_files) and @extra_rdoc_files then
@extra_rdoc_files.uniq!
@@ -975,15 +863,12 @@ module Gem
@files.uniq! if @files
end
- # Dependency methods ---------------------------------------------
-
- # Return a list of all gems that have a dependency on this
- # gemspec. The list is structured with entries that conform to:
+ ##
+ # Return a list of all gems that have a dependency on this gemspec. The
+ # list is structured with entries that conform to:
#
# [depending_gem, dependency, [list_of_gems_that_satisfy_dependency]]
- #
- # return:: [Array] [[dependent_gem, dependency, [list_of_satisfiers]]]
- #
+
def dependent_gems
out = []
Gem.source_index.each do |name,gem|
@@ -1004,8 +889,6 @@ module Gem
"#<Gem::Specification name=#{@name} version=#{@version}>"
end
- private
-
def add_dependency_with_type(dependency, type, *requirements)
requirements = if requirements.empty? then
Gem::Requirement.default
@@ -1022,6 +905,8 @@ module Gem
dependencies << dependency
end
+ private :add_dependency_with_type
+
def find_all_satisfiers(dep)
Gem.source_index.each do |name,gem|
if(gem.satisfies_requirement?(dep)) then
@@ -1030,8 +915,12 @@ module Gem
end
end
- # Return a string containing a Ruby code representation of the
- # given object.
+ private :find_all_satisfiers
+
+ ##
+ # Return a string containing a Ruby code representation of the given
+ # object.
+
def ruby_code(obj)
case obj
when String then '%q{' + obj + '}'
@@ -1046,6 +935,326 @@ module Gem
else raise Exception, "ruby_code case not handled: #{obj.class}"
end
end
+
+ private :ruby_code
+
+ # :section: Required gemspec attributes
+
+ ##
+ # The version of RubyGems used to create this gem
+
+ required_attribute :rubygems_version, Gem::RubyGemsVersion
+
+ ##
+ # The Gem::Specification version of this gemspec
+
+ required_attribute :specification_version, CURRENT_SPECIFICATION_VERSION
+
+ ##
+ # This gem's name
+
+ required_attribute :name
+
+ ##
+ # This gem's version
+
+ required_attribute :version
+
+ ##
+ # The date this gem was created
+
+ required_attribute :date, TODAY
+
+ ##
+ # A short summary of this gem's description. Displayed in `gem list -d`.
+
+ required_attribute :summary
+
+ ##
+ # Paths in the gem to add to $LOAD_PATH when this gem is activated
+
+ required_attribute :require_paths, ['lib']
+
+ # :section: Optional gemspec attributes
+
+ ##
+ # A contact email for this gem
+
+ attribute :email
+
+ ##
+ # The URL of this gem's home page
+
+ attribute :homepage
+
+ ##
+ # The rubyforge project this gem lives under. i.e. RubyGems'
+ # rubyforge_project is "rubygems".
+
+ attribute :rubyforge_project
+
+ ##
+ # A long description of this gem
+
+ attribute :description
+
+ ##
+ # Autorequire was used by old RubyGems to automatically require a file.
+ # It no longer is supported.
+
+ attribute :autorequire
+
+ ##
+ # The default executable for this gem.
+
+ attribute :default_executable
+
+ ##
+ # The path in the gem for executable scripts
+
+ attribute :bindir, 'bin'
+
+ ##
+ # True if this gem is RDoc-compliant
+
+ attribute :has_rdoc, false
+
+ ##
+ # True if this gem supports RDoc
+
+ alias :has_rdoc? :has_rdoc
+
+ ##
+ # The ruby of version required by this gem
+
+ attribute :required_ruby_version, Gem::Requirement.default
+
+ ##
+ # The RubyGems version required by this gem
+
+ attribute :required_rubygems_version, Gem::Requirement.default
+
+ ##
+ # The platform this gem runs on. See Gem::Platform for details.
+
+ attribute :platform, Gem::Platform::RUBY
+
+ ##
+ # The key used to sign this gem. See Gem::Security for details.
+
+ attribute :signing_key, nil
+
+ ##
+ # The certificate chain used to sign this gem. See Gem::Security for
+ # details.
+
+ attribute :cert_chain, []
+
+ ##
+ # A message that gets displayed after the gem is installed
+
+ attribute :post_install_message, nil
+
+ ##
+ # The list of authors who wrote this gem
+
+ array_attribute :authors
+
+ ##
+ # Files included in this gem
+
+ array_attribute :files
+
+ ##
+ # Test files included in this gem
+
+ array_attribute :test_files
+
+ ##
+ # An ARGV-style array of options to RDoc
+
+ array_attribute :rdoc_options
+
+ ##
+ # Extra files to add to RDoc
+
+ array_attribute :extra_rdoc_files
+
+ ##
+ # Executables included in the gem
+
+ array_attribute :executables
+
+ ##
+ # Extensions to build when installing the gem. See
+ # Gem::Installer#build_extensions for valid values.
+
+ array_attribute :extensions
+
+ ##
+ # 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.
+
+ array_attribute :dependencies
+
+ read_only :dependencies
+
+ # :section: Aliased gemspec attributes
+
+ ##
+ # Singular accessor for executables
+
+ attribute_alias_singular :executable, :executables
+
+ ##
+ # Singular accessor for authors
+
+ attribute_alias_singular :author, :authors
+
+ ##
+ # Singular accessor for require_paths
+
+ attribute_alias_singular :require_path, :require_paths
+
+ ##
+ # Singular accessor for test_files
+
+ attribute_alias_singular :test_file, :test_files
+
+ overwrite_accessor :version= do |version|
+ @version = Version.create(version)
+ end
+
+ overwrite_accessor :platform do
+ @new_platform
+ end
+
+ overwrite_accessor :platform= do |platform|
+ if @original_platform.nil? or
+ @original_platform == Gem::Platform::RUBY then
+ @original_platform = platform
+ end
+
+ case platform
+ when Gem::Platform::CURRENT then
+ @new_platform = Gem::Platform.local
+ @original_platform = @new_platform.to_s
+
+ when Gem::Platform then
+ @new_platform = platform
+
+ # legacy constants
+ when nil, Gem::Platform::RUBY then
+ @new_platform = Gem::Platform::RUBY
+ when 'mswin32' then # was Gem::Platform::WIN32
+ @new_platform = Gem::Platform.new 'x86-mswin32'
+ when 'i586-linux' then # was Gem::Platform::LINUX_586
+ @new_platform = Gem::Platform.new 'x86-linux'
+ when 'powerpc-darwin' then # was Gem::Platform::DARWIN
+ @new_platform = Gem::Platform.new 'ppc-darwin'
+ else
+ @new_platform = Gem::Platform.new platform
+ end
+
+ @platform = @new_platform.to_s
+
+ @new_platform
+ end
+
+ overwrite_accessor :required_ruby_version= do |value|
+ @required_ruby_version = Gem::Requirement.create(value)
+ end
+
+ overwrite_accessor :required_rubygems_version= do |value|
+ @required_rubygems_version = Gem::Requirement.create(value)
+ end
+
+ overwrite_accessor :date= do |date|
+ # We want to end up with a Time object with one-day resolution.
+ # This is the cleanest, most-readable, faster-than-using-Date
+ # way to do it.
+ case date
+ when String then
+ @date = if /\A(\d{4})-(\d{2})-(\d{2})\Z/ =~ date then
+ Time.local($1.to_i, $2.to_i, $3.to_i)
+ else
+ require 'time'
+ Time.parse date
+ end
+ when Time then
+ @date = Time.local(date.year, date.month, date.day)
+ when Date then
+ @date = Time.local(date.year, date.month, date.day)
+ else
+ @date = TODAY
+ end
+ end
+
+ overwrite_accessor :date do
+ self.date = nil if @date.nil? # HACK Sets the default value for date
+ @date
+ end
+
+ overwrite_accessor :summary= do |str|
+ @summary = if str then
+ str.strip.
+ gsub(/(\w-)\n[ \t]*(\w)/, '\1\2').
+ gsub(/\n[ \t]*/, " ")
+ end
+ end
+
+ overwrite_accessor :description= do |str|
+ @description = if str then
+ str.strip.
+ gsub(/(\w-)\n[ \t]*(\w)/, '\1\2').
+ gsub(/\n[ \t]*/, " ")
+ end
+ end
+
+ overwrite_accessor :default_executable do
+ begin
+ if defined?(@default_executable) and @default_executable
+ result = @default_executable
+ elsif @executables and @executables.size == 1
+ result = Array(@executables).first
+ else
+ result = nil
+ end
+ result
+ rescue
+ nil
+ end
+ end
+
+ overwrite_accessor :test_files do
+ # Handle the possibility that we have @test_suite_file but not
+ # @test_files. This will happen when an old gem is loaded via
+ # YAML.
+ if defined? @test_suite_file then
+ @test_files = [@test_suite_file].flatten
+ @test_suite_file = nil
+ end
+ if defined?(@test_files) and @test_files then
+ @test_files
+ else
+ @test_files = []
+ end
+ end
+
+ overwrite_accessor :files do
+ result = []
+ result.push(*@files) if defined?(@files)
+ result.push(*@test_files) if defined?(@test_files)
+ result.push(*(add_bindir(@executables)))
+ result.push(*@extra_rdoc_files) if defined?(@extra_rdoc_files)
+ result.push(*@extensions) if defined?(@extensions)
+ result.uniq.compact
+ end
end
diff --git a/lib/rubygems/test_utilities.rb b/lib/rubygems/test_utilities.rb
index e8709b9be31..8b23d3236e0 100644
--- a/lib/rubygems/test_utilities.rb
+++ b/lib/rubygems/test_utilities.rb
@@ -34,16 +34,20 @@ class Gem::FakeFetcher
path = path.to_s
@paths << path
raise ArgumentError, 'need full URI' unless path =~ %r'^http://'
- data = @data[path]
- if data.nil? then
- raise Gem::RemoteFetcher::FetchError.new('no data', path)
+ unless @data.key? path then
+ raise Gem::RemoteFetcher::FetchError.new("no data for #{path}", path)
end
+ data = @data[path]
+
if data.respond_to?(:call) then
data.call
else
- data = Gem.gunzip data if path.to_s =~ /gz$/ unless data.empty?
+ if path.to_s =~ /gz$/ and not data.nil? and not data.empty? then
+ data = Gem.gunzip data
+ end
+
data
end
end
@@ -51,13 +55,15 @@ class Gem::FakeFetcher
def fetch_size(path)
path = path.to_s
@paths << path
+
raise ArgumentError, 'need full URI' unless path =~ %r'^http://'
- data = @data[path]
- if data.nil? then
- raise Gem::RemoteFetcher::FetchError.new("no data for #{path}", nil)
+ unless @data.key? path then
+ raise Gem::RemoteFetcher::FetchError.new("no data for #{path}", path)
end
+ data = @data[path]
+
data.respond_to?(:call) ? data.call : data.length
end
diff --git a/lib/rubygems/uninstaller.rb b/lib/rubygems/uninstaller.rb
index 2ad961972b2..5f19da5e82a 100644
--- a/lib/rubygems/uninstaller.rb
+++ b/lib/rubygems/uninstaller.rb
@@ -18,9 +18,23 @@ class Gem::Uninstaller
include Gem::UserInteraction
##
- # Constructs an Uninstaller instance
- #
- # gem:: [String] The Gem name to uninstall
+ # The directory a gem's executables will be installed into
+
+ attr_reader :bin_dir
+
+ ##
+ # The gem repository the gem will be installed into
+
+ attr_reader :gem_home
+
+ ##
+ # The Gem::Specification for the gem being uninstalled, only set during
+ # #uninstall_gem
+
+ attr_reader :spec
+
+ ##
+ # Constructs an uninstaller that will uninstall +gem+
def initialize(gem, options = {})
@gem = gem
@@ -31,42 +45,63 @@ class Gem::Uninstaller
@force_all = options[:all]
@force_ignore = options[:ignore]
@bin_dir = options[:bin_dir]
+
+ spec_dir = File.join @gem_home, 'specifications'
+ @source_index = Gem::SourceIndex.from_gems_in spec_dir
end
##
- # Performs the uninstall of the Gem. This removes the spec, the
- # Gem directory, and the cached .gem file,
+ # Performs the uninstall of the gem. This removes the spec, the Gem
+ # directory, and the cached .gem file.
def uninstall
- list = Gem.source_index.search(/^#{@gem}$/, @version)
+ list = @source_index.find_name @gem, @version
if list.empty? then
raise Gem::InstallError, "Unknown gem #{@gem} #{@version}"
- elsif list.size > 1 && @force_all
- remove_all(list.dup)
- remove_executables(list.last)
- elsif list.size > 1
- say
+
+ elsif list.size > 1 and @force_all then
+ remove_all list.dup
+
+ elsif list.size > 1 then
gem_names = list.collect {|gem| gem.full_name} + ["All versions"]
- gem_name, index =
- choose_from_list("Select gem to uninstall:", gem_names)
- if index == list.size
- remove_all(list.dup)
- remove_executables(list.last)
- elsif index >= 0 && index < list.size
- to_remove = list[index]
- remove(to_remove, list)
- remove_executables(to_remove)
+
+ say
+ gem_name, index = choose_from_list "Select gem to uninstall:", gem_names
+
+ if index == list.size then
+ remove_all list.dup
+ elsif index >= 0 && index < list.size then
+ uninstall_gem list[index], list.dup
else
say "Error: must enter a number [1-#{list.size+1}]"
end
else
- remove(list[0], list.dup)
- remove_executables(list.last)
+ uninstall_gem list.first, list.dup
end
end
##
+ # Uninstalls gem +spec+
+
+ def uninstall_gem(spec, specs)
+ @spec = spec
+
+ Gem.pre_uninstall_hooks.each do |hook|
+ hook.call self
+ end
+
+ specs.each { |s| remove_executables s }
+ remove spec, specs
+
+ Gem.post_uninstall_hooks.each do |hook|
+ hook.call self
+ end
+
+ @spec = nil
+ end
+
+ ##
# Removes installed executables and batch files (windows only) for
# +gemspec+.
@@ -76,7 +111,7 @@ class Gem::Uninstaller
if gemspec.executables.size > 0 then
bindir = @bin_dir ? @bin_dir : (Gem.bindir @gem_home)
- list = Gem.source_index.search(gemspec.name).delete_if { |spec|
+ list = @source_index.find_name(gemspec.name).delete_if { |spec|
spec.version == gemspec.version
}
@@ -118,7 +153,7 @@ class Gem::Uninstaller
# NOTE: removes uninstalled gems from +list+.
def remove_all(list)
- list.dup.each { |spec| remove spec, list }
+ list.dup.each { |spec| uninstall_gem spec, list }
end
##
@@ -185,8 +220,7 @@ class Gem::Uninstaller
def dependencies_ok?(spec)
return true if @force_ignore
- source_index = Gem::SourceIndex.from_installed_gems
- deplist = Gem::DependencyList.from_source_index source_index
+ deplist = Gem::DependencyList.from_source_index @source_index
deplist.ok_to_remove?(spec.full_name) || ask_if_ok(spec)
end
diff --git a/test/rubygems/gemutilities.rb b/test/rubygems/gemutilities.rb
index 0ab2c5272cb..d1e50676d51 100644
--- a/test/rubygems/gemutilities.rb
+++ b/test/rubygems/gemutilities.rb
@@ -19,6 +19,10 @@ require 'rubygems/test_utilities'
require File.join(File.expand_path(File.dirname(__FILE__)), 'mockgemui')
module Gem
+ def self.searcher=(searcher)
+ MUTEX.synchronize do @searcher = searcher end
+ end
+
def self.source_index=(si)
@@source_index = si
end
@@ -26,7 +30,7 @@ module Gem
def self.win_platform=(val)
@@win_platform = val
end
-
+
module DefaultUserInteraction
@ui = MockGemUi.new
end
@@ -89,6 +93,27 @@ class RubyGemTestCase < Test::Unit::TestCase
'private_key.pem')
@public_cert = File.expand_path File.join(File.dirname(__FILE__),
'public_cert.pem')
+
+ Gem.post_install_hooks.clear
+ Gem.post_uninstall_hooks.clear
+ Gem.pre_install_hooks.clear
+ Gem.pre_uninstall_hooks.clear
+
+ Gem.post_install do |installer|
+ @post_install_hook_arg = installer
+ end
+
+ Gem.post_uninstall do |uninstaller|
+ @post_uninstall_hook_arg = uninstaller
+ end
+
+ Gem.pre_install do |installer|
+ @pre_install_hook_arg = installer
+ end
+
+ Gem.pre_uninstall do |uninstaller|
+ @pre_uninstall_hook_arg = uninstaller
+ end
end
def teardown
@@ -435,7 +460,15 @@ class RubyGemTestCase < Test::Unit::TestCase
end
@@ruby = rubybin
- @@rake = ENV["rake"] || (@@ruby + " " + File.expand_path("../../../bin/rake", __FILE__))
+ env_rake = ENV['rake']
+ ruby19_rake = @@ruby + " " + File.expand_path("../../../bin/rake", __FILE__)
+ @@rake = if env_rake then
+ ENV["rake"]
+ elsif File.exist? ruby19_rake then
+ ruby19_rake
+ else
+ 'rake'
+ end
end
diff --git a/test/rubygems/mockgemui.rb b/test/rubygems/mockgemui.rb
index 95a95fbf98b..57582ef57d0 100644
--- a/test/rubygems/mockgemui.rb
+++ b/test/rubygems/mockgemui.rb
@@ -12,8 +12,28 @@ require 'rubygems/user_interaction'
class MockGemUi < Gem::StreamUI
class TermError < RuntimeError; end
- def initialize(input="")
- super(StringIO.new(input), StringIO.new, StringIO.new)
+ module TTY
+
+ attr_accessor :tty
+
+ def tty?()
+ @tty = true unless defined?(@tty)
+ @tty
+ end
+
+ end
+
+ def initialize(input = "")
+ ins = StringIO.new input
+ outs = StringIO.new
+ errs = StringIO.new
+
+ ins.extend TTY
+ outs.extend TTY
+ errs.extend TTY
+
+ super ins, outs, errs
+
@terminated = false
end
diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb
index c26eeb573da..6735f2f02a7 100644
--- a/test/rubygems/test_gem.rb
+++ b/test/rubygems/test_gem.rb
@@ -45,7 +45,12 @@ class TestGem < RubyGemTestCase
def test_self_bindir_default_dir
default = Gem.default_dir
- bindir = (defined? RUBY_FRAMEWORK_VERSION) ? '/usr/bin' : Config::CONFIG['bindir']
+ bindir = if defined?(RUBY_FRAMEWORK_VERSION) then
+ '/usr/bin'
+ else
+ Config::CONFIG['bindir']
+ end
+
assert_equal bindir, Gem.bindir(default)
assert_equal bindir, Gem.bindir(Pathname.new(default))
end
@@ -218,6 +223,36 @@ class TestGem < RubyGemTestCase
Gem.ssl_available = orig_Gem_ssl_available
end
+ def test_self_find_files
+ foo1 = quick_gem 'foo', '1' do |s|
+ s.files << 'lib/foo/discover.rb'
+ end
+
+ foo2 = quick_gem 'foo', '2' do |s|
+ s.files << 'lib/foo/discover.rb'
+ end
+
+ path = File.join 'gems', foo1.full_name, 'lib', 'foo', 'discover.rb'
+ write_file(path) { |fp| fp.puts "# #{path}" }
+
+ path = File.join 'gems', foo2.full_name, 'lib', 'foo', 'discover.rb'
+ write_file(path) { |fp| fp.puts "# #{path}" }
+
+ @fetcher = Gem::FakeFetcher.new
+ Gem::RemoteFetcher.fetcher = @fetcher
+
+ Gem.source_index = util_setup_spec_fetcher foo1, foo2
+
+ Gem.searcher = nil
+
+ expected = [
+ File.join(foo1.full_gem_path, 'lib', 'foo', 'discover.rb'),
+ File.join(foo2.full_gem_path, 'lib', 'foo', 'discover.rb'),
+ ]
+
+ assert_equal expected, Gem.find_files('foo/discover').sort
+ end
+
def test_self_latest_load_paths
util_make_gems
@@ -261,20 +296,21 @@ class TestGem < RubyGemTestCase
unless win_platform?
def test_self_path_APPLE_GEM_HOME
Gem.clear_paths
- Dir.mktmpdir("apple_gem_home") {|d|
- Gem.const_set :APPLE_GEM_HOME, d
- assert Gem.path.include?(d)
- }
+ 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)
ensure
Gem.send :remove_const, :APPLE_GEM_HOME
end
-
+
def test_self_path_APPLE_GEM_HOME_GEM_PATH
Gem.clear_paths
ENV['GEM_PATH'] = @gemhome
- Gem.const_set :APPLE_GEM_HOME, '/tmp/apple_gem_home'
-
- assert !Gem.path.include?('/tmp/apple_gem_home')
+ 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)
ensure
Gem.send :remove_const, :APPLE_GEM_HOME
end
@@ -291,7 +327,7 @@ class TestGem < RubyGemTestCase
assert_equal path_count + @additional.size, Gem.path.size,
"extra path components: #{Gem.path[2..-1].inspect}"
- assert_match Gem.dir, Gem.path.last
+ assert_equal Gem.dir, Gem.path.last
end
def test_self_path_duplicate
@@ -390,6 +426,44 @@ class TestGem < RubyGemTestCase
Gem.required_location("a", "code.rb", "= 2")
end
+ def test_self_ruby_escaping_spaces_in_path
+ orig_ruby = Gem.ruby
+ orig_bindir = Gem::ConfigMap[:bindir]
+ orig_ruby_install_name = Gem::ConfigMap[:ruby_install_name]
+ orig_exe_ext = Gem::ConfigMap[:EXEEXT]
+
+ Gem::ConfigMap[:bindir] = "C:/Ruby 1.8/bin"
+ Gem::ConfigMap[:ruby_install_name] = "ruby"
+ Gem::ConfigMap[:EXEEXT] = ".exe"
+ Gem.instance_variable_set("@ruby", nil)
+
+ assert_equal "\"C:/Ruby 1.8/bin/ruby.exe\"", Gem.ruby
+ ensure
+ Gem.instance_variable_set("@ruby", orig_ruby)
+ Gem::ConfigMap[:bindir] = orig_bindir
+ Gem::ConfigMap[:ruby_install_name] = orig_ruby_install_name
+ Gem::ConfigMap[:EXEEXT] = orig_exe_ext
+ end
+
+ def test_self_ruby_path_without_spaces
+ orig_ruby = Gem.ruby
+ orig_bindir = Gem::ConfigMap[:bindir]
+ orig_ruby_install_name = Gem::ConfigMap[:ruby_install_name]
+ orig_exe_ext = Gem::ConfigMap[:EXEEXT]
+
+ Gem::ConfigMap[:bindir] = "C:/Ruby18/bin"
+ Gem::ConfigMap[:ruby_install_name] = "ruby"
+ Gem::ConfigMap[:EXEEXT] = ".exe"
+ Gem.instance_variable_set("@ruby", nil)
+
+ assert_equal "C:/Ruby18/bin/ruby.exe", Gem.ruby
+ ensure
+ Gem.instance_variable_set("@ruby", orig_ruby)
+ Gem::ConfigMap[:bindir] = orig_bindir
+ Gem::ConfigMap[:ruby_install_name] = orig_ruby_install_name
+ Gem::ConfigMap[:EXEEXT] = orig_exe_ext
+ end
+
def test_self_ruby_version
version = RUBY_VERSION.dup
version << ".#{RUBY_PATCHLEVEL}" if defined? RUBY_PATCHLEVEL
@@ -430,6 +504,11 @@ class TestGem < RubyGemTestCase
assert_equal @additional + [Gem.dir], Gem.path
end
+ def test_self_user_dir
+ assert_equal File.join(@userhome, '.gem', Gem.ruby_engine,
+ Gem::ConfigMap[:ruby_version]), Gem.user_dir
+ end
+
def test_self_user_home
if ENV['HOME'] then
assert_equal ENV['HOME'], Gem.user_home
@@ -438,6 +517,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
+
def util_ensure_gem_dirs
Gem.ensure_gem_subdirectories @gemhome
@additional.each do |dir|
diff --git a/test/rubygems/test_gem_builder.rb b/test/rubygems/test_gem_builder.rb
index 3463b4d4039..31a0d71880e 100644
--- a/test/rubygems/test_gem_builder.rb
+++ b/test/rubygems/test_gem_builder.rb
@@ -25,7 +25,7 @@ class TestGemBuilder < RubyGemTestCase
def test_build_validates
builder = Gem::Builder.new Gem::Specification.new
- assert_raise Gem::InvalidSpecificationException do
+ assert_raises Gem::InvalidSpecificationException do
builder.build
end
end
diff --git a/test/rubygems/test_gem_command_manager.rb b/test/rubygems/test_gem_command_manager.rb
index 59d3b5cb8e0..ee58e898447 100644
--- a/test/rubygems/test_gem_command_manager.rb
+++ b/test/rubygems/test_gem_command_manager.rb
@@ -31,7 +31,7 @@ class TestGemCommandManager < RubyGemTestCase
def test_run_interrupt
use_ui @ui do
@command_manager.register_command :interrupt
- assert_raise MockGemUi::TermError do
+ assert_raises MockGemUi::TermError do
@command_manager.run 'interrupt'
end
assert_equal '', ui.output
@@ -41,7 +41,7 @@ class TestGemCommandManager < RubyGemTestCase
def test_process_args_bad_arg
use_ui @ui do
- assert_raise(MockGemUi::TermError) {
+ assert_raises(MockGemUi::TermError) {
@command_manager.process_args("--bad-arg")
}
end
diff --git a/test/rubygems/test_gem_commands_dependency_command.rb b/test/rubygems/test_gem_commands_dependency_command.rb
index e143110a717..0acf2a0ddbc 100644
--- a/test/rubygems/test_gem_commands_dependency_command.rb
+++ b/test/rubygems/test_gem_commands_dependency_command.rb
@@ -199,7 +199,7 @@ ERROR: Only reverse dependencies for local gems are supported.
@fetcher.data["#{@gem_repo}Marshal.#{Gem.marshal_version}"] =
si.dump
- @fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"] = nil
+ @fetcher.data.delete "#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"
FileUtils.rm File.join(@gemhome, 'specifications',
"#{foo.full_name}.gemspec")
diff --git a/test/rubygems/test_gem_commands_install_command.rb b/test/rubygems/test_gem_commands_install_command.rb
index e972429ce13..ef04072b939 100644
--- a/test/rubygems/test_gem_commands_install_command.rb
+++ b/test/rubygems/test_gem_commands_install_command.rb
@@ -43,7 +43,7 @@ class TestGemCommandsInstallCommand < RubyGemTestCase
orig_dir = Dir.pwd
begin
Dir.chdir @tempdir
- e = assert_raise Gem::SystemExitException do
+ e = assert_raises Gem::SystemExitException do
@cmd.execute
end
assert_equal 0, e.exit_code
@@ -65,7 +65,7 @@ class TestGemCommandsInstallCommand < RubyGemTestCase
@cmd.options[:args] = %w[no_such_gem]
use_ui @ui do
- e = assert_raise Gem::SystemExitException do
+ e = assert_raises Gem::SystemExitException do
@cmd.execute
end
assert_equal 2, e.exit_code
@@ -91,7 +91,7 @@ class TestGemCommandsInstallCommand < RubyGemTestCase
@cmd.options[:args] = %w[nonexistent]
use_ui @ui do
- e = assert_raise Gem::SystemExitException do
+ e = assert_raises Gem::SystemExitException do
@cmd.execute
end
assert_equal 2, e.exit_code
@@ -114,7 +114,7 @@ class TestGemCommandsInstallCommand < RubyGemTestCase
@cmd.options[:args] = [@a2.name]
use_ui @ui do
- e = assert_raise Gem::SystemExitException do
+ e = assert_raises Gem::SystemExitException do
@cmd.execute
end
assert_equal 0, e.exit_code
@@ -146,7 +146,7 @@ class TestGemCommandsInstallCommand < RubyGemTestCase
orig_dir = Dir.pwd
begin
Dir.chdir @tempdir
- e = assert_raise Gem::SystemExitException do
+ e = assert_raises Gem::SystemExitException do
@cmd.execute
end
assert_equal 0, e.exit_code
diff --git a/test/rubygems/test_gem_commands_list_command.rb b/test/rubygems/test_gem_commands_list_command.rb
new file mode 100644
index 00000000000..bac9cca03fc
--- /dev/null
+++ b/test/rubygems/test_gem_commands_list_command.rb
@@ -0,0 +1,37 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/list_command'
+
+class TestGemCommandsListCommand < RubyGemTestCase
+
+ def setup
+ super
+
+ @cmd = Gem::Commands::ListCommand.new
+
+ util_setup_fake_fetcher
+
+ @si = util_setup_spec_fetcher @a1, @a2, @pl1
+
+ @fetcher.data["#{@gem_repo}Marshal.#{Gem.marshal_version}"] = proc do
+ raise Gem::RemoteFetcher::FetchError
+ end
+ end
+
+ def test_execute_installed
+ @cmd.handle_options %w[c --installed]
+
+ e = assert_raise Gem::SystemExitException do
+ use_ui @ui do
+ @cmd.execute
+ end
+ end
+
+ assert_equal 0, e.exit_code
+
+ assert_equal "true\n", @ui.output
+
+ assert_equal '', @ui.error
+ end
+
+end
diff --git a/test/rubygems/test_gem_commands_lock_command.rb b/test/rubygems/test_gem_commands_lock_command.rb
new file mode 100644
index 00000000000..089fed6e9a9
--- /dev/null
+++ b/test/rubygems/test_gem_commands_lock_command.rb
@@ -0,0 +1,69 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require 'rubygems/commands/lock_command'
+
+class TestGemCommandsLockCommand < RubyGemTestCase
+
+ def setup
+ super
+
+ @a1 = quick_gem 'a', '1'
+ @b1 = quick_gem 'b', '1' do |s|
+ s.add_runtime_dependency 'a'
+ end
+
+ @d1 = quick_gem 'd', '1' do |s|
+ s.add_runtime_dependency 'z'
+ end
+
+ @cmd = Gem::Commands::LockCommand.new
+ end
+
+ def test_execute
+ @cmd.handle_options %w[b-1]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ expected = <<-EXPECTED
+require 'rubygems'
+gem 'b', '= 1'
+gem 'a', '= 1'
+ EXPECTED
+
+ assert_equal expected, @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_execute_missing_dependency
+ @cmd.handle_options %w[d-1]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ expected = <<-EXPECTED
+require 'rubygems'
+gem 'd', '= 1'
+# Unable to satisfy 'z (>= 0, runtime)' from currently installed gems
+ EXPECTED
+
+ assert_equal expected, @ui.output
+ assert_equal '', @ui.error
+ end
+
+ def test_execute_strict
+ @cmd.handle_options %w[c-1 --strict]
+
+ e = assert_raise Gem::Exception do
+ use_ui @ui do
+ @cmd.execute
+ end
+ end
+
+ assert_equal 'Could not find gem c-1, try using the full name', e.message
+ end
+
+end
+
diff --git a/test/rubygems/test_gem_commands_query_command.rb b/test/rubygems/test_gem_commands_query_command.rb
index 1b65fc76332..b17e2a3ad58 100644
--- a/test/rubygems/test_gem_commands_query_command.rb
+++ b/test/rubygems/test_gem_commands_query_command.rb
@@ -180,7 +180,7 @@ pl (1)
@fetcher.data["#{@gem_repo}Marshal.#{Gem.marshal_version}"] =
si.dump
- @fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"] = nil
+ @fetcher.data.delete "#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"
@cmd.handle_options %w[-r]
@@ -265,6 +265,27 @@ pl (1)
assert_equal '', @ui.error
end
+ def test_execute_local_notty
+ @cmd.handle_options %w[]
+
+ @ui.outs.tty = false
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ expected = <<-EOF
+a (2, 1)
+a_evil (9)
+b (2)
+c (1.2)
+pl (1)
+ EOF
+
+ assert_equal expected, @ui.output
+ assert_equal '', @ui.error
+ end
+
def test_execute_no_versions
@cmd.handle_options %w[-r --no-versions]
@@ -284,5 +305,23 @@ pl
assert_equal '', @ui.error
end
+ def test_execute_notty
+ @cmd.handle_options %w[-r]
+
+ @ui.outs.tty = false
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ expected = <<-EOF
+a (2)
+pl (1)
+ EOF
+
+ assert_equal expected, @ui.output
+ assert_equal '', @ui.error
+ end
+
end
diff --git a/test/rubygems/test_gem_commands_uninstall_command.rb b/test/rubygems/test_gem_commands_uninstall_command.rb
new file mode 100644
index 00000000000..dfe84dc3486
--- /dev/null
+++ b/test/rubygems/test_gem_commands_uninstall_command.rb
@@ -0,0 +1,60 @@
+require 'test/unit'
+require File.join(File.expand_path(File.dirname(__FILE__)), 'gemutilities')
+require File.join(File.expand_path(File.dirname(__FILE__)),
+ 'gem_installer_test_case')
+require 'rubygems/commands/uninstall_command'
+
+class TestGemCommandsUninstallCommand < GemInstallerTestCase
+
+ def setup
+ super
+
+ ui = MockGemUi.new
+ util_setup_gem ui
+
+ use_ui ui do
+ @installer.install
+ end
+
+ @cmd = Gem::Commands::UninstallCommand.new
+ @cmd.options[:executables] = true
+ @executable = File.join(@gemhome, 'bin', 'executable')
+ end
+
+ def test_execute_removes_executable
+ if win_platform?
+ assert_equal true, File.exist?(@executable)
+ else
+ assert_equal true, File.symlink?(@executable)
+ end
+
+ # Evil hack to prevent false removal success
+ FileUtils.rm_f @executable
+ File.open(@executable, "wb+") {|f| f.puts "binary"}
+
+ @cmd.options[:args] = Array(@spec.name)
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ output = @ui.output.split "\n"
+ assert_match(/Removing executable/, output.shift)
+ assert_match(/Successfully uninstalled/, output.shift)
+ assert_equal false, File.exist?(@executable)
+ assert_nil output.shift, "UI output should have contained only two lines"
+ end
+
+ def test_execute_not_installed
+ @cmd.options[:args] = ["foo"]
+ e = assert_raise(Gem::InstallError) do
+ use_ui @ui do
+ @cmd.execute
+ end
+ end
+
+ assert_match(/\AUnknown gem foo >= 0$/, e.message)
+ output = @ui.output.split "\n"
+ assert output.empty?, "UI output should be empty after an uninstall error"
+ end
+end
+
diff --git a/test/rubygems/test_gem_config_file.rb b/test/rubygems/test_gem_config_file.rb
index 06321d4e7ca..17071ef65f8 100644
--- a/test/rubygems/test_gem_config_file.rb
+++ b/test/rubygems/test_gem_config_file.rb
@@ -57,6 +57,9 @@ class TestGemConfigFile < RubyGemTestCase
fp.puts ":sources:"
fp.puts " - http://more-gems.example.com"
fp.puts "install: --wrappers"
+ fp.puts ":gempath:"
+ fp.puts "- /usr/ruby/1.8/lib/ruby/gems/1.8"
+ fp.puts "- /var/ruby/1.8/gem_home"
end
util_config_file
@@ -68,6 +71,8 @@ class TestGemConfigFile < RubyGemTestCase
assert_equal false, @cfg.update_sources
assert_equal %w[http://more-gems.example.com], Gem.sources
assert_equal '--wrappers', @cfg[:install]
+ assert_equal(['/usr/ruby/1.8/lib/ruby/gems/1.8', '/var/ruby/1.8/gem_home'],
+ @cfg.path)
end
def test_initialize_handle_arguments_config_file
diff --git a/test/rubygems/test_gem_ext_configure_builder.rb b/test/rubygems/test_gem_ext_configure_builder.rb
index 9ce17075bc5..a1b656353a2 100644
--- a/test/rubygems/test_gem_ext_configure_builder.rb
+++ b/test/rubygems/test_gem_ext_configure_builder.rb
@@ -53,12 +53,13 @@ class TestGemExtConfigureBuilder < RubyGemTestCase
expected = %r(configure failed:
#{Regexp.escape sh_prefix_configure}#{Regexp.escape @dest_path}
-.*?: #{shell_error_msg})
+.*?: #{shell_error_msg}
+)
assert_match expected, error.message
assert_equal "#{sh_prefix_configure}#{@dest_path}", output.shift
- assert_match %r(#{shell_error_msg}\n), output.shift
+ assert_match %r(#{shell_error_msg}), output.shift
assert_equal true, output.empty?
end
diff --git a/test/rubygems/test_gem_ext_rake_builder.rb b/test/rubygems/test_gem_ext_rake_builder.rb
index 6d9184e8042..b1e7783d548 100644
--- a/test/rubygems/test_gem_ext_rake_builder.rb
+++ b/test/rubygems/test_gem_ext_rake_builder.rb
@@ -32,6 +32,8 @@ class TestGemExtRakeBuilder < RubyGemTestCase
end
end
+ output = output.join "\n"
+
expected = [
"#{@@ruby} mkrf_conf.rb",
"",
@@ -39,7 +41,9 @@ class TestGemExtRakeBuilder < RubyGemTestCase
"(in #{realdir})\n"
]
- assert_equal expected, output
+ assert_no_match %r%^rake failed:%, output
+ assert_match %r%^#{Regexp.escape @@ruby} mkrf_conf\.rb%, output
+ assert_match %r%^#{Regexp.escape @@rake} RUBYARCHDIR=#{Regexp.escape @dest_path} RUBYLIBDIR=#{Regexp.escape @dest_path}%, output
end
def test_class_build_fail
@@ -69,7 +73,9 @@ rake failed:
#{@@rake} RUBYARCHDIR=#{@dest_path} RUBYLIBDIR=#{@dest_path}
EOF
- assert_equal expected, error.message.split("\n")[0..4].join("\n")
+ assert_match %r%^rake failed:%, error.message
+ assert_match %r%^#{Regexp.escape @@ruby} mkrf_conf\.rb%, error.message
+ assert_match %r%^#{Regexp.escape @@rake} RUBYARCHDIR=#{Regexp.escape @dest_path} RUBYLIBDIR=#{Regexp.escape @dest_path}%, error.message
end
end
diff --git a/test/rubygems/test_gem_gem_path_searcher.rb b/test/rubygems/test_gem_gem_path_searcher.rb
index c9da4d2b05b..a6124df84dc 100644
--- a/test/rubygems/test_gem_gem_path_searcher.rb
+++ b/test/rubygems/test_gem_gem_path_searcher.rb
@@ -5,10 +5,6 @@ require 'rubygems/gem_path_searcher'
class Gem::GemPathSearcher
attr_accessor :gemspecs
attr_accessor :lib_dirs
-
- public :init_gemspecs
- public :matching_file
- public :lib_dirs_for
end
class TestGemGemPathSearcher < RubyGemTestCase
@@ -40,6 +36,10 @@ class TestGemGemPathSearcher < RubyGemTestCase
assert_equal @foo1, @gps.find('foo')
end
+ def test_find_all
+ assert_equal [@foo1], @gps.find_all('foo')
+ end
+
def test_init_gemspecs
assert_equal [@bar2, @bar1, @foo2, @foo1], @gps.init_gemspecs
end
@@ -51,9 +51,17 @@ class TestGemGemPathSearcher < RubyGemTestCase
assert_equal expected, lib_dirs
end
- def test_matching_file
- assert !@gps.matching_file(@foo1, 'bar')
- assert @gps.matching_file(@foo1, 'foo')
+ def test_matching_file_eh
+ assert !@gps.matching_file?(@foo1, 'bar')
+ assert @gps.matching_file?(@foo1, 'foo')
+ end
+
+ def test_matching_files
+ assert_equal [], @gps.matching_files(@foo1, 'bar')
+
+ expected = File.join @foo1.full_gem_path, 'lib', 'foo.rb'
+
+ assert_equal [expected], @gps.matching_files(@foo1, 'foo')
end
end
diff --git a/test/rubygems/test_gem_install_update_options.rb b/test/rubygems/test_gem_install_update_options.rb
index 9a017384a53..cccbb743149 100644
--- a/test/rubygems/test_gem_install_update_options.rb
+++ b/test/rubygems/test_gem_install_update_options.rb
@@ -41,8 +41,8 @@ class TestGemInstallUpdateOptions < GemInstallerTestCase
@installer = Gem::Installer.new @gem, @cmd.options
@installer.install
- assert File.exist?(File.join(@userhome, '.gem', 'gems'))
- assert File.exist?(File.join(@userhome, '.gem', 'gems',
+ assert File.exist?(File.join(Gem.user_dir, 'gems'))
+ assert File.exist?(File.join(Gem.user_dir, 'gems',
@spec.full_name))
end
@@ -52,7 +52,7 @@ class TestGemInstallUpdateOptions < GemInstallerTestCase
File.chmod 0755, @userhome
FileUtils.chmod 0000, @gemhome
- assert_raise(Gem::FilePermissionError) do
+ assert_raises(Gem::FilePermissionError) do
@installer = Gem::Installer.new @gem, @cmd.options
end
ensure
diff --git a/test/rubygems/test_gem_installer.rb b/test/rubygems/test_gem_installer.rb
index e57461f53a1..4dc31efd1bd 100644
--- a/test/rubygems/test_gem_installer.rb
+++ b/test/rubygems/test_gem_installer.rb
@@ -70,7 +70,10 @@ load 'my_exec'
#{Gem.ruby}: No such file or directory -- extconf.rb (LoadError)
EOF
- assert_equal expected, File.read(gem_make_out)
+ assert_match %r%#{Regexp.escape Gem.ruby} extconf.rb%,
+ File.read(gem_make_out)
+ assert_match %r%#{Regexp.escape Gem.ruby}: No such file%,
+ File.read(gem_make_out)
end
def test_build_extensions_unsupported
@@ -287,7 +290,7 @@ load 'my_exec'
Dir.mkdir util_inst_bindir
File.chmod 0000, util_inst_bindir
- assert_raise Gem::FilePermissionError do
+ assert_raises Gem::FilePermissionError do
@installer.generate_bin
end
@@ -372,7 +375,7 @@ load 'my_exec'
Dir.mkdir util_inst_bindir
File.chmod 0000, util_inst_bindir
- assert_raise Gem::FilePermissionError do
+ assert_raises Gem::FilePermissionError do
@installer.generate_bin
end
@@ -529,6 +532,16 @@ load 'my_exec'
Dir.mkdir util_inst_bindir
util_setup_gem
+ cache_file = File.join @gemhome, 'cache', "#{@spec.full_name}.gem"
+
+ Gem.pre_install do |installer|
+ assert !File.exist?(cache_file), 'cache file should not exist yet'
+ end
+
+ Gem.post_install do |installer|
+ assert File.exist?(cache_file), 'cache file should exist'
+ end
+
build_rake_in do
use_ui @ui do
assert_equal @spec, @installer.install
@@ -552,6 +565,9 @@ load 'my_exec'
assert_equal spec_file, @spec.loaded_from
assert File.exist?(spec_file)
+
+ assert_same @installer, @pre_install_hook_arg
+ assert_same @installer, @post_install_hook_arg
end
def test_install_bad_gem
@@ -586,6 +602,29 @@ load 'my_exec'
end
end
+ def test_install_check_dependencies_install_dir
+ gemhome2 = "#{@gemhome}2"
+ @spec.add_dependency 'b'
+
+ b2 = quick_gem 'b', 2
+
+ FileUtils.mv @gemhome, gemhome2
+ Gem.source_index.gems.delete b2.full_name
+ source_index = Gem::SourceIndex.from_gems_in File.join(gemhome2,
+ 'specifications')
+
+ util_setup_gem
+
+ @installer = Gem::Installer.new @gem, :install_dir => gemhome2,
+ :source_index => source_index
+
+ use_ui @ui do
+ @installer.install
+ end
+
+ assert File.exist?(File.join(gemhome2, 'gems', @spec.full_name))
+ end
+
def test_install_force
use_ui @ui do
installer = Gem::Installer.new old_ruby_required, :force => true
@@ -641,13 +680,13 @@ load 'my_exec'
assert File.exist?(File.join(@gemhome, 'specifications',
"#{@spec.full_name}.gemspec"))
end
+
unless win_platform? # File.chmod doesn't work
def test_install_user_local_fallback
Dir.mkdir util_inst_bindir
File.chmod 0755, @userhome
File.chmod 0000, util_inst_bindir
File.chmod 0000, Gem.dir
- install_dir = File.join @userhome, '.gem', 'gems', @spec.full_name
@spec.executables = ["executable"]
build_rake_in do
@@ -656,9 +695,10 @@ load 'my_exec'
@installer.install
end
end
-
- assert File.exist?(File.join(install_dir, 'lib', 'code.rb'))
- assert File.exist?(File.join(@userhome, '.gem', 'bin', 'executable'))
+
+ assert File.exist?(File.join(Gem.user_dir, 'gems',
+ @spec.full_name, 'lib', 'code.rb'))
+ assert File.exist?(File.join(Gem.user_dir, 'bin', 'executable'))
ensure
File.chmod 0755, Gem.dir
File.chmod 0755, util_inst_bindir
@@ -676,13 +716,13 @@ load 'my_exec'
@installer.install
end
end
-
- assert File.exist?(File.join(@userhome, '.gem', 'bin', 'executable'))
+
+ assert File.exist?(File.join(Gem.user_dir, 'bin', 'executable'))
ensure
File.chmod 0755, util_inst_bindir
end
end
-
+
def test_install_with_message
@spec.post_install_message = 'I am a shiny gem!'
diff --git a/test/rubygems/test_gem_local_remote_options.rb b/test/rubygems/test_gem_local_remote_options.rb
index e676c94f216..5f2a1d3d86c 100644
--- a/test/rubygems/test_gem_local_remote_options.rb
+++ b/test/rubygems/test_gem_local_remote_options.rb
@@ -19,6 +19,18 @@ class TestGemLocalRemoteOptions < RubyGemTestCase
assert @cmd.handles?(args)
end
+ def test_both_eh
+ assert_equal false, @cmd.both?
+
+ @cmd.options[:domain] = :local
+
+ assert_equal false, @cmd.both?
+
+ @cmd.options[:domain] = :both
+
+ assert_equal true, @cmd.both?
+ end
+
def test_local_eh
assert_equal false, @cmd.local?
diff --git a/test/rubygems/test_gem_package_tar_header.rb b/test/rubygems/test_gem_package_tar_header.rb
index 9158061cf62..9b7708dca80 100644
--- a/test/rubygems/test_gem_package_tar_header.rb
+++ b/test/rubygems/test_gem_package_tar_header.rb
@@ -62,19 +62,19 @@ class TestGemPackageTarHeader < TarTestCase
end
def test_initialize_bad
- assert_raise ArgumentError do
+ assert_raises ArgumentError do
Gem::Package::TarHeader.new :name => '', :size => '', :mode => ''
end
- assert_raise ArgumentError do
+ assert_raises ArgumentError do
Gem::Package::TarHeader.new :name => '', :size => '', :prefix => ''
end
- assert_raise ArgumentError do
+ assert_raises ArgumentError do
Gem::Package::TarHeader.new :name => '', :prefix => '', :mode => ''
end
- assert_raise ArgumentError do
+ assert_raises ArgumentError do
Gem::Package::TarHeader.new :prefix => '', :size => '', :mode => ''
end
end
diff --git a/test/rubygems/test_gem_platform.rb b/test/rubygems/test_gem_platform.rb
index 648c2a9f369..362a3662664 100644
--- a/test/rubygems/test_gem_platform.rb
+++ b/test/rubygems/test_gem_platform.rb
@@ -5,19 +5,6 @@ require 'rbconfig'
class TestGemPlatform < RubyGemTestCase
- def test_self_const_missing
- consts = [:DARWIN, :LINUX_586, :MSWIN32, :PPC_DARWIN, :WIN32, :X86_LINUX]
-
- consts.each do |const|
- e = assert_raise NameError do
- Gem::Platform.const_missing const
- end
-
- assert_equal "#{const} has been removed, use CURRENT instead",
- e.message
- end
- end
-
def test_self_local
util_set_arch 'i686-darwin8.10.1'
@@ -105,6 +92,12 @@ class TestGemPlatform < RubyGemTestCase
platform = Gem::Platform.new 'i386-mswin32-80'
assert_equal expected, platform.to_a, 'i386-mswin32-80'
+
+ expected = ['x86', 'solaris', '2.10']
+
+ platform = Gem::Platform.new 'i386-solaris-2.10'
+
+ assert_equal expected, platform.to_a, 'i386-solaris-2.10'
end
def test_initialize_mswin32_vc6
diff --git a/test/rubygems/test_gem_remote_fetcher.rb b/test/rubygems/test_gem_remote_fetcher.rb
index 484104dd8f0..103cb388986 100644
--- a/test/rubygems/test_gem_remote_fetcher.rb
+++ b/test/rubygems/test_gem_remote_fetcher.rb
@@ -268,15 +268,15 @@ gems:
ensure
File.chmod 0755, File.join(@gemhome, 'cache')
end
-
+
def test_download_read_only
File.chmod 0555, File.join(@gemhome, 'cache')
File.chmod 0555, File.join(@gemhome)
fetcher = util_fuck_with_fetcher File.read(@a1_gem)
fetcher.download(@a1, 'http://gems.example.com')
- assert File.exist?(File.join(@userhome, '.gem',
- 'cache', "#{@a1.full_name}.gem"))
+ assert File.exist?(File.join(Gem.user_dir, 'cache',
+ "#{@a1.full_name}.gem"))
ensure
File.chmod 0755, File.join(@gemhome)
File.chmod 0755, File.join(@gemhome, 'cache')
@@ -391,6 +391,16 @@ gems:
assert_equal 'foo', fetcher.fetch_path(@uri + 'foo.gz')
end
+ def test_fetch_path_gzip_unmodified
+ fetcher = Gem::RemoteFetcher.new nil
+
+ def fetcher.open_uri_or_path(uri, mtime, head = nil)
+ nil
+ end
+
+ assert_equal nil, fetcher.fetch_path(@uri + 'foo.gz', Time.at(0))
+ end
+
def test_fetch_path_io_error
fetcher = Gem::RemoteFetcher.new nil
@@ -441,10 +451,10 @@ gems:
fetcher = Gem::RemoteFetcher.new nil
def fetcher.open_uri_or_path(uri, mtime, head = nil)
- ''
+ nil
end
- assert_equal '', fetcher.fetch_path(URI.parse(@gem_repo), Time.at(0))
+ assert_equal nil, fetcher.fetch_path(URI.parse(@gem_repo), Time.at(0))
end
def test_get_proxy_from_env_empty
@@ -504,7 +514,7 @@ gems:
def conn.request(req)
unless defined? @requested then
@requested = true
- res = Net::HTTPRedirection.new nil, 301, nil
+ res = Net::HTTPMovedPermanently.new nil, 301, nil
res.add_field 'Location', 'http://gems.example.com/real_path'
res
else
@@ -528,7 +538,7 @@ gems:
conn = Object.new
def conn.started?() true end
def conn.request(req)
- res = Net::HTTPRedirection.new nil, 301, nil
+ res = Net::HTTPMovedPermanently.new nil, 301, nil
res.add_field 'Location', 'http://gems.example.com/redirect'
res
end
diff --git a/test/rubygems/test_gem_source_index.rb b/test/rubygems/test_gem_source_index.rb
index 263826759ab..7f379ef19a3 100644
--- a/test/rubygems/test_gem_source_index.rb
+++ b/test/rubygems/test_gem_source_index.rb
@@ -64,6 +64,54 @@ class TestGemSourceIndex < RubyGemTestCase
assert_equal a1.author, spec.author
end
+ def test_self_load_specification_utf_8
+ spec_dir = File.join @gemhome, 'specifications'
+
+ FileUtils.rm_r spec_dir
+
+ FileUtils.mkdir_p spec_dir
+
+ spec_file = File.join spec_dir, "utf-8.gemspec"
+ spec_data = <<-SPEC
+Gem::Specification.new do |s|
+ s.name = %q{utf}
+ s.version = "8"
+
+ s.required_rubygems_version = Gem::Requirement.new(">= 0")
+ s.authors = ["\317\200"]
+ s.date = %q{2008-09-10}
+ s.description = %q{This is a test description}
+ s.email = %q{example@example.com}
+ s.has_rdoc = true
+ s.homepage = %q{http://example.com}
+ s.require_paths = ["lib"]
+ s.rubygems_version = %q{1.2.0}
+ s.summary = %q{this is a summary}
+
+ if s.respond_to? :specification_version then
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
+ s.specification_version = 2
+
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
+ else
+ end
+ else
+ end
+end
+ SPEC
+
+ spec_data.force_encoding 'UTF-8'
+
+ File.open spec_file, 'w' do |io| io.write spec_data end
+
+ spec = Gem::SourceIndex.load_specification spec_file
+
+ pi = "\317\200"
+ pi.force_encoding 'UTF-8' if pi.respond_to? :force_encoding
+
+ assert_equal pi, spec.author
+ end if Gem.ruby_version > Gem::Version.new('1.9')
+
def test_self_load_specification_exception
spec_dir = File.join @gemhome, 'specifications'
@@ -437,6 +485,27 @@ WARNING: Invalid .gemspec format in '#{spec_file}'
assert_equal [], missing
end
+ def test_find_name
+ assert_equal [@a1, @a2], @source_index.find_name('a')
+ assert_equal [@a2], @source_index.find_name('a', '= 2')
+ assert_equal [], @source_index.find_name('bogusstring')
+ assert_equal [], @source_index.find_name('a', '= 3')
+
+ source_index = Gem::SourceIndex.new
+ source_index.add_spec @a1
+ source_index.add_spec @a2
+
+ assert_equal [@a1], source_index.find_name(@a1.name, '= 1')
+
+ r1 = Gem::Requirement.create '= 1'
+ assert_equal [@a1], source_index.find_name(@a1.name, r1)
+ end
+
+ def test_find_name_empty_cache
+ empty_source_index = Gem::SourceIndex.new({})
+ assert_equal [], empty_source_index.find_name("foo")
+ end
+
def test_latest_specs
p1_ruby = quick_gem 'p', '1'
p1_platform = quick_gem 'p', '1' do |spec|
@@ -573,28 +642,12 @@ WARNING: Invalid .gemspec format in '#{spec_file}'
end
def test_search
- assert_equal [@a1, @a2, @a_evil9], @source_index.search('a')
- assert_equal [@a2], @source_index.search('a', '= 2')
-
- assert_equal [], @source_index.search('bogusstring')
- assert_equal [], @source_index.search('a', '= 3')
+ requirement = Gem::Requirement.create '= 9'
+ with_version = Gem::Dependency.new(/^a/, requirement)
+ assert_equal [@a_evil9], @source_index.search(with_version)
- source_index = Gem::SourceIndex.new
- source_index.add_spec @a1
- source_index.add_spec @a2
-
- assert_equal [@a1], source_index.search(@a1.name, '= 1')
-
- r1 = Gem::Requirement.create '= 1'
- assert_equal [@a1], source_index.search(@a1.name, r1)
-
- dep = Gem::Dependency.new @a1.name, r1
- assert_equal [@a1], source_index.search(dep)
- end
-
- def test_search_empty_cache
- empty_source_index = Gem::SourceIndex.new({})
- assert_equal [], empty_source_index.search("foo")
+ with_default = Gem::Dependency.new(/^a/, Gem::Requirement.default)
+ assert_equal [@a1, @a2, @a_evil9], @source_index.search(with_default)
end
def test_search_platform
diff --git a/test/rubygems/test_gem_source_info_cache.rb b/test/rubygems/test_gem_source_info_cache.rb
index 86866a8012a..744a51c154b 100644
--- a/test/rubygems/test_gem_source_info_cache.rb
+++ b/test/rubygems/test_gem_source_info_cache.rb
@@ -224,7 +224,8 @@ class TestGemSourceInfoCache < RubyGemTestCase
@sic.set_cache_data @gem_repo => sice
latest = @sic.latest_cache_data
- gems = latest[@gem_repo].source_index.search('a').map { |s| s.full_name }
+ beginning_with_a = Gem::Dependency.new(/^a/, Gem::Requirement.default)
+ gems = latest[@gem_repo].source_index.search(beginning_with_a).map { |s| s.full_name }
assert_equal %w[a-2 a_evil-9], gems
end
diff --git a/test/rubygems/test_gem_spec_fetcher.rb b/test/rubygems/test_gem_spec_fetcher.rb
index 2e9ce1b7eb4..8f3ab77bb89 100644
--- a/test/rubygems/test_gem_spec_fetcher.rb
+++ b/test/rubygems/test_gem_spec_fetcher.rb
@@ -67,7 +67,7 @@ class TestGemSpecFetcher < RubyGemTestCase
end
def test_fetch_legacy_repo
- @fetcher.data["#{@gem_repo}specs.#{Gem.marshal_version}.gz"] = nil
+ @fetcher.data.delete "#{@gem_repo}specs.#{Gem.marshal_version}.gz"
@fetcher.data["#{@gem_repo}yaml"] = ''
util_setup_source_info_cache @a1, @a2
@@ -259,6 +259,16 @@ RubyGems will revert to legacy indexes degrading performance.
assert_equal specs, cached_specs
end
+ def test_list_latest_all
+ specs = @sf.list false
+
+ assert_equal [@latest_specs], specs.values
+
+ specs = @sf.list true
+
+ assert_equal [@specs], specs.values, 'specs file not loaded'
+ end
+
def test_load_specs
specs = @sf.load_specs @uri, 'specs'
@@ -280,7 +290,7 @@ RubyGems will revert to legacy indexes degrading performance.
end
def test_load_specs_cached
- @fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"] = ''
+ @fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"] = nil
@fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}"] =
' ' * Marshal.dump(@latest_specs).length
diff --git a/test/rubygems/test_gem_specification.rb b/test/rubygems/test_gem_specification.rb
index 57c3fdc1583..9c3b585c91d 100644
--- a/test/rubygems/test_gem_specification.rb
+++ b/test/rubygems/test_gem_specification.rb
@@ -500,7 +500,7 @@ end
end
def test_has_rdoc_eh
- assert_equal true, @a1.has_rdoc?
+ assert @a1.has_rdoc?
end
def test_hash
@@ -634,7 +634,10 @@ end
ruby_code = @a2.to_ruby
- expected = "Gem::Specification.new do |s|
+ expected = <<-SPEC
+# -*- encoding: utf-8 -*-
+
+Gem::Specification.new do |s|
s.name = %q{a}
s.version = \"2\"
@@ -654,7 +657,7 @@ end
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
s.specification_version = #{Gem::Specification::CURRENT_SPECIFICATION_VERSION}
- if current_version >= 3 then
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
s.add_runtime_dependency(%q<b>, [\"= 1\"])
else
s.add_dependency(%q<b>, [\"= 1\"])
@@ -663,7 +666,7 @@ end
s.add_dependency(%q<b>, [\"= 1\"])
end
end
-"
+ SPEC
assert_equal expected, ruby_code
@@ -679,7 +682,10 @@ end
local = Gem::Platform.local
expected_platform = "[#{local.cpu.inspect}, #{local.os.inspect}, #{local.version.inspect}]"
- expected = "Gem::Specification.new do |s|
+ expected = <<-SPEC
+# -*- encoding: utf-8 -*-
+
+Gem::Specification.new do |s|
s.name = %q{a}
s.version = \"1\"
s.platform = Gem::Platform.new(#{expected_platform})
@@ -706,7 +712,7 @@ end
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
s.specification_version = 2
- if current_version >= 3 then
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
s.add_runtime_dependency(%q<rake>, [\"> 0.4\"])
s.add_runtime_dependency(%q<jabber4r>, [\"> 0.0.0\"])
s.add_runtime_dependency(%q<pqa>, [\"> 0.4\", \"<= 0.6\"])
@@ -721,7 +727,7 @@ end
s.add_dependency(%q<pqa>, [\"> 0.4\", \"<= 0.6\"])
end
end
-"
+ SPEC
assert_equal expected, ruby_code
diff --git a/test/rubygems/test_gem_stream_ui.rb b/test/rubygems/test_gem_stream_ui.rb
index caf620ff006..a8564ba94fa 100644
--- a/test/rubygems/test_gem_stream_ui.rb
+++ b/test/rubygems/test_gem_stream_ui.rb
@@ -63,7 +63,7 @@ class TestGemStreamUI < RubyGemTestCase
@in.tty = false
timeout(0.1) do
- assert_raise(Gem::OperationNotSupportedError) do
+ assert_raises(Gem::OperationNotSupportedError) do
@sui.ask_yes_no("do coconuts migrate?")
end
end
diff --git a/test/rubygems/test_gem_uninstaller.rb b/test/rubygems/test_gem_uninstaller.rb
index 7d7890c3ea4..bb90f5cc5f9 100644
--- a/test/rubygems/test_gem_uninstaller.rb
+++ b/test/rubygems/test_gem_uninstaller.rb
@@ -62,5 +62,26 @@ class TestGemUninstaller < GemInstallerTestCase
assert_equal true, uninstaller.path_ok?(@spec)
end
+ def test_uninstall
+ uninstaller = Gem::Uninstaller.new @spec.name, :executables => true
+
+ gem_dir = File.join @gemhome, 'gems', @spec.full_name
+
+ Gem.pre_uninstall do
+ assert File.exist?(gem_dir), 'gem_dir should exist'
+ end
+
+ Gem.post_uninstall do
+ assert !File.exist?(gem_dir), 'gem_dir should not exist'
+ end
+
+ uninstaller.uninstall
+
+ assert !File.exist?(gem_dir)
+
+ assert_same uninstaller, @pre_uninstall_hook_arg
+ assert_same uninstaller, @post_uninstall_hook_arg
+ end
+
end
diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb
index 5c04502d482..8d107004907 100644
--- a/test/rubygems/test_gem_version.rb
+++ b/test/rubygems/test_gem_version.rb
@@ -107,7 +107,7 @@ class TestGemVersion < RubyGemTestCase
def test_illformed_requirements
[ ">>> 1.3.5", "> blah" ].each do |rq|
- assert_raise(ArgumentError, "req [#{rq}] should fail") {
+ assert_raises(ArgumentError, "req [#{rq}] should fail") {
Gem::Version::Requirement.new(rq)
}
end