use anyhow::Result;
use std::fs;
use std::path::{Path, PathBuf};
pub fn get_system_storage_dir() -> Result<PathBuf> {
let base_dir = if cfg!(target_os = "macos") {
dirs::home_dir()
.ok_or_else(|| anyhow::anyhow!("Unable to determine home directory"))?
.join(".local")
.join("share")
.join("octocode")
} else if cfg!(target_os = "windows") {
dirs::data_dir()
.ok_or_else(|| anyhow::anyhow!("Unable to determine data directory"))?
.join("octocode")
} else {
if let Ok(xdg_data_home) = std::env::var("XDG_DATA_HOME") {
PathBuf::from(xdg_data_home).join("octocode")
} else {
dirs::home_dir()
.ok_or_else(|| anyhow::anyhow!("Unable to determine home directory"))?
.join(".local")
.join("share")
.join("octocode")
}
};
if !base_dir.exists() {
fs::create_dir_all(&base_dir)?;
}
Ok(base_dir)
}
pub fn get_project_identifier(project_path: &Path) -> Result<String> {
Ok(octolib::utils::path_to_id(project_path))
}
pub fn get_project_storage_path(project_path: &Path) -> Result<PathBuf> {
let system_dir = get_system_storage_dir()?;
let project_id = get_project_identifier(project_path)?;
Ok(system_dir.join(project_id))
}
pub fn get_project_database_path(project_path: &Path) -> Result<PathBuf> {
let project_storage = get_project_storage_path(project_path)?;
Ok(project_storage.join("storage"))
}
pub fn get_branches_dir(project_path: &Path) -> Result<PathBuf> {
let project_storage = get_project_storage_path(project_path)?;
Ok(project_storage.join("branches"))
}
pub fn get_branch_dir(project_path: &Path, branch_name: &str) -> Result<PathBuf> {
let branches_dir = get_branches_dir(project_path)?;
let sanitized = crate::indexer::branch::sanitize_branch_name(branch_name);
Ok(branches_dir.join(sanitized))
}
pub fn get_branch_database_path(project_path: &Path, branch_name: &str) -> Result<PathBuf> {
let branch_dir = get_branch_dir(project_path, branch_name)?;
Ok(branch_dir.join("storage"))
}
pub fn get_project_config_path(project_path: &Path) -> Result<PathBuf> {
Ok(project_path.join(".octocode"))
}
pub fn get_fastembed_cache_dir() -> Result<PathBuf> {
let cache_dir = get_system_storage_dir()?.join("fastembed");
if !cache_dir.exists() {
fs::create_dir_all(&cache_dir)?;
}
Ok(cache_dir)
}
pub fn get_huggingface_cache_dir() -> Result<PathBuf> {
let cache_dir = get_system_storage_dir()?.join("sentencetransformer");
if !cache_dir.exists() {
fs::create_dir_all(&cache_dir)?;
}
Ok(cache_dir)
}
pub fn ensure_project_storage_exists(project_path: &Path) -> Result<PathBuf> {
let storage_path = get_project_storage_path(project_path)?;
if !storage_path.exists() {
fs::create_dir_all(&storage_path)?;
}
Ok(storage_path)
}
#[cfg(test)]
mod tests {
use super::*;
use std::env;
#[test]
fn test_project_identifier() {
let temp_dir = env::temp_dir().join("test_octocode");
let _ = fs::create_dir_all(&temp_dir);
let id1 = get_project_identifier(&temp_dir).expect("Should get project identifier");
let id2 =
get_project_identifier(&temp_dir).expect("Should get consistent project identifier");
assert_eq!(id1, id2);
assert_eq!(id1.len(), 16);
let _ = fs::remove_dir_all(&temp_dir);
}
#[test]
fn test_system_storage_dir() {
let storage_dir = get_system_storage_dir().expect("Should get system storage directory");
assert!(storage_dir.to_string_lossy().contains("octocode"));
assert!(storage_dir.is_absolute());
}
#[test]
fn test_fastembed_cache_dir() {
let fastembed_cache =
get_fastembed_cache_dir().expect("Should get fastembed cache directory");
assert!(fastembed_cache.to_string_lossy().contains("octocode"));
assert!(fastembed_cache.to_string_lossy().contains("fastembed"));
assert!(fastembed_cache.is_absolute());
let storage_dir = get_system_storage_dir().expect("Should get system storage directory");
assert!(fastembed_cache.starts_with(&storage_dir));
assert_eq!(fastembed_cache, storage_dir.join("fastembed"));
}
#[test]
fn test_sentencetransformer_cache_dir() {
let st_cache = get_huggingface_cache_dir().expect("Should get huggingface cache directory");
assert!(st_cache.to_string_lossy().contains("octocode"));
assert!(st_cache.to_string_lossy().contains("sentencetransformer"));
assert!(st_cache.is_absolute());
let storage_dir = get_system_storage_dir().expect("Should get system storage directory");
assert!(st_cache.starts_with(&storage_dir));
assert_eq!(st_cache, storage_dir.join("sentencetransformer"));
}
}