yp05327 1 week ago
parent
commit
dadadc7ccf
No account linked to committer's email address

+ 40
- 28
models/fixtures/access.yml View File

@@ -1,173 +1,185 @@
-
id: 1
user_id: 1
repo_id: 63
mode: 4

-
id: 2
user_id: 2
repo_id: 3
mode: 4

-
id: 2
id: 3
user_id: 2
repo_id: 5
mode: 4

-
id: 3
id: 4
user_id: 2
repo_id: 24
mode: 2

-
id: 4
id: 5
user_id: 2
repo_id: 32
mode: 4

-
id: 5
id: 6
user_id: 4
repo_id: 3
mode: 2

-
id: 6
id: 7
user_id: 4
repo_id: 4
mode: 2

-
id: 7
id: 8
user_id: 4
repo_id: 40
mode: 2

-
id: 8
id: 9
user_id: 10
repo_id: 21
mode: 2

-
id: 9
id: 10
user_id: 10
repo_id: 32
mode: 2

-
id: 10
id: 11
user_id: 12
repo_id: 62
mode: 4

-
id: 12
user_id: 15
repo_id: 21
mode: 2

-
id: 11
id: 13
user_id: 15
repo_id: 22
mode: 2

-
id: 12
id: 14
user_id: 15
repo_id: 23
mode: 4

-
id: 13
id: 15
user_id: 15
repo_id: 24
mode: 4

-
id: 14
id: 16
user_id: 15
repo_id: 32
mode: 2

-
id: 15
id: 17
user_id: 18
repo_id: 21
mode: 2

-
id: 16
id: 18
user_id: 18
repo_id: 22
mode: 2

-
id: 17
id: 19
user_id: 18
repo_id: 23
mode: 4

-
id: 18
id: 20
user_id: 18
repo_id: 24
mode: 4

-
id: 19
id: 21
user_id: 20
repo_id: 24
mode: 1

-
id: 20
id: 22
user_id: 20
repo_id: 27
mode: 4

-
id: 21
id: 23
user_id: 20
repo_id: 28
mode: 4

-
id: 22
id: 24
user_id: 29
repo_id: 4
mode: 2

-
id: 23
id: 25
user_id: 29
repo_id: 24
mode: 1

-
id: 24
id: 26
user_id: 31
repo_id: 27
mode: 4

-
id: 25
id: 27
user_id: 31
repo_id: 28
mode: 4

-
id: 26
id: 28
user_id: 38
repo_id: 60
mode: 2

-
id: 27
id: 29
user_id: 38
repo_id: 61
mode: 1

-
id: 28
id: 30
user_id: 39
repo_id: 61
mode: 1

-
id: 29
id: 31
user_id: 40
repo_id: 61
mode: 4

+ 264
- 0
models/fixtures/branch.yml View File

@@ -45,3 +45,267 @@
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: 'new-commit'
commit_id: 'cb24c347e328d83c1e0c3c908a6b2c0a2fcb8a3d'
commit_message: 'add'
commit_time: 1489927680
pusher_id: 12
is_deleted: false
deleted_by_id: 0
deleted_unix: 0

-
id: 7
repo_id: 10
name: 'no-commit'
commit_id: '65f1bf27bc3bf70f64657658635e66094edbcb4d'
commit_message: 'Initial commit'
commit_time: 1489927679
pusher_id: 12
is_deleted: false
deleted_by_id: 0
deleted_unix: 0

-
id: 8
repo_id: 10
name: 'opening-pr'
commit_id: 'cb24c347e328d83c1e0c3c908a6b2c0a2fcb8a3d'
commit_message: 'add'
commit_time: 1489927680
pusher_id: 12
is_deleted: false
deleted_by_id: 0
deleted_unix: 0

-
id: 9
repo_id: 10
name: 'closed-pr'
commit_id: 'cb24c347e328d83c1e0c3c908a6b2c0a2fcb8a3d'
commit_message: 'add'
commit_time: 1489927680
pusher_id: 12
is_deleted: false
deleted_by_id: 0
deleted_unix: 0

-
id: 10
repo_id: 10
name: 'merged-pr'
commit_id: 'cb24c347e328d83c1e0c3c908a6b2c0a2fcb8a3d'
commit_message: 'add'
commit_time: 1489927680
pusher_id: 12
is_deleted: false
deleted_by_id: 0
deleted_unix: 0

-
id: 11
repo_id: 10
name: 'closed-pr-with-deleted-branch'
commit_id: 'cb24c347e328d83c1e0c3c908a6b2c0a2fcb8a3d'
commit_message: 'add'
commit_time: 1489927680
pusher_id: 12
is_deleted: true
deleted_by_id: 12
deleted_unix: 1489927700

-
id: 12
repo_id: 10
name: 'merged-pr-with-deleted-branch'
commit_id: 'cb24c347e328d83c1e0c3c908a6b2c0a2fcb8a3d'
commit_message: 'add'
commit_time: 1489927680
pusher_id: 12
is_deleted: true
deleted_by_id: 12
deleted_unix: 1489927700

