Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/app/sub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,14 @@ where
let data_tree = if iter.len() == 0 {
data_tree
} else {
let max_depth = max_depth.get();
let children: Vec<_> = once(data_tree).chain(iter).collect();
DataTree::dir(
OsStringDisplay::os_string_from("(total)"),
Size::default(),
children,
max_depth.get(),
)
.into_par_retained(|_, depth| depth + 1 < max_depth)
};

if reporter.destroy().is_err() {
Expand Down
10 changes: 7 additions & 3 deletions src/data_tree/constructors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ use crate::size;

impl<Name, Size: size::Size> DataTree<Name, Size> {
/// Create a tree representation of a directory.
pub fn dir(name: Name, inode_size: Size, children: Vec<Self>, depth: u64) -> Self {
pub fn dir(name: Name, inode_size: Size, children: Vec<Self>) -> Self {
let size = inode_size + children.iter().map(DataTree::size).sum();
let children = if depth > 0 { children } else { Vec::new() };
DataTree {
name,
size,
Expand All @@ -27,6 +26,11 @@ impl<Name, Size: size::Size> DataTree<Name, Size> {
where
Size: Copy,
{
move |name, children| DataTree::dir(name, inode_size, children, 1)
move |name, children| DataTree::dir(name, inode_size, children)
}

/// Remove the children. Free memory usage.
pub(crate) fn drop_children(&mut self) {
self.children = Vec::new();
}
}
3 changes: 1 addition & 2 deletions src/data_tree/retain/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ type SampleData = Bytes;
type SampleTree = DataTree<SampleName, SampleData>;

fn dir<const INODE_SIZE: u64>(name: &'static str, children: Vec<SampleTree>) -> SampleTree {
SampleTree::dir(name.to_string(), INODE_SIZE.into(), children, 10)
SampleTree::dir(name.to_string(), INODE_SIZE.into(), children)
}

fn file(name: &'static str, size: u64) -> SampleTree {
Expand All @@ -23,7 +23,6 @@ fn culled_dir<const INODE_SIZE: u64>(
name.to_string(),
(INODE_SIZE + culled_size).into(),
children,
10,
)
}

Expand Down
9 changes: 7 additions & 2 deletions src/tree_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,13 @@ where
max_depth,
})
.map(Self::from)
.collect();
.collect(); // TODO: this collect can be called into different types depending on whether `max_depth` is 0

DataTree::dir(name, size, children, max_depth)
let mut tree = DataTree::dir(name, size, children);
if max_depth == 0 {
// TODO: replace this with a more memory efficient method that doesn't require constructing `children` in the first place
tree.drop_children();
}
tree
}
}
8 changes: 4 additions & 4 deletions tests/_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,13 @@ impl Default for SampleWorkspace {
MergeableFileSystemTree::<&str, String>::from(dir! {
"flat" => dir! {
"0" => file!("")
"1" => file!("a".repeat(1000))
"2" => file!("a".repeat(2000))
"3" => file!("a".repeat(3000))
"1" => file!("a".repeat(100_000))
"2" => file!("a".repeat(200_000))
"3" => file!("a".repeat(300_000))
}
"nested" => dir! {
"0" => dir! {
"1" => file!("a".repeat(5000))
"1" => file!("a".repeat(500_000))
}
}
"empty-dir" => dir! {}
Expand Down
2 changes: 1 addition & 1 deletion tests/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ type SampleTree = DataTree<SampleName, SampleData>;

fn sample_tree() -> SampleTree {
let dir = |name: &'static str, children: Vec<SampleTree>| {
SampleTree::dir(name.to_string(), 1024.into(), children, 10)
SampleTree::dir(name.to_string(), 1024.into(), children)
};
let file =
|name: &'static str, size: u64| SampleTree::file(name.to_string(), Bytes::from(size));
Expand Down
129 changes: 128 additions & 1 deletion tests/usual_cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,6 @@ fn multiple_names() {
OsStringDisplay::os_string_from("(total)"),
0.into(),
children.collect(),
10,
)
})
.into_par_sorted(|left, right| left.size().cmp(&right.size()).reverse());
Expand All @@ -640,4 +639,132 @@ fn multiple_names() {
eprintln!("EXPECTED:\n{expected}\n");

assert_eq!(actual, expected);

let mut lines = actual.lines();
assert!(lines.next().unwrap().contains("┌──1"));
assert!(lines.next().unwrap().contains("┌─┴0"));
assert!(lines.next().unwrap().contains("┌─┴nested"));
assert!(lines.next().unwrap().contains("│ ┌──1"));
assert!(lines.next().unwrap().contains("│ ├──2"));
assert!(lines.next().unwrap().contains("│ ├──3"));
assert!(lines.next().unwrap().contains("├─┴flat"));
assert!(lines.next().unwrap().contains("┌─┴(total)"));
assert_eq!(lines.next(), None);
}

#[test]
fn multiple_names_max_depth_2() {
let workspace = SampleWorkspace::default();
let actual = Command::new(PDU)
.with_current_dir(&workspace)
.with_arg("--quantity=apparent-size")
.with_arg("--total-width=100")
.with_arg("--max-depth=2")
.with_arg("nested")
.with_arg("flat")
.with_arg("empty-dir")
.pipe(stdio)
.output()
.expect("spawn command")
.pipe(stdout_text);
eprintln!("ACTUAL:\n{actual}\n");

let mut data_tree = ["nested", "flat", "empty-dir"]
.iter()
.map(|name| {
let builder = FsTreeBuilder {
root: workspace.to_path_buf().join(name),
size_getter: GetApparentSize,
reporter: ErrorOnlyReporter::new(ErrorReport::SILENT),
max_depth: 1,
};
let mut data_tree: DataTree<OsStringDisplay, _> = builder.into();
*data_tree.name_mut() = OsStringDisplay::os_string_from(name);
data_tree
})
.pipe(|children| {
DataTree::dir(
OsStringDisplay::os_string_from("(total)"),
0.into(),
children.collect(),
)
})
.into_par_sorted(|left, right| left.size().cmp(&right.size()).reverse());
data_tree.par_cull_insignificant_data(0.01);
let visualizer = Visualizer::<OsStringDisplay, _> {
data_tree: &data_tree,
bytes_format: BytesFormat::MetricUnits,
direction: Direction::BottomUp,
bar_alignment: BarAlignment::Left,
column_width_distribution: ColumnWidthDistribution::total(100),
};
let expected = format!("{visualizer}");
let expected = expected.trim_end();
eprintln!("EXPECTED:\n{expected}\n");

assert_eq!(actual, expected);

let mut lines = actual.lines();
assert!(lines.next().unwrap().contains("┌──nested"));
assert!(lines.next().unwrap().contains("├──flat"));
assert!(lines.next().unwrap().contains("┌─┴(total)"));
assert_eq!(lines.next(), None);
}

#[test]
fn multiple_names_max_depth_1() {
let workspace = SampleWorkspace::default();
let actual = Command::new(PDU)
.with_current_dir(&workspace)
.with_arg("--quantity=apparent-size")
.with_arg("--total-width=100")
.with_arg("--max-depth=1")
.with_arg("nested")
.with_arg("flat")
.with_arg("empty-dir")
.pipe(stdio)
.output()
.expect("spawn command")
.pipe(stdout_text);
eprintln!("ACTUAL:\n{actual}\n");

let mut data_tree = ["nested", "flat", "empty-dir"]
.iter()
.map(|name| {
let builder = FsTreeBuilder {
root: workspace.to_path_buf().join(name),
size_getter: GetApparentSize,
reporter: ErrorOnlyReporter::new(ErrorReport::SILENT),
max_depth: 10,
};
let mut data_tree: DataTree<OsStringDisplay, _> = builder.into();
*data_tree.name_mut() = OsStringDisplay::os_string_from(name);
data_tree
})
.pipe(|children| {
DataTree::dir(
OsStringDisplay::os_string_from("(total)"),
0.into(),
children.collect(),
)
})
.into_par_retained(|_, _| false)
.into_par_sorted(|left, right| left.size().cmp(&right.size()).reverse());
data_tree.par_cull_insignificant_data(0.01);
let visualizer = Visualizer::<OsStringDisplay, _> {
data_tree: &data_tree,
bytes_format: BytesFormat::MetricUnits,
direction: Direction::BottomUp,
bar_alignment: BarAlignment::Left,
column_width_distribution: ColumnWidthDistribution::total(100),
};
let expected = format!("{visualizer}");
let expected = expected.trim_end();
eprintln!("EXPECTED:\n{expected}\n");

assert_eq!(actual, expected);

let mut lines = actual.lines();
assert!(lines.next().unwrap().contains("┌──(total)"));
assert_eq!(lines.next(), None);
}
4 changes: 2 additions & 2 deletions tests/visualizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ fn nested_tree<Size: size::Size>(
) -> DataTree<&'static str, Size> {
if let Some((head, tail)) = dir_names.split_first() {
let child = nested_tree(tail, size_per_dir, file_name, file_size);
DataTree::dir(*head, size_per_dir, vec![child], 10)
DataTree::dir(*head, size_per_dir, vec![child])
} else {
DataTree::file(file_name, file_size)
}
Expand Down Expand Up @@ -649,7 +649,7 @@ fn empty_dir<Size>(inode_size: Size) -> DataTree<&'static str, Size>
where
Size: size::Size + Ord + From<u64> + Send,
{
DataTree::dir("empty directory", inode_size, Vec::new(), 10).into_par_sorted(order_tree)
DataTree::dir("empty directory", inode_size, Vec::new()).into_par_sorted(order_tree)
}

test_case! {
Expand Down