Class: Amp::Core::Repositories::Git::PackFile::PackFileEntry
- Inherits:
-
Struct
- Object
- Struct
- Amp::Core::Repositories::Git::PackFile::PackFileEntry
- Includes:
- Support
- Defined in:
- lib/amp-git/repo_format/packfile.rb
Overview
A single entry in a packfile. Dumb struct. However, it has some smart class methods for parsing these bad boys in from a packfile. Take a look at #at and #read.
Instance Attribute Summary collapse
-
#content ⇒ Object
Returns the value of attribute content.
-
#delta_offset ⇒ Object
Returns the value of attribute delta_offset.
-
#hash_id ⇒ Object
Returns the value of attribute hash_id.
-
#offset ⇒ Object
Returns the value of attribute offset.
-
#reference ⇒ Object
Returns the value of attribute reference.
-
#size ⇒ Object
Returns the value of attribute size.
-
#type ⇒ Object
Returns the value of attribute type.
Class Method Summary collapse
-
.at(fp, pos) ⇒ PackFileEntry
Reads a PackFileEntry from the given file at a given offset.
-
.read(fp) ⇒ PackFileEntry
Reads a PackFileEntry from the given file.
-
.read_data(fp, size) ⇒ String
Reads data from the file, uncompressing along the way, until
size
bytes have been decompressed. -
.read_header(fp) ⇒ Array(Integer, Integer)
Reads in a PackFileEntry header from the file.
-
.read_offset(fp) ⇒ Integer
Reads an OBJ_OFS_DELTA offset.
Instance Method Summary collapse
-
#calculate_hash! ⇒ Object
Calculates the hash of this particular entry.
-
#to_raw_object(opener = nil) ⇒ RawObject
Converts to an actual raw object.
Instance Attribute Details
#content ⇒ Object
Returns the value of attribute content
43 44 45 |
# File 'lib/amp-git/repo_format/packfile.rb', line 43 def content @content end |
#delta_offset ⇒ Object
Returns the value of attribute delta_offset
43 44 45 |
# File 'lib/amp-git/repo_format/packfile.rb', line 43 def delta_offset @delta_offset end |
#hash_id ⇒ Object
Returns the value of attribute hash_id
43 44 45 |
# File 'lib/amp-git/repo_format/packfile.rb', line 43 def hash_id @hash_id end |
#offset ⇒ Object
Returns the value of attribute offset
43 44 45 |
# File 'lib/amp-git/repo_format/packfile.rb', line 43 def offset @offset end |
#reference ⇒ Object
Returns the value of attribute reference
43 44 45 |
# File 'lib/amp-git/repo_format/packfile.rb', line 43 def reference @reference end |
#size ⇒ Object
Returns the value of attribute size
43 44 45 |
# File 'lib/amp-git/repo_format/packfile.rb', line 43 def size @size end |
#type ⇒ Object
Returns the value of attribute type
43 44 45 |
# File 'lib/amp-git/repo_format/packfile.rb', line 43 def type @type end |
Class Method Details
.at(fp, pos) ⇒ PackFileEntry
Reads a Amp::Core::Repositories::Git::PackFile::PackFileEntry from the given file at a given offset. This is a helper method for the entry point for reading from an actual PackFile, since often, you’ll know where the entry will be located in the PackFile.
54 55 56 57 |
# File 'lib/amp-git/repo_format/packfile.rb', line 54 def at(fp, pos) fp.seek pos, IO::SEEK_SET read fp end |
.read(fp) ⇒ PackFileEntry
Reads a Amp::Core::Repositories::Git::PackFile::PackFileEntry from the given file. This is the entry point for reading from an actual PackFile.
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/amp-git/repo_format/packfile.rb', line 65 def read(fp) result = PackFileEntry.new result.offset = fp.pos result.type, result.size = read_header(fp) if result.type == OBJ_REF_DELTA result.reference = fp.read(20) elsif result.type == OBJ_OFS_DELTA result.delta_offset = result.offset - read_offset(fp) end result.content = read_data(fp, result.size) if result.type == OBJ_REF_DELTA elsif result.type == OBJ_OFS_DELTA cur = fp.tell patch = Amp::Core::Repositories::Git::Encoding::BinaryDelta.new(result.content) previous = self.at(fp, result.delta_offset) result.content = patch.apply(previous.content) result.size = result.content.size result.type = previous.type fp.seek(cur, IO::SEEK_SET) end result.calculate_hash! result end |
.read_data(fp, size) ⇒ String
Reads data from the file, uncompressing along the way, until size
bytes have been decompressed. Since we don’t know how much that will be ahead of time, this is annoying slow. Oh wells.
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/amp-git/repo_format/packfile.rb', line 137 def read_data(fp, size) result = "" z = Zlib::Inflate.new start = fp.tell while result.size < size && !z.stream_end? result += z.inflate(fp.read(1)) end # final bytes... can't predict this yet though it's usually 5 bytes while !fp.eof? begin result += z.finish break rescue Zlib::BufError result += z.inflate(fp.read(1)) end end z.close result end |
.read_header(fp) ⇒ Array(Integer, Integer)
Reads in a PackFileEntry header from the file. This will get us the type of the entry, as well as the size of its uncompressed data.
116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/amp-git/repo_format/packfile.rb', line 116 def read_header(fp) = Support::HexString.from_bin(fp.read(1)).ord type = ( & 0x70) >> 4 size = & 0xF shift = 4 while & 0x80 > 0 = Support::HexString.from_bin(fp.read(1)).ord size += ( & 0x7F) << shift shift += 7 end [type, size] end |
.read_offset(fp) ⇒ Integer
Reads an OBJ_OFS_DELTA offset. N-bytes, encoded as a series of bytes. Each byte is shifted by (7 * n) bits, and added to the total. If the high bit (MSB) of a byte is 1, then another byte is read, If it’s 0, it stops.
98 99 100 101 102 103 104 105 106 107 |
# File 'lib/amp-git/repo_format/packfile.rb', line 98 def read_offset(fp) byte = Support::HexString.from_bin(fp.read(1)).ord tot = byte & 0x7f while (byte & 0x80) > 0 byte = Support::HexString.from_bin(fp.read(1)).ord tot = ((tot + 1) << 7) | (byte & 0x7f) break if (byte & 0x80) == 0 end tot end |
Instance Method Details
#calculate_hash! ⇒ Object
Calculates the hash of this particular entry. We need to reconstruct the loose object header to do this.
161 162 163 164 165 |
# File 'lib/amp-git/repo_format/packfile.rb', line 161 def calculate_hash! prefix = PREFIX_NAME_LOOKUP[self.type] # add special cases for refs self.hash_id = NodeId.sha1("#{prefix} #{self.size}\0#{self.content}") end |
#to_raw_object(opener = nil) ⇒ RawObject
Converts to an actual raw object.
173 174 175 |
# File 'lib/amp-git/repo_format/packfile.rb', line 173 def to_raw_object(opener = nil) RawObject.construct(hash_id, opener, PREFIX_NAME_LOOKUP[type], content) end |