Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaelMure committed Mar 18, 2023
1 parent de95159 commit 9a4aae7
Show file tree
Hide file tree
Showing 18 changed files with 317 additions and 90 deletions.
30 changes: 24 additions & 6 deletions cache/board_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func NewBoardCache(b *board.Board, repo repository.ClockedRepo, getUserIdentity
}
}

func (c *BoardCache) AddItemDraft(columnId entity.Id, title, message string, files []repository.Hash) (entity.CombinedId, *board.AddItemDraftOperation, error) {
func (c *BoardCache) AddItemDraft(columnId entity.CombinedId, title, message string, files []repository.Hash) (entity.CombinedId, *board.AddItemDraftOperation, error) {
author, err := c.getUserIdentity()
if err != nil {
return entity.UnsetCombinedId, nil, err
Expand All @@ -38,17 +38,22 @@ func (c *BoardCache) AddItemDraft(columnId entity.Id, title, message string, fil
return c.AddItemDraftRaw(author, time.Now().Unix(), columnId, title, message, files, nil)
}

func (c *BoardCache) AddItemDraftRaw(author identity.Interface, unixTime int64, columnId entity.Id, title, message string, files []repository.Hash, metadata map[string]string) (entity.CombinedId, *board.AddItemDraftOperation, error) {
func (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) {
column, err := c.Snapshot().SearchColumn(columnId)
if err != nil {
return entity.UnsetCombinedId, nil, err
}

c.mu.Lock()
itemId, op, err := board.AddItemDraft(c.entity, author, unixTime, columnId, title, message, files, metadata)
itemId, op, err := board.AddItemDraft(c.entity, author, unixTime, column.Id, title, message, files, metadata)
c.mu.Unlock()
if err != nil {
return entity.UnsetCombinedId, nil, err
}
return itemId, op, c.notifyUpdated()
}

func (c *BoardCache) AddItemEntity(columnId entity.Id, e entity.Interface) (entity.CombinedId, *board.AddItemEntityOperation, error) {
func (c *BoardCache) AddItemEntity(columnId entity.CombinedId, e entity.Interface) (entity.CombinedId, *board.AddItemEntityOperation, error) {
author, err := c.getUserIdentity()
if err != nil {
return entity.UnsetCombinedId, nil, err
Expand All @@ -57,9 +62,22 @@ func (c *BoardCache) AddItemEntity(columnId entity.Id, e entity.Interface) (enti
return c.AddItemEntityRaw(author, time.Now().Unix(), columnId, e, nil)
}

func (c *BoardCache) AddItemEntityRaw(author identity.Interface, unixTime int64, columnId entity.Id, e entity.Interface, metadata map[string]string) (entity.CombinedId, *board.AddItemEntityOperation, error) {
func (c *BoardCache) AddItemEntityRaw(author identity.Interface, unixTime int64, columnId entity.CombinedId, e entity.Interface, metadata map[string]string) (entity.CombinedId, *board.AddItemEntityOperation, error) {
column, err := c.Snapshot().SearchColumn(columnId)
if err != nil {
return entity.UnsetCombinedId, nil, err
}

var entityType board.ItemEntityType
switch e.(type) {
case *BugCache:
entityType = board.EntityTypeBug
default:
panic("unknown entity type")
}

c.mu.Lock()
itemId, op, err := board.AddItemEntity(c.entity, author, unixTime, columnId, e, metadata)
itemId, op, err := board.AddItemEntity(c.entity, author, unixTime, column.Id, entityType, e, metadata)
c.mu.Unlock()
if err != nil {
return entity.UnsetCombinedId, nil, err
Expand Down
45 changes: 45 additions & 0 deletions cache/board_subcache.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cache

import (
"errors"
"time"

"github.com/MichaelMure/git-bug/entities/board"
Expand Down Expand Up @@ -43,6 +44,50 @@ func NewRepoCacheBoard(repo repository.ClockedRepo,
return &RepoCacheBoard{SubCache: sc}
}

func (c *RepoCacheBoard) ResolveColumn(prefix string) (*BoardCache, entity.CombinedId, error) {
boardPrefix, _ := entity.SeparateIds(prefix)
boardCandidate := make([]entity.Id, 0, 5)

// build a list of possible matching boards
c.mu.RLock()
for _, excerpt := range c.excerpts {
if excerpt.Id().HasPrefix(boardPrefix) {
boardCandidate = append(boardCandidate, excerpt.Id())
}
}
c.mu.RUnlock()

matchingBoardIds := make([]entity.Id, 0, 5)
matchingColumnId := entity.UnsetCombinedId
var matchingBoard *BoardCache

// search for matching columns
// searching every board candidate allow for some collision with the board prefix only,
// before being refined with the full column prefix
for _, boardId := range boardCandidate {
b, err := c.Resolve(boardId)
if err != nil {
return nil, entity.UnsetCombinedId, err
}

for _, column := range b.Snapshot().Columns {
if column.CombinedId.HasPrefix(prefix) {
matchingBoardIds = append(matchingBoardIds, boardId)
matchingBoard = b
matchingColumnId = column.CombinedId
}
}
}

if len(matchingBoardIds) > 1 {
return nil, entity.UnsetCombinedId, entity.NewErrMultipleMatch("board/column", matchingBoardIds)
} else if len(matchingBoardIds) == 0 {
return nil, entity.UnsetCombinedId, errors.New("column doesn't exist")
}

return matchingBoard, matchingColumnId, nil
}

func (c *RepoCacheBoard) New(title, description string, columns []string) (*BoardCache, *board.CreateOperation, error) {
author, err := c.getUserIdentity()
if err != nil {
Expand Down
20 changes: 14 additions & 6 deletions cache/repo_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import (
"strconv"
"sync"

"github.com/MichaelMure/git-bug/entities/board"
"github.com/MichaelMure/git-bug/entities/bug"
"github.com/MichaelMure/git-bug/entities/identity"
"github.com/MichaelMure/git-bug/entity"
"github.com/MichaelMure/git-bug/repository"
"github.com/MichaelMure/git-bug/util/multierr"
Expand Down Expand Up @@ -99,12 +102,17 @@ func NewNamedRepoCache(r repository.ClockedRepo, name string) (*RepoCache, chan
c.subcaches = append(c.subcaches, c.boards)

c.resolvers = entity.Resolvers{
&IdentityCache{}: entity.ResolverFunc[*IdentityCache](c.identities.Resolve),
&IdentityExcerpt{}: entity.ResolverFunc[*IdentityExcerpt](c.identities.ResolveExcerpt),
&BugCache{}: entity.ResolverFunc[*BugCache](c.bugs.Resolve),
&BugExcerpt{}: entity.ResolverFunc[*BugExcerpt](c.bugs.ResolveExcerpt),
&BoardCache{}: entity.ResolverFunc[*BoardCache](c.boards.Resolve),
&BoardExcerpt{}: entity.ResolverFunc[*BoardExcerpt](c.boards.ResolveExcerpt),
identity.Interface(nil): entity.ResolverFunc[*IdentityCache](c.identities.Resolve),
&IdentityCache{}: entity.ResolverFunc[*IdentityCache](c.identities.Resolve),
&IdentityExcerpt{}: entity.ResolverFunc[*IdentityExcerpt](c.identities.ResolveExcerpt),
bug.Interface(nil): entity.ResolverFunc[*BugCache](c.bugs.Resolve),
&bug.Bug{}: entity.ResolverFunc[*BugCache](c.bugs.Resolve),
&BugCache{}: entity.ResolverFunc[*BugCache](c.bugs.Resolve),
&BugExcerpt{}: entity.ResolverFunc[*BugExcerpt](c.bugs.ResolveExcerpt),
board.Interface(nil): entity.ResolverFunc[*BoardCache](c.boards.Resolve),
&bug.Bug{}: entity.ResolverFunc[*BoardCache](c.boards.Resolve),
&BoardCache{}: entity.ResolverFunc[*BoardCache](c.boards.Resolve),
&BoardExcerpt{}: entity.ResolverFunc[*BoardExcerpt](c.boards.ResolveExcerpt),
}

// small buffer so that below functions can emit an event without blocking
Expand Down
1 change: 1 addition & 0 deletions commands/board/board.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ func NewBoardCommand() *cobra.Command {
cmd.AddCommand(newBoardDescriptionCommand())
cmd.AddCommand(newBoardTitleCommand())
cmd.AddCommand(newBoardAddDraftCommand())
cmd.AddCommand(newBoardAddBugCommand())

return cmd
}
Expand Down
86 changes: 86 additions & 0 deletions commands/board/board_addbug.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package boardcmd

import (
"fmt"
"strconv"

"github.com/spf13/cobra"

bugcmd "github.com/MichaelMure/git-bug/commands/bug"
"github.com/MichaelMure/git-bug/commands/execenv"
_select "github.com/MichaelMure/git-bug/commands/select"
"github.com/MichaelMure/git-bug/entity"
)

type boardAddBugOptions struct {
column string
}

func newBoardAddBugCommand() *cobra.Command {
env := execenv.NewEnv()
options := boardAddBugOptions{}

cmd := &cobra.Command{
Use: "add-bug [BOARD_ID] [BUG_ID]",
Short: "Add a bug to a board",
PreRunE: execenv.LoadBackend(env),
RunE: execenv.CloseBackend(env, func(cmd *cobra.Command, args []string) error {
return runBoardAddBug(env, options, args)
}),
ValidArgsFunction: BoardAndBugCompletion(env),
}

flags := cmd.Flags()
flags.SortFlags = false

flags.StringVarP(&options.column, "column", "c", "1",
"The column to add to. Either a column Id or prefix, or the column number starting from 1.")
_ = cmd.RegisterFlagCompletionFunc("column", ColumnCompletion(env))

return cmd
}

func runBoardAddBug(env *execenv.Env, opts boardAddBugOptions, args []string) error {
board, args, err := ResolveSelected(env.Backend, args)
if err != nil {
return err
}

var columnId entity.CombinedId

switch {
case err == nil:
// try to parse as column number
index, err := strconv.Atoi(opts.column)
if err == nil {
if index-1 >= 0 && index-1 < len(board.Snapshot().Columns) {
columnId = board.Snapshot().Columns[index-1].CombinedId
} else {
return fmt.Errorf("invalid column")
}
}
fallthrough // could be an Id
case _select.IsErrNoValidId(err):
board, columnId, err = env.Backend.Boards().ResolveColumn(opts.column)
if err != nil {
return err
}
default:
// actual error
return err
}

bug, _, err := bugcmd.ResolveSelected(env.Backend, args)
if err != nil {
return err
}

id, _, err := board.AddItemEntity(columnId, bug)
if err != nil {
return err
}

env.Out.Printf("%s created\n", id.Human())

return board.Commit()
}
36 changes: 24 additions & 12 deletions commands/board/board_adddraft.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package boardcmd

import (
"fmt"
"strconv"

"github.com/spf13/cobra"

buginput "github.com/MichaelMure/git-bug/commands/bug/input"
"github.com/MichaelMure/git-bug/commands/execenv"
_select "github.com/MichaelMure/git-bug/commands/select"
"github.com/MichaelMure/git-bug/entity"
)

Expand Down Expand Up @@ -43,7 +45,6 @@ func newBoardAddDraftCommand() *cobra.Command {
"Take the message from the given file. Use - to read the message from the standard input")
flags.StringVarP(&options.column, "column", "c", "1",
"The column to add to. Either a column Id or prefix, or the column number starting from 1.")
// _ = cmd.MarkFlagRequired("column")
_ = cmd.RegisterFlagCompletionFunc("column", ColumnCompletion(env))
flags.BoolVar(&options.nonInteractive, "non-interactive", false, "Do not ask for user input")

Expand All @@ -52,18 +53,29 @@ func newBoardAddDraftCommand() *cobra.Command {

func runBoardAddDraft(env *execenv.Env, opts boardAddDraftOptions, args []string) error {
b, args, err := ResolveSelected(env.Backend, args)
if err != nil {
return err
}

var columnId entity.Id

index, err := strconv.Atoi(opts.column)
if err == nil && index-1 >= 0 && index-1 < len(b.Snapshot().Columns) {
columnId = b.Snapshot().Columns[index-1].Id
} else {
// TODO: ID or combined ID?
// TODO: resolve
var columnId entity.CombinedId

switch {
case err == nil:
// try to parse as column number
index, err := strconv.Atoi(opts.column)
if err == nil {
if index-1 >= 0 && index-1 < len(b.Snapshot().Columns) {
columnId = b.Snapshot().Columns[index-1].CombinedId
} else {
return fmt.Errorf("invalid column")
}
}
fallthrough // could be an Id
case _select.IsErrNoValidId(err):
b, columnId, err = env.Backend.Boards().ResolveColumn(opts.column)
if err != nil {
return err
}
default:
// actual error
return err
}

if opts.messageFile != "" && opts.message == "" {
Expand Down

0 comments on commit 9a4aae7

Please sign in to comment.