op_set_title.go

  1package bug
  2
  3import (
  4	"fmt"
  5	"strings"
  6
  7	"github.com/MichaelMure/git-bug/identity"
  8
  9	"github.com/MichaelMure/git-bug/util/git"
 10	"github.com/MichaelMure/git-bug/util/text"
 11)
 12
 13var _ Operation = &SetTitleOperation{}
 14
 15// SetTitleOperation will change the title of a bug
 16type SetTitleOperation struct {
 17	OpBase
 18	Title string `json:"title"`
 19	Was   string `json:"was"`
 20}
 21
 22func (op *SetTitleOperation) base() *OpBase {
 23	return &op.OpBase
 24}
 25
 26func (op *SetTitleOperation) Hash() (git.Hash, error) {
 27	return hashOperation(op)
 28}
 29
 30func (op *SetTitleOperation) Apply(snapshot *Snapshot) {
 31	snapshot.Title = op.Title
 32
 33	hash, err := op.Hash()
 34	if err != nil {
 35		// Should never error unless a programming error happened
 36		// (covered in OpBase.Validate())
 37		panic(err)
 38	}
 39
 40	item := &SetTitleTimelineItem{
 41		hash:     hash,
 42		Author:   op.Author,
 43		UnixTime: Timestamp(op.UnixTime),
 44		Title:    op.Title,
 45		Was:      op.Was,
 46	}
 47
 48	snapshot.Timeline = append(snapshot.Timeline, item)
 49}
 50
 51func (op *SetTitleOperation) Validate() error {
 52	if err := opBaseValidate(op, SetTitleOp); err != nil {
 53		return err
 54	}
 55
 56	if text.Empty(op.Title) {
 57		return fmt.Errorf("title is empty")
 58	}
 59
 60	if strings.Contains(op.Title, "\n") {
 61		return fmt.Errorf("title should be a single line")
 62	}
 63
 64	if !text.Safe(op.Title) {
 65		return fmt.Errorf("title should be fully printable")
 66	}
 67
 68	if strings.Contains(op.Was, "\n") {
 69		return fmt.Errorf("previous title should be a single line")
 70	}
 71
 72	if !text.Safe(op.Was) {
 73		return fmt.Errorf("previous title should be fully printable")
 74	}
 75
 76	return nil
 77}
 78
 79// Sign post method for gqlgen
 80func (op *SetTitleOperation) IsAuthored() {}
 81
 82func NewSetTitleOp(author identity.Interface, unixTime int64, title string, was string) *SetTitleOperation {
 83	return &SetTitleOperation{
 84		OpBase: newOpBase(SetTitleOp, author, unixTime),
 85		Title:  title,
 86		Was:    was,
 87	}
 88}
 89
 90type SetTitleTimelineItem struct {
 91	hash     git.Hash
 92	Author   identity.Interface
 93	UnixTime Timestamp
 94	Title    string
 95	Was      string
 96}
 97
 98func (s SetTitleTimelineItem) Hash() git.Hash {
 99	return s.hash
100}
101
102// Convenience function to apply the operation
103func SetTitle(b Interface, author identity.Interface, unixTime int64, title string) (*SetTitleOperation, error) {
104	it := NewOperationIterator(b)
105
106	var lastTitleOp Operation
107	for it.Next() {
108		op := it.Value()
109		if op.base().OperationType == SetTitleOp {
110			lastTitleOp = op
111		}
112	}
113
114	var was string
115	if lastTitleOp != nil {
116		was = lastTitleOp.(*SetTitleOperation).Title
117	} else {
118		was = b.FirstOp().(*CreateOperation).Title
119	}
120
121	setTitleOp := NewSetTitleOp(author, unixTime, title, was)
122
123	if err := setTitleOp.Validate(); err != nil {
124		return nil, err
125	}
126
127	b.Append(setTitleOp)
128	return setTitleOp, nil
129}