Skip to main content

provenant/scanner/
count.rs

1use crate::utils::file::is_path_excluded;
2use glob::Pattern;
3use std::fs;
4use std::path::Path;
5
6pub fn count_with_size<P: AsRef<Path>>(
7    path: P,
8    max_depth: usize,
9    exclude_patterns: &[Pattern],
10) -> std::io::Result<(usize, usize, usize, u64)> {
11    let depth_limit = depth_limit_from_cli(max_depth);
12    count_internal(path.as_ref(), depth_limit, exclude_patterns)
13}
14
15fn depth_limit_from_cli(max_depth: usize) -> Option<usize> {
16    if max_depth == 0 {
17        None
18    } else {
19        Some(max_depth)
20    }
21}
22
23fn count_internal(
24    path: &Path,
25    depth_limit: Option<usize>,
26    exclude_patterns: &[Pattern],
27) -> std::io::Result<(usize, usize, usize, u64)> {
28    if is_path_excluded(path, exclude_patterns) {
29        return Ok((0, 0, 1, 0));
30    }
31
32    let mut files_count = 0;
33    let mut dirs_count = 1; // Count the current directory
34    let mut excluded_count = 0;
35    let mut total_file_bytes = 0_u64;
36
37    // Process entries in current directory
38    for entry in fs::read_dir(path)? {
39        let entry = entry?;
40        let entry_path = entry.path();
41
42        if is_path_excluded(&entry_path, exclude_patterns) {
43            excluded_count += 1;
44            continue;
45        }
46
47        let metadata = entry.metadata()?;
48        if metadata.is_file() {
49            files_count += 1;
50            total_file_bytes += metadata.len();
51        } else if metadata.is_dir() {
52            dirs_count += 1;
53
54            let should_recurse = match depth_limit {
55                None => true,
56                Some(remaining_depth) => remaining_depth > 0,
57            };
58
59            if should_recurse {
60                let next_depth_limit = depth_limit.map(|remaining_depth| remaining_depth - 1);
61                let (sub_files, sub_dirs, sub_excluded, sub_bytes) =
62                    count_internal(&entry_path, next_depth_limit, exclude_patterns)?;
63
64                files_count += sub_files;
65                dirs_count += sub_dirs - 1; // Avoid double-counting this directory
66                excluded_count += sub_excluded;
67                total_file_bytes += sub_bytes;
68            }
69        }
70    }
71
72    Ok((files_count, dirs_count, excluded_count, total_file_bytes))
73}