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
 20func (op *SetMetadataOperation) base() *OpBase {
 21	return &op.OpBase
 22}
 23
 24func (op *SetMetadataOperation) Id() entity.Id {
 25	return idOperation(op)
 26}
 27
 28func (op *SetMetadataOperation) Apply(snapshot *Snapshot) {
 29	for _, target := range snapshot.Operations {
 30		if target.Id() == op.Target {
 31			base := target.base()
 32
 33			if base.extraMetadata == nil {
 34				base.extraMetadata = make(map[string]string)
 35			}
 36
 37			for key, val := range op.NewMetadata {
 38				if _, exist := base.extraMetadata[key]; !exist {
 39					base.extraMetadata[key] = val
 40				}
 41			}
 42
 43			return
 44		}
 45	}
 46}
 47
 48func (op *SetMetadataOperation) Validate() error {
 49	if err := opBaseValidate(op, SetMetadataOp); err != nil {
 50		return err
 51	}
 52
 53	if err := op.Target.Validate(); err != nil {
 54		return errors.Wrap(err, "target invalid")
 55	}
 56
 57	return nil
 58}
 59
 60// UnmarshalJSON is a two step JSON unmarshaling
 61// This workaround is necessary to avoid the inner OpBase.MarshalJSON
 62// overriding the outer op's MarshalJSON
 63func (op *SetMetadataOperation) UnmarshalJSON(data []byte) error {
 64	// Unmarshal OpBase and the op separately
 65
 66	base := OpBase{}
 67	err := json.Unmarshal(data, &base)
 68	if err != nil {
 69		return err
 70	}
 71
 72	aux := struct {
 73		Target      entity.Id         `json:"target"`
 74		NewMetadata map[string]string `json:"new_metadata"`
 75	}{}
 76
 77	err = json.Unmarshal(data, &aux)
 78	if err != nil {
 79		return err
 80	}
 81
 82	op.OpBase = base
 83	op.Target = aux.Target
 84	op.NewMetadata = aux.NewMetadata
 85
 86	return nil
 87}
 88
 89// Sign post method for gqlgen
 90func (op *SetMetadataOperation) IsAuthored() {}
 91
 92func NewSetMetadataOp(author identity.Interface, unixTime int64, target entity.Id, newMetadata map[string]string) *SetMetadataOperation {
 93	return &SetMetadataOperation{
 94		OpBase:      newOpBase(SetMetadataOp, author, unixTime),
 95		Target:      target,
 96		NewMetadata: newMetadata,
 97	}
 98}
 99
100// Convenience function to apply the operation
101func SetMetadata(b Interface, author identity.Interface, unixTime int64, target entity.Id, newMetadata map[string]string) (*SetMetadataOperation, error) {
102	SetMetadataOp := NewSetMetadataOp(author, unixTime, target, newMetadata)
103	if err := SetMetadataOp.Validate(); err != nil {
104		return nil, err
105	}
106	b.Append(SetMetadataOp)
107	return SetMetadataOp, nil
108}