diskforge_core/
scanner.rs1use std::path::{Path, PathBuf};
2
3use anyhow::Result;
4use rayon::prelude::*;
5
6use crate::disk;
7use crate::rules::{android, dev_artifacts, docker, known_paths, simulator, user_rules};
8use crate::sizing;
9use crate::types::ScanResult;
10
11pub struct ScanOptions {
13 pub min_size: u64,
15 pub older_than: Option<u64>,
17 pub project_dirs: Vec<PathBuf>,
19}
20
21impl Default for ScanOptions {
22 fn default() -> Self {
23 let home = std::env::var("HOME").unwrap_or_else(|_| "/Users".into());
24 Self {
25 min_size: 1024 * 1024, older_than: None,
27 project_dirs: vec![PathBuf::from(&home)],
28 }
29 }
30}
31
32pub fn scan(options: &ScanOptions) -> Result<ScanResult> {
34 let home = std::env::var("HOME")?;
35 let home_path = Path::new(&home);
36
37 let disk_info = disk::get_disk_info(home_path)?;
39
40 let mut items = Vec::new();
41
42 let rules = known_paths::all_known_path_rules(&home);
44 let known_items: Vec<_> = rules
45 .into_par_iter()
46 .filter(|rule| rule.path.exists())
47 .filter_map(|rule| {
48 let stats = sizing::dir_stats(&rule.path);
49 if stats.size >= options.min_size {
50 Some(rule.into_item_with_stats(stats.size, stats.last_modified))
51 } else {
52 None
53 }
54 })
55 .collect();
56 items.extend(known_items);
57
58 for project_dir in &options.project_dirs {
60 if project_dir.exists() {
61 let dev_items = dev_artifacts::scan_dev_artifacts(project_dir);
62 items.extend(dev_items);
63 }
64 }
65
66 items.extend(simulator::scan_simulators(&home));
68
69 items.extend(android::scan_android(&home));
71
72 items.extend(docker::scan_docker(&home));
74
75 items.extend(user_rules::scan_user_rules(&home));
77
78 if let Some(older_than_secs) = options.older_than {
80 let now = std::time::SystemTime::now();
81 items.retain(|item| {
82 item.last_modified
83 .and_then(|lm| now.duration_since(lm).ok())
84 .is_some_and(|age| age.as_secs() >= older_than_secs)
85 });
86 }
87
88 let mut result = ScanResult {
89 items,
90 disk_total: disk_info.total,
91 disk_used: disk_info.used,
92 disk_free: disk_info.free,
93 };
94
95 result.sort_by_size();
96 Ok(result)
97}