aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bridge/gitlab/iterator.go212
1 files changed, 212 insertions, 0 deletions
diff --git a/bridge/gitlab/iterator.go b/bridge/gitlab/iterator.go
new file mode 100644
index 00000000..724d1c73
--- /dev/null
+++ b/bridge/gitlab/iterator.go
@@ -0,0 +1,212 @@
+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
+}