From 5bda7d06e9e0a7c77a9227014be48bd30b8dadf2 Mon Sep 17 00:00:00 2001 From: xintaofei Date: Sat, 11 Apr 2026 18:54:21 +0800 Subject: [PATCH] fix(experts): handle Windows junction removal when unlinking skill entries --- src-tauri/src/commands/acp.rs | 42 ++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/src-tauri/src/commands/acp.rs b/src-tauri/src/commands/acp.rs index 32a7b55..4f019ab 100644 --- a/src-tauri/src/commands/acp.rs +++ b/src-tauri/src/commands/acp.rs @@ -1369,13 +1369,45 @@ fn skill_content_path(layout: AgentSkillLayout, skill_path: &Path) -> PathBuf { pub(crate) fn remove_skill_entry(path: &Path) -> std::io::Result<()> { let meta = fs::symlink_metadata(path)?; let file_type = meta.file_type(); + + #[cfg(windows)] + let is_reparse_point = { + use std::os::windows::fs::MetadataExt; + const FILE_ATTRIBUTE_REPARSE_POINT: u32 = 0x0000_0400; + meta.file_attributes() & FILE_ATTRIBUTE_REPARSE_POINT != 0 + }; + if file_type.is_symlink() { - fs::remove_file(path) - } else if file_type.is_dir() { - fs::remove_dir_all(path) - } else { - fs::remove_file(path) + #[cfg(windows)] + { + // Directory symlinks on Windows require remove_dir. + return match fs::remove_file(path) { + Ok(()) => Ok(()), + Err(err) if err.kind() == std::io::ErrorKind::PermissionDenied => { + fs::remove_dir(path) + } + Err(err) => Err(err), + }; + } + + #[cfg(not(windows))] + { + return fs::remove_file(path); + } } + + if file_type.is_dir() { + #[cfg(windows)] + { + // Junctions are directory reparse points; remove only the link. + if is_reparse_point { + return fs::remove_dir(path); + } + } + return fs::remove_dir_all(path); + } + + fs::remove_file(path) } fn list_skills_from_dir(