Skip to content

Commit 27de254

Browse files
committed
performance improvements for commits list
1 parent a52720b commit 27de254

File tree

8 files changed

+125
-30
lines changed

8 files changed

+125
-30
lines changed

models/asymkey/gpg_key_commit_verification.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"code.gitea.io/gitea/models/db"
1313
repo_model "code.gitea.io/gitea/models/repo"
1414
user_model "code.gitea.io/gitea/models/user"
15+
"code.gitea.io/gitea/modules/container"
1516
"code.gitea.io/gitea/modules/git"
1617
"code.gitea.io/gitea/modules/log"
1718
"code.gitea.io/gitea/modules/setting"
@@ -71,21 +72,33 @@ const (
7172
)
7273

7374
// ParseCommitsWithSignature checks if signaute of commits are corresponding to users gpg keys.
74-
func ParseCommitsWithSignature(ctx context.Context, oldCommits []*user_model.UserCommit, repoTrustModel repo_model.TrustModelType, isOwnerMemberCollaborator func(*user_model.User) (bool, error)) []*SignCommit {
75+
func ParseCommitsWithSignature(ctx context.Context, oldCommits []*user_model.UserCommit, repoTrustModel repo_model.TrustModelType, isOwnerMemberCollaborator func(*user_model.User) (bool, error)) ([]*SignCommit, error) {
7576
newCommits := make([]*SignCommit, 0, len(oldCommits))
7677
keyMap := map[string]bool{}
7778

79+
emails := make(container.Set[string])
80+
for _, c := range oldCommits {
81+
if c.Committer != nil {
82+
emails.Add(c.Committer.Email)
83+
}
84+
}
85+
86+
emailUsers, err := user_model.GetUsersByEmails(ctx, emails.Values())
87+
if err != nil {
88+
return nil, err
89+
}
90+
7891
for _, c := range oldCommits {
7992
signCommit := &SignCommit{
8093
UserCommit: c,
81-
Verification: ParseCommitWithSignature(ctx, c.Commit),
94+
Verification: parseCommitWithSignatureCommitter(ctx, c.Commit, emailUsers[c.Committer.Email]),
8295
}
8396

8497
_ = CalculateTrustStatus(signCommit.Verification, repoTrustModel, isOwnerMemberCollaborator, &keyMap)
8598

8699
newCommits = append(newCommits, signCommit)
87100
}
88-
return newCommits
101+
return newCommits, nil
89102
}
90103

91104
// ParseCommitWithSignature check if signature is good against keystore.
@@ -113,6 +126,10 @@ func ParseCommitWithSignature(ctx context.Context, c *git.Commit) *CommitVerific
113126
}
114127
}
115128

