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