1use anyhow::{anyhow, Result};
2use std::collections::BTreeSet;
3use std::path::Path;
4
5use crate::cli::LabelAction;
6use crate::db;
7
8pub fn run(root: &Path, action: &LabelAction, json: bool) -> Result<()> {
9 let store = db::open(root)?;
10
11 match action {
12 LabelAction::Add { id, label } => {
13 let task_id = db::resolve_task_id(&store, id, false)?;
14 let ts = db::now_utc();
15 store.apply_and_persist(|doc| {
16 let tasks = doc.get_map("tasks");
17 let task =
18 db::get_task_map(&tasks, &task_id)?.ok_or_else(|| anyhow!("task not found"))?;
19 let labels = db::get_or_create_child_map(&task, "labels")?;
20 labels.insert(label, true)?;
21 task.insert("updated_at", ts.clone())?;
22 Ok(())
23 })?;
24
25 if json {
26 println!("{}", serde_json::json!({"id": task_id, "label": label}));
27 } else {
28 let c = crate::color::stdout_theme();
29 println!("{}added{} label {label}", c.green, c.reset);
30 }
31 }
32 LabelAction::Rm { id, label } => {
33 let task_id = db::resolve_task_id(&store, id, false)?;
34 let ts = db::now_utc();
35 store.apply_and_persist(|doc| {
36 let tasks = doc.get_map("tasks");
37 let task =
38 db::get_task_map(&tasks, &task_id)?.ok_or_else(|| anyhow!("task not found"))?;
39 let labels = db::get_or_create_child_map(&task, "labels")?;
40 labels.delete(label)?;
41 task.insert("updated_at", ts.clone())?;
42 Ok(())
43 })?;
44
45 if !json {
46 let c = crate::color::stdout_theme();
47 println!("{}removed{} label {label}", c.green, c.reset);
48 }
49 }
50 LabelAction::List { id } => {
51 let task_id = db::resolve_task_id(&store, id, false)?;
52 let task = store
53 .get_task(&task_id, false)?
54 .ok_or_else(|| anyhow!("task not found"))?;
55 if json {
56 println!("{}", serde_json::to_string(&task.labels)?);
57 } else {
58 for l in &task.labels {
59 println!("{l}");
60 }
61 }
62 }
63 LabelAction::ListAll => {
64 let mut set = BTreeSet::new();
65 for task in store.list_tasks()? {
66 for label in task.labels {
67 set.insert(label);
68 }
69 }
70 let labels: Vec<_> = set.into_iter().collect();
71 if json {
72 println!("{}", serde_json::to_string(&labels)?);
73 } else {
74 for l in &labels {
75 println!("{l}");
76 }
77 }
78 }
79 }
80
81 Ok(())
82}