return data from command

This commit is contained in:
Erik Winter 2024-12-29 10:16:03 +01:00
parent 45d0bdfc34
commit e2ce33899f
13 changed files with 163 additions and 66 deletions

View File

@ -86,26 +86,26 @@ type Add struct {
args AddArgs args AddArgs
} }
func (a *Add) Do(deps Dependencies) error { func (a *Add) Do(deps Dependencies) ([][]string, error) {
if err := deps.TaskRepo.Store(a.args.task); err != nil { if err := deps.TaskRepo.Store(a.args.task); err != nil {
return fmt.Errorf("could not store event: %v", err) return nil, fmt.Errorf("could not store event: %v", err)
} }
localID, err := deps.LocalIDRepo.Next() localID, err := deps.LocalIDRepo.Next()
if err != nil { if err != nil {
return fmt.Errorf("could not create next local id: %v", err) return nil, fmt.Errorf("could not create next local id: %v", err)
} }
if err := deps.LocalIDRepo.Store(a.args.task.ID, localID); err != nil { if err := deps.LocalIDRepo.Store(a.args.task.ID, localID); err != nil {
return fmt.Errorf("could not store local id: %v", err) return nil, fmt.Errorf("could not store local id: %v", err)
} }
it, err := a.args.task.Item() it, err := a.args.task.Item()
if err != nil { if err != nil {
return fmt.Errorf("could not convert event to sync item: %v", err) return nil, fmt.Errorf("could not convert event to sync item: %v", err)
} }
if err := deps.SyncRepo.Store(it); err != nil { if err := deps.SyncRepo.Store(it); err != nil {
return fmt.Errorf("could not store sync item: %v", err) return nil, fmt.Errorf("could not store sync item: %v", err)
} }
return nil return nil, nil
} }

View File

