1package bug
2
3import (
4 "fmt"
5 "time"
6
7 "github.com/git-bug/git-bug/entities/common"
8 "github.com/git-bug/git-bug/entities/identity"
9 "github.com/git-bug/git-bug/entity"
10 "github.com/git-bug/git-bug/entity/dag"
11)
12
13var _ dag.Snapshot = &Snapshot{}
14
15// Snapshot is a compiled form of the Bug data structure used for storage and merge
16type Snapshot struct {
17 id entity.Id
18
19 Status common.Status
20 Title string
21 Comments []Comment
22 Labels []Label
23 Author identity.Interface
24 Actors []identity.Interface
25 Participants []identity.Interface
26 CreateTime time.Time
27
28 Timeline []TimelineItem
29
30 Operations []dag.Operation
31}
32
33// Id returns the Bug identifier
34func (snap *Snapshot) Id() entity.Id {
35 if snap.id == "" {
36 // simply panic as it would be a coding error (no id provided at construction)
37 panic("no id")
38 }
39 return snap.id
40}
41
42func (snap *Snapshot) AllOperations() []dag.Operation {
43 return snap.Operations
44}
45
46func (snap *Snapshot) AppendOperation(op dag.Operation) {
47 snap.Operations = append(snap.Operations, op)
48}
49
50// EditTime returns the last time a bug was modified
51func (snap *Snapshot) EditTime() time.Time {
52 if len(snap.Operations) == 0 {
53 return time.Unix(0, 0)
54 }
55
56 return snap.Operations[len(snap.Operations)-1].Time()
57}
58
59// GetCreateMetadata return the creation metadata
60func (snap *Snapshot) GetCreateMetadata(key string) (string, bool) {
61 return snap.Operations[0].GetMetadata(key)
62}
63
64// SearchTimelineItem will search in the timeline for an item matching the given hash
65func (snap *Snapshot) SearchTimelineItem(id entity.CombinedId) (TimelineItem, error) {
66 for i := range snap.Timeline {
67 if snap.Timeline[i].CombinedId() == id {
68 return snap.Timeline[i], nil
69 }
70 }
71
72 return nil, fmt.Errorf("timeline item not found")
73}
74
75// SearchComment will search for a comment matching the given id
76func (snap *Snapshot) SearchComment(id entity.CombinedId) (*Comment, error) {
77 for _, c := range snap.Comments {
78 if c.combinedId == id {
79 return &c, nil
80 }
81 }
82
83 return nil, fmt.Errorf("comment not found")
84}
85
86// SearchCommentByOpId will search for a comment generated by the given operation Id
87func (snap *Snapshot) SearchCommentByOpId(id entity.Id) (*Comment, error) {
88 for _, c := range snap.Comments {
89 if c.targetId == id {
90 return &c, nil
91 }
92 }
93
94 return nil, fmt.Errorf("comment not found")
95}
96
97// append the operation author to the actors list
98func (snap *Snapshot) addActor(actor identity.Interface) {
99 for _, a := range snap.Actors {
100 if actor.Id() == a.Id() {
101 return
102 }
103 }
104
105 snap.Actors = append(snap.Actors, actor)
106}
107
108// append the operation author to the participants list
109func (snap *Snapshot) addParticipant(participant identity.Interface) {
110 for _, p := range snap.Participants {
111 if participant.Id() == p.Id() {
112 return
113 }
114 }
115
116 snap.Participants = append(snap.Participants, participant)
117}
118
119// HasParticipant return true if the id is a participant
120func (snap *Snapshot) HasParticipant(id entity.Id) bool {
121 for _, p := range snap.Participants {
122 if p.Id() == id {
123 return true
124 }
125 }
126 return false
127}
128
129// HasAnyParticipant return true if one of the ids is a participant
130func (snap *Snapshot) HasAnyParticipant(ids ...entity.Id) bool {
131 for _, id := range ids {
132 if snap.HasParticipant(id) {
133 return true
134 }
135 }
136 return false
137}
138
139// HasActor return true if the id is a actor
140func (snap *Snapshot) HasActor(id entity.Id) bool {
141 for _, p := range snap.Actors {
142 if p.Id() == id {
143 return true
144 }
145 }
146 return false
147}
148
149// HasAnyActor return true if one of the ids is a actor
150func (snap *Snapshot) HasAnyActor(ids ...entity.Id) bool {
151 for _, id := range ids {
152 if snap.HasActor(id) {
153 return true
154 }
155 }
156 return false
157}
158
159// IsAuthored is a sign post method for gqlgen
160func (snap *Snapshot) IsAuthored() {}