use crate::{cache::SourceCache, error::CacheError};
use rattler_build_networking::BaseClient;
use std::path::{Path, PathBuf};
pub struct SourceCacheBuilder {
cache_dir: Option<PathBuf>,
client: Option<BaseClient>,
enable_compression: bool,
max_concurrent_downloads: usize,
progress_handler: Option<Box<dyn ProgressHandler>>,
}
pub trait ProgressHandler: Send + Sync {
fn on_download_start(&self, url: &str, total_size: Option<u64>);
fn on_download_progress(&self, url: &str, downloaded: u64, total: Option<u64>);
fn on_download_complete(&self, url: &str);
fn on_extraction_start(&self, path: &Path);
fn on_extraction_complete(&self, path: &Path);
}
impl Default for SourceCacheBuilder {
fn default() -> Self {
Self {
cache_dir: None,
client: None,
enable_compression: true,
max_concurrent_downloads: 4,
progress_handler: None,
}
}
}
impl SourceCacheBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn cache_dir<P: Into<PathBuf>>(mut self, dir: P) -> Self {
self.cache_dir = Some(dir.into());
self
}
pub fn client(mut self, client: BaseClient) -> Self {
self.client = Some(client);
self
}
pub fn enable_compression(mut self, enable: bool) -> Self {
self.enable_compression = enable;
self
}
pub fn max_concurrent_downloads(mut self, max: usize) -> Self {
self.max_concurrent_downloads = max.max(1);
self
}
pub fn progress_handler<H: ProgressHandler + 'static>(mut self, handler: H) -> Self {
self.progress_handler = Some(Box::new(handler));
self
}
pub async fn build(self) -> Result<SourceCache, CacheError> {
let cache_dir = self.cache_dir.unwrap_or_else(|| {
dirs::cache_dir()
.unwrap_or_else(|| PathBuf::from(".cache"))
.join("rattler-build")
.join("source-cache")
});
if !cache_dir.exists() {
fs_err::tokio::create_dir_all(&cache_dir).await?;
}
let client = self
.client
.unwrap_or_else(|| BaseClient::builder().timeout(300).build());
SourceCache::new(cache_dir, client, self.progress_handler).await
}
}
pub(crate) mod dirs {
use std::path::PathBuf;
pub fn cache_dir() -> Option<PathBuf> {
#[cfg(target_os = "macos")]
{
std::env::var("HOME")
.ok()
.map(|home| PathBuf::from(home).join("Library").join("Caches"))
}
#[cfg(target_os = "linux")]
{
std::env::var("XDG_CACHE_HOME")
.ok()
.map(PathBuf::from)
.or_else(|| {
std::env::var("HOME")
.ok()
.map(|home| PathBuf::from(home).join(".cache"))
})
}
#[cfg(target_os = "windows")]
{
std::env::var("LOCALAPPDATA").ok().map(PathBuf::from)
}
#[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "windows")))]
{
None
}
}
}