1package bug
2
3import (
4 "encoding/json"
5 "fmt"
6
7 "github.com/MichaelMure/git-bug/entity"
8 "github.com/MichaelMure/git-bug/identity"
9 "github.com/MichaelMure/git-bug/util/git"
10 "github.com/MichaelMure/git-bug/util/text"
11 "github.com/MichaelMure/git-bug/util/timestamp"
12)
13
14var _ Operation = &AddCommentOperation{}
15
16// AddCommentOperation will add a new comment in the bug
17type AddCommentOperation struct {
18 OpBase
19 Message string `json:"message"`
20 // TODO: change for a map[string]util.hash to store the filename ?
21 Files []git.Hash `json:"files"`
22}
23
24func (op *AddCommentOperation) base() *OpBase {
25 return &op.OpBase
26}
27
28func (op *AddCommentOperation) Id() entity.Id {
29 return idOperation(op)
30}
31
32func (op *AddCommentOperation) Apply(snapshot *Snapshot) {
33 snapshot.addActor(op.Author)
34 snapshot.addParticipant(op.Author)
35
36 comment := Comment{
37 id: op.Id(),
38 Message: op.Message,
39 Author: op.Author,
40 Files: op.Files,
41 UnixTime: timestamp.Timestamp(op.UnixTime),
42 }
43
44 snapshot.Comments = append(snapshot.Comments, comment)
45
46 item := &AddCommentTimelineItem{
47 CommentTimelineItem: NewCommentTimelineItem(op.Id(), comment),
48 }
49
50 snapshot.Timeline = append(snapshot.Timeline, item)
51}
52
53func (op *AddCommentOperation) GetFiles() []git.Hash {
54 return op.Files
55}
56
57func (op *AddCommentOperation) Validate() error {
58 if err := opBaseValidate(op, AddCommentOp); err != nil {
59 return err
60 }
61
62 if !text.Safe(op.Message) {
63 return fmt.Errorf("message is not fully printable")
64 }
65
66 return nil
67}
68
69// UnmarshalJSON is a two step JSON unmarshaling
70// This workaround is necessary to avoid the inner OpBase.MarshalJSON
71// overriding the outer op's MarshalJSON
72func (op *AddCommentOperation) UnmarshalJSON(data []byte) error {
73 // Unmarshal OpBase and the op separately
74
75 base := OpBase{}
76 err := json.Unmarshal(data, &base)
77 if err != nil {
78 return err
79 }
80
81 aux := struct {
82 Message string `json:"message"`
83 Files []git.Hash `json:"files"`
84 }{}
85
86 err = json.Unmarshal(data, &aux)
87 if err != nil {
88 return err
89 }
90
91 op.OpBase = base
92 op.Message = aux.Message
93 op.Files = aux.Files
94
95 return nil
96}
97
98// Sign post method for gqlgen
99func (op *AddCommentOperation) IsAuthored() {}
100
101func NewAddCommentOp(author identity.Interface, unixTime int64, message string, files []git.Hash) *AddCommentOperation {
102 return &AddCommentOperation{
103 OpBase: newOpBase(AddCommentOp, author, unixTime),
104 Message: message,
105 Files: files,
106 }
107}
108
109// CreateTimelineItem replace a AddComment operation in the Timeline and hold its edition history
110type AddCommentTimelineItem struct {
111 CommentTimelineItem
112}
113
114// Sign post method for gqlgen
115func (a *AddCommentTimelineItem) IsAuthored() {}
116
117// Convenience function to apply the operation
118func AddComment(b Interface, author identity.Interface, unixTime int64, message string) (*AddCommentOperation, error) {
119 return AddCommentWithFiles(b, author, unixTime, message, nil)
120}
121
122func AddCommentWithFiles(b Interface, author identity.Interface, unixTime int64, message string, files []git.Hash) (*AddCommentOperation, error) {
123 addCommentOp := NewAddCommentOp(author, unixTime, message, files)
124 if err := addCommentOp.Validate(); err != nil {
125 return nil, err
126 }
127 b.Append(addCommentOp)
128 return addCommentOp, nil
129}