op_create.go

  1package bug
  2
  3import (
  4	"encoding/json"
  5	"fmt"
  6	"strings"
  7
  8	"github.com/MichaelMure/git-bug/entity"
  9	"github.com/MichaelMure/git-bug/identity"
 10	"github.com/MichaelMure/git-bug/repository"
 11	"github.com/MichaelMure/git-bug/util/text"
 12	"github.com/MichaelMure/git-bug/util/timestamp"
 13)
 14
 15var _ Operation = &CreateOperation{}
 16
 17// CreateOperation define the initial creation of a bug
 18type CreateOperation struct {
 19	OpBase
 20	Title   string            `json:"title"`
 21	Message string            `json:"message"`
 22	Files   []repository.Hash `json:"files"`
 23}
 24
 25// Sign-post method for gqlgen
 26func (op *CreateOperation) IsOperation() {}
 27
 28func (op *CreateOperation) base() *OpBase {
 29	return &op.OpBase
 30}
 31
 32func (op *CreateOperation) Id() entity.Id {
 33	return idOperation(op)
 34}
 35
 36func (op *CreateOperation) Apply(snapshot *Snapshot) {
 37	snapshot.addActor(op.Author)
 38	snapshot.addParticipant(op.Author)
 39
 40	snapshot.Title = op.Title
 41
 42	commentId := DeriveCommentId(snapshot.Id(), op.Id())
 43	comment := Comment{
 44		id:       commentId,
 45		Message:  op.Message,
 46		Author:   op.Author,
 47		UnixTime: timestamp.Timestamp(op.UnixTime),
 48	}
 49
 50	snapshot.Comments = []Comment{comment}
 51	snapshot.Author = op.Author
 52	snapshot.CreateTime = op.Time()
 53
 54	snapshot.Timeline = []TimelineItem{
 55		&CreateTimelineItem{
 56			CommentTimelineItem: NewCommentTimelineItem(commentId, comment),
 57		},
 58	}
 59}
 60
 61func (op *CreateOperation) GetFiles() []repository.Hash {
 62	return op.Files
 63}
 64
 65func (op *CreateOperation) Validate() error {
 66	if err := opBaseValidate(op, CreateOp); err != nil {
 67		return err
 68	}
 69
 70	if text.Empty(op.Title) {
 71		return fmt.Errorf("title is empty")
 72	}
 73
 74	if strings.Contains(op.Title, "\n") {
 75		return fmt.Errorf("title should be a single line")
 76	}
 77
 78	if !text.Safe(op.Title) {
 79		return fmt.Errorf("title is not fully printable")
 80	}
 81
 82	if !text.Safe(op.Message) {
 83		return fmt.Errorf("message is not fully printable")
 84	}
 85
 86	return nil
 87}
 88
 89// UnmarshalJSON is a two step JSON unmarshaling
 90// This workaround is necessary to avoid the inner OpBase.MarshalJSON
 91// overriding the outer op's MarshalJSON
 92func (op *CreateOperation) UnmarshalJSON(data []byte) error {
 93	// Unmarshal OpBase and the op separately
 94
 95	base := OpBase{}
 96	err := json.Unmarshal(data, &base)
 97	if err != nil {
 98		return err
 99	}
100
101	aux := struct {
102		Title   string            `json:"title"`
103		Message string            `json:"message"`
104		Files   []repository.Hash `json:"files"`
105	}{}
106
107	err = json.Unmarshal(data, &aux)
108	if err != nil {
109		return err
110	}
111
112	op.OpBase = base
113	op.Title = aux.Title
114	op.Message = aux.Message
115	op.Files = aux.Files
116
117	return nil
118}
119
120// Sign post method for gqlgen
121func (op *CreateOperation) IsAuthored() {}
122
123func NewCreateOp(author identity.Interface, unixTime int64, title, message string, files []repository.Hash) *CreateOperation {
124	return &CreateOperation{
125		OpBase:  newOpBase(CreateOp, author, unixTime),
126		Title:   title,
127		Message: message,
128		Files:   files,
129	}
130}
131
132// CreateTimelineItem replace a Create operation in the Timeline and hold its edition history
133type CreateTimelineItem struct {
134	CommentTimelineItem
135}
136
137// Sign post method for gqlgen
138func (c *CreateTimelineItem) IsAuthored() {}
139
140// Convenience function to apply the operation
141func Create(author identity.Interface, unixTime int64, title, message string) (*Bug, *CreateOperation, error) {
142	return CreateWithFiles(author, unixTime, title, message, nil)
143}
144
145func CreateWithFiles(author identity.Interface, unixTime int64, title, message string, files []repository.Hash) (*Bug, *CreateOperation, error) {
146	newBug := NewBug()
147	createOp := NewCreateOp(author, unixTime, title, message, files)
148
149	if err := createOp.Validate(); err != nil {
150		return nil, createOp, err
151	}
152
153	newBug.Append(createOp)
154
155	return newBug, createOp, nil
156}