Add --directory (-D) flag to ls, list the directory itself instead of its contents (#5970)

* Avoid extending the directory without globs in `nu_engine::glob_from`

* avoid joining a `*` to the directory without globs

* remove checks on directory permission and whether it is empty

The previous implemention of `nu_engine::glob_from` will extend the
given directory even if it containes no glob pattern. This commit
overcomes lack of consistency with the function `nu_glob::glob`.

* Add flag -D to ls, to list the directory itself instead of its contents

* add --directory (-d) flag to ls

* correct the difference between the given path and the cwd

* set default path to `.` instead of `./*` when --directory (-d) flag is true

* add comments

* add an example

* add tests

* fmt
This commit is contained in:
默可思
2022-07-09 03:15:34 +08:00
committed by GitHub
parent 125e60d06a
commit 221f36ca65
4 changed files with 113 additions and 58 deletions

View File

@ -1,5 +1,3 @@
#[cfg(unix)]
use std::os::unix::fs::PermissionsExt;
use std::path::{Component, Path, PathBuf};
use nu_glob::MatchOptions;
@ -48,39 +46,7 @@ pub fn glob_from(
} else {
return Err(ShellError::DirectoryNotFound(pattern.span, None));
};
if path.is_dir() {
if permission_denied(&path) {
#[cfg(unix)]
let error_msg = format!(
"The permissions of {:o} do not allow access for this user",
path.metadata()
.expect("this shouldn't be called since we already know there is a dir")
.permissions()
.mode()
& 0o0777
);
#[cfg(not(unix))]
let error_msg = String::from("Permission denied");
return Err(ShellError::GenericError(
"Permission denied".into(),
error_msg,
Some(pattern.span),
None,
Vec::new(),
));
}
if is_empty_dir(&path) {
return Ok((Some(path), Box::new(vec![].into_iter())));
}
(Some(path.clone()), path.join("*"))
} else {
(path.parent().map(|parent| parent.to_path_buf()), path)
}
(path.parent().map(|parent| parent.to_path_buf()), path)
};
let pattern = pattern.to_string_lossy().to_string();
@ -110,17 +76,3 @@ pub fn glob_from(
})),
))
}
fn permission_denied(dir: impl AsRef<Path>) -> bool {
match dir.as_ref().read_dir() {
Err(e) => matches!(e.kind(), std::io::ErrorKind::PermissionDenied),
Ok(_) => false,
}
}
fn is_empty_dir(dir: impl AsRef<Path>) -> bool {
match dir.as_ref().read_dir() {
Err(_) => true,
Ok(mut s) => s.next().is_none(),
}
}