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