Let ls ignore permission errors (#1435)

* Create a function to create an empty directory entry

* Print an empty directory entry if permission is denied

* Fix rustfmt whitespace issues.

* Made metadata optional for `dir_entry_dict`.

Removed `empty_dir_entry_dict` as its not needed anymore.
This commit is contained in:
Benjamin Röjder Delnavaz 2020-02-29 02:33:52 +01:00 committed by GitHub
parent a86a0abb90
commit eabfa2de54
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 92 additions and 49 deletions

View File

@ -4,7 +4,7 @@ use nu_protocol::{TaggedDictBuilder, UntaggedValue, Value};
pub(crate) fn dir_entry_dict( pub(crate) fn dir_entry_dict(
filename: &std::path::Path, filename: &std::path::Path,
metadata: &std::fs::Metadata, metadata: Option<&std::fs::Metadata>,
tag: impl Into<Tag>, tag: impl Into<Tag>,
full: bool, full: bool,
name_only: bool, name_only: bool,
@ -28,77 +28,110 @@ pub(crate) fn dir_entry_dict(
dict.insert_untagged("name", UntaggedValue::string(name)); dict.insert_untagged("name", UntaggedValue::string(name));
if metadata.is_dir() { if let Some(md) = metadata {
dict.insert_untagged("type", UntaggedValue::string("Dir")); if md.is_dir() {
} else if metadata.is_file() { dict.insert_untagged("type", UntaggedValue::string("Dir"));
dict.insert_untagged("type", UntaggedValue::string("File")); } else if md.is_file() {
dict.insert_untagged("type", UntaggedValue::string("File"));
} else {
dict.insert_untagged("type", UntaggedValue::string("Symlink"));
}
} else { } else {
dict.insert_untagged("type", UntaggedValue::string("Symlink")); dict.insert_untagged("type", UntaggedValue::nothing());
}; }
if full || with_symlink_targets { if full || with_symlink_targets {
if metadata.is_dir() || metadata.is_file() { if let Some(md) = metadata {
dict.insert_untagged("target", UntaggedValue::nothing()); if md.is_dir() || md.is_file() {
} else if let Ok(path_to_link) = filename.read_link() { dict.insert_untagged("target", UntaggedValue::nothing());
dict.insert_untagged( } else if let Ok(path_to_link) = filename.read_link() {
"target", dict.insert_untagged(
UntaggedValue::string(path_to_link.to_string_lossy()), "target",
); UntaggedValue::string(path_to_link.to_string_lossy()),
);
} else {
dict.insert_untagged(
"target",
UntaggedValue::string("Could not obtain target file's path"),
);
}
} else { } else {
dict.insert_untagged( dict.insert_untagged("target", UntaggedValue::nothing());
"target",
UntaggedValue::string("Could not obtain target file's path"),
);
} }
} }
if full { if full {
dict.insert_untagged( if let Some(md) = metadata {
"readonly",
UntaggedValue::boolean(metadata.permissions().readonly()),
);
#[cfg(unix)]
{
use std::os::unix::fs::MetadataExt;
use std::os::unix::fs::PermissionsExt;
let mode = metadata.permissions().mode();
dict.insert_untagged( dict.insert_untagged(
"mode", "readonly",
UntaggedValue::string(umask::Mode::from(mode).to_string()), UntaggedValue::boolean(md.permissions().readonly()),
); );
if let Some(user) = users::get_user_by_uid(metadata.uid()) { #[cfg(unix)]
dict.insert_untagged("uid", UntaggedValue::string(user.name().to_string_lossy())); {
} use std::os::unix::fs::MetadataExt;
use std::os::unix::fs::PermissionsExt;
if let Some(group) = users::get_group_by_gid(metadata.gid()) { let mode = md.permissions().mode();
dict.insert_untagged( dict.insert_untagged(
"group", "mode",
UntaggedValue::string(group.name().to_string_lossy()), UntaggedValue::string(umask::Mode::from(mode).to_string()),
); );
if let Some(user) = users::get_user_by_uid(md.uid()) {
dict.insert_untagged(
"uid",
UntaggedValue::string(user.name().to_string_lossy()),
);
}
if let Some(group) = users::get_group_by_gid(md.gid()) {
dict.insert_untagged(
"group",
UntaggedValue::string(group.name().to_string_lossy()),
);
}
}
} else {
dict.insert_untagged("readonly", UntaggedValue::nothing());
#[cfg(unix)]
{
dict.insert_untagged("mode", UntaggedValue::nothing());
} }
} }
} }
if metadata.is_file() { if let Some(md) = metadata {
dict.insert_untagged("size", UntaggedValue::bytes(metadata.len() as u64)); if md.is_file() {
dict.insert_untagged("size", UntaggedValue::bytes(md.len() as u64));
} else {
dict.insert_untagged("size", UntaggedValue::nothing());
}
} else { } else {
dict.insert_untagged("size", UntaggedValue::nothing()); dict.insert_untagged("size", UntaggedValue::nothing());
} }
if full { if let Some(md) = metadata {
if let Ok(c) = metadata.created() { if full {
dict.insert_untagged("created", UntaggedValue::system_date(c)); if let Ok(c) = md.created() {
dict.insert_untagged("created", UntaggedValue::system_date(c));
}
if let Ok(a) = md.accessed() {
dict.insert_untagged("accessed", UntaggedValue::system_date(a));
}
} }
if let Ok(a) = metadata.accessed() { if let Ok(m) = md.modified() {
dict.insert_untagged("accessed", UntaggedValue::system_date(a)); dict.insert_untagged("modified", UntaggedValue::system_date(m));
}
} else {
if full {
dict.insert_untagged("created", UntaggedValue::nothing());
dict.insert_untagged("accessed", UntaggedValue::nothing());
} }
}
if let Ok(m) = metadata.modified() { dict.insert_untagged("modified", UntaggedValue::nothing());
dict.insert_untagged("modified", UntaggedValue::system_date(m));
} }
Ok(dict.into_value()) Ok(dict.into_value())

View File

@ -142,12 +142,22 @@ impl Shell for FilesystemShell {
match path { match path {
Ok(p) => match std::fs::symlink_metadata(&p) { Ok(p) => match std::fs::symlink_metadata(&p) {
Ok(m) => { Ok(m) => {
match dir_entry_dict(&p, &m, name_tag.clone(), full, short_names, with_symlink_targets) { match dir_entry_dict(&p, Some(&m), name_tag.clone(), full, short_names, with_symlink_targets) {
Ok(d) => yield ReturnSuccess::value(d), Ok(d) => yield ReturnSuccess::value(d),
Err(e) => yield Err(e) Err(e) => yield Err(e)
} }
} }
Err(e) => yield Err(ShellError::from(e)) Err(e) => {
match e.kind() {
PermissionDenied => {
match dir_entry_dict(&p, None, name_tag.clone(), full, short_names, with_symlink_targets) {
Ok(d) => yield ReturnSuccess::value(d),
Err(e) => yield Err(e)
}
},
_ => yield Err(ShellError::from(e))
}
}
} }
Err(e) => yield Err(e.into_error().into()), Err(e) => yield Err(e.into_error().into()),
} }