aboutsummaryrefslogtreecommitdiffstats
path: root/operations
diff options
context:
space:
mode:
Diffstat (limited to 'operations')
-rw-r--r--operations/add_comment.go75
-rw-r--r--operations/create.go90
-rw-r--r--operations/create_test.go36
-rw-r--r--operations/label_change.go186
-rw-r--r--operations/operations.go17
-rw-r--r--operations/operations_test.go72
-rw-r--r--operations/set_status.go60
-rw-r--r--operations/set_title.go90
8 files changed, 0 insertions, 626 deletions
diff --git a/operations/add_comment.go b/operations/add_comment.go
deleted file mode 100644
index 56a2c606..00000000
--- a/operations/add_comment.go
+++ /dev/null
@@ -1,75 +0,0 @@
-package operations
-
-import (
- "fmt"
-
- "github.com/MichaelMure/git-bug/bug"
- "github.com/MichaelMure/git-bug/util/git"
- "github.com/MichaelMure/git-bug/util/text"
-)
-
-// AddCommentOperation will add a new comment in the bug
-
-var _ bug.Operation = AddCommentOperation{}
-
-type AddCommentOperation struct {
- *bug.OpBase
- Message string `json:"message"`
- // TODO: change for a map[string]util.hash to store the filename ?
- Files []git.Hash `json:"files"`
-}
-
-func (op AddCommentOperation) Apply(snapshot bug.Snapshot) bug.Snapshot {
- comment := bug.Comment{
- Message: op.Message,
- Author: op.Author,
- Files: op.Files,
- UnixTime: op.UnixTime,
- }
-
- snapshot.Comments = append(snapshot.Comments, comment)
-
- return snapshot
-}
-
-func (op AddCommentOperation) GetFiles() []git.Hash {
- return op.Files
-}
-
-func (op AddCommentOperation) Validate() error {
- if err := bug.OpBaseValidate(op, bug.AddCommentOp); err != nil {
- return err
- }
-
- if text.Empty(op.Message) {
- return fmt.Errorf("message is empty")
- }
-
- if !text.Safe(op.Message) {
- return fmt.Errorf("message is not fully printable")
- }
-
- return nil
-}
-
-func NewAddCommentOp(author bug.Person, unixTime int64, message string, files []git.Hash) AddCommentOperation {
- return AddCommentOperation{
- OpBase: bug.NewOpBase(bug.AddCommentOp, author, unixTime),
- Message: message,
- Files: files,
- }
-}
-
-// Convenience function to apply the operation
-func Comment(b bug.Interface, author bug.Person, unixTime int64, message string) error {
- return CommentWithFiles(b, author, unixTime, message, nil)
-}
-
-func CommentWithFiles(b bug.Interface, author bug.Person, unixTime int64, message string, files []git.Hash) error {
- addCommentOp := NewAddCommentOp(author, unixTime, message, files)
- if err := addCommentOp.Validate(); err != nil {
- return err
- }
- b.Append(addCommentOp)
- return nil
-}
diff --git a/operations/create.go b/operations/create.go
deleted file mode 100644
index fd66e732..00000000
--- a/operations/create.go
+++ /dev/null
@@ -1,90 +0,0 @@
-package operations
-
-import (
- "fmt"
- "strings"
-
- "github.com/MichaelMure/git-bug/bug"
- "github.com/MichaelMure/git-bug/util/git"
- "github.com/MichaelMure/git-bug/util/text"
-)
-
-// CreateOperation define the initial creation of a bug
-
-var _ bug.Operation = CreateOperation{}
-
-type CreateOperation struct {
- *bug.OpBase
- Title string `json:"title"`
- Message string `json:"message"`
- Files []git.Hash `json:"files"`
-}
-
-func (op CreateOperation) Apply(snapshot bug.Snapshot) bug.Snapshot {
- snapshot.Title = op.Title
- snapshot.Comments = []bug.Comment{
- {
- Message: op.Message,
- Author: op.Author,
- UnixTime: op.UnixTime,
- },
- }
- snapshot.Author = op.Author
- snapshot.CreatedAt = op.Time()
- return snapshot
-}
-
-func (op CreateOperation) GetFiles() []git.Hash {
- return op.Files
-}
-
-func (op CreateOperation) Validate() error {
- if err := bug.OpBaseValidate(op, bug.CreateOp); err != nil {
- return err
- }
-
- if text.Empty(op.Title) {
- return fmt.Errorf("title is empty")
- }
-
- if strings.Contains(op.Title, "\n") {
- return fmt.Errorf("title should be a single line")
- }
-
- if !text.Safe(op.Title) {
- return fmt.Errorf("title is not fully printable")
- }
-
- if !text.Safe(op.Message) {
- return fmt.Errorf("message is not fully printable")
- }
-
- return nil
-}
-
-func NewCreateOp(author bug.Person, unixTime int64, title, message string, files []git.Hash) CreateOperation {
- return CreateOperation{
- OpBase: bug.NewOpBase(bug.CreateOp, author, unixTime),
- Title: title,
- Message: message,
- Files: files,
- }
-}
-
-// Convenience function to apply the operation
-func Create(author bug.Person, unixTime int64, title, message string) (*bug.Bug, error) {
- return CreateWithFiles(author, unixTime, title, message, nil)
-}
-
-func CreateWithFiles(author bug.Person, unixTime int64, title, message string, files []git.Hash) (*bug.Bug, error) {
- newBug := bug.NewBug()
- createOp := NewCreateOp(author, unixTime, title, message, files)
-
- if err := createOp.Validate(); err != nil {
- return nil, err
- }
-
- newBug.Append(createOp)
-
- return newBug, nil
-}
diff --git a/operations/create_test.go b/operations/create_test.go
deleted file mode 100644
index c32b2868..00000000
--- a/operations/create_test.go
+++ /dev/null
@@ -1,36 +0,0 @@
-package operations
-
-import (
- "github.com/MichaelMure/git-bug/bug"
- "reflect"
- "testing"
- "time"
-)
-
-func TestCreate(t *testing.T) {
- snapshot := bug.Snapshot{}
-
- var rene = bug.Person{
- Name: "René Descartes",
- Email: "rene@descartes.fr",
- }
-
- unix := time.Now().Unix()
-
- create := NewCreateOp(rene, unix, "title", "message", nil)
-
- snapshot = create.Apply(snapshot)
-
- expected := bug.Snapshot{
- Title: "title",
- Comments: []bug.Comment{
- {Author: rene, Message: "message", UnixTime: create.UnixTime},
- },
- Author: rene,
- CreatedAt: create.Time(),
- }
-
- if !reflect.DeepEqual(snapshot, expected) {
- t.Fatalf("%v different than %v", snapshot, expected)
- }
-}
diff --git a/operations/label_change.go b/operations/label_change.go
deleted file mode 100644
index 83e3e692..00000000
--- a/operations/label_change.go
+++ /dev/null
@@ -1,186 +0,0 @@
-package operations
-
-import (
- "fmt"
- "sort"
-
- "github.com/MichaelMure/git-bug/bug"
- "github.com/pkg/errors"
-)
-
-var _ bug.Operation = LabelChangeOperation{}
-
-// LabelChangeOperation define a Bug operation to add or remove labels
-type LabelChangeOperation struct {
- *bug.OpBase
- Added []bug.Label `json:"added"`
- Removed []bug.Label `json:"removed"`
-}
-
-// Apply apply the operation
-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
-}
-
-func (op LabelChangeOperation) Validate() error {
- if err := bug.OpBaseValidate(op, bug.LabelChangeOp); err != nil {
- return err
- }
-
- for _, l := range op.Added {
- if err := l.Validate(); err != nil {
- return errors.Wrap(err, "added label")
- }
- }
-
- for _, l := range op.Removed {
- if err := l.Validate(); err != nil {
- return errors.Wrap(err, "removed label")
- }
- }
-
- if len(op.Added)+len(op.Removed) <= 0 {
- return fmt.Errorf("no label change")
- }
-
- return nil
-}
-
-func NewLabelChangeOperation(author bug.Person, unixTime int64, added, removed []bug.Label) LabelChangeOperation {
- return LabelChangeOperation{
- OpBase: bug.NewOpBase(bug.LabelChangeOp, author, unixTime),
- Added: added,
- Removed: removed,
- }
-}
-
-// ChangeLabels is a convenience function to apply the operation
-func ChangeLabels(b bug.Interface, author bug.Person, unixTime int64, add, remove []string) ([]LabelChangeResult, error) {
- var added, removed []bug.Label
- var results []LabelChangeResult
-
- snap := b.Compile()
-
- for _, str := range add {
- label := bug.Label(str)
-
- // check for duplicate
- if labelExist(added, label) {
- results = append(results, LabelChangeResult{Label: label, Status: LabelChangeDuplicateInOp})
- continue
- }
-
- // check that the label doesn't already exist
- if labelExist(snap.Labels, label) {
- results = append(results, LabelChangeResult{Label: label, Status: LabelChangeAlreadySet})
- continue
- }
-
- added = append(added, label)
- results = append(results, LabelChangeResult{Label: label, Status: LabelChangeAdded})
- }
-
- for _, str := range remove {
- label := bug.Label(str)
-
- // check for duplicate
- if labelExist(removed, label) {
- results = append(results, LabelChangeResult{Label: label, Status: LabelChangeDuplicateInOp})
- continue
- }
-
- // check that the label actually exist
- if !labelExist(snap.Labels, label) {
- results = append(results, LabelChangeResult{Label: label, Status: LabelChangeDoesntExist})
- continue
- }
-
- removed = append(removed, label)
- results = append(results, LabelChangeResult{Label: label, Status: LabelChangeRemoved})
- }
-
- if len(added) == 0 && len(removed) == 0 {
- return results, fmt.Errorf("no label added or removed")
- }
-
- labelOp := NewLabelChangeOperation(author, unixTime, added, removed)
-
- if err := labelOp.Validate(); err != nil {
- return nil, err
- }
-
- b.Append(labelOp)
-
- return results, nil
-}
-
-func labelExist(labels []bug.Label, label bug.Label) bool {
- for _, l := range labels {
- if l == label {
- return true
- }
- }
-
- return false
-}
-
-type LabelChangeStatus int
-
-const (
- _ LabelChangeStatus = iota
- LabelChangeAdded
- LabelChangeRemoved
- LabelChangeDuplicateInOp
- LabelChangeAlreadySet
- LabelChangeDoesntExist
-)
-
-type LabelChangeResult struct {
- Label bug.Label
- Status LabelChangeStatus
-}
-
-func (l LabelChangeResult) String() string {
- switch l.Status {
- case LabelChangeAdded:
- return fmt.Sprintf("label %s added", l.Label)
- case LabelChangeRemoved:
- return fmt.Sprintf("label %s removed", l.Label)
- case LabelChangeDuplicateInOp:
- return fmt.Sprintf("label %s is a duplicate", l.Label)
- case LabelChangeAlreadySet:
- return fmt.Sprintf("label %s was already set", l.Label)
- case LabelChangeDoesntExist:
- return fmt.Sprintf("label %s doesn't exist on this bug", l.Label)
- default:
- panic(fmt.Sprintf("unknown label change status %v", l.Status))
- }
-}
diff --git a/operations/operations.go b/operations/operations.go
deleted file mode 100644
index 020b8151..00000000
--- a/operations/operations.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// Package operations contains the various bug operations. A bug operation is
-// an atomic edit operation of a bug state. These operations are applied
-// sequentially to compile the current state of the bug.
-package operations
-
-import (
- "github.com/MichaelMure/git-bug/bug"
-)
-
-// Package initialisation used to register operation's type for (de)serialization
-func init() {
- bug.Register(bug.CreateOp, CreateOperation{})
- bug.Register(bug.SetTitleOp, SetTitleOperation{})
- bug.Register(bug.AddCommentOp, AddCommentOperation{})
- bug.Register(bug.SetStatusOp, SetStatusOperation{})
- bug.Register(bug.LabelChangeOp, LabelChangeOperation{})
-}
diff --git a/operations/operations_test.go b/operations/operations_test.go
deleted file mode 100644
index b94c2c0c..00000000
--- a/operations/operations_test.go
+++ /dev/null
@@ -1,72 +0,0 @@
-package operations
-
-import (
- "testing"
- "time"
-
- "github.com/MichaelMure/git-bug/bug"
- "github.com/MichaelMure/git-bug/util/git"
-)
-
-func TestValidate(t *testing.T) {
- rene := bug.Person{
- Name: "René Descartes",
- Email: "rene@descartes.fr",
- }
-
- unix := time.Now().Unix()
-
- good := []bug.Operation{
- NewCreateOp(rene, unix, "title", "message", nil),
- NewSetTitleOp(rene, unix, "title2", "title1"),
- NewAddCommentOp(rene, unix, "message2", nil),
- NewSetStatusOp(rene, unix, bug.ClosedStatus),
- NewLabelChangeOperation(rene, unix, []bug.Label{"added"}, []bug.Label{"removed"}),
- }
-
- for _, op := range good {
- if err := op.Validate(); err != nil {
- t.Fatal(err)
- }
- }
-
- bad := []bug.Operation{
- // opbase
- NewSetStatusOp(bug.Person{Name: "", Email: "rene@descartes.fr"}, unix, bug.ClosedStatus),
- NewSetStatusOp(bug.Person{Name: "René Descartes\u001b", Email: "rene@descartes.fr"}, unix, bug.ClosedStatus),
- NewSetStatusOp(bug.Person{Name: "René Descartes", Email: "rene@descartes.fr\u001b"}, unix, bug.ClosedStatus),
- NewSetStatusOp(bug.Person{Name: "René \nDescartes", Email: "rene@descartes.fr"}, unix, bug.ClosedStatus),
- NewSetStatusOp(bug.Person{Name: "René Descartes", Email: "rene@\ndescartes.fr"}, unix, bug.ClosedStatus),
- CreateOperation{OpBase: &bug.OpBase{
- Author: rene,
- UnixTime: 0,
- OperationType: bug.CreateOp,
- },
- Title: "title",
- Message: "message",
- },
-
- NewCreateOp(rene, unix, "multi\nline", "message", nil),
- NewCreateOp(rene, unix, "title", "message", []git.Hash{git.Hash("invalid")}),
- NewCreateOp(rene, unix, "title\u001b", "message", nil),
- NewCreateOp(rene, unix, "title", "message\u001b", nil),
- NewSetTitleOp(rene, unix, "multi\nline", "title1"),
- NewSetTitleOp(rene, unix, "title", "multi\nline"),
- NewSetTitleOp(rene, unix, "title\u001b", "title2"),
- NewSetTitleOp(rene, unix, "title", "title2\u001b"),
- NewAddCommentOp(rene, unix, "", nil),
- NewAddCommentOp(rene, unix, "message\u001b", nil),
- NewAddCommentOp(rene, unix, "message", []git.Hash{git.Hash("invalid")}),
- NewSetStatusOp(rene, unix, 1000),
- NewSetStatusOp(rene, unix, 0),
- NewLabelChangeOperation(rene, unix, []bug.Label{}, []bug.Label{}),
- NewLabelChangeOperation(rene, unix, []bug.Label{"multi\nline"}, []bug.Label{}),
- }
-
- for i, op := range bad {
- if err := op.Validate(); err == nil {
- t.Fatal("validation should have failed", i, op)
- }
- }
-
-}
diff --git a/operations/set_status.go b/operations/set_status.go
deleted file mode 100644
index 3e7eae4a..00000000
--- a/operations/set_status.go
+++ /dev/null
@@ -1,60 +0,0 @@
-package operations
-
-import (
- "github.com/MichaelMure/git-bug/bug"
- "github.com/pkg/errors"
-)
-
-// SetStatusOperation will change the status of a bug
-
-var _ bug.Operation = SetStatusOperation{}
-
-type SetStatusOperation struct {
- *bug.OpBase
- Status bug.Status `json:"status"`
-}
-
-func (op SetStatusOperation) Apply(snapshot bug.Snapshot) bug.Snapshot {
- snapshot.Status = op.Status
-
- return snapshot
-}
-
-func (op SetStatusOperation) Validate() error {
- if err := bug.OpBaseValidate(op, bug.SetStatusOp); err != nil {
- return err
- }
-
- if err := op.Status.Validate(); err != nil {
- return errors.Wrap(err, "status")
- }
-
- return nil
-}
-
-func NewSetStatusOp(author bug.Person, unixTime int64, status bug.Status) SetStatusOperation {
- return SetStatusOperation{
- OpBase: bug.NewOpBase(bug.SetStatusOp, author, unixTime),
- Status: status,
- }
-}
-
-// Convenience function to apply the operation
-func Open(b bug.Interface, author bug.Person, unixTime int64) error {
- op := NewSetStatusOp(author, unixTime, bug.OpenStatus)
- if err := op.Validate(); err != nil {
- return err
- }
- b.Append(op)
- return nil
-}
-
-// Convenience function to apply the operation
-func Close(b bug.Interface, author bug.Person, unixTime int64) error {
- op := NewSetStatusOp(author, unixTime, bug.ClosedStatus)
- if err := op.Validate(); err != nil {
- return err
- }
- b.Append(op)
- return nil
-}
diff --git a/operations/set_title.go b/operations/set_title.go
deleted file mode 100644
index e6964a65..00000000
--- a/operations/set_title.go
+++ /dev/null
@@ -1,90 +0,0 @@
-package operations
-
-import (
- "fmt"
- "strings"
-
- "github.com/MichaelMure/git-bug/bug"
- "github.com/MichaelMure/git-bug/util/text"
-)
-
-// SetTitleOperation will change the title of a bug
-
-var _ bug.Operation = SetTitleOperation{}
-
-type SetTitleOperation struct {
- *bug.OpBase
- Title string `json:"title"`
- Was string `json:"was"`
-}
-
-func (op SetTitleOperation) Apply(snapshot bug.Snapshot) bug.Snapshot {
- snapshot.Title = op.Title
-
- return snapshot
-}
-
-func (op SetTitleOperation) Validate() error {
- if err := bug.OpBaseValidate(op, bug.SetTitleOp); err != nil {
- return err
- }
-
- if text.Empty(op.Title) {
- return fmt.Errorf("title is empty")
- }
-
- if strings.Contains(op.Title, "\n") {
- return fmt.Errorf("title should be a single line")
- }
-
- if !text.Safe(op.Title) {
- return fmt.Errorf("title should be fully printable")
- }
-
- if strings.Contains(op.Was, "\n") {
- return fmt.Errorf("previous title should be a single line")
- }
-
- if !text.Safe(op.Was) {
- return fmt.Errorf("previous title should be fully printable")
- }
-
- return nil
-}
-
-func NewSetTitleOp(author bug.Person, unixTime int64, title string, was string) SetTitleOperation {
- return SetTitleOperation{
- OpBase: bug.NewOpBase(bug.SetTitleOp, author, unixTime),
- Title: title,
- Was: was,
- }
-}
-
-// Convenience function to apply the operation
-func SetTitle(b bug.Interface, author bug.Person, unixTime int64, title string) error {
- it := bug.NewOperationIterator(b)
-
- var lastTitleOp bug.Operation
- for it.Next() {
- op := it.Value()
- if op.OpType() == bug.SetTitleOp {
- lastTitleOp = op
- }
- }
-
- var was string
- if lastTitleOp != nil {
- was = lastTitleOp.(SetTitleOperation).Title
- } else {
- was = b.FirstOp().(CreateOperation).Title
- }
-
- setTitleOp := NewSetTitleOp(author, unixTime, title, was)
-
- if err := setTitleOp.Validate(); err != nil {
- return err
- }
-
- b.Append(setTitleOp)
- return nil
-}