1package cache
2
3import (
4 "encoding/gob"
5
6 "github.com/MichaelMure/git-bug/bug"
7 "github.com/MichaelMure/git-bug/identity"
8 "github.com/MichaelMure/git-bug/util/lamport"
9)
10
11// Package initialisation used to register the type for (de)serialization
12func init() {
13 gob.Register(BugExcerpt{})
14}
15
16// BugExcerpt hold a subset of the bug values to be able to sort and filter bugs
17// efficiently without having to read and compile each raw bugs.
18type BugExcerpt struct {
19 Id string
20
21 CreateLamportTime lamport.Time
22 EditLamportTime lamport.Time
23 CreateUnixTime int64
24 EditUnixTime int64
25
26 Status bug.Status
27 Labels []bug.Label
28
29 // If author is identity.Bare, LegacyAuthor is set
30 // If author is identity.Identity, AuthorId is set and data is deported
31 // in a IdentityExcerpt
32 LegacyAuthor LegacyAuthorExcerpt
33 AuthorId string
34
35 CreateMetadata map[string]string
36}
37
38// identity.Bare data are directly embedded in the bug excerpt
39type LegacyAuthorExcerpt struct {
40 Name string
41 Login string
42}
43
44func NewBugExcerpt(b bug.Interface, snap *bug.Snapshot) *BugExcerpt {
45 e := &BugExcerpt{
46 Id: b.Id(),
47 CreateLamportTime: b.CreateLamportTime(),
48 EditLamportTime: b.EditLamportTime(),
49 CreateUnixTime: b.FirstOp().GetUnixTime(),
50 EditUnixTime: snap.LastEditUnix(),
51 Status: snap.Status,
52 Labels: snap.Labels,
53 CreateMetadata: b.FirstOp().AllMetadata(),
54 }
55
56 switch snap.Author.(type) {
57 case *identity.Identity:
58 e.AuthorId = snap.Author.Id()
59 case *identity.Bare:
60 e.LegacyAuthor = LegacyAuthorExcerpt{
61 Login: snap.Author.Login(),
62 Name: snap.Author.Name(),
63 }
64 default:
65 panic("unhandled identity type")
66 }
67
68 return e
69}
70
71/*
72 * Sorting
73 */
74
75type BugsById []*BugExcerpt
76
77func (b BugsById) Len() int {
78 return len(b)
79}
80
81func (b BugsById) Less(i, j int) bool {
82 return b[i].Id < b[j].Id
83}
84
85func (b BugsById) Swap(i, j int) {
86 b[i], b[j] = b[j], b[i]
87}
88
89type BugsByCreationTime []*BugExcerpt
90
91func (b BugsByCreationTime) Len() int {
92 return len(b)
93}
94
95func (b BugsByCreationTime) Less(i, j int) bool {
96 if b[i].CreateLamportTime < b[j].CreateLamportTime {
97 return true
98 }
99
100 if b[i].CreateLamportTime > b[j].CreateLamportTime {
101 return false
102 }
103
104 // When the logical clocks are identical, that means we had a concurrent
105 // edition. In this case we rely on the timestamp. While the timestamp might
106 // be incorrect due to a badly set clock, the drift in sorting is bounded
107 // by the first sorting using the logical clock. That means that if users
108 // synchronize their bugs regularly, the timestamp will rarely be used, and
109 // should still provide a kinda accurate sorting when needed.
110 return b[i].CreateUnixTime < b[j].CreateUnixTime
111}
112
113func (b BugsByCreationTime) Swap(i, j int) {
114 b[i], b[j] = b[j], b[i]
115}
116
117type BugsByEditTime []*BugExcerpt
118
119func (b BugsByEditTime) Len() int {
120 return len(b)
121}
122
123func (b BugsByEditTime) Less(i, j int) bool {
124 if b[i].EditLamportTime < b[j].EditLamportTime {
125 return true
126 }
127
128 if b[i].EditLamportTime > b[j].EditLamportTime {
129 return false
130 }
131
132 // When the logical clocks are identical, that means we had a concurrent
133 // edition. In this case we rely on the timestamp. While the timestamp might
134 // be incorrect due to a badly set clock, the drift in sorting is bounded
135 // by the first sorting using the logical clock. That means that if users
136 // synchronize their bugs regularly, the timestamp will rarely be used, and
137 // should still provide a kinda accurate sorting when needed.
138 return b[i].EditUnixTime < b[j].EditUnixTime
139}
140
141func (b BugsByEditTime) Swap(i, j int) {
142 b[i], b[j] = b[j], b[i]
143}