board_subcache.go

  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}