op_set_metadata.go

  1package bug
  2
  3import (
  4	"encoding/json"
  5
  6	"github.com/pkg/errors"
  7
  8	"github.com/MichaelMure/git-bug/entity"
  9	"github.com/MichaelMure/git-bug/identity"
 10)
 11
 12var _ Operation = &SetMetadataOperation{}
 13
 14type SetMetadataOperation struct {
 15	OpBase
 16	Target      entity.Id         `json:"target"`
 17	NewMetadata map[string]string `json:"new_metadata"`
 18}
 19
 20// Sign-post method for gqlgen
 21func (op *SetMetadataOperation) IsOperation() {}
 22
 23func (op *SetMetadataOperation) Id() entity.Id {
 24	return idOperation(op, &op.OpBase)
 25}
 26
 27func (op *SetMetadataOperation) Apply(snapshot *Snapshot) {
 28	for _, target := range snapshot.Operations {
 29		if target.Id() == op.Target {
 30			// Apply the metadata in an immutable way: if a metadata already
 31			// exist, it's not possible to override it.
 32			for key, value := range op.NewMetadata {
 33				target.setExtraMetadataImmutable(key, value)
 34			}
 35			return
 36		}
 37	}
 38}
 39
 40func (op *SetMetadataOperation) Validate() error {
 41	if err := op.OpBase.Validate(op, SetMetadataOp); err != nil {
 42		return err
 43	}
 44
 45	if err := op.Target.Validate(); err != nil {
 46		return errors.Wrap(err, "target invalid")
 47	}
 48
 49	return nil
 50}
 51
 52// UnmarshalJSON is a two step JSON unmarshalling
 53// This workaround is necessary to avoid the inner OpBase.MarshalJSON
 54// overriding the outer op's MarshalJSON
 55func (op *SetMetadataOperation) UnmarshalJSON(data []byte) error {
 56	// Unmarshal OpBase and the op separately
 57
 58	base := OpBase{}
 59	err := json.Unmarshal(data, &base)
 60	if err != nil {
 61		return err
 62	}
 63
 64	aux := struct {
 65		Target      entity.Id         `json:"target"`
 66		NewMetadata map[string]string `json:"new_metadata"`
 67	}{}
 68
 69	err = json.Unmarshal(data, &aux)
 70	if err != nil {
 71		return err
 72	}
 73
 74	op.OpBase = base
 75	op.Target = aux.Target
 76	op.NewMetadata = aux.NewMetadata
 77
 78	return nil
 79}
 80
 81// Sign post method for gqlgen
 82func (op *SetMetadataOperation) IsAuthored() {}
 83
 84func NewSetMetadataOp(author identity.Interface, unixTime int64, target entity.Id, newMetadata map[string]string) *SetMetadataOperation {
 85	return &SetMetadataOperation{
 86		OpBase:      newOpBase(SetMetadataOp, author, unixTime),
 87		Target:      target,
 88		NewMetadata: newMetadata,
 89	}
 90}
 91
 92// Convenience function to apply the operation
 93func SetMetadata(b Interface, author identity.Interface, unixTime int64, target entity.Id, newMetadata map[string]string) (*SetMetadataOperation, error) {
 94	SetMetadataOp := NewSetMetadataOp(author, unixTime, target, newMetadata)
 95	if err := SetMetadataOp.Validate(); err != nil {
 96		return nil, err
 97	}
 98	b.Append(SetMetadataOp)
 99	return SetMetadataOp, nil
100}