diff options
-rw-r--r-- | bug/label.go | 4 | ||||
-rw-r--r-- | bug/operation.go | 1 | ||||
-rw-r--r-- | bug/operations/label_change.go | 56 | ||||
-rw-r--r-- | bug/operations/operations.go | 1 | ||||
-rw-r--r-- | commands/command.go | 1 | ||||
-rw-r--r-- | commands/label.go | 108 | ||||
-rw-r--r-- | commands/show.go | 11 | ||||
-rw-r--r-- | tests/operation_iterator_test.go | 5 |
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) } } |