Skip to main content

zoi_core/
cache.rs

1use std::fs;
2use std::path::PathBuf;
3
4use anyhow::{Result, anyhow};
5
6/// Returns the root directory for Zoi's cache.
7///
8/// # Errors
9///
10/// Returns an error if the user's home directory cannot be determined.
11pub fn get_cache_root() -> Result<PathBuf> {
12    let home_dir = crate::utils::get_user_home()
13        .ok_or_else(|| anyhow!("Could not find home directory."))?;
14    Ok(home_dir.join(".zoi").join("cache"))
15}
16
17/// Returns the root directory for Zoi's archive cache.
18///
19/// # Errors
20///
21/// Returns an error if the cache root directory cannot be determined.
22pub fn get_archive_cache_root() -> Result<PathBuf> {
23    let cache_root = get_cache_root()?;
24    Ok(cache_root.join("archives"))
25}
26
27/// Returns the root directory for Zoi's package definition cache.
28///
29/// # Errors
30///
31/// Returns an error if the cache root directory cannot be determined.
32pub fn get_pkgdef_cache_root() -> Result<PathBuf> {
33    let cache_root = get_cache_root()?;
34    Ok(cache_root.join("pkgdefs"))
35}
36
37/// Returns a list of candidate URLs for a given URL, including configured
38/// mirrors.
39pub fn mirror_candidate_urls(url: &str) -> Vec<String> {
40    let mut urls = vec![url.to_string()];
41    let Ok(config) = crate::config::read_config() else {
42        return urls;
43    };
44
45    let Some(filename) =
46        url.split('/').next_back().filter(|part| !part.is_empty())
47    else {
48        return urls;
49    };
50
51    for mirror in config.cache_mirrors {
52        urls.push(format!("{}/{}", mirror.trim_end_matches('/'), filename));
53    }
54
55    urls
56}
57
58/// Clears the entire Zoi cache.
59///
60/// # Errors
61///
62/// Returns an error if the cache directory cannot be removed.
63pub fn clear(dry_run: bool) -> Result<()> {
64    let cache_dir = get_cache_root()?;
65    if cache_dir.exists() {
66        if dry_run {
67            println!(
68                "(Dry-run) Would remove cache directory: {}",
69                cache_dir.display()
70            );
71        } else {
72            println!("Removing cache directory: {}", cache_dir.display());
73            fs::remove_dir_all(cache_dir)?;
74        }
75    } else {
76        println!("Cache directory does not exist. Nothing to clean.");
77    }
78    Ok(())
79}
80
81/// Clears only the archive cache.
82///
83/// # Errors
84///
85/// Returns an error if the archive cache directory cannot be removed.
86pub fn clear_archives(dry_run: bool) -> Result<()> {
87    let archive_cache_dir = get_archive_cache_root()?;
88    if archive_cache_dir.exists() {
89        if dry_run {
90            println!(
91                "(Dry-run) Would remove archive cache directory: {}",
92                archive_cache_dir.display()
93            );
94        } else {
95            println!(
96                "Removing archive cache directory: {}",
97                archive_cache_dir.display()
98            );
99            fs::remove_dir_all(archive_cache_dir)?;
100        }
101    } else {
102        println!("Archive cache directory does not exist. Nothing to clean.");
103    }
104    Ok(())
105}