notify-rs/notify

Inconsistent behaviors when root node changes

bicarlsen opened this issue · 3 comments

There is inconsistent behavior when modifying the root resource (file or directory) in different ways, so wanted to document them. This is not so much an error as documentation of these behavior.

folder/delete folder/rename folder/move file/delete file/rename file/move
Windows Remove(Any) or no event no event no event Remove(Any) Modify(Name(From)) Remove(Any)
macOS Remove(Folder) or Modify(Name(Any)) Modify(Name(Any)) Modify(Name(Any)) Modify(Name(Any)) Modify(Name(Any)) Modify(Name(Any))
Linux Remove(File) or Modify(Name(From)) Modify(Name(From)) Modify(Name(From)) Remove(File) or Modify(Name(From)) Modify(Name(From)) Modify(Name(From))
  • Windows and Linux track the actual resource, so continue emitting events even if it has been moved from its original path, but the original path is still reported for these events.
  • macOS watches the path instead of the resource. Events are emitted for whatever resource sits at that path.

Details

Windows

  • folder/delete: Using rm from command line Remove(Any) is emitted for the root, with no events emitted for the children. Using the file explorer no event emitted for root, Modify(Any) emitted for children.

    • On restore from recycle bin Modify(Any) emitted for children and subsequent events are still captured.
    • If deleted from the recycle bin Remove(Any) events emitted for children.
    • If a new folder is moved to the original path, no events are emitted from the new folder.
    • Also see #403
  • folder/rename: No events emitted for root or children.

    • Subsequent events report original path.
    • std::fs::canonicalize reports the new path and fails on the original.
    • No event emitted if moved back to the original location.
  • folder/move: No event emitted for root or children. Subsequent events continue being reported.

    • Subsequent events report original path.
    • std::fs::canonicalize reports the new path and fails on the original.
    • No event emitted if moved back to original location.
  • file/delete: Remove(Any) event emitted.

    • After deleting, if a new file is created at the original path Create(Any) is emitted and all subsequent events are emitted.
  • file/rename: Modify(Name(From)) event emitted.

    • In my case, I got a Modify(Name(From)) with no indication of the resulting name with e.g. a following Modify(Name(To)).
    • Subsequent events on original file were not emitted.
    • If renamed to original, a Modify(Name(Both)) was emitted with both the paths being the original.
    • If a new file was created at the original path a Create(Any) was emitted. Subsequent events are emitted for the new file.
    • If another file is renamed to original path a Modify(Name(To)) event was emitted. Subsequent events are emitted for the new file.
  • file/move: Remove(Any) event emitted.

    • Subsequent events on original file were not emitted.
    • Further actions match those of file/rename.

macOS

  • folder/delete: If removed from command line with rm a Remove(Folder) event is emitted. If deleted from finder a Modify(Name(Any)) is emitted with the original path.

    • No event emitted when deleted from trash.
    • Create(Folder) emitted if new folder created at original path.
    • Modify(Name(Any)) emitted if a folder is renamed or moved to the original path.
    • No events emitted for children.
  • folder/rename: Modify(Name(Any)) emitted with original path. Subsequent events not emitted.

    • If another folder is renamed or moved to original path, a Modify(Name(Any)) is emitted with the original path.
  • folder/move: Modify(Name(Any)) emitted with original path.

    • Subsequent events are not emitted.
    • Create(Folder) emitted if new folder created at original path.
    • Modify(Name(Any)) emitted if a folder is renamed or moved to the original path.
    • No events emitted for children.
  • file/delete: Modify(Name(Any)) emitted with original path.

    • No event emitted when deleted from trash.
    • If a new file is created at original path a Create(File) event is emitted. If another file is moved or renamed to the original path, a Modify(Name(Any)) event is emitted. Subsequent events on the new file are emitted.
  • file/rename: Modify(Name(Any)) emitted with original path.

    • Subsequent events on the file are not emitted.
    • If a new file is created or moved to the original path the same effect as file/delete occur.
  • file/move: Same as file/rename.

Linux

  • folder/delete: If removed from command line with rm a Remove(File) event is emitted. If deleted from finder a Modify(Name(Any)) is emitted with the original path.

    • If restored from trash a Modify(Name(From)) event is emitted.
    • No events on children are emitted.
    • If a new folder is moved to the original path, no events are emitted from it.
  • folder/rename: Modify(Name(From)) emitted.

    • Subsequent events are emitted with original path.
    • If a new folder is placed at the original path no event is emitted and no events from this folder are emitted.
    • std::fs::canonicalize reports the new path and fails on the original.
  • folder/move: Same as folder/rename.

  • file/delete: Same as folder/delete.

  • file/rename: Same as folder/rename.

  • file/move: Same as folder/rename.

Note: I performed the tests using notify_debouncer_full

In the cases where a resource's path changes but it is still being tracked and the original path is being emitted, this could lead to confusing behavior.

I made a proof of concept crate that gets a file's path from the id information provided in the file-id crate.

PollWatcher will emit Remove(Any) for all the children and the root folder after the root folder is deleted/renamed/moved. If the folder is created again, Create(Any) will be emitted for the root folder and all the children.