ref: df1f2fb3daa1acd25c88510f259d5535fb482126
dir: /object/tag/parse.go/
package tag
import (
"bytes"
"errors"
"fmt"
objectid "codeberg.org/lindenii/furgit/object/id"
objectsignature "codeberg.org/lindenii/furgit/object/signature"
objecttype "codeberg.org/lindenii/furgit/object/type"
)
// Parse decodes a tag object body.
func Parse(body []byte, algo objectid.Algorithm) (*Tag, error) {
t := new(Tag)
i := 0
var haveTarget, haveType bool
for i < len(body) {
rel := bytes.IndexByte(body[i:], '\n')
if rel < 0 {
return nil, errors.New("object: tag: missing newline")
}
line := body[i : i+rel]
i += rel + 1
if len(line) == 0 {
break
}
key, value, found := bytes.Cut(line, []byte{' '})
if !found {
return nil, errors.New("object: tag: malformed header")
}
switch string(key) {
case "object":
id, err := objectid.ParseHex(algo, string(value))
if err != nil {
return nil, fmt.Errorf("object: tag: object: %w", err)
}
t.Target = id
haveTarget = true
case "type":
ty, ok := objecttype.Parse(string(value))
if !ok {
return nil, errors.New("object: tag: unknown target type")
}
t.TargetType = ty
haveType = true
case "tag":
t.Name = append([]byte(nil), value...)
case "tagger":
idt, err := objectsignature.Parse(value)
if err != nil {
return nil, fmt.Errorf("object: tag: tagger: %w", err)
}
t.Tagger = idt
case "gpgsig", "gpgsig-sha256":
for i < len(body) {
nextRel := bytes.IndexByte(body[i:], '\n')
if nextRel < 0 {
return nil, errors.New("object: tag: unterminated gpgsig")
}
if body[i] != ' ' {
break
}
i += nextRel + 1
}
default:
// Ignore unknown headers for now.
}
}
if !haveTarget || !haveType {
return nil, errors.New("object: tag: missing required headers")
}
t.Message = append([]byte(nil), body[i:]...)
return t, nil
}