1package gitlab
2
3import (
4 "time"
5
6 "github.com/xanzy/go-gitlab"
7)
8
9type issueIterator struct {
10 page int
11 index int
12 cache []*gitlab.Issue
13}
14
15type noteIterator struct {
16 page int
17 index int
18 cache []*gitlab.Note
19}
20
21type labelEventIterator struct {
22 page int
23 index int
24 cache []*gitlab.LabelEvent
25}
26
27type iterator struct {
28 // gitlab api v4 client
29 gc *gitlab.Client
30
31 // if since is given the iterator will query only the issues
32 // updated after this date
33 since time.Time
34
35 // project id
36 project string
37
38 // number of issues and notes to query at once
39 capacity int
40
41 // sticky error
42 err error
43
44 // issues iterator
45 issue *issueIterator
46
47 // notes iterator
48 note *noteIterator
49
50 // labelEvent iterator
51 labelEvent *labelEventIterator
52}
53
54// NewIterator create a new iterator
55func NewIterator(projectID, token string, since time.Time) *iterator {
56 return &iterator{
57 gc: buildClient(token),
58 project: projectID,
59 since: since,
60 capacity: 20,
61 issue: &issueIterator{
62 index: -1,
63 page: 1,
64 },
65 note: ¬eIterator{
66 index: -1,
67 page: 1,
68 },
69 labelEvent: &labelEventIterator{
70 index: -1,
71 page: 1,
72 },
73 }
74}
75
76// Error return last encountered error
77func (i *iterator) Error() error {
78 return i.err
79}
80
81func (i *iterator) getNextIssues() bool {
82 issues, _, err := i.gc.Issues.ListProjectIssues(
83 i.project,
84 &gitlab.ListProjectIssuesOptions{
85 ListOptions: gitlab.ListOptions{
86 Page: i.issue.page,
87 PerPage: i.capacity,
88 },
89 Scope: gitlab.String("all"),
90 UpdatedAfter: &i.since,
91 Sort: gitlab.String("asc"),
92 },
93 )
94
95 if err != nil {
96 i.err = err
97 return false
98 }
99
100 // if repository doesn't have any issues
101 if len(issues) == 0 {
102 return false
103 }
104
105 i.issue.cache = issues
106 i.issue.index = 0
107 i.issue.page++
108 i.note.index = -1
109 i.note.cache = nil
110
111 return true
112}
113
114func (i *iterator) NextIssue() bool {
115 if i.err != nil {
116 return false
117 }
118
119 // first query
120 if i.issue.cache == nil {
121 return i.getNextIssues()
122 }
123
124 // move cursor index
125 if i.issue.index < len(i.issue.cache)-1 {
126 i.issue.index++
127 return true
128 }
129
130 return i.getNextIssues()
131}
132
133func (i *iterator) IssueValue() *gitlab.Issue {
134 return i.issue.cache[i.issue.index]
135}
136
137func (i *iterator) getNextNotes() bool {
138 notes, _, err := i.gc.Notes.ListIssueNotes(
139 i.project,
140 i.IssueValue().IID,
141 &gitlab.ListIssueNotesOptions{
142 ListOptions: gitlab.ListOptions{
143 Page: i.note.page,
144 PerPage: i.capacity,
145 },
146 Sort: gitlab.String("asc"),
147 OrderBy: gitlab.String("created_at"),
148 },
149 )
150
151 if err != nil {
152 i.err = err
153 return false
154 }
155
156 if len(notes) == 0 {
157 i.note.index = -1
158 i.note.page = 1
159 i.note.cache = nil
160 return false
161 }
162
163 i.note.cache = notes
164 i.note.page++
165 i.note.index = 0
166 return true
167}
168
169func (i *iterator) NextNote() bool {
170 if i.err != nil {
171 return false
172 }
173
174 if len(i.note.cache) == 0 {
175 return i.getNextNotes()
176 }
177
178 // move cursor index
179 if i.note.index < len(i.note.cache)-1 {
180 i.note.index++
181 return true
182 }
183
184 return i.getNextNotes()
185}
186
187func (i *iterator) NoteValue() *gitlab.Note {
188 return i.note.cache[i.note.index]
189}
190
191func (i *iterator) getNextLabelEvents() bool {
192 labelEvents, _, err := i.gc.ResourceLabelEvents.ListIssueLabelEvents(
193 i.project,
194 i.IssueValue().IID,
195 &gitlab.ListLabelEventsOptions{
196 ListOptions: gitlab.ListOptions{
197 Page: i.labelEvent.page,
198 PerPage: i.capacity,
199 },
200 },
201 )
202
203 if err != nil {
204 i.err = err
205 return false
206 }
207
208 if len(labelEvents) == 0 {
209 i.labelEvent.page = 1
210 i.labelEvent.index = -1
211 i.labelEvent.cache = nil
212 return false
213 }
214
215 i.labelEvent.cache = labelEvents
216 i.labelEvent.page++
217 i.labelEvent.index = 0
218 return true
219}
220
221func (i *iterator) NextLabelEvent() bool {
222 if i.err != nil {
223 return false
224 }
225
226 if len(i.labelEvent.cache) == 0 {
227 return i.getNextLabelEvents()
228 }
229
230 // move cursor index
231 if i.labelEvent.index < len(i.labelEvent.cache)-1 {
232 i.labelEvent.index++
233 return true
234 }
235
236 return i.getNextLabelEvents()
237}
238
239func (i *iterator) LabelEventValue() *gitlab.LabelEvent {
240 return i.labelEvent.cache[i.labelEvent.index]
241}