From 948b90299db6db1ef5ea8dcb503af8ee046db211 Mon Sep 17 00:00:00 2001 From: Devyn Cairns Date: Fri, 5 Jul 2024 14:10:41 -0700 Subject: [PATCH] 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` --- .../tests/commands/conversions/into/binary.rs | 13 +++++++++++++ .../tests/commands/conversions/into/mod.rs | 1 + crates/nu-protocol/src/pipeline/pipeline_data.rs | 9 +++++++-- 3 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 crates/nu-command/tests/commands/conversions/into/binary.rs diff --git a/crates/nu-command/tests/commands/conversions/into/binary.rs b/crates/nu-command/tests/commands/conversions/into/binary.rs new file mode 100644 index 0000000000..c8fd24df77 --- /dev/null +++ b/crates/nu-command/tests/commands/conversions/into/binary.rs @@ -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); +} diff --git a/crates/nu-command/tests/commands/conversions/into/mod.rs b/crates/nu-command/tests/commands/conversions/into/mod.rs index a7a829445a..ad10199b5c 100644 --- a/crates/nu-command/tests/commands/conversions/into/mod.rs +++ b/crates/nu-command/tests/commands/conversions/into/mod.rs @@ -1 +1,2 @@ +mod binary; mod int; diff --git a/crates/nu-protocol/src/pipeline/pipeline_data.rs b/crates/nu-protocol/src/pipeline/pipeline_data.rs index 03fbc64d21..c0c0bd1c33 100644 --- a/crates/nu-protocol/src/pipeline/pipeline_data.rs +++ b/crates/nu-protocol/src/pipeline/pipeline_data.rs @@ -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)) } }