From a1fc41db22e326309926b606e1a4c747afb673da Mon Sep 17 00:00:00 2001 From: YizhePKU Date: Mon, 27 May 2024 01:23:52 +0800 Subject: [PATCH] Fix `path type` using PWD from the environment (#12975) This PR fixes the `path type` command so that it resolves relative paths using PWD from the engine state. As a bonus, it also fixes the issue of `path type` returning an empty string instead of an error when it fails. --- crates/nu-command/src/path/type.rs | 42 +++++++++---------- .../nu-command/tests/commands/path/type_.rs | 11 +++++ 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/crates/nu-command/src/path/type.rs b/crates/nu-command/src/path/type.rs index 8fbc270445..e048679220 100644 --- a/crates/nu-command/src/path/type.rs +++ b/crates/nu-command/src/path/type.rs @@ -1,10 +1,11 @@ use super::PathSubcommandArguments; use nu_engine::command_prelude::*; -use nu_path::expand_tilde; use nu_protocol::engine::StateWorkingSet; -use std::path::Path; +use std::path::{Path, PathBuf}; -struct Arguments; +struct Arguments { + pwd: PathBuf, +} impl PathSubcommandArguments for Arguments {} @@ -45,19 +46,21 @@ If nothing is found, an empty string will be returned."# fn run( &self, engine_state: &EngineState, - _stack: &mut Stack, + stack: &mut Stack, call: &Call, input: PipelineData, ) -> Result { let head = call.head; - let args = Arguments; + let args = Arguments { + pwd: engine_state.cwd(Some(stack))?, + }; // This doesn't match explicit nulls if matches!(input, PipelineData::Empty) { return Err(ShellError::PipelineEmpty { dst_span: head }); } input.map( - move |value| super::operate(&r#type, &args, value, head), + move |value| super::operate(&path_type, &args, value, head), engine_state.ctrlc.clone(), ) } @@ -69,14 +72,16 @@ If nothing is found, an empty string will be returned."# input: PipelineData, ) -> Result { let head = call.head; - let args = Arguments; + let args = Arguments { + pwd: working_set.permanent().cwd(None)?, + }; // This doesn't match explicit nulls if matches!(input, PipelineData::Empty) { return Err(ShellError::PipelineEmpty { dst_span: head }); } input.map( - move |value| super::operate(&r#type, &args, value, head), + move |value| super::operate(&path_type, &args, value, head), working_set.permanent().ctrlc.clone(), ) } @@ -97,21 +102,12 @@ If nothing is found, an empty string will be returned."# } } -fn r#type(path: &Path, span: Span, _: &Arguments) -> Value { - let meta = if path.starts_with("~") { - let p = expand_tilde(path); - std::fs::symlink_metadata(p) - } else { - std::fs::symlink_metadata(path) - }; - - Value::string( - match &meta { - Ok(data) => get_file_type(data), - Err(_) => "", - }, - span, - ) +fn path_type(path: &Path, span: Span, args: &Arguments) -> Value { + let path = nu_path::expand_path_with(path, &args.pwd, true); + match std::fs::symlink_metadata(path) { + Ok(metadata) => Value::string(get_file_type(&metadata), span), + Err(err) => Value::error(err.into(), span), + } } fn get_file_type(md: &std::fs::Metadata) -> &str { diff --git a/crates/nu-command/tests/commands/path/type_.rs b/crates/nu-command/tests/commands/path/type_.rs index 2317cea060..e67b957e4c 100644 --- a/crates/nu-command/tests/commands/path/type_.rs +++ b/crates/nu-command/tests/commands/path/type_.rs @@ -74,3 +74,14 @@ fn returns_type_of_existing_file_const() { assert_eq!(actual.out, "dir"); }) } + +#[test] +fn respects_cwd() { + Playground::setup("path_type_respects_cwd", |dirs, sandbox| { + sandbox.within("foo").with_files(&[EmptyFile("bar.txt")]); + + let actual = nu!(cwd: dirs.test(), "cd foo; 'bar.txt' | path type"); + + assert_eq!(actual.out, "file"); + }) +}