1use anyhow::{bail, Result};
2use std::path::Path;
3
4use crate::db;
5
6pub fn run(root: &Path, id: &str, json: bool) -> Result<()> {
7 let conn = db::open(root)?;
8
9 let exists: bool = conn.query_row("SELECT COUNT(*) FROM tasks WHERE id = ?1", [id], |r| {
10 r.get::<_, i64>(0).map(|n| n > 0)
11 })?;
12
13 if !exists {
14 bail!("task {id} not found");
15 }
16
17 let detail = db::load_task_detail(&conn, id)?;
18
19 if json {
20 println!("{}", serde_json::to_string(&detail)?);
21 } else {
22 let c = crate::color::stdout_theme();
23 let t = &detail.task;
24 println!("{} id{} = {}", c.bold, c.reset, t.id);
25 println!("{} title{} = {}", c.bold, c.reset, t.title);
26 println!("{} status{} = {}", c.bold, c.reset, t.status);
27 println!(
28 "{} priority{} = {}",
29 c.bold,
30 c.reset,
31 db::priority_label(t.priority)
32 );
33 println!(
34 "{} effort{} = {}",
35 c.bold,
36 c.reset,
37 db::effort_label(t.effort)
38 );
39 println!("{} type{} = {}", c.bold, c.reset, t.task_type);
40 if !t.description.is_empty() {
41 println!("{} description{} = {}", c.bold, c.reset, t.description);
42 }
43 println!("{} created{} = {}", c.bold, c.reset, t.created);
44 println!("{} updated{} = {}", c.bold, c.reset, t.updated);
45 if !detail.labels.is_empty() {
46 println!(
47 "{} labels{} = {}",
48 c.bold,
49 c.reset,
50 detail.labels.join(",")
51 );
52 }
53 let (open_blockers, closed_blockers) = db::load_blockers_partitioned(&conn, &t.id)?;
54 let total = open_blockers.len() + closed_blockers.len();
55 if total > 0 {
56 let label = if total == 1 { "blocker" } else { "blockers" };
57 let all_closed = open_blockers.is_empty();
58 let mut ids: Vec<String> = Vec::new();
59 for id in &open_blockers {
60 ids.push(id.clone());
61 }
62 for id in &closed_blockers {
63 ids.push(format!("{id} [closed]"));
64 }
65
66 let value = if all_closed {
67 format!("[all closed] {}", ids.join(", "))
68 } else {
69 ids.join(", ")
70 };
71
72 // Right-align the label to match other fields (12 chars wide).
73 println!("{}{label:>12}{} = {value}", c.bold, c.reset);
74 }
75 }
76
77 Ok(())
78}