From 6cc950eb9dd61c022a09795173aba2c2343ef3b7 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Thu, 14 Mar 2024 23:05:31 -0700 Subject: [PATCH] Fix: on embedded hotreload don't watch target directory --- packages/hot-reload/src/file_watcher.rs | 56 +++++++++++++++++++++---- 1 file changed, 49 insertions(+), 7 deletions(-) diff --git a/packages/hot-reload/src/file_watcher.rs b/packages/hot-reload/src/file_watcher.rs index aae482a69..04f5e4369 100644 --- a/packages/hot-reload/src/file_watcher.rs +++ b/packages/hot-reload/src/file_watcher.rs @@ -109,14 +109,19 @@ impl Config { } /// Initialize the hot reloading listener +/// +/// This is designed to be called by hot_reload_Init!() which will pass in information about the project +/// +/// Notes: +/// - We don't wannt to watch the pub fn init(cfg: Config) { let Config { + mut rebuild_with, root_path, listening_paths, log, - mut rebuild_with, excluded_paths, - phantom: _, + .. } = cfg; let Ok(crate_dir) = PathBuf::from_str(root_path) else { @@ -146,11 +151,13 @@ pub fn init(cfg: Config) { .is_ignore() }) .unwrap(); + for err in errors { if log { println!("hot reloading failed to initialize:\n{err:?}"); } } + let file_map = Arc::new(Mutex::new(file_map)); let target_dir = crate_dir.join("target"); @@ -221,8 +228,42 @@ pub fn init(cfg: Config) { let mut watcher = RecommendedWatcher::new(tx, notify::Config::default()).unwrap(); - for path in listening_paths { - let full_path = crate_dir.join(path); + let mut listening_pathbufs = vec![]; + + // We're attempting to watch the root path... which contains a target directory... + // And on some platforms the target directory is really really large and can cause the watcher to crash + // since it runs out of file handles + // So we're going to iterate through its children and watch them instead of the root path, skipping the target + // directory. + // + // In reality, this whole approach of doing embedded file watching is kinda hairy since you want full knowledge + // of where rust code is. We could just use the filemap we generated above as an indication of where the rust + // code is in this project and deduce the subfolders under the root path from that. + // + // FIXME: use a more robust system here for embedded discovery + // + // https://github.com/DioxusLabs/dioxus/issues/1914 + if listening_paths == &[""] { + for entry in std::fs::read_dir(&crate_dir) + .expect("failed to read rust crate directory. Are you running with cargo?") + { + let entry = entry.expect("failed to read directory entry"); + let path = entry.path(); + if path.is_dir() { + if path == target_dir { + continue; + } + listening_pathbufs.push(path); + } + } + } else { + for path in listening_paths { + let full_path = crate_dir.join(path); + listening_pathbufs.push(full_path); + } + } + + for full_path in listening_pathbufs { if let Err(err) = watcher.watch(&full_path, RecursiveMode::Recursive) { if log { println!("hot reloading failed to start watching {full_path:?}:\n{err:?}",); @@ -295,11 +336,12 @@ pub fn init(cfg: Config) { return; } // find changes to the rsx in the file - match file_map + let changes = file_map .lock() .unwrap() - .update_rsx(path, crate_dir.as_path()) - { + .update_rsx(path, crate_dir.as_path()); + + match changes { Ok(UpdateResult::UpdatedRsx(msgs)) => { for msg in msgs { let mut i = 0;