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