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