2 # converted from the gitrb project
5 # Matthias Lederhofer <matled@gmx.net>
6 # Simon 'corecode' Schubert <corecode@fs.ei.tum.de>
8 # provides native ruby access to git objects and pack files
14 require 'git/raw/internal/object'
19 class LooseObjectError < StandardError
23 def initialize(directory)
24 @directory = directory
28 sha1 = sha1.unpack("H*")[0]
30 path = @directory+'/'+sha1[0...2]+'/'+sha1[2..40]
32 get_raw_object(File.read(path))
38 def get_raw_object(buf)
40 raise LooseObjectError, "object file too small"
43 if legacy_loose_object?(buf)
44 content = Zlib::Inflate.inflate(buf)
45 header, content = content.split(/\0/, 2)
46 if !header || !content
47 raise LooseObjectError, "invalid object header"
49 type, size = header.split(/ /, 2)
50 if !%w(blob tree commit tag).include?(type) || size !~ /^\d+$/
51 raise LooseObjectError, "invalid object header"
56 type, size, used = unpack_object_header_gently(buf)
57 content = Zlib::Inflate.inflate(buf[used..-1])
59 raise LooseObjectError, "size mismatch" if content.length != size
60 return RawObject.new(type, content)
64 def unpack_object_header_gently(buf)
74 raise LooseObjectError, "object file too short"
79 size += (c & 0x7f) << shift
82 type = OBJ_TYPES[type]
83 if ![:blob, :tree, :commit, :tag].include?(type)
84 raise LooseObjectError, "invalid loose object type"
86 return [type, size, used]
88 private :unpack_object_header_gently
90 def legacy_loose_object?(buf)
91 word = (buf[0] << 8) + buf[1]
92 buf[0] == 0x78 && word % 31 == 0
94 private :legacy_loose_object?
103 storage = Git::Internal::LooseStorage.new(path)
104 Find.find(path) do |p|
105 next if !/\/([0-9a-f]{2})\/([0-9a-f]{38})$/.match(p)
106 obj = storage[[$1+$2].pack("H*")]
107 puts "%s %s" % [obj.sha1.unpack("H*")[0], obj.type]