@ -66,7 +66,7 @@ func TestAdd(t *testing.T) {
if tc.expErr { if tc.expErr {
return return
} }
if err := cmd.Do(command.Dependencies{ if _, err := cmd.Do(command.Dependencies{
TaskRepo: taskRepo, TaskRepo: taskRepo,
LocalIDRepo: localIDRepo, LocalIDRepo: localIDRepo,
SyncRepo: syncRepo, SyncRepo: syncRepo,

View File

@ -6,6 +6,7 @@ import (
"slices" "slices"
"strings" "strings"
"go-mod.ewintr.nl/planner/plan/format"
"go-mod.ewintr.nl/planner/plan/storage" "go-mod.ewintr.nl/planner/plan/storage"
"go-mod.ewintr.nl/planner/sync/client" "go-mod.ewintr.nl/planner/sync/client"
) )
@ -32,7 +33,7 @@ type CommandArgs interface {
} }
type Command interface { type Command interface {
Do(deps Dependencies) error Do(deps Dependencies) ([][]string, error)
} }
type CLI struct { type CLI struct {
@ -52,17 +53,29 @@ func NewCLI(deps Dependencies) *CLI {
} }
func (cli *CLI) Run(args []string) error { func (cli *CLI) Run(args []string) error {
main, flags := FindFields(args) main, fields := FindFields(args)
for _, ca := range cli.cmdArgs { for _, ca := range cli.cmdArgs {
cmd, err := ca.Parse(main, flags) cmd, err := ca.Parse(main, fields)
switch { switch {
case errors.Is(err, ErrWrongCommand): case errors.Is(err, ErrWrongCommand):
continue continue
case err != nil: case err != nil:
return err return err
default:
return cmd.Do(cli.deps)
} }
data, err := cmd.Do(cli.deps)
if err != nil {
return err
}
switch {
case len(data) == 0:
case len(data) == 1 && len(data[0]) == 1:
fmt.Println(data[0][0])
default:
fmt.Printf("\n%s\n", format.Table(data))
}
return nil
} }
return fmt.Errorf("could not find matching command") return fmt.Errorf("could not find matching command")

View File

@ -34,11 +34,11 @@ type Delete struct {
args DeleteArgs args DeleteArgs
} }
func (del *Delete) Do(deps Dependencies) error { func (del *Delete) Do(deps Dependencies) ([][]string, error) {
var id string var id string
idMap, err := deps.LocalIDRepo.FindAll() idMap, err := deps.LocalIDRepo.FindAll()
if err != nil { if err != nil {
return fmt.Errorf("could not get local ids: %v", err) return nil, fmt.Errorf("could not get local ids: %v", err)
} }
for tskID, lid := range idMap { for tskID, lid := range idMap {
if del.args.LocalID == lid { if del.args.LocalID == lid {
@ -46,30 +46,30 @@ func (del *Delete) Do(deps Dependencies) error {
} }
} }
if id == "" { if id == "" {
return fmt.Errorf("could not find local id") return nil, fmt.Errorf("could not find local id")
} }
tsk, err := deps.TaskRepo.Find(id) tsk, err := deps.TaskRepo.Find(id)
if err != nil { if err != nil {
return fmt.Errorf("could not get task: %v", err) return nil, fmt.Errorf("could not get task: %v", err)
} }
it, err := tsk.Item() it, err := tsk.Item()
if err != nil { if err != nil {
return fmt.Errorf("could not convert task to sync item: %v", err) return nil, fmt.Errorf("could not convert task to sync item: %v", err)
} }
it.Deleted = true it.Deleted = true
if err := deps.SyncRepo.Store(it); err != nil { if err := deps.SyncRepo.Store(it); err != nil {
return fmt.Errorf("could not store sync item: %v", err) return nil, fmt.Errorf("could not store sync item: %v", err)
} }
if err := deps.LocalIDRepo.Delete(id); err != nil { if err := deps.LocalIDRepo.Delete(id); err != nil {
return fmt.Errorf("could not delete local id: %v", err) return nil, fmt.Errorf("could not delete local id: %v", err)
} }
if err := deps.TaskRepo.Delete(id); err != nil { if err := deps.TaskRepo.Delete(id); err != nil {
return fmt.Errorf("could not delete task: %v", err) return nil, fmt.Errorf("could not delete task: %v", err)
} }
return nil return nil, nil
} }

View File

@ -61,12 +61,12 @@ func TestDelete(t *testing.T) {
if tc.expParseErr { if tc.expParseErr {
return return
} }
actDoErr := cmd.Do(command.Dependencies{ _, actDoErr := cmd.Do(command.Dependencies{
TaskRepo: taskRepo, TaskRepo: taskRepo,
LocalIDRepo: localIDRepo, LocalIDRepo: localIDRepo,
SyncRepo: syncRepo, SyncRepo: syncRepo,
}) != nil })
if tc.expDoErr != actDoErr { if tc.expDoErr != (actDoErr != nil) {
t.Errorf("exp false, got %v", actDoErr) t.Errorf("exp false, got %v", actDoErr)
} }
if tc.expDoErr { if tc.expDoErr {

View File

@ -22,22 +22,22 @@ func (la ListArgs) Parse(main []string, flags map[string]string) (Command, error
type List struct { type List struct {
} }
func (list *List) Do(deps Dependencies) error { func (list *List) Do(deps Dependencies) ([][]string, error) {
localIDs, err := deps.LocalIDRepo.FindAll() localIDs, err := deps.LocalIDRepo.FindAll()
if err != nil { if err != nil {
return fmt.Errorf("could not get local ids: %v", err) return nil, fmt.Errorf("could not get local ids: %v", err)
} }
all, err := deps.TaskRepo.FindAll() all, err := deps.TaskRepo.FindAll()
if err != nil { if err != nil {
return err return nil, err
} }
for _, e := range all { for _, e := range all {
lid, ok := localIDs[e.ID] lid, ok := localIDs[e.ID]
if !ok { if !ok {
return fmt.Errorf("could not find local id for %s", e.ID) return nil, fmt.Errorf("could not find local id for %s", e.ID)
} }
fmt.Printf("%s\t%d\t%s\t%s\t%s\n", e.ID, lid, e.Title, e.Date.String(), e.Duration.String()) fmt.Printf("%s\t%d\t%s\t%s\t%s\n", e.ID, lid, e.Title, e.Date.String(), e.Duration.String())
} }
return nil return nil, nil
} }

View File

@ -54,7 +54,7 @@ func TestList(t *testing.T) {
if tc.expErr { if tc.expErr {
return return
} }
if err := cmd.Do(command.Dependencies{ if _, err := cmd.Do(command.Dependencies{
TaskRepo: taskRepo, TaskRepo: taskRepo,
LocalIDRepo: localRepo, LocalIDRepo: localRepo,
}); err != nil { }); err != nil {

View File

@ -5,7 +5,6 @@ import (
"fmt" "fmt"
"strconv" "strconv"
"go-mod.ewintr.nl/planner/plan/format"
"go-mod.ewintr.nl/planner/plan/storage" "go-mod.ewintr.nl/planner/plan/storage"
) )
@ -37,18 +36,18 @@ type Show struct {
args ShowArgs args ShowArgs
} }
func (s *Show) Do(deps Dependencies) error { func (s *Show) Do(deps Dependencies) ([][]string, error) {
id, err := deps.LocalIDRepo.FindOne(s.args.localID) id, err := deps.LocalIDRepo.FindOne(s.args.localID)
switch { switch {
case errors.Is(err, storage.ErrNotFound): case errors.Is(err, storage.ErrNotFound):
return fmt.Errorf("could not find local id") return nil, fmt.Errorf("could not find local id")
case err != nil: case err != nil:
return err return nil, err
} }
tsk, err := deps.TaskRepo.Find(id) tsk, err := deps.TaskRepo.Find(id)
if err != nil { if err != nil {
return fmt.Errorf("could not find task") return nil, fmt.Errorf("could not find task")
} }
var recurStr string var recurStr string
@ -64,7 +63,6 @@ func (s *Show) Do(deps Dependencies) error {
{"recur", recurStr}, {"recur", recurStr},
// {"id", tsk.ID}, // {"id", tsk.ID},
} }
fmt.Printf("\n%s\n", format.Table(data))
return nil return data, nil
} }

86
plan/command/show_test.go Normal file
View File

@ -0,0 +1,86 @@
package command_test
import (
"fmt"
"testing"
"github.com/google/go-cmp/cmp"
"go-mod.ewintr.nl/planner/item"
"go-mod.ewintr.nl/planner/plan/command"
"go-mod.ewintr.nl/planner/plan/storage/memory"
)
func TestShow(t *testing.T) {
t.Parallel()
taskRepo := memory.NewTask()
localRepo := memory.NewLocalID()
tsk := item.Task{
ID: "id",
Date: item.NewDate(2024, 10, 7),
TaskBody: item.TaskBody{
Title: "name",
},
}
if err := taskRepo.Store(tsk); err != nil {
t.Errorf("exp nil, got %v", err)
}
if err := localRepo.Store(tsk.ID, 1); err != nil {
t.Errorf("exp nil, got %v", err)
}
for _, tc := range []struct {
name string
main []string
expData [][]string
expParseErr bool
expDoErr bool
}{
{
name: "empty",
main: []string{},
expParseErr: true,
},
{
name: "wrong",
main: []string{"delete"},
expParseErr: true,
},
{
name: "local id",
main: []string{"1"},
expData: [][]string{
{"title", tsk.Title},
{"local id", fmt.Sprintf("%d", 1)},
{"date", tsk.Date.String()},
{"time", tsk.Time.String()},
{"duration", tsk.Duration.String()},
{"recur", ""},
},
},
} {
t.Run(tc.name, func(t *testing.T) {
cmd, actParseErr := command.NewShowArgs().Parse(tc.main, nil)
if tc.expParseErr != (actParseErr != nil) {
t.Errorf("exp %v, got %v", tc.expParseErr, actParseErr != nil)
}
if tc.expParseErr {
return
}
actData, actDoErr := cmd.Do(command.Dependencies{
TaskRepo: taskRepo,
LocalIDRepo: localRepo,
})
if tc.expDoErr != (actDoErr != nil) {
t.Errorf("exp %v, got %v", tc.expDoErr, actDoErr != nil)
}
if tc.expDoErr {
return
}
if diff := cmp.Diff(tc.expData, actData); diff != "" {
t.Errorf("(+exp, -got)%s\n", diff)
}
})
}
}

View File

@ -25,37 +25,37 @@ func (sa SyncArgs) Parse(main []string, flags map[string]string) (Command, error
type Sync struct{} type Sync struct{}
func (s *Sync) Do(deps Dependencies) error { func (s *Sync) Do(deps Dependencies) ([][]string, error) {
// local new and updated // local new and updated
sendItems, err := deps.SyncRepo.FindAll() sendItems, err := deps.SyncRepo.FindAll()
if err != nil { if err != nil {
return fmt.Errorf("could not get updated items: %v", err) return nil, fmt.Errorf("could not get updated items: %v", err)
} }
if err := deps.SyncClient.Update(sendItems); err != nil { if err := deps.SyncClient.Update(sendItems); err != nil {
return fmt.Errorf("could not send updated items: %v", err) return nil, fmt.Errorf("could not send updated items: %v", err)
} }
if err := deps.SyncRepo.DeleteAll(); err != nil { if err := deps.SyncRepo.DeleteAll(); err != nil {
return fmt.Errorf("could not clear updated items: %v", err) return nil, fmt.Errorf("could not clear updated items: %v", err)
} }
// get new/updated items // get new/updated items
ts, err := deps.SyncRepo.LastUpdate() ts, err := deps.SyncRepo.LastUpdate()
if err != nil { if err != nil {
return fmt.Errorf("could not find timestamp of last update: %v", err) return nil, fmt.Errorf("could not find timestamp of last update: %v", err)
} }
recItems, err := deps.SyncClient.Updated([]item.Kind{item.KindTask}, ts) recItems, err := deps.SyncClient.Updated([]item.Kind{item.KindTask}, ts)
if err != nil { if err != nil {
return fmt.Errorf("could not receive updates: %v", err) return nil, fmt.Errorf("could not receive updates: %v", err)
} }
updated := make([]item.Item, 0) updated := make([]item.Item, 0)
for _, ri := range recItems { for _, ri := range recItems {
if ri.Deleted { if ri.Deleted {
if err := deps.LocalIDRepo.Delete(ri.ID); err != nil && !errors.Is(err, storage.ErrNotFound) { if err := deps.LocalIDRepo.Delete(ri.ID); err != nil && !errors.Is(err, storage.ErrNotFound) {
return fmt.Errorf("could not delete local id: %v", err) return nil, fmt.Errorf("could not delete local id: %v", err)
} }
if err := deps.TaskRepo.Delete(ri.ID); err != nil && !errors.Is(err, storage.ErrNotFound) { if err := deps.TaskRepo.Delete(ri.ID); err != nil && !errors.Is(err, storage.ErrNotFound) {
return fmt.Errorf("could not delete task: %v", err) return nil, fmt.Errorf("could not delete task: %v", err)
} }
continue continue
} }
@ -64,12 +64,12 @@ func (s *Sync) Do(deps Dependencies) error {
lidMap, err := deps.LocalIDRepo.FindAll() lidMap, err := deps.LocalIDRepo.FindAll()
if err != nil { if err != nil {
return fmt.Errorf("could not get local ids: %v", err) return nil, fmt.Errorf("could not get local ids: %v", err)
} }
for _, u := range updated { for _, u := range updated {
var tskBody item.TaskBody var tskBody item.TaskBody
if err := json.Unmarshal([]byte(u.Body), &tskBody); err != nil { if err := json.Unmarshal([]byte(u.Body), &tskBody); err != nil {
return fmt.Errorf("could not unmarshal task body: %v", err) return nil, fmt.Errorf("could not unmarshal task body: %v", err)
} }
tsk := item.Task{ tsk := item.Task{
ID: u.ID, ID: u.ID,
@ -79,20 +79,20 @@ func (s *Sync) Do(deps Dependencies) error {
TaskBody: tskBody, TaskBody: tskBody,
} }
if err := deps.TaskRepo.Store(tsk); err != nil { if err := deps.TaskRepo.Store(tsk); err != nil {
return fmt.Errorf("could not store task: %v", err) return nil, fmt.Errorf("could not store task: %v", err)
} }
lid, ok := lidMap[u.ID] lid, ok := lidMap[u.ID]
if !ok { if !ok {
lid, err = deps.LocalIDRepo.Next() lid, err = deps.LocalIDRepo.Next()
if err != nil { if err != nil {
return fmt.Errorf("could not get next local id: %v", err) return nil, fmt.Errorf("could not get next local id: %v", err)
} }
if err := deps.LocalIDRepo.Store(u.ID, lid); err != nil { if err := deps.LocalIDRepo.Store(u.ID, lid); err != nil {
return fmt.Errorf("could not store local id: %v", err) return nil, fmt.Errorf("could not store local id: %v", err)
} }
} }
} }
return nil return nil, nil
} }

View File

@ -80,7 +80,7 @@ func TestSyncSend(t *testing.T) {
if err != nil { if err != nil {
t.Errorf("exp nil, got %v", err) t.Errorf("exp nil, got %v", err)
} }
if err := cmd.Do(command.Dependencies{ if _, err := cmd.Do(command.Dependencies{
TaskRepo: taskRepo, TaskRepo: taskRepo,
LocalIDRepo: localIDRepo, LocalIDRepo: localIDRepo,
SyncRepo: syncRepo, SyncRepo: syncRepo,
@ -206,7 +206,7 @@ func TestSyncReceive(t *testing.T) {
if err != nil { if err != nil {
t.Errorf("exp nil, got %v", err) t.Errorf("exp nil, got %v", err)
} }
if err := cmd.Do(command.Dependencies{ if _, err := cmd.Do(command.Dependencies{
TaskRepo: taskRepo, TaskRepo: taskRepo,
LocalIDRepo: localIDRepo, LocalIDRepo: localIDRepo,
SyncRepo: syncRepo, SyncRepo: syncRepo,

View File

@ -83,11 +83,11 @@ type Update struct {
args UpdateArgs args UpdateArgs
} }
func (u *Update) Do(deps Dependencies) error { func (u *Update) Do(deps Dependencies) ([][]string, error) {
var id string var id string
idMap, err := deps.LocalIDRepo.FindAll() idMap, err := deps.LocalIDRepo.FindAll()
if err != nil { if err != nil {
return fmt.Errorf("could not get local ids: %v", err) return nil, fmt.Errorf("could not get local ids: %v", err)
} }
for tid, lid := range idMap { for tid, lid := range idMap {
if u.args.LocalID == lid { if u.args.LocalID == lid {
@ -95,12 +95,12 @@ func (u *Update) Do(deps Dependencies) error {
} }
} }
if id == "" { if id == "" {
return fmt.Errorf("could not find local id") return nil, fmt.Errorf("could not find local id")
} }
tsk, err := deps.TaskRepo.Find(id) tsk, err := deps.TaskRepo.Find(id)
if err != nil { if err != nil {
return fmt.Errorf("could not find task") return nil, fmt.Errorf("could not find task")
} }
if u.args.Title != "" { if u.args.Title != "" {
@ -121,20 +121,20 @@ func (u *Update) Do(deps Dependencies) error {
} }
if !tsk.Valid() { if !tsk.Valid() {
return fmt.Errorf("task is unvalid") return nil, fmt.Errorf("task is unvalid")
} }
if err := deps.TaskRepo.Store(tsk); err != nil { if err := deps.TaskRepo.Store(tsk); err != nil {
return fmt.Errorf("could not store task: %v", err) return nil, fmt.Errorf("could not store task: %v", err)
} }
it, err := tsk.Item() it, err := tsk.Item()
if err != nil { if err != nil {
return fmt.Errorf("could not convert task to sync item: %v", err) return nil, fmt.Errorf("could not convert task to sync item: %v", err)
} }
if err := deps.SyncRepo.Store(it); err != nil { if err := deps.SyncRepo.Store(it); err != nil {
return fmt.Errorf("could not store sync item: %v", err) return nil, fmt.Errorf("could not store sync item: %v", err)
} }
return nil return nil, nil
} }

View File

@ -189,12 +189,12 @@ func TestUpdateExecute(t *testing.T) {
if tc.expParseErr { if tc.expParseErr {
return return
} }
actDoErr := cmd.Do(command.Dependencies{ _, actDoErr := cmd.Do(command.Dependencies{
TaskRepo: taskRepo, TaskRepo: taskRepo,
LocalIDRepo: localIDRepo, LocalIDRepo: localIDRepo,
SyncRepo: syncRepo, SyncRepo: syncRepo,
}) != nil })
if tc.expDoErr != actDoErr { if tc.expDoErr != (actDoErr != nil) {
t.Errorf("exp %v, got %v", tc.expDoErr, actDoErr) t.Errorf("exp %v, got %v", tc.expDoErr, actDoErr)
} }
if tc.expDoErr { if tc.expDoErr {