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