mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-24 12:44:18 +08:00
fix(detect): dedupe Windows Codex npm shims (#4782)
This commit is contained in:
@@ -1445,11 +1445,15 @@ fn opencode_extra_search_paths(
|
||||
fn tool_executable_candidates(tool: &str, dir: &Path) -> Vec<std::path::PathBuf> {
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
vec![
|
||||
let extensionless = dir.join(tool);
|
||||
let mut candidates = vec![
|
||||
dir.join(format!("{tool}.cmd")),
|
||||
dir.join(format!("{tool}.exe")),
|
||||
dir.join(tool),
|
||||
]
|
||||
];
|
||||
if windows_runnable_sibling_for_extensionless_tool(&extensionless).is_none() {
|
||||
candidates.push(extensionless);
|
||||
}
|
||||
candidates
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
@@ -1619,6 +1623,18 @@ fn is_windows_command_script(path: &Path) -> bool {
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn windows_runnable_sibling_for_extensionless_tool(path: &Path) -> Option<std::path::PathBuf> {
|
||||
if path.extension().is_some() {
|
||||
return None;
|
||||
}
|
||||
|
||||
["cmd", "exe"]
|
||||
.iter()
|
||||
.map(|ext| path.with_extension(ext))
|
||||
.find(|candidate| candidate.is_file())
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn run_windows_tool_version_command(
|
||||
tool_path: &Path,
|
||||
@@ -1821,7 +1837,10 @@ fn resolve_path_default(tool: &str) -> Option<std::path::PathBuf> {
|
||||
if first.is_empty() {
|
||||
return None;
|
||||
}
|
||||
std::fs::canonicalize(first).ok()
|
||||
let path = Path::new(first);
|
||||
let preferred =
|
||||
windows_runnable_sibling_for_extensionless_tool(path).unwrap_or_else(|| path.to_path_buf());
|
||||
std::fs::canonicalize(preferred).ok()
|
||||
}
|
||||
|
||||
/// 枚举工具在系统中的所有安装(不短路)。与 `scan_cli_version` 共用
|
||||
@@ -5063,6 +5082,35 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
#[test]
|
||||
fn tool_executable_candidates_windows_skips_shadowed_npm_unix_shim() {
|
||||
let dir = tempfile::tempdir().expect("temp dir should be created");
|
||||
let extensionless = dir.path().join("codex");
|
||||
let cmd = dir.path().join("codex.cmd");
|
||||
std::fs::write(&extensionless, "").expect("extensionless shim should be created");
|
||||
std::fs::write(&cmd, "").expect("cmd shim should be created");
|
||||
|
||||
let candidates = tool_executable_candidates("codex", dir.path());
|
||||
|
||||
assert_eq!(candidates, vec![cmd.clone(), dir.path().join("codex.exe")]);
|
||||
assert!(!candidates.contains(&extensionless));
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
#[test]
|
||||
fn windows_runnable_sibling_prefers_cmd_over_extensionless_tool() {
|
||||
let dir = tempfile::tempdir().expect("temp dir should be created");
|
||||
let extensionless = dir.path().join("codex");
|
||||
let cmd = dir.path().join("codex.cmd");
|
||||
std::fs::write(&extensionless, "").expect("extensionless shim should be created");
|
||||
std::fs::write(&cmd, "").expect("cmd shim should be created");
|
||||
|
||||
let preferred = windows_runnable_sibling_for_extensionless_tool(&extensionless);
|
||||
|
||||
assert_eq!(preferred.as_deref(), Some(cmd.as_path()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resolve_launch_cwd_accepts_existing_directory() {
|
||||
let resolved =
|
||||
|
||||
Reference in New Issue
Block a user