1use std::path::{Path, PathBuf};
2
3pub fn save_file_path(env_var: &str, file_name: &str) -> PathBuf {
4 if let Ok(p) = std::env::var(env_var)
5 && !p.is_empty()
6 {
7 return PathBuf::from(p);
8 }
9 std::env::current_dir()
10 .unwrap_or_else(|_| PathBuf::from("."))
11 .join(file_name)
12}
13
14pub fn store_json(text: &str, path: &Path) -> Result<(), String> {
15 if let Some(parent) = path.parent()
16 && !parent.as_os_str().is_empty()
17 {
18 std::fs::create_dir_all(parent).map_err(|e| e.to_string())?;
19 }
20 let tmp = path.with_extension("tmp");
28 std::fs::write(&tmp, text).map_err(|e| e.to_string())?;
29 std::fs::rename(&tmp, path).map_err(|e| e.to_string())
30}
31
32pub fn load_json(path: &Path) -> Result<String, String> {
33 std::fs::read_to_string(path).map_err(|e| e.to_string())
34}
35
36#[cfg(test)]
37mod tests {
38 use super::*;
39
40 #[test]
41 fn env_override_wins() {
42 let _lock = ENV_LOCK.lock().unwrap();
43 unsafe { std::env::set_var("REPAME_SAVE_TEST_PATH", "/tmp/x.json") };
44 assert_eq!(
45 save_file_path("REPAME_SAVE_TEST_PATH", "s.json"),
46 PathBuf::from("/tmp/x.json")
47 );
48 unsafe { std::env::remove_var("REPAME_SAVE_TEST_PATH") };
49 }
50
51 #[test]
52 fn round_trip_leaves_no_tmp() {
53 let dir = std::env::temp_dir().join(format!("repame-store-{}", std::process::id()));
54 let path = dir.join("save.json");
55 let _ = std::fs::remove_dir_all(&dir);
56 store_json("{\"a\":1}", &path).expect("write");
57 assert_eq!(load_json(&path).expect("read"), "{\"a\":1}");
58 assert!(
59 !path.with_extension("tmp").exists(),
60 "temp renamed away, not left behind"
61 );
62 let _ = std::fs::remove_dir_all(&dir);
63 }
64
65 static ENV_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(());
66}