Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API add/generalize pagination #9452

Merged
merged 66 commits into from
Jan 24, 2020
Merged
Show file tree
Hide file tree
Changes from 65 commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
b0e0c70
paginate results
hilariocoelho Dec 21, 2019
4f644f1
fixed deadlock
hilariocoelho Dec 21, 2019
f347568
prevented breaking change
hilariocoelho Dec 21, 2019
a982fb7
updated swagger
hilariocoelho Dec 21, 2019
dbc61ce
go fmt
hilariocoelho Dec 21, 2019
a746bdc
fixed find topic
hilariocoelho Dec 21, 2019
3153ffe
go mod tidy
hilariocoelho Dec 21, 2019
3311183
go mod vendor with go1.13.5
hilariocoelho Dec 21, 2019
e0e7d39
fixed repo find topics
hilariocoelho Dec 21, 2019
b6ed97d
fixed unit test
hilariocoelho Dec 21, 2019
d0f7898
added Limit method to Engine struct; use engine variable when provide…
hilariocoelho Dec 21, 2019
3d7fd5f
use ItemsPerPage for default pagesize; fix GetWatchers, getOrgUsersBy…
hilariocoelho Dec 22, 2019
0491de0
set Page value on Home route
hilariocoelho Dec 22, 2019
1d016ad
improved memory allocations
hilariocoelho Dec 22, 2019
ec2c3e4
fixed response headers
hilariocoelho Dec 22, 2019
ec999c1
resolved conflicts
hilariocoelho Jan 10, 2020
d4b717b
removed logfiles
hilariocoelho Jan 10, 2020
34f34c7
fixed import order
hilariocoelho Jan 10, 2020
3c9acb6
import order
hilariocoelho Jan 10, 2020
7294c5e
improved swagger
hilariocoelho Jan 10, 2020
85078bc
added function to get models.ListOptions from context
hilariocoelho Jan 10, 2020
e366eba
removed pagesize diff on unit test
hilariocoelho Jan 10, 2020
82e8b45
fixed imports
hilariocoelho Jan 10, 2020
f22b08a
removed unnecessary struct field
hilariocoelho Jan 10, 2020
13e830e
fixed go fmt
hilariocoelho Jan 10, 2020
70652e7
scoped PR
hilariocoelho Jan 10, 2020
6f66eba
code improvements
hilariocoelho Jan 10, 2020
c3b134e
code improvements
hilariocoelho Jan 10, 2020
6ee21c2
go mod tidy
hilariocoelho Jan 10, 2020
df3c3d5
fixed import order
hilariocoelho Jan 10, 2020
4d48183
fixed commit statuses session
hilariocoelho Jan 10, 2020
1cb649b
fixed files headers
hilariocoelho Jan 10, 2020
bd25b5a
Merge branch 'master' of https://github.com/go-gitea/gitea into list_…
hilariocoelho Jan 10, 2020
dcac4a7
fixed headers; added pagination for notifications
hilariocoelho Jan 10, 2020
e44d377
resolved conflicts
hilariocoelho Jan 12, 2020
f25f69c
go mod tidy
hilariocoelho Jan 12, 2020
44696d4
go fmt
hilariocoelho Jan 12, 2020
96694ca
Merge branch 'master' into list_pagination
techknowlogick Jan 12, 2020
1e0d62f
Merge branch 'master' of https://github.com/go-gitea/gitea into list_…
hilariocoelho Jan 12, 2020
871b6ac
removed Private from user search options; added setting.UI.IssuePagin…
hilariocoelho Jan 13, 2020
ed5190c
Merge branch 'master' of https://github.com/go-gitea/gitea into list_…
hilariocoelho Jan 13, 2020
e54bb68
Merge branch 'list_pagination' of https://github.com/SpaWn2KiLl/gitea…
hilariocoelho Jan 13, 2020
76ad2dc
Apply suggestions from code review
spawn2kill Jan 13, 2020
302644b
Merge branch 'master' of https://github.com/go-gitea/gitea into list_…
hilariocoelho Jan 13, 2020
0c1f71f
fixed build error
hilariocoelho Jan 13, 2020
083e202
resolved conflicts
hilariocoelho Jan 13, 2020
b6c876d
CI.restart()
hilariocoelho Jan 13, 2020
194ed26
Merge branch 'master' of https://github.com/go-gitea/gitea into list_…
hilariocoelho Jan 13, 2020
819200f
fixed merge conflicts resolve
hilariocoelho Jan 13, 2020
5ab7e99
Merge branch 'master' into list_pagination
spawn2kill Jan 14, 2020
18e87d6
Merge branch 'master' of https://github.com/go-gitea/gitea into list_…
hilariocoelho Jan 15, 2020
604c5bf
Merge branch 'master' of https://github.com/go-gitea/gitea into list_…
hilariocoelho Jan 15, 2020
e0281c3
Merge branch 'list_pagination' of https://github.com/SpaWn2KiLl/gitea…
hilariocoelho Jan 15, 2020
b673afa
fixed conflicts resolve
hilariocoelho Jan 15, 2020
e3842c7
Merge branch 'master' of https://github.com/go-gitea/gitea into list_…
hilariocoelho Jan 16, 2020
64b0caf
Merge branch 'master' of https://github.com/go-gitea/gitea into list_…
hilariocoelho Jan 22, 2020
b296662
improved FindTrackedTimesOptions.ToOptions() method
hilariocoelho Jan 22, 2020
0b821f0
added backwards compatibility on ListReleases request; fixed issue tr…
hilariocoelho Jan 22, 2020
d0f00b9
fixed build error; fixed swagger template
hilariocoelho Jan 22, 2020
9a60191
fixed swagger template
hilariocoelho Jan 22, 2020
40324a9
fixed ListReleases backwards compatibility
hilariocoelho Jan 23, 2020
46c912f
Merge branch 'master' into list_pagination
spawn2kill Jan 24, 2020
b599ec0
added page to user search route
hilariocoelho Jan 24, 2020
1b44aad
Merge branch 'master' into list_pagination
techknowlogick Jan 24, 2020
465c955
Merge branch 'list_pagination' of https://github.com/SpaWn2KiLl/gitea…
hilariocoelho Jan 24, 2020
f7a5c9f
Merge branch 'master' into list_pagination
zeripath Jan 24, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions cmd/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -351,9 +351,11 @@ func runRepoSyncReleases(c *cli.Context) error {
log.Trace("Synchronizing repository releases (this may take a while)")
for page := 1; ; page++ {
repos, count, err := models.SearchRepositoryByName(&models.SearchRepoOptions{
Page: page,
PageSize: models.RepositoryListDefaultPageSize,
Private: true,
ListOptions: models.ListOptions{
PageSize: models.RepositoryListDefaultPageSize,
Page: page,
},
Private: true,
})
if err != nil {
return fmt.Errorf("SearchRepositoryByName: %v", err)
Expand Down
2 changes: 1 addition & 1 deletion models/access.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ func (repo *Repository) refreshAccesses(e Engine, accessMap map[int64]*userAcces

// refreshCollaboratorAccesses retrieves repository collaborations with their access modes.
func (repo *Repository) refreshCollaboratorAccesses(e Engine, accessMap map[int64]*userAccess) error {
collaborators, err := repo.getCollaborators(e)
collaborators, err := repo.getCollaborators(e, ListOptions{})
if err != nil {
return fmt.Errorf("getCollaborations: %v", err)
}
Expand Down
10 changes: 7 additions & 3 deletions models/commit_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func CalcCommitStatus(statuses []*CommitStatus) *CommitStatus {

// CommitStatusOptions holds the options for query commit statuses
type CommitStatusOptions struct {
Page int
ListOptions
State string
SortType string
}
Expand All @@ -114,18 +114,22 @@ func GetCommitStatuses(repo *Repository, sha string, opts *CommitStatusOptions)
if opts.Page <= 0 {
opts.Page = 1
}
if opts.PageSize <= 0 {
lafriks marked this conversation as resolved.
Show resolved Hide resolved
opts.Page = ItemsPerPage
}

countSession := listCommitStatusesStatement(repo, sha, opts)
countSession = opts.setSessionPagination(countSession)
maxResults, err := countSession.Count(new(CommitStatus))
if err != nil {
log.Error("Count PRs: %v", err)
return nil, maxResults, err
}

statuses := make([]*CommitStatus, 0, ItemsPerPage)
statuses := make([]*CommitStatus, 0, opts.PageSize)
findSession := listCommitStatusesStatement(repo, sha, opts)
findSession = opts.setSessionPagination(findSession)
sortCommitStatusesSession(findSession, opts.SortType)
findSession.Limit(ItemsPerPage, (opts.Page-1)*ItemsPerPage)
return statuses, maxResults, findSession.Find(&statuses)
}

Expand Down
13 changes: 9 additions & 4 deletions models/gpg_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,14 @@ func (key *GPGKey) AfterLoad(session *xorm.Session) {
}

// ListGPGKeys returns a list of public keys belongs to given user.
func ListGPGKeys(uid int64) ([]*GPGKey, error) {
keys := make([]*GPGKey, 0, 5)
return keys, x.Where("owner_id=? AND primary_key_id=''", uid).Find(&keys)
func ListGPGKeys(uid int64, listOptions ListOptions) ([]*GPGKey, error) {
sess := x.Where("owner_id=? AND primary_key_id=''", uid)
if listOptions.Page != 0 {
sess = listOptions.setSessionPagination(sess)
}

keys := make([]*GPGKey, 0, 2)
return keys, sess.Find(&keys)
}

// GetGPGKeyByID returns public key by given ID.
Expand Down Expand Up @@ -628,7 +633,7 @@ func ParseCommitWithSignature(c *git.Commit) *CommitVerification {

// Now try to associate the signature with the committer, if present
if committer.ID != 0 {
keys, err := ListGPGKeys(committer.ID)
keys, err := ListGPGKeys(committer.ID, ListOptions{})
if err != nil { //Skipping failed to get gpg keys of user
log.Error("ListGPGKeys: %v", err)
return &CommitVerification{
Expand Down
3 changes: 1 addition & 2 deletions models/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -1103,13 +1103,12 @@ func GetIssuesByIDs(issueIDs []int64) ([]*Issue, error) {

// IssuesOptions represents options of an issue.
type IssuesOptions struct {
ListOptions
RepoIDs []int64 // include all repos if empty
AssigneeID int64
PosterID int64
MentionedID int64
MilestoneID int64
Page int
PageSize int
IsClosed util.OptionalBool
IsPull util.OptionalBool
LabelIDs []int64
Expand Down
6 changes: 6 additions & 0 deletions models/issue_comment.go
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,7 @@ func GetCommentByID(id int64) (*Comment, error) {

// FindCommentsOptions describes the conditions to Find comments
type FindCommentsOptions struct {
ListOptions
RepoID int64
IssueID int64
ReviewID int64
Expand Down Expand Up @@ -814,6 +815,11 @@ func findComments(e Engine, opts FindCommentsOptions) ([]*Comment, error) {
if opts.RepoID > 0 {
sess.Join("INNER", "issue", "issue.id = comment.issue_id")
}

if opts.Page != 0 {
sess = opts.setSessionPagination(sess)
}

return comments, sess.
Asc("comment.created_unix").
Asc("comment.id").
Expand Down
11 changes: 8 additions & 3 deletions models/issue_label.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright 2016 The Gogs Authors. All rights reserved.
// Copyright 2020 The Gitea Authors.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

Expand Down Expand Up @@ -298,7 +299,7 @@ func GetLabelsInRepoByIDs(repoID int64, labelIDs []int64) ([]*Label, error) {
Find(&labels)
}

func getLabelsByRepoID(e Engine, repoID int64, sortType string) ([]*Label, error) {
func getLabelsByRepoID(e Engine, repoID int64, sortType string, listOptions ListOptions) ([]*Label, error) {
labels := make([]*Label, 0, 10)
sess := e.Where("repo_id = ?", repoID)

Expand All @@ -313,12 +314,16 @@ func getLabelsByRepoID(e Engine, repoID int64, sortType string) ([]*Label, error
sess.Asc("name")
}

if listOptions.Page != 0 {
sess = listOptions.setSessionPagination(sess)
}

return labels, sess.Find(&labels)
}

// GetLabelsByRepoID returns all labels that belong to given repository by ID.
func GetLabelsByRepoID(repoID int64, sortType string) ([]*Label, error) {
return getLabelsByRepoID(x, repoID, sortType)
func GetLabelsByRepoID(repoID int64, sortType string, listOptions ListOptions) ([]*Label, error) {
return getLabelsByRepoID(x, repoID, sortType, listOptions)
}

func getLabelsByIssueID(e Engine, issueID int64) ([]*Label, error) {
Expand Down
2 changes: 1 addition & 1 deletion models/issue_label_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ func TestGetLabelsInRepoByIDs(t *testing.T) {
func TestGetLabelsByRepoID(t *testing.T) {
assert.NoError(t, PrepareTestDatabase())
testSuccess := func(repoID int64, sortType string, expectedIssueIDs []int64) {
labels, err := GetLabelsByRepoID(repoID, sortType)
labels, err := GetLabelsByRepoID(repoID, sortType, ListOptions{})
assert.NoError(t, err)
assert.Len(t, labels, len(expectedIssueIDs))
for i, label := range labels {
Expand Down
8 changes: 6 additions & 2 deletions models/issue_milestone.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ func (milestones MilestoneList) getMilestoneIDs() []int64 {
}

// GetMilestonesByRepoID returns all opened milestones of a repository.
func GetMilestonesByRepoID(repoID int64, state api.StateType) (MilestoneList, error) {
func GetMilestonesByRepoID(repoID int64, state api.StateType, listOptions ListOptions) (MilestoneList, error) {
sess := x.Where("repo_id = ?", repoID)

switch state {
Expand All @@ -238,7 +238,11 @@ func GetMilestonesByRepoID(repoID int64, state api.StateType) (MilestoneList, er
sess = sess.And("is_closed = ?", false)
}

miles := make([]*Milestone, 0, 10)
if listOptions.Page != 0 {
sess = listOptions.setSessionPagination(sess)
}

miles := make([]*Milestone, 0, listOptions.PageSize)
return miles, sess.Asc("deadline_unix").Asc("id").Find(&miles)
}

Expand Down
4 changes: 2 additions & 2 deletions models/issue_milestone_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func TestGetMilestonesByRepoID(t *testing.T) {
assert.NoError(t, PrepareTestDatabase())
test := func(repoID int64, state api.StateType) {
repo := AssertExistsAndLoadBean(t, &Repository{ID: repoID}).(*Repository)
milestones, err := GetMilestonesByRepoID(repo.ID, state)
milestones, err := GetMilestonesByRepoID(repo.ID, state, ListOptions{})
assert.NoError(t, err)

var n int
Expand Down Expand Up @@ -105,7 +105,7 @@ func TestGetMilestonesByRepoID(t *testing.T) {
test(3, api.StateClosed)
test(3, api.StateAll)

milestones, err := GetMilestonesByRepoID(NonexistentID, api.StateOpen)
milestones, err := GetMilestonesByRepoID(NonexistentID, api.StateOpen, ListOptions{})
assert.NoError(t, err)
assert.Len(t, milestones, 0)
}
Expand Down
25 changes: 17 additions & 8 deletions models/issue_reaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type Reaction struct {

// FindReactionsOptions describes the conditions to Find reactions
type FindReactionsOptions struct {
ListOptions
IssueID int64
CommentID int64
UserID int64
Expand Down Expand Up @@ -71,20 +72,28 @@ func FindCommentReactions(comment *Comment) (ReactionList, error) {
}

// FindIssueReactions returns a ReactionList of all reactions from an issue
func FindIssueReactions(issue *Issue) (ReactionList, error) {
func FindIssueReactions(issue *Issue, listOptions ListOptions) (ReactionList, error) {
return findReactions(x, FindReactionsOptions{
IssueID: issue.ID,
CommentID: -1,
ListOptions: listOptions,
IssueID: issue.ID,
CommentID: -1,
})
}

func findReactions(e Engine, opts FindReactionsOptions) ([]*Reaction, error) {
lafriks marked this conversation as resolved.
Show resolved Hide resolved
reactions := make([]*Reaction, 0, 10)
sess := e.Where(opts.toConds())
return reactions, sess.
e = e.
Where(opts.toConds()).
In("reaction.`type`", setting.UI.Reactions).
Asc("reaction.issue_id", "reaction.comment_id", "reaction.created_unix", "reaction.id").
Find(&reactions)
Asc("reaction.issue_id", "reaction.comment_id", "reaction.created_unix", "reaction.id")
if opts.Page != 0 {
e = opts.setEnginePagination(e)

reactions := make([]*Reaction, 0, opts.PageSize)
return reactions, e.Find(&reactions)
}

reactions := make([]*Reaction, 0, 10)
return reactions, e.Find(&reactions)
}

func createReaction(e *xorm.Session, opts *ReactionOptions) (*Reaction, error) {
Expand Down
11 changes: 8 additions & 3 deletions models/issue_stopwatch.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,14 @@ func getStopwatch(e Engine, userID, issueID int64) (sw *Stopwatch, exists bool,
}

// GetUserStopwatches return list of all stopwatches of a user
func GetUserStopwatches(userID int64) (sws *Stopwatches, err error) {
sws = new(Stopwatches)
err = x.Where("stopwatch.user_id = ?", userID).Find(sws)
func GetUserStopwatches(userID int64, listOptions ListOptions) (*Stopwatches, error) {
sws := new(Stopwatches)
sess := x.Where("stopwatch.user_id = ?", userID)
if listOptions.Page != 0 {
sess = listOptions.setSessionPagination(sess)
}

err := sess.Find(sws)
if err != nil {
return nil, err
}
Expand Down
18 changes: 12 additions & 6 deletions models/issue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,24 +139,30 @@ func TestIssues(t *testing.T) {
IssuesOptions{
RepoIDs: []int64{1, 3},
SortType: "oldest",
Page: 1,
PageSize: 4,
ListOptions: ListOptions{
Page: 1,
PageSize: 4,
},
},
[]int64{1, 2, 3, 5},
},
{
IssuesOptions{
LabelIDs: []int64{1},
Page: 1,
PageSize: 4,
ListOptions: ListOptions{
Page: 1,
PageSize: 4,
},
},
[]int64{2, 1},
},
{
IssuesOptions{
LabelIDs: []int64{1, 2},
Page: 1,
PageSize: 4,
ListOptions: ListOptions{
Page: 1,
PageSize: 4,
},
},
[]int64{}, // issues with **both** label 1 and 2, none of these issues matches, TODO: add more tests
},
Expand Down
16 changes: 12 additions & 4 deletions models/issue_tracked_time.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"code.gitea.io/gitea/modules/setting"

"xorm.io/builder"
"xorm.io/xorm"
)

// TrackedTime represents a time that was spent for a specific issue.
Expand Down Expand Up @@ -71,6 +70,7 @@ func (tl TrackedTimeList) LoadAttributes() (err error) {

// FindTrackedTimesOptions represent the filters for tracked times. If an ID is 0 it will be ignored.
type FindTrackedTimesOptions struct {
ListOptions
IssueID int64
UserID int64
RepositoryID int64
Expand Down Expand Up @@ -104,11 +104,19 @@ func (opts *FindTrackedTimesOptions) ToCond() builder.Cond {
}

// ToSession will convert the given options to a xorm Session by using the conditions from ToCond and joining with issue table if required
func (opts *FindTrackedTimesOptions) ToSession(e Engine) *xorm.Session {
func (opts *FindTrackedTimesOptions) ToSession(e Engine) Engine {
sess := e
if opts.RepositoryID > 0 || opts.MilestoneID > 0 {
return e.Join("INNER", "issue", "issue.id = tracked_time.issue_id").Where(opts.ToCond())
sess = e.Join("INNER", "issue", "issue.id = tracked_time.issue_id")
}
return e.Where(opts.ToCond())

sess = sess.Where(opts.ToCond())

if opts.Page != 0 {
sess = opts.setEnginePagination(sess)
}

return sess
}

func getTrackedTimes(e Engine, options FindTrackedTimesOptions) (trackedTimes TrackedTimeList, err error) {
Expand Down
16 changes: 10 additions & 6 deletions models/issue_watch.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,18 +77,22 @@ func GetIssueWatchersIDs(issueID int64) ([]int64, error) {
}

// GetIssueWatchers returns watchers/unwatchers of a given issue
func GetIssueWatchers(issueID int64) (IssueWatchList, error) {
return getIssueWatchers(x, issueID)
func GetIssueWatchers(issueID int64, listOptions ListOptions) (IssueWatchList, error) {
return getIssueWatchers(x, issueID, listOptions)
}

func getIssueWatchers(e Engine, issueID int64) (watches IssueWatchList, err error) {
err = e.
func getIssueWatchers(e Engine, issueID int64, listOptions ListOptions) (watches IssueWatchList, err error) {
sess := e.
Where("`issue_watch`.issue_id = ?", issueID).
And("`issue_watch`.is_watching = ?", true).
And("`user`.is_active = ?", true).
And("`user`.prohibit_login = ?", false).
Join("INNER", "`user`", "`user`.id = `issue_watch`.user_id").
Find(&watches)
Join("INNER", "`user`", "`user`.id = `issue_watch`.user_id")

if listOptions.Page == 0 {
sess = listOptions.setSessionPagination(sess)
}
err = sess.Find(&watches)
return
}

Expand Down
8 changes: 4 additions & 4 deletions models/issue_watch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,22 +42,22 @@ func TestGetIssueWatch(t *testing.T) {
func TestGetIssueWatchers(t *testing.T) {
assert.NoError(t, PrepareTestDatabase())

iws, err := GetIssueWatchers(1)
iws, err := GetIssueWatchers(1, ListOptions{})
assert.NoError(t, err)
// Watcher is inactive, thus 0
assert.Len(t, iws, 0)

iws, err = GetIssueWatchers(2)
iws, err = GetIssueWatchers(2, ListOptions{})
assert.NoError(t, err)
// Watcher is explicit not watching
assert.Len(t, iws, 0)

iws, err = GetIssueWatchers(5)
iws, err = GetIssueWatchers(5, ListOptions{})
assert.NoError(t, err)
// Issue has no Watchers
assert.Len(t, iws, 0)

iws, err = GetIssueWatchers(7)
iws, err = GetIssueWatchers(7, ListOptions{})
assert.NoError(t, err)
// Issue has one watcher
assert.Len(t, iws, 1)
Expand Down
Loading