spearated commands
This commit is contained in:
parent
b3fbabd4e7
commit
7845f32aae
|
@ -1,27 +1,13 @@
|
||||||
package command
|
package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.ewintr.nl/gte/internal/configuration"
|
"git.ewintr.nl/gte/internal/configuration"
|
||||||
"git.ewintr.nl/gte/internal/process"
|
|
||||||
"git.ewintr.nl/gte/internal/storage"
|
|
||||||
"git.ewintr.nl/gte/internal/task"
|
|
||||||
"git.ewintr.nl/gte/pkg/mstore"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
ErrInitCommand = errors.New("could not initialize command")
|
|
||||||
ErrFailedCommand = errors.New("could not execute command")
|
|
||||||
)
|
|
||||||
|
|
||||||
type Result struct {
|
|
||||||
Message string
|
|
||||||
}
|
|
||||||
|
|
||||||
type Command interface {
|
type Command interface {
|
||||||
Do() (Result, error)
|
Do() string
|
||||||
}
|
}
|
||||||
|
|
||||||
func Parse(args []string, conf *configuration.Configuration) (Command, error) {
|
func Parse(args []string, conf *configuration.Configuration) (Command, error) {
|
||||||
|
@ -40,87 +26,6 @@ func Parse(args []string, conf *configuration.Configuration) (Command, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Empty struct{}
|
func FormatError(err error) string {
|
||||||
|
return fmt.Sprintf("could not perform command.\n\nerror: %s\n", err.Error())
|
||||||
func NewEmpty() (*Empty, error) {
|
|
||||||
return &Empty{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cmd *Empty) Do() (Result, error) {
|
|
||||||
return Result{
|
|
||||||
Message: "did nothing\n",
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type Sync struct {
|
|
||||||
syncer *process.Sync
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewSync(conf *configuration.Configuration) (*Sync, error) {
|
|
||||||
msgStore := mstore.NewIMAP(conf.IMAP())
|
|
||||||
remote := storage.NewRemoteRepository(msgStore)
|
|
||||||
local, err := storage.NewSqlite(conf.Sqlite())
|
|
||||||
if err != nil {
|
|
||||||
return &Sync{}, fmt.Errorf("%w: %v", ErrInitCommand, err)
|
|
||||||
}
|
|
||||||
syncer := process.NewSync(remote, local)
|
|
||||||
|
|
||||||
return &Sync{
|
|
||||||
syncer: syncer,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Sync) Do() (Result, error) {
|
|
||||||
result, err := s.syncer.Process()
|
|
||||||
if err != nil {
|
|
||||||
return Result{}, fmt.Errorf("%w: %v", ErrFailedCommand, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result{
|
|
||||||
Message: fmt.Sprintf("synced %d tasks\n", result.Count),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type Today struct {
|
|
||||||
local storage.LocalRepository
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewToday(conf *configuration.Configuration) (*Today, error) {
|
|
||||||
local, err := storage.NewSqlite(conf.Sqlite())
|
|
||||||
if err != nil {
|
|
||||||
return &Today{}, fmt.Errorf("%w: %v", ErrInitCommand, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &Today{
|
|
||||||
local: local,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Today) Do() (Result, error) {
|
|
||||||
tasks, err := t.local.FindAllInFolder(task.FOLDER_PLANNED)
|
|
||||||
if err != nil {
|
|
||||||
return Result{}, fmt.Errorf("%w: %v", ErrFailedCommand, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
todayTasks := []*task.Task{}
|
|
||||||
for _, t := range tasks {
|
|
||||||
if t.Due == task.Today || task.Today.After(t.Due) {
|
|
||||||
todayTasks = append(todayTasks, t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(todayTasks) == 0 {
|
|
||||||
return Result{
|
|
||||||
Message: "nothing left",
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var msg string
|
|
||||||
for _, t := range todayTasks {
|
|
||||||
msg += fmt.Sprintf("%s - %s\n", t.Project, t.Action)
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result{
|
|
||||||
Message: msg,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
package command
|
||||||
|
|
||||||
|
type Empty struct{}
|
||||||
|
|
||||||
|
func NewEmpty() (*Empty, error) {
|
||||||
|
return &Empty{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cmd *Empty) Do() string {
|
||||||
|
return "did nothing\n"
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"git.ewintr.nl/gte/internal/configuration"
|
||||||
|
"git.ewintr.nl/gte/internal/process"
|
||||||
|
"git.ewintr.nl/gte/internal/storage"
|
||||||
|
"git.ewintr.nl/gte/pkg/mstore"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Sync struct {
|
||||||
|
syncer *process.Sync
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSync(conf *configuration.Configuration) (*Sync, error) {
|
||||||
|
msgStore := mstore.NewIMAP(conf.IMAP())
|
||||||
|
remote := storage.NewRemoteRepository(msgStore)
|
||||||
|
local, err := storage.NewSqlite(conf.Sqlite())
|
||||||
|
if err != nil {
|
||||||
|
return &Sync{}, err
|
||||||
|
}
|
||||||
|
syncer := process.NewSync(remote, local)
|
||||||
|
|
||||||
|
return &Sync{
|
||||||
|
syncer: syncer,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Sync) Do() string {
|
||||||
|
result, err := s.syncer.Process()
|
||||||
|
if err != nil {
|
||||||
|
return FormatError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("synced %d tasks\n", result.Count)
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"git.ewintr.nl/gte/internal/configuration"
|
||||||
|
"git.ewintr.nl/gte/internal/process"
|
||||||
|
"git.ewintr.nl/gte/internal/storage"
|
||||||
|
"git.ewintr.nl/gte/internal/task"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Today struct {
|
||||||
|
todayer *process.List
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewToday(conf *configuration.Configuration) (*Today, error) {
|
||||||
|
local, err := storage.NewSqlite(conf.Sqlite())
|
||||||
|
if err != nil {
|
||||||
|
return &Today{}, err
|
||||||
|
}
|
||||||
|
reqs := process.ListReqs{
|
||||||
|
Due: task.Today,
|
||||||
|
IncludeBefore: true,
|
||||||
|
}
|
||||||
|
todayer := process.NewList(local, reqs)
|
||||||
|
|
||||||
|
return &Today{
|
||||||
|
todayer: todayer,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Today) Do() string {
|
||||||
|
res, err := t.todayer.Process()
|
||||||
|
if err != nil {
|
||||||
|
return FormatError(err)
|
||||||
|
}
|
||||||
|
if len(res.Tasks) == 0 {
|
||||||
|
return "nothing left\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
var msg string
|
||||||
|
for _, t := range res.Tasks {
|
||||||
|
msg += fmt.Sprintf("%s - %s\n", t.Project, t.Action)
|
||||||
|
}
|
||||||
|
|
||||||
|
return msg
|
||||||
|
}
|
|
@ -25,10 +25,5 @@ func main() {
|
||||||
fmt.Println(err, "could not initialize command")
|
fmt.Println(err, "could not initialize command")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
result, err := cmd.Do()
|
fmt.Printf("%s\n", cmd.Do())
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err, "could not perform command")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
fmt.Printf("%s\n", result.Message)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
package process
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"git.ewintr.nl/gte/internal/storage"
|
||||||
|
"git.ewintr.nl/gte/internal/task"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrInvalidReqs = errors.New("could not make sense of requirements")
|
||||||
|
ErrListProcess = errors.New("could not fetch task list")
|
||||||
|
)
|
||||||
|
|
||||||
|
// ListReqs specifies the requirements in AND fashion for a list of tasks
|
||||||
|
type ListReqs struct {
|
||||||
|
Due task.Date
|
||||||
|
IncludeBefore bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lr ListReqs) Valid() bool {
|
||||||
|
return !lr.Due.IsZero()
|
||||||
|
}
|
||||||
|
|
||||||
|
// List finds all tasks that satisfy the given requirements
|
||||||
|
type List struct {
|
||||||
|
local storage.LocalRepository
|
||||||
|
reqs ListReqs
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListResult struct {
|
||||||
|
Tasks []*task.Task
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewList(local storage.LocalRepository, reqs ListReqs) *List {
|
||||||
|
return &List{
|
||||||
|
local: local,
|
||||||
|
reqs: reqs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *List) Process() (*ListResult, error) {
|
||||||
|
if !l.reqs.Valid() {
|
||||||
|
return &ListResult{}, ErrInvalidReqs
|
||||||
|
}
|
||||||
|
|
||||||
|
potentialTasks, err := l.local.FindAllInFolder(task.FOLDER_PLANNED)
|
||||||
|
if err != nil {
|
||||||
|
return &ListResult{}, fmt.Errorf("%w: %v", ErrListProcess, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dueTasks := []*task.Task{}
|
||||||
|
for _, t := range potentialTasks {
|
||||||
|
switch {
|
||||||
|
case t.Due.Equal(l.reqs.Due):
|
||||||
|
dueTasks = append(dueTasks, t)
|
||||||
|
case l.reqs.IncludeBefore && l.reqs.Due.After(t.Due):
|
||||||
|
dueTasks = append(dueTasks, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ListResult{
|
||||||
|
Tasks: dueTasks,
|
||||||
|
}, nil
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
package process_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.ewintr.nl/go-kit/test"
|
||||||
|
"git.ewintr.nl/gte/internal/process"
|
||||||
|
"git.ewintr.nl/gte/internal/storage"
|
||||||
|
"git.ewintr.nl/gte/internal/task"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestListProcess(t *testing.T) {
|
||||||
|
date1 := task.NewDate(2021, 7, 9)
|
||||||
|
date2 := task.NewDate(2021, 7, 10)
|
||||||
|
date3 := task.NewDate(2021, 7, 11)
|
||||||
|
|
||||||
|
task1 := &task.Task{
|
||||||
|
Id: "id1",
|
||||||
|
Version: 1,
|
||||||
|
Action: "action1",
|
||||||
|
Folder: task.FOLDER_NEW,
|
||||||
|
}
|
||||||
|
task2 := &task.Task{
|
||||||
|
Id: "id2",
|
||||||
|
Version: 1,
|
||||||
|
Action: "action2",
|
||||||
|
Due: date1,
|
||||||
|
Folder: task.FOLDER_PLANNED,
|
||||||
|
}
|
||||||
|
task3 := &task.Task{
|
||||||
|
Id: "id3",
|
||||||
|
Version: 1,
|
||||||
|
Action: "action3",
|
||||||
|
Due: date2,
|
||||||
|
Folder: task.FOLDER_PLANNED,
|
||||||
|
}
|
||||||
|
task4 := &task.Task{
|
||||||
|
Id: "id4",
|
||||||
|
Version: 1,
|
||||||
|
Action: "action4",
|
||||||
|
Due: date3,
|
||||||
|
Folder: task.FOLDER_PLANNED,
|
||||||
|
}
|
||||||
|
allTasks := []*task.Task{task1, task2, task3, task4}
|
||||||
|
|
||||||
|
local := storage.NewMemory()
|
||||||
|
test.OK(t, local.SetTasks(allTasks))
|
||||||
|
|
||||||
|
t.Run("invalid reqs", func(t *testing.T) {
|
||||||
|
list := process.NewList(local, process.ListReqs{})
|
||||||
|
_, actErr := list.Process()
|
||||||
|
test.Assert(t, errors.Is(actErr, process.ErrInvalidReqs), "expected invalid reqs err")
|
||||||
|
})
|
||||||
|
|
||||||
|
for _, tc := range []struct {
|
||||||
|
name string
|
||||||
|
reqs process.ListReqs
|
||||||
|
exp []*task.Task
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "due",
|
||||||
|
reqs: process.ListReqs{
|
||||||
|
Due: date2,
|
||||||
|
},
|
||||||
|
exp: []*task.Task{task3},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "due and before",
|
||||||
|
reqs: process.ListReqs{
|
||||||
|
Due: date2,
|
||||||
|
IncludeBefore: true,
|
||||||
|
},
|
||||||
|
exp: []*task.Task{task2, task3},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
list := process.NewList(local, tc.reqs)
|
||||||
|
|
||||||
|
act, err := list.Process()
|
||||||
|
test.OK(t, err)
|
||||||
|
test.Equals(t, tc.exp, act.Tasks)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue