aboutsummaryrefslogtreecommitdiff
path: root/object/ident.go
diff options
context:
space:
mode:
authorGravatar Runxi Yu2026-03-04 08:26:56 +0800
committerGravatar Runxi Yu2026-03-04 08:59:53 +0800
commitab7501be34032fb9e5c48726a68ae90a917af9eb (patch)
tree20d005647569befea8133e953c3270e8fd2a2a5b /object/ident.go
parent*: gofumpt (diff)
signatureNo signature
*: Lint
Diffstat (limited to 'object/ident.go')
-rw-r--r--object/ident.go18
1 files changed, 18 insertions, 0 deletions
diff --git a/object/ident.go b/object/ident.go
index 1ea55cc2..049b0c01 100644
--- a/object/ident.go
+++ b/object/ident.go
@@ -26,10 +26,12 @@ func ParseSignature(line []byte) (*Signature, error) {
if lt < 0 {
return nil, errors.New("object: signature: missing opening <")
}
+
gtRel := bytes.IndexByte(line[lt+1:], '>')
if gtRel < 0 {
return nil, errors.New("object: signature: missing closing >")
}
+
gt := lt + 1 + gtRel
nameBytes := append([]byte(nil), bytes.TrimRight(line[:lt], " ")...)
@@ -39,11 +41,14 @@ func ParseSignature(line []byte) (*Signature, error) {
if len(rest) == 0 || rest[0] != ' ' {
return nil, errors.New("object: signature: missing timestamp separator")
}
+
rest = rest[1:]
+
before, after, ok := bytes.Cut(rest, []byte{' '})
if !ok {
return nil, errors.New("object: signature: missing timezone separator")
}
+
when, err := strconv.ParseInt(string(before), 10, 64)
if err != nil {
return nil, fmt.Errorf("object: signature: invalid timestamp: %w", err)
@@ -53,7 +58,9 @@ func ParseSignature(line []byte) (*Signature, error) {
if len(tz) < 5 {
return nil, errors.New("object: signature: invalid timezone encoding")
}
+
sign := 1
+
switch tz[0] {
case '-':
sign = -1
@@ -66,24 +73,31 @@ func ParseSignature(line []byte) (*Signature, error) {
if err != nil {
return nil, fmt.Errorf("object: signature: invalid timezone hours: %w", err)
}
+
mm, err := strconv.Atoi(string(tz[3:5]))
if err != nil {
return nil, fmt.Errorf("object: signature: invalid timezone minutes: %w", err)
}
+
if hh < 0 || hh > 23 {
return nil, errors.New("object: signature: invalid timezone hours range")
}
+
if mm < 0 || mm > 59 {
return nil, errors.New("object: signature: invalid timezone minutes range")
}
+
total := int64(hh)*60 + int64(mm)
+
offset, err := intconv.Int64ToInt32(total)
if err != nil {
return nil, errors.New("object: signature: timezone overflow")
}
+
if sign < 0 {
offset = -offset
}
+
return &Signature{
Name: nameBytes,
Email: emailBytes,
@@ -104,19 +118,23 @@ func (signature Signature) Serialize() ([]byte, error) {
b.WriteByte(' ')
offset := signature.OffsetMinutes
+
sign := '+'
if offset < 0 {
sign = '-'
offset = -offset
}
+
hh := offset / 60
mm := offset % 60
fmt.Fprintf(&b, "%c%02d%02d", sign, hh, mm)
+
return []byte(b.String()), nil
}
// When returns a time.Time with the signature's timezone offset.
func (signature Signature) When() time.Time {
loc := time.FixedZone("git", int(signature.OffsetMinutes)*60)
+
return time.Unix(signature.WhenUnix, 0).In(loc)
}