iterator.go

  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 updated
 32	// issues 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 *labelEventIterator
 51}
 52
 53// NewIterator create a new iterator
 54func NewIterator(projectID, token string, capacity int, since time.Time) *iterator {
 55	return &iterator{
 56		gc:       buildClient(token),
 57		project:  projectID,
 58		since:    since,
 59		capacity: capacity,
 60		issue: &issueIterator{
 61			index: -1,
 62			page:  1,
 63		},
 64		note: &noteIterator{
 65			index: -1,
 66			page:  1,
 67		},
 68		labelEvent: &labelEventIterator{
 69			index: -1,
 70			page:  1,
 71		},
 72	}
 73}
 74
 75// Error return last encountered error
 76func (i *iterator) Error() error {
 77	return i.err
 78}
 79
 80func (i *iterator) getNextIssues() bool {
 81	sort := "asc"
 82	scope := "all"
 83	issues, _, err := i.gc.Issues.ListProjectIssues(
 84		i.project,
 85		&gitlab.ListProjectIssuesOptions{
 86			ListOptions: gitlab.ListOptions{
 87				Page:    i.issue.page,
 88				PerPage: i.capacity,
 89			},
 90			Scope:        &scope,
 91			UpdatedAfter: &i.since,
 92			Sort:         &sort,
 93		},
 94	)
 95
 96	if err != nil {
 97		i.err = err
 98		return false
 99	}
100
101	// if repository doesn't have any issues
102	if len(issues) == 0 {
103		return false
104	}
105
106	i.issue.cache = issues
107	i.issue.index = 0
108	i.issue.page++
109	i.note.index = -1
110	i.note.cache = nil
111
112	return true
113}
114
115func (i *iterator) NextIssue() bool {
116	// first query
117	if i.issue.cache == nil {
118		return i.getNextIssues()
119	}
120
121	if i.err != nil {
122		return false
123	}
124
125	// move cursor index
126	if i.issue.index < min(i.capacity, len(i.issue.cache))-1 {
127		i.issue.index++
128		return true
129	}
130
131	return i.getNextIssues()
132}
133
134func (i *iterator) IssueValue() *gitlab.Issue {
135	return i.issue.cache[i.issue.index]
136}
137
138func (i *iterator) getNextNotes() bool {
139	sort := "asc"
140	order := "created_at"
141	notes, _, err := i.gc.Notes.ListIssueNotes(
142		i.project,
143		i.IssueValue().IID,
144		&gitlab.ListIssueNotesOptions{
145			ListOptions: gitlab.ListOptions{
146				Page:    i.note.page,
147				PerPage: i.capacity,
148			},
149			Sort:    &sort,
150			OrderBy: &order,
151		},
152	)
153
154	if err != nil {
155		i.err = err
156		return false
157	}
158
159	if len(notes) == 0 {
160		i.note.index = -1
161		i.note.page = 1
162		i.note.cache = nil
163		return false
164	}
165
166	i.note.cache = notes
167	i.note.page++
168	i.note.index = 0
169	return true
170}
171
172func (i *iterator) NextNote() bool {
173	if i.err != nil {
174		return false
175	}
176
177	if len(i.note.cache) == 0 {
178		return i.getNextNotes()
179	}
180
181	// move cursor index
182	if i.note.index < min(i.capacity, len(i.note.cache))-1 {
183		i.note.index++
184		return true
185	}
186
187	return i.getNextNotes()
188}
189
190func (i *iterator) NoteValue() *gitlab.Note {
191	return i.note.cache[i.note.index]
192}
193
194func min(a, b int) int {
195	if a > b {
196		return b
197	}
198
199	return a
200}