| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- //
- // FileSystemEvent.swift
- // FileKit
- //
- // The MIT License (MIT)
- //
- // Copyright (c) 2015-2017 Nikolai Vazquez
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- // THE SOFTWARE.
- //
- import Foundation
- #if os(OSX)
- /// A filesystem event.
- public struct FileSystemEvent {
- // MARK: - Static Properties
- /// All of the event IDs.
- public static let allEventId = 0
- /// The last event ID since now.
- public static let nowEventId = FSEventStreamEventId(kFSEventStreamEventIdSinceNow)
- // MARK: - Properties
- /// The ID of the event.
- public var id: FSEventStreamEventId // swiftlint:disable:this variable_name
- /// The path for the event.
- public var path: Path
- /// The flags of the event.
- public var flags: FileSystemEventFlags
- }
- extension Path {
- // MARK: - Watching
- /// Watches a path for filesystem events and handles them in the callback.
- ///
- /// - Parameter latency: The latency in seconds.
- /// - Parameter queue: The queue to be run within.
- /// - Parameter callback: The callback to handle events.
- /// - Returns: The `FileSystemWatcher` object.
- public func watch(_ latency: TimeInterval = 0, queue: DispatchQueue = DispatchQueue.main, callback: @escaping (FileSystemEvent) -> Void) -> FileSystemWatcher {
- let watcher = FileSystemWatcher(paths: [self], latency: latency, queue: queue, callback: callback)
- watcher.watch()
- return watcher
- }
- }
- extension Sequence where Self.Iterator.Element == Path {
- // MARK: - Watching
- /// Watches the sequence of paths for filesystem events and handles them in
- /// the callback.
- ///
- /// - Parameter latency: The latency in seconds.
- /// - Parameter queue: The queue to be run within.
- /// - Parameter callback: The callback to handle events.
- /// - Returns: The `FileSystemWatcher` object.
- public func watch(_ latency: TimeInterval = 0, queue: DispatchQueue = DispatchQueue.main, callback: @escaping (FileSystemEvent) -> Void) -> FileSystemWatcher {
- let watcher = FileSystemWatcher(paths: Array(self), latency: latency, queue: queue, callback: callback)
- watcher.watch()
- return watcher
- }
- }
- /// A set of fileystem event flags.
- public struct FileSystemEventFlags: OptionSet, CustomStringConvertible, CustomDebugStringConvertible {
- // MARK: - Options
- /// There was some change in the directory at the specific path supplied in
- /// this event.
- public static let None = FileSystemEventFlags(rawValue: kFSEventStreamEventFlagNone)
- /// Your application must rescan not just the directory given in the event,
- /// but all its children, recursively.
- public static let MustScanSubDirs = FileSystemEventFlags(rawValue: kFSEventStreamEventFlagMustScanSubDirs)
- /// May be set in addition to `MustScanSubDirs` indicate that a problem
- /// occurred in buffering the events (the particular flag set indicates
- /// where the problem occurred) and that the client must do a full scan of
- /// any directories (and their subdirectories, recursively) being monitored
- /// by this stream.
- public static let UserDropped = FileSystemEventFlags(rawValue: kFSEventStreamEventFlagUserDropped)
- /// May be set in addition to `MustScanSubDirs` indicate that a problem
- /// occurred in buffering the events (the particular flag set indicates
- /// where the problem occurred) and that the client must do a full scan of
- /// any directories (and their subdirectories, recursively) being monitored
- /// by this stream.
- public static let KernelDropped = FileSystemEventFlags(rawValue: kFSEventStreamEventFlagKernelDropped)
- /// The 64-bit event ID counter wrapped around.
- public static let EventIdsWrapped = FileSystemEventFlags(rawValue: kFSEventStreamEventFlagEventIdsWrapped)
- /// Denotes a sentinel event sent to mark the end of the "historical" events
- /// sent as a result of specifying a `sinceWhen` value in the
- /// FSEventStreamCreate...() call that created this event stream.
- public static let HistoryDone = FileSystemEventFlags(rawValue: kFSEventStreamEventFlagHistoryDone)
- /// Denotes a special event sent when there is a change to one of the
- /// directories along the path to one of the directories asked to watch.
- public static let RootChanged = FileSystemEventFlags(rawValue: kFSEventStreamEventFlagRootChanged)
- /// Denotes a special event sent when a volume is mounted underneath one of
- /// the paths being monitored.
- public static let Mount = FileSystemEventFlags(rawValue: kFSEventStreamEventFlagMount)
- /// Denotes a special event sent when a volume is unmounted underneath one
- /// of the paths being monitored.
- public static let Unmount = FileSystemEventFlags(rawValue: kFSEventStreamEventFlagUnmount)
- /// A file system object was created at the specific path supplied in this
- /// event.
- public static let Created = FileSystemEventFlags(rawValue: kFSEventStreamEventFlagItemCreated)
- /// A file system object was removed at the specific path supplied in this
- /// event.
- public static let ItemRemoved = FileSystemEventFlags(rawValue: kFSEventStreamEventFlagItemRemoved)
- /// A file system object at the specific path supplied in this event had its
- /// metadata modified.
- public static let ItemInodeMetaMod = FileSystemEventFlags(rawValue: kFSEventStreamEventFlagItemInodeMetaMod)
- /// A file system object was renamed at the specific path supplied in this
- /// event.
- public static let ItemRenamed = FileSystemEventFlags(rawValue: kFSEventStreamEventFlagItemRenamed)
- /// A file system object at the specific path supplied in this event had its
- /// data modified.
- public static let ItemModified = FileSystemEventFlags(rawValue: kFSEventStreamEventFlagItemModified)
- /// A file system object at the specific path supplied in this event had its
- /// FinderInfo data modified.
- public static let ItemFinderInfoMod = FileSystemEventFlags(rawValue: kFSEventStreamEventFlagItemFinderInfoMod)
- /// A file system object at the specific path supplied in this event had its
- /// ownership changed.
- public static let ItemChangeOwner = FileSystemEventFlags(rawValue: kFSEventStreamEventFlagItemChangeOwner)
- /// A file system object at the specific path supplied in this event had its
- /// extended attributes modified.
- public static let ItemXattrMod = FileSystemEventFlags(rawValue: kFSEventStreamEventFlagItemXattrMod)
- /// The file system object at the specific path supplied in this event is a
- /// regular file.
- public static let ItemIsFile = FileSystemEventFlags(rawValue: kFSEventStreamEventFlagItemIsFile)
- /// The file system object at the specific path supplied in this event is a
- /// directory.
- public static let ItemIsDir = FileSystemEventFlags(rawValue: kFSEventStreamEventFlagItemIsDir)
- /// The file system object at the specific path supplied in this event is a
- /// symbolic link.
- public static let ItemIsSymlink = FileSystemEventFlags(rawValue: kFSEventStreamEventFlagItemIsSymlink)
- /// Indicates the event was triggered by the current process.
- public static let OwnEvent = FileSystemEventFlags(rawValue: kFSEventStreamEventFlagOwnEvent)
- /// Flag for if the item is a hardlink.
- @available(iOS 9, OSX 10.10, *)
- public static let ItemIsHardlink = FileSystemEventFlags(rawValue: kFSEventStreamEventFlagItemIsHardlink)
- /// Flag for if the item was the last hardlink.
- @available(iOS 9, OSX 10.10, *)
- public static let ItemIsLastHardlink = FileSystemEventFlags(rawValue: kFSEventStreamEventFlagItemIsLastHardlink)
- // MARK: - All Flags
- /// An array of all of the flags.
- public static var allFlags: [FileSystemEventFlags] = {
- var array: [FileSystemEventFlags] = [ // swiftlint:disable comma
- .None, .MustScanSubDirs, .UserDropped,
- .KernelDropped, .EventIdsWrapped, .HistoryDone,
- .RootChanged, .Mount, .Unmount,
- .ItemRemoved, .ItemInodeMetaMod, .ItemRenamed,
- .ItemModified, .ItemFinderInfoMod, .ItemChangeOwner,
- .ItemXattrMod, .ItemIsFile, .ItemIsDir,
- .ItemIsSymlink, .OwnEvent
- ] // swiftlint:enable comma
- if #available(iOS 9, OSX 10.10, *) {
- array += [.ItemIsHardlink, .ItemIsLastHardlink ]
- }
- return array
- }()
- /// The names of all of the flags.
- public static let allFlagNames: [String] = {
- var array: [String] = [ // swiftlint:disable comma
- "None", "MustScanSubDirs", "UserDropped",
- "KernelDropped", "EventIdsWrapped", "HistoryDone",
- "RootChanged", "Mount", "Unmount",
- "ItemRemoved", "ItemInodeMetaMod", "ItemRenamed",
- "ItemModified", "ItemFinderInfoMod", "ItemChangeOwner",
- "ItemXattrMod", "ItemIsFile", "ItemIsDir",
- "ItemIsSymlink", "OwnEvent"
- ] // swiftlint:enable comma
- if #available(iOS 9, OSX 10.10, *) {
- array += ["ItemIsHardlink", "ItemIsLastHardlink"]
- }
- return array
- }()
- // MARK: - Properties
- /// The raw event stream flag values.
- public let rawValue: Int
- /// A textual representation of `self`.
- public var description: String {
- var result = ""
- for (index, element) in FileSystemEventFlags.allFlags.enumerated() {
- if self.contains(element) {
- let name = FileSystemEventFlags.allFlagNames[index]
- result += result.isEmpty ? "\(name)": ", \(name)"
- }
- }
- return String(describing: type(of: self)) + "[\(result)]"
- }
- /// A textual representation of `self`, suitable for debugging.
- public var debugDescription: String {
- var result = ""
- for (index, element) in FileSystemEventFlags.allFlags.enumerated() {
- if self.contains(element) {
- let name = FileSystemEventFlags.allFlagNames[index] + "(\(element.rawValue))"
- result += result.isEmpty ? "\(name)": ", \(name)"
- }
- }
- return String(describing: type(of: self)) + "[\(result)]"
- }
- // MARK: - Initialization
- /// Creates a set of event stream flags from a raw value.
- ///
- /// - Parameter rawValue: The raw value to initialize from.
- public init(rawValue: Int) { self.rawValue = rawValue }
- }
- /// Flags for creating an event stream.
- public struct FileSystemEventStreamCreateFlags: OptionSet, CustomStringConvertible, CustomDebugStringConvertible {
- // MARK: - Options
- /// The default.
- public static let None = FileSystemEventStreamCreateFlags(rawValue: kFSEventStreamCreateFlagNone)
- /// The callback function will be invoked with CF types rather than raw C
- /// types.
- public static let UseCFTypes = FileSystemEventStreamCreateFlags(rawValue: kFSEventStreamCreateFlagUseCFTypes)
- /// Affects the meaning of the latency parameter.
- public static let FlagNoDefer = FileSystemEventStreamCreateFlags(rawValue: kFSEventStreamCreateFlagNoDefer)
- /// Request notifications of changes along the path to the path(s) watched.
- public static let WatchRoot = FileSystemEventStreamCreateFlags(rawValue: kFSEventStreamCreateFlagWatchRoot)
- /// Don't send events that were triggered by the current process.
- public static let IgnoreSelf = FileSystemEventStreamCreateFlags(rawValue: kFSEventStreamCreateFlagIgnoreSelf)
- /// Request file-level notifications.
- public static let FileEvents = FileSystemEventStreamCreateFlags(rawValue: kFSEventStreamCreateFlagFileEvents)
- /// Tag events that were triggered by the current process with the
- /// `OwnEvent` flag.
- public static let MarkSelf = FileSystemEventStreamCreateFlags(rawValue: kFSEventStreamCreateFlagMarkSelf)
- // MARK: - All Flags
- /// All of the event stream creation flags.
- public static let allFlags: [FileSystemEventStreamCreateFlags] = [.None, .UseCFTypes, .FlagNoDefer, .WatchRoot, .IgnoreSelf, .FileEvents, .MarkSelf]
- /// All of the names of the event stream creation flags.
- public static let allFlagNames: [String] = ["None", "UseCFTypes", "FlagNoDefer", "WatchRoot", "IgnoreSelf", "FileEvents", "MarkSelf" ]
- // MARK: - Properties
- /// The raw event stream creation flags.
- public let rawValue: Int
- /// A textual representation of `self`.
- public var description: String {
- var result = ""
- for (index, element) in FileSystemEventStreamCreateFlags.allFlags.enumerated() {
- if self.contains(element) {
- let name = FileSystemEventStreamCreateFlags.allFlagNames[index]
- result += result.isEmpty ? "\(name)": ", \(name)"
- }
- }
- return String(describing: type(of: self)) + "[\(result)]"
- }
- /// A textual representation of `self`, suitable for debugging.
- public var debugDescription: String {
- var result = ""
- for (index, element) in FileSystemEventStreamCreateFlags.allFlags.enumerated() {
- if self.contains(element) {
- let name = FileSystemEventStreamCreateFlags.allFlagNames[index] + "(\(element.rawValue))"
- result += result.isEmpty ? "\(name)": ", \(name)"
- }
- }
- return String(describing: type(of: self)) + "[\(result)]"
- }
- // MARK: - Initialization
- /// Creates a set of event stream creation flags from a raw value.
- ///
- /// - Parameter rawValue: The raw value to initialize from.
- public init(rawValue: Int) { self.rawValue = rawValue }
- }
- #endif
|