use anyhow::{Context, Result};
use std::{fs, path::PathBuf};
use crate::{PreferencesManagerError, data::UserPreferences};
pub trait PreferencesManager {
fn get_user_preferences(&self) -> Result<UserPreferences, PreferencesManagerError>;
fn set_user_preferences(
&mut self,
preferences: UserPreferences,
) -> Result<(), PreferencesManagerError>;
}
pub struct LocalPreferencesManager {
pub path: PathBuf,
}
impl LocalPreferencesManager {
fn get_user_preferences_helper(&self) -> Result<UserPreferences> {
let raw_preferences =
&fs::read_to_string(&self.path).context("failed to read user preferences")?;
let preferences = serde_json::from_str::<UserPreferences>(raw_preferences)
.context("invalid user preferences")?;
Ok(preferences)
}
fn set_user_preferences_helper(&self, preferences: &UserPreferences) -> Result<()> {
let pretty_json =
serde_json::to_string_pretty(preferences).context("invalid user preferences")?;
fs::write(&self.path, pretty_json).context("failed to write user preferences")
}
}
impl PreferencesManager for LocalPreferencesManager {
fn get_user_preferences(&self) -> Result<UserPreferences, PreferencesManagerError> {
self.get_user_preferences_helper()
.map_err(PreferencesManagerError::GetUserPreferences)
}
fn set_user_preferences(
&mut self,
preferences: UserPreferences,
) -> Result<(), PreferencesManagerError> {
self.set_user_preferences_helper(&preferences)
.map_err(PreferencesManagerError::SetUserPreferences)
}
}
#[cfg(test)]
mod tests {
use std::{fs, os::unix::fs::PermissionsExt};
use anyhow::Result;
use tempfile::tempdir;
use crate::{
USER_PREFERENCES_PATH,
data::UserPreferences,
preferences_manager::{LocalPreferencesManager, PreferencesManager},
};
#[test]
fn local_preferences_manager() -> Result<()> {
let temp_dir = tempdir().unwrap();
let path = temp_dir.path().join(USER_PREFERENCES_PATH);
let mut manager = LocalPreferencesManager { path };
let preferences = UserPreferences::default();
assert!(manager.get_user_preferences().is_err());
manager.set_user_preferences(preferences.clone())?;
assert_eq!(manager.get_user_preferences()?, preferences);
let new_preferences = UserPreferences {
ignored_paths: vec!["foo".to_string(), "bar".to_string()],
..Default::default()
};
manager.set_user_preferences(new_preferences.clone())?;
assert_eq!(manager.get_user_preferences()?, new_preferences);
Ok(())
}
#[test]
fn missing_preferences_file() {
let temp_dir = tempdir().unwrap();
let path = temp_dir.path().join(USER_PREFERENCES_PATH);
let manager = LocalPreferencesManager { path };
assert!(manager.get_user_preferences().is_err());
}
#[test]
fn unwritable_preferences_file() -> Result<()> {
let temp_dir = tempdir().unwrap();
fs::set_permissions(temp_dir.path(), fs::Permissions::from_mode(0o0))?;
let path = temp_dir.path().join(USER_PREFERENCES_PATH);
let mut manager = LocalPreferencesManager { path };
let preferences = UserPreferences::default();
assert!(manager.set_user_preferences(preferences).is_err());
Ok(())
}
}