Fast implementation of Git in pure Go
at master 79 lines 1.7 kB view raw
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}