op_set_status.go

  1package bug
  2
  3import (
  4	"encoding/json"
  5
  6	"github.com/MichaelMure/git-bug/identity"
  7	"github.com/MichaelMure/git-bug/util/git"
  8	"github.com/pkg/errors"
  9)
 10
 11var _ Operation = &SetStatusOperation{}
 12
 13// SetStatusOperation will change the status of a bug
 14type SetStatusOperation struct {
 15	OpBase
 16	Status Status
 17}
 18
 19func (op *SetStatusOperation) base() *OpBase {
 20	return &op.OpBase
 21}
 22
 23func (op *SetStatusOperation) Hash() (git.Hash, error) {
 24	return hashOperation(op)
 25}
 26
 27func (op *SetStatusOperation) Apply(snapshot *Snapshot) {
 28	snapshot.Status = op.Status
 29
 30	hash, err := op.Hash()
 31	if err != nil {
 32		// Should never error unless a programming error happened
 33		// (covered in OpBase.Validate())
 34		panic(err)
 35	}
 36
 37	item := &SetStatusTimelineItem{
 38		hash:     hash,
 39		Author:   op.Author,
 40		UnixTime: Timestamp(op.UnixTime),
 41		Status:   op.Status,
 42	}
 43
 44	snapshot.Timeline = append(snapshot.Timeline, item)
 45}
 46
 47func (op *SetStatusOperation) Validate() error {
 48	if err := opBaseValidate(op, SetStatusOp); err != nil {
 49		return err
 50	}
 51
 52	if err := op.Status.Validate(); err != nil {
 53		return errors.Wrap(err, "status")
 54	}
 55
 56	return nil
 57}
 58
 59// Workaround to avoid the inner OpBase.MarshalJSON overriding the outer op
 60// MarshalJSON
 61func (op *SetStatusOperation) MarshalJSON() ([]byte, error) {
 62	base, err := json.Marshal(op.OpBase)
 63	if err != nil {
 64		return nil, err
 65	}
 66
 67	// revert back to a flat map to be able to add our own fields
 68	var data map[string]interface{}
 69	if err := json.Unmarshal(base, &data); err != nil {
 70		return nil, err
 71	}
 72
 73	data["status"] = op.Status
 74
 75	return json.Marshal(data)
 76}
 77
 78// Workaround to avoid the inner OpBase.MarshalJSON overriding the outer op
 79// MarshalJSON
 80func (op *SetStatusOperation) UnmarshalJSON(data []byte) error {
 81	// Unmarshal OpBase and the op separately
 82
 83	base := OpBase{}
 84	err := json.Unmarshal(data, &base)
 85	if err != nil {
 86		return err
 87	}
 88
 89	aux := struct {
 90		Status Status `json:"status"`
 91	}{}
 92
 93	err = json.Unmarshal(data, &aux)
 94	if err != nil {
 95		return err
 96	}
 97
 98	op.OpBase = base
 99	op.Status = aux.Status
100
101	return nil
102}
103
104// Sign post method for gqlgen
105func (op *SetStatusOperation) IsAuthored() {}
106
107func NewSetStatusOp(author identity.Interface, unixTime int64, status Status) *SetStatusOperation {
108	return &SetStatusOperation{
109		OpBase: newOpBase(SetStatusOp, author, unixTime),
110		Status: status,
111	}
112}
113
114type SetStatusTimelineItem struct {
115	hash     git.Hash
116	Author   identity.Interface
117	UnixTime Timestamp
118	Status   Status
119}
120
121func (s SetStatusTimelineItem) Hash() git.Hash {
122	return s.hash
123}
124
125// Convenience function to apply the operation
126func Open(b Interface, author identity.Interface, unixTime int64) (*SetStatusOperation, error) {
127	op := NewSetStatusOp(author, unixTime, OpenStatus)
128	if err := op.Validate(); err != nil {
129		return nil, err
130	}
131	b.Append(op)
132	return op, nil
133}
134
135// Convenience function to apply the operation
136func Close(b Interface, author identity.Interface, unixTime int64) (*SetStatusOperation, error) {
137	op := NewSetStatusOp(author, unixTime, ClosedStatus)
138	if err := op.Validate(); err != nil {
139		return nil, err
140	}
141	b.Append(op)
142	return op, nil
143}