package gitlab
import (
"time"
"github.com/xanzy/go-gitlab"
)
type issueIterator struct {
page int
index int
cache []*gitlab.Issue
}
type noteIterator struct {
page int
index int
cache []*gitlab.Note
}
type labelEventIterator struct {
page int
index int
cache []*gitlab.LabelEvent
}
type iterator struct {
// gitlab api v4 client
gc *gitlab.Client
// if since is given the iterator will query only the updated
// issues after this date
since time.Time
// project id
project string
// number of issues and notes to query at once
capacity int
// sticky error
err error
// issues iterator
issue *issueIterator
// notes iterator
note *noteIterator
// labelEvent iterator
labelEvent *labelEventIterator
}
// NewIterator create a new iterator
func NewIterator(projectID, token string, since time.Time) *iterator {
return &iterator{
gc: buildClient(token),
project: projectID,
since: since,
capacity: 20,
issue: &issueIterator{
index: -1,
page: 1,
},
note: ¬eIterator{
index: -1,
page: 1,
},
labelEvent: &labelEventIterator{
index: -1,
page: 1,
},
}
}
// Error return last encountered error
func (i *iterator) Error() error {
return i.err
}
func (i *iterator) getNextIssues() bool {
sort := "asc"
scope := "all"
issues, _, err := i.gc.Issues.ListProjectIssues(
i.project,
&gitlab.ListProjectIssuesOptions{
ListOptions: gitlab.ListOptions{
Page: i.issue.page,
PerPage: i.capacity,
},
Scope: &scope,
UpdatedAfter: &i.since,
Sort: &sort,
},
)
if err != nil {
i.err = err
return false
}
// if repository doesn't have any issues
if len(issues) == 0 {
return false
}
i.issue.cache = issues
i.issue.index = 0
i.issue.page++
i.note.index = -1
i.note.cache = nil
return true
}
func (i *iterator) NextIssue() bool {
// first query
if i.issue.cache == nil {
return i.getNextIssues()
}
if i.err != nil {
return false
}
// move cursor index
if i.issue.index < min(i.capacity, len(i.issue.cache))-1 {
i.issue.index++
return true
}
return i.getNextIssues()
}
func (i *iterator) IssueValue() *gitlab.Issue {
return i.issue.cache[i.issue.index]
}
func (i *iterator) getNextNotes() bool {
sort := "asc"
order := "created_at"
notes, _, err := i.gc.Notes.ListIssueNotes(
i.project,
i.IssueValue().IID,
&gitlab.ListIssueNotesOptions{
ListOptions: gitlab.ListOptions{
Page: i.note.page,
PerPage: i.capacity,
},
Sort: &sort,
OrderBy: &order,
},
)
if err != nil {
i.err = err
return false
}
if len(notes) == 0 {
i.note.index = -1
i.note.page = 1
i.note.cache = nil
return false
}
i.note.cache = notes
i.note.page++
i.note.index = 0
return true
}
func (i *iterator) NextNote() bool {
if i.err != nil {
return false
}
if len(i.note.cache) == 0 {
return i.getNextNotes()
}
// move cursor index
if i.note.index < min(i.capacity, len(i.note.cache))-1 {
i.note.index++
return true
}
return i.getNextNotes()
}
func (i *iterator) NoteValue() *gitlab.Note {
return i.note.cache[i.note.index]
}
func (i *iterator) getNextLabelEvents() bool {
labelEvents, _, err := i.gc.ResourceLabelEvents.ListIssueLabelEvents(
i.project,
i.IssueValue().IID,
&gitlab.ListLabelEventsOptions{
ListOptions: gitlab.ListOptions{
Page: i.labelEvent.page,
PerPage: i.capacity,
},
},
)
if err != nil {
i.err = err
return false
}
if len(labelEvents) == 0 {
i.labelEvent.page = 1
i.labelEvent.index = -1
i.labelEvent.cache = nil
return false
}
i.labelEvent.cache = labelEvents
i.labelEvent.page++
i.labelEvent.index = 0
return true
}
func (i *iterator) NextLabelEvent() bool {
if i.err != nil {
return false
}
if len(i.labelEvent.cache) == 0 {
return i.getNextLabelEvents()
}
// move cursor index
if i.labelEvent.index < min(i.capacity, len(i.labelEvent.cache))-1 {
i.labelEvent.index++
return true
}
return i.getNextLabelEvents()
}
func (i *iterator) LabelEventValue() *gitlab.LabelEvent {
return i.labelEvent.cache[i.labelEvent.index]
}
func min(a, b int) int {
if a > b {
return b
}
return a
}