1package cache
2
3import (
4 "time"
5
6 "github.com/git-bug/git-bug/entities/board"
7 "github.com/git-bug/git-bug/entities/identity"
8 "github.com/git-bug/git-bug/entity"
9 "github.com/git-bug/git-bug/repository"
10)
11
12// BoardCache is a wrapper around a Board. It provides multiple functions:
13//
14// 1. Provide a higher level API to use than the raw API from Board.
15// 2. Maintain an up-to-date Snapshot available.
16// 3. Deal with concurrency.
17type BoardCache struct {
18 CachedEntityBase[*board.Snapshot, board.Operation]
19}
20
21func NewBoardCache(b *board.Board, repo repository.ClockedRepo, getUserIdentity getUserIdentityFunc, entityUpdated func(id entity.Id) error) *BoardCache {
22 return &BoardCache{
23 CachedEntityBase: CachedEntityBase[*board.Snapshot, board.Operation]{
24 repo: repo,
25 entityUpdated: entityUpdated,
26 getUserIdentity: getUserIdentity,
27 entity: &withSnapshot[*board.Snapshot, board.Operation]{Interface: b},
28 },
29 }
30}
31
32func (c *BoardCache) AddItemDraft(columnId entity.CombinedId, title, message string, files []repository.Hash) (entity.CombinedId, *board.AddItemDraftOperation, error) {
33 author, err := c.getUserIdentity()
34 if err != nil {
35 return entity.UnsetCombinedId, nil, err
36 }
37
38 return c.AddItemDraftRaw(author, time.Now().Unix(), columnId, title, message, files, nil)
39}
40
41func (c *BoardCache) AddItemDraftRaw(author identity.Interface, unixTime int64, columnId entity.CombinedId, title, message string, files []repository.Hash, metadata map[string]string) (entity.CombinedId, *board.AddItemDraftOperation, error) {
42 column, err := c.Snapshot().SearchColumn(columnId)
43 if err != nil {
44 return entity.UnsetCombinedId, nil, err
45 }
46
47 c.mu.Lock()
48 itemId, op, err := board.AddItemDraft(c.entity, author, unixTime, column.Id, title, message, files, metadata)
49 c.mu.Unlock()
50 if err != nil {
51 return entity.UnsetCombinedId, nil, err
52 }
53 return itemId, op, c.notifyUpdated()
54}
55
56func (c *BoardCache) AddItemEntity(columnId entity.CombinedId, e entity.Interface) (entity.CombinedId, *board.AddItemEntityOperation, error) {
57 author, err := c.getUserIdentity()
58 if err != nil {
59 return entity.UnsetCombinedId, nil, err
60 }
61
62 return c.AddItemEntityRaw(author, time.Now().Unix(), columnId, e, nil)
63}
64
65func (c *BoardCache) AddItemEntityRaw(author identity.Interface, unixTime int64, columnId entity.CombinedId, e entity.Interface, metadata map[string]string) (entity.CombinedId, *board.AddItemEntityOperation, error) {
66 column, err := c.Snapshot().SearchColumn(columnId)
67 if err != nil {
68 return entity.UnsetCombinedId, nil, err
69 }
70
71 var entityType board.ItemEntityType
72 switch e.(type) {
73 case *BugCache:
74 entityType = board.EntityTypeBug
75 default:
76 panic("unknown entity type")
77 }
78
79 c.mu.Lock()
80 itemId, op, err := board.AddItemEntity(c.entity, author, unixTime, column.Id, entityType, e, metadata)
81 c.mu.Unlock()
82 if err != nil {
83 return entity.UnsetCombinedId, nil, err
84 }
85 return itemId, op, c.notifyUpdated()
86}
87
88func (c *BoardCache) SetDescription(description string) (*board.SetDescriptionOperation, error) {
89 author, err := c.getUserIdentity()
90 if err != nil {
91 return nil, err
92 }
93
94 return c.SetDescriptionRaw(author, time.Now().Unix(), description, nil)
95}
96
97func (c *BoardCache) SetDescriptionRaw(author identity.Interface, unixTime int64, description string, metadata map[string]string) (*board.SetDescriptionOperation, error) {
98 c.mu.Lock()
99 op, err := board.SetDescription(c.entity, author, unixTime, description, metadata)
100 c.mu.Unlock()
101 if err != nil {
102 return nil, err
103 }
104 return op, c.notifyUpdated()
105}
106
107func (c *BoardCache) SetTitle(title string) (*board.SetTitleOperation, error) {
108 author, err := c.getUserIdentity()
109 if err != nil {
110 return nil, err
111 }
112
113 return c.SetTitleRaw(author, time.Now().Unix(), title, nil)
114}
115
116func (c *BoardCache) SetTitleRaw(author identity.Interface, unixTime int64, title string, metadata map[string]string) (*board.SetTitleOperation, error) {
117 c.mu.Lock()
118 op, err := board.SetTitle(c.entity, author, unixTime, title, metadata)
119 c.mu.Unlock()
120 if err != nil {
121 return nil, err
122 }
123 return op, c.notifyUpdated()
124}