op_edit_comment.go

  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, err := item.Hash()
 37
 38		if err != nil {
 39			// Should never happen, we control what goes into the timeline
 40			panic(err)
 41		}
 42
 43		if h == op.Target {
 44			target = snapshot.Timeline[i]
 45			break
 46		}
 47
 48		// Track the index in the []Comment
 49		switch item.(type) {
 50		case *CreateTimelineItem, *CommentTimelineItem:
 51			commentIndex++
 52		}
 53	}
 54
 55	if target == nil {
 56		// Target not found, edit is a no-op
 57		return
 58	}
 59
 60	comment := Comment{
 61		Message:  op.Message,
 62		Files:    op.Files,
 63		UnixTime: Timestamp(op.UnixTime),
 64	}
 65
 66	switch target.(type) {
 67	case *CreateTimelineItem:
 68		item := target.(*CreateTimelineItem)
 69		item.Append(comment)
 70
 71	case *CommentTimelineItem:
 72		item := target.(*CommentTimelineItem)
 73		item.Append(comment)
 74	}
 75
 76	snapshot.Comments[commentIndex].Message = op.Message
 77	snapshot.Comments[commentIndex].Files = op.Files
 78}
 79
 80func (op *EditCommentOperation) GetFiles() []git.Hash {
 81	return op.Files
 82}
 83
 84func (op *EditCommentOperation) Validate() error {
 85	if err := opBaseValidate(op, EditCommentOp); err != nil {
 86		return err
 87	}
 88
 89	if !op.Target.IsValid() {
 90		return fmt.Errorf("target hash is invalid")
 91	}
 92
 93	if text.Empty(op.Message) {
 94		return fmt.Errorf("message is empty")
 95	}
 96
 97	if !text.Safe(op.Message) {
 98		return fmt.Errorf("message is not fully printable")
 99	}
100
101	return nil
102}
103
104func NewEditCommentOp(author Person, unixTime int64, target git.Hash, message string, files []git.Hash) *EditCommentOperation {
105	return &EditCommentOperation{
106		OpBase:  newOpBase(EditCommentOp, author, unixTime),
107		Target:  target,
108		Message: message,
109		Files:   files,
110	}
111}
112
113// Convenience function to apply the operation
114func EditComment(b Interface, author Person, unixTime int64, target git.Hash, message string) error {
115	return EditCommentWithFiles(b, author, unixTime, target, message, nil)
116}
117
118func EditCommentWithFiles(b Interface, author Person, unixTime int64, target git.Hash, message string, files []git.Hash) error {
119	editCommentOp := NewEditCommentOp(author, unixTime, target, message, files)
120	if err := editCommentOp.Validate(); err != nil {
121		return err
122	}
123	b.Append(editCommentOp)
124	return nil
125}