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, TestRunner
Instance Method Summary (collapse)
-
- (Object) alien(gems = [])
Checks the gem directory for the following potential inconsistencies/problems:.
-
- (Validator) initialize
constructor
A new instance of Validator.
- - (Object) remove_leading_dot_dir(path)
-
- (Object) unit_test(gem_spec)
Runs unit tests for a given gem specification.
-
- (Object) verify_gem(gem_data)
Given a gem file's contents, validates against its own MD5 checksum
gem_data
- String
-
Contents of the gem file.
-
- (Object) verify_gem_file(gem_path)
Given the path to a gem file, validates against its own MD5 checksum.
Methods included from UserInteraction
Methods included from DefaultUserInteraction
ui, #ui, #ui=, ui=, use_ui, #use_ui
Constructor Details
- (Validator) initialize
A new instance of Validator
23 24 25 26 |
# File 'lib/rubygems/validator.rb', line 23 def initialize require 'find' require 'digest' end |
Instance Method Details
- (Object) alien(gems = [])
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.
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 163 164 165 166 167 168 |
# File 'lib/rubygems/validator.rb', line 90 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 = File.join install_dir, "cache", gem_spec.file_name 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 |
- (Object) remove_leading_dot_dir(path)
237 238 239 |
# File 'lib/rubygems/validator.rb', line 237 def remove_leading_dot_dir(path) path.sub(/^\.\//, "") end |
- (Object) unit_test(gem_spec)
Runs unit tests for a given gem specification
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 |
# File 'lib/rubygems/validator.rb', line 201 def unit_test(gem_spec) start_dir = Dir.pwd Dir.chdir(gem_spec.full_gem_path) $: << gem_spec.full_gem_path # XXX: why do we need this gem_spec when we've already got 'spec'? test_files = gem_spec.test_files if test_files.empty? then say "There are no unit tests to run for #{gem_spec.full_name}" return nil end gem gem_spec.name, "= #{gem_spec.version.version}" test_files.each do |f| require f end if RUBY_VERSION < '1.9' then suite = Test::Unit::TestSuite.new("#{gem_spec.name}-#{gem_spec.version}") ObjectSpace.each_object(Class) do |klass| suite << klass.suite if (klass < Test::Unit::TestCase) end result = TestRunner.run suite, ui alert_error result.to_s unless result.passed? else result = MiniTest::Unit.new result.run end result ensure Dir.chdir(start_dir) end |
- (Object) verify_gem(gem_data)
Given a gem file's contents, validates against its own MD5 checksum
gem_data |
|
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/rubygems/validator.rb', line 32 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 |
- (Object) verify_gem_file(gem_path)
Given the path to a gem file, validates against its own MD5 checksum
gem_path |
|
54 55 56 57 58 59 60 61 |
# File 'lib/rubygems/validator.rb', line 54 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 |