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