72 lines
2.1 KiB
Go
72 lines
2.1 KiB
Go
package pack
|
|
|
|
import (
|
|
"encoding/binary"
|
|
)
|
|
|
|
// V2 implements IndexVersion for v2 packfiles.
|
|
type V2 struct{}
|
|
|
|
// Name implements IndexVersion.Name by returning the 20 byte SHA-1 object name
|
|
// for the given entry at offset "at" in the v2 index file "idx".
|
|
func (v *V2) Name(idx *Index, at int64) ([]byte, error) {
|
|
var sha [20]byte
|
|
if _, err := idx.readAt(sha[:], v2ShaOffset(at)); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return sha[:], nil
|
|
}
|
|
|
|
// Entry implements IndexVersion.Entry for v2 packfiles by parsing and returning
|
|
// the IndexEntry specified at the offset "at" in the given index file.
|
|
func (v *V2) Entry(idx *Index, at int64) (*IndexEntry, error) {
|
|
var offs [4]byte
|
|
if _, err := idx.readAt(offs[:], v2SmallOffsetOffset(at, int64(idx.Count()))); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
loc := uint64(binary.BigEndian.Uint32(offs[:]))
|
|
if loc&0x80000000 > 0 {
|
|
// If the most significant bit (MSB) of the offset is set, then
|
|
// the offset encodes the location for an 8-byte offset.
|
|
//
|
|
// Mask away (offs&0x7fffffff) the MSB to return the remaining
|
|
// offset.
|
|
var offs [8]byte
|
|
if _, err := idx.readAt(offs[:], int64(loc&0x7fffffff)); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
loc = binary.BigEndian.Uint64(offs[:])
|
|
}
|
|
return &IndexEntry{PackOffset: loc}, nil
|
|
}
|
|
|
|
// Width implements IndexVersion.Width() by returning the number of bytes that
|
|
// v2 packfile index header occupy.
|
|
func (v *V2) Width() int64 {
|
|
return indexV2Width
|
|
}
|
|
|
|
// v2ShaOffset returns the offset of a SHA1 given at "at" in the V2 index file.
|
|
func v2ShaOffset(at int64) int64 {
|
|
// Skip the packfile index header and the L1 fanout table.
|
|
return indexOffsetV2Start +
|
|
// Skip until the desired name in the sorted names table.
|
|
(indexObjectNameWidth * at)
|
|
}
|
|
|
|
// v2SmallOffsetOffset returns the offset of an object's small (4-byte) offset
|
|
// given by "at".
|
|
func v2SmallOffsetOffset(at, total int64) int64 {
|
|
// Skip the packfile index header and the L1 fanout table.
|
|
return indexOffsetV2Start +
|
|
// Skip the name table.
|
|
(indexObjectNameWidth * total) +
|
|
// Skip the CRC table.
|
|
(indexObjectCRCWidth * total) +
|
|
// Skip until the desired index in the small offsets table.
|
|
(indexObjectSmallOffsetWidth * at)
|
|
}
|