Merge _configs/ into config/ for single configuration directory. Update all path references. Changes: - Move _configs/* to config/ - Update .gitignore for new patterns - No code references to _configs/ found Impact: -1 root directory (layout_conventions.md compliance)
152 lines
4.5 KiB
Rust
152 lines
4.5 KiB
Rust
//! XDG Base Directory support for Tools ecosystem
|
|
//!
|
|
//! Provides standard directories for tool-specific configuration and data storage.
|
|
//! Follows XDG Base Directory Specification on Linux and macOS.
|
|
//!
|
|
//! # Examples
|
|
//! ```no_run
|
|
//! use tools_shared::tool_data_dir;
|
|
//!
|
|
//! let data_dir = tool_data_dir("my-tool");
|
|
//! println!("Data directory: {}", data_dir.display());
|
|
//! // Outputs: ~/.local/share/tools/my-tool or $XDG_DATA_HOME/tools/my-tool
|
|
//! ```
|
|
|
|
use std::path::PathBuf;
|
|
|
|
/// Get XDG data directory for a tool
|
|
///
|
|
/// Returns: `$XDG_DATA_HOME/tools/{tool_name}/` or `~/.local/share/tools/{tool_name}/`
|
|
///
|
|
/// # Arguments
|
|
/// * `tool_name` - Name of the tool (e.g., "project-lifecycle")
|
|
///
|
|
/// # Panics
|
|
/// Panics if home directory cannot be determined
|
|
pub fn tool_data_dir(tool_name: &str) -> PathBuf {
|
|
dirs::data_dir()
|
|
.map(|d| d.join("tools").join(tool_name))
|
|
.unwrap_or_else(|| {
|
|
let home = std::env::var("HOME").unwrap_or_else(|_| ".".to_string());
|
|
PathBuf::from(home)
|
|
.join(".local/share/tools")
|
|
.join(tool_name)
|
|
})
|
|
}
|
|
|
|
/// Get XDG config directory for a tool
|
|
///
|
|
/// Returns: `$XDG_CONFIG_HOME/tools/{tool_name}/` or `~/.config/tools/{tool_name}/`
|
|
///
|
|
/// # Arguments
|
|
/// * `tool_name` - Name of the tool (e.g., "project-lifecycle")
|
|
///
|
|
/// # Panics
|
|
/// Panics if home directory cannot be determined
|
|
pub fn tool_config_dir(tool_name: &str) -> PathBuf {
|
|
dirs::config_dir()
|
|
.map(|d| d.join("tools").join(tool_name))
|
|
.unwrap_or_else(|| {
|
|
let home = std::env::var("HOME").unwrap_or_else(|_| ".".to_string());
|
|
PathBuf::from(home).join(".config/tools").join(tool_name)
|
|
})
|
|
}
|
|
|
|
/// Get XDG cache directory for a tool
|
|
///
|
|
/// Returns: `$XDG_CACHE_HOME/tools/{tool_name}/` or `~/.cache/tools/{tool_name}/`
|
|
///
|
|
/// # Arguments
|
|
/// * `tool_name` - Name of the tool (e.g., "project-lifecycle")
|
|
///
|
|
/// # Panics
|
|
/// Panics if home directory cannot be determined
|
|
pub fn tool_cache_dir(tool_name: &str) -> PathBuf {
|
|
dirs::cache_dir()
|
|
.map(|d| d.join("tools").join(tool_name))
|
|
.unwrap_or_else(|| {
|
|
let home = std::env::var("HOME").unwrap_or_else(|_| ".".to_string());
|
|
PathBuf::from(home).join(".cache/tools").join(tool_name)
|
|
})
|
|
}
|
|
|
|
/// Ensure directory exists, creating it if necessary
|
|
///
|
|
/// # Arguments
|
|
/// * `path` - Path to directory
|
|
///
|
|
/// # Errors
|
|
/// Returns error if directory cannot be created
|
|
///
|
|
/// # Examples
|
|
/// ```no_run
|
|
/// use tools_shared::{tool_data_dir, ensure_dir};
|
|
///
|
|
/// let dir = tool_data_dir("my-tool");
|
|
/// ensure_dir(&dir).expect("Failed to create directory");
|
|
/// ```
|
|
pub fn ensure_dir(path: &PathBuf) -> std::io::Result<PathBuf> {
|
|
if !path.exists() {
|
|
std::fs::create_dir_all(path)?;
|
|
}
|
|
Ok(path.clone())
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_tool_data_dir() {
|
|
let data_dir = tool_data_dir("test-tool");
|
|
assert!(data_dir.to_string_lossy().contains("test-tool"));
|
|
assert!(
|
|
data_dir.to_string_lossy().contains("tools")
|
|
|| data_dir.to_string_lossy().contains(".local")
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_tool_config_dir() {
|
|
let config_dir = tool_config_dir("test-tool");
|
|
assert!(config_dir.to_string_lossy().contains("test-tool"));
|
|
assert!(
|
|
config_dir.to_string_lossy().contains("tools")
|
|
|| config_dir.to_string_lossy().contains(".config")
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_tool_cache_dir() {
|
|
let cache_dir = tool_cache_dir("test-tool");
|
|
assert!(cache_dir.to_string_lossy().contains("test-tool"));
|
|
assert!(
|
|
cache_dir.to_string_lossy().contains("tools")
|
|
|| cache_dir.to_string_lossy().contains(".cache")
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_ensure_dir_creates_directory() {
|
|
use tempfile::TempDir;
|
|
|
|
let temp = TempDir::new().expect("Failed to create temp dir");
|
|
let test_dir = temp.path().join("test").join("nested").join("dir");
|
|
|
|
ensure_dir(&test_dir).expect("Failed to ensure dir");
|
|
assert!(test_dir.exists());
|
|
}
|
|
|
|
#[test]
|
|
fn test_ensure_dir_existing() {
|
|
use tempfile::TempDir;
|
|
|
|
let temp = TempDir::new().expect("Failed to create temp dir");
|
|
let test_dir = temp.path().join("test");
|
|
|
|
std::fs::create_dir(&test_dir).expect("Failed to create dir");
|
|
ensure_dir(&test_dir).expect("Failed to ensure dir");
|
|
assert!(test_dir.exists());
|
|
}
|
|
}
|