|
1 | 1 | package git |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "bytes" |
4 | 5 | "errors" |
5 | 6 | "fmt" |
6 | 7 | "io" |
@@ -47,60 +48,46 @@ type Signature struct { |
47 | 48 |
|
48 | 49 | // Decode decodes a byte slice into a signature |
49 | 50 | func (s *Signature) Decode(b []byte) { |
50 | | - if len(b) == 0 { |
| 51 | + open := bytes.IndexByte(b, '<') |
| 52 | + close := bytes.IndexByte(b, '>') |
| 53 | + if open == -1 || close == -1 { |
51 | 54 | return |
52 | 55 | } |
53 | 56 |
|
54 | | - from := 0 |
55 | | - state := 'n' // n: name, e: email, t: timestamp, z: timezone |
56 | | - for i := 0; ; i++ { |
57 | | - var c byte |
58 | | - var end bool |
59 | | - if i < len(b) { |
60 | | - c = b[i] |
61 | | - } else { |
62 | | - end = true |
63 | | - } |
64 | | - |
65 | | - switch state { |
66 | | - case 'n': |
67 | | - if c == '<' || end { |
68 | | - if i == 0 { |
69 | | - break |
70 | | - } |
71 | | - s.Name = string(b[from : i-1]) |
72 | | - state = 'e' |
73 | | - from = i + 1 |
74 | | - } |
75 | | - case 'e': |
76 | | - if c == '>' || end { |
77 | | - s.Email = string(b[from:i]) |
78 | | - i++ |
79 | | - state = 't' |
80 | | - from = i + 1 |
81 | | - } |
82 | | - case 't': |
83 | | - if c == ' ' || end { |
84 | | - t, err := strconv.ParseInt(string(b[from:i]), 10, 64) |
85 | | - if err == nil { |
86 | | - loc := time.UTC |
87 | | - ts := time.Unix(t, 0) |
88 | | - if len(b[i:]) >= 6 { |
89 | | - tl, err := time.Parse(" -0700", string(b[i:i+6])) |
90 | | - if err == nil { |
91 | | - loc = tl.Location() |
92 | | - } |
93 | | - } |
94 | | - s.When = ts.In(loc) |
95 | | - } |
96 | | - end = true |
97 | | - } |
98 | | - } |
99 | | - |
100 | | - if end { |
101 | | - break |
102 | | - } |
| 57 | + s.Name = string(bytes.Trim(b[:open], " ")) |
| 58 | + s.Email = string(b[open+1 : close]) |
| 59 | + |
| 60 | + hasTime := close+2 < len(b) |
| 61 | + if hasTime { |
| 62 | + s.decodeTimeAndTimeZone(b[close+2:]) |
| 63 | + } |
| 64 | +} |
| 65 | + |
| 66 | +var timeZoneLength = 5 |
| 67 | + |
| 68 | +func (s *Signature) decodeTimeAndTimeZone(b []byte) { |
| 69 | + space := bytes.IndexByte(b, ' ') |
| 70 | + if space == -1 { |
| 71 | + space = len(b) |
| 72 | + } |
| 73 | + |
| 74 | + ts, err := strconv.ParseInt(string(b[:space]), 10, 64) |
| 75 | + if err != nil { |
| 76 | + return |
103 | 77 | } |
| 78 | + |
| 79 | + s.When = time.Unix(ts, 0).In(time.UTC) |
| 80 | + var tzStart = space + 1 |
| 81 | + if tzStart >= len(b) || tzStart+timeZoneLength > len(b) { |
| 82 | + return |
| 83 | + } |
| 84 | + |
| 85 | + tl, err := time.Parse("-0700", string(b[tzStart:tzStart+timeZoneLength])) |
| 86 | + if err != nil { |
| 87 | + return |
| 88 | + } |
| 89 | + |
| 90 | + s.When = s.When.In(tl.Location()) |
104 | 91 | } |
105 | 92 |
|
106 | 93 | func (s *Signature) String() string { |
|
0 commit comments