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