Fast implementation of Git in pure Go
at master 93 lines 1.9 kB view raw
1package object 2 3import ( 4 "bytes" 5 "errors" 6 "fmt" 7 8 "codeberg.org/lindenii/furgit/objectid" 9) 10 11// ParseCommit decodes a commit object body. 12func ParseCommit(body []byte, algo objectid.Algorithm) (*Commit, error) { 13 c := new(Commit) 14 15 i := 0 16 for i < len(body) { 17 rel := bytes.IndexByte(body[i:], '\n') 18 if rel < 0 { 19 return nil, errors.New("object: commit: missing newline") 20 } 21 22 line := body[i : i+rel] 23 i += rel + 1 24 25 if len(line) == 0 { 26 break 27 } 28 29 key, value, found := bytes.Cut(line, []byte{' '}) 30 if !found { 31 return nil, errors.New("object: commit: malformed header") 32 } 33 34 switch string(key) { 35 case "tree": 36 id, err := objectid.ParseHex(algo, string(value)) 37 if err != nil { 38 return nil, fmt.Errorf("object: commit: tree: %w", err) 39 } 40 41 c.Tree = id 42 case "parent": 43 id, err := objectid.ParseHex(algo, string(value)) 44 if err != nil { 45 return nil, fmt.Errorf("object: commit: parent: %w", err) 46 } 47 48 c.Parents = append(c.Parents, id) 49 case "author": 50 idt, err := ParseSignature(value) 51 if err != nil { 52 return nil, fmt.Errorf("object: commit: author: %w", err) 53 } 54 55 c.Author = *idt 56 case "committer": 57 idt, err := ParseSignature(value) 58 if err != nil { 59 return nil, fmt.Errorf("object: commit: committer: %w", err) 60 } 61 62 c.Committer = *idt 63 case "change-id": 64 c.ChangeID = string(value) 65 case "gpgsig", "gpgsig-sha256": 66 for i < len(body) { 67 nextRel := bytes.IndexByte(body[i:], '\n') 68 if nextRel < 0 { 69 return nil, errors.New("object: commit: unterminated gpgsig") 70 } 71 72 if body[i] != ' ' { 73 break 74 } 75 76 i += nextRel + 1 77 } 78 default: 79 c.ExtraHeaders = append(c.ExtraHeaders, ExtraHeader{ 80 Key: string(key), 81 Value: append([]byte(nil), value...), 82 }) 83 } 84 } 85 86 if i > len(body) { 87 return nil, errors.New("object: commit: parser position out of bounds") 88 } 89 90 c.Message = append([]byte(nil), body[i:]...) 91 92 return c, nil 93}