1- //! First-start installation. A completed binary accepts commands; an unmarked one only sets up .
1+ //! First-start installation followed by command execution through the deployed binary .
22
33mod shell;
44
5- use std:: path:: Path ;
5+ use std:: { path:: Path , process :: ExitCode } ;
66
77use dialoguer:: { Confirm , theme:: ColorfulTheme } ;
88use vp_setup:: { SELF_SETUP_MARKER , VP_BINARY_NAME , install} ;
@@ -14,7 +14,7 @@ use crate::{
1414 error:: Error ,
1515} ;
1616
17- pub ( crate ) async fn maybe_run ( ) -> Result < bool , Error > {
17+ pub ( crate ) async fn maybe_run ( ) -> Result < Option < ExitCode > , Error > {
1818 let shell = std:: env:: var ( env_vars:: VP_SELF_SETUP_SHELL ) . ok ( ) ;
1919 if let Some ( shell) = shell. as_deref ( ) {
2020 if !matches ! ( shell, "sh" | "powershell" ) {
@@ -32,17 +32,46 @@ pub(crate) async fn maybe_run() -> Result<bool, Error> {
3232 if bin. join ( SELF_SETUP_MARKER ) . try_exists ( ) ? {
3333 if let Some ( shell) = shell. as_deref ( ) {
3434 print_shell_result ( shell) ;
35- return Ok ( true ) ;
35+ return Ok ( Some ( ExitCode :: SUCCESS ) ) ;
3636 }
37- return Ok ( false ) ;
37+ return Ok ( None ) ;
3838 }
3939
4040 vp_shared:: validate_vp_dir_env ( ) . map_err ( |error| Error :: Other ( error. to_string ( ) . into ( ) ) ) ?;
41- run ( & binary) . await ?;
41+ // Setup diagnostics must not pollute the original command's machine-readable stdout.
42+ output:: route_user_output_to_stderr ( ) ;
43+ let installed_binary = run ( & binary) . await ?;
4244 if let Some ( shell) = shell. as_deref ( ) {
4345 print_shell_result ( shell) ;
46+ return Ok ( Some ( ExitCode :: SUCCESS ) ) ;
47+ }
48+ let mut args = std:: env:: args_os ( ) ;
49+ let argv0 = args. next ( ) ;
50+ let shim_tool =
51+ argv0. as_deref ( ) . and_then ( |name| name. to_str ( ) ) . and_then ( crate :: shim:: detect_shim_tool) ;
52+ if args. len ( ) == 0 && shim_tool. is_none ( ) && std:: env:: var_os ( "VP_COMPLETE" ) . is_none ( ) {
53+ return Ok ( Some ( ExitCode :: SUCCESS ) ) ;
54+ }
55+ // Re-enter through the marked installation, inheriting cwd, environment and stdio.
56+ let mut command = std:: process:: Command :: new ( installed_binary. as_path ( ) ) ;
57+ command. args ( args) ;
58+ #[ cfg( unix) ]
59+ {
60+ use std:: os:: unix:: process:: CommandExt ;
61+
62+ if let Some ( argv0) = argv0 {
63+ command. arg0 ( argv0) ;
64+ }
65+ Err ( command. exec ( ) . into ( ) )
66+ }
67+ #[ cfg( windows) ]
68+ {
69+ if let Some ( tool) = shim_tool {
70+ command. env ( env_vars:: VP_SHIM_TOOL , tool) ;
71+ }
72+ let status = command. status ( ) ?;
73+ Ok ( Some ( ExitCode :: from ( vp_shared:: exit_code_from_status ( status) as u8 ) ) )
4474 }
45- Ok ( true )
4675}
4776
4877// Only successful setup emits executable output; logs use stderr in this mode.
@@ -68,7 +97,7 @@ fn print_shell_result(shell: &str) {
6897}
6998
7099/// Setup Vite+ for the first run
71- async fn run ( source : & Path ) -> Result < ( ) , Error > {
100+ async fn run ( source : & Path ) -> Result < AbsolutePathBuf , Error > {
72101 let env = EnvConfig :: get ( ) ;
73102 let dirs = & env. dirs ;
74103 let active_binary = dirs. data . join ( "current" ) . join ( "bin" ) . join ( VP_BINARY_NAME ) ;
@@ -231,7 +260,7 @@ async fn run(source: &Path) -> Result<(), Error> {
231260 // A failure above leaves the marker absent so a later launch can retry.
232261 tokio:: fs:: write ( version_dir. join ( "bin" ) . join ( SELF_SETUP_MARKER ) , b"" ) . await ?;
233262 output:: success ( "Vite+ setup complete." ) ;
234- Ok ( ( ) )
263+ Ok ( binary )
235264}
236265
237266fn interactive ( ) -> bool {
0 commit comments