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