Skip to content

Commit b840c94

Browse files
KN4CK3Rfuxiaohei
authored andcommitted
Read previous info from git blame (go-gitea#28306)
Fixes go-gitea#28280 Reads the `previous` info from the `git blame` output instead of calculating it afterwards.
1 parent 35118d7 commit b840c94

File tree

3 files changed

+49
-54
lines changed

3 files changed

+49
-54
lines changed

modules/git/blame.go

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,18 @@ import (
1111
"io"
1212
"os"
1313
"regexp"
14+
"strings"
1415

1516
"code.gitea.io/gitea/modules/log"
1617
"code.gitea.io/gitea/modules/util"
1718
)
1819

1920
// BlamePart represents block of blame - continuous lines with one sha
2021
type BlamePart struct {
21-
Sha string
22-
Lines []string
22+
Sha string
23+
Lines []string
24+
PreviousSha string
25+
PreviousPath string
2326
}
2427

2528
// BlameReader returns part of file blame one by one
@@ -43,30 +46,38 @@ func (r *BlameReader) NextPart() (*BlamePart, error) {
4346
var blamePart *BlamePart
4447

4548
if r.lastSha != nil {
46-
blamePart = &BlamePart{*r.lastSha, make([]string, 0)}
49+
blamePart = &BlamePart{
50+
Sha: *r.lastSha,
51+
Lines: make([]string, 0),
52+
}
4753
}
4854

49-
var line []byte
55+
var lineBytes []byte
5056
var isPrefix bool
5157
var err error
5258

5359
for err != io.EOF {
54-
line, isPrefix, err = r.bufferedReader.ReadLine()
60+
lineBytes, isPrefix, err = r.bufferedReader.ReadLine()
5561
if err != nil && err != io.EOF {
5662
return blamePart, err
5763
}
5864

59-
if len(line) == 0 {
65+
if len(lineBytes) == 0 {
6066
// isPrefix will be false
6167
continue
6268
}
6369

64-
lines := shaLineRegex.FindSubmatch(line)
70+
line := string(lineBytes)
71+
72+
lines := shaLineRegex.FindStringSubmatch(line)
6573
if lines != nil {
66-
sha1 := string(lines[1])
74+
sha1 := lines[1]
6775

6876
if blamePart == nil {
69-
blamePart = &BlamePart{sha1, make([]string, 0)}
77+
blamePart = &BlamePart{
78+
Sha: sha1,
79+
Lines: make([]string, 0),
80+
}
7081
}
7182

7283
if blamePart.Sha != sha1 {
@@ -81,9 +92,11 @@ func (r *BlameReader) NextPart() (*BlamePart, error) {
8192
return blamePart, nil
8293
}
8394
} else if line[0] == '\t' {
84-
code := line[1:]
85-
86-
blamePart.Lines = append(blamePart.Lines, string(code))
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]
87100
}
88101

89102
// need to munch to end of line...

modules/git/blame_test.go

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,17 @@ func TestReadingBlameOutput(t *testing.T) {
2424

2525
parts := []*BlamePart{
2626
{
27-
"72866af952e98d02a73003501836074b286a78f6",
28-
[]string{
27+
Sha: "72866af952e98d02a73003501836074b286a78f6",
28+
Lines: []string{
2929
"# test_repo",
3030
"Test repository for testing migration from github to gitea",
3131
},
3232
},
3333
{
34-
"f32b0a9dfd09a60f616f29158f772cedd89942d2",
35-
[]string{"", "Do not make any changes to this repo it is used for unit testing"},
34+
Sha: "f32b0a9dfd09a60f616f29158f772cedd89942d2",
35+
Lines: []string{"", "Do not make any changes to this repo it is used for unit testing"},
36+
PreviousSha: "72866af952e98d02a73003501836074b286a78f6",
37+
PreviousPath: "README.md",
3638
},
3739
}
3840

@@ -64,16 +66,18 @@ func TestReadingBlameOutput(t *testing.T) {
6466

6567
full := []*BlamePart{
6668
{
67-
"af7486bd54cfc39eea97207ca666aa69c9d6df93",
68-
[]string{"line", "line"},
69+
Sha: "af7486bd54cfc39eea97207ca666aa69c9d6df93",
70+
Lines: []string{"line", "line"},
6971
},
7072
{
71-
"45fb6cbc12f970b04eacd5cd4165edd11c8d7376",
72-
[]string{"changed line"},
73+
Sha: "45fb6cbc12f970b04eacd5cd4165edd11c8d7376",
74+
Lines: []string{"changed line"},
75+
PreviousSha: "af7486bd54cfc39eea97207ca666aa69c9d6df93",
76+
PreviousPath: "blame.txt",
7377
},
7478
{
75-
"af7486bd54cfc39eea97207ca666aa69c9d6df93",
76-
[]string{"line", "line", ""},
79+
Sha: "af7486bd54cfc39eea97207ca666aa69c9d6df93",
80+
Lines: []string{"line", "line", ""},
7781
},
7882
}
7983

@@ -89,8 +93,8 @@ func TestReadingBlameOutput(t *testing.T) {
8993
Bypass: false,
9094
Parts: []*BlamePart{
9195
{
92-
"af7486bd54cfc39eea97207ca666aa69c9d6df93",
93-
[]string{"line", "line", "changed line", "line", "line", ""},
96+
Sha: "af7486bd54cfc39eea97207ca666aa69c9d6df93",
97+
Lines: []string{"line", "line", "changed line", "line", "line", ""},
9498
},
9599
},
96100
},

routers/web/repo/blame.go

Lines changed: 8 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,12 @@ func RefBlame(ctx *context.Context) {
114114
return
115115
}
116116

117-
commitNames, previousCommits := processBlameParts(ctx, result.Parts)
117+
commitNames := processBlameParts(ctx, result.Parts)
118118
if ctx.Written() {
119119
return
120120
}
121121

122-
renderBlame(ctx, result.Parts, commitNames, previousCommits)
122+
renderBlame(ctx, result.Parts, commitNames)
123123

124124
ctx.HTML(http.StatusOK, tplRepoHome)
125125
}
@@ -185,12 +185,9 @@ func fillBlameResult(br *git.BlameReader, r *blameResult) error {
185185
return nil
186186
}
187187

188-
func processBlameParts(ctx *context.Context, blameParts []git.BlamePart) (map[string]*user_model.UserCommit, map[string]string) {
188+
func processBlameParts(ctx *context.Context, blameParts []git.BlamePart) map[string]*user_model.UserCommit {
189189
// store commit data by SHA to look up avatar info etc
190190
commitNames := make(map[string]*user_model.UserCommit)
191-
// previousCommits contains links from SHA to parent SHA,
192-
// if parent also contains the current TreePath.
193-
previousCommits := make(map[string]string)
194191
// and as blameParts can reference the same commits multiple
195192
// times, we cache the lookup work locally
196193
commits := make([]*git.Commit, 0, len(blameParts))
@@ -214,29 +211,11 @@ func processBlameParts(ctx *context.Context, blameParts []git.BlamePart) (map[st
214211
} else {
215212
ctx.ServerError("Repo.GitRepo.GetCommit", err)
216213
}
217-
return nil, nil
214+
return nil
218215
}
219216
commitCache[sha] = commit
220217
}
221218

222-
// find parent commit
223-
if commit.ParentCount() > 0 {
224-
psha := commit.Parents[0]
225-
previousCommit, ok := commitCache[psha.String()]
226-
if !ok {
227-
previousCommit, _ = commit.Parent(0)
228-
if previousCommit != nil {
229-
commitCache[psha.String()] = previousCommit
230-
}
231-
}
232-
// only store parent commit ONCE, if it has the file
233-
if previousCommit != nil {
234-
if haz1, _ := previousCommit.HasFile(ctx.Repo.TreePath); haz1 {
235-
previousCommits[commit.ID.String()] = previousCommit.ID.String()
236-
}
237-
}
238-
}
239-
240219
commits = append(commits, commit)
241220
}
242221

@@ -245,10 +224,10 @@ func processBlameParts(ctx *context.Context, blameParts []git.BlamePart) (map[st
245224
commitNames[c.ID.String()] = c
246225
}
247226

248-
return commitNames, previousCommits
227+
return commitNames
249228
}
250229

251-
func renderBlame(ctx *context.Context, blameParts []git.BlamePart, commitNames map[string]*user_model.UserCommit, previousCommits map[string]string) {
230+
func renderBlame(ctx *context.Context, blameParts []git.BlamePart, commitNames map[string]*user_model.UserCommit) {
252231
repoLink := ctx.Repo.RepoLink
253232

254233
language := ""
@@ -295,7 +274,6 @@ func renderBlame(ctx *context.Context, blameParts []git.BlamePart, commitNames m
295274
}
296275

297276
commit := commitNames[part.Sha]
298-
previousSha := previousCommits[part.Sha]
299277
if index == 0 {
300278
// Count commit number
301279
commitCnt++
@@ -313,8 +291,8 @@ func renderBlame(ctx *context.Context, blameParts []git.BlamePart, commitNames m
313291
br.Avatar = gotemplate.HTML(avatar)
314292
br.RepoLink = repoLink
315293
br.PartSha = part.Sha
316-
br.PreviousSha = previousSha
317-
br.PreviousShaURL = fmt.Sprintf("%s/blame/commit/%s/%s", repoLink, url.PathEscape(previousSha), util.PathEscapeSegments(ctx.Repo.TreePath))
294+
br.PreviousSha = part.PreviousSha
295+
br.PreviousShaURL = fmt.Sprintf("%s/blame/commit/%s/%s", repoLink, url.PathEscape(part.PreviousSha), util.PathEscapeSegments(part.PreviousPath))
318296
br.CommitURL = fmt.Sprintf("%s/commit/%s", repoLink, url.PathEscape(part.Sha))
319297
br.CommitMessage = commit.CommitMessage
320298
br.CommitSince = commitSince

0 commit comments

Comments
 (0)