<h1>
<a href="https://prefix.dev/tools/rattler-build">
<img alt="banner" src="https://github.com/user-attachments/assets/456f8ef1-1c7b-463d-ad88-de3496b05db2">
</a>
</h1>
# rattler_build_source_cache
A unified source cache for Rattler-Build that handles Git repositories, URL downloads, and local paths with proper caching, extraction, and concurrent access control.
## Features
- **Unified Cache**: Single interface for Git, URL, and Path sources
- **Content-Addressable Storage**: Sources are indexed by content hash for deduplication
- **Concurrent Access Control**: File locking ensures safe concurrent access from multiple processes
- **Automatic Extraction**: Archives (.tar.gz, .zip, .7z, etc.) are automatically extracted
- **Cache Management**: Automatic cleanup of old entries, configurable TTL
- **Progress Tracking**: Optional progress callbacks for downloads and extractions
- **Checksum Validation**: SHA256 and MD5 checksum support for URL downloads
## Usage
```rust
use rattler_build_source_cache::{SourceCacheBuilder, Source, UrlSource, GitSource, GitReference, Checksum};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create a cache with custom configuration
let cache = SourceCacheBuilder::new()
.cache_dir("/path/to/cache")
.max_age(chrono::Duration::days(30))
.enable_cleanup(true)
.cleanup_interval(std::time::Duration::from_secs(3600))
.build()
.await?;
// Fetch a URL source
let url_source = Source::Url(UrlSource {
urls: vec!["https://example.com/archive.tar.gz".parse()?],
checksum: Some(Checksum::Sha256(vec![/* hash bytes */])),
file_name: None, // Will auto-extract
});
let path = cache.get_source(&url_source).await?;
println!("Source cached at: {}", path.display());
// Fetch a Git repository
use rattler_build_source_cache::GitReference;
let git_source = Source::Git(GitSource::new(
"https://github.com/example/repo".parse()?,
GitReference::Branch("main".to_string()),
Some(1),
false,
true,
));
let repo_path = cache.get_source(&git_source).await?;
println!("Repository cloned at: {}", repo_path.display());
// Path sources are passed through without caching
let path_source = Source::Path("/local/path".into());
let local_path = cache.get_source(&path_source).await?;
assert_eq!(local_path, std::path::Path::new("/local/path"));
Ok(())
}
```
## Cache Structure
The cache directory is organized as follows:
```
cache_dir/
├── .metadata/ # JSON metadata files for each cache entry
│ ├── <hash>.json
│ └── ...
├── .locks/ # Lock files for concurrent access control
│ ├── <hash>.lock
│ └── ...
├── <hash>_file.tar.gz # Downloaded archives
├── <hash>_extracted/ # Extracted archive contents
└── git_<hash>/ # Cloned git repositories
```
## Configuration
The `SourceCacheBuilder` provides various configuration options:
- `cache_dir`: Location of the cache directory (defaults to system cache dir)
- `client`: Custom HTTP client for downloads
- `max_age`: Maximum age before entries are considered stale
- `enable_cleanup`: Enable automatic cleanup of old entries
- `cleanup_interval`: How often to run cleanup
- `enable_compression`: Whether to compress cached files (future feature)
- `max_concurrent_downloads`: Limit concurrent downloads
- `progress_handler`: Custom progress reporting
## Thread Safety
The cache is designed for safe concurrent access:
- File locks prevent multiple processes from modifying the same cache entry
- The index uses async RwLock for thread-safe in-memory access
- Lock files are automatically cleaned up when guards are dropped
## License
BSD-3-Clause