1use anyhow::Result;
2use serde::Serialize;
3use std::path::Path;
4
5use crate::db;
6use crate::ops;
7
8#[derive(Serialize)]
9struct RmResult {
10 requested_ids: Vec<String>,
11 deleted_ids: Vec<String>,
12 unblocked_ids: Vec<String>,
13}
14
15pub fn run(root: &Path, ids: &[String], recursive: bool, force: bool, json: bool) -> Result<()> {
16 let store = db::open(root)?;
17
18 let resolved: Vec<db::TaskId> = ids
19 .iter()
20 .map(|raw| db::resolve_task_id(&store, raw, false))
21 .collect::<Result<_>>()?;
22
23 let result = ops::soft_delete(&store, &resolved, recursive)?;
24
25 if !force && !result.unblocked_ids.is_empty() {
26 let short: Vec<String> = result
27 .unblocked_ids
28 .iter()
29 .map(ToString::to_string)
30 .collect();
31 eprintln!("warning: removed blockers from {}", short.join(", "));
32 }
33
34 if json {
35 let out = RmResult {
36 requested_ids: ids.to_vec(),
37 deleted_ids: result.deleted_ids.iter().map(ToString::to_string).collect(),
38 unblocked_ids: result
39 .unblocked_ids
40 .iter()
41 .map(ToString::to_string)
42 .collect(),
43 };
44 println!("{}", serde_json::to_string(&out)?);
45 } else {
46 let c = crate::color::stdout_theme();
47 for id in result.deleted_ids {
48 println!("{}deleted{} {id}", c.green, c.reset);
49 }
50 }
51
52 Ok(())
53}