summaryrefslogtreecommitdiffstats
path: root/models
diff options
context:
space:
mode:
authoryp05327 <576951401@qq.com>2024-05-23 13:14:26 +0900
committerGitHub <noreply@github.com>2024-05-23 04:14:26 +0000
commit564fef1e208290f2ead151cdc95ed846f93178c7 (patch)
tree0ea3d3b63f84d6069733aeb11d8905c472192783 /models
parent14ed06d675a7d69ef40fdd5a7f63327d294cfe67 (diff)
downloadgitea-564fef1e208290f2ead151cdc95ed846f93178c7.tar.gz
gitea-564fef1e208290f2ead151cdc95ed846f93178c7.zip
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 <me@silverwind.io> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Diffstat (limited to 'models')
-rw-r--r--models/fixtures/branch.yml36
-rw-r--r--models/fixtures/issue_index.yml8
-rw-r--r--models/fixtures/org_user.yml12
-rw-r--r--models/fixtures/repository.yml2
-rw-r--r--models/fixtures/team.yml22
-rw-r--r--models/fixtures/team_unit.yml18
-rw-r--r--models/fixtures/team_user.yml12
-rw-r--r--models/fixtures/user.yml8
-rw-r--r--models/git/branch.go142
-rw-r--r--models/git/branch_list.go19
-rw-r--r--models/organization/org_user_test.go6
-rw-r--r--models/repo/repo_list.go6
12 files changed, 261 insertions, 30 deletions
diff --git a/models/fixtures/branch.yml b/models/fixtures/branch.yml
index 93003049c6..c7bdff7733 100644
--- a/models/fixtures/branch.yml
+++ b/models/fixtures/branch.yml
@@ -45,3 +45,39 @@
is_deleted: false
deleted_by_id: 0
deleted_unix: 0
+
+-
+ id: 5
+ repo_id: 10
+ name: 'master'
+ commit_id: '65f1bf27bc3bf70f64657658635e66094edbcb4d'
+ commit_message: 'Initial commit'
+ commit_time: 1489927679
+ pusher_id: 12
+ is_deleted: false
+ deleted_by_id: 0
+ deleted_unix: 0
+
+-
+ id: 6
+ repo_id: 10
+ name: 'outdated-new-branch'
+ commit_id: 'cb24c347e328d83c1e0c3c908a6b2c0a2fcb8a3d'
+ commit_message: 'add'
+ commit_time: 1489927679
+ pusher_id: 12
+ is_deleted: false
+ deleted_by_id: 0
+ deleted_unix: 0
+
+-
+ id: 14
+ repo_id: 11
+ name: 'master'
+ commit_id: '65f1bf27bc3bf70f64657658635e66094edbcb4d'
+ commit_message: 'Initial commit'
+ commit_time: 1489927679
+ pusher_id: 13
+ is_deleted: false
+ deleted_by_id: 0
+ deleted_unix: 0
diff --git a/models/fixtures/issue_index.yml b/models/fixtures/issue_index.yml
index de6e955804..5aabc08e38 100644
--- a/models/fixtures/issue_index.yml
+++ b/models/fixtures/issue_index.yml
@@ -1,27 +1,35 @@
-
group_id: 1
max_index: 5
+
-
group_id: 2
max_index: 2
+
-
group_id: 3
max_index: 2
+
-
group_id: 10
max_index: 1
+
-
group_id: 32
max_index: 2
+
-
group_id: 48
max_index: 1
+
-
group_id: 42
max_index: 1
+
-
group_id: 50
max_index: 1
+
-
group_id: 51
max_index: 1
diff --git a/models/fixtures/org_user.yml b/models/fixtures/org_user.yml
index a7fbcb2c5a..cf21b84aa9 100644
--- a/models/fixtures/org_user.yml
+++ b/models/fixtures/org_user.yml
@@ -117,3 +117,15 @@
uid: 40
org_id: 41
is_public: true
+
+-
+ id: 21
+ uid: 12
+ org_id: 25
+ is_public: true
+
+-
+ id: 22
+ uid: 2
+ org_id: 35
+ is_public: true
diff --git a/models/fixtures/repository.yml b/models/fixtures/repository.yml
index e5c6224c96..e1f1dd7367 100644
--- a/models/fixtures/repository.yml
+++ b/models/fixtures/repository.yml
@@ -327,7 +327,7 @@
is_archived: false
is_mirror: false
status: 0
- is_fork: false
+ is_fork: true
fork_id: 10
is_template: false
template_id: 0
diff --git a/models/fixtures/team.yml b/models/fixtures/team.yml
index 149fe90888..b549d0589b 100644
--- a/models/fixtures/team.yml
+++ b/models/fixtures/team.yml
@@ -239,3 +239,25 @@
num_members: 2
includes_all_repositories: false
can_create_org_repo: false
+
+-
+ id: 23
+ org_id: 25
+ lower_name: owners
+ name: Owners
+ authorize: 4 # owner
+ num_repos: 0
+ num_members: 1
+ includes_all_repositories: false
+ can_create_org_repo: true
+
+-
+ id: 24
+ org_id: 35
+ lower_name: team24
+ name: team24
+ authorize: 2 # write
+ num_repos: 0
+ num_members: 1
+ includes_all_repositories: true
+ can_create_org_repo: false
diff --git a/models/fixtures/team_unit.yml b/models/fixtures/team_unit.yml
index de0e8d738b..110019eee3 100644
--- a/models/fixtures/team_unit.yml
+++ b/models/fixtures/team_unit.yml
@@ -322,3 +322,21 @@
team_id: 22
type: 3
access_mode: 1
+
+-
+ id: 55
+ team_id: 18
+ type: 1 # code
+ access_mode: 4
+
+-
+ id: 56
+ team_id: 23
+ type: 1 # code
+ access_mode: 4
+
+-
+ id: 57
+ team_id: 24
+ type: 1 # code
+ access_mode: 2
diff --git a/models/fixtures/team_user.yml b/models/fixtures/team_user.yml
index 02d57ae644..6b2d153278 100644
--- a/models/fixtures/team_user.yml
+++ b/models/fixtures/team_user.yml
@@ -147,3 +147,15 @@
org_id: 41
team_id: 22
uid: 39
+
+-
+ id: 26
+ org_id: 25
+ team_id: 23
+ uid: 12
+
+-
+ id: 27
+ org_id: 35
+ team_id: 24
+ uid: 2
diff --git a/models/fixtures/user.yml b/models/fixtures/user.yml
index a3de535508..8504d88ce5 100644
--- a/models/fixtures/user.yml
+++ b/models/fixtures/user.yml
@@ -918,8 +918,8 @@
num_following: 0
num_stars: 0
num_repos: 0
- num_teams: 1
- num_members: 1
+ num_teams: 2
+ num_members: 2
visibility: 0
repo_admin_change_team_access: false
theme: ""
@@ -1289,8 +1289,8 @@
num_following: 0
num_stars: 0
num_repos: 0
- num_teams: 1
- num_members: 1
+ num_teams: 2
+ num_members: 2
visibility: 2
repo_admin_change_team_access: false
theme: ""
diff --git a/models/git/branch.go b/models/git/branch.go
index 2979dff3d2..c315d921ff 100644
--- a/models/git/branch.go
+++ b/models/git/branch.go
@@ -10,9 +10,11 @@ import (
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
+ "code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
+ "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
@@ -102,8 +104,9 @@ func (err ErrBranchesEqual) Unwrap() error {
// for pagination, keyword search and filtering
type Branch struct {
ID int64
- RepoID int64 `xorm:"UNIQUE(s)"`
- 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
+ RepoID int64 `xorm:"UNIQUE(s)"`
+ Repo *repo_model.Repository `xorm:"-"`
+ 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
CommitID string
CommitMessage string `xorm:"TEXT"` // it only stores the message summary (the first line)
PusherID int64
@@ -139,6 +142,14 @@ func (b *Branch) LoadPusher(ctx context.Context) (err error) {
return err
}
+func (b *Branch) LoadRepo(ctx context.Context) (err error) {
+ if b.Repo != nil || b.RepoID == 0 {
+ return nil
+ }
+ b.Repo, err = repo_model.GetRepositoryByID(ctx, b.RepoID)
+ return err
+}
+
func init() {
db.RegisterModel(new(Branch))
db.RegisterModel(new(RenamedBranch))
@@ -400,24 +411,111 @@ func RenameBranch(ctx context.Context, repo *repo_model.Repository, from, to str
return committer.Commit()
}
-// FindRecentlyPushedNewBranches return at most 2 new branches pushed by the user in 6 hours which has no opened PRs created
-// except the indicate branch
-func FindRecentlyPushedNewBranches(ctx context.Context, repoID, userID int64, excludeBranchName string) (BranchList, error) {
- branches := make(BranchList, 0, 2)
- subQuery := builder.Select("head_branch").From("pull_request").
- InnerJoin("issue", "issue.id = pull_request.issue_id").
- Where(builder.Eq{
- "pull_request.head_repo_id": repoID,
- "issue.is_closed": false,
- })
- err := db.GetEngine(ctx).
- Where("pusher_id=? AND is_deleted=?", userID, false).
- And("name <> ?", excludeBranchName).
- And("repo_id = ?", repoID).
- And("commit_time >= ?", time.Now().Add(-time.Hour*6).Unix()).
- NotIn("name", subQuery).
- OrderBy("branch.commit_time DESC").
- Limit(2).
- Find(&branches)
- return branches, err
+type FindRecentlyPushedNewBranchesOptions struct {
+ Repo *repo_model.Repository
+ BaseRepo *repo_model.Repository
+ CommitAfterUnix int64
+ MaxCount int
+}
+
+type RecentlyPushedNewBranch struct {
+ BranchDisplayName string
+ BranchLink string
+ BranchCompareURL string
+ CommitTime timeutil.TimeStamp
+}
+
+// FindRecentlyPushedNewBranches return at most 2 new branches pushed by the user in 2 hours which has no opened PRs created
+// if opts.CommitAfterUnix is 0, we will find the branches that were committed to in the last 2 hours
+// if opts.ListOptions is not set, we will only display top 2 latest branch
+func FindRecentlyPushedNewBranches(ctx context.Context, doer *user_model.User, opts *FindRecentlyPushedNewBranchesOptions) ([]*RecentlyPushedNewBranch, error) {
+ if doer == nil {
+ return []*RecentlyPushedNewBranch{}, nil
+ }
+
+ // find all related repo ids
+ repoOpts := repo_model.SearchRepoOptions{
+ Actor: doer,
+ Private: true,
+ AllPublic: false, // Include also all public repositories of users and public organisations
+ AllLimited: false, // Include also all public repositories of limited organisations
+ Fork: optional.Some(true),
+ ForkFrom: opts.BaseRepo.ID,
+ Archived: optional.Some(false),
+ }
+ repoCond := repo_model.SearchRepositoryCondition(&repoOpts).And(repo_model.AccessibleRepositoryCondition(doer, unit.TypeCode))
+ if opts.Repo.ID == opts.BaseRepo.ID {
+ // should also include the base repo's branches
+ repoCond = repoCond.Or(builder.Eq{"id": opts.BaseRepo.ID})
+ } else {
+ // in fork repo, we only detect the fork repo's branch
+ repoCond = repoCond.And(builder.Eq{"id": opts.Repo.ID})
+ }
+ repoIDs := builder.Select("id").From("repository").Where(repoCond)
+
+ if opts.CommitAfterUnix == 0 {
+ opts.CommitAfterUnix = time.Now().Add(-time.Hour * 2).Unix()
+ }
+
+ baseBranch, err := GetBranch(ctx, opts.BaseRepo.ID, opts.BaseRepo.DefaultBranch)
+ if err != nil {
+ return nil, err
+ }
+
+ // find all related branches, these branches may already created PRs, we will check later
+ var branches []*Branch
+ if err := db.GetEngine(ctx).
+ Where(builder.And(
+ builder.Eq{
+ "pusher_id": doer.ID,
+ "is_deleted": false,
+ },
+ builder.Gte{"commit_time": opts.CommitAfterUnix},
+ builder.In("repo_id", repoIDs),
+ // newly created branch have no changes, so skip them
+ builder.Neq{"commit_id": baseBranch.CommitID},
+ )).
+ OrderBy(db.SearchOrderByRecentUpdated.String()).
+ Find(&branches); err != nil {
+ return nil, err
+ }
+
+ newBranches := make([]*RecentlyPushedNewBranch, 0, len(branches))
+ if opts.MaxCount == 0 {
+ // by default we display 2 recently pushed new branch
+ opts.MaxCount = 2
+ }
+ for _, branch := range branches {
+ // whether branch have already created PR
+ count, err := db.GetEngine(ctx).Table("pull_request").
+ // we should not only use branch name here, because if there are branches with same name in other repos,
+ // we can not detect them correctly
+ Where(builder.Eq{"head_repo_id": branch.RepoID, "head_branch": branch.Name}).Count()
+ if err != nil {
+ return nil, err
+ }
+
+ // if no PR, we add to the result
+ if count == 0 {
+ if err := branch.LoadRepo(ctx); err != nil {
+ return nil, err
+ }
+
+ branchDisplayName := branch.Name
+ if branch.Repo.ID != opts.BaseRepo.ID && branch.Repo.ID != opts.Repo.ID {
+ branchDisplayName = fmt.Sprintf("%s:%s", branch.Repo.FullName(), branchDisplayName)
+ }
+ newBranches = append(newBranches, &RecentlyPushedNewBranch{
+ BranchDisplayName: branchDisplayName,
+ BranchLink: fmt.Sprintf("%s/src/branch/%s", branch.Repo.Link(), util.PathEscapeSegments(branch.Name)),
+ BranchCompareURL: branch.Repo.ComposeBranchCompareURL(opts.BaseRepo, branch.Name),
+ CommitTime: branch.CommitTime,
+ })
+ }
+ if len(newBranches) == opts.MaxCount {
+ break
+ }
+ }
+
+ return newBranches, nil
}
diff --git a/models/git/branch_list.go b/models/git/branch_list.go
index 980bd7b4c9..5c887461d5 100644
--- a/models/git/branch_list.go
+++ b/models/git/branch_list.go
@@ -7,6 +7,7 @@ import (
"context"
"code.gitea.io/gitea/models/db"
+ repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/optional"
@@ -59,6 +60,24 @@ func (branches BranchList) LoadPusher(ctx context.Context) error {
return nil
}
+func (branches BranchList) LoadRepo(ctx context.Context) error {
+ ids := container.FilterSlice(branches, func(branch *Branch) (int64, bool) {
+ return branch.RepoID, branch.RepoID > 0 && branch.Repo == nil
+ })
+
+ reposMap := make(map[int64]*repo_model.Repository, len(ids))
+ if err := db.GetEngine(ctx).In("id", ids).Find(&reposMap); err != nil {
+ return err
+ }
+ for _, branch := range branches {
+ if branch.RepoID <= 0 || branch.Repo != nil {
+ continue
+ }
+ branch.Repo = reposMap[branch.RepoID]
+ }
+ return nil
+}
+
type FindBranchOptions struct {
db.ListOptions
RepoID int64
diff --git a/models/organization/org_user_test.go b/models/organization/org_user_test.go
index 7924517f31..cf7acdf83b 100644
--- a/models/organization/org_user_test.go
+++ b/models/organization/org_user_test.go
@@ -81,7 +81,7 @@ func TestUserListIsPublicMember(t *testing.T) {
{3, map[int64]bool{2: true, 4: false, 28: true}},
{6, map[int64]bool{5: true, 28: true}},
{7, map[int64]bool{5: false}},
- {25, map[int64]bool{24: true}},
+ {25, map[int64]bool{12: true, 24: true}},
{22, map[int64]bool{}},
}
for _, v := range tt {
@@ -108,8 +108,8 @@ func TestUserListIsUserOrgOwner(t *testing.T) {
{3, map[int64]bool{2: true, 4: false, 28: false}},
{6, map[int64]bool{5: true, 28: false}},
{7, map[int64]bool{5: true}},
- {25, map[int64]bool{24: false}}, // ErrTeamNotExist
- {22, map[int64]bool{}}, // No member
+ {25, map[int64]bool{12: true, 24: false}}, // ErrTeamNotExist
+ {22, map[int64]bool{}}, // No member
}
for _, v := range tt {
t.Run(fmt.Sprintf("IsUserOrgOwnerOfOrgId%d", v.orgid), func(t *testing.T) {
diff --git a/models/repo/repo_list.go b/models/repo/repo_list.go
index 987c7df9b0..eacc98e222 100644
--- a/models/repo/repo_list.go
+++ b/models/repo/repo_list.go
@@ -175,6 +175,8 @@ type SearchRepoOptions struct {
// True -> include just forks
// False -> include just non-forks
Fork optional.Option[bool]
+ // If Fork option is True, you can use this option to limit the forks of a special repo by repo id.
+ ForkFrom int64
// None -> include templates AND non-templates
// True -> include just templates
// False -> include just non-templates
@@ -514,6 +516,10 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond {
cond = cond.And(builder.Eq{"is_fork": false})
} else {
cond = cond.And(builder.Eq{"is_fork": opts.Fork.Value()})
+
+ if opts.ForkFrom > 0 && opts.Fork.Value() {
+ cond = cond.And(builder.Eq{"fork_id": opts.ForkFrom})
+ }
}
}