1
Fork 0
mirror of https://github.com/RGBCube/superfreq synced 2025-07-27 17:07:44 +00:00

config: streamline hotreload; don't search in $XDG_CONFIG_HOME

This commit is contained in:
NotAShelf 2025-05-16 21:03:10 +03:00
parent 1eeb6d2d90
commit ed1aeddaed
No known key found for this signature in database
GPG key ID: 29D95B64378DB4BF
4 changed files with 64 additions and 28 deletions

View file

@ -32,22 +32,27 @@ pub fn load_config_from_path(specific_path: Option<&str>) -> Result<AppConfig, C
)));
}
// Otherwise try the standard paths
let mut config_paths: Vec<PathBuf> = Vec::new();
// User-specific path
if let Some(home_dir) = dirs::home_dir() {
let user_config_path = home_dir.join(".config/superfreq/config.toml");
config_paths.push(user_config_path);
} else {
// Check for SUPERFREQ_CONFIG environment variable
if let Ok(env_path) = std::env::var("SUPERFREQ_CONFIG") {
let env_path = Path::new(&env_path);
if env_path.exists() {
println!(
"Loading config from SUPERFREQ_CONFIG: {}",
env_path.display()
);
return load_and_parse_config(env_path);
}
eprintln!(
"Warning: Could not determine home directory. User-specific config will not be loaded."
"Warning: Config file specified by SUPERFREQ_CONFIG not found: {}",
env_path.display()
);
}
// System-wide paths
config_paths.push(PathBuf::from("/etc/xdg/superfreq/config.toml"));
config_paths.push(PathBuf::from("/etc/superfreq.toml"));
let config_paths = vec![
PathBuf::from("/etc/xdg/superfreq/config.toml"),
PathBuf::from("/etc/superfreq.toml"),
];
for path in config_paths {
if path.exists() {

View file

@ -87,8 +87,6 @@ pub struct AppConfig {
pub enum ConfigError {
IoError(std::io::Error),
TomlError(toml::de::Error),
NoValidConfigFound,
HomeDirNotFound,
ValidationError(String),
}
@ -109,8 +107,6 @@ impl std::fmt::Display for ConfigError {
match self {
Self::IoError(e) => write!(f, "I/O error: {e}"),
Self::TomlError(e) => write!(f, "TOML parsing error: {e}"),
Self::NoValidConfigFound => write!(f, "No valid configuration file found."),
Self::HomeDirNotFound => write!(f, "Could not determine user home directory."),
Self::ValidationError(s) => write!(f, "Configuration validation error: {s}"),
}
}

View file

@ -1,3 +1,4 @@
use log::{debug, error, warn};
use notify::{Config, Event, EventKind, RecommendedWatcher, RecursiveMode, Watcher};
use std::error::Error;
use std::path::Path;
@ -26,6 +27,8 @@ impl ConfigWatcher {
// Start watching the config file
watcher.watch(Path::new(config_path), RecursiveMode::NonRecursive)?;
debug!("Started watching config file: {config_path}");
Ok(Self {
rx,
_watcher: watcher,
@ -46,15 +49,34 @@ impl ConfigWatcher {
loop {
match self.rx.try_recv() {
Ok(Ok(event)) => {
// Only process write/modify events
if matches!(event.kind, EventKind::Modify(_)) {
should_reload = true;
// Process various file events that might indicate configuration changes
match event.kind {
EventKind::Modify(_) => {
debug!("Detected modification to config file: {}", self.config_path);
should_reload = true;
}
EventKind::Create(_) => {
debug!("Detected recreation of config file: {}", self.config_path);
should_reload = true;
}
EventKind::Remove(_) => {
// Some editors delete then recreate the file when saving
// Just log this event and wait for the create event
debug!(
"Detected removal of config file: {} - waiting for recreation",
self.config_path
);
}
_ => {} // Ignore other event types
}
if should_reload {
self.last_event_time = std::time::Instant::now();
}
}
Ok(Err(e)) => {
// File watcher error, log but continue
eprintln!("Error watching config file: {e}");
warn!("Error watching config file: {e}");
}
Err(TryRecvError::Empty) => {
// No more events
@ -62,7 +84,7 @@ impl ConfigWatcher {
}
Err(TryRecvError::Disconnected) => {
// Channel disconnected, watcher is dead
eprintln!("Config watcher channel disconnected");
error!("Config watcher channel disconnected");
return None;
}
}
@ -78,18 +100,31 @@ impl ConfigWatcher {
thread::sleep(debounce_time - time_since_last_event);
}
// Ensure the file exists before attempting to reload
let config_path = Path::new(&self.config_path);
if !config_path.exists() {
warn!(
"Config file does not exist after change events: {}",
self.config_path
);
return None;
}
debug!("Reloading configuration from {}", self.config_path);
// Attempt to reload the config from the specific path being watched
match load_config_from_path(Some(&self.config_path)) {
Ok(config) => Some(Ok(config)),
Err(e) => Some(Err(Box::new(e))),
Ok(config) => {
debug!("Successfully reloaded configuration");
Some(Ok(config))
}
Err(e) => {
error!("Failed to reload configuration: {e}");
Some(Err(Box::new(e)))
}
}
} else {
None
}
}
/// Get the path of the config file being watched
pub const fn config_path(&self) -> &String {
&self.config_path
}
}

View file

@ -101,7 +101,7 @@ fn main() {
Ok(cfg) => cfg,
Err(e) => {
error!("Error loading configuration: {e}. Using default values.");
// Proceed with default config if loading fails, as per previous steps
// Proceed with default config if loading fails
AppConfig::default()
}
};