use anyhow::{anyhow, Result};
use std::fs;
use std::path::{Path, PathBuf};
pub fn data_dir() -> Result<PathBuf> {
let base_dir =
dirs::data_local_dir().ok_or_else(|| anyhow!("Unable to determine data directory"))?;
Ok(base_dir.join("tcl-mcp-server"))
}
pub fn config_dir() -> Result<PathBuf> {
let base_dir =
dirs::config_dir().ok_or_else(|| anyhow!("Unable to determine config directory"))?;
Ok(base_dir.join("tcl-mcp-server"))
}
pub fn cache_dir() -> Result<PathBuf> {
let base_dir =
dirs::cache_dir().ok_or_else(|| anyhow!("Unable to determine cache directory"))?;
Ok(base_dir.join("tcl-mcp-server"))
}
pub fn ensure_dir(path: &Path) -> Result<()> {
if !path.exists() {
fs::create_dir_all(path)?;
}
Ok(())
}
pub fn tools_dir() -> Result<PathBuf> {
let data = data_dir()?;
Ok(data.join("tools"))
}
pub fn mcp_index_path() -> Result<PathBuf> {
let data = data_dir()?;
Ok(data.join("mcp-index.json"))
}
pub fn scripts_dir() -> Result<PathBuf> {
let data = data_dir()?;
Ok(data.join("scripts"))
}
pub fn init_directories() -> Result<()> {
ensure_dir(&data_dir()?)?;
ensure_dir(&config_dir()?)?;
ensure_dir(&cache_dir()?)?;
ensure_dir(&tools_dir()?)?;
ensure_dir(&scripts_dir()?)?;
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_data_dir() {
let dir = data_dir().unwrap();
assert!(dir.to_string_lossy().contains("tcl-mcp-server"));
}
#[test]
fn test_platform_specific_paths() {
let data = data_dir().unwrap();
let config = config_dir().unwrap();
let cache = cache_dir().unwrap();
if cfg!(target_os = "linux") {
let home = std::env::var("HOME").unwrap();
assert!(
data.starts_with(home.as_str()) || data.to_string_lossy().contains(".local/share")
);
assert!(
config.starts_with(home.as_str()) || config.to_string_lossy().contains(".config")
);
assert!(cache.starts_with(home.as_str()) || cache.to_string_lossy().contains(".cache"));
} else if cfg!(target_os = "macos") {
assert!(data
.to_string_lossy()
.contains("Library/Application Support"));
assert!(config.to_string_lossy().contains("Library/Preferences"));
assert!(cache.to_string_lossy().contains("Library/Caches"));
} else if cfg!(target_os = "windows") {
assert!(data.to_string_lossy().contains("AppData"));
}
}
#[test]
fn test_subdirectories() {
let tools = tools_dir().unwrap();
let scripts = scripts_dir().unwrap();
let mcp_index = mcp_index_path().unwrap();
assert!(tools.ends_with("tools"));
assert!(scripts.ends_with("scripts"));
assert!(mcp_index.file_name().unwrap() == "mcp-index.json");
}
}