diff options
author | Jari Vetoniemi <jari.vetoniemi@indooratlas.com> | 2020-03-16 18:49:26 +0900 |
---|---|---|
committer | Jari Vetoniemi <jari.vetoniemi@indooratlas.com> | 2020-03-30 00:39:06 +0900 |
commit | fcbf63e62c627deae76c1b8cb8c0876c536ed811 (patch) | |
tree | 64cb17de3f41a2b6fef2368028fbd00349946994 /jni/ruby/lib/rubygems/commands/cleanup_command.rb |
Fresh start
Diffstat (limited to 'jni/ruby/lib/rubygems/commands/cleanup_command.rb')
-rw-r--r-- | jni/ruby/lib/rubygems/commands/cleanup_command.rb | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/jni/ruby/lib/rubygems/commands/cleanup_command.rb b/jni/ruby/lib/rubygems/commands/cleanup_command.rb new file mode 100644 index 0000000..6997564 --- /dev/null +++ b/jni/ruby/lib/rubygems/commands/cleanup_command.rb @@ -0,0 +1,165 @@ +require 'rubygems/command' +require 'rubygems/dependency_list' +require 'rubygems/uninstaller' + +class Gem::Commands::CleanupCommand < Gem::Command + + def initialize + super 'cleanup', + 'Clean up old versions of installed gems', + :force => false, :install_dir => Gem.dir + + add_option('-n', '-d', '--dryrun', + 'Do not uninstall gems') do |value, options| + options[:dryrun] = true + end + + @candidate_gems = nil + @default_gems = [] + @full = nil + @gems_to_cleanup = nil + @original_home = nil + @original_path = nil + @primary_gems = nil + end + + def arguments # :nodoc: + "GEMNAME name of gem to cleanup" + end + + def defaults_str # :nodoc: + "--no-dryrun" + end + + def description # :nodoc: + <<-EOF +The cleanup command removes old versions of gems from GEM_HOME that are not +required to meet a dependency. If a gem is installed elsewhere in GEM_PATH +the cleanup command won't delete it. + +If no gems are named all gems in GEM_HOME are cleaned. + EOF + end + + def usage # :nodoc: + "#{program_name} [GEMNAME ...]" + end + + def execute + say "Cleaning up installed gems..." + + if options[:args].empty? then + done = false + last_set = nil + + until done do + clean_gems + + this_set = @gems_to_cleanup.map { |spec| spec.full_name }.sort + + done = this_set.empty? || last_set == this_set + + last_set = this_set + end + else + clean_gems + end + + say "Clean Up Complete" + + verbose do + skipped = @default_gems.map { |spec| spec.full_name } + + "Skipped default gems: #{skipped.join ', '}" + end + end + + def clean_gems + get_primary_gems + get_candidate_gems + get_gems_to_cleanup + + @full = Gem::DependencyList.from_specs + + deplist = Gem::DependencyList.new + @gems_to_cleanup.each do |spec| deplist.add spec end + + deps = deplist.strongly_connected_components.flatten + + @original_home = Gem.dir + @original_path = Gem.path + + deps.reverse_each do |spec| + uninstall_dep spec + end + + Gem::Specification.reset + end + + def get_candidate_gems + @candidate_gems = unless options[:args].empty? then + options[:args].map do |gem_name| + Gem::Specification.find_all_by_name gem_name + end.flatten + else + Gem::Specification.to_a + end + end + + def get_gems_to_cleanup + gems_to_cleanup = @candidate_gems.select { |spec| + @primary_gems[spec.name].version != spec.version + } + + default_gems, gems_to_cleanup = gems_to_cleanup.partition { |spec| + spec.default_gem? + } + + @default_gems += default_gems + @default_gems.uniq! + @gems_to_cleanup = gems_to_cleanup.uniq + end + + def get_primary_gems + @primary_gems = {} + + Gem::Specification.each do |spec| + if @primary_gems[spec.name].nil? or + @primary_gems[spec.name].version < spec.version then + @primary_gems[spec.name] = spec + end + end + end + + def uninstall_dep spec + return unless @full.ok_to_remove?(spec.full_name) + + if options[:dryrun] then + say "Dry Run Mode: Would uninstall #{spec.full_name}" + return + end + + say "Attempting to uninstall #{spec.full_name}" + + uninstall_options = { + :executables => false, + :version => "= #{spec.version}", + } + + uninstall_options[:user_install] = Gem.user_dir == spec.base_dir + + uninstaller = Gem::Uninstaller.new spec.name, uninstall_options + + begin + uninstaller.uninstall + rescue Gem::DependencyRemovalException, Gem::InstallError, + Gem::GemNotInHomeException, Gem::FilePermissionError => e + say "Unable to uninstall #{spec.full_name}:" + say "\t#{e.class}: #{e.message}" + end + ensure + # Restore path Gem::Uninstaller may have changed + Gem.use_paths @original_home, *@original_path + end + +end |