diff options
Diffstat (limited to 'ident.go')
| -rw-r--r-- | ident.go | 127 |
1 files changed, 0 insertions, 127 deletions
diff --git a/ident.go b/ident.go deleted file mode 100644 index 50676a45..00000000 --- a/ident.go +++ /dev/null @@ -1,127 +0,0 @@ -package furgit - -import ( - "bytes" - "errors" - "fmt" - "math" - "strconv" - "strings" - "time" -) - -// Ident represents a Git identity (author/committer/tagger). -type Ident struct { - // Name represents the person's name. - Name []byte - // Email represents the person's email. - Email []byte - // WhenUnix represents the timestamp as a Unix time. - // This value is in UTC. - WhenUnix int64 - // The timezone offset in minutes. - OffsetMinutes int32 -} - -// parseIdent parses an identity line from the canonical Git format: -// "Name <email> 123456789 +0000". -func parseIdent(line []byte) (*Ident, error) { - lt := bytes.IndexByte(line, '<') - if lt < 0 { - return nil, errors.New("furgit: ident: missing opening <") - } - gtRel := bytes.IndexByte(line[lt+1:], '>') - if gtRel < 0 { - return nil, errors.New("furgit: ident: missing closing >") - } - gt := lt + 1 + gtRel - nameBytes := append([]byte(nil), line[:lt]...) - emailBytes := append([]byte(nil), line[lt+1:gt]...) - - rest := line[gt+1:] - if len(rest) == 0 || rest[0] != ' ' { - return nil, errors.New("furgit: ident: missing timestamp separator") - } - rest = rest[1:] - sp := bytes.IndexByte(rest, ' ') - if sp < 0 { - return nil, errors.New("furgit: ident: missing timezone separator") - } - whenStr := string(rest[:sp]) - when, err := strconv.ParseInt(whenStr, 10, 64) - if err != nil { - return nil, fmt.Errorf("furgit: ident: invalid timestamp: %w", err) - } - - tz := rest[sp+1:] - if len(tz) < 5 { - return nil, errors.New("furgit: ident: invalid timezone encoding") - } - sign := 1 - switch tz[0] { - case '-': - sign = -1 - case '+': - default: - return nil, errors.New("furgit: ident: invalid timezone sign") - } - - hh, err := strconv.Atoi(string(tz[1:3])) - if err != nil { - return nil, fmt.Errorf("furgit: ident: invalid timezone hours: %w", err) - } - mm, err := strconv.Atoi(string(tz[3:5])) - if err != nil { - return nil, fmt.Errorf("furgit: ident: invalid timezone minutes: %w", err) - } - if hh < 0 || hh > 23 { - return nil, errors.New("furgit: ident: invalid timezone hours range") - } - if mm < 0 || mm > 59 { - return nil, errors.New("furgit: ident: invalid timezone minutes range") - } - total := int64(hh)*60 + int64(mm) - if total > math.MaxInt32 { - return nil, errors.New("furgit: ident: timezone overflow") - } - offset := int32(total) - if sign < 0 { - offset = -offset - } - - return &Ident{ - Name: nameBytes, - Email: emailBytes, - WhenUnix: when, - OffsetMinutes: offset, - }, nil -} - -// Serialize renders an Ident into canonical Git format. -func (ident Ident) Serialize() ([]byte, error) { - var b strings.Builder - b.Grow(len(ident.Name) + len(ident.Email) + 32) - b.Write(ident.Name) - b.WriteString(" <") - b.Write(ident.Email) - b.WriteString("> ") - b.WriteString(strconv.FormatInt(ident.WhenUnix, 10)) - b.WriteByte(' ') - - offset := ident.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 the ident's time.Time with the correct timezone. -func (ident Ident) When() time.Time { - loc := time.FixedZone("git", int(ident.OffsetMinutes)*60) - return time.Unix(ident.WhenUnix, 0).In(loc) -} |
