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