ricecoder_storage/
first_run.rs1use crate::error::StorageResult;
7use crate::manager::PathResolver;
8use std::fs;
9use std::path::{Path, PathBuf};
10
11const FIRST_RUN_MARKER: &str = ".ricecoder-initialized";
13
14pub struct FirstRunHandler;
16
17impl FirstRunHandler {
18 pub fn is_first_run(global_path: &Path) -> StorageResult<bool> {
22 let marker_path = global_path.join(FIRST_RUN_MARKER);
23 Ok(!marker_path.exists())
24 }
25
26 pub fn mark_first_run_complete(global_path: &Path) -> StorageResult<()> {
30 let marker_path = global_path.join(FIRST_RUN_MARKER);
31
32 if let Some(parent) = marker_path.parent() {
34 if !parent.exists() {
35 fs::create_dir_all(parent).map_err(|e| {
36 crate::error::StorageError::directory_creation_failed(parent.to_path_buf(), e)
37 })?;
38 }
39 }
40
41 fs::write(&marker_path, "").map_err(|e| {
43 crate::error::StorageError::io_error(marker_path, crate::error::IoOperation::Write, e)
44 })?;
45
46 Ok(())
47 }
48
49 pub fn get_suggested_path() -> StorageResult<PathBuf> {
53 PathResolver::resolve_global_path()
54 }
55
56 pub fn detect_first_run() -> StorageResult<bool> {
62 let global_path = PathResolver::resolve_global_path()?;
63
64 if !global_path.exists() {
65 return Ok(true);
66 }
67
68 Self::is_first_run(&global_path)
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75 use tempfile::TempDir;
76
77 #[test]
78 fn test_is_first_run_no_marker() {
79 let temp_dir = TempDir::new().expect("Failed to create temp dir");
80 let is_first =
81 FirstRunHandler::is_first_run(temp_dir.path()).expect("Failed to check first run");
82 assert!(is_first, "Should be first run when marker doesn't exist");
83 }
84
85 #[test]
86 fn test_is_first_run_with_marker() {
87 let temp_dir = TempDir::new().expect("Failed to create temp dir");
88 let marker_path = temp_dir.path().join(FIRST_RUN_MARKER);
89 fs::write(&marker_path, "").expect("Failed to create marker");
90
91 let is_first =
92 FirstRunHandler::is_first_run(temp_dir.path()).expect("Failed to check first run");
93 assert!(!is_first, "Should not be first run when marker exists");
94 }
95
96 #[test]
97 fn test_mark_first_run_complete() {
98 let temp_dir = TempDir::new().expect("Failed to create temp dir");
99 let path = temp_dir.path().to_path_buf();
100
101 let is_first_before =
103 FirstRunHandler::is_first_run(&path).expect("Failed to check first run");
104 assert!(is_first_before);
105
106 FirstRunHandler::mark_first_run_complete(&path).expect("Failed to mark first run complete");
108
109 let is_first_after =
111 FirstRunHandler::is_first_run(&path).expect("Failed to check first run");
112 assert!(!is_first_after);
113 }
114
115 #[test]
116 fn test_get_suggested_path() {
117 let path = FirstRunHandler::get_suggested_path().expect("Failed to get suggested path");
118 assert!(path.to_string_lossy().contains(".ricecoder"));
119 }
120
121 #[test]
122 fn test_detect_first_run_nonexistent_dir() {
123 let result = FirstRunHandler::detect_first_run();
125 assert!(
126 result.is_ok(),
127 "Should successfully detect first run status"
128 );
129 }
130}