diff --git a/Cargo.lock b/Cargo.lock index 384693cb7d..5662f8c863 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1117,7 +1117,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.61.1", ] [[package]] @@ -1776,7 +1776,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.5.10", + "socket2 0.6.0", "tokio", "tower-service", "tracing", @@ -2834,7 +2834,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "socket2 0.5.10", + "socket2 0.6.0", "thiserror 2.0.17", "tokio", "tracing", @@ -2871,9 +2871,9 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.5.10", + "socket2 0.6.0", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] @@ -3147,7 +3147,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.61.1", ] [[package]] @@ -3654,7 +3654,7 @@ dependencies = [ "getrandom 0.3.3", "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.61.1", ] [[package]] @@ -4169,6 +4169,7 @@ dependencies = [ "vite_path", "vite_str", "vite_workspace", + "which", ] [[package]] @@ -4472,7 +4473,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.1", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index ba277739e4..74a731dcf4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -72,6 +72,7 @@ vite_str = { git = "https://github.com/voidzero-dev/vite-task", rev = "d66556ab0 vite_task = { git = "https://github.com/voidzero-dev/vite-task", rev = "d66556ab090fb5c5d85ecc7798a0fe9b6f1f26da" } vite_workspace = { git = "https://github.com/voidzero-dev/vite-task", rev = "d66556ab090fb5c5d85ecc7798a0fe9b6f1f26da" } wax = "0.6.0" +which = "8.0.0" napi = { version = "3.0.0", default-features = false, features = ["async", "error_anyhow"] } napi-build = "2" diff --git a/crates/vite_error/src/lib.rs b/crates/vite_error/src/lib.rs index 260cf60ac6..bc00a2a345 100644 --- a/crates/vite_error/src/lib.rs +++ b/crates/vite_error/src/lib.rs @@ -122,6 +122,9 @@ pub enum Error { #[error("Unsupported hash algorithm: {0}")] UnsupportedHashAlgorithm(Str), + #[error("Cannot find binary path for command '{0}'")] + CannotFindBinaryPath(Str), + #[error(transparent)] Anyhow(#[from] anyhow::Error), } diff --git a/crates/vite_install/Cargo.toml b/crates/vite_install/Cargo.toml index 15cfd2ee35..f56bc8bb09 100644 --- a/crates/vite_install/Cargo.toml +++ b/crates/vite_install/Cargo.toml @@ -30,6 +30,7 @@ vite_glob = { workspace = true } vite_path = { workspace = true } vite_str = { workspace = true } vite_workspace = { workspace = true } +which = { workspace = true, features = ["tracing"] } [target.'cfg(target_os = "windows")'.dependencies] reqwest = { workspace = true, features = ["stream", "native-tls-vendored", "json"] } diff --git a/crates/vite_install/src/package_manager.rs b/crates/vite_install/src/package_manager.rs index f240492b93..52fa1326de 100644 --- a/crates/vite_install/src/package_manager.rs +++ b/crates/vite_install/src/package_manager.rs @@ -332,7 +332,7 @@ async fn download_package_manager( let cache_dir = get_cache_dir()?; let bin_name = package_manager_type.to_string(); // $CACHE_DIR/vite/package_manager/pnpm/10.0.0 - let target_dir = cache_dir.join(format!("package_manager/{bin_name}/{version}")); + let target_dir = cache_dir.join("package_manager").join(&bin_name).join(version); let install_dir = target_dir.join(&bin_name); // If all shims are already exists, return the target directory @@ -559,7 +559,14 @@ pub(crate) async fn run_command( ) -> Result { println!("Running: {} {}", bin_name, args.join(" ")); - let mut cmd = Command::new(bin_name); + // Resolve the command path using which crate + // If PATH is provided in envs, use which_in to search in custom paths + // Otherwise, use which to search in system PATH + let paths = envs.get("PATH"); + let bin_path = which::which_in(bin_name, paths, cwd.as_ref()) + .map_err(|_| Error::CannotFindBinaryPath(bin_name.into()))?; + + let mut cmd = Command::new(bin_path); cmd.args(args) .envs(envs) .current_dir(cwd.as_ref()) @@ -1865,4 +1872,33 @@ mod tests { assert!(matcher.is_match("src/app.ts"), "Should ignore source files"); } } + + mod run_command_tests { + use super::*; + + #[tokio::test] + async fn test_run_command_and_find_binary_path() { + let temp_dir = create_temp_dir(); + let temp_dir_path = AbsolutePathBuf::new(temp_dir.path().to_path_buf()).unwrap(); + let envs = HashMap::from([("PATH".to_string(), format_path_env(&temp_dir_path))]); + let result = + run_command("npm", &["--version".to_string()], &envs, &temp_dir_path).await; + assert!(result.is_ok(), "Should run command successfully, but got error: {:?}", result); + } + + #[tokio::test] + async fn test_run_command_and_not_find_binary_path() { + let temp_dir = create_temp_dir(); + let temp_dir_path = AbsolutePathBuf::new(temp_dir.path().to_path_buf()).unwrap(); + let envs = HashMap::from([("PATH".to_string(), format_path_env(&temp_dir_path))]); + let result = + run_command("npm-not-exists", &["--version".to_string()], &envs, &temp_dir_path) + .await; + assert!(result.is_err(), "Should not find binary path, but got: {:?}", result); + assert_eq!( + result.unwrap_err().to_string(), + "Cannot find binary path for command 'npm-not-exists'" + ); + } + } }