-
id: 13
repo_id: 10
name: 'deleted-branch'
commit_id: 'cb24c347e328d83c1e0c3c908a6b2c0a2fcb8a3d'
commit_message: 'add'
commit_time: 1489927680
pusher_id: 12
is_deleted: true
deleted_by_id: 12
deleted_unix: 1489927700

-
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

-
id: 15
repo_id: 11
name: 'user-fork-new-commit'
commit_id: 'cb24c347e328d83c1e0c3c908a6b2c0a2fcb8a3d'
commit_message: 'add'
commit_time: 1489927680
pusher_id: 13
is_deleted: false
deleted_by_id: 0
deleted_unix: 0

-
id: 16
repo_id: 11
name: 'user-fork-no-commit'
commit_id: '65f1bf27bc3bf70f64657658635e66094edbcb4d'
commit_message: 'Initial commit'
commit_time: 1489927679
pusher_id: 13
is_deleted: false
deleted_by_id: 0
deleted_unix: 0

-
id: 17
repo_id: 62
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: 18
repo_id: 62
name: 'org-fork-new-commit'
commit_id: 'cb24c347e328d83c1e0c3c908a6b2c0a2fcb8a3d'
commit_message: 'add'
commit_time: 1489927691
pusher_id: 12
is_deleted: false
deleted_by_id: 0
deleted_unix: 0

-
id: 19
repo_id: 62
name: 'org-fork-no-commit'
commit_id: '65f1bf27bc3bf70f64657658635e66094edbcb4d'
commit_message: 'Initial commit'
commit_time: 1489927691
pusher_id: 12
is_deleted: false
deleted_by_id: 0
deleted_unix: 0

-
id: 20
repo_id: 63
name: 'master'
commit_id: '65f1bf27bc3bf70f64657658635e66094edbcb4d'
commit_message: 'Initial commit'
commit_time: 1489927679
pusher_id: 1
is_deleted: false
deleted_by_id: 0
deleted_unix: 0

-
id: 21
repo_id: 63
name: 'private-org-fork-new-commit'
commit_id: 'cb24c347e328d83c1e0c3c908a6b2c0a2fcb8a3d'
commit_message: 'add'
commit_time: 1489927680
pusher_id: 1
is_deleted: false
deleted_by_id: 0
deleted_unix: 0

-
id: 22
repo_id: 63
name: 'private-org-fork-no-commit'
commit_id: '65f1bf27bc3bf70f64657658635e66094edbcb4d'
commit_message: 'Initial commit'
commit_time: 1489927679
pusher_id: 1
is_deleted: false
deleted_by_id: 0
deleted_unix: 0

-
id: 23
repo_id: 63
name: 'private-org-fork-no-permission-new-commit'
commit_id: 'cb24c347e328d83c1e0c3c908a6b2c0a2fcb8a3d'
commit_message: 'add'
commit_time: 1489927680
pusher_id: 2
is_deleted: false
deleted_by_id: 0
deleted_unix: 0

-
id: 24
repo_id: 63
name: 'private-org-fork-no-permission-no-commit'
commit_id: '65f1bf27bc3bf70f64657658635e66094edbcb4d'
commit_message: 'Initial commit'
commit_time: 1489927679
pusher_id: 2
is_deleted: false
deleted_by_id: 0
deleted_unix: 0

-
id: 25
repo_id: 10
name: 'same-name-branch-in-pr'
commit_id: 'cb24c347e328d83c1e0c3c908a6b2c0a2fcb8a3d'
commit_message: 'add'
commit_time: 1489927680
pusher_id: 13
is_deleted: false
deleted_by_id: 0
deleted_unix: 0

-
id: 26
repo_id: 11
name: 'same-name-branch-in-pr'
commit_id: 'cb24c347e328d83c1e0c3c908a6b2c0a2fcb8a3d'
commit_message: 'add'
commit_time: 1489927680
pusher_id: 13
is_deleted: false
deleted_by_id: 0
deleted_unix: 0

+ 102
- 0
models/fixtures/issue.yml View File

@@ -372,3 +372,105 @@
created_unix: 1707270422
updated_unix: 1707270422
is_locked: false

-
id: 23
repo_id: 10
index: 2
poster_id: 12
original_author_id: 0
name: opening pr for recently new branch search test
content: content
milestone_id: 0
priority: 0
is_closed: false
is_pull: true
num_comments: 0
created_unix: 946684830
updated_unix: 978307200
is_locked: false

-
id: 24
repo_id: 10
index: 3
poster_id: 12
original_author_id: 0
name: closed pr for recently new branch search test
content: content
milestone_id: 0
priority: 0
is_closed: true
is_pull: true
num_comments: 0
created_unix: 946684830
updated_unix: 978307200
is_locked: false

