mirror of
https://github.com/lsd-rs/lsd
synced 2024-12-13 13:42:34 +00:00
fix long listing for symlinkd dirs
This commit is contained in:
parent
cffda506f1
commit
5c128780f1
4 changed files with 63 additions and 24 deletions
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue