Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions crates/vite_install/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,18 @@ tar = { workspace = true }
tempfile = { workspace = true }
tokio = { workspace = true, features = ["full"] }
tracing = { workspace = true }
vite_command = { workspace = true }
vite_error = { workspace = true }
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"] }

[target.'cfg(not(target_os = "windows"))'.dependencies]
reqwest = { workspace = true, features = ["stream", "rustls-tls", "json"] }
nix = { workspace = true }

[dev-dependencies]
httpmock = { workspace = true }
Expand Down
3 changes: 2 additions & 1 deletion crates/vite_install/src/commands/add.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use std::{collections::HashMap, process::ExitStatus};

use vite_command::run_command;
use vite_error::Error;
use vite_path::AbsolutePath;

use crate::package_manager::{
PackageManager, PackageManagerType, ResolveCommandResult, format_path_env, run_command,
PackageManager, PackageManagerType, ResolveCommandResult, format_path_env,
};

/// The type of dependency to save.
Expand Down
3 changes: 2 additions & 1 deletion crates/vite_install/src/commands/dedupe.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use std::{collections::HashMap, process::ExitStatus};

use vite_command::run_command;
use vite_error::Error;
use vite_path::AbsolutePath;

use crate::package_manager::{
PackageManager, PackageManagerType, ResolveCommandResult, format_path_env, run_command,
PackageManager, PackageManagerType, ResolveCommandResult, format_path_env,
};

/// Options for the dedupe command.
Expand Down
3 changes: 2 additions & 1 deletion crates/vite_install/src/commands/link.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use std::{collections::HashMap, process::ExitStatus};

use vite_command::run_command;
use vite_error::Error;
use vite_path::AbsolutePath;

use crate::package_manager::{
PackageManager, PackageManagerType, ResolveCommandResult, format_path_env, run_command,
PackageManager, PackageManagerType, ResolveCommandResult, format_path_env,
};

/// Options for the link command.
Expand Down
3 changes: 2 additions & 1 deletion crates/vite_install/src/commands/outdated.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use std::{collections::HashMap, process::ExitStatus, str::FromStr};

use vite_command::run_command;
use vite_error::Error;
use vite_path::AbsolutePath;

use crate::package_manager::{
PackageManager, PackageManagerType, ResolveCommandResult, format_path_env, run_command,
PackageManager, PackageManagerType, ResolveCommandResult, format_path_env,
};

/// Output format for the outdated command.
Expand Down
3 changes: 2 additions & 1 deletion crates/vite_install/src/commands/remove.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use std::{collections::HashMap, process::ExitStatus};

use vite_command::run_command;
use vite_error::Error;
use vite_path::AbsolutePath;

use crate::package_manager::{
PackageManager, PackageManagerType, ResolveCommandResult, format_path_env, run_command,
PackageManager, PackageManagerType, ResolveCommandResult, format_path_env,
};

/// Options for the remove command.
Expand Down
3 changes: 2 additions & 1 deletion crates/vite_install/src/commands/unlink.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use std::{collections::HashMap, process::ExitStatus};

use vite_command::run_command;
use vite_error::Error;
use vite_path::AbsolutePath;

use crate::package_manager::{
PackageManager, PackageManagerType, ResolveCommandResult, format_path_env, run_command,
PackageManager, PackageManagerType, ResolveCommandResult, format_path_env,
};

/// Options for the unlink command.
Expand Down
3 changes: 2 additions & 1 deletion crates/vite_install/src/commands/update.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use std::{collections::HashMap, process::ExitStatus};

use vite_command::run_command;
use vite_error::Error;
use vite_path::AbsolutePath;

use crate::package_manager::{
PackageManager, PackageManagerType, ResolveCommandResult, format_path_env, run_command,
PackageManager, PackageManagerType, ResolveCommandResult, format_path_env,
};

/// Options for the update command.
Expand Down
3 changes: 2 additions & 1 deletion crates/vite_install/src/commands/why.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use std::{collections::HashMap, process::ExitStatus};

use vite_command::run_command;
use vite_error::Error;
use vite_path::AbsolutePath;

