Skip to content

Commit 3d801d9

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

21 files changed

Lines changed: 213 additions & 274 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: 10 additions & 32 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

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.
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
}

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/cli/snap-tests/vitest-browser-mode/snap.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
> vite test
22

3-
RUN v<semver> <cwd>
3+
RUN v<semver> /private/var/folders/d7/5vmw5m15727gcsyvrqxyrr9h0000gn/T/vite-plus-test-623cfd5e-c93e-4b2f-abce-5621fc6d6231/vitest-browser-mode
44

55
✓ |chromium| src/foo.test.js (1 test) <variable>ms
66

@@ -15,7 +15,7 @@
1515
> vite test
1616
✗ cache miss: content of input 'src/foo.js' changed, executing
1717

18-
RUN v<semver> <cwd>
18+
RUN v<semver> /private/var/folders/d7/5vmw5m15727gcsyvrqxyrr9h0000gn/T/vite-plus-test-623cfd5e-c93e-4b2f-abce-5621fc6d6231/vitest-browser-mode
1919

2020
✓ |chromium| src/foo.test.js (1 test) <variable>ms
2121

@@ -30,7 +30,7 @@
3030
> vite test
3131
✓ cache hit, replaying
3232

33-
RUN v<semver> <cwd>
33+
RUN v<semver> /private/var/folders/d7/5vmw5m15727gcsyvrqxyrr9h0000gn/T/vite-plus-test-623cfd5e-c93e-4b2f-abce-5621fc6d6231/vitest-browser-mode
3434

3535
✓ |chromium| src/foo.test.js (1 test) <variable>ms
3636

packages/cli/snap-tests/yarn-install-with-options/snap.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
--mutex <type>[:specifier] use a mutex to ensure only one yarn instance is executing
4141
--emoji [bool] enable emoji in output (default: true)
4242
-s, --silent skip Yarn console logs, other types of logs (script output) will be printed
43-
--cwd <cwd> working directory to use (default: <cwd>)
43+
--cwd <cwd> working directory to use (default: /private/var/folders/d7/5vmw5m15727gcsyvrqxyrr9h0000gn/T/vite-plus-test-623cfd5e-c93e-4b2f-abce-5621fc6d6231/yarn-install-with-options)
4444
--proxy <host>
4545
--https-proxy <host>
4646
--registry <url> override configuration registry

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
> vp add testnpm2 -D -w -- --no-audit && cat package.json packages/app/package.json packages/utils/package.json # should add package to workspace root
22
Running: npm install --include-workspace-root --save-dev --no-audit testnpm2
3+
CWD: <cwd>
34

45
added 3 packages in <variable>ms
5-
66
{
77
"name": "command-add-npm10-with-workspace",
88
"version": "1.0.0",
@@ -25,9 +25,9 @@ added 3 packages in <variable>ms
2525

2626
> 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
2727
Running: npm install --no-audit @vite-plus-test/utils
28+
CWD: <cwd>
2829

2930
up to date in <variable>ms
30-
3131
{
3232
"name": "command-add-npm10-with-workspace",
3333
"version": "1.0.0",
@@ -53,9 +53,9 @@ up to date in <variable>ms
5353

5454
> 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
5555
Running: npm install --workspace app --no-audit testnpm2 test-vite-plus-install@<semver>
56+
CWD: <cwd>
5657

5758
added 1 package in <variable>ms
58-
5959
{
6060
"name": "command-add-npm10-with-workspace",
6161
"version": "1.0.0",
@@ -85,9 +85,9 @@ added 1 package in <variable>ms
8585

8686
> 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
8787
Running: npm install --workspace app --no-audit @vite-plus-test/utils
88+
CWD: <cwd>
8889

8990
up to date in <variable>ms
90-
9191
{
9292
"name": "command-add-npm10-with-workspace",
9393
"version": "1.0.0",
@@ -118,9 +118,9 @@ up to date in <variable>ms
118118

119119
> 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
120120
Running: npm install --workspace * --no-audit testnpm2 test-vite-plus-install@<semver>
121+
CWD: <cwd>
121122

122123
up to date in <variable>ms
123-
124124
{
125125
"name": "command-add-npm10-with-workspace",
126126
"version": "1.0.0",
@@ -155,9 +155,9 @@ up to date in <variable>ms
155155

156156
> 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
157157
Running: npm install --workspace * --include-workspace-root --save-exact --no-audit testnpm2 test-vite-plus-install@<semver>
158+
CWD: <cwd>
158159

159160
up to date in <variable>ms
160-
161161
{
162162
"name": "command-add-npm10-with-workspace",
163163
"version": "1.0.0",
@@ -193,9 +193,9 @@ up to date in <variable>ms
193193

194194
> 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
195195
Running: npm install --workspace * --include-workspace-root --no-audit test-vite-plus-package@<semver>
196+
CWD: <cwd>
196197

197198
added 1 package in <variable>ms
198-
199199
{
200200
"name": "command-add-npm10-with-workspace",
201201
"version": "1.0.0",

0 commit comments

Comments
 (0)