-
id: 25
repo_id: 10
index: 4
poster_id: 12
original_author_id: 0
name: merged pr for recently new branch search test
content: content
milestone_id: 0
priority: 0
is_closed: false
is_pull: true
num_comments: 0
created_unix: 946684830
updated_unix: 978307200
is_locked: false

-
id: 26
repo_id: 10
index: 5
poster_id: 12
original_author_id: 0
name: closed pr with deleted branch for recently new branch search test
content: content
milestone_id: 0
priority: 0
is_closed: true
is_pull: true
num_comments: 0
created_unix: 946684830
updated_unix: 978307200
is_locked: false

-
id: 27
repo_id: 10
index: 6
poster_id: 12
original_author_id: 0
name: merged pr with deleted branch for recently new branch search test
content: content
milestone_id: 0
priority: 0
is_closed: false
is_pull: true
num_comments: 0
created_unix: 946684830
updated_unix: 978307200
is_locked: false

-
id: 28
repo_id: 11
index: 1
poster_id: 13
original_author_id: 0
name: pr with same branch name for recently new branch search test
content: content
milestone_id: 0
priority: 0
is_closed: false
is_pull: true
num_comments: 0
created_unix: 946684830
updated_unix: 978307200
is_locked: false

+ 9
- 1
models/fixtures/issue_index.yml View File

@@ -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
max_index: 6

-
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

+ 12
- 0
models/fixtures/org_user.yml View File

@@ -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

+ 78
- 0
models/fixtures/pull_request.yml View File

@@ -117,3 +117,81 @@
index: 1
head_repo_id: 61
base_repo_id: 61

-
id: 11
type: 0 # gitea pull request
status: 2 # mergable
issue_id: 23
index: 2
head_repo_id: 10
base_repo_id: 10
head_branch: opening-pr
base_branch: master
merge_base: cb24c347e328d83c1e0c3c908a6b2c0a2fcb8a3d
has_merged: false

-
id: 12
type: 0 # gitea pull request
status: 2 # mergable
issue_id: 24
index: 3
head_repo_id: 10
base_repo_id: 10
head_branch: closed-pr
base_branch: master
merge_base: cb24c347e328d83c1e0c3c908a6b2c0a2fcb8a3d
has_merged: false

-
id: 13
type: 0 # gitea pull request
status: 3 # manually merged
issue_id: 25
index: 4
head_repo_id: 10
base_repo_id: 10
head_branch: merged-pr
base_branch: master
merge_base: cb24c347e328d83c1e0c3c908a6b2c0a2fcb8a3d
has_merged: true

-
id: 14
type: 0 # gitea pull request
status: 2 # mergable
issue_id: 26
index: 5
head_repo_id: 10
base_repo_id: 10
head_branch: closed-pr-with-deleted-branch
base_branch: master
merge_base: cb24c347e328d83c1e0c3c908a6b2c0a2fcb8a3d
has_merged: false

-
id: 15
type: 0 # gitea pull request
status: 3 # manually merged
issue_id: 27
index: 6
head_repo_id: 10
base_repo_id: 10
head_branch: merged-pr-with-deleted-branch
base_branch: master
merge_base: cb24c347e328d83c1e0c3c908a6b2c0a2fcb8a3d
has_merged: true

-
id: 16
type: 0 # gitea pull request
status: 2 # mergable
issue_id: 28
index: 1
head_repo_id: 11
base_repo_id: 10
head_branch: same-name-branch-in-pr
base_branch: master
merge_base: cb24c347e328d83c1e0c3c908a6b2c0a2fcb8a3d
has_merged: false

+ 12
- 0
models/fixtures/repo_unit.yml View File

@@ -712,3 +712,15 @@
type: 3
config: "{\"IgnoreWhitespaceConflicts\":false,\"AllowMerge\":true,\"AllowRebase\":true,\"AllowRebaseMerge\":true,\"AllowSquash\":true}"
created_unix: 946684810

-
id: 108
repo_id: 62
type: 1
created_unix: 946684810

-
id: 109
repo_id: 63
type: 1
created_unix: 946684810

+ 65
- 5
models/fixtures/repository.yml View File

@@ -282,11 +282,11 @@
default_branch: master
num_watches: 0
num_stars: 0
num_forks: 1
num_forks: 3
num_issues: 0
num_closed_issues: 0
num_pulls: 1
num_closed_pulls: 0
num_pulls: 6
num_closed_pulls: 2
num_milestones: 1
num_closed_milestones: 0
num_projects: 0
@@ -316,7 +316,7 @@
num_forks: 0
num_issues: 0
num_closed_issues: 0
num_pulls: 0
num_pulls: 1
num_closed_pulls: 0
num_milestones: 0
num_closed_milestones: 0
@@ -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
@@ -1768,3 +1768,63 @@
size: 0
is_fsck_enabled: true
close_issues_via_commit_in_any_branch: false

