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