Skip to content

Commit 564fef1

Browse files
yp05327silverwindlunnywxiaoguang
authored
Fix wrong display of recently pushed notification (#25812) (#31043)
Backport #25812 ~~ps: removed some new codes in `tests/integration/pull_merge_test.go`~~ --------- Co-authored-by: silverwind <[email protected]> Co-authored-by: Lunny Xiao <[email protected]> Co-authored-by: wxiaoguang <[email protected]>
1 parent 14ed06d commit 564fef1

26 files changed

+508
-72
lines changed

models/fixtures/branch.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,39 @@
4545
is_deleted: false
4646
deleted_by_id: 0
4747
deleted_unix: 0
48+
49+
-
50+
id: 5
51+
repo_id: 10
52+
name: 'master'
53+
commit_id: '65f1bf27bc3bf70f64657658635e66094edbcb4d'
54+
commit_message: 'Initial commit'
55+
commit_time: 1489927679
56+
pusher_id: 12
57+
is_deleted: false
58+
deleted_by_id: 0
59+
deleted_unix: 0
60+
61+
-
62+
id: 6
63+
repo_id: 10
64+
name: 'outdated-new-branch'
65+
commit_id: 'cb24c347e328d83c1e0c3c908a6b2c0a2fcb8a3d'
66+
commit_message: 'add'
67+
commit_time: 1489927679
68+
pusher_id: 12
69+
is_deleted: false
70+
deleted_by_id: 0
71+
deleted_unix: 0
72+
73+
-
74+
id: 14
75+
repo_id: 11
76+
name: 'master'
77+
commit_id: '65f1bf27bc3bf70f64657658635e66094edbcb4d'
78+
commit_message: 'Initial commit'
79+
commit_time: 1489927679
80+
pusher_id: 13
81+
is_deleted: false
82+
deleted_by_id: 0
83+
deleted_unix: 0

models/fixtures/issue_index.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,35 @@
11
-
22
group_id: 1
33
max_index: 5
4+
45
-
56
group_id: 2
67
max_index: 2
8+
79
-
810
group_id: 3
911
max_index: 2
12+
1013
-
1114
group_id: 10
1215
max_index: 1
16+
1317
-
1418
group_id: 32
1519
max_index: 2
20+
1621
-
1722
group_id: 48
1823
max_index: 1
24+
1925
-
2026
group_id: 42
2127
max_index: 1
28+
2229
-
2330
group_id: 50
2431
max_index: 1
32+
2533
-
2634
group_id: 51
2735
max_index: 1

models/fixtures/org_user.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,3 +117,15 @@
117117
uid: 40
118118
org_id: 41
119119
is_public: true
120+
121+
-
122+
id: 21
123+
uid: 12
124+
org_id: 25
125+
is_public: true
126+
127+
-
128+
id: 22
129+
uid: 2
130+
org_id: 35
131+
is_public: true

models/fixtures/repository.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@
327327
is_archived: false
328328
is_mirror: false
329329
status: 0
330-
is_fork: false
330+
is_fork: true
331331
fork_id: 10
332332
is_template: false
333333
template_id: 0

models/fixtures/team.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,3 +239,25 @@
239239
num_members: 2
240240
includes_all_repositories: false
241241
can_create_org_repo: false
242+
243+
-
244+
id: 23
245+
org_id: 25
246+
lower_name: owners
247+
name: Owners
248+
authorize: 4 # owner
249+
num_repos: 0
250+
num_members: 1
251+
includes_all_repositories: false
252+
can_create_org_repo: true
253+
254+
-
255+
id: 24
256+
org_id: 35
257+
lower_name: team24
258+
name: team24
259+
authorize: 2 # write
260+
num_repos: 0
261+
num_members: 1
262+
includes_all_repositories: true
263+
can_create_org_repo: false

models/fixtures/team_unit.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,3 +322,21 @@
322322
team_id: 22
323323
type: 3
324324
access_mode: 1
325+
326+
-
327+
id: 55
328+
team_id: 18
329+
type: 1 # code
330+
access_mode: 4
331+
332+
-
333+
id: 56
334+
team_id: 23
335+
type: 1 # code
336+
access_mode: 4
337+
338+
-
339+
id: 57
340+
team_id: 24
341+
type: 1 # code
342+
access_mode: 2

models/fixtures/team_user.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,15 @@
147147
org_id: 41
148148
team_id: 22
149149
uid: 39
150+
151+
-
152+
id: 26
153+
org_id: 25
154+
team_id: 23
155+
uid: 12
156+
157+
-
158+
id: 27
159+
org_id: 35
160+
team_id: 24
161+
uid: 2

models/fixtures/user.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -918,8 +918,8 @@
918918
num_following: 0
919919
num_stars: 0
920920
num_repos: 0
921-
num_teams: 1
922-
num_members: 1
921+
num_teams: 2
922+
num_members: 2
923923
visibility: 0
924924
repo_admin_change_team_access: false
925925
theme: ""
@@ -1289,8 +1289,8 @@
12891289
num_following: 0
12901290
num_stars: 0
12911291
num_repos: 0
1292-
num_teams: 1
1293-
num_members: 1
1292+
num_teams: 2
1293+
num_members: 2
12941294
visibility: 2
12951295
repo_admin_change_team_access: false
12961296
theme: ""

models/git/branch.go

Lines changed: 120 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ import (
1010

1111
"code.gitea.io/gitea/models/db"
1212
repo_model "code.gitea.io/gitea/models/repo"
13+
"code.gitea.io/gitea/models/unit"
1314
user_model "code.gitea.io/gitea/models/user"
1415
"code.gitea.io/gitea/modules/git"
1516
"code.gitea.io/gitea/modules/log"
17+
"code.gitea.io/gitea/modules/optional"
1618
"code.gitea.io/gitea/modules/timeutil"
1719
"code.gitea.io/gitea/modules/util"
1820

@@ -102,8 +104,9 @@ func (err ErrBranchesEqual) Unwrap() error {
102104
// for pagination, keyword search and filtering
103105
type Branch struct {
104106
ID int64
105-
RepoID int64 `xorm:"UNIQUE(s)"`
106-
Name string `xorm:"UNIQUE(s) NOT NULL"` // git's ref-name is case-sensitive internally, however, in some databases (mssql, mysql, by default), it's case-insensitive at the moment
107+
RepoID int64 `xorm:"UNIQUE(s)"`
108+
Repo *repo_model.Repository `xorm:"-"`
109+
Name string `xorm:"UNIQUE(s) NOT NULL"` // git's ref-name is case-sensitive internally, however, in some databases (mssql, mysql, by default), it's case-insensitive at the moment
107110
CommitID string
108111
CommitMessage string `xorm:"TEXT"` // it only stores the message summary (the first line)
109112
PusherID int64
@@ -139,6 +142,14 @@ func (b *Branch) LoadPusher(ctx context.Context) (err error) {
139142
return err
140143
}
141144

145+
func (b *Branch) LoadRepo(ctx context.Context) (err error) {
146+
if b.Repo != nil || b.RepoID == 0 {
147+
return nil
148+
}
149+
b.Repo, err = repo_model.GetRepositoryByID(ctx, b.RepoID)
150+
return err
151+
}
152+
142153
func init() {
143154
db.RegisterModel(new(Branch))
144155
db.RegisterModel(new(RenamedBranch))
@@ -400,24 +411,111 @@ func RenameBranch(ctx context.Context, repo *repo_model.Repository, from, to str
400411
return committer.Commit()
401412
}
402413

403-
// FindRecentlyPushedNewBranches return at most 2 new branches pushed by the user in 6 hours which has no opened PRs created
404-
// except the indicate branch
405-
func FindRecentlyPushedNewBranches(ctx context.Context, repoID, userID int64, excludeBranchName string) (BranchList, error) {
406-
branches := make(BranchList, 0, 2)
407-
subQuery := builder.Select("head_branch").From("pull_request").
408-
InnerJoin("issue", "issue.id = pull_request.issue_id").
409-
Where(builder.Eq{
410-
"pull_request.head_repo_id": repoID,
411-
"issue.is_closed": false,
412-
})
413-
err := db.GetEngine(ctx).
414-
Where("pusher_id=? AND is_deleted=?", userID, false).
415-
And("name <> ?", excludeBranchName).
416-
And("repo_id = ?", repoID).
417-
And("commit_time >= ?", time.Now().Add(-time.Hour*6).Unix()).
418-
NotIn("name", subQuery).
419-
OrderBy("branch.commit_time DESC").
420-
Limit(2).
421-
Find(&branches)
422-
return branches, err
414+
type FindRecentlyPushedNewBranchesOptions struct {
415+
Repo *repo_model.Repository
416+
BaseRepo *repo_model.Repository
417+
CommitAfterUnix int64
418+
MaxCount int
419+
}
420+
421+
type RecentlyPushedNewBranch struct {
422+
BranchDisplayName string
423+
BranchLink string
424+
BranchCompareURL string
425+
CommitTime timeutil.TimeStamp
426+
}
427+
428+
// FindRecentlyPushedNewBranches return at most 2 new branches pushed by the user in 2 hours which has no opened PRs created
429+
// if opts.CommitAfterUnix is 0, we will find the branches that were committed to in the last 2 hours
430+
// if opts.ListOptions is not set, we will only display top 2 latest branch
431+
func FindRecentlyPushedNewBranches(ctx context.Context, doer *user_model.User, opts *FindRecentlyPushedNewBranchesOptions) ([]*RecentlyPushedNewBranch, error) {
432+
if doer == nil {
433+
return []*RecentlyPushedNewBranch{}, nil
434+
}
435+
436+
// find all related repo ids
437+
repoOpts := repo_model.SearchRepoOptions{
438+
Actor: doer,
439+
Private: true,
440+
AllPublic: false, // Include also all public repositories of users and public organisations
441+
AllLimited: false, // Include also all public repositories of limited organisations
442+
Fork: optional.Some(true),
443+
ForkFrom: opts.BaseRepo.ID,
444+
Archived: optional.Some(false),
445+
}
446+
repoCond := repo_model.SearchRepositoryCondition(&repoOpts).And(repo_model.AccessibleRepositoryCondition(doer, unit.TypeCode))
447+
if opts.Repo.ID == opts.BaseRepo.ID {
448+
// should also include the base repo's branches
449+
repoCond = repoCond.Or(builder.Eq{"id": opts.BaseRepo.ID})
450+
} else {
451+
// in fork repo, we only detect the fork repo's branch
452+
repoCond = repoCond.And(builder.Eq{"id": opts.Repo.ID})
453+
}
454+
repoIDs := builder.Select("id").From("repository").Where(repoCond)
455+
456+
if opts.CommitAfterUnix == 0 {
457+
opts.CommitAfterUnix = time.Now().Add(-time.Hour * 2).Unix()
458+
}
459+
460+
baseBranch, err := GetBranch(ctx, opts.BaseRepo.ID, opts.BaseRepo.DefaultBranch)
461+
if err != nil {
462+
return nil, err
463+
}
464+
465+
// find all related branches, these branches may already created PRs, we will check later
466+
var branches []*Branch
467+
if err := db.GetEngine(ctx).
468+
Where(builder.And(
469+
builder.Eq{
470+
"pusher_id": doer.ID,
471+
"is_deleted": false,
472+
},
473+
builder.Gte{"commit_time": opts.CommitAfterUnix},
474+
builder.In("repo_id", repoIDs),
475+
// newly created branch have no changes, so skip them
476+
builder.Neq{"commit_id": baseBranch.CommitID},
477+
)).
478+
OrderBy(db.SearchOrderByRecentUpdated.String()).
479+
Find(&branches); err != nil {
480+
return nil, err
481+
}
482+
483+
newBranches := make([]*RecentlyPushedNewBranch, 0, len(branches))
484+
if opts.MaxCount == 0 {
485+
// by default we display 2 recently pushed new branch
486+
opts.MaxCount = 2
487+
}
488+
for _, branch := range branches {
489+
// whether branch have already created PR
490+
count, err := db.GetEngine(ctx).Table("pull_request").
491+
// we should not only use branch name here, because if there are branches with same name in other repos,
492+
// we can not detect them correctly
493+
Where(builder.Eq{"head_repo_id": branch.RepoID, "head_branch": branch.Name}).Count()
494+
if err != nil {
495+
return nil, err
496+
}
497+
498+
// if no PR, we add to the result
499+
if count == 0 {
500+
if err := branch.LoadRepo(ctx); err != nil {
501+
return nil, err
502+
}
503+
504+
branchDisplayName := branch.Name
505+
if branch.Repo.ID != opts.BaseRepo.ID && branch.Repo.ID != opts.Repo.ID {
506+
branchDisplayName = fmt.Sprintf("%s:%s", branch.Repo.FullName(), branchDisplayName)
507+
}
508+
newBranches = append(newBranches, &RecentlyPushedNewBranch{
509+
BranchDisplayName: branchDisplayName,
510+
BranchLink: fmt.Sprintf("%s/src/branch/%s", branch.Repo.Link(), util.PathEscapeSegments(branch.Name)),
511+
BranchCompareURL: branch.Repo.ComposeBranchCompareURL(opts.BaseRepo, branch.Name),
512+
CommitTime: branch.CommitTime,
513+
})
514+
}
515+
if len(newBranches) == opts.MaxCount {
516+
break
517+
}
518+
}
519+
520+
return newBranches, nil
423521
}

models/git/branch_list.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"context"
88

99
"code.gitea.io/gitea/models/db"
10+
repo_model "code.gitea.io/gitea/models/repo"
1011
user_model "code.gitea.io/gitea/models/user"
1112
"code.gitea.io/gitea/modules/container"
1213
"code.gitea.io/gitea/modules/optional"
@@ -59,6 +60,24 @@ func (branches BranchList) LoadPusher(ctx context.Context) error {
5960
return nil
6061
}
6162

63+
func (branches BranchList) LoadRepo(ctx context.Context) error {
64+
ids := container.FilterSlice(branches, func(branch *Branch) (int64, bool) {
65+
return branch.RepoID, branch.RepoID > 0 && branch.Repo == nil
66+
})
67+
68+
reposMap := make(map[int64]*repo_model.Repository, len(ids))
69+
if err := db.GetEngine(ctx).In("id", ids).Find(&reposMap); err != nil {
70+
return err
71+
}
72+
for _, branch := range branches {
73+
if branch.RepoID <= 0 || branch.Repo != nil {
74+
continue
75+
}
76+
branch.Repo = reposMap[branch.RepoID]
77+
}
78+
return nil
79+
}
80+
6281
type FindBranchOptions struct {
6382
db.ListOptions
6483
RepoID int64

0 commit comments

Comments
 (0)