Skip to main content

dev_sweep/cleaner/
mod.rs

1use std::fs;
2use std::path::Path;
3
4use anyhow::{Context, Result};
5
6use crate::scanner::ScannedProject;
7
8/// Result of a clean operation on a single project.
9#[derive(Debug)]
10pub struct CleanResult {
11    pub project_name: String,
12    pub targets_cleaned: usize,
13    pub bytes_freed: u64,
14    pub errors: Vec<String>,
15}
16
17/// Clean the specified targets from a project.
18///
19/// If `dry_run` is true, only reports what *would* be cleaned without deleting anything.
20pub fn clean_project(project: &ScannedProject, dry_run: bool) -> Result<CleanResult> {
21    let mut result = CleanResult {
22        project_name: project.name.clone(),
23        targets_cleaned: 0,
24        bytes_freed: 0,
25        errors: Vec::new(),
26    };
27
28    for target in &project.clean_targets {
29        if dry_run {
30            result.targets_cleaned += 1;
31            result.bytes_freed += target.size_bytes;
32            continue;
33        }
34
35        match remove_dir_all(&target.path) {
36            Ok(()) => {
37                result.targets_cleaned += 1;
38                result.bytes_freed += target.size_bytes;
39            }
40            Err(e) => {
41                result.errors.push(format!(
42                    "Failed to remove {}: {}",
43                    target.path.display(),
44                    e
45                ));
46            }
47        }
48    }
49
50    Ok(result)
51}
52
53/// Remove a directory and all its contents.
54///
55/// This is a wrapper around `fs::remove_dir_all` with better error context.
56fn remove_dir_all(path: &Path) -> Result<()> {
57    fs::remove_dir_all(path)
58        .with_context(|| format!("Failed to remove directory: {}", path.display()))?;
59    Ok(())
60}
61
62/// Clean multiple projects and return results.
63pub fn clean_projects(
64    projects: &[&ScannedProject],
65    dry_run: bool,
66) -> Vec<CleanResult> {
67    projects
68        .iter()
69        .map(|p| {
70            clean_project(p, dry_run).unwrap_or_else(|e| CleanResult {
71                project_name: p.name.clone(),
72                targets_cleaned: 0,
73                bytes_freed: 0,
74                errors: vec![e.to_string()],
75            })
76        })
77        .collect()
78}