bug/label.go 🔗
@@ -1,3 +1,7 @@
package bug
type Label string
+
+func (l Label) String() string {
+ return string(l)
+}
Michael Muré created
bug/label.go | 4 +
bug/operation.go | 1
bug/operations/label_change.go | 56 +++++++++++++++++
bug/operations/operations.go | 1
commands/command.go | 1
commands/label.go | 108 ++++++++++++++++++++++++++++++++++
commands/show.go | 11 ++
tests/operation_iterator_test.go | 5 +
8 files changed, 184 insertions(+), 3 deletions(-)
@@ -1,3 +1,7 @@
package bug
type Label string
+
+func (l Label) String() string {
+ return string(l)
+}
@@ -10,6 +10,7 @@ const (
SetTitleOp
AddCommentOp
SetStatusOp
+ LabelChangeOp
)
type Operation interface {
@@ -0,0 +1,56 @@
+package operations
+
+import (
+ "github.com/MichaelMure/git-bug/bug"
+ "sort"
+)
+
+// LabelChangeOperation will add or remove a set of labels
+
+var _ bug.Operation = LabelChangeOperation{}
+
+type LabelChangeOperation struct {
+ bug.OpBase
+ Added []bug.Label
+ Removed []bug.Label
+}
+
+func NewLabelChangeOperation(author bug.Person, added, removed []bug.Label) LabelChangeOperation {
+ return LabelChangeOperation{
+ OpBase: bug.NewOpBase(bug.LabelChangeOp, author),
+ Added: added,
+ Removed: removed,
+ }
+}
+
+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
+}
@@ -8,4 +8,5 @@ func init() {
gob.Register(CreateOperation{})
gob.Register(SetTitleOperation{})
gob.Register(SetStatusOperation{})
+ gob.Register(LabelChangeOperation{})
}
@@ -47,6 +47,7 @@ func init() {
"close": closeCmd,
"commands": commandsCmd,
"comment": commentCmd,
+ "label": labelCmd,
"ls": lsCmd,
"new": newCmd,
"open": openCmd,
@@ -0,0 +1,108 @@
+package commands
+
+import (
+ "errors"
+ "flag"
+ "fmt"
+ "github.com/MichaelMure/git-bug/bug"
+ "github.com/MichaelMure/git-bug/bug/operations"
+ "github.com/MichaelMure/git-bug/repository"
+)
+
+var labelFlagSet = flag.NewFlagSet("label", flag.ExitOnError)
+
+var (
+ labelRemove = newFlagSet.Bool("r", false, "Remove a label")
+)
+
+func runLabel(repo repository.Repo, args []string) error {
+ labelFlagSet.Parse(args)
+ args = labelFlagSet.Args()
+
+ if len(args) == 0 {
+ return errors.New("You must provide a bug id")
+ }
+
+ if len(args) == 1 {
+ return errors.New("You must provide a label")
+ }
+
+ prefix := args[0]
+
+ b, err := bug.FindBug(repo, prefix)
+ if err != nil {
+ return err
+ }
+
+ author, err := bug.GetUser(repo)
+ if err != nil {
+ return err
+ }
+
+ var added, removed []bug.Label
+
+ snap := b.Compile()
+
+ for _, arg := range args[1:] {
+ label := bug.Label(arg)
+
+ if *labelRemove {
+ // check for duplicate
+ if labelExist(removed, label) {
+ fmt.Printf("label \"%s\" is a duplicate\n", arg)
+ continue
+ }
+
+ // check that the label actually exist
+ if !labelExist(snap.Labels, label) {
+ fmt.Printf("label \"%s\" doesn't exist on this bug\n", arg)
+ continue
+ }
+
+ removed = append(removed, label)
+ } else {
+ // check for duplicate
+ if labelExist(added, label) {
+ fmt.Printf("label \"%s\" is a duplicate\n", arg)
+ continue
+ }
+
+ // check that the label doesn't already exist
+ if labelExist(snap.Labels, label) {
+ fmt.Printf("label \"%s\" is already set on this bug\n", arg)
+ continue
+ }
+
+ added = append(added, label)
+ }
+ }
+
+ if len(added) == 0 && len(removed) == 0 {
+ return errors.New("no label added or removed")
+ }
+
+ labelOp := operations.NewLabelChangeOperation(author, added, removed)
+
+ b.Append(labelOp)
+
+ err = b.Commit(repo)
+
+ return err
+}
+
+func labelExist(labels []bug.Label, label bug.Label) bool {
+ for _, l := range labels {
+ if l == label {
+ return true
+ }
+ }
+
+ return false
+}
+
+var labelCmd = &Command{
+ Description: "Manipulate bug's label",
+ Usage: "<id> [<option>...] [<label>...]",
+ flagSet: labelFlagSet,
+ RunMethod: runLabel,
+}
@@ -9,8 +9,6 @@ import (
"strings"
)
-var line = strings.Repeat("-", 50)
-
func runShowBug(repo repository.Repo, args []string) error {
if len(args) > 1 {
return errors.New("Only showing one bug at a time is supported")
@@ -47,6 +45,15 @@ func runShowBug(repo repository.Repo, args []string) error {
firstComment.FormatTime(),
)
+ var labels = make([]string, len(snapshot.Labels))
+ for i := range snapshot.Labels {
+ labels[i] = string(snapshot.Labels[i])
+ }
+
+ fmt.Printf("labels: %s\n\n",
+ strings.Join(labels, ", "),
+ )
+
// Comments
indent := " "
@@ -17,6 +17,7 @@ var (
setTitleOp = operations.NewSetTitleOp(rene, "title2")
addCommentOp = operations.NewAddCommentOp(rene, "message2")
setStatusOp = operations.NewSetStatusOp(rene, bug.ClosedStatus)
+ labelChangeOp = operations.NewLabelChangeOperation(rene, []bug.Label{"added"}, []bug.Label{"removed"})
mockRepo = repository.NewMockRepoForTest()
)
@@ -30,7 +31,9 @@ func TestOpIterator(t *testing.T) {
bug1.Append(createOp)
bug1.Append(setTitleOp)
+ bug1.Append(addCommentOp)
bug1.Append(setStatusOp)
+ bug1.Append(labelChangeOp)
bug1.Commit(mockRepo)
bug1.Append(setTitleOp)
@@ -50,7 +53,7 @@ func TestOpIterator(t *testing.T) {
counter++
}
- if counter != 9 {
+ if counter != 11 {
t.Fatalf("Wrong count of value iterated (%d instead of 8)", counter)
}
}