Class | Gem::Validator |
In: |
lib/rubygems/validator.rb
|
Parent: | Object |
Validator performs various gem file and gem database validation
ErrorData | = | Struct.new :path, :problem |
Checks the gem directory for the following potential inconsistencies/problems:
returns a hash of ErrorData objects, keyed on the problem gem‘s name.
# File lib/rubygems/validator.rb, line 84 84: def alien 85: errors = {} 86: 87: Gem::SourceIndex.from_installed_gems.each do |gem_name, gem_spec| 88: errors[gem_name] ||= [] 89: 90: gem_path = File.join(Gem.dir, "cache", gem_spec.full_name) + ".gem" 91: spec_path = File.join(Gem.dir, "specifications", gem_spec.full_name) + ".gemspec" 92: gem_directory = File.join(Gem.dir, "gems", gem_spec.full_name) 93: 94: installed_files = find_files_for_gem(gem_directory) 95: 96: unless File.exist? spec_path then 97: errors[gem_name] << ErrorData.new(spec_path, "Spec file doesn't exist for installed gem") 98: end 99: 100: begin 101: verify_gem_file(gem_path) 102: 103: open gem_path, Gem.binary_mode do |file| 104: format = Gem::Format.from_file_by_path(gem_path) 105: format.file_entries.each do |entry, data| 106: # Found this file. Delete it from list 107: installed_files.delete remove_leading_dot_dir(entry['path']) 108: 109: next unless data # HACK `gem check -a mkrf` 110: 111: open File.join(gem_directory, entry['path']), Gem.binary_mode do |f| 112: unless Gem::MD5.hexdigest(f.read).to_s == 113: Gem::MD5.hexdigest(data).to_s then 114: errors[gem_name] << ErrorData.new(entry['path'], "installed file doesn't match original from gem") 115: end 116: end 117: end 118: end 119: rescue Gem::VerificationError => e 120: errors[gem_name] << ErrorData.new(gem_path, e.message) 121: end 122: 123: # Clean out directories that weren't explicitly included in the gemspec 124: # FIXME: This still allows arbitrary incorrect directories. 125: installed_files.delete_if {|potential_directory| 126: File.directory?(File.join(gem_directory, potential_directory)) 127: } 128: if(installed_files.size > 0) then 129: errors[gem_name] << ErrorData.new(gem_path, "Unmanaged files in gem: #{installed_files.inspect}") 130: end 131: end 132: 133: errors 134: end
# File lib/rubygems/validator.rb, line 203 203: def remove_leading_dot_dir(path) 204: path.sub(/^\.\//, "") 205: end
Runs unit tests for a given gem specification
# File lib/rubygems/validator.rb, line 167 167: def unit_test(gem_spec) 168: start_dir = Dir.pwd 169: Dir.chdir(gem_spec.full_gem_path) 170: $: << File.join(Gem.dir, "gems", gem_spec.full_name) 171: # XXX: why do we need this gem_spec when we've already got 'spec'? 172: test_files = gem_spec.test_files 173: 174: if test_files.empty? then 175: say "There are no unit tests to run for #{gem_spec.full_name}" 176: return nil 177: end 178: 179: gem gem_spec.name, "= #{gem_spec.version.version}" 180: 181: test_files.each do |f| require f end 182: 183: if RUBY_VERSION < '1.9' then 184: suite = Test::Unit::TestSuite.new("#{gem_spec.name}-#{gem_spec.version}") 185: 186: ObjectSpace.each_object(Class) do |klass| 187: suite << klass.suite if (klass < Test::Unit::TestCase) 188: end 189: 190: result = TestRunner.run suite, ui 191: 192: alert_error result.to_s unless result.passed? 193: else 194: result = MiniTest::Unit.new 195: result.run 196: end 197: 198: result 199: ensure 200: Dir.chdir(start_dir) 201: end
Given a gem file‘s contents, validates against its own MD5 checksum
gem_data: | [String] Contents of the gem file |
# File lib/rubygems/validator.rb, line 24 24: def verify_gem(gem_data) 25: raise Gem::VerificationError, 'empty gem file' if gem_data.size == 0 26: 27: unless gem_data =~ /MD5SUM/ then 28: return # Don't worry about it...this sucks. Need to fix MD5 stuff for 29: # new format 30: # FIXME 31: end 32: 33: sum_data = gem_data.gsub(/MD5SUM = "([a-z0-9]+)"/, 34: "MD5SUM = \"#{"F" * 32}\"") 35: 36: unless Gem::MD5.hexdigest(sum_data) == $1.to_s then 37: raise Gem::VerificationError, 'invalid checksum for gem file' 38: end 39: end
Given the path to a gem file, validates against its own MD5 checksum
gem_path: | [String] Path to gem file |
# File lib/rubygems/validator.rb, line 46 46: def verify_gem_file(gem_path) 47: open gem_path, Gem.binary_mode do |file| 48: gem_data = file.read 49: verify_gem gem_data 50: end 51: rescue Errno::ENOENT 52: raise Gem::VerificationError, "missing gem file #{gem_path}" 53: end