Fast implementation of Git in pure Go
1package read
2
3import (
4 "bytes"
5 "fmt"
6 "io"
7
8 "codeberg.org/lindenii/furgit/objectid"
9)
10
11// HashVersion returns the commit-graph hash version.
12func (reader *Reader) HashVersion() uint8 {
13 return reader.hashVersion
14}
15
16func validateChainBaseHashes(algo objectid.Algorithm, chain []string, idx int, graph *layer) error {
17 if idx == 0 {
18 if len(graph.chunkBaseGraphs) != 0 {
19 return &MalformedError{Path: graph.path, Reason: "unexpected BASE chunk in first graph"}
20 }
21
22 return nil
23 }
24
25 hashSize := algo.Size()
26
27 expectedLen := idx * hashSize
28 if len(graph.chunkBaseGraphs) != expectedLen {
29 return &MalformedError{
30 Path: graph.path,
31 Reason: fmt.Sprintf("BASE chunk length %d does not match expected %d", len(graph.chunkBaseGraphs), expectedLen),
32 }
33 }
34
35 for i := range idx {
36 start := i * hashSize
37 end := start + hashSize
38
39 baseHash, err := objectid.FromBytes(algo, graph.chunkBaseGraphs[start:end])
40 if err != nil {
41 return err
42 }
43
44 if baseHash.String() != chain[i] {
45 return &MalformedError{
46 Path: graph.path,
47 Reason: fmt.Sprintf("BASE chunk mismatch at index %d", i),
48 }
49 }
50 }
51
52 return nil
53}
54
55func verifyTrailerHash(data []byte, algo objectid.Algorithm, path string) error {
56 hashSize := algo.Size()
57 if len(data) < hashSize {
58 return &MalformedError{Path: path, Reason: "file too short for trailer"}
59 }
60
61 hashImpl, err := algo.New()
62 if err != nil {
63 return err
64 }
65
66 _, err = io.Copy(hashImpl, bytes.NewReader(data[:len(data)-hashSize]))
67 if err != nil {
68 return err
69 }
70
71 got := hashImpl.Sum(nil)
72
73 want := data[len(data)-hashSize:]
74 if !bytes.Equal(got, want) {
75 return &MalformedError{Path: path, Reason: "trailer hash mismatch"}
76 }
77
78 return nil
79}