[前][次][番号順一覧][スレッド一覧]

ruby-changes:26647

From: drbrain <ko1@a...>
Date: Sat, 5 Jan 2013 07:58:31 +0900 (JST)
Subject: [ruby-changes:26647] drbrain:r38698 (trunk): * lib/rubygems/commands/cleanup_command.rb: Clean all possible gems

drbrain	2013-01-05 07:58:15 +0900 (Sat, 05 Jan 2013)

  New Revision: 38698

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=38698

  Log:
    * lib/rubygems/commands/cleanup_command.rb:  Clean all possible gems
      using multiple passes.  Fixes RubyGems bug #422.  Refactored for
      maintainability.
    * test/rubygems/test_gem_commands_cleanup_command.rb:  Test for above.

  Modified files:
    trunk/ChangeLog
    trunk/lib/rubygems/commands/cleanup_command.rb
    trunk/test/rubygems/test_gem_commands_cleanup_command.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 38697)
+++ ChangeLog	(revision 38698)
@@ -1,3 +1,10 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Sat Jan  5 07:54:59 2013  Eric Hodel  <drbrain@s...>
+
+	* lib/rubygems/commands/cleanup_command.rb:  Clean all possible gems
+	  using multiple passes.  Fixes RubyGems bug #422.  Refactored for
+	  maintainability.
+	* test/rubygems/test_gem_commands_cleanup_command.rb:  Test for above.
+
 Sat Jan  5 05:04:39 2013  KOSAKI Motohiro  <kosaki.motohiro@g...>
 
 	* gc.c (vm_xrealloc): add a few comment why we avoid realloc(ptr,0).
Index: lib/rubygems/commands/cleanup_command.rb
===================================================================
--- lib/rubygems/commands/cleanup_command.rb	(revision 38697)
+++ lib/rubygems/commands/cleanup_command.rb	(revision 38698)
@@ -12,6 +12,14 @@ class Gem::Commands::CleanupCommand < Ge https://github.com/ruby/ruby/blob/trunk/lib/rubygems/commands/cleanup_command.rb#L12
     add_option('-d', '--dryrun', "") 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:
@@ -38,79 +46,119 @@ are not removed. https://github.com/ruby/ruby/blob/trunk/lib/rubygems/commands/cleanup_command.rb#L46
 
   def execute
     say "Cleaning up installed 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
+    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
 
-    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
-
-    gems_to_cleanup = candidate_gems.select { |spec|
-      !spec.default_gem? and
-        primary_gems[spec.name].version != spec.version
-    }
+    say "Clean Up Complete"
+
+    if Gem.configuration.really_verbose then
+      skipped = @default_gems.map { |spec| spec.full_name }
+
+      say "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
+    @full = Gem::DependencyList.from_specs
 
     deplist = Gem::DependencyList.new
-    gems_to_cleanup.uniq.each do |spec| deplist.add spec end
+    @gems_to_cleanup.each do |spec| deplist.add spec end
 
-    deps = deplist.strongly_connected_components.flatten.reverse
+    deps = deplist.strongly_connected_components.flatten
 
-    original_home = Gem.dir
-    original_path = Gem.path
+    @original_home = Gem.dir
+    @original_path = Gem.path
 
-    deps.each do |spec|
-      next unless full.ok_to_remove?(spec.full_name)
+    deps.reverse_each do |spec|
+      uninstall_dep spec
+    end
 
-      if options[:dryrun] then
-        say "Dry Run Mode: Would uninstall #{spec.full_name}"
-      else
-        say "Attempting to uninstall #{spec.full_name}"
+    Gem::Specification.reset
+  end
 
-        options[:args] = [spec.name]
+  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
+    }
 
-        uninstall_options = {
-          :executables => false,
-          :version => "= #{spec.version}",
-        }
+    default_gems, gems_to_cleanup = gems_to_cleanup.partition { |spec|
+      spec.default_gem?
+    }
 
-        uninstall_options[:user_install] = Gem.user_dir == spec.base_dir
+    @default_gems += default_gems
+    @default_gems.uniq!
+    @gems_to_cleanup = gems_to_cleanup.uniq
+  end
 
-        uninstaller = Gem::Uninstaller.new spec.name, uninstall_options
+  def get_primary_gems
+    @primary_gems = {}
 
-        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
+    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
 
-      # Restore path Gem::Uninstaller may have change
-      Gem.use_paths(original_home, *original_path)
+  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 "Clean Up Complete"
+    say "Attempting to uninstall #{spec.full_name}"
 
-    if Gem.configuration.really_verbose then
-      skipped = candidate_gems.
-        select { |spec| spec.default_gem? }.
-        map { |spec| spec.full_name}
+    uninstall_options = {
+      :executables => false,
+      :version => "= #{spec.version}",
+    }
 
-      say "Skipped default gems: #{skipped.join ', '}"
+    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
Index: test/rubygems/test_gem_commands_cleanup_command.rb
===================================================================
--- test/rubygems/test_gem_commands_cleanup_command.rb	(revision 38697)
+++ test/rubygems/test_gem_commands_cleanup_command.rb	(revision 38698)
@@ -23,6 +23,21 @@ class TestGemCommandsCleanupCommand < Ge https://github.com/ruby/ruby/blob/trunk/test/rubygems/test_gem_commands_cleanup_command.rb#L23
     refute_path_exists @a_1.gem_dir
   end
 
+  def test_execute_all_dependencies
+    @b_1 = quick_spec 'b', 1 do |s| s.add_dependency 'a', '1' end
+    @b_2 = quick_spec 'b', 2 do |s| s.add_dependency 'a', '2' end
+
+    install_gem @b_1
+    install_gem @b_2
+
+    @cmd.options[:args] = []
+
+    @cmd.execute
+
+    refute_path_exists @a_1.gem_dir
+    refute_path_exists @b_1.gem_dir
+  end
+
   def test_execute_all
     gemhome2 = File.join @tempdir, 'gemhome2'
 

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]