watchexec/cargo-watch

Cargo-watch reacts to `IsFile` event, while it should not.

wdanilo opened this issue · 10 comments

Hi, I'm using cargo-watch 8.1.1 (because 8.3.0 does not work for me). Recently, our build script, which uses cargo-watch under the hood, started looping indefinitely. After debugging it turned out, that when using std::fs::copy("a.txt", "b.txt") on macOS, a file system event IsFile is sometimes emitted on the source file ("a.txt"). The term "sometimes" is better explained here. Our build script is copying some files to target directory, which causes the sources to emit this event, which causes cargo-watch to re-run the whole operation again.

System: macOS Monterey (12.0.1), M1 pro

IsFile is a bit in the event mask, not an event type per se, similar to the IS_DIR bit in Linux. The event itself is probably a new possibly-undocumented one, so it doesn't appear in the fswatch handling, and passes through fsevents and notify to us.

This makes this bug platform version specific: it doesn't appear on Linux, and it doesn't appear on the old macbook air I have, which can't get upgraded to macOS 12.x

Fixing the issue is probably best done upstream in notify as by the time it gets handled here, it's already reduced to one of only five categories. However, cargo-watch 8.x uses watchexec 1.17, which uses notify 4.x (the latest version is 5.0.0)... but it might be possible to have a patch release made for that release branch. Ask there.

In the meantime, you can likely work around the issue by using --watch-when-idle.

@passcod thanks for the explanation. I created an issue in the notify repo.

Regarding --watch-when-idle, unfortunately, it does not help. It still loops forever. Here are the logs with --why option. Please note that logs are interleaved with our build script logs:

out-2.txt

Is there anything I can do to help debugging it further?

Wow I hadn't realised you were embedding cargo watch in your program. That's... not supported. I can't stop you, but this is not something that I would ever recommend doing. Use the libraries directly if you need to.

Regardless:

  • if you use watchexec with --print-events (like --why) and -p -1 (hidden testing flag, will stop at first event), and fswatch, you should be able to catch this new event, and see what watchexec interprets it as.
  • notify from your latest log displays it as Some((none)), which we should be able to catch and ignore in here. That's probably a good workaround until the event is properly caught.

@passcod we are not embedding it. We have a build script which basically downloads fonts to a folder, then compiles some C binaries, etc., end then runs cargo-watch to watch for changes (it runs cargo-watch as cmd command cargo watch ...). Every time a change happens, we are just running cargo and also npm to build our JS app. I believe that this is just a normal usage of cargo-watch, wich does not stand in opposite to how this library is meant to be used. Am I correct?

Regarding the points that you mentioned:

  1. That's a very handy info, thank you! I'll try to dig deeper and check how watch exec interprets it.
  2. It would be amazing to ignore it and check out if it fixes things - do you think you'd be able to implement it?

Not really interested in debating what exactly counts as embedding. This isn't a gotcha or invalidating a support contract or whatever. Interactive use is the intended use. If your setup works for you, fine.

  1. Sure. Can't guarantee when, though. Probably sometime next month? If you or anyone's interested in patching earlier, then start looking here.

Hi @passcod, did you find time to take a look into this issue? :)

No. Again, if you want it earlier, a PR is welcome.

@passcod I totally understand it. Unfortunately, I don't have enough of time to contribute here, as it requires pretty in-depth debugging. While I find cargo-watch to be the right solution in long-term, as it's written purely in Rust, until it works properly on modern MacOS and covers all .gitignore syntax, we made another project that is a in-place replacement for cargo-watch - we made it just in 1 evening, as it uses well-tested JS libs under the hood – for anyone facing this issue, you can find it here: https://github.com/enso-org/cargo-watch-plus (it works well on all Mac, Linux, and Windows, and supports all .gitignore syntax).

I'd say please don't use the name cargo-watch, but otherwise, best of luck

I'm using cargo- prefix because this way it registers as cargo command. I was trying to be very explicit that cargo-watch is the go to tool when it will work fine on MacOS. TBH, I hope I'd be able to delete this project sooner than later, as soon as cargo-watch will again work on my system.