From 05ddbdbcd131db48fa951fe238e2aa3d7f1e2e00 Mon Sep 17 00:00:00 2001 From: Lemon-miaow Date: Sat, 7 Nov 2026 09:24:10 +0800 Subject: [PATCH] =?UTF-8?q?fix(macos):=20=E5=BA=94=E7=94=A8=E5=8C=85?= =?UTF-8?q?=E5=86=85=E8=87=AA=E5=B8=A6=20interface.json=20=E6=97=B6?= =?UTF-8?q?=E4=BB=A5=E5=8F=AF=E6=89=A7=E8=A1=8C=E6=96=87=E4=BB=B6=E7=9B=AE?= =?UTF-8?q?=E5=BD=95=E4=B8=BA=E9=A1=B9=E7=9B=AE=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src-tauri/src/commands/utils.rs | 55 +++++++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/src-tauri/src/commands/utils.rs b/src-tauri/src/commands/utils.rs index a8f1ef81..71702ffb 100644 --- a/src-tauri/src/commands/utils.rs +++ b/src-tauri/src/commands/utils.rs @@ -292,26 +292,26 @@ pub fn get_logs_dir() -> PathBuf { .join("debug") } -/// 获取运行时项目目录(内部使用)。 -/// -/// Windows/Linux 下为可执行文件所在目录;macOS 使用 `.app` 发布时, -/// 为 `.app` 所在目录,使 `interface.json`、`maafw/` 等项目资源仍可与 -/// 应用包并列放置。 +/// 获取运行时项目目录(内部使用):macOS `.app` 内没有 `interface.json` 时为 `.app` 所在目录,否则为可执行文件所在目录。 pub fn get_exe_directory() -> Result { let exe_path = std::env::current_exe().map_err(|e| format!("获取 exe 路径失败: {}", e))?; - let exe_dir = exe_path - .parent() - .map(|p| p.to_path_buf()) - .ok_or_else(|| "无法获取 exe 所在目录".to_string())?; + project_dir_for_executable(&exe_path).ok_or_else(|| "无法获取 exe 所在目录".to_string()) +} + +fn project_dir_for_executable(exe_path: &std::path::Path) -> Option { + let exe_dir = exe_path.parent()?; #[cfg(target_os = "macos")] - if let Some(bundle) = macos_app_bundle(&exe_path) { - if let Some(project_dir) = bundle.parent() { - return Ok(project_dir.to_path_buf()); + if !exe_dir.join("interface.json").exists() { + if let Some(project_dir) = macos_app_bundle(exe_path) + .as_deref() + .and_then(std::path::Path::parent) + { + return Some(project_dir.to_path_buf()); } } - Ok(exe_dir) + Some(exe_dir.to_path_buf()) } #[cfg(any(target_os = "macos", test))] @@ -348,6 +348,35 @@ mod tests { assert!(macos_app_bundle(Path::new("project/mxu")).is_none()); assert!(macos_app_bundle(Path::new("project/MXU.app/mxu")).is_none()); } + + #[cfg(target_os = "macos")] + #[test] + fn macos_project_dir_follows_interface_location() { + let root = std::env::temp_dir().join(format!( + "mxu-project-dir-{}-{}", + std::process::id(), + std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap() + .as_nanos() + )); + let project = root.join("project"); + let macos = project.join("MaaEnd.app/Contents/MacOS"); + let portable = root.join("portable"); + std::fs::create_dir_all(&macos).unwrap(); + std::fs::create_dir_all(&portable).unwrap(); + let exe = macos.join("MaaEnd"); + + assert_eq!(project_dir_for_executable(&exe), Some(project)); + std::fs::write(macos.join("interface.json"), b"{}").unwrap(); + assert_eq!(project_dir_for_executable(&exe), Some(macos)); + assert_eq!( + project_dir_for_executable(&portable.join("mxu")), + Some(portable) + ); + + std::fs::remove_dir_all(root).unwrap(); + } } /// 获取运行时项目目录下的 maafw 子目录