use crate::errors::{ConfGuardContext, ConfGuardError, ConfGuardResult};
use std::fs;
use std::path::{Path, PathBuf};
pub fn to_home_based(path: &Path) -> ConfGuardResult<String> {
if !path.is_absolute() {
return Err(ConfGuardError::PathNotAbsolute(path.to_path_buf()));
}
let home_dir = dirs::home_dir().ok_or(ConfGuardError::CannotDetermineHome)?;
let home_dir_str = home_dir
.to_str()
.ok_or_else(|| ConfGuardError::InvalidUtf8Path(home_dir.clone()))?;
let path_str = path.display().to_string();
let relative_path = path_str.replace(home_dir_str, "$HOME");
Ok(relative_path)
}
pub fn from_home_based(path: &str) -> ConfGuardResult<PathBuf> {
let home_dir = dirs::home_dir().ok_or(ConfGuardError::CannotDetermineHome)?;
let home_dir_str = home_dir
.to_str()
.ok_or_else(|| ConfGuardError::InvalidUtf8Path(home_dir.clone()))?;
let path = path.replace("$HOME", home_dir_str);
let path = PathBuf::from(&path);
fs::canonicalize(&path).with_context(|| format!("canonicalize path: {:?}", path))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_to_home_based_with_home_directory() {
let home = dirs::home_dir().unwrap();
let path = home.join("Documents/test.txt");
let result = to_home_based(&path).unwrap();
assert_eq!(result, "$HOME/Documents/test.txt");
}
#[test]
fn test_to_home_based_with_relative_directory() {
let path = Path::new("relative/Documents/test.txt");
let result = to_home_based(path);
assert!(result.is_err());
}
#[test]
fn test_to_home_based_without_home_directory() {
let path = Path::new("/etc/config/settings.txt");
let result = to_home_based(path).unwrap();
assert_eq!(result, "/etc/config/settings.txt");
}
#[test]
fn test_to_home_based_with_invalid_path() {
let path = Path::new("/invalid_path");
let result = to_home_based(path).unwrap();
assert_eq!(result, "/invalid_path");
}
#[test]
fn test_from_home_based() {
let result = from_home_based("$HOME");
if let Ok(path) = result {
assert!(path.is_absolute());
assert_eq!(path, dirs::home_dir().unwrap());
}
}
}