Skip to content

Commit

Permalink
Revert "Switched to using Core Foundation types"
Browse files Browse the repository at this point in the history
This reverts commit 9352098 and fixes
pr #1.
  • Loading branch information
jgvanwyk committed Aug 30, 2023
1 parent 9352098 commit 0710c3c
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 38 deletions.
64 changes: 38 additions & 26 deletions Sources/SwiftFileSystemEvents/FileSystemEventStream.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,34 +42,33 @@ public final class FileSystemEventStream {
latency: TimeInterval = 0,
flags: Flags = [],
handler: @escaping (FileSystemEvent) -> Void) {
var flags = flags
flags.insert(.useCFTypes)
self.handler = handler
let pathsToWatch = directoriesToWatch.map { $0.path } as CFArray
let pathsToWatch: CFArray
if #available(macOS 13.0, *) {
pathsToWatch = directoriesToWatch.map { $0.path(percentEncoded: false) } as CFArray
} else {
pathsToWatch = directoriesToWatch.map { $0.path } as CFArray
}
// We pass an unmanaged pointer to `self` as context info to the stream.
// `FileSystemEventStream.callback` uses this to call `handler` with each event.
// As the memory for `self` is managed by Swift, we pass `nil` for both `retain`
// and `release`.
var context = FSEventStreamContext(
version: 0,
info: Unmanaged.passUnretained(self).toOpaque(),
retain: nil,
release: nil,
copyDescription: nil
)
var context = FSEventStreamContext(version: 0,
info: Unmanaged.passUnretained(self).toOpaque(),
retain: nil,
release: nil,
copyDescription: nil)
// While the return value of `FSEventStreamCreate` is imported in Swift as
// `FSEventStreamRef?`, the documentation for `FSEventStreamCreate` asserts that
// its return value will always be a valid `FSEventStreamRef`, so we unwrap the
// return value here.
self.streamRef = FSEventStreamCreate(
kCFAllocatorDefault,
Self.callback,
&context,
pathsToWatch,
sinceWhen.rawValue,
latency,
flags.rawValue
)!
self.streamRef = FSEventStreamCreate(kCFAllocatorDefault,
Self.callback,
&context,
pathsToWatch,
sinceWhen.rawValue,
latency,
flags.rawValue)!
}

deinit {
Expand All @@ -78,10 +77,12 @@ public final class FileSystemEventStream {

private static let callback: FSEventStreamCallback = { _, info, numEvents, eventPaths, eventFlags, eventIDs in
guard let info = info else { return }
let eventPaths = Unmanaged<CFArray>.fromOpaque(eventPaths).takeUnretainedValue() as! [CFString]
let eventPaths = eventPaths.assumingMemoryBound(to: UnsafeMutablePointer<CChar>.self)
let stream = Unmanaged<FileSystemEventStream>.fromOpaque(info).takeUnretainedValue()
for index in 0..<numEvents {
let url = CFURLCreateWithString(nil, eventPaths[index], nil) as URL
let url = URL(fileURLWithFileSystemRepresentation: eventPaths[index],
isDirectory: true,
relativeTo: nil)
let flags = FileSystemEvent.Flags(rawValue: eventFlags[index])
let id = FileSystemEvent.ID(rawValue: eventIDs[index])
let event = FileSystemEvent(url: url, id: id, flags: flags)
Expand All @@ -105,9 +106,15 @@ public final class FileSystemEventStream {
/// This calls `FSEventStreamCopyPathsBeingWatched`.
@available(macOS 10.5, *)
public var directoriesBeingWatched: [URL] {
// `FSEventStreamCopyPathsBeingWatched` returns a `CFArray` of `CFString`.
let paths = FSEventStreamCopyPathsBeingWatched(streamRef) as! [CFString]
let urls = paths.map { CFURLCreateWithString(nil, $0, nil) as URL }
// `FSEventStreamCopyPathsBeingWatched` returns a `CFArray` of `CFStringRef`, which
// can always be converted to `[String]`.
let paths = FSEventStreamCopyPathsBeingWatched(streamRef) as! [String]
let urls: [URL]
if #available(macOS 13.0, *) {
urls = paths.map { URL(filePath: $0, directoryHint: .isDirectory) }
} else {
urls = paths.map { URL(fileURLWithPath: $0, isDirectory: true) }
}
return urls
}

Expand Down Expand Up @@ -231,7 +238,12 @@ public final class FileSystemEventStream {
/// This calls `FSEventStreamSetExclusionPaths(_:,_:)`.
@available(macOS 10.9, *)
public func setExclusionDirectories(_ directoryURLs: [URL]) throws {
let paths = directoryURLs.map { $0.path } as CFArray
let paths: CFArray
if #available(macOS 13.0, *) {
paths = directoryURLs.map { $0.path(percentEncoded: false) } as CFArray
} else {
paths = directoryURLs.map { $0.path } as CFArray
}
guard FSEventStreamSetExclusionPaths(streamRef, paths) else { throw Error.couldNotExcludeDirectories }
}

Expand All @@ -258,7 +270,7 @@ public final class FileSystemEventStream {
/// This wraps `kFSEventStreamCreateFlagNone`.
public static let none = Self.init(rawValue: FSEventStreamCreateFlags(kFSEventStreamCreateFlagNone))

fileprivate static let useCFTypes = Self.init(rawValue: FSEventStreamCreateFlags(kFSEventStreamCreateFlagUseCFTypes))
// public static let useCFTypes = Self.init(rawValue: FSEventStreamCreateFlags(kFSEventStreamCreateFlagUseCFTypes))

/// Change the meaning of the latency parameter.
///
Expand Down
12 changes: 10 additions & 2 deletions Sources/SwiftFileSystemEvents/StringConvertible.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,19 @@ extension FileSystemEventStream.Flags: CustomStringConvertible, CustomDebugStrin
extension FileSystemEvent: CustomStringConvertible, CustomDebugStringConvertible {

public var description: String {
return "FileSystemEvent(path: \(url.path), flags: \(flags.description), id: \(id.description))"
if #available(macOS 13.0, *) {
return "FileSystemEvent(path: \(url.path(percentEncoded: false)), flags: \(flags.description), id: \(id.description))"
} else {
return "FileSystemEvent(path: \(url.path), flags: \(flags.description), id: \(id.description))"
}
}

public var debugDescription: String {
return "FileSystemEvent(path: \(url.path), flags: Flags(rawValue: \(flags.rawValue)), id: ID(rawValue: \(id.rawValue)))"
if #available(macOS 13.0, *) {
return "FileSystemEvent(path: \(url.path(percentEncoded: false)), flags: Flags(rawValue: \(flags.rawValue)), id: ID(rawValue: \(id.rawValue)))"
} else {
return "FileSystemEvent(path: \(url.path), flags: Flags(rawValue: \(flags.rawValue)), id: ID(rawValue: \(id.rawValue)))"
}
}

}
Expand Down
10 changes: 0 additions & 10 deletions Tests/SwiftFileSystemEventsTests/SwiftFileSystemEventsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,6 @@ import XCTest


final class SwiftFileSystemEventsTests: XCTestCase {

@available(macOS 13.0, *)
func test() {
let stream = FileSystemEventStream(directoriesToWatch: [.downloadsDirectory], handler: { print($0) })
stream.setDispatchQueue(.global(qos: .background))
try! stream.start()
Thread.sleep(forTimeInterval: 30)
stream.stop()
stream.invalidate()
}

func testFileSystemEventStreamFlagsDescription() {
let flags0: FileSystemEventStream.Flags = []
Expand Down

0 comments on commit 0710c3c

Please sign in to comment.