summaryrefslogtreecommitdiff
path: root/internal/task/crud.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/task/crud.go')
-rw-r--r--internal/task/crud.go66
1 files changed, 66 insertions, 0 deletions
diff --git a/internal/task/crud.go b/internal/task/crud.go
index 51dd13c..d0ec612 100644
--- a/internal/task/crud.go
+++ b/internal/task/crud.go
@@ -255,6 +255,72 @@ func SetRecurrenceContext(ctx context.Context, id int, rec string) error {
return modifyTaskContext(ctx, id, "recur:"+rec)
}
+// SetRecurringSeriesRecurrenceContext sets the recurrence for every known task
+// in a recurring series identified by rootUUID.
+func SetRecurringSeriesRecurrenceContext(ctx context.Context, rootUUID, rec string) error {
+ tasks, err := RecurringSeries(ctx, rootUUID)
+ if err != nil {
+ return err
+ }
+ tasks = recurringSeriesUpdateOrder(tasks, rootUUID)
+ if len(tasks) == 0 {
+ return fmt.Errorf("recurring series %s not found", rootUUID)
+ }
+
+ completed := make([]Task, 0, len(tasks))
+ for _, tsk := range tasks {
+ if tsk.UUID == "" {
+ continue
+ }
+ if err := setRecurrenceUUIDContext(ctx, tsk.UUID, rec); err != nil {
+ if rollbackErr := restoreRecurringSeriesRecurrences(completed); rollbackErr != nil {
+ return fmt.Errorf("set recurrence for %s: %w; rollback failed: %w", tsk.UUID, err, rollbackErr)
+ }
+ return fmt.Errorf("set recurrence for %s: %w", tsk.UUID, err)
+ }
+ completed = append(completed, tsk)
+ }
+ if len(completed) == 0 {
+ return fmt.Errorf("recurring series %s has no task UUIDs", rootUUID)
+ }
+ return nil
+}
+
+func recurringSeriesUpdateOrder(tasks []Task, rootUUID string) []Task {
+ ordered := make([]Task, 0, len(tasks))
+ var root []Task
+ for _, tsk := range tasks {
+ if tsk.UUID == "" {
+ continue
+ }
+ if tsk.UUID == rootUUID {
+ root = append(root, tsk)
+ continue
+ }
+ ordered = append(ordered, tsk)
+ }
+ return append(ordered, root...)
+}
+
+func restoreRecurringSeriesRecurrences(tasks []Task) error {
+ ctx, cancel := rollbackContext()
+ defer cancel()
+
+ for i := len(tasks) - 1; i >= 0; i-- {
+ if err := setRecurrenceUUIDContext(ctx, tasks[i].UUID, tasks[i].Recur); err != nil {
+ return fmt.Errorf("restore recurrence for %s: %w", tasks[i].UUID, err)
+ }
+ }
+ return nil
+}
+
+func setRecurrenceUUIDContext(ctx context.Context, uuid, rec string) error {
+ if uuid == "" {
+ return fmt.Errorf("empty task UUID")
+ }
+ return runContext(ctx, "rc.recurrence.confirmation=no", uuid, "modify", "recur:"+rec)
+}
+
// SetDueDate sets the due date for the task with the given id.
func SetDueDate(id int, due string) error {
return SetDueDateContext(context.Background(), id, due)