show the full directory / file path in "directory not found" error (#10430)

should close https://github.com/nushell/nushell/issues/10406

# Description
when writing a script, with variables you try to `ls` or `open`, you
will get a "directory not found" error but the variable won't be
expanded and you won't be able to see which one of the variable was the
issue...

this PR adds this information to the error.

# User-Facing Changes
let's define a variable
```nushell
let does_not_exist = "i_do_not_exist_in_the_current_directory"
```
### before
```nushell
> open $does_not_exist
Error: nu:🐚:directory_not_found

  × Directory not found
   ╭─[entry #7:1:1]
 1 │ open $does_not_exist
   ·      ───────┬───────
   ·             ╰── directory not found
   ╰────
```
```nushell
> ls $does_not_exist
Error: nu:🐚:directory_not_found

  × Directory not found
   ╭─[entry #8:1:1]
 1 │ ls $does_not_exist
   ·    ───────┬───────
   ·           ╰── directory not found
   ╰────
```

### after
```nushell
> open $does_not_exist
Error: nu:🐚:directory_not_found

  × Directory not found
   ╭─[entry #3:1:1]
 1 │ open $does_not_exist
   ·      ───────┬───────
   ·             ╰── directory not found
   ╰────
  help: /home/amtoine/documents/repos/github.com/amtoine/nushell/i_do_not_exist_in_the_current_directory does not exist
```
```nushell
> ls $does_not_exist
Error: nu:🐚:directory_not_found

  × Directory not found
   ╭─[entry #4:1:1]
 1 │ ls $does_not_exist
   ·    ───────┬───────
   ·           ╰── directory not found
   ╰────
  help: /home/amtoine/documents/repos/github.com/amtoine/nushell/i_do_not_exist_in_the_current_directory does not exist
```

# Tests + Formatting
shouldn't harm anything 🤞 

# After Submitting
This commit is contained in:
Antoine Stevan 2023-09-26 11:38:58 +02:00 committed by GitHub
parent 65074ec449
commit feef612388
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 37 additions and 20 deletions

View File

@ -512,7 +512,10 @@ pub fn evaluate_repl(
report_error( report_error(
&working_set, &working_set,
&ShellError::DirectoryNotFound(tokens.0[0].span, None), &ShellError::DirectoryNotFound(
tokens.0[0].span,
path.to_string_lossy().to_string(),
),
); );
} }
let path = nu_path::canonicalize_with(path, &cwd) let path = nu_path::canonicalize_with(path, &cwd)

View File

