op_edit_comment.go

  1package bug
  2
  3import (
  4	"fmt"
  5
  6	"github.com/MichaelMure/git-bug/identity"
  7
  8	"github.com/MichaelMure/git-bug/util/git"
  9	"github.com/MichaelMure/git-bug/util/text"
 10)
 11
 12var _ Operation = &EditCommentOperation{}
 13
 14// EditCommentOperation will change a comment in the bug
 15type EditCommentOperation struct {
 16	OpBase
 17	Target  git.Hash   `json:"target"`
 18	Message string     `json:"message"`
 19	Files   []git.Hash `json:"files"`
 20}
 21
 22func (op *EditCommentOperation) base() *OpBase {
 23	return &op.OpBase
 24}
 25
 26func (op *EditCommentOperation) Hash() (git.Hash, error) {
 27	return hashOperation(op)
 28}
 29
 30func (op *EditCommentOperation) Apply(snapshot *Snapshot) {
 31	// Todo: currently any message can be edited, even by a different author
 32	// crypto signature are needed.
 33
 34	var target TimelineItem
 35	var commentIndex int
 36
 37	for i, item := range snapshot.Timeline {
 38		h := item.Hash()
 39
 40		if h == op.Target {
 41			target = snapshot.Timeline[i]
 42			break
 43		}
 44
 45		// Track the index in the []Comment
 46		switch item.(type) {
 47		case *CreateTimelineItem, *CommentTimelineItem:
 48			commentIndex++
 49		}
 50	}
 51
 52	if target == nil {
 53		// Target not found, edit is a no-op
 54		return
 55	}
 56
 57	comment := Comment{
 58		Message:  op.Message,
 59		Files:    op.Files,
 60		UnixTime: Timestamp(op.UnixTime),
 61	}
 62
 63	switch target.(type) {
 64	case *CreateTimelineItem:
 65		item := target.(*CreateTimelineItem)
 66		item.Append(comment)
 67
 68	case *AddCommentTimelineItem:
 69		item := target.(*AddCommentTimelineItem)
 70		item.Append(comment)
 71	}
 72
 73	snapshot.Comments[commentIndex].Message = op.Message
 74	snapshot.Comments[commentIndex].Files = op.Files
 75}
 76
 77func (op *EditCommentOperation) GetFiles() []git.Hash {
 78	return op.Files
 79}
 80
 81func (op *EditCommentOperation) Validate() error {
 82	if err := opBaseValidate(op, EditCommentOp); err != nil {
 83		return err
 84	}
 85
 86	if !op.Target.IsValid() {
 87		return fmt.Errorf("target hash is invalid")
 88	}
 89
 90	if !text.Safe(op.Message) {
 91		return fmt.Errorf("message is not fully printable")
 92	}
 93
 94	return nil
 95}
 96
 97// Sign post method for gqlgen
 98func (op *EditCommentOperation) IsAuthored() {}
 99
100func NewEditCommentOp(author identity.Interface, unixTime int64, target git.Hash, message string, files []git.Hash) *EditCommentOperation {
101	return &EditCommentOperation{
102		OpBase:  newOpBase(EditCommentOp, author, unixTime),
103		Target:  target,
104		Message: message,
105		Files:   files,
106	}
107}
108
109// Convenience function to apply the operation
110func EditComment(b Interface, author identity.Interface, unixTime int64, target git.Hash, message string) (*EditCommentOperation, error) {
111	return EditCommentWithFiles(b, author, unixTime, target, message, nil)
112}
113
114func EditCommentWithFiles(b Interface, author identity.Interface, unixTime int64, target git.Hash, message string, files []git.Hash) (*EditCommentOperation, error) {
115	editCommentOp := NewEditCommentOp(author, unixTime, target, message, files)
116	if err := editCommentOp.Validate(); err != nil {
117		return nil, err
118	}
119	b.Append(editCommentOp)
120	return editCommentOp, nil
121}