Skip to main content

things3_cloud/
cmd_ctx.rs

1use crate::app::Cli;
2use crate::cloud_writer::{CloudWriter, DryRunCloudWriter, LiveCloudWriter, LoggingCloudWriter};
3use crate::ids::ThingsId;
4use crate::wire::wire_object::WireObject;
5use anyhow::Result;
6use chrono::{DateTime, TimeZone, Utc};
7use std::collections::BTreeMap;
8
9pub trait CmdCtx {
10    fn now_timestamp(&self) -> f64;
11    fn today_timestamp(&self) -> i64;
12    fn today(&self) -> DateTime<Utc> {
13        let ts = self.today_timestamp();
14        Utc.timestamp_opt(ts, 0)
15            .single()
16            .unwrap_or_else(Utc::now)
17            .date_naive()
18            .and_hms_opt(0, 0, 0)
19            .map(|d| Utc.from_utc_datetime(&d))
20            .unwrap_or_else(Utc::now)
21    }
22    fn next_id(&mut self) -> String;
23    fn commit_changes(
24        &mut self,
25        changes: BTreeMap<String, WireObject>,
26        ancestor_index: Option<i64>,
27    ) -> Result<i64>;
28    fn current_head_index(&self) -> i64;
29}
30
31#[derive(Default)]
32pub struct DefaultCmdCtx {
33    no_cloud: bool,
34    today_ts_override: Option<i64>,
35    now_ts_override: Option<f64>,
36    writer: Option<Box<dyn CloudWriter>>,
37}
38
39impl DefaultCmdCtx {
40    pub fn from_cli(cli: &Cli) -> Self {
41        Self {
42            no_cloud: cli.no_cloud,
43            today_ts_override: cli.today_ts,
44            now_ts_override: cli.now_ts,
45            writer: None,
46        }
47    }
48
49    fn writer_mut(&mut self) -> Result<&mut dyn CloudWriter> {
50        if self.writer.is_none() {
51            let inner: Box<dyn CloudWriter> = if self.no_cloud {
52                Box::new(DryRunCloudWriter::new())
53            } else {
54                Box::new(LiveCloudWriter::new()?)
55            };
56            self.writer = Some(Box::new(LoggingCloudWriter::new(inner)));
57        }
58        Ok(self.writer.as_deref_mut().expect("writer initialized"))
59    }
60}
61
62impl CmdCtx for DefaultCmdCtx {
63    fn now_timestamp(&self) -> f64 {
64        self.now_ts_override
65            .unwrap_or_else(crate::common::now_ts_f64)
66    }
67
68    fn today_timestamp(&self) -> i64 {
69        self.today_ts_override
70            .unwrap_or_else(|| crate::common::today_utc().timestamp())
71    }
72
73    fn next_id(&mut self) -> String {
74        ThingsId::random().to_string()
75    }
76
77    fn commit_changes(
78        &mut self,
79        changes: BTreeMap<String, WireObject>,
80        ancestor_index: Option<i64>,
81    ) -> Result<i64> {
82        self.writer_mut()?.commit(changes, ancestor_index)
83    }
84
85    fn current_head_index(&self) -> i64 {
86        self.writer.as_deref().map_or(0, CloudWriter::head_index)
87    }
88}