forked from extern/nushell
Support binary data to stdin of run-external (#4984)
* Add test for passing binary data through externals This change adds an ignored test to confirm that binary data is passed correctly between externals to be enabled in a later commit along with the fix. To assist in platform agnostic testing of binary data a couple of additional testbins were added to allow testing on `Value::Binary` inside `ExternalStream`. * Support binary data to stdin of run-external Prior to this change, any pipeline producing binary data (not detected as string) then feed into an external would be ignored due to run-external only supporting `Value::String` on stdin. This change adds binary stdin support for externals allowing something like this for example: 〉^cat /dev/urandom | ^head -c 1MiB | ^pv -b | ignore 1.00MiB This would previously output `0.00 B [0.00 B/s]` due to the data not being pushed to stdin at each stage.
This commit is contained in:
parent
91e17d2f9f
commit
a64e0956cd
@ -169,12 +169,13 @@ impl ExternalCommand {
|
|||||||
|
|
||||||
if let Ok(input) = input {
|
if let Ok(input) = input {
|
||||||
for value in input.into_iter() {
|
for value in input.into_iter() {
|
||||||
if let Value::String { val, span: _ } = value {
|
let buf = match value {
|
||||||
if stdin_write.write(val.as_bytes()).is_err() {
|
Value::String { val, .. } => val.into_bytes(),
|
||||||
return Ok(());
|
Value::Binary { val, .. } => val,
|
||||||
}
|
_ => return Err(()),
|
||||||
} else {
|
};
|
||||||
return Err(());
|
if stdin_write.write(&buf).is_err() {
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -159,6 +159,8 @@ fn main() -> Result<()> {
|
|||||||
"echo_env" => test_bins::echo_env(),
|
"echo_env" => test_bins::echo_env(),
|
||||||
"cococo" => test_bins::cococo(),
|
"cococo" => test_bins::cococo(),
|
||||||
"meow" => test_bins::meow(),
|
"meow" => test_bins::meow(),
|
||||||
|
"meowb" => test_bins::meowb(),
|
||||||
|
"relay" => test_bins::relay(),
|
||||||
"iecho" => test_bins::iecho(),
|
"iecho" => test_bins::iecho(),
|
||||||
"fail" => test_bins::fail(),
|
"fail" => test_bins::fail(),
|
||||||
"nonu" => test_bins::nonu(),
|
"nonu" => test_bins::nonu(),
|
||||||
|
@ -34,6 +34,25 @@ pub fn meow() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A binary version of meow
|
||||||
|
pub fn meowb() {
|
||||||
|
let args: Vec<String> = args();
|
||||||
|
|
||||||
|
let stdout = io::stdout();
|
||||||
|
let mut handle = stdout.lock();
|
||||||
|
|
||||||
|
for arg in args.iter().skip(1) {
|
||||||
|
let buf = std::fs::read(arg).expect("Expected a filepath");
|
||||||
|
handle.write_all(&buf).expect("failed to write to stdout");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Relays anything received on stdin to stdout
|
||||||
|
pub fn relay() {
|
||||||
|
io::copy(&mut io::stdin().lock(), &mut io::stdout().lock())
|
||||||
|
.expect("failed to copy stdin to stdout");
|
||||||
|
}
|
||||||
|
|
||||||
pub fn nonu() {
|
pub fn nonu() {
|
||||||
args().iter().skip(1).for_each(|arg| print!("{}", arg));
|
args().iter().skip(1).for_each(|arg| print!("{}", arg));
|
||||||
}
|
}
|
||||||
|
@ -97,6 +97,16 @@ fn redirects_custom_command_external() {
|
|||||||
assert_eq!(actual.out, "8");
|
assert_eq!(actual.out, "8");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn passes_binary_data_between_externals() {
|
||||||
|
let actual = nu!(cwd: "tests/fixtures/formats", r#"nu --testbin meowb sample.db | nu --testbin relay | hash sha256"#);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
actual.out,
|
||||||
|
"2f5050e7eea415c1f3d80b5d93355efd15043ec9157a2bb167a9e73f2ae651f2"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
mod it_evaluation {
|
mod it_evaluation {
|
||||||
use super::nu;
|
use super::nu;
|
||||||
use nu_test_support::fs::Stub::{EmptyFile, FileWithContent, FileWithContentToBeTrimmed};
|
use nu_test_support::fs::Stub::{EmptyFile, FileWithContent, FileWithContentToBeTrimmed};
|
||||||
|
Loading…
Reference in New Issue
Block a user