class Grit::GitRuby::Internal::LooseStorage

Public Class Methods

calculate_sha(content, type) click to toggle source

simply figure out the sha

# File lib/grit/lib/grit/git-ruby/internal/loose.rb, line 87
def self.calculate_sha(content, type)
  size = content.length.to_s
  verify_header(type, size)
  header = "#{type} #{size}\0"
  store = header + content

  Digest::SHA1.hexdigest(store)
end
new(directory) click to toggle source
# File lib/grit/lib/grit/git-ruby/internal/loose.rb, line 23
def initialize(directory)
  @directory = directory
end
verify_header(type, size) click to toggle source
# File lib/grit/lib/grit/git-ruby/internal/loose.rb, line 96
def self.verify_header(type, size)
  if !%w(blob tree commit tag).include?(type) || size !~ /^\d+$/
    raise LooseObjectError, "invalid object header"
  end
end

Public Instance Methods

[](sha1) click to toggle source
# File lib/grit/lib/grit/git-ruby/internal/loose.rb, line 27
def [](sha1)
  sha1 = sha1.unpack("H*")[0]
  begin
    return nil unless sha1[0...2] && sha1[2..39]
    path = @directory + '/' + sha1[0...2] + '/' + sha1[2..39]
    get_raw_object(File.read(path))
  rescue Errno::ENOENT
    nil
  end
end
get_raw_object(buf) click to toggle source
# File lib/grit/lib/grit/git-ruby/internal/loose.rb, line 38
def get_raw_object(buf)
  if buf.length < 2
    raise LooseObjectError, "object file too small"
  end

  if legacy_loose_object?(buf)
    content = Zlib::Inflate.inflate(buf)
    header, content = content.split(/\0/, 2)
    if !header || !content
      raise LooseObjectError, "invalid object header"
    end
    type, size = header.split(/ /, 2)
    if !%w(blob tree commit tag).include?(type) || size !~ /^\d+$/
      raise LooseObjectError, "invalid object header"
    end
    type = type.to_sym
    size = size.to_i
  else
    type, size, used = unpack_object_header_gently(buf)
    content = Zlib::Inflate.inflate(buf[used..-1])
  end
  raise LooseObjectError, "size mismatch" if content.length != size
  return RawObject.new(type, content)
end
put_raw_object(content, type) click to toggle source

currently, I’m using the legacy format because it’s easier to do this function takes content and a type and writes out the loose object and returns a sha

# File lib/grit/lib/grit/git-ruby/internal/loose.rb, line 65
def put_raw_object(content, type)
  size = content.length.to_s
  LooseStorage.verify_header(type, size)

  header = "#{type} #{size}\0"
  store = header + content

  sha1 = Digest::SHA1.hexdigest(store)
  path = @directory+'/'+sha1[0...2]+'/'+sha1[2..40]

  if !File.exists?(path)
    content = Zlib::Deflate.deflate(store)

    FileUtils.mkdir_p(@directory+'/'+sha1[0...2])
    File.open(path, 'wb') do |f|
      f.write content
    end
  end
  return sha1
end

Private Instance Methods

legacy_loose_object?(buf) click to toggle source
# File lib/grit/lib/grit/git-ruby/internal/loose.rb, line 129
def legacy_loose_object?(buf)
  word = (buf.getord(0) << 8) + buf.getord(1)
  buf.getord(0) == 0x78 && word % 31 == 0
end
unpack_object_header_gently(buf) click to toggle source

private

# File lib/grit/lib/grit/git-ruby/internal/loose.rb, line 103
def unpack_object_header_gently(buf)
  used = 0
  c = buf.getord(used)
  used += 1

  type = (c >> 4) & 7;
  size = c & 15;
  shift = 4;
  while c & 0x80 != 0
    if buf.length <= used
      raise LooseObjectError, "object file too short"
    end
    c = buf.getord(used)
    used += 1

    size += (c & 0x7f) << shift
    shift += 7
  end
  type = OBJ_TYPES[type]
  if ![:blob, :tree, :commit, :tag].include?(type)
    raise LooseObjectError, "invalid loose object type"
  end
  return [type, size, used]
end