Skip to content

Commit

Permalink
Inotify's symlink follow with recursive option (#1088)
Browse files Browse the repository at this point in the history
* Using symlink follow now working as intended with recursive (used to
  be shallow only)
* Add test for recursive + follow symlink for Inotify observer
* Improve test for recursive cases : in case of recursive Inotify
  directory open event always triggers

Co-authored-by: Corentin <[email protected]>
  • Loading branch information
Corentin-pro and Corentin-pro authored Nov 19, 2024
1 parent 9df81ab commit 39bff24
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 3 deletions.
2 changes: 1 addition & 1 deletion src/watchdog/observers/inotify_c.py
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ def _add_dir_watch(self, path: bytes, mask: int, *, recursive: bool) -> None:
raise OSError(errno.ENOTDIR, os.strerror(errno.ENOTDIR), path)
self._add_watch(path, mask)
if recursive:
for root, dirnames, _ in os.walk(path):
for root, dirnames, _ in os.walk(path, followlinks=self._follow_symlink):
for dirname in dirnames:
full_path = os.path.join(root, dirname)
if not self._follow_symlink and os.path.islink(full_path):
Expand Down
27 changes: 25 additions & 2 deletions tests/test_inotify_buffer.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
import random
import time

from watchdog.observers.inotify_buffer import InotifyBuffer
from watchdog.observers.inotify_c import InotifyConstants
from watchdog.observers.inotify_buffer import InotifyBuffer, InotifyEvent

from .shell import mkdir, mount_tmpfs, mv, rm, symlink, touch, unmount

Expand Down Expand Up @@ -126,7 +127,29 @@ def test_delete_watched_directory_symlink_followed(p):
rm(p("dir", "dir2"), recursive=True)

# Wait for the event to be picked up
inotify.read_event()
event = inotify.read_event()
while not isinstance(event, InotifyEvent) or (
event.mask != (InotifyConstants.IN_DELETE | InotifyConstants.IN_ISDIR)):
event = inotify.read_event()

# Ensure InotifyBuffer shuts down cleanly without raising an exception
inotify.close()


@pytest.mark.timeout(5)
def test_delete_watched_directory_symlink_followed_recursive(p):
mkdir(p("dir"), parents=True)
mkdir(p("dir2", "dir3", "dir4"), parents=True)
symlink(p("dir2"), p("dir", "symdir"), target_is_directory=True)

inotify = InotifyBuffer(p("dir").encode(), follow_symlink=True, recursive=True)
rm(p("dir2", "dir3", "dir4"), recursive=True)

# Wait for the event to be picked up
event = inotify.read_event()
while not isinstance(event, InotifyEvent) or (
event.mask != (InotifyConstants.IN_DELETE | InotifyConstants.IN_ISDIR)):
event = inotify.read_event()

# Ensure InotifyBuffer shuts down cleanly without raising an exception
inotify.close()
Expand Down

0 comments on commit 39bff24

Please sign in to comment.