use crate::error::Result;
use anyhow::Context;
use std::path::{Path, PathBuf};
pub fn get_absolute_path<P: AsRef<Path>>(path: P) -> Result<PathBuf> {
let path = path.as_ref();
std::fs::canonicalize(path).with_context(|| format!("无法解析路径: {:?}", path))
}
pub fn get_home_dir() -> Result<PathBuf> {
dirs::home_dir().context("无法获取用户主目录")
}
pub fn is_file_exists<P: AsRef<Path>>(path: P) -> bool {
path.as_ref().is_file()
}
pub fn cache_dir(app_name: &str) -> Result<PathBuf> {
let base = if cfg!(target_os = "macos") {
dirs::home_dir()
.map(|h| h.join("Library").join("Caches"))
.context("无法获取 macOS 缓存目录")
} else if cfg!(target_os = "windows") {
std::env::var("LOCALAPPDATA")
.map(PathBuf::from)
.or_else(|_| {
dirs::home_dir()
.map(|h| h.join("AppData").join("Local"))
.ok_or(std::env::VarError::NotPresent)
})
.map(|p| p.join(app_name).join("cache"))
.context("无法获取 Windows 缓存目录")
} else {
std::env::var("XDG_CACHE_HOME")
.map(PathBuf::from)
.or_else(|_| {
dirs::home_dir()
.map(|h| h.join(".cache"))
.ok_or(std::env::VarError::NotPresent)
})
.context("无法获取缓存目录")
}?;
let dir = if cfg!(target_os = "macos") || cfg!(not(target_os = "windows")) {
base.join(app_name)
} else {
base
};
std::fs::create_dir_all(&dir).with_context(|| format!("创建缓存目录失败: {:?}", dir))?;
Ok(dir)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_get_home_dir() {
let home = get_home_dir().expect("home dir 应可解析");
assert!(home.is_absolute());
assert!(home.exists());
}
#[test]
fn test_get_absolute_path_preserves_suffix() {
let me = concat!(env!("CARGO_MANIFEST_DIR"), "/src/path.rs");
let abs = get_absolute_path(me).expect("当前文件应存在且可解析");
assert!(abs.ends_with("path.rs"));
}
#[test]
fn test_is_file_exists() {
let me = concat!(env!("CARGO_MANIFEST_DIR"), "/src/path.rs");
assert!(is_file_exists(me));
assert!(!is_file_exists("/nonexistent/definitely/missing"));
}
}