Add --with-symlink-targets option for the ls command that displays a new column for the target files of symlinks (#1292)

* Add `--with-symlink-targets` option for the `ls` command that displays a new column for the target files of symlinks

* Fix clippy warning

Co-authored-by: Jonathan Turner <jonathandturner@users.noreply.github.com>
This commit is contained in:
Joseph T. Lyons 2020-01-28 01:48:41 -05:00 committed by Jonathan Turner
parent f20a4a42e8
commit 9ec6d0c90e
3 changed files with 26 additions and 2 deletions

View File

@ -13,6 +13,8 @@ pub struct LsArgs {
pub full: bool,
#[serde(rename = "short-names")]
pub short_names: bool,
#[serde(rename = "with-symlink-targets")]
pub with_symlink_targets: bool,
}
impl PerItemCommand for Ls {
@ -29,6 +31,10 @@ impl PerItemCommand for Ls {
)
.switch("full", "list all available columns for each entry")
.switch("short-names", "only print the file names and not the path")
.switch(
"with-symlink-targets",
"display the paths to the target files that symlinks point to",
)
}
fn usage(&self) -> &str {

View File

@ -7,6 +7,7 @@ pub(crate) fn dir_entry_dict(
metadata: &std::fs::Metadata,
tag: impl Into<Tag>,
full: bool,
with_symlink_targets: bool,
) -> Result<Value, ShellError> {
let mut dict = TaggedDictBuilder::new(tag);
dict.insert_untagged("name", UntaggedValue::string(filename.to_string_lossy()));
@ -19,6 +20,22 @@ pub(crate) fn dir_entry_dict(
dict.insert_untagged("type", UntaggedValue::string("Symlink"));
};
if full || with_symlink_targets {
if metadata.is_dir() || metadata.is_file() {
dict.insert_untagged("target", UntaggedValue::bytes(0u64));
} else if let Ok(path_to_link) = filename.read_link() {
dict.insert_untagged(
"target",
UntaggedValue::string(path_to_link.to_string_lossy()),
);
} else {
dict.insert_untagged(
"target",
UntaggedValue::string("Could not obtain target file's path"),
);
}
}
if full {
dict.insert_untagged(
"readonly",

View File

@ -92,6 +92,7 @@ impl Shell for FilesystemShell {
path,
full,
short_names,
with_symlink_targets,
}: LsArgs,
context: &RunnablePerItemContext,
) -> Result<OutputStream, ShellError> {
@ -166,7 +167,7 @@ impl Shell for FilesystemShell {
}
}
let value = dir_entry_dict(filename, &metadata, &name_tag, full)?;
let value = dir_entry_dict(filename, &metadata, &name_tag, full, with_symlink_targets)?;
yield ReturnSuccess::value(value);
}
}
@ -217,7 +218,7 @@ impl Shell for FilesystemShell {
}
}
if let Ok(value) = dir_entry_dict(filename, &metadata, &name_tag, full) {
if let Ok(value) = dir_entry_dict(filename, &metadata, &name_tag, full, with_symlink_targets) {
yield ReturnSuccess::value(value);
}
}