taskers_core/
session_store.rs1use std::{
2 fs,
3 path::{Path, PathBuf},
4};
5
6use anyhow::{Result, bail};
7use taskers_domain::{AppModel, PersistedSession, SESSION_SCHEMA_VERSION};
8use taskers_paths::default_session_path as shared_default_session_path;
9
10pub fn default_session_path() -> PathBuf {
11 shared_default_session_path()
12}
13
14pub fn load_or_bootstrap(path: &Path, demo: bool) -> Result<AppModel> {
15 if path.exists() {
16 match load_session(path) {
17 Ok(model) => Ok(model),
18 Err(error) => {
19 backup_incompatible_session(path)?;
20 eprintln!("failed to load session from {}: {}", path.display(), error);
21 if demo {
22 Ok(AppModel::demo())
23 } else {
24 Ok(AppModel::new("Workspace 1"))
25 }
26 }
27 }
28 } else if demo {
29 Ok(AppModel::demo())
30 } else {
31 Ok(AppModel::new("Workspace 1"))
32 }
33}
34
35pub fn load_session(path: &Path) -> Result<AppModel> {
36 let data = fs::read_to_string(path)?;
37 let session: PersistedSession = serde_json::from_str(&data)?;
38
39 if session.schema_version != SESSION_SCHEMA_VERSION {
40 bail!(
41 "unsupported session schema version {}, expected {}",
42 session.schema_version,
43 SESSION_SCHEMA_VERSION
44 );
45 }
46
47 Ok(session.model)
48}
49
50pub fn save_session(path: &Path, model: &AppModel) -> Result<()> {
51 if let Some(parent) = path.parent() {
52 fs::create_dir_all(parent)?;
53 }
54
55 let session = model.snapshot();
56 let data = serde_json::to_string_pretty(&session)?;
57 fs::write(path, data)?;
58
59 Ok(())
60}
61
62fn backup_incompatible_session(path: &Path) -> Result<()> {
63 let backup_path = path.with_extension("json.bak");
64 if backup_path.exists() {
65 fs::remove_file(&backup_path)?;
66 }
67 fs::rename(path, backup_path)?;
68 Ok(())
69}
70
71#[cfg(test)]
72mod tests {
73 use tempfile::tempdir;
74
75 use super::{load_session, save_session};
76 use taskers_domain::AppModel;
77
78 #[test]
79 fn roundtrips_session_files() {
80 let tempdir = tempdir().expect("tempdir");
81 let session_path = tempdir.path().join("session.json");
82 let model = AppModel::demo();
83
84 save_session(&session_path, &model).expect("session saved");
85 let loaded = load_session(&session_path).expect("session loaded");
86
87 assert_eq!(loaded, model);
88 }
89}