diff options
author | Matthias Simon <matthias.simon@nokia.com> | 2021-02-14 20:35:03 +0100 |
---|---|---|
committer | Matthias Simon <matthias.simon@nokia.com> | 2021-04-23 09:02:48 +0200 |
commit | aa4e225a80b37ce26f5f8c69041ee735f512b113 (patch) | |
tree | f34b7ff03f4cec4be4ed6eb3458d515452a92fe6 /bridge/gitlab/gitlab_api.go | |
parent | a8f3b55986982db5f7c3918acaba2c214c919d11 (diff) | |
download | git-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.go | 171 |
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 +} |