lib/checkm.rb in checkm-0.0.4 vs lib/checkm.rb in checkm-0.0.6

- old
+ new

@@ -1,183 +1,32 @@ -require 'time' +require 'checkm/manifest' +require 'checkm/entry' module Checkm + # Size (in bytes) to read (in chunks) to compute checksums CHUNK_SIZE = 8*1024*1024 + + # Compute the checksum 'alg' for a file + # @param [File] file + # @param [String] alg md5, sha1, sha256, dir def self.checksum file, alg digest_alg = case alg when nil return true when /md5/ - Digest::MD5.new if alg == 'md5' + Digest::MD5.new when /sha1/ + Digest::SHA1.new when /sha256/ + Digest::SHA2.new(256) when /dir/ return File.directory? file else return false end while not file.eof? and chunk = file.readpartial(CHUNK_SIZE) digest_alg << chunk end digest_alg.hexdigest - end - - class Manifest - def self.parse str, args = {} - Manifest.new str, args - end - - attr_reader :version - attr_reader :entries - attr_reader :fields - attr_reader :path - - def initialize checkm, args = {} - @args = args - @version = nil - @checkm = checkm - @lines = checkm.split "\n" - @entries = [] - @eof = false - @fields= nil - @path = args[:path] - @path ||= Dir.pwd - parse_lines - # xxx error on empty entries? - @lines.unshift('#%checkm_0.7') and @version = '0.7' if @version.nil? - - end - - def valid? - return true if @entries.empty? - not @entries.map { |e| e.valid? }.any? { |b| b == false } - end - - def add path, args = {} - line = Checkm::Entry.create path, args - - Checkm::Manifest.new [@lines, line].flatten.join("\n"), @args - end - - def remove path - Checkm::Manifest.new @lines.reject { |x| x =~ /^@?#{path}/ }.join("\n"), @args - end - - def to_s - @lines.join("\n") - end - - def to_hash - Hash[*@entries.map { |x| [x.sourcefileorurl, x] }.flatten] - end - - private - - def parse_lines - @lines.each do |line| - case line - when /^#%/ - parse_header line - when /^#/ - parse_comment line - when /^$/ - - when /^@/ - parse_line line - else - parse_line line - end - end - end - - def parse_header line - case line - when /^#%checkm/ - match = /^#%checkm_(\d+)\.(\d+)/.match line - @version = "#{match[1]}.#{match[2]}" if match - when /^#%eof/ - @eof = true - when /^#%fields/ - list = line.split('|') - list.shift - @fields = list.map { |v| v.strip.downcase } - when /^#%prefix/ - - when /^#%profile/ - - end - end - - def parse_comment line - - end - - def parse_line line - @entries << Entry.new(line, self) - end - - end - - class Entry - BASE_FIELDS = ['sourcefileorurl', 'alg', 'digest', 'length', 'modtime', 'targetfileorurl'] - attr_reader :values - - def self.create path, args = {} - base = args[:base] || Dir.pwd - alg = args[:alg] || 'md5' - file = File.new File.join(base, path) - - "%s | %s | %s | %s | %s | %s" % [path, alg, Checkm.checksum(file, alg), File.size(file.path), file.mtime.utc.xmlschema, nil] - end - - def initialize line, manifest = nil - @line = line.strip - @include = false - @fields = BASE_FIELDS - @fields = manifest.fields if manifest and manifest.fields - @values = line.split('|').map { |s| s.strip } - @manifest = manifest - end - - def method_missing(sym, *args, &block) - @values[@fields.index(sym.to_s.downcase) || BASE_FIELDS.index(sym.to_s.downcase)] rescue nil - end - - - def valid? - return source_exists? && valid_checksum? && valid_multilevel? # xxx && valid_length? && valid_modtime? - end - - private - def source - file = sourcefileorurl - file = file[1..-1] if file =~ /^@/ - File.join(@manifest.path, file) - end - - def source_exists? - return File.exists? source - end - - def valid_checksum? - file = File.new source - checksum = Checkm.checksum(file, alg) - checksum === true or checksum == digest - end - - - def valid_length? - throw NotImplementedError - end - - def valid_modtime? - throw NotImplementedError - end - - def valid_multilevel? - return true unless sourcefileorurl =~ /^@/ - - return Manifest.parse(open(source).read, File.dirname(source)) - end end end