use crate::package_manager::{
PackageManager, PackageManagerType, ResolveCommandResult, format_path_env, run_command,
PackageManager, PackageManagerType, ResolveCommandResult, format_path_env,
};

/// Options for the why command.
Expand Down
115 changes: 1 addition & 114 deletions crates/vite_install/src/package_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@ use std::{
fs::{self, File},
io::BufReader,
path::Path,
process::{ExitStatus, Stdio},
};

use semver::{Version, VersionReq};
use serde::{Deserialize, Serialize};
use tokio::{fs::remove_dir_all, process::Command};
use tokio::fs::remove_dir_all;
use vite_error::Error;
use vite_path::{AbsolutePath, AbsolutePathBuf};
use vite_str::Str;
Expand Down Expand Up @@ -504,89 +503,6 @@ pub(crate) fn format_path_env(bin_prefix: impl AsRef<Path>) -> String {
env::join_paths(paths).unwrap().to_string_lossy().to_string()
}

#[cfg(unix)]
fn fix_stdio_streams() {
// libuv may mark stdin/stdout/stderr as close-on-exec, which interferes with Rust's subprocess spawning.
// As a workaround, we clear the FD_CLOEXEC flag on these file descriptors to prevent them from being closed when spawning child processes.
//
// For details see https://github.com/libuv/libuv/issues/2062
// Fixed by reference from https://github.com/electron/electron/pull/15555

use std::os::fd::BorrowedFd;

use nix::{
fcntl::{FcntlArg, FdFlag, fcntl},
libc::{STDERR_FILENO, STDIN_FILENO, STDOUT_FILENO},
};

// Safe function to clear FD_CLOEXEC flag
fn clear_cloexec(fd: BorrowedFd<'_>) {
// Borrow RawFd as BorrowedFd to satisfy AsFd constraint
if let Ok(flags) = fcntl(fd, FcntlArg::F_GETFD) {
let mut fd_flags = FdFlag::from_bits_retain(flags);
if fd_flags.contains(FdFlag::FD_CLOEXEC) {
fd_flags.remove(FdFlag::FD_CLOEXEC);
// Ignore errors: some fd may be closed
let _ = fcntl(fd, FcntlArg::F_SETFD(fd_flags));
}
}
}

// Clear FD_CLOEXEC on stdin, stdout, stderr
clear_cloexec(unsafe { BorrowedFd::borrow_raw(STDIN_FILENO) });
clear_cloexec(unsafe { BorrowedFd::borrow_raw(STDOUT_FILENO) });
clear_cloexec(unsafe { BorrowedFd::borrow_raw(STDERR_FILENO) });
}

// TODO: should move to vite-command crate later
/// Run a command with the given bin name, arguments, environment variables, and current working directory.
///
/// # Arguments
///
/// * `bin_name`: The name of the binary to run.
/// * `args`: The arguments to pass to the binary.
/// * `envs`: The custom environment variables to set for the command, will be merged with the system environment variables.
/// * `cwd`: The current working directory for the command.
///
/// # Returns
///
/// Returns the exit status of the command.
pub(crate) async fn run_command(
bin_name: &str,
args: &[String],
envs: &HashMap<String, String>,
cwd: impl AsRef<AbsolutePath>,
) -> Result<ExitStatus, Error> {
println!("Running: {} {}", bin_name, args.join(" "));

// 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())
.stdin(Stdio::inherit())
.stdout(Stdio::inherit())
.stderr(Stdio::inherit());

// fix stdio streams on unix
#[cfg(unix)]
unsafe {
cmd.pre_exec(|| {
fix_stdio_streams();
Ok(())
});
}

let status = cmd.status().await?;
Ok(status)
}

#[cfg(test)]
mod tests {
use std::fs;
Expand Down Expand Up @@ -1872,33 +1788,4 @@ 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'"
);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
> vp add testnpm2 -D -w -- --no-audit && cat package.json packages/app/package.json packages/utils/package.json # should add package to workspace root
Running: npm install --include-workspace-root --save-dev --no-audit testnpm2

added 3 packages in <variable>ms
{
Expand All @@ -23,7 +22,6 @@ added 3 packages in <variable>ms
}

