Add exit code verification (#1622)

This commit is contained in:
Jonathan Turner 2020-04-21 15:14:18 +12:00 committed by GitHub
parent 72cf57dd99
commit 0f7b270740
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 58 additions and 36 deletions

View File

@ -878,20 +878,20 @@ async fn process_line(
} }
pub fn print_err(err: ShellError, host: &dyn Host, source: &Text) { pub fn print_err(err: ShellError, host: &dyn Host, source: &Text) {
let diag = err.into_diagnostic(); if let Some(diag) = err.into_diagnostic() {
let writer = host.err_termcolor();
let writer = host.err_termcolor(); let mut source = source.to_string();
let mut source = source.to_string(); source.push_str(" ");
source.push_str(" "); let files = nu_parser::Files::new(source);
let files = nu_parser::Files::new(source); let _ = std::panic::catch_unwind(move || {
let _ = std::panic::catch_unwind(move || { let _ = language_reporting::emit(
let _ = language_reporting::emit( &mut writer.lock(),
&mut writer.lock(), &files,
&files, &diag,
&diag, &language_reporting::DefaultConfig,
&language_reporting::DefaultConfig, );
); });
}); }
} }
#[cfg(test)] #[cfg(test)]

View File

@ -422,7 +422,15 @@ fn spawn(
// We can give an error when we see a non-zero exit code, but this is different // We can give an error when we see a non-zero exit code, but this is different
// than what other shells will do. // than what other shells will do.
if child.wait().is_err() { let external_failed = match child.wait() {
Err(_) => true,
Ok(exit_status) => match exit_status.code() {
Some(e) if e != 0 => true,
_ => false,
},
};
if external_failed {
let cfg = crate::data::config::config(Tag::unknown()); let cfg = crate::data::config::config(Tag::unknown());
if let Ok(cfg) = cfg { if let Ok(cfg) = cfg {
if cfg.contains_key("nonzero_exit_errors") { if cfg.contains_key("nonzero_exit_errors") {
@ -432,10 +440,14 @@ fn spawn(
"command failed", "command failed",
&stdout_name_tag, &stdout_name_tag,
)), )),
tag: stdout_name_tag, tag: stdout_name_tag.clone(),
})); }));
} }
} }
let _ = stdout_read_tx.send(Ok(Value {
value: UntaggedValue::Error(ShellError::external_non_zero()),
tag: stdout_name_tag,
}));
} }
Ok(()) Ok(())

View File

