From 25a9b62d45ddd60a231272567c7dda9337da9b62 Mon Sep 17 00:00:00 2001 From: ryan Date: Tue, 1 Mar 2011 09:41:32 +0000 Subject: Import rubygems 1.6.0 (released version @ 58d8a0b9) git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@30996 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 5 + bin/gem | 2 +- lib/rubygems.rb | 197 +++++++--- lib/rubygems/commands/owner_command.rb | 5 +- lib/rubygems/commands/pristine_command.rb | 8 +- lib/rubygems/commands/push_command.rb | 12 +- lib/rubygems/commands/setup_command.rb | 11 +- lib/rubygems/commands/uninstall_command.rb | 5 + lib/rubygems/commands/unpack_command.rb | 26 +- lib/rubygems/commands/update_command.rb | 137 ++++--- lib/rubygems/config_file.rb | 17 +- lib/rubygems/custom_require.rb | 19 +- lib/rubygems/dependency.rb | 41 +- lib/rubygems/dependency_installer.rb | 27 +- lib/rubygems/dependency_list.rb | 38 +- lib/rubygems/doc_manager.rb | 9 +- lib/rubygems/gem_path_searcher.rb | 46 ++- lib/rubygems/gemcutter_utilities.rb | 31 ++ lib/rubygems/installer.rb | 18 +- lib/rubygems/installer_test_case.rb | 38 +- lib/rubygems/package/tar_reader/entry.rb | 3 +- lib/rubygems/remote_fetcher.rb | 39 +- lib/rubygems/requirement.rb | 5 +- lib/rubygems/security.rb | 1 + lib/rubygems/source_index.rb | 5 +- lib/rubygems/spec_fetcher.rb | 6 +- lib/rubygems/specification.rb | 83 +++- lib/rubygems/test_case.rb | 155 +++++--- lib/rubygems/test_utilities.rb | 12 +- lib/rubygems/uninstaller.rb | 33 +- lib/rubygems/user_interaction.rb | 53 +-- lib/rubygems/validator.rb | 2 +- test/rubygems/fix_openssl_warnings.rb | 18 + test/rubygems/plugin/load/rubygems_plugin.rb | 4 +- test/rubygems/test_gem.rb | 422 +++++++++++++++++++-- test/rubygems/test_gem_builder.rb | 2 +- test/rubygems/test_gem_command_manager.rb | 4 +- test/rubygems/test_gem_commands_build_command.rb | 2 +- test/rubygems/test_gem_commands_cert_command.rb | 3 +- .../test_gem_commands_dependency_command.rb | 11 +- test/rubygems/test_gem_commands_fetch_command.rb | 8 +- test/rubygems/test_gem_commands_install_command.rb | 39 +- test/rubygems/test_gem_commands_lock_command.rb | 2 +- .../rubygems/test_gem_commands_outdated_command.rb | 7 +- test/rubygems/test_gem_commands_owner_command.rb | 42 ++ .../rubygems/test_gem_commands_pristine_command.rb | 36 +- test/rubygems/test_gem_commands_push_command.rb | 36 +- .../test_gem_commands_specification_command.rb | 16 +- test/rubygems/test_gem_commands_stale_command.rb | 6 +- .../test_gem_commands_uninstall_command.rb | 27 +- test/rubygems/test_gem_commands_unpack_command.rb | 18 +- test/rubygems/test_gem_commands_update_command.rb | 202 +++++++++- test/rubygems/test_gem_commands_which_command.rb | 2 +- test/rubygems/test_gem_config_file.rb | 14 + test/rubygems/test_gem_dependency.rb | 39 ++ test/rubygems/test_gem_dependency_installer.rb | 305 ++++++++++----- test/rubygems/test_gem_dependency_list.rb | 54 ++- test/rubygems/test_gem_doc_manager.rb | 9 +- test/rubygems/test_gem_format.rb | 4 +- test/rubygems/test_gem_gemcutter_utilities.rb | 48 +++ test/rubygems/test_gem_indexer.rb | 19 +- test/rubygems/test_gem_install_update_options.rb | 2 - test/rubygems/test_gem_installer.rb | 229 +++++++---- test/rubygems/test_gem_package_tar_output.rb | 3 + test/rubygems/test_gem_remote_fetcher.rb | 37 +- test/rubygems/test_gem_security.rb | 1 + test/rubygems/test_gem_silent_ui.rb | 117 ++++++ test/rubygems/test_gem_source_index.rb | 33 +- test/rubygems/test_gem_spec_fetcher.rb | 7 +- test/rubygems/test_gem_specification.rb | 118 ++++-- test/rubygems/test_gem_uninstaller.rb | 80 +++- test/rubygems/test_gem_validator.rb | 2 +- test/rubygems/test_kernel.rb | 2 +- 73 files changed, 2404 insertions(+), 715 deletions(-) create mode 100644 test/rubygems/fix_openssl_warnings.rb create mode 100644 test/rubygems/test_gem_silent_ui.rb diff --git a/ChangeLog b/ChangeLog index 3fda059f7e..19d360ebe8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Tue Mar 1 18:40:38 2011 Ryan Davis + + * lib/rubygems*: Import rubygems 1.6.0 (released version @ 58d8a0b9) + * test/rubygems: Ditto + Tue Mar 1 16:22:22 2011 NAKAMURA Usaku * win32/win32.c: revert r30987 because it causes some failures in diff --git a/bin/gem b/bin/gem index 14c3d3c480..a4ec754abb 100755 --- a/bin/gem +++ b/bin/gem @@ -9,7 +9,7 @@ require 'rubygems' require 'rubygems/gem_runner' require 'rubygems/exceptions' -required_version = Gem::Requirement.new ">= 1.8.6" +required_version = Gem::Requirement.new ">= 1.8.7" unless required_version.satisfied_by? Gem.ruby_version then abort "Expected Ruby Version #{required_version}, is #{Gem.ruby_version}" diff --git a/lib/rubygems.rb b/lib/rubygems.rb index ddb4c2aaa4..b1aa6c547d 100644 --- a/lib/rubygems.rb +++ b/lib/rubygems.rb @@ -32,8 +32,8 @@ if Gem::GEM_PRELUDE_SUCKAGE and defined?(Gem::QuickLoader) then end require 'rubygems/defaults' +require "rubygems/dependency_list" require 'rbconfig' -require 'thread' # HACK: remove me for 1.5 - this is here just for rails ## # RubyGems is the Ruby standard for publishing and managing third party @@ -124,7 +124,7 @@ require 'thread' # HACK: remove me for 1.5 - this is here just for rails # -The RubyGems Team module Gem - RubyGemsVersion = VERSION = '1.5.0' + VERSION = '1.6.0' ## # Raised when RubyGems is unable to load or activate a gem. Contains the @@ -137,25 +137,11 @@ module Gem # Version requirement of gem attr_accessor :requirement + end - def version_requirement - warn "#{Gem.location_of_caller.join ':'}:Warning: " \ - "Gem::LoadError#version_requirement is deprecated " \ - "and will be removed on or after January 2011. " \ - "Use #requirement." - - requirement - end - - def version_requirement= requirement - warn "#{Gem.location_of_caller.join ':'}:Warning: " \ - "Gem::LoadError#version_requirement= is deprecated " \ - "and will be removed on or after January 2011. " \ - "Use #requirement." + # :stopdoc: - self.requirement = requirement - end - end + RubyGemsVersion = VERSION RbConfigPriorities = %w[ EXEEXT RUBY_SO_NAME arch bindir datadir libdir ruby_install_name @@ -180,6 +166,9 @@ module Gem DIRECTORIES = %w[cache doc gems specifications] unless defined?(DIRECTORIES) RubyGemsPackageVersion = VERSION + + RUBYGEMS_DIR = File.dirname File.expand_path(__FILE__) + # :startdoc: ## @@ -216,21 +205,30 @@ module Gem # activated. Returns false if it can't find the path in a gem. def self.try_activate path + # finds the _latest_ version... regardless of loaded specs and their deps + + # TODO: use find_all and bork if ambiguous + spec = Gem.searcher.find path return false unless spec - Gem.activate spec.name, "= #{spec.version}" + begin + Gem.activate spec.name, "= #{spec.version}" + rescue Gem::LoadError # this could fail due to gem dep collisions, go lax + Gem.activate spec.name + end + return true end ## - # Activates an installed gem matching +gem+. The gem must satisfy + # Activates an installed gem matching +dep+. The gem must satisfy # +requirements+. # # Returns true if the gem is activated, false if it is already # loaded, or an exception otherwise. # - # Gem#activate adds the library paths in +gem+ to $LOAD_PATH. Before a Gem + # Gem#activate adds the library paths in +dep+ to $LOAD_PATH. Before a Gem # is activated its required Gems are activated. If the version information # is omitted, the highest version Gem of the supplied name is loaded. If a # Gem is not found that meets the version requirements or a required Gem is @@ -239,63 +237,78 @@ module Gem # More information on version requirements can be found in the # Gem::Requirement and Gem::Version documentation. - def self.activate(gem, *requirements) + def self.activate(dep, *requirements) + # TODO: remove options entirely if requirements.last.is_a?(Hash) options = requirements.pop else options = {} end - sources = options[:sources] || [] - - if requirements.empty? then - requirements = Gem::Requirement.default - end - - unless gem.respond_to?(:name) and - gem.respond_to?(:requirement) then - gem = Gem::Dependency.new(gem, requirements) - end + requirements = Gem::Requirement.default if requirements.empty? + dep = Gem::Dependency.new(dep, requirements) unless Gem::Dependency === dep - matches = Gem.source_index.find_name(gem.name, gem.requirement) - report_activate_error(gem) if matches.empty? + # TODO: remove sources entirely + sources = options[:sources] || [] + matches = Gem.source_index.search dep, true + report_activate_error(dep) if matches.empty? - if @loaded_specs[gem.name] then + if @loaded_specs[dep.name] then # This gem is already loaded. If the currently loaded gem is not in the # list of candidate gems, then we have a version conflict. - existing_spec = @loaded_specs[gem.name] + existing_spec = @loaded_specs[dep.name] unless matches.any? { |spec| spec.version == existing_spec.version } then - sources_message = sources.map { |spec| spec.full_name } - stack_message = @loaded_stacks[gem.name].map { |spec| spec.full_name } + sources_message = sources.map { |spec| spec.full_name } + stack_message = @loaded_stacks[dep.name].map { |spec| spec.full_name } - msg = "can't activate #{gem} for #{sources_message.inspect}, " - msg << "already activated #{existing_spec.full_name} for " - msg << "#{stack_message.inspect}" + msg = "can't activate #{dep} for #{sources_message.inspect}, " + msg << "already activated #{existing_spec.full_name} for " + msg << "#{stack_message.inspect}" - e = Gem::LoadError.new msg - e.name = gem.name - e.requirement = gem.requirement + e = Gem::LoadError.new msg + e.name = dep.name + e.requirement = dep.requirement - raise e + raise e end return false end - # new load spec = matches.last + + conf = spec.conflicts + unless conf.empty? then + why = conf.map { |act,con| + "#{act.full_name} conflicts with #{con.join(", ")}" + }.join ", " + + # TODO: improve message by saying who activated `con` + + raise LoadError, "Unable to activate #{spec.full_name}, because #{why}" + end + return false if spec.loaded? spec.loaded = true - @loaded_specs[spec.name] = spec + @loaded_specs[spec.name] = spec @loaded_stacks[spec.name] = sources.dup - # Load dependent gems first - spec.runtime_dependencies.each do |dep_gem| - activate dep_gem, :sources => [spec, *sources] + spec.runtime_dependencies.each do |spec_dep| + next if Gem.loaded_specs.include? spec_dep.name + specs = Gem.source_index.search spec_dep, true + + if specs.size == 1 then + self.activate spec_dep + else + name = spec_dep.name + unresolved_deps[name] = unresolved_deps[name].merge spec_dep + end end + unresolved_deps.delete spec.name + require_paths = spec.require_paths.map do |path| File.join spec.full_gem_path, path end @@ -314,6 +327,10 @@ module Gem return true end + def self.unresolved_deps + @unresolved_deps ||= Hash.new { |h, n| h[n] = Gem::Dependency.new n } + end + ## # An Array of all possible load paths for all versions of all gems in the # Gem installation. @@ -546,6 +563,7 @@ module Gem # to be depending on HOME in those code samples. I propose that # it should fallback to USERPROFILE and HOMEDRIVE + HOMEPATH (at # least on Win32). + #++ def self.find_home unless RUBY_VERSION > '1.9' then @@ -722,6 +740,27 @@ module Gem @gem_path end + ## + # Get the appropriate cache path. + # + # Pass a string to use a different base path, or nil/false (default) for + # Gem.dir. + # + + def self.cache_dir(custom_dir=false) + File.join(custom_dir ? custom_dir : Gem.dir, 'cache') + end + + ## + # Given a gem path, find the gem in cache. + # + # Pass a string as the second argument to use a different base path, or + # nil/false (default) for Gem.dir. + + def self.cache_gem(filename, user_dir=false) + File.join(cache_dir(user_dir), filename) + end + ## # Set array of platforms this RubyGems supports (primarily for testing). @@ -787,17 +826,16 @@ module Gem end ## - # The directory prefix this RubyGems was installed at. + # The directory prefix this RubyGems was installed at. If your + # prefix is in a standard location (ie, rubygems is installed where + # you'd expect it to be), then prefix returns nil. def self.prefix - dir = File.dirname File.expand_path(__FILE__) - prefix = File.dirname dir + prefix = File.dirname RUBYGEMS_DIR - if prefix == File.expand_path(ConfigMap[:sitelibdir]) or - prefix == File.expand_path(ConfigMap[:libdir]) or - 'lib' != File.basename(dir) then - nil - else + if prefix != File.expand_path(ConfigMap[:sitelibdir]) and + prefix != File.expand_path(ConfigMap[:libdir]) and + 'lib' == File.basename(RUBYGEMS_DIR) then prefix end end @@ -905,6 +943,29 @@ module Gem @ruby end + def self.latest_spec_for name + dependency = Gem::Dependency.new name + fetcher = Gem::SpecFetcher.fetcher + spec_tuples = fetcher.find_matching dependency + + match = spec_tuples.select { |(n, _, p), _| + n == name and Gem::Platform.match p + }.sort_by { |(_, version, _), _| + version + }.last + + match and fetcher.fetch_spec(*match) + end + + def self.latest_version_for name + spec = latest_spec_for name + spec and spec.version + end + + def self.latest_rubygems_version + latest_version_for "rubygems-update" + end + ## # A Gem::Version for the currently running ruby. @@ -1002,6 +1063,13 @@ module Gem @suffix_pattern ||= "{#{suffixes.join(',')}}" end + def self.loaded_path? path + # TODO: ruby needs a feature to let us query what's loaded in 1.8 and 1.9 + $LOADED_FEATURES.find { |s| + s =~ /(^|\/)#{Regexp.escape path}#{Regexp.union(*Gem.suffixes)}$/ + } + end + ## # Suffixes for require-able paths. @@ -1148,12 +1216,15 @@ module Gem attr_reader :pre_uninstall_hooks - # :stopdoc: - - alias cache source_index # an alias for the old name + end - # :startdoc: + def self.cache # :nodoc: + warn "#{Gem.location_of_caller.join ':'}:Warning: " \ + "Gem::cache is deprecated and will be removed on or after " \ + "August 2012. " \ + "Use Gem::source_index." + source_index end ## diff --git a/lib/rubygems/commands/owner_command.rb b/lib/rubygems/commands/owner_command.rb index 8b770e6f54..34f4efaa59 100644 --- a/lib/rubygems/commands/owner_command.rb +++ b/lib/rubygems/commands/owner_command.rb @@ -23,6 +23,7 @@ class Gem::Commands::OwnerCommand < Gem::Command def initialize super 'owner', description add_proxy_option + add_key_option defaults.merge! :add => [], :remove => [] add_option '-a', '--add EMAIL', 'Add an owner' do |value, options| @@ -45,7 +46,7 @@ class Gem::Commands::OwnerCommand < Gem::Command def show_owners name response = rubygems_api_request :get, "api/v1/gems/#{name}/owners.yaml" do |request| - request.add_field "Authorization", Gem.configuration.rubygems_api_key + request.add_field "Authorization", api_key end with_response response do |resp| @@ -70,7 +71,7 @@ class Gem::Commands::OwnerCommand < Gem::Command owners.each do |owner| response = rubygems_api_request method, "api/v1/gems/#{name}/owners" do |request| request.set_form_data 'email' => owner - request.add_field "Authorization", Gem.configuration.rubygems_api_key + request.add_field "Authorization", api_key end with_response response diff --git a/lib/rubygems/commands/pristine_command.rb b/lib/rubygems/commands/pristine_command.rb index 64ea8ce91c..9a0b2e9f11 100644 --- a/lib/rubygems/commands/pristine_command.rb +++ b/lib/rubygems/commands/pristine_command.rb @@ -79,11 +79,13 @@ revert the gem. say "Restoring gem(s) to pristine condition..." specs.each do |spec| - gem = Dir[File.join(Gem.dir, 'cache', spec.file_name)].first + gem = spec.cache_gem if gem.nil? then - alert_error "Cached gem for #{spec.full_name} not found, use `gem install` to restore" - next + say "Cached gem for #{spec.full_name} not found, attempting to fetch..." + dep = Gem::Dependency.new spec.name, spec.version + Gem::RemoteFetcher.fetcher.download_to_cache dep + gem = spec.cache_gem end # TODO use installer options diff --git a/lib/rubygems/commands/push_command.rb b/lib/rubygems/commands/push_command.rb index e72b74ebbf..c85a259564 100644 --- a/lib/rubygems/commands/push_command.rb +++ b/lib/rubygems/commands/push_command.rb @@ -27,7 +27,8 @@ class Gem::Commands::PushCommand < Gem::Command def initialize super 'push', description add_proxy_option - + add_key_option + add_option( '--host HOST', 'Push to another gemcutter-compatible host' @@ -42,17 +43,20 @@ class Gem::Commands::PushCommand < Gem::Command end def send_gem name - say "Pushing gem to #{options[:host] || Gem.host}..." - args = [:post, "api/v1/gems"] args << options[:host] if options[:host] + if Gem.latest_rubygems_version < Gem::Version.new(Gem::VERSION) then + alert_error "Using beta/unreleased version of rubygems. Not pushing." + terminate_interaction 1 + end + response = rubygems_api_request(*args) do |request| request.body = Gem.read_binary name request.add_field "Content-Length", request.body.size request.add_field "Content-Type", "application/octet-stream" - request.add_field "Authorization", Gem.configuration.rubygems_api_key + request.add_field "Authorization", api_key end with_response response diff --git a/lib/rubygems/commands/setup_command.rb b/lib/rubygems/commands/setup_command.rb index f40733a3ed..9090353e3b 100644 --- a/lib/rubygems/commands/setup_command.rb +++ b/lib/rubygems/commands/setup_command.rb @@ -33,13 +33,7 @@ class Gem::Commands::SetupCommand < Gem::Command end add_option '--[no-]vendor', - 'Install into vendorlibdir not sitelibdir', - '(Requires Ruby 1.8.7)' do |vendor, options| - if vendor and Gem.ruby_version < Gem::Version.new('1.8.7') then - raise OptionParser::InvalidOption, - "requires ruby 1.8.7+ (you have #{Gem.ruby_version})" - end - + 'Install into vendorlibdir not sitelibdir' do |vendor, options| options[:site_or_vendor] = vendor ? :vendorlibdir : :sitelibdir end @@ -61,7 +55,7 @@ class Gem::Commands::SetupCommand < Gem::Command end def check_ruby_version - required_version = Gem::Requirement.new '>= 1.8.6' + required_version = Gem::Requirement.new '>= 1.8.7' unless required_version.satisfied_by? Gem.ruby_version then alert_error "Expected Ruby version #{required_version}, is #{Gem.ruby_version}" @@ -341,7 +335,6 @@ abort "#{deprecation_message}" require 'rdoc/rdoc' - args << '--quiet' args << '--main' << 'README.rdoc' args << '.' args << 'README.rdoc' << 'UPGRADING.rdoc' diff --git a/lib/rubygems/commands/uninstall_command.rb b/lib/rubygems/commands/uninstall_command.rb index 52d5b03edb..d190777825 100644 --- a/lib/rubygems/commands/uninstall_command.rb +++ b/lib/rubygems/commands/uninstall_command.rb @@ -55,6 +55,11 @@ class Gem::Commands::UninstallCommand < Gem::Command options[:user_install] = value end + add_option('--[no-]format-executable', + 'Assume executable names match Ruby\'s prefix and suffix.') do |value, options| + options[:format_executable] = value + end + add_version_option add_platform_option end diff --git a/lib/rubygems/commands/unpack_command.rb b/lib/rubygems/commands/unpack_command.rb index ac1d376106..ef0d65e073 100644 --- a/lib/rubygems/commands/unpack_command.rb +++ b/lib/rubygems/commands/unpack_command.rb @@ -7,6 +7,7 @@ require 'rubygems/command' require 'rubygems/installer' require 'rubygems/version_option' +require 'rubygems/remote_fetcher' class Gem::Commands::UnpackCommand < Gem::Command @@ -39,16 +40,6 @@ class Gem::Commands::UnpackCommand < Gem::Command "#{program_name} GEMNAME" end - def download dependency - found = Gem::SpecFetcher.fetcher.fetch dependency - - return if found.empty? - - spec, source_uri = found.first - - Gem::RemoteFetcher.fetcher.download spec, source_uri - end - #-- # TODO: allow, e.g., 'gem unpack rake-0.3.1'. Find a general solution for # this, so that it works for uninstall as well. (And check other commands @@ -79,8 +70,9 @@ class Gem::Commands::UnpackCommand < Gem::Command # TODO: see comments in get_path() about general service. def find_in_cache(filename) - Gem.path.each do |gem_dir| - this_path = File.join gem_dir, 'cache', filename + + Gem.path.each do |path| + this_path = Gem.cache_gem(filename, path) return this_path if File.exist? this_path end @@ -111,15 +103,17 @@ class Gem::Commands::UnpackCommand < Gem::Command selected = specs.sort_by { |s| s.version }.last - return download(dependency) if selected.nil? + return Gem::RemoteFetcher.fetcher.download_to_cache(dependency) unless + selected return unless dependency.name =~ /^#{selected.name}$/i # We expect to find (basename).gem in the 'cache' directory. Furthermore, # the name match must be exact (ignoring case). - - path = find_in_cache(selected.file_name) - return download(dependency) unless path + + path = find_in_cache selected.file_name + + return Gem::RemoteFetcher.fetcher.download_to_cache(dependency) unless path path end diff --git a/lib/rubygems/commands/update_command.rb b/lib/rubygems/commands/update_command.rb index b2f69a5b52..b7c65eb2a4 100644 --- a/lib/rubygems/commands/update_command.rb +++ b/lib/rubygems/commands/update_command.rb @@ -27,8 +27,16 @@ class Gem::Commands::UpdateCommand < Gem::Command add_install_update_options - add_option('--system', + OptionParser.accept Gem::Version do |value| + Gem::Version.new value + + value + end + + add_option('--system [VERSION]', Gem::Version, 'Update the RubyGems system software') do |value, options| + value = true unless value + options[:system] = value end @@ -50,33 +58,13 @@ class Gem::Commands::UpdateCommand < Gem::Command end def execute + @installer = Gem::DependencyInstaller.new options + @updated = [] + hig = {} if options[:system] then - say "Updating RubyGems" - - unless options[:args].empty? then - raise "No gem names are allowed with the --system option" - end - - rubygems_update = Gem::Specification.new - rubygems_update.name = 'rubygems-update' - rubygems_update.version = Gem::Version.new Gem::VERSION - hig['rubygems-update'] = rubygems_update - - options[:user_install] = false - - Gem.source_index.refresh! - - update_gems = Gem.source_index.find_name 'rubygems-update' - - latest_update_gem = update_gems.sort_by { |s| s.version }.last - - say "Updating RubyGems to #{latest_update_gem.version}" - installed = do_rubygems_update latest_update_gem.version - - say "RubyGems system software updated" if installed - + update_rubygems return else say "Updating installed gems" @@ -92,28 +80,7 @@ class Gem::Commands::UpdateCommand < Gem::Command gems_to_update = which_to_update hig, options[:args] - updated = [] - - installer = Gem::DependencyInstaller.new options - - gems_to_update.uniq.sort.each do |name| - next if updated.any? { |spec| spec.name == name } - success = false - - say "Updating #{name}" - begin - installer.install name - success = true - rescue Gem::InstallError => e - alert_error "Error installing #{name}:\n\t#{e.message}" - success = false - end - - installer.installed_gems.each do |spec| - updated << spec - say "Successfully installed #{spec.full_name}" if success - end - end + updated = update_gems gems_to_update if updated.empty? then say "Nothing to update" @@ -136,12 +103,77 @@ class Gem::Commands::UpdateCommand < Gem::Command end end + def update_gem name, version = Gem::Requirement.default + return if @updated.any? { |spec| spec.name == name } + success = false + + say "Updating #{name}" + begin + @installer.install name, version + success = true + rescue Gem::InstallError => e + alert_error "Error installing #{name}:\n\t#{e.message}" + success = false + end + + @installer.installed_gems.each do |spec| + @updated << spec + say "Successfully installed #{spec.full_name}" if success + end + end + + def update_gems gems_to_update + gems_to_update.uniq.sort.each do |name| + update_gem name + end + + @updated + end + ## - # Update the RubyGems software to +version+. + # Update RubyGems software to the latest version. + + def update_rubygems + unless options[:args].empty? then + alert_error "Gem names are not allowed with the --system option" + terminate_interaction 1 + end + + options[:user_install] = false + + version = options[:system] + if version == true then + version = Gem::Version.new Gem::VERSION + requirement = Gem::Requirement.new ">= #{Gem::VERSION}" + else + version = Gem::Version.new version + requirement = Gem::Requirement.new version + end + + rubygems_update = Gem::Specification.new + rubygems_update.name = 'rubygems-update' + rubygems_update.version = version + + hig = { + 'rubygems-update' => rubygems_update + } + + gems_to_update = which_to_update hig, options[:args] + + if gems_to_update.empty? then + say "Latest version currently installed. Aborting." + terminate_interaction + end + + update_gem gems_to_update.first, requirement + + Gem.source_index.refresh! + + installed_gems = Gem.source_index.find_name 'rubygems-update', requirement + version = installed_gems.last.version - def do_rubygems_update(version) args = [] - args.push '--prefix', Gem.prefix unless Gem.prefix.nil? + args << '--prefix' << Gem.prefix if Gem.prefix args << '--no-rdoc' unless options[:generate_rdoc] args << '--no-ri' unless options[:generate_ri] args << '--no-format-executable' if options[:no_format_executable] @@ -154,8 +186,9 @@ class Gem::Commands::UpdateCommand < Gem::Command # Make sure old rubygems isn't loaded old = ENV["RUBYOPT"] - ENV.delete("RUBYOPT") - system setup_cmd + ENV.delete("RUBYOPT") if old + installed = system setup_cmd + say "RubyGems system software updated" if installed ENV["RUBYOPT"] = old if old end end diff --git a/lib/rubygems/config_file.rb b/lib/rubygems/config_file.rb index f3593999d3..1d16cd90ce 100644 --- a/lib/rubygems/config_file.rb +++ b/lib/rubygems/config_file.rb @@ -129,6 +129,11 @@ class Gem::ConfigFile attr_reader :rubygems_api_key + ## + # Hash of RubyGems.org and alternate API keys + + attr_reader :api_keys + ## # Create the config file object. +args+ is the list of arguments # from the command line. @@ -192,7 +197,7 @@ class Gem::ConfigFile @update_sources = @hash[:update_sources] if @hash.key? :update_sources @verbose = @hash[:verbose] if @hash.key? :verbose - load_rubygems_api_key + load_api_keys Gem.sources = @hash[:sources] if @hash.key? :sources handle_arguments arg_list @@ -205,10 +210,12 @@ class Gem::ConfigFile File.join(Gem.user_home, '.gem', 'credentials') end - def load_rubygems_api_key - api_key_hash = File.exists?(credentials_path) ? load_file(credentials_path) : @hash - - @rubygems_api_key = api_key_hash[:rubygems_api_key] if api_key_hash.key? :rubygems_api_key + def load_api_keys + @api_keys = File.exists?(credentials_path) ? load_file(credentials_path) : @hash + if @api_keys.key? :rubygems_api_key then + @rubygems_api_key = @api_keys[:rubygems_api_key] + @api_keys[:rubygems] = @api_keys.delete :rubygems_api_key unless @api_keys.key? :rubygems + end end def rubygems_api_key=(api_key) diff --git a/lib/rubygems/custom_require.rb b/lib/rubygems/custom_require.rb index 88e7aa4c4c..ebe7b05558 100644 --- a/lib/rubygems/custom_require.rb +++ b/lib/rubygems/custom_require.rb @@ -31,8 +31,23 @@ module Kernel # The normal require functionality of returning false if # that file has already been loaded is preserved. - def require(path) # :doc: - gem_original_require path + def require path + if Gem.unresolved_deps.empty? or Gem.loaded_path? path then + gem_original_require path + else + specs = Gem.searcher.find_in_unresolved path + unless specs.empty? then + specs = [specs.last] + else + specs = Gem.searcher.find_in_unresolved_tree path + end + + specs.each do |spec| + Gem.activate spec.name, spec.version # FIX: this is dumb + end + + return gem_original_require path + end rescue LoadError => load_error if load_error.message.end_with?(path) and Gem.try_activate(path) then return gem_original_require(path) diff --git a/lib/rubygems/dependency.rb b/lib/rubygems/dependency.rb index 4c61b6563e..e4d1bfffe8 100644 --- a/lib/rubygems/dependency.rb +++ b/lib/rubygems/dependency.rb @@ -32,11 +32,6 @@ class Gem::Dependency attr_writer :prerelease - ## - # Dependency type. - - attr_reader :type - ## # Constructs a dependency with +name+ and +requirements+. The last # argument can optionally be the dependency type, which defaults to @@ -72,7 +67,7 @@ class Gem::Dependency def inspect # :nodoc: "<%s type=%p name=%p requirements=%p>" % - [self.class, @type, @name, requirement.to_s] + [self.class, self.type, self.name, requirement.to_s] end ## @@ -132,7 +127,18 @@ class Gem::Dependency end def to_s # :nodoc: - "#{name} (#{requirement}, #{type})" + if type != :runtime then + "#{name} (#{requirement}, #{type})" + else + "#{name} (#{requirement})" + end + end + + ## + # Dependency type. + + def type + @type ||= :runtime end def == other # :nodoc: @@ -146,7 +152,7 @@ class Gem::Dependency # Dependencies are ordered by name. def <=> other - @name <=> other.name + self.name <=> other.name end ## @@ -187,5 +193,24 @@ class Gem::Dependency requirement.satisfied_by?(spec.version) end + ## + # Merges the requirements of +other+ into this dependency + + def merge other + unless name == other.name then + raise ArgumentError, + "#{self} and #{other} have different names" + end + + default = Gem::Requirement.default + self_req = self.requirement + other_req = other.requirement + + return self.class.new name, self_req if other_req == default + return self.class.new name, other_req if self_req == default + + self.class.new name, self_req.as_list.concat(other_req.as_list) + end + end diff --git a/lib/rubygems/dependency_installer.rb b/lib/rubygems/dependency_installer.rb index 23462fbe33..46ec63f14f 100644 --- a/lib/rubygems/dependency_installer.rb +++ b/lib/rubygems/dependency_installer.rb @@ -74,7 +74,7 @@ class Gem::DependencyInstaller @installed_gems = [] @install_dir = options[:install_dir] || Gem.dir - @cache_dir = options[:cache_dir] || @install_dir + @cache_dir = options[:cache_dir] || Gem.cache_dir(@install_dir) # Set with any errors that SpecFetcher finds while search through # gemspecs for a dep @@ -136,17 +136,33 @@ class Gem::DependencyInstaller def gather_dependencies specs = @specs_and_sources.map { |spec,_| spec } + # these gems were listed by the user, always install them + keep_names = specs.map { |spec| spec.full_name } + dependency_list = Gem::DependencyList.new @development dependency_list.add(*specs) to_do = specs.dup add_found_dependencies to_do, dependency_list unless @ignore_dependencies + dependency_list.specs.reject! { |spec| + ! keep_names.include? spec.full_name and + @source_index.any? { |n,_| n == spec.full_name } + } + + unless dependency_list.ok? or @ignore_dependencies or @force then + reason = dependency_list.why_not_ok?.map { |k,v| + "#{k} requires #{v.join(", ")}" + }.join("; ") + raise Gem::DependencyError, "Unable to resolve dependencies: #{reason}" + end + @gems_to_install = dependency_list.dependency_order.reverse end def add_found_dependencies to_do, dependency_list seen = {} + dependencies = Hash.new { |h, name| h[name] = Gem::Dependency.new name } until to_do.empty? do spec = to_do.shift @@ -157,10 +173,10 @@ class Gem::DependencyInstaller deps |= spec.development_dependencies if @development deps.each do |dep| + dependencies[dep.name] = dependencies[dep.name].merge dep + results = find_gems_with_sources(dep).reverse - # FIX: throw in everything that satisfies, and let - # FIX: dependencylist reduce to the chosen few results.reject! do |dep_spec,| to_do.push dep_spec @@ -172,14 +188,14 @@ class Gem::DependencyInstaller end results.each do |dep_spec, source_uri| - next if seen[dep_spec.name] @specs_and_sources << [dep_spec, source_uri] - # FIX: this is the bug dependency_list.add dep_spec end end end + + dependency_list.remove_specs_unsatisfied_by dependencies end ## @@ -259,7 +275,6 @@ class Gem::DependencyInstaller @gems_to_install.each do |spec| last = spec == @gems_to_install.last - # HACK is this test for full_name acceptable? next if @source_index.any? { |n,_| n == spec.full_name } and not last # TODO: make this sorta_verbose so other users can benefit from it diff --git a/lib/rubygems/dependency_list.rb b/lib/rubygems/dependency_list.rb index 647bb91ae2..91c7c5ade4 100644 --- a/lib/rubygems/dependency_list.rb +++ b/lib/rubygems/dependency_list.rb @@ -17,6 +17,7 @@ require 'tsort' # correct order to avoid conflicts. class Gem::DependencyList + attr_reader :specs include Enumerable include TSort @@ -56,6 +57,10 @@ class Gem::DependencyList @specs.push(*gemspecs) end + def clear + @specs.clear + end + ## # Return a list of the gem specifications in the dependency list, sorted in # order so that no gemspec in the list depends on a gemspec earlier in the @@ -110,11 +115,26 @@ class Gem::DependencyList # Are all the dependencies in the list satisfied? def ok? - @specs.all? do |spec| - spec.runtime_dependencies.all? do |dep| - @specs.find { |s| s.satisfies_requirement? dep } + why_not_ok?(:quick).empty? + end + + def why_not_ok? quick = false + unsatisfied = Hash.new { |h,k| h[k] = [] } + source_index = Gem.source_index + @specs.each do |spec| + spec.runtime_dependencies.each do |dep| + inst = source_index.any? { |_, installed_spec| + dep.name == installed_spec.name and + dep.requirement.satisfied_by? installed_spec.version + } + + unless inst or @specs.find { |s| s.satisfies_requirement? dep } then + unsatisfied[spec.name] << dep + return unsatisfied if quick + end end end + unsatisfied end ## @@ -146,6 +166,18 @@ class Gem::DependencyList } end + ## + # Remove everything in the DependencyList that matches but doesn't + # satisfy items in +dependencies+ (a hash of gem names to arrays of + # dependencies). + + def remove_specs_unsatisfied_by dependencies + specs.reject! { |spec| + dep = dependencies[spec.name] + dep and not dep.requirement.satisfied_by? spec.version + } + end + ## # Removes the gemspec matching +full_name+ from the dependency list diff --git a/lib/rubygems/doc_manager.rb b/lib/rubygems/doc_manager.rb index e900396aa4..71c7d850ad 100644 --- a/lib/rubygems/doc_manager.rb +++ b/lib/rubygems/doc_manager.rb @@ -168,7 +168,6 @@ class Gem::DocManager 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 << '--title' << "#{@spec.full_name} Documentation" @@ -182,6 +181,8 @@ class Gem::DocManager # HACK more end + debug_args = args.dup + r = RDoc::RDoc.new old_pwd = Dir.pwd @@ -199,10 +200,10 @@ class Gem::DocManager rescue Exception => 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 "... RDOC args: #{debug_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)" + Gem.configuration.backtrace + terminate_interaction 1 ensure Dir.chdir old_pwd end diff --git a/lib/rubygems/gem_path_searcher.rb b/lib/rubygems/gem_path_searcher.rb index 9dae006222..5b85cbc9fb 100644 --- a/lib/rubygems/gem_path_searcher.rb +++ b/lib/rubygems/gem_path_searcher.rb @@ -16,6 +16,7 @@ class Gem::GemPathSearcher def initialize # We want a record of all the installed gemspecs, in the order we wish to # examine them. + # TODO: remove this stupid method @gemspecs = init_gemspecs # Map gem spec to glob of full require_path directories. Preparing this @@ -48,7 +49,9 @@ class Gem::GemPathSearcher # only that there is a match. def find(glob) + # HACK violation of encapsulation @gemspecs.find do |spec| + # TODO: inverted responsibility matching_file? spec, glob end end @@ -57,9 +60,39 @@ class Gem::GemPathSearcher # Works like #find, but finds all gemspecs matching +glob+. def find_all(glob) + # HACK violation of encapsulation @gemspecs.select do |spec| + # TODO: inverted responsibility matching_file? spec, glob + end || [] + end + + def find_in_unresolved(glob) + # HACK violation + specs = Gem.unresolved_deps.values.map { |dep| + Gem.source_index.search dep, true + }.flatten + + specs.select do |spec| + # TODO: inverted responsibility + matching_file? spec, glob + end || [] + end + + def find_in_unresolved_tree glob + # HACK violation + # TODO: inverted responsibility + specs = Gem.unresolved_deps.values.map { |dep| + Gem.source_index.search dep, true + }.flatten + + specs.reverse_each do |spec| + trails = matching_paths(spec, glob) + next if trails.empty? + return trails.map(&:reverse).sort.first.reverse end + + [] end ## @@ -67,7 +100,18 @@ class Gem::GemPathSearcher # +spec+. def matching_file?(spec, path) - !matching_files(spec, path).empty? + not matching_files(spec, path).empty? + end + + def matching_paths(spec, path) + trails = [] + + spec.traverse do |from_spec, dep, to_spec, trail| + next unless to_spec.conflicts.empty? + trails << trail unless matching_files(to_spec, path).empty? + end + + trails end ## diff --git a/lib/rubygems/gemcutter_utilities.rb b/lib/rubygems/gemcutter_utilities.rb index 1681356805..a77a4911f2 100644 --- a/lib/rubygems/gemcutter_utilities.rb +++ b/lib/rubygems/gemcutter_utilities.rb @@ -7,6 +7,26 @@ require 'rubygems/remote_fetcher' module Gem::GemcutterUtilities + OptionParser.accept Symbol do |value| + value.to_sym + end + + ## + # Add the --key option + + def add_key_option + add_option '-k', '--key KEYNAME', Symbol, 'Use the given API key' do |value,options| + options[:key] = value + end + end + + def api_key + if options[:key] then + verify_api_key options[:key] + else + Gem.configuration.rubygems_api_key + end + end def sign_in return if Gem.configuration.rubygems_api_key @@ -33,6 +53,8 @@ module Gem::GemcutterUtilities host = ENV['RUBYGEMS_HOST'] if ENV['RUBYGEMS_HOST'] uri = URI.parse "#{host}/#{path}" + say "Pushing gem to #{host}..." + request_method = Net::HTTP.const_get method.to_s.capitalize Gem::RemoteFetcher.fetcher.request(uri, request_method, &block) @@ -52,4 +74,13 @@ module Gem::GemcutterUtilities end end + def verify_api_key(key) + if Gem.configuration.api_keys.key? key then + Gem.configuration.api_keys[key] + else + alert_error "No such API key. You can add it with gem keys --add #{key}" + terminate_interaction 1 + end + end + end diff --git a/lib/rubygems/installer.rb b/lib/rubygems/installer.rb index 5c7c57685b..8c6aeb44c7 100644 --- a/lib/rubygems/installer.rb +++ b/lib/rubygems/installer.rb @@ -156,6 +156,9 @@ class Gem::Installer Gem.ensure_gem_subdirectories @gem_home + # Completely remove any previous gem files + FileUtils.rm_rf(@gem_dir) if File.exist?(@gem_dir) + FileUtils.mkdir_p @gem_dir extract_files @@ -179,10 +182,9 @@ class Gem::Installer write_require_paths_file_if_needed if Gem::QUICKLOADER_SUCKAGE - # HACK remove? Isn't this done in multiple places? - cached_gem = File.join @gem_home, "cache", @gem.split(/\//).pop + cached_gem = Gem.cache_gem(File.basename(@gem), @gem_home) unless File.exist? cached_gem then - FileUtils.cp @gem, File.join(@gem_home, "cache") + FileUtils.cp @gem, Gem.cache_dir(@gem_home) end say @spec.post_install_message unless @spec.post_install_message.nil? @@ -235,7 +237,7 @@ class Gem::Installer # specifications directory. def write_spec - rubycode = @spec.to_ruby + rubycode = @spec.to_ruby_for_cache file_name = File.join @gem_home, 'specifications', @spec.spec_name @@ -275,8 +277,10 @@ class Gem::Installer @spec.executables.each do |filename| filename.untaint bin_path = File.expand_path "#{@spec.bindir}/#{filename}", @gem_dir - mode = File.stat(bin_path).mode | 0111 - File.chmod mode, bin_path + if File.exist?(bin_path) + mode = File.stat(bin_path).mode | 0111 + File.chmod mode, bin_path + end if @wrappers then generate_bin_script filename, bindir @@ -298,7 +302,7 @@ class Gem::Installer FileUtils.rm_f bin_script_path # prior install may have been --no-wrappers - File.open bin_script_path, 'w', 0755 do |file| + File.open bin_script_path, 'wb', 0755 do |file| file.print app_script_text(filename) end diff --git a/lib/rubygems/installer_test_case.rb b/lib/rubygems/installer_test_case.rb index c1f86d547b..26b590786b 100644 --- a/lib/rubygems/installer_test_case.rb +++ b/lib/rubygems/installer_test_case.rb @@ -64,12 +64,15 @@ class Gem::InstallerTestCase < Gem::TestCase super @spec = quick_gem 'a' + util_make_exec @spec @gem = File.join @tempdir, @spec.file_name @installer = util_installer @spec, @gem, @gemhome @user_spec = quick_gem 'b' + util_make_exec @user_spec + @user_gem = File.join @tempdir, @user_spec.file_name @user_installer = util_installer @user_spec, @user_gem, Gem.user_dir @@ -77,31 +80,38 @@ class Gem::InstallerTestCase < Gem::TestCase @user_spec.full_name) end - def util_gem_bindir(version = '2') - File.join util_gem_dir(version), "bin" + def util_gem_bindir spec = @spec + File.join util_gem_dir(spec), "bin" end - def util_gem_dir(version = '2') - File.join @gemhome, "gems", "a-#{version}" # HACK + def util_gem_dir spec = @spec + File.join @gemhome, "gems", spec.full_name end def util_inst_bindir File.join @gemhome, "bin" end - def util_make_exec(version = '2', shebang = "#!/usr/bin/ruby") - @spec.executables = ["my_exec"] + def util_make_exec(spec = @spec, shebang = "#!/usr/bin/ruby") + spec.executables = %w[executable] + spec.files << 'bin/executable' + + bindir = util_gem_bindir spec + FileUtils.mkdir_p bindir + exec_path = File.join bindir, 'executable' + open exec_path, 'w' do |io| + io.puts shebang + end - FileUtils.mkdir_p util_gem_bindir(version) - exec_path = File.join util_gem_bindir(version), "my_exec" - File.open exec_path, 'w' do |f| - f.puts shebang + temp_bin = File.join(@tempdir, 'bin') + FileUtils.mkdir_p temp_bin + open File.join(temp_bin, 'executable'), 'w' do |io| + io.puts shebang end end def util_setup_gem(ui = @ui) # HACK fix use_ui to make this automatic - @spec.files = File.join('lib', 'code.rb') - @spec.executables << 'executable' + @spec.files << File.join('lib', 'code.rb') @spec.extensions << File.join('ext', 'a', 'mkrf_conf.rb') Dir.chdir @tempdir do @@ -127,9 +137,7 @@ class Gem::InstallerTestCase < Gem::TestCase def util_installer(spec, gem_path, gem_home) util_build_gem spec - FileUtils.mv File.join(@gemhome, 'cache', spec.file_name), - @tempdir - + FileUtils.mv Gem.cache_gem(spec.file_name), @tempdir installer = Gem::Installer.new gem_path installer.gem_dir = util_gem_dir installer.gem_home = gem_home diff --git a/lib/rubygems/package/tar_reader/entry.rb b/lib/rubygems/package/tar_reader/entry.rb index c70248f159..d7b5280213 100644 --- a/lib/rubygems/package/tar_reader/entry.rb +++ b/lib/rubygems/package/tar_reader/entry.rb @@ -4,8 +4,9 @@ # File a patch instead and assign it to Ryan Davis or Eric Hodel. ###################################################################### +# -*- coding: utf-8 -*- #++ -# Copyright (C) 2004 Mauricio Julio Fernández Pradier +# Copyright (C) 2004 Mauricio Julio Fernández Pradier # See LICENSE.txt for additional licensing information. #-- diff --git a/lib/rubygems/remote_fetcher.rb b/lib/rubygems/remote_fetcher.rb index aa63392848..520adb5827 100644 --- a/lib/rubygems/remote_fetcher.rb +++ b/lib/rubygems/remote_fetcher.rb @@ -77,6 +77,23 @@ class Gem::RemoteFetcher end end + ## + # Given a name and requirement, downloads this gem into cache and returns the + # filename. Returns nil if the gem cannot be located. + #-- + # Should probably be integrated with #download below, but that will be a + # larger, more emcompassing effort. -erikh + + def download_to_cache dependency + found = Gem::SpecFetcher.fetcher.fetch dependency + + return if found.empty? + + spec, source_uri = found.first + + download spec, source_uri + end + ## # Moves the gem +spec+ from +source_uri+ to the cache dir unless it is # already there. If the source_uri is local the gem cache dir copy is @@ -86,9 +103,9 @@ class Gem::RemoteFetcher Gem.ensure_gem_subdirectories(install_dir) rescue nil if File.writable?(install_dir) - cache_dir = File.join install_dir, 'cache' + cache_dir = Gem.cache_dir(install_dir) else - cache_dir = File.join(Gem.user_dir, 'cache') + cache_dir = Gem.cache_dir(Gem.user_dir) end gem_file_name = spec.file_name @@ -140,7 +157,7 @@ class Gem::RemoteFetcher path = source_uri.path path = File.dirname(path) if File.extname(path) == '.gem' - remote_gem_path = File.join(path, 'gems', gem_file_name) + remote_gem_path = correct_for_windows_path(File.join(path, 'gems', gem_file_name)) FileUtils.cp(remote_gem_path, local_gem_path) rescue Errno::EACCES @@ -276,6 +293,14 @@ class Gem::RemoteFetcher raise FetchError.new(e.message, uri) end + def correct_for_windows_path(path) + if path[0].chr == '/' && path[1].chr =~ /[a-z]/i && path[2].chr == ':' + path = path[1..-1] + else + path + end + end + ## # Read the data from the (source based) URI, but if it is a file:// URI, # read from the filesystem instead. @@ -293,13 +318,7 @@ class Gem::RemoteFetcher end if uri.scheme == 'file' - path = uri.path - - # Deal with leading slash on Windows paths - if path[0].chr == '/' && path[1].chr =~ /[a-zA-Z]/ && path[2].chr == ':' - path = path[1..-1] - end - + path = correct_for_windows_path(uri.path) return Gem.read_binary(path) end diff --git a/lib/rubygems/requirement.rb b/lib/rubygems/requirement.rb index 8af5fbd6b4..35f7d0809a 100644 --- a/lib/rubygems/requirement.rb +++ b/lib/rubygems/requirement.rb @@ -108,7 +108,7 @@ class Gem::Requirement end def as_list # :nodoc: - requirements.map { |op, version| "#{op} #{version}" } + requirements.map { |op, version| "#{op} #{version}" }.sort end def hash # :nodoc: @@ -137,7 +137,8 @@ class Gem::Requirement # True if +version+ satisfies this Requirement. def satisfied_by? version - requirements.all? { |op, rv| OPS[op].call version, rv } + # #28965: syck has a bug with unquoted '=' YAML.loading as YAML::DefaultKey + requirements.all? { |op, rv| (OPS[op] || OPS["="]).call version, rv } end def to_s # :nodoc: diff --git a/lib/rubygems/security.rb b/lib/rubygems/security.rb index 9f3daa9453..1ff375dc4a 100644 --- a/lib/rubygems/security.rb +++ b/lib/rubygems/security.rb @@ -12,6 +12,7 @@ require 'rubygems/exceptions' require 'rubygems/gem_openssl' +require 'fileutils' # # = Signed Gems README diff --git a/lib/rubygems/source_index.rb b/lib/rubygems/source_index.rb index 7c571fff55..a6733fac31 100644 --- a/lib/rubygems/source_index.rb +++ b/lib/rubygems/source_index.rb @@ -131,7 +131,7 @@ class Gem::SourceIndex # Returns an Array specifications for the latest released versions # of each gem in this index. - def latest_specs + def latest_specs(include_prerelease=false) result = Hash.new { |h,k| h[k] = [] } latest = {} @@ -140,7 +140,7 @@ class Gem::SourceIndex curr_ver = spec.version prev_ver = latest.key?(name) ? latest[name].version : nil - next if curr_ver.prerelease? + next if !include_prerelease && curr_ver.prerelease? next unless prev_ver.nil? or curr_ver >= prev_ver or latest[name].platform != Gem::Platform::RUBY @@ -273,6 +273,7 @@ class Gem::SourceIndex when Gem::Dependency then only_platform = platform_only requirement = gem_pattern.requirement + gem_pattern = if Regexp === gem_pattern.name then gem_pattern.name elsif gem_pattern.name.empty? then diff --git a/lib/rubygems/spec_fetcher.rb b/lib/rubygems/spec_fetcher.rb index c999a65cd9..ab05c2f9dd 100644 --- a/lib/rubygems/spec_fetcher.rb +++ b/lib/rubygems/spec_fetcher.rb @@ -76,7 +76,8 @@ class Gem::SpecFetcher # Returns the local directory to write +uri+ to. def cache_dir(uri) - File.join @dir, "#{uri.host}%#{uri.port}", File.dirname(uri.path) + escaped_path = uri.path.sub(%r[^/([a-z]):/]i, '/\\1-/') # Correct for windows paths + File.join @dir, "#{uri.host}%#{uri.port}", File.dirname(escaped_path) end ## @@ -100,6 +101,7 @@ class Gem::SpecFetcher end def fetch_spec(spec, source_uri) + source_uri = URI.parse source_uri if String === source_uri spec = spec - [nil, 'ruby', ''] spec_file_name = "#{spec.join '-'}.gemspec" @@ -179,7 +181,7 @@ class Gem::SpecFetcher def suggest_gems_from_name gem_name gem_name = gem_name.downcase max = gem_name.size / 2 - specs = list.values.flatten(1) # flatten(1) is 1.8.7 and up + specs = list.values.flatten 1 matches = specs.map { |name, version, platform| next unless Gem::Platform.match platform diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb index f66288498b..a5e250a5df 100644 --- a/lib/rubygems/specification.rb +++ b/lib/rubygems/specification.rb @@ -339,7 +339,8 @@ class Gem::Specification # List of dependencies that will automatically be activated at runtime. def runtime_dependencies - dependencies.select { |d| d.type == :runtime || d.type == nil } + # TODO: fix #type to return :runtime if nil + dependencies.select { |d| d.type == :runtime } end ## @@ -542,8 +543,8 @@ class Gem::Specification def self.normalize_yaml_input(input) result = input.respond_to?(:read) ? input.read : input - result = "--- " + result unless result =~ /^--- / - result + result = "--- " + result unless result =~ /\A--- / + result.gsub(/ !!null \n/, " \n") end ## @@ -684,6 +685,14 @@ class Gem::Specification alias eql? == # :nodoc: + ## + # A macro to yield cached gem path + # + def cache_gem + cache_name = File.join(Gem.dir, 'cache', file_name) + return File.exist?(cache_name) ? cache_name : nil + end + ## # True if this gem has the same attributes as +other+. @@ -726,11 +735,13 @@ class Gem::Specification end def to_yaml(opts = {}) # :nodoc: - return super if YAML.const_defined?(:ENGINE) && !YAML::ENGINE.syck? - - YAML.quick_emit object_id, opts do |out| - out.map taguri, to_yaml_style do |map| - encode_with map + if YAML.const_defined?(:ENGINE) && !YAML::ENGINE.syck? then + super.gsub(/ !!null \n/, " \n") + else + YAML.quick_emit object_id, opts do |out| + out.map taguri, to_yaml_style do |map| + encode_with map + end end end end @@ -795,21 +806,17 @@ class Gem::Specification result << " if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then" - unless dependencies.empty? then - dependencies.each do |dep| - version_reqs_param = dep.requirements_list.inspect - dep.instance_variable_set :@type, :runtime if dep.type.nil? # HACK - result << " s.add_#{dep.type}_dependency(%q<#{dep.name}>, #{version_reqs_param})" - end + dependencies.each do |dep| + req = dep.requirements_list.inspect + dep.instance_variable_set :@type, :runtime if dep.type.nil? # HACK + result << " s.add_#{dep.type}_dependency(%q<#{dep.name}>, #{req})" end result << " else" - unless dependencies.empty? then - dependencies.each do |dep| - version_reqs_param = dep.requirements_list.inspect - result << " s.add_dependency(%q<#{dep.name}>, #{version_reqs_param})" - end + dependencies.each do |dep| + version_reqs_param = dep.requirements_list.inspect + result << " s.add_dependency(%q<#{dep.name}>, #{version_reqs_param})" end result << ' end' @@ -827,6 +834,15 @@ class Gem::Specification result.join "\n" end + def to_ruby_for_cache + s = dup + # remove large blobs that aren't used at runtime: + s.files = nil + s.extra_rdoc_files = nil + s.rdoc_options = nil + s.to_ruby + end + ## # Checks that the specification contains all required fields, and does a # very basic sanity check. @@ -835,6 +851,7 @@ class Gem::Specification # checks.. def validate + require 'rubygems/user_interaction' extend Gem::UserInteraction normalize @@ -1523,4 +1540,32 @@ class Gem::Specification @extensions, ].flatten.uniq.compact end + + def conflicts + conflicts = {} + Gem.loaded_specs.values.each do |spec| + bad = self.runtime_dependencies.find_all { |dep| + spec.name == dep.name and not spec.satisfies_requirement? dep + } + + conflicts[spec] = bad unless bad.empty? + end + conflicts + end + + def traverse trail = [], &b + trail = trail + [self] + runtime_dependencies.each do |dep| + dep_specs = Gem.source_index.search dep, true + dep_specs.each do |dep_spec| + b[self, dep, dep_spec, trail + [dep_spec]] + dep_spec.traverse(trail, &b) unless + trail.map(&:name).include? dep_spec.name + end + end + end + + def dependent_specs + runtime_dependencies.map { |dep| Gem.source_index.search dep, true }.flatten + end end diff --git a/lib/rubygems/test_case.rb b/lib/rubygems/test_case.rb index 447a30f780..5c32bd2ddb 100644 --- a/lib/rubygems/test_case.rb +++ b/lib/rubygems/test_case.rb @@ -24,20 +24,8 @@ require 'uri' require 'rubygems/package' require 'rubygems/test_utilities' require 'pp' -require 'yaml' require 'zlib' - -begin - YAML::ENGINE.yamler = 'psych' -rescue LoadError -end if YAML.const_defined? :ENGINE - -begin - gem 'rdoc' -rescue Gem::LoadError -end - -require 'rdoc/rdoc' +Gem.load_yaml require 'rubygems/mock_gem_ui' @@ -99,6 +87,8 @@ class Gem::TestCase < MiniTest::Unit::TestCase undef_method :default_test if instance_methods.include? 'default_test' or instance_methods.include? :default_test + @@project_dir = Dir.pwd + ## # #setup prepares a sandboxed location to install gems. All installs are # directed to a temporary directory. All install plugins are removed. @@ -128,8 +118,6 @@ class Gem::TestCase < MiniTest::Unit::TestCase @gemhome = File.join @tempdir, 'gemhome' @userhome = File.join @tempdir, 'userhome' - Gem.ensure_gem_subdirectories @gemhome - @orig_ruby = if ruby = ENV['RUBY'] then Gem.class_eval { ruby, @ruby = @ruby, ruby } ruby @@ -137,6 +125,8 @@ class Gem::TestCase < MiniTest::Unit::TestCase Gem.ensure_gem_subdirectories @gemhome + Dir.chdir @tempdir + @orig_ENV_HOME = ENV['HOME'] ENV['HOME'] = @userhome Gem.instance_variable_set :@user_home, nil @@ -146,6 +136,7 @@ class Gem::TestCase < MiniTest::Unit::TestCase Gem.use_paths(@gemhome) Gem.loaded_specs.clear + Gem.unresolved_deps.clear Gem.configuration.verbose = true Gem.configuration.update_sources = true @@ -154,6 +145,7 @@ class Gem::TestCase < MiniTest::Unit::TestCase @uri = URI.parse @gem_repo Gem.sources.replace [@gem_repo] + Gem.searcher = nil Gem::SpecFetcher.fetcher = nil @orig_BASERUBY = Gem::ConfigMap[:BASERUBY] @@ -169,17 +161,14 @@ class Gem::TestCase < MiniTest::Unit::TestCase @marshal_version = "#{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}" - @private_key = File.expand_path('../../../test/rubygems/private_key.pem', - __FILE__) - @public_cert = File.expand_path('../../../test/rubygems/public_cert.pem', - __FILE__) - + # TODO: move to installer test cases Gem.post_build_hooks.clear Gem.post_install_hooks.clear Gem.post_uninstall_hooks.clear Gem.pre_install_hooks.clear Gem.pre_uninstall_hooks.clear + # TODO: move to installer test cases Gem.post_build do |installer| @post_build_hook_arg = installer true @@ -219,6 +208,8 @@ class Gem::TestCase < MiniTest::Unit::TestCase Gem::RemoteFetcher.fetcher = nil end + Dir.chdir @@project_dir + FileUtils.rm_rf @tempdir unless ENV['KEEP_FILES'] ENV['GEM_HOME'] = @orig_gem_home @@ -319,14 +310,14 @@ class Gem::TestCase < MiniTest::Unit::TestCase require 'rubygems/specification' spec = Gem::Specification.new do |s| - s.platform = Gem::Platform::RUBY - s.name = name - s.version = version - s.author = 'A User' - s.email = 'example@example.com' - s.homepage = 'http://example.com' - s.has_rdoc = true - s.summary = "this is a summary" + s.platform = Gem::Platform::RUBY + s.name = name + s.version = version + s.author = 'A User' + s.email = 'example@example.com' + s.homepage = 'http://example.com' + s.has_rdoc = true + s.summary = "this is a summary" s.description = "This is a test description" yield(s) if block_given? @@ -344,6 +335,30 @@ class Gem::TestCase < MiniTest::Unit::TestCase return spec end + def quick_spec name, version = '2' + require 'rubygems/specification' + + spec = Gem::Specification.new do |s| + s.platform = Gem::Platform::RUBY + s.name = name + s.version = version + s.author = 'A User' + s.email = 'example@example.com' + s.homepage = 'http://example.com' + s.has_rdoc = true + s.summary = "this is a summary" + s.description = "This is a test description" + + yield(s) if block_given? + end + + spec.loaded_from = @gemhome + + Gem.source_index.add_spec spec + + return spec + end + ## # Builds a gem from +spec+ and places it in File.join @gemhome, # 'cache'. Automatically creates files based on +spec.files+ @@ -364,7 +379,7 @@ class Gem::TestCase < MiniTest::Unit::TestCase end FileUtils.mv spec.file_name, - File.join(@gemhome, 'cache', "#{spec.original_name}.gem") + Gem.cache_gem("#{spec.original_name}.gem") end end @@ -372,11 +387,60 @@ class Gem::TestCase < MiniTest::Unit::TestCase # Removes all installed gems from +@gemhome+. def util_clear_gems - FileUtils.rm_r File.join(@gemhome, 'gems') - FileUtils.rm_r File.join(@gemhome, 'specifications') + FileUtils.rm_rf File.join(@gemhome, 'gems') + FileUtils.rm_rf File.join(@gemhome, 'specifications') Gem.source_index.refresh! end + ## + # Install the provided specs + + def install_specs(*specs) + specs.each do |spec| + # TODO: inverted responsibility + Gem.source_index.add_spec spec + end + Gem.searcher = nil + end + + ## + # Create a new spec (or gem if passed an array of files) and set it + # up properly. Use this instead of util_spec and util_gem. + + def new_spec name, version, deps = nil, *files + # TODO: unfactor and deprecate util_gem and util_spec + spec, = unless files.empty? then + util_gem name, version do |s| + Array(deps).each do |n,v| + s.add_dependency n, v + end + s.files.push(*files) + end + else + util_spec name, version, deps + end + spec.loaded_from = File.join @gemhome, 'specifications', spec.spec_name + spec.loaded = false + spec + end + + ## + # Creates a spec with +name+, +version+ and +deps+. + + def util_spec(name, version, deps = nil, &block) + raise "deps or block, not both" if deps and block + + if deps then + block = proc do |s| + deps.each do |n, req| + s.add_dependency n, (req || '>= 0') + end + end + end + + quick_spec(name, version, &block) + end + ## # Creates a gem with +name+, +version+ and +deps+. The specification will # be yielded before gem creation for customization. The gem will be placed @@ -384,6 +448,8 @@ class Gem::TestCase < MiniTest::Unit::TestCase # location are returned. def util_gem(name, version, deps = nil, &block) + raise "deps or block, not both" if deps and block + if deps then block = proc do |s| deps.each do |n, req| @@ -397,8 +463,9 @@ class Gem::TestCase < MiniTest::Unit::TestCase util_build_gem spec cache_file = File.join @tempdir, 'gems', "#{spec.original_name}.gem" - FileUtils.mv File.join(@gemhome, 'cache', "#{spec.original_name}.gem"), - cache_file + gems_dir = File.dirname cache_file + FileUtils.mkdir_p File.dirname cache_file + FileUtils.mv Gem.cache_gem("#{spec.original_name}.gem"), cache_file FileUtils.rm File.join(@gemhome, 'specifications', spec.spec_name) spec.loaded_from = nil @@ -436,6 +503,7 @@ class Gem::TestCase < MiniTest::Unit::TestCase # Additional +prerelease+ gems may also be created: # # +@a2_pre+:: gem a version 2.a + # TODO: nuke this and fix tests. this should speed up a lot def util_make_gems(prerelease = false) @a1 = quick_gem 'a', '1' do |s| @@ -459,11 +527,12 @@ Also, a list: s.require_paths = %w[lib] end - @a2 = quick_gem('a', '2', &init) - @a3a = quick_gem('a', '3.a', &init) + @a2 = quick_gem('a', '2', &init) + @a3a = quick_gem('a', '3.a', &init) @a_evil9 = quick_gem('a_evil', '9', &init) - @b2 = quick_gem('b', '2', &init) - @c1_2 = quick_gem('c', '1.2', &init) + @b2 = quick_gem('b', '2', &init) + @c1_2 = quick_gem('c', '1.2', &init) + @pl1 = quick_gem 'pl', '1' do |s| # l for legacy s.files = %w[lib/code.rb] s.require_paths = %w[lib] @@ -477,12 +546,12 @@ Also, a list: util_build_gem @a2_pre end - write_file File.join(*%W[gems #{@a1.original_name} lib code.rb]) - write_file File.join(*%W[gems #{@a2.original_name} lib code.rb]) - write_file File.join(*%W[gems #{@a3a.original_name} lib code.rb]) - write_file File.join(*%W[gems #{@b2.original_name} lib code.rb]) + write_file File.join(*%W[gems #{@a1.original_name} lib code.rb]) + write_file File.join(*%W[gems #{@a2.original_name} lib code.rb]) + write_file File.join(*%W[gems #{@a3a.original_name} lib code.rb]) + write_file File.join(*%W[gems #{@b2.original_name} lib code.rb]) write_file File.join(*%W[gems #{@c1_2.original_name} lib code.rb]) - write_file File.join(*%W[gems #{@pl1.original_name} lib code.rb]) + write_file File.join(*%W[gems #{@pl1.original_name} lib code.rb]) [@a1, @a2, @a3a, @a_evil9, @b2, @c1_2, @pl1].each do |spec| util_build_gem spec @@ -703,7 +772,7 @@ Also, a list: @@ruby = rubybin env_rake = ENV['rake'] - ruby19_rake = File.expand_path("../../../bin/rake", __FILE__) + ruby19_rake = File.expand_path("bin/rake", @@project_dir) @@rake = if env_rake then ENV["rake"] elsif File.exist? ruby19_rake then diff --git a/lib/rubygems/test_utilities.rb b/lib/rubygems/test_utilities.rb index 892e4dd9e5..43f905f017 100644 --- a/lib/rubygems/test_utilities.rb +++ b/lib/rubygems/test_utilities.rb @@ -104,7 +104,7 @@ class Gem::FakeFetcher def download spec, source_uri, install_dir = Gem.dir name = spec.file_name - path = File.join(install_dir, 'cache', name) + path = Gem.cache_gem(name, install_dir) Gem.ensure_gem_subdirectories install_dir @@ -119,6 +119,16 @@ class Gem::FakeFetcher path end + def download_to_cache dependency + found = Gem::SpecFetcher.fetcher.fetch dependency + + return if found.empty? + + spec, source_uri = found.first + + download spec, source_uri + end + end # :stopdoc: diff --git a/lib/rubygems/uninstaller.rb b/lib/rubygems/uninstaller.rb index df45771846..02976866b1 100644 --- a/lib/rubygems/uninstaller.rb +++ b/lib/rubygems/uninstaller.rb @@ -56,6 +56,7 @@ class Gem::Uninstaller @force_all = options[:all] @force_ignore = options[:ignore] @bin_dir = options[:bin_dir] + @format_executable = options[:format_executable] # only add user directory if install_dir is not set @user_install = false @@ -108,6 +109,13 @@ class Gem::Uninstaller def uninstall_gem(spec, specs) @spec = spec + unless dependencies_ok? spec + unless ask_if_ok(spec) + raise Gem::DependencyRemovalException, + "Uninstallation aborted due to dependent gem(s)" + end + end + Gem.pre_uninstall_hooks.each do |hook| hook.call self end @@ -161,8 +169,8 @@ class Gem::Uninstaller spec.executables.each do |exe_name| say "Removing #{exe_name}" - FileUtils.rm_f File.join(bindir, exe_name) - FileUtils.rm_f File.join(bindir, "#{exe_name}.bat") + FileUtils.rm_f File.join(bindir, formatted_program_filename(exe_name)) + FileUtils.rm_f File.join(bindir, "#{formatted_program_filename(exe_name)}.bat") end end end @@ -184,11 +192,6 @@ class Gem::Uninstaller # uninstalled a gem, it is removed from that list. def remove(spec, list) - unless dependencies_ok? spec then - raise Gem::DependencyRemovalException, - "Uninstallation aborted due to dependent gem(s)" - end - unless path_ok?(@gem_home, spec) or (@user_install and path_ok?(Gem.user_dir, spec)) then e = Gem::GemNotInHomeException.new \ @@ -215,11 +218,10 @@ class Gem::Uninstaller FileUtils.rm_rf gemspec - cache_dir = File.join spec.installation_path, 'cache' - gem = File.join cache_dir, spec.file_name + gem = Gem.cache_gem(spec.file_name, spec.installation_path) unless File.exist? gem then - gem = File.join cache_dir, "#{original_platform_name}.gem" + gem = Gem.cache_gem("#{original_platform_name}.gem", spec.installation_path) end FileUtils.rm_rf gem @@ -246,7 +248,7 @@ class Gem::Uninstaller deplist = Gem::DependencyList.from_source_index @source_index deplist.add(*@user_index.gems.values) if @user_install - deplist.ok_to_remove?(spec.full_name) || ask_if_ok(spec) + deplist.ok_to_remove?(spec.full_name) end def ask_if_ok(spec) @@ -263,5 +265,14 @@ class Gem::Uninstaller return ask_yes_no(msg.join("\n"), true) end + def formatted_program_filename(filename) + if @format_executable then + Gem::Installer.exec_format % File.basename(filename) + else + filename + end + end + + end diff --git a/lib/rubygems/user_interaction.rb b/lib/rubygems/user_interaction.rb index ff5800c116..538793181e 100644 --- a/lib/rubygems/user_interaction.rb +++ b/lib/rubygems/user_interaction.rb @@ -182,29 +182,24 @@ class Gem::StreamUI end end - qstr = case default - when nil - 'yn' - when true - 'Yn' - else - 'yN' - end + default_answer = case default + when nil + 'yn' + when true + 'Yn' + else + 'yN' + end result = nil - while result.nil? - result = ask("#{question} [#{qstr}]") - result = case result - when /^[Yy].*/ - true - when /^[Nn].*/ - false - when /^$/ - default - else - nil - end + while result.nil? do + result = case ask "#{question} [#{default_answer}]" + when /^y/i then true + when /^n/i then false + when /^$/ then default + else nil + end end return result @@ -531,20 +526,26 @@ end # SilentUI is a UI choice that is absolutely silent. class Gem::SilentUI < Gem::StreamUI - def initialize - reader, writer = nil, nil - if Gem.win_platform? - reader = File.open('nul', 'r') - writer = File.open('nul', 'w') - else + begin reader = File.open('/dev/null', 'r') writer = File.open('/dev/null', 'w') + rescue Errno::ENOENT + reader = File.open('nul', 'r') + writer = File.open('nul', 'w') end super reader, writer, writer end + + def download_reporter(*args) + SilentDownloadReporter.new(@outs, *args) + end + + def progress_reporter(*args) + SilentProgressReporter.new(@outs, *args) + end end diff --git a/lib/rubygems/validator.rb b/lib/rubygems/validator.rb index d2750f14ea..bc6c520d8b 100644 --- a/lib/rubygems/validator.rb +++ b/lib/rubygems/validator.rb @@ -94,7 +94,7 @@ class Gem::Validator next unless gems.include? gem_spec.name unless gems.empty? install_dir = gem_spec.installation_path - gem_path = File.join install_dir, "cache", gem_spec.file_name + gem_path = Gem.cache_gem(gem_spec.file_name, install_dir) spec_path = File.join install_dir, "specifications", gem_spec.spec_name gem_directory = gem_spec.full_gem_path diff --git a/test/rubygems/fix_openssl_warnings.rb b/test/rubygems/fix_openssl_warnings.rb new file mode 100644 index 0000000000..313c63628f --- /dev/null +++ b/test/rubygems/fix_openssl_warnings.rb @@ -0,0 +1,18 @@ +###################################################################### +# This file is imported from the rubygems project. +# DO NOT make modifications in this repo. They _will_ be reverted! +# File a patch instead and assign it to Ryan Davis or Eric Hodel. +###################################################################### + +## +# HACK: this drives me BONKERS + +if defined? OpenSSL then + class OpenSSL::X509::ExtensionFactory + alias :old_create_ext :create_ext + def create_ext(*args) + @config ||= nil + old_create_ext(*args) + end + end +end if RUBY_VERSION < "1.9" diff --git a/test/rubygems/plugin/load/rubygems_plugin.rb b/test/rubygems/plugin/load/rubygems_plugin.rb index 32faee7e2b..9b37ce09f3 100644 --- a/test/rubygems/plugin/load/rubygems_plugin.rb +++ b/test/rubygems/plugin/load/rubygems_plugin.rb @@ -4,4 +4,6 @@ # File a patch instead and assign it to Ryan Davis or Eric Hodel. ###################################################################### -TestGem::TEST_PLUGIN_LOAD = :loaded \ No newline at end of file +class TestGem + TEST_PLUGIN_LOAD = :loaded +end diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 06f25d4775..98d37a807e 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -26,6 +26,352 @@ class TestGem < Gem::TestCase util_remove_interrupt_command end + def assert_activate expected, *specs + specs.each do |spec| + case spec + when Array + Gem.activate(*spec) + when String + Gem.activate spec + else + Gem.activate spec.name + end + end + + loaded = Gem.loaded_specs.values.map(&:full_name) + + assert_equal expected.sort, loaded.sort if expected + end + + def test_self_activate + foo = util_spec 'foo', '1' + + assert_activate %w[foo-1], foo + end + + def loaded_spec_names + Gem.loaded_specs.values.map(&:full_name).sort + end + + def unresolved_names + Gem.unresolved_deps.values.map(&:to_s).sort + end + + def test_self_activate_via_require + a1 = new_spec "a", "1", "b" => "= 1" + b1 = new_spec "b", "1", nil, "lib/b/c.rb" + b2 = new_spec "b", "2", nil, "lib/b/c.rb" + + Gem.activate "a", "= 1" + require "b/c" + + assert_equal %w(a-1 b-1), loaded_spec_names + end + + def test_self_activate_deep_unambiguous + a1 = new_spec "a", "1", "b" => "= 1" + b1 = new_spec "b", "1", "c" => "= 1" + b2 = new_spec "b", "2", "c" => "= 2" + c1 = new_spec "c", "1" + c2 = new_spec "c", "2" + + install_specs a1, b1, b2, c1, c2 + + Gem.activate "a", "= 1" + assert_equal %w(a-1 b-1 c-1), loaded_spec_names + end + + def save_loaded_features + old_loaded_features = $LOADED_FEATURES.dup + yield + ensure + $LOADED_FEATURES.replace old_loaded_features + end + + def test_self_activate_ambiguous_direct + save_loaded_features do + a1 = new_spec "a", "1", "b" => "> 0" + b1 = new_spec("b", "1", { "c" => ">= 1" }, "lib/d.rb") + b2 = new_spec("b", "2", { "c" => ">= 2" }, "lib/d.rb") + c1 = new_spec "c", "1" + c2 = new_spec "c", "2" + + install_specs a1, b1, b2, c1, c2 + + Gem.activate "a", "= 1" + assert_equal %w(a-1), loaded_spec_names + assert_equal ["b (> 0)"], unresolved_names + + require "d" + + assert_equal %w(a-1 b-2 c-2), loaded_spec_names + assert_equal [], unresolved_names + end + end + + def test_self_activate_ambiguous_indirect + save_loaded_features do + a1 = new_spec "a", "1", "b" => "> 0" + b1 = new_spec "b", "1", "c" => ">= 1" + b2 = new_spec "b", "2", "c" => ">= 2" + c1 = new_spec "c", "1", nil, "lib/d.rb" + c2 = new_spec "c", "2", nil, "lib/d.rb" + + install_specs a1, b1, b2, c1, c2 + + Gem.activate "a", "= 1" + assert_equal %w(a-1), loaded_spec_names + assert_equal ["b (> 0)"], unresolved_names + + require "d" + + assert_equal %w(a-1 b-2 c-2), loaded_spec_names + assert_equal [], unresolved_names + end + end + + def test_self_activate_ambiguous_unrelated + save_loaded_features do + a1 = new_spec "a", "1", "b" => "> 0" + b1 = new_spec "b", "1", "c" => ">= 1" + b2 = new_spec "b", "2", "c" => ">= 2" + c1 = new_spec "c", "1" + c2 = new_spec "c", "2" + d1 = new_spec "d", "1", nil, "lib/d.rb" + + install_specs a1, b1, b2, c1, c2 + + Gem.activate "a", "= 1" + assert_equal %w(a-1), loaded_spec_names + assert_equal ["b (> 0)"], unresolved_names + + require "d" + + assert_equal %w(a-1 d-1), loaded_spec_names + assert_equal ["b (> 0)"], unresolved_names + end + end + + def test_self_activate_ambiguous_indirect_conflict + save_loaded_features do + a1 = new_spec "a", "1", "b" => "> 0" + a2 = new_spec "a", "2", "b" => "> 0" + b1 = new_spec "b", "1", "c" => ">= 1" + b2 = new_spec "b", "2", "c" => ">= 2" + c1 = new_spec "c", "1", nil, "lib/d.rb" + c2 = new_spec("c", "2", { "a" => "1" }, "lib/d.rb") # conflicts with a-2 + + install_specs a1, b1, b2, c1, c2 + + Gem.activate "a", "= 2" + assert_equal %w(a-2), loaded_spec_names + assert_equal ["b (> 0)"], unresolved_names + + require "d" + + assert_equal %w(a-2 b-1 c-1), loaded_spec_names + assert_equal [], unresolved_names + end + end + + def test_require_missing + save_loaded_features do + assert_raises ::LoadError do + require "q" + end + end + end + + def test_self_activate_loaded + util_spec 'foo', '1' + + assert Gem.activate 'foo' + refute Gem.activate 'foo' + end + + ## + # [A] depends on + # [B] >= 1.0 (satisfied by 2.0) + # [C] depends on nothing + + def test_self_activate_unrelated + a = util_spec 'a', '1.0', 'b' => '>= 1.0' + util_spec 'b', '1.0' + c = util_spec 'c', '1.0' + + assert_activate %w[b-1.0 c-1.0 a-1.0], a, c, "b" + end + + ## + # [A] depends on + # [B] >= 1.0 (satisfied by 2.0) + # [C] = 1.0 depends on + # [B] ~> 1.0 + # + # and should resolve using b-1.0 + + def test_self_activate_over + a, _ = util_spec 'a', '1.0', 'b' => '>= 1.0', 'c' => '= 1.0' + util_spec 'b', '1.0' + util_spec 'b', '1.1' + util_spec 'b', '2.0' + c, _ = util_spec 'c', '1.0', 'b' => '~> 1.0' + + Gem.activate "a" + + assert_equal %w[a-1.0 c-1.0], loaded_spec_names + assert_equal ["b (>= 1.0, ~> 1.0)"], unresolved_names + end + + ## + # [A] depends on + # [B] ~> 1.0 (satisfied by 1.1) + # [C] = 1.0 depends on + # [B] = 1.0 + # + # and should resolve using b-1.0 + # + # TODO: this is not under, but over... under would require depth + # first resolve through a dependency that is later pruned. + + def test_self_activate_under + a, _ = util_spec 'a', '1.0', 'b' => '~> 1.0', 'c' => '= 1.0' + util_spec 'b', '1.0' + util_spec 'b', '1.1' + c, _ = util_spec 'c', '1.0', 'b' => '= 1.0' + + assert_activate %w[b-1.0 c-1.0 a-1.0], a, c, "b" + end + + ## + # [A1] depends on + # [B] > 0 (satisfied by 2.0) + # [B1] depends on + # [C] > 0 (satisfied by 1.0) + # [B2] depends on nothing! + # [C1] depends on nothing + + def test_self_activate_dropped + a1, = util_spec 'a', '1', 'b' => nil + util_spec 'b', '1', 'c' => nil + util_spec 'b', '2' + util_spec 'c', '1' + + assert_activate %w[b-2 a-1], a1, "b" + end + + ## + # [A] depends on + # [B] >= 1.0 (satisfied by 1.1) depends on + # [Z] + # [C] >= 1.0 depends on + # [B] = 1.0 + # + # and should backtrack to resolve using b-1.0, pruning Z from the + # resolve. + + def test_self_activate_raggi_the_edgecase_generator + a, _ = util_spec 'a', '1.0', 'b' => '>= 1.0', 'c' => '>= 1.0' + util_spec 'b', '1.0' + util_spec 'b', '1.1', 'z' => '>= 1.0' + c, _ = util_spec 'c', '1.0', 'b' => '= 1.0' + + assert_activate %w[b-1.0 c-1.0 a-1.0], a, c, "b" + end + + def test_self_activate_conflict + util_spec 'b', '1.0' + util_spec 'b', '2.0' + + gem "b", "= 1.0" + + assert_raises Gem::LoadError do + gem "b", "= 2.0" + end + end + + ## + # [A] depends on + # [B] ~> 1.0 (satisfied by 1.0) + # [C] = 1.0 depends on + # [B] = 2.0 + + def test_self_activate_divergent + a, _ = util_spec 'a', '1.0', 'b' => '~> 1.0', 'c' => '= 1.0' + util_spec 'b', '1.0' + util_spec 'b', '2.0' + c, _ = util_spec 'c', '1.0', 'b' => '= 2.0' + + e = assert_raises Gem::LoadError do + assert_activate nil, a, c, "b" + end + + assert_match(/Unable to activate c-1.0,/, e.message) + assert_match(/because b-1.0 conflicts with b .= 2.0/, e.message) + end + + ## + # DOC + + def test_self_activate_platform_alternate + @x1_m = util_spec 'x', '1' do |s| + s.platform = Gem::Platform.new %w[cpu my_platform 1] + end + + @x1_o = util_spec 'x', '1' do |s| + s.platform = Gem::Platform.new %w[cpu other_platform 1] + end + + @w1 = util_spec 'w', '1', 'x' => nil + + util_set_arch 'cpu-my_platform1' + + assert_activate %w[x-1-cpu-my_platform-1 w-1], @w1, @x1_m + end + + ## + # DOC + + def test_self_activate_platform_bump + @y1 = util_spec 'y', '1' + + @y1_1_p = util_spec 'y', '1.1' do |s| + s.platform = Gem::Platform.new %w[cpu my_platform 1] + end + + @z1 = util_spec 'z', '1', 'y' => nil + + assert_activate %w[y-1 z-1], @z1, @y1 + end + + ## + # [C] depends on + # [A] = 1.a + # [B] = 1.0 depends on + # [A] >= 0 (satisfied by 1.a) + + def test_self_activate_prerelease + @c1_pre = util_spec 'c', '1.a', "a" => "1.a", "b" => "1" + @a1_pre = util_spec 'a', '1.a' + @b1 = util_spec 'b', '1' do |s| + s.add_dependency 'a' + s.add_development_dependency 'aa' + end + + assert_activate %w[a-1.a b-1 c-1.a], @c1_pre, @a1_pre, @b1 + end + + ## + # DOC + + def test_self_activate_old_required + e1, = util_spec 'e', '1', 'd' => '= 1' + @d1 = util_spec 'd', '1' + @d2 = util_spec 'd', '2' + + assert_activate %w[d-1 e-1], e1, "d" + end + def test_self_all_load_paths util_make_gems @@ -71,7 +417,7 @@ class TestGem < Gem::TestCase end def test_self_bin_path_nonexistent_binfile - quick_gem 'a', '2' do |s| + quick_spec 'a', '2' do |s| s.executables = ['exec'] end assert_raises(Gem::GemNotFoundException) do @@ -80,7 +426,7 @@ class TestGem < Gem::TestCase end def test_self_bin_path_no_bin_file - quick_gem 'a', '1' + quick_spec 'a', '1' assert_raises(Gem::Exception) do Gem.bin_path('a', nil, '1') end @@ -94,7 +440,7 @@ class TestGem < Gem::TestCase def test_self_bin_path_bin_file_gone_in_latest util_exec_gem - quick_gem 'a', '10' do |s| + quick_spec 'a', '10' do |s| s.executables = [] s.default_executable = nil end @@ -150,7 +496,7 @@ class TestGem < Gem::TestCase fp.puts 'blah' end - foo = quick_gem 'foo' do |s| s.files = %w[data/foo.txt] end + foo = quick_spec 'foo' do |s| s.files = %w[data/foo.txt] end install_gem foo end @@ -212,7 +558,7 @@ class TestGem < Gem::TestCase Gem.ensure_gem_subdirectories @gemhome - assert File.directory?(File.join(@gemhome, "cache")) + assert File.directory?(Gem.cache_dir(@gemhome)) end def test_self_ensure_gem_directories_missing_parents @@ -224,7 +570,7 @@ class TestGem < Gem::TestCase Gem.ensure_gem_subdirectories gemdir - assert File.directory?("#{gemdir}/cache") + assert File.directory?(Gem.cache_dir(gemdir)) end unless win_platform? then # only for FS that support write protection @@ -238,7 +584,7 @@ class TestGem < Gem::TestCase Gem.ensure_gem_subdirectories gemdir - refute File.exist?("#{gemdir}/cache") + refute File.exist?(Gem.cache_dir(gemdir)) ensure FileUtils.chmod 0600, gemdir end @@ -255,7 +601,7 @@ class TestGem < Gem::TestCase Gem.ensure_gem_subdirectories gemdir - refute File.exist?("#{gemdir}/cache") + refute File.exist?(Gem.cache_dir(gemdir)) ensure FileUtils.chmod 0600, parent end @@ -276,8 +622,8 @@ class TestGem < Gem::TestCase def test_self_find_files discover_path = File.join 'lib', 'sff', 'discover.rb' - cwd = File.expand_path '..', __FILE__ - $LOAD_PATH.unshift cwd.dup + cwd = File.expand_path("test/rubygems", @@project_dir) + $LOAD_PATH.unshift cwd foo1 = quick_gem 'sff', '1' do |s| s.files << discover_path @@ -301,7 +647,7 @@ class TestGem < Gem::TestCase Gem.searcher = nil expected = [ - File.expand_path('../sff/discover.rb', __FILE__), + File.expand_path('test/rubygems/sff/discover.rb', @@project_dir), File.join(foo2.full_gem_path, discover_path), File.join(foo1.full_gem_path, discover_path), ] @@ -327,7 +673,7 @@ class TestGem < Gem::TestCase end def test_self_loaded_specs - foo = quick_gem 'foo' + foo = quick_spec 'foo' install_gem foo Gem.source_index = nil @@ -430,22 +776,12 @@ class TestGem < Gem::TestCase end def test_self_prefix - file_name = File.expand_path __FILE__ - - prefix = File.dirname File.dirname(file_name) - prefix = File.dirname prefix if File.basename(prefix) == 'test' - - assert_equal prefix, Gem.prefix + assert_equal @@project_dir, Gem.prefix end def test_self_prefix_libdir orig_libdir = Gem::ConfigMap[:libdir] - - file_name = File.expand_path __FILE__ - prefix = File.dirname File.dirname(file_name) - prefix = File.dirname prefix if File.basename(prefix) == 'test' - - Gem::ConfigMap[:libdir] = prefix + Gem::ConfigMap[:libdir] = @@project_dir assert_nil Gem.prefix ensure @@ -454,12 +790,7 @@ class TestGem < Gem::TestCase def test_self_prefix_sitelibdir orig_sitelibdir = Gem::ConfigMap[:sitelibdir] - - file_name = File.expand_path __FILE__ - prefix = File.dirname File.dirname(file_name) - prefix = File.dirname prefix if File.basename(prefix) == 'test' - - Gem::ConfigMap[:sitelibdir] = prefix + Gem::ConfigMap[:sitelibdir] = @@project_dir assert_nil Gem.prefix ensure @@ -623,6 +954,20 @@ class TestGem < Gem::TestCase end end + def test_self_cache_dir + util_ensure_gem_dirs + + assert_equal File.join(@gemhome, 'cache'), Gem.cache_dir + assert_equal File.join(@userhome, '.gem', Gem.ruby_engine, Gem::ConfigMap[:ruby_version], 'cache'), Gem.cache_dir(Gem.user_dir) + end + + def test_self_cache_gem + util_ensure_gem_dirs + + assert_equal File.join(@gemhome, 'cache', 'test.gem'), Gem.cache_gem('test.gem') + assert_equal File.join(@userhome, '.gem', Gem.ruby_engine, Gem::ConfigMap[:ruby_version], 'cache', 'test.gem'), Gem.cache_gem('test.gem', Gem.user_dir) + end + if Gem.win_platform? then def test_self_user_home_userprofile skip 'Ruby 1.9 properly handles ~ path expansion' unless '1.9' > RUBY_VERSION @@ -674,10 +1019,10 @@ class TestGem < Gem::TestCase Dir.chdir @tempdir do FileUtils.mkdir_p 'lib' File.open plugin_path, "w" do |fp| - fp.puts "TestGem::TEST_SPEC_PLUGIN_LOAD = :loaded" + fp.puts "class TestGem; TEST_SPEC_PLUGIN_LOAD = :loaded; end" end - foo = quick_gem 'foo', '1' do |s| + foo = quick_spec 'foo', '1' do |s| s.files << plugin_path end @@ -685,6 +1030,7 @@ class TestGem < Gem::TestCase end Gem.source_index = nil + Gem.searcher = nil gem 'foo' @@ -695,23 +1041,24 @@ class TestGem < Gem::TestCase def test_load_env_plugins with_plugin('load') { Gem.load_env_plugins } - assert_equal :loaded, TEST_PLUGIN_LOAD + assert_equal :loaded, TEST_PLUGIN_LOAD rescue nil util_remove_interrupt_command # Should attempt to cause a StandardError with_plugin('standarderror') { Gem.load_env_plugins } - assert_equal :loaded, TEST_PLUGIN_STANDARDERROR + assert_equal :loaded, TEST_PLUGIN_STANDARDERROR rescue nil util_remove_interrupt_command # Should attempt to cause an Exception with_plugin('exception') { Gem.load_env_plugins } - assert_equal :loaded, TEST_PLUGIN_EXCEPTION + assert_equal :loaded, TEST_PLUGIN_EXCEPTION rescue nil end def with_plugin(path) - test_plugin_path = File.expand_path "../plugin/#{path}", __FILE__ + test_plugin_path = File.expand_path("test/rubygems/plugin/#{path}", + @@project_dir) # A single test plugin should get loaded once only, in order to preserve # sane test semantics. @@ -733,7 +1080,7 @@ class TestGem < Gem::TestCase end def util_exec_gem - spec, _ = quick_gem 'a', '4' do |s| + spec, _ = quick_spec 'a', '4' do |s| s.default_executable = 'exec' s.executables = ['exec', 'abin'] end @@ -777,6 +1124,5 @@ class TestGem < Gem::TestCase Gem::Commands.send :remove_const, :InterruptCommand if Gem::Commands.const_defined? :InterruptCommand end - end diff --git a/test/rubygems/test_gem_builder.rb b/test/rubygems/test_gem_builder.rb index d146c843bb..f95472f626 100644 --- a/test/rubygems/test_gem_builder.rb +++ b/test/rubygems/test_gem_builder.rb @@ -10,7 +10,7 @@ require 'rubygems/builder' class TestGemBuilder < Gem::TestCase def test_build - builder = Gem::Builder.new quick_gem('a') + builder = Gem::Builder.new quick_spec('a') use_ui @ui do Dir.chdir @tempdir do diff --git a/test/rubygems/test_gem_command_manager.rb b/test/rubygems/test_gem_command_manager.rb index daadf2520e..3769c250d5 100644 --- a/test/rubygems/test_gem_command_manager.rb +++ b/test/rubygems/test_gem_command_manager.rb @@ -17,7 +17,7 @@ class TestGemCommandManager < Gem::TestCase def test_run_interrupt old_load_path = $:.dup - $: << "test/rubygems" + $: << File.expand_path("test/rubygems", @@project_dir) Gem.load_env_plugins use_ui @ui do @@ -33,7 +33,7 @@ class TestGemCommandManager < Gem::TestCase def test_run_crash_command old_load_path = $:.dup - $: << "test/rubygems" + $: << File.expand_path("test/rubygems", @@project_dir) @command_manager.register_command :crash use_ui @ui do diff --git a/test/rubygems/test_gem_commands_build_command.rb b/test/rubygems/test_gem_commands_build_command.rb index 5c9c5eeb6e..5c38a1a5e8 100644 --- a/test/rubygems/test_gem_commands_build_command.rb +++ b/test/rubygems/test_gem_commands_build_command.rb @@ -13,7 +13,7 @@ class TestGemCommandsBuildCommand < Gem::TestCase def setup super - @gem = quick_gem 'some_gem' do |s| + @gem = quick_spec 'some_gem' do |s| s.rubyforge_project = 'example' end diff --git a/test/rubygems/test_gem_commands_cert_command.rb b/test/rubygems/test_gem_commands_cert_command.rb index 9d5fc1eada..a514ea41f2 100644 --- a/test/rubygems/test_gem_commands_cert_command.rb +++ b/test/rubygems/test_gem_commands_cert_command.rb @@ -6,6 +6,7 @@ require 'rubygems/test_case' require 'rubygems/commands/cert_command' +require 'rubygems/fix_openssl_warnings' if RUBY_VERSION < "1.9" unless defined? OpenSSL then warn "`gem cert` tests are being skipped, module OpenSSL not found" @@ -21,7 +22,7 @@ class TestGemCommandsCertCommand < Gem::TestCase @cmd = Gem::Commands::CertCommand.new - root = File.expand_path(File.dirname(__FILE__)) + root = File.expand_path(File.dirname(__FILE__), @@project_dir) FileUtils.cp File.join(root, 'data', 'gem-private_key.pem'), @tempdir FileUtils.cp File.join(root, 'data', 'gem-public_cert.pem'), @tempdir diff --git a/test/rubygems/test_gem_commands_dependency_command.rb b/test/rubygems/test_gem_commands_dependency_command.rb index 40d96f729a..665cd98c4d 100644 --- a/test/rubygems/test_gem_commands_dependency_command.rb +++ b/test/rubygems/test_gem_commands_dependency_command.rb @@ -32,7 +32,7 @@ class TestGemCommandsDependencyCommand < Gem::TestCase @cmd.execute end - assert_equal "Gem foo-2\n bar (> 1, runtime)\n baz (> 1, runtime)\n\n", + assert_equal "Gem foo-2\n bar (> 1)\n baz (> 1)\n\n", @ui.output assert_equal '', @ui.error end @@ -83,7 +83,7 @@ Gem pl-1-x86-linux end def test_execute_pipe_format - quick_gem 'foo' do |gem| + quick_spec 'foo' do |gem| gem.add_dependency 'bar', '> 1' end @@ -127,6 +127,7 @@ Gem b-2 end def test_execute_reverse + # FIX: this shouldn't need to write out, but fails if you switch it quick_gem 'foo' do |gem| gem.add_dependency 'bar', '> 1' end @@ -146,9 +147,9 @@ Gem b-2 expected = <<-EOF Gem foo-2 - bar (> 1, runtime) + bar (> 1) Used by - baz-2 (foo (>= 0, runtime)) + baz-2 (foo (>= 0)) EOF @@ -194,7 +195,7 @@ ERROR: Only reverse dependencies for local gems are supported. @cmd.execute end - assert_equal "Gem foo-2\n bar (> 1, runtime)\n\n", @ui.output + assert_equal "Gem foo-2\n bar (> 1)\n\n", @ui.output assert_equal '', @ui.error end diff --git a/test/rubygems/test_gem_commands_fetch_command.rb b/test/rubygems/test_gem_commands_fetch_command.rb index 657e8e9f80..173a33572f 100644 --- a/test/rubygems/test_gem_commands_fetch_command.rb +++ b/test/rubygems/test_gem_commands_fetch_command.rb @@ -22,7 +22,7 @@ class TestGemCommandsFetchCommand < Gem::TestCase util_setup_spec_fetcher @a2 @fetcher.data["#{@gem_repo}gems/#{@a2.file_name}"] = - File.read(File.join(@gemhome, 'cache', @a2.file_name)) + File.read(Gem.cache_gem(@a2.file_name, @gemhome)) @cmd.options[:args] = [@a2.name] @@ -41,9 +41,9 @@ class TestGemCommandsFetchCommand < Gem::TestCase util_setup_spec_fetcher @a2, @a2_pre @fetcher.data["#{@gem_repo}gems/#{@a2.file_name}"] = - File.read(File.join(@gemhome, 'cache', @a2.file_name)) + File.read(Gem.cache_gem(@a2.file_name, @gemhome)) @fetcher.data["#{@gem_repo}gems/#{@a2_pre.file_name}"] = - File.read(File.join(@gemhome, 'cache', @a2_pre.file_name)) + File.read(Gem.cache_gem(@a2_pre.file_name, @gemhome)) @cmd.options[:args] = [@a2.name] @cmd.options[:prerelease] = true @@ -63,7 +63,7 @@ class TestGemCommandsFetchCommand < Gem::TestCase util_setup_spec_fetcher @a1, @a2 @fetcher.data["#{@gem_repo}gems/#{@a1.file_name}"] = - File.read(File.join(@gemhome, 'cache', @a1.file_name)) + File.read(Gem.cache_gem(@a1.file_name, @gemhome)) @cmd.options[:args] = [@a2.name] @cmd.options[:version] = Gem::Requirement.new '1' diff --git a/test/rubygems/test_gem_commands_install_command.rb b/test/rubygems/test_gem_commands_install_command.rb index a3ceb81ab7..adc66aa911 100644 --- a/test/rubygems/test_gem_commands_install_command.rb +++ b/test/rubygems/test_gem_commands_install_command.rb @@ -7,6 +7,12 @@ require 'rubygems/test_case' require 'rubygems/commands/install_command' +begin + gem "rdoc" +rescue Gem::LoadError + # ignore +end + class TestGemCommandsInstallCommand < Gem::TestCase def setup @@ -22,9 +28,9 @@ class TestGemCommandsInstallCommand < Gem::TestCase util_setup_spec_fetcher @a2, @a2_pre @fetcher.data["#{@gem_repo}gems/#{@a2.file_name}"] = - read_binary(File.join(@gemhome, 'cache', @a2.file_name)) + read_binary(Gem.cache_gem(@a2.file_name, @gemhome)) @fetcher.data["#{@gem_repo}gems/#{@a2_pre.file_name}"] = - read_binary(File.join(@gemhome, 'cache', @a2_pre.file_name)) + read_binary(Gem.cache_gem(@a2_pre.file_name, @gemhome)) @cmd.options[:args] = [@a2.name] @@ -44,11 +50,12 @@ class TestGemCommandsInstallCommand < Gem::TestCase util_setup_spec_fetcher @a2, @a2_pre @fetcher.data["#{@gem_repo}gems/#{@a2.file_name}"] = - read_binary(File.join(@gemhome, 'cache', @a2.file_name)) + read_binary(Gem.cache_gem(@a2.file_name, @gemhome)) @fetcher.data["#{@gem_repo}gems/#{@a2_pre.file_name}"] = - read_binary(File.join(@gemhome, 'cache', @a2_pre.file_name)) + read_binary(Gem.cache_gem(@a2_pre.file_name, @gemhome)) - @cmd.handle_options [@a2_pre.name, '--version', @a2_pre.version.to_s] + @cmd.handle_options [@a2_pre.name, '--version', @a2_pre.version.to_s, + "--no-ri", "--no-rdoc"] assert @cmd.options[:prerelease] assert @cmd.options[:version].satisfied_by?(@a2_pre.version) @@ -85,8 +92,7 @@ class TestGemCommandsInstallCommand < Gem::TestCase util_setup_fake_fetcher @cmd.options[:domain] = :local - FileUtils.mv File.join(@gemhome, 'cache', @a2.file_name), - File.join(@tempdir) + FileUtils.mv Gem.cache_gem(@a2.file_name, @gemhome), @tempdir @cmd.options[:args] = [@a2.name] @@ -115,8 +121,7 @@ class TestGemCommandsInstallCommand < Gem::TestCase util_setup_fake_fetcher @cmd.options[:user_install] = false - FileUtils.mv File.join(@gemhome, 'cache', @a2.file_name), - File.join(@tempdir) + FileUtils.mv Gem.cache_gem(@a2.file_name, @gemhome), @tempdir @cmd.options[:args] = [@a2.name] @@ -183,7 +188,7 @@ class TestGemCommandsInstallCommand < Gem::TestCase correctly_spelled = "non_existent_with_hint" util_setup_fake_fetcher - util_setup_spec_fetcher quick_gem(correctly_spelled, '2') + util_setup_spec_fetcher quick_spec(correctly_spelled, '2') @cmd.options[:args] = [misspelled] @@ -207,9 +212,9 @@ ERROR: Possible alternatives: non_existent_with_hint util_setup_spec_fetcher @a2, @a2_pre @fetcher.data["#{@gem_repo}gems/#{@a2.file_name}"] = - read_binary(File.join(@gemhome, 'cache', @a2.file_name)) + read_binary(Gem.cache_gem(@a2.file_name, @gemhome)) @fetcher.data["#{@gem_repo}gems/#{@a2_pre.file_name}"] = - read_binary(File.join(@gemhome, 'cache', @a2_pre.file_name)) + read_binary(Gem.cache_gem(@a2_pre.file_name, @gemhome)) @cmd.options[:prerelease] = true @cmd.options[:args] = [@a2_pre.name] @@ -233,7 +238,7 @@ ERROR: Possible alternatives: non_existent_with_hint util_setup_spec_fetcher @a2 @fetcher.data["#{@gem_repo}gems/#{@a2.file_name}"] = - read_binary(File.join(@gemhome, 'cache', @a2.file_name)) + read_binary(Gem.cache_gem(@a2.file_name, @gemhome)) @cmd.options[:args] = [@a2.name] @@ -260,11 +265,9 @@ ERROR: Possible alternatives: non_existent_with_hint util_setup_fake_fetcher @cmd.options[:domain] = :local - FileUtils.mv File.join(@gemhome, 'cache', @a2.file_name), - File.join(@tempdir) + FileUtils.mv Gem.cache_gem(@a2.file_name, @gemhome), @tempdir - FileUtils.mv File.join(@gemhome, 'cache', @b2.file_name), - File.join(@tempdir) + FileUtils.mv Gem.cache_gem(@b2.file_name, @gemhome), @tempdir @cmd.options[:args] = [@a2.name, @b2.name] @@ -293,7 +296,7 @@ ERROR: Possible alternatives: non_existent_with_hint util_setup_spec_fetcher @b2 @fetcher.data["#{@gem_repo}gems/#{@b2.file_name}"] = - read_binary(File.join(@gemhome, 'cache', @b2.file_name)) + read_binary(Gem.cache_gem(@b2.file_name, @gemhome)) uninstall_gem(@b2) diff --git a/test/rubygems/test_gem_commands_lock_command.rb b/test/rubygems/test_gem_commands_lock_command.rb index 25b033af5d..bb3134661d 100644 --- a/test/rubygems/test_gem_commands_lock_command.rb +++ b/test/rubygems/test_gem_commands_lock_command.rb @@ -51,7 +51,7 @@ gem 'a', '= 1' expected = <<-EXPECTED require 'rubygems' gem 'd', '= 1' -# Unable to satisfy 'z (>= 0, runtime)' from currently installed gems +# Unable to satisfy 'z (>= 0)' from currently installed gems EXPECTED assert_equal expected, @ui.output diff --git a/test/rubygems/test_gem_commands_outdated_command.rb b/test/rubygems/test_gem_commands_outdated_command.rb index 6f99f33e99..632e9a5548 100644 --- a/test/rubygems/test_gem_commands_outdated_command.rb +++ b/test/rubygems/test_gem_commands_outdated_command.rb @@ -22,14 +22,11 @@ class TestGemCommandsOutdatedCommand < Gem::TestCase def test_execute quick_gem 'foo', '0.1' quick_gem 'foo', '0.2' - remote_10 = quick_gem 'foo', '1.0' - remote_20 = quick_gem 'foo', '2.0' + remote_10 = quick_spec 'foo', '1.0' + remote_20 = quick_spec 'foo', '2.0' remote_spec_file = File.join @gemhome, 'specifications', remote_10.spec_name - FileUtils.rm remote_spec_file - remote_spec_file = File.join @gemhome, 'specifications', remote_20.spec_name - FileUtils.rm remote_spec_file @fetcher = Gem::FakeFetcher.new Gem::RemoteFetcher.fetcher = @fetcher diff --git a/test/rubygems/test_gem_commands_owner_command.rb b/test/rubygems/test_gem_commands_owner_command.rb index 38e49ea79d..a07c3095aa 100644 --- a/test/rubygems/test_gem_commands_owner_command.rb +++ b/test/rubygems/test_gem_commands_owner_command.rb @@ -53,6 +53,20 @@ EOF assert_match response, @ui.output end + def test_show_owners_key + response = "- email: user1@example.com\n" + @fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, 'OK'] + File.open Gem.configuration.credentials_path, 'a' do |f| + f.write ':other: 701229f217cdf23b1344c7b4b54ca97' + end + Gem.configuration.load_api_keys + + @cmd.handle_options %w(-k other) + @cmd.show_owners('freewill') + + assert_equal '701229f217cdf23b1344c7b4b54ca97', @fetcher.last_request['Authorization'] + end + def test_add_owners response = "Owner added successfully." @fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 200, 'OK'] @@ -81,6 +95,20 @@ EOF assert_match response, @ui.output end + def test_add_owners_key + response = "Owner added successfully." + @fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 200, 'OK'] + File.open Gem.configuration.credentials_path, 'a' do |f| + f.write ':other: 701229f217cdf23b1344c7b4b54ca97' + end + Gem.configuration.load_api_keys + + @cmd.handle_options %w(-k other) + @cmd.add_owners('freewill', ['user-new1@example.com']) + + assert_equal '701229f217cdf23b1344c7b4b54ca97', @fetcher.last_request['Authorization'] + end + def test_remove_owners response = "Owner removed successfully." @fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 200, 'OK'] @@ -108,4 +136,18 @@ EOF assert_match response, @ui.output end + + def test_remove_owners_key + response = "Owner removed successfully." + @fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 200, 'OK'] + File.open Gem.configuration.credentials_path, 'a' do |f| + f.write ':other: 701229f217cdf23b1344c7b4b54ca97' + end + Gem.configuration.load_api_keys + + @cmd.handle_options %w(-k other) + @cmd.remove_owners('freewill', ['user-remove1@example.com']) + + assert_equal '701229f217cdf23b1344c7b4b54ca97', @fetcher.last_request['Authorization'] + end end diff --git a/test/rubygems/test_gem_commands_pristine_command.rb b/test/rubygems/test_gem_commands_pristine_command.rb index 9cab574a1f..4decdf81b9 100644 --- a/test/rubygems/test_gem_commands_pristine_command.rb +++ b/test/rubygems/test_gem_commands_pristine_command.rb @@ -15,7 +15,7 @@ class TestGemCommandsPristineCommand < Gem::TestCase end def test_execute - a = quick_gem 'a' do |s| s.executables = %w[foo] end + a = quick_spec 'a' do |s| s.executables = %w[foo] end FileUtils.mkdir_p File.join(@tempdir, 'bin') File.open File.join(@tempdir, 'bin', 'foo'), 'w' do |fp| fp.puts "#!/usr/bin/ruby" @@ -45,7 +45,7 @@ class TestGemCommandsPristineCommand < Gem::TestCase end def test_execute_all - a = quick_gem 'a' do |s| s.executables = %w[foo] end + a = quick_spec 'a' do |s| s.executables = %w[foo] end FileUtils.mkdir_p File.join(@tempdir, 'bin') File.open File.join(@tempdir, 'bin', 'foo'), 'w' do |fp| fp.puts "#!/usr/bin/ruby" @@ -73,15 +73,29 @@ class TestGemCommandsPristineCommand < Gem::TestCase end def test_execute_missing_cache_gem - a = quick_gem 'a' do |s| s.executables = %w[foo] end + a = quick_spec 'a' do |s| + s.executables = %w[foo] + end + FileUtils.mkdir_p File.join(@tempdir, 'bin') + File.open File.join(@tempdir, 'bin', 'foo'), 'w' do |fp| fp.puts "#!/usr/bin/ruby" end install_gem a - FileUtils.rm File.join(@gemhome, 'cache', a.file_name) + a_data = nil + open File.join(@gemhome, 'cache', a.file_name), 'rb' do |fp| + a_data = fp.read + end + + util_setup_fake_fetcher + util_setup_spec_fetcher a + + Gem::RemoteFetcher.fetcher.data["http://gems.example.com/gems/#{a.file_name}"] = a_data + + FileUtils.rm Gem.cache_gem(a.file_name, @gemhome) @cmd.options[:args] = %w[a] @@ -91,11 +105,17 @@ class TestGemCommandsPristineCommand < Gem::TestCase out = @ui.output.split "\n" - assert_equal "Restoring gem\(s\) to pristine condition...", out.shift - assert_empty out, out.inspect + [ + "Restoring gem\(s\) to pristine condition...", + "Restored a-1", + "Cached gem for a-2 not found, attempting to fetch...", + "Restored a-2", + "Restored a-3.a" + ].each do |line| + assert_equal line, out.shift + end - assert_equal "ERROR: Cached gem for #{a.full_name} not found, use `gem install` to restore\n", - @ui.error + assert_empty out, out.inspect end def test_execute_no_gem diff --git a/test/rubygems/test_gem_commands_push_command.rb b/test/rubygems/test_gem_commands_push_command.rb index b95af2380b..917407dc32 100644 --- a/test/rubygems/test_gem_commands_push_command.rb +++ b/test/rubygems/test_gem_commands_push_command.rb @@ -7,16 +7,28 @@ require 'rubygems/test_case' require 'rubygems/commands/push_command' +module Gem + class << self; remove_method :latest_rubygems_version; end + + def self.latest_rubygems_version + Gem::Version.new Gem::VERSION + end +end + class TestGemCommandsPushCommand < Gem::TestCase def setup super - @gems_dir = File.join @tempdir, 'gems' - @cache_dir = File.join @gemhome, 'cache' + @gems_dir = File.join @tempdir, 'gems' + @cache_dir = Gem.cache_dir @gemhome + FileUtils.mkdir @gems_dir - Gem.configuration.rubygems_api_key = "ed244fbf2b1a52e012da8616c512fa47f9aa5250" - @spec, @path = util_gem("freewill", "1.0.0") + + Gem.configuration.rubygems_api_key = + "ed244fbf2b1a52e012da8616c512fa47f9aa5250" + + @spec, @path = util_gem "freewill", "1.0.0" @fetcher = Gem::FakeFetcher.new Gem::RemoteFetcher.fetcher = @fetcher @@ -83,5 +95,19 @@ class TestGemCommandsPushCommand < Gem::TestCase assert_match response, @ui.output end -end + def test_sending_gem_key + @response = "Successfully registered gem: freewill (1.0.0)" + @fetcher.data["#{Gem.host}/api/v1/gems"] = [@response, 200, "OK"] + File.open Gem.configuration.credentials_path, 'a' do |f| + f.write ':other: 701229f217cdf23b1344c7b4b54ca97' + end + Gem.configuration.load_api_keys + + @cmd.handle_options %w(-k other) + @cmd.send_gem(@path) + assert_equal Gem.configuration.api_keys[:other], + @fetcher.last_request["Authorization"] + end + +end diff --git a/test/rubygems/test_gem_commands_specification_command.rb b/test/rubygems/test_gem_commands_specification_command.rb index ca210059fd..767992f240 100644 --- a/test/rubygems/test_gem_commands_specification_command.rb +++ b/test/rubygems/test_gem_commands_specification_command.rb @@ -16,7 +16,7 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase end def test_execute - foo = quick_gem 'foo' + foo = quick_spec 'foo' Gem.source_index.add_spec foo @cmd.options[:args] = %w[foo] @@ -31,8 +31,8 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase end def test_execute_all - quick_gem 'foo', '0.0.1' - quick_gem 'foo', '0.0.2' + quick_spec 'foo', '0.0.1' + quick_spec 'foo', '0.0.2' @cmd.options[:args] = %w[foo] @cmd.options[:all] = true @@ -62,8 +62,8 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase end def test_execute_exact_match - quick_gem 'foo' - quick_gem 'foo_bar' + quick_spec 'foo' + quick_spec 'foo_bar' @cmd.options[:args] = %w[foo] @@ -77,7 +77,7 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase end def test_execute_field - foo = quick_gem 'foo' + foo = quick_spec 'foo' Gem.source_index.add_spec foo @cmd.options[:args] = %w[foo name] @@ -90,7 +90,7 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase end def test_execute_marshal - foo = quick_gem 'foo' + foo = quick_spec 'foo' Gem.source_index.add_spec foo @cmd.options[:args] = %w[foo] @@ -126,7 +126,7 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase end def test_execute_ruby - foo = quick_gem 'foo' + foo = quick_spec 'foo' Gem.source_index.add_spec foo @cmd.options[:args] = %w[foo] diff --git a/test/rubygems/test_gem_commands_stale_command.rb b/test/rubygems/test_gem_commands_stale_command.rb index f3876d90db..d5aad6ce0c 100644 --- a/test/rubygems/test_gem_commands_stale_command.rb +++ b/test/rubygems/test_gem_commands_stale_command.rb @@ -16,10 +16,11 @@ class TestGemCommandsStaleCommand < Gem::TestCase def test_execute_sorts files = %w[lib/foo_bar.rb Rakefile] - foo_bar = quick_gem 'foo_bar' do |gem| + foo_bar = quick_spec 'foo_bar' do |gem| gem.files = files end - bar_baz = quick_gem 'bar_baz' do |gem| + + bar_baz = quick_spec 'bar_baz' do |gem| gem.files = files end @@ -36,6 +37,7 @@ class TestGemCommandsStaleCommand < Gem::TestCase use_ui @ui do @cmd.execute end + lines = @ui.output.split("\n") assert_equal("#{foo_bar.name}-#{foo_bar.version}", lines[0].split.first) assert_equal("#{bar_baz.name}-#{bar_baz.version}", lines[1].split.first) diff --git a/test/rubygems/test_gem_commands_uninstall_command.rb b/test/rubygems/test_gem_commands_uninstall_command.rb index c5be3beb90..47f4960145 100644 --- a/test/rubygems/test_gem_commands_uninstall_command.rb +++ b/test/rubygems/test_gem_commands_uninstall_command.rb @@ -33,7 +33,7 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase end end - if win_platform? + if win_platform? then assert File.exist?(@executable) else assert File.symlink?(@executable) @@ -42,9 +42,9 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase # Evil hack to prevent false removal success FileUtils.rm_f @executable - open(@executable, "wb+") {|f| f.puts "binary"} + open @executable, "wb+" do |f| f.puts "binary" end - @cmd.options[:args] = Array(@spec.name) + @cmd.options[:args] = [@spec.name] use_ui @ui do @cmd.execute end @@ -56,6 +56,25 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase assert_nil output.shift, "UI output should have contained only two lines" end + def test_execute_removes_formatted_executable + FileUtils.rm_f @executable # Wish this didn't happen in #setup + + Gem::Installer.exec_format = 'foo-%s-bar' + + @installer.format_executable = true + @installer.install + + formatted_executable = File.join @gemhome, 'bin', 'foo-executable-bar' + assert_equal true, File.exist?(formatted_executable) + + @cmd.options[:format_executable] = true + @cmd.execute + + assert_equal false, File.exist?(formatted_executable) + rescue + Gem::Installer.exec_format = nil + end + def test_execute_not_installed @cmd.options[:args] = ["foo"] e = assert_raises Gem::InstallError do @@ -70,7 +89,7 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase end def test_execute_prerelease - @spec = quick_gem "pre", "2.b" + @spec = quick_spec "pre", "2.b" @gem = File.join @tempdir, @spec.file_name FileUtils.touch @gem diff --git a/test/rubygems/test_gem_commands_unpack_command.rb b/test/rubygems/test_gem_commands_unpack_command.rb index 0fb4ef3843..8291a6b949 100644 --- a/test/rubygems/test_gem_commands_unpack_command.rb +++ b/test/rubygems/test_gem_commands_unpack_command.rb @@ -22,7 +22,7 @@ class TestGemCommandsUnpackCommand < Gem::TestCase assert_equal( @cmd.find_in_cache(@a1.file_name), - File.join(@gemhome, 'cache', @a1.file_name), + Gem.cache_gem(@a1.file_name, @gemhome), 'found a-1.gem in the cache' ) end @@ -34,7 +34,7 @@ class TestGemCommandsUnpackCommand < Gem::TestCase a1_data = nil - open File.join(@gemhome, 'cache', @a1.file_name), 'rb' do |fp| + open Gem.cache_gem(@a1.file_name, @gemhome), 'rb' do |fp| a1_data = fp.read end @@ -44,15 +44,15 @@ class TestGemCommandsUnpackCommand < Gem::TestCase dep = Gem::Dependency.new(@a1.name, @a1.version) assert_equal( @cmd.get_path(dep), - File.join(@gemhome, 'cache', @a1.file_name), + Gem.cache_gem(@a1.file_name, @gemhome), 'fetches a-1 and returns the cache path' ) - FileUtils.rm File.join(@gemhome, 'cache', @a1.file_name) + FileUtils.rm Gem.cache_gem(@a1.file_name, @gemhome) assert_equal( @cmd.get_path(dep), - File.join(@gemhome, 'cache', @a1.file_name), + Gem.cache_gem(@a1.file_name, @gemhome), 'when removed from cache, refetches a-1' ) end @@ -74,6 +74,8 @@ class TestGemCommandsUnpackCommand < Gem::TestCase def test_execute_gem_path util_make_gems + util_setup_spec_fetcher + util_setup_fake_fetcher Gem.clear_paths @@ -121,7 +123,7 @@ class TestGemCommandsUnpackCommand < Gem::TestCase util_clear_gems a2_data = nil - open File.join(@gemhome, 'cache', @a2.file_name), 'rb' do |fp| + open Gem.cache_gem(@a2.file_name, @gemhome), 'rb' do |fp| a2_data = fp.read end @@ -175,8 +177,8 @@ class TestGemCommandsUnpackCommand < Gem::TestCase end def test_execute_exact_match - foo_spec = quick_gem 'foo' - foo_bar_spec = quick_gem 'foo_bar' + foo_spec = quick_spec 'foo' + foo_bar_spec = quick_spec 'foo_bar' use_ui @ui do Dir.chdir @tempdir do diff --git a/test/rubygems/test_gem_commands_update_command.rb b/test/rubygems/test_gem_commands_update_command.rb index 6c16713130..24966a3a84 100644 --- a/test/rubygems/test_gem_commands_update_command.rb +++ b/test/rubygems/test_gem_commands_update_command.rb @@ -7,6 +7,12 @@ require 'rubygems/test_case' require 'rubygems/commands/update_command' +begin + gem "rdoc" +rescue Gem::LoadError + # ignore +end + class TestGemCommandsUpdateCommand < Gem::TestCase def setup @@ -19,8 +25,8 @@ class TestGemCommandsUpdateCommand < Gem::TestCase util_setup_fake_fetcher - @a1_path = File.join @gemhome, 'cache', @a1.file_name - @a2_path = File.join @gemhome, 'cache', @a2.file_name + @a1_path = Gem.cache_gem(@a1.file_name, @gemhome) + @a2_path = Gem.cache_gem(@a2.file_name, @gemhome) util_setup_spec_fetcher @a1, @a2 @@ -36,8 +42,8 @@ class TestGemCommandsUpdateCommand < Gem::TestCase Gem::Installer.new(@a1_path).install @cmd.options[:args] = [] - @cmd.options[:generate_rdoc] = true - @cmd.options[:generate_ri] = true + @cmd.options[:generate_rdoc] = false + @cmd.options[:generate_ri] = false use_ui @ui do @cmd.execute @@ -48,12 +54,153 @@ class TestGemCommandsUpdateCommand < Gem::TestCase assert_equal "Updating #{@a2.name}", out.shift assert_equal "Successfully installed #{@a2.full_name}", out.shift assert_equal "Gems updated: #{@a2.name}", out.shift - assert_equal "Installing ri documentation for a-2...", out.shift - assert_equal "Installing RDoc documentation for a-2...", out.shift + assert_empty out + end + + def util_setup_rubygem version + gem = quick_spec('rubygems-update', version.to_s) do |s| + s.files = %w[setup.rb] + end + write_file File.join(*%W[gems #{gem.original_name} setup.rb]) + util_build_gem gem + util_setup_spec_fetcher gem + gem + end + + def util_setup_rubygem8 + @rubygem8 = util_setup_rubygem 8 + end + + def util_setup_rubygem9 + @rubygem9 = util_setup_rubygem 9 + end + + def util_setup_rubygem_current + @rubygem_current = util_setup_rubygem Gem::VERSION + end + + def util_add_to_fetcher *specs + specs.each do |spec| + gem_file = Gem.cache_gem(spec.file_name, @gemhome) + + @fetcher.data["http://gems.example.com/gems/#{spec.file_name}"] = + Gem.read_binary gem_file + end + end + + def test_execute_system + util_setup_rubygem9 + util_setup_spec_fetcher @rubygem9 + util_add_to_fetcher @rubygem9 + util_clear_gems + + @cmd.options[:args] = [] + @cmd.options[:system] = true + @cmd.options[:generate_rdoc] = false + @cmd.options[:generate_ri] = false + + use_ui @ui do + @cmd.execute + end + + out = @ui.output.split "\n" + assert_equal "Updating rubygems-update", out.shift + assert_equal "Successfully installed rubygems-update-9", out.shift + assert_equal "Installing RubyGems 9", out.shift + assert_equal "RubyGems system software updated", out.shift + + assert_empty out + end + + def test_execute_system_at_latest + util_setup_rubygem_current + util_setup_spec_fetcher @rubygem_current + util_add_to_fetcher @rubygem_current + util_clear_gems + + @cmd.options[:args] = [] + @cmd.options[:system] = true + @cmd.options[:generate_rdoc] = false + @cmd.options[:generate_ri] = false + + assert_raises Gem::SystemExitException do + use_ui @ui do + @cmd.execute + end + end + + out = @ui.output.split "\n" + assert_equal "Latest version currently installed. Aborting.", out.shift + assert_empty out + end + + def test_execute_system_multiple + util_setup_rubygem9 + util_setup_rubygem8 + util_setup_spec_fetcher @rubygem8, @rubygem9 + util_add_to_fetcher @rubygem8, @rubygem9 + util_clear_gems + + @cmd.options[:args] = [] + @cmd.options[:system] = true + @cmd.options[:generate_rdoc] = false + @cmd.options[:generate_ri] = false + + use_ui @ui do + @cmd.execute + end + + out = @ui.output.split "\n" + assert_equal "Updating rubygems-update", out.shift + assert_equal "Successfully installed rubygems-update-9", out.shift + assert_equal "Installing RubyGems 9", out.shift + assert_equal "RubyGems system software updated", out.shift + + assert_empty out + end + + def test_execute_system_specific + util_clear_gems + util_setup_rubygem9 + util_setup_rubygem8 + util_setup_spec_fetcher @rubygem8, @rubygem9 + util_add_to_fetcher @rubygem8, @rubygem9 + + @cmd.options[:args] = [] + @cmd.options[:system] = "8" + @cmd.options[:generate_rdoc] = false + @cmd.options[:generate_ri] = false + + use_ui @ui do + @cmd.execute + end + + out = @ui.output.split "\n" + assert_equal "Updating rubygems-update", out.shift + assert_equal "Successfully installed rubygems-update-8", out.shift + assert_equal "Installing RubyGems 8", out.shift + assert_equal "RubyGems system software updated", out.shift assert_empty out end + def test_execute_system_with_gems + @cmd.options[:args] = %w[gem] + @cmd.options[:system] = true + @cmd.options[:generate_rdoc] = false + @cmd.options[:generate_ri] = false + + assert_raises Gem::MockGemUi::TermError do + use_ui @ui do + @cmd.execute + end + end + + assert_empty @ui.output + assert_equal "ERROR: Gem names are not allowed with the --system option\n", + @ui.error + end + # before: # a1 -> c1.2 # after: @@ -63,7 +210,7 @@ class TestGemCommandsUpdateCommand < Gem::TestCase def test_execute_dependencies @a1.add_dependency 'c', '1.2' - @c2 = quick_gem 'c', '2' do |s| + @c2 = quick_spec 'c', '2' do |s| s.files = %w[lib/code.rb] s.require_paths = %w[lib] end @@ -71,9 +218,9 @@ class TestGemCommandsUpdateCommand < Gem::TestCase @a2.add_dependency 'c', '2' @a2.add_dependency 'b', '2' - @b2_path = File.join @gemhome, 'cache', @b2.file_name - @c1_2_path = File.join @gemhome, 'cache', @c1_2.file_name - @c2_path = File.join @gemhome, 'cache', @c2.file_name + @b2_path = Gem.cache_gem(@b2.file_name, @gemhome) + @c1_2_path = Gem.cache_gem(@c1_2.file_name, @gemhome) + @c2_path = Gem.cache_gem(@c2.file_name, @gemhome) @source_index = Gem::SourceIndex.new @source_index.add_spec @a1 @@ -172,4 +319,39 @@ class TestGemCommandsUpdateCommand < Gem::TestCase assert_empty out end + + def test_handle_options_system + @cmd.handle_options %w[--system] + + expected = { + :generate_ri => true, + :system => true, + :force => false, + :args => [], + :generate_rdoc => true, + } + + assert_equal expected, @cmd.options + end + + def test_handle_options_system_non_version + assert_raises ArgumentError do + @cmd.handle_options %w[--system non-version] + end + end + + def test_handle_options_system_specific + @cmd.handle_options %w[--system 1.3.7] + + expected = { + :generate_ri => true, + :system => "1.3.7", + :force => false, + :args => [], + :generate_rdoc => true, + } + + assert_equal expected, @cmd.options + end + end diff --git a/test/rubygems/test_gem_commands_which_command.rb b/test/rubygems/test_gem_commands_which_command.rb index 41cd7cd3f8..8f9a2926db 100644 --- a/test/rubygems/test_gem_commands_which_command.rb +++ b/test/rubygems/test_gem_commands_which_command.rb @@ -57,7 +57,7 @@ class TestGemCommandsWhichCommand < Gem::TestCase def util_foo_bar files = %w[lib/foo_bar.rb Rakefile] - @foo_bar = quick_gem 'foo_bar' do |gem| + @foo_bar = quick_spec 'foo_bar' do |gem| gem.files = files end diff --git a/test/rubygems/test_gem_config_file.rb b/test/rubygems/test_gem_config_file.rb index dc53d21933..424fd92f80 100644 --- a/test/rubygems/test_gem_config_file.rb +++ b/test/rubygems/test_gem_config_file.rb @@ -283,6 +283,20 @@ class TestGemConfigFile < Gem::TestCase assert_equal "701229f217cdf23b1344c7b4b54ca97", @cfg.rubygems_api_key end + def test_load_api_keys_from_config + temp_cred = File.join Gem.user_home, '.gem', 'credentials' + FileUtils.mkdir File.dirname(temp_cred) + File.open temp_cred, 'w' do |fp| + fp.puts ":rubygems_api_key: 701229f217cdf23b1344c7b4b54ca97" + fp.puts ":other: a5fdbb6ba150cbb83aad2bb2fede64c" + end + + util_config_file + + assert_equal({:rubygems => '701229f217cdf23b1344c7b4b54ca97', + :other => 'a5fdbb6ba150cbb83aad2bb2fede64c'}, @cfg.api_keys) + end + def util_config_file(args = @cfg_args) @cfg = Gem::ConfigFile.new args end diff --git a/test/rubygems/test_gem_dependency.rb b/test/rubygems/test_gem_dependency.rb index 51b746f555..b4a21b896c 100644 --- a/test/rubygems/test_gem_dependency.rb +++ b/test/rubygems/test_gem_dependency.rb @@ -106,6 +106,45 @@ class TestGemDependency < Gem::TestCase refute_equal dep("pkg", :development), dep("pkg", :runtime), "type" end + def test_merge + a1 = dep 'a', '~> 1.0' + a2 = dep 'a', '= 1.0' + + a3 = a1.merge a2 + + assert_equal dep('a', '~> 1.0', '= 1.0'), a3 + end + + def test_merge_default + a1 = dep 'a' + a2 = dep 'a', '1' + + a3 = a1.merge a2 + + assert_equal dep('a', '1'), a3 + end + + def test_merge_name_mismatch + a = dep 'a' + b = dep 'b' + + e = assert_raises ArgumentError do + a.merge b + end + + assert_equal 'a (>= 0) and b (>= 0) have different names', + e.message + end + + def test_merge_other_default + a1 = dep 'a', '1' + a2 = dep 'a' + + a3 = a1.merge a2 + + assert_equal dep('a', '1'), a3 + end + def test_prerelease_eh d = dep "pkg", "= 1" diff --git a/test/rubygems/test_gem_dependency_installer.rb b/test/rubygems/test_gem_dependency_installer.rb index cdc0428e9f..5cf79d3c59 100644 --- a/test/rubygems/test_gem_dependency_installer.rb +++ b/test/rubygems/test_gem_dependency_installer.rb @@ -6,66 +6,28 @@ require 'rubygems/test_case' require 'rubygems/dependency_installer' +require 'rubygems/security' class TestGemDependencyInstaller < Gem::TestCase def setup super - @gems_dir = File.join @tempdir, 'gems' - @cache_dir = File.join @gemhome, 'cache' - FileUtils.mkdir @gems_dir + @gems_dir = File.join @tempdir, 'gems' + @cache_dir = Gem.cache_dir(@gemhome) - write_file File.join('gems', 'a-1', 'bin', 'a_bin') do |fp| - fp.puts "#!/usr/bin/ruby" - end + FileUtils.mkdir @gems_dir - @a1, @a1_gem = util_gem 'a', '1' do |s| s.executables << 'a_bin' end - @aa1, @aa1_gem = util_gem 'aa', '1' + @a1, @a1_gem = util_gem 'a', '1' do |s| s.executables << 'a_bin' end @a1_pre, @a1_pre_gem = util_gem 'a', '1.a' - - @b1, @b1_gem = util_gem 'b', '1' do |s| - s.add_dependency 'a' - s.add_development_dependency 'aa' - end - - @b1_pre, @b1_pre_gem = util_gem 'b', '1.a' do |s| + @b1, @b1_gem = util_gem 'b', '1' do |s| s.add_dependency 'a' s.add_development_dependency 'aa' end - @c1_pre, @c1_pre_gem = util_gem 'c', '1.a' do |s| - s.add_dependency 'a', '1.a' - s.add_dependency 'b', '1' - end - - @d1, @d1_gem = util_gem 'd', '1' - @d2, @d2_gem = util_gem 'd', '2' - - @x1_m, @x1_m_gem = util_gem 'x', '1' do |s| - s.platform = Gem::Platform.new %w[cpu my_platform 1] - end - - @x1_o, @x1_o_gem = util_gem 'x', '1' do |s| - s.platform = Gem::Platform.new %w[cpu other_platform 1] - end - - @w1, @w1_gem = util_gem 'w', '1', 'x' => nil - - @y1, @y1_gem = util_gem 'y', '1' - @y1_1_p, @y1_1_p_gem = util_gem 'y', '1.1' do |s| - s.platform = Gem::Platform.new %w[cpu my_platform 1] - end - - @z1, @z1_gem = util_gem 'z', '1', 'y' => nil - - @fetcher = Gem::FakeFetcher.new - Gem::RemoteFetcher.fetcher = @fetcher - - util_setup_spec_fetcher(@a1, @a1_pre, @b1, @b1_pre, @c1_pre, @d1, @d2, - @x1_m, @x1_o, @w1, @y1, @y1_1_p, @z1) + Gem::RemoteFetcher.fetcher = @fetcher = Gem::FakeFetcher.new - util_clear_gems + util_reset_gems end def test_install @@ -120,8 +82,8 @@ class TestGemDependencyInstaller < Gem::TestCase assert_equal %w[a-1 b-1], inst.installed_gems.map { |s| s.full_name } - assert File.exist?(File.join(@tempdir, 'cache', @a1.file_name)) - assert File.exist?(File.join(@tempdir, 'cache', @b1.file_name)) + assert Gem.cache_gem(@a1.file_name, @gemhome) + assert Gem.cache_gem(@b1.file_name, @gemhome) end def test_install_dependencies_satisfied @@ -168,6 +130,10 @@ class TestGemDependencyInstaller < Gem::TestCase end def test_install_dependency_development + @aa1, @aa1_gem = util_gem 'aa', '1' + + util_reset_gems + FileUtils.mv @a1_gem, @tempdir FileUtils.mv @aa1_gem, @tempdir FileUtils.mv @b1_gem, @tempdir @@ -321,7 +287,7 @@ class TestGemDependencyInstaller < Gem::TestCase assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name } assert File.exist?(File.join(gemhome2, 'specifications', @a1.spec_name)) - assert File.exist?(File.join(gemhome2, 'cache', @a1.file_name)) + assert File.exist?(Gem.cache_gem(@a1.file_name, gemhome2)) end def test_install_domain_both @@ -376,12 +342,13 @@ class TestGemDependencyInstaller < Gem::TestCase Gem.source_index.remove_spec @a1_pre.full_name Dir.chdir @tempdir do - e = assert_raises Gem::InstallError do + e = assert_raises Gem::DependencyError do inst = Gem::DependencyInstaller.new :domain => :local inst.install 'b' end - assert_equal 'b requires a (>= 0, runtime)', e.message + expected = "Unable to resolve dependencies: b requires a (>= 0)" + assert_equal expected, e.message end assert_equal [], inst.installed_gems.map { |s| s.full_name } @@ -425,6 +392,22 @@ class TestGemDependencyInstaller < Gem::TestCase assert_equal %w[b-1], inst.installed_gems.map { |s| s.full_name } end + def test_install_reinstall + Gem::Installer.new(@a1_gem).install + FileUtils.mv @a1_gem, @tempdir + inst = nil + + Dir.chdir @tempdir do + inst = Gem::DependencyInstaller.new + inst.install 'a' + end + + assert_equal Gem::SourceIndex.new(@a1.full_name => @a1), + Gem::SourceIndex.from_installed_gems + + assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name } + end + def test_install_remote a1_data = nil File.open @a1_gem, 'rb' do |fp| @@ -460,7 +443,7 @@ class TestGemDependencyInstaller < Gem::TestCase assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name } end - def test_install_domain_remote_platform_newer + def test_install_remote_platform_newer a2_o, a2_o_gem = util_gem 'a', '2' do |s| s.platform = Gem::Platform.new %w[cpu other_platform 1] end @@ -488,22 +471,6 @@ class TestGemDependencyInstaller < Gem::TestCase assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name } end - def test_install_reinstall - Gem::Installer.new(@a1_gem).install - FileUtils.mv @a1_gem, @tempdir - inst = nil - - Dir.chdir @tempdir do - inst = Gem::DependencyInstaller.new - inst.install 'a' - end - - assert_equal Gem::SourceIndex.new(@a1.full_name => @a1), - Gem::SourceIndex.from_installed_gems - - assert_equal %w[a-1], inst.installed_gems.map { |s| s.full_name } - end - if defined? OpenSSL then def test_install_security_policy data = File.open(@a1_gem, 'rb') { |f| f.read } @@ -539,6 +506,8 @@ class TestGemDependencyInstaller < Gem::TestCase end def test_install_version + util_setup_d + data = File.open(@d2_gem, 'rb') { |f| f.read } @fetcher.data['http://gems.example.com/gems/d-2.gem'] = data @@ -553,6 +522,8 @@ class TestGemDependencyInstaller < Gem::TestCase end def test_install_version_default + util_setup_d + data = File.open(@d2_gem, 'rb') { |f| f.read } @fetcher.data['http://gems.example.com/gems/d-2.gem'] = data @@ -619,7 +590,22 @@ class TestGemDependencyInstaller < Gem::TestCase util_setup_spec_fetcher(*specs) inst = Gem::DependencyInstaller.new - inst.find_spec_by_name_and_version 'a' + inst.find_spec_by_name_and_version specs.first.name + inst.gather_dependencies + + actual = inst.gems_to_install.map { |s| s.full_name } + assert_equal expected, actual + end + + def assert_resolve_pre expected, *specs + util_clear_gems + + util_setup_spec_fetcher(*specs) + + spec = specs.first + + inst = Gem::DependencyInstaller.new :prerelease => true + inst.find_spec_by_name_and_version spec.name, spec.version inst.gather_dependencies actual = inst.gems_to_install.map { |s| s.full_name } @@ -634,47 +620,182 @@ class TestGemDependencyInstaller < Gem::TestCase assert_equal %w[a-1 b-1], inst.gems_to_install.map { |s| s.full_name } end + ## + # [A1] depends on + # [B] > 0 (satisfied by 2.0) + # [B1] depends on + # [C] > 0 (satisfied by 1.0) + # [B2] depends on nothing! + # [C1] depends on nothing + + def test_gather_dependencies_dropped + a1, = util_spec 'a', '1', 'b' => nil + b1, = util_spec 'b', '1', 'c' => nil + b2, = util_spec 'b', '2' + c1, = util_spec 'c', '1' + + assert_resolve %w[b-2 a-1], a1, b1, b2, c1 + end + + ## + # [A] depends on + # [B] >= 1.0 (satisfied by 1.1) depends on + # [Z] + # [C] >= 1.0 depends on + # [B] = 1.0 + # + # and should backtrack to resolve using b-1.0, pruning Z from the + # resolve. + + def test_gather_dependencies_raggi_the_edgecase_generator + a, _ = util_spec 'a', '1.0', 'b' => '>= 1.0', 'c' => '>= 1.0' + b1, _ = util_spec 'b', '1.0' + b2, _ = util_spec 'b', '1.1', 'z' => '>= 1.0' + c, _ = util_spec 'c', '1.0', 'b' => '= 1.0' + + assert_resolve %w[b-1.0 c-1.0 a-1.0], a, b1, b2, c + end + + ## + # [A] depends on + # [B] >= 1.0 (satisfied by 2.0) + # [C] = 1.0 depends on + # [B] ~> 1.0 + # + # and should resolve using b-1.0 + + def test_gather_dependencies_over + a, _ = util_spec 'a', '1.0', 'b' => '>= 1.0', 'c' => '= 1.0' + b1, _ = util_spec 'b', '1.0' + b2, _ = util_spec 'b', '2.0' + c, _ = util_spec 'c', '1.0', 'b' => '~> 1.0' + + assert_resolve %w[b-1.0 c-1.0 a-1.0], a, b1, b2, c + end + + ## + # [A] depends on + # [B] ~> 1.0 (satisfied by 1.1) + # [C] = 1.0 depends on + # [B] = 1.0 + # + # and should resolve using b-1.0 + # + # TODO: this is not under, but over... under would require depth + # first resolve through a dependency that is later pruned. + + def test_gather_dependencies_under + a, _ = util_spec 'a', '1.0', 'b' => '~> 1.0', 'c' => '= 1.0' + b10, _ = util_spec 'b', '1.0' + b11, _ = util_spec 'b', '1.1' + c, _ = util_spec 'c', '1.0', 'b' => '= 1.0' + + assert_resolve %w[b-1.0 c-1.0 a-1.0], a, b10, b11, c + end + + # under + # + # [A] depends on + # [B] ~> 1.0 (satisfied by 1.0) + # [C] = 1.0 depends on + # [B] = 2.0 + + def test_gather_dependencies_divergent + a, _ = util_spec 'a', '1.0', 'b' => '~> 1.0', 'c' => '= 1.0' + b1, _ = util_spec 'b', '1.0' + b2, _ = util_spec 'b', '2.0' + c, _ = util_spec 'c', '1.0', 'b' => '= 2.0' + + assert_raises Gem::DependencyError do + assert_resolve :ignored, a, b1, b2, c + end + end + def test_gather_dependencies_platform_alternate + util_setup_wxyz util_set_arch 'cpu-my_platform1' - inst = Gem::DependencyInstaller.new - inst.find_spec_by_name_and_version 'w' - inst.gather_dependencies - - assert_equal %w[x-1-cpu-my_platform-1 w-1], - inst.gems_to_install.map { |s| s.full_name } + assert_resolve %w[x-1-cpu-my_platform-1 w-1], @w1, @x1_m end def test_gather_dependencies_platform_bump - inst = Gem::DependencyInstaller.new - inst.find_spec_by_name_and_version 'z' - inst.gather_dependencies + util_setup_wxyz - assert_equal %w[y-1 z-1], inst.gems_to_install.map { |s| s.full_name } + assert_resolve %w[y-1 z-1], @z1, @y1 end def test_gather_dependencies_prerelease - inst = Gem::DependencyInstaller.new :prerelease => true - inst.find_spec_by_name_and_version 'c', '1.a' - inst.gather_dependencies + util_setup_c1_pre - assert_equal %w[a-1.a b-1 c-1.a], - inst.gems_to_install.map { |s| s.full_name } + assert_resolve_pre %w[a-1.a b-1 c-1.a], @c1_pre, @a1_pre, @b1 end def test_gather_dependencies_old_required - e1, = util_gem 'e', '1', 'd' => '= 1' - + util_setup_d + e1, = util_spec 'e', '1', 'd' => '= 1' util_clear_gems - util_setup_spec_fetcher @d1, @d2, e1 + assert_resolve %w[d-1 e-1], e1, @d1, @d2 + end - inst = Gem::DependencyInstaller.new - inst.find_spec_by_name_and_version 'e' - inst.gather_dependencies + def util_write_a1_bin + write_file File.join('gems', 'a-1', 'bin', 'a_bin') do |fp| + fp.puts "#!/usr/bin/ruby" + end + end + + def util_setup_c1_pre + @c1_pre, @c1_pre_gem = util_spec 'c', '1.a' do |s| + s.add_dependency 'a', '1.a' + s.add_dependency 'b', '1' + end - assert_equal %w[d-1 e-1], inst.gems_to_install.map { |s| s.full_name } + util_reset_gems end -end + def util_setup_d + @d1, @d1_gem = util_gem 'd', '1' + @d2, @d2_gem = util_gem 'd', '2' + + util_reset_gems + end + def util_setup_wxyz + @x1_m, @x1_m_gem = util_spec 'x', '1' do |s| + s.platform = Gem::Platform.new %w[cpu my_platform 1] + end + + @x1_o, @x1_o_gem = util_spec 'x', '1' do |s| + s.platform = Gem::Platform.new %w[cpu other_platform 1] + end + + @w1, @w1_gem = util_spec 'w', '1', 'x' => nil + + @y1, @y1_gem = util_spec 'y', '1' + @y1_1_p, @y1_1_p_gem = util_spec 'y', '1.1' do |s| + s.platform = Gem::Platform.new %w[cpu my_platform 1] + end + + @z1, @z1_gem = util_spec 'z', '1', 'y' => nil + + util_reset_gems + end + + def util_reset_gems + @c1_pre ||= nil + @d1 ||= nil + @d2 ||= nil + @w1 ||= nil + @x1_m ||= nil + @x1_o ||= nil + @y1 ||= nil + @y1_1_p ||= nil + @z1 ||= nil + + util_setup_spec_fetcher(*[@a1, @a1_pre, @b1, @c1_pre, + @d1, @d2, @x1_m, @x1_o, @w1, @y1, + @y1_1_p, @z1].compact) + + util_clear_gems + end +end diff --git a/test/rubygems/test_gem_dependency_list.rb b/test/rubygems/test_gem_dependency_list.rb index 92966ace08..688455475b 100644 --- a/test/rubygems/test_gem_dependency_list.rb +++ b/test/rubygems/test_gem_dependency_list.rb @@ -14,17 +14,17 @@ class TestGemDependencyList < Gem::TestCase @deplist = Gem::DependencyList.new - @a1 = quick_gem 'a', '1' - @a2 = quick_gem 'a', '2' - @a3 = quick_gem 'a', '3' + @a1 = quick_spec 'a', '1' + @a2 = quick_spec 'a', '2' + @a3 = quick_spec 'a', '3' - @b1 = quick_gem 'b', '1' do |s| s.add_dependency 'a', '>= 1' end - @b2 = quick_gem 'b', '2' do |s| s.add_dependency 'a', '>= 1' end + @b1 = quick_spec 'b', '1' do |s| s.add_dependency 'a', '>= 1' end + @b2 = quick_spec 'b', '2' do |s| s.add_dependency 'a', '>= 1' end - @c1 = quick_gem 'c', '1' do |s| s.add_dependency 'b', '>= 1' end - @c2 = quick_gem 'c', '2' + @c1 = quick_spec 'c', '1' do |s| s.add_dependency 'b', '>= 1' end + @c2 = quick_spec 'c', '2' - @d1 = quick_gem 'd', '1' do |s| s.add_dependency 'c', '>= 1' end + @d1 = quick_spec 'd', '1' do |s| s.add_dependency 'c', '>= 1' end end def test_self_from_source_index @@ -72,9 +72,9 @@ class TestGemDependencyList < Gem::TestCase end def test_dependency_order_development - e1 = quick_gem 'e', '1' - f1 = quick_gem 'f', '1' - g1 = quick_gem 'g', '1' + e1 = quick_spec 'e', '1' + f1 = quick_spec 'f', '1' + g1 = quick_spec 'g', '1' @a1.add_dependency 'e' @a1.add_dependency 'f' @@ -100,7 +100,7 @@ class TestGemDependencyList < Gem::TestCase def test_dependency_order_diamond util_diamond - e1 = quick_gem 'e', '1' + e1 = quick_spec 'e', '1' @deplist.add e1 @a1.add_dependency 'e', '>= 1' @@ -128,6 +128,8 @@ class TestGemDependencyList < Gem::TestCase end def test_ok_eh + util_clear_gems + assert @deplist.ok?, 'no dependencies' @deplist.add @b2 @@ -139,14 +141,30 @@ class TestGemDependencyList < Gem::TestCase assert @deplist.ok?, 'satisfied dependency' end + def test_why_not_ok_eh + util_clear_gems + + assert_equal({}, @deplist.why_not_ok?) + + @deplist.add @b2 + + exp = { + "b" => [ + Gem::Dependency.new("a", ">= 1") + ] + } + + assert_equal exp, @deplist.why_not_ok? + end + def test_ok_eh_mismatch - a1 = quick_gem 'a', '1' - a2 = quick_gem 'a', '2' + a1 = quick_spec 'a', '1' + a2 = quick_spec 'a', '2' - b = quick_gem 'b', '1' do |s| s.add_dependency 'a', '= 1' end - c = quick_gem 'c', '1' do |s| s.add_dependency 'a', '= 2' end + b = quick_spec 'b', '1' do |s| s.add_dependency 'a', '= 1' end + c = quick_spec 'c', '1' do |s| s.add_dependency 'a', '= 2' end - d = quick_gem 'd', '1' do |s| + d = quick_spec 'd', '1' do |s| s.add_dependency 'b' s.add_dependency 'c' end @@ -192,6 +210,8 @@ class TestGemDependencyList < Gem::TestCase end def test_remove_by_name + util_clear_gems + @deplist.add @a1, @b2 @deplist.remove_by_name "a-1" diff --git a/test/rubygems/test_gem_doc_manager.rb b/test/rubygems/test_gem_doc_manager.rb index be4c12bd5b..f52f1f87f1 100644 --- a/test/rubygems/test_gem_doc_manager.rb +++ b/test/rubygems/test_gem_doc_manager.rb @@ -12,25 +12,26 @@ class TestGemDocManager < Gem::TestCase def setup super - @spec = quick_gem 'a' + @spec = quick_gem 'a', 2 @manager = Gem::DocManager.new(@spec) end def test_uninstall_doc_unwritable - orig_mode = File.stat(@spec.installation_path).mode + path = @spec.installation_path + orig_mode = File.stat(path).mode # File.chmod has no effect on MS Windows directories (it needs ACL). if win_platform? skip("test_uninstall_doc_unwritable skipped on MS Windows") else - File.chmod(0, @spec.installation_path) + File.chmod 0000, path end assert_raises Gem::FilePermissionError do @manager.uninstall_doc end ensure - File.chmod orig_mode, @spec.installation_path + File.chmod orig_mode, path end end diff --git a/test/rubygems/test_gem_format.rb b/test/rubygems/test_gem_format.rb index f964cab143..6f169588eb 100644 --- a/test/rubygems/test_gem_format.rb +++ b/test/rubygems/test_gem_format.rb @@ -5,7 +5,7 @@ ###################################################################### require 'rubygems/package/tar_test_case' -require 'test/rubygems/simple_gem' +require 'rubygems/simple_gem' require 'rubygems/format' class TestGemFormat < Gem::Package::TarTestCase @@ -20,7 +20,7 @@ class TestGemFormat < Gem::Package::TarTestCase def test_class_from_file_by_path util_make_gems - gems = Dir[File.join(@gemhome, 'cache', '*.gem')] + gems = Dir[Gem.cache_gem('*.gem', @gemhome)] names = [@a1, @a2, @a3a, @a_evil9, @b2, @c1_2, @pl1].map do |spec| spec.original_name diff --git a/test/rubygems/test_gem_gemcutter_utilities.rb b/test/rubygems/test_gem_gemcutter_utilities.rb index 79d1e6cdb8..a01328fbab 100644 --- a/test/rubygems/test_gem_gemcutter_utilities.rb +++ b/test/rubygems/test_gem_gemcutter_utilities.rb @@ -6,6 +6,7 @@ require 'rubygems/test_case' require 'rubygems' +require 'rubygems/command' require 'rubygems/gemcutter_utilities' class TestGemGemcutterUtilities < Gem::TestCase @@ -20,6 +21,35 @@ class TestGemGemcutterUtilities < Gem::TestCase @cmd.extend Gem::GemcutterUtilities end + def test_api_key + keys = { :rubygems_api_key => 'KEY' } + FileUtils.mkdir_p File.dirname Gem.configuration.credentials_path + + open Gem.configuration.credentials_path, 'w' do |f| + f.write keys.to_yaml + end + + Gem.configuration.load_api_keys + + assert_equal 'KEY', @cmd.api_key + end + + def test_api_key_override + keys = { :rubygems_api_key => 'KEY', :other => 'OTHER' } + FileUtils.mkdir_p File.dirname Gem.configuration.credentials_path + + open Gem.configuration.credentials_path, 'w' do |f| + f.write keys.to_yaml + end + + Gem.configuration.load_api_keys + + @cmd.add_key_option + @cmd.handle_options %w[--key other] + + assert_equal 'OTHER', @cmd.api_key + end + def test_sign_in api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903' util_sign_in [api_key, 200, 'OK'] @@ -105,5 +135,23 @@ class TestGemGemcutterUtilities < Gem::TestCase end end + def test_verify_api_key + keys = {:other => 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903'} + FileUtils.mkdir_p File.dirname(Gem.configuration.credentials_path) + File.open Gem.configuration.credentials_path, 'w' do |f| + f.write keys.to_yaml + end + Gem.configuration.load_api_keys + + assert_equal 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903', + @cmd.verify_api_key(:other) + end + + def test_verify_missing_api_key + assert_raises Gem::MockGemUi::TermError do + @cmd.verify_api_key :missing + end + end + end diff --git a/test/rubygems/test_gem_indexer.rb b/test/rubygems/test_gem_indexer.rb index a7f49506a6..71fb965460 100644 --- a/test/rubygems/test_gem_indexer.rb +++ b/test/rubygems/test_gem_indexer.rb @@ -18,21 +18,20 @@ class TestGemIndexer < Gem::TestCase util_make_gems - @d2_0 = quick_gem 'd', '2.0' do |s| + @d2_0 = quick_spec 'd', '2.0' do |s| s.date = Gem::Specification::TODAY - 86400 * 3 end util_build_gem @d2_0 - @d2_0_a = quick_gem 'd', '2.0.a' + @d2_0_a = quick_spec 'd', '2.0.a' util_build_gem @d2_0_a - @d2_0_b = quick_gem 'd', '2.0.b' + @d2_0_b = quick_spec 'd', '2.0.b' util_build_gem @d2_0_b gems = File.join(@tempdir, 'gems') FileUtils.mkdir_p gems - cache_gems = File.join @gemhome, 'cache', '*.gem' - FileUtils.mv Dir[cache_gems], gems + FileUtils.mv Dir[Gem.cache_gem('*.gem', @gemhome)], gems @indexer = Gem::Indexer.new @tempdir, :rss_title => 'ExampleForge gems', :rss_host => 'example.com', @@ -60,7 +59,7 @@ class TestGemIndexer < Gem::TestCase end def test_build_indicies - spec = quick_gem 'd', '2.0' + spec = quick_spec 'd', '2.0' spec.instance_variable_set :@original_platform, '' @indexer.make_temp_directories @@ -510,17 +509,17 @@ eighty characters.</pre> assert File.directory?(quickdir) assert File.directory?(marshal_quickdir) - @d2_1 = quick_gem 'd', '2.1' + @d2_1 = quick_spec 'd', '2.1' util_build_gem @d2_1 @d2_1_tuple = [@d2_1.name, @d2_1.version, @d2_1.original_platform] - @d2_1_a = quick_gem 'd', '2.2.a' + @d2_1_a = quick_spec 'd', '2.2.a' util_build_gem @d2_1_a @d2_1_a_tuple = [@d2_1_a.name, @d2_1_a.version, @d2_1_a.original_platform] gems = File.join @tempdir, 'gems' - FileUtils.mv File.join(@gemhome, 'cache', @d2_1.file_name), gems - FileUtils.mv File.join(@gemhome, 'cache', @d2_1_a.file_name), gems + FileUtils.mv Gem.cache_gem(@d2_1.file_name, @gemhome), gems + FileUtils.mv Gem.cache_gem(@d2_1_a.file_name, @gemhome), gems use_ui @ui do @indexer.update_index diff --git a/test/rubygems/test_gem_install_update_options.rb b/test/rubygems/test_gem_install_update_options.rb index 937774617f..fe10fd4949 100644 --- a/test/rubygems/test_gem_install_update_options.rb +++ b/test/rubygems/test_gem_install_update_options.rb @@ -69,6 +69,4 @@ class TestGemInstallUpdateOptions < Gem::InstallerTestCase ensure FileUtils.chmod 0755, @gemhome end - end - diff --git a/test/rubygems/test_gem_installer.rb b/test/rubygems/test_gem_installer.rb index 94fa4423bc..0b73af996d 100644 --- a/test/rubygems/test_gem_installer.rb +++ b/test/rubygems/test_gem_installer.rb @@ -9,7 +9,8 @@ require 'rubygems/installer_test_case' class TestGemInstaller < Gem::InstallerTestCase def test_app_script_text - util_make_exec '2', '' + @spec.version = 2 + util_make_exec @spec, '' expected = <<-EOF #!#{Gem.ruby} @@ -30,10 +31,10 @@ if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then end gem 'a', version -load Gem.bin_path('a', 'my_exec', version) +load Gem.bin_path('a', 'executable', version) EOF - wrapper = @installer.app_script_text 'my_exec' + wrapper = @installer.app_script_text 'executable' assert_equal expected, wrapper end @@ -101,7 +102,7 @@ load Gem.bin_path('a', 'my_exec', version) @installer.ensure_dependency @spec, dep end - assert_equal 'a requires b (> 2, runtime)', e.message + assert_equal 'a requires b (> 2)', e.message end def test_extract_files @@ -170,11 +171,11 @@ load Gem.bin_path('a', 'my_exec', version) def test_generate_bin_bindir @installer.wrappers = true - @spec.executables = ["my_exec"] + @spec.executables = %w[executable] @spec.bindir = '.' - exec_file = @installer.formatted_program_filename "my_exec" - exec_path = File.join util_gem_dir(@spec.version), exec_file + exec_file = @installer.formatted_program_filename 'executable' + exec_path = File.join util_gem_dir(@spec), exec_file File.open exec_path, 'w' do |f| f.puts '#!/usr/bin/ruby' end @@ -184,7 +185,7 @@ load Gem.bin_path('a', 'my_exec', version) @installer.generate_bin assert_equal true, File.directory?(util_inst_bindir) - installed_exec = File.join(util_inst_bindir, "my_exec") + installed_exec = File.join(util_inst_bindir, 'executable') assert_equal true, File.exist?(installed_exec) assert_equal(0100755, File.stat(installed_exec).mode) unless win_platform? @@ -199,7 +200,7 @@ load Gem.bin_path('a', 'my_exec', version) @installer.generate_bin assert_equal true, File.directory?(util_inst_bindir) - installed_exec = File.join(util_inst_bindir, "my_exec") + installed_exec = File.join(util_inst_bindir, 'executable') assert_equal true, File.exist?(installed_exec) assert_equal(0100755, File.stat(installed_exec).mode) unless win_platform? @@ -216,7 +217,7 @@ load Gem.bin_path('a', 'my_exec', version) Gem::Installer.exec_format = 'foo-%s-bar' @installer.generate_bin assert_equal true, File.directory?(util_inst_bindir) - installed_exec = File.join util_inst_bindir, 'foo-my_exec-bar' + installed_exec = File.join util_inst_bindir, 'foo-executable-bar' assert_equal true, File.exist?(installed_exec) ensure Gem::Installer.exec_format = nil @@ -230,7 +231,7 @@ load Gem.bin_path('a', 'my_exec', version) Gem::Installer.exec_format = 'foo-%s-bar' @installer.generate_bin assert_equal true, File.directory?(util_inst_bindir) - installed_exec = File.join util_inst_bindir, 'my_exec' + installed_exec = File.join util_inst_bindir, 'executable' assert_equal true, File.exist?(installed_exec) ensure Gem::Installer.exec_format = nil @@ -238,12 +239,12 @@ load Gem.bin_path('a', 'my_exec', version) def test_generate_bin_script_install_dir @installer.wrappers = true - @spec.executables = ["my_exec"] + @spec.executables = %w[executable] gem_dir = File.join "#{@gemhome}2", 'gems', @spec.full_name gem_bindir = File.join gem_dir, 'bin' FileUtils.mkdir_p gem_bindir - File.open File.join(gem_bindir, "my_exec"), 'w' do |f| + File.open File.join(gem_bindir, 'executable'), 'w' do |f| f.puts "#!/bin/ruby" end @@ -252,7 +253,7 @@ load Gem.bin_path('a', 'my_exec', version) @installer.generate_bin - installed_exec = File.join("#{@gemhome}2", 'bin', 'my_exec') + installed_exec = File.join("#{@gemhome}2", 'bin', 'executable') assert_equal true, File.exist?(installed_exec) assert_equal(0100755, File.stat(installed_exec).mode) unless win_platform? @@ -261,9 +262,12 @@ load Gem.bin_path('a', 'my_exec', version) end def test_generate_bin_script_no_execs + util_execless + @installer.wrappers = true @installer.generate_bin - assert_equal false, File.exist?(util_inst_bindir) + + refute File.exist?(util_inst_bindir), 'bin dir was created when not needed' end def test_generate_bin_script_no_perms @@ -287,18 +291,18 @@ load Gem.bin_path('a', 'my_exec', version) def test_generate_bin_script_no_shebang @installer.wrappers = true - @spec.executables = ["my_exec"] + @spec.executables = %w[executable] gem_dir = File.join @gemhome, 'gems', @spec.full_name gem_bindir = File.join gem_dir, 'bin' FileUtils.mkdir_p gem_bindir - File.open File.join(gem_bindir, "my_exec"), 'w' do |f| + File.open File.join(gem_bindir, 'executable'), 'w' do |f| f.puts "blah blah blah" end @installer.generate_bin - installed_exec = File.join @gemhome, 'bin', 'my_exec' + installed_exec = File.join @gemhome, 'bin', 'executable' assert_equal true, File.exist?(installed_exec) assert_equal 0100755, File.stat(installed_exec).mode unless win_platform? @@ -312,9 +316,9 @@ load Gem.bin_path('a', 'my_exec', version) @installer.wrappers = true util_make_exec @installer.gem_dir = util_gem_dir - installed_exec = File.join(util_inst_bindir, "my_exec") + installed_exec = File.join(util_inst_bindir, 'executable') - real_exec = File.join util_gem_dir, 'bin', 'my_exec' + real_exec = File.join util_gem_dir, 'bin', 'executable' # fake --no-wrappers for previous install unless Gem.win_platform? then @@ -342,16 +346,19 @@ load Gem.bin_path('a', 'my_exec', version) @installer.generate_bin assert_equal true, File.directory?(util_inst_bindir) - installed_exec = File.join(util_inst_bindir, "my_exec") + installed_exec = File.join(util_inst_bindir, 'executable') assert_equal true, File.symlink?(installed_exec) - assert_equal(File.join(util_gem_dir, "bin", "my_exec"), + assert_equal(File.join(util_gem_dir, 'bin', 'executable'), File.readlink(installed_exec)) end def test_generate_bin_symlink_no_execs + util_execless + @installer.wrappers = false @installer.generate_bin - assert_equal false, File.exist?(util_inst_bindir) + + refute File.exist?(util_inst_bindir) end def test_generate_bin_symlink_no_perms @@ -382,8 +389,8 @@ load Gem.bin_path('a', 'my_exec', version) @installer.gem_dir = util_gem_dir @installer.generate_bin - installed_exec = File.join(util_inst_bindir, "my_exec") - assert_equal(File.join(util_gem_dir, "bin", "my_exec"), + installed_exec = File.join(util_inst_bindir, 'executable') + assert_equal(File.join(util_gem_dir, 'bin', 'executable'), File.readlink(installed_exec)) @spec = Gem::Specification.new do |s| @@ -395,11 +402,12 @@ load Gem.bin_path('a', 'my_exec', version) s.require_path = 'lib' end - util_make_exec '3' - @installer.gem_dir = File.join util_gem_dir('3') + @spec.version = 3 + util_make_exec + @installer.gem_dir = File.join util_gem_dir @spec @installer.generate_bin - installed_exec = File.join(util_inst_bindir, "my_exec") - assert_equal(File.join(util_gem_bindir('3'), "my_exec"), + installed_exec = File.join(util_inst_bindir, 'executable') + assert_equal(File.join(util_gem_bindir(@spec), 'executable'), File.readlink(installed_exec), "Ensure symlink moved to latest version") end @@ -412,8 +420,8 @@ load Gem.bin_path('a', 'my_exec', version) @installer.gem_dir = util_gem_dir @installer.generate_bin - installed_exec = File.join(util_inst_bindir, "my_exec") - assert_equal(File.join(util_gem_dir, "bin", "my_exec"), + installed_exec = File.join(util_inst_bindir, 'executable') + assert_equal(File.join(util_gem_dir, 'bin', 'executable'), File.readlink(installed_exec)) spec = Gem::Specification.new do |s| @@ -425,14 +433,16 @@ load Gem.bin_path('a', 'my_exec', version) s.require_path = 'lib' end - util_make_exec '1' - @installer.gem_dir = util_gem_dir('1') + util_make_exec + one = @spec.dup + one.version = 1 + @installer.gem_dir = util_gem_dir one @installer.spec = spec @installer.generate_bin - installed_exec = File.join(util_inst_bindir, "my_exec") - assert_equal(File.join(util_gem_dir('2'), "bin", "my_exec"), + installed_exec = File.join(util_inst_bindir, 'executable') + assert_equal(File.join(util_gem_dir, 'bin', 'executable'), File.readlink(installed_exec), "Ensure symlink not moved") end @@ -445,7 +455,7 @@ load Gem.bin_path('a', 'my_exec', version) @installer.gem_dir = util_gem_dir @installer.generate_bin - installed_exec = File.join(util_inst_bindir, "my_exec") + installed_exec = File.join(util_inst_bindir, 'executable') assert_equal true, File.exist?(installed_exec) @spec = Gem::Specification.new do |s| @@ -458,11 +468,12 @@ load Gem.bin_path('a', 'my_exec', version) end @installer.wrappers = false - util_make_exec '3' - @installer.gem_dir = util_gem_dir '3' + @spec.version = 3 + util_make_exec + @installer.gem_dir = util_gem_dir @installer.generate_bin - installed_exec = File.join(util_inst_bindir, "my_exec") - assert_equal(File.join(util_gem_dir('3'), "bin", "my_exec"), + installed_exec = File.join(util_inst_bindir, 'executable') + assert_equal(File.join(util_gem_dir, 'bin', 'executable'), File.readlink(installed_exec), "Ensure symlink moved to latest version") end @@ -479,7 +490,7 @@ load Gem.bin_path('a', 'my_exec', version) end assert_equal true, File.directory?(util_inst_bindir) - installed_exec = File.join(util_inst_bindir, "my_exec") + installed_exec = File.join(util_inst_bindir, 'executable') assert_equal true, File.exist?(installed_exec) assert_match(/Unable to use symlinks on Windows, installing wrapper/i, @@ -500,19 +511,18 @@ load Gem.bin_path('a', 'my_exec', version) @installer.generate_bin default_shebang = Gem.ruby - shebang_line = open("#{@gemhome}/bin/my_exec") { |f| f.readlines.first } + shebang_line = open("#{@gemhome}/bin/executable") { |f| f.readlines.first } assert_match(/\A#!/, shebang_line) assert_match(/#{default_shebang}/, shebang_line) end def test_initialize - spec = quick_gem 'a' do |s| s.platform = Gem::Platform.new 'mswin32' end + spec = quick_spec 'a' do |s| s.platform = Gem::Platform.new 'mswin32' end gem = File.join @tempdir, spec.file_name Dir.mkdir util_inst_bindir util_build_gem spec - FileUtils.mv File.join(@gemhome, 'cache', spec.file_name), - @tempdir + FileUtils.mv Gem.cache_gem(spec.file_name, @gemhome), @tempdir installer = Gem::Installer.new gem @@ -525,7 +535,7 @@ load Gem.bin_path('a', 'my_exec', version) util_clear_gems gemdir = File.join @gemhome, 'gems', @spec.full_name - cache_file = File.join @gemhome, 'cache', @spec.file_name + cache_file = Gem.cache_gem(@spec.file_name, @gemhome) stub_exe = File.join @gemhome, 'bin', 'executable' rakefile = File.join gemdir, 'ext', 'a', 'Rakefile' @@ -574,6 +584,42 @@ load Gem.bin_path('a', 'my_exec', version) assert_same @installer, @pre_install_hook_arg end + def test_install_with_no_prior_files + Dir.mkdir util_inst_bindir + util_clear_gems + + util_setup_gem + build_rake_in do + use_ui @ui do + assert_equal @spec, @installer.install + end + end + + gemdir = File.join(@gemhome, 'gems', @spec.full_name) + assert File.exist?(File.join(gemdir, 'lib', 'code.rb')) + + util_setup_gem + # Morph spec to have lib/other.rb instead of code.rb and recreate + @spec.files = File.join('lib', 'other.rb') + Dir.chdir @tempdir do + File.open File.join('lib', 'other.rb'), 'w' do |f| f.puts '1' end + use_ui ui do + FileUtils.rm @gem + Gem::Builder.new(@spec).build + end + end + @installer = Gem::Installer.new @gem + build_rake_in do + use_ui @ui do + assert_equal @spec, @installer.install + end + end + + assert File.exist?(File.join(gemdir, 'lib', 'other.rb')) + refute(File.exist?(File.join(gemdir, 'lib', 'code.rb')), + "code.rb from prior install of same gem shouldn't remain here") + end + def test_install_bad_gem gem = nil @@ -610,7 +656,7 @@ load Gem.bin_path('a', 'my_exec', version) gemhome2 = "#{@gemhome}2" @spec.add_dependency 'b' - b2 = quick_gem 'b', 2 + b2 = quick_spec 'b', 2 FileUtils.mv @gemhome, gemhome2 Gem.source_index.gems.delete b2.full_name @@ -666,7 +712,7 @@ load Gem.bin_path('a', 'my_exec', version) end def test_install_missing_dirs - FileUtils.rm_f File.join(Gem.dir, 'cache') + FileUtils.rm_f Gem.cache_dir FileUtils.rm_f File.join(Gem.dir, 'docs') FileUtils.rm_f File.join(Gem.dir, 'specifications') @@ -676,11 +722,11 @@ load Gem.bin_path('a', 'my_exec', version) @installer.install end - File.directory? File.join(Gem.dir, 'cache') + File.directory? Gem.cache_dir File.directory? File.join(Gem.dir, 'docs') File.directory? File.join(Gem.dir, 'specifications') - assert File.exist?(File.join(@gemhome, 'cache', @spec.file_name)) + assert File.exist?(Gem.cache_gem(@spec.file_name, @gemhome)) assert File.exist?(File.join(@gemhome, 'specifications', @spec.spec_name)) end @@ -786,13 +832,13 @@ load Gem.bin_path('a', 'my_exec', version) end def test_install_wrong_rubygems_version - spec = quick_gem 'old_rubygems_required', '1' do |s| + spec = quick_spec 'old_rubygems_required', '1' do |s| s.required_rubygems_version = '< 0' end util_build_gem spec - gem = File.join @gemhome, 'cache', spec.file_name + gem = Gem.cache_gem(spec.file_name, @gemhome) use_ui @ui do @installer = Gem::Installer.new gem @@ -813,49 +859,49 @@ load Gem.bin_path('a', 'my_exec', version) end def test_shebang - util_make_exec '2', "#!/usr/bin/ruby" + util_make_exec @spec, "#!/usr/bin/ruby" - shebang = @installer.shebang 'my_exec' + shebang = @installer.shebang 'executable' assert_equal "#!#{Gem.ruby}", shebang end def test_shebang_arguments - util_make_exec '2', "#!/usr/bin/ruby -ws" + util_make_exec @spec, "#!/usr/bin/ruby -ws" - shebang = @installer.shebang 'my_exec' + shebang = @installer.shebang 'executable' assert_equal "#!#{Gem.ruby} -ws", shebang end def test_shebang_empty - util_make_exec '2', '' + util_make_exec @spec, '' - shebang = @installer.shebang 'my_exec' + shebang = @installer.shebang 'executable' assert_equal "#!#{Gem.ruby}", shebang end def test_shebang_env - util_make_exec '2', "#!/usr/bin/env ruby" + util_make_exec @spec, "#!/usr/bin/env ruby" - shebang = @installer.shebang 'my_exec' + shebang = @installer.shebang 'executable' assert_equal "#!#{Gem.ruby}", shebang end def test_shebang_env_arguments - util_make_exec '2', "#!/usr/bin/env ruby -ws" + util_make_exec @spec, "#!/usr/bin/env ruby -ws" - shebang = @installer.shebang 'my_exec' + shebang = @installer.shebang 'executable' assert_equal "#!#{Gem.ruby} -ws", shebang end def test_shebang_env_shebang - util_make_exec '2', '' + util_make_exec @spec, '' @installer.env_shebang = true - shebang = @installer.shebang 'my_exec' + shebang = @installer.shebang 'executable' env_shebang = "/usr/bin/env" unless Gem.win_platform? @@ -864,49 +910,49 @@ load Gem.bin_path('a', 'my_exec', version) end def test_shebang_nested - util_make_exec '2', "#!/opt/local/ruby/bin/ruby" + util_make_exec @spec, "#!/opt/local/ruby/bin/ruby" - shebang = @installer.shebang 'my_exec' + shebang = @installer.shebang 'executable' assert_equal "#!#{Gem.ruby}", shebang end def test_shebang_nested_arguments - util_make_exec '2', "#!/opt/local/ruby/bin/ruby -ws" + util_make_exec @spec, "#!/opt/local/ruby/bin/ruby -ws" - shebang = @installer.shebang 'my_exec' + shebang = @installer.shebang 'executable' assert_equal "#!#{Gem.ruby} -ws", shebang end def test_shebang_version - util_make_exec '2', "#!/usr/bin/ruby18" + util_make_exec @spec, "#!/usr/bin/ruby18" - shebang = @installer.shebang 'my_exec' + shebang = @installer.shebang 'executable' assert_equal "#!#{Gem.ruby}", shebang end def test_shebang_version_arguments - util_make_exec '2', "#!/usr/bin/ruby18 -ws" + util_make_exec @spec, "#!/usr/bin/ruby18 -ws" - shebang = @installer.shebang 'my_exec' + shebang = @installer.shebang 'executable' assert_equal "#!#{Gem.ruby} -ws", shebang end def test_shebang_version_env - util_make_exec '2', "#!/usr/bin/env ruby18" + util_make_exec @spec, "#!/usr/bin/env ruby18" - shebang = @installer.shebang 'my_exec' + shebang = @installer.shebang 'executable' assert_equal "#!#{Gem.ruby}", shebang end def test_shebang_version_env_arguments - util_make_exec '2', "#!/usr/bin/env ruby18 -ws" + util_make_exec @spec, "#!/usr/bin/env ruby18 -ws" - shebang = @installer.shebang 'my_exec' + shebang = @installer.shebang 'executable' assert_equal "#!#{Gem.ruby} -ws", shebang end @@ -937,14 +983,41 @@ load Gem.bin_path('a', 'my_exec', version) assert_equal @spec, eval(File.read(spec_file)) end + def test_write_spec_writes_cached_spec + spec_dir = File.join @gemhome, 'specifications' + spec_file = File.join spec_dir, @spec.spec_name + FileUtils.rm spec_file + refute File.exist?(spec_file) + + @spec.files = %w[a.rb b.rb c.rb] + + @installer.spec = @spec + @installer.gem_home = @gemhome + + @installer.write_spec + + # cached specs have no file manifest: + @spec.files = [] + + assert_equal @spec, eval(File.read(spec_file)) + end + def old_ruby_required - spec = quick_gem 'old_ruby_required', '1' do |s| + spec = quick_spec 'old_ruby_required', '1' do |s| s.required_ruby_version = '= 1.4.6' end util_build_gem spec - File.join @gemhome, 'cache', spec.file_name + Gem.cache_gem(spec.file_name, @gemhome) + end + + def util_execless + @spec = quick_spec 'z' + + gem = File.join @tempdir, @spec.file_name + + @installer = util_installer @spec, gem, @gemhome end end diff --git a/test/rubygems/test_gem_package_tar_output.rb b/test/rubygems/test_gem_package_tar_output.rb index 7458a749dd..77f31852f9 100644 --- a/test/rubygems/test_gem_package_tar_output.rb +++ b/test/rubygems/test_gem_package_tar_output.rb @@ -55,6 +55,9 @@ class TestGemPackageTarOutput < Gem::Package::TarTestCase if defined? OpenSSL then def test_self_open_signed + @private_key = File.expand_path('test/rubygems/private_key.pem', @@project_dir) + @public_cert = File.expand_path('test/rubygems/public_cert.pem', @@project_dir) + signer = Gem::Security::Signer.new @private_key, [@public_cert] open @file, 'wb' do |tar_io| diff --git a/test/rubygems/test_gem_remote_fetcher.rb b/test/rubygems/test_gem_remote_fetcher.rb index 135b2c7e53..66fb682c6c 100644 --- a/test/rubygems/test_gem_remote_fetcher.rb +++ b/test/rubygems/test_gem_remote_fetcher.rb @@ -99,9 +99,10 @@ gems: # REFACTOR: copied from test_gem_dependency_installer.rb @gems_dir = File.join @tempdir, 'gems' - @cache_dir = File.join @gemhome, 'cache' + @cache_dir = Gem.cache_dir(@gemhome) FileUtils.mkdir @gems_dir + # TODO: why does the remote fetcher need it written to disk? @a1, @a1_gem = util_gem 'a', '1' do |s| s.executables << 'a_bin' end Gem::RemoteFetcher.fetcher = nil @@ -208,7 +209,7 @@ gems: fetcher = util_fuck_with_fetcher a1_data - a1_cache_gem = File.join(@gemhome, 'cache', @a1.file_name) + a1_cache_gem = Gem.cache_gem(@a1.file_name, @gemhome) assert_equal a1_cache_gem, fetcher.download(@a1, 'http://gems.example.com') assert_equal("http://gems.example.com/gems/a-1.gem", fetcher.instance_variable_get(:@test_arg).to_s) @@ -220,7 +221,7 @@ gems: inst = Gem::RemoteFetcher.fetcher - assert_equal File.join(@gemhome, 'cache', @a1.file_name), + assert_equal Gem.cache_gem(@a1.file_name, @gemhome), inst.download(@a1, 'http://gems.example.com') end @@ -233,7 +234,7 @@ gems: inst = Gem::RemoteFetcher.fetcher end - assert_equal File.join(@gemhome, 'cache', @a1.file_name), + assert_equal Gem.cache_gem(@a1.file_name, @gemhome), inst.download(@a1, local_path) end @@ -248,7 +249,7 @@ gems: inst = Gem::RemoteFetcher.fetcher end - assert_equal File.join(@gemhome, 'cache', @a1.file_name), + assert_equal Gem.cache_gem(@a1.file_name, @gemhome), inst.download(@a1, local_path) end @@ -262,7 +263,7 @@ gems: install_dir = File.join @tempdir, 'more_gems' - a1_cache_gem = File.join install_dir, 'cache', @a1.file_name + a1_cache_gem = Gem.cache_gem(@a1.file_name, install_dir) FileUtils.mkdir_p(File.dirname(a1_cache_gem)) actual = fetcher.download(@a1, 'http://gems.example.com', install_dir) @@ -278,7 +279,7 @@ gems: FileUtils.mv @a1_gem, @tempdir local_path = File.join @tempdir, @a1.file_name inst = nil - File.chmod 0555, File.join(@gemhome, 'cache') + File.chmod 0555, Gem.cache_dir(@gemhome) Dir.chdir @tempdir do inst = Gem::RemoteFetcher.fetcher @@ -287,19 +288,19 @@ gems: assert_equal File.join(@tempdir, @a1.file_name), inst.download(@a1, local_path) ensure - File.chmod 0755, File.join(@gemhome, 'cache') + File.chmod 0755, Gem.cache_dir(@gemhome) end def test_download_read_only - File.chmod 0555, File.join(@gemhome, 'cache') + File.chmod 0555, Gem.cache_dir(@gemhome) 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(Gem.user_dir, 'cache', @a1.file_name)) + assert File.exist?(Gem.cache_gem(@a1.file_name, Gem.user_dir)) ensure - File.chmod 0755, File.join(@gemhome) - File.chmod 0755, File.join(@gemhome, 'cache') + File.chmod 0755, @gemhome + File.chmod 0755, Gem.cache_dir(@gemhome) end end @@ -318,7 +319,7 @@ gems: fetcher = util_fuck_with_fetcher e1_data, :blow_chunks - e1_cache_gem = File.join(@gemhome, 'cache', e1.file_name) + e1_cache_gem = Gem.cache_gem(e1.file_name, @gemhome) assert_equal e1_cache_gem, fetcher.download(e1, 'http://gems.example.com') @@ -336,7 +337,7 @@ gems: inst = Gem::RemoteFetcher.fetcher end - cache_path = File.join @gemhome, 'cache', @a1.file_name + cache_path = Gem.cache_gem(@a1.file_name, @gemhome) FileUtils.mv local_path, cache_path gem = Gem::Format.from_file_by_path cache_path @@ -744,5 +745,13 @@ gems: end end + def test_correct_for_windows_path + path = "/C:/WINDOWS/Temp/gems" + assert_equal "C:/WINDOWS/Temp/gems", @fetcher.correct_for_windows_path(path) + + path = "/home/skillet" + assert_equal "/home/skillet", @fetcher.correct_for_windows_path(path) + end + end diff --git a/test/rubygems/test_gem_security.rb b/test/rubygems/test_gem_security.rb index bb579d7927..62156be4f5 100644 --- a/test/rubygems/test_gem_security.rb +++ b/test/rubygems/test_gem_security.rb @@ -6,6 +6,7 @@ require 'rubygems/test_case' require 'rubygems/security' +require 'rubygems/fix_openssl_warnings' if RUBY_VERSION < "1.9" class TestGemSecurity < Gem::TestCase diff --git a/test/rubygems/test_gem_silent_ui.rb b/test/rubygems/test_gem_silent_ui.rb new file mode 100644 index 0000000000..1968a89b28 --- /dev/null +++ b/test/rubygems/test_gem_silent_ui.rb @@ -0,0 +1,117 @@ +###################################################################### +# This file is imported from the rubygems project. +# DO NOT make modifications in this repo. They _will_ be reverted! +# File a patch instead and assign it to Ryan Davis or Eric Hodel. +###################################################################### + +require 'rubygems/test_case' +require 'rubygems/user_interaction' +require 'timeout' + +class TestGemSilentUI < Gem::TestCase + + def setup + super + @sui = Gem::SilentUI.new + end + + def test_ask + value = nil + out, err = capture_io do + use_ui @sui do + value = @sui.ask 'Problem?' + end + end + + assert_empty out, 'No output' + assert_empty err, 'No output' + + assert_nil value, 'No value' + end + + def test_ask_for_password + value = nil + out, err = capture_io do + use_ui @sui do + value = @sui.ask_for_password 'Problem?' + end + end + + assert_empty out, 'No output' + assert_empty err, 'No output' + + assert_nil value, 'No value' + end + + def test_ask_yes_no + value = nil + out, err = capture_io do + use_ui @sui do + assert_raises(Gem::OperationNotSupportedError) do + @sui.ask_yes_no 'Problem?' + end + end + end + + assert_empty out, 'No output' + assert_empty err, 'No output' + + out, err = capture_io do + use_ui @sui do + value = @sui.ask_yes_no 'Problem?', true + end + end + + assert_empty out, 'No output' + assert_empty err, 'No output' + + assert value, 'Value is true' + + out, err = capture_io do + use_ui @sui do + value = @sui.ask_yes_no 'Problem?', false + end + end + + assert_empty out, 'No output' + assert_empty err, 'No output' + + assert_equal value, false, 'Value is false' + end + + def test_choose_from_list + value = nil + out, err = capture_io do + use_ui @sui do + value = @sui.choose_from_list 'Problem?', %w[yes no] + end + end + + assert_empty out, 'No output' + assert_empty err, 'No output' + + assert_equal [nil, nil], value, 'Value is nil!' + end + + def test_progress_reporter + out, err = capture_io do + use_ui @sui do + @sui.progress_reporter 10, 'hi' + end + end + + assert_empty out, 'No output' + assert_empty err, 'No output' + end + + def test_download_reporter + out, err = capture_io do + use_ui @sui do + @sui.download_reporter.fetch 'a.gem', 1024 + end + end + + assert_empty out, 'No output' + assert_empty err, 'No output' + end +end diff --git a/test/rubygems/test_gem_source_index.rb b/test/rubygems/test_gem_source_index.rb index 9846c9cc89..89e2ea3894 100644 --- a/test/rubygems/test_gem_source_index.rb +++ b/test/rubygems/test_gem_source_index.rb @@ -23,7 +23,7 @@ class TestGemSourceIndex < Gem::TestCase FileUtils.mkdir_p spec_dir - a1 = quick_gem 'a', '1' do |spec| spec.author = 'author 1' end + a1 = quick_spec 'a', '1' do |spec| spec.author = 'author 1' end spec_file = File.join spec_dir, a1.spec_name @@ -44,7 +44,7 @@ class TestGemSourceIndex < Gem::TestCase FileUtils.mkdir_p spec_dir - a1 = quick_gem 'a', '1' do |spec| spec.author = 'author 1' end + a1 = quick_spec 'a', '1' do |spec| spec.author = 'author 1' end spec_file = File.join spec_dir, a1.spec_name @@ -214,24 +214,24 @@ end end def test_latest_specs - p1_ruby = quick_gem 'p', '1' - p1_platform = quick_gem 'p', '1' do |spec| + p1_ruby = quick_spec 'p', '1' + p1_platform = quick_spec 'p', '1' do |spec| spec.platform = Gem::Platform::CURRENT end - a1_platform = quick_gem @a1.name, (@a1.version) do |s| + a1_platform = quick_spec @a1.name, (@a1.version) do |s| s.platform = Gem::Platform.new 'x86-my_platform1' end - a2_platform = quick_gem @a2.name, (@a2.version) do |s| + a2_platform = quick_spec @a2.name, (@a2.version) do |s| s.platform = Gem::Platform.new 'x86-my_platform1' end - a2_platform_other = quick_gem @a2.name, (@a2.version) do |s| + a2_platform_other = quick_spec @a2.name, (@a2.version) do |s| s.platform = Gem::Platform.new 'x86-other_platform1' end - a3_platform_other = quick_gem @a2.name, (@a2.version.bump) do |s| + a3_platform_other = quick_spec @a2.name, (@a2.version.bump) do |s| s.platform = Gem::Platform.new 'x86-other_platform1' end @@ -266,8 +266,8 @@ end FileUtils.mkdir_p spec_dir1 FileUtils.mkdir_p spec_dir2 - a1 = quick_gem 'a', '1' do |spec| spec.author = 'author 1' end - a2 = quick_gem 'a', '1' do |spec| spec.author = 'author 2' end + a1 = quick_spec 'a', '1' do |spec| spec.author = 'author 1' end + a2 = quick_spec 'a', '1' do |spec| spec.author = 'author 2' end File.open File.join(spec_dir1, a1.spec_name), 'w' do |fp| fp.write a1.to_ruby @@ -287,12 +287,12 @@ end assert_equal [], @source_index.outdated - updated = quick_gem @a2.name, (@a2.version.bump) + updated = quick_spec @a2.name, (@a2.version.bump) util_setup_spec_fetcher updated assert_equal [updated.name], @source_index.outdated - updated_platform = quick_gem @a2.name, (updated.version.bump) do |s| + updated_platform = quick_spec @a2.name, (updated.version.bump) do |s| s.platform = Gem::Platform.new 'x86-other_platform1' end @@ -302,10 +302,11 @@ end end def test_prerelease_specs_kept_in_right_place - gem_a1_alpha = quick_gem 'abba', '1.a' + gem_a1_alpha = quick_spec 'abba', '1.a' @source_index.add_spec gem_a1_alpha refute @source_index.latest_specs.include?(gem_a1_alpha) + assert @source_index.latest_specs(true).include?(gem_a1_alpha) assert @source_index.find_name(gem_a1_alpha.full_name).empty? assert @source_index.prerelease_specs.include?(gem_a1_alpha) end @@ -363,11 +364,11 @@ end def test_search_platform util_set_arch 'x86-my_platform1' - a1 = quick_gem 'a', '1' - a1_mine = quick_gem 'a', '1' do |s| + a1 = quick_spec 'a', '1' + a1_mine = quick_spec 'a', '1' do |s| s.platform = Gem::Platform.new 'x86-my_platform1' end - a1_other = quick_gem 'a', '1' do |s| + a1_other = quick_spec 'a', '1' do |s| s.platform = Gem::Platform.new 'x86-other_platform1' end diff --git a/test/rubygems/test_gem_spec_fetcher.rb b/test/rubygems/test_gem_spec_fetcher.rb index 6e3891b866..57983a2752 100644 --- a/test/rubygems/test_gem_spec_fetcher.rb +++ b/test/rubygems/test_gem_spec_fetcher.rb @@ -16,7 +16,7 @@ class TestGemSpecFetcher < Gem::TestCase util_setup_fake_fetcher - @a_pre = quick_gem 'a', '1.a' + @a_pre = quick_spec 'a', '1.a' @source_index.add_spec @pl1 @source_index.add_spec @a_pre @@ -412,5 +412,10 @@ class TestGemSpecFetcher < Gem::TestCase assert_equal @latest_specs, latest_specs end + def test_cache_dir_escapes_windows_paths + uri = URI.parse("file:///C:/WINDOWS/Temp/gem_repo") + cache_dir = @sf.cache_dir(uri) + assert cache_dir !~ /:/, "#{cache_dir} should not contain a :" + end end diff --git a/test/rubygems/test_gem_specification.rb b/test/rubygems/test_gem_specification.rb index 49862fe4bb..f820d7c1c3 100644 --- a/test/rubygems/test_gem_specification.rb +++ b/test/rubygems/test_gem_specification.rb @@ -46,6 +46,7 @@ end def setup super + # TODO: there is no reason why the spec tests need to write to disk @a1 = quick_gem 'a', '1' do |s| s.executable = 'exec' s.extensions << 'ext/a/extconf.rb' @@ -167,6 +168,13 @@ end Gem::Specification.normalize_yaml_input(StringIO.new(input)) end + def test_self_normalize_yaml_input_with_192_yaml + input = "--- !ruby/object:Gem::Specification \nblah: !!null \n" + expected = "--- !ruby/object:Gem::Specification \nblah: \n" + + assert_equal expected, Gem::Specification.normalize_yaml_input(input) + end + def test_initialize spec = Gem::Specification.new do |s| s.name = "blah" @@ -294,7 +302,7 @@ end end def test_add_dependency_with_explicit_type - gem = quick_gem "awesome", "1.0" do |awesome| + gem = quick_spec "awesome", "1.0" do |awesome| awesome.add_development_dependency "monkey" end @@ -371,18 +379,19 @@ end assert_equal [rake, jabber, pqa], @a1.dependencies end - def test_dependencies_scoped_by_type - gem = quick_gem "awesome", "1.0" do |awesome| - awesome.add_runtime_dependency "bonobo", [] - awesome.add_development_dependency "monkey", [] - end + def test_dependencies + util_setup_deps + assert_equal [@bonobo, @monkey], @gem.dependencies + end - bonobo = Gem::Dependency.new("bonobo", []) - monkey = Gem::Dependency.new("monkey", [], :development) + def test_runtime_dependencies + util_setup_deps + assert_equal [@bonobo], @gem.runtime_dependencies + end - assert_equal([bonobo, monkey], gem.dependencies) - assert_equal([bonobo], gem.runtime_dependencies) - assert_equal([monkey], gem.development_dependencies) + def test_development_dependencies + util_setup_deps + assert_equal [@monkey], @gem.development_dependencies end def test_description @@ -390,8 +399,8 @@ end end def test_eql_eh - g1 = quick_gem 'gem' - g2 = quick_gem 'gem' + g1 = quick_spec 'gem' + g2 = quick_spec 'gem' assert_equal g1, g2 assert_equal g1.hash, g2.hash @@ -690,7 +699,7 @@ end end def test_prerelease_spec_adds_required_rubygems_version - @prerelease = quick_gem('tardis', '2.2.0.a') + @prerelease = quick_spec('tardis', '2.2.0.a') refute @prerelease.required_rubygems_version.satisfied_by?(Gem::Version.new('1.3.1')) assert @prerelease.required_rubygems_version.satisfied_by?(Gem::Version.new('1.4.0')) end @@ -716,8 +725,8 @@ end end def test_spaceship_name - s1 = quick_gem 'a', '1' - s2 = quick_gem 'b', '1' + s1 = quick_spec 'a', '1' + s2 = quick_spec 'b', '1' assert_equal(-1, (s1 <=> s2)) assert_equal( 0, (s1 <=> s1)) @@ -725,8 +734,8 @@ end end def test_spaceship_platform - s1 = quick_gem 'a', '1' - s2 = quick_gem 'a', '1' do |s| + s1 = quick_spec 'a', '1' + s2 = quick_spec 'a', '1' do |s| s.platform = Gem::Platform.new 'x86-my_platform1' end @@ -736,8 +745,8 @@ end end def test_spaceship_version - s1 = quick_gem 'a', '1' - s2 = quick_gem 'a', '2' + s1 = quick_spec 'a', '1' + s2 = quick_spec 'a', '2' assert_equal( -1, (s1 <=> s2)) assert_equal( 0, (s1 <=> s1)) @@ -803,6 +812,54 @@ end assert_equal @a2, same_spec end + def test_to_ruby_for_cache + @a2.add_runtime_dependency 'b', '1' + @a2.dependencies.first.instance_variable_set :@type, nil + @a2.required_rubygems_version = Gem::Requirement.new '> 0' + + # cached specs do not have spec.files populated: + ruby_code = @a2.to_ruby_for_cache + + expected = <<-SPEC +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{a} + s.version = \"2\" + + s.required_rubygems_version = Gem::Requirement.new(\"> 0\") if s.respond_to? :required_rubygems_version= + s.authors = [\"A User\"] + s.date = %q{#{Gem::Specification::TODAY.strftime "%Y-%m-%d"}} + s.description = %q{This is a test description} + s.email = %q{example@example.com} + s.homepage = %q{http://example.com} + s.require_paths = [\"lib\"] + s.rubygems_version = %q{#{Gem::VERSION}} + s.summary = %q{this is a summary} + + if s.respond_to? :specification_version then + s.specification_version = #{Gem::Specification::CURRENT_SPECIFICATION_VERSION} + + if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then + s.add_runtime_dependency(%q, [\"= 1\"]) + else + s.add_dependency(%q, [\"= 1\"]) + end + else + s.add_dependency(%q, [\"= 1\"]) + end +end + SPEC + + assert_equal expected, ruby_code + + same_spec = eval ruby_code + + # cached specs do not have spec.files populated: + @a2.files = [] + assert_equal @a2, same_spec + end + def test_to_ruby_fancy @a1.platform = Gem::Platform.local ruby_code = @a1.to_ruby @@ -842,16 +899,16 @@ Gem::Specification.new do |s| if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_runtime_dependency(%q, [\"> 0.4\"]) s.add_runtime_dependency(%q, [\"> 0.0.0\"]) - s.add_runtime_dependency(%q, [\"> 0.4\", \"<= 0.6\"]) + s.add_runtime_dependency(%q, [\"<= 0.6\", \"> 0.4\"]) else s.add_dependency(%q, [\"> 0.4\"]) s.add_dependency(%q, [\"> 0.0.0\"]) - s.add_dependency(%q, [\"> 0.4\", \"<= 0.6\"]) + s.add_dependency(%q, [\"<= 0.6\", \"> 0.4\"]) end else s.add_dependency(%q, [\"> 0.4\"]) s.add_dependency(%q, [\"> 0.0.0\"]) - s.add_dependency(%q, [\"> 0.4\", \"<= 0.6\"]) + s.add_dependency(%q, [\"<= 0.6\", \"> 0.4\"]) end end SPEC @@ -884,6 +941,9 @@ end def test_to_yaml yaml_str = @a1.to_yaml + + refute_match '!!null', yaml_str + same_spec = YAML.load(yaml_str) assert_equal @a1, same_spec @@ -1258,6 +1318,16 @@ end specfile.delete end + def util_setup_deps + @gem = quick_spec "awesome", "1.0" do |awesome| + awesome.add_runtime_dependency "bonobo", [] + awesome.add_development_dependency "monkey", [] + end + + @bonobo = Gem::Dependency.new("bonobo", []) + @monkey = Gem::Dependency.new("monkey", [], :development) + end + def util_setup_validate Dir.chdir @tempdir do FileUtils.mkdir_p File.join('ext', 'a') @@ -1269,6 +1339,4 @@ end FileUtils.touch File.join('test', 'suite.rb') end end - end - diff --git a/test/rubygems/test_gem_uninstaller.rb b/test/rubygems/test_gem_uninstaller.rb index 3925ab1a63..0c08f42d01 100644 --- a/test/rubygems/test_gem_uninstaller.rb +++ b/test/rubygems/test_gem_uninstaller.rb @@ -12,19 +12,19 @@ class TestGemUninstaller < Gem::InstallerTestCase def setup super - @user_spec.executables = ["my_exec"] + @user_spec.executables = ["executable"] # HACK util_make_exec user_bin_dir = File.join Gem.user_dir, 'gems', @user_spec.full_name, 'bin' FileUtils.mkdir_p user_bin_dir - exec_path = File.join user_bin_dir, "my_exec" + exec_path = File.join user_bin_dir, "executable" open exec_path, 'w' do |f| f.puts "#!/usr/bin/ruby" end user_bin_dir = File.join Gem.user_dir, 'bin' FileUtils.mkdir_p user_bin_dir - exec_path = File.join user_bin_dir, "my_exec" + exec_path = File.join user_bin_dir, "executable" open exec_path, 'w' do |f| f.puts "#!/usr/bin/ruby" end @@ -47,8 +47,8 @@ class TestGemUninstaller < Gem::InstallerTestCase def test_remove_executables_force_keep uninstaller = Gem::Uninstaller.new nil, :executables => false - executable = File.join Gem.user_dir, 'bin', 'my_exec' - assert File.exist? executable + executable = File.join Gem.user_dir, 'bin', 'executable' + assert File.exist?(executable), 'executable not written' use_ui @ui do uninstaller.remove_executables @user_spec @@ -62,14 +62,14 @@ class TestGemUninstaller < Gem::InstallerTestCase def test_remove_executables_force_remove uninstaller = Gem::Uninstaller.new nil, :executables => true - executable = File.join Gem.user_dir, 'bin', 'my_exec' - assert File.exist? executable + executable = File.join Gem.user_dir, 'bin', 'executable' + assert File.exist?(executable), 'executable not written' use_ui @ui do uninstaller.remove_executables @user_spec end - assert_equal "Removing my_exec\n", @ui.output + assert_equal "Removing executable\n", @ui.output refute File.exist? executable end @@ -81,12 +81,47 @@ class TestGemUninstaller < Gem::InstallerTestCase uninstaller.remove_executables @user_spec end - exec_path = File.join Gem.user_dir, 'bin', 'my_exec' + exec_path = File.join Gem.user_dir, 'bin', 'executable' assert_equal false, File.exist?(exec_path), 'removed exec from bin dir' - assert_equal "Removing my_exec\n", @ui.output + assert_equal "Removing executable\n", @ui.output end + def test_remove_executables_user_format + Gem::Installer.exec_format = 'foo-%s-bar' + + uninstaller = Gem::Uninstaller.new nil, :executables => true, :format_executable => true + + use_ui @ui do + uninstaller.remove_executables @user_spec + end + + exec_path = File.join Gem.user_dir, 'bin', 'foo-executable-bar' + assert_equal false, File.exist?(exec_path), 'removed exec from bin dir' + + assert_equal "Removing executable\n", @ui.output + ensure + Gem::Installer.exec_format = nil + end + + def test_remove_executables_user_format_disabled + Gem::Installer.exec_format = 'foo-%s-bar' + + uninstaller = Gem::Uninstaller.new nil, :executables => true + + use_ui @ui do + uninstaller.remove_executables @user_spec + end + + exec_path = File.join Gem.user_dir, 'bin', 'executable' + assert_equal false, File.exist?(exec_path), 'removed exec from bin dir' + + assert_equal "Removing executable\n", @ui.output + ensure + Gem::Installer.exec_format = nil + end + + def test_path_ok_eh uninstaller = Gem::Uninstaller.new nil @@ -129,6 +164,31 @@ class TestGemUninstaller < Gem::InstallerTestCase assert_same uninstaller, @post_uninstall_hook_arg end + def test_uninstall_not_ok + quick_gem 'z' do |s| + s.add_runtime_dependency @spec.name + end + + uninstaller = Gem::Uninstaller.new @spec.name + + gem_dir = File.join @gemhome, 'gems', @spec.full_name + executable = File.join @gemhome, 'bin', 'executable' + + assert File.exist?(gem_dir), 'gem_dir must exist' + assert File.exist?(executable), 'executable must exist' + + ui = Gem::MockGemUi.new "n\n" + + assert_raises Gem::DependencyRemovalException do + use_ui ui do + uninstaller.uninstall + end + end + + assert File.exist?(gem_dir), 'gem_dir must still exist' + assert File.exist?(executable), 'executable must still exist' + end + def test_uninstall_user uninstaller = Gem::Uninstaller.new @user_spec.name, :executables => true, :user_install => true diff --git a/test/rubygems/test_gem_validator.rb b/test/rubygems/test_gem_validator.rb index aa4bd38eb6..304c141483 100644 --- a/test/rubygems/test_gem_validator.rb +++ b/test/rubygems/test_gem_validator.rb @@ -5,7 +5,7 @@ ###################################################################### require 'rubygems/test_case' -require "test/rubygems/simple_gem" +require "rubygems/simple_gem" require 'rubygems/validator' class TestGemValidator < Gem::TestCase diff --git a/test/rubygems/test_kernel.rb b/test/rubygems/test_kernel.rb index 98d27a6123..d3714a2c59 100644 --- a/test/rubygems/test_kernel.rb +++ b/test/rubygems/test_kernel.rb @@ -46,7 +46,7 @@ class TestKernel < Gem::TestCase gem 'a', '= 2' end - assert_match(/activate a \(= 2, runtime\)/, ex.message) + assert_match(/activate a \(= 2\)/, ex.message) assert_match(/activated a-1/, ex.message) assert_equal 'a', ex.name assert_equal Gem::Requirement.new('= 2'), ex.requirement -- cgit v1.2.3