├── .gitignore
├── .swiftpm
└── xcode
│ └── package.xcworkspace
│ └── contents.xcworkspacedata
├── .travis.yml
├── BuildTest
├── BuildTest.xcodeproj
│ ├── project.pbxproj
│ └── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── MacCatalystBuildTest
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ └── Contents.json
│ │ └── Contents.json
│ ├── Base.lproj
│ │ └── LaunchScreen.storyboard
│ ├── Info.plist
│ ├── MacCatalystBuildTest.entitlements
│ └── Preview Content
│ │ └── Preview Assets.xcassets
│ │ └── Contents.json
└── MacOSBuildTest
│ └── main.swift
├── EonilFSEventsDemoGUI
├── EonilFSEventsDemoGUI.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── EonilFSEventsDemoGUI.xcscheme
└── EonilFSEventsDemoGUI
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ └── Contents.json
│ └── Contents.json
│ ├── Base.lproj
│ └── Main.storyboard
│ ├── EonilFSEventsDemoGUI.entitlements
│ ├── Info.plist
│ └── ViewController.swift
├── LICENSE.md
├── Package.swift
├── README.md
├── Sources
├── EonilFSEvents
│ ├── EonilFSEventStream.swift
│ ├── EonilFSEventStreamCreateFlags.swift
│ ├── EonilFSEventStreamError.swift
│ ├── EonilFSEventStreamEvent.swift
│ ├── EonilFSEventStreamEventFlags.swift
│ ├── EonilFSEventStreamEventID.swift
│ ├── EonilFSEventStreamIllogicalErrorLog.swift
│ └── EonilFSEvents.swift
└── EonilFSEventsDemoCLI
│ └── main.swift
└── test.zsh
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | /build
3 | .build
4 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: swift
2 | os: osx
3 | osx_image: xcode11
4 | script: zsh test.zsh
5 |
--------------------------------------------------------------------------------
/BuildTest/BuildTest.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 52;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | D74D88E72498C12A00A0F885 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = D74D88E62498C12A00A0F885 /* main.swift */; };
11 | D74D88F22498C16200A0F885 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D74D88F12498C16200A0F885 /* AppDelegate.swift */; };
12 | D74D88F82498C16500A0F885 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D74D88F72498C16500A0F885 /* Assets.xcassets */; };
13 | D74D88FB2498C16500A0F885 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D74D88FA2498C16500A0F885 /* Preview Assets.xcassets */; };
14 | D74D88FE2498C16500A0F885 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D74D88FC2498C16500A0F885 /* LaunchScreen.storyboard */; };
15 | D74D89072498C1A600A0F885 /* EonilFSEvents in Frameworks */ = {isa = PBXBuildFile; platformFilter = maccatalyst; productRef = D74D89062498C1A600A0F885 /* EonilFSEvents */; };
16 | D74D89092498C1AC00A0F885 /* EonilFSEvents in Frameworks */ = {isa = PBXBuildFile; productRef = D74D89082498C1AC00A0F885 /* EonilFSEvents */; };
17 | /* End PBXBuildFile section */
18 |
19 | /* Begin PBXCopyFilesBuildPhase section */
20 | D74D88E12498C12A00A0F885 /* CopyFiles */ = {
21 | isa = PBXCopyFilesBuildPhase;
22 | buildActionMask = 2147483647;
23 | dstPath = /usr/share/man/man1/;
24 | dstSubfolderSpec = 0;
25 | files = (
26 | );
27 | runOnlyForDeploymentPostprocessing = 1;
28 | };
29 | /* End PBXCopyFilesBuildPhase section */
30 |
31 | /* Begin PBXFileReference section */
32 | D74D88E32498C12A00A0F885 /* MacOSBuildTest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = MacOSBuildTest; sourceTree = BUILT_PRODUCTS_DIR; };
33 | D74D88E62498C12A00A0F885 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; };
34 | D74D88EF2498C16200A0F885 /* MacCatalystBuildTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MacCatalystBuildTest.app; sourceTree = BUILT_PRODUCTS_DIR; };
35 | D74D88F12498C16200A0F885 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
36 | D74D88F72498C16500A0F885 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
37 | D74D88FA2498C16500A0F885 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; };
38 | D74D88FD2498C16500A0F885 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
39 | D74D88FF2498C16500A0F885 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
40 | D74D89032498C16B00A0F885 /* MacCatalystBuildTest.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = MacCatalystBuildTest.entitlements; sourceTree = ""; };
41 | D74D89042498C1A200A0F885 /* FSEvents */ = {isa = PBXFileReference; lastKnownFileType = folder; name = FSEvents; path = ..; sourceTree = ""; };
42 | /* End PBXFileReference section */
43 |
44 | /* Begin PBXFrameworksBuildPhase section */
45 | D74D88E02498C12A00A0F885 /* Frameworks */ = {
46 | isa = PBXFrameworksBuildPhase;
47 | buildActionMask = 2147483647;
48 | files = (
49 | D74D89092498C1AC00A0F885 /* EonilFSEvents in Frameworks */,
50 | );
51 | runOnlyForDeploymentPostprocessing = 0;
52 | };
53 | D74D88EC2498C16200A0F885 /* Frameworks */ = {
54 | isa = PBXFrameworksBuildPhase;
55 | buildActionMask = 2147483647;
56 | files = (
57 | D74D89072498C1A600A0F885 /* EonilFSEvents in Frameworks */,
58 | );
59 | runOnlyForDeploymentPostprocessing = 0;
60 | };
61 | /* End PBXFrameworksBuildPhase section */
62 |
63 | /* Begin PBXGroup section */
64 | D74D88D82498C10A00A0F885 = {
65 | isa = PBXGroup;
66 | children = (
67 | D74D89042498C1A200A0F885 /* FSEvents */,
68 | D74D88E52498C12A00A0F885 /* MacOSBuildTest */,
69 | D74D88F02498C16200A0F885 /* MacCatalystBuildTest */,
70 | D74D88E42498C12A00A0F885 /* Products */,
71 | D74D89052498C1A600A0F885 /* Frameworks */,
72 | );
73 | sourceTree = "";
74 | };
75 | D74D88E42498C12A00A0F885 /* Products */ = {
76 | isa = PBXGroup;
77 | children = (
78 | D74D88E32498C12A00A0F885 /* MacOSBuildTest */,
79 | D74D88EF2498C16200A0F885 /* MacCatalystBuildTest.app */,
80 | );
81 | name = Products;
82 | sourceTree = "";
83 | };
84 | D74D88E52498C12A00A0F885 /* MacOSBuildTest */ = {
85 | isa = PBXGroup;
86 | children = (
87 | D74D88E62498C12A00A0F885 /* main.swift */,
88 | );
89 | path = MacOSBuildTest;
90 | sourceTree = "";
91 | };
92 | D74D88F02498C16200A0F885 /* MacCatalystBuildTest */ = {
93 | isa = PBXGroup;
94 | children = (
95 | D74D89032498C16B00A0F885 /* MacCatalystBuildTest.entitlements */,
96 | D74D88F12498C16200A0F885 /* AppDelegate.swift */,
97 | D74D88F72498C16500A0F885 /* Assets.xcassets */,
98 | D74D88FC2498C16500A0F885 /* LaunchScreen.storyboard */,
99 | D74D88FF2498C16500A0F885 /* Info.plist */,
100 | D74D88F92498C16500A0F885 /* Preview Content */,
101 | );
102 | path = MacCatalystBuildTest;
103 | sourceTree = "";
104 | };
105 | D74D88F92498C16500A0F885 /* Preview Content */ = {
106 | isa = PBXGroup;
107 | children = (
108 | D74D88FA2498C16500A0F885 /* Preview Assets.xcassets */,
109 | );
110 | path = "Preview Content";
111 | sourceTree = "";
112 | };
113 | D74D89052498C1A600A0F885 /* Frameworks */ = {
114 | isa = PBXGroup;
115 | children = (
116 | );
117 | name = Frameworks;
118 | sourceTree = "";
119 | };
120 | /* End PBXGroup section */
121 |
122 | /* Begin PBXNativeTarget section */
123 | D74D88E22498C12A00A0F885 /* MacOSBuildTest */ = {
124 | isa = PBXNativeTarget;
125 | buildConfigurationList = D74D88E82498C12A00A0F885 /* Build configuration list for PBXNativeTarget "MacOSBuildTest" */;
126 | buildPhases = (
127 | D74D88DF2498C12A00A0F885 /* Sources */,
128 | D74D88E02498C12A00A0F885 /* Frameworks */,
129 | D74D88E12498C12A00A0F885 /* CopyFiles */,
130 | );
131 | buildRules = (
132 | );
133 | dependencies = (
134 | );
135 | name = MacOSBuildTest;
136 | packageProductDependencies = (
137 | D74D89082498C1AC00A0F885 /* EonilFSEvents */,
138 | );
139 | productName = MacOSBuildTest;
140 | productReference = D74D88E32498C12A00A0F885 /* MacOSBuildTest */;
141 | productType = "com.apple.product-type.tool";
142 | };
143 | D74D88EE2498C16200A0F885 /* MacCatalystBuildTest */ = {
144 | isa = PBXNativeTarget;
145 | buildConfigurationList = D74D89002498C16500A0F885 /* Build configuration list for PBXNativeTarget "MacCatalystBuildTest" */;
146 | buildPhases = (
147 | D74D88EB2498C16200A0F885 /* Sources */,
148 | D74D88EC2498C16200A0F885 /* Frameworks */,
149 | D74D88ED2498C16200A0F885 /* Resources */,
150 | );
151 | buildRules = (
152 | );
153 | dependencies = (
154 | );
155 | name = MacCatalystBuildTest;
156 | packageProductDependencies = (
157 | D74D89062498C1A600A0F885 /* EonilFSEvents */,
158 | );
159 | productName = MacCatalystBuildTest;
160 | productReference = D74D88EF2498C16200A0F885 /* MacCatalystBuildTest.app */;
161 | productType = "com.apple.product-type.application";
162 | };
163 | /* End PBXNativeTarget section */
164 |
165 | /* Begin PBXProject section */
166 | D74D88D92498C10A00A0F885 /* Project object */ = {
167 | isa = PBXProject;
168 | attributes = {
169 | LastSwiftUpdateCheck = 1150;
170 | LastUpgradeCheck = 1150;
171 | TargetAttributes = {
172 | D74D88E22498C12A00A0F885 = {
173 | CreatedOnToolsVersion = 11.5;
174 | };
175 | D74D88EE2498C16200A0F885 = {
176 | CreatedOnToolsVersion = 11.5;
177 | };
178 | };
179 | };
180 | buildConfigurationList = D74D88DC2498C10A00A0F885 /* Build configuration list for PBXProject "BuildTest" */;
181 | compatibilityVersion = "Xcode 9.3";
182 | developmentRegion = en;
183 | hasScannedForEncodings = 0;
184 | knownRegions = (
185 | en,
186 | Base,
187 | );
188 | mainGroup = D74D88D82498C10A00A0F885;
189 | productRefGroup = D74D88E42498C12A00A0F885 /* Products */;
190 | projectDirPath = "";
191 | projectRoot = "";
192 | targets = (
193 | D74D88E22498C12A00A0F885 /* MacOSBuildTest */,
194 | D74D88EE2498C16200A0F885 /* MacCatalystBuildTest */,
195 | );
196 | };
197 | /* End PBXProject section */
198 |
199 | /* Begin PBXResourcesBuildPhase section */
200 | D74D88ED2498C16200A0F885 /* Resources */ = {
201 | isa = PBXResourcesBuildPhase;
202 | buildActionMask = 2147483647;
203 | files = (
204 | D74D88FE2498C16500A0F885 /* LaunchScreen.storyboard in Resources */,
205 | D74D88FB2498C16500A0F885 /* Preview Assets.xcassets in Resources */,
206 | D74D88F82498C16500A0F885 /* Assets.xcassets in Resources */,
207 | );
208 | runOnlyForDeploymentPostprocessing = 0;
209 | };
210 | /* End PBXResourcesBuildPhase section */
211 |
212 | /* Begin PBXSourcesBuildPhase section */
213 | D74D88DF2498C12A00A0F885 /* Sources */ = {
214 | isa = PBXSourcesBuildPhase;
215 | buildActionMask = 2147483647;
216 | files = (
217 | D74D88E72498C12A00A0F885 /* main.swift in Sources */,
218 | );
219 | runOnlyForDeploymentPostprocessing = 0;
220 | };
221 | D74D88EB2498C16200A0F885 /* Sources */ = {
222 | isa = PBXSourcesBuildPhase;
223 | buildActionMask = 2147483647;
224 | files = (
225 | D74D88F22498C16200A0F885 /* AppDelegate.swift in Sources */,
226 | );
227 | runOnlyForDeploymentPostprocessing = 0;
228 | };
229 | /* End PBXSourcesBuildPhase section */
230 |
231 | /* Begin PBXVariantGroup section */
232 | D74D88FC2498C16500A0F885 /* LaunchScreen.storyboard */ = {
233 | isa = PBXVariantGroup;
234 | children = (
235 | D74D88FD2498C16500A0F885 /* Base */,
236 | );
237 | name = LaunchScreen.storyboard;
238 | sourceTree = "";
239 | };
240 | /* End PBXVariantGroup section */
241 |
242 | /* Begin XCBuildConfiguration section */
243 | D74D88DD2498C10A00A0F885 /* Debug */ = {
244 | isa = XCBuildConfiguration;
245 | buildSettings = {
246 | };
247 | name = Debug;
248 | };
249 | D74D88DE2498C10A00A0F885 /* Release */ = {
250 | isa = XCBuildConfiguration;
251 | buildSettings = {
252 | };
253 | name = Release;
254 | };
255 | D74D88E92498C12A00A0F885 /* Debug */ = {
256 | isa = XCBuildConfiguration;
257 | buildSettings = {
258 | ALWAYS_SEARCH_USER_PATHS = NO;
259 | CLANG_ANALYZER_NONNULL = YES;
260 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
261 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
262 | CLANG_CXX_LIBRARY = "libc++";
263 | CLANG_ENABLE_MODULES = YES;
264 | CLANG_ENABLE_OBJC_ARC = YES;
265 | CLANG_ENABLE_OBJC_WEAK = YES;
266 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
267 | CLANG_WARN_BOOL_CONVERSION = YES;
268 | CLANG_WARN_COMMA = YES;
269 | CLANG_WARN_CONSTANT_CONVERSION = YES;
270 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
271 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
272 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
273 | CLANG_WARN_EMPTY_BODY = YES;
274 | CLANG_WARN_ENUM_CONVERSION = YES;
275 | CLANG_WARN_INFINITE_RECURSION = YES;
276 | CLANG_WARN_INT_CONVERSION = YES;
277 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
278 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
279 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
280 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
281 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
282 | CLANG_WARN_STRICT_PROTOTYPES = YES;
283 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
284 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
285 | CLANG_WARN_UNREACHABLE_CODE = YES;
286 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
287 | CODE_SIGN_STYLE = Automatic;
288 | COPY_PHASE_STRIP = NO;
289 | DEBUG_INFORMATION_FORMAT = dwarf;
290 | ENABLE_STRICT_OBJC_MSGSEND = YES;
291 | ENABLE_TESTABILITY = YES;
292 | GCC_C_LANGUAGE_STANDARD = gnu11;
293 | GCC_DYNAMIC_NO_PIC = NO;
294 | GCC_NO_COMMON_BLOCKS = YES;
295 | GCC_OPTIMIZATION_LEVEL = 0;
296 | GCC_PREPROCESSOR_DEFINITIONS = (
297 | "DEBUG=1",
298 | "$(inherited)",
299 | );
300 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
301 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
302 | GCC_WARN_UNDECLARED_SELECTOR = YES;
303 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
304 | GCC_WARN_UNUSED_FUNCTION = YES;
305 | GCC_WARN_UNUSED_VARIABLE = YES;
306 | MACOSX_DEPLOYMENT_TARGET = 10.15;
307 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
308 | MTL_FAST_MATH = YES;
309 | ONLY_ACTIVE_ARCH = YES;
310 | PRODUCT_NAME = "$(TARGET_NAME)";
311 | SDKROOT = macosx;
312 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
313 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
314 | SWIFT_VERSION = 5.0;
315 | };
316 | name = Debug;
317 | };
318 | D74D88EA2498C12A00A0F885 /* Release */ = {
319 | isa = XCBuildConfiguration;
320 | buildSettings = {
321 | ALWAYS_SEARCH_USER_PATHS = NO;
322 | CLANG_ANALYZER_NONNULL = YES;
323 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
324 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
325 | CLANG_CXX_LIBRARY = "libc++";
326 | CLANG_ENABLE_MODULES = YES;
327 | CLANG_ENABLE_OBJC_ARC = YES;
328 | CLANG_ENABLE_OBJC_WEAK = YES;
329 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
330 | CLANG_WARN_BOOL_CONVERSION = YES;
331 | CLANG_WARN_COMMA = YES;
332 | CLANG_WARN_CONSTANT_CONVERSION = YES;
333 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
334 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
335 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
336 | CLANG_WARN_EMPTY_BODY = YES;
337 | CLANG_WARN_ENUM_CONVERSION = YES;
338 | CLANG_WARN_INFINITE_RECURSION = YES;
339 | CLANG_WARN_INT_CONVERSION = YES;
340 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
341 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
342 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
343 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
344 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
345 | CLANG_WARN_STRICT_PROTOTYPES = YES;
346 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
347 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
348 | CLANG_WARN_UNREACHABLE_CODE = YES;
349 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
350 | CODE_SIGN_STYLE = Automatic;
351 | COPY_PHASE_STRIP = NO;
352 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
353 | ENABLE_NS_ASSERTIONS = NO;
354 | ENABLE_STRICT_OBJC_MSGSEND = YES;
355 | GCC_C_LANGUAGE_STANDARD = gnu11;
356 | GCC_NO_COMMON_BLOCKS = YES;
357 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
358 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
359 | GCC_WARN_UNDECLARED_SELECTOR = YES;
360 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
361 | GCC_WARN_UNUSED_FUNCTION = YES;
362 | GCC_WARN_UNUSED_VARIABLE = YES;
363 | MACOSX_DEPLOYMENT_TARGET = 10.15;
364 | MTL_ENABLE_DEBUG_INFO = NO;
365 | MTL_FAST_MATH = YES;
366 | PRODUCT_NAME = "$(TARGET_NAME)";
367 | SDKROOT = macosx;
368 | SWIFT_COMPILATION_MODE = wholemodule;
369 | SWIFT_OPTIMIZATION_LEVEL = "-O";
370 | SWIFT_VERSION = 5.0;
371 | };
372 | name = Release;
373 | };
374 | D74D89012498C16500A0F885 /* Debug */ = {
375 | isa = XCBuildConfiguration;
376 | buildSettings = {
377 | ALWAYS_SEARCH_USER_PATHS = NO;
378 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
379 | CLANG_ANALYZER_NONNULL = YES;
380 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
381 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
382 | CLANG_CXX_LIBRARY = "libc++";
383 | CLANG_ENABLE_MODULES = YES;
384 | CLANG_ENABLE_OBJC_ARC = YES;
385 | CLANG_ENABLE_OBJC_WEAK = YES;
386 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
387 | CLANG_WARN_BOOL_CONVERSION = YES;
388 | CLANG_WARN_COMMA = YES;
389 | CLANG_WARN_CONSTANT_CONVERSION = YES;
390 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
391 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
392 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
393 | CLANG_WARN_EMPTY_BODY = YES;
394 | CLANG_WARN_ENUM_CONVERSION = YES;
395 | CLANG_WARN_INFINITE_RECURSION = YES;
396 | CLANG_WARN_INT_CONVERSION = YES;
397 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
398 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
399 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
400 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
401 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
402 | CLANG_WARN_STRICT_PROTOTYPES = YES;
403 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
404 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
405 | CLANG_WARN_UNREACHABLE_CODE = YES;
406 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
407 | CODE_SIGN_ENTITLEMENTS = MacCatalystBuildTest/MacCatalystBuildTest.entitlements;
408 | CODE_SIGN_IDENTITY = "Apple Development";
409 | "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
410 | CODE_SIGN_STYLE = Manual;
411 | COPY_PHASE_STRIP = NO;
412 | DEBUG_INFORMATION_FORMAT = dwarf;
413 | DEVELOPMENT_ASSET_PATHS = "\"MacCatalystBuildTest/Preview Content\"";
414 | DEVELOPMENT_TEAM = "";
415 | ENABLE_PREVIEWS = YES;
416 | ENABLE_STRICT_OBJC_MSGSEND = YES;
417 | ENABLE_TESTABILITY = YES;
418 | GCC_C_LANGUAGE_STANDARD = gnu11;
419 | GCC_DYNAMIC_NO_PIC = NO;
420 | GCC_NO_COMMON_BLOCKS = YES;
421 | GCC_OPTIMIZATION_LEVEL = 0;
422 | GCC_PREPROCESSOR_DEFINITIONS = (
423 | "DEBUG=1",
424 | "$(inherited)",
425 | );
426 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
427 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
428 | GCC_WARN_UNDECLARED_SELECTOR = YES;
429 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
430 | GCC_WARN_UNUSED_FUNCTION = YES;
431 | GCC_WARN_UNUSED_VARIABLE = YES;
432 | INFOPLIST_FILE = MacCatalystBuildTest/Info.plist;
433 | IPHONEOS_DEPLOYMENT_TARGET = 13.4;
434 | LD_RUNPATH_SEARCH_PATHS = (
435 | "$(inherited)",
436 | "@executable_path/Frameworks",
437 | );
438 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
439 | MTL_FAST_MATH = YES;
440 | ONLY_ACTIVE_ARCH = YES;
441 | PRODUCT_BUNDLE_IDENTIFIER = Eonil.MacCatalystBuildTest;
442 | PRODUCT_NAME = "$(TARGET_NAME)";
443 | PROVISIONING_PROFILE_SPECIFIER = "";
444 | "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = "";
445 | SDKROOT = iphoneos;
446 | SUPPORTS_MACCATALYST = YES;
447 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
448 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
449 | SWIFT_VERSION = 5.0;
450 | TARGETED_DEVICE_FAMILY = 2;
451 | };
452 | name = Debug;
453 | };
454 | D74D89022498C16500A0F885 /* Release */ = {
455 | isa = XCBuildConfiguration;
456 | buildSettings = {
457 | ALWAYS_SEARCH_USER_PATHS = NO;
458 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
459 | CLANG_ANALYZER_NONNULL = YES;
460 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
461 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
462 | CLANG_CXX_LIBRARY = "libc++";
463 | CLANG_ENABLE_MODULES = YES;
464 | CLANG_ENABLE_OBJC_ARC = YES;
465 | CLANG_ENABLE_OBJC_WEAK = YES;
466 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
467 | CLANG_WARN_BOOL_CONVERSION = YES;
468 | CLANG_WARN_COMMA = YES;
469 | CLANG_WARN_CONSTANT_CONVERSION = YES;
470 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
471 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
472 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
473 | CLANG_WARN_EMPTY_BODY = YES;
474 | CLANG_WARN_ENUM_CONVERSION = YES;
475 | CLANG_WARN_INFINITE_RECURSION = YES;
476 | CLANG_WARN_INT_CONVERSION = YES;
477 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
478 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
479 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
480 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
481 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
482 | CLANG_WARN_STRICT_PROTOTYPES = YES;
483 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
484 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
485 | CLANG_WARN_UNREACHABLE_CODE = YES;
486 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
487 | CODE_SIGN_ENTITLEMENTS = MacCatalystBuildTest/MacCatalystBuildTest.entitlements;
488 | CODE_SIGN_IDENTITY = "Apple Development";
489 | "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
490 | CODE_SIGN_STYLE = Manual;
491 | COPY_PHASE_STRIP = NO;
492 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
493 | DEVELOPMENT_ASSET_PATHS = "\"MacCatalystBuildTest/Preview Content\"";
494 | DEVELOPMENT_TEAM = "";
495 | ENABLE_NS_ASSERTIONS = NO;
496 | ENABLE_PREVIEWS = YES;
497 | ENABLE_STRICT_OBJC_MSGSEND = YES;
498 | GCC_C_LANGUAGE_STANDARD = gnu11;
499 | GCC_NO_COMMON_BLOCKS = YES;
500 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
501 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
502 | GCC_WARN_UNDECLARED_SELECTOR = YES;
503 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
504 | GCC_WARN_UNUSED_FUNCTION = YES;
505 | GCC_WARN_UNUSED_VARIABLE = YES;
506 | INFOPLIST_FILE = MacCatalystBuildTest/Info.plist;
507 | IPHONEOS_DEPLOYMENT_TARGET = 13.4;
508 | LD_RUNPATH_SEARCH_PATHS = (
509 | "$(inherited)",
510 | "@executable_path/Frameworks",
511 | );
512 | MTL_ENABLE_DEBUG_INFO = NO;
513 | MTL_FAST_MATH = YES;
514 | PRODUCT_BUNDLE_IDENTIFIER = Eonil.MacCatalystBuildTest;
515 | PRODUCT_NAME = "$(TARGET_NAME)";
516 | PROVISIONING_PROFILE_SPECIFIER = "";
517 | "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = "";
518 | SDKROOT = iphoneos;
519 | SUPPORTS_MACCATALYST = YES;
520 | SWIFT_COMPILATION_MODE = wholemodule;
521 | SWIFT_OPTIMIZATION_LEVEL = "-O";
522 | SWIFT_VERSION = 5.0;
523 | TARGETED_DEVICE_FAMILY = 2;
524 | VALIDATE_PRODUCT = YES;
525 | };
526 | name = Release;
527 | };
528 | /* End XCBuildConfiguration section */
529 |
530 | /* Begin XCConfigurationList section */
531 | D74D88DC2498C10A00A0F885 /* Build configuration list for PBXProject "BuildTest" */ = {
532 | isa = XCConfigurationList;
533 | buildConfigurations = (
534 | D74D88DD2498C10A00A0F885 /* Debug */,
535 | D74D88DE2498C10A00A0F885 /* Release */,
536 | );
537 | defaultConfigurationIsVisible = 0;
538 | defaultConfigurationName = Release;
539 | };
540 | D74D88E82498C12A00A0F885 /* Build configuration list for PBXNativeTarget "MacOSBuildTest" */ = {
541 | isa = XCConfigurationList;
542 | buildConfigurations = (
543 | D74D88E92498C12A00A0F885 /* Debug */,
544 | D74D88EA2498C12A00A0F885 /* Release */,
545 | );
546 | defaultConfigurationIsVisible = 0;
547 | defaultConfigurationName = Release;
548 | };
549 | D74D89002498C16500A0F885 /* Build configuration list for PBXNativeTarget "MacCatalystBuildTest" */ = {
550 | isa = XCConfigurationList;
551 | buildConfigurations = (
552 | D74D89012498C16500A0F885 /* Debug */,
553 | D74D89022498C16500A0F885 /* Release */,
554 | );
555 | defaultConfigurationIsVisible = 0;
556 | defaultConfigurationName = Release;
557 | };
558 | /* End XCConfigurationList section */
559 |
560 | /* Begin XCSwiftPackageProductDependency section */
561 | D74D89062498C1A600A0F885 /* EonilFSEvents */ = {
562 | isa = XCSwiftPackageProductDependency;
563 | productName = EonilFSEvents;
564 | };
565 | D74D89082498C1AC00A0F885 /* EonilFSEvents */ = {
566 | isa = XCSwiftPackageProductDependency;
567 | productName = EonilFSEvents;
568 | };
569 | /* End XCSwiftPackageProductDependency section */
570 | };
571 | rootObject = D74D88D92498C10A00A0F885 /* Project object */;
572 | }
573 |
--------------------------------------------------------------------------------
/BuildTest/BuildTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/BuildTest/BuildTest.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/BuildTest/MacCatalystBuildTest/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // MacCatalystBuildTest
4 | //
5 | // Created by Henry Hathaway on 6/16/20.
6 | //
7 |
8 | import UIKit
9 |
10 | @UIApplicationMain
11 | class AppDelegate: UIResponder, UIApplicationDelegate {
12 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
13 | true
14 | }
15 | }
16 |
17 |
--------------------------------------------------------------------------------
/BuildTest/MacCatalystBuildTest/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "scale" : "2x",
6 | "size" : "20x20"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "scale" : "3x",
11 | "size" : "20x20"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "scale" : "2x",
16 | "size" : "29x29"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "scale" : "3x",
21 | "size" : "29x29"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "scale" : "2x",
26 | "size" : "40x40"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "scale" : "3x",
31 | "size" : "40x40"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "scale" : "2x",
36 | "size" : "60x60"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "scale" : "3x",
41 | "size" : "60x60"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "scale" : "1x",
46 | "size" : "20x20"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "scale" : "2x",
51 | "size" : "20x20"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "scale" : "1x",
56 | "size" : "29x29"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "scale" : "2x",
61 | "size" : "29x29"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "scale" : "1x",
66 | "size" : "40x40"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "scale" : "2x",
71 | "size" : "40x40"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "scale" : "1x",
76 | "size" : "76x76"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "scale" : "2x",
81 | "size" : "76x76"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "scale" : "2x",
86 | "size" : "83.5x83.5"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "scale" : "1x",
91 | "size" : "1024x1024"
92 | }
93 | ],
94 | "info" : {
95 | "author" : "xcode",
96 | "version" : 1
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/BuildTest/MacCatalystBuildTest/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/BuildTest/MacCatalystBuildTest/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/BuildTest/MacCatalystBuildTest/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | UIApplicationSceneManifest
24 |
25 | UIApplicationSupportsMultipleScenes
26 |
27 | UISceneConfigurations
28 |
29 | UIWindowSceneSessionRoleApplication
30 |
31 |
32 | UISceneConfigurationName
33 | Default Configuration
34 | UISceneDelegateClassName
35 | $(PRODUCT_MODULE_NAME).SceneDelegate
36 |
37 |
38 |
39 |
40 | UILaunchStoryboardName
41 | LaunchScreen
42 | UIRequiredDeviceCapabilities
43 |
44 | armv7
45 |
46 | UISupportedInterfaceOrientations
47 |
48 | UIInterfaceOrientationPortrait
49 | UIInterfaceOrientationLandscapeLeft
50 | UIInterfaceOrientationLandscapeRight
51 |
52 | UISupportedInterfaceOrientations~ipad
53 |
54 | UIInterfaceOrientationPortrait
55 | UIInterfaceOrientationPortraitUpsideDown
56 | UIInterfaceOrientationLandscapeLeft
57 | UIInterfaceOrientationLandscapeRight
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/BuildTest/MacCatalystBuildTest/MacCatalystBuildTest.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 | com.apple.security.network.client
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/BuildTest/MacCatalystBuildTest/Preview Content/Preview Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/BuildTest/MacOSBuildTest/main.swift:
--------------------------------------------------------------------------------
1 | //
2 | // main.swift
3 | // MacOSBuildTest
4 | //
5 | // Created by Henry Hathaway on 6/16/20.
6 | //
7 |
8 | import Foundation
9 |
10 | print("Hello, World!")
11 |
12 |
--------------------------------------------------------------------------------
/EonilFSEventsDemoGUI/EonilFSEventsDemoGUI.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 52;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 4513D3E521D533BE0070A7A5 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4513D3E421D533BE0070A7A5 /* AppDelegate.swift */; };
11 | 4513D3E721D533BE0070A7A5 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4513D3E621D533BE0070A7A5 /* ViewController.swift */; };
12 | 4513D3E921D533C00070A7A5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4513D3E821D533C00070A7A5 /* Assets.xcassets */; };
13 | 4513D3EC21D533C00070A7A5 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4513D3EA21D533C00070A7A5 /* Main.storyboard */; };
14 | BA53C7BB232B904E00838304 /* EonilFSEvents in Frameworks */ = {isa = PBXBuildFile; productRef = BA53C7BA232B904E00838304 /* EonilFSEvents */; };
15 | /* End PBXBuildFile section */
16 |
17 | /* Begin PBXFileReference section */
18 | 4513D3E221D533BE0070A7A5 /* EonilFSEventsDemoGUI.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = EonilFSEventsDemoGUI.app; sourceTree = BUILT_PRODUCTS_DIR; };
19 | 4513D3E421D533BE0070A7A5 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
20 | 4513D3E621D533BE0070A7A5 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
21 | 4513D3E821D533C00070A7A5 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
22 | 4513D3EB21D533C00070A7A5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
23 | 4513D3ED21D533C00070A7A5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
24 | 4513D3EE21D533C00070A7A5 /* EonilFSEventsDemoGUI.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = EonilFSEventsDemoGUI.entitlements; sourceTree = ""; };
25 | 4513D42421D55AB30070A7A5 /* libFSEventUnofficialWrapperStream.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libFSEventUnofficialWrapperStream.a; sourceTree = BUILT_PRODUCTS_DIR; };
26 | 4513D42621D55AB70070A7A5 /* libFSEventUnofficialWrapperStream.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libFSEventUnofficialWrapperStream.a; sourceTree = BUILT_PRODUCTS_DIR; };
27 | D7675AB023457A86002AC0F7 /* FSEvents */ = {isa = PBXFileReference; lastKnownFileType = folder; name = FSEvents; path = ..; sourceTree = ""; };
28 | /* End PBXFileReference section */
29 |
30 | /* Begin PBXFrameworksBuildPhase section */
31 | 4513D3DF21D533BE0070A7A5 /* Frameworks */ = {
32 | isa = PBXFrameworksBuildPhase;
33 | buildActionMask = 2147483647;
34 | files = (
35 | BA53C7BB232B904E00838304 /* EonilFSEvents in Frameworks */,
36 | );
37 | runOnlyForDeploymentPostprocessing = 0;
38 | };
39 | /* End PBXFrameworksBuildPhase section */
40 |
41 | /* Begin PBXGroup section */
42 | 4513D3CB21D5334D0070A7A5 = {
43 | isa = PBXGroup;
44 | children = (
45 | D7675AB023457A86002AC0F7 /* FSEvents */,
46 | 4513D3E321D533BE0070A7A5 /* EonilFSEventsDemoGUI */,
47 | 4513D3D721D533B20070A7A5 /* Products */,
48 | 4513D41F21D533EB0070A7A5 /* Frameworks */,
49 | );
50 | sourceTree = "";
51 | };
52 | 4513D3D721D533B20070A7A5 /* Products */ = {
53 | isa = PBXGroup;
54 | children = (
55 | 4513D3E221D533BE0070A7A5 /* EonilFSEventsDemoGUI.app */,
56 | );
57 | name = Products;
58 | sourceTree = "";
59 | };
60 | 4513D3E321D533BE0070A7A5 /* EonilFSEventsDemoGUI */ = {
61 | isa = PBXGroup;
62 | children = (
63 | 4513D3E421D533BE0070A7A5 /* AppDelegate.swift */,
64 | 4513D3E621D533BE0070A7A5 /* ViewController.swift */,
65 | 4513D3E821D533C00070A7A5 /* Assets.xcassets */,
66 | 4513D3EA21D533C00070A7A5 /* Main.storyboard */,
67 | 4513D3ED21D533C00070A7A5 /* Info.plist */,
68 | 4513D3EE21D533C00070A7A5 /* EonilFSEventsDemoGUI.entitlements */,
69 | );
70 | path = EonilFSEventsDemoGUI;
71 | sourceTree = "";
72 | };
73 | 4513D41F21D533EB0070A7A5 /* Frameworks */ = {
74 | isa = PBXGroup;
75 | children = (
76 | 4513D42621D55AB70070A7A5 /* libFSEventUnofficialWrapperStream.a */,
77 | 4513D42421D55AB30070A7A5 /* libFSEventUnofficialWrapperStream.a */,
78 | );
79 | name = Frameworks;
80 | sourceTree = "";
81 | };
82 | /* End PBXGroup section */
83 |
84 | /* Begin PBXNativeTarget section */
85 | 4513D3E121D533BE0070A7A5 /* EonilFSEventsDemoGUI */ = {
86 | isa = PBXNativeTarget;
87 | buildConfigurationList = 4513D40521D533C00070A7A5 /* Build configuration list for PBXNativeTarget "EonilFSEventsDemoGUI" */;
88 | buildPhases = (
89 | 4513D3DE21D533BE0070A7A5 /* Sources */,
90 | 4513D3DF21D533BE0070A7A5 /* Frameworks */,
91 | 4513D3E021D533BE0070A7A5 /* Resources */,
92 | );
93 | buildRules = (
94 | );
95 | dependencies = (
96 | );
97 | name = EonilFSEventsDemoGUI;
98 | packageProductDependencies = (
99 | BA53C7BA232B904E00838304 /* EonilFSEvents */,
100 | );
101 | productName = FileSystemWatcherDemoGUI;
102 | productReference = 4513D3E221D533BE0070A7A5 /* EonilFSEventsDemoGUI.app */;
103 | productType = "com.apple.product-type.application";
104 | };
105 | /* End PBXNativeTarget section */
106 |
107 | /* Begin PBXProject section */
108 | 4513D3CC21D5334D0070A7A5 /* Project object */ = {
109 | isa = PBXProject;
110 | attributes = {
111 | LastSwiftUpdateCheck = 1010;
112 | LastUpgradeCheck = 1100;
113 | TargetAttributes = {
114 | 4513D3E121D533BE0070A7A5 = {
115 | CreatedOnToolsVersion = 10.1;
116 | LastSwiftMigration = 1100;
117 | SystemCapabilities = {
118 | com.apple.Sandbox = {
119 | enabled = 0;
120 | };
121 | };
122 | };
123 | };
124 | };
125 | buildConfigurationList = 4513D3CF21D5334D0070A7A5 /* Build configuration list for PBXProject "EonilFSEventsDemoGUI" */;
126 | compatibilityVersion = "Xcode 9.3";
127 | developmentRegion = en;
128 | hasScannedForEncodings = 0;
129 | knownRegions = (
130 | en,
131 | Base,
132 | );
133 | mainGroup = 4513D3CB21D5334D0070A7A5;
134 | productRefGroup = 4513D3D721D533B20070A7A5 /* Products */;
135 | projectDirPath = "";
136 | projectRoot = "";
137 | targets = (
138 | 4513D3E121D533BE0070A7A5 /* EonilFSEventsDemoGUI */,
139 | );
140 | };
141 | /* End PBXProject section */
142 |
143 | /* Begin PBXResourcesBuildPhase section */
144 | 4513D3E021D533BE0070A7A5 /* Resources */ = {
145 | isa = PBXResourcesBuildPhase;
146 | buildActionMask = 2147483647;
147 | files = (
148 | 4513D3E921D533C00070A7A5 /* Assets.xcassets in Resources */,
149 | 4513D3EC21D533C00070A7A5 /* Main.storyboard in Resources */,
150 | );
151 | runOnlyForDeploymentPostprocessing = 0;
152 | };
153 | /* End PBXResourcesBuildPhase section */
154 |
155 | /* Begin PBXSourcesBuildPhase section */
156 | 4513D3DE21D533BE0070A7A5 /* Sources */ = {
157 | isa = PBXSourcesBuildPhase;
158 | buildActionMask = 2147483647;
159 | files = (
160 | 4513D3E721D533BE0070A7A5 /* ViewController.swift in Sources */,
161 | 4513D3E521D533BE0070A7A5 /* AppDelegate.swift in Sources */,
162 | );
163 | runOnlyForDeploymentPostprocessing = 0;
164 | };
165 | /* End PBXSourcesBuildPhase section */
166 |
167 | /* Begin PBXVariantGroup section */
168 | 4513D3EA21D533C00070A7A5 /* Main.storyboard */ = {
169 | isa = PBXVariantGroup;
170 | children = (
171 | 4513D3EB21D533C00070A7A5 /* Base */,
172 | );
173 | name = Main.storyboard;
174 | sourceTree = "";
175 | };
176 | /* End PBXVariantGroup section */
177 |
178 | /* Begin XCBuildConfiguration section */
179 | 4513D3D021D5334D0070A7A5 /* Debug */ = {
180 | isa = XCBuildConfiguration;
181 | buildSettings = {
182 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
183 | CLANG_WARN_BOOL_CONVERSION = YES;
184 | CLANG_WARN_COMMA = YES;
185 | CLANG_WARN_CONSTANT_CONVERSION = YES;
186 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
187 | CLANG_WARN_EMPTY_BODY = YES;
188 | CLANG_WARN_ENUM_CONVERSION = YES;
189 | CLANG_WARN_INFINITE_RECURSION = YES;
190 | CLANG_WARN_INT_CONVERSION = YES;
191 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
192 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
193 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
194 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
195 | CLANG_WARN_STRICT_PROTOTYPES = YES;
196 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
197 | CLANG_WARN_UNREACHABLE_CODE = YES;
198 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
199 | ENABLE_STRICT_OBJC_MSGSEND = YES;
200 | ENABLE_TESTABILITY = YES;
201 | GCC_NO_COMMON_BLOCKS = YES;
202 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
203 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
204 | GCC_WARN_UNDECLARED_SELECTOR = YES;
205 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
206 | GCC_WARN_UNUSED_FUNCTION = YES;
207 | GCC_WARN_UNUSED_VARIABLE = YES;
208 | ONLY_ACTIVE_ARCH = YES;
209 | };
210 | name = Debug;
211 | };
212 | 4513D3D121D5334D0070A7A5 /* Release */ = {
213 | isa = XCBuildConfiguration;
214 | buildSettings = {
215 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
216 | CLANG_WARN_BOOL_CONVERSION = YES;
217 | CLANG_WARN_COMMA = YES;
218 | CLANG_WARN_CONSTANT_CONVERSION = YES;
219 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
220 | CLANG_WARN_EMPTY_BODY = YES;
221 | CLANG_WARN_ENUM_CONVERSION = YES;
222 | CLANG_WARN_INFINITE_RECURSION = YES;
223 | CLANG_WARN_INT_CONVERSION = YES;
224 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
225 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
226 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
227 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
228 | CLANG_WARN_STRICT_PROTOTYPES = YES;
229 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
230 | CLANG_WARN_UNREACHABLE_CODE = YES;
231 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
232 | ENABLE_STRICT_OBJC_MSGSEND = YES;
233 | GCC_NO_COMMON_BLOCKS = YES;
234 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
235 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
236 | GCC_WARN_UNDECLARED_SELECTOR = YES;
237 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
238 | GCC_WARN_UNUSED_FUNCTION = YES;
239 | GCC_WARN_UNUSED_VARIABLE = YES;
240 | };
241 | name = Release;
242 | };
243 | 4513D40621D533C00070A7A5 /* Debug */ = {
244 | isa = XCBuildConfiguration;
245 | buildSettings = {
246 | ALWAYS_SEARCH_USER_PATHS = NO;
247 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
248 | CLANG_ANALYZER_NONNULL = YES;
249 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
250 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
251 | CLANG_CXX_LIBRARY = "libc++";
252 | CLANG_ENABLE_MODULES = YES;
253 | CLANG_ENABLE_OBJC_ARC = YES;
254 | CLANG_ENABLE_OBJC_WEAK = YES;
255 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
256 | CLANG_WARN_BOOL_CONVERSION = YES;
257 | CLANG_WARN_COMMA = YES;
258 | CLANG_WARN_CONSTANT_CONVERSION = YES;
259 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
260 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
261 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
262 | CLANG_WARN_EMPTY_BODY = YES;
263 | CLANG_WARN_ENUM_CONVERSION = YES;
264 | CLANG_WARN_INFINITE_RECURSION = YES;
265 | CLANG_WARN_INT_CONVERSION = YES;
266 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
267 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
268 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
269 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
270 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
271 | CLANG_WARN_STRICT_PROTOTYPES = YES;
272 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
273 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
274 | CLANG_WARN_UNREACHABLE_CODE = YES;
275 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
276 | CODE_SIGN_STYLE = Manual;
277 | COMBINE_HIDPI_IMAGES = YES;
278 | COPY_PHASE_STRIP = NO;
279 | DEBUG_INFORMATION_FORMAT = dwarf;
280 | ENABLE_STRICT_OBJC_MSGSEND = YES;
281 | ENABLE_TESTABILITY = YES;
282 | GCC_C_LANGUAGE_STANDARD = gnu11;
283 | GCC_DYNAMIC_NO_PIC = NO;
284 | GCC_NO_COMMON_BLOCKS = YES;
285 | GCC_OPTIMIZATION_LEVEL = 0;
286 | GCC_PREPROCESSOR_DEFINITIONS = (
287 | "DEBUG=1",
288 | "$(inherited)",
289 | );
290 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
291 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
292 | GCC_WARN_UNDECLARED_SELECTOR = YES;
293 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
294 | GCC_WARN_UNUSED_FUNCTION = YES;
295 | GCC_WARN_UNUSED_VARIABLE = YES;
296 | INFOPLIST_FILE = EonilFSEventsDemoGUI/Info.plist;
297 | LD_RUNPATH_SEARCH_PATHS = (
298 | "$(inherited)",
299 | "@executable_path/../Frameworks",
300 | );
301 | MACOSX_DEPLOYMENT_TARGET = 10.14;
302 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
303 | MTL_FAST_MATH = YES;
304 | ONLY_ACTIVE_ARCH = YES;
305 | PRODUCT_BUNDLE_IDENTIFIER = Eonil.FSEventsDemoGUI;
306 | PRODUCT_NAME = "$(TARGET_NAME)";
307 | SDKROOT = macosx;
308 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
309 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
310 | SWIFT_VERSION = 5.0;
311 | };
312 | name = Debug;
313 | };
314 | 4513D40721D533C00070A7A5 /* Release */ = {
315 | isa = XCBuildConfiguration;
316 | buildSettings = {
317 | ALWAYS_SEARCH_USER_PATHS = NO;
318 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
319 | CLANG_ANALYZER_NONNULL = YES;
320 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
321 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
322 | CLANG_CXX_LIBRARY = "libc++";
323 | CLANG_ENABLE_MODULES = YES;
324 | CLANG_ENABLE_OBJC_ARC = YES;
325 | CLANG_ENABLE_OBJC_WEAK = YES;
326 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
327 | CLANG_WARN_BOOL_CONVERSION = YES;
328 | CLANG_WARN_COMMA = YES;
329 | CLANG_WARN_CONSTANT_CONVERSION = YES;
330 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
331 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
332 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
333 | CLANG_WARN_EMPTY_BODY = YES;
334 | CLANG_WARN_ENUM_CONVERSION = YES;
335 | CLANG_WARN_INFINITE_RECURSION = YES;
336 | CLANG_WARN_INT_CONVERSION = YES;
337 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
338 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
339 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
340 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
341 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
342 | CLANG_WARN_STRICT_PROTOTYPES = YES;
343 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
344 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
345 | CLANG_WARN_UNREACHABLE_CODE = YES;
346 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
347 | CODE_SIGN_STYLE = Manual;
348 | COMBINE_HIDPI_IMAGES = YES;
349 | COPY_PHASE_STRIP = NO;
350 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
351 | ENABLE_NS_ASSERTIONS = NO;
352 | ENABLE_STRICT_OBJC_MSGSEND = YES;
353 | GCC_C_LANGUAGE_STANDARD = gnu11;
354 | GCC_NO_COMMON_BLOCKS = YES;
355 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
356 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
357 | GCC_WARN_UNDECLARED_SELECTOR = YES;
358 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
359 | GCC_WARN_UNUSED_FUNCTION = YES;
360 | GCC_WARN_UNUSED_VARIABLE = YES;
361 | INFOPLIST_FILE = EonilFSEventsDemoGUI/Info.plist;
362 | LD_RUNPATH_SEARCH_PATHS = (
363 | "$(inherited)",
364 | "@executable_path/../Frameworks",
365 | );
366 | MACOSX_DEPLOYMENT_TARGET = 10.14;
367 | MTL_ENABLE_DEBUG_INFO = NO;
368 | MTL_FAST_MATH = YES;
369 | PRODUCT_BUNDLE_IDENTIFIER = Eonil.FSEventsDemoGUI;
370 | PRODUCT_NAME = "$(TARGET_NAME)";
371 | SDKROOT = macosx;
372 | SWIFT_COMPILATION_MODE = wholemodule;
373 | SWIFT_OPTIMIZATION_LEVEL = "-O";
374 | SWIFT_VERSION = 5.0;
375 | };
376 | name = Release;
377 | };
378 | /* End XCBuildConfiguration section */
379 |
380 | /* Begin XCConfigurationList section */
381 | 4513D3CF21D5334D0070A7A5 /* Build configuration list for PBXProject "EonilFSEventsDemoGUI" */ = {
382 | isa = XCConfigurationList;
383 | buildConfigurations = (
384 | 4513D3D021D5334D0070A7A5 /* Debug */,
385 | 4513D3D121D5334D0070A7A5 /* Release */,
386 | );
387 | defaultConfigurationIsVisible = 0;
388 | defaultConfigurationName = Release;
389 | };
390 | 4513D40521D533C00070A7A5 /* Build configuration list for PBXNativeTarget "EonilFSEventsDemoGUI" */ = {
391 | isa = XCConfigurationList;
392 | buildConfigurations = (
393 | 4513D40621D533C00070A7A5 /* Debug */,
394 | 4513D40721D533C00070A7A5 /* Release */,
395 | );
396 | defaultConfigurationIsVisible = 0;
397 | defaultConfigurationName = Release;
398 | };
399 | /* End XCConfigurationList section */
400 |
401 | /* Begin XCSwiftPackageProductDependency section */
402 | BA53C7BA232B904E00838304 /* EonilFSEvents */ = {
403 | isa = XCSwiftPackageProductDependency;
404 | productName = EonilFSEvents;
405 | };
406 | /* End XCSwiftPackageProductDependency section */
407 | };
408 | rootObject = 4513D3CC21D5334D0070A7A5 /* Project object */;
409 | }
410 |
--------------------------------------------------------------------------------
/EonilFSEventsDemoGUI/EonilFSEventsDemoGUI.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/EonilFSEventsDemoGUI/EonilFSEventsDemoGUI.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/EonilFSEventsDemoGUI/EonilFSEventsDemoGUI.xcodeproj/xcshareddata/xcschemes/EonilFSEventsDemoGUI.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
45 |
51 |
52 |
53 |
54 |
60 |
62 |
68 |
69 |
70 |
71 |
73 |
74 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/EonilFSEventsDemoGUI/EonilFSEventsDemoGUI/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // EonilFSEventsDemoGUI
4 | //
5 | // Created by Henry on 2018/12/27.
6 | //
7 |
8 | import Cocoa
9 |
10 | @NSApplicationMain
11 | class AppDelegate: NSObject, NSApplicationDelegate {}
12 |
13 |
--------------------------------------------------------------------------------
/EonilFSEventsDemoGUI/EonilFSEventsDemoGUI/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "size" : "16x16",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "size" : "16x16",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "mac",
15 | "size" : "32x32",
16 | "scale" : "1x"
17 | },
18 | {
19 | "idiom" : "mac",
20 | "size" : "32x32",
21 | "scale" : "2x"
22 | },
23 | {
24 | "idiom" : "mac",
25 | "size" : "128x128",
26 | "scale" : "1x"
27 | },
28 | {
29 | "idiom" : "mac",
30 | "size" : "128x128",
31 | "scale" : "2x"
32 | },
33 | {
34 | "idiom" : "mac",
35 | "size" : "256x256",
36 | "scale" : "1x"
37 | },
38 | {
39 | "idiom" : "mac",
40 | "size" : "256x256",
41 | "scale" : "2x"
42 | },
43 | {
44 | "idiom" : "mac",
45 | "size" : "512x512",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "mac",
50 | "size" : "512x512",
51 | "scale" : "2x"
52 | }
53 | ],
54 | "info" : {
55 | "version" : 1,
56 | "author" : "xcode"
57 | }
58 | }
--------------------------------------------------------------------------------
/EonilFSEventsDemoGUI/EonilFSEventsDemoGUI/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/EonilFSEventsDemoGUI/EonilFSEventsDemoGUI/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
673 |
674 |
675 |
676 |
677 |
678 |
679 |
680 |
681 |
682 |
683 |
684 |
685 |
686 |
687 |
688 |
689 |
690 |
691 |
692 |
693 |
694 |
695 |
696 |
697 |
698 |
699 |
700 |
701 |
702 |
703 |
704 |
705 |
706 |
707 |
708 |
709 |
710 |
711 |
712 |
713 |
714 |
715 |
716 |
717 |
718 |
719 |
720 |
721 |
722 |
723 |
724 |
725 |
726 |
727 |
728 |
729 |
730 |
731 |
732 |
733 |
734 |
735 |
736 |
737 |
738 |
739 |
740 |
741 |
742 |
743 |
744 |
745 |
746 |
747 |
748 |
749 |
750 |
751 |
752 |
753 |
754 |
755 |
756 |
757 |
758 |
759 |
760 |
761 |
762 |
763 |
764 |
765 |
766 |
767 |
768 |
769 |
770 |
771 |
772 |
773 |
774 |
775 |
776 |
777 |
778 |
779 |
780 |
781 |
782 |
783 |
784 |
785 |
786 |
787 |
788 |
789 |
790 |
791 |
792 |
793 |
794 |
795 |
796 |
797 |
798 |
799 |
800 |
801 |
802 |
803 |
804 |
805 |
806 |
807 |
808 |
809 |
810 |
811 |
812 |
813 |
814 |
815 |
816 |
817 |
818 |
819 |
820 |
821 |
822 |
823 |
824 |
825 |
826 |
827 |
828 |
829 |
830 |
831 |
832 |
833 |
834 |
835 |
836 |
837 |
838 |
839 |
840 |
841 |
842 |
843 |
844 |
845 |
846 |
847 |
848 |
849 |
850 |
851 |
--------------------------------------------------------------------------------
/EonilFSEventsDemoGUI/EonilFSEventsDemoGUI/EonilFSEventsDemoGUI.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/EonilFSEventsDemoGUI/EonilFSEventsDemoGUI/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleVersion
22 | 1
23 | LSMinimumSystemVersion
24 | $(MACOSX_DEPLOYMENT_TARGET)
25 | NSMainStoryboardFile
26 | Main
27 | NSPrincipalClass
28 | NSApplication
29 |
30 |
31 |
--------------------------------------------------------------------------------
/EonilFSEventsDemoGUI/EonilFSEventsDemoGUI/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // EonilFSEventsDemoGUI
4 | //
5 | // Created by Henry on 2018/12/27.
6 | //
7 |
8 | import Cocoa
9 | import EonilFSEvents
10 |
11 | class ViewController: NSViewController, NSTableViewDataSource, NSTableViewDelegate {
12 |
13 | private var items = [EonilFSEventsEvent]()
14 | private func process(fileSystemEvent e: EonilFSEventsEvent) {
15 | guard let v = tableView else { return }
16 | items.append(e)
17 | let a = v.numberOfRows
18 | let b = items.count
19 | let c = a.. Int {
48 | return items.count
49 | }
50 | func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
51 | guard let c = tableColumn else { return nil }
52 | let v = tableView.makeView(withIdentifier: c.identifier, owner: self) as! NSTableCellView
53 | let item = items[row]
54 | v.identifier = c.identifier
55 | switch c.identifier {
56 | case nameTableColumn?.identifier:
57 | v.imageView?.image = NSWorkspace.shared.icon(forFile: item.path)
58 | v.textField?.stringValue = item.path
59 | case actionsTableColumn?.identifier:
60 | v.textField?.stringValue = item.flag?.description ?? ""
61 | default:
62 | break
63 | }
64 | return v
65 | }
66 | // func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? {
67 | // guard let tableColumn = tableColumn else { return nil }
68 | // let item = items[row]
69 | // switch tableColumn.identifier {
70 | // case nameTableColumn?.identifier: return item.path
71 | // case actionsTableColumn?.identifier: return item.flag
72 | // default: return nil
73 | // }
74 | // }
75 | }
76 |
77 | //extension EonilFSEventsEventFlags {
78 | // var description: String {
79 | // let all = [
80 | // .historyDone: ".historyDone",
81 | // .idsWrapped: ".idsWrapped",
82 | // .itemChangeOwner: ".itemChangeOwner",
83 | // .itemCreated: ".itemCreated",
84 | // .itemFinderInfoMod: ".itemFinderInfoMod",
85 | // .itemInodeMetaMod: ".itemInodeMetaMod",
86 | // .itemIsDir: ".itemIsDir",
87 | // .itemIsFile: ".itemIsFile",
88 | // .itemIsHardlink: ".itemIsHardlink",
89 | // .itemIsLastHardlink: ".itemIsLastHardlink",
90 | // .itemIsSymlink: ".itemIsSymlink",
91 | // .itemModified: ".itemModified",
92 | // .itemRemoved: ".itemRemoved",
93 | // .itemRenamed: ".itemRenamed",
94 | // .itemXattrMod: ".itemXattrMod",
95 | // .kernelDropped: ".kernelDropped",
96 | // .mount: ".mount",
97 | // .mustScanSubDirs: ".mustScanSubDirs",
98 | // .none: ".none",
99 | // .ownEvent: ".ownEvent",
100 | // .rootChanged: ".rootChanged",
101 | // .unmount: ".unmount",
102 | // .userDropped: ".userDropped",
103 | // ] as [EonilFSEventsEventFlags: String]
104 | // var s = [String]()
105 | // for (k,n) in all {
106 | // if contains(k) {
107 | // s.append(n)
108 | // }
109 | // }
110 | // return s.joined(separator: ", ")
111 | // }
112 | //}
113 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016 Hoon H., Eonil
2 |
3 | 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:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | 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.
8 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.1
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 |
6 | let package = Package(
7 | name: "EonilFSEvents",
8 | platforms: [
9 | .macOS(.v10_10),
10 | ],
11 | products: [
12 | .library(name: "EonilFSEvents", targets: ["EonilFSEvents"]),
13 | .executable(name: "EonilFSEventsDemoCLI", targets: ["EonilFSEventsDemoCLI"]),
14 | ],
15 | dependencies: [
16 | ],
17 | targets: [
18 | .target(name: "EonilFSEvents", dependencies: []),
19 | .target(name: "EonilFSEventsDemoCLI", dependencies: ["EonilFSEvents"]),
20 | ]
21 | )
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | EonilFSEvents
2 | =============================
3 | Eonil
4 | 2018 Maintenance.
5 | 2019 Maintenance.
6 |
7 | [](https://travis-ci.org/eonil/FSEvents)
8 |
9 | It's possible to use FSEvents directly in Swift, but it still involves
10 | many boilerplate works and subtle conversions.
11 |
12 | This library provides mostly-faithful wrapper around FSEvents feature tailored
13 | for Swift 5.
14 |
15 |
16 |
17 | Quickstart
18 | -------------
19 | Import.
20 |
21 | import EonilFSEvents
22 |
23 | Start.
24 |
25 | try EonilFSEvents.startWatching(
26 | paths: ["/"],
27 | for: ObjectIdentifier(self),
28 | with: { event in print(event) })
29 |
30 | Stop.
31 |
32 | EonilFSEvents.stopWatching(for: ObjectIdentifier(self))
33 |
34 |
35 |
36 | Using Full Features
37 | -----------------------
38 | Make a `EonilFSEventStream`, schedule it to a GCD queue, and start.
39 |
40 | let s = try EonilFSEventStream(pathsToWatch: paths,
41 | sinceWhen: .now,
42 | latency: 0,
43 | flags: [],
44 | handler: handler)
45 | s.setDispatchQueue(DispatchQueue.main)
46 | try s.start()
47 |
48 | After use, deinitialize by stop, invalidate(unschedule).
49 |
50 | s.stop()
51 | s.invalidate()
52 |
53 | As soon as the last strong reference gets removed,
54 | the stream will be destroyed.
55 |
56 |
57 |
58 | Caveats
59 | ----------
60 | In the Xcode, AppKit apps are configured to use Sandbox by default.
61 | Sandboxed apps cannot access files out of its container.
62 | Therefore, it could look like it cannot receive file system events
63 | out of the container. To receive file system events out of
64 | container, you should turn off sandboxing.
65 |
66 | At this point, `xcodebuild` fails on dependency resolution for packages.
67 | I don't know why. It seems Xcode have some issues with it.
68 | To work around, just set `SYMROOT` explicitly.
69 | See `test.zsh` how to set it.
70 |
71 |
72 |
73 | Credits & License
74 | ------------------------
75 | Copyright(c) 2018 Hoon H., Eonil.
76 | All rights reserved.
77 | Use of this library is granted under "MIT License".
78 |
--------------------------------------------------------------------------------
/Sources/EonilFSEvents/EonilFSEventStream.swift:
--------------------------------------------------------------------------------
1 | //
2 | // EonilFSEventStream.swift
3 | // FSEventStreamWrapper
4 | //
5 | // Created by Hoon H. on 2016/10/02.
6 | //
7 | //
8 |
9 | import Foundation
10 | import CoreServices
11 |
12 | /// Replicate `FSEventStream`'s features and interface as close as possible in Swift-y interface.
13 | /// Apple can provide official wrapper in future release, and the name of the future wrapper type
14 | /// is likely to be `FSEventStream`. So this wrapper suffixes name with `~UnofficialWrapper` to avoid
15 | /// potential future name conflict.
16 | ///
17 | /// - TODO: Device watching support.
18 | ///
19 | public final class EonilFSEventStream {
20 | // This must be a non-nil value if an instance of this class has been created successfully.
21 | fileprivate var rawref: FSEventStreamRef!
22 | private let handler: (EonilFSEventsEvent) -> ()
23 |
24 | /*
25 | * FSEventStreamCreate()
26 | *
27 | * Discussion:
28 | * Creates a new FS event stream object with the given parameters.
29 | * In order to start receiving callbacks you must also call
30 | * FSEventStreamScheduleWithRunLoop() and FSEventStreamStart().
31 | *
32 | * Parameters:
33 | *
34 | * allocator:
35 | * The CFAllocator to be used to allocate memory for the stream.
36 | * Pass NULL or kCFAllocatorDefault to use the current default
37 | * allocator.
38 | *
39 | * callback:
40 | * An FSEventStreamCallback which will be called when FS events
41 | * occur.
42 | *
43 | * context:
44 | * A pointer to the FSEventStreamContext structure the client
45 | * wants to associate with this stream. Its fields are copied out
46 | * into the stream itself so its memory can be released after the
47 | * stream is created. Passing NULL is allowed and has the same
48 | * effect as passing a structure whose fields are all set to zero.
49 | *
50 | * pathsToWatch:
51 | * A CFArray of CFStringRefs, each specifying a path to a
52 | * directory, signifying the root of a filesystem hierarchy to be
53 | * watched for modifications.
54 | *
55 | * sinceWhen:
56 | * The service will supply events that have happened after the
57 | * given event ID. To ask for events "since now" pass the constant
58 | * kFSEventStreamEventIdSinceNow. Often, clients will supply the
59 | * highest-numbered FSEventStreamEventId they have received in a
60 | * callback, which they can obtain via the
61 | * FSEventStreamGetLatestEventId() accessor. Do not pass zero for
62 | * sinceWhen, unless you want to receive events for every
63 | * directory modified since "the beginning of time" -- an unlikely
64 | * scenario.
65 | *
66 | * latency:
67 | * The number of seconds the service should wait after hearing
68 | * about an event from the kernel before passing it along to the
69 | * client via its callback. Specifying a larger value may result
70 | * in more effective temporal coalescing, resulting in fewer
71 | * callbacks and greater overall efficiency.
72 | *
73 | * flags:
74 | * Flags that modify the behavior of the stream being created. See
75 | * FSEventStreamCreateFlags.
76 | *
77 | * Result:
78 | * A valid FSEventStreamRef.
79 | *
80 | * Availability:
81 | * Mac OS X: in version 10.5 and later in CoreServices.framework
82 | * CarbonLib: not available
83 | * Non-Carbon CFM: not available
84 | */
85 | public init(pathsToWatch: [String], sinceWhen: EonilFSEventsEventID, latency: TimeInterval, flags: EonilFSEventsCreateFlags, handler: @escaping (EonilFSEventsEvent) -> ()) throws {
86 | // `CoreServices.FSEventStreamCallback` is C callback and follows
87 | // C convention. Which means it cannot capture any external value.
88 | let callback: CoreServices.FSEventStreamCallback = { (
89 | _ streamRef: ConstFSEventStreamRef,
90 | _ clientCallBackInfo: UnsafeMutableRawPointer?,
91 | _ numEvents: Int,
92 | _ eventPaths: UnsafeMutableRawPointer,
93 | _ eventFlags: UnsafePointer,
94 | _ eventIds: UnsafePointer) -> () in
95 | guard let clientCallBackInfo1 = clientCallBackInfo else {
96 | EonilFSEventsIllogicalErrorLog(code: .missingContextRawPointerValue).cast()
97 | return
98 | }
99 | let eventPaths1: CFArray = Unmanaged.fromOpaque(eventPaths).takeUnretainedValue()
100 | guard let eventPaths2 = eventPaths1 as NSArray as? [NSString] as [String]? else {
101 | EonilFSEventsIllogicalErrorLog(code: .unexpectedPathValueType, message: "Cannot convert `\(eventPaths1)` into [String].").cast()
102 | return
103 | }
104 | guard numEvents == eventPaths2.count else {
105 | EonilFSEventsIllogicalErrorLog(code: .unmatchedEventParameterCounts, message: "Event count is `\(numEvents)`, but path count is `\(eventPaths2.count)`").cast()
106 | return
107 | }
108 | let unmanagedPtr: Unmanaged = Unmanaged.fromOpaque(clientCallBackInfo1)
109 | let self1 = unmanagedPtr.takeUnretainedValue()
110 | for i in 0..(value: UnsafeMutablePointer) -> UnsafeMutablePointer {
130 | return value
131 | }
132 | // Get pointer to a value on stack.
133 | // Stream creation function will copy the value, so it's safe to keep it
134 | // on stack.
135 | let context1: UnsafeMutablePointer? = getPtr(value: &context)
136 | let pathsToWatch1: CFArray = pathsToWatch as [NSString] as NSArray as CFArray
137 | let sinceWhen1: FSEventStreamEventId = sinceWhen.rawValue
138 | let latency1: CFTimeInterval = latency as CFTimeInterval
139 | // Always use CF types to avoid copying cost. But I am pretty sure that this
140 | // ultimately trigger copying inside of the system framework...
141 | let flags1: FSEventStreamCreateFlags = flags.union(.useCFTypes).rawValue
142 | guard let newRawref = FSEventStreamCreate(nil, callback, context1, pathsToWatch1, sinceWhen1, latency1, flags1) else {
143 | throw EonilFSEventsError(code: .cannotCreateStream)
144 | }
145 | rawref = newRawref
146 | }
147 | deinit {
148 | // It seems `rawref` does not get deallocated according to Instruments:
149 | // Run EonilFSEventsDemoGUI via Instruments with "Leaks" and close the main window.
150 | FSEventStreamRelease(self.rawref)
151 | }
152 | }
153 |
154 | /*
155 | * Accessors
156 | */
157 | extension EonilFSEventStream {
158 | /*
159 | * FSEventStreamGetLatestEventId()
160 | *
161 | * Discussion:
162 | * Fetches the sinceWhen property of the stream. Upon receiving an
163 | * event (and just before invoking the client's callback) this
164 | * attribute is updated to the highest-numbered event ID mentioned
165 | * in the event.
166 | *
167 | * Parameters:
168 | *
169 | * streamRef:
170 | * A valid stream.
171 | *
172 | * Result:
173 | * The sinceWhen attribute of the stream.
174 | *
175 | * Availability:
176 | * Mac OS X: in version 10.5 and later in CoreServices.framework
177 | * CarbonLib: not available
178 | * Non-Carbon CFM: not available
179 | */
180 |
181 | @available(macOS, introduced: 10.5)
182 | @available(iOS, introduced: 6.0)
183 | public func getLatestEventID() -> EonilFSEventsEventID {
184 | let eventId = FSEventStreamGetLatestEventId(rawref)
185 | let eventID1 = EonilFSEventsEventID(rawValue: eventId)
186 | return eventID1
187 | }
188 |
189 |
190 | // /*
191 | // * FSEventStreamGetDeviceBeingWatched()
192 | // *
193 | // * Discussion:
194 | // * Fetches the dev_t supplied when the stream was created via
195 | // * FSEventStreamCreateRelativeToDevice(), otherwise 0.
196 | // *
197 | // * Parameters:
198 | // *
199 | // * streamRef:
200 | // * A valid stream.
201 | // *
202 | // * Result:
203 | // * The dev_t for a device-relative stream, otherwise 0.
204 | // *
205 | // * Availability:
206 | // * Mac OS X: in version 10.5 and later in CoreServices.framework
207 | // * CarbonLib: not available
208 | // * Non-Carbon CFM: not available
209 | // */
210 | // @available(macOS, introduced: 10.5)
211 | // @available(iOS, introduced: 6.0)
212 | // public func getDeviceBeingWatched() -> dev_t {
213 | // return FSEventStreamGetDeviceBeingWatched(rawref)
214 | // }
215 |
216 | /*
217 | * FSEventStreamCopyPathsBeingWatched()
218 | *
219 | * Discussion:
220 | * Fetches the paths supplied when the stream was created via one of
221 | * the FSEventStreamCreate...() functions.
222 | *
223 | * Parameters:
224 | *
225 | * streamRef:
226 | * A valid stream.
227 | *
228 | * Result:
229 | * A CFArray of CFStringRefs corresponding to those supplied when
230 | * the stream was created. Ownership follows the Copy rule.
231 | *
232 | * Availability:
233 | * Mac OS X: in version 10.5 and later in CoreServices.framework
234 | * CarbonLib: not available
235 | * Non-Carbon CFM: not available
236 | */
237 | @available(macOS, introduced: 10.5)
238 | @available(iOS, introduced: 6.0)
239 | public func copyPathsBeingWatched() -> [String] {
240 | let ret = FSEventStreamCopyPathsBeingWatched(rawref)
241 | guard let paths = ret as NSArray as? [NSString] as [String]? else {
242 | EonilFSEventsIllogicalErrorLog(code: .unexpectedPathValueType, message: "Cannot convert retrieved object `\(ret)` into `[String]`.").cast()
243 | // Unrecoverable.
244 | fatalError()
245 | }
246 | return paths
247 | }
248 |
249 | // /*
250 | // * FSEventsCopyUUIDForDevice()
251 | // *
252 | // * Discussion:
253 | // * Gets the UUID associated with a device, or NULL if not possible
254 | // * (for example, on read-only device). A (non-NULL) UUID uniquely
255 | // * identifies a given stream of FSEvents. If this (non-NULL) UUID
256 | // * is different than one that you stored from a previous run then
257 | // * the event stream is different (for example, because FSEvents were
258 | // * purged, because the disk was erased, or because the event ID
259 | // * counter wrapped around back to zero). A NULL return value
260 | // * indicates that "historical" events are not available, i.e., you
261 | // * should not supply a "sinceWhen" value to FSEventStreamCreate...()
262 | // * other than kFSEventStreamEventIdSinceNow.
263 | // *
264 | // * Parameters:
265 | // *
266 | // * dev:
267 | // * The dev_t of the device that you want to get the UUID for.
268 | // *
269 | // * Result:
270 | // * The UUID associated with the stream of events on this device, or
271 | // * NULL if no UUID is available (for example, on a read-only
272 | // * device). The UUID is stored on the device itself and travels
273 | // * with it even when the device is attached to different computers.
274 | // * Ownership follows the Copy Rule.
275 | // *
276 | // * Availability:
277 | // * Mac OS X: in version 10.5 and later in CoreServices.framework
278 | // * CarbonLib: not available
279 | // * Non-Carbon CFM: not available
280 | // */
281 | // extern CF_RETURNS_RETAINED CFUUIDRef __nullable
282 | // FSEventsCopyUUIDForDevice(dev_t dev) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_6_0);
283 |
284 | // /*
285 | // * FSEventsGetLastEventIdForDeviceBeforeTime()
286 | // *
287 | // * Discussion:
288 | // * Gets the last event ID for the given device that was returned
289 | // * before the given time. This is conservative in the sense that if
290 | // * you then use the returned event ID as the sinceWhen parameter of
291 | // * FSEventStreamCreateRelativeToDevice() that you will not miss any
292 | // * events that happened since that time. On the other hand, you
293 | // * might receive some (harmless) extra events. Beware: there are
294 | // * things that can cause this to fail to be accurate. For example,
295 | // * someone might change the system's clock (either backwards or
296 | // * forwards). Or an external drive might be used on different
297 | // * systems without perfectly synchronized clocks.
298 | // *
299 | // * Parameters:
300 | // *
301 | // * dev:
302 | // * The dev_t of the device.
303 | // *
304 | // * time:
305 | // * The time as a CFAbsoluteTime whose value is the number of
306 | // * seconds since Jan 1, 1970 (i.e. a posix style time_t).
307 | // *
308 | // * Result:
309 | // * The last event ID for the given device that was returned before
310 | // * the given time.
311 | // *
312 | // * Availability:
313 | // * Mac OS X: in version 10.5 and later in CoreServices.framework
314 | // * CarbonLib: not available
315 | // * Non-Carbon CFM: not available
316 | // */
317 | // extern FSEventStreamEventId
318 | // FSEventsGetLastEventIdForDeviceBeforeTime(
319 | // dev_t dev,
320 | // CFAbsoluteTime time) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_6_0);
321 |
322 | // /*
323 | // * FSEventsPurgeEventsForDeviceUpToEventId()
324 | // *
325 | // * Discussion:
326 | // * Purges old events from the persistent per-volume database
327 | // * maintained by the service. Can only be called by the root user.
328 | // *
329 | // * Parameters:
330 | // *
331 | // * dev:
332 | // * The dev_t of the device.
333 | // *
334 | // * eventId:
335 | // * The event ID.
336 | // *
337 | // * Result:
338 | // * True if it succeeds, otherwise False if it fails.
339 | // *
340 | // * Availability:
341 | // * Mac OS X: in version 10.5 and later in CoreServices.framework
342 | // * CarbonLib: not available
343 | // * Non-Carbon CFM: not available
344 | // */
345 | // extern Boolean
346 | // FSEventsPurgeEventsForDeviceUpToEventId(
347 | // dev_t dev,
348 | // FSEventStreamEventId eventId) __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_6_0);
349 |
350 | }
351 |
352 | /*
353 | * ScheduleWithRunLoop, UnscheduleFromRunLoop, Invalidate
354 | */
355 | extension EonilFSEventStream {
356 | /*
357 | * FSEventStreamScheduleWithRunLoop()
358 | *
359 | * Discussion:
360 | * This function schedules the stream on the specified run loop,
361 | * like CFRunLoopAddSource() does for a CFRunLoopSourceRef. The
362 | * caller is responsible for ensuring that the stream is scheduled
363 | * on at least one run loop and that at least one of the run loops
364 | * on which the stream is scheduled is being run. To start receiving
365 | * events on the stream, call FSEventStreamStart(). To remove the
366 | * stream from the run loops upon which it has been scheduled, call
367 | * FSEventStreamUnscheduleFromRunLoop() or FSEventStreamInvalidate().
368 | *
369 | * Parameters:
370 | *
371 | * streamRef:
372 | * A valid stream.
373 | *
374 | * runLoop:
375 | * The run loop on which to schedule the stream.
376 | *
377 | * runLoopMode:
378 | * A run loop mode on which to schedule the stream.
379 | *
380 | * Availability:
381 | * Mac OS X: in version 10.5 and later in CoreServices.framework
382 | * CarbonLib: not available
383 | * Non-Carbon CFM: not available
384 | */
385 | @available(OSX 10.5, *)
386 | public func scheduleWithRunloop(runLoop: RunLoop, runLoopMode: RunLoop.Mode) {
387 | let runLoopMode1 = runLoopMode as CFString
388 | FSEventStreamScheduleWithRunLoop(rawref, runLoop.getCFRunLoop(), runLoopMode1)
389 | }
390 |
391 | /*
392 | * FSEventStreamUnscheduleFromRunLoop()
393 | *
394 | * Discussion:
395 | * This function removes the stream from the specified run loop,
396 | * like CFRunLoopRemoveSource() does for a CFRunLoopSourceRef.
397 | *
398 | * Parameters:
399 | *
400 | * streamRef:
401 | * A valid stream.
402 | *
403 | * runLoop:
404 | * The run loop from which to unschedule the stream.
405 | *
406 | * runLoopMode:
407 | * The run loop mode from which to unschedule the stream.
408 | *
409 | * Availability:
410 | * Mac OS X: in version 10.5 and later in CoreServices.framework
411 | * CarbonLib: not available
412 | * Non-Carbon CFM: not available
413 | */
414 | @available(OSX 10.5, *)
415 | public func unscheduleFromRunLoop(runLoop: RunLoop, runLoopMode: RunLoop.Mode) {
416 | let runLoopMode1 = runLoopMode as CFString
417 | FSEventStreamUnscheduleFromRunLoop(rawref, runLoop.getCFRunLoop(), runLoopMode1)
418 | }
419 |
420 | /*
421 | * FSEventStreamSetDispatchQueue()
422 | *
423 | * Discussion:
424 | * This function schedules the stream on the specified dispatch
425 | * queue. The caller is responsible for ensuring that the stream is
426 | * scheduled on a dispatch queue and that the queue is started. If
427 | * there is a problem scheduling the stream on the queue an error
428 | * will be returned when you try to Start the stream. To start
429 | * receiving events on the stream, call FSEventStreamStart(). To
430 | * remove the stream from the queue on which it was scheduled, call
431 | * FSEventStreamSetDispatchQueue() with a NULL queue parameter or
432 | * call FSEventStreamInvalidate() which will do the same thing.
433 | * Note: you must eventually call FSEventStreamInvalidate() and it
434 | * is an error to call FSEventStreamInvalidate() without having the
435 | * stream either scheduled on a runloop or a dispatch queue, so do
436 | * not set the dispatch queue to NULL before calling
437 | * FSEventStreamInvalidate().
438 | *
439 | * Parameters:
440 | *
441 | * streamRef:
442 | * A valid stream.
443 | *
444 | * q:
445 | * The dispatch queue to use to receive events (or NULL to to stop
446 | * receiving events from the stream).
447 | *
448 | * Availability:
449 | * Mac OS X: in version 10.6 and later in CoreServices.framework
450 | * CarbonLib: not available
451 | * Non-Carbon CFM: not available
452 | */
453 | @available(OSX 10.6, *)
454 | public func setDispatchQueue(_ q: DispatchQueue?) {
455 | FSEventStreamSetDispatchQueue(rawref, q)
456 | }
457 |
458 | /*
459 | * FSEventStreamInvalidate()
460 | *
461 | * Discussion:
462 | * Invalidates the stream, like CFRunLoopSourceInvalidate() does for
463 | * a CFRunLoopSourceRef. It will be unscheduled from any runloops
464 | * or dispatch queues upon which it had been scheduled.
465 | * FSEventStreamInvalidate() can only be called on the stream after
466 | * you have called FSEventStreamScheduleWithRunLoop() or
467 | * FSEventStreamSetDispatchQueue().
468 | *
469 | * Parameters:
470 | *
471 | * streamRef:
472 | * A valid stream.
473 | *
474 | * Availability:
475 | * Mac OS X: in version 10.5 and later in CoreServices.framework
476 | * CarbonLib: not available
477 | * Non-Carbon CFM: not available
478 | */
479 | @available(OSX 10.5, *)
480 | public func invalidate() {
481 | FSEventStreamInvalidate(rawref)
482 | }
483 | }
484 |
485 | /*
486 | * Start, Flush, Stop
487 | */
488 | extension EonilFSEventStream {
489 | /*
490 | * FSEventStreamStart()
491 | *
492 | * Discussion:
493 | * Attempts to register with the FS Events service to receive events
494 | * per the parameters in the stream. FSEventStreamStart() can only
495 | * be called once the stream has been scheduled on at least one
496 | * runloop, via FSEventStreamScheduleWithRunLoop(). Once started,
497 | * the stream can be stopped via FSEventStreamStop().
498 | *
499 | * Parameters:
500 | *
501 | * streamRef:
502 | * A valid stream.
503 | *
504 | * Result:
505 | * True if it succeeds, otherwise False if it fails. It ought to
506 | * always succeed, but in the event it does not then your code
507 | * should fall back to performing recursive scans of the directories
508 | * of interest as appropriate.
509 | *
510 | * Availability:
511 | * Mac OS X: in version 10.5 and later in CoreServices.framework
512 | * CarbonLib: not available
513 | * Non-Carbon CFM: not available
514 | */
515 | @available(OSX 10.5, *)
516 | public func start() throws {
517 | switch FSEventStreamStart(rawref) {
518 | case false:
519 | throw EonilFSEventsError.init(code: .cannotStartStream)
520 | case true:
521 | return
522 | }
523 | }
524 |
525 | /*
526 | * FSEventStreamFlushAsync()
527 | *
528 | * Discussion:
529 | * Asks the FS Events service to flush out any events that have
530 | * occurred but have not yet been delivered, due to the latency
531 | * parameter that was supplied when the stream was created. This
532 | * flushing occurs asynchronously -- do not expect the events to
533 | * have already been delivered by the time this call returns.
534 | * FSEventStreamFlushAsync() can only be called after the stream has
535 | * been started, via FSEventStreamStart().
536 | *
537 | * Parameters:
538 | *
539 | * streamRef:
540 | * A valid stream.
541 | *
542 | * Result:
543 | * The largest event id of any event ever queued for this stream,
544 | * otherwise zero if no events have been queued for this stream.
545 | *
546 | * Availability:
547 | * Mac OS X: in version 10.5 and later in CoreServices.framework
548 | * CarbonLib: not available
549 | * Non-Carbon CFM: not available
550 | */
551 | @available(OSX 10.5, *)
552 | public func flushAsync() -> EonilFSEventsEventID {
553 | let eventId = FSEventStreamFlushAsync(rawref)
554 | let eventId1 = EonilFSEventsEventID(rawValue: eventId)
555 | return eventId1
556 | }
557 |
558 | /*
559 | * FSEventStreamFlushSync()
560 | *
561 | * Discussion:
562 | * Asks the FS Events service to flush out any events that have
563 | * occurred but have not yet been delivered, due to the latency
564 | * parameter that was supplied when the stream was created. This
565 | * flushing occurs synchronously -- by the time this call returns,
566 | * your callback will have been invoked for every event that had
567 | * already occurred at the time you made this call.
568 | * FSEventStreamFlushSync() can only be called after the stream has
569 | * been started, via FSEventStreamStart().
570 | *
571 | * Parameters:
572 | *
573 | * streamRef:
574 | * A valid stream.
575 | *
576 | * Availability:
577 | * Mac OS X: in version 10.5 and later in CoreServices.framework
578 | * CarbonLib: not available
579 | * Non-Carbon CFM: not available
580 | */
581 | @available(OSX 10.5, *)
582 | public func flushSync() {
583 | FSEventStreamFlushSync(rawref)
584 | }
585 |
586 | /*
587 | * FSEventStreamStop()
588 | *
589 | * Discussion:
590 | * Unregisters with the FS Events service. The client callback will
591 | * not be called for this stream while it is stopped.
592 | * FSEventStreamStop() can only be called if the stream has been
593 | * started, via FSEventStreamStart(). Once stopped, the stream can
594 | * be restarted via FSEventStreamStart(), at which point it will
595 | * resume receiving events from where it left off ("sinceWhen").
596 | *
597 | * Parameters:
598 | *
599 | * streamRef:
600 | * A valid stream.
601 | *
602 | * Availability:
603 | * Mac OS X: in version 10.5 and later in CoreServices.framework
604 | * CarbonLib: not available
605 | * Non-Carbon CFM: not available
606 | */
607 | @available(OSX 10.5, *)
608 | public func stop() {
609 | FSEventStreamStop(rawref)
610 | }
611 | }
612 |
613 | /*
614 | * Debugging
615 | */
616 | extension EonilFSEventStream {
617 | /*
618 | * FSEventStreamShow()
619 | *
620 | * Discussion:
621 | * Prints a description of the supplied stream to stderr. For
622 | * debugging only.
623 | *
624 | * Parameters:
625 | *
626 | * streamRef:
627 | * A valid stream.
628 | *
629 | * Availability:
630 | * Mac OS X: in version 10.5 and later in CoreServices.framework
631 | * CarbonLib: not available
632 | * Non-Carbon CFM: not available
633 | */
634 | @available(OSX 10.5, *)
635 | private func show() {
636 | FSEventStreamShow(rawref)
637 | }
638 |
639 | /*
640 | * FSEventStreamCopyDescription()
641 | *
642 | * Discussion:
643 | * Returns a CFStringRef containing the description of the supplied
644 | * stream. For debugging only.
645 | *
646 | * Result:
647 | * A CFStringRef containing the description of the supplied stream.
648 | * Ownership follows the Copy rule.
649 | *
650 | * Availability:
651 | * Mac OS X: in version 10.5 and later in CoreServices.framework
652 | * CarbonLib: not available
653 | * Non-Carbon CFM: not available
654 | */
655 | @available(OSX 10.5, *)
656 | fileprivate func copyDescription() -> String {
657 | let desc = FSEventStreamCopyDescription(rawref)
658 | let desc1 = desc as String
659 | return desc1
660 | }
661 |
662 | /*
663 | * FSEventStreamSetExclusionPaths()
664 | *
665 | * Discussion:
666 | * Sets directories to be filtered from the EventStream.
667 | * A maximum of 8 directories maybe specified.
668 | *
669 | * Result:
670 | * True if it succeeds, otherwise False if it fails.
671 | *
672 | * Availability:
673 | * Mac OS X: in version 10.9 and later in CoreServices.framework
674 | * CarbonLib: not available
675 | * Non-Carbon CFM: not available
676 | */
677 | @available(OSX 10.9, *)
678 | @discardableResult
679 | public func setExclusionPaths(_ pathsToExclude: [String]) -> Bool {
680 | let pathsToExclude1 = pathsToExclude as [NSString] as NSArray as CFArray
681 | return FSEventStreamSetExclusionPaths(rawref, pathsToExclude1)
682 | }
683 | }
684 | extension EonilFSEventStream: CustomStringConvertible, CustomDebugStringConvertible {
685 | public var description: String {
686 | return copyDescription()
687 | }
688 | public var debugDescription: String {
689 | return copyDescription()
690 | }
691 | }
692 |
693 |
694 |
--------------------------------------------------------------------------------
/Sources/EonilFSEvents/EonilFSEventStreamCreateFlags.swift:
--------------------------------------------------------------------------------
1 | //
2 | // EonilFSEventsCreateFlags.swift
3 | // EonilFSEvents
4 | //
5 | // Created by Hoon H. on 2016/10/02.
6 | //
7 | //
8 |
9 | import Foundation
10 | import CoreServices
11 |
12 | public struct EonilFSEventsCreateFlags: OptionSet {
13 | public let rawValue: FSEventStreamCreateFlags
14 | public init(rawValue: FSEventStreamCreateFlags) {
15 | self.rawValue = rawValue
16 | }
17 | fileprivate init(rawValue: Int) {
18 | self.rawValue = FSEventStreamCreateFlags(truncatingIfNeeded: rawValue)
19 | }
20 | }
21 |
22 | /// Flags that can be passed to `EonilFSEvents.init`
23 | /// to modify the behavior of the stream being created.
24 | ///
25 | /// - Note:
26 | /// Documentation comments are copied from Apple's documentation
27 | /// for convenience.
28 | ///
29 | /// - Note:
30 | /// `kFSEventStreamCreateFlagUseCFTypes` is not available because
31 | /// this wrapper designed to be Swift-y interface as much as possible
32 | /// by sacrificing a bit of performance.
33 | ///
34 | public extension EonilFSEventsCreateFlags {
35 |
36 | /*
37 | * The default.
38 | */
39 | static var none: EonilFSEventsCreateFlags {
40 | return EonilFSEventsCreateFlags(rawValue: kFSEventStreamCreateFlagNone)
41 | }
42 |
43 | /*
44 | * The framework will invoke your callback function with CF types
45 | * rather than raw C types (i.e., a CFArrayRef of CFStringRefs,
46 | * rather than a raw C array of raw C string pointers). See
47 | * FSEventStreamCallback.
48 | */
49 | internal static var useCFTypes: EonilFSEventsCreateFlags {
50 | return EonilFSEventsCreateFlags(rawValue: kFSEventStreamCreateFlagUseCFTypes)
51 | }
52 |
53 | /*
54 | * Affects the meaning of the latency parameter. If you specify this
55 | * flag and more than latency seconds have elapsed since the last
56 | * event, your app will receive the event immediately. The delivery
57 | * of the event resets the latency timer and any further events will
58 | * be delivered after latency seconds have elapsed. This flag is
59 | * useful for apps that are interactive and want to react immediately
60 | * to changes but avoid getting swamped by notifications when changes
61 | * are occurringin rapid succession. If you do not specify this flag,
62 | * then when an event occurs after a period of no events, the latency
63 | * timer is started. Any events that occur during the next latency
64 | * seconds will be delivered as one group (including that first
65 | * event). The delivery of the group of events resets the latency
66 | * timer and any further events will be delivered after latency
67 | * seconds. This is the default behavior and is more appropriate for
68 | * background, daemon or batch processing apps.
69 | */
70 | static var noDefer: EonilFSEventsCreateFlags {
71 | return EonilFSEventsCreateFlags(rawValue: kFSEventStreamCreateFlagNoDefer)
72 | }
73 |
74 | /*
75 | * Request notifications of changes along the path to the path(s)
76 | * you're watching. For example, with this flag, if you watch
77 | * "/foo/bar" and it is renamed to "/foo/bar.old", you would receive
78 | * a RootChanged event. The same is true if the directory "/foo" were
79 | * renamed. The event you receive is a special event: the path for
80 | * the event is the original path you specified, the flag
81 | * kFSEventStreamEventFlagRootChanged is set and event ID is zero.
82 | * RootChanged events are useful to indicate that you should rescan a
83 | * particular hierarchy because it changed completely (as opposed to
84 | * the things inside of it changing). If you want to track the
85 | * current location of a directory, it is best to open the directory
86 | * before creating the stream so that you have a file descriptor for
87 | * it and can issue an F_GETPATH fcntl() to find the current path.
88 | */
89 | static var watchRoot: EonilFSEventsCreateFlags {
90 | return EonilFSEventsCreateFlags(rawValue: kFSEventStreamCreateFlagWatchRoot)
91 | }
92 |
93 | /*
94 | * Don't send events that were triggered by the current process. This
95 | * is useful for reducing the volume of events that are sent. It is
96 | * only useful if your process might modify the file system hierarchy
97 | * beneath the path(s) being monitored. Note: this has no effect on
98 | * historical events, i.e., those delivered before the HistoryDone
99 | * sentinel event. Also, this does not apply to RootChanged events
100 | * because the WatchRoot feature uses a separate mechanism that is
101 | * unable to provide information about the responsible process.
102 | */
103 | @available(macOS, introduced: 10.6)
104 | @available(iOS, introduced: 6.0)
105 | static var ignoreSelf: EonilFSEventsCreateFlags {
106 | return EonilFSEventsCreateFlags(rawValue: kFSEventStreamCreateFlagIgnoreSelf)
107 | }
108 |
109 | /*
110 | * Request file-level notifications. Your stream will receive events
111 | * about individual files in the hierarchy you're watching instead of
112 | * only receiving directory level notifications. Use this flag with
113 | * care as it will generate significantly more events than without it.
114 | */
115 | @available(macOS, introduced: 10.7)
116 | @available(iOS, introduced: 6.0)
117 | static var fileEvents: EonilFSEventsCreateFlags {
118 | return EonilFSEventsCreateFlags(rawValue: kFSEventStreamCreateFlagFileEvents)
119 | }
120 |
121 | /*
122 | * Tag events that were triggered by the current process with the "OwnEvent" flag.
123 | * This is only useful if your process might modify the file system hierarchy
124 | * beneath the path(s) being monitored and you wish to know which events were
125 | * triggered by your process. Note: this has no effect on historical events, i.e.,
126 | * those delivered before the HistoryDone sentinel event.
127 | */
128 | @available(macOS, introduced: 10.9)
129 | @available(iOS, introduced: 7.0)
130 | static var markSelf: EonilFSEventsCreateFlags {
131 | return EonilFSEventsCreateFlags(rawValue: kFSEventStreamCreateFlagMarkSelf)
132 | }
133 | }
134 | //public enum EonilFSEventsCreateFlags: UInt32, OptionSet {
135 | //// public static let none = EonilFSEventsCreateFlags([])
136 | //
137 | //// public init(rawValue: UInt32) {
138 | //// self = rawValue
139 | //// }
140 | //
141 | // /*
142 | // * The framework will invoke your callback function with CF types
143 | // * rather than raw C types (i.e., a CFArrayRef of CFStringRefs,
144 | // * rather than a raw C array of raw C string pointers). See
145 | // * FSEventStreamCallback.
146 | // */
147 | // case useCFTypes = 0x00000001
148 | //
149 | // /*
150 | // * Affects the meaning of the latency parameter. If you specify this
151 | // * flag and more than latency seconds have elapsed since the last
152 | // * event, your app will receive the event immediately. The delivery
153 | // * of the event resets the latency timer and any further events will
154 | // * be delivered after latency seconds have elapsed. This flag is
155 | // * useful for apps that are interactive and want to react immediately
156 | // * to changes but avoid getting swamped by notifications when changes
157 | // * are occurringin rapid succession. If you do not specify this flag,
158 | // * then when an event occurs after a period of no events, the latency
159 | // * timer is started. Any events that occur during the next latency
160 | // * seconds will be delivered as one group (including that first
161 | // * event). The delivery of the group of events resets the latency
162 | // * timer and any further events will be delivered after latency
163 | // * seconds. This is the default behavior and is more appropriate for
164 | // * background, daemon or batch processing apps.
165 | // */
166 | // case noDefer = 0x00000002
167 | //
168 | // /*
169 | // * Request notifications of changes along the path to the path(s)
170 | // * you're watching. For example, with this flag, if you watch
171 | // * "/foo/bar" and it is renamed to "/foo/bar.old", you would receive
172 | // * a RootChanged event. The same is true if the directory "/foo" were
173 | // * renamed. The event you receive is a special event: the path for
174 | // * the event is the original path you specified, the flag
175 | // * kFSEventStreamEventFlagRootChanged is set and event ID is zero.
176 | // * RootChanged events are useful to indicate that you should rescan a
177 | // * particular hierarchy because it changed completely (as opposed to
178 | // * the things inside of it changing). If you want to track the
179 | // * current location of a directory, it is best to open the directory
180 | // * before creating the stream so that you have a file descriptor for
181 | // * it and can issue an F_GETPATH fcntl() to find the current path.
182 | // */
183 | // case watchRoot = 0x00000004
184 | //
185 | // /*
186 | // * Don't send events that were triggered by the current process. This
187 | // * is useful for reducing the volume of events that are sent. It is
188 | // * only useful if your process might modify the file system hierarchy
189 | // * beneath the path(s) being monitored. Note: this has no effect on
190 | // * historical events, i.e., those delivered before the HistoryDone
191 | // * sentinel event. Also, this does not apply to RootChanged events
192 | // * because the WatchRoot feature uses a separate mechanism that is
193 | // * unable to provide information about the responsible process.
194 | // */
195 | // @available(macOS, introduced: 10.6)
196 | // @available(iOS, introduced: 6.0)
197 | // case ignoreSelf = 0x00000008
198 | //
199 | // /*
200 | // * Request file-level notifications. Your stream will receive events
201 | // * about individual files in the hierarchy you're watching instead of
202 | // * only receiving directory level notifications. Use this flag with
203 | // * care as it will generate significantly more events than without it.
204 | // */
205 | // @available(macOS, introduced: 10.7)
206 | // @available(iOS, introduced: 6.0)
207 | // case fileEvents = 0x00000010
208 | //
209 | // /*
210 | // * Tag events that were triggered by the current process with the "OwnEvent" flag.
211 | // * This is only useful if your process might modify the file system hierarchy
212 | // * beneath the path(s) being monitored and you wish to know which events were
213 | // * triggered by your process. Note: this has no effect on historical events, i.e.,
214 | // * those delivered before the HistoryDone sentinel event.
215 | // */
216 | // @available(macOS, introduced: 10.9)
217 | // @available(iOS, introduced: 7.0)
218 | // case markSelf = 0x00000020
219 | //}
220 |
221 | extension EonilFSEventsCreateFlags: Hashable, CustomStringConvertible, CustomDebugStringConvertible {
222 | public var hashValue: Int {
223 | return rawValue.hashValue
224 | }
225 | private static func getNameMapping() -> [EonilFSEventsCreateFlags: String] {
226 | return [
227 | .none: ".none",
228 | .useCFTypes: ".useCFTypes",
229 | .noDefer: ".noDefer",
230 | .watchRoot: ".watchRoot",
231 | .ignoreSelf: ".ignoreSelf",
232 | .fileEvents: ".fileEvents",
233 | .markSelf: ".markSelf",
234 | ]
235 | }
236 | public var description: String {
237 | return debugDescription
238 | }
239 | public var debugDescription: String {
240 | let map = EonilFSEventsCreateFlags.getNameMapping()
241 | let ns1 = map.filter({ contains($0.key) }).map({ $0.value })
242 | return "[\(ns1.joined(separator: ","))]"
243 | }
244 | }
245 |
246 |
--------------------------------------------------------------------------------
/Sources/EonilFSEvents/EonilFSEventStreamError.swift:
--------------------------------------------------------------------------------
1 | //
2 | // EonilFSEventsError.swift
3 | // EonilFSEvents
4 | //
5 | // Created by Hoon H. on 2016/10/02.
6 | //
7 | //
8 |
9 | public struct EonilFSEventsError: Error {
10 | public var code: EonilFSEventsErrorCode
11 | public var message: String?
12 | init(code: EonilFSEventsErrorCode) {
13 | self.code = code
14 | }
15 | init(code: EonilFSEventsErrorCode, message: String) {
16 | self.code = code
17 | self.message = message
18 | }
19 | }
20 |
21 | public enum EonilFSEventsErrorCode {
22 | case cannotCreateStream
23 | case cannotStartStream
24 | }
25 |
--------------------------------------------------------------------------------
/Sources/EonilFSEvents/EonilFSEventStreamEvent.swift:
--------------------------------------------------------------------------------
1 | //
2 | // EonilFSEventsEvent.swift
3 | // EonilFSEvents
4 | //
5 | // Created by Hoon H. on 2016/10/02.
6 | //
7 | //
8 |
9 | public struct EonilFSEventsEvent {
10 | public var path: String
11 | public var flag: EonilFSEventsEventFlags?
12 | public var ID: EonilFSEventsEventID?
13 | }
14 |
--------------------------------------------------------------------------------
/Sources/EonilFSEvents/EonilFSEventStreamEventFlags.swift:
--------------------------------------------------------------------------------
1 | //
2 | // EonilFSEventsEventFlags.swift
3 | // EonilFSEvents
4 | //
5 | // Created by Hoon H. on 2016/10/02.
6 | //
7 | //
8 |
9 | import Foundation
10 | import CoreServices
11 |
12 | /// Flags that can be passed to your `EonilFSEvents`'s handler function.
13 | /*
14 | * FSEventStreamEventFlags
15 | *
16 | * Discussion:
17 | * Flags that can be passed to your FSEventStreamCallback function.
18 | *
19 | * It is important to note that event flags are simply hints about the
20 | * sort of operations that occurred at that path.
21 | *
22 | * Furthermore, the FSEvent stream should NOT be treated as a form of
23 | * historical log that could somehow be replayed to arrive at the
24 | * current state of the file system.
25 | *
26 | * The FSEvent stream simply indicates what paths changed; and clients
27 | * need to reconcile what is really in the file system with their internal
28 | * data model - and recognize that what is actually in the file system can
29 | * change immediately after you check it.
30 | */
31 | public struct EonilFSEventsEventFlags: OptionSet {
32 | public let rawValue: FSEventStreamEventFlags
33 | public init(rawValue: FSEventStreamEventFlags) {
34 | self.rawValue = rawValue
35 | }
36 | fileprivate init(rawValue: Int) {
37 | self.rawValue = FSEventStreamEventFlags(truncatingIfNeeded: rawValue)
38 | }
39 | }
40 |
41 | public extension EonilFSEventsEventFlags {
42 |
43 | /*
44 | * There was some change in the directory at the specific path
45 | * supplied in this event.
46 | */
47 | static var none: EonilFSEventsEventFlags {
48 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagNone)
49 | }
50 |
51 | /*
52 | * Your application must rescan not just the directory given in the
53 | * event, but all its children, recursively. This can happen if there
54 | * was a problem whereby events were coalesced hierarchically. For
55 | * example, an event in /Users/jsmith/Music and an event in
56 | * /Users/jsmith/Pictures might be coalesced into an event with this
57 | * flag set and path=/Users/jsmith. If this flag is set you may be
58 | * able to get an idea of whether the bottleneck happened in the
59 | * kernel (less likely) or in your client (more likely) by checking
60 | * for the presence of the informational flags
61 | * kFSEventStreamEventFlagUserDropped or
62 | * kFSEventStreamEventFlagKernelDropped.
63 | */
64 | static var mustScanSubDirs: EonilFSEventsEventFlags {
65 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagMustScanSubDirs)
66 | }
67 |
68 | /*
69 | * The kFSEventStreamEventFlagUserDropped or
70 | * kFSEventStreamEventFlagKernelDropped flags may be set in addition
71 | * to the kFSEventStreamEventFlagMustScanSubDirs flag to indicate
72 | * that a problem occurred in buffering the events (the particular
73 | * flag set indicates where the problem occurred) and that the client
74 | * must do a full scan of any directories (and their subdirectories,
75 | * recursively) being monitored by this stream. If you asked to
76 | * monitor multiple paths with this stream then you will be notified
77 | * about all of them. Your code need only check for the
78 | * kFSEventStreamEventFlagMustScanSubDirs flag; these flags (if
79 | * present) only provide information to help you diagnose the problem.
80 | */
81 | static var userDropped: EonilFSEventsEventFlags {
82 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagUserDropped)
83 | }
84 |
85 | /*
86 | * The kFSEventStreamEventFlagUserDropped or
87 | * kFSEventStreamEventFlagKernelDropped flags may be set in addition
88 | * to the kFSEventStreamEventFlagMustScanSubDirs flag to indicate
89 | * that a problem occurred in buffering the events (the particular
90 | * flag set indicates where the problem occurred) and that the client
91 | * must do a full scan of any directories (and their subdirectories,
92 | * recursively) being monitored by this stream. If you asked to
93 | * monitor multiple paths with this stream then you will be notified
94 | * about all of them. Your code need only check for the
95 | * kFSEventStreamEventFlagMustScanSubDirs flag; these flags (if
96 | * present) only provide information to help you diagnose the problem.
97 | */
98 | static var kernelDropped: EonilFSEventsEventFlags {
99 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagKernelDropped)
100 | }
101 |
102 | /*
103 | * If kFSEventStreamEventFlagEventIdsWrapped is set, it means the
104 | * 64-bit event ID counter wrapped around. As a result,
105 | * previously-issued event ID's are no longer valid arguments for the
106 | * sinceWhen parameter of the FSEventStreamCreate...() functions.
107 | */
108 | static var idsWrapped: EonilFSEventsEventFlags {
109 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagEventIdsWrapped)
110 | }
111 |
112 | /*
113 | * Denotes a sentinel event sent to mark the end of the "historical"
114 | * events sent as a result of specifying a sinceWhen value in the
115 | * FSEventStreamCreate...() call that created this event stream. (It
116 | * will not be sent if kFSEventStreamEventIdSinceNow was passed for
117 | * sinceWhen.) After invoking the client's callback with all the
118 | * "historical" events that occurred before now, the client's
119 | * callback will be invoked with an event where the
120 | * kFSEventStreamEventFlagHistoryDone flag is set. The client should
121 | * ignore the path supplied in this callback.
122 | */
123 | static var historyDone: EonilFSEventsEventFlags {
124 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagHistoryDone)
125 | }
126 |
127 | /*
128 | * Denotes a special event sent when there is a change to one of the
129 | * directories along the path to one of the directories you asked to
130 | * watch. When this flag is set, the event ID is zero and the path
131 | * corresponds to one of the paths you asked to watch (specifically,
132 | * the one that changed). The path may no longer exist because it or
133 | * one of its parents was deleted or renamed. Events with this flag
134 | * set will only be sent if you passed the flag
135 | * kFSEventStreamCreateFlagWatchRoot to FSEventStreamCreate...() when
136 | * you created the stream.
137 | */
138 | static var rootChanged: EonilFSEventsEventFlags {
139 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagRootChanged)
140 | }
141 |
142 | /*
143 | * Denotes a special event sent when a volume is mounted underneath
144 | * one of the paths being monitored. The path in the event is the
145 | * path to the newly-mounted volume. You will receive one of these
146 | * notifications for every volume mount event inside the kernel
147 | * (independent of DiskArbitration). Beware that a newly-mounted
148 | * volume could contain an arbitrarily large directory hierarchy.
149 | * Avoid pitfalls like triggering a recursive scan of a non-local
150 | * filesystem, which you can detect by checking for the absence of
151 | * the MNT_LOCAL flag in the f_flags returned by statfs(). Also be
152 | * aware of the MNT_DONTBROWSE flag that is set for volumes which
153 | * should not be displayed by user interface elements.
154 | */
155 | static var mount: EonilFSEventsEventFlags {
156 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagMount)
157 | }
158 |
159 | /*
160 | * Denotes a special event sent when a volume is unmounted underneath
161 | * one of the paths being monitored. The path in the event is the
162 | * path to the directory from which the volume was unmounted. You
163 | * will receive one of these notifications for every volume unmount
164 | * event inside the kernel. This is not a substitute for the
165 | * notifications provided by the DiskArbitration framework; you only
166 | * get notified after the unmount has occurred. Beware that
167 | * unmounting a volume could uncover an arbitrarily large directory
168 | * hierarchy, although Mac OS X never does that.
169 | */
170 | static var unmount: EonilFSEventsEventFlags {
171 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagUnmount)
172 | }
173 |
174 | /*
175 | * A file system object was created at the specific path supplied in this event.
176 | * (This flag is only ever set if you specified the FileEvents flag when creating the stream.)
177 | */
178 | @available(OSX 10.7, *)
179 | static var itemCreated: EonilFSEventsEventFlags {
180 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagItemCreated)
181 | }
182 |
183 | /*
184 | * A file system object was removed at the specific path supplied in this event.
185 | * (This flag is only ever set if you specified the FileEvents flag when creating the stream.)
186 | */
187 | @available(OSX 10.7, *)
188 | static var itemRemoved: EonilFSEventsEventFlags {
189 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagItemRemoved)
190 | }
191 |
192 | /*
193 | * A file system object at the specific path supplied in this event had its metadata modified.
194 | * (This flag is only ever set if you specified the FileEvents flag when creating the stream.)
195 | */
196 | @available(OSX 10.7, *)
197 | static var itemInodeMetaMod: EonilFSEventsEventFlags {
198 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagItemInodeMetaMod)
199 | }
200 |
201 | /*
202 | * A file system object was renamed at the specific path supplied in this event.
203 | * (This flag is only ever set if you specified the FileEvents flag when creating the stream.)
204 | */
205 | @available(OSX 10.7, *)
206 | static var itemRenamed: EonilFSEventsEventFlags {
207 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagItemRenamed)
208 | }
209 |
210 | /*
211 | * A file system object at the specific path supplied in this event had its data modified.
212 | * (This flag is only ever set if you specified the FileEvents flag when creating the stream.)
213 | */
214 | @available(OSX 10.7, *)
215 | static var itemModified: EonilFSEventsEventFlags {
216 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagItemModified)
217 | }
218 |
219 | /*
220 | * A file system object at the specific path supplied in this event had its FinderInfo data modified.
221 | * (This flag is only ever set if you specified the FileEvents flag when creating the stream.)
222 | */
223 | @available(OSX 10.7, *)
224 | static var itemFinderInfoMod: EonilFSEventsEventFlags {
225 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagItemFinderInfoMod)
226 | }
227 |
228 | /*
229 | * A file system object at the specific path supplied in this event had its ownership changed.
230 | * (This flag is only ever set if you specified the FileEvents flag when creating the stream.)
231 | */
232 | @available(OSX 10.7, *)
233 | static var itemChangeOwner: EonilFSEventsEventFlags {
234 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagItemChangeOwner)
235 | }
236 |
237 | /*
238 | * A file system object at the specific path supplied in this event had its extended attributes modified.
239 | * (This flag is only ever set if you specified the FileEvents flag when creating the stream.)
240 | */
241 | @available(OSX 10.7, *)
242 | static var itemXattrMod: EonilFSEventsEventFlags {
243 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagItemXattrMod)
244 | }
245 |
246 | /*
247 | * The file system object at the specific path supplied in this event is a regular file.
248 | * (This flag is only ever set if you specified the FileEvents flag when creating the stream.)
249 | */
250 | @available(OSX 10.7, *)
251 | static var itemIsFile: EonilFSEventsEventFlags {
252 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagItemIsFile)
253 | }
254 |
255 | /*
256 | * The file system object at the specific path supplied in this event is a directory.
257 | * (This flag is only ever set if you specified the FileEvents flag when creating the stream.)
258 | */
259 | @available(OSX 10.7, *)
260 | static var itemIsDir: EonilFSEventsEventFlags {
261 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagItemIsDir)
262 | }
263 |
264 | /*
265 | * The file system object at the specific path supplied in this event is a symbolic link.
266 | * (This flag is only ever set if you specified the FileEvents flag when creating the stream.)
267 | */
268 | @available(OSX 10.7, *)
269 | static var itemIsSymlink: EonilFSEventsEventFlags {
270 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagItemIsSymlink)
271 | }
272 |
273 | /*
274 | * Indicates the event was triggered by the current process.
275 | * (This flag is only ever set if you specified the MarkSelf flag when creating the stream.)
276 | */
277 | @available(OSX 10.9, *)
278 | static var ownEvent: EonilFSEventsEventFlags {
279 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagOwnEvent)
280 | }
281 |
282 | /*
283 | * Indicates the object at the specified path supplied in this event is a hard link.
284 | * (This flag is only ever set if you specified the FileEvents flag when creating the stream.)
285 | */
286 | @available(OSX 10.10, *)
287 | static var itemIsHardlink: EonilFSEventsEventFlags {
288 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagItemIsHardlink)
289 | }
290 |
291 | /* Indicates the object at the specific path supplied in this event was the last hard link.
292 | * (This flag is only ever set if you specified the FileEvents flag when creating the stream.)
293 | */
294 | @available(OSX 10.10, *)
295 | static var itemIsLastHardlink: EonilFSEventsEventFlags {
296 | return EonilFSEventsEventFlags(rawValue: kFSEventStreamEventFlagItemIsLastHardlink)
297 | }
298 |
299 | }
300 |
301 | extension EonilFSEventsEventFlags: Hashable {
302 | public var hashValue: Int {
303 | return rawValue.hashValue
304 | }
305 | }
306 | extension EonilFSEventsEventFlags: CustomStringConvertible, CustomDebugStringConvertible {
307 | // private static func getAllFlags() -> [EonilFSEventsEventFlags] {
308 | // return [
309 | //// .none,
310 | // .mustScanSubDirs,
311 | // .userDropped,
312 | // .kernelDropped,
313 | // .idsWrapped,
314 | // .historyDone,
315 | // .rootChanged,
316 | // .mount,
317 | // .unmount,
318 | // .itemCreated,
319 | // .itemRemoved,
320 | // .itemInodeMetaMod,
321 | // .itemRenamed,
322 | // .itemModified,
323 | // .itemFinderInfoMod,
324 | // .itemChangeOwner,
325 | // .itemXattrMod,
326 | // .itemIsFile,
327 | // .itemIsDir,
328 | // .itemIsSymlink,
329 | // .ownEvent,
330 | // .itemIsHardlink,
331 | // .itemIsLastHardlink,
332 | // ]
333 | // }
334 | private static func getNameMapping() -> [EonilFSEventsEventFlags: String] {
335 | return [
336 | // .none: ".none",
337 | .mustScanSubDirs: ".mustScanSubDirs",
338 | .userDropped: ".userDropped",
339 | .kernelDropped: ".kernelDropped",
340 | .idsWrapped: ".idsWrapped",
341 | .historyDone: ".historyDone",
342 | .rootChanged: ".rootChanged",
343 | .mount: ".mount",
344 | .unmount: ".unmount",
345 | .itemCreated: ".itemCreated",
346 | .itemRemoved: ".itemRemoved",
347 | .itemInodeMetaMod: ".itemInodeMetaMod",
348 | .itemRenamed: ".itemRenamed",
349 | .itemModified: ".itemModified",
350 | .itemFinderInfoMod: ".itemFinderInfoMod",
351 | .itemChangeOwner: ".itemChangeOwner",
352 | .itemXattrMod: ".itemXattrMod",
353 | .itemIsFile: ".itemIsFile",
354 | .itemIsDir: ".itemIsDir",
355 | .itemIsSymlink: ".itemIsSymlink",
356 | .ownEvent: ".ownEvent",
357 | .itemIsHardlink: ".itemIsHardlink",
358 | .itemIsLastHardlink: ".itemIsLastHardlink",
359 | ]
360 | }
361 | public var description: String {
362 | return debugDescription
363 | }
364 | public var debugDescription: String {
365 | let ns = EonilFSEventsEventFlags.getNameMapping()
366 | let ns1 = ns.filter({ contains($0.key) }).map({ $0.value })
367 | return "[\(ns1.joined(separator: ","))]"
368 | }
369 | }
370 |
--------------------------------------------------------------------------------
/Sources/EonilFSEvents/EonilFSEventStreamEventID.swift:
--------------------------------------------------------------------------------
1 | //
2 | // EonilFSEventsEventID.swift
3 | // EonilFSEvents
4 | //
5 | // Created by Hoon H. on 2016/10/02.
6 | //
7 | //
8 |
9 | import Foundation
10 | import CoreServices
11 |
12 | public struct EonilFSEventsEventID: Hashable, RawRepresentable {
13 | public let rawValue: FSEventStreamEventId
14 | public init(rawValue: FSEventStreamEventId) {
15 | self.rawValue = rawValue
16 | }
17 | fileprivate init(rawValue: UInt) {
18 | self.rawValue = FSEventStreamEventId(UInt32(truncatingIfNeeded: rawValue))
19 | }
20 | }
21 | public func == (a: EonilFSEventsEventID, b: EonilFSEventsEventID) -> Bool {
22 | return a.rawValue == b.rawValue
23 | }
24 |
25 | public extension EonilFSEventsEventID {
26 | static var now: EonilFSEventsEventID {
27 | return EonilFSEventsEventID(rawValue: kFSEventStreamEventIdSinceNow)
28 | }
29 | /*
30 | * FSEventsGetCurrentEventId()
31 | *
32 | * Discussion:
33 | * Fetches the most recently generated event ID, system-wide (not
34 | * just for one stream). By thetime it is returned to your
35 | * application even newer events may have already been generated.
36 | *
37 | * Result:
38 | * The event ID of the most recent event generated by the system.
39 | *
40 | * Availability:
41 | * Mac OS X: in version 10.5 and later in CoreServices.framework
42 | * CarbonLib: not available
43 | * Non-Carbon CFM: not available
44 | */
45 | @available(macOS, introduced: 10.5)
46 | @available(iOS, introduced: 6.0)
47 | static func getCurrentEventId() -> EonilFSEventsEventID {
48 | let eventId = FSEventsGetCurrentEventId()
49 | return EonilFSEventsEventID(rawValue: eventId)
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Sources/EonilFSEvents/EonilFSEventStreamIllogicalErrorLog.swift:
--------------------------------------------------------------------------------
1 | //
2 | // EonilFSEventsIllogicalErrorLog.swift
3 | // EonilFSEvents
4 | //
5 | // Created by Hoon H. on 2016/10/02.
6 | //
7 | //
8 |
9 | /// An error that is very unlikely to happen if this library code is properly written.
10 | ///
11 | public struct EonilFSEventsIllogicalErrorLog {
12 | public var code: EonilFSEventsCriticalErrorCode
13 | public var message: String?
14 | init(code: EonilFSEventsCriticalErrorCode) {
15 | self.code = code
16 | }
17 | init(code: EonilFSEventsCriticalErrorCode, message: String) {
18 | self.code = code
19 | self.message = message
20 | }
21 | func cast() {
22 | EonilFSEventsIllogicalErrorLog.handler(self)
23 | }
24 |
25 | /// Can be called at any thread.
26 | public static var handler: (EonilFSEventsIllogicalErrorLog) -> () = { assert(false, "EonilFSEvents: \($0)") }
27 | }
28 |
29 | public enum EonilFSEventsCriticalErrorCode {
30 | case missingContextRawPointerValue
31 | case unexpectedPathValueType
32 | case unmatchedEventParameterCounts
33 | }
34 |
--------------------------------------------------------------------------------
/Sources/EonilFSEvents/EonilFSEvents.swift:
--------------------------------------------------------------------------------
1 | //
2 | // EonilFSEvents.swift
3 | // EonilFSEvents
4 | //
5 | // Created by Hoon H. on 2016/10/02.
6 | //
7 | //
8 |
9 | import Foundation
10 |
11 |
12 | ///
13 | /// Simple access to file-system events.
14 | ///
15 | /// - Note:
16 | /// This is specifically designed for GUI apps.
17 | /// Use only in main thread.
18 | /// If you want to access all the options of "FSEvents",
19 | /// use `EonilFSEvents` class directly.
20 | ///
21 | public struct EonilFSEvents {
22 | public static func startWatching(paths: [String], for id: ObjectIdentifier, with handler: @escaping (EonilFSEventsEvent) -> ()) throws {
23 | assert(Thread.isMainThread)
24 | assert(watchers[id] == nil)
25 | // This is convenient wrapper for UI.
26 | // UI usually needs quicker response rather than maximum throughput.
27 | // Tuned for quickest response.
28 | // For non-UI code, I strongly recommend to instantiate `EonilFSEvents` yourself
29 | // with proper parameters.
30 | let s = try EonilFSEventStream(
31 | pathsToWatch: paths,
32 | sinceWhen: .now,
33 | latency: 0,
34 | flags: [.noDefer, .fileEvents],
35 | handler: handler)
36 | s.setDispatchQueue(DispatchQueue.main)
37 | try s.start()
38 | watchers[id] = s
39 | }
40 | public static func stopWatching(for id: ObjectIdentifier) {
41 | assert(Thread.isMainThread)
42 |
43 | guard let s = watchers[id] else { return }
44 | s.stop()
45 | s.invalidate()
46 | watchers[id] = nil
47 | }
48 | }
49 | private var watchers = [ObjectIdentifier: EonilFSEventStream]()
50 |
--------------------------------------------------------------------------------
/Sources/EonilFSEventsDemoCLI/main.swift:
--------------------------------------------------------------------------------
1 | //
2 | // main.swift
3 | // EonilFSEventsDemoCLI
4 | //
5 | // Created by Henry on 2018/12/27.
6 | //
7 |
8 | import Foundation
9 | import EonilFSEvents
10 |
11 | let k = NSObject()
12 | try EonilFSEvents.startWatching(
13 | paths: [NSHomeDirectory()],
14 | for: ObjectIdentifier(k),
15 | with: { e in print(e) })
16 |
17 | RunLoop.main.run()
18 |
--------------------------------------------------------------------------------
/test.zsh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env zsh
2 |
3 | rm -rf .build build
4 |
5 | swift build
6 | # I don't know why, but "xcodebuild" doesn't work
7 | # without explicit setting of "SYMROOT".
8 | # It seems Xcode have some issues.
9 | OPTS=SYMROOT=`pwd`/build
10 |
11 | DEMO=EonilFSEventsDemoGUI
12 | cd $DEMO
13 | xcodebuild -project $DEMO.xcodeproj -target $DEMO -configuration Debug $OPTS
14 | xcodebuild -project $DEMO.xcodeproj -target $DEMO -configuration Release $OPTS
15 | cd ..
16 |
17 | # I can't figure out how to build without provisioning profile for Mac Catalyst.
18 | # Therefore, test has been disabled. You can perform test manually by opening the project.
19 | #cd BuildTest
20 | #xcodebuild -project BuildTest.xcodeproj -target MacOSBuildTest -configuration Debug $OPTS
21 | #xcodebuild -project BuildTest.xcodeproj -target MacOSBuildTest -configuration Release $OPTS
22 | #xcodebuild -project BuildTest.xcodeproj -target MacCatalystBuildTest -configuration Debug $OPTS
23 | #xcodebuild -project BuildTest.xcodeproj -target MacCatalystBuildTest -configuration Release $OPTS
24 | #cd ..
25 |
--------------------------------------------------------------------------------