@ -303,6 +303,9 @@ impl PrettyDebug for ShellError {
ProximateShellError::UntaggedRuntimeError { reason } => { ProximateShellError::UntaggedRuntimeError { reason } => {
b::error("Unknown Error") + b::delimit("(", b::description(reason), ")") b::error("Unknown Error") + b::delimit("(", b::description(reason), ")")
} }
ProximateShellError::ExternalPlaceholderError => {
b::error("non-zero external exit code")
}
} }
} }
} }
@ -415,7 +418,11 @@ impl ShellError {
ProximateShellError::Diagnostic(ShellDiagnostic { diagnostic }).start() ProximateShellError::Diagnostic(ShellDiagnostic { diagnostic }).start()
} }
pub fn into_diagnostic(self) -> Diagnostic<Span> { pub fn external_non_zero() -> ShellError {
ProximateShellError::ExternalPlaceholderError.start()
}
pub fn into_diagnostic(self) -> Option<Diagnostic<Span>> {
match self.error { match self.error {
ProximateShellError::MissingValue { span, reason } => { ProximateShellError::MissingValue { span, reason } => {
let mut d = Diagnostic::new( let mut d = Diagnostic::new(
@ -427,12 +434,12 @@ impl ShellError {
d = d.with_label(Label::new_primary(span)); d = d.with_label(Label::new_primary(span));
} }
d Some(d)
} }
ProximateShellError::ArgumentError { ProximateShellError::ArgumentError {
command, command,
error, error,
} => match error { } => Some(match error {
ArgumentError::InvalidExternalWord => Diagnostic::new( ArgumentError::InvalidExternalWord => Diagnostic::new(
Severity::Error, Severity::Error,
"Invalid bare word for Nu command (did you intend to invoke an external command?)".to_string()) "Invalid bare word for Nu command (did you intend to invoke an external command?)".to_string())
@ -492,7 +499,7 @@ impl ShellError {
), ),
) )
.with_label(Label::new_primary(command.span)), .with_label(Label::new_primary(command.span)),
}, }),
ProximateShellError::TypeError { ProximateShellError::TypeError {
expected, expected,
actual: actual:
@ -500,9 +507,9 @@ impl ShellError {
item: Some(actual), item: Some(actual),
span, span,
}, },
} => Diagnostic::new(Severity::Error, "Type Error").with_label( } => Some(Diagnostic::new(Severity::Error, "Type Error").with_label(
Label::new_primary(span) Label::new_primary(span)
.with_message(format!("Expected {}, found {}", expected, actual)), .with_message(format!("Expected {}, found {}", expected, actual))),
), ),
ProximateShellError::TypeError { ProximateShellError::TypeError {
expected, expected,
@ -511,13 +518,13 @@ impl ShellError {
item: None, item: None,
span span
}, },
} => Diagnostic::new(Severity::Error, "Type Error") } => Some(Diagnostic::new(Severity::Error, "Type Error")
.with_label(Label::new_primary(span).with_message(expected)), .with_label(Label::new_primary(span).with_message(expected))),
ProximateShellError::UnexpectedEof { ProximateShellError::UnexpectedEof {
expected, span expected, span
} => Diagnostic::new(Severity::Error, "Unexpected end of input".to_string()) } => Some(Diagnostic::new(Severity::Error, "Unexpected end of input".to_string())
.with_label(Label::new_primary(span).with_message(format!("Expected {}", expected))), .with_label(Label::new_primary(span).with_message(format!("Expected {}", expected)))),
ProximateShellError::RangeError { ProximateShellError::RangeError {
kind, kind,
@ -527,13 +534,13 @@ impl ShellError {
item, item,
span span
}, },
} => Diagnostic::new(Severity::Error, "Range Error").with_label( } => Some(Diagnostic::new(Severity::Error, "Range Error").with_label(
Label::new_primary(span).with_message(format!( Label::new_primary(span).with_message(format!(
"Expected to convert {} to {} while {}, but it was out of range", "Expected to convert {} to {} while {}, but it was out of range",
item, item,
kind.display(), kind.display(),
operation operation
)), ))),
), ),
ProximateShellError::SyntaxError { ProximateShellError::SyntaxError {
@ -542,8 +549,8 @@ impl ShellError {
span, span,
item item
}, },
} => Diagnostic::new(Severity::Error, "Syntax Error") } => Some(Diagnostic::new(Severity::Error, "Syntax Error")
.with_label(Label::new_primary(span).with_message(item)), .with_label(Label::new_primary(span).with_message(item))),
ProximateShellError::MissingProperty { subpath, expr, .. } => { ProximateShellError::MissingProperty { subpath, expr, .. } => {
@ -562,7 +569,7 @@ impl ShellError {
} }
diag Some(diag)
} }
ProximateShellError::InvalidIntegerIndex { subpath,integer } => { ProximateShellError::InvalidIntegerIndex { subpath,integer } => {
@ -577,17 +584,18 @@ impl ShellError {
diag = diag.with_label(Label::new_secondary(integer).with_message("integer")); diag = diag.with_label(Label::new_secondary(integer).with_message("integer"));
diag Some(diag)
} }
ProximateShellError::Diagnostic(diag) => diag.diagnostic, ProximateShellError::Diagnostic(diag) => Some(diag.diagnostic),
ProximateShellError::CoerceError { left, right } => { ProximateShellError::CoerceError { left, right } => {
Diagnostic::new(Severity::Error, "Coercion error") Some(Diagnostic::new(Severity::Error, "Coercion error")
.with_label(Label::new_primary(left.span).with_message(left.item)) .with_label(Label::new_primary(left.span).with_message(left.item))
.with_label(Label::new_secondary(right.span).with_message(right.item)) .with_label(Label::new_secondary(right.span).with_message(right.item)))
} }
ProximateShellError::UntaggedRuntimeError { reason } => Diagnostic::new(Severity::Error, format!("Error: {}", reason)) ProximateShellError::UntaggedRuntimeError { reason } => Some(Diagnostic::new(Severity::Error, format!("Error: {}", reason))),
ProximateShellError::ExternalPlaceholderError => None,
} }
} }
@ -733,6 +741,7 @@ pub enum ProximateShellError {
UntaggedRuntimeError { UntaggedRuntimeError {
reason: String, reason: String,
}, },
ExternalPlaceholderError,
} }
impl ProximateShellError { impl ProximateShellError {
@ -764,6 +773,7 @@ impl HasFallibleSpan for ProximateShellError {
ProximateShellError::Diagnostic(_) => return None, ProximateShellError::Diagnostic(_) => return None,
ProximateShellError::CoerceError { left, right } => left.span.until(right.span), ProximateShellError::CoerceError { left, right } => left.span.until(right.span),
ProximateShellError::UntaggedRuntimeError { .. } => return None, ProximateShellError::UntaggedRuntimeError { .. } => return None,
ProximateShellError::ExternalPlaceholderError => return None,
}) })
} }
} }