1package bug
2
3import (
4 "github.com/kevinburke/go.uuid"
5)
6
7// Bug hold the data of a bug thread, organized in a way close to
8// how it will be persisted inside Git. This is the datastructure
9// used for merge of two different version.
10type Bug struct {
11 // Id used as unique identifier
12 Id uuid.UUID
13
14 // TODO: need a way to order bugs
15 // Probably a Lamport clock
16
17 Packs []OperationPack
18
19 Staging OperationPack
20}
21
22// Create a new Bug
23func NewBug() (*Bug, error) {
24
25 // Creating UUID Version 4
26 id, err := uuid.ID4()
27
28 if err != nil {
29 return nil, err
30 }
31
32 return &Bug{
33 Id: id,
34 }, nil
35}
36
37// IsValid check if the Bug data is valid
38func (bug *Bug) IsValid() bool {
39 // non-empty
40 if len(bug.Packs) == 0 && bug.Staging.IsEmpty() {
41 return false
42 }
43
44 // check if each pack is valid
45 for _, pack := range bug.Packs {
46 if !pack.IsValid() {
47 return false
48 }
49 }
50
51 // check if Staging is valid if needed
52 if !bug.Staging.IsEmpty() {
53 if !bug.Staging.IsValid() {
54 return false
55 }
56 }
57
58 // The very first Op should be a CREATE
59 firstOp := bug.firstOp()
60 if firstOp == nil || firstOp.OpType() != CREATE {
61 return false
62 }
63
64 // Check that there is no more CREATE op
65 it := NewOperationIterator(bug)
66 createCount := 0
67 for it.Next() {
68 if it.Value().OpType() == CREATE {
69 createCount++
70 }
71 }
72
73 if createCount != 1 {
74 return false
75 }
76
77 return true
78}
79
80func (bug *Bug) Append(op Operation) {
81 bug.Staging.Append(op)
82}
83
84func (bug *Bug) Commit() {
85 bug.Packs = append(bug.Packs, bug.Staging)
86 bug.Staging = OperationPack{}
87}
88
89func (bug *Bug) HumanId() string {
90 return bug.Id.String()
91}
92
93func (bug *Bug) firstOp() Operation {
94 for _, pack := range bug.Packs {
95 for _, op := range pack.Operations {
96 return op
97 }
98 }
99
100 if !bug.Staging.IsEmpty() {
101 return bug.Staging.Operations[0]
102 }
103
104 return nil
105}