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
20// Sign-post method for gqlgen
21func (op *SetMetadataOperation) IsOperation() {}
22
23func (op *SetMetadataOperation) Id() entity.Id {
24 return idOperation(op, &op.OpBase)
25}
26
27func (op *SetMetadataOperation) Apply(snapshot *Snapshot) {
28 for _, target := range snapshot.Operations {
29 if target.Id() == op.Target {
30 // Apply the metadata in an immutable way: if a metadata already
31 // exist, it's not possible to override it.
32 for key, value := range op.NewMetadata {
33 target.setExtraMetadataImmutable(key, value)
34 }
35 return
36 }
37 }
38}
39
40func (op *SetMetadataOperation) Validate() error {
41 if err := op.OpBase.Validate(op, SetMetadataOp); err != nil {
42 return err
43 }
44
45 if err := op.Target.Validate(); err != nil {
46 return errors.Wrap(err, "target invalid")
47 }
48
49 return nil
50}
51
52// UnmarshalJSON is a two step JSON unmarshalling
53// This workaround is necessary to avoid the inner OpBase.MarshalJSON
54// overriding the outer op's MarshalJSON
55func (op *SetMetadataOperation) UnmarshalJSON(data []byte) error {
56 // Unmarshal OpBase and the op separately
57
58 base := OpBase{}
59 err := json.Unmarshal(data, &base)
60 if err != nil {
61 return err
62 }
63
64 aux := struct {
65 Target entity.Id `json:"target"`
66 NewMetadata map[string]string `json:"new_metadata"`
67 }{}
68
69 err = json.Unmarshal(data, &aux)
70 if err != nil {
71 return err
72 }
73
74 op.OpBase = base
75 op.Target = aux.Target
76 op.NewMetadata = aux.NewMetadata
77
78 return nil
79}
80
81// Sign post method for gqlgen
82func (op *SetMetadataOperation) IsAuthored() {}
83
84func NewSetMetadataOp(author identity.Interface, unixTime int64, target entity.Id, newMetadata map[string]string) *SetMetadataOperation {
85 return &SetMetadataOperation{
86 OpBase: newOpBase(SetMetadataOp, author, unixTime),
87 Target: target,
88 NewMetadata: newMetadata,
89 }
90}
91
92// Convenience function to apply the operation
93func SetMetadata(b Interface, author identity.Interface, unixTime int64, target entity.Id, newMetadata map[string]string) (*SetMetadataOperation, error) {
94 SetMetadataOp := NewSetMetadataOp(author, unixTime, target, newMetadata)
95 if err := SetMetadataOp.Validate(); err != nil {
96 return nil, err
97 }
98 b.Append(SetMetadataOp)
99 return SetMetadataOp, nil
100}