129+
return parseCommitWithSignatureCommitter(ctx, c, committer)
130+
}
131+
132+
func parseCommitWithSignatureCommitter(ctx context.Context, c *git.Commit, committer *user_model.User) *CommitVerification {
116133
// If no signature just report the committer
117134
if c.Signature == nil {
118135
return &CommitVerification{

models/git/commit_status.go

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,7 @@ type SignCommitWithStatuses struct {
497497
}
498498

499499
// ParseCommitsWithStatus checks commits latest statuses and calculates its worst status state
500-
func ParseCommitsWithStatus(ctx context.Context, oldCommits []*asymkey_model.SignCommit, repo *repo_model.Repository) []*SignCommitWithStatuses {
500+
func ParseCommitsWithStatus(ctx context.Context, oldCommits []*asymkey_model.SignCommit, repo *repo_model.Repository) ([]*SignCommitWithStatuses, error) {
501501
newCommits := make([]*SignCommitWithStatuses, 0, len(oldCommits))
502502

503503
for _, c := range oldCommits {
@@ -506,15 +506,14 @@ func ParseCommitsWithStatus(ctx context.Context, oldCommits []*asymkey_model.Sig
506506
}
507507
statuses, _, err := GetLatestCommitStatus(ctx, repo.ID, commit.ID.String(), db.ListOptions{})
508508
if err != nil {
509-
log.Error("GetLatestCommitStatus: %v", err)
510-
} else {
511-
commit.Statuses = statuses
512-
commit.Status = CalcCommitStatus(statuses)
509+
return nil, err
513510
}
514511

512+
commit.Statuses = statuses
513+
commit.Status = CalcCommitStatus(statuses)
515514
newCommits = append(newCommits, commit)
516515
}
517-
return newCommits
516+
return newCommits, nil
518517
}
519518

520519
// hashCommitStatusContext hash context
@@ -523,18 +522,19 @@ func hashCommitStatusContext(context string) string {
523522
}
524523

525524
// ConvertFromGitCommit converts git commits into SignCommitWithStatuses
526-
func ConvertFromGitCommit(ctx context.Context, commits []*git.Commit, repo *repo_model.Repository) []*SignCommitWithStatuses {
527-
return ParseCommitsWithStatus(ctx,
528-
asymkey_model.ParseCommitsWithSignature(
529-
ctx,
530-
user_model.ValidateCommitsWithEmails(ctx, commits),
531-
repo.GetTrustModel(),
532-
func(user *user_model.User) (bool, error) {
533-
return repo_model.IsOwnerMemberCollaborator(ctx, repo, user.ID)
534-
},
535-
),
536-
repo,
525+
func ConvertFromGitCommit(ctx context.Context, commits []*git.Commit, repo *repo_model.Repository) ([]*SignCommitWithStatuses, error) {
526+
signedCommits, err := asymkey_model.ParseCommitsWithSignature(
527+
ctx,
528+
user_model.ValidateCommitsWithEmails(ctx, commits),
529+
repo.GetTrustModel(),
530+
func(user *user_model.User) (bool, error) {
531+
return repo_model.IsOwnerMemberCollaborator(ctx, repo, user.ID)
532+
},
537533
)
534+
if err != nil {
535+
return nil, err
536+
}
537+
return ParseCommitsWithStatus(ctx, signedCommits, repo)
538538
}
539539

540540
// CommitStatusesHideActionsURL hide Gitea Actions urls

models/issues/comment.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -802,7 +802,10 @@ func (c *Comment) LoadPushCommits(ctx context.Context) (err error) {
802802
}
803803
defer closer.Close()
804804

805-
c.Commits = git_model.ConvertFromGitCommit(ctx, gitRepo.GetCommitsFromIDs(data.CommitIDs), c.Issue.Repo)
805+
c.Commits, err = git_model.ConvertFromGitCommit(ctx, gitRepo.GetCommitsFromIDs(data.CommitIDs), c.Issue.Repo)
806+
if err != nil {
807+
return err
808+
}
806809
c.CommitsNum = int64(len(c.Commits))
807810
}
808811

models/user/user.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1153,6 +1153,51 @@ func ValidateCommitsWithEmails(ctx context.Context, oldCommits []*git.Commit) []
11531153
return newCommits
11541154
}
11551155

1156+
func GetUsersByEmails(ctx context.Context, emails []string) (map[string]*User, error) {
1157+
if len(emails) == 0 {
1158+
return nil, nil
1159+
}
1160+
1161+
needCheckEmails := make(container.Set[string])
1162+
needCheckUserNames := make(container.Set[string])
1163+
for _, email := range emails {
1164+
if strings.HasSuffix(email, fmt.Sprintf("@%s", setting.Service.NoReplyAddress)) {
1165+
username := strings.TrimSuffix(email, fmt.Sprintf("@%s", setting.Service.NoReplyAddress))
1166+
needCheckUserNames.Add(username)
1167+
} else {
1168+
needCheckEmails.Add(strings.ToLower(email))
1169+
}
1170+
}
1171+
1172+
emailAddresses := make([]*EmailAddress, 0, len(needCheckEmails))
1173+
if err := db.GetEngine(ctx).In("lower_email", needCheckEmails.Values()).
1174+
And("is_activated=?", true).
1175+
Find(&emailAddresses); err != nil {
1176+
return nil, err
1177+
}
1178+
userIDs := make(container.Set[int64])
1179+
for _, email := range emailAddresses {
1180+
userIDs.Add(email.UID)
1181+
}
1182+
users, err := GetUsersByIDs(ctx, userIDs.Values())
1183+
if err != nil {
1184+
return nil, err
1185+
}
1186+
1187+
results := make(map[string]*User, len(emails))
1188+
for _, user := range users {
1189+
results[user.Email] = user
1190+
}
1191+
users = make([]*User, 0, len(needCheckUserNames))
1192+
if err := db.GetEngine(ctx).In("lower_name=?", needCheckUserNames.Values()).Find(users); err != nil {
1193+
return nil, err
1194+
}
1195+
for _, user := range users {
1196+
results[user.LowerName+"@"+setting.Service.NoReplyAddress] = user
1197+
}
1198+
return results, nil
1199+
}
1200+
11561201
// GetUserByEmail returns the user object by given e-mail if exists.
11571202
func GetUserByEmail(ctx context.Context, email string) (*User, error) {
11581203
if len(email) == 0 {

routers/web/repo/commit.go

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,11 @@ func Commits(ctx *context.Context) {
8080
ctx.ServerError("CommitsByRange", err)
8181
return
8282
}
83-
ctx.Data["Commits"] = processGitCommits(ctx, commits)
83+
ctx.Data["Commits"], err = processGitCommits(ctx, commits)
84+
if err != nil {
85+
ctx.ServerError("processGitCommits", err)
86+
return
87+
}
8488
commitIDs := make([]string, 0, len(commits))
8589
for _, c := range commits {
8690
commitIDs = append(commitIDs, c.ID.String())
@@ -192,7 +196,11 @@ func SearchCommits(ctx *context.Context) {
192196
return
193197
}
194198
ctx.Data["CommitCount"] = len(commits)
195-
ctx.Data["Commits"] = processGitCommits(ctx, commits)
199+
ctx.Data["Commits"], err = processGitCommits(ctx, commits)
200+
if err != nil {
201+
ctx.ServerError("processGitCommits", err)
202+
return
203+
}
196204

197205
ctx.Data["Keyword"] = query
198206
if all {
@@ -235,7 +243,11 @@ func FileHistory(ctx *context.Context) {
235243
ctx.ServerError("CommitsByFileAndRange", err)
236244
return
237245
}
238-
ctx.Data["Commits"] = processGitCommits(ctx, commits)
246+
ctx.Data["Commits"], err = processGitCommits(ctx, commits)
247+
if err != nil {
248+
ctx.ServerError("processGitCommits", err)
249+
return
250+
}
239251

240252
ctx.Data["Username"] = ctx.Repo.Owner.Name
241253
ctx.Data["Reponame"] = ctx.Repo.Repository.Name
@@ -416,13 +428,16 @@ func RawDiff(ctx *context.Context) {
416428
}
417429
}
418430

419-
func processGitCommits(ctx *context.Context, gitCommits []*git.Commit) []*git_model.SignCommitWithStatuses {
420-
commits := git_model.ConvertFromGitCommit(ctx, gitCommits, ctx.Repo.Repository)
431+
func processGitCommits(ctx *context.Context, gitCommits []*git.Commit) ([]*git_model.SignCommitWithStatuses, error) {
432+
commits, err := git_model.ConvertFromGitCommit(ctx, gitCommits, ctx.Repo.Repository)
433+
if err != nil {
434+
return nil, err
435+
}
421436
if !ctx.Repo.CanRead(unit_model.TypeActions) {
422437
for _, commit := range commits {
423438
commit.Status.HideActionsURL(ctx)
424439
git_model.CommitStatusesHideActionsURL(ctx, commit.Statuses)
425440
}
426441
}
427-
return commits
442+
return commits, nil
428443
}

routers/web/repo/compare.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,11 @@ func PrepareCompareDiff(
647647
return false
648648
}
649649

650-
commits := processGitCommits(ctx, ci.CompareInfo.Commits)
650+
commits, err := processGitCommits(ctx, ci.CompareInfo.Commits)
651+
if err != nil {
652+
ctx.ServerError("processGitCommits", err)
653+
return false
654+
}
651655
ctx.Data["Commits"] = commits
652656
ctx.Data["CommitCount"] = len(commits)
653657

routers/web/repo/pull.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -631,7 +631,11 @@ func ViewPullCommits(ctx *context.Context) {
631631
ctx.Data["Username"] = ctx.Repo.Owner.Name
632632
ctx.Data["Reponame"] = ctx.Repo.Repository.Name
633633

634-
commits := processGitCommits(ctx, prInfo.Commits)
634+
commits, err := processGitCommits(ctx, prInfo.Commits)
635+
if err != nil {
636+
ctx.ServerError("processGitCommits", err)
637+
return
638+
}
635639
ctx.Data["Commits"] = commits
636640
ctx.Data["CommitCount"] = len(commits)
637641

routers/web/repo/wiki.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,14 @@ func renderRevisionPage(ctx *context.Context) (*git.Repository, *git.TreeEntry)
437437
ctx.ServerError("CommitsByFileAndRange", err)
438438
return nil, nil
439439
}
440-
ctx.Data["Commits"] = git_model.ConvertFromGitCommit(ctx, commitsHistory, ctx.Repo.Repository)
440+
ctx.Data["Commits"], err = git_model.ConvertFromGitCommit(ctx, commitsHistory, ctx.Repo.Repository)
441+
if err != nil {
442+
if wikiRepo != nil {
443+
wikiRepo.Close()
444+
}
445+
ctx.ServerError("ConvertFromGitCommit", err)
446+
return nil, nil
447+
}
441448

442449
pager := context.NewPagination(int(commitsCount), setting.Git.CommitsRangeSize, page, 5)
443450
pager.AddParamFromRequest(ctx.Req)

0 commit comments

Comments
 (0)