@ -85,21 +85,21 @@ impl Command for Cd {
let path = oldpwd.as_path()?; let path = oldpwd.as_path()?;
let path = match nu_path::canonicalize_with(path.clone(), &cwd) { let path = match nu_path::canonicalize_with(path.clone(), &cwd) {
Ok(p) => p, Ok(p) => p,
Err(e1) => { Err(_) => {
if use_abbrev { if use_abbrev {
match query(&path, None, v.span) { match query(&path, None, v.span) {
Ok(p) => p, Ok(p) => p,
Err(e) => { Err(_) => {
return Err(ShellError::DirectoryNotFound( return Err(ShellError::DirectoryNotFound(
v.span, v.span,
Some(format!("IO Error: {e:?}")), path.to_string_lossy().to_string(),
)) ))
} }
} }
} else { } else {
return Err(ShellError::DirectoryNotFound( return Err(ShellError::DirectoryNotFound(
v.span, v.span,
Some(format!("IO Error: {e1:?}")), path.to_string_lossy().to_string(),
)); ));
} }
} }
@ -119,10 +119,10 @@ impl Command for Cd {
// if it's not a dir, let's check to see if it's something abbreviated // if it's not a dir, let's check to see if it's something abbreviated
match query(&p, None, v.span) { match query(&p, None, v.span) {
Ok(path) => path, Ok(path) => path,
Err(e) => { Err(_) => {
return Err(ShellError::DirectoryNotFound( return Err(ShellError::DirectoryNotFound(
v.span, v.span,
Some(format!("IO Error: {e:?}")), p.to_string_lossy().to_string(),
)) ))
} }
}; };
@ -138,15 +138,18 @@ impl Command for Cd {
if use_abbrev { if use_abbrev {
match query(&path_no_whitespace, None, v.span) { match query(&path_no_whitespace, None, v.span) {
Ok(path) => path, Ok(path) => path,
Err(e) => { Err(_) => {
return Err(ShellError::DirectoryNotFound( return Err(ShellError::DirectoryNotFound(
v.span, v.span,
Some(format!("IO Error: {e:?}")), path_no_whitespace.to_string(),
)) ))
} }
} }
} else { } else {
return Err(ShellError::DirectoryNotFound(v.span, None)); return Err(ShellError::DirectoryNotFound(
v.span,
path_no_whitespace.to_string(),
));
} }
} }
}; };

View File

@ -103,7 +103,7 @@ impl Command for Cp {
if is_directory && !destination.exists() { if is_directory && !destination.exists() {
return Err(ShellError::DirectoryNotFound( return Err(ShellError::DirectoryNotFound(
dst.span, dst.span,
Some("destination directory does not exist".to_string()), destination.to_string_lossy().to_string(),
)); ));
} }
let ctrlc = engine_state.ctrlc.clone(); let ctrlc = engine_state.ctrlc.clone();

View File

@ -276,7 +276,10 @@ fn move_file(
}; };
if !destination_dir_exists { if !destination_dir_exists {
return Err(ShellError::DirectoryNotFound(to_span, None)); return Err(ShellError::DirectoryNotFound(
to_span,
to.to_string_lossy().to_string(),
));
} }
// This can happen when changing case on a case-insensitive filesystem (ex: changing foo to Foo on Windows) // This can happen when changing case on a case-insensitive filesystem (ex: changing foo to Foo on Windows)
@ -287,7 +290,12 @@ fn move_file(
if !from_to_are_same_file && to.is_dir() { if !from_to_are_same_file && to.is_dir() {
let from_file_name = match from.file_name() { let from_file_name = match from.file_name() {
Some(name) => name, Some(name) => name,
None => return Err(ShellError::DirectoryNotFound(to_span, None)), None => {
return Err(ShellError::DirectoryNotFound(
to_span,
from.to_string_lossy().to_string(),
))
}
}; };
to.push(from_file_name); to.push(from_file_name);

View File

@ -82,10 +82,10 @@ impl Command for Watch {
let path = match nu_path::canonicalize_with(path_no_whitespace, cwd) { let path = match nu_path::canonicalize_with(path_no_whitespace, cwd) {
Ok(p) => p, Ok(p) => p,
Err(e) => { Err(_) => {
return Err(ShellError::DirectoryNotFound( return Err(ShellError::DirectoryNotFound(
path_arg.span, path_arg.span,
Some(format!("IO Error: {e:?}")), path_no_whitespace.to_string(),
)) ))
} }
}; };

View File

@ -391,7 +391,7 @@ fn copy_to_non_existing_dir_impl(progress: bool) {
progress_flag progress_flag
); );
assert!(actual.err.contains("directory not found")); assert!(actual.err.contains("directory not found"));
assert!(actual.err.contains("destination directory does not exist")); assert!(actual.err.contains("does not exist"));
}); });
} }

View File

@ -69,10 +69,13 @@ pub fn glob_from(
if is_symlink { if is_symlink {
(path.parent().map(|parent| parent.to_path_buf()), path) (path.parent().map(|parent| parent.to_path_buf()), path)
} else { } else {
let path = if let Ok(p) = canonicalize_with(path, cwd) { let path = if let Ok(p) = canonicalize_with(path.clone(), cwd) {
p p
} else { } else {
return Err(ShellError::DirectoryNotFound(pattern.span, None)); return Err(ShellError::DirectoryNotFound(
pattern.span,
path.to_string_lossy().to_string(),
));
}; };
(path.parent().map(|parent| parent.to_path_buf()), path) (path.parent().map(|parent| parent.to_path_buf()), path)
} }

View File

@ -801,8 +801,8 @@ pub enum ShellError {
/// ///
/// Make sure the directory in the error message actually exists before trying again. /// Make sure the directory in the error message actually exists before trying again.
#[error("Directory not found")] #[error("Directory not found")]
#[diagnostic(code(nu::shell::directory_not_found))] #[diagnostic(code(nu::shell::directory_not_found), help("{1} does not exist"))]
DirectoryNotFound(#[label("directory not found")] Span, #[help] Option<String>), DirectoryNotFound(#[label("directory not found")] Span, String),
/// Attempted to perform an operation on a directory that doesn't exist. /// Attempted to perform an operation on a directory that doesn't exist.
/// ///