-
id: 62
owner_id: 25
owner_name: org25
lower_name: org_fork_repo62
name: org_fork_repo62
num_watches: 0
num_stars: 0
num_forks: 0
num_issues: 0
num_closed_issues: 0
num_pulls: 0
num_closed_pulls: 0
num_milestones: 0
num_closed_milestones: 0
num_projects: 0
num_closed_projects: 0
is_private: false
is_empty: false
is_archived: false
is_mirror: false
status: 0
is_fork: true
fork_id: 10
is_template: false
template_id: 0
size: 0
is_fsck_enabled: true
close_issues_via_commit_in_any_branch: false

-
id: 63
owner_id: 35
owner_name: private_org35
lower_name: private_org_fork_repo63
name: private_org_fork_repo63
num_watches: 0
num_stars: 0
num_forks: 0
num_issues: 0
num_closed_issues: 0
num_pulls: 0
num_closed_pulls: 0
num_milestones: 0
num_closed_milestones: 0
num_projects: 0
num_closed_projects: 0
is_private: true
is_empty: false
is_archived: false
is_mirror: false
status: 0
is_fork: true
fork_id: 10
is_template: false
template_id: 0
size: 0
is_fsck_enabled: true
close_issues_via_commit_in_any_branch: false

+ 23
- 1
models/fixtures/team.yml View File

@@ -191,7 +191,7 @@
lower_name: owners
name: Owners
authorize: 4 # owner
num_repos: 0
num_repos: 1
num_members: 1
includes_all_repositories: false
can_create_org_repo: true
@@ -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: team24noreadcode
name: team24noreadcode
authorize: 0 # no access
num_repos: 1
num_members: 1
includes_all_repositories: false
can_create_org_repo: false

+ 12
- 0
models/fixtures/team_repo.yml View File

@@ -75,3 +75,15 @@
org_id: 41
team_id: 22
repo_id: 61

-
id: 14
org_id: 35
team_id: 18
repo_id: 63

-
id: 15
org_id: 35
team_id: 24
repo_id: 63

+ 18
- 0
models/fixtures/team_unit.yml View File

@@ -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: 0

+ 12
- 0
models/fixtures/team_user.yml View File

@@ -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

+ 6
- 6
models/fixtures/user.yml View File

@@ -917,9 +917,9 @@
num_followers: 0
num_following: 0
num_stars: 0
num_repos: 0
num_teams: 1
num_members: 1
num_repos: 1
num_teams: 2
num_members: 2
visibility: 0
repo_admin_change_team_access: false
theme: ""
@@ -1288,9 +1288,9 @@
num_followers: 0
num_following: 0
num_stars: 0
num_repos: 0
num_teams: 1
num_members: 1
num_repos: 1
num_teams: 2
num_members: 2
visibility: 2
repo_admin_change_team_access: false
theme: ""

+ 114
- 22
models/git/branch.go View File

@@ -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,105 @@ 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 {
Actor *user_model.User
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
// opts.Actor should not be nil
// 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, opts *FindRecentlyPushedNewBranchesOptions) ([]*RecentlyPushedNewBranch, error) {
// find all related repo ids
repoOpts := repo_model.SearchRepoOptions{
Actor: opts.Actor,
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(opts.Actor, 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
branches, err := db.Find[Branch](ctx, FindBranchOptions{
RepoCond: builder.In("branch.repo_id", repoIDs),
CommitCond: builder.Neq{"branch.commit_id": baseBranch.CommitID}, // newly created branch have no changes, so skip them,
PusherID: opts.Actor.ID,
IsDeletedBranch: optional.Some(false),
CommitAfterUnix: opts.CommitAfterUnix,
OrderBy: "branch.updated_unix DESC",
ListOptions: db.ListOptionsAll,
})
if 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
}

+ 47
- 2
models/git/branch_list.go View File

@@ -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,30 +60,74 @@ 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
RepoCond builder.Cond
ExcludeBranchNames []string
CommitCond builder.Cond
PusherID int64
IsDeletedBranch optional.Option[bool]
CommitAfterUnix int64
CommitBeforeUnix int64
OrderBy string
Keyword string
}

func (opts FindBranchOptions) ToConds() builder.Cond {
cond := builder.NewCond()

if opts.RepoID > 0 {
cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
}
if opts.RepoCond != nil {
cond = cond.And(opts.RepoCond)
}

if len(opts.ExcludeBranchNames) > 0 {
cond = cond.And(builder.NotIn("name", opts.ExcludeBranchNames))
cond = cond.And(builder.NotIn("branch.name", opts.ExcludeBranchNames))
}

if opts.CommitCond != nil {
cond = cond.And(opts.CommitCond)
}

if opts.PusherID > 0 {
cond = cond.And(builder.Eq{"branch.pusher_id": opts.PusherID})
}

if opts.IsDeletedBranch.Has() {
cond = cond.And(builder.Eq{"is_deleted": opts.IsDeletedBranch.Value()})
cond = cond.And(builder.Eq{"branch.is_deleted": opts.IsDeletedBranch.Value()})
}
if opts.Keyword != "" {
cond = cond.And(builder.Like{"name", opts.Keyword})
}

if opts.CommitAfterUnix != 0 {
cond = cond.And(builder.Gte{"branch.commit_time": opts.CommitAfterUnix})
}
if opts.CommitBeforeUnix != 0 {
cond = cond.And(builder.Lte{"branch.commit_time": opts.CommitBeforeUnix})
}

return cond
}


+ 88
- 0
models/git/branch_test.go View File

@@ -12,6 +12,7 @@ import (
issues_model "code.gitea.io/gitea/models/issues"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/optional"

@@ -183,3 +184,90 @@ func TestOnlyGetDeletedBranchOnCorrectRepo(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, deletedBranch)
}

func TestFindRecentlyPushedNewBranches(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())

repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 10})
user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
user12 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 12})
user13 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 13})

