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