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, resp, 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
72 lei.cache = append(lei.cache, labelEvents...)
73
74 if resp.TotalPages == page {
75 break
76 }
77
78 page++
79 }
80
81 sort.Sort(lei)
82 lei.index = 0
83
84 return len(lei.cache) > 0, nil
85}
86
87func (lei *labelEventIterator) Reset(issue int) {
88 lei.issue = issue
89 lei.index = -1
90 lei.cache = nil
91}
92
93// ORDERING
94
95func (lei *labelEventIterator) Len() int {
96 return len(lei.cache)
97}
98
99func (lei *labelEventIterator) Swap(i, j int) {
100 lei.cache[i], lei.cache[j] = lei.cache[j], lei.cache[i]
101}
102
103func (lei *labelEventIterator) Less(i, j int) bool {
104 return lei.cache[i].ID < lei.cache[j].ID
105}