86 lines
2.1 KiB
Go
86 lines
2.1 KiB
Go
package common
|
|
|
|
import (
|
|
"log/slog"
|
|
|
|
"tasksquire/taskwarrior"
|
|
"tasksquire/timewarrior"
|
|
)
|
|
|
|
// FindTaskByUUID queries Taskwarrior for a task with the given UUID.
|
|
// Returns nil if not found.
|
|
func FindTaskByUUID(tw taskwarrior.TaskWarrior, uuid string) *taskwarrior.Task {
|
|
if uuid == "" {
|
|
return nil
|
|
}
|
|
|
|
// Use empty report to query by UUID filter
|
|
report := &taskwarrior.Report{Name: ""}
|
|
tasks := tw.GetTasks(report, "uuid:"+uuid)
|
|
|
|
if len(tasks) > 0 {
|
|
return tasks[0]
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// SyncIntervalToTask synchronizes a Timewarrior interval's state to the corresponding Taskwarrior task.
|
|
// Action should be "start" or "stop".
|
|
// This function is idempotent and handles edge cases gracefully.
|
|
func SyncIntervalToTask(interval *timewarrior.Interval, tw taskwarrior.TaskWarrior, action string) {
|
|
if interval == nil {
|
|
return
|
|
}
|
|
|
|
// Extract UUID from interval tags
|
|
uuid := timewarrior.ExtractUUID(interval.Tags)
|
|
if uuid == "" {
|
|
slog.Debug("Interval has no UUID tag, skipping task sync",
|
|
"intervalID", interval.ID)
|
|
return
|
|
}
|
|
|
|
// Find corresponding task
|
|
task := FindTaskByUUID(tw, uuid)
|
|
if task == nil {
|
|
slog.Warn("Task not found for UUID, skipping sync",
|
|
"uuid", uuid)
|
|
return
|
|
}
|
|
|
|
// Perform sync action
|
|
switch action {
|
|
case "start":
|
|
// Start task if it's pending (idempotent - taskwarrior handles already-started tasks)
|
|
if task.Status == "pending" {
|
|
slog.Info("Starting Taskwarrior task from interval",
|
|
"uuid", uuid,
|
|
"description", task.Description,
|
|
"alreadyStarted", task.Start != "")
|
|
tw.StartTask(task)
|
|
} else {
|
|
slog.Debug("Task not pending, skipping start",
|
|
"uuid", uuid,
|
|
"status", task.Status)
|
|
}
|
|
|
|
case "stop":
|
|
// Only stop if task is pending and currently started
|
|
if task.Status == "pending" && task.Start != "" {
|
|
slog.Info("Stopping Taskwarrior task from interval",
|
|
"uuid", uuid,
|
|
"description", task.Description)
|
|
tw.StopTask(task)
|
|
} else {
|
|
slog.Debug("Task not started or not pending, skipping stop",
|
|
"uuid", uuid,
|
|
"status", task.Status,
|
|
"hasStart", task.Start != "")
|
|
}
|
|
|
|
default:
|
|
slog.Error("Unknown sync action", "action", action)
|
|
}
|
|
}
|