~ewintr/gte

86ad6cb0fb94a1eb95872a70e1c3786c93fe95c3 — Erik Winter 2 months ago a2a0e9b
introduce local status
M cmd/cli/format/format.go => cmd/cli/format/format.go +1 -1
@@ 21,7 21,7 @@ func FormatTaskTable(tasks []*task.LocalTask) string {
	var output string
	for _, t := range tasks {
		var updateStr string
		if t.LocalUpdate.ForVersion != 0 {
		if t.LocalStatus == task.STATUS_UPDATED {
			updateStr = " *"
		}
		output += fmt.Sprintf("%d%s\t%s\t%s (%s)\n", t.LocalId, updateStr, t.Due.String(), t.Action, t.Project)

M internal/process/list_test.go => internal/process/list_test.go +3 -3
@@ 48,9 48,9 @@ func TestListProcess(t *testing.T) {
		Project: "project2",
	}
	allTasks := []*task.Task{task1, task2, task3, task4}
	localTask2 := &task.LocalTask{Task: *task2, LocalUpdate: &task.LocalUpdate{}}
	localTask3 := &task.LocalTask{Task: *task3, LocalUpdate: &task.LocalUpdate{}}
	localTask4 := &task.LocalTask{Task: *task4, LocalUpdate: &task.LocalUpdate{}}
	localTask2 := &task.LocalTask{Task: *task2, LocalUpdate: &task.LocalUpdate{}, LocalStatus: task.STATUS_FETCHED}
	localTask3 := &task.LocalTask{Task: *task3, LocalUpdate: &task.LocalUpdate{}, LocalStatus: task.STATUS_FETCHED}
	localTask4 := &task.LocalTask{Task: *task4, LocalUpdate: &task.LocalUpdate{}, LocalStatus: task.STATUS_FETCHED}
	local := storage.NewMemory()
	test.OK(t, local.SetTasks(allTasks))


M internal/process/sync_test.go => internal/process/sync_test.go +2 -2
@@ 25,8 25,8 @@ func TestSyncProcess(t *testing.T) {
		Folder:  task.FOLDER_UNPLANNED,
	}

	localTask1 := &task.LocalTask{Task: *task1, LocalUpdate: &task.LocalUpdate{}}
	localTask2 := &task.LocalTask{Task: *task2, LocalUpdate: &task.LocalUpdate{}}
	localTask1 := &task.LocalTask{Task: *task1, LocalUpdate: &task.LocalUpdate{}, LocalStatus: task.STATUS_FETCHED}
	localTask2 := &task.LocalTask{Task: *task2, LocalUpdate: &task.LocalUpdate{}, LocalStatus: task.STATUS_FETCHED}

	mstorer, err := mstore.NewMemory(task.KnownFolders)
	test.OK(t, err)

M internal/storage/local.go => internal/storage/local.go +4 -2
@@ 72,8 72,8 @@ func NextLocalId(used []int) int {

// MergeNewTaskSet updates a local set of tasks with a remote one
//
// New set is leading and tasks that are not in there get dismissed. Tasks that
// were created locally and got dispatched  might temporarily dissappear if the
// The new set is leading and tasks that are not in there get dismissed. Tasks that
// were created locally and got dispatched might temporarily dissappear if the
// remote inbox has a delay in processing.
func MergeNewTaskSet(oldTasks []*task.LocalTask, newTasks []*task.Task) []*task.LocalTask {



@@ 84,6 84,7 @@ func MergeNewTaskSet(oldTasks []*task.LocalTask, newTasks []*task.Task) []*task.
			Task:        *nt,
			LocalId:     0,
			LocalUpdate: &task.LocalUpdate{},
			LocalStatus: task.STATUS_FETCHED,
		}
	}
	oldMap := map[string]*task.LocalTask{}


@@ 116,6 117,7 @@ func MergeNewTaskSet(oldTasks []*task.LocalTask, newTasks []*task.Task) []*task.
		if nt, ok := resultMap[ot.Id]; ok {
			if ot.LocalUpdate.ForVersion >= nt.Version {
				resultMap[ot.Id].LocalUpdate = ot.LocalUpdate
				resultMap[ot.Id].LocalStatus = task.STATUS_UPDATED
			}
		}
	}

M internal/storage/local_test.go => internal/storage/local_test.go +7 -6
@@ 106,8 106,8 @@ func TestMergeNewTaskSet(t *testing.T) {
			oldTasks: []*task.LocalTask{},
			newTasks: []*task.Task{task1, task2},
			exp: []*task.LocalTask{
				{Task: *task1, LocalUpdate: emptyUpdate},
				{Task: *task2, LocalUpdate: emptyUpdate},
				{Task: *task1, LocalUpdate: emptyUpdate, LocalStatus: task.STATUS_FETCHED},
				{Task: *task2, LocalUpdate: emptyUpdate, LocalStatus: task.STATUS_FETCHED},
			},
		},
		{


@@ 118,8 118,8 @@ func TestMergeNewTaskSet(t *testing.T) {
			},
			newTasks: []*task.Task{task1v2, task2},
			exp: []*task.LocalTask{
				{Task: *task1v2, LocalUpdate: emptyUpdate},
				{Task: *task2, LocalUpdate: emptyUpdate},
				{Task: *task1v2, LocalUpdate: emptyUpdate, LocalStatus: task.STATUS_FETCHED},
				{Task: *task2, LocalUpdate: emptyUpdate, LocalStatus: task.STATUS_FETCHED},
			},
		},
		{


@@ 130,7 130,7 @@ func TestMergeNewTaskSet(t *testing.T) {
			},
			newTasks: []*task.Task{task2},
			exp: []*task.LocalTask{
				{Task: *task2, LocalUpdate: emptyUpdate},
				{Task: *task2, LocalUpdate: emptyUpdate, LocalStatus: task.STATUS_FETCHED},
			},
		},
		{


@@ 153,13 153,14 @@ func TestMergeNewTaskSet(t *testing.T) {
			},
			newTasks: []*task.Task{task1v2, task2},
			exp: []*task.LocalTask{
				{Task: *task1v2, LocalUpdate: emptyUpdate},
				{Task: *task1v2, LocalUpdate: emptyUpdate, LocalStatus: task.STATUS_FETCHED},
				{
					Task: *task2,
					LocalUpdate: &task.LocalUpdate{
						ForVersion: 2,
						Project:    "project-v3",
					},
					LocalStatus: task.STATUS_UPDATED,
				},
			},
		},

M internal/storage/memory_test.go => internal/storage/memory_test.go +3 -3
@@ 43,9 43,9 @@ func TestMemory(t *testing.T) {
	}
	tasks := []*task.Task{task1, task2, task3}
	emptyUpdate := &task.LocalUpdate{}
	localTask1 := &task.LocalTask{Task: *task1, LocalUpdate: emptyUpdate}
	localTask2 := &task.LocalTask{Task: *task2, LocalUpdate: emptyUpdate}
	localTask3 := &task.LocalTask{Task: *task3, LocalUpdate: emptyUpdate}
	localTask1 := &task.LocalTask{Task: *task1, LocalUpdate: emptyUpdate, LocalStatus: task.STATUS_FETCHED}
	localTask2 := &task.LocalTask{Task: *task2, LocalUpdate: emptyUpdate, LocalStatus: task.STATUS_FETCHED}
	localTask3 := &task.LocalTask{Task: *task3, LocalUpdate: emptyUpdate, LocalStatus: task.STATUS_FETCHED}

	t.Run("sync", func(t *testing.T) {
		mem := storage.NewMemory()

M internal/storage/sqlite.go => internal/storage/sqlite.go +38 -39
@@ 24,6 24,8 @@ var sqliteMigrations = []sqliteMigration{
	`UPDATE task SET local_id = (SELECT local_id FROM local_task WHERE local_task.id=task.id)`,
	`UPDATE task SET local_update = (SELECT local_update FROM local_task WHERE local_task.id=task.id)`,
	`DROP TABLE local_task`,
	`ALTER TABLE task ADD COLUMN local_status TEXT`,
	`UPDATE task SET local_status = "fetched"`,
}

var (


@@ 93,10 95,10 @@ func (s *Sqlite) SetTasks(tasks []*task.Task) error {

		_, err := s.db.Exec(`
INSERT INTO task
(id, local_id, version, folder, action, project, due, recur, local_update)
(id, local_id, version, folder, action, project, due, recur, local_update, local_status)
VALUES
(?, ?, ?, ?, ?, ?, ?, ?, ?)`,
			t.Id, t.LocalId, t.Version, t.Folder, t.Action, t.Project, t.Due.String(), recurStr, t.LocalUpdate)
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
			t.Id, t.LocalId, t.Version, t.Folder, t.Action, t.Project, t.Due.String(), recurStr, t.LocalUpdate, t.LocalStatus)

		if err != nil {
			return fmt.Errorf("%w: %v", ErrSqliteFailure, err)


@@ 108,25 110,50 @@ VALUES

func (s *Sqlite) FindAll() ([]*task.LocalTask, error) {
	rows, err := s.db.Query(`
SELECT id, local_id, version, folder, action, project, due, recur, local_update
SELECT id, local_id, version, folder, action, project, due, recur, local_update, local_status
FROM task`)
	if err != nil {
		return []*task.LocalTask{}, fmt.Errorf("%w: %v", ErrSqliteFailure, err)
	}

	return tasksFromRows(rows)
	tasks := []*task.LocalTask{}
	defer rows.Close()
	for rows.Next() {
		var id, folder, action, project, due, recur, localStatus string
		var localId, version int
		var localUpdate task.LocalUpdate
		if err := rows.Scan(&id, &localId, &version, &folder, &action, &project, &due, &recur, &localUpdate, &localStatus); err != nil {
			return []*task.LocalTask{}, fmt.Errorf("%w: %v", ErrSqliteFailure, err)
		}
		tasks = append(tasks, &task.LocalTask{
			Task: task.Task{
				Id:      id,
				Version: version,
				Folder:  folder,
				Action:  action,
				Project: project,
				Due:     task.NewDateFromString(due),
				Recur:   task.NewRecurrer(recur),
			},
			LocalId:     localId,
			LocalUpdate: &localUpdate,
			LocalStatus: localStatus,
		})
	}

	return tasks, nil
}

func (s *Sqlite) FindById(id string) (*task.LocalTask, error) {
	var folder, action, project, due, recur string
	var folder, action, project, due, recur, localStatus string
	var localId, version int
	var localUpdate task.LocalUpdate
	row := s.db.QueryRow(`
SELECT local_id, version, folder, action, project, due, recur, local_update
SELECT local_id, version, folder, action, project, due, recur, local_update, local_status
FROM task
WHERE task.id = ?
LIMIT 1`, id)
	if err := row.Scan(&localId, &version, &folder, &action, &project, &due, &recur, &localUpdate); err != nil {
	if err := row.Scan(&localId, &version, &folder, &action, &project, &due, &recur, &localUpdate, &localStatus); err != nil {
		return &task.LocalTask{}, fmt.Errorf("%w: %v", ErrSqliteFailure, err)
	}



@@ 142,6 169,7 @@ LIMIT 1`, id)
		},
		LocalId:     localId,
		LocalUpdate: &localUpdate,
		LocalStatus: localStatus,
	}, nil
}



@@ 163,43 191,14 @@ func (s *Sqlite) FindByLocalId(localId int) (*task.LocalTask, error) {
func (s *Sqlite) SetLocalUpdate(tsk *task.LocalTask) error {
	if _, err := s.db.Exec(`
UPDATE task
SET local_update = ?
WHERE local_id = ?`, tsk.LocalUpdate, tsk.LocalId); err != nil {
SET local_update = ?, local_status = ?
WHERE local_id = ?`, tsk.LocalUpdate, task.STATUS_UPDATED, tsk.LocalId); err != nil {
		return fmt.Errorf("%w: %v", ErrSqliteFailure, err)
	}

	return nil
}

func tasksFromRows(rows *sql.Rows) ([]*task.LocalTask, error) {
	tasks := []*task.LocalTask{}

	defer rows.Close()
	for rows.Next() {
		var id, folder, action, project, due, recur string
		var localId, version int
		var localUpdate task.LocalUpdate
		if err := rows.Scan(&id, &localId, &version, &folder, &action, &project, &due, &recur, &localUpdate); err != nil {
			return []*task.LocalTask{}, fmt.Errorf("%w: %v", ErrSqliteFailure, err)
		}
		tasks = append(tasks, &task.LocalTask{
			Task: task.Task{
				Id:      id,
				Version: version,
				Folder:  folder,
				Action:  action,
				Project: project,
				Due:     task.NewDateFromString(due),
				Recur:   task.NewRecurrer(recur),
			},
			LocalId:     localId,
			LocalUpdate: &localUpdate,
		})
	}

	return tasks, nil
}

func (s *Sqlite) migrate(wanted []sqliteMigration) error {
	// admin table
	if _, err := s.db.Exec(`

M internal/task/localtask.go => internal/task/localtask.go +6 -0
@@ 7,10 7,16 @@ import (
	"strings"
)

const (
	STATUS_FETCHED = "fetched"
	STATUS_UPDATED = "updated"
)

type LocalTask struct {
	Task
	LocalId     int
	LocalUpdate *LocalUpdate
	LocalStatus string
}

func (lt *LocalTask) HasUpdate() bool {

M pkg/mstore/mstore.go => pkg/mstore/mstore.go +0 -17
@@ 2,7 2,6 @@ package mstore

import (
	"errors"
	"fmt"
)

var (


@@ 25,29 24,13 @@ func (m *Message) Valid() bool {
}

func (m *Message) Equal(n *Message) bool {
	var prt bool
	if m.Uid == 156 && n.Uid == 155 {
		prt = true
	}
	if m.Uid == 155 && n.Uid == 156 {
		prt = true
	}
	if m.Folder != n.Folder {
		if prt {
			fmt.Println("folder")
		}
		return false
	}
	if m.Subject != n.Subject {
		if prt {
			fmt.Println("subject")
		}
		return false
	}
	if m.Body != n.Body {
		if prt {
			fmt.Println("body")
		}
		return false
	}