Class | Gem::Uninstaller |
In: |
lib/rubygems/uninstaller.rb
|
Parent: | Object |
An Uninstaller.
The uninstaller fires pre and post uninstall hooks. Hooks can be added either through a rubygems_plugin.rb file in an installed gem or via a rubygems/defaults/#{RUBY_ENGINE}.rb or rubygems/defaults/operating_system.rb file. See Gem.pre_uninstall and Gem.post_uninstall for details.
bin_dir | [R] | The directory a gem‘s executables will be installed into |
gem_home | [R] | The gem repository the gem will be installed into |
spec | [R] | The Gem::Specification for the gem being uninstalled, only set during uninstall_gem |
Constructs an uninstaller that will uninstall gem
# File lib/rubygems/uninstaller.rb, line 44 44: def initialize(gem, options = {}) 45: @gem = gem 46: @version = options[:version] || Gem::Requirement.default 47: @gem_home = File.expand_path(options[:install_dir] || Gem.dir) 48: @force_executables = options[:executables] 49: @force_all = options[:all] 50: @force_ignore = options[:ignore] 51: @bin_dir = options[:bin_dir] 52: @format_executable = options[:format_executable] 53: 54: # only add user directory if install_dir is not set 55: @user_install = false 56: @user_install = options[:user_install] unless options[:install_dir] 57: 58: if @user_install then 59: Gem.use_paths Gem.user_dir, @gem_home 60: else 61: Gem.use_paths @gem_home 62: end 63: end
# File lib/rubygems/uninstaller.rb, line 247 247: def ask_if_ok(spec) 248: msg = [''] 249: msg << 'You have requested to uninstall the gem:' 250: msg << "\t#{spec.full_name}" 251: 252: spec.dependent_gems.each do |dep_spec, dep, satlist| 253: msg << 254: ("#{dep_spec.name}-#{dep_spec.version} depends on " + 255: "[#{dep.name} (#{dep.requirement})]") 256: end 257: 258: msg << 'If you remove this gems, one or more dependencies will not be met.' 259: msg << 'Continue with Uninstall?' 260: return ask_yes_no(msg.join("\n"), true) 261: end
# File lib/rubygems/uninstaller.rb, line 240 240: def dependencies_ok?(spec) 241: return true if @force_ignore 242: 243: deplist = Gem::DependencyList.from_specs 244: deplist.ok_to_remove?(spec.full_name) 245: end
# File lib/rubygems/uninstaller.rb, line 263 263: def formatted_program_filename(filename) 264: if @format_executable then 265: require 'rubygems/installer' 266: Gem::Installer.exec_format % File.basename(filename) 267: else 268: filename 269: end 270: end
Is spec in gem_dir?
# File lib/rubygems/uninstaller.rb, line 233 233: def path_ok?(gem_dir, spec) 234: full_path = File.join gem_dir, 'gems', spec.full_name 235: original_path = File.join gem_dir, 'gems', spec.original_name 236: 237: full_path == spec.full_gem_path || original_path == spec.full_gem_path 238: end
spec: | the spec of the gem to be uninstalled |
list: | the list of all such gems |
Warning: this method modifies the list parameter. Once it has uninstalled a gem, it is removed from that list.
# File lib/rubygems/uninstaller.rb, line 189 189: def remove(spec) 190: unless path_ok?(@gem_home, spec) or 191: (@user_install and path_ok?(Gem.user_dir, spec)) then 192: e = Gem::GemNotInHomeException.new \ 193: "Gem is not installed in directory #{@gem_home}" 194: e.spec = spec 195: 196: raise e 197: end 198: 199: raise Gem::FilePermissionError, spec.base_dir unless 200: File.writable?(spec.base_dir) 201: 202: FileUtils.rm_rf spec.full_gem_path 203: 204: # TODO: should this be moved to spec?... I vote eww (also exists in docmgr) 205: old_platform_name = [spec.name, 206: spec.version, 207: spec.original_platform].join '-' 208: 209: gemspec = spec.spec_file 210: 211: unless File.exist? gemspec then 212: gemspec = File.join(File.dirname(gemspec), "#{old_platform_name}.gemspec") 213: end 214: 215: FileUtils.rm_rf gemspec 216: 217: gem = spec.cache_file 218: gem = File.join(spec.cache_dir, "#{old_platform_name}.gem") unless 219: File.exist? gem 220: 221: FileUtils.rm_rf gem 222: 223: Gem::DocManager.new(spec).uninstall_doc 224: 225: say "Successfully uninstalled #{spec.full_name}" 226: 227: Gem::Specification.remove_spec spec 228: end
Removes all gems in list.
NOTE: removes uninstalled gems from list.
# File lib/rubygems/uninstaller.rb, line 178 178: def remove_all(list) 179: list.each { |spec| uninstall_gem spec } 180: end
Removes installed executables and batch files (windows only) for gemspec.
# File lib/rubygems/uninstaller.rb, line 127 127: def remove_executables(spec) 128: return if spec.nil? or spec.executables.empty? 129: 130: list = Gem::Specification.find_all { |s| 131: s.name == spec.name && s.version != spec.version 132: } 133: 134: executables = spec.executables.clone 135: 136: list.each do |s| 137: s.executables.each do |exe_name| 138: executables.delete exe_name 139: end 140: end 141: 142: return if executables.empty? 143: 144: executables = executables.map { |exec| formatted_program_filename exec } 145: 146: remove = if @force_executables.nil? then 147: ask_yes_no("Remove executables:\n" \ 148: "\t#{executables.join ', '}\n\n" \ 149: "in addition to the gem?", 150: true) 151: else 152: @force_executables 153: end 154: 155: unless remove then 156: say "Executables and scripts will remain installed." 157: else 158: bin_dir = @bin_dir || Gem.bindir(spec.base_dir) 159: 160: raise Gem::FilePermissionError, bin_dir unless File.writable? bin_dir 161: 162: executables.each do |exe_name| 163: say "Removing #{exe_name}" 164: 165: exe_file = File.join bin_dir, exe_name 166: 167: FileUtils.rm_f exe_file 168: FileUtils.rm_f "#{exe_file}.bat" 169: end 170: end 171: end
Performs the uninstall of the gem. This removes the spec, the Gem directory, and the cached .gem file.
# File lib/rubygems/uninstaller.rb, line 69 69: def uninstall 70: list = Gem::Specification.find_all_by_name(@gem, @version) 71: 72: if list.empty? then 73: raise Gem::InstallError, "gem #{@gem.inspect} is not installed" 74: 75: elsif list.size > 1 and @force_all then 76: remove_all list 77: 78: elsif list.size > 1 then 79: gem_names = list.collect {|gem| gem.full_name} + ["All versions"] 80: 81: say 82: _, index = choose_from_list "Select gem to uninstall:", gem_names 83: 84: if index == list.size then 85: remove_all list 86: elsif index >= 0 && index < list.size then 87: uninstall_gem list[index] 88: else 89: say "Error: must enter a number [1-#{list.size+1}]" 90: end 91: else 92: uninstall_gem list.first 93: end 94: end
Uninstalls gem spec
# File lib/rubygems/uninstaller.rb, line 99 99: def uninstall_gem(spec) 100: @spec = spec 101: 102: unless dependencies_ok? spec 103: unless ask_if_ok(spec) 104: raise Gem::DependencyRemovalException, 105: "Uninstallation aborted due to dependent gem(s)" 106: end 107: end 108: 109: Gem.pre_uninstall_hooks.each do |hook| 110: hook.call self 111: end 112: 113: remove_executables @spec 114: remove @spec 115: 116: Gem.post_uninstall_hooks.each do |hook| 117: hook.call self 118: end 119: 120: @spec = nil 121: end