package gitlab
import (
"time"
"github.com/xanzy/go-gitlab"
)
type issueIterator struct {
page int
index int
cache []*gitlab.Issue
}
type commentIterator struct {
page int
index int
cache []*gitlab.Note
}
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
// comments iterator
comment *commentIterator
}
// NewIterator create a new iterator
func NewIterator(projectID, token string, capacity int, since time.Time) *iterator {
return &iterator{
gc: buildClient(token),
project: projectID,
since: since,
capacity: capacity,
issue: &issueIterator{
index: -1,
page: 1,
},
comment: &commentIterator{
index: -1,
page: 1,
},
}
}
// Error return last encountered error
func (i *iterator) Error() error {
return i.err
}
func (i *iterator) getIssues() ([]*gitlab.Issue, error) {
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,
},
)
return issues, err
}
func (i *iterator) NextIssue() bool {
// first query
if i.issue.cache == nil {
issues, err := i.getIssues()
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++
return true
}
if i.err != nil {
return false
}
// move cursor index
if i.issue.index < min(i.capacity, len(i.issue.cache)) {
i.issue.index++
return true
}
// query next issues
issues, err := i.getIssues()
if err != nil {
i.err = err
return false
}
// no more issues to query
if len(issues) == 0 {
return false
}
i.issue.page++
i.issue.index = 0
i.comment.index = 0
return true
}
func (i *iterator) IssueValue() *gitlab.Issue {
return i.issue.cache[i.issue.index]
}
func (i *iterator) getComments() ([]*gitlab.Note, error) {
notes, _, err := i.gc.Notes.ListIssueNotes(
i.project,
i.IssueValue().IID,
&gitlab.ListIssueNotesOptions{
ListOptions: gitlab.ListOptions{
Page: i.issue.page,
PerPage: i.capacity,
},
},
)
return notes, err
}
func (i *iterator) NextComment() bool {
if i.err != nil {
return false
}
if len(i.comment.cache) == 0 {
// query next issues
comments, err := i.getComments()
if err != nil {
i.err = err
return false
}
if len(comments) == 0 {
i.comment.index = 0
i.comment.page = 1
return false
}
i.comment.page++
i.comment.index = 0
return true
}
// move cursor index
if i.comment.index < min(i.capacity, len(i.comment.cache)) {
i.comment.index++
return true
}
// query next issues
comments, err := i.getComments()
if err != nil {
i.err = err
return false
}
if len(comments) == 0 {
i.comment.index = 0
i.comment.page = 1
return false
}
i.comment.page++
i.comment.index = 0
return false
}
func (i *iterator) CommentValue() *gitlab.Note {
return i.comment.cache[i.comment.index]
}
func min(a, b int) int {
if a > b {
return b
}
return a
}