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!(
27 "{}",
28 serde_json::json!({"id": task_id.as_str(), "label": label})
29 );
30 } else {
31 let c = crate::color::stdout_theme();
32 println!("{}added{} label {label}", c.green, c.reset);
33 }
34 }
35 LabelAction::Rm { id, label } => {
36 let task_id = db::resolve_task_id(&store, id, false)?;
37 let ts = db::now_utc();
38 store.apply_and_persist(|doc| {
39 let tasks = doc.get_map("tasks");
40 let task =
41 db::get_task_map(&tasks, &task_id)?.ok_or_else(|| anyhow!("task not found"))?;
42 let labels = db::get_or_create_child_map(&task, "labels")?;
43 labels.delete(label)?;
44 task.insert("updated_at", ts.clone())?;
45 Ok(())
46 })?;
47
48 if !json {
49 let c = crate::color::stdout_theme();
50 println!("{}removed{} label {label}", c.green, c.reset);
51 }
52 }
53 LabelAction::List { id } => {
54 let task_id = db::resolve_task_id(&store, id, false)?;
55 let task = store
56 .get_task(&task_id, false)?
57 .ok_or_else(|| anyhow!("task not found"))?;
58 if json {
59 println!("{}", serde_json::to_string(&task.labels)?);
60 } else {
61 for l in &task.labels {
62 println!("{l}");
63 }
64 }
65 }
66 LabelAction::ListAll => {
67 let mut set = BTreeSet::new();
68 for task in store.list_tasks()? {
69 for label in task.labels {
70 set.insert(label);
71 }
72 }
73 let labels: Vec<_> = set.into_iter().collect();
74 if json {
75 println!("{}", serde_json::to_string(&labels)?);
76 } else {
77 for l in &labels {
78 println!("{l}");
79 }
80 }
81 }
82 }
83
84 Ok(())
85}