update.rs

 1use anyhow::Result;
 2use std::path::Path;
 3
 4use crate::db;
 5
 6pub struct Opts<'a> {
 7    pub status: Option<&'a str>,
 8    pub priority: Option<i32>,
 9    pub effort: Option<i32>,
10    pub title: Option<&'a str>,
11    pub desc: Option<&'a str>,
12    pub json: bool,
13}
14
15pub fn run(root: &Path, id: &str, opts: Opts) -> Result<()> {
16    let conn = db::open(root)?;
17    let ts = db::now_utc();
18
19    let mut sets = vec![format!("updated = '{ts}'")];
20    let mut params: Vec<Box<dyn rusqlite::types::ToSql>> = Vec::new();
21    let mut idx = 1;
22
23    if let Some(s) = opts.status {
24        sets.push(format!("status = ?{idx}"));
25        params.push(Box::new(s.to_string()));
26        idx += 1;
27    }
28    if let Some(p) = opts.priority {
29        sets.push(format!("priority = ?{idx}"));
30        params.push(Box::new(p));
31        idx += 1;
32    }
33    if let Some(e) = opts.effort {
34        sets.push(format!("effort = ?{idx}"));
35        params.push(Box::new(e));
36        idx += 1;
37    }
38    if let Some(t) = opts.title {
39        sets.push(format!("title = ?{idx}"));
40        params.push(Box::new(t.to_string()));
41        idx += 1;
42    }
43    if let Some(d) = opts.desc {
44        sets.push(format!("description = ?{idx}"));
45        params.push(Box::new(d.to_string()));
46        idx += 1;
47    }
48
49    let sql = format!("UPDATE tasks SET {} WHERE id = ?{idx}", sets.join(", "));
50    params.push(Box::new(id.to_string()));
51
52    let param_refs: Vec<&dyn rusqlite::types::ToSql> = params.iter().map(|p| p.as_ref()).collect();
53    conn.execute(&sql, param_refs.as_slice())?;
54
55    if opts.json {
56        let detail = db::load_task_detail(&conn, id)?;
57        println!("{}", serde_json::to_string(&detail)?);
58    } else {
59        let c = crate::color::stdout_theme();
60        println!("{}updated{} {id}", c.green, c.reset);
61    }
62
63    Ok(())
64}