rwasm/rsw-rs

Watch mode in windows doesn't refresh

garlandcrow opened this issue · 8 comments

I can use this on linux, but tried working on windows today and the watch mode doesn't see file changes. This has happened before with some "watch" libraries I've used where they don't see updates from windows filesystem so maybe an issue for the underlying thing rsw uses for getting the events for a file changing.

lencx commented

It may be caused by this rwasm/vite-plugin-rsw#33
Please use cargo to install:

cargo install rsw

Yea I noticed that before and install rsw with cargo. RSW starts fine when I run "rsw watch" and says it's watching the correct folder, it just doesn't actually react to any file changes. I'm sure it's likely something with notify events.

lencx commented

Can you provide a screenshot of rsw watch?

  • syetem version: ?
  • vite-plugin-rsw version: ?

tracer is the where the folder created using rsw new and added to the rsw.toml folder. My system is:

  • Microsoft Windows [Version 10.0.22000.795]
  • node 16.16.0
  • npm 8.14.0
  • rustc 1.61.0-nightly (458262b13 2022-03-09)
  • rsw v0.7.10

Screenshot 2022-07-20 130318

It all looks right to me, but saving any rust file in the folder doesn't trigger any rebuild on the rsw side. The same rsw.toml config is working on mac.

lencx commented

The problem you are currently having is that the rust file changes are not triggering the build, I would like to see the output log. Could you try executing RUST_LOG=rsw rsw watch and provide a screenshot? I don't have a windows platform right now to verify this. But as far as I understand window is executable. Or download the source code locally, build it, and debug the src/core/watch.rs file.

[rsw::DEBUG] rsw::core::watch NoticeWrite()
[rsw::DEBUG] rsw::core::watch Write()

rsw-watch

Ok ran that w/ the debug flag and I don't get those 2 rsw::DEBUG lines, so I'll build locally later and dive into the code a bit and let you know
Screenshot 2022-07-23 011322
.

Tested the code on windows and found the source of the issue. The way paths are handling fail with the regex match.

Can't do PRs right now, but adding a diff to potential fixes. Also took the liberty of cleaning up path usage a bit.

diff --git a/src/core/watch.rs b/src/core/watch.rs
index f3b968a..a41006b 100644
--- a/src/core/watch.rs
+++ b/src/core/watch.rs
@@ -3,7 +3,6 @@
 use ignore::gitignore::Gitignore;
 use notify::{DebouncedEvent::*, RecursiveMode::*, Watcher};
 use path_clean::PathClean;
-use regex::Regex;
 use std::{
     collections::HashMap, path::PathBuf, sync::mpsc::channel, sync::Arc, thread::sleep,
     time::Duration,
@@ -32,7 +31,8 @@ impl Watch {
         let mut crate_map = HashMap::new();
         let mut path_map = HashMap::new();
         let (tx, rx) = channel();
-        let root = format!("{}/", get_root().to_string_lossy().to_string());
+        // Keep the root as a path instead
+        let cwd = get_root();
 
         let mut watcher = match notify::watcher(tx, Duration::from_secs(1)) {
             Ok(w) => w,
@@ -44,7 +44,17 @@ impl Watch {
 
         for i in &config.crates {
             // TODO: local deps watch
-            let crate_root = PathBuf::from(i.root.as_ref().unwrap()).join(&i.name);
+
+            // Make sure the crate root path is absolute
+            let crate_root = {
+                let cr = PathBuf::from(i.root.as_deref().unwrap()).join(&i.name);
+                if cr.is_relative() {
+                    cwd.to_owned().join(cr)
+                } else {
+                    cwd.to_owned()
+                }
+            };
+
             let _ = watcher.watch(crate_root.join("src"), Recursive);
             let _ = watcher.watch(crate_root.join("Cargo.toml"), NonRecursive);
 
@@ -72,50 +82,52 @@ impl Watch {
 
                 match event {
                     Write(path) | Remove(path) | Rename(_, path) => {
-                        let path = Arc::new(path);
-
-                        let path2 = path.to_string_lossy().to_string();
-                        let project_path_split = path2.split(&root);
-                        let project_path = project_path_split.collect::<Vec<&str>>().join("");
-
-                        if gitignore.matched(project_path, false).is_ignore() {
+                        // Simplify gitignore matching code
+                        // strip_prefix is simpler to use
+                        let project_path = match path.strip_prefix(&cwd) {
+                            Ok(p) => p,
+                            Err(_) => continue,
+                        };
+
+                        if gitignore.matched(&project_path, false).is_ignore() {
                             continue;
                         }
 
                         for (key, val) in &path_map {
-                            if Regex::new(val.to_str().unwrap())
-                                .unwrap()
-                                .is_match(path.to_owned().to_str().unwrap())
-                            {
-                                let crate_config = (*crate_map.get(key).unwrap()).clone();
-                                print(RswInfo::CrateChange(path.clone().to_path_buf()));
-
-                                if let Some(join_handle) = build_task_join_handle {
-                                    debug!("abort building task");
-                                    join_handle.abort();
-                                }
+                            // Use starts_with instead of regex comparing strings
+                            // This way we avoid potential issues with extra slashes
+                            if !path.starts_with(val) {
+                                continue;
+                            }
+
+                            let crate_config = (*crate_map.get(key).unwrap()).clone();
+                            print(RswInfo::CrateChange(path.clone().to_path_buf()));
 
-                                let config = config.clone();
-                                let caller = caller.clone();
-                                let path = path.clone();
-                                let join_handle = tokio::spawn(async move {
-                                    let is_ok = Build::new(
-                                        crate_config.clone(),
-                                        "watch",
-                                        config.cli.to_owned().unwrap(),
-                                        false,
-                                    )
-                                    .init();
-
-                                    if is_ok {
-                                        caller(&crate_config, path.clone().to_path_buf());
-                                    }
-                                });
-
-                                build_task_join_handle = Some(join_handle);
-
-                                break;
+                            if let Some(join_handle) = build_task_join_handle {
+                                debug!("abort building task");
+                                join_handle.abort();
                             }
+
+                            let config = config.clone();
+                            let caller = caller.clone();
+                            let path = path.clone();
+                            let join_handle = tokio::spawn(async move {
+                                let is_ok = Build::new(
+                                    crate_config.clone(),
+                                    "watch",
+                                    config.cli.to_owned().unwrap(),
+                                    false,
+                                )
+                                .init();
+
+                                if is_ok {
+                                    caller(&crate_config, path.clone());
+                                }
+                            });
+
+                            build_task_join_handle = Some(join_handle);
+
+                            break;
                         }
                     }
                     _ => (),
lencx commented

@flaxed Thanks, I have adopted your suggestion in v0.7.11.