Skip to content

Commit b5b411b

Browse files
authored
Merge pull request #284 from joehasson/feat/include-directory-inodes-in-size-calculations
Fix: Directories themselves do not contribute to size like they do in du
2 parents ca6122f + a93b28e commit b5b411b

File tree

3 files changed

+62
-21
lines changed

3 files changed

+62
-21
lines changed

src/aggregate.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,7 @@ pub fn aggregate(
5252
Ok(entry) => {
5353
let file_size = match entry.client_state {
5454
Some(Ok(ref m))
55-
if !m.is_dir()
56-
&& (walk_options.count_hard_links || inodes.add(m))
55+
if (walk_options.count_hard_links || inodes.add(m))
5756
&& (walk_options.cross_filesystems
5857
|| crossdev::is_same_device(device_id, m)) =>
5958
{

src/interactive/app/tests/utils.rs

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -234,12 +234,12 @@ pub fn sample_01_tree() -> Tree {
234234
{
235235
let mut add_node = make_add_node(&mut tree);
236236
#[cfg(not(windows))]
237-
let root_size = 1259070;
237+
let root_size = 1275454;
238238
#[cfg(windows)]
239239
let root_size = 1259069;
240-
let rn = add_node("", root_size, 10, None);
240+
let rn = add_node("", root_size, 14, None);
241241
{
242-
let sn = add_node(&fixture_str("sample-01"), root_size, 10, Some(rn));
242+
let sn = add_node(&fixture_str("sample-01"), root_size, 14, Some(rn));
243243
{
244244
add_node(".hidden.666", 666, 0, Some(sn));
245245
add_node("a", 256, 0, Some(sn));
@@ -248,16 +248,26 @@ pub fn sample_01_tree() -> Tree {
248248
add_node("c.lnk", 1, 0, Some(sn));
249249
#[cfg(windows)]
250250
add_node("c.lnk", 0, 0, Some(sn));
251-
let dn = add_node("dir", 1258024, 5, Some(sn));
251+
252+
#[cfg(not(windows))]
253+
let dn = add_node("dir", 1270312, 8, Some(sn));
254+
#[cfg(windows)]
255+
let dn = add_node("dir", 1258024, 8, Some(sn));
252256
{
253257
add_node("1000bytes", 1000, 0, Some(dn));
254258
add_node("dir-a.1mb", 1_000_000, 0, Some(dn));
255259
add_node("dir-a.kb", 1024, 0, Some(dn));
256-
let en = add_node("empty-dir", 0, 1, Some(dn));
260+
#[cfg(not(windows))]
261+
let en = add_node("empty-dir", 4096, 2, Some(dn));
262+
#[cfg(windows)]
263+
let en = add_node("empty-dir", 0, 2, Some(dn));
257264
{
258265
add_node(".gitkeep", 0, 0, Some(en));
259266
}
260-
let sub = add_node("sub", 256_000, 1, Some(dn));
267+
#[cfg(not(windows))]
268+
let sub = add_node("sub", 260_096, 2, Some(dn));
269+
#[cfg(windows)]
270+
let sub = add_node("sub", 256_000, 2, Some(dn));
261271
{
262272
add_node("dir-sub-a.256kb", 256_000, 0, Some(sub));
263273
}
@@ -274,8 +284,11 @@ pub fn sample_02_tree(use_native_separator: bool) -> (Tree, TreeIndex) {
274284
let root_index: TreeIndex;
275285
{
276286
let mut add_node = make_add_node(&mut tree);
287+
#[cfg(not(windows))]
288+
let root_size = 17924;
289+
#[cfg(windows)]
277290
let root_size = 1540;
278-
root_index = add_node("", root_size, 6, None);
291+
root_index = add_node("", root_size, 10, None);
279292
{
280293
let sn = add_node(
281294
format!(
@@ -288,21 +301,30 @@ pub fn sample_02_tree(use_native_separator: bool) -> (Tree, TreeIndex) {
288301
)
289302
.as_str(),
290303
root_size,
291-
6,
304+
10,
292305
Some(root_index),
293306
);
294307
{
295308
add_node("a", 256, 0, Some(sn));
296309
add_node("b", 1, 0, Some(sn));
297-
let dn = add_node("dir", 1283, 4, Some(sn));
310+
#[cfg(not(windows))]
311+
let dn = add_node("dir", 13571, 7, Some(sn));
312+
#[cfg(windows)]
313+
let dn = add_node("dir", 1283, 7, Some(sn));
298314
{
299315
add_node("c", 257, 0, Some(dn));
300316
add_node("d", 2, 0, Some(dn));
301-
let en = add_node("empty-dir", 0, 1, Some(dn));
317+
#[cfg(not(windows))]
318+
let en = add_node("empty-dir", 4096, 2, Some(dn));
319+
#[cfg(windows)]
320+
let en = add_node("empty-dir", 0, 2, Some(dn));
302321
{
303322
add_node(".gitkeep", 0, 0, Some(en));
304323
}
305-
let sub = add_node("sub", 1024, 1, Some(dn));
324+
#[cfg(not(windows))]
325+
let sub = add_node("sub", 5120, 2, Some(dn));
326+
#[cfg(windows)]
327+
let sub = add_node("sub", 1024, 2, Some(dn));
306328
{
307329
add_node("e", 1024, 0, Some(sub));
308330
}
@@ -331,5 +353,5 @@ pub fn make_add_node(
331353
}
332354

333355
pub fn debug(item: impl fmt::Debug) -> String {
334-
format!("{item:?}")
356+
format!("{item:#?}")
335357
}

src/traverse.rs

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub type Tree = StableGraph<EntryData, (), Directed>;
1919
pub struct EntryData {
2020
pub name: PathBuf,
2121
/// The entry's size in bytes. If it's a directory, the size is the aggregated file size of all children
22+
/// plus the size of the directory entry itself
2223
pub size: u128,
2324
pub mtime: SystemTime,
2425
pub entry_count: Option<u64>,
@@ -128,6 +129,7 @@ impl EntryInfo {
128129
pub fn set_entry_info_or_panic(
129130
tree: &mut Tree,
130131
node_idx: TreeIndex,
132+
node_own_size: u128,
131133
EntryInfo {
132134
size,
133135
entries_count,
@@ -136,8 +138,8 @@ pub fn set_entry_info_or_panic(
136138
let node = tree
137139
.node_weight_mut(node_idx)
138140
.expect("node for parent index we just retrieved");
139-
node.size = size;
140-
node.entry_count = entries_count;
141+
node.size = size + node_own_size;
142+
node.entry_count = entries_count.map(|n| n + 1);
141143
}
142144

143145
pub fn parent_or_panic(tree: &mut Tree, parent_node_idx: TreeIndex) -> TreeIndex {
@@ -146,7 +148,7 @@ pub fn parent_or_panic(tree: &mut Tree, parent_node_idx: TreeIndex) -> TreeIndex
146148
.expect("every node in the iteration has a parent")
147149
}
148150

149-
pub fn pop_or_panic(v: &mut Vec<EntryInfo>) -> EntryInfo {
151+
pub fn pop_or_panic<T>(v: &mut Vec<T>) -> T {
150152
v.pop().expect("sizes per level to be in sync with graph")
151153
}
152154

@@ -168,6 +170,9 @@ pub struct BackgroundTraversal {
168170
parent_node_idx: TreeIndex,
169171
directory_info_per_depth_level: Vec<EntryInfo>,
170172
current_directory_at_depth: EntryInfo,
173+
parent_node_size: u128,
174+
parent_node_size_per_depth_level: Vec<u128>,
175+
previous_node_size: u128,
171176
previous_depth: usize,
172177
inodes: InodeFilter,
173178
throttle: Option<Throttle>,
@@ -234,6 +239,9 @@ impl BackgroundTraversal {
234239
stats: TraversalStats::default(),
235240
previous_node_idx: root_idx,
236241
parent_node_idx: root_idx,
242+
previous_node_size: 0,
243+
parent_node_size: 0,
244+
parent_node_size_per_depth_level: Vec::new(),
237245
directory_info_per_depth_level: Vec::new(),
238246
current_directory_at_depth: EntryInfo::default(),
239247
previous_depth: 0,
@@ -279,10 +287,10 @@ impl BackgroundTraversal {
279287
let mut file_count = 0u64;
280288
match &entry.client_state {
281289
Some(Ok(ref m)) => {
282-
if !m.is_dir()
283-
&& (self.walk_options.count_hard_links || self.inodes.add(m))
284-
&& (self.walk_options.cross_filesystems
285-
|| crossdev::is_same_device(device_id, m))
290+
if self.walk_options.count_hard_links
291+
|| self.inodes.add(m)
292+
&& (self.walk_options.cross_filesystems
293+
|| crossdev::is_same_device(device_id, m))
286294
{
287295
file_count = 1;
288296
if self.walk_options.apparent_size {
@@ -326,13 +334,19 @@ impl BackgroundTraversal {
326334
size: file_size,
327335
entries_count: Some(file_count),
328336
};
337+
338+
self.parent_node_size_per_depth_level
339+
.push(self.previous_node_size);
340+
329341
self.parent_node_idx = self.previous_node_idx;
342+
self.parent_node_size = self.previous_node_size;
330343
}
331344
(n, p) if n < p => {
332345
for _ in n..p {
333346
set_entry_info_or_panic(
334347
&mut traversal.tree,
335348
self.parent_node_idx,
349+
self.parent_node_size,
336350
self.current_directory_at_depth,
337351
);
338352
let dir_info =
@@ -343,6 +357,8 @@ impl BackgroundTraversal {
343357

344358
self.parent_node_idx =
345359
parent_or_panic(&mut traversal.tree, self.parent_node_idx);
360+
self.parent_node_size =
361+
pop_or_panic(&mut self.parent_node_size_per_depth_level);
346362
}
347363
self.current_directory_at_depth.size += file_size;
348364
*self
@@ -352,6 +368,7 @@ impl BackgroundTraversal {
352368
set_entry_info_or_panic(
353369
&mut traversal.tree,
354370
self.parent_node_idx,
371+
self.parent_node_size,
355372
self.current_directory_at_depth,
356373
);
357374
}
@@ -372,6 +389,7 @@ impl BackgroundTraversal {
372389
.tree
373390
.add_edge(self.parent_node_idx, entry_index, ());
374391
self.previous_node_idx = entry_index;
392+
self.previous_node_size = file_size;
375393
self.previous_depth = entry.depth;
376394
}
377395
Err(_) => {
@@ -406,6 +424,7 @@ impl BackgroundTraversal {
406424
set_entry_info_or_panic(
407425
&mut traversal.tree,
408426
self.parent_node_idx,
427+
self.parent_node_size,
409428
self.current_directory_at_depth,
410429
);
411430
self.parent_node_idx =
@@ -415,6 +434,7 @@ impl BackgroundTraversal {
415434
set_entry_info_or_panic(
416435
&mut traversal.tree,
417436
self.root_idx,
437+
root_size,
418438
EntryInfo {
419439
size: root_size,
420440
entries_count: (self.stats.entries_traversed > 0)

0 commit comments

Comments
 (0)