| 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 = options[:install_dir] || Gem.dir
48: @gem_home = File.expand_path gem_home
49: @force_executables = options[:executables]
50: @force_all = options[:all]
51: @force_ignore = options[:ignore]
52: @bin_dir = options[:bin_dir]
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: spec_dir = File.join @gem_home, 'specifications'
59: @source_index = Gem::SourceIndex.from_gems_in spec_dir
60:
61: if @user_install then
62: user_dir = File.join Gem.user_dir, 'specifications'
63: @user_index = Gem::SourceIndex.from_gems_in user_dir
64: end
65: 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: spec.dependent_gems.each do |gem,dep,satlist|
252: msg <<
253: ("#{gem.name}-#{gem.version} depends on " +
254: "[#{dep.name} (#{dep.version_requirements})]")
255: end
256: msg << 'If you remove this gems, one or more dependencies will not be met.'
257: msg << 'Continue with Uninstall?'
258: return ask_yes_no(msg.join("\n"), true)
259: end
# File lib/rubygems/uninstaller.rb, line 239
239: def dependencies_ok?(spec)
240: return true if @force_ignore
241:
242: deplist = Gem::DependencyList.from_source_index @source_index
243: deplist.add(*@user_index.gems.values) if @user_install
244: deplist.ok_to_remove?(spec.full_name) || ask_if_ok(spec)
245: end
Is spec in gem_dir?
# File lib/rubygems/uninstaller.rb, line 232
232: def path_ok?(gem_dir, spec)
233: full_path = File.join gem_dir, 'gems', spec.full_name
234: original_path = File.join gem_dir, 'gems', spec.original_name
235:
236: full_path == spec.full_gem_path || original_path == spec.full_gem_path
237: 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 181
181: def remove(spec, list)
182: unless dependencies_ok? spec then
183: raise Gem::DependencyRemovalException,
184: "Uninstallation aborted due to dependent gem(s)"
185: end
186:
187: unless path_ok?(@gem_home, spec) or
188: (@user_install and path_ok?(Gem.user_dir, spec)) then
189: e = Gem::GemNotInHomeException.new \
190: "Gem is not installed in directory #{@gem_home}"
191: e.spec = spec
192:
193: raise e
194: end
195:
196: raise Gem::FilePermissionError, spec.installation_path unless
197: File.writable?(spec.installation_path)
198:
199: FileUtils.rm_rf spec.full_gem_path
200:
201: original_platform_name = [
202: spec.name, spec.version, spec.original_platform].join '-'
203:
204: spec_dir = File.join spec.installation_path, 'specifications'
205: gemspec = File.join spec_dir, "#{spec.full_name}.gemspec"
206:
207: unless File.exist? gemspec then
208: gemspec = File.join spec_dir, "#{original_platform_name}.gemspec"
209: end
210:
211: FileUtils.rm_rf gemspec
212:
213: cache_dir = File.join spec.installation_path, 'cache'
214: gem = File.join cache_dir, "#{spec.full_name}.gem"
215:
216: unless File.exist? gem then
217: gem = File.join cache_dir, "#{original_platform_name}.gem"
218: end
219:
220: FileUtils.rm_rf gem
221:
222: Gem::DocManager.new(spec).uninstall_doc
223:
224: say "Successfully uninstalled #{spec.full_name}"
225:
226: list.delete spec
227: end
Removes all gems in list.
NOTE: removes uninstalled gems from list.
# File lib/rubygems/uninstaller.rb, line 170
170: def remove_all(list)
171: list.dup.each { |spec| uninstall_gem spec, list }
172: end
Removes installed executables and batch files (windows only) for gemspec.
# File lib/rubygems/uninstaller.rb, line 123
123: def remove_executables(spec)
124: return if spec.nil?
125:
126: unless spec.executables.empty? then
127: bindir = @bin_dir ? @bin_dir : Gem.bindir(spec.installation_path)
128:
129: list = @source_index.find_name(spec.name).delete_if { |s|
130: s.version == spec.version
131: }
132:
133: executables = spec.executables.clone
134:
135: list.each do |s|
136: s.executables.each do |exe_name|
137: executables.delete exe_name
138: end
139: end
140:
141: return if executables.empty?
142:
143: answer = if @force_executables.nil? then
144: ask_yes_no("Remove executables:\n" \
145: "\t#{spec.executables.join(", ")}\n\nin addition to the gem?",
146: true) # " # appease ruby-mode - don't ask
147: else
148: @force_executables
149: end
150:
151: unless answer then
152: say "Executables and scripts will remain installed."
153: else
154: raise Gem::FilePermissionError, bindir unless File.writable? bindir
155:
156: spec.executables.each do |exe_name|
157: say "Removing #{exe_name}"
158: FileUtils.rm_f File.join(bindir, exe_name)
159: FileUtils.rm_f File.join(bindir, "#{exe_name}.bat")
160: end
161: end
162: end
163: 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 71
71: def uninstall
72: list = @source_index.find_name @gem, @version
73: list += @user_index.find_name @gem, @version if @user_install
74:
75: if list.empty? then
76: raise Gem::InstallError, "cannot uninstall, check `gem list -d #{@gem}`"
77:
78: elsif list.size > 1 and @force_all then
79: remove_all list.dup
80:
81: elsif list.size > 1 then
82: gem_names = list.collect {|gem| gem.full_name} + ["All versions"]
83:
84: say
85: gem_name, index = choose_from_list "Select gem to uninstall:", gem_names
86:
87: if index == list.size then
88: remove_all list.dup
89: elsif index >= 0 && index < list.size then
90: uninstall_gem list[index], list.dup
91: else
92: say "Error: must enter a number [1-#{list.size+1}]"
93: end
94: else
95: uninstall_gem list.first, list.dup
96: end
97: end
Uninstalls gem spec
# File lib/rubygems/uninstaller.rb, line 102
102: def uninstall_gem(spec, specs)
103: @spec = spec
104:
105: Gem.pre_uninstall_hooks.each do |hook|
106: hook.call self
107: end
108:
109: remove_executables @spec
110: remove @spec, specs
111:
112: Gem.post_uninstall_hooks.each do |hook|
113: hook.call self
114: end
115:
116: @spec = nil
117: end