tests := []struct {
name string
opts *git_model.FindRecentlyPushedNewBranchesOptions
count int
want []string
}{
// user12 is the owner of the repo10 and the organization org25
// in repo10, user12 has opening/closed/merged pr and closed/merged pr with deleted branch
{
name: "new branch of the repo, org fork repo, pr branches and deleted branch",
opts: &git_model.FindRecentlyPushedNewBranchesOptions{
Actor: user12,
CommitAfterUnix: 1489927670,
MaxCount: 10,
},
count: 2,
want: []string{"new-commit", "org25/org_fork_repo62:org-fork-new-commit"},
},
// user13 pushed 2 branches with the same name in repo10 and repo11
// and repo11's branch has a pr, but repo10's branch doesn't
// in this case, we should get repo10's branch but not repo11's branch
{
name: "new branch from user fork repo and same name branch",
opts: &git_model.FindRecentlyPushedNewBranchesOptions{
Actor: user13,
CommitAfterUnix: 1489927670,
MaxCount: 10,
},
count: 2,
want: []string{"user13/repo11:user-fork-new-commit", "same-name-branch-in-pr"},
},
// user1 is the owner of private_org35
{
name: "new branch from private org with code permission repo",
opts: &git_model.FindRecentlyPushedNewBranchesOptions{
Actor: user1,
CommitAfterUnix: 1489927670,
},
count: 1,
want: []string{"private_org35/private_org_fork_repo63:private-org-fork-new-commit"},
},
// user2 does not have code permission in private_org35
{
name: "new branch from private org with no code permission repo",
opts: &git_model.FindRecentlyPushedNewBranchesOptions{
Actor: user2,
CommitAfterUnix: 1489927670,
},
count: 0,
want: []string{},
},
{
name: "test commitAfterUnix option",
opts: &git_model.FindRecentlyPushedNewBranchesOptions{
Actor: user12,
CommitAfterUnix: 1489927690,
},
count: 1,
want: []string{"org25/org_fork_repo62:org-fork-new-commit"},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.opts.Repo = repo
tt.opts.BaseRepo = repo
branches, err := git_model.FindRecentlyPushedNewBranches(db.DefaultContext, tt.opts)

assert.NoError(t, err)
assert.Equal(t, tt.count, len(branches))

for i := 0; i < tt.count; i++ {
assert.Equal(t, tt.want[i], branches[i].BranchDisplayName)
}
})
}
}

+ 1
- 1
models/issues/issue_test.go View File

@@ -379,7 +379,7 @@ func TestCountIssues(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
count, err := issues_model.CountIssues(db.DefaultContext, &issues_model.IssuesOptions{})
assert.NoError(t, err)
assert.EqualValues(t, 22, count)
assert.EqualValues(t, 28, count)
}

func TestIssueLoadAttributes(t *testing.T) {

+ 3
- 3
models/organization/org_user_test.go View File

@@ -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) {

+ 6
- 0
models/repo/repo_list.go View File

@@ -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})
}
}
}


+ 3
- 3
models/repo/repo_list_test.go View File

