File: index_v2.go

package info (click to toggle)
golang-github-git-lfs-gitobj 2.1.1-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 432 kB
  • sloc: makefile: 2; sh: 1
file content (97 lines) | stat: -rw-r--r-- 2,989 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package pack

import (
	"encoding/binary"
	"hash"
)

// V2 implements IndexVersion for v2 packfiles.
type V2 struct {
	hash hash.Hash
}

// 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 [MaxHashSize]byte

	hashlen := v.hash.Size()

	if _, err := idx.readAt(sha[:hashlen], v2ShaOffset(at, int64(hashlen))); err != nil {
		return nil, err
	}

	return sha[:hashlen], 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

	hashlen := v.hash.Size()

	if _, err := idx.readAt(offs[:], v2SmallOffsetOffset(at, int64(idx.Count()), int64(hashlen))); 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 indexed location for an 8-byte offset.
		//
		// Mask away (offs&0x7fffffff) the MSB to use as an index to
		// find the offset of the 8-byte pack offset.
		lo := v2LargeOffsetOffset(int64(loc&0x7fffffff), int64(idx.Count()), int64(hashlen))

		var offs [8]byte
		if _, err := idx.readAt(offs[:], lo); 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, hashlen int64) int64 {
	// Skip the packfile index header and the L1 fanout table.
	return indexOffsetV2Start +
		// Skip until the desired name in the sorted names table.
		(hashlen * at)
}

// v2SmallOffsetOffset returns the offset of an object's small (4-byte) offset
// given by "at".
func v2SmallOffsetOffset(at, total, hashlen int64) int64 {
	// Skip the packfile index header and the L1 fanout table.
	return indexOffsetV2Start +
		// Skip the name table.
		(hashlen * total) +
		// Skip the CRC table.
		(indexObjectCRCWidth * total) +
		// Skip until the desired index in the small offsets table.
		(indexObjectSmallOffsetWidth * at)
}

// v2LargeOffsetOffset returns the offset of an object's large (4-byte) offset,
// given by the index "at".
func v2LargeOffsetOffset(at, total, hashlen int64) int64 {
	// Skip the packfile index header and the L1 fanout table.
	return indexOffsetV2Start +
		// Skip the name table.
		(hashlen * total) +
		// Skip the CRC table.
		(indexObjectCRCWidth * total) +
		// Skip the small offsets table.
		(indexObjectSmallOffsetWidth * total) +
		// Seek to the large offset within the large offset(s) table.
		(indexObjectLargeOffsetWidth * at)
}