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
|
package ingest
import (
"encoding/binary"
"io"
"codeberg.org/lindenii/furgit/internal/intconv"
objectid "codeberg.org/lindenii/furgit/object/id"
)
// rewritePackHeaderAndTrailer rewrites object count and trailer hash using ReadAt/WriteAt.
func rewritePackHeaderAndTrailer(state *ingestState) error {
var countRaw [4]byte
recordCountUint32, err := intconv.IntToUint32(len(state.records))
if err != nil {
return err
}
binary.BigEndian.PutUint32(countRaw[:], recordCountUint32)
_, err = state.packFile.WriteAt(countRaw[:], 8)
if err != nil {
return err
}
info, err := state.packFile.Stat()
if err != nil {
return err
}
endWithoutTrailer := info.Size()
hashImpl, err := state.algo.New()
if err != nil {
return err
}
var (
buf [128 << 10]byte
pos int64
)
for pos < endWithoutTrailer {
want := int64(len(buf))
remaining := endWithoutTrailer - pos
if remaining < want {
want = remaining
}
n, err := state.packFile.ReadAt(buf[:want], pos)
if err != nil && err != io.EOF {
return err
}
if n == 0 {
return io.ErrUnexpectedEOF
}
_, _ = hashImpl.Write(buf[:n])
pos += int64(n)
}
sum := hashImpl.Sum(nil)
_, err = state.packFile.WriteAt(sum, endWithoutTrailer)
if err != nil {
return err
}
packHash, err := objectid.FromBytes(state.algo, sum)
if err != nil {
return err
}
state.packHash = packHash
state.objectCountHeader = recordCountUint32
sumLenInt64 := int64(len(sum))
newConsumed, err := intconv.Int64ToUint64(endWithoutTrailer + sumLenInt64)
if err != nil {
return err
}
state.stream.consumed = newConsumed
return nil
}
|