Custom canonicalize method on Filesystem Shell. (#1485)

* Custom canonicalize method for FilesystemShell.

* Use custom canonicalize method.
Fixed missing import.

* Move function body to already impl body.

* Create test that aims to resolve.
This commit is contained in:
Kevin DCR 2020-03-16 01:28:18 -05:00 committed by GitHub
parent 45a3afdc79
commit 8d19b21b9f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 48 additions and 4 deletions

View File

@ -14,7 +14,7 @@ use nu_parser::ExpandContext;
use nu_protocol::{Primitive, ReturnSuccess, UntaggedValue};
use rustyline::completion::FilenameCompleter;
use rustyline::hint::{Hinter, HistoryHinter};
use std::path::{Path, PathBuf};
use std::path::{Component, Path, PathBuf};
use std::sync::atomic::Ordering;
use trash as SendToTrash;
@ -78,6 +78,29 @@ impl FilesystemShell {
hinter: HistoryHinter {},
}
}
fn canonicalize(&self, path: impl AsRef<Path>) -> std::io::Result<PathBuf> {
let path = if path.as_ref().is_relative() {
let components = path.as_ref().components();
let mut result = PathBuf::from(self.path());
for component in components {
match component {
Component::CurDir => { /* ignore current dir */ }
Component::ParentDir => {
result.pop();
}
Component::Normal(normal) => result.push(normal),
_ => {}
}
}
result
} else {
path.as_ref().into()
};
dunce::canonicalize(path)
}
}
impl Shell for FilesystemShell {
@ -201,11 +224,10 @@ impl Shell for FilesystemShell {
Some(v) => {
let target = v.as_path()?;
if PathBuf::from("-") == target {
if target == Path::new("-") {
PathBuf::from(&self.last_path)
} else {
let path = PathBuf::from(self.path());
let path = dunce::canonicalize(path.join(&target)).map_err(|_| {
let path = self.canonicalize(target).map_err(|_| {
ShellError::labeled_error(
"Cannot change to directory",
"directory not found",

View File

@ -85,6 +85,28 @@ fn filesystem_change_current_directory_to_parent_directory() {
})
}
#[test]
fn filesystem_change_current_directory_to_parent_directory_after_delete_cwd() {
Playground::setup("cd_test_5_1", |dirs, sandbox| {
sandbox.within("foo").mkdir("bar");
let actual = nu!(
cwd: dirs.test().join("foo/bar"),
r#"
rm {}/foo/bar
echo ","
cd ..
pwd | echo $it
"#,
dirs.test()
);
let actual = actual.split(',').nth(1).unwrap();
assert_eq!(PathBuf::from(actual), *dirs.test().join("foo"));
})
}
#[test]
fn filesystem_change_to_home_directory() {
Playground::setup("cd_test_6", |dirs, _| {