diff --git a/crates/nu-command/src/filesystem/save.rs b/crates/nu-command/src/filesystem/save.rs index 05fe8ce12..1f64c7975 100644 --- a/crates/nu-command/src/filesystem/save.rs +++ b/crates/nu-command/src/filesystem/save.rs @@ -1,4 +1,6 @@ +use nu_engine::current_dir; use nu_engine::CallExt; +use nu_path::expand_path_with; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EngineState, Stack}; use nu_protocol::{ @@ -7,7 +9,7 @@ use nu_protocol::{ }; use std::fs::File; use std::io::Write; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::thread; use crate::progress_bar; @@ -67,9 +69,20 @@ impl Command for Save { let progress = call.has_flag("progress"); let span = call.head; + let cwd = current_dir(engine_state, stack)?; - let path = call.req::>(engine_state, stack, 0)?; - let stderr_path = call.get_flag::>(engine_state, stack, "stderr")?; + let path_arg = call.req::>(engine_state, stack, 0)?; + let path = Spanned { + item: expand_path_with(path_arg.item, &cwd), + span: path_arg.span, + }; + + let stderr_path = call + .get_flag::>(engine_state, stack, "stderr")? + .map(|arg| Spanned { + item: expand_path_with(arg.item, cwd), + span: arg.span, + }); match input { PipelineData::ExternalStream { stdout: None, .. } => { @@ -258,12 +271,12 @@ fn value_to_bytes(value: Value) -> Result, ShellError> { /// Convert string path to [`Path`] and [`Span`] and check if this path /// can be used with given flags fn prepare_path( - path: &Spanned, + path: &Spanned, append: bool, force: bool, ) -> Result<(&Path, Span), ShellError> { let span = path.span; - let path = Path::new(&path.item); + let path = &path.item; if !(force || append) && path.exists() { Err(ShellError::GenericError( @@ -303,8 +316,8 @@ fn open_file(path: &Path, span: Span, append: bool) -> Result /// Get output file and optional stderr file fn get_files( - path: &Spanned, - stderr_path: &Option>, + path: &Spanned, + stderr_path: &Option>, append: bool, force: bool, ) -> Result<(File, Option), ShellError> { diff --git a/crates/nu-command/tests/commands/save.rs b/crates/nu-command/tests/commands/save.rs index a540f6753..24a5e95aa 100644 --- a/crates/nu-command/tests/commands/save.rs +++ b/crates/nu-command/tests/commands/save.rs @@ -297,3 +297,31 @@ fn writes_out_range() { assert_eq!(actual, "[\n 1,\n 2,\n 3\n]") }) } + +// https://github.com/nushell/nushell/issues/10044 +#[test] +fn save_file_correct_relative_path() { + Playground::setup("save_test_15", |dirs, sandbox| { + sandbox.with_files(vec![Stub::FileWithContent( + "test.nu", + r#" + export def main [] { + let foo = "foo" + mkdir bar + cd bar + 'foo!' | save $foo + } + "#, + )]); + + let expected_file = dirs.test().join("bar/foo"); + + nu!( + cwd: dirs.test(), + r#"use test.nu; test"# + ); + + let actual = file_contents(expected_file); + assert_eq!(actual, "foo!"); + }) +}