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