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