@@ -138,12 +138,12 @@ func getTestCases() []struct {
{
name: "AllPublic/PublicRepositoriesOfUserIncludingCollaborative",
opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, AllPublic: true, Template: optional.Some(false)},
count: 33,
count: 34,
},
{
name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborative",
opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true, AllPublic: true, AllLimited: true, Template: optional.Some(false)},
count: 38,
count: 39,
},
{
name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborativeByName",
@@ -158,7 +158,7 @@ func getTestCases() []struct {
{
name: "AllPublic/PublicRepositoriesOfOrganization",
opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 17, AllPublic: true, Collaborate: optional.Some(false), Template: optional.Some(false)},
count: 33,
count: 34,
},
{
name: "AllTemplates",

+ 7
- 7
modules/indexer/issues/indexer_test.go View File

@@ -215,7 +215,7 @@ func searchIssueIsPull(t *testing.T) {
SearchOptions{
IsPull: optional.Some(true),
},
[]int64{22, 21, 12, 11, 20, 19, 9, 8, 3, 2},
[]int64{22, 21, 12, 11, 20, 28, 27, 26, 25, 24, 23, 19, 9, 8, 3, 2},
},
}
for _, test := range tests {
@@ -236,13 +236,13 @@ func searchIssueIsClosed(t *testing.T) {
SearchOptions{
IsClosed: optional.Some(false),
},
[]int64{22, 21, 17, 16, 15, 14, 13, 12, 11, 20, 6, 19, 18, 10, 7, 9, 8, 3, 2, 1},
[]int64{22, 21, 17, 16, 15, 14, 13, 12, 11, 20, 6, 28, 27, 25, 23, 19, 18, 10, 7, 9, 8, 3, 2, 1},
},
{
SearchOptions{
IsClosed: optional.Some(true),
},
[]int64{5, 4},
[]int64{5, 26, 24, 4},
},
}
for _, test := range tests {
@@ -302,7 +302,7 @@ func searchIssueByLabelID(t *testing.T) {
SearchOptions{
ExcludedLabelIDs: []int64{1},
},
[]int64{22, 21, 17, 16, 15, 14, 13, 12, 11, 20, 6, 5, 19, 18, 10, 7, 4, 9, 8, 3},
[]int64{22, 21, 17, 16, 15, 14, 13, 12, 11, 20, 6, 5, 28, 27, 26, 25, 24, 23, 19, 18, 10, 7, 4, 9, 8, 3},
},
}
for _, test := range tests {
@@ -323,7 +323,7 @@ func searchIssueByTime(t *testing.T) {
SearchOptions{
UpdatedAfterUnix: optional.Some(int64(0)),
},
[]int64{22, 21, 17, 16, 15, 14, 13, 12, 11, 20, 6, 5, 19, 18, 10, 7, 4, 9, 8, 3, 2, 1},
[]int64{22, 21, 17, 16, 15, 14, 13, 12, 11, 20, 6, 5, 28, 27, 26, 25, 24, 23, 19, 18, 10, 7, 4, 9, 8, 3, 2, 1},
},
}
for _, test := range tests {
@@ -344,7 +344,7 @@ func searchIssueWithOrder(t *testing.T) {
SearchOptions{
SortBy: internal.SortByCreatedAsc,
},
[]int64{1, 2, 3, 8, 9, 4, 7, 10, 18, 19, 5, 6, 20, 11, 12, 13, 14, 15, 16, 17, 21, 22},
[]int64{1, 2, 3, 8, 9, 4, 7, 10, 18, 19, 23, 24, 25, 26, 27, 28, 5, 6, 20, 11, 12, 13, 14, 15, 16, 17, 21, 22},
},
}
for _, test := range tests {
@@ -402,7 +402,7 @@ func searchIssueWithPaginator(t *testing.T) {
},
},
[]int64{22, 21, 17, 16, 15},
22,
28,
},
}
for _, test := range tests {

+ 20
- 7
routers/web/repo/view.go View File

@@ -29,6 +29,7 @@ import (
"code.gitea.io/gitea/models/db"
git_model "code.gitea.io/gitea/models/git"
issue_model "code.gitea.io/gitea/models/issues"
access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo"
unit_model "code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user"
@@ -1027,15 +1028,27 @@ func renderHomeCode(ctx *context.Context) {
return
}

showRecentlyPushedNewBranches := true
if ctx.Repo.Repository.IsMirror ||
!ctx.Repo.Repository.UnitEnabled(ctx, unit_model.TypePullRequests) {
showRecentlyPushedNewBranches = false
opts := &git_model.FindRecentlyPushedNewBranchesOptions{
Actor: ctx.Doer,
Repo: ctx.Repo.Repository,
BaseRepo: ctx.Repo.Repository,
}
if showRecentlyPushedNewBranches {
ctx.Data["RecentlyPushedNewBranches"], err = git_model.FindRecentlyPushedNewBranches(ctx, ctx.Repo.Repository.ID, ctx.Doer.ID, ctx.Repo.Repository.DefaultBranch)
if ctx.Repo.Repository.IsFork {
opts.BaseRepo = ctx.Repo.Repository.BaseRepo
}

baseRepoPerm, err := access_model.GetUserRepoPermission(ctx, opts.BaseRepo, ctx.Doer)
if err != nil {
ctx.ServerError("GetUserRepoPermission", err)
return
}

if !opts.Repo.IsMirror && !opts.BaseRepo.IsMirror &&
opts.BaseRepo.UnitEnabled(ctx, unit_model.TypePullRequests) &&
baseRepoPerm.CanRead(unit_model.TypePullRequests) {
ctx.Data["RecentlyPushedNewBranches"], err = git_model.FindRecentlyPushedNewBranches(ctx, opts)
if err != nil {
ctx.ServerError("GetRecentlyPushedBranches", err)
ctx.ServerError("FindRecentlyPushedNewBranches", err)
return
}
}

+ 3
- 2
services/issue/issue_test.go View File

@@ -35,9 +35,10 @@ func TestGetRefEndNamesAndURLs(t *testing.T) {
func TestIssue_DeleteIssue(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())

issueCount := 5
issueIDs, err := issues_model.GetIssueIDsByRepoID(db.DefaultContext, 1)
assert.NoError(t, err)
assert.Len(t, issueIDs, 5)
assert.Len(t, issueIDs, issueCount)

issue := &issues_model.Issue{
RepoID: 1,
@@ -48,7 +49,7 @@ func TestIssue_DeleteIssue(t *testing.T) {
assert.NoError(t, err)
issueIDs, err = issues_model.GetIssueIDsByRepoID(db.DefaultContext, 1)
assert.NoError(t, err)
assert.Len(t, issueIDs, 4)
assert.Len(t, issueIDs, issueCount-1)

// check attachment removal
attachments, err := repo_model.GetAttachmentsByIssueID(db.DefaultContext, 4)

+ 2
- 2
templates/repo/code/recently_pushed_new_branches.tmpl View File

@@ -2,10 +2,10 @@
<div class="ui positive message tw-flex tw-items-center">
<div class="tw-flex-1">
{{$timeSince := TimeSince .CommitTime.AsTime ctx.Locale}}
{{$branchLink := HTMLFormat `<a href="%s/src/branch/%s">%s</a>` $.RepoLink (PathEscapeSegments .Name) .Name}}
{{$branchLink := HTMLFormat `<a href="%s">%s</a>` .BranchLink .BranchDisplayName}}
{{ctx.Locale.Tr "repo.pulls.recently_pushed_new_branches" $branchLink $timeSince}}
</div>
<a role="button" class="ui compact green button tw-m-0" href="{{$.Repository.ComposeBranchCompareURL $.Repository.BaseRepo .Name}}">
<a role="button" class="ui compact green button tw-m-0" href="{{.BranchCompareURL}}">
{{ctx.Locale.Tr "repo.pulls.compare_changes"}}
</a>
</div>

+ 6
- 6
tests/integration/api_issue_test.go View File

@@ -223,7 +223,7 @@ func TestAPISearchIssues(t *testing.T) {
defer tests.PrepareTestEnv(t)()

// as this API was used in the frontend, it uses UI page size
expectedIssueCount := 20 // from the fixtures
expectedIssueCount := 24 // from the fixtures
if expectedIssueCount > setting.UI.IssuePagingNum {
expectedIssueCount = setting.UI.IssuePagingNum
}
@@ -247,7 +247,7 @@ func TestAPISearchIssues(t *testing.T) {
req = NewRequest(t, "GET", link.String()).AddTokenAuth(token)
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiIssues)
assert.Len(t, apiIssues, 11)
assert.Len(t, apiIssues, 15)
query.Del("since")
query.Del("before")

@@ -256,14 +256,14 @@ func TestAPISearchIssues(t *testing.T) {
req = NewRequest(t, "GET", link.String()).AddTokenAuth(token)
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiIssues)
assert.Len(t, apiIssues, 2)
assert.Len(t, apiIssues, 4)

query.Set("state", "all")
link.RawQuery = query.Encode()
req = NewRequest(t, "GET", link.String()).AddTokenAuth(token)
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiIssues)
assert.EqualValues(t, "22", resp.Header().Get("X-Total-Count"))
assert.EqualValues(t, "28", resp.Header().Get("X-Total-Count"))
assert.Len(t, apiIssues, 20)

query.Add("limit", "10")
@@ -271,7 +271,7 @@ func TestAPISearchIssues(t *testing.T) {
req = NewRequest(t, "GET", link.String()).AddTokenAuth(token)
resp = MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiIssues)
assert.EqualValues(t, "22", resp.Header().Get("X-Total-Count"))
assert.EqualValues(t, "28", resp.Header().Get("X-Total-Count"))
assert.Len(t, apiIssues, 10)

query = url.Values{"assigned": {"true"}, "state": {"all"}}
@@ -321,7 +321,7 @@ func TestAPISearchIssuesWithLabels(t *testing.T) {
defer tests.PrepareTestEnv(t)()

// as this API was used in the frontend, it uses UI page size
expectedIssueCount := 20 // from the fixtures
expectedIssueCount := 24 // from the fixtures
if expectedIssueCount > setting.UI.IssuePagingNum {
expectedIssueCount = setting.UI.IssuePagingNum
}

+ 1
- 1
tests/integration/api_nodeinfo_test.go View File

@@ -33,7 +33,7 @@ func TestNodeinfo(t *testing.T) {
assert.True(t, nodeinfo.OpenRegistrations)
assert.Equal(t, "gitea", nodeinfo.Software.Name)
assert.Equal(t, 29, nodeinfo.Usage.Users.Total)
assert.Equal(t, 22, nodeinfo.Usage.LocalPosts)
assert.Equal(t, 28, nodeinfo.Usage.LocalPosts)
assert.Equal(t, 3, nodeinfo.Usage.LocalComments)
})
}

+ 5
- 5
tests/integration/api_repo_test.go View File

@@ -93,9 +93,9 @@ func TestAPISearchRepo(t *testing.T) {
}{
{
name: "RepositoriesMax50", requestURL: "/api/v1/repos/search?limit=50&private=false", expectedResults: expectedResults{
nil: {count: 35},
user: {count: 35},
user2: {count: 35},
nil: {count: 36},
user: {count: 36},
user2: {count: 36},
},
},
{
@@ -275,8 +275,8 @@ func TestAPIViewRepo(t *testing.T) {
DecodeJSON(t, resp, &repo)
assert.EqualValues(t, 10, repo.ID)
assert.EqualValues(t, "repo10", repo.Name)
assert.EqualValues(t, 1, repo.OpenPulls)
assert.EqualValues(t, 1, repo.Forks)
assert.EqualValues(t, 4, repo.OpenPulls)
assert.EqualValues(t, 3, repo.Forks)

req = NewRequest(t, "GET", "/api/v1/repos/user5/repo4")
resp = MakeRequest(t, req, http.StatusOK)

+ 26
- 0
tests/integration/api_user_orgs_test.go View File

@@ -29,6 +29,7 @@ func TestUserOrgs(t *testing.T) {

org3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "org3"})
org17 := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "org17"})
org35 := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "private_org35"})

assert.Equal(t, []*api.Organization{
{
@@ -55,6 +56,18 @@ func TestUserOrgs(t *testing.T) {
Location: "",
Visibility: "public",
},
{
ID: 35,
Name: org35.Name,
UserName: org35.Name,
FullName: org35.FullName,
Email: org35.Email,
AvatarURL: org35.AvatarLink(db.DefaultContext),
Description: "",
Website: "",
Location: "",
Visibility: "private",
},
}, orgs)

// user itself should get it's org's he is a member of
@@ -102,6 +115,7 @@ func TestMyOrgs(t *testing.T) {
DecodeJSON(t, resp, &orgs)
org3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "org3"})
org17 := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "org17"})
org35 := unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: "private_org35"})

