aboutsummaryrefslogtreecommitdiffstats
path: root/entities/bug/op_create.go
diff options
context:
space:
mode:
Diffstat (limited to 'entities/bug/op_create.go')
-rw-r--r--entities/bug/op_create.go112
1 files changed, 112 insertions, 0 deletions
diff --git a/entities/bug/op_create.go b/entities/bug/op_create.go
new file mode 100644
index 00000000..fdfa131b
--- /dev/null
+++ b/entities/bug/op_create.go
@@ -0,0 +1,112 @@
+package bug
+
+import (
+ "fmt"
+
+ "github.com/MichaelMure/git-bug/entities/identity"
+ "github.com/MichaelMure/git-bug/entity"
+ "github.com/MichaelMure/git-bug/entity/dag"
+ "github.com/MichaelMure/git-bug/repository"
+ "github.com/MichaelMure/git-bug/util/text"
+ "github.com/MichaelMure/git-bug/util/timestamp"
+)
+
+var _ Operation = &CreateOperation{}
+var _ dag.OperationWithFiles = &CreateOperation{}
+
+// CreateOperation define the initial creation of a bug
+type CreateOperation struct {
+ dag.OpBase
+ Title string `json:"title"`
+ Message string `json:"message"`
+ Files []repository.Hash `json:"files"`
+}
+
+func (op *CreateOperation) Id() entity.Id {
+ return dag.IdOperation(op, &op.OpBase)
+}
+
+func (op *CreateOperation) Apply(snapshot *Snapshot) {
+ // sanity check: will fail when adding a second Create
+ if snapshot.id != "" && snapshot.id != entity.UnsetId && snapshot.id != op.Id() {
+ return
+ }
+
+ snapshot.id = op.Id()
+
+ snapshot.addActor(op.Author())
+ snapshot.addParticipant(op.Author())
+
+ snapshot.Title = op.Title
+
+ comment := Comment{
+ id: entity.CombineIds(snapshot.Id(), op.Id()),
+ Message: op.Message,
+ Author: op.Author(),
+ UnixTime: timestamp.Timestamp(op.UnixTime),
+ }
+
+ snapshot.Comments = []Comment{comment}
+ snapshot.Author = op.Author()
+ snapshot.CreateTime = op.Time()
+
+ snapshot.Timeline = []TimelineItem{
+ &CreateTimelineItem{
+ CommentTimelineItem: NewCommentTimelineItem(comment),
+ },
+ }
+}
+
+func (op *CreateOperation) GetFiles() []repository.Hash {
+ return op.Files
+}
+
+func (op *CreateOperation) Validate() error {
+ if err := op.OpBase.Validate(op, CreateOp); err != nil {
+ return err
+ }
+
+ if text.Empty(op.Title) {
+ return fmt.Errorf("title is empty")
+ }
+ if !text.SafeOneLine(op.Title) {
+ return fmt.Errorf("title has unsafe characters")
+ }
+
+ if !text.Safe(op.Message) {
+ return fmt.Errorf("message is not fully printable")
+ }
+
+ return nil
+}
+
+func NewCreateOp(author identity.Interface, unixTime int64, title, message string, files []repository.Hash) *CreateOperation {
+ return &CreateOperation{
+ OpBase: dag.NewOpBase(CreateOp, author, unixTime),
+ Title: title,
+ Message: message,
+ Files: files,
+ }
+}
+
+// CreateTimelineItem replace a Create operation in the Timeline and hold its edition history
+type CreateTimelineItem struct {
+ CommentTimelineItem
+}
+
+// IsAuthored is a sign post method for gqlgen
+func (c *CreateTimelineItem) IsAuthored() {}
+
+// Create is a convenience function to create a bug
+func Create(author identity.Interface, unixTime int64, title, message string, files []repository.Hash, metadata map[string]string) (*Bug, *CreateOperation, error) {
+ b := NewBug()
+ op := NewCreateOp(author, unixTime, title, message, files)
+ for key, val := range metadata {
+ op.SetMetadata(key, val)
+ }
+ if err := op.Validate(); err != nil {
+ return nil, op, err
+ }
+ b.Append(op)
+ return b, op, nil
+}