- | |||||
id: 1 | |||||
repo_id: 1 | |||||
index: 1 | |||||
poster_id: 1 | |||||
name: issue1 | |||||
content: content1 | |||||
is_closed: false | |||||
is_pull: false | |||||
created_unix: 946684800 | |||||
updated_unix: 978307200 | |||||
- | |||||
id: 2 | |||||
repo_id: 1 | |||||
index: 2 | |||||
poster_id: 1 | |||||
name: issue2 | |||||
content: content2 | |||||
is_closed: false | |||||
is_pull: true | |||||
created_unix: 946684810 | |||||
updated_unix: 978307190 | |||||
- | |||||
id: 3 | |||||
repo_id: 1 | |||||
index: 3 | |||||
poster_id: 1 | |||||
name: issue3 | |||||
content: content4 | |||||
is_closed: false | |||||
is_pull: true | |||||
created_unix: 946684820 | |||||
updated_unix: 978307180 | |||||
- | |||||
id: 4 | |||||
repo_id: 2 | |||||
index: 1 | |||||
poster_id: 2 | |||||
name: issue4 | |||||
content: content4 | |||||
is_closed: true | |||||
is_pull: false |
- | |||||
id: 1 | |||||
type: 0 # gitea pull request | |||||
status: 2 # mergable | |||||
issue_id: 2 | |||||
index: 1 | |||||
head_repo_id: 1 | |||||
base_repo_id: 1 | |||||
head_user_name: user1 | |||||
head_branch: branch1 | |||||
base_branch: master | |||||
merge_base: 1234567890abcdef | |||||
has_merged: true | |||||
merger_id: 2 | |||||
- | |||||
id: 2 | |||||
type: 0 # gitea pull request | |||||
status: 1 # checking | |||||
issue_id: 3 | |||||
index: 2 | |||||
head_repo_id: 1 | |||||
base_repo_id: 1 | |||||
head_user_name: user1 | |||||
head_branch: branch2 | |||||
base_branch: master | |||||
merge_base: fedcba9876543210 | |||||
has_merged: false |
- | |||||
id: 1 | |||||
owner_id: 2 | |||||
lower_name: repo1 | |||||
name: repo1 | |||||
is_private: false | |||||
num_issues: 1 | |||||
num_closed_issues: 0 | |||||
num_pulls: 2 | |||||
num_closed_pulls: 0 | |||||
- | |||||
id: 2 | |||||
owner_id: 2 | |||||
lower_name: repo2 | |||||
name: repo2 | |||||
is_private: true | |||||
num_issues: 1 | |||||
num_closed_issues: 1 | |||||
num_pulls: 0 | |||||
num_closed_pulls: 0 |
- # NOTE: this user (id=1) is the admin | |||||
id: 1 | |||||
lower_name: user1 | |||||
name: user1 | |||||
email: user1@example.com | |||||
passwd: password | |||||
type: 0 # individual | |||||
salt: salt | |||||
is_admin: true | |||||
avatar: avatar1 | |||||
avatar_email: user2@example.com | |||||
num_repos: 0 | |||||
- | |||||
id: 2 | |||||
lower_name: user2 | |||||
name: user2 | |||||
email: user2@example.com | |||||
passwd: password | |||||
type: 0 # individual | |||||
salt: salt | |||||
is_admin: false | |||||
avatar: avatar2 | |||||
avatar_email: user2@example.com | |||||
num_repos: 2 |
SortType string | SortType string | ||||
} | } | ||||
// sortIssuesSession sort an issues-related session based on the provided | |||||
// sortType string | |||||
func sortIssuesSession(sess *xorm.Session, sortType string) { | |||||
switch sortType { | |||||
case "oldest": | |||||
sess.Asc("issue.created_unix") | |||||
case "recentupdate": | |||||
sess.Desc("issue.updated_unix") | |||||
case "leastupdate": | |||||
sess.Asc("issue.updated_unix") | |||||
case "mostcomment": | |||||
sess.Desc("issue.num_comments") | |||||
case "leastcomment": | |||||
sess.Asc("issue.num_comments") | |||||
case "priority": | |||||
sess.Desc("issue.priority") | |||||
default: | |||||
sess.Desc("issue.created_unix") | |||||
} | |||||
} | |||||
// Issues returns a list of issues by given conditions. | // Issues returns a list of issues by given conditions. | ||||
func Issues(opts *IssuesOptions) ([]*Issue, error) { | func Issues(opts *IssuesOptions) ([]*Issue, error) { | ||||
if opts.Page <= 0 { | if opts.Page <= 0 { | ||||
sess.And("issue.is_pull=?", opts.IsPull) | sess.And("issue.is_pull=?", opts.IsPull) | ||||
switch opts.SortType { | |||||
case "oldest": | |||||
sess.Asc("issue.created_unix") | |||||
case "recentupdate": | |||||
sess.Desc("issue.updated_unix") | |||||
case "leastupdate": | |||||
sess.Asc("issue.updated_unix") | |||||
case "mostcomment": | |||||
sess.Desc("issue.num_comments") | |||||
case "leastcomment": | |||||
sess.Asc("issue.num_comments") | |||||
case "priority": | |||||
sess.Desc("issue.priority") | |||||
default: | |||||
sess.Desc("issue.created_unix") | |||||
} | |||||
sortIssuesSession(sess, opts.SortType) | |||||
if len(opts.Labels) > 0 && opts.Labels != "0" { | if len(opts.Labels) > 0 && opts.Labels != "0" { | ||||
labelIDs, err := base.StringsToInt64s(strings.Split(opts.Labels, ",")) | labelIDs, err := base.StringsToInt64s(strings.Split(opts.Labels, ",")) |
api "code.gitea.io/sdk/gitea" | api "code.gitea.io/sdk/gitea" | ||||
"github.com/Unknwon/com" | "github.com/Unknwon/com" | ||||
"github.com/go-xorm/xorm" | "github.com/go-xorm/xorm" | ||||
"code.gitea.io/gitea/modules/base" | |||||
) | ) | ||||
var pullRequestQueue = sync.NewUniqueQueue(setting.Repository.PullRequestQueueLength) | var pullRequestQueue = sync.NewUniqueQueue(setting.Repository.PullRequestQueueLength) | ||||
MilestoneID int64 | MilestoneID int64 | ||||
} | } | ||||
func listPullRequestStatement(baseRepoID int64, opts *PullRequestsOptions) *xorm.Session { | |||||
func listPullRequestStatement(baseRepoID int64, opts *PullRequestsOptions) (*xorm.Session, error) { | |||||
sess := x.Where("pull_request.base_repo_id=?", baseRepoID) | sess := x.Where("pull_request.base_repo_id=?", baseRepoID) | ||||
sess.Join("INNER", "issue", "pull_request.issue_id = issue.id") | sess.Join("INNER", "issue", "pull_request.issue_id = issue.id") | ||||
sess.And("issue.is_closed=?", opts.State == "closed") | sess.And("issue.is_closed=?", opts.State == "closed") | ||||
} | } | ||||
return sess | |||||
sortIssuesSession(sess, opts.SortType) | |||||
if labelIDs, err := base.StringsToInt64s(opts.Labels); err != nil { | |||||
return nil, err | |||||
} else if len(labelIDs) > 0 { | |||||
sess.Join("INNER", "issue_label", "issue.id = issue_label.issue_id"). | |||||
In("issue_label.label_id", labelIDs) | |||||
} | |||||
if opts.MilestoneID > 0 { | |||||
sess.And("issue.milestone_id=?", opts.MilestoneID) | |||||
} | |||||
return sess, nil | |||||
} | } | ||||
// PullRequests returns all pull requests for a base Repo by the given conditions | // PullRequests returns all pull requests for a base Repo by the given conditions | ||||
opts.Page = 1 | opts.Page = 1 | ||||
} | } | ||||
countSession := listPullRequestStatement(baseRepoID, opts) | |||||
countSession, err := listPullRequestStatement(baseRepoID, opts) | |||||
if err != nil { | |||||
log.Error(4, "listPullRequestStatement", err) | |||||
return nil, 0, err | |||||
} | |||||
maxResults, err := countSession.Count(new(PullRequest)) | maxResults, err := countSession.Count(new(PullRequest)) | ||||
if err != nil { | if err != nil { | ||||
log.Error(4, "Count PRs", err) | log.Error(4, "Count PRs", err) | ||||
} | } | ||||
prs := make([]*PullRequest, 0, ItemsPerPage) | prs := make([]*PullRequest, 0, ItemsPerPage) | ||||
findSession := listPullRequestStatement(baseRepoID, opts) | |||||
findSession, err := listPullRequestStatement(baseRepoID, opts) | |||||
if err != nil { | |||||
log.Error(4, "listPullRequestStatement", err) | |||||
return nil, maxResults, err | |||||
} | |||||
findSession.Limit(ItemsPerPage, (opts.Page-1)*ItemsPerPage) | findSession.Limit(ItemsPerPage, (opts.Page-1)*ItemsPerPage) | ||||
return prs, maxResults, findSession.Find(&prs) | return prs, maxResults, findSession.Find(&prs) | ||||
} | } | ||||
if err != nil { | if err != nil { | ||||
return nil, err | return nil, err | ||||
} else if !has { | } else if !has { | ||||
return nil, ErrPullRequestNotExist{0, repoID, index, 0, "", ""} | |||||
return nil, ErrPullRequestNotExist{0, 0, 0, repoID, "", ""} | |||||
} | } | ||||
if err = pr.LoadAttributes(); err != nil { | if err = pr.LoadAttributes(); err != nil { |
// Copyright 2017 The Gitea Authors. All rights reserved. | |||||
// Use of this source code is governed by a MIT-style | |||||
// license that can be found in the LICENSE file. | |||||
package models | |||||
import ( | |||||
"testing" | |||||
"time" | |||||
"github.com/stretchr/testify/assert" | |||||
) | |||||
// getPullRequest load a fixture pull request from the test database | |||||
func loadFixturePullRequest(t *testing.T, id int64) *PullRequest { | |||||
sess := x.NewSession() | |||||
defer sess.Close() | |||||
pr := &PullRequest{ID: id} | |||||
has, err := sess.Get(pr) | |||||
assert.NoError(t, err) | |||||
assert.True(t, has) | |||||
return pr | |||||
} | |||||
func TestPullRequest_LoadAttributes(t *testing.T) { | |||||
assert.NoError(t, PrepareTestDatabase()) | |||||
pr := loadFixturePullRequest(t, 1) | |||||
assert.NoError(t, pr.LoadAttributes()) | |||||
assert.NotNil(t, pr.Merger) | |||||
assert.Equal(t, pr.MergerID, pr.Merger.ID) | |||||
} | |||||
func TestPullRequest_LoadIssue(t *testing.T) { | |||||
assert.NoError(t, PrepareTestDatabase()) | |||||
pr := loadFixturePullRequest(t, 1) | |||||
assert.NoError(t, pr.LoadIssue()) | |||||
assert.NotNil(t, pr.Issue) | |||||
assert.Equal(t, int64(2), pr.Issue.ID) | |||||
} | |||||
// TODO TestPullRequest_APIFormat | |||||
func TestPullRequest_GetBaseRepo(t *testing.T) { | |||||
assert.NoError(t, PrepareTestDatabase()) | |||||
pr := loadFixturePullRequest(t, 1) | |||||
assert.NoError(t, pr.GetBaseRepo()) | |||||
assert.NotNil(t, pr.BaseRepo) | |||||
assert.Equal(t, pr.BaseRepoID, pr.BaseRepo.ID) | |||||
} | |||||
func TestPullRequest_GetHeadRepo(t *testing.T) { | |||||
assert.NoError(t, PrepareTestDatabase()) | |||||
pr := loadFixturePullRequest(t, 1) | |||||
assert.NoError(t, pr.GetHeadRepo()) | |||||
assert.NotNil(t, pr.HeadRepo) | |||||
assert.Equal(t, pr.HeadRepoID, pr.HeadRepo.ID) | |||||
} | |||||
// TODO TestMerge | |||||
// TODO TestNewPullRequest | |||||
func TestPullRequestsNewest(t *testing.T) { | |||||
assert.NoError(t, PrepareTestDatabase()) | |||||
prs, count, err := PullRequests(1, &PullRequestsOptions{ | |||||
Page: 1, | |||||
State: "open", | |||||
SortType: "newest", | |||||
Labels: []string{}, | |||||
}) | |||||
assert.NoError(t, err) | |||||
assert.Equal(t, int64(2), count) | |||||
assert.Len(t, prs, 2) | |||||
assert.Equal(t, int64(2), prs[0].ID) | |||||
assert.Equal(t, int64(1), prs[1].ID) | |||||
} | |||||
func TestPullRequestsOldest(t *testing.T) { | |||||
assert.NoError(t, PrepareTestDatabase()) | |||||
prs, count, err := PullRequests(1, &PullRequestsOptions{ | |||||
Page: 1, | |||||
State: "open", | |||||
SortType: "oldest", | |||||
Labels: []string{}, | |||||
}) | |||||
assert.NoError(t, err) | |||||
assert.Equal(t, int64(2), count) | |||||
assert.Len(t, prs, 2) | |||||
assert.Equal(t, int64(1), prs[0].ID) | |||||
assert.Equal(t, int64(2), prs[1].ID) | |||||
} | |||||
func TestGetUnmergedPullRequest(t *testing.T) { | |||||
assert.NoError(t, PrepareTestDatabase()) | |||||
pr, err := GetUnmergedPullRequest(1, 1, "branch2", "master") | |||||
assert.NoError(t, err) | |||||
assert.Equal(t, int64(2), pr.ID) | |||||
pr, err = GetUnmergedPullRequest(1, 9223372036854775807, "branch1", "master") | |||||
assert.Error(t, err) | |||||
assert.True(t, IsErrPullRequestNotExist(err)) | |||||
} | |||||
func TestGetUnmergedPullRequestsByHeadInfo(t *testing.T) { | |||||
assert.NoError(t, PrepareTestDatabase()) | |||||
prs, err := GetUnmergedPullRequestsByHeadInfo(1, "branch2") | |||||
assert.NoError(t, err) | |||||
assert.Len(t, prs, 1) | |||||
for _, pr := range prs { | |||||
assert.Equal(t, int64(1), pr.HeadRepoID) | |||||
assert.Equal(t, "branch2", pr.HeadBranch) | |||||
} | |||||
} | |||||
func TestGetUnmergedPullRequestsByBaseInfo(t *testing.T) { | |||||
assert.NoError(t, PrepareTestDatabase()) | |||||
prs, err := GetUnmergedPullRequestsByBaseInfo(1, "master") | |||||
assert.NoError(t, err) | |||||
assert.Len(t, prs, 1) | |||||
pr := prs[0] | |||||
assert.Equal(t, int64(2), pr.ID) | |||||
assert.Equal(t, int64(1), pr.BaseRepoID) | |||||
assert.Equal(t, "master", pr.BaseBranch) | |||||
} | |||||
func TestGetPullRequestByIndex(t *testing.T) { | |||||
assert.NoError(t, PrepareTestDatabase()) | |||||
pr, err := GetPullRequestByIndex(1, 2) | |||||
assert.NoError(t, err) | |||||
assert.Equal(t, int64(1), pr.BaseRepoID) | |||||
assert.Equal(t, int64(2), pr.Index) | |||||
pr, err = GetPullRequestByIndex(9223372036854775807, 9223372036854775807) | |||||
assert.Error(t, err) | |||||
assert.True(t, IsErrPullRequestNotExist(err)) | |||||
} | |||||
func TestGetPullRequestByID(t *testing.T) { | |||||
assert.NoError(t, PrepareTestDatabase()) | |||||
pr, err := GetPullRequestByID(1) | |||||
assert.NoError(t, err) | |||||
assert.Equal(t, int64(1), pr.ID) | |||||
assert.Equal(t, int64(2), pr.IssueID) | |||||
_, err = GetPullRequestByID(9223372036854775807) | |||||
assert.Error(t, err) | |||||
assert.True(t, IsErrPullRequestNotExist(err)) | |||||
} | |||||
func TestGetPullRequestByIssueID(t *testing.T) { | |||||
assert.NoError(t, PrepareTestDatabase()) | |||||
pr, err := GetPullRequestByIssueID(2) | |||||
assert.NoError(t, err) | |||||
assert.Equal(t, int64(2), pr.IssueID) | |||||
pr, err = GetPullRequestByIssueID(9223372036854775807) | |||||
assert.Error(t, err) | |||||
assert.True(t, IsErrPullRequestNotExist(err)) | |||||
} | |||||
func TestPullRequest_Update(t *testing.T) { | |||||
assert.NoError(t, PrepareTestDatabase()) | |||||
pr := &PullRequest{ | |||||
ID: 1, | |||||
IssueID: 100, | |||||
BaseBranch: "baseBranch", | |||||
HeadBranch: "headBranch", | |||||
} | |||||
pr.Update() | |||||
sess := x.NewSession() | |||||
defer sess.Close() | |||||
pr = &PullRequest{ID: 1} | |||||
has, err := sess.Get(pr) | |||||
assert.NoError(t, err) | |||||
assert.True(t, has) | |||||
assert.Equal(t, int64(100), pr.IssueID) | |||||
assert.Equal(t, "baseBranch", pr.BaseBranch) | |||||
assert.Equal(t, "headBranch", pr.HeadBranch) | |||||
} | |||||
func TestPullRequest_UpdateCols(t *testing.T) { | |||||
assert.NoError(t, PrepareTestDatabase()) | |||||
pr := &PullRequest{ | |||||
ID: 1, | |||||
IssueID: int64(100), | |||||
BaseBranch: "baseBranch", | |||||
HeadBranch: "headBranch", | |||||
} | |||||
pr.UpdateCols("issue_id", "head_branch") | |||||
sess := x.NewSession() | |||||
defer sess.Close() | |||||
pr = &PullRequest{ID: 1} | |||||
has, err := sess.Get(pr) | |||||
assert.NoError(t, err) | |||||
assert.True(t, has) | |||||
assert.Equal(t, int64(100), pr.IssueID) | |||||
assert.Equal(t, "master", pr.BaseBranch) | |||||
assert.Equal(t, "headBranch", pr.HeadBranch) | |||||
} | |||||
// TODO TestPullRequest_UpdatePatch | |||||
// TODO TestPullRequest_PushToBaseRepo | |||||
func TestPullRequest_AddToTaskQueue(t *testing.T) { | |||||
assert.NoError(t, PrepareTestDatabase()) | |||||
pr := loadFixturePullRequest(t, 1) | |||||
pr.AddToTaskQueue() | |||||
// briefly sleep so that background threads have time to run | |||||
time.Sleep(time.Millisecond) | |||||
assert.True(t, pullRequestQueue.Exist(pr.ID)) | |||||
pr = loadFixturePullRequest(t, 1) | |||||
assert.Equal(t, PullRequestStatusChecking, pr.Status) | |||||
} | |||||
func TestPullRequestList_LoadAttributes(t *testing.T) { | |||||
assert.NoError(t, PrepareTestDatabase()) | |||||
prs := []*PullRequest{ | |||||
loadFixturePullRequest(t, 1), | |||||
loadFixturePullRequest(t, 2), | |||||
} | |||||
assert.NoError(t, PullRequestList(prs).LoadAttributes()) | |||||
for _, pr := range prs { | |||||
assert.NotNil(t, pr.Issue) | |||||
assert.Equal(t, pr.IssueID, pr.Issue.ID) | |||||
} | |||||
} | |||||
// TODO TestAddTestPullRequestTask | |||||
func TestChangeUsernameInPullRequests(t *testing.T) { | |||||
assert.NoError(t, PrepareTestDatabase()) | |||||
const newUsername = "newusername" | |||||
assert.NoError(t, ChangeUsernameInPullRequests("user1", newUsername)) | |||||
sess := x.NewSession() | |||||
defer sess.Close() | |||||
prs := make([]*PullRequest, 0, 10) | |||||
assert.NoError(t, sess.Where("head_user_name = ?", newUsername).Find(&prs)) | |||||
assert.Len(t, prs, 2) | |||||
for _, pr := range prs { | |||||
assert.Equal(t, newUsername, pr.HeadUserName) | |||||
} | |||||
} |
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/modules/sync" | "code.gitea.io/gitea/modules/sync" | ||||
api "code.gitea.io/sdk/gitea" | api "code.gitea.io/sdk/gitea" | ||||
"github.com/Unknwon/cae/zip" | "github.com/Unknwon/cae/zip" | ||||
"github.com/Unknwon/com" | "github.com/Unknwon/com" | ||||
"github.com/go-xorm/xorm" | "github.com/go-xorm/xorm" |