1require 'rubygems/command' 2require 'rubygems/package' 3require 'rubygems/installer' 4require 'rubygems/version_option' 5 6class Gem::Commands::PristineCommand < Gem::Command 7 8 include Gem::VersionOption 9 10 def initialize 11 super 'pristine', 12 'Restores installed gems to pristine condition from files located in the gem cache', 13 :version => Gem::Requirement.default, 14 :extensions => true, 15 :all => false 16 17 add_option('--all', 18 'Restore all installed gems to pristine', 19 'condition') do |value, options| 20 options[:all] = value 21 end 22 23 add_option('--[no-]extensions', 24 'Restore gems with extensions', 25 'in addition to regular gems') do |value, options| 26 options[:extensions] = value 27 end 28 29 add_option('--only-executables', 30 'Only restore executables') do |value, options| 31 options[:only_executables] = value 32 end 33 34 add_version_option('restore to', 'pristine condition') 35 end 36 37 def arguments # :nodoc: 38 "GEMNAME gem to restore to pristine condition (unless --all)" 39 end 40 41 def defaults_str # :nodoc: 42 '--extensions' 43 end 44 45 def description # :nodoc: 46 <<-EOF 47The pristine command compares an installed gem with the contents of its 48cached .gem file and restores any files that don't match the cached .gem's 49copy. 50 51If you have made modifications to an installed gem, the pristine command 52will revert them. All extensions are rebuilt and all bin stubs for the gem 53are regenerated after checking for modifications. 54 55If the cached gem cannot be found it will be downloaded. 56 57If --no-extensions is provided pristine will not attempt to restore a gem 58with an extension. 59 EOF 60 end 61 62 def usage # :nodoc: 63 "#{program_name} [GEMNAME ...]" 64 end 65 66 def execute 67 specs = if options[:all] then 68 Gem::Specification.map 69 else 70 get_all_gem_names.map do |gem_name| 71 Gem::Specification.find_all_by_name gem_name, options[:version] 72 end.flatten 73 end 74 75 if specs.to_a.empty? then 76 raise Gem::Exception, 77 "Failed to find gems #{options[:args]} #{options[:version]}" 78 end 79 80 install_dir = Gem.dir # TODO use installer option 81 82 raise Gem::FilePermissionError.new(install_dir) unless 83 File.writable?(install_dir) 84 85 say "Restoring gems to pristine condition..." 86 87 specs.each do |spec| 88 if spec.default_gem? 89 say "Skipped #{spec.full_name}, it is a default gem" 90 next 91 end 92 93 unless spec.extensions.empty? or options[:extensions] then 94 say "Skipped #{spec.full_name}, it needs to compile an extension" 95 next 96 end 97 98 gem = spec.cache_file 99 100 unless File.exist? gem then 101 require 'rubygems/remote_fetcher' 102 103 say "Cached gem for #{spec.full_name} not found, attempting to fetch..." 104 dep = Gem::Dependency.new spec.name, spec.version 105 Gem::RemoteFetcher.fetcher.download_to_cache dep 106 end 107 108 # TODO use installer options 109 install_defaults = Gem::ConfigFile::PLATFORM_DEFAULTS['install'] 110 installer_env_shebang = install_defaults.to_s['--env-shebang'] 111 112 installer = Gem::Installer.new(gem, 113 :wrappers => true, 114 :force => true, 115 :install_dir => spec.base_dir, 116 :env_shebang => installer_env_shebang, 117 :build_args => spec.build_args) 118 if options[:only_executables] then 119 installer.generate_bin 120 else 121 installer.install 122 end 123 124 say "Restored #{spec.full_name}" 125 end 126 end 127end 128