Class: Gem::Validator
- Inherits:
-
Object
- Object
- Gem::Validator
- Includes:
- UserInteraction
- Defined in:
- lib/rubygems/validator.rb
Overview
Validator performs various gem file and gem database validation
Defined Under Namespace
Classes: ErrorData
Instance Method Summary collapse
-
#alien(gems = []) ⇒ Object
Checks the gem directory for the following potential inconsistencies/problems:.
-
#initialize ⇒ Validator
constructor
A new instance of Validator.
- #remove_leading_dot_dir(path) ⇒ Object
-
#verify_gem(gem_data) ⇒ Object
- Given a gem file’s contents, validates against its own MD5 checksum gem_data
- String
-
Contents of the gem file.
-
#verify_gem_file(gem_path) ⇒ Object
Given the path to a gem file, validates against its own MD5 checksum.
Methods included from UserInteraction
#alert, #alert_error, #alert_warning, #ask, #ask_for_password, #ask_yes_no, #choose_from_list, #say, #terminate_interaction
Methods included from DefaultUserInteraction
ui, #ui, ui=, #ui=, use_ui, #use_ui
Constructor Details
#initialize ⇒ Validator
Returns a new instance of Validator.
17 18 19 20 |
# File 'lib/rubygems/validator.rb', line 17 def initialize require 'find' require 'digest' end |
Instance Method Details
#alien(gems = []) ⇒ Object
Checks the gem directory for the following potential inconsistencies/problems:
-
Checksum gem itself
-
For each file in each gem, check consistency of installed versions
-
Check for files that aren’t part of the gem but are in the gems directory
-
1 cache - 1 spec - 1 directory.
returns a hash of ErrorData objects, keyed on the problem gem’s name.
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/rubygems/validator.rb', line 84 def alien(gems=[]) errors = Hash.new { |h,k| h[k] = {} } Gem::SourceIndex.from_installed_gems.each do |gem_name, gem_spec| next unless gems.include? gem_spec.name unless gems.empty? install_dir = gem_spec.installation_path gem_path = Gem.cache_gem(gem_spec.file_name, install_dir) spec_path = File.join install_dir, "specifications", gem_spec.spec_name gem_directory = gem_spec.full_gem_path unless File.directory? gem_directory then errors[gem_name][gem_spec.full_name] = "Gem registered but doesn't exist at #{gem_directory}" next end unless File.exist? spec_path then errors[gem_name][spec_path] = "Spec file missing for installed gem" end begin verify_gem_file(gem_path) good, gone, unreadable = nil, nil, nil, nil open gem_path, Gem.binary_mode do |file| format = Gem::Format.from_file_by_path(gem_path) good, gone = format.file_entries.partition { |entry, _| File.exist? File.join(gem_directory, entry['path']) } gone.map! { |entry, _| entry['path'] } gone.sort.each do |path| errors[gem_name][path] = "Missing file" end good, unreadable = good.partition { |entry, _| File.readable? File.join(gem_directory, entry['path']) } unreadable.map! { |entry, _| entry['path'] } unreadable.sort.each do |path| errors[gem_name][path] = "Unreadable file" end good.each do |entry, data| begin next unless data # HACK `gem check -a mkrf` open File.join(gem_directory, entry['path']), Gem.binary_mode do |f| unless Digest::MD5.hexdigest(f.read).to_s == Digest::MD5.hexdigest(data).to_s then errors[gem_name][entry['path']] = "Modified from original" end end end end end installed_files = find_files_for_gem(gem_directory) good.map! { |entry, _| entry['path'] } extras = installed_files - good - unreadable extras.each do |extra| errors[gem_name][extra] = "Extra file" end rescue Gem::VerificationError => e errors[gem_name][gem_path] = e. end end errors.each do |name, subhash| errors[name] = subhash.map { |path, msg| ErrorData.new(path, msg) } end errors end |
#remove_leading_dot_dir(path) ⇒ Object
164 165 166 |
# File 'lib/rubygems/validator.rb', line 164 def remove_leading_dot_dir(path) path.sub(/^\.\//, "") end |
#verify_gem(gem_data) ⇒ Object
Given a gem file’s contents, validates against its own MD5 checksum
- gem_data
- String
-
Contents of the gem file
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/rubygems/validator.rb', line 26 def verify_gem(gem_data) raise Gem::VerificationError, 'empty gem file' if gem_data.size == 0 unless gem_data =~ /MD5SUM/ then return # Don't worry about it...this sucks. Need to fix MD5 stuff for # new format # FIXME end sum_data = gem_data.gsub(/MD5SUM = "([a-z0-9]+)"/, "MD5SUM = \"#{"F" * 32}\"") unless Digest::MD5.hexdigest(sum_data) == $1.to_s then raise Gem::VerificationError, 'invalid checksum for gem file' end end |
#verify_gem_file(gem_path) ⇒ Object
Given the path to a gem file, validates against its own MD5 checksum
- gem_path
- String
-
Path to gem file
48 49 50 51 52 53 54 55 |
# File 'lib/rubygems/validator.rb', line 48 def verify_gem_file(gem_path) open gem_path, Gem.binary_mode do |file| gem_data = file.read verify_gem gem_data end rescue Errno::ENOENT, Errno::EINVAL raise Gem::VerificationError, "missing gem file #{gem_path}" end |