aboutsummaryrefslogtreecommitdiffstats
path: root/bridge/gitlab/gitlab_api.go
diff options
context:
space:
mode:
authorMatthias Simon <matthias.simon@nokia.com>2021-02-14 20:35:03 +0100
committerMatthias Simon <matthias.simon@nokia.com>2021-04-23 09:02:48 +0200
commitaa4e225a80b37ce26f5f8c69041ee735f512b113 (patch)
treef34b7ff03f4cec4be4ed6eb3458d515452a92fe6 /bridge/gitlab/gitlab_api.go
parenta8f3b55986982db5f7c3918acaba2c214c919d11 (diff)
downloadgit-bug-aa4e225a80b37ce26f5f8c69041ee735f512b113.tar.gz
gitlab: Add new iterator with state change events
Retrieving events is spread across various various Gitlab APIs. This makes importing and sorting Gitlab events by time quite complicated. This commit replaces the old iterators with a goroutine/channel-based iterator, which merges the individual Gitlab API streams into a single (sorted) event stream.
Diffstat (limited to 'bridge/gitlab/gitlab_api.go')
-rw-r--r--bridge/gitlab/gitlab_api.go171
1 files changed, 171 insertions, 0 deletions
diff --git a/bridge/gitlab/gitlab_api.go b/bridge/gitlab/gitlab_api.go
new file mode 100644
index 00000000..706861e9
--- /dev/null
+++ b/bridge/gitlab/gitlab_api.go
@@ -0,0 +1,171 @@
+package gitlab
+
+import (
+ "context"
+ "sync"
+ "time"
+
+ "github.com/MichaelMure/git-bug/util/text"
+ "github.com/xanzy/go-gitlab"
+)
+
+func Issues(ctx context.Context, client *gitlab.Client, pid string, since time.Time) <-chan *gitlab.Issue {
+
+ out := make(chan *gitlab.Issue)
+
+ go func() {
+ defer close(out)
+
+ opts := gitlab.ListProjectIssuesOptions{
+ UpdatedAfter: &since,
+ Scope: gitlab.String("all"),
+ Sort: gitlab.String("asc"),
+ }
+
+ for {
+ issues, resp, err := client.Issues.ListProjectIssues(pid, &opts)
+ if err != nil {
+ return
+ }
+
+ for _, issue := range issues {
+ out <- issue
+ }
+
+ if resp.CurrentPage >= resp.TotalPages {
+ break
+ }
+
+ opts.Page = resp.NextPage
+ }
+ }()
+
+ return out
+}
+
+func IssueEvents(ctx context.Context, client *gitlab.Client, issue *gitlab.Issue) <-chan Event {
+ cs := []<-chan Event{
+ Notes(ctx, client, issue),
+ LabelEvents(ctx, client, issue),
+ StateEvents(ctx, client, issue),
+ }
+
+ var wg sync.WaitGroup
+ out := make(chan Event)
+
+ output := func(c <-chan Event) {
+ for n := range c {
+ out <- n
+ }
+ wg.Done()
+ }
+
+ wg.Add(len(cs))
+ for _, c := range cs {
+ go output(c)
+ }
+
+ go func() {
+ wg.Wait()
+ close(out)
+ }()
+
+ return out
+}
+
+func Notes(ctx context.Context, client *gitlab.Client, issue *gitlab.Issue) <-chan Event {
+
+ out := make(chan Event)
+
+ go func() {
+ defer close(out)
+
+ opts := gitlab.ListIssueNotesOptions{
+ OrderBy: gitlab.String("created_at"),
+ Sort: gitlab.String("asc"),
+ }
+
+ for {
+ notes, resp, err := client.Notes.ListIssueNotes(issue.ProjectID, issue.IID, &opts)
+
+ if err != nil {
+ out <- ErrorEvent{Err: err, Time: time.Now()}
+ }
+
+ for _, note := range notes {
+ out <- NoteEvent{*note}
+ }
+
+ if resp.CurrentPage >= resp.TotalPages {
+ break
+ }
+
+ opts.Page = resp.NextPage
+ }
+ }()
+
+ return out
+}
+
+func LabelEvents(ctx context.Context, client *gitlab.Client, issue *gitlab.Issue) <-chan Event {
+
+ out := make(chan Event)
+
+ go func() {
+ defer close(out)
+
+ opts := gitlab.ListLabelEventsOptions{}
+
+ for {
+ events, resp, err := client.ResourceLabelEvents.ListIssueLabelEvents(issue.ProjectID, issue.IID, &opts)
+
+ if err != nil {
+ out <- ErrorEvent{Err: err, Time: time.Now()}
+ }
+
+ for _, e := range events {
+ le := LabelEvent{*e}
+ le.Label.Name = text.CleanupOneLine(le.Label.Name)
+ out <- le
+ }
+
+ if resp.CurrentPage >= resp.TotalPages {
+ break
+ }
+
+ opts.Page = resp.NextPage
+ }
+ }()
+
+ return out
+}
+
+func StateEvents(ctx context.Context, client *gitlab.Client, issue *gitlab.Issue) <-chan Event {
+
+ out := make(chan Event)
+
+ go func() {
+ defer close(out)
+
+ opts := gitlab.ListStateEventsOptions{}
+
+ for {
+ events, resp, err := client.ResourceStateEvents.ListIssueStateEvents(issue.ProjectID, issue.IID, &opts)
+ if err != nil {
+ out <- ErrorEvent{Err: err, Time: time.Now()}
+ }
+
+ for _, e := range events {
+ out <- StateEvent{*e}
+ }
+
+ if resp.CurrentPage >= resp.TotalPages {
+ break
+ }
+
+ opts.Page = resp.NextPage
+ }
+ }()
+
+ return out
+}