summaryrefslogtreecommitdiff
path: root/lib/rubygems/uninstaller.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rubygems/uninstaller.rb')
-rw-r--r--lib/rubygems/uninstaller.rb115
1 files changed, 74 insertions, 41 deletions
diff --git a/lib/rubygems/uninstaller.rb b/lib/rubygems/uninstaller.rb
index 51ac3494f3..c96df2a085 100644
--- a/lib/rubygems/uninstaller.rb
+++ b/lib/rubygems/uninstaller.rb
@@ -1,16 +1,17 @@
# frozen_string_literal: true
+
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++
-require 'fileutils'
-require 'rubygems'
-require 'rubygems/installer_uninstaller_utils'
-require 'rubygems/dependency_list'
-require 'rubygems/rdoc'
-require 'rubygems/user_interaction'
+require "fileutils"
+require_relative "../rubygems"
+require_relative "installer_uninstaller_utils"
+require_relative "dependency_list"
+require_relative "rdoc"
+require_relative "user_interaction"
##
# An Uninstaller.
@@ -45,7 +46,7 @@ class Gem::Uninstaller
# Constructs an uninstaller that will uninstall +gem+
def initialize(gem, options = {})
- # TODO document the valid options
+ # TODO: document the valid options
@gem = gem
@version = options[:version] || Gem::Requirement.default
@gem_home = File.realpath(options[:install_dir] || Gem.dir)
@@ -70,6 +71,9 @@ class Gem::Uninstaller
# only add user directory if install_dir is not set
@user_install = false
@user_install = options[:user_install] unless options[:install_dir]
+
+ # Optimization: populated during #uninstall
+ @default_specs_matching_uninstall_params = []
end
##
@@ -95,17 +99,13 @@ class Gem::Uninstaller
raise Gem::InstallError, "gem #{@gem.inspect} is not installed"
end
- default_specs, list = list.partition do |spec|
- spec.default_gem?
- end
-
- default_specs.each do |default_spec|
- say "Gem #{default_spec.full_name} cannot be uninstalled because it is a default gem"
- end
+ default_specs, list = list.partition(&:default_gem?)
+ warn_cannot_uninstall_default_gems(default_specs - list)
+ @default_specs_matching_uninstall_params = default_specs
list, other_repo_specs = list.partition do |spec|
- @gem_home == spec.base_dir or
- (@user_install and spec.base_dir == Gem.user_dir)
+ @gem_home == spec.base_dir ||
+ (@user_install && spec.base_dir == Gem.user_dir)
end
list.sort!
@@ -113,7 +113,7 @@ class Gem::Uninstaller
if list.empty?
return unless other_repo_specs.any?
- other_repos = other_repo_specs.map {|spec| spec.base_dir }.uniq
+ other_repos = other_repo_specs.map(&:base_dir).uniq
message = ["#{@gem} is not installed in GEM_HOME, try:"]
message.concat other_repos.map {|repo|
@@ -125,7 +125,7 @@ class Gem::Uninstaller
remove_all list
elsif list.size > 1
- gem_names = list.map {|gem| gem.full_name }
+ gem_names = list.map(&:full_name)
gem_names << "All versions"
say
@@ -133,7 +133,7 @@ class Gem::Uninstaller
if index == list.size
remove_all list
- elsif index >= 0 && index < list.size
+ elsif index && index >= 0 && index < list.size
uninstall_gem list[index]
else
say "Error: must enter a number [1-#{list.size + 1}]"
@@ -199,13 +199,13 @@ class Gem::Uninstaller
executables = executables.map {|exec| formatted_program_filename exec }
remove = if @force_executables.nil?
- ask_yes_no("Remove executables:\n" +
- "\t#{executables.join ', '}\n\n" +
- "in addition to the gem?",
- true)
- else
- @force_executables
- end
+ ask_yes_no("Remove executables:\n" \
+ "\t#{executables.join ", "}\n\n" \
+ "in addition to the gem?",
+ true)
+ else
+ @force_executables
+ end
if remove
bin_dir = @bin_dir || Gem.bindir(spec.base_dir)
@@ -238,10 +238,10 @@ class Gem::Uninstaller
# spec:: the spec of the gem to be uninstalled
def remove(spec)
- unless path_ok?(@gem_home, spec) or
- (@user_install and path_ok?(Gem.user_dir, spec))
+ unless path_ok?(@gem_home, spec) ||
+ (@user_install && path_ok?(Gem.user_dir, spec))
e = Gem::GemNotInHomeException.new \
- "Gem '#{spec.full_name}' is not installed in directory #{@gem_home}"
+ "Gem '#{spec.full_name}' is not installed in directory #{@gem_home}"
e.spec = spec
raise e
@@ -261,7 +261,10 @@ class Gem::Uninstaller
safe_delete { FileUtils.rm_r gem }
- Gem::RDoc.new(spec).remove
+ begin
+ Gem::RDoc.new(spec).remove
+ rescue NameError
+ end
gemspec = spec.spec_file
@@ -270,7 +273,7 @@ class Gem::Uninstaller
end
safe_delete { FileUtils.rm_r gemspec }
- say "Successfully uninstalled #{spec.full_name}"
+ announce_deletion_of(spec)
Gem::Specification.reset
end
@@ -298,8 +301,8 @@ class Gem::Uninstaller
# Is +spec+ in +gem_dir+?
def path_ok?(gem_dir, spec)
- full_path = File.join gem_dir, 'gems', spec.full_name
- original_path = File.join gem_dir, 'gems', spec.original_name
+ full_path = File.join gem_dir, "gems", spec.full_name
+ original_path = File.join gem_dir, "gems", spec.original_name
full_path == spec.full_gem_path || original_path == spec.full_gem_path
end
@@ -328,24 +331,24 @@ class Gem::Uninstaller
# Asks if it is OK to remove +spec+. Returns true if it is OK.
def ask_if_ok(spec) # :nodoc:
- msg = ['']
- msg << 'You have requested to uninstall the gem:'
+ msg = [""]
+ msg << "You have requested to uninstall the gem:"
msg << "\t#{spec.full_name}"
- msg << ''
+ msg << ""
siblings = Gem::Specification.select do |s|
s.name == spec.name && s.full_name != spec.full_name
end
- spec.dependent_gems(@check_dev).each do |dep_spec, dep, satlist|
+ spec.dependent_gems(@check_dev).each do |dep_spec, dep, _satlist|
unless siblings.any? {|s| s.satisfies_requirement? dep }
msg << "#{dep_spec.name}-#{dep_spec.version} depends on #{dep}"
end
end
- msg << 'If you remove this gem, these dependencies will not be met.'
- msg << 'Continue with Uninstall?'
- return ask_yes_no(msg.join("\n"), false)
+ msg << "If you remove this gem, these dependencies will not be met."
+ msg << "Continue with Uninstall?"
+ ask_yes_no(msg.join("\n"), false)
end
##
@@ -356,7 +359,7 @@ class Gem::Uninstaller
# of what it did for us to find rather than trying to recreate
# it again.
if @format_executable
- require 'rubygems/installer'
+ require_relative "installer"
Gem::Installer.exec_format % File.basename(filename)
else
filename
@@ -373,4 +376,34 @@ class Gem::Uninstaller
raise e
end
+
+ private
+
+ def announce_deletion_of(spec)
+ name = spec.full_name
+ say "Successfully uninstalled #{name}"
+ if default_spec_matches?(spec)
+ say(
+ "There was both a regular copy and a default copy of #{name}. The " \
+ "regular copy was successfully uninstalled, but the default copy " \
+ "was left around because default gems can't be removed."
+ )
+ end
+ end
+
+ # @return true if the specs of any default gems are `==` to the given `spec`.
+ def default_spec_matches?(spec)
+ !default_specs_that_match(spec).empty?
+ end
+
+ # @return [Array] specs of default gems that are `==` to the given `spec`.
+ def default_specs_that_match(spec)
+ @default_specs_matching_uninstall_params.select {|default_spec| spec == default_spec }
+ end
+
+ def warn_cannot_uninstall_default_gems(specs)
+ specs.each do |spec|
+ say "Gem #{spec.full_name} cannot be uninstalled because it is a default gem"
+ end
+ end
end