Skip to content

Commit 777bd7c

Browse files
committed
refactor(pm): directly run add command
1 parent c1c764a commit 777bd7c

20 files changed

Lines changed: 162 additions & 272 deletions

File tree

crates/vite_package_manager/src/add.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
use std::collections::HashMap;
1+
use std::{collections::HashMap, process::ExitStatus};
2+
3+
use vite_error::Error;
4+
use vite_path::AbsolutePath;
25

36
use crate::package_manager::{
4-
PackageManager, PackageManagerType, ResolveCommandResult, format_path_env,
7+
PackageManager, PackageManagerType, ResolveCommandResult, format_path_env, run_command,
58
};
69

710
/// The type of dependency to save.
@@ -33,6 +36,19 @@ pub struct AddCommandOptions<'a> {
3336
}
3437

3538
impl PackageManager {
39+
/// Run the add command with the package manager.
40+
/// Return the exit status of the command.
41+
#[must_use]
42+
pub async fn run_add_command(
43+
&self,
44+
options: &AddCommandOptions<'_>,
45+
cwd: impl AsRef<AbsolutePath>,
46+
) -> Result<ExitStatus, Error> {
47+
let resolve_command = self.resolve_add_command(options);
48+
run_command(&resolve_command.bin_path, &resolve_command.args, &resolve_command.envs, cwd)
49+
.await
50+
}
51+
3652
/// Resolve the add command.
3753
#[must_use]
3854
pub fn resolve_add_command(&self, options: &AddCommandOptions) -> ResolveCommandResult {

crates/vite_package_manager/src/package_manager.rs

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ use std::{
44
fs::{self, File},
55
io::{BufReader, Seek, SeekFrom},
66
path::Path,
7+
process::{ExitStatus, Stdio},
78
};
89

910
use semver::{Version, VersionReq};
1011
use serde::{Deserialize, Serialize};
11-
use tokio::fs::remove_dir_all;
12+
use tokio::{fs::remove_dir_all, process::Command};
1213
use vite_error::Error;
1314
use vite_path::{AbsolutePath, AbsolutePathBuf, RelativePathBuf};
1415
use vite_str::Str;
@@ -138,8 +139,8 @@ impl PackageManagerBuilder {
138139
}
139140

140141
impl PackageManager {
141-
pub fn builder(workspace_root: impl AsRef<AbsolutePath>) -> PackageManagerBuilder {
142-
PackageManagerBuilder::new(workspace_root)
142+
pub fn builder(cwd: impl AsRef<AbsolutePath>) -> PackageManagerBuilder {
143+
PackageManagerBuilder::new(cwd)
143144
}
144145

145146
#[must_use]
@@ -600,6 +601,27 @@ pub(crate) fn format_path_env(bin_prefix: impl AsRef<Path>) -> String {
600601
env::join_paths(paths).unwrap().to_string_lossy().to_string()
601602
}
602603

604+
pub(crate) async fn run_command(
605+
bin_name: &str,
606+
args: &Vec<String>,
607+
envs: &HashMap<String, String>,
608+
cwd: impl AsRef<AbsolutePath>,
609+
) -> Result<ExitStatus, Error> {
610+
println!("Running: {} {}", bin_name, args.join(" "));
611+
612+
// TODO: color support for stdout/stderr
613+
let status = Command::new(bin_name)
614+
.args(args)
615+
.envs(envs)
616+
.current_dir(cwd.as_ref())
617+
.stdin(Stdio::inherit())
618+
.stdout(Stdio::inherit())
619+
.stderr(Stdio::inherit())
620+
.status()
621+
.await?;
622+
Ok(status)
623+
}
624+
603625
#[cfg(test)]
604626
mod tests {
605627
use std::fs;

crates/vite_task/src/add.rs

Lines changed: 11 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,24 @@
1-
use petgraph::stable_graph::StableGraph;
1+
use std::process::ExitStatus;
2+
23
use vite_package_manager::{
34
add::{AddCommandOptions, SaveDependencyType},
45
package_manager::PackageManager,
56
};
67
use vite_path::AbsolutePathBuf;
78

8-
use crate::{
9-
Error, ResolveCommandResult, Workspace,
10-
config::ResolvedTask,
11-
schedule::{ExecutionPlan, ExecutionSummary},
12-
};
9+
use crate::Error;
1310

1411
/// Add command for adding packages to dependencies.
1512
///
1613
/// This command automatically detects the package manager and translates
1714
/// the add command to the appropriate package manager-specific syntax.
1815
pub struct AddCommand {
19-
workspace_root: AbsolutePathBuf,
16+
cwd: AbsolutePathBuf,
2017
}
2118

2219
impl AddCommand {
23-
pub fn new(workspace_root: AbsolutePathBuf) -> Self {
24-
Self { workspace_root }
20+
pub fn new(cwd: AbsolutePathBuf) -> Self {
21+
Self { cwd }
2522
}
2623

2724
pub async fn execute(
@@ -36,15 +33,11 @@ impl AddCommand {
3633
global: bool,
3734
allow_build: Option<&str>,
3835
pass_through_args: Option<&[String]>,
39-
) -> Result<ExecutionSummary, Error> {
36+
) -> Result<ExitStatus, Error> {
4037
if packages.is_empty() {
4138
return Err(Error::NoPackagesSpecified);
4239
}
4340

44-
// Detect package manager
45-
let package_manager = PackageManager::builder(&self.workspace_root).build().await?;
46-
let workspace = Workspace::partial_load(self.workspace_root)?;
47-
4841
let add_command_options = AddCommandOptions {
4942
packages,
5043
save_dependency_type,
@@ -57,26 +50,11 @@ impl AddCommand {
5750
allow_build,
5851
pass_through_args,
5952
};
60-
let resolve_command = package_manager.resolve_add_command(&add_command_options);
6153

62-
println!("Running: {} {}", resolve_command.bin_path, resolve_command.args.join(" "));
63-
64-
// TODO: set cacheable to false
65-
let resolved_task = ResolvedTask::resolve_from_builtin_with_command_result(
66-
&workspace,
67-
"add",
68-
resolve_command.args.iter(),
69-
ResolveCommandResult { bin_path: resolve_command.bin_path, envs: resolve_command.envs },
70-
false,
71-
None,
72-
)?;
73-
74-
let mut task_graph: StableGraph<ResolvedTask, ()> = Default::default();
75-
task_graph.add_node(resolved_task);
76-
let summary = ExecutionPlan::plan(task_graph, false)?.execute(&workspace).await?;
77-
workspace.unload().await?;
54+
// Detect package manager
55+
let package_manager = PackageManager::builder(&self.cwd).build().await?;
7856

79-
Ok(summary)
57+
package_manager.run_add_command(&add_command_options, &self.cwd).await
8058
}
8159
}
8260

@@ -93,7 +71,7 @@ mod tests {
9371
};
9472

9573
let cmd = AddCommand::new(workspace_root.clone());
96-
assert_eq!(cmd.workspace_root, workspace_root);
74+
assert_eq!(cmd.cwd, workspace_root);
9775
}
9876

9977
#[tokio::test]

crates/vite_task/src/lib.rs

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ async fn execute_add_command(
241241
global: bool,
242242
allow_build: Option<&str>,
243243
pass_through_args: Option<&[String]>,
244-
) -> Result<ExecutionSummary, Error> {
244+
) -> Result<ExitStatus, Error> {
245245
let save_dependency_type = if save_dev {
246246
Some(SaveDependencyType::Dev)
247247
} else if save_peer {
@@ -342,6 +342,37 @@ pub struct ResolvedUniversalViteConfig {
342342
pub fmt: Option<FmtConfig>,
343343
}
344344

345+
#[cfg(unix)]
346+
fn fix_stdio_streams() {
347+
// libuv may mark stdin/stdout/stderr as close-on-exec, which interferes with Rust's subprocess spawning.
348+
// As a workaround, we clear the FD_CLOEXEC flag on these file descriptors to prevent them from being closed when spawning child processes.
349+
//
350+
// For details see https://github.com/libuv/libuv/issues/2062
351+
// Fixed by reference from https://github.com/electron/electron/pull/15555
352+
353+
use std::os::unix::io::RawFd;
354+
355+
use nix::libc;
356+
357+
unsafe {
358+
// Helper function to clear FD_CLOEXEC flag on a file descriptor
359+
let clear_cloexec = |fd: RawFd| {
360+
// Get current file descriptor flags
361+
let flags = libc::fcntl(fd, libc::F_GETFD);
362+
if flags >= 0 {
363+
// Clear the FD_CLOEXEC flag
364+
let new_flags = flags & !libc::FD_CLOEXEC;
365+
libc::fcntl(fd, libc::F_SETFD, new_flags);
366+
}
367+
};
368+
369+
// Clear FD_CLOEXEC on stdin, stdout, stderr
370+
clear_cloexec(libc::STDIN_FILENO);
371+
clear_cloexec(libc::STDOUT_FILENO);
372+
clear_cloexec(libc::STDERR_FILENO);
373+
}
374+
}
375+
345376
/// Main entry point for vite-plus task execution.
346377
///
347378
/// # Execution Flow
@@ -409,6 +440,9 @@ pub async fn main<
409440
>,
410441
>,
411442
) -> Result<std::process::ExitStatus, Error> {
443+
#[cfg(unix)]
444+
fix_stdio_streams();
445+
412446
// Auto-install dependencies if needed, but skip for install command itself, or if `VITE_DISABLE_AUTO_INSTALL=1` is set.
413447
if !matches!(args.commands, Commands::Install { .. })
414448
&& std::env::var_os("VITE_DISABLE_AUTO_INSTALL") != Some("1".into())
@@ -534,7 +568,7 @@ pub async fn main<
534568
allow_build,
535569
pass_through_args,
536570
} => {
537-
execute_add_command(
571+
let exit_status = execute_add_command(
538572
cwd,
539573
packages,
540574
*save_prod,
@@ -551,7 +585,8 @@ pub async fn main<
551585
allow_build.as_deref(),
552586
pass_through_args.as_deref(),
553587
)
554-
.await?
588+
.await?;
589+
return Ok(exit_status);
555590
}
556591
Commands::Install { args } => {
557592
// Check if args contain packages - if yes, redirect to Add command
@@ -573,7 +608,7 @@ pub async fn main<
573608
pass_through_args,
574609
}) = parse_install_as_add(args)
575610
{
576-
execute_add_command(
611+
let exit_status = execute_add_command(
577612
cwd,
578613
&packages,
579614
save_prod,
@@ -590,7 +625,8 @@ pub async fn main<
590625
allow_build.as_deref(),
591626
pass_through_args.as_deref(),
592627
)
593-
.await?
628+
.await?;
629+
return Ok(exit_status);
594630
} else {
595631
install::InstallCommand::builder(cwd).build().execute(args).await?
596632
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"install-global-cli": "npm install -g ./packages/global",
1414
"typecheck": "tsc -b tsconfig.json",
1515
"lint": "vite lint && vite run typecheck",
16-
"test": "vite test && pnpm -r snap-test",
16+
"test": "vite test run && pnpm -r snap-test",
1717
"prepare": "husky"
1818
},
1919
"devDependencies": {

packages/cli/binding/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,8 @@ pub async fn run(options: CliOptions) -> Result<i32> {
197197
)
198198
.await;
199199

200+
tracing::debug!("Result: {result:?}");
201+
200202
match result {
201203
Ok(exit_status) => Ok(exit_status.code().unwrap_or(1)),
202204
Err(e) => {

packages/global/snap-tests/command-add-npm10-with-workspace/snap.txt

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
Running: npm install --include-workspace-root --save-dev --no-audit testnpm2
33

44
added 3 packages in <variable>ms
5-
65
{
76
"name": "command-add-npm10-with-workspace",
87
"version": "1.0.0",
@@ -27,7 +26,6 @@ added 3 packages in <variable>ms
2726
Running: npm install --no-audit @vite-plus-test/utils
2827

2928
up to date in <variable>ms
30-
3129
{
3230
"name": "command-add-npm10-with-workspace",
3331
"version": "1.0.0",
@@ -55,7 +53,6 @@ up to date in <variable>ms
5553
Running: npm install --workspace app --no-audit testnpm2 test-vite-plus-install@<semver>
5654

5755
added 1 package in <variable>ms
58-
5956
{
6057
"name": "command-add-npm10-with-workspace",
6158
"version": "1.0.0",
@@ -87,7 +84,6 @@ added 1 package in <variable>ms
8784
Running: npm install --workspace app --no-audit @vite-plus-test/utils
8885

8986
up to date in <variable>ms
90-
9187
{
9288
"name": "command-add-npm10-with-workspace",
9389
"version": "1.0.0",
@@ -120,7 +116,6 @@ up to date in <variable>ms
120116
Running: npm install --workspace * --no-audit testnpm2 test-vite-plus-install@<semver>
121117

122118
up to date in <variable>ms
123-
124119
{
125120
"name": "command-add-npm10-with-workspace",
126121
"version": "1.0.0",
@@ -157,7 +152,6 @@ up to date in <variable>ms
157152
Running: npm install --workspace * --include-workspace-root --save-exact --no-audit testnpm2 test-vite-plus-install@<semver>
158153

159154
up to date in <variable>ms
160-
161155
{
162156
"name": "command-add-npm10-with-workspace",
163157
"version": "1.0.0",
@@ -195,7 +189,6 @@ up to date in <variable>ms
195189
Running: npm install --workspace * --include-workspace-root --no-audit test-vite-plus-package@<semver>
196190

197191
added 1 package in <variable>ms
198-
199192
{
200193
"name": "command-add-npm10-with-workspace",
201194
"version": "1.0.0",

packages/global/snap-tests/command-add-npm10/snap.txt

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ Options:
3939
Running: npm install --save-dev --no-audit testnpm2
4040

4141
added 1 package in <variable>ms
42-
4342
{
4443
"name": "command-add-npm10",
4544
"version": "1.0.0",
@@ -53,7 +52,6 @@ added 1 package in <variable>ms
5352
Running: npm install --no-audit testnpm2 test-vite-plus-install
5453

5554
added 1 package in <variable>ms
56-
5755
{
5856
"name": "command-add-npm10",
5957
"version": "1.0.0",
@@ -70,7 +68,6 @@ added 1 package in <variable>ms
7068
Running: npm install --save-peer --no-audit test-vite-plus-package@<semver>
7169

7270
added 1 package in <variable>ms
73-
7471
{
7572
"name": "command-add-npm10",
7673
"version": "1.0.0",
@@ -90,7 +87,6 @@ added 1 package in <variable>ms
9087
Running: npm install --save-optional --no-audit test-vite-plus-package-optional
9188

9289
added 1 package in <variable>ms
93-
9490
{
9591
"name": "command-add-npm10",
9692
"version": "1.0.0",
@@ -113,7 +109,6 @@ added 1 package in <variable>ms
113109
Running: npm install --loglevel=warn --no-audit test-vite-plus-package-optional
114110

115111
up to date in <variable>ms
116-
117112
{
118113
"name": "command-add-npm10",
119114
"version": "1.0.0",

0 commit comments

Comments
 (0)