assert.Equal(t, []*api.Organization{
{
@@ -128,5 +142,17 @@ func TestMyOrgs(t *testing.T) {
Location: "",
Visibility: "public",
},
{
ID: 35,
Name: org35.Name,
UserName: org35.Name,
FullName: org35.FullName,
Email: org35.Email,
AvatarURL: org35.AvatarLink(db.DefaultContext),
Description: "",
Website: "",
Location: "",
Visibility: "private",
},
}, orgs)
}

+ 6
- 6
tests/integration/issue_test.go View File

@@ -407,7 +407,7 @@ func TestSearchIssues(t *testing.T) {

session := loginUser(t, "user2")

expectedIssueCount := 20 // from the fixtures
expectedIssueCount := 24 // from the fixtures
if expectedIssueCount > setting.UI.IssuePagingNum {
expectedIssueCount = setting.UI.IssuePagingNum
}
@@ -428,7 +428,7 @@ func TestSearchIssues(t *testing.T) {
req = NewRequest(t, "GET", link.String())
resp = session.MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiIssues)
assert.Len(t, apiIssues, 11)
assert.Len(t, apiIssues, 15)
query.Del("since")
query.Del("before")

@@ -437,14 +437,14 @@ func TestSearchIssues(t *testing.T) {
req = NewRequest(t, "GET", link.String())
resp = session.MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiIssues)
assert.Len(t, apiIssues, 2)
assert.Len(t, apiIssues, 4)

query.Set("state", "all")
link.RawQuery = query.Encode()
req = NewRequest(t, "GET", link.String())
resp = session.MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiIssues)
assert.EqualValues(t, "22", resp.Header().Get("X-Total-Count"))
assert.EqualValues(t, "28", resp.Header().Get("X-Total-Count"))
assert.Len(t, apiIssues, 20)

query.Add("limit", "5")
@@ -452,7 +452,7 @@ func TestSearchIssues(t *testing.T) {
req = NewRequest(t, "GET", link.String())
resp = session.MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiIssues)
assert.EqualValues(t, "22", resp.Header().Get("X-Total-Count"))
assert.EqualValues(t, "28", resp.Header().Get("X-Total-Count"))
assert.Len(t, apiIssues, 5)

query = url.Values{"assigned": {"true"}, "state": {"all"}}
@@ -501,7 +501,7 @@ func TestSearchIssues(t *testing.T) {
func TestSearchIssuesWithLabels(t *testing.T) {
defer tests.PrepareTestEnv(t)()

expectedIssueCount := 20 // from the fixtures
expectedIssueCount := 24 // from the fixtures
if expectedIssueCount > setting.UI.IssuePagingNum {
expectedIssueCount = setting.UI.IssuePagingNum
}

Loading…
Cancel
Save