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// BugExcerpt hold a subset of the bug values to be able to sort and filter bugs
12// efficiently without having to read and compile each raw bugs.
13type BugExcerpt struct {
14 Id string
15
16 CreateLamportTime lamport.Time
17 EditLamportTime lamport.Time
18 CreateUnixTime int64
19 EditUnixTime int64
20
21 Status bug.Status
22 Labels []bug.Label
23
24 // If author is identity.Bare, LegacyAuthor is set
25 // If author is identity.Identity, AuthorId is set and data is deported
26 // in a IdentityExcerpt
27 LegacyAuthor LegacyAuthorExcerpt
28 AuthorId string
29
30 CreateMetadata map[string]string
31}
32
33// identity.Bare data are directly embedded in the bug excerpt
34type LegacyAuthorExcerpt struct {
35 Name string
36 Login string
37}
38
39func NewBugExcerpt(b bug.Interface, snap *bug.Snapshot) *BugExcerpt {
40 e := &BugExcerpt{
41 Id: b.Id(),
42 CreateLamportTime: b.CreateLamportTime(),
43 EditLamportTime: b.EditLamportTime(),
44 CreateUnixTime: b.FirstOp().GetUnixTime(),
45 EditUnixTime: snap.LastEditUnix(),
46 Status: snap.Status,
47 Labels: snap.Labels,
48 CreateMetadata: b.FirstOp().AllMetadata(),
49 }
50
51 switch snap.Author.(type) {
52 case *identity.Identity:
53 e.AuthorId = snap.Author.Id()
54 case *identity.Bare:
55 e.LegacyAuthor = LegacyAuthorExcerpt{
56 Login: snap.Author.Login(),
57 Name: snap.Author.Name(),
58 }
59 default:
60 panic("unhandled identity type")
61 }
62
63 return e
64}
65
66// Package initialisation used to register the type for (de)serialization
67func init() {
68 gob.Register(BugExcerpt{})
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}