forked from extern/nushell
Add exec
command for Windows (#11001)
# Description Based of the work and discussion in #10844, this PR adds the `exec` command for Windows. This is done by simply spawning a `std::process::Command` and then immediately exiting via `std::process::exit` once the child process is finished. The child process's exit code is passed to `exit`. # User-Facing Changes The `exec` command is now available on Windows, and there should be no change in behaviour for Unix systems.
This commit is contained in:
parent
59ea28cf06
commit
1fd3bc1ba6
@ -115,6 +115,7 @@ pub fn add_shell_command_context(mut engine_state: EngineState) -> EngineState {
|
|||||||
bind_command! {
|
bind_command! {
|
||||||
Complete,
|
Complete,
|
||||||
External,
|
External,
|
||||||
|
Exec,
|
||||||
NuCheck,
|
NuCheck,
|
||||||
Sys,
|
Sys,
|
||||||
};
|
};
|
||||||
@ -145,9 +146,6 @@ pub fn add_shell_command_context(mut engine_state: EngineState) -> EngineState {
|
|||||||
ViewSpan,
|
ViewSpan,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(unix)]
|
|
||||||
bind_command! { Exec }
|
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
bind_command! { RegistryQuery }
|
bind_command! { RegistryQuery }
|
||||||
|
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
use super::run_external::create_external_command;
|
use super::run_external::create_external_command;
|
||||||
use nu_engine::{current_dir, CallExt};
|
use nu_engine::current_dir;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ast::Call,
|
ast::Call,
|
||||||
engine::{Command, EngineState, Stack},
|
engine::{Command, EngineState, Stack},
|
||||||
Category, Example, PipelineData, ShellError, Signature, Spanned, SyntaxShape, Type,
|
Category, Example, PipelineData, ShellError, Signature, Span, SyntaxShape, Type,
|
||||||
};
|
};
|
||||||
use std::os::unix::process::CommandExt;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Exec;
|
pub struct Exec;
|
||||||
@ -24,11 +23,12 @@ impl Command for Exec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
"Execute a command, replacing the current process."
|
"Execute a command, replacing or exiting the current process, depending on platform."
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extra_usage(&self) -> &str {
|
fn extra_usage(&self) -> &str {
|
||||||
"Currently supported only on Unix-based systems."
|
r#"On Unix-based systems, the current process is replaced with the command.
|
||||||
|
On Windows based systems, Nushell will wait for the command to finish and then exit with the command's exit code."#
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(
|
fn run(
|
||||||
@ -62,36 +62,49 @@ fn exec(
|
|||||||
stack: &mut Stack,
|
stack: &mut Stack,
|
||||||
call: &Call,
|
call: &Call,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
let name: Spanned<String> = call.req(engine_state, stack, 0)?;
|
let external_command =
|
||||||
let name_span = name.span;
|
create_external_command(engine_state, stack, call, false, false, false, false)?;
|
||||||
|
|
||||||
let redirect_stdout = call.has_flag("redirect-stdout");
|
|
||||||
let redirect_stderr = call.has_flag("redirect-stderr");
|
|
||||||
let redirect_combine = call.has_flag("redirect-combine");
|
|
||||||
let trim_end_newline = call.has_flag("trim-end-newline");
|
|
||||||
|
|
||||||
let external_command = create_external_command(
|
|
||||||
engine_state,
|
|
||||||
stack,
|
|
||||||
call,
|
|
||||||
redirect_stdout,
|
|
||||||
redirect_stderr,
|
|
||||||
redirect_combine,
|
|
||||||
trim_end_newline,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let cwd = current_dir(engine_state, stack)?;
|
let cwd = current_dir(engine_state, stack)?;
|
||||||
let mut command = external_command.spawn_simple_command(&cwd.to_string_lossy())?;
|
let mut command = external_command.spawn_simple_command(&cwd.to_string_lossy())?;
|
||||||
command.current_dir(cwd);
|
command.current_dir(cwd);
|
||||||
command.envs(&external_command.env_vars);
|
command.envs(external_command.env_vars);
|
||||||
|
|
||||||
let err = command.exec(); // this replaces our process, should not return
|
// this either replaces our process and should not return,
|
||||||
|
// or the exec fails and we get an error back
|
||||||
|
exec_impl(command, call.head)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
fn exec_impl(mut command: std::process::Command, span: Span) -> Result<PipelineData, ShellError> {
|
||||||
|
use std::os::unix::process::CommandExt;
|
||||||
|
|
||||||
|
let error = command.exec();
|
||||||
|
|
||||||
Err(ShellError::GenericError(
|
Err(ShellError::GenericError(
|
||||||
"Error on exec".to_string(),
|
"Error on exec".into(),
|
||||||
err.to_string(),
|
error.to_string(),
|
||||||
Some(name_span),
|
Some(span),
|
||||||
None,
|
None,
|
||||||
Vec::new(),
|
Vec::new(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
fn exec_impl(mut command: std::process::Command, span: Span) -> Result<PipelineData, ShellError> {
|
||||||
|
match command.spawn() {
|
||||||
|
Ok(mut child) => match child.wait() {
|
||||||
|
Ok(status) => std::process::exit(status.code().unwrap_or(0)),
|
||||||
|
Err(e) => Err(ShellError::ExternalCommand {
|
||||||
|
label: "Error in external command".into(),
|
||||||
|
help: e.to_string(),
|
||||||
|
span,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
Err(e) => Err(ShellError::ExternalCommand {
|
||||||
|
label: "Error spawning external command".into(),
|
||||||
|
help: e.to_string(),
|
||||||
|
span,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
mod complete;
|
mod complete;
|
||||||
#[cfg(unix)]
|
|
||||||
mod exec;
|
mod exec;
|
||||||
mod nu_check;
|
mod nu_check;
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
@ -16,7 +15,6 @@ mod sys;
|
|||||||
mod which_;
|
mod which_;
|
||||||
|
|
||||||
pub use complete::Complete;
|
pub use complete::Complete;
|
||||||
#[cfg(unix)]
|
|
||||||
pub use exec::Exec;
|
pub use exec::Exec;
|
||||||
pub use nu_check::NuCheck;
|
pub use nu_check::NuCheck;
|
||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
|
@ -24,7 +24,6 @@ mod echo;
|
|||||||
mod empty;
|
mod empty;
|
||||||
mod error_make;
|
mod error_make;
|
||||||
mod every;
|
mod every;
|
||||||
#[cfg(not(windows))]
|
|
||||||
mod exec;
|
mod exec;
|
||||||
mod export_def;
|
mod export_def;
|
||||||
mod fill;
|
mod fill;
|
||||||
|
Loading…
Reference in New Issue
Block a user