Skip to content

Commit 1f01f53

Browse files
SpaWn2KiLltechknowlogick6543zeripath
committed
API add/generalize pagination (#9452)
* paginate results * fixed deadlock * prevented breaking change * updated swagger * go fmt * fixed find topic * go mod tidy * go mod vendor with go1.13.5 * fixed repo find topics * fixed unit test * added Limit method to Engine struct; use engine variable when provided; fixed gitignore * use ItemsPerPage for default pagesize; fix GetWatchers, getOrgUsersByOrgID and GetStargazers; fix GetAllCommits headers; reverted some changed behaviors * set Page value on Home route * improved memory allocations * fixed response headers * removed logfiles * fixed import order * import order * improved swagger * added function to get models.ListOptions from context * removed pagesize diff on unit test * fixed imports * removed unnecessary struct field * fixed go fmt * scoped PR * code improvements * code improvements * go mod tidy * fixed import order * fixed commit statuses session * fixed files headers * fixed headers; added pagination for notifications * go mod tidy * go fmt * removed Private from user search options; added setting.UI.IssuePagingNum as default valeu on repo's issues list * Apply suggestions from code review Co-Authored-By: 6543 <[email protected]> Co-Authored-By: zeripath <[email protected]> * fixed build error * CI.restart() * fixed merge conflicts resolve * fixed conflicts resolve * improved FindTrackedTimesOptions.ToOptions() method * added backwards compatibility on ListReleases request; fixed issue tracked time ToSession * fixed build error; fixed swagger template * fixed swagger template * fixed ListReleases backwards compatibility * added page to user search route Co-authored-by: techknowlogick <[email protected]> Co-authored-by: 6543 <[email protected]> Co-authored-by: zeripath <[email protected]>
1 parent 333401e commit 1f01f53

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

113 files changed

+1890
-569
lines changed

cmd/admin.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -351,9 +351,11 @@ func runRepoSyncReleases(c *cli.Context) error {
351351
log.Trace("Synchronizing repository releases (this may take a while)")
352352
for page := 1; ; page++ {
353353
repos, count, err := models.SearchRepositoryByName(&models.SearchRepoOptions{
354-
Page: page,
355-
PageSize: models.RepositoryListDefaultPageSize,
356-
Private: true,
354+
ListOptions: models.ListOptions{
355+
PageSize: models.RepositoryListDefaultPageSize,
356+
Page: page,
357+
},
358+
Private: true,
357359
})
358360
if err != nil {
359361
return fmt.Errorf("SearchRepositoryByName: %v", err)

models/access.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ func (repo *Repository) refreshAccesses(e Engine, accessMap map[int64]*userAcces
215215

216216
// refreshCollaboratorAccesses retrieves repository collaborations with their access modes.
217217
func (repo *Repository) refreshCollaboratorAccesses(e Engine, accessMap map[int64]*userAccess) error {
218-
collaborators, err := repo.getCollaborators(e)
218+
collaborators, err := repo.getCollaborators(e, ListOptions{})
219219
if err != nil {
220220
return fmt.Errorf("getCollaborations: %v", err)
221221
}

models/commit_status.go

+7-3
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ func CalcCommitStatus(statuses []*CommitStatus) *CommitStatus {
104104

105105
// CommitStatusOptions holds the options for query commit statuses
106106
type CommitStatusOptions struct {
107-
Page int
107+
ListOptions
108108
State string
109109
SortType string
110110
}
@@ -114,18 +114,22 @@ func GetCommitStatuses(repo *Repository, sha string, opts *CommitStatusOptions)
114114
if opts.Page <= 0 {
115115
opts.Page = 1
116116
}
117+
if opts.PageSize <= 0 {
118+
opts.Page = ItemsPerPage
119+
}
117120

118121
countSession := listCommitStatusesStatement(repo, sha, opts)
122+
countSession = opts.setSessionPagination(countSession)
119123
maxResults, err := countSession.Count(new(CommitStatus))
120124
if err != nil {
121125
log.Error("Count PRs: %v", err)
122126
return nil, maxResults, err
123127
}
124128

125-
statuses := make([]*CommitStatus, 0, ItemsPerPage)
129+
statuses := make([]*CommitStatus, 0, opts.PageSize)
126130
findSession := listCommitStatusesStatement(repo, sha, opts)
131+
findSession = opts.setSessionPagination(findSession)
127132
sortCommitStatusesSession(findSession, opts.SortType)
128-
findSession.Limit(ItemsPerPage, (opts.Page-1)*ItemsPerPage)
129133
return statuses, maxResults, findSession.Find(&statuses)
130134
}
131135

models/gpg_key.go

+9-4
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,14 @@ func (key *GPGKey) AfterLoad(session *xorm.Session) {
6464
}
6565

6666
// ListGPGKeys returns a list of public keys belongs to given user.
67-
func ListGPGKeys(uid int64) ([]*GPGKey, error) {
68-
keys := make([]*GPGKey, 0, 5)
69-
return keys, x.Where("owner_id=? AND primary_key_id=''", uid).Find(&keys)
67+
func ListGPGKeys(uid int64, listOptions ListOptions) ([]*GPGKey, error) {
68+
sess := x.Where("owner_id=? AND primary_key_id=''", uid)
69+
if listOptions.Page != 0 {
70+
sess = listOptions.setSessionPagination(sess)
71+
}
72+
73+
keys := make([]*GPGKey, 0, 2)
74+
return keys, sess.Find(&keys)
7075
}
7176

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

629634
// Now try to associate the signature with the committer, if present
630635
if committer.ID != 0 {
631-
keys, err := ListGPGKeys(committer.ID)
636+
keys, err := ListGPGKeys(committer.ID, ListOptions{})
632637
if err != nil { //Skipping failed to get gpg keys of user
633638
log.Error("ListGPGKeys: %v", err)
634639
return &CommitVerification{

models/issue.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -1103,13 +1103,12 @@ func GetIssuesByIDs(issueIDs []int64) ([]*Issue, error) {
11031103

11041104
// IssuesOptions represents options of an issue.
11051105
type IssuesOptions struct {
1106+
ListOptions
11061107
RepoIDs []int64 // include all repos if empty
11071108
AssigneeID int64
11081109
PosterID int64
11091110
MentionedID int64
11101111
MilestoneID int64
1111-
Page int
1112-
PageSize int
11131112
IsClosed util.OptionalBool
11141113
IsPull util.OptionalBool
11151114
LabelIDs []int64

models/issue_comment.go

+6
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,7 @@ func GetCommentByID(id int64) (*Comment, error) {
777777

778778
// FindCommentsOptions describes the conditions to Find comments
779779
type FindCommentsOptions struct {
780+
ListOptions
780781
RepoID int64
781782
IssueID int64
782783
ReviewID int64
@@ -814,6 +815,11 @@ func findComments(e Engine, opts FindCommentsOptions) ([]*Comment, error) {
814815
if opts.RepoID > 0 {
815816
sess.Join("INNER", "issue", "issue.id = comment.issue_id")
816817
}
818+
819+
if opts.Page != 0 {
820+
sess = opts.setSessionPagination(sess)
821+
}
822+
817823
return comments, sess.
818824
Asc("comment.created_unix").
819825
Asc("comment.id").

models/issue_label.go

+8-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// Copyright 2016 The Gogs Authors. All rights reserved.
2+
// Copyright 2020 The Gitea Authors.
23
// Use of this source code is governed by a MIT-style
34
// license that can be found in the LICENSE file.
45

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

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

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

317+
if listOptions.Page != 0 {
318+
sess = listOptions.setSessionPagination(sess)
319+
}
320+
316321
return labels, sess.Find(&labels)
317322
}
318323

319324
// GetLabelsByRepoID returns all labels that belong to given repository by ID.
320-
func GetLabelsByRepoID(repoID int64, sortType string) ([]*Label, error) {
321-
return getLabelsByRepoID(x, repoID, sortType)
325+
func GetLabelsByRepoID(repoID int64, sortType string, listOptions ListOptions) ([]*Label, error) {
326+
return getLabelsByRepoID(x, repoID, sortType, listOptions)
322327
}
323328

324329
func getLabelsByIssueID(e Engine, issueID int64) ([]*Label, error) {

models/issue_label_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ func TestGetLabelsInRepoByIDs(t *testing.T) {
131131
func TestGetLabelsByRepoID(t *testing.T) {
132132
assert.NoError(t, PrepareTestDatabase())
133133
testSuccess := func(repoID int64, sortType string, expectedIssueIDs []int64) {
134-
labels, err := GetLabelsByRepoID(repoID, sortType)
134+
labels, err := GetLabelsByRepoID(repoID, sortType, ListOptions{})
135135
assert.NoError(t, err)
136136
assert.Len(t, labels, len(expectedIssueIDs))
137137
for i, label := range labels {

models/issue_milestone.go

+6-2
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ func (milestones MilestoneList) getMilestoneIDs() []int64 {
221221
}
222222

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

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

241-
miles := make([]*Milestone, 0, 10)
241+
if listOptions.Page != 0 {
242+
sess = listOptions.setSessionPagination(sess)
243+
}
244+
245+
miles := make([]*Milestone, 0, listOptions.PageSize)
242246
return miles, sess.Asc("deadline_unix").Asc("id").Find(&miles)
243247
}
244248

models/issue_milestone_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ func TestGetMilestonesByRepoID(t *testing.T) {
7171
assert.NoError(t, PrepareTestDatabase())
7272
test := func(repoID int64, state api.StateType) {
7373
repo := AssertExistsAndLoadBean(t, &Repository{ID: repoID}).(*Repository)
74-
milestones, err := GetMilestonesByRepoID(repo.ID, state)
74+
milestones, err := GetMilestonesByRepoID(repo.ID, state, ListOptions{})
7575
assert.NoError(t, err)
7676

7777
var n int
@@ -105,7 +105,7 @@ func TestGetMilestonesByRepoID(t *testing.T) {
105105
test(3, api.StateClosed)
106106
test(3, api.StateAll)
107107

108-
milestones, err := GetMilestonesByRepoID(NonexistentID, api.StateOpen)
108+
milestones, err := GetMilestonesByRepoID(NonexistentID, api.StateOpen, ListOptions{})
109109
assert.NoError(t, err)
110110
assert.Len(t, milestones, 0)
111111
}

models/issue_reaction.go

+17-8
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ type Reaction struct {
3030

3131
// FindReactionsOptions describes the conditions to Find reactions
3232
type FindReactionsOptions struct {
33+
ListOptions
3334
IssueID int64
3435
CommentID int64
3536
UserID int64
@@ -71,20 +72,28 @@ func FindCommentReactions(comment *Comment) (ReactionList, error) {
7172
}
7273

7374
// FindIssueReactions returns a ReactionList of all reactions from an issue
74-
func FindIssueReactions(issue *Issue) (ReactionList, error) {
75+
func FindIssueReactions(issue *Issue, listOptions ListOptions) (ReactionList, error) {
7576
return findReactions(x, FindReactionsOptions{
76-
IssueID: issue.ID,
77-
CommentID: -1,
77+
ListOptions: listOptions,
78+
IssueID: issue.ID,
79+
CommentID: -1,
7880
})
7981
}
8082

8183
func findReactions(e Engine, opts FindReactionsOptions) ([]*Reaction, error) {
82-
reactions := make([]*Reaction, 0, 10)
83-
sess := e.Where(opts.toConds())
84-
return reactions, sess.
84+
e = e.
85+
Where(opts.toConds()).
8586
In("reaction.`type`", setting.UI.Reactions).
86-
Asc("reaction.issue_id", "reaction.comment_id", "reaction.created_unix", "reaction.id").
87-
Find(&reactions)
87+
Asc("reaction.issue_id", "reaction.comment_id", "reaction.created_unix", "reaction.id")
88+
if opts.Page != 0 {
89+
e = opts.setEnginePagination(e)
90+
91+
reactions := make([]*Reaction, 0, opts.PageSize)
92+
return reactions, e.Find(&reactions)
93+
}
94+
95+
reactions := make([]*Reaction, 0, 10)
96+
return reactions, e.Find(&reactions)
8897
}
8998

9099
func createReaction(e *xorm.Session, opts *ReactionOptions) (*Reaction, error) {

models/issue_stopwatch.go

+8-3
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,14 @@ func getStopwatch(e Engine, userID, issueID int64) (sw *Stopwatch, exists bool,
3333
}
3434

3535
// GetUserStopwatches return list of all stopwatches of a user
36-
func GetUserStopwatches(userID int64) (sws *Stopwatches, err error) {
37-
sws = new(Stopwatches)
38-
err = x.Where("stopwatch.user_id = ?", userID).Find(sws)
36+
func GetUserStopwatches(userID int64, listOptions ListOptions) (*Stopwatches, error) {
37+
sws := new(Stopwatches)
38+
sess := x.Where("stopwatch.user_id = ?", userID)
39+
if listOptions.Page != 0 {
40+
sess = listOptions.setSessionPagination(sess)
41+
}
42+
43+
err := sess.Find(sws)
3944
if err != nil {
4045
return nil, err
4146
}

models/issue_test.go

+12-6
Original file line numberDiff line numberDiff line change
@@ -139,24 +139,30 @@ func TestIssues(t *testing.T) {
139139
IssuesOptions{
140140
RepoIDs: []int64{1, 3},
141141
SortType: "oldest",
142-
Page: 1,
143-
PageSize: 4,
142+
ListOptions: ListOptions{
143+
Page: 1,
144+
PageSize: 4,
145+
},
144146
},
145147
[]int64{1, 2, 3, 5},
146148
},
147149
{
148150
IssuesOptions{
149151
LabelIDs: []int64{1},
150-
Page: 1,
151-
PageSize: 4,
152+
ListOptions: ListOptions{
153+
Page: 1,
154+
PageSize: 4,
155+
},
152156
},
153157
[]int64{2, 1},
154158
},
155159
{
156160
IssuesOptions{
157161
LabelIDs: []int64{1, 2},
158-
Page: 1,
159-
PageSize: 4,
162+
ListOptions: ListOptions{
163+
Page: 1,
164+
PageSize: 4,
165+
},
160166
},
161167
[]int64{}, // issues with **both** label 1 and 2, none of these issues matches, TODO: add more tests
162168
},

models/issue_tracked_time.go

+12-4
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010
"code.gitea.io/gitea/modules/setting"
1111

1212
"xorm.io/builder"
13-
"xorm.io/xorm"
1413
)
1514

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

7271
// FindTrackedTimesOptions represent the filters for tracked times. If an ID is 0 it will be ignored.
7372
type FindTrackedTimesOptions struct {
73+
ListOptions
7474
IssueID int64
7575
UserID int64
7676
RepositoryID int64
@@ -104,11 +104,19 @@ func (opts *FindTrackedTimesOptions) ToCond() builder.Cond {
104104
}
105105

106106
// ToSession will convert the given options to a xorm Session by using the conditions from ToCond and joining with issue table if required
107-
func (opts *FindTrackedTimesOptions) ToSession(e Engine) *xorm.Session {
107+
func (opts *FindTrackedTimesOptions) ToSession(e Engine) Engine {
108+
sess := e
108109
if opts.RepositoryID > 0 || opts.MilestoneID > 0 {
109-
return e.Join("INNER", "issue", "issue.id = tracked_time.issue_id").Where(opts.ToCond())
110+
sess = e.Join("INNER", "issue", "issue.id = tracked_time.issue_id")
110111
}
111-
return e.Where(opts.ToCond())
112+
113+
sess = sess.Where(opts.ToCond())
114+
115+
if opts.Page != 0 {
116+
sess = opts.setEnginePagination(sess)
117+
}
118+
119+
return sess
112120
}
113121

114122
func getTrackedTimes(e Engine, options FindTrackedTimesOptions) (trackedTimes TrackedTimeList, err error) {

models/issue_watch.go

+10-6
Original file line numberDiff line numberDiff line change
@@ -77,18 +77,22 @@ func GetIssueWatchersIDs(issueID int64) ([]int64, error) {
7777
}
7878

7979
// GetIssueWatchers returns watchers/unwatchers of a given issue
80-
func GetIssueWatchers(issueID int64) (IssueWatchList, error) {
81-
return getIssueWatchers(x, issueID)
80+
func GetIssueWatchers(issueID int64, listOptions ListOptions) (IssueWatchList, error) {
81+
return getIssueWatchers(x, issueID, listOptions)
8282
}
8383

84-
func getIssueWatchers(e Engine, issueID int64) (watches IssueWatchList, err error) {
85-
err = e.
84+
func getIssueWatchers(e Engine, issueID int64, listOptions ListOptions) (watches IssueWatchList, err error) {
85+
sess := e.
8686
Where("`issue_watch`.issue_id = ?", issueID).
8787
And("`issue_watch`.is_watching = ?", true).
8888
And("`user`.is_active = ?", true).
8989
And("`user`.prohibit_login = ?", false).
90-
Join("INNER", "`user`", "`user`.id = `issue_watch`.user_id").
91-
Find(&watches)
90+
Join("INNER", "`user`", "`user`.id = `issue_watch`.user_id")
91+
92+
if listOptions.Page == 0 {
93+
sess = listOptions.setSessionPagination(sess)
94+
}
95+
err = sess.Find(&watches)
9296
return
9397
}
9498

models/issue_watch_test.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -42,22 +42,22 @@ func TestGetIssueWatch(t *testing.T) {
4242
func TestGetIssueWatchers(t *testing.T) {
4343
assert.NoError(t, PrepareTestDatabase())
4444

45-
iws, err := GetIssueWatchers(1)
45+
iws, err := GetIssueWatchers(1, ListOptions{})
4646
assert.NoError(t, err)
4747
// Watcher is inactive, thus 0
4848
assert.Len(t, iws, 0)
4949

50-
iws, err = GetIssueWatchers(2)
50+
iws, err = GetIssueWatchers(2, ListOptions{})
5151
assert.NoError(t, err)
5252
// Watcher is explicit not watching
5353
assert.Len(t, iws, 0)
5454

55-
iws, err = GetIssueWatchers(5)
55+
iws, err = GetIssueWatchers(5, ListOptions{})
5656
assert.NoError(t, err)
5757
// Issue has no Watchers
5858
assert.Len(t, iws, 0)
5959

60-
iws, err = GetIssueWatchers(7)
60+
iws, err = GetIssueWatchers(7, ListOptions{})
6161
assert.NoError(t, err)
6262
// Issue has one watcher
6363
assert.Len(t, iws, 1)

0 commit comments

Comments
 (0)