aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/mozart/src/commands/clear_cache.rs
blob: 0740c85c952b228ce6c7e93fac74b96aa5d3727d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use clap::Args;
use mozart_registry::cache::{Cache, build_cache_config};

#[derive(Args)]
pub struct ClearCacheArgs {
    /// Only run garbage collection, not a full cache clear
    #[arg(long)]
    pub gc: bool,
}

pub async fn execute(
    args: &ClearCacheArgs,
    cli: &super::Cli,
    console: &mozart_core::console::Console,
) -> anyhow::Result<()> {
    let config = build_cache_config(cli.no_cache);

    // Build the list of (key, path) pairs to process.
    // cache-dir is only included in full clear mode, not GC mode.
    let mut cache_paths = vec![
        ("cache-vcs-dir", &config.cache_vcs_dir),
        ("cache-repo-dir", &config.cache_repo_dir),
        ("cache-files-dir", &config.cache_files_dir),
    ];
    if !args.gc {
        cache_paths.push(("cache-dir", &config.cache_dir));
    }

    for (key, path) in &cache_paths {
        // Non-existent directory: skip with informational message
        if !path.exists() {
            console.info(&format!(
                "Cache directory does not exist ({key}): {}",
                path.display()
            ));
            continue;
        }

        // Read-only guard: skip with informational message
        if config.read_only {
            console.info(&format!("Cache is not enabled ({key}): {}", path.display()));
            continue;
        }

        if args.gc {
            console.info(&format!(
                "Garbage-collecting cache ({key}): {}",
                path.display()
            ));
            let cache = Cache::new((*path).clone(), !config.no_cache);
            let result = match *key {
                "cache-files-dir" => cache.gc(config.cache_files_ttl, config.cache_files_maxsize),
                "cache-vcs-dir" => cache.gc_vcs(config.cache_ttl),
                // cache-repo-dir: 1 GB cap (matches Composer)
                _ => cache.gc(config.cache_ttl, 1024 * 1024 * 1024),
            };
            if let Err(e) = result {
                console.error(&format!("Error during GC of {key}: {e}"));
            }
        } else {
            console.info(&format!("Clearing cache ({key}): {}", path.display()));
            if *key == "cache-dir" {
                // Clear anything at the root that isn't covered by sub-caches
                let result = (|| -> anyhow::Result<()> {
                    for entry in std::fs::read_dir(path)? {
                        let entry = entry?;
                        let entry_path = entry.path();
                        // Skip repo/files/vcs subdirs (cleared by their own iterations)
                        if entry_path == config.cache_files_dir
                            || entry_path == config.cache_repo_dir
                            || entry_path == config.cache_vcs_dir
                        {
                            continue;
                        }
                        if entry_path.is_file() {
                            std::fs::remove_file(&entry_path)?;
                        } else if entry_path.is_dir() {
                            std::fs::remove_dir_all(&entry_path)?;
                        }
                    }
                    Ok(())
                })();
                if let Err(e) = result {
                    console.error(&format!("Error clearing {key}: {e}"));
                }
            } else {
                let cache = Cache::new((*path).clone(), !config.no_cache);
                if let Err(e) = cache.clear() {
                    console.error(&format!("Error clearing {key}: {e}"));
                }
            }
        }
    }

    if args.gc {
        console.info("All caches garbage-collected.");
    } else {
        console.info("All caches cleared.");
    }

    Ok(())
}