subx_cli/core/
file_manager.rs1use std::fs;
2use std::path::{Path, PathBuf};
3
4use crate::{Result, error::SubXError};
5
6pub struct FileManager {
8 operations: Vec<FileOperation>,
9}
10
11#[cfg(test)]
12mod tests {
13 use super::*;
14 use std::fs;
15 use tempfile::TempDir;
16
17 #[test]
18 fn test_file_manager_remove_and_rollback() {
19 let temp_dir = TempDir::new().unwrap();
20 let file_path = temp_dir.path().join("test.txt");
21 fs::write(&file_path, "test content").unwrap();
22
23 let mut manager = FileManager::new();
24 manager.remove_file(&file_path).unwrap();
25 assert!(!file_path.exists(), "檔案應已移除");
26
27 let new_file = temp_dir.path().join("new.txt");
29 fs::write(&new_file, "content").unwrap();
30 manager.record_creation(&new_file);
31 manager.rollback().unwrap();
32 assert!(!new_file.exists(), "建立的檔案應已回滾移除");
33 }
34}
35
36#[derive(Debug)]
38enum FileOperation {
39 Created(PathBuf),
40 Removed(PathBuf),
41}
42
43impl FileManager {
44 pub fn new() -> Self {
46 Self {
47 operations: Vec::new(),
48 }
49 }
50
51 pub fn record_creation<P: AsRef<Path>>(&mut self, path: P) {
53 self.operations
54 .push(FileOperation::Created(path.as_ref().to_path_buf()));
55 }
56
57 pub fn remove_file<P: AsRef<Path>>(&mut self, path: P) -> Result<()> {
59 let path_buf = path.as_ref().to_path_buf();
60 if !path_buf.exists() {
61 return Err(SubXError::FileNotFound(
62 path_buf.to_string_lossy().to_string(),
63 ));
64 }
65 fs::remove_file(&path_buf).map_err(|e| SubXError::FileOperationFailed(e.to_string()))?;
66 self.operations
67 .push(FileOperation::Removed(path_buf.clone()));
68 println!("🗑️ 已移除原始檔案: {}", path_buf.display());
69 Ok(())
70 }
71
72 pub fn rollback(&mut self) -> Result<()> {
74 for op in self.operations.drain(..).rev() {
75 match op {
76 FileOperation::Created(path) => {
77 if path.exists() {
78 fs::remove_file(&path)
79 .map_err(|e| SubXError::FileOperationFailed(e.to_string()))?;
80 println!("🔄 已回滾建立的檔案: {}", path.display());
81 }
82 }
83 FileOperation::Removed(_) => {
84 eprintln!("⚠️ 警告:無法恢復已移除的檔案");
86 }
87 }
88 }
89 Ok(())
90 }
91}
92
93impl Default for FileManager {
94 fn default() -> Self {
95 FileManager::new()
96 }
97}