mirror of
https://github.com/nushell/nushell.git
synced 2024-12-23 15:39:06 +01:00
Eval external command result immediately when using do
command with -c
(#6645)
* make capture error works better in do command * remove into string test because we have no way to generate Value::Error for now
This commit is contained in:
parent
6f59167960
commit
530ff3893e
@ -2,7 +2,8 @@ use nu_engine::{eval_block, CallExt};
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
Category, Example, IntoPipelineData, PipelineData, Signature, SyntaxShape, Value,
|
||||
Category, Example, ListStream, PipelineData, RawStream, ShellError, Signature, SyntaxShape,
|
||||
Value,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -102,9 +103,75 @@ impl Command for Do {
|
||||
Err(_) => Ok(PipelineData::new(call.head)),
|
||||
}
|
||||
} else if capture_errors {
|
||||
// collect stdout and stderr and check exit code.
|
||||
// if exit code is not 0, return back ShellError.
|
||||
match result {
|
||||
Ok(x) => Ok(x),
|
||||
Err(err) => Ok((Value::Error { error: err }).into_pipeline_data()),
|
||||
Ok(PipelineData::ExternalStream {
|
||||
stdout,
|
||||
stderr,
|
||||
exit_code,
|
||||
span,
|
||||
metadata,
|
||||
}) => {
|
||||
// collect all output first.
|
||||
let mut stderr_ctrlc = None;
|
||||
let stderr_msg = match stderr {
|
||||
None => "".to_string(),
|
||||
Some(stderr_stream) => {
|
||||
stderr_ctrlc = stderr_stream.ctrlc.clone();
|
||||
stderr_stream.into_string().map(|s| s.item)?
|
||||
}
|
||||
};
|
||||
|
||||
let mut stdout_ctrlc = None;
|
||||
let stdout_msg = match stdout {
|
||||
None => "".to_string(),
|
||||
Some(stdout_stream) => {
|
||||
stdout_ctrlc = stdout_stream.ctrlc.clone();
|
||||
stdout_stream.into_string().map(|s| s.item)?
|
||||
}
|
||||
};
|
||||
|
||||
let mut exit_code_ctrlc = None;
|
||||
let exit_code: Vec<Value> = match exit_code {
|
||||
None => vec![],
|
||||
Some(exit_code_stream) => {
|
||||
exit_code_ctrlc = exit_code_stream.ctrlc.clone();
|
||||
exit_code_stream.into_iter().collect()
|
||||
}
|
||||
};
|
||||
if let Some(Value::Int { val: code, .. }) = exit_code.last() {
|
||||
// if exit_code is not 0, it indicates error occured, return back Err.
|
||||
if *code != 0 {
|
||||
return Err(ShellError::ExternalCommand(
|
||||
"External command runs to failed".to_string(),
|
||||
stderr_msg,
|
||||
span,
|
||||
));
|
||||
}
|
||||
}
|
||||
// construct pipeline data to our caller
|
||||
Ok(PipelineData::ExternalStream {
|
||||
stdout: Some(RawStream::new(
|
||||
Box::new(vec![Ok(stdout_msg.into_bytes())].into_iter()),
|
||||
stdout_ctrlc,
|
||||
span,
|
||||
)),
|
||||
stderr: Some(RawStream::new(
|
||||
Box::new(vec![Ok(stderr_msg.into_bytes())].into_iter()),
|
||||
stderr_ctrlc,
|
||||
span,
|
||||
)),
|
||||
exit_code: Some(ListStream::from_stream(
|
||||
exit_code.into_iter(),
|
||||
exit_code_ctrlc,
|
||||
)),
|
||||
span,
|
||||
metadata,
|
||||
})
|
||||
}
|
||||
Ok(other) => Ok(other),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
} else {
|
||||
result
|
||||
|
@ -5,11 +5,47 @@ fn capture_errors_works() {
|
||||
let actual = nu!(
|
||||
cwd: ".", pipeline(
|
||||
r#"
|
||||
do -c {$env.use} | describe
|
||||
do -c {$env.use}
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "error");
|
||||
assert!(actual.err.contains("column_not_found"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn capture_errors_works_for_external() {
|
||||
let actual = nu!(
|
||||
cwd: ".", pipeline(
|
||||
r#"
|
||||
do -c {nu --testbin fail}
|
||||
"#
|
||||
));
|
||||
assert!(actual.err.contains("External command runs to failed"));
|
||||
assert_eq!(actual.out, "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn capture_errors_works_for_external_with_pipeline() {
|
||||
let actual = nu!(
|
||||
cwd: ".", pipeline(
|
||||
r#"
|
||||
do -c {nu --testbin fail} | echo `text`
|
||||
"#
|
||||
));
|
||||
assert!(actual.err.contains("External command runs to failed"));
|
||||
assert_eq!(actual.out, "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn capture_errors_works_for_external_with_semicolon() {
|
||||
let actual = nu!(
|
||||
cwd: ".", pipeline(
|
||||
r#"
|
||||
do -c {nu --testbin fail}; echo `text`
|
||||
"#
|
||||
));
|
||||
assert!(actual.err.contains("External command runs to failed"));
|
||||
assert_eq!(actual.out, "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -172,18 +172,6 @@ fn from_nothing() {
|
||||
assert_eq!(actual.out, "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_error() {
|
||||
let actual = nu!(
|
||||
cwd: ".", pipeline(
|
||||
r#"
|
||||
do -c {$env.use} | into string
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual.out, "nu::shell::column_not_found");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn int_into_string() {
|
||||
let actual = nu!(
|
||||
|
Loading…
Reference in New Issue
Block a user