> vp add @vite-plus-test/utils --workspace -- --no-audit && cat package.json packages/app/package.json packages/utils/package.json # should add @vite-plus-test/utils to workspace root
Running: npm install --no-audit @vite-plus-test/utils

up to date in <variable>ms
{
Expand All @@ -50,7 +48,6 @@ up to date in <variable>ms
}

> vp add testnpm2 test-vite-plus-install@1.0.0 --filter app -- --no-audit && cat package.json packages/app/package.json packages/utils/package.json # should add packages to packages/app
Running: npm install --workspace app --no-audit testnpm2 test-vite-plus-install@<semver>

added 1 package in <variable>ms
{
Expand Down Expand Up @@ -81,7 +78,6 @@ added 1 package in <variable>ms
}

> vp add @vite-plus-test/utils --workspace --filter app -- --no-audit && cat package.json packages/app/package.json packages/utils/package.json # should add @vite-plus-test/utils to packages/app
Running: npm install --workspace app --no-audit @vite-plus-test/utils

up to date in <variable>ms
{
Expand Down Expand Up @@ -113,7 +109,6 @@ up to date in <variable>ms
}

> vp add testnpm2 test-vite-plus-install@1.0.0 --filter "*" -- --no-audit && cat package.json packages/app/package.json packages/utils/package.json # should add testnpm2 test-vite-plus-install to all packages except workspace root
Running: npm install --workspace * --no-audit testnpm2 test-vite-plus-install@<semver>

up to date in <variable>ms
{
Expand Down Expand Up @@ -149,7 +144,6 @@ up to date in <variable>ms
}

> vp add -E testnpm2 test-vite-plus-install@1.0.0 --filter "*" --workspace-root -- --no-audit && cat package.json packages/app/package.json packages/utils/package.json # should add testnpm2 test-vite-plus-install to all packages include workspace root
Running: npm install --workspace * --include-workspace-root --save-exact --no-audit testnpm2 test-vite-plus-install@<semver>

up to date in <variable>ms
{
Expand Down Expand Up @@ -186,7 +180,6 @@ up to date in <variable>ms
}

> vp install test-vite-plus-package@1.0.0 --filter "*" --workspace-root -- --no-audit && cat package.json packages/app/package.json packages/utils/package.json # should install packages alias for add command
Running: npm install --workspace * --include-workspace-root --no-audit test-vite-plus-package@<semver>

added 1 package in <variable>ms
{
Expand Down
5 changes: 0 additions & 5 deletions packages/global/snap-tests/command-add-npm10/snap.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ Options:
Print help

> vp add testnpm2 -D -- --no-audit && cat package.json # should add package as dev dependencies
Running: npm install --save-dev --no-audit testnpm2

added 1 package in <variable>ms
{
Expand All @@ -49,7 +48,6 @@ added 1 package in <variable>ms
}

> vp add testnpm2 test-vite-plus-install --allow-build=test-vite-plus-install -- --no-audit && cat package.json # should add packages to dependencies
Running: npm install --no-audit testnpm2 test-vite-plus-install

added 1 package in <variable>ms
{
Expand All @@ -65,7 +63,6 @@ added 1 package in <variable>ms
}

> vp install test-vite-plus-package@1.0.0 --save-peer -- --no-audit && cat package.json # should install package alias for add
Running: npm install --save-peer --no-audit test-vite-plus-package@<semver>

added 1 package in <variable>ms
{
Expand All @@ -84,7 +81,6 @@ added 1 package in <variable>ms
}

> vp add test-vite-plus-package-optional -O -- --no-audit && cat package.json # should add package as optional dependencies
Running: npm install --save-optional --no-audit test-vite-plus-package-optional

added 1 package in <variable>ms
{
Expand All @@ -106,7 +102,6 @@ added 1 package in <variable>ms
}

> vp add test-vite-plus-package-optional -- --loglevel=warn --no-audit && cat package.json # support pass through arguments
Running: npm install --loglevel=warn --no-audit test-vite-plus-package-optional

up to date in <variable>ms
{
Expand Down
Loading
Loading