run-external spreads command if it's a list (#15776)

This commit is contained in:
Firegem 2025-05-18 04:09:32 -04:00 committed by GitHub
parent 5483519c7d
commit 1e8876b076
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 43 additions and 3 deletions

View File

@ -53,9 +53,9 @@ impl Command for External {
) -> Result<PipelineData, ShellError> { ) -> Result<PipelineData, ShellError> {
let cwd = engine_state.cwd(Some(stack))?; let cwd = engine_state.cwd(Some(stack))?;
let rest = call.rest::<Value>(engine_state, stack, 0)?; let rest = call.rest::<Value>(engine_state, stack, 0)?;
let name_args = rest.split_first(); let name_args = rest.split_first().map(|(x, y)| (x, y.to_vec()));
let Some((name, call_args)) = name_args else { let Some((name, mut call_args)) = name_args else {
return Err(ShellError::MissingParameter { return Err(ShellError::MissingParameter {
param_name: "no command given".into(), param_name: "no command given".into(),
span: call.head, span: call.head,
@ -65,6 +65,17 @@ impl Command for External {
let name_str: Cow<str> = match &name { let name_str: Cow<str> = match &name {
Value::Glob { val, .. } => Cow::Borrowed(val), Value::Glob { val, .. } => Cow::Borrowed(val),
Value::String { val, .. } => Cow::Borrowed(val), Value::String { val, .. } => Cow::Borrowed(val),
Value::List { vals, .. } => {
let Some((first, args)) = vals.split_first() else {
return Err(ShellError::MissingParameter {
param_name: "external command given as list empty".into(),
span: call.head,
});
};
// Prepend elements in command list to the list of arguments except the first
call_args.splice(0..0, args.to_vec());
first.coerce_str()?
}
_ => Cow::Owned(name.clone().coerce_into_string()?), _ => Cow::Owned(name.clone().coerce_into_string()?),
}; };
@ -164,7 +175,7 @@ impl Command for External {
command.envs(envs); command.envs(envs);
// Configure args. // Configure args.
let args = eval_external_arguments(engine_state, stack, call_args.to_vec())?; let args = eval_external_arguments(engine_state, stack, call_args)?;
#[cfg(windows)] #[cfg(windows)]
if is_cmd_internal_command(&name_str) || pathext_script_in_windows { if is_cmd_internal_command(&name_str) || pathext_script_in_windows {
// The /D flag disables execution of AutoRun commands from registry. // The /D flag disables execution of AutoRun commands from registry.

View File

@ -535,3 +535,32 @@ fn can_run_ps1_files(prefix: &str) {
assert!(actual.out.contains("Hello World")); assert!(actual.out.contains("Hello World"));
}); });
} }
#[rstest]
#[case("^")]
#[case("run-external ")]
fn expand_command_if_list(#[case] prefix: &str) {
use nu_test_support::fs::Stub::FileWithContent;
Playground::setup("expand command if list", |dirs, sandbox| {
sandbox.with_files(&[FileWithContent("foo.txt", "Hello World")]);
let actual = nu!(
cwd: dirs.test(),
r#"
let cmd = [nu `--testbin`]; {}$cmd meow foo.txt
"#,
prefix
);
assert!(actual.out.contains("Hello World"));
})
}
#[rstest]
#[case("^")]
#[case("run-external ")]
fn error_when_command_list_empty(#[case] prefix: &str) {
Playground::setup("error when command is list with no items", |dirs, _| {
let actual = nu!(cwd: dirs.test(), "let cmd = []; {}$cmd", prefix);
assert!(actual.err.contains("missing parameter"));
})
}