Fast implementation of Git in pure Go
at master 81 lines 1.4 kB view raw
1package read 2 3import ( 4 "os" 5 "syscall" 6 7 "codeberg.org/lindenii/furgit/commitgraph" 8 "codeberg.org/lindenii/furgit/internal/intconv" 9 "codeberg.org/lindenii/furgit/objectid" 10) 11 12func openLayer(root *os.Root, relPath string, algo objectid.Algorithm) (*layer, error) { 13 file, err := root.Open(relPath) 14 if err != nil { 15 return nil, err 16 } 17 18 info, err := file.Stat() 19 if err != nil { 20 _ = file.Close() 21 22 return nil, err 23 } 24 25 size := info.Size() 26 if size < int64(commitgraph.HeaderSize+commitgraph.FanoutSize+algo.Size()) { 27 _ = file.Close() 28 29 return nil, &MalformedError{Path: relPath, Reason: "file too short"} 30 } 31 32 mapLen, err := intconv.Int64ToUint64(size) 33 if err != nil { 34 _ = file.Close() 35 36 return nil, err 37 } 38 39 mapLenInt, err := intconv.Uint64ToInt(mapLen) 40 if err != nil { 41 _ = file.Close() 42 43 return nil, err 44 } 45 46 fd, err := intconv.UintptrToInt(file.Fd()) 47 if err != nil { 48 _ = file.Close() 49 50 return nil, err 51 } 52 53 data, err := syscall.Mmap(fd, 0, mapLenInt, syscall.PROT_READ, syscall.MAP_PRIVATE) 54 if err != nil { 55 _ = file.Close() 56 57 return nil, err 58 } 59 60 out := &layer{ 61 path: relPath, 62 file: file, 63 data: data, 64 } 65 66 parseErr := parseLayer(out, algo) 67 if parseErr != nil { 68 _ = out.close() 69 70 return nil, parseErr 71 } 72 73 verifyErr := verifyTrailerHash(out.data, algo, relPath) 74 if verifyErr != nil { 75 _ = out.close() 76 77 return nil, verifyErr 78 } 79 80 return out, nil 81}