Fix custom converters with save (#12833)

# Description
Fixes #10429 where `save` fails if a custom command is used as the file
format converter.

# Tests + Formatting
Added a test.
This commit is contained in:
Ian Manske 2024-05-12 11:19:28 +00:00 committed by GitHub
parent 075535f869
commit 30fc832035
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 36 additions and 22 deletions

View File

@ -1,4 +1,5 @@
use crate::progress_bar; use crate::progress_bar;
use nu_engine::get_eval_block;
#[allow(deprecated)] #[allow(deprecated)]
use nu_engine::{command_prelude::*, current_dir}; use nu_engine::{command_prelude::*, current_dir};
use nu_path::expand_path_with; use nu_path::expand_path_with;
@ -311,12 +312,13 @@ fn input_to_bytes(
.map(|name| name.to_string_lossy().to_string()) .map(|name| name.to_string_lossy().to_string())
}; };
if let Some(ext) = ext { let input = if let Some(ext) = ext {
convert_to_extension(engine_state, &ext, stack, input, span) convert_to_extension(engine_state, &ext, stack, input, span)?
} else { } else {
let value = input.into_value(span); input
value_to_bytes(value) };
}
value_to_bytes(input.into_value(span))
} }
/// Convert given data into content of file of specified extension if /// Convert given data into content of file of specified extension if
@ -328,24 +330,19 @@ fn convert_to_extension(
stack: &mut Stack, stack: &mut Stack,
input: PipelineData, input: PipelineData,
span: Span, span: Span,
) -> Result<Vec<u8>, ShellError> { ) -> Result<PipelineData, ShellError> {
let converter = engine_state.find_decl(format!("to {extension}").as_bytes(), &[]); if let Some(decl_id) = engine_state.find_decl(format!("to {extension}").as_bytes(), &[]) {
let decl = engine_state.get_decl(decl_id);
let output = match converter { if let Some(block_id) = decl.get_block_id() {
Some(converter_id) => { let block = engine_state.get_block(block_id);
let output = engine_state.get_decl(converter_id).run( let eval_block = get_eval_block(engine_state);
engine_state, eval_block(engine_state, stack, block, input)
stack, } else {
&Call::new(span), decl.run(engine_state, stack, &Call::new(span), input)
input,
)?;
output.into_value(span)
} }
None => input.into_value(span), } else {
}; Ok(input)
}
value_to_bytes(output)
} }
/// Convert [`Value::String`] [`Value::Binary`] or [`Value::List`] into [`Vec`] of bytes /// Convert [`Value::String`] [`Value::Binary`] or [`Value::List`] into [`Vec`] of bytes

View File

@ -407,3 +407,20 @@ fn save_same_file_without_extension_pipeline() {
.contains("pipeline input and output are the same file")); .contains("pipeline input and output are the same file"));
}) })
} }
#[test]
fn save_with_custom_converter() {
Playground::setup("save_with_custom_converter", |dirs, _| {
let file = dirs.test().join("test.ndjson");
nu!(cwd: dirs.test(), pipeline(
r#"
def "to ndjson" []: any -> string { each { to json --raw } | to text } ;
{a: 1, b: 2} | save test.ndjson
"#
));
let actual = file_contents(file);
assert_eq!(actual, r#"{"a":1,"b":2}"#);
})
}