62 lines
1.7 KiB
Rust

use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fs;
use std::path::{Path, PathBuf};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CacheManifest {
#[serde(default)]
pub git: HashMap<String, GitCacheEntry>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GitCacheEntry {
pub path: PathBuf,
pub resolved_ref: String,
pub fetched_at: String,
}
impl CacheManifest {
pub fn load(cache_dir: &Path) -> Result<Self> {
let manifest_path = cache_dir.join("cache.json");
if !manifest_path.exists() {
return Ok(Self {
git: HashMap::new(),
});
}
let content = fs::read_to_string(&manifest_path)?;
let manifest = serde_json::from_str(&content)?;
Ok(manifest)
}
pub fn save(&self, cache_dir: &Path) -> Result<()> {
if !cache_dir.exists() {
fs::create_dir_all(cache_dir)?;
}
let manifest_path = cache_dir.join("cache.json");
let content = serde_json::to_string_pretty(self)?;
fs::write(manifest_path, content)?;
Ok(())
}
}
pub fn get_cache_root(project_root: &Path) -> PathBuf {
project_root.join("cache")
}
pub fn get_git_worktree_path(project_root: &Path, repo_url: &str) -> PathBuf {
let cache_root = get_cache_root(project_root);
let id = normalized_repo_id(repo_url);
cache_root.join("git").join(id).join("worktree")
}
fn normalized_repo_id(url: &str) -> String {
let mut hash = 0xcbf29ce484222325;
for b in url.as_bytes() {
hash ^= *b as u64;
hash = hash.wrapping_mul(0x100000001b3);
}
format!("{:016x}", hash)
}