@@ -10,8 +10,6 @@ import (
10
10
"fmt"
11
11
"io"
12
12
"os"
13
- "regexp"
14
- "strings"
15
13
16
14
"code.gitea.io/gitea/modules/log"
17
15
"code.gitea.io/gitea/modules/util"
@@ -33,14 +31,13 @@ type BlameReader struct {
33
31
done chan error
34
32
lastSha * string
35
33
ignoreRevsFile * string
34
+ objectFormat ObjectFormat
36
35
}
37
36
38
37
func (r * BlameReader ) UsesIgnoreRevs () bool {
39
38
return r .ignoreRevsFile != nil
40
39
}
41
40
42
- var shaLineRegex = regexp .MustCompile ("^([a-z0-9]{40})" )
43
-
44
41
// NextPart returns next part of blame (sequential code lines with the same commit)
45
42
func (r * BlameReader ) NextPart () (* BlamePart , error ) {
46
43
var blamePart * BlamePart
@@ -52,6 +49,7 @@ func (r *BlameReader) NextPart() (*BlamePart, error) {
52
49
}
53
50
}
54
51
52
+ const previousHeader = "previous "
55
53
var lineBytes []byte
56
54
var isPrefix bool
57
55
var err error
@@ -67,21 +65,22 @@ func (r *BlameReader) NextPart() (*BlamePart, error) {
67
65
continue
68
66
}
69
67
70
- line := string (lineBytes )
71
-
72
- lines := shaLineRegex .FindStringSubmatch (line )
73
- if lines != nil {
74
- sha1 := lines [1 ]
68
+ var objectID string
69
+ objectFormatLength := r .objectFormat .FullLength ()
75
70
71
+ if len (lineBytes ) > objectFormatLength && lineBytes [objectFormatLength ] == ' ' && r .objectFormat .IsValid (string (lineBytes [0 :objectFormatLength ])) {
72
+ objectID = string (lineBytes [0 :objectFormatLength ])
73
+ }
74
+ if len (objectID ) > 0 {
76
75
if blamePart == nil {
77
76
blamePart = & BlamePart {
78
- Sha : sha1 ,
77
+ Sha : objectID ,
79
78
Lines : make ([]string , 0 ),
80
79
}
81
80
}
82
81
83
- if blamePart .Sha != sha1 {
84
- r .lastSha = & sha1
82
+ if blamePart .Sha != objectID {
83
+ r .lastSha = & objectID
85
84
// need to munch to end of line...
86
85
for isPrefix {
87
86
_ , isPrefix , err = r .bufferedReader .ReadLine ()
@@ -91,12 +90,13 @@ func (r *BlameReader) NextPart() (*BlamePart, error) {
91
90
}
92
91
return blamePart , nil
93
92
}
94
- } else if line [0 ] == '\t' {
95
- blamePart .Lines = append (blamePart .Lines , line [1 :])
96
- } else if strings .HasPrefix (line , "previous " ) {
97
- parts := strings .SplitN (line [len ("previous " ):], " " , 2 )
98
- blamePart .PreviousSha = parts [0 ]
99
- blamePart .PreviousPath = parts [1 ]
93
+ } else if lineBytes [0 ] == '\t' {
94
+ blamePart .Lines = append (blamePart .Lines , string (lineBytes [1 :]))
95
+ } else if bytes .HasPrefix (lineBytes , []byte (previousHeader )) {
96
+ offset := len (previousHeader ) // already includes a space
97
+ blamePart .PreviousSha = string (lineBytes [offset : offset + objectFormatLength ])
98
+ offset += objectFormatLength + 1 // +1 for space
99
+ blamePart .PreviousPath = string (lineBytes [offset :])
100
100
}
101
101
102
102
// need to munch to end of line...
@@ -126,7 +126,7 @@ func (r *BlameReader) Close() error {
126
126
}
127
127
128
128
// CreateBlameReader creates reader for given repository, commit and file
129
- func CreateBlameReader (ctx context.Context , repoPath string , commit * Commit , file string , bypassBlameIgnore bool ) (* BlameReader , error ) {
129
+ func CreateBlameReader (ctx context.Context , objectFormat ObjectFormat , repoPath string , commit * Commit , file string , bypassBlameIgnore bool ) (* BlameReader , error ) {
130
130
var ignoreRevsFile * string
131
131
if CheckGitVersionAtLeast ("2.23" ) == nil && ! bypassBlameIgnore {
132
132
ignoreRevsFile = tryCreateBlameIgnoreRevsFile (commit )
@@ -175,6 +175,7 @@ func CreateBlameReader(ctx context.Context, repoPath string, commit *Commit, fil
175
175
bufferedReader : bufferedReader ,
176
176
done : done ,
177
177
ignoreRevsFile : ignoreRevsFile ,
178
+ objectFormat : objectFormat ,
178
179
}, nil
179
180
}
180
181
0 commit comments