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}