summaryrefslogtreecommitdiff
path: root/alacritty/src/config/monitor.rs
diff options
context:
space:
mode:
authorChristian Duerr <contact@christianduerr.com>2024-07-21 10:49:47 +0200
committerGitHub <noreply@github.com>2024-07-21 11:49:47 +0300
commit6bd1674bd80e73df0d41e4342ad4e34bb7d04f84 (patch)
treef7f176d2dd1c4a09973e7c1f026761a15fa50813 /alacritty/src/config/monitor.rs
parentc3075f189c2d8148c70a82f176565ea8e420b49f (diff)
downloadalacritty-6bd1674bd80e73df0d41e4342ad4e34bb7d04f84.tar.gz
alacritty-6bd1674bd80e73df0d41e4342ad4e34bb7d04f84.zip
Restart config monitor on import change
This patch checks the hash of the import paths on every config change and restarts the config monitor whenever the current monitor's hash diverges from the updated config's list of imports. Closes #7981.
Diffstat (limited to 'alacritty/src/config/monitor.rs')
-rw-r--r--alacritty/src/config/monitor.rs37
1 files changed, 36 insertions, 1 deletions
diff --git a/alacritty/src/config/monitor.rs b/alacritty/src/config/monitor.rs
index 53cff1c9..3f73f120 100644
--- a/alacritty/src/config/monitor.rs
+++ b/alacritty/src/config/monitor.rs
@@ -1,3 +1,5 @@
+use std::collections::hash_map::DefaultHasher;
+use std::hash::{Hash, Hasher};
use std::path::PathBuf;
use std::sync::mpsc::{self, RecvTimeoutError, Sender};
use std::thread::JoinHandle;
@@ -23,6 +25,7 @@ const FALLBACK_POLLING_TIMEOUT: Duration = Duration::from_secs(1);
pub struct ConfigMonitor {
thread: JoinHandle<()>,
shutdown_tx: Sender<Result<NotifyEvent, NotifyError>>,
+ watched_hash: Option<u64>,
}
impl ConfigMonitor {
@@ -32,6 +35,9 @@ impl ConfigMonitor {
return None;
}
+ // Calculate the hash for the unmodified list of paths.
+ let watched_hash = Self::hash_paths(&paths);
+
// Exclude char devices like `/dev/null`, sockets, and so on, by checking that file type is
// a regular file.
paths.retain(|path| {
@@ -139,7 +145,7 @@ impl ConfigMonitor {
}
});
- Some(Self { thread: join_handle, shutdown_tx: tx })
+ Some(Self { watched_hash, thread: join_handle, shutdown_tx: tx })
}
/// Synchronously shut down the monitor.
@@ -154,4 +160,33 @@ impl ConfigMonitor {
warn!("config monitor shutdown failed: {err:?}");
}
}
+
+ /// Check if the config monitor needs to be restarted.
+ ///
+ /// This checks the supplied list of files against the monitored files to determine if a
+ /// restart is necessary.
+ pub fn needs_restart(&self, files: &[PathBuf]) -> bool {
+ Self::hash_paths(files).map_or(true, |hash| Some(hash) == self.watched_hash)
+ }
+
+ /// Generate the hash for a list of paths.
+ fn hash_paths(files: &[PathBuf]) -> Option<u64> {
+ // Use file count limit to avoid allocations.
+ const MAX_PATHS: usize = 1024;
+ if files.len() > MAX_PATHS {
+ return None;
+ }
+
+ // Sort files to avoid restart on order change.
+ let mut sorted_files = [None; MAX_PATHS];
+ for (i, file) in files.iter().enumerate() {
+ sorted_files[i] = Some(file);
+ }
+ sorted_files.sort_unstable();
+
+ // Calculate hash for the paths, regardless of order.
+ let mut hasher = DefaultHasher::new();
+ Hash::hash_slice(&sorted_files, &mut hasher);
+ Some(hasher.finish())
+ }
}