1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
package operations
import (
"fmt"
"sort"
"github.com/MichaelMure/git-bug/bug"
)
var _ bug.Operation = LabelChangeOperation{}
// LabelChangeOperation define a Bug operation to add or remove labels
type LabelChangeOperation struct {
bug.OpBase
Added []bug.Label `json:"added"`
Removed []bug.Label `json:"removed"`
}
// Apply apply the operation
func (op LabelChangeOperation) Apply(snapshot bug.Snapshot) bug.Snapshot {
// Add in the set
AddLoop:
for _, added := range op.Added {
for _, label := range snapshot.Labels {
if label == added {
// Already exist
continue AddLoop
}
}
snapshot.Labels = append(snapshot.Labels, added)
}
// Remove in the set
for _, removed := range op.Removed {
for i, label := range snapshot.Labels {
if label == removed {
snapshot.Labels[i] = snapshot.Labels[len(snapshot.Labels)-1]
snapshot.Labels = snapshot.Labels[:len(snapshot.Labels)-1]
}
}
}
// Sort
sort.Slice(snapshot.Labels, func(i, j int) bool {
return string(snapshot.Labels[i]) < string(snapshot.Labels[j])
})
return snapshot
}
func NewLabelChangeOperation(author bug.Person, added, removed []bug.Label) LabelChangeOperation {
return LabelChangeOperation{
OpBase: bug.NewOpBase(bug.LabelChangeOp, author),
Added: added,
Removed: removed,
}
}
// ChangeLabels is a convenience function to apply the operation
func ChangeLabels(b bug.Interface, author bug.Person, add, remove []string) ([]LabelChangeResult, error) {
var added, removed []bug.Label
var results []LabelChangeResult
snap := b.Compile()
for _, str := range add {
label := bug.Label(str)
// check for duplicate
if labelExist(added, label) {
results = append(results, LabelChangeResult{Label: label, Status: LabelChangeDuplicateInOp})
continue
}
// check that the label doesn't already exist
if labelExist(snap.Labels, label) {
results = append(results, LabelChangeResult{Label: label, Status: LabelChangeAlreadySet})
continue
}
added = append(added, label)
results = append(results, LabelChangeResult{Label: label, Status: LabelChangeAdded})
}
for _, str := range remove {
label := bug.Label(str)
// check for duplicate
if labelExist(removed, label) {
results = append(results, LabelChangeResult{Label: label, Status: LabelChangeDuplicateInOp})
continue
}
// check that the label actually exist
if !labelExist(snap.Labels, label) {
results = append(results, LabelChangeResult{Label: label, Status: LabelChangeDoesntExist})
continue
}
removed = append(removed, label)
results = append(results, LabelChangeResult{Label: label, Status: LabelChangeRemoved})
}
if len(added) == 0 && len(removed) == 0 {
return results, fmt.Errorf("no label added or removed")
}
labelOp := NewLabelChangeOperation(author, added, removed)
b.Append(labelOp)
return results, nil
}
func labelExist(labels []bug.Label, label bug.Label) bool {
for _, l := range labels {
if l == label {
return true
}
}
return false
}
type LabelChangeStatus int
const (
_ LabelChangeStatus = iota
LabelChangeAdded
LabelChangeRemoved
LabelChangeDuplicateInOp
LabelChangeAlreadySet
LabelChangeDoesntExist
)
type LabelChangeResult struct {
Label bug.Label
Status LabelChangeStatus
}
|