mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 00:44:57 +02:00
Fix try
printing when it is not the last pipeline element (#13992)
# Description Fixes #13991. This was done by more clearly separating the case when a pipeline is drained vs when it is being written (to a file). I also added an `OutDest::Print` case which might not be strictly necessary, but is a helpful addition. # User-Facing Changes Bug fix. # Tests + Formatting Added a test. # After Submitting There are still a few redirection bugs that I found, but they require larger code changes, so I'll leave them until after the release.
This commit is contained in:
@ -205,7 +205,7 @@ impl BlockBuilder {
|
||||
Instruction::Span { src_dst } => allocate(&[*src_dst], &[*src_dst]),
|
||||
Instruction::Drop { src } => allocate(&[*src], &[]),
|
||||
Instruction::Drain { src } => allocate(&[*src], &[]),
|
||||
Instruction::WriteToOutDests { src } => allocate(&[*src], &[]),
|
||||
Instruction::DrainIfEnd { src } => allocate(&[*src], &[]),
|
||||
Instruction::LoadVariable { dst, var_id: _ } => allocate(&[], &[*dst]),
|
||||
Instruction::StoreVariable { var_id: _, src } => allocate(&[*src], &[]),
|
||||
Instruction::DropVariable { var_id: _ } => Ok(()),
|
||||
|
@ -473,7 +473,7 @@ pub(crate) fn compile_try(
|
||||
if let Some(mode) = redirect_modes.err {
|
||||
builder.push(mode.map(|mode| Instruction::RedirectErr { mode }))?;
|
||||
}
|
||||
builder.push(Instruction::WriteToOutDests { src: io_reg }.into_spanned(call.head))?;
|
||||
builder.push(Instruction::DrainIfEnd { src: io_reg }.into_spanned(call.head))?;
|
||||
builder.push(Instruction::PopErrorHandler.into_spanned(call.head))?;
|
||||
|
||||
// Jump over the failure case
|
||||
|
@ -151,7 +151,8 @@ pub(crate) fn out_dest_to_redirect_mode(
|
||||
OutDest::PipeSeparate => Ok(RedirectMode::PipeSeparate),
|
||||
OutDest::Value => Ok(RedirectMode::Value),
|
||||
OutDest::Null => Ok(RedirectMode::Null),
|
||||
OutDest::Inherit => Ok(RedirectMode::Inherit),
|
||||
OutDest::Print => Ok(RedirectMode::Print),
|
||||
OutDest::Inherit => Err(CompileError::InvalidRedirectMode { span }),
|
||||
OutDest::File(_) => Err(CompileError::InvalidRedirectMode { span }),
|
||||
})
|
||||
.transpose()
|
||||
|
@ -395,13 +395,13 @@ fn eval_element_with_input_inner<D: DebugContext>(
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
let data = eval_expression_with_input::<D>(engine_state, stack, &element.expr, input)?;
|
||||
|
||||
if let Some(redirection) = element.redirection.as_ref() {
|
||||
let is_external = if let PipelineData::ByteStream(stream, ..) = &data {
|
||||
matches!(stream.source(), ByteStreamSource::Child(..))
|
||||
} else {
|
||||
false
|
||||
};
|
||||
let is_external = if let PipelineData::ByteStream(stream, ..) = &data {
|
||||
matches!(stream.source(), ByteStreamSource::Child(..))
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
if let Some(redirection) = element.redirection.as_ref() {
|
||||
if !is_external {
|
||||
match redirection {
|
||||
&PipelineRedirection::Single {
|
||||
@ -437,30 +437,24 @@ fn eval_element_with_input_inner<D: DebugContext>(
|
||||
}
|
||||
}
|
||||
|
||||
let has_stdout_file = matches!(stack.pipe_stdout(), Some(OutDest::File(_)));
|
||||
|
||||
let data = match &data {
|
||||
PipelineData::Value(..) | PipelineData::ListStream(..) => {
|
||||
if has_stdout_file {
|
||||
data.write_to_out_dests(engine_state, stack)?;
|
||||
let data = if let Some(OutDest::File(file)) = stack.pipe_stdout() {
|
||||
match &data {
|
||||
PipelineData::Value(..) | PipelineData::ListStream(..) => {
|
||||
data.write_to(file.as_ref())?;
|
||||
PipelineData::Empty
|
||||
} else {
|
||||
data
|
||||
}
|
||||
}
|
||||
PipelineData::ByteStream(stream, ..) => {
|
||||
let write = match stream.source() {
|
||||
ByteStreamSource::Read(_) | ByteStreamSource::File(_) => has_stdout_file,
|
||||
ByteStreamSource::Child(_) => false,
|
||||
};
|
||||
if write {
|
||||
data.write_to_out_dests(engine_state, stack)?;
|
||||
PipelineData::Empty
|
||||
} else {
|
||||
data
|
||||
PipelineData::ByteStream(..) => {
|
||||
if !is_external {
|
||||
data.write_to(file.as_ref())?;
|
||||
PipelineData::Empty
|
||||
} else {
|
||||
data
|
||||
}
|
||||
}
|
||||
PipelineData::Empty => PipelineData::Empty,
|
||||
}
|
||||
PipelineData::Empty => PipelineData::Empty,
|
||||
} else {
|
||||
data
|
||||
};
|
||||
|
||||
Ok(data)
|
||||
|
@ -322,13 +322,13 @@ fn eval_instruction<D: DebugContext>(
|
||||
let data = ctx.take_reg(*src);
|
||||
drain(ctx, data)
|
||||
}
|
||||
Instruction::WriteToOutDests { src } => {
|
||||
Instruction::DrainIfEnd { src } => {
|
||||
let data = ctx.take_reg(*src);
|
||||
let res = {
|
||||
let stack = &mut ctx
|
||||
.stack
|
||||
.push_redirection(ctx.redirect_out.clone(), ctx.redirect_err.clone());
|
||||
data.write_to_out_dests(ctx.engine_state, stack)?
|
||||
data.drain_to_out_dests(ctx.engine_state, stack)?
|
||||
};
|
||||
ctx.put_reg(*src, res);
|
||||
Ok(Continue)
|
||||
@ -507,14 +507,19 @@ fn eval_instruction<D: DebugContext>(
|
||||
msg: format!("Tried to write to file #{file_num}, but it is not open"),
|
||||
span: Some(*span),
|
||||
})?;
|
||||
let result = {
|
||||
let mut stack = ctx
|
||||
.stack
|
||||
.push_redirection(Some(Redirection::File(file)), None);
|
||||
src.write_to_out_dests(ctx.engine_state, &mut stack)?
|
||||
let is_external = if let PipelineData::ByteStream(stream, ..) = &src {
|
||||
matches!(stream.source(), ByteStreamSource::Child(..))
|
||||
} else {
|
||||
false
|
||||
};
|
||||
// Abort execution if there's an exit code from a failed external
|
||||
drain(ctx, result)
|
||||
if let Err(err) = src.write_to(file.as_ref()) {
|
||||
if is_external {
|
||||
ctx.stack.set_last_error(&err);
|
||||
}
|
||||
Err(err)?
|
||||
} else {
|
||||
Ok(Continue)
|
||||
}
|
||||
}
|
||||
Instruction::CloseFile { file_num } => {
|
||||
if ctx.files[*file_num as usize].take().is_some() {
|
||||
@ -1421,6 +1426,7 @@ fn eval_redirection(
|
||||
RedirectMode::Value => Ok(Some(Redirection::Pipe(OutDest::Value))),
|
||||
RedirectMode::Null => Ok(Some(Redirection::Pipe(OutDest::Null))),
|
||||
RedirectMode::Inherit => Ok(Some(Redirection::Pipe(OutDest::Inherit))),
|
||||
RedirectMode::Print => Ok(Some(Redirection::Pipe(OutDest::Print))),
|
||||
RedirectMode::File { file_num } => {
|
||||
let file = ctx
|
||||
.files
|
||||
|
Reference in New Issue
Block a user