1package bug
  2
  3import (
  4	"fmt"
  5
  6	"github.com/git-bug/git-bug/entities/identity"
  7	"github.com/git-bug/git-bug/entity"
  8	"github.com/git-bug/git-bug/entity/dag"
  9	"github.com/git-bug/git-bug/repository"
 10	"github.com/git-bug/git-bug/util/text"
 11	"github.com/git-bug/git-bug/util/timestamp"
 12)
 13
 14var _ Operation = &AddCommentOperation{}
 15var _ dag.OperationWithFiles = &AddCommentOperation{}
 16
 17// AddCommentOperation will add a new comment in the bug
 18type AddCommentOperation struct {
 19	dag.OpBase
 20	Message string `json:"message"`
 21	// TODO: change for a map[string]util.hash to store the filename ?
 22	Files []repository.Hash `json:"files"`
 23}
 24
 25func (op *AddCommentOperation) Id() entity.Id {
 26	return dag.IdOperation(op, &op.OpBase)
 27}
 28
 29func (op *AddCommentOperation) Apply(snapshot *Snapshot) {
 30	snapshot.addActor(op.Author())
 31	snapshot.addParticipant(op.Author())
 32
 33	opId := op.Id()
 34
 35	comment := Comment{
 36		combinedId: entity.CombineIds(snapshot.Id(), opId),
 37		targetId:   opId,
 38		Message:    op.Message,
 39		Author:     op.Author(),
 40		Files:      op.Files,
 41		unixTime:   timestamp.Timestamp(op.UnixTime),
 42	}
 43
 44	snapshot.Comments = append(snapshot.Comments, comment)
 45
 46	item := &AddCommentTimelineItem{
 47		CommentTimelineItem: NewCommentTimelineItem(comment),
 48	}
 49
 50	snapshot.Timeline = append(snapshot.Timeline, item)
 51}
 52
 53func (op *AddCommentOperation) GetFiles() []repository.Hash {
 54	return op.Files
 55}
 56
 57func (op *AddCommentOperation) Validate() error {
 58	if err := op.OpBase.Validate(op, AddCommentOp); err != nil {
 59		return err
 60	}
 61
 62	if !text.Safe(op.Message) {
 63		return fmt.Errorf("message is not fully printable")
 64	}
 65
 66	for _, file := range op.Files {
 67		if !file.IsValid() {
 68			return fmt.Errorf("invalid file hash")
 69		}
 70	}
 71
 72	return nil
 73}
 74
 75func NewAddCommentOp(author identity.Interface, unixTime int64, message string, files []repository.Hash) *AddCommentOperation {
 76	return &AddCommentOperation{
 77		OpBase:  dag.NewOpBase(AddCommentOp, author, unixTime),
 78		Message: message,
 79		Files:   files,
 80	}
 81}
 82
 83// AddCommentTimelineItem replace a AddComment operation in the Timeline and hold its edition history
 84type AddCommentTimelineItem struct {
 85	CommentTimelineItem
 86}
 87
 88// IsAuthored is a sign post method for gqlgen
 89func (a *AddCommentTimelineItem) IsAuthored() {}
 90
 91// AddComment is a convenience function to add a comment to a bug
 92func AddComment(b ReadWrite, author identity.Interface, unixTime int64, message string, files []repository.Hash, metadata map[string]string) (entity.CombinedId, *AddCommentOperation, error) {
 93	op := NewAddCommentOp(author, unixTime, message, files)
 94	for key, val := range metadata {
 95		op.SetMetadata(key, val)
 96	}
 97	if err := op.Validate(); err != nil {
 98		return entity.UnsetCombinedId, nil, err
 99	}
100	b.Append(op)
101	return entity.CombineIds(b.Id(), op.Id()), op, nil
102}