Preserve attributes on external ByteStreams (#13305)

# Description

Bug fix: `PipelineData::check_external_failed()` was not preserving the
original `type_` and `known_size` attributes of the stream passed in for
streams that come from children, so `external-command | into binary` did
not work properly and always ended up still being unknown type.

# User-Facing Changes
The following test case now works as expected:

```nushell
> head -c 2 /dev/urandom | into binary
# Expected: pretty hex dump of binary
# Previous behavior: just raw binary in the terminal
```

# Tests + Formatting
Added a test to cover this to `into binary`
This commit is contained in:
Devyn Cairns 2024-07-05 14:10:41 -07:00 committed by GitHub
parent 34da26d039
commit 948b90299d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 21 additions and 2 deletions

View File

@ -0,0 +1,13 @@
use nu_test_support::nu;
#[test]
fn sets_stream_from_internal_command_as_binary() {
let result = nu!("seq 1 10 | to text | into binary | describe");
assert_eq!("binary (stream)", result.out);
}
#[test]
fn sets_stream_from_external_command_as_binary() {
let result = nu!("^nu --testbin cococo | into binary | describe");
assert_eq!("binary (stream)", result.out);
}

View File

@ -1 +1,2 @@
mod binary;
mod int;

View File

@ -453,7 +453,10 @@ impl PipelineData {
/// Currently this will consume an external command to completion.
pub fn check_external_failed(self) -> Result<(Self, bool), ShellError> {
if let PipelineData::ByteStream(stream, metadata) = self {
// Preserve stream attributes
let span = stream.span();
let type_ = stream.type_();
let known_size = stream.known_size();
match stream.into_child() {
Ok(mut child) => {
// Only check children without stdout. This means that nothing
@ -485,10 +488,12 @@ impl PipelineData {
child.stderr = Some(ChildPipe::Tee(Box::new(Cursor::new(stderr))));
}
child.set_exit_code(code);
let stream = ByteStream::child(child, span);
let stream = ByteStream::child(child, span).with_type(type_);
Ok((PipelineData::ByteStream(stream, metadata), code != 0))
} else {
let stream = ByteStream::child(child, span);
let stream = ByteStream::child(child, span)
.with_type(type_)
.with_known_size(known_size);
Ok((PipelineData::ByteStream(stream, metadata), false))
}
}