diff --git a/src/render/context/mod.rs b/src/render/context/mod.rs index c589ec67..7a9cf420 100644 --- a/src/render/context/mod.rs +++ b/src/render/context/mod.rs @@ -255,10 +255,10 @@ impl Context { /// Determines whether or not it's appropriate to display color in output based on /// `--no-color`, `--force-color`, and whether or not stdout is connected to a tty. /// - /// If `--force-color` is true then this will always evaluate to `false`. + /// If `--force-color` is `true` then this will always evaluate to `false`. pub const fn no_color(&self) -> bool { if self.force_color { - return false + return false; } self.no_color || !self.stdout_is_tty diff --git a/src/render/disk_usage/file_size.rs b/src/render/disk_usage/file_size.rs index 233ad6ac..5270921c 100644 --- a/src/render/disk_usage/file_size.rs +++ b/src/render/disk_usage/file_size.rs @@ -194,9 +194,9 @@ impl FileSize { } } -impl AddAssign for FileSize { - fn add_assign(&mut self, rhs: u64) { - self.bytes += rhs; +impl AddAssign<&Self> for FileSize { + fn add_assign(&mut self, rhs: &Self) { + self.bytes += rhs.bytes; } } diff --git a/src/render/tree/mod.rs b/src/render/tree/mod.rs index 994ce8e1..6d4ea856 100644 --- a/src/render/tree/mod.rs +++ b/src/render/tree/mod.rs @@ -1,7 +1,10 @@ -use crate::render::{ - context::{error::Error as CtxError, Context}, - disk_usage::file_size::FileSize, - styles, +use crate::{ + fs::inode::Inode, + render::{ + context::{error::Error as CtxError, Context}, + disk_usage::file_size::FileSize, + styles, + }, }; use count::FileCount; use error::Error; @@ -128,8 +131,6 @@ where let res = s.spawn(move || { let mut tree = Arena::new(); let mut branches: HashMap> = HashMap::new(); - let mut inodes = HashSet::new(); - let mut root_id = None; while let Ok(TraversalState::Ongoing(node)) = rx.recv() { @@ -146,13 +147,6 @@ where } } - // If a hard-link is already accounted for, skip all subsequent ones. - if let Some(inode) = node.inode() { - if inode.nlink > 1 && !inodes.insert(inode) { - continue; - } - } - let parent = node.parent_path().ok_or(Error::ExpectedParent)?.to_owned(); let node_id = tree.new_node(node); @@ -168,8 +162,16 @@ where let root = root_id.ok_or(Error::MissingRoot)?; let node_comparator = node::cmp::comparator(ctx); + let mut inodes = HashSet::new(); - Self::assemble_tree(&mut tree, root, &mut branches, &node_comparator, ctx); + Self::assemble_tree( + &mut tree, + root, + &mut branches, + &node_comparator, + &mut inodes, + ctx, + ); if ctx.prune { Self::prune_directories(root, &mut tree); @@ -199,6 +201,7 @@ where current_node_id: NodeId, branches: &mut HashMap>, node_comparator: &NodeComparator, + inode_set: &mut HashSet, ctx: &Context, ) { let current_node = tree[current_node_id].get_mut(); @@ -216,11 +219,20 @@ where }; if is_dir { - Self::assemble_tree(tree, index, branches, node_comparator, ctx); + Self::assemble_tree(tree, index, branches, node_comparator, inode_set, ctx); + } + + let node = tree[index].get(); + + // If a hard-link is already accounted for then don't increment parent dir size. + if let Some(inode) = node.inode() { + if inode.nlink > 1 && !inode_set.insert(inode) { + continue; + } } - if let Some(file_size) = tree[index].get().file_size() { - dir_size += file_size.bytes; + if let Some(file_size) = node.file_size() { + dir_size += file_size; } } diff --git a/tests/hardlink.rs b/tests/hardlink.rs new file mode 100644 index 00000000..56cc0d7e --- /dev/null +++ b/tests/hardlink.rs @@ -0,0 +1,38 @@ +use indoc::indoc; +use std::{env::current_dir, error::Error, fs}; + +mod utils; + +#[test] +fn hardlink() -> Result<(), Box> { + let current_dir = current_dir()?; + + let src = current_dir + .join("tests") + .join("hardlinks") + .join("kadath.txt"); + + let link = current_dir + .join("tests") + .join("hardlinks") + .join("curwin.hpl"); + + fs::hard_link(&src, &link)?; + + let out = utils::run_cmd(&["--sort", "name", "tests/hardlinks"]); + + fs::remove_file(&link)?; + + assert_eq!( + out, + indoc!( + "157 B hardlinks + 157 B ├─ curwin.hpl + 157 B └─ kadath.txt + + 2 files" + ) + ); + + Ok(()) +} diff --git a/tests/hardlinks/kadath.txt b/tests/hardlinks/kadath.txt new file mode 100644 index 00000000..a6e0404e --- /dev/null +++ b/tests/hardlinks/kadath.txt @@ -0,0 +1 @@ +“It was a song, but not the song of any voice. Night and the spheres sang it, and it was old when space and Nyarlathotep and the Other Gods were born.”