Skip to content

Commit

Permalink
Merge pull request #136 from solidiquis/opt/show-hardlinks
Browse files Browse the repository at this point in the history
show hardlinks but don't duplicate file size count
  • Loading branch information
solidiquis authored Apr 20, 2023
2 parents 14fd53e + 5a98577 commit 651c4cc
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 22 deletions.
4 changes: 2 additions & 2 deletions src/render/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions src/render/disk_usage/file_size.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,9 +194,9 @@ impl FileSize {
}
}

impl AddAssign<u64> 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;
}
}

Expand Down
46 changes: 29 additions & 17 deletions src/render/tree/mod.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -128,8 +131,6 @@ where
let res = s.spawn(move || {
let mut tree = Arena::new();
let mut branches: HashMap<PathBuf, Vec<NodeId>> = HashMap::new();
let mut inodes = HashSet::new();

let mut root_id = None;

while let Ok(TraversalState::Ongoing(node)) = rx.recv() {
Expand All @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -199,6 +201,7 @@ where
current_node_id: NodeId,
branches: &mut HashMap<PathBuf, Vec<NodeId>>,
node_comparator: &NodeComparator,
inode_set: &mut HashSet<Inode>,
ctx: &Context,
) {
let current_node = tree[current_node_id].get_mut();
Expand All @@ -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;
}
}

Expand Down
38 changes: 38 additions & 0 deletions tests/hardlink.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use indoc::indoc;
use std::{env::current_dir, error::Error, fs};

mod utils;

#[test]
fn hardlink() -> Result<(), Box<dyn Error>> {
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(())
}
1 change: 1 addition & 0 deletions tests/hardlinks/kadath.txt
Original file line number Diff line number Diff line change
@@ -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.”

0 comments on commit 651c4cc

Please sign in to comment.