Skip to content

Commit 2fb6734

Browse files
authored
Merge pull request #745 from bmeneguele/fix-pagination-header
gitlab: handle API response without X-Total(-Pages) HTTP header
2 parents 31ae4a7 + a59a5aa commit 2fb6734

1 file changed

Lines changed: 78 additions & 60 deletions

File tree

internal/gitlab/gitlab.go

Lines changed: 78 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -421,10 +421,12 @@ func MRList(project string, opts gitlab.ListProjectMergeRequestsOptions, n int)
421421
if err != nil {
422422
return nil, err
423423
}
424-
if resp.CurrentPage == resp.TotalPages {
424+
425+
var ok bool
426+
if opts.Page, ok = hasNextPage(resp); !ok {
425427
return list, nil
426428
}
427-
opts.Page = resp.NextPage
429+
428430
for len(list) < n || n == -1 {
429431
if n != -1 {
430432
opts.PerPage = n - len(list)
@@ -433,12 +435,13 @@ func MRList(project string, opts gitlab.ListProjectMergeRequestsOptions, n int)
433435
if err != nil {
434436
return nil, err
435437
}
436-
opts.Page = resp.NextPage
437438
list = append(list, mrs...)
438-
if resp.CurrentPage == resp.TotalPages {
439+
440+
if opts.Page, ok = hasNextPage(resp); !ok {
439441
break
440442
}
441443
}
444+
442445
return list, nil
443446
}
444447

@@ -501,13 +504,12 @@ func MRListDiscussions(project string, mrNum int) ([]*gitlab.Discussion, error)
501504
// ... and add them to our collection of discussions
502505
discussions = append(discussions, d...)
503506

504-
// if we've seen all the pages, then we can break here
505-
if resp.CurrentPage >= resp.TotalPages {
507+
// if we've seen all the pages, then we can break here.
508+
// otherwise, update the page number to get the next page.
509+
var ok bool
510+
if opt.Page, ok = hasNextPage(resp); !ok {
506511
break
507512
}
508-
509-
// otherwise, update the page number to get the next page.
510-
opt.Page = resp.NextPage
511513
}
512514

513515
return discussions, nil
@@ -678,7 +680,9 @@ func IssueList(project string, opts gitlab.ListProjectIssuesOptions, n int) ([]*
678680
if err != nil {
679681
return nil, err
680682
}
681-
if resp.CurrentPage == resp.TotalPages {
683+
684+
var ok bool
685+
if opts.Page, ok = hasNextPage(resp); !ok {
682686
return list, nil
683687
}
684688

@@ -691,9 +695,9 @@ func IssueList(project string, opts gitlab.ListProjectIssuesOptions, n int) ([]*
691695
if err != nil {
692696
return nil, err
693697
}
694-
opts.Page = resp.NextPage
695698
list = append(list, issues...)
696-
if resp.CurrentPage == resp.TotalPages {
699+
700+
if opts.Page, ok = hasNextPage(resp); !ok {
697701
break
698702
}
699703
}
@@ -778,13 +782,12 @@ func IssueListDiscussions(project string, issueNum int) ([]*gitlab.Discussion, e
778782
// ... and add them to our collection of discussions
779783
discussions = append(discussions, d...)
780784

781-
// if we've seen all the pages, then we can break here
782-
if resp.CurrentPage >= resp.TotalPages {
785+
// if we've seen all the pages, then we can break here.
786+
// otherwise, update the page number to get the next page.
787+
var ok bool
788+
if opt.Page, ok = hasNextPage(resp); !ok {
783789
break
784790
}
785-
786-
// otherwise, update the page number to get the next page.
787-
opt.Page = resp.NextPage
788791
}
789792

790793
return discussions, nil
@@ -846,12 +849,11 @@ func LabelList(project string) ([]*gitlab.Label, error) {
846849
labels = append(labels, l...)
847850

848851
// if we've seen all the pages, then we can break here
849-
if resp.CurrentPage >= resp.TotalPages {
852+
// otherwise, update the page number to get the next page.
853+
var ok bool
854+
if opt.Page, ok = hasNextPage(resp); !ok {
850855
break
851856
}
852-
853-
// otherwise, update the page number to get the next page.
854-
opt.Page = resp.NextPage
855857
}
856858

857859
return labels, nil
@@ -897,10 +899,10 @@ func BranchList(project string, opts *gitlab.ListBranchesOptions) ([]*gitlab.Bra
897899
}
898900
branches = append(branches, bList...)
899901

900-
if resp.CurrentPage >= resp.TotalPages {
902+
var ok bool
903+
if opts.Page, ok = hasNextPage(resp); !ok {
901904
break
902905
}
903-
opts.Page = resp.NextPage
904906
}
905907

906908
return branches, nil
@@ -939,13 +941,12 @@ func MilestoneList(project string, opt *gitlab.ListMilestonesOptions) ([]*gitlab
939941

940942
milestones = append(milestones, m...)
941943

942-
// if we've seen all the pages, then we can break here
943-
if resp.CurrentPage >= resp.TotalPages {
944+
// if we've seen all the pages, then we can break here.
945+
// otherwise, update the page number to get the next page.
946+
var ok bool
947+
if opt.Page, ok = hasNextPage(resp); !ok {
944948
break
945949
}
946-
947-
// otherwise, update the page number to get the next page.
948-
opt.Page = resp.NextPage
949950
}
950951

951952
if p.Namespace.Kind != "group" {
@@ -985,12 +986,11 @@ func MilestoneList(project string, opt *gitlab.ListMilestonesOptions) ([]*gitlab
985986
}
986987

987988
// if we've seen all the pages, then we can break here
988-
if resp.CurrentPage >= resp.TotalPages {
989+
// otherwise, update the page number to get the next page.
990+
var ok bool
991+
if gopt.Page, ok = hasNextPage(resp); !ok {
989992
break
990993
}
991-
992-
// otherwise, update the page number to get the next page.
993-
gopt.Page = resp.NextPage
994994
}
995995

996996
return milestones, nil
@@ -1043,10 +1043,12 @@ func ProjectSnippetList(pid interface{}, opts gitlab.ListProjectSnippetsOptions,
10431043
if err != nil {
10441044
return nil, err
10451045
}
1046-
if resp.CurrentPage == resp.TotalPages {
1046+
1047+
var ok bool
1048+
if opts.Page, ok = hasNextPage(resp); !ok {
10471049
return list, nil
10481050
}
1049-
opts.Page = resp.NextPage
1051+
10501052
for len(list) < n || n == -1 {
10511053
if n != -1 {
10521054
opts.PerPage = n - len(list)
@@ -1055,12 +1057,13 @@ func ProjectSnippetList(pid interface{}, opts gitlab.ListProjectSnippetsOptions,
10551057
if err != nil {
10561058
return nil, err
10571059
}
1058-
opts.Page = resp.NextPage
10591060
list = append(list, snips...)
1060-
if resp.CurrentPage == resp.TotalPages {
1061+
1062+
if opts.Page, ok = hasNextPage(resp); !ok {
10611063
break
10621064
}
10631065
}
1066+
10641067
return list, nil
10651068
}
10661069

@@ -1089,10 +1092,12 @@ func SnippetList(opts gitlab.ListSnippetsOptions, n int) ([]*gitlab.Snippet, err
10891092
if err != nil {
10901093
return nil, err
10911094
}
1092-
if resp.CurrentPage == resp.TotalPages {
1095+
1096+
var ok bool
1097+
if opts.Page, ok = hasNextPage(resp); !ok {
10931098
return list, nil
10941099
}
1095-
opts.Page = resp.NextPage
1100+
10961101
for len(list) < n || n == -1 {
10971102
if n != -1 {
10981103
opts.PerPage = n - len(list)
@@ -1101,12 +1106,13 @@ func SnippetList(opts gitlab.ListSnippetsOptions, n int) ([]*gitlab.Snippet, err
11011106
if err != nil {
11021107
return nil, err
11031108
}
1104-
opts.Page = resp.NextPage
11051109
list = append(list, snips...)
1106-
if resp.CurrentPage == resp.TotalPages {
1110+
1111+
if opts.Page, ok = hasNextPage(resp); !ok {
11071112
break
11081113
}
11091114
}
1115+
11101116
return list, nil
11111117
}
11121118

@@ -1146,10 +1152,12 @@ func ProjectList(opts gitlab.ListProjectsOptions, n int) ([]*gitlab.Project, err
11461152
if err != nil {
11471153
return nil, err
11481154
}
1149-
if resp.CurrentPage == resp.TotalPages {
1155+
1156+
var ok bool
1157+
if opts.Page, ok = hasNextPage(resp); !ok {
11501158
return list, nil
11511159
}
1152-
opts.Page = resp.NextPage
1160+
11531161
for len(list) < n || n == -1 {
11541162
if n != -1 {
11551163
opts.PerPage = n - len(list)
@@ -1158,12 +1166,13 @@ func ProjectList(opts gitlab.ListProjectsOptions, n int) ([]*gitlab.Project, err
11581166
if err != nil {
11591167
return nil, err
11601168
}
1161-
opts.Page = resp.NextPage
11621169
list = append(list, projects...)
1163-
if resp.CurrentPage == resp.TotalPages {
1170+
1171+
if opts.Page, ok = hasNextPage(resp); !ok {
11641172
break
11651173
}
11661174
}
1175+
11671176
return list, nil
11681177
}
11691178

@@ -1232,6 +1241,8 @@ func CIJobs(pid interface{}, id int, followBridge bool, bridgeName string) ([]Jo
12321241

12331242
// First we get the jobs with direct relation to the actual project
12341243
list := make([]JobStruct, 0)
1244+
var ok bool
1245+
12351246
for {
12361247
jobs, resp, err := lab.Jobs.ListPipelineJobs(pid, id, opts)
12371248
if err != nil {
@@ -1242,8 +1253,7 @@ func CIJobs(pid interface{}, id int, followBridge bool, bridgeName string) ([]Jo
12421253
list = append(list, JobStruct{job, pid})
12431254
}
12441255

1245-
opts.Page = resp.NextPage
1246-
if resp.CurrentPage == resp.TotalPages {
1256+
if opts.Page, ok = hasNextPage(resp); !ok {
12471257
break
12481258
}
12491259
}
@@ -1260,10 +1270,9 @@ func CIJobs(pid interface{}, id int, followBridge bool, bridgeName string) ([]Jo
12601270
if err != nil {
12611271
return nil, err
12621272
}
1263-
1264-
opts.Page = resp.NextPage
12651273
bridgeList = append(bridgeList, bridges...)
1266-
if resp.CurrentPage == resp.TotalPages {
1274+
1275+
if opts.Page, ok = hasNextPage(resp); !ok {
12671276
break
12681277
}
12691278
}
@@ -1288,8 +1297,7 @@ func CIJobs(pid interface{}, id int, followBridge bool, bridgeName string) ([]Jo
12881297
list = append(list, JobStruct{job, pid})
12891298
}
12901299

1291-
opts.Page = resp.NextPage
1292-
if resp.CurrentPage == resp.TotalPages {
1300+
if opts.Page, ok = hasNextPage(resp); !ok {
12931301
break
12941302
}
12951303
}
@@ -1693,11 +1701,11 @@ func TodoList(opts gitlab.ListTodosOptions, n int) ([]*gitlab.Todo, error) {
16931701
return nil, err
16941702
}
16951703

1696-
if resp.CurrentPage == resp.TotalPages {
1704+
var ok bool
1705+
if opts.Page, ok = hasNextPage(resp); !ok {
16971706
return list, nil
16981707
}
16991708

1700-
opts.Page = resp.NextPage
17011709
for len(list) < n || n == -1 {
17021710
if n != -1 {
17031711
opts.PerPage = n - len(list)
@@ -1707,10 +1715,9 @@ func TodoList(opts gitlab.ListTodosOptions, n int) ([]*gitlab.Todo, error) {
17071715
if err != nil {
17081716
return nil, err
17091717
}
1710-
1711-
opts.Page = resp.NextPage
17121718
list = append(list, todos...)
1713-
if resp.CurrentPage == resp.TotalPages {
1719+
1720+
if opts.Page, ok = hasNextPage(resp); !ok {
17141721
break
17151722
}
17161723
}
@@ -1793,12 +1800,11 @@ func GetCommitDiff(project string, sha string) ([]*gitlab.Diff, error) {
17931800
diffs = append(diffs, ds...)
17941801

17951802
// if we've seen all the pages, then we can break here
1796-
if resp.CurrentPage >= resp.TotalPages {
1803+
// otherwise, update the page number to get the next page.
1804+
var ok bool
1805+
if opt.Page, ok = hasNextPage(resp); !ok {
17971806
break
17981807
}
1799-
1800-
// otherwise, update the page number to get the next page.
1801-
opt.Page = resp.NextPage
18021808
}
18031809

18041810
return diffs, nil
@@ -1900,3 +1906,15 @@ func CreateMergeRequestCommitDiscussion(project string, mrID int, sha string, ne
19001906
note := discussion.Notes[0]
19011907
return fmt.Sprintf("%s/merge_requests/%d#note_%d", p.WebURL, note.NoteableIID, note.ID), nil
19021908
}
1909+
1910+
// hasNextPage get the next page number in case the API response has more
1911+
// than one. It also uses only the "X-Page" and "X-Next-Page" HTTP headers,
1912+
// since in some cases the API response may come without the HTTP
1913+
// X-Total(-Page) header. Reference:
1914+
// https://docs.gitlab.com/ee/user/gitlab_com/index.html#pagination-response-headers
1915+
func hasNextPage(resp *gitlab.Response) (int, bool) {
1916+
if resp.CurrentPage >= resp.NextPage {
1917+
return 0, false
1918+
}
1919+
return resp.NextPage, true
1920+
}

0 commit comments

Comments
 (0)