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