1package dag
2
3import (
4 "fmt"
5
6 "github.com/pkg/errors"
7
8 "github.com/MichaelMure/git-bug/entity"
9 "github.com/MichaelMure/git-bug/util/text"
10)
11
12var _ Operation = &SetMetadataOperation[entity.Snapshot]{}
13var _ entity.OperationDoesntChangeSnapshot = &SetMetadataOperation[entity.Snapshot]{}
14
15type SetMetadataOperation[SnapT entity.Snapshot] struct {
16 OpBase
17 Target entity.Id `json:"target"`
18 NewMetadata map[string]string `json:"new_metadata"`
19}
20
21func NewSetMetadataOp[SnapT entity.Snapshot](opType entity.OperationType, author entity.Identity, unixTime int64, target entity.Id, newMetadata map[string]string) *SetMetadataOperation[SnapT] {
22 return &SetMetadataOperation[SnapT]{
23 OpBase: NewOpBase(opType, author, unixTime),
24 Target: target,
25 NewMetadata: newMetadata,
26 }
27}
28
29func (op *SetMetadataOperation[SnapT]) Id() entity.Id {
30 return IdOperation(op, &op.OpBase)
31}
32
33func (op *SetMetadataOperation[SnapT]) Apply(snapshot SnapT) {
34 for _, target := range snapshot.AllOperations() {
35 // cast to dag.Operation to have the private methods
36 if target, ok := target.(Operation); ok {
37 if target.Id() == op.Target {
38 // Apply the metadata in an immutable way: if a metadata already
39 // exist, it's not possible to override it.
40 for key, value := range op.NewMetadata {
41 target.setExtraMetadataImmutable(key, value)
42 }
43 return
44 }
45 }
46 }
47}
48
49func (op *SetMetadataOperation[SnapT]) Validate() error {
50 if err := op.OpBase.Validate(op, op.OperationType); err != nil {
51 return err
52 }
53
54 if err := op.Target.Validate(); err != nil {
55 return errors.Wrap(err, "target invalid")
56 }
57
58 for key, val := range op.NewMetadata {
59 if !text.SafeOneLine(key) {
60 return fmt.Errorf("metadata key is unsafe")
61 }
62 if !text.Safe(val) {
63 return fmt.Errorf("metadata value is not fully printable")
64 }
65 }
66
67 return nil
68}
69
70func (op *SetMetadataOperation[SnapT]) DoesntChangeSnapshot() {}