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	commentId := entity.CombineIds(snapshot.Id(), op.Id())
 35	comment := Comment{
 36		id:       commentId,
 37		Message:  op.Message,
 38		Author:   op.Author_,
 39		Files:    op.Files,
 40		UnixTime: timestamp.Timestamp(op.UnixTime),
 41	}
 42
 43	snapshot.Comments = append(snapshot.Comments, comment)
 44
 45	item := &AddCommentTimelineItem{
 46		CommentTimelineItem: NewCommentTimelineItem(commentId, comment),
 47	}
 48
 49	snapshot.Timeline = append(snapshot.Timeline, item)
 50}
 51
 52func (op *AddCommentOperation) GetFiles() []repository.Hash {
 53	return op.Files
 54}
 55
 56func (op *AddCommentOperation) Validate() error {
 57	if err := op.OpBase.Validate(op, AddCommentOp); err != nil {
 58		return err
 59	}
 60
 61	if !text.Safe(op.Message) {
 62		return fmt.Errorf("message is not fully printable")
 63	}
 64
 65	return nil
 66}
 67
 68// UnmarshalJSON is a two step JSON unmarshalling
 69// This workaround is necessary to avoid the inner OpBase.MarshalJSON
 70// overriding the outer op's MarshalJSON
 71func (op *AddCommentOperation) UnmarshalJSON(data []byte) error {
 72	// Unmarshal OpBase and the op separately
 73
 74	base := OpBase{}
 75	err := json.Unmarshal(data, &base)
 76	if err != nil {
 77		return err
 78	}
 79
 80	aux := struct {
 81		Message string            `json:"message"`
 82		Files   []repository.Hash `json:"files"`
 83	}{}
 84
 85	err = json.Unmarshal(data, &aux)
 86	if err != nil {
 87		return err
 88	}
 89
 90	op.OpBase = base
 91	op.Message = aux.Message
 92	op.Files = aux.Files
 93
 94	return nil
 95}
 96
 97// Sign post method for gqlgen
 98func (op *AddCommentOperation) IsAuthored() {}
 99
100func NewAddCommentOp(author identity.Interface, unixTime int64, message string, files []repository.Hash) *AddCommentOperation {
101	return &AddCommentOperation{
102		OpBase:  newOpBase(AddCommentOp, author, unixTime),
103		Message: message,
104		Files:   files,
105	}
106}
107
108// CreateTimelineItem replace a AddComment operation in the Timeline and hold its edition history
109type AddCommentTimelineItem struct {
110	CommentTimelineItem
111}
112
113// Sign post method for gqlgen
114func (a *AddCommentTimelineItem) IsAuthored() {}
115
116// Convenience function to apply the operation
117func AddComment(b Interface, author identity.Interface, unixTime int64, message string) (*AddCommentOperation, error) {
118	return AddCommentWithFiles(b, author, unixTime, message, nil)
119}
120
121func AddCommentWithFiles(b Interface, author identity.Interface, unixTime int64, message string, files []repository.Hash) (*AddCommentOperation, error) {
122	addCommentOp := NewAddCommentOp(author, unixTime, message, files)
123	if err := addCommentOp.Validate(); err != nil {
124		return nil, err
125	}
126	b.Append(addCommentOp)
127	return addCommentOp, nil
128}