1package bug
2
3import (
4 "encoding/json"
5
6 "github.com/pkg/errors"
7
8 "github.com/MichaelMure/git-bug/entity"
9 "github.com/MichaelMure/git-bug/identity"
10)
11
12var _ Operation = &SetMetadataOperation{}
13
14type SetMetadataOperation struct {
15 OpBase
16 Target entity.Id `json:"target"`
17 NewMetadata map[string]string `json:"new_metadata"`
18}
19
20func (op *SetMetadataOperation) base() *OpBase {
21 return &op.OpBase
22}
23
24func (op *SetMetadataOperation) Id() entity.Id {
25 return idOperation(op)
26}
27
28func (op *SetMetadataOperation) Apply(snapshot *Snapshot) {
29 for _, target := range snapshot.Operations {
30 if target.Id() == op.Target {
31 base := target.base()
32
33 if base.extraMetadata == nil {
34 base.extraMetadata = make(map[string]string)
35 }
36
37 for key, val := range op.NewMetadata {
38 if _, exist := base.extraMetadata[key]; !exist {
39 base.extraMetadata[key] = val
40 }
41 }
42
43 return
44 }
45 }
46}
47
48func (op *SetMetadataOperation) Validate() error {
49 if err := opBaseValidate(op, SetMetadataOp); err != nil {
50 return err
51 }
52
53 if err := op.Target.Validate(); err != nil {
54 return errors.Wrap(err, "target invalid")
55 }
56
57 return nil
58}
59
60// UnmarshalJSON is a two step JSON unmarshaling
61// This workaround is necessary to avoid the inner OpBase.MarshalJSON
62// overriding the outer op's MarshalJSON
63func (op *SetMetadataOperation) UnmarshalJSON(data []byte) error {
64 // Unmarshal OpBase and the op separately
65
66 base := OpBase{}
67 err := json.Unmarshal(data, &base)
68 if err != nil {
69 return err
70 }
71
72 aux := struct {
73 Target entity.Id `json:"target"`
74 NewMetadata map[string]string `json:"new_metadata"`
75 }{}
76
77 err = json.Unmarshal(data, &aux)
78 if err != nil {
79 return err
80 }
81
82 op.OpBase = base
83 op.Target = aux.Target
84 op.NewMetadata = aux.NewMetadata
85
86 return nil
87}
88
89// Sign post method for gqlgen
90func (op *SetMetadataOperation) IsAuthored() {}
91
92func NewSetMetadataOp(author identity.Interface, unixTime int64, target entity.Id, newMetadata map[string]string) *SetMetadataOperation {
93 return &SetMetadataOperation{
94 OpBase: newOpBase(SetMetadataOp, author, unixTime),
95 Target: target,
96 NewMetadata: newMetadata,
97 }
98}
99
100// Convenience function to apply the operation
101func SetMetadata(b Interface, author identity.Interface, unixTime int64, target entity.Id, newMetadata map[string]string) (*SetMetadataOperation, error) {
102 SetMetadataOp := NewSetMetadataOp(author, unixTime, target, newMetadata)
103 if err := SetMetadataOp.Validate(); err != nil {
104 return nil, err
105 }
106 b.Append(SetMetadataOp)
107 return SetMetadataOp, nil
108}