Implement auto subtree watching of a directory

Allow recursively watching a directory while adding newly created
subdirectories to the inotify watch list.
This commit is contained in:
T. R. Bernstein
2026-03-12 12:04:08 +01:00
parent a8d7fb017f
commit ffac6d17a5
4 changed files with 85 additions and 8 deletions

View File

@@ -13,11 +13,31 @@ struct RecursiveEventTests {
let events = try await getEventsForTrigger(
in: dir,
mask: [.create],
recursive: true
recursive: .recursive
) { _ in try createFile(at: "\(filepath)", contents: "hello") }
let createEvent = events.first { $0.mask.contains(.create) && $0.path.string == filepath }
#expect(createEvent != nil, "Expected CREATE for '\(filepath)', got: \(events)")
}
}
@Test func newSubfoldersOfRecursiveWatchAreAutomaticallyWatchedToo() async throws {
try await withTempDir { dir in
let subDirectory = "\(dir)/Subfolder"
let filepath = "\(subDirectory)/modify-target.txt"
let events = try await getEventsForTrigger(
in: dir,
mask: [.create],
recursive: .withAutomaticSubtreeWatching
) { _ in
try FileManager.default.createDirectory(atPath: subDirectory, withIntermediateDirectories: true)
try await Task.sleep(for: .milliseconds(200))
try createFile(at: "\(filepath)", contents: "hello")
}
let createEvent = events.first { $0.mask.contains(.create) && $0.path.string == filepath }
#expect(createEvent != nil, "Expected CREATE for '\(filepath)', got: \(events)")
}
}
}

View File

@@ -1,16 +1,25 @@
import Inotify
enum RecursivKind {
case nonrecursive
case recursive
case withAutomaticSubtreeWatching
}
func getEventsForTrigger(
in dir: String,
mask: InotifyEventMask,
recursive: Bool = false,
recursive: RecursivKind = .nonrecursive,
trigger: @escaping (String) async throws -> Void,
) async throws -> [InotifyEvent] {
let watcher = try Inotify()
if recursive {
try await watcher.addRecursiveWatch(forDirectory: dir, mask: mask)
} else {
switch recursive {
case .nonrecursive:
try await watcher.addWatch(path: dir, mask: mask)
case .recursive:
try await watcher.addRecursiveWatch(forDirectory: dir, mask: mask)
case .withAutomaticSubtreeWatching:
try await watcher.addWatchWithAutomaticSubtreeWatching(forDirectory: dir, mask: mask)
}
let eventTask = Task {