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:
parent
1eeb6d2d90
commit
ed1aeddaed
4 changed files with 64 additions and 28 deletions
|
@ -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() {
|
||||
|
|
|
@ -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}"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue