use std::path::Path; use anyhow::{Result, anyhow}; /// 文件系统操作工具 /// 遵循 Tauri 开发规范的文件系统安全操作 pub struct FileSystemService; impl FileSystemService { /// 验证路径是否存在且可访问 pub fn validate_path(path: &str) -> Result { let path = Path::new(path); Ok(path.exists() && path.is_dir()) } /// 获取路径的绝对路径 pub fn get_absolute_path(path: &str) -> Result { let path = Path::new(path); let absolute_path = path.canonicalize()?; Ok(absolute_path.to_string_lossy().to_string()) } /// 检查路径是否为有效的项目目录 pub fn is_valid_project_directory(path: &str) -> Result { let path = Path::new(path); // 检查路径是否存在且为目录 if !path.exists() || !path.is_dir() { return Ok(false); } // 检查是否有读写权限 let metadata = path.metadata()?; if metadata.permissions().readonly() { return Ok(false); } Ok(true) } /// 获取目录名称 pub fn get_directory_name(path: &str) -> Result { let path = Path::new(path); match path.file_name() { Some(name) => Ok(name.to_string_lossy().to_string()), None => Err(anyhow::anyhow!("Invalid directory path")), } } /// 创建项目目录结构 pub fn create_project_structure(project_path: &str) -> Result<()> { let base_path = Path::new(project_path); // 创建基本目录结构 let directories = [ "assets", "output", "temp", "config", ]; for dir in &directories { let dir_path = base_path.join(dir); if !dir_path.exists() { std::fs::create_dir_all(&dir_path)?; } } // 创建项目配置文件 let config_file = base_path.join("mixvideo.project.json"); if !config_file.exists() { let default_config = serde_json::json!({ "version": "0.1.0", "created_at": chrono::Utc::now().to_rfc3339(), "settings": { "auto_save": true, "backup_enabled": true } }); std::fs::write(config_file, serde_json::to_string_pretty(&default_config)?)?; } Ok(()) } /// 检查是否为现有的 MixVideo 项目 pub fn is_mixvideo_project(path: &str) -> bool { let project_file = Path::new(path).join("mixvideo.project.json"); project_file.exists() } /// 创建目录(如果不存在) pub fn create_directory_if_not_exists(path: &str) -> Result<()> { let dir_path = Path::new(path); if !dir_path.exists() { std::fs::create_dir_all(dir_path)?; } Ok(()) } /// 移动文件 pub fn move_file(source: &str, destination: &str) -> Result<()> { let source_path = Path::new(source); let dest_path = Path::new(destination); // 确保源文件存在 if !source_path.exists() { return Err(anyhow!("源文件不存在: {}", source)); } // 确保目标目录存在 if let Some(parent) = dest_path.parent() { std::fs::create_dir_all(parent)?; } // 移动文件 std::fs::rename(source_path, dest_path)?; Ok(()) } /// 复制文件 pub fn copy_file(source: &str, destination: &str) -> Result<()> { let source_path = Path::new(source); let dest_path = Path::new(destination); // 确保源文件存在 if !source_path.exists() { return Err(anyhow!("源文件不存在: {}", source)); } // 确保目标目录存在 if let Some(parent) = dest_path.parent() { std::fs::create_dir_all(parent)?; } // 复制文件 std::fs::copy(source_path, dest_path)?; Ok(()) } /// 获取文件大小 pub fn get_file_size(path: &str) -> Result { let metadata = std::fs::metadata(path)?; Ok(metadata.len()) } /// 检查文件是否存在 pub fn file_exists(path: &str) -> bool { Path::new(path).exists() } } #[cfg(test)] mod tests { use super::*; use tempfile::TempDir; #[test] fn test_validate_path() { // 测试存在的目录 let temp_dir = TempDir::new().unwrap(); let path = temp_dir.path().to_str().unwrap(); assert!(FileSystemService::validate_path(path).unwrap()); // 测试不存在的路径 assert!(!FileSystemService::validate_path("/non/existent/path").unwrap()); } #[test] fn test_get_absolute_path() { let temp_dir = TempDir::new().unwrap(); let path = temp_dir.path().to_str().unwrap(); let absolute_path = FileSystemService::get_absolute_path(path).unwrap(); assert!(absolute_path.len() > path.len() || absolute_path == path); } #[test] fn test_is_valid_project_directory() { let temp_dir = TempDir::new().unwrap(); let path = temp_dir.path().to_str().unwrap(); // 有效目录应该返回 true assert!(FileSystemService::is_valid_project_directory(path).unwrap()); // 不存在的路径应该返回 false assert!(!FileSystemService::is_valid_project_directory("/non/existent/path").unwrap()); } #[test] fn test_get_directory_name() { assert_eq!( FileSystemService::get_directory_name("/path/to/project").unwrap(), "project" ); assert_eq!( FileSystemService::get_directory_name("C:\\Users\\test\\project").unwrap(), "project" ); } #[test] fn test_create_project_structure() { let temp_dir = TempDir::new().unwrap(); let project_path = temp_dir.path().to_str().unwrap(); FileSystemService::create_project_structure(project_path).unwrap(); // 检查目录是否创建 assert!(temp_dir.path().join("assets").exists()); assert!(temp_dir.path().join("output").exists()); assert!(temp_dir.path().join("temp").exists()); assert!(temp_dir.path().join("config").exists()); // 检查配置文件是否创建 assert!(temp_dir.path().join("mixvideo.project.json").exists()); } #[test] fn test_is_mixvideo_project() { let temp_dir = TempDir::new().unwrap(); let project_path = temp_dir.path().to_str().unwrap(); // 初始状态不是 MixVideo 项目 assert!(!FileSystemService::is_mixvideo_project(project_path)); // 创建项目结构后应该是 MixVideo 项目 FileSystemService::create_project_structure(project_path).unwrap(); assert!(FileSystemService::is_mixvideo_project(project_path)); } }