Fast implementation of Git in pure Go
at master 88 lines 1.7 kB view raw
1package object 2 3import ( 4 "bytes" 5 "errors" 6 "fmt" 7 8 "codeberg.org/lindenii/furgit/objectid" 9 "codeberg.org/lindenii/furgit/objecttype" 10) 11 12// ParseTag decodes a tag object body. 13func ParseTag(body []byte, algo objectid.Algorithm) (*Tag, error) { 14 t := new(Tag) 15 i := 0 16 17 var haveTarget, haveType bool 18 19 for i < len(body) { 20 rel := bytes.IndexByte(body[i:], '\n') 21 if rel < 0 { 22 return nil, errors.New("object: tag: missing newline") 23 } 24 25 line := body[i : i+rel] 26 i += rel + 1 27 28 if len(line) == 0 { 29 break 30 } 31 32 key, value, found := bytes.Cut(line, []byte{' '}) 33 if !found { 34 return nil, errors.New("object: tag: malformed header") 35 } 36 37 switch string(key) { 38 case "object": 39 id, err := objectid.ParseHex(algo, string(value)) 40 if err != nil { 41 return nil, fmt.Errorf("object: tag: object: %w", err) 42 } 43 44 t.Target = id 45 haveTarget = true 46 case "type": 47 ty, ok := objecttype.ParseName(string(value)) 48 if !ok { 49 return nil, errors.New("object: tag: unknown target type") 50 } 51 52 t.TargetType = ty 53 haveType = true 54 case "tag": 55 t.Name = append([]byte(nil), value...) 56 case "tagger": 57 idt, err := ParseSignature(value) 58 if err != nil { 59 return nil, fmt.Errorf("object: tag: tagger: %w", err) 60 } 61 62 t.Tagger = idt 63 case "gpgsig", "gpgsig-sha256": 64 for i < len(body) { 65 nextRel := bytes.IndexByte(body[i:], '\n') 66 if nextRel < 0 { 67 return nil, errors.New("object: tag: unterminated gpgsig") 68 } 69 70 if body[i] != ' ' { 71 break 72 } 73 74 i += nextRel + 1 75 } 76 default: 77 // Ignore unknown headers for now. 78 } 79 } 80 81 if !haveTarget || !haveType { 82 return nil, errors.New("object: tag: missing required headers") 83 } 84 85 t.Message = append([]byte(nil), body[i:]...) 86 87 return t, nil 88}