feat: add hard delete flag and opal clean command
Add --hard flag to `opal delete` for permanent removal and a new `opal clean` command to bulk-purge soft-deleted tasks with optional --older duration filter. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+31
-10
@@ -8,19 +8,25 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var hardDeleteFlag bool
|
||||
|
||||
var deleteCmd = &cobra.Command{
|
||||
Use: "delete [filter...]",
|
||||
Short: "Delete tasks",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
parsed := getParsedArgs(cmd)
|
||||
if err := deleteTasks(parsed.Filters); err != nil {
|
||||
if err := deleteTasks(parsed.Filters, hardDeleteFlag); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func deleteTasks(args []string) error {
|
||||
func init() {
|
||||
deleteCmd.Flags().BoolVar(&hardDeleteFlag, "hard", false, "Permanently remove task from database")
|
||||
}
|
||||
|
||||
func deleteTasks(args []string, hard bool) error {
|
||||
filter, err := engine.ParseFilter(args)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -53,15 +59,24 @@ func deleteTasks(args []string) error {
|
||||
return fmt.Errorf("no tasks matched filter")
|
||||
}
|
||||
|
||||
action := "delete"
|
||||
if hard {
|
||||
action = "permanently delete"
|
||||
}
|
||||
|
||||
if dryRunFlag {
|
||||
fmt.Print(engine.FormatTaskConfirmList("delete", tasks, ws))
|
||||
fmt.Print(engine.FormatTaskConfirmList(action, tasks, ws))
|
||||
fmt.Println("Dry run — no changes made.")
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(tasks) > 1 {
|
||||
fmt.Print(engine.FormatTaskConfirmList("delete", tasks, ws))
|
||||
fmt.Printf("Proceed? (y/N): ")
|
||||
if len(tasks) > 1 || hard {
|
||||
fmt.Print(engine.FormatTaskConfirmList(action, tasks, ws))
|
||||
if hard {
|
||||
fmt.Printf("This cannot be undone. Proceed? (y/N): ")
|
||||
} else {
|
||||
fmt.Printf("Proceed? (y/N): ")
|
||||
}
|
||||
var confirm string
|
||||
fmt.Scanln(&confirm)
|
||||
if confirm != "y" && confirm != "Y" {
|
||||
@@ -71,14 +86,20 @@ func deleteTasks(args []string) error {
|
||||
}
|
||||
|
||||
for _, task := range tasks {
|
||||
task.Delete(false) // Soft delete
|
||||
engine.RecordUndo("delete", task.UUID)
|
||||
task.Delete(hard)
|
||||
if !hard {
|
||||
engine.RecordUndo("delete", task.UUID)
|
||||
}
|
||||
}
|
||||
|
||||
verb := "Deleted"
|
||||
if hard {
|
||||
verb = "Permanently deleted"
|
||||
}
|
||||
if len(tasks) == 1 {
|
||||
fmt.Printf("Deleted task %s\n", engine.FormatTaskSummary(tasks[0], ws))
|
||||
fmt.Printf("%s task %s\n", verb, engine.FormatTaskSummary(tasks[0], ws))
|
||||
} else {
|
||||
fmt.Printf("Deleted %d task(s).\n", len(tasks))
|
||||
fmt.Printf("%s %d task(s).\n", verb, len(tasks))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user