1package iterator
2
3import (
4 "context"
5 "sort"
6
7 "github.com/xanzy/go-gitlab"
8)
9
10// Since Gitlab does not return the label events items in the correct order
11// we need to sort the list ourselves and stop relying on the pagination model
12// #BecauseGitlab
13type labelEventIterator struct {
14 issue int
15 index int
16 cache []*gitlab.LabelEvent
17}
18
19func newLabelEventIterator() *labelEventIterator {
20 lei := &labelEventIterator{}
21 lei.Reset(-1)
22 return lei
23}
24
25func (lei *labelEventIterator) Next(ctx context.Context, conf config) (bool, error) {
26 // first query
27 if lei.cache == nil {
28 return lei.getNext(ctx, conf)
29 }
30
31 // move cursor index
32 if lei.index < len(lei.cache)-1 {
33 lei.index++
34 return true, nil
35 }
36
37 return false, nil
38}
39
40func (lei *labelEventIterator) Value() *gitlab.LabelEvent {
41 return lei.cache[lei.index]
42}
43
44func (lei *labelEventIterator) getNext(ctx context.Context, conf config) (bool, error) {
45 ctx, cancel := context.WithTimeout(ctx, conf.timeout)
46 defer cancel()
47
48 // since order is not guaranteed we should query all label events
49 // and sort them by ID
50 page := 1
51 for {
52 labelEvents, _, err := conf.gc.ResourceLabelEvents.ListIssueLabelEvents(
53 conf.project,
54 lei.issue,
55 &gitlab.ListLabelEventsOptions{
56 ListOptions: gitlab.ListOptions{
57 Page: page,
58 PerPage: conf.capacity,
59 },
60 },
61 gitlab.WithContext(ctx),
62 )
63 if err != nil {
64 lei.Reset(-1)
65 return false, err
66 }
67
68 if len(labelEvents) == 0 {
69 break
70 }
71 lei.cache = append(lei.cache, labelEvents...)
72 page++
73 }
74
75 sort.Sort(lei)
76 lei.index = 0
77
78 return len(lei.cache) > 0, nil
79}
80
81func (lei *labelEventIterator) Reset(issue int) {
82 lei.issue = issue
83 lei.index = -1
84 lei.cache = nil
85}
86
87// ORDERING
88
89func (lei *labelEventIterator) Len() int {
90 return len(lei.cache)
91}
92
93func (lei *labelEventIterator) Swap(i, j int) {
94 lei.cache[i], lei.cache[j] = lei.cache[j], lei.cache[i]
95}
96
97func (lei *labelEventIterator) Less(i, j int) bool {
98 return lei.cache[i].ID < lei.cache[j].ID
99}