From 5e961815fcd2130a964796e350f3e97dba216603 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20N=2E=20Robalino?= Date: Mon, 16 Dec 2019 16:51:19 -0500 Subject: [PATCH] can contain a string line or plain string data. --- crates/test-support/src/macros.rs | 54 ------------------- src/commands/classified/external.rs | 25 ++++++--- tests/shell/mod.rs | 84 ++++++++++++++++++++++++----- 3 files changed, 88 insertions(+), 75 deletions(-) diff --git a/crates/test-support/src/macros.rs b/crates/test-support/src/macros.rs index d97ebbc897..6b883c94be 100644 --- a/crates/test-support/src/macros.rs +++ b/crates/test-support/src/macros.rs @@ -103,57 +103,3 @@ macro_rules! nu_error { out.into_owned() }}; } - -#[macro_export] -macro_rules! nu_combined { - (cwd: $cwd:expr, $path:expr, $($part:expr),*) => {{ - use $crate::fs::DisplayPath; - - let path = format!($path, $( - $part.display_path() - ),*); - - nu_combined!($cwd, &path) - }}; - - (cwd: $cwd:expr, $path:expr) => {{ - nu_combined!($cwd, $path) - }}; - - ($cwd:expr, $path:expr) => {{ - pub use std::error::Error; - pub use std::io::prelude::*; - pub use std::process::{Command, Stdio}; - - let commands = &*format!( - " - cd {} - {} - exit", - $crate::fs::in_directory($cwd), - $crate::fs::DisplayPath::display_path(&$path) - ); - - let mut process = Command::new($crate::fs::executable_path()) - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) - .spawn() - .expect("couldn't run test"); - - let stdin = process.stdin.as_mut().expect("couldn't open stdin"); - stdin - .write_all(commands.as_bytes()) - .expect("couldn't write to stdin"); - - let output = process - .wait_with_output() - .expect("couldn't read from stdout/stderr"); - - let err = String::from_utf8_lossy(&output.stderr).into_owned(); - let out = String::from_utf8_lossy(&output.stdout).into_owned(); - let out = out.replace("\r\n", ""); - let out = out.replace("\n", ""); - (out, err) - }}; -} diff --git a/src/commands/classified/external.rs b/src/commands/classified/external.rs index aa009dbf20..190ff2ad5f 100644 --- a/src/commands/classified/external.rs +++ b/src/commands/classified/external.rs @@ -5,7 +5,7 @@ use futures_codec::{Decoder, Encoder, Framed}; use log::trace; use nu_errors::ShellError; use nu_parser::ExternalCommand; -use nu_protocol::{UntaggedValue, Value}; +use nu_protocol::{Primitive, UntaggedValue, Value}; use std::io::{Error, ErrorKind}; use std::ops::Deref; use subprocess::Exec; @@ -82,23 +82,32 @@ pub(crate) async fn run_external_command( if arg_string.contains("$it") { let input_strings = inputs .iter() - .map(|i| { - i.as_string().map(|s| s.to_string()).map_err(|_| { + .map(|i| match i { + Value { + value: UntaggedValue::Primitive(Primitive::String(s)), + .. + } + | Value { + value: UntaggedValue::Primitive(Primitive::Line(s)), + .. + } => Ok(s.clone()), + _ => { let arg = command.args.iter().find(|arg| arg.contains("$it")); + if let Some(arg) = arg { - ShellError::labeled_error( + Err(ShellError::labeled_error( "External $it needs string data", "given row instead of string data", &arg.tag, - ) + )) } else { - ShellError::labeled_error( + Err(ShellError::labeled_error( "$it needs string data", "given something else", command.name_tag.clone(), - ) + )) } - }) + } }) .collect::, ShellError>>()?; diff --git a/tests/shell/mod.rs b/tests/shell/mod.rs index 5cbb3fd272..1c4dd89fc7 100644 --- a/tests/shell/mod.rs +++ b/tests/shell/mod.rs @@ -1,32 +1,90 @@ mod pipeline { - use test_support::fs::Stub::FileWithContent; + use test_support::fs::Stub::EmptyFile; use test_support::playground::Playground; - use test_support::{nu_combined, pipeline}; + use test_support::{nu, pipeline}; #[test] - fn it_arg_works_with_many_inputs_to_external_command() { - Playground::setup("it_arg_works_with_many_inputs", |dirs, sandbox| { + fn can_process_row_as_it_argument_to_an_external_command_given_the_it_data_is_a_string() { + Playground::setup("it_argument_test_1", |dirs, sandbox| { sandbox.with_files(vec![ - FileWithContent("file1", "text"), - FileWithContent("file2", " and more text"), + EmptyFile("jonathan_likes_cake.txt"), + EmptyFile("andres_likes_arepas.txt"), ]); - let (stdout, stderr) = nu_combined!( + let actual = nu!( cwd: dirs.test(), pipeline( r#" - echo hello world - | split-row " " + ls + | sort-by name + | get name | ^echo $it "# )); #[cfg(windows)] - assert_eq!("hello world", stdout); + assert_eq!(actual, "andres_likes_arepas.txt jonathan_likes_cake.txt"); #[cfg(not(windows))] - assert_eq!("helloworld", stdout); - - assert!(!stderr.contains("No such file or directory")); + assert_eq!(actual, "andres_likes_arepas.txtjonathan_likes_cake.txt"); }) } + + #[test] + fn can_process_row_as_it_argument_to_an_external_command_given_the_it_data_is_one_string_line() + { + Playground::setup("it_argument_test_2", |dirs, sandbox| { + sandbox.with_files(vec![ + EmptyFile("jonathan_likes_cake.txt"), + EmptyFile("andres_likes_arepas.txt"), + ]); + + let actual = nu!( + cwd: dirs.test(), pipeline( + r#" + ls + | sort-by name + | get name + | lines + | ^echo $it + "# + )); + + #[cfg(windows)] + assert_eq!(actual, "andres_likes_arepas.txt jonathan_likes_cake.txt"); + + #[cfg(not(windows))] + assert_eq!(actual, "andres_likes_arepas.txtjonathan_likes_cake.txt"); + }) + } + + mod expands_tilde { + use super::nu; + + #[test] + fn as_home_directory_when_passed_as_argument_and_begins_with_tilde_to_an_external() { + let actual = nu!( + cwd: std::path::PathBuf::from("."), + r#" + sh -c "echo ~" + "# + ); + + assert!( + !actual.contains("~"), + format!("'{}' should not contain ~", actual) + ); + } + + #[test] + fn does_not_expand_when_passed_as_argument_and_does_not_start_with_tilde_to_an_external() { + let actual = nu!( + cwd: std::path::PathBuf::from("."), + r#" + sh -c "echo 1~1" + "# + ); + + assert_eq!(actual, "1~1"); + } + } }