aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bug/label.go4
-rw-r--r--bug/operation.go1
-rw-r--r--bug/operations/label_change.go56
-rw-r--r--bug/operations/operations.go1
-rw-r--r--commands/command.go1
-rw-r--r--commands/label.go108
-rw-r--r--commands/show.go11
-rw-r--r--tests/operation_iterator_test.go5
8 files changed, 184 insertions, 3 deletions
diff --git a/bug/label.go b/bug/label.go
index c202cd70..889bf455 100644
--- a/bug/label.go
+++ b/bug/label.go
@@ -1,3 +1,7 @@
package bug
type Label string
+
+func (l Label) String() string {
+ return string(l)
+}
diff --git a/bug/operation.go b/bug/operation.go
index 15374f08..9e31637a 100644
--- a/bug/operation.go
+++ b/bug/operation.go
@@ -10,6 +10,7 @@ const (
SetTitleOp
AddCommentOp
SetStatusOp
+ LabelChangeOp
)
type Operation interface {
diff --git a/bug/operations/label_change.go b/bug/operations/label_change.go
new file mode 100644
index 00000000..ca07f6f5
--- /dev/null
+++ b/bug/operations/label_change.go
@@ -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
+}
diff --git a/bug/operations/operations.go b/bug/operations/operations.go
index 50692952..0bfd3b84 100644
--- a/bug/operations/operations.go
+++ b/bug/operations/operations.go
@@ -8,4 +8,5 @@ func init() {
gob.Register(CreateOperation{})
gob.Register(SetTitleOperation{})
gob.Register(SetStatusOperation{})
+ gob.Register(LabelChangeOperation{})
}
diff --git a/commands/command.go b/commands/command.go
index 30f86848..89420b46 100644
--- a/commands/command.go
+++ b/commands/command.go
@@ -47,6 +47,7 @@ func init() {
"close": closeCmd,
"commands": commandsCmd,
"comment": commentCmd,
+ "label": labelCmd,
"ls": lsCmd,
"new": newCmd,
"open": openCmd,
diff --git a/commands/label.go b/commands/label.go
new file mode 100644
index 00000000..ad3a388b
--- /dev/null
+++ b/commands/label.go
@@ -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,
+}
diff --git a/commands/show.go b/commands/show.go
index a8414384..c5a043c7 100644
--- a/commands/show.go
+++ b/commands/show.go
@@ -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 := " "
diff --git a/tests/operation_iterator_test.go b/tests/operation_iterator_test.go
index 66e1ca1b..bcbcfb08 100644
--- a/tests/operation_iterator_test.go
+++ b/tests/operation_iterator_test.go
@@ -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)
}
}