fn main() {
for root in std::env::args().skip(1) {
let p = std::path::Path::new(&root);
let ignore = filesnap::load_ignore(p);
let report = |label: &str, files: &[std::path::PathBuf], elapsed: std::time::Duration| {
let bytes: u64 = files
.iter()
.filter_map(|f| std::fs::metadata(f).ok())
.map(|m| m.len())
.sum();
println!(
" {label:<16} {:>7} files {:>9.1} MB {elapsed:?}",
files.len(),
bytes as f64 / 1_048_576.0
);
};
println!("{root}");
let t = std::time::Instant::now();
let all = subtree_walk(p);
report("subtree walk", &all, t.elapsed());
let t = std::time::Instant::now();
let git = filesnap::git_tracked_files(p, &ignore);
report("git-tracked", &git, t.elapsed());
let covered: std::collections::BTreeSet<_> = git.iter().cloned().collect();
let t = std::time::Instant::now();
let recent = filesnap::recent_files(
p,
&ignore,
filesnap::HiddenFiles::Skip,
&covered,
filesnap::ScanLimits::default(),
);
report("recent (residue)", &recent.files, t.elapsed());
let blind = filesnap::recent_files(
p,
&ignore,
filesnap::HiddenFiles::Skip,
&std::collections::BTreeSet::new(),
filesnap::ScanLimits::default(),
);
let wasted = blind.files.iter().filter(|f| covered.contains(*f)).count();
println!(
" {:<16} {wasted:>7} of {} slots would go to files git already covers",
"without it:",
blind.files.len()
);
}
}
fn subtree_walk(root: &std::path::Path) -> Vec<std::path::PathBuf> {
fn walk(dir: &std::path::Path, out: &mut Vec<std::path::PathBuf>) {
let Ok(entries) = std::fs::read_dir(dir) else {
return;
};
for entry in entries.flatten() {
if entry.file_name().to_string_lossy().starts_with('.') {
continue;
}
let path = entry.path();
if path.is_dir() {
walk(&path, out);
} else if path.is_file() {
out.push(path);
}
}
}
let mut out = Vec::new();
walk(root, &mut out);
out
}