summaryrefslogtreecommitdiff
path: root/lib/rubygems/doctor.rb
diff options
context:
space:
mode:
authordrbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-12-23 00:35:09 +0000
committerdrbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-12-23 00:35:09 +0000
commit6fe32d72667945605ef710395706e04491bfd86a (patch)
tree7fe4b8f779ff75067b45f48502864fb05787cee7 /lib/rubygems/doctor.rb
parentc47c095b9740e7c19d6fdca29ab661c1089221d4 (diff)
* lib/rubygems/commands/check_command.rb: Added --doctor and --dry-run
options to clean up after failed uninstallation. * test/rubygems/test_gem_commands_check_command.rb: Test for above. * lib/rubygems/commands/push_command.rb: Allow pushes from RubyGems 2.0.0.preview3 * lib/rubygems/commands/update_command.rb: Use Gem.ruby_version * lib/rubygems/dependency.rb: Update style. * lib/rubygems/installer.rb: Ensure installed gem specifications will be useable. Refactor. * test/rubygems/test_gem_installer.rb: ditto. * lib/rubygems/validator.rb: Fixed bug with unreadable files. * lib/rubygems.rb: Fixed broken methods. * test/rubygems/test_gem.rb: Test for above. * test/rubygems/test_gem_commands_push_command.rb: Fixed overridden Gem.latest_rubygems_version git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@38564 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/rubygems/doctor.rb')
-rw-r--r--lib/rubygems/doctor.rb124
1 files changed, 124 insertions, 0 deletions
diff --git a/lib/rubygems/doctor.rb b/lib/rubygems/doctor.rb
new file mode 100644
index 0000000000..198c758b00
--- /dev/null
+++ b/lib/rubygems/doctor.rb
@@ -0,0 +1,124 @@
+require 'rubygems'
+require 'rubygems/user_interaction'
+require 'pathname'
+
+##
+# Cleans up after a partially-failed uninstall or for an invalid
+# Gem::Specification.
+#
+# If a specification was removed by hand this will remove any remaining files.
+#
+# If a corrupt specification was installed this will clean up warnings by
+# removing the bogus specification.
+
+class Gem::Doctor
+
+ include Gem::UserInteraction
+
+ ##
+ # Maps a gem subdirectory to the files that are expected to exist in the
+ # subdirectory.
+
+ REPOSITORY_EXTENSION_MAP = { # :nodoc:
+ 'build_info' => '.info',
+ 'cache' => '.gem',
+ 'doc' => '',
+ 'gems' => '',
+ 'specifications' => '.gemspec'
+ }
+
+ raise 'Update REPOSITORY_EXTENSION_MAP' unless
+ Gem::REPOSITORY_SUBDIRECTORIES == REPOSITORY_EXTENSION_MAP.keys.sort
+
+ ##
+ # Creates a new Gem::Doctor that will clean up +gem_repository+. Only one
+ # gem repository may be cleaned at a time.
+ #
+ # If +dry_run+ is true no files or directories will be removed.
+
+ def initialize gem_repository, dry_run = false
+ @gem_repository = Pathname(gem_repository)
+ @dry_run = dry_run
+
+ @installed_specs = nil
+ end
+
+ ##
+ # Specs installed in this gem repository
+
+ def installed_specs # :nodoc:
+ @installed_specs ||= Gem::Specification.map { |s| s.full_name }
+ end
+
+ ##
+ # Are we doctoring a gem repository?
+
+ def gem_repository?
+ not installed_specs.empty?
+ end
+
+ ##
+ # Cleans up uninstalled files and invalid gem specifications
+
+ def doctor
+ @orig_home = Gem.dir
+ @orig_path = Gem.path
+
+ say "Checking #{@gem_repository}"
+
+ Gem.use_paths @gem_repository.to_s
+
+ unless gem_repository? then
+ say 'This directory does not appear to be a RubyGems repository, ' +
+ 'skipping'
+ say
+ return
+ end
+
+ doctor_children
+
+ say
+ ensure
+ Gem.use_paths @orig_home, *@orig_path
+ end
+
+ ##
+ # Cleans up children of this gem repository
+
+ def doctor_children # :nodoc:
+ REPOSITORY_EXTENSION_MAP.each do |sub_directory, extension|
+ doctor_child sub_directory, extension
+ end
+ end
+
+ ##
+ # Removes files in +sub_directory+ with +extension+
+
+ def doctor_child sub_directory, extension # :nodoc:
+ directory = @gem_repository + sub_directory
+
+ directory.each_child do |child|
+ next unless child.exist?
+
+ basename = child.basename(extension).to_s
+ next if installed_specs.include? basename
+ next if /^rubygems-\d/ =~ basename
+ next if 'specifications' == sub_directory and 'default' == basename
+
+ type = child.directory? ? 'directory' : 'file'
+
+ action = if @dry_run then
+ 'Extra'
+ else
+ child.rmtree
+ 'Removed'
+ end
+
+ say "#{action} #{type} #{sub_directory}/#{child.basename}"
+ end
+ rescue Errno::ENOENT
+ # ignore
+ end
+
+end
+