op_add_comment.go

  1package bug
  2
  3import (
  4	"encoding/json"
  5	"fmt"
  6
  7	"github.com/MichaelMure/git-bug/entity"
  8	"github.com/MichaelMure/git-bug/entity/dag"
  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 = &AddCommentOperation{}
 16var _ dag.OperationWithFiles = &AddCommentOperation{}
 17
 18// AddCommentOperation will add a new comment in the bug
 19type AddCommentOperation struct {
 20	OpBase
 21	Message string `json:"message"`
 22	// TODO: change for a map[string]util.hash to store the filename ?
 23	Files []repository.Hash `json:"files"`
 24}
 25
 26func (op *AddCommentOperation) Id() entity.Id {
 27	return idOperation(op, &op.OpBase)
 28}
 29
 30func (op *AddCommentOperation) Apply(snapshot *Snapshot) {
 31	snapshot.addActor(op.Author_)
 32	snapshot.addParticipant(op.Author_)
 33
 34	comment := Comment{
 35		id:       entity.CombineIds(snapshot.Id(), op.Id()),
 36		Message:  op.Message,
 37		Author:   op.Author_,
 38		Files:    op.Files,
 39		UnixTime: timestamp.Timestamp(op.UnixTime),
 40	}
 41
 42	snapshot.Comments = append(snapshot.Comments, comment)
 43
 44	item := &AddCommentTimelineItem{
 45		CommentTimelineItem: NewCommentTimelineItem(comment),
 46	}
 47
 48	snapshot.Timeline = append(snapshot.Timeline, item)
 49}
 50
 51func (op *AddCommentOperation) GetFiles() []repository.Hash {
 52	return op.Files
 53}
 54
 55func (op *AddCommentOperation) Validate() error {
 56	if err := op.OpBase.Validate(op, AddCommentOp); err != nil {
 57		return err
 58	}
 59
 60	if !text.Safe(op.Message) {
 61		return fmt.Errorf("message is not fully printable")
 62	}
 63
 64	return nil
 65}
 66
 67// UnmarshalJSON is a two-steps JSON unmarshalling
 68// This workaround is necessary to avoid the inner OpBase.MarshalJSON
 69// overriding the outer op's MarshalJSON
 70func (op *AddCommentOperation) UnmarshalJSON(data []byte) error {
 71	// Unmarshal OpBase and the op separately
 72
 73	base := OpBase{}
 74	err := json.Unmarshal(data, &base)
 75	if err != nil {
 76		return err
 77	}
 78
 79	aux := struct {
 80		Message string            `json:"message"`
 81		Files   []repository.Hash `json:"files"`
 82	}{}
 83
 84	err = json.Unmarshal(data, &aux)
 85	if err != nil {
 86		return err
 87	}
 88
 89	op.OpBase = base
 90	op.Message = aux.Message
 91	op.Files = aux.Files
 92
 93	return nil
 94}
 95
 96// Sign post method for gqlgen
 97func (op *AddCommentOperation) IsAuthored() {}
 98
 99func NewAddCommentOp(author identity.Interface, unixTime int64, message string, files []repository.Hash) *AddCommentOperation {
100	return &AddCommentOperation{
101		OpBase:  newOpBase(AddCommentOp, author, unixTime),
102		Message: message,
103		Files:   files,
104	}
105}
106
107// CreateTimelineItem replace a AddComment operation in the Timeline and hold its edition history
108type AddCommentTimelineItem struct {
109	CommentTimelineItem
110}
111
112// Sign post method for gqlgen
113func (a *AddCommentTimelineItem) IsAuthored() {}
114
115// Convenience function to apply the operation
116func AddComment(b Interface, author identity.Interface, unixTime int64, message string) (*AddCommentOperation, error) {
117	return AddCommentWithFiles(b, author, unixTime, message, nil)
118}
119
120func AddCommentWithFiles(b Interface, author identity.Interface, unixTime int64, message string, files []repository.Hash) (*AddCommentOperation, error) {
121	addCommentOp := NewAddCommentOp(author, unixTime, message, files)
122	if err := addCommentOp.Validate(); err != nil {
123		return nil, err
124	}
125	b.Append(addCommentOp)
126	return addCommentOp, nil
127}