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 commentIterator struct {
 16	page  int
 17	index int
 18	cache []*gitlab.Note
 19}
 20
 21type iterator struct {
 22	// gitlab api v4 client
 23	gc *gitlab.Client
 24
 25	// if since is given the iterator will query only the updated
 26	// issues after this date
 27	since time.Time
 28
 29	// project id
 30	project string
 31
 32	// number of issues and notes to query at once
 33	capacity int
 34
 35	// sticky error
 36	err error
 37
 38	// issues iterator
 39	issue *issueIterator
 40
 41	// comments iterator
 42	comment *commentIterator
 43}
 44
 45// NewIterator create a new iterator
 46func NewIterator(projectID, token string, capacity int, since time.Time) *iterator {
 47	return &iterator{
 48		gc:       buildClient(token),
 49		project:  projectID,
 50		since:    since,
 51		capacity: capacity,
 52		issue: &issueIterator{
 53			index: -1,
 54			page:  1,
 55		},
 56		comment: &commentIterator{
 57			index: -1,
 58			page:  1,
 59		},
 60	}
 61}
 62
 63// Error return last encountered error
 64func (i *iterator) Error() error {
 65	return i.err
 66}
 67
 68func (i *iterator) getIssues() ([]*gitlab.Issue, error) {
 69	scope := "all"
 70	issues, _, err := i.gc.Issues.ListProjectIssues(
 71		i.project,
 72		&gitlab.ListProjectIssuesOptions{
 73			ListOptions: gitlab.ListOptions{
 74				Page:    i.issue.page,
 75				PerPage: i.capacity,
 76			},
 77			Scope:        &scope,
 78			UpdatedAfter: &i.since,
 79		},
 80	)
 81
 82	return issues, err
 83}
 84
 85func (i *iterator) NextIssue() bool {
 86	// first query
 87	if i.issue.cache == nil {
 88		issues, err := i.getIssues()
 89		if err != nil {
 90			i.err = err
 91			return false
 92		}
 93
 94		// if repository doesn't have any issues
 95		if len(issues) == 0 {
 96			return false
 97		}
 98
 99		i.issue.cache = issues
100		i.issue.index++
101		return true
102	}
103
104	if i.err != nil {
105		return false
106	}
107
108	// move cursor index
109	if i.issue.index < min(i.capacity, len(i.issue.cache)) {
110		i.issue.index++
111		return true
112	}
113
114	// query next issues
115	issues, err := i.getIssues()
116	if err != nil {
117		i.err = err
118		return false
119	}
120
121	// no more issues to query
122	if len(issues) == 0 {
123		return false
124	}
125
126	i.issue.page++
127	i.issue.index = 0
128	i.comment.index = 0
129
130	return true
131}
132
133func (i *iterator) IssueValue() *gitlab.Issue {
134	return i.issue.cache[i.issue.index]
135}
136
137func (i *iterator) getComments() ([]*gitlab.Note, error) {
138	notes, _, err := i.gc.Notes.ListIssueNotes(
139		i.project,
140		i.IssueValue().IID,
141		&gitlab.ListIssueNotesOptions{
142			ListOptions: gitlab.ListOptions{
143				Page:    i.issue.page,
144				PerPage: i.capacity,
145			},
146		},
147	)
148
149	return notes, err
150}
151
152func (i *iterator) NextComment() bool {
153	if i.err != nil {
154		return false
155	}
156
157	if len(i.comment.cache) == 0 {
158		// query next issues
159		comments, err := i.getComments()
160		if err != nil {
161			i.err = err
162			return false
163		}
164
165		if len(comments) == 0 {
166			i.comment.index = 0
167			i.comment.page = 1
168			return false
169		}
170
171		i.comment.page++
172		i.comment.index = 0
173
174		return true
175	}
176
177	// move cursor index
178	if i.comment.index < min(i.capacity, len(i.comment.cache)) {
179		i.comment.index++
180		return true
181	}
182
183	// query next issues
184	comments, err := i.getComments()
185	if err != nil {
186		i.err = err
187		return false
188	}
189
190	if len(comments) == 0 {
191		i.comment.index = 0
192		i.comment.page = 1
193		return false
194	}
195
196	i.comment.page++
197	i.comment.index = 0
198
199	return false
200}
201
202func (i *iterator) CommentValue() *gitlab.Note {
203	return i.comment.cache[i.comment.index]
204}
205
206func min(a, b int) int {
207	if a > b {
208		return b
209	}
210
211	return a
212}