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}