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}