summaryrefslogtreecommitdiff
path: root/lib/rubygems/commands/pristine_command.rb
diff options
context:
space:
mode:
authordrbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-11-10 07:48:56 +0000
committerdrbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-11-10 07:48:56 +0000
commitfbf59bdbea63efd34ccc144e648467d2f52e7345 (patch)
tree244f0e7ae112cc7dd135e5d1ac24e6c70ba71b4a /lib/rubygems/commands/pristine_command.rb
parent7a4aad75356496559460041a6c063bdb736c7236 (diff)
Import RubyGems trunk revision 1493.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13862 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/rubygems/commands/pristine_command.rb')
-rw-r--r--lib/rubygems/commands/pristine_command.rb133
1 files changed, 133 insertions, 0 deletions
diff --git a/lib/rubygems/commands/pristine_command.rb b/lib/rubygems/commands/pristine_command.rb
new file mode 100644
index 0000000000..2900e7e739
--- /dev/null
+++ b/lib/rubygems/commands/pristine_command.rb
@@ -0,0 +1,133 @@
+require 'fileutils'
+require 'rubygems/command'
+require 'rubygems/format'
+require 'rubygems/installer'
+require 'rubygems/version_option'
+
+class Gem::Commands::PristineCommand < Gem::Command
+
+ include Gem::VersionOption
+
+ def initialize
+ super 'pristine',
+ 'Restores installed gems to pristine condition from files located in the gem cache',
+ :version => Gem::Requirement.default
+
+ add_option('--all',
+ 'Restore all installed gems to pristine',
+ 'condition') do |value, options|
+ options[:all] = value
+ end
+
+ add_version_option('restore to', 'pristine condition')
+ end
+
+ def arguments # :nodoc:
+ "GEMNAME gem to restore to pristine condition (unless --all)"
+ end
+
+ def defaults_str # :nodoc:
+ "--all"
+ end
+
+ def description # :nodoc:
+ <<-EOF
+The pristine command compares the installed gems with the contents of the
+cached gem and restores any files that don't match the cached gem's copy.
+
+If you have made modifications to your installed gems, the pristine command
+will revert them. After all the gem's files have been checked all bin stubs
+for the gem are regenerated.
+
+If the cached gem cannot be found, you will need to use `gem install` to
+revert the gem.
+ EOF
+ end
+
+ def usage # :nodoc:
+ "#{program_name} [args]"
+ end
+
+ def execute
+ gem_name = nil
+
+ specs = if options[:all] then
+ Gem::SourceIndex.from_installed_gems.map do |name, spec|
+ spec
+ end
+ else
+ gem_name = get_one_gem_name
+ Gem::SourceIndex.from_installed_gems.search(gem_name,
+ options[:version])
+ end
+
+ if specs.empty? then
+ raise Gem::Exception,
+ "Failed to find gem #{gem_name} #{options[:version]}"
+ end
+
+ install_dir = Gem.dir # TODO use installer option
+
+ raise Gem::FilePermissionError.new(install_dir) unless
+ File.writable?(install_dir)
+
+ say "Restoring gem(s) to pristine condition..."
+
+ specs.each do |spec|
+ gem = Dir[File.join(Gem.dir, 'cache', "#{spec.full_name}.gem")].first
+
+ if gem.nil? then
+ alert_error "Cached gem for #{spec.full_name} not found, use `gem install` to restore"
+ next
+ end
+
+ # TODO use installer options
+ installer = Gem::Installer.new gem, :wrappers => true
+
+ gem_file = File.join install_dir, "cache", "#{spec.full_name}.gem"
+
+ security_policy = nil # TODO use installer option
+
+ format = Gem::Format.from_file_by_path gem_file, security_policy
+
+ target_directory = File.join(install_dir, "gems", format.spec.full_name)
+ target_directory.untaint
+
+ pristine_files = format.file_entries.collect { |data| data[0]["path"] }
+ file_map = {}
+
+ format.file_entries.each do |entry, file_data|
+ file_map[entry["path"]] = file_data
+ end
+
+ Dir.chdir target_directory do
+ deployed_files = Dir.glob(File.join("**", "*")) +
+ Dir.glob(File.join("**", ".*"))
+
+ pristine_files = pristine_files.map { |f| File.expand_path f }
+ deployed_files = deployed_files.map { |f| File.expand_path f }
+
+ to_redeploy = (pristine_files - deployed_files)
+ to_redeploy = to_redeploy.map { |path| path.untaint}
+
+ if to_redeploy.length > 0 then
+ say "Restoring #{to_redeploy.length} file#{to_redeploy.length == 1 ? "" : "s"} to #{spec.full_name}..."
+
+ to_redeploy.each do |path|
+ say " #{path}"
+ FileUtils.mkdir_p File.dirname(path)
+ File.open(path, "wb") do |out|
+ out.write file_map[path]
+ end
+ end
+ else
+ say "#{spec.full_name} is in pristine condition"
+ end
+ end
+
+ installer.generate_bin
+ end
+ end
+
+end
+