1package cache
2
3import (
4 "errors"
5 "time"
6
7 "github.com/git-bug/git-bug/entities/board"
8 "github.com/git-bug/git-bug/entities/identity"
9 "github.com/git-bug/git-bug/entity"
10 "github.com/git-bug/git-bug/repository"
11)
12
13type RepoCacheBoard struct {
14 *SubCache[*board.Board, *BoardExcerpt, *BoardCache]
15}
16
17func NewRepoCacheBoard(repo repository.ClockedRepo,
18 resolvers func() entity.Resolvers,
19 getUserIdentity getUserIdentityFunc) *RepoCacheBoard {
20
21 makeCached := func(b *board.Board, entityUpdated func(id entity.Id) error) *BoardCache {
22 return NewBoardCache(b, repo, getUserIdentity, entityUpdated)
23 }
24
25 makeIndexData := func(b *BoardCache) []string {
26 // no indexing
27 return nil
28 }
29
30 actions := Actions[*board.Board]{
31 ReadWithResolver: board.ReadWithResolver,
32 ReadAllWithResolver: board.ReadAllWithResolver,
33 Remove: board.Remove,
34 MergeAll: board.MergeAll,
35 }
36
37 sc := NewSubCache[*board.Board, *BoardExcerpt, *BoardCache](
38 repo, resolvers, getUserIdentity,
39 makeCached, NewBoardExcerpt, makeIndexData, actions,
40 board.Typename, board.Namespace,
41 formatVersion, defaultMaxLoadedBugs,
42 )
43
44 return &RepoCacheBoard{SubCache: sc}
45}
46
47func (c *RepoCacheBoard) ResolveColumn(prefix string) (*BoardCache, entity.CombinedId, error) {
48 boardPrefix, _ := entity.SeparateIds(prefix)
49 boardCandidate := make([]entity.Id, 0, 5)
50
51 // build a list of possible matching boards
52 c.mu.RLock()
53 for _, excerpt := range c.excerpts {
54 if excerpt.Id().HasPrefix(boardPrefix) {
55 boardCandidate = append(boardCandidate, excerpt.Id())
56 }
57 }
58 c.mu.RUnlock()
59
60 matchingBoardIds := make([]entity.Id, 0, 5)
61 matchingColumnId := entity.UnsetCombinedId
62 var matchingBoard *BoardCache
63
64 // search for matching columns
65 // searching every board candidate allow for some collision with the board prefix only,
66 // before being refined with the full column prefix
67 for _, boardId := range boardCandidate {
68 b, err := c.Resolve(boardId)
69 if err != nil {
70 return nil, entity.UnsetCombinedId, err
71 }
72
73 for _, column := range b.Snapshot().Columns {
74 if column.CombinedId.HasPrefix(prefix) {
75 matchingBoardIds = append(matchingBoardIds, boardId)
76 matchingBoard = b
77 matchingColumnId = column.CombinedId
78 }
79 }
80 }
81
82 if len(matchingBoardIds) > 1 {
83 return nil, entity.UnsetCombinedId, entity.NewErrMultipleMatch("board/column", matchingBoardIds)
84 } else if len(matchingBoardIds) == 0 {
85 return nil, entity.UnsetCombinedId, errors.New("column doesn't exist")
86 }
87
88 return matchingBoard, matchingColumnId, nil
89}
90
91func (c *RepoCacheBoard) New(title, description string, columns []string) (*BoardCache, *board.CreateOperation, error) {
92 author, err := c.getUserIdentity()
93 if err != nil {
94 return nil, nil, err
95 }
96
97 return c.NewRaw(author, time.Now().Unix(), title, description, columns, nil)
98}
99
100func (c *RepoCacheBoard) NewDefaultColumns(title, description string) (*BoardCache, *board.CreateOperation, error) {
101 return c.New(title, description, board.DefaultColumns)
102}
103
104// NewRaw create a new board with the given title, description and columns.
105// The new board is written in the repository (commit).
106func (c *RepoCacheBoard) NewRaw(author identity.Interface, unixTime int64, title, description string, columns []string, metadata map[string]string) (*BoardCache, *board.CreateOperation, error) {
107 b, op, err := board.Create(author, unixTime, title, description, columns, metadata)
108 if err != nil {
109 return nil, nil, err
110 }
111
112 err = b.Commit(c.repo)
113 if err != nil {
114 return nil, nil, err
115 }
116
117 cached, err := c.add(b)
118 if err != nil {
119 return nil, nil, err
120 }
121
122 return cached, op, nil
123}