DELETE
events for sub directories of moved directories:Once the call to watch returns, onEvent is guaranteed to receive a an event containing the path for:
- Every file or folder that gets created, deleted, updated or moved within the watched folders
- For copied or moved folders, the path of the new folder as well as every file or folder within it.
- For deleted or moved folders, the root folder which was deleted/moved, but without the paths of every file that was within it at the original location
I apologize for all the spam but here is a simple test that shows that the problem is in WatchService
. os.watch
is likely masking some of those issues in its implementation but not all.
https://github.com/utgheith/watch3/blob/master/src/main/scala/main.scala
It seems that readme.md
is using travis-ci badges instead of the github actions ones. Clicking on the build status goes back to a January build (telling me that the switch occurred around this time). Tried to submit a pull request that fixes that but it gets stuck and never runs the tests. This seems to be related to an issue that I don't fully understand but requires special privileges to deal with anyway. Here is a link:
https://github.community/t/expected-waiting-for-status-to-be-reported/16727
os.watch
and I want to know your thoughts on them.os.watch
is the sort of thing that requires stress testing. Unit testing is still important obviously. Do you have your own stress tests? If not, is there value in developing some and running them as part of CI?OVERFLOW
(silently drop events, force the caller to re-examine the world, ...). inotify
uses a finite system-wide queue for notifications and there is no guarantee that it will not overflow.
Same test as before but uses inotify
(not directly but by spawning a process running inotifywatch
). Works reliably on the same test that was failing before. This strongly hints that using inotify
directly will be more reliable. Also inotify
is explicit about how it handles moves (move_to, move_from, move_self, etc)
https://github.com/utgheith/watch4/blob/master/src/main/scala/main.scala
inotify
-based implementation too, if you don't mind wrangling some JNA FFI code. That's what we ended up doing for the OS-X backend anyway so it's not unprecedented
intofiy
based Watcher
implementation (com-lihaoyi/os-lib#70). It's still rough around the edges and didn't have a change to stress-test it but it already passes the existing os.watch
tests reliably (even on Docker). Would be great if you took look at the overall design.
scalacheck
as a dependency? It makes working with such tests easier.
OSX
and Linux
when using the WatchServiceWatcher
. They are currently disabled for OSX
.
def apply(src: Path, sort: Boolean = true) = { ... }
def apply(src: Path) = apply(src, true)
def setLinkUserAndGroup(link: os.Path, usr: String, grp: String) : Unit = {
val lookupService = FileSystems.getDefault.getUserPrincipalLookupService
val attrView = Files.getFileAttributeView(Paths.get(link.toString()), classOf[PosixFileAttributeView],
LinkOption.NOFOLLOW_LINKS)
attrView.setOwner(lookupService.lookupPrincipalByName(usr))
attrView.setGroup(lookupService.lookupPrincipalByGroupName(grp))
}
or something, I guess. I feel your pain.
.call(check = false)
not work?$ amm
Loading...
Welcome to the Ammonite Repl 2.4.0 (Scala 2.13.6 Java 11.0.11)
@ os.proc("foo").call(check = false)
java.io.IOException: Cannot run program "foo" (in directory ".../oslib"): error=2, No such file or directory
java.lang.ProcessBuilder.start(ProcessBuilder.java:1128)
java.lang.ProcessBuilder.start(ProcessBuilder.java:1071)
os.proc.proc$lzycompute$1(ProcessOps.scala:128)
os.proc.proc$1(ProcessOps.scala:122)
os.proc.spawn(ProcessOps.scala:135)
os.proc.call(ProcessOps.scala:76)
ammonite.$sess.cmd0$.<clinit>(cmd0.sc:1)
java.io.IOException: error=2, No such file or directory
...
IOException
so something is going on here: https://github.com/com-lihaoyi/os-lib/blob/790b81aba491047b73dd481e290abb36ee1a7de8/os/src-jvm/ProcessOps.scala#L84
proc.spawn
is accidentally throwing the exception here: https://github.com/com-lihaoyi/os-lib/blob/790b81aba491047b73dd481e290abb36ee1a7de8/os/src-jvm/ProcessOps.scala#L128 I'll file an issue
scala> os.proc("false").call() // false returns 1, so this should throw
os.SubprocessException: CommandResult 1
at os.SubprocessException$.apply(Model.scala:202)
at os.proc.call(ProcessOps.scala:85)
... 28 elided
scala> os.proc("false").call(check = false) // error is suppressed
val res4: os.CommandResult = CommandResult 1
scala> os.proc("nonexistant").call(check = false) // we still get an error, because "nonexistant" is does not exist
java.io.IOException: Cannot run program "nonexistant" (in directory "/home/jodersky/p/buildsio"): error=2, No such file or directory
at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1141)
at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1072)
at os.proc.proc$lzyINIT1$7(ProcessOps.scala:128)
at os.proc.proc$1(ProcessOps.scala:133)
at os.proc.spawn(ProcessOps.scala:135)
at os.proc.call(ProcessOps.scala:76)
... 28 elided
Caused by: java.io.IOException: error=2, No such file or directory
at java.base/java.lang.ProcessImpl.forkAndExec(Native Method)
at java.base/java.lang.ProcessImpl.<init>(ProcessImpl.java:313)
at java.base/java.lang.ProcessImpl.start(ProcessImpl.java:244)
at java.base/java.lang.ProcessBuilder.start(ProcessBuilder.java:1108)
... 33 more