Skip to content

Commit d4240dc

Browse files
committed
fix
1 parent 4bb1fcd commit d4240dc

8 files changed

+104
-149
lines changed

modules/git/repo.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ func GetLatestCommitTime(ctx context.Context, repoPath string) (time.Time, error
271271
return time.Time{}, err
272272
}
273273
commitTime := strings.TrimSpace(stdout)
274-
return time.Parse(GitTimeLayout, commitTime)
274+
return time.Parse("Mon Jan _2 15:04:05 2006 -0700", commitTime)
275275
}
276276

277277
// DivergeObject represents commit count diverging commits

modules/git/repo_tag.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -183,11 +183,7 @@ func parseTagRef(objectFormat ObjectFormat, ref map[string]string) (tag *Tag, er
183183
}
184184
}
185185

186-
tag.Tagger, err = newSignatureFromCommitline([]byte(ref["creator"]))
187-
if err != nil {
188-
return nil, fmt.Errorf("parse tagger: %w", err)
189-
}
190-
186+
tag.Tagger = parseSignatureFromCommitLine(ref["creator"])
191187
tag.Message = ref["contents"]
192188
// strip PGP signature if present in contents field
193189
pgpStart := strings.Index(tag.Message, beginpgp)

modules/git/repo_tag_test.go

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ func TestRepository_parseTagRef(t *testing.T) {
227227
ID: MustIDFromString("ab23e4b7f4cd0caafe0174c0e7ef6d651ba72889"),
228228
Object: MustIDFromString("ab23e4b7f4cd0caafe0174c0e7ef6d651ba72889"),
229229
Type: "commit",
230-
Tagger: parseAuthorLine(t, "Foo Bar <[email protected]> 1565789218 +0300"),
230+
Tagger: parseSignatureFromCommitLine("Foo Bar <[email protected]> 1565789218 +0300"),
231231
Message: "Add changelog of v1.9.1 (#7859)\n\n* add changelog of v1.9.1\n* Update CHANGELOG.md\n",
232232
Signature: nil,
233233
},
@@ -256,7 +256,7 @@ func TestRepository_parseTagRef(t *testing.T) {
256256
ID: MustIDFromString("8c68a1f06fc59c655b7e3905b159d761e91c53c9"),
257257
Object: MustIDFromString("3325fd8a973321fd59455492976c042dde3fd1ca"),
258258
Type: "tag",
259-
Tagger: parseAuthorLine(t, "Foo Bar <[email protected]> 1565789218 +0300"),
259+
Tagger: parseSignatureFromCommitLine("Foo Bar <[email protected]> 1565789218 +0300"),
260260
Message: "Add changelog of v1.9.1 (#7859)\n\n* add changelog of v1.9.1\n* Update CHANGELOG.md\n",
261261
Signature: nil,
262262
},
@@ -314,7 +314,7 @@ qbHDASXl
314314
ID: MustIDFromString("8c68a1f06fc59c655b7e3905b159d761e91c53c9"),
315315
Object: MustIDFromString("3325fd8a973321fd59455492976c042dde3fd1ca"),
316316
Type: "tag",
317-
Tagger: parseAuthorLine(t, "Foo Bar <[email protected]> 1565789218 +0300"),
317+
Tagger: parseSignatureFromCommitLine("Foo Bar <[email protected]> 1565789218 +0300"),
318318
Message: "Add changelog of v1.9.1 (#7859)\n\n* add changelog of v1.9.1\n* Update CHANGELOG.md",
319319
Signature: &CommitGPGSignature{
320320
Signature: `-----BEGIN PGP SIGNATURE-----
@@ -363,14 +363,3 @@ Add changelog of v1.9.1 (#7859)
363363
})
364364
}
365365
}
366-
367-
func parseAuthorLine(t *testing.T, committer string) *Signature {
368-
t.Helper()
369-
370-
sig, err := newSignatureFromCommitline([]byte(committer))
371-
if err != nil {
372-
t.Fatalf("parse author line '%s': %v", committer, err)
373-
}
374-
375-
return sig
376-
}

modules/git/signature.go

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,46 @@
44

55
package git
66

7-
const (
8-
// GitTimeLayout is the (default) time layout used by git.
9-
GitTimeLayout = "Mon Jan _2 15:04:05 2006 -0700"
7+
import (
8+
"strconv"
9+
"strings"
10+
"time"
11+
12+
"code.gitea.io/gitea/modules/log"
1013
)
14+
15+
// Helper to get a signature from the commit line, which looks like:
16+
//
17+
// full name <[email protected]> 1378823654 +0200
18+
//
19+
// Haven't found the official reference for the standard format yet.
20+
// This function never fails, if the "line" can't be parsed, it returns a default Signature with "zero" time.
21+
func parseSignatureFromCommitLine(line string) *Signature {
22+
sig := &Signature{}
23+
s1, sx, ok1 := strings.Cut(line, " <")
24+
s2, s3, ok2 := strings.Cut(sx, "> ")
25+
if !ok1 || !ok2 {
26+
sig.Name = line
27+
return sig
28+
}
29+
sig.Name, sig.Email = s1, s2
30+
31+
if strings.Count(s3, " ") == 1 {
32+
ts, tz, _ := strings.Cut(s3, " ")
33+
seconds, _ := strconv.ParseInt(ts, 10, 64)
34+
if tzTime, err := time.Parse("-0700", tz); err == nil {
35+
sig.When = time.Unix(seconds, 0).In(tzTime.Location())
36+
}
37+
} else {
38+
// the old gitea code tried to parse the date in a few different formats, but it's not clear why.
39+
// according to public document, only the standard format "timestamp timezone" could be found, so drop other formats.
40+
log.Error("suspicious commit line format: %q", line)
41+
for _, fmt := range []string{ /*"Mon Jan _2 15:04:05 2006 -0700"*/ } {
42+
if t, err := time.Parse(fmt, s3); err == nil {
43+
sig.When = t
44+
break
45+
}
46+
}
47+
}
48+
return sig
49+
}

modules/git/signature_gogit.go

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -7,52 +7,8 @@
77
package git
88

99
import (
10-
"bytes"
11-
"strconv"
12-
"strings"
13-
"time"
14-
1510
"github.com/go-git/go-git/v5/plumbing/object"
1611
)
1712

1813
// Signature represents the Author or Committer information.
1914
type Signature = object.Signature
20-
21-
// Helper to get a signature from the commit line, which looks like these:
22-
//
23-
// author Patrick Gundlach <[email protected]> 1378823654 +0200
24-
// author Patrick Gundlach <[email protected]> Thu, 07 Apr 2005 22:13:13 +0200
25-
//
26-
// but without the "author " at the beginning (this method should)
27-
// be used for author and committer.
28-
//
29-
// FIXME: include timezone for timestamp!
30-
func newSignatureFromCommitline(line []byte) (_ *Signature, err error) {
31-
sig := new(Signature)
32-
emailStart := bytes.IndexByte(line, '<')
33-
if emailStart > 0 { // Empty name has already occurred, even if it shouldn't
34-
sig.Name = strings.TrimSpace(string(line[:emailStart-1]))
35-
}
36-
emailEnd := bytes.IndexByte(line, '>')
37-
sig.Email = string(line[emailStart+1 : emailEnd])
38-
39-
// Check date format.
40-
if len(line) > emailEnd+2 {
41-
firstChar := line[emailEnd+2]
42-
if firstChar >= 48 && firstChar <= 57 {
43-
timestop := bytes.IndexByte(line[emailEnd+2:], ' ')
44-
timestring := string(line[emailEnd+2 : emailEnd+2+timestop])
45-
seconds, _ := strconv.ParseInt(timestring, 10, 64)
46-
sig.When = time.Unix(seconds, 0)
47-
} else {
48-
sig.When, err = time.Parse(GitTimeLayout, string(line[emailEnd+2:]))
49-
if err != nil {
50-
return nil, err
51-
}
52-
}
53-
} else {
54-
// Fall back to unix 0 time
55-
sig.When = time.Unix(0, 0)
56-
}
57-
return sig, nil
58-
}

modules/git/signature_nogogit.go

Lines changed: 7 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,17 @@
77
package git
88

99
import (
10-
"bytes"
1110
"fmt"
12-
"strconv"
13-
"strings"
1411
"time"
12+
13+
"code.gitea.io/gitea/modules/util"
1514
)
1615

17-
// Signature represents the Author or Committer information.
16+
// Signature represents the Author, Committer or Tagger information.
1817
type Signature struct {
19-
// Name represents a person name. It is an arbitrary string.
20-
Name string
21-
// Email is an email, but it cannot be assumed to be well-formed.
22-
Email string
23-
// When is the timestamp of the signature.
24-
When time.Time
18+
Name string // the committer name, it can be anything
19+
Email string // the committer email, it can be anything
20+
When time.Time // the timestamp of the signature
2521
}
2622

2723
func (s *Signature) String() string {
@@ -30,71 +26,5 @@ func (s *Signature) String() string {
3026

3127
// Decode decodes a byte array representing a signature to signature
3228
func (s *Signature) Decode(b []byte) {
33-
sig, _ := newSignatureFromCommitline(b)
34-
s.Email = sig.Email
35-
s.Name = sig.Name
36-
s.When = sig.When
37-
}
38-
39-
// Helper to get a signature from the commit line, which looks like these:
40-
//
41-
// author Patrick Gundlach <[email protected]> 1378823654 +0200
42-
// author Patrick Gundlach <[email protected]> Thu, 07 Apr 2005 22:13:13 +0200
43-
//
44-
// but without the "author " at the beginning (this method should)
45-
// be used for author and committer.
46-
// FIXME: there are a lot of "return sig, err" (but the err is also nil), that's the old behavior, to avoid breaking
47-
func newSignatureFromCommitline(line []byte) (sig *Signature, err error) {
48-
sig = new(Signature)
49-
emailStart := bytes.LastIndexByte(line, '<')
50-
emailEnd := bytes.LastIndexByte(line, '>')
51-
if emailStart == -1 || emailEnd == -1 || emailEnd < emailStart {
52-
return sig, err
53-
}
54-
55-
if emailStart > 0 { // Empty name has already occurred, even if it shouldn't
56-
sig.Name = strings.TrimSpace(string(line[:emailStart-1]))
57-
}
58-
sig.Email = string(line[emailStart+1 : emailEnd])
59-
60-
hasTime := emailEnd+2 < len(line)
61-
if !hasTime {
62-
return sig, err
63-
}
64-
65-
// Check date format.
66-
firstChar := line[emailEnd+2]
67-
if firstChar >= 48 && firstChar <= 57 {
68-
idx := bytes.IndexByte(line[emailEnd+2:], ' ')
69-
if idx < 0 {
70-
return sig, err
71-
}
72-
73-
timestring := string(line[emailEnd+2 : emailEnd+2+idx])
74-
seconds, _ := strconv.ParseInt(timestring, 10, 64)
75-
sig.When = time.Unix(seconds, 0)
76-
77-
idx += emailEnd + 3
78-
if idx >= len(line) || idx+5 > len(line) {
79-
return sig, err
80-
}
81-
82-
timezone := string(line[idx : idx+5])
83-
tzhours, err1 := strconv.ParseInt(timezone[0:3], 10, 64)
84-
tzmins, err2 := strconv.ParseInt(timezone[3:], 10, 64)
85-
if err1 != nil || err2 != nil {
86-
return sig, err
87-
}
88-
if tzhours < 0 {
89-
tzmins *= -1
90-
}
91-
tz := time.FixedZone("", int(tzhours*60*60+tzmins*60))
92-
sig.When = sig.When.In(tz)
93-
} else {
94-
sig.When, err = time.Parse(GitTimeLayout, string(line[emailEnd+2:]))
95-
if err != nil {
96-
return sig, err
97-
}
98-
}
99-
return sig, err
29+
*s = *parseSignatureFromCommitLine(util.UnsafeBytesToString(b))
10030
}

modules/git/signature_test.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright 2019 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package git
5+
6+
import (
7+
"testing"
8+
"time"
9+
10+
"github.com/stretchr/testify/assert"
11+
)
12+
13+
func TestParseSignatureFromCommitLine(t *testing.T) {
14+
tests := []struct {
15+
line string
16+
want *Signature
17+
}{
18+
{
19+
line: "a b <[email protected]> 12345 +0100",
20+
want: &Signature{
21+
Name: "a b",
22+
23+
When: time.Unix(12345, 0).In(time.FixedZone("", 3600)),
24+
},
25+
},
26+
{
27+
line: "bad line",
28+
want: &Signature{Name: "bad line"},
29+
},
30+
{
31+
line: "bad < line",
32+
want: &Signature{Name: "bad < line"},
33+
},
34+
{
35+
line: "bad > line",
36+
want: &Signature{Name: "bad > line"},
37+
},
38+
{
39+
line: "bad-line <[email protected]>",
40+
want: &Signature{Name: "bad-line <[email protected]>"},
41+
},
42+
}
43+
for _, test := range tests {
44+
got := parseSignatureFromCommitLine(test.line)
45+
assert.EqualValues(t, test.want, got)
46+
}
47+
}

modules/git/tag.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import (
77
"bytes"
88
"sort"
99
"strings"
10+
11+
"code.gitea.io/gitea/modules/util"
1012
)
1113

1214
const (
@@ -59,11 +61,7 @@ l:
5961
// A commit can have one or more parents
6062
tag.Type = string(line[spacepos+1:])
6163
case "tagger":
62-
sig, err := newSignatureFromCommitline(line[spacepos+1:])
63-
if err != nil {
64-
return nil, err
65-
}
66-
tag.Tagger = sig
64+
tag.Tagger = parseSignatureFromCommitLine(util.UnsafeBytesToString(line[spacepos+1:]))
6765
}
6866
nextline += eol + 1
6967
case eol == 0:

0 commit comments

Comments
 (0)