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 switch target.(type) {
61 case *CreateTimelineItem:
62 item := target.(*CreateTimelineItem)
63 newComment := item.LastState()
64 newComment.Message = op.Message
65 item.History = append(item.History, newComment)
66
67 case *CommentTimelineItem:
68 item := target.(*CommentTimelineItem)
69 newComment := item.LastState()
70 newComment.Message = op.Message
71 item.History = append(item.History, newComment)
72 }
73
74 snapshot.Comments[commentIndex].Message = op.Message
75 snapshot.Comments[commentIndex].Files = op.Files
76}
77
78func (op *EditCommentOperation) GetFiles() []git.Hash {
79 return op.Files
80}
81
82func (op *EditCommentOperation) Validate() error {
83 if err := opBaseValidate(op, EditCommentOp); err != nil {
84 return err
85 }
86
87 if !op.Target.IsValid() {
88 return fmt.Errorf("target hash is invalid")
89 }
90
91 if text.Empty(op.Message) {
92 return fmt.Errorf("message is empty")
93 }
94
95 if !text.Safe(op.Message) {
96 return fmt.Errorf("message is not fully printable")
97 }
98
99 return nil
100}
101
102func NewEditCommentOp(author Person, unixTime int64, target git.Hash, message string, files []git.Hash) *EditCommentOperation {
103 return &EditCommentOperation{
104 OpBase: newOpBase(EditCommentOp, author, unixTime),
105 Target: target,
106 Message: message,
107 Files: files,
108 }
109}
110
111// Convenience function to apply the operation
112func EditComment(b Interface, author Person, unixTime int64, target git.Hash, message string) error {
113 return EditCommentWithFiles(b, author, unixTime, target, message, nil)
114}
115
116func EditCommentWithFiles(b Interface, author Person, unixTime int64, target git.Hash, message string, files []git.Hash) error {
117 editCommentOp := NewEditCommentOp(author, unixTime, target, message, files)
118 if err := editCommentOp.Validate(); err != nil {
119 return err
120 }
121 b.Append(editCommentOp)
122 return nil
123}