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
77func NewSetTitleOp(author Person, unixTime int64, title string, was string) *SetTitleOperation {
78 return &SetTitleOperation{
79 OpBase: newOpBase(SetTitleOp, author, unixTime),
80 Title: title,
81 Was: was,
82 }
83}
84
85type SetTitleTimelineItem struct {
86 hash git.Hash
87 Author Person
88 UnixTime Timestamp
89 Title string
90 Was string
91}
92
93func (s SetTitleTimelineItem) Hash() git.Hash {
94 return s.hash
95}
96
97// Convenience function to apply the operation
98func SetTitle(b Interface, author Person, unixTime int64, title string) error {
99 it := NewOperationIterator(b)
100
101 var lastTitleOp Operation
102 for it.Next() {
103 op := it.Value()
104 if op.base().OperationType == SetTitleOp {
105 lastTitleOp = op
106 }
107 }
108
109 var was string
110 if lastTitleOp != nil {
111 was = lastTitleOp.(*SetTitleOperation).Title
112 } else {
113 was = b.FirstOp().(*CreateOperation).Title
114 }
115
116 setTitleOp := NewSetTitleOp(author, unixTime, title, was)
117
118 if err := setTitleOp.Validate(); err != nil {
119 return err
120 }
121
122 b.Append(setTitleOp)
123 return nil
124}