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
24// Sign-post method for gqlgen
25func (op *AddCommentOperation) IsOperation() {}
26
27func (op *AddCommentOperation) base() *OpBase {
28 return &op.OpBase
29}
30
31func (op *AddCommentOperation) Id() entity.Id {
32 return idOperation(op)
33}
34
35func (op *AddCommentOperation) Apply(snapshot *Snapshot) {
36 snapshot.addActor(op.Author)
37 snapshot.addParticipant(op.Author)
38
39 comment := Comment{
40 id: op.Id(),
41 Message: op.Message,
42 Author: op.Author,
43 Files: op.Files,
44 UnixTime: timestamp.Timestamp(op.UnixTime),
45 }
46
47 snapshot.Comments = append(snapshot.Comments, comment)
48
49 item := &AddCommentTimelineItem{
50 CommentTimelineItem: NewCommentTimelineItem(op.Id(), comment),
51 }
52
53 snapshot.Timeline = append(snapshot.Timeline, item)
54}
55
56func (op *AddCommentOperation) GetFiles() []git.Hash {
57 return op.Files
58}
59
60func (op *AddCommentOperation) Validate() error {
61 if err := opBaseValidate(op, AddCommentOp); err != nil {
62 return err
63 }
64
65 if !text.Safe(op.Message) {
66 return fmt.Errorf("message is not fully printable")
67 }
68
69 return nil
70}
71
72// UnmarshalJSON is a two step JSON unmarshaling
73// This workaround is necessary to avoid the inner OpBase.MarshalJSON
74// overriding the outer op's MarshalJSON
75func (op *AddCommentOperation) UnmarshalJSON(data []byte) error {
76 // Unmarshal OpBase and the op separately
77
78 base := OpBase{}
79 err := json.Unmarshal(data, &base)
80 if err != nil {
81 return err
82 }
83
84 aux := struct {
85 Message string `json:"message"`
86 Files []git.Hash `json:"files"`
87 }{}
88
89 err = json.Unmarshal(data, &aux)
90 if err != nil {
91 return err
92 }
93
94 op.OpBase = base
95 op.Message = aux.Message
96 op.Files = aux.Files
97
98 return nil
99}
100
101// Sign post method for gqlgen
102func (op *AddCommentOperation) IsAuthored() {}
103
104func NewAddCommentOp(author identity.Interface, unixTime int64, message string, files []git.Hash) *AddCommentOperation {
105 return &AddCommentOperation{
106 OpBase: newOpBase(AddCommentOp, author, unixTime),
107 Message: message,
108 Files: files,
109 }
110}
111
112// CreateTimelineItem replace a AddComment operation in the Timeline and hold its edition history
113type AddCommentTimelineItem struct {
114 CommentTimelineItem
115}
116
117// Sign post method for gqlgen
118func (a *AddCommentTimelineItem) IsAuthored() {}
119
120// Convenience function to apply the operation
121func AddComment(b Interface, author identity.Interface, unixTime int64, message string) (*AddCommentOperation, error) {
122 return AddCommentWithFiles(b, author, unixTime, message, nil)
123}
124
125func OpAddComment(author identity.Interface, unixTime int64, message string) (*AddCommentOperation, error) {
126 return OpAddCommentWithFiles(author, unixTime, message, nil)
127}
128
129func AddCommentWithFiles(b Interface, author identity.Interface, unixTime int64, message string, files []git.Hash) (*AddCommentOperation, error) {
130 op, err := OpAddCommentWithFiles(author, unixTime, message, files)
131 if err != nil {
132 return nil, err
133 }
134 b.Append(op)
135 return op, nil
136}
137
138func OpAddCommentWithFiles(author identity.Interface, unixTime int64, message string, files []git.Hash) (*AddCommentOperation, error) {
139 addCommentOp := NewAddCommentOp(author, unixTime, message, files)
140 if err := addCommentOp.Validate(); err != nil {
141 return nil, err
142 }
143 return addCommentOp, nil
144}