class Nanoc::Int::Checksummer

Creates checksums for given objects.

A checksum is a string, such as “mL+TaqNsEeiPkWloPgCtAofT1yg=”, that is used to determine whether a piece of data has changed.

@api private

Public Class Methods

calc(obj, digest_class = CompactDigest) click to toggle source

@param obj The object to create a checksum for

@return [String] The digest

# File lib/nanoc/base/checksummer.rb, line 41
def calc(obj, digest_class = CompactDigest)
  digest = digest_class.new
  update(obj, digest)
  digest.to_s
end

Private Class Methods

update(obj, digest, visited = Set.new) click to toggle source
# File lib/nanoc/base/checksummer.rb, line 49
def update(obj, digest, visited = Set.new)
  digest.update(obj.class.to_s)
  digest.update('<')

  if visited.include?(obj)
    digest.update('recur>')
    return
  end

  case obj
  when ::String, ::Symbol, ::Numeric
    digest.update(obj.to_s)
  when nil, true, false
  when ::Array, ::Nanoc::Int::IdentifiableCollection
    obj.each do |el|
      update(el, digest, visited + [obj])
      digest.update(',')
    end
  when ::Hash, ::Nanoc::Int::Configuration
    obj.each do |key, value|
      update(key, digest, visited + [obj])
      digest.update('=')
      update(value, digest, visited + [obj])
      digest.update(',')
    end
  when ::Pathname
    filename = obj.to_s
    if File.exist?(filename)
      stat = File.stat(filename)
      digest.update(stat.size.to_s + '-' + stat.mtime.to_i.to_s)
    else
      digest.update('???')
    end
  when Time
    digest.update(obj.to_i.to_s)
  when Nanoc::Identifier
    update(obj.to_s, digest)
  # TODO: Use RuleMemory rather than RulesCollection
  when Nanoc::RuleDSL::RulesCollection, Nanoc::Int::CodeSnippet
    update(obj.data, digest)
  when Nanoc::Int::TextualContent
    update(obj.string, digest)
  when Nanoc::Int::BinaryContent
    update(Pathname.new(obj.filename), digest)
  when Nanoc::Int::Item, Nanoc::Int::Layout
    digest.update('content=')
    update(obj.content, digest)

    digest.update(',attributes=')
    update(obj.attributes, digest, visited + [obj])

    digest.update(',identifier=')
    update(obj.identifier, digest)
  when Nanoc::ItemWithRepsView, Nanoc::ItemWithoutRepsView, Nanoc::LayoutView, Nanoc::ConfigView, Nanoc::IdentifiableCollectionView
    update(obj.unwrap, digest)
  else
    data = begin
      Marshal.dump(obj)
    rescue
      obj.inspect
    end

    digest.update(data)
  end

  digest.update('>')
end