op_set_metadata.go

 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() {}