dep.rs

 1use anyhow::{bail, Result};
 2use std::path::Path;
 3
 4use crate::cli::DepAction;
 5use crate::db;
 6
 7pub fn run(root: &Path, action: &DepAction, json: bool) -> Result<()> {
 8    let conn = db::open(root)?;
 9
10    match action {
11        DepAction::Add { child, parent } => {
12            if db::would_cycle(&conn, parent, child)? {
13                bail!("adding dependency would create a cycle: {child} → {parent} → … → {child}");
14            }
15            conn.execute(
16                "INSERT OR IGNORE INTO blockers (task_id, blocker_id) VALUES (?1, ?2)",
17                [child, parent],
18            )?;
19            conn.execute(
20                "UPDATE tasks SET updated = ?1 WHERE id = ?2",
21                rusqlite::params![db::now_utc(), child],
22            )?;
23            if json {
24                println!("{}", serde_json::json!({"child": child, "blocker": parent}));
25            } else {
26                let c = crate::color::stdout_theme();
27                println!(
28                    "{}{child}{} blocked by {}{parent}{}",
29                    c.green, c.reset, c.yellow, c.reset
30                );
31            }
32        }
33        DepAction::Rm { child, parent } => {
34            conn.execute(
35                "DELETE FROM blockers WHERE task_id = ?1 AND blocker_id = ?2",
36                [child, parent],
37            )?;
38            conn.execute(
39                "UPDATE tasks SET updated = ?1 WHERE id = ?2",
40                rusqlite::params![db::now_utc(), child],
41            )?;
42            if !json {
43                let c = crate::color::stdout_theme();
44                println!(
45                    "{}{child}{} no longer blocked by {}{parent}{}",
46                    c.green, c.reset, c.yellow, c.reset
47                );
48            }
49        }
50        DepAction::Tree { id } => {
51            println!("{id}");
52            let mut stmt = conn.prepare("SELECT id FROM tasks WHERE parent = ?1 ORDER BY id")?;
53            let children: Vec<String> = stmt
54                .query_map([id], |r| r.get(0))?
55                .collect::<rusqlite::Result<_>>()?;
56            for child in &children {
57                println!("  {child}");
58            }
59        }
60    }
61
62    Ok(())
63}