fix long listing for symlinkd dirs

This commit is contained in:
Abin Simon 2020-08-22 00:46:59 +05:30
parent cffda506f1
commit 5c128780f1
4 changed files with 63 additions and 24 deletions

View file

@ -95,12 +95,7 @@ impl Core {
meta_list.push(meta); meta_list.push(meta);
} }
_ => { _ => {
match meta.recurse_into( match meta.recurse_into(depth, &self.flags) {
depth,
self.flags.display,
&self.flags.ignore_globs,
self.flags.dereference,
) {
Ok(content) => { Ok(content) => {
meta.content = content; meta.content = content;
meta_list.push(meta); meta_list.push(meta);

View file

@ -68,7 +68,8 @@ fn inner_display_grid(
// Maybe skip showing the directory meta now; show its contents later. // Maybe skip showing the directory meta now; show its contents later.
if skip_dirs if skip_dirs
&& (matches!(meta.file_type, FileType::Directory{..}) && (matches!(meta.file_type, FileType::Directory{..})
|| matches!(meta.file_type, FileType::SymLink { is_dir: true })) || (matches!(meta.file_type, FileType::SymLink { is_dir: true })
&& flags.layout != Layout::OneLine))
{ {
continue; continue;
} }
@ -109,7 +110,7 @@ fn inner_display_grid(
output += &grid.fit_into_columns(flags.blocks.len()).to_string(); output += &grid.fit_into_columns(flags.blocks.len()).to_string();
} }
let should_display_folder_path = should_display_folder_path(depth, &metas); let should_display_folder_path = should_display_folder_path(depth, &metas, &flags);
// print the folder content // print the folder content
for meta in metas { for meta in metas {
@ -218,7 +219,7 @@ fn inner_display_tree(
output output
} }
fn should_display_folder_path(depth: usize, metas: &[Meta]) -> bool { fn should_display_folder_path(depth: usize, metas: &[Meta], flags: &Flags) -> bool {
if depth > 0 { if depth > 0 {
true true
} else { } else {
@ -226,7 +227,8 @@ fn should_display_folder_path(depth: usize, metas: &[Meta]) -> bool {
.iter() .iter()
.filter(|x| { .filter(|x| {
matches!(x.file_type, FileType::Directory { .. }) matches!(x.file_type, FileType::Directory { .. })
|| matches!(x.file_type, FileType::SymLink { is_dir: true }) || (matches!(x.file_type, FileType::SymLink { is_dir: true })
&& flags.layout != Layout::OneLine)
}) })
.count(); .count();

View file

@ -20,7 +20,7 @@ pub use self::owner::Owner;
pub use self::permissions::Permissions; pub use self::permissions::Permissions;
pub use self::size::Size; pub use self::size::Size;
pub use self::symlink::SymLink; pub use self::symlink::SymLink;
pub use crate::flags::Display; pub use crate::flags::{Display, Flags, Layout};
pub use crate::icon::Icons; pub use crate::icon::Icons;
use crate::print_error; use crate::print_error;
@ -28,8 +28,6 @@ use std::fs::read_link;
use std::io::{Error, ErrorKind}; use std::io::{Error, ErrorKind};
use std::path::{Component, Path, PathBuf}; use std::path::{Component, Path, PathBuf};
use globset::GlobSet;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Meta { pub struct Meta {
pub name: Name, pub name: Name,
@ -49,21 +47,23 @@ impl Meta {
pub fn recurse_into( pub fn recurse_into(
&self, &self,
depth: usize, depth: usize,
display: Display, flags: &Flags,
ignore_globs: &GlobSet,
dereference: bool,
) -> Result<Option<Vec<Meta>>, std::io::Error> { ) -> Result<Option<Vec<Meta>>, std::io::Error> {
if depth == 0 { if depth == 0 {
return Ok(None); return Ok(None);
} }
if display == Display::DisplayDirectoryItself { if flags.display == Display::DisplayDirectoryItself {
return Ok(None); return Ok(None);
} }
match self.file_type { match self.file_type {
FileType::Directory { .. } => (), FileType::Directory { .. } => (),
FileType::SymLink { is_dir: true } => (), FileType::SymLink { is_dir: true } => {
if flags.layout == Layout::OneLine {
return Ok(None);
}
}
_ => return Ok(None), _ => return Ok(None),
} }
@ -77,13 +77,14 @@ impl Meta {
let mut content: Vec<Meta> = Vec::new(); let mut content: Vec<Meta> = Vec::new();
if let Display::DisplayAll = display { if let Display::DisplayAll = flags.display {
let mut current_meta; let mut current_meta;
current_meta = self.clone(); current_meta = self.clone();
current_meta.name.name = ".".to_owned(); current_meta.name.name = ".".to_owned();
let parent_meta = Self::from_path(&self.path.join(Component::ParentDir), dereference)?; let parent_meta =
Self::from_path(&self.path.join(Component::ParentDir), flags.dereference)?;
content.push(current_meta); content.push(current_meta);
content.push(parent_meta); content.push(parent_meta);
@ -96,17 +97,17 @@ impl Meta {
.file_name() .file_name()
.ok_or_else(|| Error::new(ErrorKind::InvalidInput, "invalid file name"))?; .ok_or_else(|| Error::new(ErrorKind::InvalidInput, "invalid file name"))?;
if ignore_globs.is_match(&name) { if flags.ignore_globs.is_match(&name) {
continue; continue;
} }
if let Display::DisplayOnlyVisible = display { if let Display::DisplayOnlyVisible = flags.display {
if name.to_string_lossy().starts_with('.') { if name.to_string_lossy().starts_with('.') {
continue; continue;
} }
} }
let mut entry_meta = match Self::from_path(&path, dereference) { let mut entry_meta = match Self::from_path(&path, flags.dereference) {
Ok(res) => res, Ok(res) => res,
Err(err) => { Err(err) => {
print_error!("lsd: {}: {}\n", path.display(), err); print_error!("lsd: {}: {}\n", path.display(), err);
@ -114,7 +115,7 @@ impl Meta {
} }
}; };
match entry_meta.recurse_into(depth - 1, display, ignore_globs, dereference) { match entry_meta.recurse_into(depth - 1, &flags) {
Ok(content) => entry_meta.content = content, Ok(content) => entry_meta.content = content,
Err(err) => { Err(err) => {
print_error!("lsd: {}: {}\n", path.display(), err); print_error!("lsd: {}: {}\n", path.display(), err);

View file

@ -219,6 +219,47 @@ fn test_show_folder_content_of_symlink() {
.stdout(predicate::str::starts_with("inside")); .stdout(predicate::str::starts_with("inside"));
} }
#[cfg(unix)]
#[test]
fn test_no_show_folder_content_of_symlink_for_long() {
let dir = tempdir();
dir.child("target").child("inside").touch().unwrap();
let link = dir.path().join("link");
fs::symlink("target", &link).unwrap();
cmd()
.arg("-l")
.arg(link)
.assert()
.stdout(predicate::str::starts_with("lrw"))
.stdout(predicate::str::contains(""));
cmd()
.arg("-l")
.arg(dir.path().join("link/"))
.assert()
.stdout(predicate::str::starts_with(".rw"))
.stdout(predicate::str::contains("").not());
}
#[cfg(unix)]
#[test]
fn test_show_folder_of_symlink_for_long_multi() {
let dir = tempdir();
dir.child("target").child("inside").touch().unwrap();
let link = dir.path().join("link");
fs::symlink("target", &link).unwrap();
cmd()
.arg("-l")
.arg(dir.path().join("link/"))
.arg(dir.path().join("link"))
.assert()
.stdout(predicate::str::starts_with("lrw"))
.stdout(predicate::str::contains("link:").not()) // do not show dir content when no /
.stdout(predicate::str::contains("link/:"));
}
fn cmd() -> Command { fn cmd() -> Command {
Command::cargo_bin(env!("CARGO_PKG_NAME")).unwrap() Command::cargo_bin(env!("CARGO_PKG_NAME")).unwrap()
} }